Convert source to literate coffee script v2

We're intending to write all the source code in literate coffee script
v2, which should make the code self-documenting and hopefully enforce
better standards.
This commit is contained in:
Oliver Blanthorn 2017-02-25 13:05:29 +00:00
parent ec4eaced3d
commit 17c1bbc05f
4 changed files with 136 additions and 170 deletions

View file

@ -1,50 +0,0 @@
# Just a test
#
#
#
config =
scrollDown: "j"
scrollUp: "k"
back: "H"
forward: "L"
console.log("hello")
historyHandler = (message) ->
window.history.go(message.number)
scrollHandler = (message) ->
window.scrollBy(0, message.number)
# First 0 corresponds to horizontal scroll, which is literally never needed ever
# We should work out some way to have a configuration file and hooks
# And generally document things well
arbitraryHandler = (message) ->
window[message.object].apply(window,message.args)
# apply's first argument tells it what "this" is
# I don't understand why it is needed, isn't "window" "this"?
# only works with direct methods e.g. "scrollBy", not "history.go"
# Testing function for really arbitrary evaluation in the context of the content script.
evalHandler = (message) ->
eval(message.string)
messageHandler = (message) ->
switch(message.command)
when "history" then historyHandler(message)
when "scroll" then scrollHandler(message)
when "arbitrary" then arbitraryHandler(message)
when "eval" then evalHandler(message)
browser.runtime.onMessage.addListener(messageHandler)
keyHandler = (event) ->
switch(event.key)
when config.scrollDown then scrollHandler({number:10})
when config.scrollUp then scrollHandler({number:-10})
when config.back then historyHandler({number:-1})
when config.forward then historyHandler({number:1})
document.addEventListener("keydown", keyHandler)

View file

@ -0,0 +1,50 @@
# Just a test
#
#
#
config =
scrollDown: "j"
scrollUp: "k"
back: "H"
forward: "L"
console.log("hello")
historyHandler = (message) ->
window.history.go(message.number)
scrollHandler = (message) ->
window.scrollBy(0, message.number)
# First 0 corresponds to horizontal scroll, which is literally never needed ever
# We should work out some way to have a configuration file and hooks
# And generally document things well
arbitraryHandler = (message) ->
window[message.object].apply(window,message.args)
# apply's first argument tells it what "this" is
# I don't understand why it is needed, isn't "window" "this"?
# only works with direct methods e.g. "scrollBy", not "history.go"
# Testing function for really arbitrary evaluation in the context of the content script.
evalHandler = (message) ->
eval(message.string)
messageHandler = (message) ->
switch(message.command)
when "history" then historyHandler(message)
when "scroll" then scrollHandler(message)
when "arbitrary" then arbitraryHandler(message)
when "eval" then evalHandler(message)
browser.runtime.onMessage.addListener(messageHandler)
keyHandler = (event) ->
switch(event.key)
when config.scrollDown then scrollHandler({number:10})
when config.scrollUp then scrollHandler({number:-10})
when config.back then historyHandler({number:-1})
when config.forward then historyHandler({number:1})
document.addEventListener("keydown", keyHandler)

View file

