[vim/vim] vim9.txt revisions, standardizing SS1,3-7 (PR #20706)

1 view
Skip to first unread message

Peter Kenny

unread,
Jul 4, 2026, 7:49:14 PM (5 hours ago) Jul 4
to vim/vim, Subscribed

vim9.txt: conclusion to the rewrite and enhancements - part 1 of 2

In this “part 1”, several global changes and improvements are made to vim9.txt (except for sections 2 and 8, which will be addressed in “part 2”). “Part 2” is written already, but is large. So it is better separated from this PR.

The changes are:

  • Minimisation of spacing with two-space indents for the scripts, more use of tabs, etc., and reflect the discussion at PR19298.
  • Where is makes sense, tags are indented consistently with seven tabs.
  • Vim9 script code blocks have >vim9 on the blank line that separates the text from the code block. (This makes maintenance easier too with fewer lines getting wrapped unnecessarily when using gq.)
  • The Notes: blocks are reformatted. They now have no indent, as discussed and agreed in PR19250.
  • Line length is kept to 78 characters (displayed width, excluding concealed characters). Therefore, lines like 3464, which is only 72 display characters' width is okay (despite having 80 characters if the concealed | and ` characters are counted).

Locations of changes are indicated by reference to *tag* in the updated file.

Introduction

3. New style functions

  • “If the script the :def function is defined in is a Vim9...”: The paragraph and example are extended and qualified to cover exists_compiled().
  • The following example has the “unus” and “duo” changed to “one” and “two” to match the re-work of the prior example and now demonstrates the exists() versus exists_compiled() difference.

4. Types

*tuple-type*

  • The initial five examples are made sourceable.

*variadic-tuple*

  • The second sentence now demonstrates E1539 specifically and, like the initial five examples, is re-worked to be tuples “t6” to “t8”, and is sourceable.

*vim9-func-declaration*

  • Tags *E1005* and *E1007* are moved to the end of the passage on the func type as they are specific func related errors.

  • Regarding the func list in the current help:

    • It was the only type where examples are not provided. (I’d thought about it when updating Section 4 last year, but skipped past it at the time.) It needs examples because they are not all obvious. Using a similar function-func pattern makes them relatively short (<=7 lines each).
    • The current final example, func({type}, ?{type}, ...list<{type}>): {type}, is sufficiently problematic to warrant it being omitted. Although it can “work” in some scenarios, the danger is that it is interpreted as meaning the optional parameter 2 always may be omitted when parameter 3 is provided. It (or more correctly, they, if the [: void] variant was also included) could be reverted, and included as the last examples:
      func({type}, ?{type}, ...list<{type}>)[: void]
      		- typed mandatory argument
      		- typed optional argument
      		- typed list for variable number of arguments
      		- does not return a value
      
      func({type}, ?{type}, ...list<{type}>): {type}
      		- typed mandatory argument
      		- typed optional argument
      		- typed list for variable number of arguments
      		- returns a typed value
    

    However, doing so would need to come with warnings regarding unintended consequences and errors. A mostly “working” example is this (echoing 9 for all output except the last line):

     vim9script
     def D(n: number, o: float = 0.1, ...l: list<number>): number
       return (n + o + max(sort(l, (x, y) => x + y)))->float2nr()
     enddef
     const F: func(number, ?float, ...list<number>): number = D->function()
     echo F(9)
     echo F(8, 1.0)
     echo F(7, 1.0, 0, 1)
     echo F(6, 2.0, 1)
     echo F(5, 3, 1)
     echo F(4, 5)
     echo F(8, 1)  # E1013
    

    The problem with this example is that, although it appears to be successfully skipping the float, that’s not what it’s doing. What is happening is that the number (3 in the third-to-last echo, then 5 in the penultimate echo) is being coerced to a float. This can be proven by adding an echo l[0] to D():

     vim9script
     def D(n: number, o: float = 0.1, ...l: list<number>): number
       echo $'({l[0]} is the first list item)'
       return (n + o + max(sort(l, (x, y) => x + y)))->float2nr()
     enddef
     const F: func(number, ?float, ...list<number>): number = D->function()
     echo F(1, 2.0, 1, 6)
     echo F(1, 2, 6)
    

    This shows that 6 is the first list item in the second echo, not 2, which it would be if the optional float was truly being skipped.
    It feels wrong to be documenting a questionable “way”: As this example shows, the optional parameter cannot actually be skipped. It is always filled positionally, either by coercion or error. So, it does not feel helpful suggesting this “way”.

    • Did not provide other “ways”. Now the following are included:

      func(?{type}): {type}

      func(...list<{type}>): {type}

      func({type}, ...list<{type}>)[: void]

      func({type}, ...list<{type}>): {type}
    • “If the return type is "void" the function does not return a value.”: This makes sense to retain, though it is benefited from listing the variations up front and using [: void] for the implicit/explicit indicator of no typed return value.

*E1005*

  • Tag *E1005* is distinctly addressed. It was not stated anywhere what this is relates to. Providing an example of, “No more than 19 argument types may be used...”, takes only a few lines to illustrate the point. A working, extreme example with precisely 19 arguments (for anyone who wants it 😀️) is:
     vim9script
     var X: func
     X = (a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s) => 0
     # The lambda X() can have up to 20 arguments (19 are shown here):
     echo X(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 19)
     # The Funcref F() can have up to 19 arguments:
     var F: func(any, any, any, any, any, any, any, any, any, any, any,
       \ any, any, any, any, any, any, any, any): any = X->function()
     echo F(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6, 7, 8, 19)
    

*E1007*

  • Tag *E1007* is treated separately too. It is another specific error related to Funcrefs - i.e., trying to use a mandatory argument after an optional argument. (Incidental: It has some parallels to the removed, problematic, func({type}, ?{type}, ...list<{type}>): {type}.)

5. Generic functions

This section receives the same global changes applied elsewhere (2-space body indent, standalone >vim9 syntax blocks, trailing-comment condensation, “Note:” treatment, etc.); there are no substantive content changes.

6. Namespace, Import and Export

*E1304*

  • The tag is moved above the paragraph, which is improved and extended, now noting the other error (E1016, with a hot-link), and two examples are provided to illustrate E1016 and E1304.

Export

*:export*

  • Tag *:exp* is removed because using that invalid shortened form gives E1065.
  • The list is made more consistent and the conflicting final someValue/const somevalue is removed. Also,function is added: legacy functions, not just :def functions, can be exported.

*E1043*

  • This tag now stands alone, is explained (the current help is silent), and a one-line script demonstrates it occurring.

*E1042*

  • This tag and its explanation are refined to note “:export can only be used in a Vim9 script scope.” This is more accurate than the current help, which says, “at the script level”, which is inaccurate. For example, this script will export a constant, and it is not at the script level:
     vim9script
     b:tmp = $'{tempname()}.vim'->substitute('\\', '/', 'g')
     ['vim9script',
     'export def D(): void',
     '  export const C = "C is exported!"',
     'enddef']->writefile(b:tmp)
     import b:tmp as imported
     imported.D()
     echo $"Exported constant 'C' in 'imported' ({b:tmp}):\n" .. imported.C
    

*E1044*

  • This tag now also stands alone, and an example is provided to demonstrate it occurring.

Import

*:import*

  • Tag *:imp* is relocated because, like tag *:exp*, it is not helpful implying :imp is allowed in Vim9 script (it gives E1065, which is “command cannot be shortened”). It is relocated to the *import-legacy* passage, thought, because it is permitted in legacy Vim script.
  • Error tags currently appearing along with *:import* are relocated to their own distinct places, along with explanations and examples.

*E1094*

  • This is addressed separately and early because it is a general importing error relating to the limitation of only being able to import from a script local scope. An example shows how E1094 is given if it is not (such as from a function-local scope).

*E1053* *E1071*

  • Similarly, these are general importing errors, now explained succinctly and with one-line examples.

*:import-as*

  • The tags *E1257* and *E1261* are relocated later with distinct explanations and examples.
  • The introductory paragraphs and non-sourceable examples are re-worked into comprehensive explanations and a self-contained example of using :export and :import-as. It is helpful because, from personal experience, trying to understand the nuances of exporting and importing is not easy using the current help. Hopefully, providing working examples and more detailed explanations will make it easier.

*E1047* to *E1262*

  • The 12 errors are now itemised with their own tags, explanations, and examples. Many were not clearly touched on, let alone explained, in the current help. Examples either import ccomplete.vim in Vim's $VIMRUNTIME path or temporarily write a Vim9 script to tempname(), then import it.

*import-map*

  • After the Note sentence, a self-contained example of using <ScriptCmd> is provided.

*import-legacy* *legacy-import* *:imp*

  • The tag :imp is moved here since the shortened form, :imp, is only valid in a legacy Vim script.
  • The sentence “And using the...” is merged with the following one which notes “the namespace cannot be resolved on its own”. A legacy Vim script sourceable example demonstrates both points.

7. Classes and interfaces

  • The second paragraph adds, “, |vim9class.txt|, though there are some examples in this help file such as at |vim9-class-type|, |vim9-enum-type|, and elsewhere.” The examples in vim9.txt are generally more detailed than those in vim9class.txt, so it is worth pointing users to them.

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

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

Commit Summary

  • 0d4f3ee vim9.txt revisions, standardizing SS1,3-7

File Changes

(1 file)

Patch Links:


Reply to this email directly, view it on GitHub, or unsubscribe.
Triage notifications, keep track of coding agent tasks and review pull requests on the go with GitHub Mobile for iOS and Android. Download it today!
You are receiving this because you are subscribed to this thread.Message ID: <vim/vim/pull/20706@github.com>

Reply all
Reply to author
Forward
0 new messages