diff options
Diffstat (limited to 'runtime/lua')
-rw-r--r-- | runtime/lua/nvim/health.lua | 72 | ||||
-rw-r--r-- | runtime/lua/provider/clipboard/health.lua | 5 | ||||
-rw-r--r-- | runtime/lua/provider/node/health.lua | 13 | ||||
-rw-r--r-- | runtime/lua/provider/python/health.lua | 11 | ||||
-rw-r--r-- | runtime/lua/provider/ruby/health.lua | 3 | ||||
-rw-r--r-- | runtime/lua/vim/_comment.lua | 266 | ||||
-rw-r--r-- | runtime/lua/vim/_defaults.lua | 48 | ||||
-rw-r--r-- | runtime/lua/vim/_meta/vimfn.lua | 4 | ||||
-rw-r--r-- | runtime/lua/vim/filetype.lua | 1 | ||||
-rw-r--r-- | runtime/lua/vim/health.lua | 9 | ||||
-rw-r--r-- | runtime/lua/vim/lsp/client.lua | 1 |
11 files changed, 365 insertions, 68 deletions
diff --git a/runtime/lua/nvim/health.lua b/runtime/lua/nvim/health.lua index 585c8deaee..35d293bee6 100644 --- a/runtime/lua/nvim/health.lua +++ b/runtime/lua/nvim/health.lua @@ -1,18 +1,6 @@ local M = {} local health = require('vim.health') -local fn_bool = function(key) - return function(...) - return vim.fn[key](...) == 1 - end -end - -local has = fn_bool('has') -local executable = fn_bool('executable') -local empty = fn_bool('empty') -local filereadable = fn_bool('filereadable') -local filewritable = fn_bool('filewritable') - local shell_error = function() return vim.v.shell_error ~= 0 end @@ -62,11 +50,11 @@ local function check_config() local init_lua = vim.fn.stdpath('config') .. '/init.lua' local init_vim = vim.fn.stdpath('config') .. '/init.vim' - local vimrc = empty(vim.env.MYVIMRC) and init_lua or vim.env.MYVIMRC + local vimrc = vim.env.MYVIMRC or init_lua - if not filereadable(vimrc) and not filereadable(init_vim) then + if vim.fn.filereadable(vimrc) == 0 and vim.fn.filereadable(init_vim) == 0 then ok = false - local has_vim = filereadable(vim.fn.expand('~/.vimrc')) + local has_vim = vim.fn.filereadable(vim.fn.expand('~/.vimrc')) == 1 health.warn( ('%s user config file: %s'):format( -1 == vim.fn.getfsize(vimrc) and 'Missing' or 'Unreadable', @@ -77,7 +65,7 @@ local function check_config() end -- If $VIM is empty we don't care. Else make sure it is valid. - if not empty(vim.env.VIM) and not filereadable(vim.env.VIM .. '/runtime/doc/nvim.txt') then + if vim.env.VIM and vim.fn.filereadable(vim.env.VIM .. '/runtime/doc/nvim.txt') == 0 then ok = false health.error('$VIM is invalid: ' .. vim.env.VIM) end @@ -121,17 +109,17 @@ local function check_config() local writeable = true local shadaopt = vim.fn.split(vim.o.shada, ',') local shadafile = ( - empty(vim.o.shada) and vim.o.shada + vim.o.shada == '' and vim.o.shada or vim.fn.substitute(vim.fn.matchstr(shadaopt[#shadaopt], '^n.\\+'), '^n', '', '') ) shadafile = ( - empty(vim.o.shadafile) - and (empty(shadafile) and vim.fn.stdpath('state') .. '/shada/main.shada' or vim.fn.expand( + vim.o.shadafile == '' + and (shadafile == '' and vim.fn.stdpath('state') .. '/shada/main.shada' or vim.fn.expand( shadafile )) or (vim.o.shadafile == 'NONE' and '' or vim.o.shadafile) ) - if not empty(shadafile) and empty(vim.fn.glob(shadafile)) then + if shadafile ~= '' and vim.fn.glob(shadafile) == '' then -- Since this may be the first time Nvim has been run, try to create a shada file. if not pcall(vim.cmd.wshada) then writeable = false @@ -139,12 +127,15 @@ local function check_config() end if not writeable - or (not empty(shadafile) and (not filereadable(shadafile) or not filewritable(shadafile))) + or ( + shadafile ~= '' + and (vim.fn.filereadable(shadafile) == 0 or vim.fn.filewritable(shadafile) ~= 1) + ) then ok = false health.error( 'shada file is not ' - .. ((not writeable or filereadable(shadafile)) and 'writeable' or 'readable') + .. ((not writeable or vim.fn.filereadable(shadafile) == 1) and 'writeable' or 'readable') .. ':\n' .. shadafile ) @@ -160,7 +151,7 @@ local function check_performance() -- Check buildtype local buildtype = vim.fn.matchstr(vim.fn.execute('version'), [[\v\cbuild type:?\s*[^\n\r\t ]+]]) - if empty(buildtype) then + if buildtype == '' then health.error('failed to get build type from :version') elseif vim.regex([[\v(MinSizeRel|Release|RelWithDebInfo)]]):match_str(buildtype) then health.ok(buildtype) @@ -196,12 +187,12 @@ local function check_rplugin_manifest() local require_update = false local handle_path = function(path) local python_glob = vim.fn.glob(path .. '/rplugin/python*', true, true) - if empty(python_glob) then + if vim.tbl_isempty(python_glob) then return end local python_dir = python_glob[1] - local python_version = vim.fn.fnamemodify(python_dir, ':t') + local python_version = vim.fs.basename(python_dir) local scripts = vim.fn.glob(python_dir .. '/*.py', true, true) vim.list_extend(scripts, vim.fn.glob(python_dir .. '/*/__init__.py', true, true)) @@ -213,12 +204,12 @@ local function check_rplugin_manifest() script = vim.fn.tr(vim.fn.fnamemodify(script, ':h'), '\\', '/') end if not existing_rplugins[script] then - local msg = vim.fn.printf('"%s" is not registered.', vim.fn.fnamemodify(path, ':t')) + local msg = vim.fn.printf('"%s" is not registered.', vim.fs.basename(path)) if python_version == 'pythonx' then - if not has('python3') then + if vim.fn.has('python3') == 0 then msg = msg .. ' (python3 not available)' end - elseif not has(python_version) then + elseif vim.fn.has(python_version) == 0 then msg = msg .. vim.fn.printf(' (%s not available)', python_version) else require_update = true @@ -232,7 +223,7 @@ local function check_rplugin_manifest() end end - for _, path in ipairs(vim.fn.map(vim.fn.split(vim.o.runtimepath, ','), 'resolve(v:val)')) do + for _, path in ipairs(vim.fn.map(vim.split(vim.o.runtimepath, ','), 'resolve(v:val)')) do handle_path(path) end @@ -244,7 +235,7 @@ local function check_rplugin_manifest() end local function check_tmux() - if empty(vim.env.TMUX) or not executable('tmux') then + if not vim.env.TMUX or vim.fn.executable('tmux') == 0 then return end @@ -255,7 +246,7 @@ local function check_tmux() if shell_error() then health.error('command failed: ' .. cmd .. '\n' .. out) return 'error' - elseif empty(val) then + elseif val == '' then cmd = 'tmux show-option -qvgs ' .. option -- try session scope out = vim.fn.system(vim.fn.split(cmd)) val = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g') @@ -274,7 +265,7 @@ local function check_tmux() { 'set escape-time in ~/.tmux.conf:\nset-option -sg escape-time 10', suggest_faq } local tmux_esc_time = get_tmux_option('escape-time') if tmux_esc_time ~= 'error' then - if empty(tmux_esc_time) then + if tmux_esc_time == '' then health.error('`escape-time` is not set', suggestions) elseif tonumber(tmux_esc_time) > 300 then health.error('`escape-time` (' .. tmux_esc_time .. ') is higher than 300ms', suggestions) @@ -286,7 +277,7 @@ local function check_tmux() -- check focus-events local tmux_focus_events = get_tmux_option('focus-events') if tmux_focus_events ~= 'error' then - if empty(tmux_focus_events) or tmux_focus_events ~= 'on' then + if tmux_focus_events == '' or tmux_focus_events ~= 'on' then health.warn( "`focus-events` is not enabled. |'autoread'| may not work.", { '(tmux 1.9+ only) Set `focus-events` in ~/.tmux.conf:\nset-option -g focus-events on' } @@ -301,7 +292,7 @@ local function check_tmux() local cmd = 'tmux show-option -qvg default-terminal' local out = vim.fn.system(vim.fn.split(cmd)) local tmux_default_term = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g') - if empty(tmux_default_term) then + if tmux_default_term == '' then cmd = 'tmux show-option -qvgs default-terminal' out = vim.fn.system(vim.fn.split(cmd)) tmux_default_term = vim.fn.substitute(out, [[\v(\s|\r|\n)]], '', 'g') @@ -341,7 +332,7 @@ local function check_tmux() end local function check_terminal() - if not executable('infocmp') then + if vim.fn.executable('infocmp') == 0 then return end @@ -354,13 +345,12 @@ local function check_terminal() if shell_error() and ( - not has('win32') - or empty( - vim.fn.matchstr( + vim.fn.has('win32') == 0 + or vim.fn.matchstr( out, [[infocmp: couldn't open terminfo file .\+\%(conemu\|vtpcon\|win32con\)]] ) - ) + == '' ) then health.error('command failed: ' .. cmd .. '\n' .. out) @@ -368,14 +358,14 @@ local function check_terminal() health.info( vim.fn.printf( 'key_backspace (kbs) terminfo entry: `%s`', - (empty(kbs_entry) and '? (not found)' or kbs_entry) + (kbs_entry == '' and '? (not found)' or kbs_entry) ) ) health.info( vim.fn.printf( 'key_dc (kdch1) terminfo entry: `%s`', - (empty(kbs_entry) and '? (not found)' or kdch1_entry) + (kbs_entry == '' and '? (not found)' or kdch1_entry) ) ) end diff --git a/runtime/lua/provider/clipboard/health.lua b/runtime/lua/provider/clipboard/health.lua index dc33cb0ab0..e44f7d32cc 100644 --- a/runtime/lua/provider/clipboard/health.lua +++ b/runtime/lua/provider/clipboard/health.lua @@ -1,5 +1,4 @@ local health = vim.health -local executable = health.executable local M = {} @@ -8,8 +7,8 @@ function M.check() if os.getenv('TMUX') - and executable('tmux') - and executable('pbpaste') + and vim.fn.executable('tmux') == 1 + and vim.fn.executable('pbpaste') == 1 and not health.cmd_ok('pbpaste') then local tmux_version = string.match(vim.fn.system('tmux -V'), '%d+%.%d+') diff --git a/runtime/lua/provider/node/health.lua b/runtime/lua/provider/node/health.lua index a434f8a92b..b4dca2f482 100644 --- a/runtime/lua/provider/node/health.lua +++ b/runtime/lua/provider/node/health.lua @@ -1,5 +1,4 @@ local health = vim.health -local executable = health.executable local iswin = vim.loop.os_uname().sysname == 'Windows_NT' local M = {} @@ -12,8 +11,12 @@ function M.check() end if - not executable('node') - or (not executable('npm') and not executable('yarn') and not executable('pnpm')) + vim.fn.executable('node') == 0 + or ( + vim.fn.executable('npm') == 0 + and vim.fn.executable('yarn') == 0 + and vim.fn.executable('pnpm') == 0 + ) then health.warn( '`node` and `npm` (or `yarn`, `pnpm`) must be in $PATH.', @@ -50,9 +53,9 @@ function M.check() health.info('Nvim node.js host: ' .. host) local manager = 'npm' - if executable('yarn') then + if vim.fn.executable('yarn') == 1 then manager = 'yarn' - elseif executable('pnpm') then + elseif vim.fn.executable('pnpm') == 1 then manager = 'pnpm' end diff --git a/runtime/lua/provider/python/health.lua b/runtime/lua/provider/python/health.lua index 333890b62b..a5bd738063 100644 --- a/runtime/lua/provider/python/health.lua +++ b/runtime/lua/provider/python/health.lua @@ -1,5 +1,4 @@ local health = vim.health -local executable = health.executable local iswin = vim.loop.os_uname().sysname == 'Windows_NT' local M = {} @@ -60,7 +59,7 @@ local function check_bin(bin) if not is(bin, 'file') and (not iswin or not is(bin .. '.exe', 'file')) then health.error('"' .. bin .. '" was not found.') return false - elseif not executable(bin) then + elseif vim.fn.executable(bin) == 0 then health.error('"' .. bin .. '" is not executable.') return false end @@ -69,7 +68,7 @@ end -- Fetch the contents of a URL. local function download(url) - local has_curl = executable('curl') + local has_curl = vim.fn.executable('curl') == 1 if has_curl and vim.fn.system({ 'curl', '-V' }):find('Protocols:.*https') then local out, rc = health.system({ 'curl', '-sL', url }, { stderr = true, ignore_error = true }) if rc ~= 0 then @@ -77,7 +76,7 @@ local function download(url) else return out end - elseif executable('python') then + elseif vim.fn.executable('python') == 1 then local script = "try:\n\ from urllib.request import urlopen\n\ except ImportError:\n\ @@ -284,7 +283,7 @@ function M.check() if path_bin ~= vim.fs.normalize(python_exe) and vim.tbl_contains(python_multiple, path_bin) - and executable(path_bin) + and vim.fn.executable(path_bin) == 1 then python_multiple[#python_multiple + 1] = path_bin end @@ -472,7 +471,7 @@ function M.check() bin_dir, table.concat( vim.tbl_map(function(v) - return vim.fn.fnamemodify(v, ':t') + return vim.fs.basename(v) end, venv_bins), ', ' ) diff --git a/runtime/lua/provider/ruby/health.lua b/runtime/lua/provider/ruby/health.lua index 04f6e303e6..4d859597a4 100644 --- a/runtime/lua/provider/ruby/health.lua +++ b/runtime/lua/provider/ruby/health.lua @@ -1,5 +1,4 @@ local health = vim.health -local executable = health.executable local iswin = vim.loop.os_uname().sysname == 'Windows_NT' local M = {} @@ -11,7 +10,7 @@ function M.check() return end - if not executable('ruby') or not executable('gem') then + if vim.fn.executable('ruby') == 0 or vim.fn.executable('gem') == 0 then health.warn( '`ruby` and `gem` must be in $PATH.', 'Install Ruby and verify that `ruby` and `gem` commands work.' diff --git a/runtime/lua/vim/_comment.lua b/runtime/lua/vim/_comment.lua new file mode 100644 index 0000000000..e9cd662c9d --- /dev/null +++ b/runtime/lua/vim/_comment.lua @@ -0,0 +1,266 @@ +---@nodoc +---@class vim._comment.Parts +---@field left string Left part of comment +---@field right string Right part of comment + +--- Get 'commentstring' at cursor +---@param ref_position integer[] +---@return string +local function get_commentstring(ref_position) + local buf_cs = vim.bo.commentstring + + local has_ts_parser, ts_parser = pcall(vim.treesitter.get_parser) + if not has_ts_parser then + return buf_cs + end + + -- Try to get 'commentstring' associated with local tree-sitter language. + -- This is useful for injected languages (like markdown with code blocks). + local row, col = ref_position[1] - 1, ref_position[2] + local ref_range = { row, col, row, col + 1 } + + -- - Get 'commentstring' from the deepest LanguageTree which both contains + -- reference range and has valid 'commentstring' (meaning it has at least + -- one associated 'filetype' with valid 'commentstring'). + -- In simple cases using `parser:language_for_range()` would be enough, but + -- it fails for languages without valid 'commentstring' (like 'comment'). + local ts_cs, res_level = nil, 0 + + ---@param lang_tree vim.treesitter.LanguageTree + local function traverse(lang_tree, level) + if not lang_tree:contains(ref_range) then + return + end + + local lang = lang_tree:lang() + local filetypes = vim.treesitter.language.get_filetypes(lang) + for _, ft in ipairs(filetypes) do + local cur_cs = vim.filetype.get_option(ft, 'commentstring') + if cur_cs ~= '' and level > res_level then + ts_cs = cur_cs + end + end + + for _, child_lang_tree in pairs(lang_tree:children()) do + traverse(child_lang_tree, level + 1) + end + end + traverse(ts_parser, 1) + + return ts_cs or buf_cs +end + +--- Compute comment parts from 'commentstring' +---@param ref_position integer[] +---@return vim._comment.Parts +local function get_comment_parts(ref_position) + local cs = get_commentstring(ref_position) + + if cs == nil or cs == '' then + vim.api.nvim_echo({ { "Option 'commentstring' is empty.", 'WarningMsg' } }, true, {}) + return { left = '', right = '' } + end + + if not (type(cs) == 'string' and cs:find('%%s') ~= nil) then + error(vim.inspect(cs) .. " is not a valid 'commentstring'.") + end + + -- Structure of 'commentstring': <left part> <%s> <right part> + local left, right = cs:match('^(.-)%%s(.-)$') + return { left = left, right = right } +end + +--- Make a function that checks if a line is commented +---@param parts vim._comment.Parts +---@return fun(line: string): boolean +local function make_comment_check(parts) + local l_esc, r_esc = vim.pesc(parts.left), vim.pesc(parts.right) + + -- Commented line has the following structure: + -- <possible whitespace> <left> <anything> <right> <possible whitespace> + local nonblank_regex = '^%s-' .. l_esc .. '.*' .. r_esc .. '%s-$' + + -- Commented blank line can have any amoung of whitespace around parts + local blank_regex = '^%s-' .. vim.trim(l_esc) .. '%s*' .. vim.trim(r_esc) .. '%s-$' + + return function(line) + return line:find(nonblank_regex) ~= nil or line:find(blank_regex) ~= nil + end +end + +--- Compute comment-related information about lines +---@param lines string[] +---@param parts vim._comment.Parts +---@return string indent +---@return boolean is_commented +local function get_lines_info(lines, parts) + local comment_check = make_comment_check(parts) + + local is_commented = true + local indent_width = math.huge + ---@type string + local indent + + for _, l in ipairs(lines) do + -- Update lines indent: minimum of all indents except blank lines + local _, indent_width_cur, indent_cur = l:find('^(%s*)') + + -- Ignore blank lines completely when making a decision + if indent_width_cur < l:len() then + -- NOTE: Copying actual indent instead of recreating it with `indent_width` + -- allows to handle both tabs and spaces + if indent_width_cur < indent_width then + ---@diagnostic disable-next-line:cast-local-type + indent_width, indent = indent_width_cur, indent_cur + end + + -- Update comment info: commented if every non-blank line is commented + if is_commented then + is_commented = comment_check(l) + end + end + end + + -- `indent` can still be `nil` in case all `lines` are empty + return indent or '', is_commented +end + +--- Compute whether a string is blank +---@param x string +---@return boolean is_blank +local function is_blank(x) + return x:find('^%s*$') ~= nil +end + +--- Make a function which comments a line +---@param parts vim._comment.Parts +---@param indent string +---@return fun(line: string): string +local function make_comment_function(parts, indent) + local prefix, nonindent_start, suffix = indent .. parts.left, indent:len() + 1, parts.right + local blank_comment = indent .. vim.trim(parts.left) .. vim.trim(parts.right) + + return function(line) + if is_blank(line) then + return blank_comment + end + return prefix .. line:sub(nonindent_start) .. suffix + end +end + +--- Make a function which uncomments a line +---@param parts vim._comment.Parts +---@return fun(line: string): string +local function make_uncomment_function(parts) + local l_esc, r_esc = vim.pesc(parts.left), vim.pesc(parts.right) + local nonblank_regex = '^(%s*)' .. l_esc .. '(.*)' .. r_esc .. '(%s-)$' + local blank_regex = '^(%s*)' .. vim.trim(l_esc) .. '(%s*)' .. vim.trim(r_esc) .. '(%s-)$' + + return function(line) + -- Try both non-blank and blank regexes + local indent, new_line, trail = line:match(nonblank_regex) + if new_line == nil then + indent, new_line, trail = line:match(blank_regex) + end + + -- Return original if line is not commented + if new_line == nil then + return line + end + + -- Prevent trailing whitespace + if is_blank(new_line) then + indent, trail = '', '' + end + + return indent .. new_line .. trail + end +end + +--- Comment/uncomment buffer range +---@param line_start integer +---@param line_end integer +---@param ref_position? integer[] +local function toggle_lines(line_start, line_end, ref_position) + ref_position = ref_position or { line_start, 0 } + local parts = get_comment_parts(ref_position) + local lines = vim.api.nvim_buf_get_lines(0, line_start - 1, line_end, false) + local indent, is_comment = get_lines_info(lines, parts) + + local f = is_comment and make_uncomment_function(parts) or make_comment_function(parts, indent) + + -- Direct `nvim_buf_set_lines()` essentially removes both regular and + -- extended marks (squashes to empty range at either side of the region) + -- inside region. Use 'lockmarks' to preserve regular marks. + -- Preserving extmarks is not a universally good thing to do: + -- - Good for non-highlighting in text area extmarks (like showing signs). + -- - Debatable for highlighting in text area (like LSP semantic tokens). + -- Mostly because it causes flicker as highlighting is preserved during + -- comment toggling. + package.loaded['vim._comment']._lines = vim.tbl_map(f, lines) + local lua_cmd = string.format( + 'vim.api.nvim_buf_set_lines(0, %d, %d, false, package.loaded["vim._comment"]._lines)', + line_start - 1, + line_end + ) + vim.cmd.lua({ lua_cmd, mods = { lockmarks = true } }) + package.loaded['vim._comment']._lines = nil +end + +--- Operator which toggles user-supplied range of lines +---@param mode string? +---|"'line'" +---|"'char'" +---|"'block'" +local function operator(mode) + -- Used without arguments as part of expression mapping. Otherwise it is + -- called as 'operatorfunc'. + if mode == nil then + vim.o.operatorfunc = "v:lua.require'vim._comment'.operator" + return 'g@' + end + + -- Compute target range + local mark_from, mark_to = "'[", "']" + local lnum_from, col_from = vim.fn.line(mark_from), vim.fn.col(mark_from) + local lnum_to, col_to = vim.fn.line(mark_to), vim.fn.col(mark_to) + + -- Do nothing if "from" mark is after "to" (like in empty textobject) + if (lnum_from > lnum_to) or (lnum_from == lnum_to and col_from > col_to) then + return + end + + -- NOTE: use cursor position as reference for possibly computing local + -- tree-sitter-based 'commentstring'. Recompute every time for a proper + -- dot-repeat. In Visual and sometimes Normal mode it uses start position. + toggle_lines(lnum_from, lnum_to, vim.api.nvim_win_get_cursor(0)) + return '' +end + +--- Select contiguous commented lines at cursor +local function textobject() + local lnum_cur = vim.fn.line('.') + local parts = get_comment_parts({ lnum_cur, vim.fn.col('.') }) + local comment_check = make_comment_check(parts) + + if not comment_check(vim.fn.getline(lnum_cur)) then + return + end + + -- Compute commented range + local lnum_from = lnum_cur + while (lnum_from >= 2) and comment_check(vim.fn.getline(lnum_from - 1)) do + lnum_from = lnum_from - 1 + end + + local lnum_to = lnum_cur + local n_lines = vim.api.nvim_buf_line_count(0) + while (lnum_to <= n_lines - 1) and comment_check(vim.fn.getline(lnum_to + 1)) do + lnum_to = lnum_to + 1 + end + + -- Select range linewise for operator to act upon + vim.cmd('normal! ' .. lnum_from .. 'GV' .. lnum_to .. 'G') +end + +return { operator = operator, textobject = textobject, toggle_lines = toggle_lines } diff --git a/runtime/lua/vim/_defaults.lua b/runtime/lua/vim/_defaults.lua index 6223082622..90d05f67a5 100644 --- a/runtime/lua/vim/_defaults.lua +++ b/runtime/lua/vim/_defaults.lua @@ -1,3 +1,31 @@ +--- Default user commands +do + vim.api.nvim_create_user_command('Inspect', function(cmd) + if cmd.bang then + vim.print(vim.inspect_pos()) + else + vim.show_pos() + end + end, { desc = 'Inspect highlights and extmarks at the cursor', bang = true }) + + vim.api.nvim_create_user_command('InspectTree', function(cmd) + if cmd.mods ~= '' or cmd.count ~= 0 then + local count = cmd.count ~= 0 and cmd.count or '' + local new = cmd.mods ~= '' and 'new' or 'vnew' + + vim.treesitter.inspect_tree({ + command = ('%s %s%s'):format(cmd.mods, count, new), + }) + else + vim.treesitter.inspect_tree() + end + end, { desc = 'Inspect treesitter language tree for buffer', count = true }) + + vim.api.nvim_create_user_command('EditQuery', function(cmd) + vim.treesitter.query.edit(cmd.fargs[1]) + end, { desc = 'Edit treesitter query', nargs = '?' }) +end + --- Default mappings do --- Default maps for * and # in visual mode. @@ -86,6 +114,24 @@ do do_open(table.concat(vim.iter(lines):map(vim.trim):totable())) end, { desc = gx_desc }) end + + --- Default maps for built-in commenting + do + local operator_rhs = function() + return require('vim._comment').operator() + end + vim.keymap.set({ 'n', 'x' }, 'gc', operator_rhs, { expr = true, desc = 'Toggle comment' }) + + local line_rhs = function() + return require('vim._comment').operator() .. '_' + end + vim.keymap.set('n', 'gcc', line_rhs, { expr = true, desc = 'Toggle comment line' }) + + local textobject_rhs = function() + require('vim._comment').textobject() + end + vim.keymap.set({ 'o' }, 'gc', textobject_rhs, { desc = 'Comment textobject' }) + end end --- Default menus @@ -93,7 +139,6 @@ do --- Right click popup menu -- TODO VimScript, no l10n vim.cmd([[ - aunmenu * vnoremenu PopUp.Cut "+x vnoremenu PopUp.Copy "+y anoremenu PopUp.Paste "+gP @@ -102,6 +147,7 @@ do nnoremenu PopUp.Select\ All ggVG vnoremenu PopUp.Select\ All gg0oG$ inoremenu PopUp.Select\ All <C-Home><C-O>VG + anoremenu PopUp.Inspect <Cmd>Inspect<CR> anoremenu PopUp.-1- <Nop> anoremenu PopUp.How-to\ disable\ mouse <Cmd>help disable-mouse<CR> ]]) diff --git a/runtime/lua/vim/_meta/vimfn.lua b/runtime/lua/vim/_meta/vimfn.lua index caddd4dde2..c114c3b212 100644 --- a/runtime/lua/vim/_meta/vimfn.lua +++ b/runtime/lua/vim/_meta/vimfn.lua @@ -1598,11 +1598,10 @@ function vim.fn.eventhandler() end --- The result is a Number: --- 1 exists --- 0 does not exist ---- -1 not implemented on this system --- |exepath()| can be used to get the full path of an executable. --- --- @param expr any ---- @return 0|1|-1 +--- @return 0|1 function vim.fn.executable(expr) end --- Execute {command} and capture its output. @@ -1959,6 +1958,7 @@ function vim.fn.extendnew(expr1, expr2, expr3) end --- 't' Handle keys as if typed; otherwise they are handled as --- if coming from a mapping. This matters for undo, --- opening folds, etc. +--- 'L' Lowlevel input. Other flags are not used. --- 'i' Insert the string instead of appending (see above). --- 'x' Execute commands until typeahead is empty. This is --- similar to using ":normal!". You can call feedkeys() diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index 1198a9972f..9b1fd80b82 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -1293,6 +1293,7 @@ local filename = { jbuild = 'dune', ['dune-workspace'] = 'dune', ['dune-project'] = 'dune', + Earthfile = 'earthfile', ['.editorconfig'] = 'editorconfig', ['elinks.conf'] = 'elinks', ['mix.lock'] = 'elixir', diff --git a/runtime/lua/vim/health.lua b/runtime/lua/vim/health.lua index f6f7abef8f..9e9c557ad3 100644 --- a/runtime/lua/vim/health.lua +++ b/runtime/lua/vim/health.lua @@ -386,7 +386,7 @@ local path2name = function(path) path = path:gsub('^.*/lua/', '') -- Remove the filename (health.lua) - path = vim.fn.fnamemodify(path, ':h') + path = vim.fs.dirname(path) -- Change slashes to dots path = path:gsub('/', '.') @@ -497,11 +497,4 @@ function M._check(mods, plugin_names) vim.print('') end -local fn_bool = function(key) - return function(...) - return vim.fn[key](...) == 1 - end -end -M.executable = fn_bool('executable') - return M diff --git a/runtime/lua/vim/lsp/client.lua b/runtime/lua/vim/lsp/client.lua index f73f97b8cd..09064b9510 100644 --- a/runtime/lua/vim/lsp/client.lua +++ b/runtime/lua/vim/lsp/client.lua @@ -579,6 +579,7 @@ function Client:initialize() initializationOptions = config.init_options, capabilities = self.capabilities, trace = self._trace, + workDoneToken = '1', } self:_run_callbacks( |