@@ -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,48 @@ 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- candidates = [cmd for cmd in self .command_names if cmd .startswith (partial )]
218+ # Strip leading '/' if present for comparison with command names
219+ if partial .startswith ("/" ):
220+ partial = partial [1 :]
221+ # Compare with command names without leading '/'
222+ candidates = [cmd for cmd in self .command_names if cmd [1 :].startswith (partial )]
219223 for candidate in sorted (candidates ):
224+ # Add back the leading '/' for the completion
220225 yield Completion (candidate , start_position = - len (words [- 1 ]))
221226 return
222227
223- if len (words ) <= 1 or text [- 1 ].isspace ():
224- return
228+ # Handle command followed by space: trigger auto-completion with empty partial
229+ if text [- 1 ].isspace ():
230+ # We have a command followed by space, trigger auto-completion with empty string
231+ if len (words ) == 1 :
232+ # Command with no arguments yet, just a trailing space
233+ partial = ""
234+ # We need to get the command name without the trailing space
235+ # The command is words[0] but might have leading '/'
236+ cmd_text = words [0 ]
237+ else :
238+ # Command with arguments and trailing space
239+ partial = ""
240+ cmd_text = text .rstrip () # Remove trailing space for matching
241+ else :
242+ # No trailing space
243+ if len (words ) <= 1 :
244+ return
245+ partial = words [- 1 ].lower ()
246+ cmd_text = text
225247
226- cmd = words [0 ]
227- partial = words [- 1 ].lower ()
248+ # Pass the text (without trailing space if present) to matching_commands
249+ matches , matched_cmd , _ = self .commands .matching_commands (cmd_text .rstrip ())
250+ if not matches :
251+ return
228252
229- matches , _ , _ = self .commands .matching_commands (cmd )
230253 if len (matches ) == 1 :
231254 cmd = matches [0 ]
232- elif cmd not in matches :
255+ elif matched_cmd in matches :
256+ cmd = matched_cmd
257+ else :
233258 return
234259
235260 raw_completer = self .commands .get_raw_completions (cmd )
@@ -242,11 +267,14 @@ def get_command_completions(self, document, complete_event, text, words):
242267 if candidates is None :
243268 return
244269
245- if cmd in self .post_filter_commands :
246- candidates = [word for word in candidates if partial in word .lower ()]
270+ candidates = [word for word in candidates if partial in word .lower ()]
247271
248272 for candidate in sorted (candidates ):
249- yield Completion (candidate , start_position = - len (words [- 1 ]))
273+ # Calculate start position based on partial, not words[-1]
274+ # When partial is empty (trailing space), start_position should be 0
275+ # When partial is not empty, replace that many characters
276+ start_position = - len (partial ) if partial else 0
277+ yield Completion (candidate , start_position = start_position )
250278
251279 def get_completions (self , document , complete_event ):
252280 self .tokenize ()
@@ -256,8 +284,9 @@ def get_completions(self, document, complete_event):
256284 if not words :
257285 return
258286
259- if text and text [- 1 ].isspace ():
260- # don't keep completing after a space
287+ if text and text [- 1 ].isspace () and not text .startswith ("/" ):
288+ # don't keep completing after a space for non-commands
289+ # For commands, we want to allow completion with empty string partial
261290 return
262291
263292 if text [0 ] == "/" :
0 commit comments