Skip to content

Commit 5a1e148

Browse files
committed
Update tui key bindings to have a specified completion key, move through completions with left and right arrows since that makes way more sense
1 parent dfba5e5 commit 5a1e148

2 files changed

Lines changed: 64 additions & 37 deletions

File tree

aider/tui/app.py

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -69,40 +69,57 @@ def __init__(self, coder_worker, output_queue, input_queue, args):
6969
)
7070

7171
self.bind(
72-
self.tui_config["key_bindings"]["newline"], "noop", description="New Line", show=True
72+
self._encode_keys(self.get_keys_for("newline")),
73+
"noop",
74+
description="New Line",
75+
show=True,
7376
)
7477
self.bind(
75-
self.tui_config["key_bindings"]["submit"], "noop", description="Submit", show=True
78+
self._encode_keys(self.get_keys_for("submit")), "noop", description="Submit", show=True
7679
)
7780
self.bind(
78-
self.tui_config["key_bindings"]["cycle_forward"],
81+
self._encode_keys(self.get_keys_for("completion")),
82+
"noop",
83+
description="Accept Completion",
84+
show=True,
85+
)
86+
self.bind(
87+
self._encode_keys(self.get_keys_for("cycle_forward")),
7988
"noop",
8089
description="Cycle Forward",
8190
show=True,
8291
)
8392
self.bind(
84-
self.tui_config["key_bindings"]["cycle_backward"],
93+
self._encode_keys(self.get_keys_for("cycle_backward")),
8594
"noop",
8695
description="Cycle Backward",
8796
show=True,
8897
)
8998
self.bind(
90-
self.tui_config["key_bindings"]["cancel"], "noop", description="Cancel", show=True
99+
self._encode_keys(self.get_keys_for("cancel")), "noop", description="Cancel", show=True
91100
)
92101

93102
self.bind(
94-
self.tui_config["key_bindings"]["focus"],
103+
self._encode_keys(self.get_keys_for("focus")),
95104
"focus_input",
96105
description="Focus Input",
97106
show=True,
98107
)
99108
self.bind(
100-
self.tui_config["key_bindings"]["stop"], "interrupt", description="Interrupt", show=True
109+
self._encode_keys(self.get_keys_for("stop")),
110+
"interrupt",
111+
description="Interrupt",
112+
show=True,
101113
)
102114
self.bind(
103-
self.tui_config["key_bindings"]["clear"], "clear_output", description="Clear", show=True
115+
self._encode_keys(self.get_keys_for("clear")),
116+
"clear_output",
117+
description="Clear",
118+
show=True,
119+
)
120+
self.bind(
121+
self._encode_keys(self.get_keys_for("focus")), "quit", description="Quit", show=True
104122
)
105-
self.bind(self.tui_config["key_bindings"]["focus"], "quit", description="Quit", show=True)
106123

