I've been programming on pure instinct for like five hours and I'm not
sure what exactly I did any more. I *think* that what I did was
something like:
* Split `state.ts` into `state.ts` and `content_state.ts`, then
removed mode from state and moved it to content_state.
* Made the types in content_state.ts a hair more powerful
* Fixed all errors resulting from those two changes, in the process
swapping state out for content_state wherever appropriate.
* Moved a couple excmds from background into content since they
depended heavily on the mode and should live with the mode
* Split the controller in half, moving the parser logic to the content
script and leaving acceptExCmds in the background
version. content_controller forwards excmds to background script
using messaging.
* Nuked the keydown_* code, since we no longer need to forward keys to
the background.
* Went around fixing everything resulting from *those* changes, mostly
the various perversions of keydown listeners
* Various tweaks here and there that probably didn't do anything but I
was just changing things at random a third of the time and I really
need to go through this and clean it up.
Things that work:
* excmds are nice now. each tab has its own commandline; they stay
open when you navigate between tabs and you can come back to them
after doing stuff in another tab and finish your command line input.
* keybinds that don't don't involve mode switching: `[[`, `]]`, `j`,
`k`, `r`, etc, all still functional.
* You can turn on hinting mode and, again, navigate to another tab
which will *not* be in hinting mode, do whatever you need to do
there including excmds or more hinting, and then come back to finish
the hint you started in the first tab
* You can exit hint mode by pressing escape. :P
Things that I broke:
* ...Actually quite a bunch of stuff, I think.
* I don't seem to be able to *finish* a hint any more. Sometimes I
can't even get one key in.
This commit implements typechecking in the `:set` excmd. It uses metadata
to make sure the given argument is valid.
Some of the settings were stored as numbers in the config while they
were passed as strings to `:set()`. This prevented them from being
configurable. This has been fixed by turning them into string in the
config and ensuring that they are correctly deserialized when retrieved
from the config.
Note that there still are a few settings that are stored as int in the
config (namely the tts ones). This should probably be fixed at some
point but is not urgent as it has always been impossible to configure
them and nobody ever complained about it.
Rapid hinting now returns an array. When no hints have been selected, an
empty array is returned. When no hints have been selected in regular
hinting mode, an empty string is returned.
Making hint mode less janky is achieved by not resetting hint mode when
a hint has been selected. New command line options, `-q*` where `*`
stands for any alread-existing flag, are added.
The global hint flow is as following:
- User goes into hint mode
- hint mode promise is created
- When a hint is selected, the corresponding action is performed (e.g.
opening a link, killing an element...)
- The result of the action is saved in the hint
- If we're not in rapid hint mode, modeState is reset, and the hint mode
promise is resolved with the result of the action as parameter
- If we're in rapid hint mode, modeState is not reset. Instead its
filter is reset and all its hints are displayed again.
- Rapid hint mode is only left on escape, and this means that the
promise will be rejected.
Rejecting the promise means that we can't pipe elements selected in hint
rapid hint mode to other commands. This makes sense because pursuing
execution of a pipe several times in parallel, on top of being possibly
hard to implement, would probably be confusing.
Instead of using a pipe in order to execute arbitrary commands in hint
mode, users can use `-qW excmd`. Contrary to the pipe, this makes clear that
the excmd will be executed multiple times, once per focused hint.
This way of handling rapid hint mode has the advantage of simplifying
the `hint` function. Now, instead of having to return a tuple with the
number of available hints, the function can just return the selected
element or whatever the command line arguments specifies it should
return.
Instead of returning null when no hint has been selected, hinting.pipe
will now return a promise that will be resolved once a hint has been
selected or rejected if hintstate is destroyed without a hint being
explicitly selected by the user or if there are no hints to select.
Promise rejection is then handled at the end of excmds.ts:hint(), as
suggested by bovine3dom on Riot.
In hinting.ts, pipe() and pipe_elements() assumed that the resolve
function they passed to hintPage() would always be called, which wasn't
always the case (e.g. when a users goes into hint mode but presses
`<Esc>`).
This caused unresolved promises to linger in the tab. When the tab was
closed, an error was thrown about the message manager being
disconnected. This was caught by Tridactyl and displayed in the command
line.
We're fixing this bug by passing no-op functions as onSelect to
hintPage() and explicitly passing the resolve function. The resolve
function is then saved in HintState and called when destroying
HintState.
We parametrize reset() in order to be able to distinguish between resets
caused by a hint being selected and by the user pressing `<Esc>`. This
is necessary because we need to know when the function should resolve
the last focused hint and when it shouldn't.
We then add a bunch of null handling in excmds.ts:hint() in order to
make sure not to introduce other bugs.
This fixes https://github.com/cmcaine/tridactyl/issues/855.
Now returns a tuple of the element and the number of hints available
when the function was run. This mainly fixes the rapid hint bug
encountered when the user enters rapid hint mode with only one link
available.
Another application idea would be modeline info or something in that
vein.