mirror of
https://github.com/vale981/tridactyl
synced 2025-03-05 09:31:41 -05:00
Delete irrelevant litcoffee flies
This commit is contained in:
parent
32491df069
commit
22b01774ea
6 changed files with 0 additions and 266 deletions
|
@ -1,47 +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)
|
|
@ -1,16 +0,0 @@
|
|||
TODO: get litcoffee highlighting off @cmcaine
|
||||
|
||||
commands = {
|
||||
"setTab": tridactyl.func.setTab
|
||||
}
|
||||
|
||||
exStrParser = (str) ->
|
||||
strArray = str.split(" ")
|
||||
command = strArray[0]
|
||||
func = commands[command]
|
||||
args = strArray.slice(1)
|
||||
args = ((if Number(a) then Number(a) else a) for a in args) # more concise way of doing this?
|
||||
return {func, args}
|
||||
|
||||
|
||||
Example: call `var x = exStrParser("setTab 1"); funcParser(x.func,x.args)` in the Firefox addon console
|
|
@ -1,7 +0,0 @@
|
|||
Takes functions from parser controller and calls them. Eventually, this will get more complicated to allow command chaining.
|
||||
|
||||
|
||||
funcParser = (command,args) ->
|
||||
command(args...) # ... is unpacks the list
|
||||
|
||||
Example: call `var x = exStrParser("setTab 1"); funcParser(x.func,x.args)` in the Firefox addon console
|
|
@ -1,101 +0,0 @@
|
|||
# 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)
|
||||
- adapt vim-coffeescript to work with litcoffee2
|
||||
- stop coffeescript vim thing from making newline # in markdown
|
||||
- update vim-coffeescript to highlight await keywords, etc.
|
||||
|
||||
The following is an attempt at namespacing in CoffeeScript. If we used TypeScript instead we could just use modules, but Olie is squeamish about the syntax (no list comprehensions and too much that can be implied, like `let` and all the damn braces). I sympathise, but the compile time errors are really useful. For now, we'll stick with Coffee.
|
||||
|
||||
tridactyl = {}
|
||||
tridactyl.func ?= {}
|
||||
|
||||
tridactyl.func.__init__ = ->
|
||||
|
||||
This allows us to use setTab in this file, but requires us to use the entire name outside.
|
||||
|
||||
tridactyl.func.setTab = setTab = (id) ->
|
||||
browser.tabs.update(id,{active:true})
|
||||
|
||||
tridactyl.func.tabByIndex = tabByIndex = (index) ->
|
||||
browser.tabs.query({}).then((tabs) ->
|
||||
desiredTab = (tab for tab in tabs when tab.index == desIndex)[0]
|
||||
)
|
||||
|
||||
tridactyl.func.incTab = 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)
|
||||
|
||||
## First attempt at message parsing wrapper to avoid duplication of code
|
||||
|
||||
The following functions all talk to the content.js script to perform functions that need to operate on, e.g., the `window.history` object.
|
||||
|
||||
tridactyl.func.goHistory = goHistory = (n) ->
|
||||
sendMessageToActiveTab({command:"history", number:n})
|
||||
|
||||
tridactyl.func.goScroll = goScroll = (n) ->
|
||||
sendMessageToActiveTab({command:"scroll",number:n})
|
||||
|
||||
tridactyl.func.sendMessageToActiveTab = sendMessageToActiveTab = (message) ->
|
||||
sendMessageToFilteredTabs({active:true},message)
|
||||
|
||||
tridactyl.func.sendMessageToFilteredTabs = sendMessageToFilteredTabs = (filter,message) ->
|
||||
filtTabs = await browser.tabs.query(filter)
|
||||
browser.tabs.sendMessage(tab.id,message) for tab in filtTabs
|
||||
|
||||
tridactyl.func.doArbitraryCodeInWindow = doArbitraryCodeInWindow = (object, args) ->
|
||||
sendMessageToActiveTab({command:"arbitrary",object,args})
|
||||
# example: doArbitraryCodeInWindow("scrollBy",[0,100])
|
||||
|
||||
## Regex test
|
||||
|
||||
Adapted from http://www.dustindiaz.com/autocomplete-fuzzy-matching
|
||||
|
||||
tridactyl.mystrings = mystrings = ["colin", "olie", "jake", "harri"]
|
||||
tridactyl.func.matchString = matchString = (input) ->
|
||||
search = new RegExp(input.split('').join('\\w*').replace(/\W/, ""), 'i')
|
||||
mystrings.filter((string) ->
|
||||
if string.match(search)
|
||||
return string
|
||||
)
|
||||
|
||||
## Finish the Tridactyl namespace and initialise it
|
||||
|
||||
tridactyl.func.__init__()
|
||||
|
||||
# Misc helper functions
|
||||
|
||||
## Modulus
|
||||
|
||||
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)
|
||||
|
||||
Let the console know we got home safely.
|
||||
|
||||
console.log("Loaded Tridactyl")
|
|
@ -1,91 +0,0 @@
|
|||
# A simple observable-like class
|
||||
|
||||
**This doesn't work.** Async functions (any function that contains the `await` keyword) return a promise immediately and do their work sometime in the future. I think the principle is still doable, without polling, but not like this.
|
||||
|
||||
This class guarantees that the subscriber is called once per push and that each call of the subscriber completes before the next call. This indirection is required because subscriber() may be paused by an `await` - if subscriber was called directly by e.g. onKeyEvent(subscriber), then more than one subscriber call can be threaded concurrently if subscriber ever pauses execution... Controlling flow like this must have been a real pain in the arse before `await`...
|
||||
|
||||
class Sequential
|
||||
constructor: (subscriber) ->
|
||||
this._subscriber = subscriber
|
||||
this._is_consuming = false
|
||||
|
||||
push: (v) ->
|
||||
this._queue.push(v)
|
||||
if not this._is_consuming
|
||||
this.consume()
|
||||
|
||||
consume: ->
|
||||
this._is_consuming = true
|
||||
for v in this._queue
|
||||
this._subscriber(v)
|
||||
this._is_consuming = false
|
||||
|
||||
sleep = (ms) ->
|
||||
new Promise((resolve) ->
|
||||
setTimeout(resolve, ms))
|
||||
|
||||
class ParserController
|
||||
constructor: ->
|
||||
this._state = ""
|
||||
|
||||
pushEvent: (ev) =>
|
||||
await sleep(1000)
|
||||
this._state += ev.key
|
||||
console.log(this._state)
|
||||
|
||||
parserController = new ParserController()
|
||||
|
||||
queue = new Sequential(parserController.pushEvent)
|
||||
document.addEventListener(queue.push)
|
||||
|
||||
## This time with generators: simpler and maybe more idiomatic
|
||||
|
||||
I was very confused about how the `await` shims could work, so I had TypeScript output me one: turns out they're built on generators! That's a much more natural mechanism for our original use case.
|
||||
|
||||
For now, we'll just keep parserController synchronous and use this generator syntax.
|
||||
|
||||
ParserController = ->
|
||||
# Loop forever.
|
||||
loop
|
||||
# Receive keys until the mode parser tells us to handle an ex_str.
|
||||
loop
|
||||
keys = []
|
||||
ex_str = ""
|
||||
|
||||
# Pause execution until someone calls parserController.next(<somevalue>)
|
||||
keys.push(yield)
|
||||
|
||||
# Mode parsers can return an object with either a `keys` or an `ex_str` property.
|
||||
|
||||
# If `.keys` exists it is a mapping of keys to continue to append to and resend (the mapping was not terminal, send me these keys again). `.keys` may differ from the passed value.
|
||||
# If `.ex_str`, the mapping was terminal: drop all the keys you have now and break to handle the ex_str.
|
||||
response = normal_mode_parser(keys)
|
||||
|
||||
if response.keys != undefined
|
||||
keys = response.keys
|
||||
else
|
||||
ex_str = response.ex_str
|
||||
break
|
||||
|
||||
# Parse the ex_str into a function and command to run.
|
||||
[func, args] = ex_str_parser(ex_str)
|
||||
|
||||
# Execute the ex_str.
|
||||
func(args...)
|
||||
|
||||
# Create the generator object
|
||||
parserController = ParserController()
|
||||
|
||||
# Run the parserController until the first yield.
|
||||
parserController.next()
|
||||
|
||||
# parserController.next needs isn't bound to parserController, so needs to be made indirect:
|
||||
feeder = (ev) ->
|
||||
parserController.next(ev)
|
||||
|
||||
# Feed the parserController events.
|
||||
document.addEventListener("keyDown", feeder)
|
||||
|
||||
Fun digression: I first encountered the generator/yield syntax in Python2 where it was not asynchronous and only allows data transfer from the yielder to the caller of next(). It took me an embarassingly long time to get my head around the new semantics when I saw it again in python3's async library and the data was moving in both directions.
|
||||
|
||||
Don't be like me: grok it now with these helpful links: [mdn](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*), [python wiki](https://wiki.python.org/moin/Generators)
|
|
@ -1,4 +0,0 @@
|
|||
# Test
|
||||
|
||||
test = () ->
|
||||
"hello"
|
Loading…
Add table
Reference in a new issue