Created
November 25, 2017 18:39
-
-
Save qix/fd20fdf6660b3a41e5dd8144b3e8f0b5 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
const { | |
commands, | |
extensions, | |
} = options; | |
const { | |
CancelCommand, | |
ClickCommand, | |
ExecCommand, | |
I3Command, | |
KeyCommand, | |
KeyHoldCommand, | |
ModeCommand, | |
MultiCommand, | |
NoopCommand, | |
PreviousCommand, | |
PriorityCommand, | |
RecordCommand, | |
RepeatCommand, | |
SleepCommand, | |
VscodeCommand, | |
WaitCommand, | |
RelativePathCommand, | |
} = options.commands; | |
function relpath(path) { | |
return new RelativePathCommand(path); | |
} | |
function cancel() { | |
return new CancelCommand(); | |
} | |
function noop() { | |
return new NoopCommand(); | |
} | |
function bash(command) { | |
return new ExecCommand(command, { | |
shell: true, | |
}); | |
} | |
function wait(delay) { | |
return new WaitCommand(delay); | |
} | |
function exec(command) { | |
return new ExecCommand(command); | |
} | |
function i3(command) { | |
return new I3Command(command); | |
} | |
function vscodeMode(test) { | |
return extensions.vscode.modeTest(options.mode, test); | |
} | |
function vscode(command, args) { | |
return new VscodeCommand(command, args); | |
} | |
function vscodeSelectable(command, args) { | |
if (vscodeMode('editorHasSelection')) { | |
command += 'Select'; | |
} | |
return new VscodeCommand(command, args); | |
} | |
function vscodeType(command) { | |
return VscodeCommand.fromTypeCommand(command); | |
} | |
function vscodeVim(command) { | |
return vscode('extension.vim-command.run', {command}); | |
} | |
function repeat(count, command) { | |
if (count === 1) { | |
return command; | |
} | |
return new RepeatCommand(count, command); | |
} | |
function mode(name) { | |
return new ModeCommand([name], []); | |
} | |
function modeOff(name) { | |
return new ModeCommand([], [name]); | |
} | |
function multi(...commands) { | |
if (commands.length === 0) { | |
return noop(); | |
} else if (commands.length === 1) { | |
return commands[0]; | |
} | |
return new MultiCommand(commands); | |
} | |
function key(name) { | |
return new KeyCommand(name); | |
} | |
function type(keys) { | |
const names = {'\n': 'enter'}; | |
if (typeof keys === 'string') { | |
keys = keys.split('').map(key => { | |
return names[key] || key; | |
}); | |
} | |
return multi(...keys.map(name => key(name))); | |
} | |
function typeLine(keys) { | |
return multi(type(keys), key('enter')); | |
} | |
function camel(words, big=false) { | |
let first = words.shift(); | |
first = big ? upperFirst(first) : first; | |
return first + words.map(upperFirst).join(''); | |
} | |
function snake(words) { | |
return words.join('_'); | |
} | |
function vimex(command) { | |
return escaped(typeLine(`:${command}`)); | |
} | |
function upperFirst(word) { | |
return word.substring(0, 1).toUpperCase() + word.substring(1); | |
} | |
function escaped(command) { | |
return multi(key('escape'), command); | |
} | |
function extractList(list, index) { | |
return list.map(element => element[index]); | |
} | |
function extractOptional(optional, index, def=null) { | |
return optional ? optional[index] : def; | |
} | |
function optional(v, def=null) { | |
return extractOptional(v, 1, def); | |
} | |
function flatten(arr) { | |
return arr.reduce((flat, next) => ( | |
flat.concat(Array.isArray(next) ? flatten(next) : next) | |
), []); | |
} | |
} | |
wake_up => new SleepCommand(false); | |
go_to_sleep => new SleepCommand(true); | |
snore => new SleepCommand(true); | |
restart voice => exec('~/bin/voice'); | |
close voice => bash("xdotool search --name '^pegvoice$' | xargs -n 1 xdotool windowkill"); | |
stop voice => bash("xdotool search --name '^pegvoice$' | xargs -n 1 xdotool windowkill"); | |
record on => new RecordCommand(true); | |
record off => new RecordCommand(false); | |
click => new ClickCommand(); | |
move window :direction => i3(`move ${direction}`); | |
close window => i3('kill'); | |
window ...{ | |
float => i3('floating toggle'); | |
:direction => i3(`focus ${direction}`); | |
move :direction => i3(`move ${direction}`); | |
close => i3('kill'); | |
} | |
window? move screen :i3screen => i3(`move container to workspace ${i3screen}`); | |
window move :i3screen => i3(`move container to workspace ${i3screen}`); | |
focus floating => i3('focus floating'); | |
focus tiling => i3('focus tiling'); | |
screen ...{ | |
lock => multi(exec('lock'), new SleepCommand(true)); | |
:i3screen => i3(`workspace ${i3screen}, focus tiling`); | |
brightness :number => exec(`brightness ${number}`); | |
previous => i3(`workspace prev, focus tiling`); | |
left => i3(`workspace prev, focus tiling`); | |
right => i3(`workspace next, focus tiling`); | |
move :i3screen => i3(`move container to workspace ${i3screen}`); | |
} | |
screen next? => i3(`workspace next, focus tiling`); | |
open terminal :folder? => exec( | |
`gnome-terminal --hide-menubar ` + | |
`--working-directory="${optional(folder, '/home/josh')}"` | |
); | |
open monitor grammar => exec(`gnome-terminal --hide-menubar -e "bash -i -c '~/pegvoice/src/check-results.js --watch'"`); | |
open monitor voice => exec(`gnome-terminal --hide-menubar -e "bash -i -c '~/pegvoice/src/check-results.js --watch'"`); | |
open grammar monitor => exec(`gnome-terminal --hide-menubar -e "bash -i -c '~/pegvoice/src/check-results.js --watch'"`); | |
open code grammar => exec('code --new-window ~/.pegvoice/grammar.pgv'); | |
open code :folder? => exec(`code --new-window ${optional(folder, '/home/josh')}`); | |
open editor grammar => exec('code --new-window ~/.pegvoice/grammar.pgv'); | |
open editor :folder? => exec(`code --new-window ${optional(folder, '/home/josh')}`); | |
open chrome? incognito => exec('google-chrome -incognito'); | |
open chrome => exec('google-chrome'); | |
call :ident => multi(type(`${ident}()`), key('left')); | |
string :keys => type("'" + keys + "'"); | |
console log => type('console.log('); | |
arrow function => multi(type(' => '), key('shift-['), key('enter')); | |
arrow => type(' => '); | |
&slack ...{ | |
pizza party => type( | |
':party-dino: ' + | |
':pizzaspin: :pizzaspin2: :antipizza: :pizzaspin3: :pizzaspin4:' + | |
' :party-dino:' | |
); | |
} | |
&bash ...{ | |
copy => key('ctrl-shift-c'); | |
paste => key('ctrl-shift-v'); | |
delete line => multi(key('home'), key('ctrl-k')); | |
k:modified_key => key(k); | |
source rebase => type('git rebase -i HEAD~25'); | |
source commit all => multi(type('git commit -a -m \'\''), key('left')); | |
source commit => multi(type('git commit -m \'\''), key('left')); | |
source diff letter => type('git diff --word-diff-regex=.'); | |
source => type('git '); | |
def => type('diff '); | |
big option => type(' --'); | |
option => type(' -'); | |
equal => type('='); | |
less => type('less '); | |
ls => type('ls '); | |
run test => multi(type('authbox-test '), relpath('~/authbox/authbox-api/tests/~~'), key('tab')); | |
page up => key('shift-pageup'); | |
page down? => key('shift-pagedown'); | |
} | |
vscode_multi_select = ...{ | |
multi_select all => vscode('editor.action.selectHighlights'); | |
multi_select up => vscode('editor.action.insertCursorAbove'); | |
multi_select down => vscode('editor.action.insertCursorBelow'); | |
multi_select next? => vscode('editor.action.addSelectionToNextFindMatch'); | |
} | |
vscode_edit_repeatable = ...{ | |
dir:direction => vscodeSelectable('cursor' + upperFirst(dir)); | |
cmd:vscode_multi_select => cmd; | |
paste => vscode('editor.action.clipboardPasteAction'); | |
line above => vscode('editor.action.insertLineBefore'); | |
line before => vscode('editor.action.insertLineBefore'); | |
line_up => vscode('editor.action.insertLineBefore'); | |
line below => vscode('editor.action.insertLineAfter'); | |
line after => vscode('editor.action.insertLineAfter'); | |
line down => vscode('editor.action.insertLineAfter'); | |
move line_up => vscode('editor.action.moveLinesUpAction'); | |
move line down => vscode('editor.action.moveLinesDownAction'); | |
dedent => vscode('editor.action.outdentLines'); | |
indent => vscode('editor.action.indentLines'); | |
change word left => vscode('deleteWordLeft'); | |
change word right? => vscode('deleteWordRight'); | |
delete line => vscode('editor.action.deleteLines'); | |
copy line ...{ | |
down => vscode('editor.action.copyLinesDownAction'); | |
up => vscode('editor.action.copyLinesUpAction'); | |
} | |
} | |
vscode_select_command = ...{ | |
grow => vscode(`editor.action.smartSelect.grow`); | |
shrink => vscode(`editor.action.smartSelect.shrink`); | |
line up => multi(vscode('cursorUpSelect'), vscode('cursorHomeSelect')); | |
line left => vscode(`cursorHomeSelect`); | |
line right => vscode(`cursorEndSelect`); | |
line down? => vscode('expandLineSelection'); | |
dir:direction => vscode('cursor' + upperFirst(dir) + 'Select'); | |
word left => vscode('cursorWordEndLeftSelect'); | |
word right => vscode('cursorWordEndRightSelect'); | |
column dir:direction => vscode('cursorColumnSelect' + upperFirst); | |
column => vscode('columnSelect'); | |
} | |
&vscode ...{ | |
save => vscode('workbench.action.files.save'); | |
new => vscode('workbench.action.files.newUntitledFile'); | |
select all => vscode('editor.action.selectAll'); | |
explorer => vscode('workbench.files.action.focusFilesExplorer'); | |
increment => vscodeVim('<C-a>'); | |
decrement => vscodeVim('<C-x>'); | |
close editor => vscode('workbench.action.closeActiveEditor'); | |
close file => vscode('workbench.action.closeActiveEditor'); | |
close messages => vscode('workbench.action.closeMessages'); | |
editor group one => vscode('workbench.action.focusFirstEditorGroup'); | |
editor group two => vscode('workbench.action.focusSecondEditorGroup'); | |
editor group three => vscode('workbench.action.focusThirdEditorGroup'); | |
toggle_any ...{ | |
menu => vscode('workbench.action.toggleMenuBar'); | |
terminal => vscode('workbench.action.terminal.toggleTerminal'); | |
} | |
&=>vscodeMode('terminalFocus') ...{ | |
terminal => vscode('workbench.action.terminal.toggleTerminal'); | |
} | |
terminal => vscode('workbench.action.terminal.focus'); | |
editor => vscode('workbench.action.focusActiveEditorGroup'); | |
delete inside => multi( | |
vscode(`editor.action.smartSelect.grow`), | |
vscode('deleteRight') | |
); | |
focus ...{ | |
explorer => vscode('workbench.view.explorer'); | |
editor => vscode('workbench.action.focusActiveEditorGroup'); | |
terminal => vscode('workbench.action.terminal.focus'); | |
} | |
find => multi( | |
vscode('actions.find'), | |
modeOff('vscode-editorTextFocus'), | |
mode('vscode-findWidgetVisible') | |
); | |
&=>vscodeMode('suggestWidgetMultipleSuggestions') ...{ | |
c:count dir:direction => repeat(c, key(dir)); | |
dir:direction => key(dir); | |
tab => multi( | |
key('tab'), | |
modeOff('vscode-suggestWidgetMultipleSuggestions') | |
); | |
} | |
:count? again => repeat(optional(count, 1), new PreviousCommand()); | |
multi select lines => vscode('editor.action.insertCursorAtEndOfEachLineSelected'); | |
&=>vscodeMode('findWidgetVisible') ...{ | |
regex => vscode('toggleFindRegex'); | |
case_sensitive => vscode('toggleFindCaseSensitive'); | |
next => vscode('editor.action.nextMatchFindAction'); | |
previous => vscode('editor.action.previousMatchFindAction'); | |
cmd:vscode_multi_select => cmd; | |
} | |
open next => vscode('workbench.action.nextEditorInGroup'); | |
open => multi( | |
vscode('workbench.action.quickOpen'), | |
modeOff('vscode-editorTextFocus') | |
); | |
&=>vscodeMode('editorHasSelection') ...{ | |
:count? cmd:vscode_select_command => repeat(optional(count, 1), cmd); | |
} | |
&=>vscodeMode('editorTextFocus') ...{ | |
copy => vscode('editor.action.clipboardCopyAction'); | |
jump => vscode('editor.action.jumpToBracket'); | |
page up => vscode('cursorPageUp'); | |
page down? => vscode('cursorPageDown'); | |
} | |
&=>vscodeMode('editorTextFocus && !editorReadonly') ...{ | |
undo => vscode('undo'); | |
redo => vscode('redo'); | |
cut => vscode('editor.action.clipboardCutAction'); | |
home => vscodeSelectable('cursorHome'); | |
end => vscodeSelectable('cursorEnd'); | |
:count? cmd:vscode_edit_repeatable => repeat(optional(count, 1), cmd); | |
first_line => vscodeSelectable('cursorTop'); | |
last line => vscodeSelectable('cursorBottom'); | |
go to ...{ | |
top => vscodeSelectable('cursorTop'); | |
bottom => vscodeSelectable('cursorBottom'); | |
line :number => multi( | |
vscode('workbench.action.gotoLine'), | |
type(`${number}\n`) | |
); | |
} | |
:count? select cmd:vscode_select_command => multi( | |
repeat(optional(count, 1), cmd), | |
mode('vscode-editorHasSelection') | |
); | |
comment line => vscode('editor.action.commentLine'); | |
cmd:dictate_command => vscodeType(cmd); | |
} | |
!{vscodeMode('inDebugMode')} ...{ | |
start debugging => vscode('workbench.action.debug.start'); | |
} | |
cmd:dictate_command => cmd; | |
} | |
&chrome ...{ | |
tab :number => key(`ctrl-${number}`); | |
switch tab => key('ctrl-9'); | |
search :say? => multi(key('ctrl-k'), optional(say, noop()), say ? key('enter') : noop()); | |
google :say? => multi(key('ctrl-k'), optional(say, noop()), say ? key('enter') : noop()); | |
open tools => key('ctrl-shift-j'); | |
close tools => key('ctrl-shift-j'); | |
link => escaped(key('f')); | |
big link => escaped(key('F')); | |
close tab? => key('ctrl-w'); | |
open tab? :website => multi(key('ctrl-t'), type(website), key('enter')); | |
open tab? => key('ctrl-t'); | |
undo => key('ctrl-z'); | |
tab => key('tab'); | |
go_to ...{ | |
top => type('gg'); | |
bottom => type('G'); | |
line :number => type(`:${number}`); | |
:website => multi(key('ctrl-l'), type(website), key('enter')); | |
:dictate => multi(key('ctrl-l'), dictate); | |
} | |
new tab :website => multi(key('ctrl-t'), type(website), key('enter')); | |
new tab => key('ctrl-t'); | |
select all => key('ctrl-a'); | |
next tab => key('ctrl-tab'); | |
previous tab => key('ctrl-shift-tab'); | |
reopen tab => key('ctrl-shift-t'); | |
reopened at => key('ctrl-shift-t'); | |
back => key('H'); | |
forward => key('L'); | |
refresh => key('ctrl-r'); | |
l:letter => key(l); | |
k:modified_key => key(k); | |
hold key k:key => new KeyHoldCommand(k, true); | |
escape => multi(cancel(), key('escape')); | |
find :dictate? => multi(key('ctrl-f'), optional(dictate, noop())); | |
:dictate => dictate; | |
} | |
hold key k:key => new KeyHoldCommand(k, true); | |
cancel => cancel(); | |
key k:key => key(k); | |
k:modified_key => key(k); | |
page up => key('pageup'); | |
page down? => key('pagedown'); | |
type :ascii_string => type(ascii_string); | |
dictate :dictate => dictate; | |
word :word => type(word); | |
&vimVisual ...{ | |
swap corner => key('O'); | |
swap => key('o'); | |
change => multi(key('c'), modeOff('vim-visual'), mode('vim-insert')); | |
delete => multi(key('d'), modeOff('vim-visual')); | |
indent => multi(key('>'), modeOff('vim-visual')); | |
dedent => multi(key('<'), modeOff('vim-visual')); | |
format => multi(key('='), modeOff('vim-visual')); | |
replace k:key => multi(key('r'), key(k), modeOff('vim-visual')); | |
surround s:surrounder => multi(type(`S${s}`), modeOff('vim-visual')); | |
cut => multi(key('x'), modeOff('vim-visual')); | |
global yank => multi(type('"+y'), modeOff('vim-visual')); | |
sort => multi(type(':!sort\n'), modeOff('vim-visual')); | |
yank => multi(key('y'), modeOff('vim-visual')); | |
unique => multi(type(':!sort\ngv:!uniq\n'), modeOff('vim-visual')); | |
d:vim_direction => type(d); | |
undo => noop(); | |
} | |
&vim ...{ | |
exit without save => vimex('q!'); | |
save exit => vimex('wq'); | |
save as => escaped(type(':w ')); | |
save => vimex('w'); | |
switch buffer => escaped(repeat(2, key('ctrl-w'))); | |
close buffer => vimex('bd'); | |
flip => escaped(key('ctrl-6')); | |
} | |
&vimNotInsert ...{ | |
f:vim_find empty line => type(`${f}^$\n`); | |
f:vim_find :dictate? => multi(type(f), optional(dictate, noop())); | |
previous => type('N'); | |
next => type('n'); | |
word => key('w'); | |
forward until? c:ascii => type(`f${c}`); | |
back until? c:ascii => type(`F${c}`); | |
:direction :count => repeat(count, key(direction)); | |
// Jumps to other side [bracket/etc] | |
jump => key('%'); | |
mark :letter => type(`m${letter}`); | |
go_to ...{ | |
top => type('gg'); | |
bottom => type('G'); | |
:letter => type(`'${letter}`); | |
} | |
} | |
&vimNormal ...{ | |
open above => multi(type('O'), mode('vim-insert')); | |
open => multi(type('o'), mode('vim-insert')); | |
above => multi(type('O'), mode('vim-insert')); | |
append end => multi(type('A'), mode('vim-insert')); | |
append => multi(type('a'), mode('vim-insert')); | |
insert => multi(type('i'), mode('vim-insert')); | |
big replace => multi(type('R'), mode('vim-insert')); | |
:number => type(`${number}`); | |
create macro :letter => type(`q${letter}`); | |
macro :letter => type(`q${letter}`); | |
play :letter => type(`@${letter}`); | |
end macro => type(`q`); | |
big cut => type('x'); | |
cut => type('x'); | |
replace k:key => multi(key('r'), key(k)); | |
paste from k:ascii => type(`${k}+p`); | |
big paste => type('P'); | |
paste above => type('P'); | |
paste => type('p'); | |
repeat => type('.'); | |
undo => type('u'); | |
visual dir:vim_direction => multi(type(`v${dir}`), mode('vim-visual')); | |
visual block => multi(key('ctrl-v'), mode('vim-visual')); | |
visual line => multi(type('V'), mode('vim-visual')); | |
visual => multi(type('v'), mode('vim-visual')); | |
reselect => multi(type('gv'), mode('vim-visual')); | |
tree :folder? => vimex(`NERDTree ${optional(folder, '/home/josh')}`); | |
file :folder? => vimex(`FZF ${optional(folder, '/home/josh')}`); | |
big change => key('C'); | |
change ...{ | |
surrounding a:surrounder b:surrounder => type(`cs${a}${b}`); | |
line => multi(type('cc'), mode('vim-insert')); | |
dir:vim_direction => multi(type(`c${dir}`), mode('vim-insert')); | |
} | |
big delete => key('D'); | |
delete ...{ | |
line => type('dd'); | |
surrounding s:surrounder => type(`ds${s}`); | |
dir:vim_direction => type(`d${dir}`); | |
} | |
big yank => key('Y'); | |
yank ...{ | |
line => type('yy'); | |
dir:vim_direction => type(`y${dir}`); | |
} | |
indent ...{ | |
line => type('>>'); | |
dir:vim_direction => type(`>${dir}`); | |
} | |
dedent ...{ | |
line => type('<<'); | |
dir:vim_direction => type(`<${dir}`); | |
} | |
:editor_movement => editor_movement; | |
:ascii => key(ascii); | |
} | |
&vimTree ...{ | |
change :number => type(`:${number}\nC`); | |
change => type('C'); | |
open :number => type(`:${number}\no`); | |
open => type('o'); | |
tree :folder? => vimex(`NERDTree ${optional(folder, '/home/josh')}`); | |
} | |
&vimRebase ...{ | |
cmd:rebase_command => multi(type(`cw${cmd}`), key('escape'), key('enter')); | |
} | |
&vimInsert ...{ | |
node require :ident => typeLine(`const ${ident} = require('${ident}');`); | |
delete => key('delete'); | |
paste editor => multi(key('ctrl-r'), key('"')); | |
paste clipboard? => multi(key('ctrl-r'), key('*')); | |
escape => multi(cancel(), key('escape')); | |
:dictate => dictate; | |
} | |
enter => key('enter'); | |
undo => key('ctrl-z'); | |
redo => key('ctrl-r'); | |
escape => multi(cancel(), key('escape')); | |
slap it? => key('enter'); | |
&bash cmd:dictate_command => cmd; | |
/***** | |
HELPERS | |
*****/ | |
folder = ...{ | |
box :authbox_folder => `/home/josh/authbox${authbox_folder}`; | |
box => `/home/josh/authbox`; | |
voice => "/home/josh/pegvoice/src"; | |
} | |
authbox_folder = ...{ | |
lib => "/authbox-api/lib"; | |
tests => "/authbox-api/tests"; | |
apps => "/apps"; | |
s => "/apps/s"; | |
sierra => "/apps/s"; | |
config => "/config"; | |
} | |
i3screen = ...{ | |
dash => '-'; | |
equal => '='; | |
:number => number; | |
} | |
website = ...{ | |
calendar => 'https://google.com/calendar'; | |
news => 'https://news.ycombinator.com'; | |
fast mail => 'https://www.fastmail.com'; | |
google calendar => 'https://google.com/calendar'; | |
google flights => 'https://www.google.com/flights'; | |
google => 'https://www.google.com'; | |
gmail => 'https://mail.google.com'; | |
reddit :word? => ( | |
"https://www.reddit.com" + (word ? `/r/${optional(word)}` : '') | |
); | |
slack => 'https://smyte.slack.com/messages'; | |
} | |
:editor_movement => editor_movement; | |
/*** | |
DEFINITIONS | |
***/ | |
_modified_key | |
= capital _ k:_key { return `shift-${k}`; } | |
/ alt _ k:_key { return `alt-${k}`; } | |
/ control _ alt _ k:_key { return `ctrl-alt-${k}`; } | |
/ control _ k:_key { return `ctrl-${k}`; } | |
/ shift k_ :_key { return `shift-${k}`; } | |
_editor_movement = count:(_count _) k:(_direction / backspace / space / slap) { | |
return repeat(extractOptional(count, 0, 1), key({ | |
slap: 'enter', | |
}[k] || k)); | |
} | |
:direction => key(direction); | |
:count :direction => repeat(count, key(direction)); | |
backspace => key('backspace'); | |
:count backspace => repeat(count, key('backspace')); | |
_vim_find = find prev:(_ previous)? { | |
return prev ? '?' : '/'; | |
} | |
_vim_direction = pos:((_vim_inside / _vim_around) _)? dir:( | |
word / _paren / _vim_until / _vim_including / _surrounder | |
) { | |
return extractOptional(pos, 0, '') + ({ | |
word: 'w', | |
}[dir] || dir); | |
} | |
_vim_inside = (inner / inside / in) { return 'i'; } | |
_vim_around = (around / outside) { return 'a'; } | |
_vim_including = (including) _ code:_ascii { | |
return `f${code}`; | |
} | |
_vim_until = (to / until) _ code:_ascii { | |
return `t${code}`; | |
} | |
_vscode = &{ | |
return options.mode.has('vscode'); | |
}; | |
_chrome = &{ | |
return options.mode.has('chrome'); | |
}; | |
_slack = &{ | |
return options.mode.has('slack'); | |
}; | |
_vim = &{ | |
return options.mode.has('vim'); | |
}; | |
_vimNormal = &{ | |
return ( | |
options.mode.has('vim') && | |
!options.mode.has('vim-insert') && | |
!options.mode.has('vim-tree') && | |
!options.mode.has('vim-visual') | |
); | |
}; | |
_vimNotInsert = &{ | |
return ( | |
options.mode.has('vim') && | |
!options.mode.has('vim-insert') | |
); | |
}; | |
_bash = &{ | |
return ( | |
options.mode.has('terminal') || | |
options.mode.has('vscode-terminalFocus') | |
); | |
}; | |
_vimInsert = &{ | |
return options.mode.has('vim-insert'); | |
}; | |
_vimVisual = &{ | |
return options.mode.has('vim-visual'); | |
}; | |
_vimTree = &{ | |
return options.mode.has('vim-tree'); | |
}; | |
_vimRebase = &{ | |
return options.mode.has('vim-rebase'); | |
}; | |
_direction = (up / down / left / right); | |
_keys = head:_key "."? tail:(_ _key "."?)* { | |
return [head, ...extractList(tail, 1)]; | |
} | |
_say = words:_say_words { | |
return type(words.join(' ')); | |
} | |
_say_words = head:_word tail:_say_word* (_ unsay)? { | |
return [head, ...tail]; | |
} | |
_say_word = _ !unsay w:_word { return w; } | |
_dictate = head:_dictate_command tail:(_ _dictate_command &_)* { | |
return multi(head, ...extractList(tail, 1)); | |
} | |
_dictate_command | |
= d:_special_dictate { return d; } | |
/ k:_dictate_keys { return k; } | |
/ joiner:_dictate_joiner _ words:_say_words { | |
words = flatten(words.map(w => w.toLowerCase().split('-'))); | |
return type(joiner(words)); | |
} | |
/ i:_ident_word { return type(i); } | |
_dictate_joiner | |
= big:(big _)? camel { | |
return (words => camel(words, big || false)); | |
} | |
/ snake { return snake; } | |
_dictate_compare = w:(greater / less) equal:((_ or)? _ equal)? { | |
return type(' ' + ({ | |
greater: '>', | |
less: '<', | |
}[w]) + (equal ? '=' : '') + ' '); | |
} | |
dictate_keys = ...{ | |
k:modified_key => key(k); | |
:count d:dictate_repeatable => repeat(count, d); | |
k:non_digit_key => key(k); | |
page => key('pagedown'); | |
d:dictate_repeatable => d; | |
} | |
special_dictate = ...{ | |
:special_word => type(special_word); | |
:dictate_compare => dictate_compare; | |
say :say => say; | |
word :word => type(word); | |
type s:ascii_string => type(s); | |
key k:key => key(k); | |
at me => type('@yud.co.za'); | |
ellipsis => type('...'); | |
comma slap => type(',\n'); | |
comma => type(', '); | |
lee => type('let '); | |
const => type('const '); | |
finish => type(';\n'); | |
class words:say_words => type('class ' + camel(words, true)); | |
} | |
special_word = ...{ | |
dotcom => '.com'; | |
equal_to => ' === '; | |
equal => ' = '; | |
not_equal => ' !== '; | |
greater => ' > '; | |
less => ' < '; | |
arrow => ' => '; | |
or => ' || '; | |
and => ' && '; | |
comment => '// '; | |
to do => '@TODO'; | |
} | |
_dictate_repeatable = k:(_direction / backspace / space / slap / delete) { | |
return key({ | |
slap: 'enter', | |
}[k] || k); | |
} | |
_ident = _ident_word | |
_ident_word | |
= n:_ident_number { return n; } | |
/ w:_word { return w.toLowerCase(); }; | |
_ident_number = (number _)? head:_number tail:(_ _number)* &_ { | |
return [head, ...extractList(tail, 1)].join(''); | |
} | |
word = ...{ | |
smyte => 'smyte'; | |
trace => 'trc'; | |
:anything => anything; | |
} | |
_anything = (!_ .)+ &_ { | |
// Take the first entry dragon returns | |
return text().split('\\')[0].toLowerCase(); | |
} | |
_rebase_command = (pick / squash / reword / edit / drop); | |
_key "<key>" | |
= _non_digit_key | |
/ _digit; | |
_non_digit_key "<key>" | |
= enter | |
/ escape | |
/ backspace | |
/ home | |
/ end | |
/ pageup | |
/ pagedown | |
/ _paren | |
/ _direction | |
/ _non_digit_ascii; | |
paren = ...{ | |
left_curly => '{' || 'balance }'; | |
left_paren => '('; | |
left_square => '['; | |
left_triangle => '<'; | |
right_curly => !'balance {' || '}'; | |
right_paren => ')'; | |
right_square => ']'; | |
right_triangle => '>'; | |
} | |
_ascii_string = head:_ascii tail:(_ _ascii)* { | |
return [head, ...extractList(tail, 1)].join(''); | |
} | |
_ascii "<ascii>" = _digit / _non_digit_ascii; | |
non_digit_ascii "<ascii nd>" = ...{ | |
and => '&'; | |
at => '@'; | |
backslash => '\\'; | |
backtick => '`'; | |
big_quote => '"'; | |
caret => '^'; | |
colon => ':'; | |
comma => ','; | |
dash => '-'; | |
dollar => '$'; | |
equal => '='; | |
exclamation => '!'; | |
greater => '>'; | |
hash => '#'; | |
less => '<'; | |
percent => '%'; | |
period => '.'; | |
pipe => '|'; | |
plus => '+'; | |
question => '?'; | |
quote => '\''; | |
semicolon => ';'; | |
slash => '/'; | |
space => ' '; | |
star => '*'; | |
tab => '\t'; | |
tilde => '~'; | |
underscore => '_'; | |
:paren => paren; | |
:right_paren => right_paren; | |
:letter => letter; | |
} | |
_letter = _phonetic_letter / _alphabet_letter; | |
_phonetic_letter = capital:((big / capital) _)? code:( | |
alfa / | |
bravo / | |
charlie / | |
delta / | |
echo / | |
foxtrot / | |
golf / | |
hotel / | |
india / | |
juliett / | |
kilo / | |
lima / | |
mike / | |
november / | |
oscar / | |
papa / | |
quebec / | |
romeo / | |
sierra / | |
tango / | |
uniform / | |
victor / | |
whiskey / | |
xray / | |
yankee / | |
zulu | |
) &_ { | |
const letter = code.charAt(0).toLowerCase(); | |
return capital ? letter.toUpperCase() : letter;; | |
}; | |
_alphabet_letter = capital:((big / capital) _)? letter:( | |
a / b / c / d / e / f / g / h / i / j / k / l / m / | |
n / o / p / q / r / s / t / u / v / w / x / y / z | |
) { | |
if (text().includes('uppercase-letter')) { | |
capital = true; | |
} | |
return capital ? letter.toUpperCase() : letter.toLowerCase(); | |
}; | |
// @TODO: This doesn't work unfortunately | |
_repeat = count:(_count _)? { | |
if (count) { | |
return ((cmd) => repeat(count[0], cmd)); | |
} else { | |
return (cmd => cmd); | |
} | |
} | |
_count = _tuple_length / _number; | |
_tuple_length = length:(single / double / triple) &_ { | |
return { | |
"single": 1, | |
"double": 2, | |
"triple": 3, | |
}[length]; | |
} | |
_number = _number_hundred_word / _number_hundred / _number_ten; | |
_number_hundred_word = a _ hundred { return 100; } | |
_number_hundred = hundred:(_number_ten _ "hundred" (_ "and")?) ten:(_ _number_ten)? { | |
let number = 0; | |
if (hundred) { | |
number += hundred[0] * 100; | |
} | |
return number + (ten ? ten[1] : 0); | |
} | |
_number_ten = _number_ten_word / _number_ten_combo / _digit; | |
number_ten_word = ...{ | |
ten => 10; | |
eleven => 11; | |
twelve => 12; | |
thirteen => 13; | |
fourteen => 14; | |
fifteen => 15; | |
sixteen => 16; | |
seventeen => 17; | |
eighteen => 18; | |
nineteen => 19; | |
} | |
number_ten_combo_word = ...{ | |
twenty => 20; | |
thirty => 30; | |
fourty => 40; | |
fifty => 50; | |
sixty => 60; | |
seventy => 70; | |
eighty => 80; | |
ninety => 90; | |
} | |
_number_ten_combo = word:_number_ten_combo_word digit:(_ _digit)? { | |
return word + (extractOptional(digit, 1) || 0); | |
} | |
_digit = word:( | |
one / two / three / four / five / | |
six / seven / eight / nine / naught / zero / | |
"1" / "2" / "3" / "4" / "5" / "6" / "7" / "8" / "9" / "0" | |
) _dragon? { | |
const digits = { | |
"one": 1, | |
"two": 2, | |
"three": 3, | |
"four": 4, | |
"five": 5, | |
"six": 6, | |
"seven": 7, | |
"eight": 8, | |
"nine": 9, | |
"zero": 0, | |
"naught": 0, | |
}; | |
return digits.hasOwnProperty(word) ? digits[word] : parseInt(word, 10); | |
} | |
surrounder = ...{ | |
p:right_paren => p; | |
backtick => '`'; | |
quote => "'"; | |
big quote => '"'; | |
} | |
_right_paren = char:( | |
curly / | |
paren / | |
square / | |
triangle | |
) &_ { | |
return { | |
/* { <= needed for peg rule parsing bug */ | |
curly: '}', | |
paren: ')', | |
square: ']', | |
triangle: '>', | |
}[char]; | |
} | |
left_curly = (left _ curly / "{" _dragon?) &_ { return "left_curly"; } | |
left_paren = (left _ paren / "(" _dragon?) &_ { return "left_paren"; } | |
left_square = (left _ square / "[" _dragon?) &_ { return "left_square"; } | |
left_triangle = (left _ triangle / "<" _dragon?) &_ { return "left_triangle"; } | |
right_curly = (right _ curly / "}" _dragon?) &_ { return "right_curly"; } | |
right_paren = (right _ paren / ")" _dragon?) &_ { return "right_paren"; } | |
right_square = (right _ square / "]" _dragon?) &_ { return "right_square"; } | |
right_triangle = (right _ triangle / ">" _dragon?) &_ { return "right_triangle"; } | |
spell exit / x it; | |
spell undo / and do / under; | |
spell equal_to / equal to; | |
spell big_quote / big quote; | |
spell not_equal / not equal; | |
spell a; | |
spell alt; | |
spell and; | |
spell apps; | |
spell around; | |
spell arrow; | |
spell assign / the sign / and signed; | |
spell at; | |
spell backslash / "\\" / "\\backslash\\backslash"; | |
spell backspace / back space / that space / backtrace; | |
spell backtick / "`\\backquote\\back tick"; | |
spell b / be; | |
spell box; | |
spell capital; | |
spell caret / carrot / "^\\caret\\caret"; | |
spell close / closed; | |
spell colon / ":"; | |
spell comma / ","; | |
spell config; | |
spell control; | |
spell create / great / created; | |
spell c / see; | |
spell curly; | |
spell d; | |
spell dash / "-" / "–\\dash\\dash"; | |
spell dedent / decent / "didn't" / the dent; | |
spell dictate / dictates; | |
spell diff / def / differential / dif / diffs; | |
spell do; | |
spell dollar; | |
spell dotcom / ".com\\\\dot com"; | |
spell double; | |
spell down / dance; | |
spell drop; | |
spell e; | |
spell edit; | |
spell eight / it; | |
spell eighty; | |
spell ellipsis / "…"; | |
spell end; | |
spell enter / inter / into / "\\new-line\\new line"; | |
spell equal / equals; | |
spell escape / escaped; | |
spell exclamation; | |
spell f; | |
spell fifty; | |
spell find; | |
spell five; | |
spell focus / focused; | |
spell forward; | |
spell four / for; | |
spell fourty / forty; | |
spell g; | |
spell gmail; | |
spell go_to / go to / good; | |
spell go_to_sleep / go to sleep / good asleep; | |
spell greater / grader / grade or; | |
spell h; | |
spell hash; | |
spell home; | |
spell hundred; | |
spell i; | |
spell in; | |
spell including; | |
spell indent; | |
spell inner / in a; | |
spell inside; | |
spell j; | |
spell k; | |
spell key / he; | |
spell l / al; | |
spell lee / leigh / li / leave; | |
spell left; | |
spell less; | |
spell letter / letters; | |
spell lib / lab; | |
spell line / lines; | |
spell m; | |
spell me; | |
spell n; | |
spell naught / nought; | |
spell news / new / new is; | |
spell nine; | |
spell ninety; | |
spell not; | |
spell number; | |
spell one; | |
spell o / oh; | |
spell open / opened; | |
spell or; | |
spell outside; | |
spell p; | |
spell pagedown / page down; | |
spell pageup / page up; | |
spell paren / parental / prevent; | |
spell paste / based; | |
spell percent; | |
spell period / "." / ".\\dot\\dot"; | |
spell pick / pip; | |
spell pipe; | |
spell plus; | |
spell q; | |
spell question; | |
spell quote / quotes; | |
spell r / are; | |
spell rebase / "we base"; | |
spell reddit / redick; | |
spell reopen / reopened; | |
spell reword; | |
spell right / write / rights; | |
spell s; | |
spell save / safe / saved; | |
spell say / save; | |
spell screen / green; | |
spell semicolon / ";"; | |
spell seven; | |
spell seventy; | |
spell shift; | |
spell single; | |
spell six; | |
spell sixty; | |
spell slash / "/" / "/\\slash\\slash"; | |
spell smyte / smite; | |
spell space; | |
spell square; | |
spell squash; | |
spell star; | |
spell t; | |
spell tab / "\\tab-key\\tab key"; | |
spell ten; | |
spell tests; | |
spell than; | |
spell thirty; | |
spell three; | |
spell tilde / "~\\tilde\\tilde"; | |
spell to / do; | |
spell tree / treat; | |
spell triangle; | |
spell triple; | |
spell twenty; | |
spell two / to; | |
spell u; | |
spell under; | |
spell underscore / "_" / "_\\underscore\\underscore"; | |
spell unsay / under say / and say; | |
spell until; | |
spell up; | |
spell v / the; | |
spell voice; | |
spell w; | |
spell wake_up / wake up / "wake-up" / "wake up"; | |
spell window / windows; | |
spell word / words; | |
spell x; | |
spell y; | |
spell yank / copy; | |
spell zero; | |
spell z / said; | |
spell ls / ellis; | |
spell multi / "multi-"; | |
spell regex / rejects; | |
spell case_sensitive / "case-sensitive"; | |
spell camel; | |
spell snake; | |
spell line_up / line up / lineup; | |
spell multi_select / multi cursor / multi select; | |
spell visual / select; | |
spell commit / comma it; | |
spell first_line / "first-line" / first line; | |
spell toggle_any / toggle / open / close / show; | |
spell alfa / alpha / offer / of the; | |
spell bravo / brother; | |
spell charlie; | |
spell delta; | |
spell echo / easy; | |
spell foxtrot; | |
spell golf; | |
spell hotel; | |
spell india; | |
spell juliett / juliet; | |
spell kilo; | |
spell lima; | |
spell mike; | |
spell november; | |
spell oscar; | |
spell papa / pepper; | |
spell quebec / "québec"; | |
spell romeo; | |
spell sierra / c error / ciera; | |
spell tango; | |
spell uniform; | |
spell victor; | |
spell whiskey; | |
spell xray / "x-ray"; | |
spell yankee; | |
spell zulu / sooner; | |
_dragon = "\\" (!_ [ -~])+ &_; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment