We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`grave` command in dictation mode
The use of `grave` as an alternative to `backtick` is more rare (using backticks at all is rare), and some folks have complained about `grave` showing up in speech when they don't want it. I propose removing it from the keys list.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `core/keys/keys.py`
Content:
```
1 from talon import Context, Module, actions, app
2 
3 from ..user_settings import get_list_from_csv
4 
5 
6 def setup_default_alphabet():
7     """set up common default alphabet.
8 
9     no need to modify this here, change your alphabet using alphabet.csv"""
10     initial_default_alphabet = "air bat cap drum each fine gust harp sit jury crunch look made near odd pit quench red sun trap urge vest whale plex yank zip".split(
11         " "
12     )
13     initial_letters_string = "abcdefghijklmnopqrstuvwxyz"
14     initial_default_alphabet_dict = dict(
15         zip(initial_default_alphabet, initial_letters_string)
16     )
17 
18     return initial_default_alphabet_dict
19 
20 
21 alphabet_list = get_list_from_csv(
22     "alphabet.csv", ("Letter", "Spoken Form"), setup_default_alphabet()
23 )
24 
25 default_digits = "zero one two three four five six seven eight nine".split(" ")
26 numbers = [str(i) for i in range(10)]
27 default_f_digits = (
28     "one two three four five six seven eight nine ten eleven twelve".split(" ")
29 )
30 
31 mod = Module()
32 mod.list("letter", desc="The spoken phonetic alphabet")
33 mod.list("symbol_key", desc="All symbols from the keyboard")
34 mod.list("arrow_key", desc="All arrow keys")
35 mod.list("number_key", desc="All number keys")
36 mod.list("modifier_key", desc="All modifier keys")
37 mod.list("function_key", desc="All function keys")
38 mod.list("special_key", desc="All special keys")
39 mod.list("punctuation", desc="words for inserting punctuation into text")
40 
41 
42 @mod.capture(rule="{self.modifier_key}+")
43 def modifiers(m) -> str:
44     "One or more modifier keys"
45     return "-".join(m.modifier_key_list)
46 
47 
48 @mod.capture(rule="{self.arrow_key}")
49 def arrow_key(m) -> str:
50     "One directional arrow key"
51     return m.arrow_key
52 
53 
54 @mod.capture(rule="<self.arrow_key>+")
55 def arrow_keys(m) -> str:
56     "One or more arrow keys separated by a space"
57     return str(m)
58 
59 
60 @mod.capture(rule="{self.number_key}")
61 def number_key(m) -> str:
62     "One number key"
63     return m.number_key
64 
65 
66 @mod.capture(rule="{self.letter}")
67 def letter(m) -> str:
68     "One letter key"
69     return m.letter
70 
71 
72 @mod.capture(rule="{self.special_key}")
73 def special_key(m) -> str:
74     "One special key"
75     return m.special_key
76 
77 
78 @mod.capture(rule="{self.symbol_key}")
79 def symbol_key(m) -> str:
80     "One symbol key"
81     return m.symbol_key
82 
83 
84 @mod.capture(rule="{self.function_key}")
85 def function_key(m) -> str:
86     "One function key"
87     return m.function_key
88 
89 
90 @mod.capture(rule="( <self.letter> | <self.number_key> | <self.symbol_key> )")
91 def any_alphanumeric_key(m) -> str:
92     "any alphanumeric key"
93     return str(m)
94 
95 
96 @mod.capture(
97     rule="( <self.letter> | <self.number_key> | <self.symbol_key> "
98     "| <self.arrow_key> | <self.function_key> | <self.special_key> )"
99 )
100 def unmodified_key(m) -> str:
101     "A single key with no modifiers"
102     return str(m)
103 
104 
105 @mod.capture(rule="{self.modifier_key}* <self.unmodified_key>")
106 def key(m) -> str:
107     "A single key with optional modifiers"
108     try:
109         mods = m.modifier_key_list
110     except AttributeError:
111         mods = []
112     return "-".join(mods + [m.unmodified_key])
113 
114 
115 @mod.capture(rule="<self.key>+")
116 def keys(m) -> str:
117     "A sequence of one or more keys with optional modifiers"
118     return " ".join(m.key_list)
119 
120 
121 @mod.capture(rule="{self.letter}+")
122 def letters(m) -> str:
123     "Multiple letter keys"
124     return "".join(m.letter_list)
125 
126 
127 ctx = Context()
128 modifier_keys = {
129     # If you find 'alt' is often misrecognized, try using 'alter'.
130     "alt": "alt",  #'alter': 'alt',
131     "control": "ctrl",  #'troll':   'ctrl',
132     "shift": "shift",  #'sky':     'shift',
133     "super": "super",
134 }
135 if app.platform == "mac":
136     modifier_keys["command"] = "cmd"
137     modifier_keys["option"] = "alt"
138 ctx.lists["self.modifier_key"] = modifier_keys
139 ctx.lists["self.letter"] = alphabet_list
140 
141 # `punctuation_words` is for words you want available BOTH in dictation and as key names in command mode.
142 # `symbol_key_words` is for key names that should be available in command mode, but NOT during dictation.
143 punctuation_words = {
144     # TODO: I'm not sure why we need these, I think it has something to do with
145     # Dragon. Possibly it has been fixed by later improvements to talon? -rntz
146     "`": "`",
147     ",": ",",  # <== these things
148     "back tick": "`",
149     "grave": "`",
150     "comma": ",",
151     # Workaround for issue with conformer b-series; see #946
152     "coma": ",",
153     "period": ".",
154     "full stop": ".",
155     "semicolon": ";",
156     "colon": ":",
157     "forward slash": "/",
158     "question mark": "?",
159     "exclamation mark": "!",
160     "exclamation point": "!",
161     "asterisk": "*",
162     "hash sign": "#",
163     "number sign": "#",
164     "percent sign": "%",
165     "at sign": "@",
166     "and sign": "&",
167     "ampersand": "&",
168     # Currencies
169     "dollar sign": "$",
170     "pound sign": "£",
171     "hyphen": "-",
172     "L paren": "(",
173     "left paren": "(",
174     "R paren": ")",
175     "right paren": ")",
176 }
177 symbol_key_words = {
178     "dot": ".",
179     "point": ".",
180     "quote": "'",
181     "question": "?",
182     "apostrophe": "'",
183     "L square": "[",
184     "left square": "[",
185     "square": "[",
186     "R square": "]",
187     "right square": "]",
188     "slash": "/",
189     "backslash": "\\",
190     "minus": "-",
191     "dash": "-",
192     "equals": "=",
193     "plus": "+",
194     "tilde": "~",
195     "bang": "!",
196     "down score": "_",
197     "underscore": "_",
198     "paren": "(",
199     "brace": "{",
200     "left brace": "{",
201     "brack": "{",
202     "bracket": "{",
203     "left bracket": "{",
204     "r brace": "}",
205     "right brace": "}",
206     "r brack": "}",
207     "r bracket": "}",
208     "right bracket": "}",
209     "angle": "<",
210     "left angle": "<",
211     "less than": "<",
212     "rangle": ">",
213     "R angle": ">",
214     "right angle": ">",
215     "greater than": ">",
216     "star": "*",
217     "hash": "#",
218     "percent": "%",
219     "caret": "^",
220     "amper": "&",
221     "pipe": "|",
222     "dub quote": '"',
223     "double quote": '"',
224     # Currencies
225     "dollar": "$",
226     "pound": "£",
227 }
228 
229 # make punctuation words also included in {user.symbol_keys}
230 symbol_key_words.update(punctuation_words)
231 ctx.lists["self.punctuation"] = punctuation_words
232 ctx.lists["self.symbol_key"] = symbol_key_words
233 ctx.lists["self.number_key"] = dict(zip(default_digits, numbers))
234 ctx.lists["self.arrow_key"] = {
235     "down": "down",
236     "left": "left",
237     "right": "right",
238     "up": "up",
239 }
240 
241 simple_keys = [
242     "end",
243     "enter",
244     "escape",
245     "home",
246     "insert",
247     "pagedown",
248     "pageup",
249     "space",
250     "tab",
251 ]
252 
253 alternate_keys = {
254     "wipe": "backspace",
255     "delete": "backspace",
256     #'junk': 'backspace',
257     "forward delete": "delete",
258     "page up": "pageup",
259     "page down": "pagedown",
260 }
261 # mac apparently doesn't have the menu key.
262 if app.platform in ("windows", "linux"):
263     alternate_keys["menu key"] = "menu"
264     alternate_keys["print screen"] = "printscr"
265 
266 special_keys = {k: k for k in simple_keys}
267 special_keys.update(alternate_keys)
268 ctx.lists["self.special_key"] = special_keys
269 ctx.lists["self.function_key"] = {
270     f"F {default_f_digits[i]}": f"f{i + 1}" for i in range(12)
271 }
272 
273 
274 @mod.action_class
275 class Actions:
276     def move_cursor(s: str):
277         """Given a sequence of directions, eg. 'left left up', moves the cursor accordingly using edit.{left,right,up,down}."""
278         for d in s.split():
279             if d in ("left", "right", "up", "down"):
280                 getattr(actions.edit, d)()
281             else:
282                 raise RuntimeError(f"invalid arrow key: {d}")
283
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/core/keys/keys.py b/core/keys/keys.py
--- a/core/keys/keys.py
+++ b/core/keys/keys.py
@@ -146,7 +146,6 @@
     "`": "`",
     ",": ",",  # <== these things
     "back tick": "`",
