diff options
-rw-r--r-- | .github/workflows/notes.md | 5 | ||||
-rw-r--r-- | CMakeLists.txt | 6 | ||||
-rw-r--r-- | runtime/doc/lua.txt | 43 | ||||
-rw-r--r-- | runtime/doc/various.txt | 6 | ||||
-rw-r--r-- | runtime/filetype.lua | 2 | ||||
-rw-r--r-- | runtime/lua/vim/filetype.lua | 88 | ||||
-rw-r--r-- | runtime/pack/dist/opt/termdebug/plugin/termdebug.vim | 3 | ||||
-rw-r--r-- | src/nvim/eval.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_cmdline.vim | 6 | ||||
-rw-r--r-- | src/nvim/testdir/test_quickfix.vim | 16 | ||||
-rw-r--r-- | test/functional/lua/filetype_spec.lua | 15 |
11 files changed, 141 insertions, 51 deletions
diff --git a/.github/workflows/notes.md b/.github/workflows/notes.md index 86f9e8e618..d752f10609 100644 --- a/.github/workflows/notes.md +++ b/.github/workflows/notes.md @@ -21,8 +21,9 @@ ${NVIM_VERSION} ### macOS 1. Download **nvim-macos.tar.gz** -2. Extract: `tar xzvf nvim-macos.tar.gz` -3. Run `./nvim-macos/bin/nvim` +2. Run `xattr -c ./nvim-macos.tar.gz` (to avoid "unknown developer" warning) +3. Extract: `tar xzvf nvim-macos.tar.gz` +4. Run `./nvim-macos/bin/nvim` ### Linux (x64) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9502190708..097ef041ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -573,11 +573,7 @@ endif() message(STATUS "Using Lua interpreter: ${LUA_PRG}") -if(DEBUG) - option(COMPILE_LUA "Pre-compile Lua sources into bytecode (for sources that are included in the binary)" OFF) -else() - option(COMPILE_LUA "Pre-compile Lua sources into bytecode (for sources that are included in the binary)" ON) -endif() +option(COMPILE_LUA "Pre-compile Lua sources into bytecode (for sources that are included in the binary)" ON) if(COMPILE_LUA AND NOT WIN32) if(PREFER_LUA) diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index 9f8d4a8479..f40b32c469 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -2064,14 +2064,45 @@ add({filetypes}) *vim.filetype.add()* {filetypes} (table) A table containing new filetype maps (see example). -match({name}, {bufnr}) *vim.filetype.match()* - Find the filetype for the given filename and buffer. +match({arg}) *vim.filetype.match()* + Perform filetype detection. + + The filetype can be detected using one of three methods: + 1. Using an existing buffer + 2. Using only a file name + 3. Using only file contents + + Of these, option 1 provides the most accurate result as it + uses both the buffer's filename and (optionally) the buffer + contents. Options 2 and 3 can be used without an existing + buffer, but may not always provide a match in cases where the + filename (or contents) cannot unambiguously determine the + filetype. + + Each of the three options is specified using a key to the + single argument of this function. Example: +> + + -- Using a buffer number + vim.filetype.match({ buf = 42 }) + + -- Using a filename + vim.filetype.match({ filename = "main.lua" }) + + -- Using file contents + vim.filetype.match({ contents = {"#!/usr/bin/env bash"} }) +< Parameters: ~ - {name} (string) File name (can be an absolute or - relative path) - {bufnr} (number|nil) The buffer to set the filetype for. - Defaults to the current buffer. + {arg} (table) Table specifying which matching strategy to + use. It is an error to provide more than one + strategy. Accepted keys are: + • buf (number): Buffer number to use for matching + • filename (string): Filename to use for matching. + Note that the file need not actually exist in the + filesystem, only the name itself is used. + • contents (table): An array of lines representing + file contents to use for matching. Return: ~ (string|nil) If a match was found, the matched filetype. diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 562faeaa2c..9eb6470962 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -346,7 +346,11 @@ g8 Print the hex values of the bytes used in the Only string variables can be used. After the redirection starts, if the variable is removed or locked or the variable type is changed, then further - command output messages will cause errors. + command output messages will cause errors. When using + a local variable (l:var in a function or s:var in a + script) and another `:redir` causes the current one to + end, the scope might be different and the assignment + fails. To get the output of one command the |execute()| function can be used instead of redirection. diff --git a/runtime/filetype.lua b/runtime/filetype.lua index b002b8971b..35bb31edce 100644 --- a/runtime/filetype.lua +++ b/runtime/filetype.lua @@ -12,7 +12,7 @@ vim.api.nvim_create_augroup('filetypedetect', { clear = false }) vim.api.nvim_create_autocmd({ 'BufRead', 'BufNewFile' }, { group = 'filetypedetect', callback = function(args) - local ft, on_detect = vim.filetype.match(args.file, args.buf) + local ft, on_detect = vim.filetype.match({ buf = args.buf }) if ft then vim.api.nvim_buf_set_option(args.buf, 'filetype', ft) if on_detect then diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 6c4894208f..3e86159489 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -2047,7 +2047,7 @@ local pattern = { end end, { priority = -math.huge + 1 }), ['XF86Config.*'] = starsetf(function(path, bufnr) - return require('vim.filetype.detect').xfree86(bufnr) + return require('vim.filetype.detect').xfree86() end), ['%.zcompdump.*'] = starsetf('zsh'), -- .zlog* and zlog* @@ -2185,17 +2185,24 @@ end local function dispatch(ft, path, bufnr, ...) local on_detect if type(ft) == 'function' then - ft, on_detect = ft(path, bufnr, ...) + if bufnr then + ft, on_detect = ft(path, bufnr, ...) + else + -- If bufnr is nil (meaning we are matching only against the filename), set it to an invalid + -- value (-1) and catch any errors from the filetype detection function. If the function tries + -- to use the buffer then it will fail, but this enables functions which do not need a buffer + -- to still work. + local ok + ok, ft, on_detect = pcall(ft, path, -1, ...) + if not ok then + return + end + end end if type(ft) == 'string' then return ft, on_detect end - - -- Any non-falsey value (that is, anything other than 'nil' or 'false') will - -- end filetype matching. This is useful for e.g. the dist#ft functions that - -- return 0, but set the buffer's filetype themselves - return ft end ---@private @@ -2214,29 +2221,74 @@ local function match_pattern(name, path, tail, pat) return matches end ---- Find the filetype for the given filename and buffer. +--- Perform filetype detection. +--- +--- The filetype can be detected using one of three methods: +--- 1. Using an existing buffer +--- 2. Using only a file name +--- 3. Using only file contents +--- +--- Of these, option 1 provides the most accurate result as it uses both the buffer's filename and +--- (optionally) the buffer contents. Options 2 and 3 can be used without an existing buffer, but +--- may not always provide a match in cases where the filename (or contents) cannot unambiguously +--- determine the filetype. +--- +--- Each of the three options is specified using a key to the single argument of this function. +--- Example: +--- +--- <pre> +--- -- Using a buffer number +--- vim.filetype.match({ buf = 42 }) --- ----@param name string File name (can be an absolute or relative path) ----@param bufnr number|nil The buffer to set the filetype for. Defaults to the current buffer. +--- -- Using a filename +--- vim.filetype.match({ filename = "main.lua" }) +--- +--- -- Using file contents +--- vim.filetype.match({ contents = {"#!/usr/bin/env bash"} }) +--- </pre> +--- +---@param arg table Table specifying which matching strategy to use. It is an error to provide more +--- than one strategy. Accepted keys are: +--- * buf (number): Buffer number to use for matching +--- * filename (string): Filename to use for matching. Note that the file need not +--- actually exist in the filesystem, only the name itself is +--- used. +--- * contents (table): An array of lines representing file contents to use for +--- matching. ---@return string|nil If a match was found, the matched filetype. ---@return function|nil A function that modifies buffer state when called (for example, to set some --- filetype specific buffer variables). The function accepts a buffer number as --- its only argument. -function M.match(name, bufnr) +function M.match(arg) vim.validate({ - name = { name, 's' }, - bufnr = { bufnr, 'n', true }, + arg = { arg, 't' }, }) - -- When fired from the main filetypedetect autocommand the {bufnr} argument is omitted, so we use - -- the current buffer. The {bufnr} argument is provided to allow extensibility in case callers - -- wish to perform filetype detection on buffers other than the current one. - bufnr = bufnr or api.nvim_get_current_buf() + if not (arg.buf or arg.filename or arg.contents) then + error('One of "buf", "filename", or "contents" must be given') + end + + if (arg.buf and arg.filename) or (arg.buf and arg.contents) or (arg.filename and arg.contents) then + error('Only one of "buf", "filename", or "contents" must be given') + end + + local bufnr = arg.buf + local name = bufnr and api.nvim_buf_get_name(bufnr) or arg.filename + local contents = arg.contents - name = normalize_path(name) + if name then + name = normalize_path(name) + end local ft, on_detect + if not (bufnr or name) then + -- Sanity check: this should not happen + assert(contents, 'contents should be non-nil when bufnr and filename are nil') + -- TODO: "scripts.lua" content matching + return + end + -- First check for the simple case where the full path exists as a key local path = vim.fn.resolve(vim.fn.fnamemodify(name, ':p')) ft, on_detect = dispatch(filename[path], path, bufnr) diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index f76bdebe9b..c4e90eb373 100644 --- a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim +++ b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim @@ -2,7 +2,7 @@ " " Author: Bram Moolenaar " Copyright: Vim license applies, see ":help license" -" Last Change: 2022 Jun 22 +" Last Change: 2022 Jun 24 " " WORK IN PROGRESS - The basics works stable, more to come " Note: In general you need at least GDB 7.12 because this provides the @@ -539,6 +539,7 @@ func TermDebugSendCommand(cmd) endif sleep 10m endif + " TODO: should we prepend CTRL-U to clear the command? call chansend(s:gdb_job_id, a:cmd . "\r") if do_continue Continue diff --git a/src/nvim/eval.c b/src/nvim/eval.c index be2df9488e..7b6e954b3a 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -469,7 +469,9 @@ void eval_clear(void) hash_clear(&compat_hashtab); free_scriptnames(); +# ifdef HAVE_WORKING_LIBINTL free_locales(); +# endif // global variables vars_clear(&globvarht); diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim index 887c8e1593..8d1746be2f 100644 --- a/src/nvim/testdir/test_cmdline.vim +++ b/src/nvim/testdir/test_cmdline.vim @@ -305,7 +305,7 @@ func Test_getcompletion() call assert_equal([], l) let l = getcompletion('', 'dir') - call assert_true(index(l, expand('sautest/')) >= 0) + call assert_true(index(l, 'sautest/') >= 0) let l = getcompletion('NoMatch', 'dir') call assert_equal([], l) @@ -415,7 +415,7 @@ func Test_getcompletion() " Command line completion tests let l = getcompletion('cd ', 'cmdline') - call assert_true(index(l, expand('sautest/')) >= 0) + call assert_true(index(l, 'sautest/') >= 0) let l = getcompletion('cd NoMatch', 'cmdline') call assert_equal([], l) let l = getcompletion('let v:n', 'cmdline') @@ -539,7 +539,7 @@ func Test_expand_star_star() call mkdir('a/b', 'p') call writefile(['asdfasdf'], 'a/b/fileXname') call feedkeys(":find **/fileXname\<Tab>\<CR>", 'xt') - call assert_equal('find '.expand('a/b/fileXname'), getreg(':')) + call assert_equal('find a/b/fileXname', getreg(':')) bwipe! call delete('a', 'rf') endfunc diff --git a/src/nvim/testdir/test_quickfix.vim b/src/nvim/testdir/test_quickfix.vim index e43db4d692..5826666cbb 100644 --- a/src/nvim/testdir/test_quickfix.vim +++ b/src/nvim/testdir/test_quickfix.vim @@ -1060,17 +1060,17 @@ func s:dir_stack_tests(cchar) let qf = g:Xgetlist() - call assert_equal(expand('dir1/a/habits2.txt'), bufname(qf[1].bufnr)) + call assert_equal('dir1/a/habits2.txt', bufname(qf[1].bufnr)) call assert_equal(1, qf[1].lnum) - call assert_equal(expand('dir1/a/b/habits3.txt'), bufname(qf[3].bufnr)) + call assert_equal('dir1/a/b/habits3.txt', bufname(qf[3].bufnr)) call assert_equal(2, qf[3].lnum) - call assert_equal(expand('dir1/a/habits2.txt'), bufname(qf[4].bufnr)) + call assert_equal('dir1/a/habits2.txt', bufname(qf[4].bufnr)) call assert_equal(7, qf[4].lnum) - call assert_equal(expand('dir1/c/habits4.txt'), bufname(qf[6].bufnr)) + call assert_equal('dir1/c/habits4.txt', bufname(qf[6].bufnr)) call assert_equal(3, qf[6].lnum) call assert_equal('habits1.txt', bufname(qf[9].bufnr)) call assert_equal(4, qf[9].lnum) - call assert_equal(expand('dir2/habits5.txt'), bufname(qf[11].bufnr)) + call assert_equal('dir2/habits5.txt', bufname(qf[11].bufnr)) call assert_equal(5, qf[11].lnum) let &efm=save_efm @@ -1300,7 +1300,7 @@ func Test_efm2() call assert_equal(8, len(l)) call assert_equal(89, l[4].lnum) call assert_equal(1, l[4].valid) - call assert_equal(expand('unittests/dbfacadeTest.py'), bufname(l[4].bufnr)) + call assert_equal('unittests/dbfacadeTest.py', bufname(l[4].bufnr)) call assert_equal('W', l[4].type) " Test for %o @@ -2074,11 +2074,11 @@ func Test_two_windows() laddexpr 'one.txt:3:one one one' let loc_one = getloclist(one_id) - call assert_equal(expand('Xone/a/one.txt'), bufname(loc_one[1].bufnr)) + call assert_equal('Xone/a/one.txt', bufname(loc_one[1].bufnr)) call assert_equal(3, loc_one[1].lnum) let loc_two = getloclist(two_id) - call assert_equal(expand('Xtwo/a/two.txt'), bufname(loc_two[1].bufnr)) + call assert_equal('Xtwo/a/two.txt', bufname(loc_two[1].bufnr)) call assert_equal(5, loc_two[1].lnum) call win_gotoid(one_id) diff --git a/test/functional/lua/filetype_spec.lua b/test/functional/lua/filetype_spec.lua index d0cef53c4b..be57b2db31 100644 --- a/test/functional/lua/filetype_spec.lua +++ b/test/functional/lua/filetype_spec.lua @@ -3,6 +3,7 @@ local exec_lua = helpers.exec_lua local eq = helpers.eq local clear = helpers.clear local pathroot = helpers.pathroot +local command = helpers.command local root = pathroot() @@ -23,7 +24,7 @@ describe('vim.filetype', function() rs = 'radicalscript', }, }) - return vim.filetype.match('main.rs') + return vim.filetype.match({ filename = 'main.rs' }) ]]) end) @@ -37,7 +38,7 @@ describe('vim.filetype', function() ['main.rs'] = 'somethingelse', }, }) - return vim.filetype.match('main.rs') + return vim.filetype.match({ filename = 'main.rs' }) ]]) end) @@ -48,7 +49,7 @@ describe('vim.filetype', function() ['s_O_m_e_F_i_l_e'] = 'nim', }, }) - return vim.filetype.match('s_O_m_e_F_i_l_e') + return vim.filetype.match({ filename = 's_O_m_e_F_i_l_e' }) ]]) eq('dosini', exec_lua([[ @@ -59,7 +60,7 @@ describe('vim.filetype', function() [root .. '/.config/fun/config'] = 'dosini', }, }) - return vim.filetype.match(root .. '/.config/fun/config') + return vim.filetype.match({ filename = root .. '/.config/fun/config' }) ]], root)) end) @@ -72,11 +73,13 @@ describe('vim.filetype', function() ['~/blog/.*%.txt'] = 'markdown', } }) - return vim.filetype.match('~/blog/why_neovim_is_awesome.txt') + return vim.filetype.match({ filename = '~/blog/why_neovim_is_awesome.txt' }) ]], root)) end) it('works with functions', function() + command('new') + command('file relevant_to_me') eq('foss', exec_lua [[ vim.filetype.add({ pattern = { @@ -87,7 +90,7 @@ describe('vim.filetype', function() end, } }) - return vim.filetype.match('relevant_to_me') + return vim.filetype.match({ buf = 0 }) ]]) end) end) |