From 15a5804b7c50711bc0153f7379e38f5cf8f2d13c Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Mon, 9 Aug 2021 22:54:24 +0100 Subject: [PATCH 01/20] Attempt to optimize DFA --- src/actions/move_bring.py | 23 ------------- src/actions/multiple_target_action.py | 47 +++++++++++++++++++++++++++ src/actions/swap.py | 14 -------- src/call.py | 14 -------- src/compound_targets.py | 21 +++++++++--- src/cursorless.talon | 28 +++++++--------- src/modifiers/surrounding_pair.py | 1 - src/primitive_target.py | 11 ++----- 8 files changed, 78 insertions(+), 81 deletions(-) delete mode 100644 src/actions/move_bring.py create mode 100644 src/actions/multiple_target_action.py delete mode 100644 src/actions/swap.py delete mode 100644 src/call.py diff --git a/src/actions/move_bring.py b/src/actions/move_bring.py deleted file mode 100644 index 2580f506..00000000 --- a/src/actions/move_bring.py +++ /dev/null @@ -1,23 +0,0 @@ -from ..primitive_target import STRICT_HERE -from talon import Context, Module - -mod = Module() - -ctx = Context() -ctx.matches = r""" -tag: user.cursorless -""" - - -mod.list("cursorless_move_bring_action", desc="Cursorless move or bring actions") -ctx.lists["self.cursorless_move_bring_action"] = {"bring", "move"} - - -@mod.capture(rule=(" [to ]")) -def cursorless_move_bring_targets(m) -> str: - target_list = m.cursorless_target_list - - if len(target_list) == 1: - target_list = target_list + [STRICT_HERE] - - return target_list diff --git a/src/actions/multiple_target_action.py b/src/actions/multiple_target_action.py new file mode 100644 index 00000000..f3df9a1b --- /dev/null +++ b/src/actions/multiple_target_action.py @@ -0,0 +1,47 @@ +from ..primitive_target import STRICT_HERE +from talon import Context, Module + +mod = Module() + +ctx = Context() +ctx.matches = r""" +tag: user.cursorless +""" + + +mod.list("cursorless_multiple_target_action", desc="Cursorless move or bring actions") +ctx.lists["self.cursorless_multiple_target_action"] = {"bring", "move", "swap", "call"} + +target_separator = { + "onto", + "before", # TODO: Make this work + "after", # TODO: Make this work +} + +mod.list( + "cursorless_target_separator", desc="A symbol that comes in pairs, eg brackets" +) +ctx.lists["self.cursorless_target_separator"] = target_separator + + +@mod.capture( + rule=( + "[{user.cursorless_target_separator}] | " + " {user.cursorless_target_separator} " + ) +) +def cursorless_multiple_targets(m) -> str: + target_list = m.cursorless_target_list + + try: + target_separater = m.cursorless_target_separator + except AttributeError: + target_separater = None + + if len(target_list) == 1: + if target_separater is not None: + target_list = [STRICT_HERE] + target_list + else: + target_list = target_list + [STRICT_HERE] + + return target_list diff --git a/src/actions/swap.py b/src/actions/swap.py deleted file mode 100644 index 75d210a2..00000000 --- a/src/actions/swap.py +++ /dev/null @@ -1,14 +0,0 @@ -from ..primitive_target import BASE_TARGET -from talon import Module - -mod = Module() - - -@mod.capture(rule=("swap [] with ")) -def cursorless_swap(m) -> str: - target_list = m.cursorless_target_list - - if len(target_list) == 1: - target_list = [BASE_TARGET] + target_list - - return target_list diff --git a/src/call.py b/src/call.py deleted file mode 100644 index efcf976f..00000000 --- a/src/call.py +++ /dev/null @@ -1,14 +0,0 @@ -from .primitive_target import STRICT_HERE -from talon import Module - -mod = Module() - - -@mod.capture(rule=("call [on ]")) -def cursorless_call(m) -> str: - target_list = m.cursorless_target_list - - if len(target_list) == 1: - target_list = target_list + [STRICT_HERE] - - return target_list diff --git a/src/compound_targets.py b/src/compound_targets.py index 1c32f3cf..2f8d389e 100644 --- a/src/compound_targets.py +++ b/src/compound_targets.py @@ -1,14 +1,27 @@ from .primitive_target import BASE_TARGET -from talon import Module +from talon import Module, Context mod = Module() +ctx = Context() + +ctx.matches = r""" +tag: user.cursorless +""" + +range_specifier = { + "past", + "until", + "tween", +} + +mod.list("cursorless_range_specifier", desc="A symbol that comes in pairs, eg brackets") +ctx.lists["self.cursorless_range_specifier"] = range_specifier @mod.capture( rule=( - " | " - "(past|until|tween) | " - " (past|until|tween) " + "[{user.cursorless_range_specifier}] | " + " {user.cursorless_range_specifier} " ) ) def cursorless_range(m) -> str: diff --git a/src/cursorless.talon b/src/cursorless.talon index 51b44fff..15fc4e56 100644 --- a/src/cursorless.talon +++ b/src/cursorless.talon @@ -5,32 +5,26 @@ tag(): user.cursorless {user.cursorless_simple_action} : user.cursorless_simple_action(cursorless_simple_action, cursorless_target) +{user.cursorless_multiple_target_action} : + user.cursorless_multiple_target_command(cursorless_multiple_target_action, cursorless_multiple_targets) + wrap : user.cursorless_single_target_command_with_arg_list("wrap", cursorless_target, cursorless_wrapper) -wrap with funk : - user.cursorless_single_target_command("wrap", cursorless_target, "{code_functions}(", ")") +# wrap with funk : +# user.cursorless_single_target_command("wrap", cursorless_target, "{code_functions}(", ")") replace with $: user.cursorless_replace(cursorless_target, cursorless_replace_value) -reformat as : +format onto : user.cursorless_reformat(cursorless_target, formatters) -extract as $: - user.cursorless_single_target_command("extractVariable", cursorless_target) - sleep(300ms) - user.code_public_variable_formatter(text) - key(enter) - -: - user.cursorless_multiple_target_command("swap", cursorless_swap) - -{user.cursorless_move_bring_action} : - user.cursorless_multiple_target_command(cursorless_move_bring_action, cursorless_move_bring_targets) - -: - user.cursorless_multiple_target_command("call", cursorless_call) +# extract as $: +# user.cursorless_single_target_command("extractVariable", cursorless_target) +# sleep(300ms) +# user.code_public_variable_formatter(text) +# key(enter) pour cell: user.vscode("jupyter.insertCellBelow") diff --git a/src/modifiers/surrounding_pair.py b/src/modifiers/surrounding_pair.py index 6368e416..6dd76456 100644 --- a/src/modifiers/surrounding_pair.py +++ b/src/modifiers/surrounding_pair.py @@ -8,7 +8,6 @@ """ pair_symbols = { - "angle": "angleBrackets", "diamond": "angleBrackets", "curly": "curlyBrackets", "round": "parentheses", diff --git a/src/primitive_target.py b/src/primitive_target.py index 230a5364..c43e3018 100644 --- a/src/primitive_target.py +++ b/src/primitive_target.py @@ -30,15 +30,10 @@ # "", # matching ] -modifiers_and_mark = ( - f"({'|'.join(modifiers)})* " # 0 or more parameters - "" # 1 mark -) - -modifiers_only = f"({'|'.join(modifiers)})+" # 1 or more parameters - -@mod.capture(rule=f"({modifiers_and_mark}) | ({modifiers_only})") +@mod.capture( + rule=f"({'|'.join(modifiers)})+ [] | " +) def cursorless_primitive_target(m) -> str: """Supported extents for cursorless navigation""" object = BASE_TARGET.copy() From dc2fec2e660243aeff4a0430ac228ef14613766c Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 10 Aug 2021 10:59:32 +0200 Subject: [PATCH 02/20] Optimisations and clean up --- src/cursorless.talon | 9 ------ src/modifiers/containing_scope.py | 35 +++++++--------------- src/modifiers/head_tail.py | 14 +++++++-- src/modifiers/inside_outside.py | 14 ++++----- src/modifiers/matching_pair_symbol.py | 8 +---- src/modifiers/position.py | 2 +- src/modifiers/selection_type.py | 43 ++++----------------------- src/modifiers/surrounding_pair.py | 2 -- src/primitive_target.py | 37 +++++++---------------- 9 files changed, 45 insertions(+), 119 deletions(-) diff --git a/src/cursorless.talon b/src/cursorless.talon index 51b44fff..9fb7ed33 100644 --- a/src/cursorless.talon +++ b/src/cursorless.talon @@ -8,21 +8,12 @@ tag(): user.cursorless wrap : user.cursorless_single_target_command_with_arg_list("wrap", cursorless_target, cursorless_wrapper) -wrap with funk : - user.cursorless_single_target_command("wrap", cursorless_target, "{code_functions}(", ")") - replace with $: user.cursorless_replace(cursorless_target, cursorless_replace_value) reformat as : user.cursorless_reformat(cursorless_target, formatters) -extract as $: - user.cursorless_single_target_command("extractVariable", cursorless_target) - sleep(300ms) - user.code_public_variable_formatter(text) - key(enter) - : user.cursorless_multiple_target_command("swap", cursorless_swap) diff --git a/src/modifiers/containing_scope.py b/src/modifiers/containing_scope.py index 8877822a..23d11ad3 100644 --- a/src/modifiers/containing_scope.py +++ b/src/modifiers/containing_scope.py @@ -1,5 +1,4 @@ from talon import Context, Module -import copy mod = Module() ctx = Context() @@ -8,7 +7,9 @@ tag: user.cursorless """ -containing_scope_type_map = { + +mod.list("cursorless_containing_scope_type", desc="Supported containing scope types") +ctx.lists["self.cursorless_containing_scope_type"] = { "arg": "argumentOrParameter", "arrow": "arrowFunction", "call": "functionCall", @@ -37,30 +38,14 @@ "end tag": "xmlEndTag", } -containing_scope_types = { - term: { + +@mod.capture(rule="[every] {user.cursorless_containing_scope_type}") +def cursorless_containing_scope(m) -> str: + """Supported containing scope types""" + return { "modifier": { "type": "containingScope", - "scopeType": containing_scope_type, + "scopeType": m.cursorless_containing_scope_type, + "includeSiblings": m[0] == "every", } } - for term, containing_scope_type in containing_scope_type_map.items() -} - -mod.list("cursorless_containing_scope_type", desc="Supported containing scope types") -ctx.lists["self.cursorless_containing_scope_type"] = containing_scope_types.keys() - - -@mod.capture(rule="{user.cursorless_containing_scope_type}") -def cursorless_containing_scope_type(m) -> str: - return containing_scope_types[m.cursorless_containing_scope_type] - - -@mod.capture(rule=("[every] ")) -def cursorless_containing_scope(m) -> str: - """Supported containing scope types""" - if m[0] == "every": - current_target = copy.deepcopy(m.cursorless_containing_scope_type) - current_target["modifier"]["includeSiblings"] = True - return current_target - return m.cursorless_containing_scope_type diff --git a/src/modifiers/head_tail.py b/src/modifiers/head_tail.py index 7d2d7210..e4badd98 100644 --- a/src/modifiers/head_tail.py +++ b/src/modifiers/head_tail.py @@ -1,8 +1,16 @@ -from talon import Module +from talon import Context, Module mod = Module() +ctx = Context() +ctx.matches = r""" +tag: user.cursorless +""" -@mod.capture(rule="head | tail") +mod.list("cursorless_head_tail", desc="Types of head_tail") +ctx.lists["self.cursorless_head_tail"] = {"head", "tail"} + + +@mod.capture(rule="{user.cursorless_head_tail}") def cursorless_head_tail(m) -> str: - return {"modifier": {"type": m[0]}} + return {"modifier": {"type": m.cursorless_head_tail}} diff --git a/src/modifiers/inside_outside.py b/src/modifiers/inside_outside.py index f44f2bd2..8ed9a327 100644 --- a/src/modifiers/inside_outside.py +++ b/src/modifiers/inside_outside.py @@ -7,15 +7,13 @@ tag: user.cursorless """ -inside_outside = { - "inner": {"insideOutsideType": "inside"}, - "outer": {"insideOutsideType": "outside"}, -} - mod.list("cursorless_inside_outside", desc="Supported inside/outside types") -ctx.lists["self.cursorless_inside_outside"] = inside_outside.keys() +ctx.lists["self.cursorless_inside_outside"] = { + "inner": "inside", + "outer": "outside", +} -@mod.capture(rule=("{user.cursorless_inside_outside}")) +@mod.capture(rule="{user.cursorless_inside_outside}") def cursorless_inside_outside(m) -> str: - return inside_outside[m.cursorless_inside_outside] + return {"insideOutsideType": m.cursorless_inside_outside} diff --git a/src/modifiers/matching_pair_symbol.py b/src/modifiers/matching_pair_symbol.py index fe7bd2b8..eea22ca4 100644 --- a/src/modifiers/matching_pair_symbol.py +++ b/src/modifiers/matching_pair_symbol.py @@ -1,12 +1,6 @@ -from talon import Context, Module -from dataclasses import dataclass +from talon import Module mod = Module() -ctx = Context() - -ctx.matches = r""" -tag: user.cursorless -""" @mod.capture(rule="matching") diff --git a/src/modifiers/position.py b/src/modifiers/position.py index 570b1574..325b91bd 100644 --- a/src/modifiers/position.py +++ b/src/modifiers/position.py @@ -1,5 +1,4 @@ from talon import Context, Module -from .selection_type import LINE mod = Module() ctx = Context() @@ -22,6 +21,7 @@ mod.list("cursorless_position", desc="Types of positions") ctx.lists["self.cursorless_position"] = positions.keys() + @mod.capture(rule="{user.cursorless_position}") def cursorless_position(m) -> str: return positions[m.cursorless_position] diff --git a/src/modifiers/selection_type.py b/src/modifiers/selection_type.py index 27ae2b7b..6baa0c9c 100644 --- a/src/modifiers/selection_type.py +++ b/src/modifiers/selection_type.py @@ -8,46 +8,15 @@ tag: user.cursorless """ -SELECTION_TYPE_KEY = "selectionType" - - -@dataclass -class SelectionType: - singular: str - plural: str - json_name: str - rank: int - - @property - def json_repr(self): - return {SELECTION_TYPE_KEY: self.json_name} - - -TOKEN = SelectionType("token", "tokens", "token", 0) -LINE = SelectionType("line", "lines", "line", 1) -BLOCK = SelectionType("block", "blocks", "paragraph", 2) -FILE = SelectionType("file", "files", "document", 3) - -SELECTION_TYPES = [ - TOKEN, - LINE, - BLOCK, - FILE -] - -RANKED_SELECTION_TYPES = { - selection_type.json_name: selection_type.rank for selection_type in SELECTION_TYPES -} - -selection_type_map = { - selection_type.json_name: selection_type.json_repr for selection_type in SELECTION_TYPES -} - mod.list("cursorless_selection_type", desc="Types of selection_types") ctx.lists["self.cursorless_selection_type"] = { - type.singular: type.json_name for type in SELECTION_TYPES + "token": "token", + "line": "line", + "block": "paragraph", + "file": "document", } + @mod.capture(rule="{user.cursorless_selection_type}") def cursorless_selection_type(m) -> str: - return selection_type_map[m.cursorless_selection_type] + return {"selectionType": m.cursorless_selection_type} diff --git a/src/modifiers/surrounding_pair.py b/src/modifiers/surrounding_pair.py index 6368e416..9658383a 100644 --- a/src/modifiers/surrounding_pair.py +++ b/src/modifiers/surrounding_pair.py @@ -8,7 +8,6 @@ """ pair_symbols = { - "angle": "angleBrackets", "diamond": "angleBrackets", "curly": "curlyBrackets", "round": "parentheses", @@ -32,7 +31,6 @@ def cursorless_surrounding_pair(m) -> str: cursorless_pair_symbol = m.cursorless_pair_symbol except AttributeError: cursorless_pair_symbol = None - return { "modifier": { "type": "surroundingPair", diff --git a/src/primitive_target.py b/src/primitive_target.py index 230a5364..ac8ec67d 100644 --- a/src/primitive_target.py +++ b/src/primitive_target.py @@ -1,13 +1,7 @@ -from dataclasses import dataclass -from talon import Context, Module -from .modifiers.selection_type import SELECTION_TYPE_KEY, RANKED_SELECTION_TYPES +from talon import Module -ctx = Context() -mod = Module() -ctx.matches = r""" -tag: user.cursorless -""" +mod = Module() BASE_TARGET = {"type": "primitive"} STRICT_HERE = { @@ -19,36 +13,25 @@ "insideOutsideType": "inside", } + modifiers = [ "", # before, end of "", # token, line, file + "", # inner, outer + "", # head, tail "", # funk, state, class "", # first past second word - "", # head, tail - "", # inner, outer "", # curly, round # "", # matching ] -modifiers_and_mark = ( - f"({'|'.join(modifiers)})* " # 0 or more parameters - "" # 1 mark -) - -modifiers_only = f"({'|'.join(modifiers)})+" # 1 or more parameters +modifiers = "|".join(modifiers) -@mod.capture(rule=f"({modifiers_and_mark}) | ({modifiers_only})") +@mod.capture(rule=f"({modifiers})+ [] | ") def cursorless_primitive_target(m) -> str: """Supported extents for cursorless navigation""" - object = BASE_TARGET.copy() + result = BASE_TARGET.copy() for capture in m: - for key, value in capture.items(): - if ( - key in object - and key == SELECTION_TYPE_KEY - and RANKED_SELECTION_TYPES[value] < RANKED_SELECTION_TYPES[object[key]] - ): - continue - object[key] = value - return object + result.update(capture) + return result From 472accfa5f8509f5df3b89ab396d8468f3d8bdaf Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 10 Aug 2021 14:36:24 +0200 Subject: [PATCH 03/20] Require matching prefix --- src/modifiers/surrounding_pair.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/modifiers/surrounding_pair.py b/src/modifiers/surrounding_pair.py index 96c7764b..8e7515f4 100644 --- a/src/modifiers/surrounding_pair.py +++ b/src/modifiers/surrounding_pair.py @@ -19,11 +19,7 @@ } -@mod.capture( - rule=( - "matching | {user.cursorless_pair_symbol} | pair [{user.cursorless_pair_symbol}] " - ) -) +@mod.capture(rule=("(matching | pair) [{user.cursorless_pair_symbol}]")) def cursorless_surrounding_pair(m) -> str: """Surrounding pair modifier""" try: From 3e4a6fdadbaa789b640efcff0783cd2854378039 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 10 Aug 2021 14:47:23 +0200 Subject: [PATCH 04/20] Added matching brick --- src/modifiers/surrounding_pair.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modifiers/surrounding_pair.py b/src/modifiers/surrounding_pair.py index 8e7515f4..c7f7c2d6 100644 --- a/src/modifiers/surrounding_pair.py +++ b/src/modifiers/surrounding_pair.py @@ -16,6 +16,7 @@ "square": "squareBrackets", "quad": "doubleQuotes", "twin": "singleQuotes", + "brick": "backtickQuotes" } From 2bf8cd01c2cb3192ba6d95fb40f14b0c5045d906 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 10 Aug 2021 14:53:13 +0200 Subject: [PATCH 05/20] Updated comment --- src/primitive_target.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/primitive_target.py b/src/primitive_target.py index 7c6a4c46..0b71b09b 100644 --- a/src/primitive_target.py +++ b/src/primitive_target.py @@ -21,7 +21,7 @@ "", # head, tail "", # funk, state, class "", # first past second word - "", # curly, round + "", # matching/pair [curly, round] # "", # matching ] From e93d82e817b4fbb23c1c04c56d8d41fe7a896546 Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Tue, 10 Aug 2021 14:41:18 +0100 Subject: [PATCH 06/20] Apply suggestions from code review --- src/modifiers/containing_scope.py | 2 +- src/modifiers/head_tail.py | 2 +- src/primitive_target.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modifiers/containing_scope.py b/src/modifiers/containing_scope.py index 23d11ad3..b811d8e5 100644 --- a/src/modifiers/containing_scope.py +++ b/src/modifiers/containing_scope.py @@ -8,7 +8,7 @@ """ -mod.list("cursorless_containing_scope_type", desc="Supported containing scope types") +mod.list("cursorless_scope_type", desc="Supported scope types") ctx.lists["self.cursorless_containing_scope_type"] = { "arg": "argumentOrParameter", "arrow": "arrowFunction", diff --git a/src/modifiers/head_tail.py b/src/modifiers/head_tail.py index e4badd98..6cb08575 100644 --- a/src/modifiers/head_tail.py +++ b/src/modifiers/head_tail.py @@ -7,7 +7,7 @@ tag: user.cursorless """ -mod.list("cursorless_head_tail", desc="Types of head_tail") +mod.list("cursorless_head_tail", desc="Cursorless modifier for head or tail of line") ctx.lists["self.cursorless_head_tail"] = {"head", "tail"} diff --git a/src/primitive_target.py b/src/primitive_target.py index 0b71b09b..5f1c0422 100644 --- a/src/primitive_target.py +++ b/src/primitive_target.py @@ -27,7 +27,7 @@ -@mod.capture(rule=f"{'|'.join(modifiers)}") +@mod.capture(rule='|'.join(modifiers)) def cursorless_modifier(m) -> str: """Cursorless modifier""" return m[0] From e41753405a2f60ddbd69bb3b2b6313e01c6fddc8 Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Tue, 10 Aug 2021 14:43:02 +0100 Subject: [PATCH 07/20] Tweaks --- src/modifiers/containing_scope.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modifiers/containing_scope.py b/src/modifiers/containing_scope.py index b811d8e5..8ef9788b 100644 --- a/src/modifiers/containing_scope.py +++ b/src/modifiers/containing_scope.py @@ -9,7 +9,7 @@ mod.list("cursorless_scope_type", desc="Supported scope types") -ctx.lists["self.cursorless_containing_scope_type"] = { +ctx.lists["self.cursorless_scope_type"] = { "arg": "argumentOrParameter", "arrow": "arrowFunction", "call": "functionCall", @@ -39,13 +39,13 @@ } -@mod.capture(rule="[every] {user.cursorless_containing_scope_type}") +@mod.capture(rule="[every] {user.cursorless_scope_type}") def cursorless_containing_scope(m) -> str: - """Supported containing scope types""" + """Expand to containing scope""" return { "modifier": { "type": "containingScope", - "scopeType": m.cursorless_containing_scope_type, + "scopeType": m.cursorless_scope_type, "includeSiblings": m[0] == "every", } } From 733c5fbd0a9a149cb11bc103801e58a1c261e066 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 11 Aug 2021 15:09:42 +0200 Subject: [PATCH 08/20] cleanup --- src/modifiers/surrounding_pair.py | 2 +- src/primitive_target.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modifiers/surrounding_pair.py b/src/modifiers/surrounding_pair.py index c7f7c2d6..23787cc8 100644 --- a/src/modifiers/surrounding_pair.py +++ b/src/modifiers/surrounding_pair.py @@ -20,7 +20,7 @@ } -@mod.capture(rule=("(matching | pair) [{user.cursorless_pair_symbol}]")) +@mod.capture(rule="(matching | pair) [{user.cursorless_pair_symbol}]") def cursorless_surrounding_pair(m) -> str: """Surrounding pair modifier""" try: diff --git a/src/primitive_target.py b/src/primitive_target.py index 5f1c0422..4b3fe2f0 100644 --- a/src/primitive_target.py +++ b/src/primitive_target.py @@ -27,7 +27,7 @@ -@mod.capture(rule='|'.join(modifiers)) +@mod.capture(rule="|".join(modifiers)) def cursorless_modifier(m) -> str: """Cursorless modifier""" return m[0] From b6fa7eda8576dc08df3c30ed1ec2ea46d24754ad Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Wed, 11 Aug 2021 15:44:57 +0200 Subject: [PATCH 09/20] Update positions on elements --- src/actions/multiple_target_action.py | 31 ++++++++++++++++----------- 1 file changed, 18 insertions(+), 13 deletions(-) diff --git a/src/actions/multiple_target_action.py b/src/actions/multiple_target_action.py index 4318b25e..daf897f1 100644 --- a/src/actions/multiple_target_action.py +++ b/src/actions/multiple_target_action.py @@ -12,21 +12,14 @@ mod.list("cursorless_multiple_target_action", desc="Cursorless move or bring actions") ctx.lists["self.cursorless_multiple_target_action"] = {"bring", "move", "swap", "call"} - -mod.list( - "cursorless_target_separator", desc="A symbol that comes in pairs, eg brackets" -) -ctx.lists["self.cursorless_target_separator"] = { - "at", - "before", - "after", -} - +@mod.capture(rule="at | ") +def cursorless_target_separator(m) -> str: + return m[0] @mod.capture( rule=( - "[{user.cursorless_target_separator}] | " - " {user.cursorless_target_separator} " + "[] | " + " " ) ) def cursorless_multiple_targets(m) -> str: @@ -35,7 +28,7 @@ def cursorless_multiple_targets(m) -> str: try: target_separater = m.cursorless_target_separator if target_separater != "at": - target_list[-1]["position"] = target_separater + update_target(target_list[-1], target_separater) except AttributeError: target_separater = None @@ -46,3 +39,15 @@ def cursorless_multiple_targets(m) -> str: target_list = target_list + [STRICT_HERE] return target_list + + +def update_target(target: dict, value: dict): + type = target["type"] + if type == "list": + for target in target["elements"]: + update_target(target, value) + # elif type == "range": + # update_target(target["start"], value) + # update_target(target["end"], value) + elif type == "primitive": + target.update(value) From 2cb4916e8d9b76990e19ad2ea38902fd58c9ce12 Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Fri, 13 Aug 2021 14:14:28 +0100 Subject: [PATCH 10/20] Some changes --- src/actions/replace.py | 2 ++ src/cursorless.talon | 6 ++++-- src/modifiers/surrounding_pair.py | 6 +++--- 3 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/actions/replace.py b/src/actions/replace.py index b294478a..798d643f 100644 --- a/src/actions/replace.py +++ b/src/actions/replace.py @@ -1,3 +1,5 @@ +# disabling for now until we can figure out dfa compilation +# See https://github.com/pokey/cursorless-talon/issues/58 from talon import Module, actions mod = Module() diff --git a/src/cursorless.talon b/src/cursorless.talon index a03624ea..f2afe21b 100644 --- a/src/cursorless.talon +++ b/src/cursorless.talon @@ -11,8 +11,10 @@ tag(): user.cursorless wrap : user.cursorless_single_target_command_with_arg_list("wrap", cursorless_target, cursorless_wrapper) -replace with $: - user.cursorless_replace(cursorless_target, cursorless_replace_value) +# disabling for now until we can figure out dfa compilation +# See https://github.com/pokey/cursorless-talon/issues/58 +# replace with $: +# user.cursorless_replace(cursorless_target, cursorless_replace_value) format at : user.cursorless_reformat(cursorless_target, formatters) diff --git a/src/modifiers/surrounding_pair.py b/src/modifiers/surrounding_pair.py index 23787cc8..26c6b0bf 100644 --- a/src/modifiers/surrounding_pair.py +++ b/src/modifiers/surrounding_pair.py @@ -10,13 +10,13 @@ mod.list("cursorless_pair_symbol", desc="A symbol that comes in pairs, eg brackets") ctx.lists["self.cursorless_pair_symbol"] = { - "diamond": "angleBrackets", + "skis": "backtickQuotes", "curly": "curlyBrackets", + "diamond": "angleBrackets", + "quad": "doubleQuotes", "round": "parentheses", "square": "squareBrackets", - "quad": "doubleQuotes", "twin": "singleQuotes", - "brick": "backtickQuotes" } From aa56dc9363ca00b71eb92414626fd2768c85aac8 Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Fri, 13 Aug 2021 14:28:25 +0100 Subject: [PATCH 11/20] Reinstate old bring move swap grammar --- src/actions/call.py | 14 +++++++ src/actions/move_bring.py | 23 ++++++++++++ src/actions/multiple_target_action.py | 53 --------------------------- src/actions/swap.py | 14 +++++++ src/cursorless.talon | 10 ++++- 5 files changed, 59 insertions(+), 55 deletions(-) create mode 100644 src/actions/call.py create mode 100644 src/actions/move_bring.py delete mode 100644 src/actions/multiple_target_action.py create mode 100644 src/actions/swap.py diff --git a/src/actions/call.py b/src/actions/call.py new file mode 100644 index 00000000..f721905c --- /dev/null +++ b/src/actions/call.py @@ -0,0 +1,14 @@ +from ..primitive_target import STRICT_HERE +from talon import Module + +mod = Module() + + +@mod.capture(rule=("call [on ]")) +def cursorless_call(m) -> str: + target_list = m.cursorless_target_list + + if len(target_list) == 1: + target_list = target_list + [STRICT_HERE] + + return target_list diff --git a/src/actions/move_bring.py b/src/actions/move_bring.py new file mode 100644 index 00000000..2580f506 --- /dev/null +++ b/src/actions/move_bring.py @@ -0,0 +1,23 @@ +from ..primitive_target import STRICT_HERE +from talon import Context, Module + +mod = Module() + +ctx = Context() +ctx.matches = r""" +tag: user.cursorless +""" + + +mod.list("cursorless_move_bring_action", desc="Cursorless move or bring actions") +ctx.lists["self.cursorless_move_bring_action"] = {"bring", "move"} + + +@mod.capture(rule=(" [to ]")) +def cursorless_move_bring_targets(m) -> str: + target_list = m.cursorless_target_list + + if len(target_list) == 1: + target_list = target_list + [STRICT_HERE] + + return target_list diff --git a/src/actions/multiple_target_action.py b/src/actions/multiple_target_action.py deleted file mode 100644 index daf897f1..00000000 --- a/src/actions/multiple_target_action.py +++ /dev/null @@ -1,53 +0,0 @@ -from ..primitive_target import STRICT_HERE -from talon import Context, Module - -mod = Module() - -ctx = Context() -ctx.matches = r""" -tag: user.cursorless -""" - - -mod.list("cursorless_multiple_target_action", desc="Cursorless move or bring actions") -ctx.lists["self.cursorless_multiple_target_action"] = {"bring", "move", "swap", "call"} - -@mod.capture(rule="at | ") -def cursorless_target_separator(m) -> str: - return m[0] - -@mod.capture( - rule=( - "[] | " - " " - ) -) -def cursorless_multiple_targets(m) -> str: - target_list = m.cursorless_target_list - - try: - target_separater = m.cursorless_target_separator - if target_separater != "at": - update_target(target_list[-1], target_separater) - except AttributeError: - target_separater = None - - if len(target_list) == 1: - if target_separater is not None: - target_list = [STRICT_HERE] + target_list - else: - target_list = target_list + [STRICT_HERE] - - return target_list - - -def update_target(target: dict, value: dict): - type = target["type"] - if type == "list": - for target in target["elements"]: - update_target(target, value) - # elif type == "range": - # update_target(target["start"], value) - # update_target(target["end"], value) - elif type == "primitive": - target.update(value) diff --git a/src/actions/swap.py b/src/actions/swap.py new file mode 100644 index 00000000..75d210a2 --- /dev/null +++ b/src/actions/swap.py @@ -0,0 +1,14 @@ +from ..primitive_target import BASE_TARGET +from talon import Module + +mod = Module() + + +@mod.capture(rule=("swap [] with ")) +def cursorless_swap(m) -> str: + target_list = m.cursorless_target_list + + if len(target_list) == 1: + target_list = [BASE_TARGET] + target_list + + return target_list diff --git a/src/cursorless.talon b/src/cursorless.talon index f2afe21b..98fc9317 100644 --- a/src/cursorless.talon +++ b/src/cursorless.talon @@ -5,8 +5,14 @@ tag(): user.cursorless {user.cursorless_simple_action} : user.cursorless_simple_action(cursorless_simple_action, cursorless_target) -{user.cursorless_multiple_target_action} : - user.cursorless_multiple_target_command(cursorless_multiple_target_action, cursorless_multiple_targets) +: + user.cursorless_multiple_target_command("swap", cursorless_swap) + +{user.cursorless_move_bring_action} : + user.cursorless_multiple_target_command(cursorless_move_bring_action, cursorless_move_bring_targets) + +: + user.cursorless_multiple_target_command("call", cursorless_call) wrap : user.cursorless_single_target_command_with_arg_list("wrap", cursorless_target, cursorless_wrapper) From f6f9250111e0392d06e9c73cfb662cb960cf3533 Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Fri, 13 Aug 2021 14:32:33 +0100 Subject: [PATCH 12/20] Switch "tween" to "between" --- src/compound_targets.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/compound_targets.py b/src/compound_targets.py index 2f8d389e..c2f796fe 100644 --- a/src/compound_targets.py +++ b/src/compound_targets.py @@ -11,7 +11,7 @@ range_specifier = { "past", "until", - "tween", + "between", } mod.list("cursorless_range_specifier", desc="A symbol that comes in pairs, eg brackets") @@ -38,8 +38,8 @@ def cursorless_range(m) -> str: "type": "range", "start": start, "end": m[-1], - "excludeStart": modifier == "tween", - "excludeEnd": modifier in ["tween", "until"], + "excludeStart": modifier == "between", + "excludeEnd": modifier in ["between", "until"], } From 0681756971fb6467fb317cd0b6ce3703a730b35c Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Fri, 13 Aug 2021 17:00:21 +0100 Subject: [PATCH 13/20] More fixes --- src/actions/actions.py | 2 +- src/modifiers/inside_outside.py | 19 ------------------- src/modifiers/surrounding_pair.py | 29 +++++++++++++++++++++-------- src/primitive_target.py | 2 -- 4 files changed, 22 insertions(+), 30 deletions(-) delete mode 100644 src/modifiers/inside_outside.py diff --git a/src/actions/actions.py b/src/actions/actions.py index 05f257c9..accd25e0 100644 --- a/src/actions/actions.py +++ b/src/actions/actions.py @@ -20,8 +20,8 @@ class MakeshiftAction: makeshift_actions = [ - MakeshiftAction("define", "editor.action.revealDefinition"), MakeshiftAction("drink cell", "jupyter.insertCellAbove"), + MakeshiftAction("follow", "editor.action.revealDefinition"), MakeshiftAction("hover", "editor.action.showHover"), MakeshiftAction("inspect", "editor.debug.action.showDebugHover"), MakeshiftAction("pour cell", "jupyter.insertCellBelow"), diff --git a/src/modifiers/inside_outside.py b/src/modifiers/inside_outside.py deleted file mode 100644 index 8ed9a327..00000000 --- a/src/modifiers/inside_outside.py +++ /dev/null @@ -1,19 +0,0 @@ -from talon import Context, Module - -mod = Module() -ctx = Context() - -ctx.matches = r""" -tag: user.cursorless -""" - -mod.list("cursorless_inside_outside", desc="Supported inside/outside types") -ctx.lists["self.cursorless_inside_outside"] = { - "inner": "inside", - "outer": "outside", -} - - -@mod.capture(rule="{user.cursorless_inside_outside}") -def cursorless_inside_outside(m) -> str: - return {"insideOutsideType": m.cursorless_inside_outside} diff --git a/src/modifiers/surrounding_pair.py b/src/modifiers/surrounding_pair.py index 26c6b0bf..d9036daa 100644 --- a/src/modifiers/surrounding_pair.py +++ b/src/modifiers/surrounding_pair.py @@ -19,18 +19,31 @@ "twin": "singleQuotes", } +mod.list( + "cursorless_delimiter_inclusion", + desc="Whether to include delimiters in surrounding range", +) +ctx.lists["self.cursorless_delimiter_inclusion"] = { + "inside": "excludeDelimiters", + "outside": "includeDelimiters", + "pair": "delimitersOnly", +} + -@mod.capture(rule="(matching | pair) [{user.cursorless_pair_symbol}]") +@mod.capture( + rule=( + "[{user.cursorless_delimiter_inclusion}] {user.cursorless_pair_symbol} | " + "{user.cursorless_delimiter_inclusion}" + ) +) def cursorless_surrounding_pair(m) -> str: """Surrounding pair modifier""" - try: - cursorless_pair_symbol = m.cursorless_pair_symbol - except AttributeError: - cursorless_pair_symbol = None return { "modifier": { "type": "surroundingPair", - "delimiter": cursorless_pair_symbol, - "delimitersOnly": m[0] == "pair", - } + "delimiter": getattr(m, "cursorless_pair_symbol", None), + "delimiterInclusion": getattr( + m, "cursorless_delimiter_inclusion", "includeDelimiters" + ), + }, } diff --git a/src/primitive_target.py b/src/primitive_target.py index 4b3fe2f0..43c1eb4b 100644 --- a/src/primitive_target.py +++ b/src/primitive_target.py @@ -17,7 +17,6 @@ modifiers = [ "", # before, end of "", # token, line, file - "", # inner, outer "", # head, tail "", # funk, state, class "", # first past second word @@ -26,7 +25,6 @@ ] - @mod.capture(rule="|".join(modifiers)) def cursorless_modifier(m) -> str: """Cursorless modifier""" From c4f30c6ec7d94598afc94d863b4a0321c490a619 Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Fri, 13 Aug 2021 17:05:43 +0100 Subject: [PATCH 14/20] Revert format action grammar change --- src/cursorless.talon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cursorless.talon b/src/cursorless.talon index 98fc9317..186a335e 100644 --- a/src/cursorless.talon +++ b/src/cursorless.talon @@ -22,7 +22,7 @@ tag(): user.cursorless # replace with $: # user.cursorless_replace(cursorless_target, cursorless_replace_value) -format at : +format as : user.cursorless_reformat(cursorless_target, formatters) pour cell: user.vscode("jupyter.insertCellBelow") From bd529412dd0cf460410928017226c04a8091d5d2 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Fri, 13 Aug 2021 20:38:44 +0200 Subject: [PATCH 15/20] Renamed paste action --- src/actions/actions.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/actions/actions.py b/src/actions/actions.py index 05f257c9..bb4e9798 100644 --- a/src/actions/actions.py +++ b/src/actions/actions.py @@ -68,7 +68,7 @@ class CallbackAction: "float": "insertEmptyLineBelow", "fold": "fold", "indent": "indentLines", - "paste": "paste", + "paste to": "paste", "post": "setSelectionAfter", "pour": "editNewLineBelow", "pre": "setSelectionBefore", From ebe91fd8985ceebc6d622e86ca80cf42340042b5 Mon Sep 17 00:00:00 2001 From: Pokey Rule Date: Sat, 14 Aug 2021 15:50:13 +0100 Subject: [PATCH 16/20] Change command names --- src/actions/actions.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/actions/actions.py b/src/actions/actions.py index 09179489..84632bd3 100644 --- a/src/actions/actions.py +++ b/src/actions/actions.py @@ -21,7 +21,7 @@ class MakeshiftAction: makeshift_actions = [ MakeshiftAction("drink cell", "jupyter.insertCellAbove"), - MakeshiftAction("follow", "editor.action.revealDefinition"), + MakeshiftAction("define", "editor.action.revealDefinition"), MakeshiftAction("hover", "editor.action.showHover"), MakeshiftAction("inspect", "editor.debug.action.showDebugHover"), MakeshiftAction("pour cell", "jupyter.insertCellBelow"), @@ -41,7 +41,7 @@ class CallbackAction: callbacks = [ - CallbackAction("find", "find", run_find_action), + CallbackAction("scout", "find", run_find_action), CallbackAction("phones", "nextHomophone", run_homophones_action), ] @@ -56,15 +56,15 @@ class CallbackAction: "center": "scrollToCenter", "chuck": "delete", "clear": "clear", + "clone up": "copyLinesUp", + "clone": "copyLinesDown", "comment": "commentLines", "copy": "copy", + "crown": "scrollToTop", "dedent": "outdentLines", "drink": "editNewLineAbove", "drop": "insertEmptyLineAbove", - "clone": "copyLinesDown", - "clone up": "copyLinesUp", "extract": "extractVariable", - "find all": "findInFiles", "float": "insertEmptyLineBelow", "fold": "fold", "indent": "indentLines", @@ -74,12 +74,12 @@ class CallbackAction: "pre": "setSelectionBefore", "puff": "insertEmptyLinesAround", "reverse": "reverse", + "scout all": "findInFiles", "sort": "sort", "take": "setSelection", - "top": "scrollToTop", "unfold": "unfold", - **{callback.term: callback.action for callback in callbacks}, **{action.term: action.term for action in makeshift_actions}, + **{callback.term: callback.action for callback in callbacks}, } From d569ab5194b2abe39380a8464215e5ed10bf2e09 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 14 Aug 2021 19:36:49 +0200 Subject: [PATCH 17/20] Turn call into simple action --- src/actions/actions.py | 2 ++ src/actions/call.py | 13 ++++--------- src/actions/get_text.py | 4 ++-- src/actions/replace.py | 33 ++------------------------------- src/cursorless.talon | 10 +--------- src/primitive_target.py | 2 +- 6 files changed, 12 insertions(+), 52 deletions(-) diff --git a/src/actions/actions.py b/src/actions/actions.py index 84632bd3..19c4b9bb 100644 --- a/src/actions/actions.py +++ b/src/actions/actions.py @@ -2,6 +2,7 @@ from dataclasses import dataclass from .homophones import run_homophones_action from .find import run_find_action +from .call import run_call_action mod = Module() @@ -41,6 +42,7 @@ class CallbackAction: callbacks = [ + CallbackAction("call", "call", run_call_action), CallbackAction("scout", "find", run_find_action), CallbackAction("phones", "nextHomophone", run_homophones_action), ] diff --git a/src/actions/call.py b/src/actions/call.py index f721905c..7134b539 100644 --- a/src/actions/call.py +++ b/src/actions/call.py @@ -1,14 +1,9 @@ from ..primitive_target import STRICT_HERE -from talon import Module +from talon import Module, actions mod = Module() -@mod.capture(rule=("call [on ]")) -def cursorless_call(m) -> str: - target_list = m.cursorless_target_list - - if len(target_list) == 1: - target_list = target_list + [STRICT_HERE] - - return target_list +def run_call_action(target: dict): + targets = [target, STRICT_HERE] + actions.user.cursorless_multiple_target_command("call", targets) diff --git a/src/actions/get_text.py b/src/actions/get_text.py index 933e4692..b99b406e 100644 --- a/src/actions/get_text.py +++ b/src/actions/get_text.py @@ -2,12 +2,12 @@ def get_text( - targets: dict, show_decorations: bool = None, ensure_single_target: bool = None + target: dict, show_decorations: bool = None, ensure_single_target: bool = None ): """Get target texts""" return actions.user.cursorless_single_target_command_get( "getText", - targets, + target, { "showDecorations": show_decorations, "ensureSingleTarget": ensure_single_target, diff --git a/src/actions/replace.py b/src/actions/replace.py index 798d643f..7fd080ce 100644 --- a/src/actions/replace.py +++ b/src/actions/replace.py @@ -1,39 +1,10 @@ -# disabling for now until we can figure out dfa compilation -# See https://github.com/pokey/cursorless-talon/issues/58 from talon import Module, actions mod = Module() -@mod.capture(rule="count [from ]") -def cursorless_count(m) -> str: - try: - start = m.number_small - except AttributeError: - start = 0 - return {"start": start} - - -@mod.capture(rule="[] (and )*") -def cursorless_texts(m) -> str: - texts = m.text_list - try: - formatters = m.formatters - texts = list( - map(lambda text: actions.user.formatted_text(text, formatters), texts) - ) - except AttributeError: - pass - return texts - - -@mod.capture(rule=" | ") -def cursorless_replace_value(m) -> str: - return m[0] - - @mod.action_class class Actions: - def cursorless_replace(targets: dict, texts: list[str] or dict): + def cursorless_replace(target: dict, texts: list[str] or dict): """Replaced targets with texts""" - actions.user.cursorless_single_target_command("replace", targets, texts) + actions.user.cursorless_single_target_command("replace", target, texts) diff --git a/src/cursorless.talon b/src/cursorless.talon index 186a335e..abb2a6e3 100644 --- a/src/cursorless.talon +++ b/src/cursorless.talon @@ -11,18 +11,10 @@ tag(): user.cursorless {user.cursorless_move_bring_action} : user.cursorless_multiple_target_command(cursorless_move_bring_action, cursorless_move_bring_targets) -: - user.cursorless_multiple_target_command("call", cursorless_call) - wrap : user.cursorless_single_target_command_with_arg_list("wrap", cursorless_target, cursorless_wrapper) -# disabling for now until we can figure out dfa compilation -# See https://github.com/pokey/cursorless-talon/issues/58 -# replace with $: -# user.cursorless_replace(cursorless_target, cursorless_replace_value) - -format as : +format at : user.cursorless_reformat(cursorless_target, formatters) pour cell: user.vscode("jupyter.insertCellBelow") diff --git a/src/primitive_target.py b/src/primitive_target.py index 43c1eb4b..11fbd850 100644 --- a/src/primitive_target.py +++ b/src/primitive_target.py @@ -20,7 +20,7 @@ "", # head, tail "", # funk, state, class "", # first past second word - "", # matching/pair [curly, round] + # "", # matching/pair [curly, round] # "", # matching ] From f4d3bd0a34ad4b5527713b796728c9f158c99bec Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 14 Aug 2021 20:37:36 +0200 Subject: [PATCH 18/20] Updated if state name --- src/modifiers/containing_scope.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modifiers/containing_scope.py b/src/modifiers/containing_scope.py index 8ef9788b..32092ba1 100644 --- a/src/modifiers/containing_scope.py +++ b/src/modifiers/containing_scope.py @@ -18,7 +18,7 @@ "comment": "comment", "funk name": "functionName", "funk": "namedFunction", - "if": "ifStatement", + "if state": "ifStatement", "item": "collectionItem", "key": "collectionKey", "lambda": "arrowFunction", From 837c664219de2740e4f12eeb66001eb8d0f20f0e Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 14 Aug 2021 20:39:28 +0200 Subject: [PATCH 19/20] renamed attribute scope --- src/modifiers/containing_scope.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modifiers/containing_scope.py b/src/modifiers/containing_scope.py index 32092ba1..735ea8b2 100644 --- a/src/modifiers/containing_scope.py +++ b/src/modifiers/containing_scope.py @@ -31,7 +31,7 @@ "type": "type", "value": "value", # XML, JSX - "attribute": "xmlAttribute", + "attribute": "attribute", "element": "xmlElement", "tags": "xmlBothTags", "start tag": "xmlStartTag", From 87938718cf523068b55da91b0cc65b7e1f679268 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sat, 14 Aug 2021 20:40:41 +0200 Subject: [PATCH 20/20] Sorted scopes --- src/modifiers/containing_scope.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modifiers/containing_scope.py b/src/modifiers/containing_scope.py index 735ea8b2..83e3a5a9 100644 --- a/src/modifiers/containing_scope.py +++ b/src/modifiers/containing_scope.py @@ -12,6 +12,7 @@ ctx.lists["self.cursorless_scope_type"] = { "arg": "argumentOrParameter", "arrow": "arrowFunction", + "attribute": "attribute", "call": "functionCall", "class name": "className", "class": "class", @@ -31,7 +32,6 @@ "type": "type", "value": "value", # XML, JSX - "attribute": "attribute", "element": "xmlElement", "tags": "xmlBothTags", "start tag": "xmlStartTag",