-    "grave": "`",
     "comma": ",",
     # Workaround for issue with conformer b-series; see #946
     "coma": ",",
@@ -191,6 +190,7 @@
     "dash": "-",
     "equals": "=",
     "plus": "+",
+    "grave": "`",
     "tilde": "~",
     "bang": "!",
     "down score": "_",

{"golden_diff": "diff --git a/core/keys/keys.py b/core/keys/keys.py\n--- a/core/keys/keys.py\n+++ b/core/keys/keys.py\n@@ -146,7 +146,6 @@\n     \"`\": \"`\",\n     \",\": \",\",  # <== these things\n     \"back tick\": \"`\",\n-    \"grave\": \"`\",\n     \"comma\": \",\",\n     # Workaround for issue with conformer b-series; see #946\n     \"coma\": \",\",\n@@ -191,6 +190,7 @@\n     \"dash\": \"-\",\n     \"equals\": \"=\",\n     \"plus\": \"+\",\n+    \"grave\": \"`\",\n     \"tilde\": \"~\",\n     \"bang\": \"!\",\n     \"down score\": \"_\",\n", "issue": "`grave` command in dictation mode\nThe use of `grave` as an alternative to `backtick` is more rare (using backticks at all is rare), and some folks have complained about `grave` showing up in speech when they don't want it. I propose removing it from the keys list.\n", "before_files": [{"content": "from talon import Context, Module, actions, app\n\nfrom ..user_settings import get_list_from_csv\n\n\ndef setup_default_alphabet():\n    \"\"\"set up common default alphabet.\n\n    no need to modify this here, change your alphabet using alphabet.csv\"\"\"\n    initial_default_alphabet = \"air bat cap drum each fine gust harp sit jury crunch look made near odd pit quench red sun trap urge vest whale plex yank zip\".split(\n        \" \"\n    )\n    initial_letters_string = \"abcdefghijklmnopqrstuvwxyz\"\n    initial_default_alphabet_dict = dict(\n        zip(initial_default_alphabet, initial_letters_string)\n    )\n\n    return initial_default_alphabet_dict\n\n\nalphabet_list = get_list_from_csv(\n    \"alphabet.csv\", (\"Letter\", \"Spoken Form\"), setup_default_alphabet()\n)\n\ndefault_digits = \"zero one two three four five six seven eight nine\".split(\" \")\nnumbers = [str(i) for i in range(10)]\ndefault_f_digits = (\n    \"one two three four five six seven eight nine ten eleven twelve\".split(\" \")\n)\n\nmod = Module()\nmod.list(\"letter\", desc=\"The spoken phonetic alphabet\")\nmod.list(\"symbol_key\", desc=\"All symbols from the keyboard\")\nmod.list(\"arrow_key\", desc=\"All arrow keys\")\nmod.list(\"number_key\", desc=\"All number keys\")\nmod.list(\"modifier_key\", desc=\"All modifier keys\")\nmod.list(\"function_key\", desc=\"All function keys\")\nmod.list(\"special_key\", desc=\"All special keys\")\nmod.list(\"punctuation\", desc=\"words for inserting punctuation into text\")\n\n\n@mod.capture(rule=\"{self.modifier_key}+\")\ndef modifiers(m) -> str:\n    \"One or more modifier keys\"\n    return \"-\".join(m.modifier_key_list)\n\n\n@mod.capture(rule=\"{self.arrow_key}\")\ndef arrow_key(m) -> str:\n    \"One directional arrow key\"\n    return m.arrow_key\n\n\n@mod.capture(rule=\"<self.arrow_key>+\")\ndef arrow_keys(m) -> str:\n    \"One or more arrow keys separated by a space\"\n    return str(m)\n\n\n@mod.capture(rule=\"{self.number_key}\")\ndef number_key(m) -> str:\n    \"One number key\"\n    return m.number_key\n\n\n@mod.capture(rule=\"{self.letter}\")\ndef letter(m) -> str:\n    \"One letter key\"\n    return m.letter\n\n\n@mod.capture(rule=\"{self.special_key}\")\ndef special_key(m) -> str:\n    \"One special key\"\n    return m.special_key\n\n\n@mod.capture(rule=\"{self.symbol_key}\")\ndef symbol_key(m) -> str:\n    \"One symbol key\"\n    return m.symbol_key\n\n\n@mod.capture(rule=\"{self.function_key}\")\ndef function_key(m) -> str:\n    \"One function key\"\n    return m.function_key\n\n\n@mod.capture(rule=\"( <self.letter> | <self.number_key> | <self.symbol_key> )\")\ndef any_alphanumeric_key(m) -> str:\n    \"any alphanumeric key\"\n    return str(m)\n\n\n@mod.capture(\n    rule=\"( <self.letter> | <self.number_key> | <self.symbol_key> \"\n    \"| <self.arrow_key> | <self.function_key> | <self.special_key> )\"\n)\ndef unmodified_key(m) -> str:\n    \"A single key with no modifiers\"\n    return str(m)\n\n\n@mod.capture(rule=\"{self.modifier_key}* <self.unmodified_key>\")\ndef key(m) -> str:\n    \"A single key with optional modifiers\"\n    try:\n        mods = m.modifier_key_list\n    except AttributeError:\n        mods = []\n    return \"-\".join(mods + [m.unmodified_key])\n\n\n@mod.capture(rule=\"<self.key>+\")\ndef keys(m) -> str:\n    \"A sequence of one or more keys with optional modifiers\"\n    return \" \".join(m.key_list)\n\n\n@mod.capture(rule=\"{self.letter}+\")\ndef letters(m) -> str:\n    \"Multiple letter keys\"\n    return \"\".join(m.letter_list)\n\n\nctx = Context()\nmodifier_keys = {\n    # If you find 'alt' is often misrecognized, try using 'alter'.\n    \"alt\": \"alt\",  #'alter': 'alt',\n    \"control\": \"ctrl\",  #'troll':   'ctrl',\n    \"shift\": \"shift\",  #'sky':     'shift',\n    \"super\": \"super\",\n}\nif app.platform == \"mac\":\n    modifier_keys[\"command\"] = \"cmd\"\n    modifier_keys[\"option\"] = \"alt\"\nctx.lists[\"self.modifier_key\"] = modifier_keys\nctx.lists[\"self.letter\"] = alphabet_list\n\n# `punctuation_words` is for words you want available BOTH in dictation and as key names in command mode.\n# `symbol_key_words` is for key names that should be available in command mode, but NOT during dictation.\npunctuation_words = {\n    # TODO: I'm not sure why we need these, I think it has something to do with\n    # Dragon. Possibly it has been fixed by later improvements to talon? -rntz\n    \"`\": \"`\",\n    \",\": \",\",  # <== these things\n    \"back tick\": \"`\",\n    \"grave\": \"`\",\n    \"comma\": \",\",\n    # Workaround for issue with conformer b-series; see #946\n    \"coma\": \",\",\n    \"period\": \".\",\n    \"full stop\": \".\",\n    \"semicolon\": \";\",\n    \"colon\": \":\",\n    \"forward slash\": \"/\",\n    \"question mark\": \"?\",\n    \"exclamation mark\": \"!\",\n    \"exclamation point\": \"!\",\n    \"asterisk\": \"*\",\n    \"hash sign\": \"#\",\n    \"number sign\": \"#\",\n    \"percent sign\": \"%\",\n    \"at sign\": \"@\",\n    \"and sign\": \"&\",\n    \"ampersand\": \"&\",\n    # Currencies\n    \"dollar sign\": \"$\",\n    \"pound sign\": \"\u00a3\",\n    \"hyphen\": \"-\",\n    \"L paren\": \"(\",\n    \"left paren\": \"(\",\n    \"R paren\": \")\",\n    \"right paren\": \")\",\n}\nsymbol_key_words = {\n    \"dot\": \".\",\n    \"point\": \".\",\n    \"quote\": \"'\",\n    \"question\": \"?\",\n    \"apostrophe\": \"'\",\n    \"L square\": \"[\",\n    \"left square\": \"[\",\n    \"square\": \"[\",\n    \"R square\": \"]\",\n    \"right square\": \"]\",\n    \"slash\": \"/\",\n    \"backslash\": \"\\\\\",\n    \"minus\": \"-\",\n    \"dash\": \"-\",\n    \"equals\": \"=\",\n    \"plus\": \"+\",\n    \"tilde\": \"~\",\n    \"bang\": \"!\",\n    \"down score\": \"_\",\n    \"underscore\": \"_\",\n    \"paren\": \"(\",\n    \"brace\": \"{\",\n    \"left brace\": \"{\",\n    \"brack\": \"{\",\n    \"bracket\": \"{\",\n    \"left bracket\": \"{\",\n    \"r brace\": \"}\",\n    \"right brace\": \"}\",\n    \"r brack\": \"}\",\n    \"r bracket\": \"}\",\n    \"right bracket\": \"}\",\n    \"angle\": \"<\",\n    \"left angle\": \"<\",\n    \"less than\": \"<\",\n    \"rangle\": \">\",\n    \"R angle\": \">\",\n    \"right angle\": \">\",\n    \"greater than\": \">\",\n    \"star\": \"*\",\n    \"hash\": \"#\",\n    \"percent\": \"%\",\n    \"caret\": \"^\",\n    \"amper\": \"&\",\n    \"pipe\": \"|\",\n    \"dub quote\": '\"',\n    \"double quote\": '\"',\n    # Currencies\n    \"dollar\": \"$\",\n    \"pound\": \"\u00a3\",\n}\n\n# make punctuation words also included in {user.symbol_keys}\nsymbol_key_words.update(punctuation_words)\nctx.lists[\"self.punctuation\"] = punctuation_words\nctx.lists[\"self.symbol_key\"] = symbol_key_words\nctx.lists[\"self.number_key\"] = dict(zip(default_digits, numbers))\nctx.lists[\"self.arrow_key\"] = {\n    \"down\": \"down\",\n    \"left\": \"left\",\n    \"right\": \"right\",\n    \"up\": \"up\",\n}\n\nsimple_keys = [\n    \"end\",\n    \"enter\",\n    \"escape\",\n    \"home\",\n    \"insert\",\n    \"pagedown\",\n    \"pageup\",\n    \"space\",\n    \"tab\",\n]\n\nalternate_keys = {\n    \"wipe\": \"backspace\",\n    \"delete\": \"backspace\",\n    #'junk': 'backspace',\n    \"forward delete\": \"delete\",\n    \"page up\": \"pageup\",\n    \"page down\": \"pagedown\",\n}\n# mac apparently doesn't have the menu key.\nif app.platform in (\"windows\", \"linux\"):\n    alternate_keys[\"menu key\"] = \"menu\"\n    alternate_keys[\"print screen\"] = \"printscr\"\n\nspecial_keys = {k: k for k in simple_keys}\nspecial_keys.update(alternate_keys)\nctx.lists[\"self.special_key\"] = special_keys\nctx.lists[\"self.function_key\"] = {\n    f\"F {default_f_digits[i]}\": f\"f{i + 1}\" for i in range(12)\n}\n\n\n@mod.action_class\nclass Actions:\n    def move_cursor(s: str):\n        \"\"\"Given a sequence of directions, eg. 'left left up', moves the cursor accordingly using edit.{left,right,up,down}.\"\"\"\n        for d in s.split():\n            if d in (\"left\", \"right\", \"up\", \"down\"):\n                getattr(actions.edit, d)()\n            else:\n                raise RuntimeError(f\"invalid arrow key: {d}\")\n", "path": "core/keys/keys.py"}], "after_files": [{"content": "from talon import Context, Module, actions, app\n\nfrom ..user_settings import get_list_from_csv\n\n\ndef setup_default_alphabet():\n    \"\"\"set up common default alphabet.\n\n    no need to modify this here, change your alphabet using alphabet.csv\"\"\"\n    initial_default_alphabet = \"air bat cap drum each fine gust harp sit jury crunch look made near odd pit quench red sun trap urge vest whale plex yank zip\".split(\n        \" \"\n    )\n    initial_letters_string = \"abcdefghijklmnopqrstuvwxyz\"\n    initial_default_alphabet_dict = dict(\n        zip(initial_default_alphabet, initial_letters_string)\n    )\n\n    return initial_default_alphabet_dict\n\n\nalphabet_list = get_list_from_csv(\n    \"alphabet.csv\", (\"Letter\", \"Spoken Form\"), setup_default_alphabet()\n)\n\ndefault_digits = \"zero one two three four five six seven eight nine\".split(\" \")\nnumbers = [str(i) for i in range(10)]\ndefault_f_digits = (\n    \"one two three four five six seven eight nine ten eleven twelve\".split(\" \")\n)\n\nmod = Module()\nmod.list(\"letter\", desc=\"The spoken phonetic alphabet\")\nmod.list(\"symbol_key\", desc=\"All symbols from the keyboard\")\nmod.list(\"arrow_key\", desc=\"All arrow keys\")\nmod.list(\"number_key\", desc=\"All number keys\")\nmod.list(\"modifier_key\", desc=\"All modifier keys\")\nmod.list(\"function_key\", desc=\"All function keys\")\nmod.list(\"special_key\", desc=\"All special keys\")\nmod.list(\"punctuation\", desc=\"words for inserting punctuation into text\")\n\n\n@mod.capture(rule=\"{self.modifier_key}+\")\ndef modifiers(m) -> str:\n    \"One or more modifier keys\"\n    return \"-\".join(m.modifier_key_list)\n\n\n@mod.capture(rule=\"{self.arrow_key}\")\ndef arrow_key(m) -> str:\n    \"One directional arrow key\"\n    return m.arrow_key\n\n\n@mod.capture(rule=\"<self.arrow_key>+\")\ndef arrow_keys(m) -> str:\n    \"One or more arrow keys separated by a space\"\n    return str(m)\n\n\n@mod.capture(rule=\"{self.number_key}\")\ndef number_key(m) -> str:\n    \"One number key\"\n    return m.number_key\n\n\n@mod.capture(rule=\"{self.letter}\")\ndef letter(m) -> str:\n    \"One letter key\"\n    return m.letter\n\n\n@mod.capture(rule=\"{self.special_key}\")\ndef special_key(m) -> str:\n    \"One special key\"\n    return m.special_key\n\n\n@mod.capture(rule=\"{self.symbol_key}\")\ndef symbol_key(m) -> str:\n    \"One symbol key\"\n    return m.symbol_key\n\n\n@mod.capture(rule=\"{self.function_key}\")\ndef function_key(m) -> str:\n    \"One function key\"\n    return m.function_key\n\n\n@mod.capture(rule=\"( <self.letter> | <self.number_key> | <self.symbol_key> )\")\ndef any_alphanumeric_key(m) -> str:\n    \"any alphanumeric key\"\n    return str(m)\n\n\n@mod.capture(\n    rule=\"( <self.letter> | <self.number_key> | <self.symbol_key> \"\n    \"| <self.arrow_key> | <self.function_key> | <self.special_key> )\"\n)\ndef unmodified_key(m) -> str:\n    \"A single key with no modifiers\"\n    return str(m)\n\n\n@mod.capture(rule=\"{self.modifier_key}* <self.unmodified_key>\")\ndef key(m) -> str:\n    \"A single key with optional modifiers\"\n    try:\n        mods = m.modifier_key_list\n    except AttributeError:\n        mods = []\n    return \"-\".join(mods + [m.unmodified_key])\n\n\n@mod.capture(rule=\"<self.key>+\")\ndef keys(m) -> str:\n    \"A sequence of one or more keys with optional modifiers\"\n    return \" \".join(m.key_list)\n\n\n@mod.capture(rule=\"{self.letter}+\")\ndef letters(m) -> str:\n    \"Multiple letter keys\"\n    return \"\".join(m.letter_list)\n\n\nctx = Context()\nmodifier_keys = {\n    # If you find 'alt' is often misrecognized, try using 'alter'.\n    \"alt\": \"alt\",  #'alter': 'alt',\n    \"control\": \"ctrl\",  #'troll':   'ctrl',\n    \"shift\": \"shift\",  #'sky':     'shift',\n    \"super\": \"super\",\n}\nif app.platform == \"mac\":\n    modifier_keys[\"command\"] = \"cmd\"\n    modifier_keys[\"option\"] = \"alt\"\nctx.lists[\"self.modifier_key\"] = modifier_keys\nctx.lists[\"self.letter\"] = alphabet_list\n\n# `punctuation_words` is for words you want available BOTH in dictation and as key names in command mode.\n# `symbol_key_words` is for key names that should be available in command mode, but NOT during dictation.\npunctuation_words = {\n    # TODO: I'm not sure why we need these, I think it has something to do with\n    # Dragon. Possibly it has been fixed by later improvements to talon? -rntz\n    \"`\": \"`\",\n    \",\": \",\",  # <== these things\n    \"back tick\": \"`\",\n    \"comma\": \",\",\n    # Workaround for issue with conformer b-series; see #946\n    \"coma\": \",\",\n    \"period\": \".\",\n    \"full stop\": \".\",\n    \"semicolon\": \";\",\n    \"colon\": \":\",\n    \"forward slash\": \"/\",\n    \"question mark\": \"?\",\n    \"exclamation mark\": \"!\",\n    \"exclamation point\": \"!\",\n    \"asterisk\": \"*\",\n    \"hash sign\": \"#\",\n    \"number sign\": \"#\",\n    \"percent sign\": \"%\",\n    \"at sign\": \"@\",\n    \"and sign\": \"&\",\n    \"ampersand\": \"&\",\n    # Currencies\n    \"dollar sign\": \"$\",\n    \"pound sign\": \"\u00a3\",\n    \"hyphen\": \"-\",\n    \"L paren\": \"(\",\n    \"left paren\": \"(\",\n    \"R paren\": \")\",\n    \"right paren\": \")\",\n}\nsymbol_key_words = {\n    \"dot\": \".\",\n    \"point\": \".\",\n    \"quote\": \"'\",\n    \"question\": \"?\",\n    \"apostrophe\": \"'\",\n    \"L square\": \"[\",\n    \"left square\": \"[\",\n    \"square\": \"[\",\n    \"R square\": \"]\",\n    \"right square\": \"]\",\n    \"slash\": \"/\",\n    \"backslash\": \"\\\\\",\n    \"minus\": \"-\",\n    \"dash\": \"-\",\n    \"equals\": \"=\",\n    \"plus\": \"+\",\n    \"grave\": \"`\",\n    \"tilde\": \"~\",\n    \"bang\": \"!\",\n    \"down score\": \"_\",\n    \"underscore\": \"_\",\n    \"paren\": \"(\",\n    \"brace\": \"{\",\n    \"left brace\": \"{\",\n    \"brack\": \"{\",\n    \"bracket\": \"{\",\n    \"left bracket\": \"{\",\n    \"r brace\": \"}\",\n    \"right brace\": \"}\",\n    \"r brack\": \"}\",\n    \"r bracket\": \"}\",\n    \"right bracket\": \"}\",\n    \"angle\": \"<\",\n    \"left angle\": \"<\",\n    \"less than\": \"<\",\n    \"rangle\": \">\",\n    \"R angle\": \">\",\n    \"right angle\": \">\",\n    \"greater than\": \">\",\n    \"star\": \"*\",\n    \"hash\": \"#\",\n    \"percent\": \"%\",\n    \"caret\": \"^\",\n    \"amper\": \"&\",\n    \"pipe\": \"|\",\n    \"dub quote\": '\"',\n    \"double quote\": '\"',\n    # Currencies\n    \"dollar\": \"$\",\n    \"pound\": \"\u00a3\",\n}\n\n# make punctuation words also included in {user.symbol_keys}\nsymbol_key_words.update(punctuation_words)\nctx.lists[\"self.punctuation\"] = punctuation_words\nctx.lists[\"self.symbol_key\"] = symbol_key_words\nctx.lists[\"self.number_key\"] = dict(zip(default_digits, numbers))\nctx.lists[\"self.arrow_key\"] = {\n    \"down\": \"down\",\n    \"left\": \"left\",\n    \"right\": \"right\",\n    \"up\": \"up\",\n}\n\nsimple_keys = [\n    \"end\",\n    \"enter\",\n    \"escape\",\n    \"home\",\n    \"insert\",\n    \"pagedown\",\n    \"pageup\",\n    \"space\",\n    \"tab\",\n]\n\nalternate_keys = {\n    \"wipe\": \"backspace\",\n    \"delete\": \"backspace\",\n    #'junk': 'backspace',\n    \"forward delete\": \"delete\",\n    \"page up\": \"pageup\",\n    \"page down\": \"pagedown\",\n}\n# mac apparently doesn't have the menu key.\nif app.platform in (\"windows\", \"linux\"):\n    alternate_keys[\"menu key\"] = \"menu\"\n    alternate_keys[\"print screen\"] = \"printscr\"\n\nspecial_keys = {k: k for k in simple_keys}\nspecial_keys.update(alternate_keys)\nctx.lists[\"self.special_key\"] = special_keys\nctx.lists[\"self.function_key\"] = {\n    f\"F {default_f_digits[i]}\": f\"f{i + 1}\" for i in range(12)\n}\n\n\n@mod.action_class\nclass Actions:\n    def move_cursor(s: str):\n        \"\"\"Given a sequence of directions, eg. 'left left up', moves the cursor accordingly using edit.{left,right,up,down}.\"\"\"\n        for d in s.split():\n            if d in (\"left\", \"right\", \"up\", \"down\"):\n                getattr(actions.edit, d)()\n            else:\n                raise RuntimeError(f\"invalid arrow key: {d}\")\n", "path": "core/keys/keys.py"}]}