Skip to content

Commit ee2de9b

Browse files
committed
Auto complete works on empty input
1 parent 0caaf61 commit ee2de9b

2 files changed

Lines changed: 64 additions & 19 deletions

File tree

cecli/io.py

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,6 @@ def __init__(
148148
self.rel_fnames = rel_fnames
149149
self.encoding = encoding
150150
self.abs_read_only_fnames = abs_read_only_fnames or []
151-
self.post_filter_commands = ["/add"]
152151

153152
fname_to_rel_fnames = defaultdict(list)
154153
for rel_fname in addable_rel_fnames:
@@ -214,22 +213,47 @@ def tokenize(self):
214213

215214
def get_command_completions(self, document, complete_event, text, words):
216215
if len(words) == 1 and not text[-1].isspace():
216+
# Handle command completion (e.g., typing "/ad" should complete to "/add")
217217
partial = words[0].lower()
218+
# Strip leading '/' if present for comparison with command names
219+
if partial.startswith("/"):
220+
partial = partial[1:]
218221
candidates = [cmd for cmd in self.command_names if cmd.startswith(partial)]
219222
for candidate in sorted(candidates):
220-
yield Completion(candidate, start_position=-len(words[-1]))
223+
# Add back the leading '/' for the completion
224+
yield Completion("/" + candidate, start_position=-len(words[-1]))
221225
return
222226

223-
if len(words) <= 1 or text[-1].isspace():
224-
return
227+
# Handle command followed by space: trigger auto-completion with empty partial
228+
if text[-1].isspace():
229+
# We have a command followed by space, trigger auto-completion with empty string
230+
if len(words) == 1:
231+
# Command with no arguments yet, just a trailing space
232+
partial = ""
233+
# We need to get the command name without the trailing space
234+
# The command is words[0] but might have leading '/'
235+
cmd_text = words[0]
236+
else:
237+
# Command with arguments and trailing space
238+
partial = ""
239+
cmd_text = text.rstrip() # Remove trailing space for matching
240+
else:
241+
# No trailing space
242+
if len(words) <= 1:
243+
return
244+
partial = words[-1].lower()
245+
cmd_text = text
225246

226-
cmd = words[0]
227-
partial = words[-1].lower()
247+
# Pass the text (without trailing space if present) to matching_commands
248+
matches, matched_cmd, _ = self.commands.matching_commands(cmd_text.rstrip())
249+
if not matches:
250+
return
228251

229-
matches, _, _ = self.commands.matching_commands(cmd)
230252
if len(matches) == 1:
231253
cmd = matches[0]
232-
elif cmd not in matches:
254+
elif matched_cmd in matches:
255+
cmd = matched_cmd
256+
else:
233257
return
234258

235259
raw_completer = self.commands.get_raw_completions(cmd)
@@ -242,11 +266,14 @@ def get_command_completions(self, document, complete_event, text, words):
242266
if candidates is None:
243267
return
244268

245-
if cmd in self.post_filter_commands:
246-
candidates = [word for word in candidates if partial in word.lower()]
269+
candidates = [word for word in candidates if partial in word.lower()]
247270

248271
for candidate in sorted(candidates):
249-
yield Completion(candidate, start_position=-len(words[-1]))
272+
# Calculate start position based on partial, not words[-1]
273+
# When partial is empty (trailing space), start_position should be 0
274+
# When partial is not empty, replace that many characters
275+
start_position = -len(partial) if partial else 0
276+
yield Completion(candidate, start_position=start_position)
250277

251278
def get_completions(self, document, complete_event):
252279
self.tokenize()
@@ -256,8 +283,9 @@ def get_completions(self, document, complete_event):
256283
if not words:
257284
return
258285

259-
if text and text[-1].isspace():
260-
# don't keep completing after a space
286+
if text and text[-1].isspace() and not text.startswith("/"):
287+
# don't keep completing after a space for non-commands
288+
# For commands, we want to allow completion with empty string partial
261289
return
262290

263291
if text[0] == "/":

cecli/tui/app.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -884,7 +884,9 @@ def _get_suggestions(self, text: str) -> list[str]:
884884
suggestions = []
885885
commands = self.worker.coder.commands
886886

887-
if len(text) and text[-1] == " ":
887+
# Only return early for non-commands ending with space
888+
# For commands, we want to allow completion with empty string partial
889+
if len(text) and text[-1] == " " and not text.startswith("/"):
888890
return
889891

890892
if "@" in text:
@@ -905,12 +907,21 @@ def _get_suggestions(self, text: str) -> list[str]:
905907
suggestions = all_commands
906908
else:
907909
suggestions = [c for c in all_commands if c.startswith(cmd_part)]
908-
elif len(parts) > 1:
910+
else:
909911
# Complete command argument
912+
# This handles both:
913+
# 1. len(parts) > 1: command with arguments
914+
# 2. len(parts) == 1 and text.endswith(" "): command with trailing space
910915
cmd_name = cmd_part
911-
end_lookup = text.rsplit(maxsplit=1)
912916

913-
arg_prefix = end_lookup[-1]
917+
if text.endswith(" "):
918+
# Command with trailing space, empty argument prefix
919+
arg_prefix = ""
920+
else:
921+
# Get the last word as argument prefix
922+
end_lookup = text.rsplit(maxsplit=1)
923+
arg_prefix = end_lookup[-1]
924+
914925
arg_prefix_lower = arg_prefix.lower()
915926

916927
# Check if this command needs path-based completion
@@ -955,8 +966,14 @@ def _get_completed_text(self, current_text: str, completion: str) -> str:
955966
"""Calculate the new text after applying completion."""
956967
if current_text.startswith("/"):
957968
parts = current_text.rsplit(maxsplit=1)
958-
if len(parts) == 1:
959-
# Replace entire command
969+
970+
# Check if we have a command with trailing space
971+
# This is when we want to insert argument completions after the space
972+
if len(parts) == 1 and current_text.endswith(" "):
973+
# Command with trailing space, insert completion after space
974+
return current_text + completion
975+
elif len(parts) == 1:
976+
# Replace entire command (command name completion)
960977
# Only add space if command takes arguments
961978
commands = self.worker.coder.commands
962979
try:

0 commit comments

Comments
 (0)