[vim/vim] usercmd: add -completeopt=escape to escape spaces in custom completion (PR #20239)

3 views
Skip to first unread message

mattn

unread,
May 18, 2026, 4:45:17 AM (21 hours ago) May 18
to vim/vim, Subscribed

Currently, when a user command uses -complete=custom or -complete=customlist and the completion function returns a match containing spaces or backslashes, those characters are inserted into the command line as-is and the argument splitter treats them as separate arguments. Plugin authors have had to work around this by parsing getcmdline() themselves to reconstruct the intended single argument, which is fragile and repetitive.

This adds a new -completeopt=escape attribute that escapes spaces and backslashes when the selected match is inserted, while keeping the unescaped form for the popup menu, wildmenu and getcompletion(). ArgLead passed to the completion function is also unescaped, so the function continues to see the logical argument. Plugins that opt in can stop hand-rolling their own quoting/parsing logic.

Tests in Test_command_completeopt_escape cover customlist/custom insertion of spaces and backslashes, the no-escape baseline, getcompletion() returning the unescaped form, ArgLead unescaping, Tab-completion of the attribute value, and E475/E179 errors for invalid/empty values.


You can view, comment on, or merge this pull request online at:

  https://github.com/vim/vim/pull/20239

Commit Summary

  • 01f323d Add -completeopt=escape attribute for user commands

File Changes

(7 files)

Patch Links:


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/20239@github.com>

h_east

unread,
May 18, 2026, 7:59:46 AM (18 hours ago) May 18
to vim/vim, Subscribed
h-east left a comment (vim/vim#20239)

Overlap with v9.2.0494 (-nargs=_)

v9.2.0494 (merged from #20189 about 15 hours before this PR was opened) already addresses the same underlying problem — "custom/customlist completion cannot return matches with spaces" — via -nargs=_. Could you clarify how this PR is meant to coexist with it?

Specifically:

  • Both features target the same use case from #20102 / #19294.
  • -nargs=_ solves it by disabling the argument splitter during completion (single argument, no escaping needed). The match is inserted verbatim and <q-args> returns it as-is.
  • -completeopt=escape solves it by keeping the splitter and inserting a backslash-escaped form. <q-args> then returns the unescaped value.

From a user's point of view this introduces two attributes that overlap heavily for the most common case (single argument with spaces), and the <q-args> semantics differ between the two — a plugin author now has to know which mechanism a given command was defined with.

Questions:

  1. What is the intended split between -nargs=_ and -completeopt=escape? Is the latter only meant for the narrower case of multiple arguments where each may contain spaces?
  2. If so, would it be possible to document that boundary clearly in :help :command-completeopt, and to note in :help :command-nargs that -nargs=_ should be preferred for the single-argument case?
  3. Given that v9.2.0494 already covers the primary use case at +110/-14 lines, is the +459/-24 lines of escape/unescape machinery here justified by the remaining cases? A concrete example that -nargs=_ cannot handle would help motivate the addition.

Without that justification, the simpler path is to keep -nargs=_ as the single mechanism and close this PR.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/20239/c4477423914@github.com>

mattn

unread,
May 18, 2026, 8:52:55 AM (17 hours ago) May 18
to vim/vim, Push

@mattn pushed 1 commit.

  • d936b76 Remove redundant FEAT_EVAL guards in f_getcompletion


View it on GitHub or unsubscribe.


Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/20239/before/01f323dd007cae39fcce5460ee6b3207fa5f3041/after/d936b76115739c4e846b6766231702fdbbba9289@github.com>

mattn

unread,
May 18, 2026, 8:58:48 AM (17 hours ago) May 18
to vim/vim, Subscribed
mattn left a comment (vim/vim#20239)

The two features address different shapes of the problem.

-nargs=_ treats the entire argument area as a single "line" exactly as typed — even if it contains spaces, it is one value. That is the right tool when you want to take the visible line, as-is, as a single argument.

-completeopt=escape is for the multi-argument case (-nargs=+, -nargs=*, etc.) where the splitter must keep working but an individual argument may itself contain spaces. The completion result foo bar is inserted as foo\ bar so the splitter still sees it as one argument, while ArgLead is passed to the completion function as the unescaped foo bar so the function works with the logical value.

Concrete example:

func MyComplete(ArgLead, CmdLine, CursorPos)
  return ["one value", "two values", "three values"]->matchfuzzy(a:ArgLead)
endfunc
command -nargs=+ -complete=customlist,MyComplete -completeopt=escape MyCmd echo <f-args>

Completing :MyCmd one va<Tab> two<Tab> produces :MyCmd one\ value two\ values, and <f-args> yields two arguments one value and two values. -nargs=_ cannot express this because it disables splitting entirely.

So the split is: -nargs=_ when the whole line should be taken as one argument as-is, -completeopt=escape for multi-argument commands where arguments may contain spaces. I'm happy to document that boundary in :help :command-completeopt and add a note in :help :command-nargs, and to add a -nargs=+ test case so the multi-argument scenario is covered explicitly (the current tests focus on -nargs=1, which admittedly overlaps with -nargs=_).


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/20239/c4477897009@github.com>

h_east

unread,
May 18, 2026, 9:38:45 AM (16 hours ago) May 18
to vim/vim, Subscribed
h-east left a comment (vim/vim#20239)

On the user-visible boundary between -nargs=_ and -completeopt=escape

Thanks, the example clarifies the intent. After reading it I agree the two features are genuinely orthogonal:

  • -nargs=_ is an argument-count rule — the splitter is disabled, there is always exactly one argument equal to the whole tail.
  • -completeopt=escape is an insertion rule — the splitter still runs, and individual arguments may carry escaped spaces.

These cannot reasonably be folded into a single attribute without awkward composite values like -nargs=+esc, so the two-attribute design is justified.

That said, since v9.2.0494 only landed yesterday, the public surface here is not yet frozen, and I'd like to make sure users do not have to puzzle out the boundary themselves. Three small requests:

1. Document the boundary explicitly

Add a short comparison in :help :command-completeopt and a cross-reference from :help :command-nargs, along the lines of:

  • "whole line as one argument, no escaping" → -nargs=_
  • "multiple arguments, each may contain spaces" → -nargs=+/* + -completeopt=escape

This makes it clear that the two attributes target different shapes, not competing solutions for the same shape — which is the question I expect most plugin authors to ask first.

2. Reject combining -nargs=_ with -completeopt=escape

The two have orthogonal purposes, and a command using both is almost certainly a misunderstanding (the escape attribute has no effect when the splitter is already disabled). Emitting an error at command-definition time, e.g.

E???: -nargs=_ cannot be combined with -completeopt=escape

removes one obvious source of confusion at the cheapest possible cost.

3. Add a -nargs=+ test case

You already offered this — having an explicit -nargs=+ test next to the existing -nargs=1 ones in Test_command_completeopt_escape would make the multi-argument scenario (which is the case -nargs=_ cannot express) visible in the test suite, and serves as living documentation for the boundary.

If those three are in scope, I have no further concerns about the overlap.


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications on the go with GitHub Mobile for iOS or Android.

You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/20239/c4478204350@github.com>

Reply all
Reply to author
Forward
0 new messages