@ -1,120 +0,0 @@
# Quick and dirty prototyping.
#
# Functions declared here can be called in the debug window in ff.
handleBrowserAction = () ->
# .then takes a function that consumes at least one argument. this is an
# example of a named function, but anonymous functions are fine, too.
browser.tabs.query({active: true}).then(console.log)
# Change to the next tab in window, wrapping back to the start, if req.
#
# Get an array of all tabs, find the active tab's index, and the tab id of
# the tab with the next index.
#
# TODO: limit to focused window.
nextTab1 = () ->
browser.tabs.query({}).then(
(tabs) ->
# Doing my own list comprehensions means they're not done
# asynchronously from each other, but they will be very fast and
# this makes the code much simpler.
active = (tab for tab in tabs when tab.active == true)[0]
target_index = (active.index + 1) % tabs.length
target = (tab for tab in tabs when tab.index == target_index)[0]
displayTab(target.id)
console.error)
# Change to the next tab in window, wrapping back to the start, if req.
#
# Get an array of all tabs, find the active tab's index, and the tab id of
# the tab with the next index.
#
# TODO: limit to focused window.
nextTab2 = () ->
# Alternative implementation without list comprehensions.
#
# If querying all tabs to get number of tabs is too slow (as if), could
# query for index+1 and then test if result array.length == 0.
browser.tabs.query({}).then(
(tabs) ->
browser.tabs.query({active: true}).then(
(tabs2) ->
active = tabs2[0]
target_index = (active.index + 1) % tabs.length
browser.tabs.query({index: target_index}).then(
(tabs3) ->
displayTab(tabs3[0].id)
, console.error)
, console.error)
, console.error)
# Convenience: mark tab_id as active (active tabs are displayed in their window)
displayTab = (tab_id) ->
browser.tabs.update(tab_id, {active: true}).then(null, console.error)
# Example of a listener. Presumably we wouldn't use the browserAction button in
# the real thing.
browser.browserAction.onClicked.addListener(handleBrowserAction)
incTab = (inc) ->
browser.windows.getCurrent().then(
(window) ->
browser.tabs.query({windowId:window.id}).then(
(tabs) ->
activeTab = (tab for tab in tabs when tab.active)[0]
desiredIndex = (activeTab.index + inc).mod(tabs.length)
desiredTab = (tab for tab in tabs when tab.index == desiredIndex)[0]
setTab(desiredTab.id)
).catch(console.error)
).catch(console.error)
setTab = (id) ->
browser.tabs.update(id,{active:true})
tabByIndex = (index) ->
browser.tabs.query({}).then((tabs) ->
desiredTab = tab for tab in tabs when tab.index == desIndex
)
# modulus that always returns a non-negative number, as mathematicians expect.
#
# In mathematics, mod usually returns the remainder of euclidean division of
# two numbers and the remainder is always positive.
#
# In most programming languages, mod can return a negative number and the
# return value of mod always matches the sign of one or the other of the
# arguments. In JS the built-in % operator's returned value always has the same
# sign as the dividend, in python, the divisor.
Number.prototype.mod = (n) ->
Math.abs(this % n)
##
#
# First attempt at message parsing wrapper to avoid duplication of code
#
##
# The following functions all talk to the content.js script
goHistory = (n) ->
sendMessageToActiveTab({command:"history", number:n})
goScroll = (n) ->
sendMessageToActiveTab({command:"scroll",number:n})
sendMessageToActiveTab = (message) ->
sendMessageToFilteredTabs({active:true},message)
sendMessageToFilteredTabs = (filter,message) ->
browser.tabs.query(filter).then(
(tabs) ->
browser.tabs.sendMessage(tab.id,message) for tab in tabs
)
doArbitraryCodeInWindow = (object, args) ->
sendMessageToActiveTab({command:"arbitrary",object,args})
# example: doArbitraryCodeInWindow("scrollBy",[0,100])
console.log("Loaded Tridactyl")

86
addon/src/main.litcoffee Normal file
View file

@ -0,0 +1,86 @@
# main.litcoffee
## Introduction
We're writing everything in CoffeeScript v2: http://coffeescript.org/v2/
You can install it with `npm install --global coffeescript@next`. You need Firefox version 52+ to use the `await` command we are using here.
Functions declared here can be called in the debug window in ff. This is the main
background script that can access all of the WebExtension APIs.
## TODO:
This is a todolist
- get web-ext to run FF dev (~/bin/firefox)
- stop coffeescript vim thing from making newline # in markdown
- update vim-coffeescript to highlight await keywords, etc.
handleBrowserAction = () ->
# .then takes a function that consumes at least one argument. this is an
# example of a named function, but anonymous functions are fine, too.
x = await browser.tabs.query({active: true}).then(console.log)
# Example of a listener. Presumably we wouldn't use the browserAction button in
# the real thing.
browser.browserAction.onClicked.addListener(handleBrowserAction)
incTab = (inc) ->
try
window = await browser.windows.getCurrent()
tabs = await browser.tabs.query({windowId:window.id})
activeTab = (tab for tab in tabs when tab.active)[0]
desiredIndex = (activeTab.index + inc).mod(tabs.length)
desiredTab = (tab for tab in tabs when tab.index == desiredIndex)[0]
setTab(desiredTab.id)
catch error
console.log(error)
setTab = (id) ->
browser.tabs.update(id,{active:true})
tabByIndex = (index) ->
browser.tabs.query({}).then((tabs) ->
desiredTab = tab for tab in tabs when tab.index == desIndex
)
# modulus that always returns a non-negative number, as mathematicians expect.
#
# In mathematics, mod usually returns the remainder of euclidean division of
# two numbers and the remainder is always positive.
#
# In most programming languages, mod can return a negative number and the
# return value of mod always matches the sign of one or the other of the
# arguments. In JS the built-in % operator's returned value always has the same
# sign as the dividend, in python, the divisor.
Number.prototype.mod = (n) ->
Math.abs(this % n)
##
#
# First attempt at message parsing wrapper to avoid duplication of code
#
##
# The following functions all talk to the content.js script
goHistory = (n) ->
sendMessageToActiveTab({command:"history", number:n})
goScroll = (n) ->
sendMessageToActiveTab({command:"scroll",number:n})
sendMessageToActiveTab = (message) ->
sendMessageToFilteredTabs({active:true},message)
sendMessageToFilteredTabs = (filter,message) ->
filtTabs = await browser.tabs.query(filter)
browser.tabs.sendMessage(tab.id,message) for tab in filtTabs
doArbitraryCodeInWindow = (object, args) ->
sendMessageToActiveTab({command:"arbitrary",object,args})
# example: doArbitraryCodeInWindow("scrollBy",[0,100])
console.log("Loaded Tridactyl")