107124
self.register_theme(BASE_THEME)
108125
self.theme = "aider"
@@ -166,9 +183,10 @@ def _get_config(self):
166183
default_key_bindings = {
167184
"newline": "enter" if is_multiline else "shift+enter",
168185
"submit": "shift+enter" if is_multiline else "enter",
186+
"completion": "tab",
169187
"stop": "escape",
170-
"cycle_forward": "tab",
171-
"cycle_backward": "shift+tab",
188+
"cycle_forward": "right",
189+
"cycle_backward": "left",
172190
"focus": "ctrl+f",
173191
"cancel": "ctrl+c",
174192
"clear": "ctrl+l",
@@ -267,10 +285,10 @@ def update_key_hints(self, generating=False):
267285
try:
268286
hints = self.query_one(KeyHints)
269287
if generating:
270-
stop = self.app._decode_keys(self.app.tui_config["key_bindings"]["stop"])
288+
stop = self.app.get_keys_for("stop")
271289
hints.update(f"{stop} to cancel")
272290
else:
273-
submit = self.app._decode_keys(self.app.tui_config["key_bindings"]["submit"])
291+
submit = self.app.get_keys_for("submit")
274292
hints.update(f"{submit} to submit")
275293
except Exception:
276294
pass
@@ -486,17 +504,26 @@ def action_noop(self):
486504
pass
487505

488506
def _encode_keys(self, key):
489-
if key == "shift+enter":
490-
return "ctrl+j"
507+
key = key.replace("shift+enter", "ctrl+j")
491508

492509
return key
493510

494511
def _decode_keys(self, key):
495-
if key == "ctrl+j":
496-
return "shift+enter"
512+
key = key.replace("ctrl+j", "shift+enter")
497513

498514
return key
499515

516+
def is_key_for(self, type, key):
517+
allowed_keys = self.tui_config["key_bindings"][type].split(",")
518+
if key in allowed_keys:
519+
return True
520+
521+
return False
522+
523+
def get_keys_for(self, type):
524+
allowed_keys = self.tui_config["key_bindings"][type]
525+
return self._decode_keys(allowed_keys)
526+
500527
def _do_quit(self):
501528
"""Perform the actual quit after UI updates."""
502529
self.worker.stop()

aider/tui/widgets/input_area.py

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,8 @@ def __init__(self, history_file: str = None, **kwargs):
5959
# Let's assume kwargs might handle it or we set it.
6060
# Actually, let's just set the default if it's empty.
6161
if not self.placeholder:
62-
submit = self.app._decode_keys(self.app.tui_config["key_bindings"]["submit"])
63-
newline = self.app._decode_keys(self.app.tui_config["key_bindings"]["newline"])
62+
submit = self.app.get_keys_for("submit")
63+
newline = self.app.get_keys_for("newline")
6464

6565
self.placeholder = (
6666
f"> Type your message... ({submit} to submit, {newline} for new line)"
@@ -208,38 +208,38 @@ def on_key(self, event) -> None:
208208
if self.disabled:
209209
return
210210

211-
if event.key == self.app.tui_config["key_bindings"]["cancel"]:
211+
if self.app.is_key_for("cancel", event.key):
212212
event.stop()
213213
event.prevent_default()
214214
if self.text.strip():
215215
self.save_to_history(self.text)
216216
self.text = ""
217217
return
218218

219-
if event.key == self.app.tui_config["key_bindings"]["submit"]:
219+
if self.completion_active and self.app.is_key_for("completion", event.key):
220+
# Accept completion
221+
self.post_message(self.CompletionAccept())
222+
event.stop()
223+
event.prevent_default()
224+
return
225+
226+
if self.app.is_key_for("submit", event.key):
220227
# Submit message
221228
event.stop()
222229
event.prevent_default()
223230
self.post_message(self.Submit(self.text))
224231
return
225232

226-
if event.key == self.app.tui_config["key_bindings"]["newline"]:
227-
if self.completion_active:
228-
# Accept completion
229-
self.post_message(self.CompletionAccept())
230-
event.stop()
231-
event.prevent_default()
232-
return
233-
else:
234-
if self.app.tui_config["key_bindings"]["newline"] != "enter":
235-
self.insert("\n")
233+
if self.app.is_key_for("newline", event.key):
234+
if self.app.get_keys_for("newline") != "enter":
235+
self.insert("\n")
236236

237-
current_row, current_col = self.cursor_location
238-
self.cursor_location = (current_row + 1, 0)
237+
current_row, current_col = self.cursor_location
238+
self.cursor_location = (current_row + 1, 0)
239239

240-
return
240+
return
241241

242-
if event.key == self.app.tui_config["key_bindings"]["cycle_forward"]:
242+
if self.app.is_key_for("cycle_forward", event.key):
243243
event.stop()
244244
event.prevent_default()
245245
if self.completion_active:
@@ -248,7 +248,7 @@ def on_key(self, event) -> None:
248248
else:
249249
# Request completions
250250
self.post_message(self.CompletionRequested(self.text))
251-
elif event.key == self.app.tui_config["key_bindings"]["cycle_backward"]:
251+
elif self.app.is_key_for("cycle_backward", event.key):
252252
event.stop()
253253
event.prevent_default()
254254
if self.completion_active:
@@ -257,7 +257,7 @@ def on_key(self, event) -> None:
257257
else:
258258
# Request completions
259259
self.post_message(self.CompletionRequested(self.text))
260-
elif event.key == self.app.tui_config["key_bindings"]["stop"] and self.completion_active:
260+
elif self.app.is_key_for("stop", event.key) and self.completion_active:
261261
event.stop()
262262
event.prevent_default()
263263
self.post_message(self.CompletionDismiss())

0 commit comments

Comments
 (0)