diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index bdf683a9d1..fb972b57fd 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1494,25 +1494,24 @@ $VIMRUNTIME/ftplugin directory, sets the 'formatexpr' option to: > That means, you will find the corresponding script, defining the xmlformat#Format() function, in the file `$VIMRUNTIME/autoload/xmlformat.vim` -Here is an example script that removes trailing whitespace from the selected -text. Put it in your autoload directory, e.g. ~/.vim/autoload/format.vim: ->vim - func! format#Format() - " only reformat on explicit gq command - if mode() != 'n' - " fall back to Vim's internal reformatting +Here is an example that removes trailing whitespace from the selected text. +Put it in your |ftplugin|: +>lua + vim.bo.formatexpr = function() + -- only reformat on explicit gq command + if vim.fn.mode() ~= 'n' then + -- fall back to the internal reformatting return 1 - endif - let lines = getline(v:lnum, v:lnum + v:count - 1) - call map(lines, {key, val -> substitute(val, '\s\+$', '', 'g')}) - call setline('.', lines) + end + local lines = vim.fn.getline(vim.v.lnum, vim.v.lnum + vim.v.count - 1) + for i, val in ipairs(lines) do + lines[i] = (val:gsub('%s+$', '')) + end + vim.fn.setline('.', lines) - " do not run internal formatter! + -- do not run internal formatter! return 0 - endfunc - -You can then enable the formatting by executing: > - setlocal formatexpr=format#Format() + end Note: this function explicitly returns non-zero when called from insert mode (which basically means, text is inserted beyond the 'textwidth' limit). This diff --git a/runtime/doc/diff.txt b/runtime/doc/diff.txt index e8e99901dd..5b8efd5bd1 100644 --- a/runtime/doc/diff.txt +++ b/runtime/doc/diff.txt @@ -511,28 +511,22 @@ Additionally, 'diffexpr' should take care of "icase" and "iwhite" in the The advantage of using a function call without arguments is that it is faster, see |expr-option-function|. -Example (this does almost the same as 'diffexpr' being empty): > +Example (this does almost the same as 'diffexpr' being empty): >lua - set diffexpr=MyDiff() - function MyDiff() - let opt = "" - if &diffopt =~ "icase" - let opt = opt .. "-i " - endif - if &diffopt =~ "iwhite" - let opt = opt .. "-b " - endif - silent execute "!diff -a --binary " .. opt .. v:fname_in .. " " .. v:fname_new .. - \ " > " .. v:fname_out - redraw! - endfunction + vim.o.diffexpr = function() + local opt = '' + if vim.o.diffopt:find('icase') then + opt = opt .. '-i ' + end + if vim.o.diffopt:find('iwhite') then + opt = opt .. '-b ' + end + vim.fn.system(('diff -a %s%s %s > %s'):format( + opt, vim.v.fname_in, vim.v.fname_new, vim.v.fname_out)) + end The "-a" argument is used to force comparing the files as text, comparing as -binaries isn't useful. The "--binary" argument makes the files read in binary -mode, so that a CTRL-Z doesn't end the text on DOS. - -The `redraw!` command may not be needed, depending on whether executing a -shell command shows something on the display or not. +binaries isn't useful. If the 'diffexpr' expression starts with s: or ||, then it is replaced with the script ID (|local-function|). Example: > @@ -579,13 +573,12 @@ will have the same effect. These variables are set to the file names used: The advantage of using a function call without arguments is that it is faster, see |expr-option-function|. -Example (this does the same as 'patchexpr' being empty): > +Example (this does the same as 'patchexpr' being empty): >lua - set patchexpr=MyPatch() - function MyPatch() - :call system("patch -o " .. v:fname_out .. " " .. v:fname_in .. - \ " < " .. v:fname_diff) - endfunction + vim.o.patchexpr = function() + vim.fn.system(('patch -o %s %s < %s'):format( + vim.v.fname_out, vim.v.fname_in, vim.v.fname_diff)) + end Make sure that using the "patch" program doesn't have unwanted side effects. For example, watch out for additionally generated files, which should be diff --git a/runtime/doc/fold.txt b/runtime/doc/fold.txt index e9bcaf60d2..6d55041451 100644 --- a/runtime/doc/fold.txt +++ b/runtime/doc/fold.txt @@ -67,17 +67,35 @@ EXPR *fold-expr* The folds are automatically defined by their foldlevel, like with the "indent" method. The value of the 'foldexpr' option is evaluated to get the foldlevel of a line. Examples: -This will create a fold for all consecutive lines that start with a tab: > +This will create a fold for all consecutive lines that start with a tab: >lua + vim.wo.foldexpr = function() + return vim.fn.getline(vim.v.lnum):sub(1, 1) == '\t' and 1 or 0 + end +This will make a fold out of paragraphs separated by blank lines: >lua + vim.wo.foldexpr = function() + if vim.fn.getline(vim.v.lnum):match('^%s*$') + and vim.fn.getline(vim.v.lnum + 1):match('%S') then + return '<1' + end + return 1 + end +This does the same: >lua + vim.wo.foldexpr = function() + if vim.fn.getline(vim.v.lnum - 1):match('^%s*$') + and vim.fn.getline(vim.v.lnum):match('%S') then + return '>1' + end + return 1 + end + +When setting an expression string with ":set" instead, backslashes must be +used to escape characters that ":set" handles differently (space, backslash, +double quote, etc., see |option-backslash|): >vim :set foldexpr=getline(v:lnum)[0]==\"\\t\" -This will make a fold out of paragraphs separated by blank lines: > - :set foldexpr=getline(v:lnum)=~'^\\s*$'&&getline(v:lnum+1)=~'\\S'?'<1':1 -This does the same: > - :set foldexpr=getline(v:lnum-1)=~'^\\s*$'&&getline(v:lnum)=~'\\S'?'>1':1 -Note that backslashes must be used to escape characters that ":set" handles -differently (space, backslash, double quote, etc., see |option-backslash|). - -The most efficient is to call a function without arguments: > +The most efficient is to use a function value (|expr-option-function|): >lua + vim.wo.foldexpr = MyFoldLevel +or to call a Vimscript function without arguments: >vim :set foldexpr=MyFoldLevel() The function must use v:lnum. See |expr-option-function|. @@ -159,20 +177,20 @@ level is found. If this proves difficult, the next best thing could be to cache all fold levels in a buffer-local variable (b:foldlevels) that is only updated on |b:changedtick|: ->vim - func MyFoldFunc() - if b:lasttick == b:changedtick - return b:foldlevels[v:lnum - 1] - endif - let b:lasttick = b:changedtick - let b:foldlevels = [] - " compute foldlevels ... - return b:foldlevels[v:lnum - 1] - enddef - set foldexpr=s:MyFoldFunc() +>lua + vim.wo.foldexpr = function() + if vim.b.lasttick == vim.b.changedtick then + return vim.b.foldlevels[vim.v.lnum] + end + vim.b.lasttick = vim.b.changedtick + local levels = {} + -- compute foldlevels ... + vim.b.foldlevels = levels + return levels[vim.v.lnum] + end < -In above example further speedup was gained by using a function without -arguments (that must still use v:lnum). See |expr-option-function|. +A function value also avoids re-parsing the expression for every line (it must +still use v:lnum). See |expr-option-function|. SYNTAX *fold-syntax* @@ -523,11 +541,14 @@ folds will be opened. FOLDTEXT *fold-foldtext* 'foldtext' is a string option that specifies an expression. This expression -is evaluated to obtain the text displayed for a closed fold. Example: > +is evaluated to obtain the text displayed for a closed fold. Example: >lua - :set foldtext=v:folddashes.substitute(getline(v:foldstart),'/\\*\\\|\\*/\\\|{{{\\d\\=','','g') + vim.wo.foldtext = function() + local line = vim.fn.getline(vim.v.foldstart) + return vim.v.folddashes .. line:gsub('/%*', ''):gsub('%*/', '') + end -This shows the first line of the fold, with "/*", "*/" and "{{{" removed. +This shows the first line of the fold, with "/*" and "*/" removed. Note the use of backslashes to avoid some characters to be interpreted by the ":set" command. It is much simpler to define a function and call it: > diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index cef97fb1bc..04132d592f 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -696,16 +696,16 @@ had been typed. For example, the following will map to either actually insert a if the current line is currently only whitespace, or start/continue a CTRL-N -completion operation: > +completion operation: >lua - function! CleverTab() - if strpart( getline('.'), 0, col('.')-1 ) =~ '^\s*$' - return "\" - else - return "\" - endif - endfunction - inoremap =CleverTab() + function _G.clever_tab() + if vim.fn.getline('.'):sub(1, vim.fn.col('.') - 1):match('^%s*$') then + return vim.keycode('') + else + return vim.keycode('') + end + end + vim.keymap.set('i', '', '=v:lua.clever_tab()') @@ -876,29 +876,29 @@ not used. See |complete-functions| for an explanation of how the function is invoked and what it should return. Here is an example that uses the "aiksaurus" command (provided by Magnus -Groß): > +Groß): >lua - func Thesaur(findstart, base) - if a:findstart - return searchpos('\<', 'bnW', line('.'))[1] - 1 - endif - let res = [] - let h = '' - for l in systemlist('aiksaurus ' .. shellescape(a:base)) - if l[:3] == '=== ' - let h = '(' .. substitute(l[4:], ' =*$', ')', '') - elseif l ==# 'Alphabetically similar known words are: ' - let h = "\U0001f52e" - elseif l[0] =~ '\a' || (h ==# "\U0001f52e" && l[0] ==# "\t") - call extend(res, map(split(substitute(l, '^\t', '', ''), ', '), {_, val -> {'word': val, 'menu': h}})) - endif - endfor + vim.o.thesaurusfunc = function(findstart, base) + if findstart == 1 then + return vim.fn.searchpos('\\<', 'bnW', vim.fn.line('.'))[2] - 1 + end + local res = {} + local h = '' + for _, l in ipairs(vim.fn.systemlist('aiksaurus ' + .. vim.fn.shellescape(base))) do + if l:sub(1, 4) == '=== ' then + h = ('(%s)'):format((l:sub(5):gsub(' =*$', ''))) + elseif l == 'Alphabetically similar known words are: ' then + h = '🔮' + elseif l:match('^%a') or (h == '🔮' and l:sub(1, 1) == '\t') then + local words = (l:gsub('^\t', '')) + for _, val in ipairs(vim.split(words, ', ', { plain = true })) do + table.insert(res, { word = val, menu = h }) + end + end + end return res - endfunc - - if exists('+thesaurusfunc') - set thesaurusfunc=Thesaur - endif + end Completing keywords in the current and included files *compl-keyword* @@ -1291,54 +1291,50 @@ while still searching for matches. Stop searching when it returns non-zero. The function is allowed to move the cursor, it is restored afterwards. The function is not allowed to move to another window or delete text. -An example that completes the names of the months: > - fun! CompleteMonths(findstart, base) - if a:findstart - " locate the start of the word - let line = getline('.') - let start = col('.') - 1 - while start > 0 && line[start - 1] =~ '\a' - let start -= 1 - endwhile - return start - else - " find months matching with "a:base" - let res = [] - for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec") - if m =~ '^' .. a:base - call add(res, m) - endif - endfor - return res - endif - endfun - set completefunc=CompleteMonths +An example that completes the names of the months: >lua + vim.o.completefunc = function(findstart, base) + if findstart == 1 then -- Locate the start of the word. + local line = vim.fn.getline('.') + local start = vim.fn.col('.') - 1 + while start > 0 and line:sub(start, start):match('%a') do + start = start - 1 + end + return start + else -- Find months matching with "base". + local res = {} + local months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec' + for m in months:gmatch('%a+') do + if vim.startswith(m, base) then + table.insert(res, m) + end + end + return res + end + end < -The same, but now pretending searching for matches is slow: > - fun! CompleteMonths(findstart, base) - if a:findstart - " locate the start of the word - let line = getline('.') - let start = col('.') - 1 - while start > 0 && line[start - 1] =~ '\a' - let start -= 1 - endwhile - return start - else - " find months matching with "a:base" - for m in split("Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec") - if m =~ '^' .. a:base - call complete_add(m) - endif - sleep 300m " simulate searching for next match - if complete_check() - break - endif - endfor - return [] - endif - endfun - set completefunc=CompleteMonths +The same, but now pretending searching for matches is slow: >lua + vim.o.completefunc = function(findstart, base) + if findstart == 1 then -- Locate the start of the word. + local line = vim.fn.getline('.') + local start = vim.fn.col('.') - 1 + while start > 0 and line:sub(start, start):match('%a') do + start = start - 1 + end + return start + else -- Find months matching with "base". + local months = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec' + for m in months:gmatch('%a+') do + if vim.startswith(m, base) then + vim.fn.complete_add(m) + end + vim.uv.sleep(300) -- Simulate searching for next match. + if vim.fn.complete_check() ~= 0 then + break + end + end + return {} + end + end < INSERT COMPLETION POPUP MENU *ins-completion-menu* diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 78bdca7a15..681aced893 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -1210,7 +1210,7 @@ foldexpr({lnum}) *vim.lsp.foldexpr()* To use, set 'foldmethod' to "expr" and set the value of 'foldexpr': >lua vim.o.foldmethod = 'expr' - vim.o.foldexpr = 'v:lua.vim.lsp.foldexpr()' + vim.o.foldexpr = vim.lsp.foldexpr < Or use it only when supported by checking for the @@ -1218,14 +1218,14 @@ foldexpr({lnum}) *vim.lsp.foldexpr()* Example: >lua vim.o.foldmethod = 'expr' -- Default to treesitter folding - vim.o.foldexpr = 'v:lua.vim.treesitter.foldexpr()' + vim.o.foldexpr = vim.treesitter.foldexpr -- Prefer LSP folding if client supports it vim.api.nvim_create_autocmd('LspAttach', { callback = function(ev) local client = vim.lsp.get_client_by_id(ev.data.client_id) if client:supports_method('textDocument/foldingRange') then local win = vim.api.nvim_get_current_win() - vim.wo[win][0].foldexpr = 'v:lua.vim.lsp.foldexpr()' + vim.wo[win][0].foldexpr = vim.lsp.foldexpr end end, }) @@ -1248,9 +1248,12 @@ formatexpr({opts}) *vim.lsp.formatexpr()* function. Currently only supports a single client. This can be set via - `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` or (more typically) in - `on_attach` via - `vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`. + `vim.bo[bufnr].formatexpr = vim.lsp.formatexpr`, or with a wrapper to pass + options: >lua + vim.bo[bufnr].formatexpr = function() + return vim.lsp.formatexpr({ timeout_ms = 250 }) + end +< Parameters: ~ • {opts} (`table?`) A table with the following fields: diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index ff963ecad1..058a1dc4f2 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -1315,7 +1315,7 @@ vim.lua_omnifunc({find_start}) *vim.lua_omnifunc()* Omnifunc for completing Lua values from the runtime Lua interpreter, similar to the builtin completion for the `:lua` command. - Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a Lua buffer. + Activate using `vim.bo.omnifunc = vim.lua_omnifunc` in a Lua buffer. Parameters: ~ • {find_start} (`1|0`) @@ -2644,15 +2644,15 @@ vim.fs.dir({path}, {opts}) *vim.fs.dir()* Parameters: ~ • {path} (`string`) Directory to iterate over, normalized via |vim.fs.normalize()| unless `opts.normalize=false`. - • {opts} (`table?`) Optional keyword arguments: + • {opts} (`table?`) A table with the following fields: • {depth}? (`integer`, default: `1`) How deep to traverse. • {err}? (`boolean`, default: `false`) Report errors via the iterator's third value ("err"), instead of silently skipping. • {follow}? (`boolean`, default: `false`) Follow symbolic links. - • {normalize}? (`boolean`, default: `true`) Expand "~" and "$" - in {path} before scanning the directory. + • {plain}? (`boolean`, default: `false`) Do not expand special + forms like "~" and "$" in {path}. • {skip}? (`fun(dir_name: string): boolean`) Predicate to control traversal. Return false to stop searching the current directory. Only useful when depth > 1 Return an diff --git a/runtime/doc/motion.txt b/runtime/doc/motion.txt index 1b4daa36e2..f341eaf945 100644 --- a/runtime/doc/motion.txt +++ b/runtime/doc/motion.txt @@ -330,6 +330,9 @@ g [count] display lines downward. |exclusive| motion. *-* `-` [count] lines upward, on the first non-blank character |linewise|. + *-_default* + By default "-" is mapped to open the parent directory + of the current buffer. |dir-mappings| |default-mappings| `+` or *+* CTRL-M or *CTRL-M* ** diff --git a/runtime/doc/news.txt b/runtime/doc/news.txt index 53d9d68da7..0fd7f18e27 100644 --- a/runtime/doc/news.txt +++ b/runtime/doc/news.txt @@ -320,7 +320,7 @@ LUA • |vim.fs.abspath()| gained `cwd` and `plain` parameters. • |vim.fs.dir()| with `opts.err=true`, reports errors. An inaccessible root dir yields a single (name, nil, err) item. -• |vim.fs.dir()| gained a `normalize` parameter. +• |vim.fs.dir()| gained a `plain` parameter. • |vim.fs.find()| returns a list of errors as its second return value. • |vim.fs.mkdir()| creates directories, including parent directories with `opts.parents=true`. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index ee3913ecba..34a03b6fdb 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1386,14 +1386,13 @@ A jump table for the options with a short description can be found at |Q_op|. Conversion between "latin1", "unicode", "ucs-2", "ucs-4" and "utf-8" is done internally by Vim, 'charconvert' is not used for this. Also used for Unicode conversion. - Example: >vim - set charconvert=CharConvert() - fun CharConvert() - system("recode " - \ .. v:charconvert_from .. ".." .. v:charconvert_to - \ .. " <" .. v:fname_in .. " >" .. v:fname_out) - return v:shell_error - endfun + Example: >lua + vim.o.charconvert = function() + vim.fn.system(('recode %s..%s <%s >%s'):format( + vim.v.charconvert_from, vim.v.charconvert_to, + vim.v.fname_in, vim.v.fname_out)) + return vim.v.shell_error + end < The related Vim variables are: v:charconvert_from name of the current encoding v:charconvert_to name of the desired encoding @@ -2988,20 +2987,20 @@ A jump table for the options with a short description can be found at |Q_op|. Examples: - >vim - " Use glob() - func FindFuncGlob(cmdarg, cmdcomplete) - let pat = a:cmdcomplete ? $'{a:cmdarg}*' : a:cmdarg - return glob(pat, v:false, v:true) - endfunc - set findfunc=FindFuncGlob + >lua + -- Use vim.fn.glob() + vim.o.findfunc = function(cmdarg, cmdcomplete) + local pat = cmdcomplete and (cmdarg .. '*') or cmdarg + return vim.fn.glob(pat, false, true) + end - " Use the 'git ls-files' output - func FindGitFiles(cmdarg, cmdcomplete) - let fnames = systemlist('git ls-files') - return fnames->filter('v:val =~? a:cmdarg') - endfunc - set findfunc=FindGitFiles + -- Use the "git ls-files" output + vim.o.findfunc = function(cmdarg, cmdcomplete) + local fnames = vim.fn.systemlist('git ls-files') + return vim.tbl_filter(function(v) + return v:lower():find(cmdarg:lower(), 1, true) ~= nil + end, fnames) + end < *'fixendofline'* *'fixeol'* *'nofixendofline'* *'nofixeol'* diff --git a/runtime/doc/tagsrch.txt b/runtime/doc/tagsrch.txt index f7c1007c9f..fd9b274d71 100644 --- a/runtime/doc/tagsrch.txt +++ b/runtime/doc/tagsrch.txt @@ -967,20 +967,14 @@ It is not allowed to close a window or change window from inside 'tagfunc'. The following is a hypothetical example of a function used for 'tagfunc'. It uses the output of |taglist()| to generate the result: a list of tags in the inverse order of file names. ->vim - function CompareFilenames(item1, item2) - let f1 = a:item1['filename'] - let f2 = a:item2['filename'] - return f1 >=# f2 ? -1 : f1 <=# f2 ? 1 : 0 - endfunction - - function TagFunc(pattern, flags, info) - let result = taglist(a:pattern) - call sort(result, "CompareFilenames") - +>lua + vim.bo.tagfunc = function(pattern, flags, info) + local result = vim.fn.taglist(pattern) + table.sort(result, function(item1, item2) + return item1.filename > item2.filename + end) return result - endfunc - set tagfunc=TagFunc + end < Note: When executing |taglist()| the 'tagfunc' function won't be called recursively. diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index 07574cf310..03bef85178 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -958,7 +958,7 @@ Lua module: vim.treesitter *lua-treesitter-core* foldexpr({lnum}) *vim.treesitter.foldexpr()* Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr': >lua - vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' + vim.wo.foldexpr = vim.treesitter.foldexpr < Attributes: ~ diff --git a/runtime/lua/nvim/dir/fs.lua b/runtime/lua/nvim/dir/fs.lua index d599b70ba5..0f75233832 100644 --- a/runtime/lua/nvim/dir/fs.lua +++ b/runtime/lua/nvim/dir/fs.lua @@ -60,7 +60,7 @@ end ---@param cb fun(err?: string, entries?: nvim.dir.Entry[]) function M.list(_, path, cb) local entries = {} ---@type nvim.dir.Entry[] - for name, type, err in fs.dir(path, { err = true, normalize = false }) do + for name, type, err in fs.dir(path, { err = true, plain = true }) do if err then cb(err) return diff --git a/runtime/lua/vim/_core/editor.lua b/runtime/lua/vim/_core/editor.lua index dcafd385eb..3d876d2187 100644 --- a/runtime/lua/vim/_core/editor.lua +++ b/runtime/lua/vim/_core/editor.lua @@ -1217,7 +1217,7 @@ do --- Omnifunc for completing Lua values from the runtime Lua interpreter, --- similar to the builtin completion for the `:lua` command. --- - --- Activate using `set omnifunc=v:lua.vim.lua_omnifunc` in a Lua buffer. + --- Activate using `vim.bo.omnifunc = vim.lua_omnifunc` in a Lua buffer. --- @param find_start 1|0 function vim.lua_omnifunc(find_start, _) if find_start == 1 then diff --git a/runtime/lua/vim/_meta/options.gen.lua b/runtime/lua/vim/_meta/options.gen.lua index 6489c43ad7..898d57edc2 100644 --- a/runtime/lua/vim/_meta/options.gen.lua +++ b/runtime/lua/vim/_meta/options.gen.lua @@ -811,14 +811,13 @@ vim.bo.channel = vim.o.channel --- Also used for Unicode conversion. --- Example: --- ---- ```vim ---- set charconvert=CharConvert() ---- fun CharConvert() ---- system("recode " ---- \ .. v:charconvert_from .. ".." .. v:charconvert_to ---- \ .. " <" .. v:fname_in .. " >" .. v:fname_out) ---- return v:shell_error ---- endfun +--- ```lua +--- vim.o.charconvert = function() +--- vim.fn.system(('recode %s..%s <%s >%s'):format( +--- vim.v.charconvert_from, vim.v.charconvert_to, +--- vim.v.fname_in, vim.v.fname_out)) +--- return vim.v.shell_error +--- end --- ``` --- The related Vim variables are: --- v:charconvert_from name of the current encoding @@ -2655,20 +2654,20 @@ vim.go.fcs = vim.go.fillchars --- --- Examples: --- ---- ```vim ---- " Use glob() ---- func FindFuncGlob(cmdarg, cmdcomplete) ---- let pat = a:cmdcomplete ? $'{a:cmdarg}*' : a:cmdarg ---- return glob(pat, v:false, v:true) ---- endfunc ---- set findfunc=FindFuncGlob +--- ```lua +--- -- Use vim.fn.glob() +--- vim.o.findfunc = function(cmdarg, cmdcomplete) +--- local pat = cmdcomplete and (cmdarg .. '*') or cmdarg +--- return vim.fn.glob(pat, false, true) +--- end --- ---- " Use the 'git ls-files' output ---- func FindGitFiles(cmdarg, cmdcomplete) ---- let fnames = systemlist('git ls-files') ---- return fnames->filter('v:val =~? a:cmdarg') ---- endfunc ---- set findfunc=FindGitFiles +--- -- Use the "git ls-files" output +--- vim.o.findfunc = function(cmdarg, cmdcomplete) +--- local fnames = vim.fn.systemlist('git ls-files') +--- return vim.tbl_filter(function(v) +--- return v:lower():find(cmdarg:lower(), 1, true) ~= nil +--- end, fnames) +--- end --- ``` --- --- diff --git a/runtime/lua/vim/fs.lua b/runtime/lua/vim/fs.lua index 0be6333d76..4788776660 100644 --- a/runtime/lua/vim/fs.lua +++ b/runtime/lua/vim/fs.lua @@ -191,9 +191,9 @@ end --- (default: `false`) --- @field follow? boolean --- ---- Expand "~" and "$" in {path} before scanning the directory. ---- (default: `true`) ---- @field normalize? boolean +--- Do not expand special forms like "~" and "$" in {path}. +--- (default: `false`) +--- @field plain? boolean --- Gets an iterator over items found in `path` (normalized via |vim.fs.normalize()|). --- @@ -210,7 +210,7 @@ end ---@since 10 ---@param path (string) Directory to iterate over, normalized via |vim.fs.normalize()| unless --- `opts.normalize=false`. ----@param opts? vim.fs.dir.Opts Optional keyword arguments: +---@param opts? vim.fs.dir.Opts ---@return fun(): string?, string?, string? # Iterator over items in {path}, yielding (name, type, err): --- - name: Basename of the item relative to {path}. --- - type: One of: "file", "directory", "link", "fifo", "socket", "char", "block", "unknown". @@ -224,9 +224,9 @@ function M.dir(path, opts) vim.validate('err', opts.err, 'boolean', true) vim.validate('follow', opts.follow, 'boolean', true) vim.validate('skip', opts.skip, 'function', true) - vim.validate('normalize', opts.normalize, 'boolean', true) + vim.validate('plain', opts.plain, 'boolean', true) - if opts.normalize ~= false then + if opts.plain ~= true then path = M.normalize(path) end diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index fa23039833..cd4a983c08 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1374,8 +1374,13 @@ end --- Provides an interface between the built-in client and a `formatexpr` function. --- --- Currently only supports a single client. This can be set via ---- `setlocal formatexpr=v:lua.vim.lsp.formatexpr()` or (more typically) in `on_attach` ---- via `vim.bo[bufnr].formatexpr = 'v:lua.vim.lsp.formatexpr(#{timeout_ms:250})'`. +--- `vim.bo[bufnr].formatexpr = vim.lsp.formatexpr`, or with a wrapper to pass options: +--- +--- ```lua +--- vim.bo[bufnr].formatexpr = function() +--- return vim.lsp.formatexpr({ timeout_ms = 250 }) +--- end +--- ``` --- ---@param opts? vim.lsp.formatexpr.Opts function lsp.formatexpr(opts) @@ -1445,7 +1450,7 @@ end --- --- ```lua --- vim.o.foldmethod = 'expr' ---- vim.o.foldexpr = 'v:lua.vim.lsp.foldexpr()' +--- vim.o.foldexpr = vim.lsp.foldexpr --- ``` --- --- Or use it only when supported by checking for the "textDocument/foldingRange" @@ -1454,14 +1459,14 @@ end --- ```lua --- vim.o.foldmethod = 'expr' --- -- Default to treesitter folding ---- vim.o.foldexpr = 'v:lua.vim.treesitter.foldexpr()' +--- vim.o.foldexpr = vim.treesitter.foldexpr --- -- Prefer LSP folding if client supports it --- vim.api.nvim_create_autocmd('LspAttach', { --- callback = function(ev) --- local client = vim.lsp.get_client_by_id(ev.data.client_id) --- if client:supports_method('textDocument/foldingRange') then --- local win = vim.api.nvim_get_current_win() ---- vim.wo[win][0].foldexpr = 'v:lua.vim.lsp.foldexpr()' +--- vim.wo[win][0].foldexpr = vim.lsp.foldexpr --- end --- end, --- }) diff --git a/runtime/lua/vim/treesitter.lua b/runtime/lua/vim/treesitter.lua index fb264ba8f9..ff9d903589 100644 --- a/runtime/lua/vim/treesitter.lua +++ b/runtime/lua/vim/treesitter.lua @@ -502,7 +502,7 @@ end --- Returns the fold level for {lnum} in the current buffer. Can be set directly to 'foldexpr': --- --- ```lua ---- vim.wo.foldexpr = 'v:lua.vim.treesitter.foldexpr()' +--- vim.wo.foldexpr = vim.treesitter.foldexpr --- ``` --- ---@since 11 diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 8dfc6bb46d..2b73f9c046 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1195,14 +1195,13 @@ local options = { Conversion between "latin1", "unicode", "ucs-2", "ucs-4" and "utf-8" is done internally by Vim, 'charconvert' is not used for this. Also used for Unicode conversion. - Example: >vim - set charconvert=CharConvert() - fun CharConvert() - system("recode " - \ .. v:charconvert_from .. ".." .. v:charconvert_to - \ .. " <" .. v:fname_in .. " >" .. v:fname_out) - return v:shell_error - endfun + Example: >lua + vim.o.charconvert = function() + vim.fn.system(('recode %s..%s <%s >%s'):format( + vim.v.charconvert_from, vim.v.charconvert_to, + vim.v.fname_in, vim.v.fname_out)) + return vim.v.shell_error + end < The related Vim variables are: v:charconvert_from name of the current encoding v:charconvert_to name of the desired encoding @@ -3449,20 +3448,20 @@ local options = { Examples: - >vim - " Use glob() - func FindFuncGlob(cmdarg, cmdcomplete) - let pat = a:cmdcomplete ? $'{a:cmdarg}*' : a:cmdarg - return glob(pat, v:false, v:true) - endfunc - set findfunc=FindFuncGlob + >lua + -- Use vim.fn.glob() + vim.o.findfunc = function(cmdarg, cmdcomplete) + local pat = cmdcomplete and (cmdarg .. '*') or cmdarg + return vim.fn.glob(pat, false, true) + end - " Use the 'git ls-files' output - func FindGitFiles(cmdarg, cmdcomplete) - let fnames = systemlist('git ls-files') - return fnames->filter('v:val =~? a:cmdarg') - endfunc - set findfunc=FindGitFiles + -- Use the "git ls-files" output + vim.o.findfunc = function(cmdarg, cmdcomplete) + local fnames = vim.fn.systemlist('git ls-files') + return vim.tbl_filter(function(v) + return v:lower():find(cmdarg:lower(), 1, true) ~= nil + end, fnames) + end < ]=], full_name = 'findfunc', diff --git a/test/functional/lua/fs_spec.lua b/test/functional/lua/fs_spec.lua index 88cb63a692..c428e32bb0 100644 --- a/test/functional/lua/fs_spec.lua +++ b/test/functional/lua/fs_spec.lua @@ -345,7 +345,7 @@ describe('vim.fs', function() eq(nil, result['a/noaccess']) end) - it('opts.normalize=false uses {path} literally', function() + it('plain=true', function() mkdir('testdir') mkdir('testdir/$XTEST_FS_DIR') mkdir('testdir/expanded') @@ -360,9 +360,9 @@ describe('vim.fs', function() exec_lua(function() vim.uv.os_setenv('XTEST_FS_DIR', 'expanded') local out = {} ---@type table[] - for i, normalize in ipairs({ true, false }) do + for i, plain in ipairs({ false, true }) do out[i] = {} - for name, etype in vim.fs.dir('testdir/$XTEST_FS_DIR', { normalize = normalize }) do + for name, etype in vim.fs.dir('testdir/$XTEST_FS_DIR', { plain = plain }) do out[i][name] = etype end end