diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index a6aa2fc5853..31fc1ab32ae 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -2890,7 +2890,7 @@ nvim_cmd({cmd}, {opts}) *nvim_cmd()* Executes an Ex command `cmd`, specified as a Dict with the same structure as returned by |nvim_parse_cmd()|. - Use `magic={…=false}` to disable special chars: >lua + Use `magic={…=false}` to disable special chars (see also |open-file|): >lua vim.api.nvim_cmd({ cmd = 'edit', args = { '%foo"|bar#baz"' }, diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index 8916b30a90a..824fe4d87e5 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -330,13 +330,11 @@ current file name. Besides the things mentioned here, more special items for where a filename is expected are mentioned at |cmdline-special|. -Note for systems other than Unix: When using a command that accepts a single -file name (like ":edit file") spaces in the file name are allowed, but -trailing spaces are ignored. This is useful on systems that regularly embed -spaces in file names (like MS-Windows). Example: The command ":e Long File -Name " will edit the file "Long File Name". When using a command that accepts -more than one file name (like ":next file1 file2") embedded spaces must be -escaped with a backslash. +When using a command that accepts a single file name (like ":edit file") +spaces in the file name are allowed, but trailing spaces are ignored. +Example: The command ":e Long File Name " will edit the file "Long File +Name". When using a command that accepts more than one file name (like ":next +file1 file2") embedded spaces must be escaped with a backslash. *wildcard* *wildcards* Wildcards in {file} are expanded, but as with file completion, 'wildignore' @@ -361,18 +359,18 @@ Note there are some commands where this works slightly differently, see |file-searching|. Example: > :n **/*.txt -Finds files: - aaa.txt ~ - subdir/bbb.txt ~ - a/b/c/d/ccc.txt ~ +Finds files: > + aaa.txt + subdir/bbb.txt + a/b/c/d/ccc.txt When non-wildcard characters are used right before or after "**" these are only matched in the top directory. They are not used for directories further down in the tree. For example: > :n /usr/inc**/types.h -Finds files: - /usr/include/types.h ~ - /usr/include/sys/types.h ~ - /usr/inc/old/types.h ~ +Finds files: > + /usr/include/types.h + /usr/include/sys/types.h + /usr/inc/old/types.h Note that the path with "/sys" is included because it does not need to match "/inc". Thus it's like matching "/usr/inc*/*/*...", not "/usr/inc*/inc*/inc*". @@ -558,7 +556,7 @@ Before editing binary, executable or Vim script files you should set the option. This will avoid the use of 'fileformat'. Without this you risk that single characters are unexpectedly replaced with . -END OF LINE AND END OF FILE *eol-and-eof* +END-OF-LINE AND END-OF-FILE *eol-and-eof* Vim has several options to control the file format: 'fileformat' the style: Unix, DOS, Mac @@ -596,6 +594,28 @@ If you want to preserve the fileformat exactly as-is, including any final and final CTRL-Z: > setl nofixeol +OPENING FILES PROGRAMMATICALLY *buffer-open* *open-file* + +When a plugin already has a literal filepath (e.g. from a picker, LSP result, +or filesystem scan) and just wants to open it, |:edit| is the wrong tool: its +argument is subject to |cmdline-special| expansion, |wildcard| expansion, etc. +|fnameescape()| escapes only some of these, and may depend on 'isfname'. + +Instead, to open a filepath literally, use `bufadd(vim.fs.normalize(…))`: >lua + local buf = vim.fn.bufadd(vim.fs.normalize(path)) + vim.fn.bufload(buf) -- Trigger BufReadPre/BufReadPost/FileType. + vim.bo[buf].buflisted = true -- Show in ":ls". + vim.api.nvim_win_set_buf(0, buf) -- Show in current window. + +Alternatively, |nvim_cmd()| and |vim.cmd()| accept a structured form whose +`args` are tokenized verbatim. But the argument still goes through |:edit|'s +filename-expansion phase, so some parts of `path` are still expanded: >lua + vim.cmd{ cmd = 'edit', + args = { path }, + magic = { file = false, bar = false }, + } +< + ============================================================================== 3. The argument list *argument-list* *arglist* @@ -1347,15 +1367,16 @@ use has("browsefilter"): > ============================================================================== 7. The current directory *current-directory* -You can use |:cd|, |:tcd| and |:lcd| to change to another directory, so you -will not have to type that directory name in front of the file names. It also -makes a difference for executing external commands, e.g. ":!ls" or ":te ls". +There are three current-directory "scopes": global, tab and window. You can +use |:cd|, |:tcd| and |:lcd| to change to another directory. This affects +anything that operates on relative paths, e.g. ":edit ./foo.txt" or shell +commands like ":!ls" or ":te ls". -There are three current-directory "scopes": global, tab and window. The -window-local working directory takes precedence over the tab-local -working directory, which in turn takes precedence over the global -working directory. If a local working directory (tab or window) does not -exist, the next-higher scope in the hierarchy applies. +Use |getcwd()| to get the effective directory from the current scope. The +window-local working directory takes precedence over the tab-local working +directory, which in turn takes precedence over the global working directory. +If a local working directory (tab or window) does not exist, the next-higher +scope in the hierarchy applies. *:cd* *E747* *E472* :cd[!] On non-Unix systems when 'cdhome' is off: Print the diff --git a/runtime/doc/lua-guide.txt b/runtime/doc/lua-guide.txt index 678b499d241..5179ace04ed 100644 --- a/runtime/doc/lua-guide.txt +++ b/runtime/doc/lua-guide.txt @@ -19,11 +19,11 @@ This is not a comprehensive encyclopedia of all available features. Think of it as a survival kit: the bare minimum needed to comfortably get started on using Lua in Nvim. -See |lua-plugin| for guidance on developing Lua plugins. -See |luaref| and |lua-concepts| for details on the Lua programming language. +- See |lua-plugin| for guidance on developing Lua plugins. +- See |luaref| and |lua-concepts| for details on the Lua programming language. ------------------------------------------------------------------------------ -Some words on the API *lua-guide-api* +About the API *lua-guide-api* The purpose of this guide is to introduce the different ways of interacting with Nvim through Lua (the "API"). This API consists of three different diff --git a/runtime/doc/lua-plugin.txt b/runtime/doc/lua-plugin.txt index fd511f69d38..2a4a667bb85 100644 --- a/runtime/doc/lua-plugin.txt +++ b/runtime/doc/lua-plugin.txt @@ -12,8 +12,8 @@ Introduction *lua-plugin* This document provides guidance for developing Nvim Lua plugins. -See |lua-guide| for guidance on using Lua to configure and operate Nvim. -See |luaref| and |lua-concepts| for details on the Lua programming language. +- See |lua-guide| for guidance on using Lua to configure and operate Nvim. +- See |luaref| and |lua-concepts| for details on the Lua programming language. ============================================================================== Creating your first plugin *lua-plugin-new* @@ -243,6 +243,11 @@ A plugin tailored to Rust development might have initialization in print('Hello') end, { buf = bufnr }) < +============================================================================== +Opening files *lua-plugin-open-file* + +To robustly open a file, see |open-file|. + ============================================================================== Configuration *lua-plugin-config* diff --git a/runtime/doc/vimfn.txt b/runtime/doc/vimfn.txt index 737c18f6ae3..19223349435 100644 --- a/runtime/doc/vimfn.txt +++ b/runtime/doc/vimfn.txt @@ -593,18 +593,18 @@ browsedir({title}, {initdir}) *browsedir()* (`0|1`) bufadd({name}) *bufadd()* - Add a buffer to the buffer list with name {name} (must be a - String). - If a buffer for file {name} already exists, return that buffer - number. Otherwise return the buffer number of the newly - created buffer. When {name} is an empty string then a new - buffer is always created. - The buffer will not have 'buflisted' set and not be loaded - yet. To add some text to the buffer use this: >vim - let bufnr = bufadd('someName') - call bufload(bufnr) - call setbufline(bufnr, 1, ['some', 'text']) -< Returns 0 on error. + Adds buffer {name} to the buffer list literally: no special + chars or expansion are applied (including "~"). Returns the + new (or existing matching) buffer number, or 0 on error. + + The buffer is not loaded and 'buflisted' is not set. When + {name} is an empty string, a new buffer is always created. + + Example (Lua): >lua + local b = vim.fn.bufadd(vim.fs.normalize('someName')) + vim.bo[b].buflisted = true + vim.fn.bufload(b) +< Parameters: ~ • {name} (`string`) @@ -2722,14 +2722,15 @@ fmod({expr1}, {expr2}) *fmod()* Return: ~ (`any`) -fnameescape({string}) *fnameescape()* - Lua: Prefer |nvim_cmd()| or |vim.cmd()| with structured - arguments to avoid Ex filename escaping. +fnameescape({filepath}) *fnameescape()* + Escapes {filepath} for use as a command argument. - Escape {string} for use as file name command argument. All - characters that have a special meaning, such as `'%'` and `'|'` - are escaped with a backslash. For most systems the characters - escaped are: > + (Note: To open a literal filepath programmatically use + `bufadd(vim.fs.normalize(…))`, see |open-file|.) + + All characters that have a special meaning, such as `'%'` and + `'|'` are escaped with a backslash. For most systems the + characters escaped are: > \t\n *?[{`$\\%#'\"|!< < For systems where a backslash appears in a filename, it depends on the value of 'isfname'. A leading '+' and '>' is @@ -2744,7 +2745,7 @@ fnameescape({string}) *fnameescape()* < Parameters: ~ - • {string} (`string`) + • {filepath} (`string`) Return: ~ (`string`) diff --git a/runtime/lua/vim/_meta/api.gen.lua b/runtime/lua/vim/_meta/api.gen.lua index 8f9ebbafe26..e3a4fda5c69 100644 --- a/runtime/lua/vim/_meta/api.gen.lua +++ b/runtime/lua/vim/_meta/api.gen.lua @@ -849,7 +849,7 @@ function vim.api.nvim_clear_autocmds(opts) end --- Executes an Ex command `cmd`, specified as a Dict with the same structure as returned by --- `nvim_parse_cmd()`. --- ---- Use `magic={…=false}` to disable special chars: +--- Use `magic={…=false}` to disable special chars (see also `open-file`): --- ```lua --- vim.api.nvim_cmd({ --- cmd = 'edit', diff --git a/runtime/lua/vim/_meta/vimfn.gen.lua b/runtime/lua/vim/_meta/vimfn.gen.lua index e953d4829f8..9d08c79764b 100644 --- a/runtime/lua/vim/_meta/vimfn.gen.lua +++ b/runtime/lua/vim/_meta/vimfn.gen.lua @@ -496,18 +496,18 @@ function vim.fn.browse(save, title, initdir, default) end --- @return 0|1 function vim.fn.browsedir(title, initdir) end ---- Add a buffer to the buffer list with name {name} (must be a ---- String). ---- If a buffer for file {name} already exists, return that buffer ---- number. Otherwise return the buffer number of the newly ---- created buffer. When {name} is an empty string then a new ---- buffer is always created. ---- The buffer will not have 'buflisted' set and not be loaded ---- yet. To add some text to the buffer use this: >vim ---- let bufnr = bufadd('someName') ---- call bufload(bufnr) ---- call setbufline(bufnr, 1, ['some', 'text']) ---- lua +--- local b = vim.fn.bufadd(vim.fs.normalize('someName')) +--- vim.bo[b].buflisted = true +--- vim.fn.bufload(b) +--- < --- --- @param name string --- @return integer @@ -2418,12 +2418,14 @@ function vim.fn.floor(expr) end --- @return any function vim.fn.fmod(expr1, expr2) end ---- Lua: Prefer |nvim_cmd()| or |vim.cmd()| with structured arguments to avoid Ex filename escaping. +--- Escapes {filepath} for use as a command argument. --- ---- Escape {string} for use as file name command argument. All ---- characters that have a special meaning, such as `'%'` and `'|'` ---- are escaped with a backslash. For most systems the characters ---- escaped are: > +--- (Note: To open a literal filepath programmatically use +--- `bufadd(vim.fs.normalize(…))`, see |open-file|.) +--- +--- All characters that have a special meaning, such as `'%'` and +--- `'|'` are escaped with a backslash. For most systems the +--- characters escaped are: > --- \t\n *?[{`$\\%#'\"|!< --- ' is @@ -2437,9 +2439,9 @@ function vim.fn.fmod(expr1, expr2) end --- edit \+some\ str\%nge\|name --- < --- ---- @param string string +--- @param filepath string --- @return string -function vim.fn.fnameescape(string) end +function vim.fn.fnameescape(filepath) end --- Lua: Prefer |vim.fs.dirname()|, |vim.fs.basename()|, |vim.fs.abspath()|, and |vim.fs.normalize()| for common path modifiers; modifier coverage differs. --- diff --git a/src/nvim/api/command.c b/src/nvim/api/command.c index 974a6abb7dc..cfe87cd6415 100644 --- a/src/nvim/api/command.c +++ b/src/nvim/api/command.c @@ -324,7 +324,7 @@ end: /// Executes an Ex command `cmd`, specified as a Dict with the same structure as returned by /// |nvim_parse_cmd()|. /// -/// Use `magic={…=false}` to disable special chars: +/// Use `magic={…=false}` to disable special chars (see also |open-file|): /// ```lua /// vim.api.nvim_cmd({ /// cmd = 'edit', diff --git a/src/nvim/eval.lua b/src/nvim/eval.lua index 187b109841f..f6b49db15af 100644 --- a/src/nvim/eval.lua +++ b/src/nvim/eval.lua @@ -671,18 +671,18 @@ M.funcs = { args = 1, base = 1, desc = [=[ - Add a buffer to the buffer list with name {name} (must be a - String). - If a buffer for file {name} already exists, return that buffer - number. Otherwise return the buffer number of the newly - created buffer. When {name} is an empty string then a new - buffer is always created. - The buffer will not have 'buflisted' set and not be loaded - yet. To add some text to the buffer use this: >vim - let bufnr = bufadd('someName') - call bufload(bufnr) - call setbufline(bufnr, 1, ['some', 'text']) - lua + local b = vim.fn.bufadd(vim.fs.normalize('someName')) + vim.bo[b].buflisted = true + vim.fn.bufload(b) + < ]=], name = 'bufadd', params = { { 'name', 'string' } }, @@ -3028,10 +3028,14 @@ M.funcs = { args = 1, base = 1, desc = [=[ - Escape {string} for use as file name command argument. All - characters that have a special meaning, such as `'%'` and `'|'` - are escaped with a backslash. For most systems the characters - escaped are: > + Escapes {filepath} for use as a command argument. + + (Note: To open a literal filepath programmatically use + `bufadd(vim.fs.normalize(…))`, see |open-file|.) + + All characters that have a special meaning, such as `'%'` and + `'|'` are escaped with a backslash. For most systems the + characters escaped are: > \t\n *?[{`$\\%#'\"|!< ' is @@ -3047,12 +3051,9 @@ M.funcs = { ]=], fast = true, name = 'fnameescape', - params = { { 'string', 'string' } }, + params = { { 'filepath', 'string' } }, returns = 'string', - signature = 'fnameescape({string})', - see_lua = { - '|nvim_cmd()| or |vim.cmd()| with structured arguments to avoid Ex filename escaping', - }, + signature = 'fnameescape({filepath})', }, fnamemodify = { args = 2,