Skip to content

Instantly share code, notes, and snippets.

@lexxish
Last active January 25, 2020 01:39
Show Gist options
  • Save lexxish/1a9582f175119f36a508282a81761d2a to your computer and use it in GitHub Desktop.
Save lexxish/1a9582f175119f36a508282a81761d2a to your computer and use it in GitHub Desktop.
#
# __author__ = "lexxish"
#
from dragonspeak.rules.vim_helper import VimHelper
from dragonspeak.rules.vim_mode import VimMode
class SurfingKeysMode():
CARET_MODE = 1
NORMAL = 2
INSERT = 3
VISUAL = 4
class SurfingKeysHelper(VimHelper):
def enter_caret_mode(self):
self.CURRENT_MODE = SurfingKeysMode.CARET_MODE
# __author__ = "lexxish"
#
# ---------------------------------------------------------------------------
import sys
from dragonfly import (Repeat, Function, ShortIntegerRef, Dictation, Pause)
from dragonspeak.dragon.action import F, T, K
from dragonspeak.grammars.vim_grammar import *
from dragonspeak.dragon.inherited_rule import InheritedRule
from dragonspeak.rules.surfing_keys_helper import SurfingKeysHelper
from dragonspeak.rules.vim_helper import VimHelper
from dragonspeak.grammars import ide_grammar as ide
from castervoice.lib.actions import Text
from dragonspeak.rules.vim_mode import VimMode
vh = SurfingKeysHelper(VimMode.NORMAL)
def to_text(text=""):
T(text).execute()
def surfing(action):
action.execute()
def enter_caret_mode():
Text("v").execute()
class SurfingKeysRule(InheritedRule):
pronunciation = "surfing keys"
def get_mapping(self):
return SurfingKeysRule.mapping
def get_extras(self):
return SurfingKeysRule.extras + super(SurfingKeysRule, self).get_extras()
mapping = {
# directions
"%s [<n>]" % ide.DOWN: F(surfing, K("j", True) * Repeat(extra="n")),
"%s [<n>]" % ide.UP: K("k") * Repeat(extra="n"),
"%s [<n>]" % ide.RIGHT: K("h") * Repeat(extra="n"),
"%s [<n>]" % ide.LEFT: K("l") * Repeat(extra="n"),
"google [<text>]": T("og") + Pause("30") + F(to_text),
# TODO Improve visual selection mode with plugin to track mode and auto switch to selection mode from cursor
# mode
"light|lite": T("v"),
"follow|link[s]|leap": T("f"),
"new (follow|link[s]|leap)": T("af"),
HOME: T("0"),
HOMING: vh.visual(T("0")),
END: Function(lambda n: T("$" + "$" * (n + 1)).execute()),
ENDING: vh.visual(T("$")),
SKIP: T("w") * Repeat(extra="n"),
SKIPPING: vh.visual(T("e") * Repeat(extra="n")),
SKIPPED: T("de") * Repeat(extra="n"),
TRIP: T("b") * Repeat(extra="n"),
TRIPPING: vh.visual(T("b")),
TRIPPED: T("db"),
"close [tabs] to left": T("gx0"),
"close [tabs] to right": T("gx$"),
"toggle surfingkeys": K("a-s"),
"edit input": K("I"),
"save session": T("ZZ"),
"restore session": T("ZR"),
}
extras = [
ShortIntegerRef("n", 1, 10000, 1),
Dictation("text", default="")
]
#
# __author__ = "lexxish"
#
from dragonfly import (Repeat, Function, ShortIntegerRef, Dictation, Pause)
from dragonspeak.dragon.action import F, T, K
from dragonspeak.grammars.vim_grammar import *
from dragonspeak.dragon.inherited_rule import InheritedRule
from dragonspeak.rules.surfing_keys_helper import SurfingKeysHelper
from dragonspeak.grammars import ide_grammar as ide
from castervoice.lib.actions import Text
from dragonspeak.rules.vim_mode import VimMode
vh = SurfingKeysHelper(VimMode.NORMAL)
def to_text(text=""):
T(text).execute()
def surfing(action):
action.execute()
def enter_caret_mode():
Text("v").execute()
class SurfingKeysRule(InheritedRule):
pronunciation = "surfing keys"
def get_mapping(self):
return SurfingKeysRule.mapping
def get_extras(self):
return SurfingKeysRule.extras + super(SurfingKeysRule, self).get_extras()
mapping = {
# directions
"%s [<n>]" % ide.DOWN: F(surfing, K("j", True) * Repeat(extra="n")),
"%s [<n>]" % ide.UP: K("k") * Repeat(extra="n"),
"%s [<n>]" % ide.RIGHT: K("h") * Repeat(extra="n"),
"%s [<n>]" % ide.LEFT: K("l") * Repeat(extra="n"),
"google [<text>]": T("og") + Pause("30") + F(to_text),
# TODO Improve visual selection mode with plugin to track mode and auto switch to selection mode from cursor
# mode
"light|lite": T("v"),
"follow|link[s]|leap": T("f"),
"new (follow|link[s]|leap)": T("af"),
HOME: T("0"),
HOMING: vh.visual(T("0")),
END: Function(lambda n: T("$" + "$" * (n + 1)).execute()),
ENDING: vh.visual(T("$")),
SKIP: T("w") * Repeat(extra="n"),
SKIPPING: vh.visual(T("e") * Repeat(extra="n")),
SKIPPED: T("de") * Repeat(extra="n"),
TRIP: T("b") * Repeat(extra="n"),
TRIPPING: vh.visual(T("b")),
TRIPPED: T("db"),
"close [tabs] to left": T("gx0"),
"close [tabs] to right": T("gx$"),
"toggle surfingkeys": K("a-s"),
"edit input": K("I"),
"save session": T("ZZ"),
"restore session": T("ZR"),
}
extras = [
ShortIntegerRef("n", 1, 10000, 1),
Dictation("text", default="")
]
import logging
from dragonfly import Key, Text, Function, Pause
from dragonspeak.dragon.action import Action, F, T
from dragonspeak.rules.vim_mode import VimMode
COMMAND_MODE_DELAY = 0
INSERT_MODE_DELAY = 0
class VimHelper():
def __init__(self, startingMode=VimMode.INSERT):
self.logger = logging.getLogger(__name__)
self.CURRENT_MODE = startingMode
def indent(self, indent_dedent):
action = ">"
if indent_dedent == "dedent":
action = "<"
if self.CURRENT_MODE == VimMode.VISUAL:
return Text(action).execute()
elif self.CURRENT_MODE == VimMode.NORMAL:
return Text(action*2).execute()
else:
return self.normal(action * 2).execute()
def set_mode_normal(self):
self.CURRENT_MODE = VimMode.NORMAL
def set_mode_insert(self):
self.CURRENT_MODE = VimMode.INSERT
def set_mode_visual(self):
self.CURRENT_MODE = VimMode.VISUAL
def enter_visual_mode(self):
self.logger.error("mode is " + str(self.CURRENT_MODE))
if self.CURRENT_MODE == VimMode.VISUAL:
action = Text("")
elif self.CURRENT_MODE == VimMode.NORMAL:
# Handles surfing keys
action = Key("v/30")
else:
action = Key("escape/%s, v, o, l, o" % COMMAND_MODE_DELAY)
self.CURRENT_MODE = VimMode.VISUAL
return action.execute()
def enter_insert_mode(self, end_of_line=False):
self.CURRENT_MODE = VimMode.INSERT
c = self.escape_if_visual(Text(""))
return self.add_insert_keys(c, end_of_line).execute()
def add_insert_keys(self, c, end_of_line=False):
if end_of_line:
c += Key("a/%s" % INSERT_MODE_DELAY)
else:
c += Key("i/%s" % INSERT_MODE_DELAY)
return c
def enter_normal_mode(self):
self.logger.error("entering command mode, mode was " + str(self.CURRENT_MODE))
return (
Function(self.set_mode_normal)
+ Function(self.escape_if_visual)
+ self.escape()
# TODO: after entering normal mode we must wait
# remove after https://youtrack.jetbrains.com/issue/VIM-1678 is fixed
# + Pause("10")
).execute()
def visual(self, c, adjust=True):
if adjust:
c = Text("l") + c
if self.CURRENT_MODE == VimMode.VISUAL:
return Action(c)
else:
return Action(Function(self.enter_visual_mode) + c)
def escape(self, c=Text(""), adjust=False):
return Key("escape/%s" % COMMAND_MODE_DELAY) + c
def normal(self, c, end_of_line=False):
# TODO won't work for end of line
c = T("l") + c # TODO can we move this to after we are out of normal mode?
c = F(self.enter_normal_mode) + c
c = self.escape_if_visual(c)
c = self.add_insert_keys(c, end_of_line)
c += Function(self.set_mode_insert)
return Action(c)
def escape_if_visual(self, c=Text("")):
if self.CURRENT_MODE == VimMode.VISUAL:
return self.escape(c)
return c
def insert(self, c, adjust=False):
c = self.escape_if_visual(c)
self.CURRENT_MODE = VimMode.INSERT
return Action(c)
def go_to_line_n(self):
return Text(":%(n)s") + Key("enter")
def move_x_lines_by_y(self, x, y, up_or_down):
if "+" == up_or_down:
y += x - 1
else:
y += 1
return self.normal(Text(":.,+" + str(x - 1) + "m %s" % up_or_down + str(y)) + Key("enter")).execute()
def log_mode(self):
self.logger.error(str(self.CURRENT_MODE))
return Text("").execute()
#
# __author__ = "lexxish"
#
from enum import Enum
class VimMode(Enum):
NORMAL = 2
INSERT = 3
VISUAL = 4
# __author__ = "lexxish"
#
from dragonfly import (Dictation, Choice, ShortIntegerRef, Pause, Repetition)
from dragonspeak.grammars import ide_grammar as ide
from dragonspeak.dragon.action import Action, T, F, K, Rep, A
from dragonspeak.grammars.basic_grammar import get_alphabet, get_capitalization, get_spacing, get_any_symbol, \
get_enclosing_symbols, SEMICOLON, COMMA
from dragonspeak.utilities.directory_utilities import open_file
from dragonspeak.grammars.vim_grammar import *
from dragonspeak.rules.vim_and_browser_rule import VimAndBrowserRule
from dragonspeak.rules.vim_helper import VimHelper
# global so it can be used with lambdas
v = VimHelper()
# TODO cleanup
BEFORE_COLON_DELAY = "10"
class VimRule(VimAndBrowserRule):
pronunciation = "jet brains"
DELAY = "30"
MULTIPLE_CHARACTERS = "<symbol_sequence>"
CHARACTERS = "%(symbol_sequence)s"
def get_mapping(self):
return self.merge(super(VimRule, self).get_mapping(), VimRule.mapping)
def get_extras(self):
return VimRule.extras + super(VimRule, self).get_extras()
mapping = {
# # modes
"visual mode": F(v.enter_visual_mode),
"insert mode": F(v.enter_insert_mode),
"command mode": F(v.enter_normal_mode),
# line operations
"lined [<n>](cut <n>)": v.normal(T("%(n)sdd")),
"lining %s [<n>]" % ide.UP: v.visual(T("V") + F(
lambda n: None if n == 1 else T(str(n - 1) + "k").execute())),
"lining [<n>]": v.visual(T("V") + F(
# TODO should n be measured as lines from line 0 as in n, not n-1 (add the option?)
lambda n: None if n == 1 else T(str(n - 1) + "j").execute())),
"line join|(join [line])": v.normal(T("J")),
ide.MOVE_LINE_UP: v.normal(F(lambda n: T(":m -" + (str(n + 1))).execute()) +
Pause(BEFORE_COLON_DELAY)
+ K("enter")),
ide.MOVE_LINE_DOWN: v.normal(T(":m +%(n)s") + Pause(BEFORE_COLON_DELAY) + K("enter")),
ide.GO_TO_LINE: v.normal(T(":%(n)s") + K("enter")),
ide.DELETE_LINE: v.normal(T("%(n)sdd")),
"[line] below": F(v.enter_normal_mode) + T("o") + F(v.set_mode_insert),
"[line] above": F(v.enter_normal_mode) + T("O") + F(v.set_mode_insert),
"below %s|%s below" % (SEMICOLON, SEMICOLON):
Action(T("$a;") + F(v.enter_normal_mode) + T("o") + F(v.set_mode_insert)),
"below %s|%s below" % (COMMA, COMMA):
Action(T("$a;") + F(v.enter_normal_mode) + T("o") + F(v.set_mode_insert)),
"<indent_dedent>": F(v.indent) + F(v.enter_insert_mode),
#
# # TODO duplicate grammars
ide.DELETE_TO_LINE_START: v.normal(T("d0")),
# ide.DELETE_TO_LINE_END: v.normal(T("d$")),
#
# # TODO add duple 5 up meaning duplicate 5 lines upward direction
# # TODO ":" just after normal mode command (not mode switch) requires delay
"duple <n> down": v.normal(T("%(n)sY") + F(lambda n: T(str(n - 1) + "jp").execute())),
ide.DUPLICATE_LINE_DOWN: v.normal(
T("yyp")
# TODO cleanup
+ Pause("80") # ???
+ F(lambda n:
None if n == 1
else (T(":m +" + str(n - 1))
# TODO cleanup
# + Pause("50")
+ K("enter")).execute())),
ide.DUPLICATE_LINE_UP: v.normal(
T("yyP")
# TODO cleanup
+ Pause("80") # ???
+ F(lambda n:
None if n == 1
else (T(":m -" + str(n))
# TODO cleanup
+ Pause("0") # TODO why so long for this one (P is slower than p?)?
+ K("enter")).execute())),
ide.COMMENT_LINE_X_TO_Y: v.normal(
T("mb:%(x)s") + K("enter/%s, c-v" % DELAY) + T("%(y)sG") + K(
"s-i") + T("#") + K("escape") + T("`b")),
"<x> (line|lines) down [<y>]": F(lambda x, y, v: v.move_x_lines_by_y(x, y, "+")),
"<x> (line|lines) up [<y>]": F(lambda x, y, v: v.move_x_lines_by_y(x, y, "-")),
# <x
ide.GO_TO_DECLARATION: v.normal(T("gd")),
# basic editing
"shock [<n>]": v.insert(K("enter") * Rep("n")),
"clear [<n>]": v.insert(K("backspace") * Rep("n")),
"deli [<n>]": v.insert(K("del") * Rep("n")),
"ace [<n>]": v.insert(K("space") * Rep("n")),
# "test one": K("escape") + T("/\ca") + K("enter") + T("i"),
# "test broken": K("escape, 5, k, i, escape, 5, j, i, escape, 5, k, i, escape, 5, j, i"),
"record [macro] [<letter>]": K("escape") + T("q%(letter)s") + T("i"),
"done [macro] [<letter>]": K("escape") + T("q") + Pause("30") + T("i"),
"play [macro] [<letter>] [<n>]": K("escape") + Pause("30") + T("%(n)s@%(letter)s"),
#
# # marks
"marking [<letter>]": v.normal(T("m%(letter)s")),
"mark [<letter>]": v.normal(T("`%(letter)s")),
"marked [<letter>]": v.normal(T("d`%(letter)s")),
"marky [<letter>]": v.normal(T("y`%(letter)s")),
#
# movement
HOME: v.normal(
T("%(n)s^")),
HOMING: v.visual(
T("%(n)s^")),
HOMED: v.normal(
T("d%(n)s^")),
END: v.normal(
T("%(n)s$"), end_of_line=True),
ENDING: v.visual(
T("%(n)s$")),
ENDED: v.normal(
T("d%(n)s$"), end_of_line=True),
SKIP: v.normal(
T("w") * Rep("n")),
SKIPPING: v.visual(T("e") * Rep("n")),
SKIPPED: v.normal(T("de") * Rep("n")),
TRIP: v.normal(T("b") * Rep("n")),
TRIPPING: v.visual(T("b")),
TRIPPED: v.normal(T("db")),
HOP: v.normal(T("W") * Rep("n")),
HOPPING: v.visual(T("W") * Rep("n")),
HOPPED: v.normal(T("dW") * Rep("n")),
FLOP: v.normal(T("B") * Rep("n")),
FLOPPING: v.visual(T("B") * Rep("n")),
"flopped [<n>]": v.normal(T("dB") * Rep("n")),
# # jump novakeen == jumped novakeen
# # jump julia == jumped julia
# # jumP != jumped
"fly %s [<n>]" % MULTIPLE_CHARACTERS:
F(lambda symbol_sequence:
v.normal(
T("/\c%s" % ''.join(symbol_sequence)) + K("enter")).execute()), # + Pause("15")),
"flying %s [<n>]" % MULTIPLE_CHARACTERS:
F(lambda symbol_sequence:
v.visual(
# ideavim bug need h before //e
T("/\c%s" % ''.join(symbol_sequence)) + K("enter") + Pause(
"15") + T("h//e") + K("enter")).execute()),
"(flew|flewed) %s [<n>]" % MULTIPLE_CHARACTERS:
F(lambda symbol_sequence:
v.visual(
T("/\c%s" % ''.join(symbol_sequence)) + K("enter") + Pause("15") + T(
"h//e") + K("enter, d") + F(v.enter_insert_mode)).execute()),
"fall %s [<n>]" % MULTIPLE_CHARACTERS:
F(lambda symbol_sequence:
v.normal(
T("?\\c%s" % ''.join(symbol_sequence)) + K("enter")).execute()),
"falling %s [<n>]" % MULTIPLE_CHARACTERS:
F(lambda symbol_sequence:
v.visual(
T("?\c%s" % ''.join(symbol_sequence)) + K("enter")
).execute()
),
"(falled|fell|felled) %s [<n>]" % MULTIPLE_CHARACTERS:
F(lambda symbol_sequence:
v.visual(
T("?\c%s" % ''.join(symbol_sequence)) + K("enter") + Pause("15") + K("d")).execute()),
"jump <letter>": A(K("cs-o, a") + T("%(letter)s")),
"jump <letter><letter2>": A(
K("cs-o, s") + T("%(letter)s%(letter2)s")),
"jump": A(
K("escape, cs-o, f")),
"leap": v.normal("%"),
#
# # v.visual mode
"light": F(v.enter_visual_mode),
"other": v.visual(T("o"), adjust=False),
"yank": v.visual(T('"*y') + F(v.enter_normal_mode)),
"cut": v.visual(T('"*d') + F(v.enter_normal_mode)),
# TODO moves left when at end of line
"put": v.normal(T('p')),
"[light with]in <enclosing_symbol>": v.visual(
T("li%(enclosing_symbol)s")),
"kill in <enclosing_symbol>": v.normal(
T("ci%(enclosing_symbol)s")),
"(yank|copy) in <enclosing_symbol>": v.normal(
T("yi%(enclosing_symbol)s")),
#
# # general vim
"center": v.normal(T('zz')),
#
# # find and replace vim
# "%s %s <text>" % (ide.FIND, ide.LEFT): v.command(T("?\c%(text)s") + K("enter")),
# "%s %s <text>" % (ide.FIND, ide.RIGHT): v.command(T("/\c%(text)s") + K("enter")),
# # kjump must be bound manually
ide.REPLACE_IN_CURRENT_FILE:
# TODO note will be in command mode after, but nothing we can do
A(
F(v.enter_normal_mode) + T(":") + K("percent") +
T("s//g") + K("left") * Rep(2)
),
ide.FIND_IN_CURRENT_FILE:
# TODO note will be in command mode after, but nothing we can do
A(
F(v.enter_normal_mode) + K("slash, backslash, c")
),
ide.FIND_NEXT_MATCH: v.normal(
T("n") * Rep("n")),
ide.FIND_PREVIOUS_MATCH: v.normal(
T("N") * Rep("n")),
#
# tabs
ide.CLOSE_TAB_N_TIMES: v.normal(
K("c-w,c/%s" % DELAY)) * Rep("n"),
ide.PREVIOUS_TAB: v.normal(
K("a-left/%s" % DELAY)) * Rep("n"),
# jet brains can only split horizontally or vertically
ide.CLOSE_PANE_N_TIMES: v.normal(
K("c-w,q/%s" % DELAY)) * Rep("n"),
ide.SPLIT_WINDOW_UP: v.normal(
K("c-w,s")),
ide.SPLIT_WINDOW_DOWN: v.normal(
K("c-w,s")),
ide.SPLIT_WINDOW_RIGHT: v.normal(
K("c-w,v")),
ide.SPLIT_WINDOW_LEFT: v.normal(
K("c-w,v")),
ide.SPLIT_MOVE_DOWN: v.normal(
K("cs-s,down")) * Rep("n"),
ide.SPLIT_MOVE_RIGHT: v.normal(
K("cs-s,right")) * Rep("n"),
ide.SPLIT_MOVE_LEFT: v.normal(
K("cs-s,left")) * Rep("n"),
# # must be bound manually below this point
# directions
"%s [<n>]" % ide.DOWN: K("down") * Rep("n"),
"%s [<n>]" % ide.UP: K("up") * Rep("n"),
"%s [<n>]" % ide.RIGHT: K("right") * Rep("n"),
"%s [<n>]" % ide.LEFT: K("left") * Rep("n"),
# quick motion
"[<n>] %s %s" % (ide.DOWN, MULTIPLE_CHARACTERS):
F(lambda symbol_sequence:
v.normal(K("down") * Rep("n") + T("0") + T("/\c%s" % ''.join(symbol_sequence)) + K("enter")).execute()),
"[<n>] %s %s" % (ide.UP, MULTIPLE_CHARACTERS):
F(lambda symbol_sequence:
v.normal(K("up") * Rep("n") + T("0") + T("/\c%s" ''.join(symbol_sequence)) + K("enter")).execute()),
"<any_symbol>":
v.insert(T("%(any_symbol)s")),
"log mode": F(v.log_mode),
ide.CANCEL: K("escape"),
# "(<capitalization> <spacing> | <capitalization> | <spacing>) <textnv>":
# v.insert(F(textformat.master_format_text))
"insert (debug|debugging)": v.insert(T('import pydevd\npydevd.settrace("localhost", port=5678)')),
"insert (to|two|too) do": v.insert(T('# TODO ')),
"insert (log|logging|logger)": v.insert(T('logger = logging.getLogger(__name__)\nlogger.error()') + K("left")),
"file <text>": F(open_file),
# manually bound
ide.EXPAND_SELECTION: v.visual(K("cs-o,e") * Rep("n")),
# manually bound
ide.SHRINK_SELECTION: v.visual(K("cs-o,w") * Rep("n")),
}
symbol_choice = get_any_symbol("symbol")
extras = [
Repetition(symbol_choice, min=1, max=4, name="symbol_sequence"),
get_alphabet(),
get_alphabet("letter2"),
get_any_symbol(),
get_any_symbol("any_symbol2"),
# get_any_symbol("character"),
# get_any_symbol("character2"),
# get_any_symbol("character3"),
# get_any_symbol("character4"),
get_any_symbol("any_symbol2"),
get_enclosing_symbols(),
ShortIntegerRef("n", 1, 1000, 1),
ShortIntegerRef("x", 1, 1000, 1),
ShortIntegerRef("y", 1, 1000, 1),
Dictation("text"),
get_capitalization(),
get_spacing(),
Dictation("textnv"),
Choice("indent_dedent", {
"indent": "indent",
"dedent": "dedent"
})
]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment