We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
please map both comma and coma to , for now in keys.py
coma being recognized instead of comma comes up a lot for conformer b-series
I think for now we should bind both comma and coma as , in keys.py
and revisit if a future model sorts out the difference better

--- END ISSUE ---

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

{"golden_diff": "diff --git a/code/keys.py b/code/keys.py\n--- a/code/keys.py\n+++ b/code/keys.py\n@@ -132,6 +132,8 @@\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", "issue": "please map both comma and coma to , for now in keys.py\ncoma being recognized instead of comma comes up a lot for conformer b-series\r\nI think for now we should bind both comma and coma as , in keys.py\r\nand revisit if a future model sorts out the difference better\n", "before_files": [{"content": "from talon import Context, Module, actions, app\n\ndefault_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)\nletters_string = \"abcdefghijklmnopqrstuvwxyz\"\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\nalphabet = dict(zip(default_alphabet, letters_string))\nctx.lists[\"self.letter\"] = alphabet\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    \"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}\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    \"L paren\": \"(\",\n    \"left paren\": \"(\",\n    \"R paren\": \")\",\n    \"right 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    \"dubquote\": '\"',\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": "code/keys.py"}], "after_files": [{"content": "from talon import Context, Module, actions, app\n\ndefault_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)\nletters_string = \"abcdefghijklmnopqrstuvwxyz\"\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\nalphabet = dict(zip(default_alphabet, letters_string))\nctx.lists[\"self.letter\"] = alphabet\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}\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    \"L paren\": \"(\",\n    \"left paren\": \"(\",\n    \"R paren\": \")\",\n    \"right 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    \"dubquote\": '\"',\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": "code/keys.py"}]}