Skip to content

Instantly share code, notes, and snippets.

@girishji
Last active June 6, 2024 09:14
Show Gist options
  • Save girishji/fc5aa175d2ab63d514cd5f3601ac70ae to your computer and use it in GitHub Desktop.
Save girishji/fc5aa175d2ab63d514cd5f3601ac70ae to your computer and use it in GitHub Desktop.
Vim Tip: Vim9script in Command Line

Note: This gist is now part of VimBits plugin.

As a Vim user, you might prefer the new vim9script over the legacy script, and wish to use it in the command line. While there's no direct option to switch the command line to parse vim9script, you can execute vim9script commands by simply prepending each command with vim9.

However, remember that execution occurs in the global context, not the script-local context. This means you need to declare variables with the g: prefix, like g:foo = 'bar'.

Common commands such as visual mode select ('<,'>), shell commands (!), substitution (s//), and global (g//) work as expected, even with vim9 prepended.

When specifying a range for the substitution command, the range should be prefixed by a colon. For example, to specify a line range from line 1 to line 10, use :vim9 :1,10s/foo/bar. Ranges can also be specified with marks, visual selection, and search patterns.

If you work with multi-byte UTF-8 characters, you'll appreciate the vim9 command line. When slicing a UTF-8 string using the [x : y] operator, vim9 is more predictable because it uses character-based addressing, unlike the byte-based addressing of the legacy script.

Add this to your .vimrc:

augroup vim9cmdline | autocmd!
    autocmd CmdlineEnter : {
        if visualmode() == null_string
            setcmdline('vim9 ')
        else
            setcmdline('vim9 :')
            visualmode(1)
        endif
        cnoremap        <c-u>    <c-u>vim9<space>
        cnoremap        <c-b>    <c-b><c-right><right>
        cnoremap <expr> <c-w>    getcmdpos() > 6 ? "\<c-w>" : ""
        cnoremap <expr> <c-left> getcmdpos() > 6 ? "\<c-left>" : ""
        cnoremap <expr> <bs>     getcmdpos() > 6 ? "\<bs>" : ""
        cnoremap <expr> <left>   getcmdpos() > 6 ? "\<left>" : ""
    }
    autocmd CmdlineLeave : {
        cunmap <c-u>
        cunmap <c-w>
        cunmap <c-b>
        cunmap <c-left>
        cunmap <bs>
        cunmap <left>
    }
augroup END

Edit: Prefixed colon to visual mode substitution command.

Edit: If you want the option to toggle between vim9 and legacy script in the command line (using :Vim9cmdlineToggle command), use the following gist:

vim9script
var vim9cmdline_enable = true

command Vim9cmdlineToggle {
    vim9cmdline_enable = !vim9cmdline_enable
}

augroup vim9cmdline | autocmd!
    autocmd CmdlineEnter : {
        if vim9cmdline_enable
            if visualmode() == null_string
                setcmdline('vim9 ')
            else
                setcmdline('vim9 :')
                visualmode(1)
            endif
            cnoremap        <c-u>    <c-u>vim9<space>
            cnoremap        <c-b>    <c-b><c-right><right>
            cnoremap <expr> <c-w>    getcmdpos() > 6 ? "\<c-w>" : ""
            cnoremap <expr> <c-left> getcmdpos() > 6 ? "\<c-left>" : ""
            cnoremap <expr> <bs>     getcmdpos() > 6 ? "\<bs>" : ""
            cnoremap <expr> <left>   getcmdpos() > 6 ? "\<left>" : ""
        endif
    }
    autocmd CmdlineLeave : {
        if vim9cmdline_enable
            cunmap <c-u>
            cunmap <c-w>
            cunmap <c-b>
            cunmap <c-left>
            cunmap <bs>
            cunmap <left>
        endif
    }
augroup END
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment