diff options
Diffstat (limited to 'runtime')
38 files changed, 1404 insertions, 734 deletions
diff --git a/runtime/autoload/health/nvim.vim b/runtime/autoload/health/nvim.vim index f3732e012f..9b387095ee 100644 --- a/runtime/autoload/health/nvim.vim +++ b/runtime/autoload/health/nvim.vim @@ -45,7 +45,7 @@ function! s:check_config() abort let shadafile = empty(&shada) ? &shada : substitute(matchstr( \ split(&shada, ',')[-1], '^n.\+'), '^n', '', '') let shadafile = empty(&shadafile) ? empty(shadafile) ? - \ stdpath('data').'/shada/main.shada' : expand(shadafile) + \ stdpath('state').'/shada/main.shada' : expand(shadafile) \ : &shadafile ==# 'NONE' ? '' : &shadafile if !empty(shadafile) && empty(glob(shadafile)) " Since this may be the first time neovim has been run, we will try to diff --git a/runtime/colors/README.txt b/runtime/colors/README.txt index bda0300678..4ea8e5e640 100644 --- a/runtime/colors/README.txt +++ b/runtime/colors/README.txt @@ -1,14 +1,18 @@ README.txt for color scheme files -These files are used for the ":colorscheme" command. They appear in the +These files are used for the `:colorscheme` command. They appear in the "Edit/Color Scheme" menu in the GUI. +The colorschemes were updated for the Vim 9 release. If you don't like the +changes you can find the old ones here: +https://github.com/vim/colorschemes/tree/master/legacy_colors + Hints for writing a color scheme file: There are two basic ways to define a color scheme: -1. Define a new Normal color and set the 'background' option accordingly. +1. Define a new Normal color and set the 'background' option accordingly. > set background={light or dark} highlight clear @@ -16,7 +20,7 @@ There are two basic ways to define a color scheme: ... 2. Use the default Normal color and automatically adjust to the value of - 'background'. + 'background'. > highlight clear Normal set background& @@ -29,17 +33,17 @@ There are two basic ways to define a color scheme: ... endif -You can use ":highlight clear" to reset everything to the defaults, and then +You can use `:highlight clear` to reset everything to the defaults, and then change the groups that you want differently. This will also work for groups that are added in later versions of Vim. -Note that ":highlight clear" uses the value of 'background', thus set it +Note that `:highlight clear` uses the value of 'background', thus set it before this command. Some attributes (e.g., bold) might be set in the defaults that you want removed in your color scheme. Use something like "gui=NONE" to remove the attributes. In case you want to set 'background' depending on the colorscheme selected, -this autocmd might be useful: +this autocmd might be useful: > autocmd SourcePre */colors/blue_sky.vim set background=dark @@ -49,7 +53,7 @@ In case you want to tweak a colorscheme after it was loaded, check out the ColorScheme autocommand event. To clean up just before loading another colorscheme, use the ColorSchemePre -autocommand event. For example: +autocommand event. For example: > let g:term_ansi_colors = ... augroup MyColorscheme @@ -59,20 +63,20 @@ autocommand event. For example: augroup END To customize a colorscheme use another name, e.g. "~/.vim/colors/mine.vim", -and use ":runtime" to load the original colorscheme: +and use ":runtime" to load the original colorscheme: > " load the "evening" colorscheme runtime colors/evening.vim " change the color of statements hi Statement ctermfg=Blue guifg=Blue -To see which highlight group is used where, see ":help highlight-groups" and -":help group-name". +To see which highlight group is used where, see `:help highlight-groups` and +`:help group-name` . You can use ":highlight" to find out the current colors. Exception: the ctermfg and ctermbg values are numbers, which are only valid for the current terminal. Use the color names instead for better portability. See -":help cterm-colors". +`:help cterm-colors` . The default color settings can be found in the source file "src/nvim/highlight_group.c". Search for "highlight_init". @@ -86,7 +90,7 @@ please check the following items: - Does it work in a color terminal as well as in the GUI? Is it consistent? - Is "g:colors_name" set to a meaningful value? In case of doubt you can do - it this way: + it this way: > let g:colors_name = expand('<sfile>:t:r') @@ -121,7 +125,7 @@ please check the following items: - Try to keep your color scheme simple by avoiding unnecessary logic and refraining from adding options. The best color scheme is one that only - requires: + requires: > colorscheme foobar @@ -136,3 +140,6 @@ that: - it was made with colortemplate, and join us at vim/colorschemes: (https://github.com/vim/colorschemes). + + +vim: set ft=help : diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 812208ca31..3ab7c77056 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -442,6 +442,9 @@ to disable various visual features such as the 'number' column. Currently, floating windows don't support some widgets like scrollbar. +The output of |:mksession| does not include commands for restoring floating +windows. + Example: create a float with scratch buffer: > let buf = nvim_create_buf(v:false, v:true) @@ -844,8 +847,11 @@ nvim_eval_statusline({str}, {*opts}) *nvim_eval_statusline()* Treated as single-width even if it isn't. • highlights: (boolean) Return highlight information. + • use_winbar: (boolean) Evaluate winbar instead of + statusline. • use_tabline: (boolean) Evaluate tabline instead of statusline. When |TRUE|, {winid} is ignored. + Mutually exclusive with {use_winbar}. Return: ~ Dictionary containing statusline information, with these @@ -1668,12 +1674,18 @@ nvim_set_option_value({name}, {value}, {*opts}) global and local value are set unless otherwise specified with {scope}. + Note the options {win} and {buf} cannot be used together. + Parameters: ~ {name} Option name {value} New option value {opts} Optional parameters • scope: One of 'global' or 'local'. Analogous to |:setglobal| and |:setlocal|, respectively. + • win: |window-ID|. Used for setting window local + option. + • buf: Buffer number. Used for setting buffer + local option. nvim_set_var({name}, {value}) *nvim_set_var()* Sets a global (g:) variable. @@ -1725,8 +1737,7 @@ Vimscript Functions *api-vimscript* nvim_call_dict_function({dict}, {fn}, {args}) Calls a VimL |Dictionary-function| with the given arguments. - On execution error: fails with VimL error, does not update - v:errmsg. + On execution error: fails with VimL error, updates v:errmsg. Parameters: ~ {dict} Dictionary, or String evaluating to a VimL |self| @@ -1740,8 +1751,7 @@ nvim_call_dict_function({dict}, {fn}, {args}) nvim_call_function({fn}, {args}) *nvim_call_function()* Calls a VimL function with the given arguments. - On execution error: fails with VimL error, does not update - v:errmsg. + On execution error: fails with VimL error, updates v:errmsg. Parameters: ~ {fn} Function to call @@ -1760,6 +1770,8 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()* argument, expanding filenames in a command that otherwise doesn't expand filenames, etc. + On execution error: fails with VimL error, updates v:errmsg. + Parameters: ~ {cmd} Command to execute. Must be a Dictionary that can contain the same values as the return value of @@ -1781,8 +1793,7 @@ nvim_cmd({*cmd}, {*opts}) *nvim_cmd()* nvim_command({command}) *nvim_command()* Executes an Ex command. - On execution error: fails with VimL error, does not update - v:errmsg. + On execution error: fails with VimL error, updates v:errmsg. Prefer using |nvim_cmd()| or |nvim_exec()| over this. To evaluate multiple lines of Vim script or an Ex command @@ -1798,8 +1809,7 @@ nvim_eval({expr}) *nvim_eval()* Evaluates a VimL |expression|. Dictionaries and Lists are recursively expanded. - On execution error: fails with VimL error, does not update - v:errmsg. + On execution error: fails with VimL error, updates v:errmsg. Parameters: ~ {expr} VimL expression string @@ -1814,8 +1824,7 @@ nvim_exec({src}, {output}) *nvim_exec()* Unlike |nvim_command()| this function supports heredocs, script-scope (s:), etc. - On execution error: fails with VimL error, does not update - v:errmsg. + On execution error: fails with VimL error, updates v:errmsg. Parameters: ~ {src} Vimscript code @@ -2656,13 +2665,12 @@ nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts}) nvim_buf_set_extmark({buffer}, {ns_id}, {line}, {col}, {*opts}) Creates or updates an extmark. - To create a new extmark, pass id=0. The extmark id will be - returned. To move an existing mark, pass its id. - - It is also allowed to create a new mark by passing in a - previously unused id, but the caller must then keep track of - existing and unused ids itself. (Useful over RPC, to avoid - waiting for the return value.) + By default a new extmark is created when no id is passed in, + but it is also possible to create a new mark by passing in a + previously unused id or move an existing mark by passing in + its id. The caller must then keep track of existing and unused + ids itself. (Useful over RPC, to avoid waiting for the return + value.) Using the optional arguments, it is possible to use this to highlight a range of text, and also to associate virtual text @@ -3469,6 +3477,8 @@ nvim_create_autocmd({event}, {*opts}) *nvim_create_autocmd()* • buf: (number) the expanded value of |<abuf>| • file: (string) the expanded value of |<afile>| + • data: (any) arbitrary data passed to + |nvim_exec_autocmds()| • command (string) optional: Vim command to execute on event. Cannot be used with @@ -3544,6 +3554,9 @@ nvim_exec_autocmds({event}, {*opts}) *nvim_exec_autocmds()* • modeline (bool) optional: defaults to true. Process the modeline after the autocommands |<nomodeline>|. + • data (any): arbitrary data to send to the + autocommand callback. See + |nvim_create_autocmd()| for details. See also: ~ |:doautocmd| diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index d197a2c62c..cb0b3d3aa6 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -1026,7 +1026,7 @@ chansend({id}, {data}) *chansend()* char2nr({string} [, {utf8}]) *char2nr()* - Return number value of the first char in {string}. + Return Number value of the first char in {string}. Examples: > char2nr(" ") returns 32 char2nr("ABC") returns 65 @@ -1313,13 +1313,13 @@ confirm({msg} [, {choices} [, {default} [, {type}]]]) An example: > let choice = confirm("What do you want?", - \ "&Apples\n&Oranges\n&Bananas", 2) + \ "&Apples\n&Oranges\n&Bananas", 2) if choice == 0 - echo "make up your mind!" + echo "make up your mind!" elseif choice == 3 - echo "tasteful" + echo "tasteful" else - echo "I prefer bananas myself." + echo "I prefer bananas myself." endif < In a GUI dialog, buttons are used. The layout of the buttons depends on the 'v' flag in 'guioptions'. If it is included, @@ -1894,8 +1894,8 @@ exists({expr}) The result is a Number, which is |TRUE| if {expr} is < There must be no space between the symbol (&/$/*/#) and the name. There must be no extra characters after the name, although in - a few cases this is ignored. That may become more strict in - the future, thus don't count on it! + a few cases this is ignored. That may become stricter in the + future, thus don't count on it! Working example: > exists(":make") < NOT working example: > @@ -2680,7 +2680,7 @@ getchar([expr]) *getchar()* Without [expr] and when [expr] is 0 a whole character or special key is returned. If it is a single character, the - result is a number. Use nr2char() to convert it to a String. + result is a Number. Use |nr2char()| to convert it to a String. Otherwise a String is returned with the encoded character. For a special key it's a String with a sequence of bytes starting with 0x80 (decimal: 128). This is the same value as @@ -7612,9 +7612,11 @@ strftime({format} [, {time}]) *strftime()* GetFormat()->strftime() strgetchar({str}, {index}) *strgetchar()* - Get character {index} from {str}. This uses a character - index, not a byte index. Composing characters are considered - separate characters here. + Get a Number corresponding to the character at {index} in + {str}. This uses a zero-based character index, not a byte + index. Composing characters are considered separate + characters here. Use |nr2char()| to convert the Number to a + String. Also see |strcharpart()| and |strchars()|. Can also be used as a |method|: > diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index 6228c9238f..23a87505ad 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -1065,8 +1065,7 @@ line contains the command as typed so far. The left column will show a character that indicates the type of command-line being edited, see |cmdwin-char|. -Vim will be in Normal mode when the editor is opened, except when 'insertmode' -is set. +Vim will be in Normal mode when the editor is opened. The height of the window is specified with 'cmdwinheight' (or smaller if there is no room). The window is always full width and is positioned just above the diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 13644cf208..e328bd28b5 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -106,11 +106,13 @@ internally and are no longer exposed as part of the API. Instead, use *vim.lsp.diagnostic.set_underline()* *vim.lsp.diagnostic.set_virtual_text()* -LSP Utility Functions ~ +LSP Functions ~ *vim.lsp.util.diagnostics_to_items()* Use |vim.diagnostic.toqflist()| instead. *vim.lsp.util.set_qflist()* Use |setqflist()| instead. *vim.lsp.util.set_loclist()* Use |setloclist()| instead. +*vim.lsp.buf_get_clients()* Use |vim.lsp.get_active_clients()| with + {buffer = bufnr} instead. Lua ~ *vim.register_keystroke_callback()* Use |vim.on_key()| instead. diff --git a/runtime/doc/dev_style.txt b/runtime/doc/dev_style.txt index 6f0b862d3f..a2ea1204b5 100644 --- a/runtime/doc/dev_style.txt +++ b/runtime/doc/dev_style.txt @@ -913,19 +913,9 @@ Don't use spaces inside parentheses. Always use curly braces. > ... } -You must have a space between the `if` and the open parenthesis. You must also -have a space between the close parenthesis and the curly brace, if you're -using one. > - - if(condition) { // BAD: space missing after IF. - if (condition){ // BAD: space missing before {. - if (condition) { // GOOD: proper space after IF and before {. - - Loops and Switch Statements ~ -Annotate non-trivial fall-through between cases. Empty loop bodies should use -`{}` or `continue`. +Annotate non-trivial fall-through between cases. If not conditional on an enumerated value, switch statements should always have a `default` case (in the case of an enumerated value, the compiler will @@ -943,16 +933,6 @@ execute, simply `assert`: > assert(false); } -Empty loop bodies should use `{}` or `continue`, but not a single semicolon. > - - while (condition) { - // Repeat test until it returns false. - } - for (int i = 0; i < kSomeNumber; i++) {} // GOOD: empty body. - while (condition) continue; // GOOD: continue indicates no logic. - - while (condition); // BAD: looks like part of do/while loop. - Pointer Expressions ~ No spaces around period or arrow. Pointer operators do not have trailing @@ -1009,37 +989,6 @@ expr;`. > return(result); // return is not a function! -Preprocessor Directives ~ - -The hash mark that starts a preprocessor directive should always be at the -beginning of the line. - -Even when preprocessor directives are within the body of indented code, the -directives should start at the beginning of the line. - -Nested directives should add one spaces after the hash mark for each level of -indentation. - - // GOOD: directives at beginning of line > - if (lopsided_score) { - #if DISASTER_PENDING // Correct -- Starts at beginning of line - drop_everything(); - # if NOTIFY // One space after # - notify_client(); - # endif - #endif - BackToNormal(); - } - -< // BAD: indented directives > - if (lopsided_score) { - #if DISASTER_PENDING // Wrong! The "#if" should be at beginning of line - drop_everything(); - #endif // Wrong! Do not indent "#endif" - back_to_normal(); - } - - Horizontal Whitespace ~ Use of horizontal whitespace depends on location. Never put trailing @@ -1070,14 +1019,6 @@ whitespace at the end of a line. }; < - Macros ~ -> - #define FI(x) \ // Don't align \'s in macro definitions. - foo(); \ - bar(); \ - ... -< - Loops and Conditionals ~ > if (b) { // Space after the keyword in condition. @@ -1111,12 +1052,6 @@ Vertical Whitespace ~ Minimize use of vertical whitespace. -This is more a principle than a rule: don't use blank lines when you don't -have to. In particular, don't put more than one or two blank lines between -functions, resist starting functions with a blank line, don't end functions -with a blank line, and be discriminating with your use of blank lines inside -functions. - The basic principle is: The more code that fits on one screen, the easier it is to follow and understand the control flow of the program. Of course, readability can suffer from code being too dense as well as too spread out, so diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index d1686741b4..71f5ad4536 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1366,7 +1366,7 @@ option *expr-option* *E112* *E113* Examples: > echo "tabstop is " .. &tabstop - if &insertmode + if &expandtab Any option name can be used here. See |options|. When using the local value and there is no buffer-local or window-local value, the global value is used diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt index 812259741f..e296141c39 100644 --- a/runtime/doc/gui.txt +++ b/runtime/doc/gui.txt @@ -224,9 +224,6 @@ some modes: Cmdline <C-C> <C-\><C-G> Op-pending <C-C> <C-\><C-G> -Appending CTRL-\ CTRL-G is for going back to insert mode when 'insertmode' is -set. |CTRL-\_CTRL-G| - Example: > :amenu File.Next :next^M diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index 5c36eaf8e5..ee8a820e53 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -26,7 +26,7 @@ tag char action in Insert mode ~ insert |i_CTRL-A| CTRL-A insert previously inserted text |i_CTRL-C| CTRL-C quit insert mode, without checking for - abbreviation, unless 'insertmode' set. + abbreviation |i_CTRL-D| CTRL-D delete one shiftwidth of indent in the current line |i_CTRL-E| CTRL-E insert the character which is below the cursor @@ -50,7 +50,6 @@ tag char action in Insert mode ~ |i_CTRL-J| CTRL-J same as <CR> |i_CTRL-K| CTRL-K {char1} {char2} enter digraph -|i_CTRL-L| CTRL-L when 'insertmode' set: Leave Insert mode |i_<CR>| <CR> begin new line |i_CTRL-M| CTRL-M same as <CR> |i_CTRL-N| CTRL-N find next match for keyword in front of the @@ -86,11 +85,10 @@ tag char action in Insert mode ~ |i_CTRL-W| CTRL-W delete word before the cursor |i_CTRL-X| CTRL-X {mode} enter CTRL-X sub mode, see |i_CTRL-X_index| |i_CTRL-Y| CTRL-Y insert the character which is above the cursor -|i_CTRL-Z| CTRL-Z when 'insertmode' set: suspend Vim -|i_<Esc>| <Esc> end insert mode (unless 'insertmode' set) +|i_<Esc>| <Esc> end insert mode |i_CTRL-[| CTRL-[ same as <Esc> |i_CTRL-\_CTRL-N| CTRL-\ CTRL-N go to Normal mode -|i_CTRL-\_CTRL-G| CTRL-\ CTRL-G go to mode specified with 'insertmode' +|i_CTRL-\_CTRL-G| CTRL-\ CTRL-G go to Normal mode CTRL-\ a - z reserved for extensions CTRL-\ others not used |i_CTRL-]| CTRL-] trigger abbreviation @@ -221,7 +219,7 @@ tag char note action in Normal mode ~ |CTRL-Z| CTRL-Z suspend program (or start new shell) CTRL-[ <Esc> not used |CTRL-\_CTRL-N| CTRL-\ CTRL-N go to Normal mode (no-op) -|CTRL-\_CTRL-G| CTRL-\ CTRL-G go to mode specified with 'insertmode' +|CTRL-\_CTRL-G| CTRL-\ CTRL-G go to Normal mode (no-op) CTRL-\ a - z reserved for extensions CTRL-\ others not used |CTRL-]| CTRL-] :ta to ident under cursor @@ -892,7 +890,7 @@ here are those that are different. tag command note action in Visual mode ~ ------------------------------------------------------------------------------ |v_CTRL-\_CTRL-N| CTRL-\ CTRL-N stop Visual mode -|v_CTRL-\_CTRL-G| CTRL-\ CTRL-G go to mode specified with 'insertmode' +|v_CTRL-\_CTRL-G| CTRL-\ CTRL-G go to Normal mode |v_CTRL-A| CTRL-A 2 add N to number in highlighted text |v_CTRL-C| CTRL-C stop Visual mode |v_CTRL-G| CTRL-G toggle between Visual mode and Select mode @@ -1068,8 +1066,7 @@ tag command action in Command-line editing mode ~ |c_<Esc>| <Esc> abandon command-line without executing it |c_CTRL-[| CTRL-[ same as <Esc> |c_CTRL-\_CTRL-N| CTRL-\ CTRL-N go to Normal mode, abandon command-line -|c_CTRL-\_CTRL-G| CTRL-\ CTRL-G go to mode specified with 'insertmode', - abandon command-line +|c_CTRL-\_CTRL-G| CTRL-\ CTRL-G go to Normal mode, abandon command-line CTRL-\ a - d reserved for extensions |c_CTRL-\_e| CTRL-\ e {expr} replace the command line with the result of {expr} @@ -1501,8 +1498,9 @@ tag command action ~ |:recover| :rec[over] recover a file from a swap file |:redo| :red[o] redo one undone change |:redir| :redi[r] redirect messages to a file or register -|:redraw| :redr[aw] force a redraw of the display -|:redrawstatus| :redraws[tatus] force a redraw of the status line(s) +|:redraw| :redr[aw] force a redraw of the display +|:redrawstatus| :redraws[tatus] force a redraw of the status line(s) and + window bar(s) |:redrawtabline| :redrawt[abline] force a redraw of the tabline |:registers| :reg[isters] display the contents of registers |:resize| :res[ize] change current window height diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index 7f6662089d..3c5d246a49 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -32,9 +32,6 @@ If you are working in a special language mode when inserting text, see the 'langmap' option, |'langmap'|, on how to avoid switching this mode on and off all the time. -If you have 'insertmode' set, <Esc> and a few other keys get another meaning. -See |'insertmode'|. - char action ~ ----------------------------------------------------------------------- *i_CTRL-[* *i_<Esc>* @@ -335,9 +332,8 @@ that key is interpreted as in Insert mode. The following keys are special. They stop the current insert, do something, and then restart insertion. This means you can do something without getting out of Insert mode. This is very handy if you prefer to use the Insert mode -all the time, just like editors that don't have a separate Normal mode. You -may also want to set the 'insertmode' option. You can use CTRL-O if you want -to map a function key to a command. +all the time, just like editors that don't have a separate Normal mode. You +can use CTRL-O if you want to map a function key to a command. The changes (inserted or deleted characters) before and after these keys can be undone separately. Only the last change can be redone and always behaves @@ -378,7 +374,6 @@ CTRL-G CTRL-J cursor one line down, insert start column *i_CTRL-G_CTRL-J* <S-ScrollWheelRight> move window one page right *i_<S-ScrollWheelRight>* CTRL-O execute one command, return to Insert mode *i_CTRL-O* CTRL-\ CTRL-O like CTRL-O but don't move the cursor *i_CTRL-\_CTRL-O* -CTRL-L when 'insertmode' is set: go to Normal mode *i_CTRL-L* CTRL-G u break undo sequence, start new change *i_CTRL-G_u* CTRL-G U don't break undo with next left/right cursor *i_CTRL-G_U* movement, if the cursor stays within the diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index 4e3dcf850c..0074dc0733 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -424,8 +424,7 @@ Vim has seven BASIC modes: *Normal* *Normal-mode* *command-mode* Normal mode In Normal mode you can enter all the normal editor commands. If you start the editor you are in this - mode (unless you have set the 'insertmode' option, - see below). This is also known as command mode. + mode. This is also known as command mode. Visual mode This is like Normal mode, but the movement commands extend a highlighted area. When a non-movement @@ -551,8 +550,6 @@ Ex :vi -- -- -- -- -- *6 Go from Select mode to Insert mode by typing a printable character. The selection is deleted and the character is inserted. -If the 'insertmode' option is on, editing a file will start in Insert mode. - *CTRL-\_CTRL-N* *i_CTRL-\_CTRL-N* *c_CTRL-\_CTRL-N* *v_CTRL-\_CTRL-N* Additionally the command CTRL-\ CTRL-N or <C-\><C-N> can be used to go to Normal mode from any other mode. This can be used to make sure Vim is in @@ -561,10 +558,7 @@ work in Ex mode. When used after a command that takes an argument, such as |f| or |m|, the timeout set with 'ttimeoutlen' applies. *CTRL-\_CTRL-G* *i_CTRL-\_CTRL-G* *c_CTRL-\_CTRL-G* *v_CTRL-\_CTRL-G* -The command CTRL-\ CTRL-G or <C-\><C-G> can be used to go to Insert mode when -'insertmode' is set. Otherwise it goes to Normal mode. This can be used to -make sure Vim is in the mode indicated by 'insertmode', without knowing in -what mode Vim currently is. +CTRL-\ CTRL-G works the same as |CTRL-\_CTRL-N| for backward compatibility. *gQ* *mode-Ex* *Ex-mode* *Ex* *EX* *E501* gQ Switch to Ex mode. This is like typing ":" commands diff --git a/runtime/doc/lsp.txt b/runtime/doc/lsp.txt index 569c570624..41f083687d 100644 --- a/runtime/doc/lsp.txt +++ b/runtime/doc/lsp.txt @@ -461,6 +461,39 @@ LspSignatureActiveParameter ============================================================================== EVENTS *lsp-events* + *LspAttach* +After an LSP client attaches to a buffer. The |autocmd-pattern| is the +name of the buffer. When used from Lua, the client ID is passed to the +callback in the "data" table. Example: > + + vim.api.nvim_create_autocmd("LspAttach", { + callback = function(args) + local bufnr = args.buf + local client = vim.lsp.get_client_by_id(args.data.client_id) + if client.server_capabilities.completionProvider then + vim.bo[bufnr].omnifunc = "v:lua.vim.lsp.omnifunc" + end + if client.server_capabilities.definitionProvider then + vim.bo[bufnr].tagfunc = "v:lua.vim.lsp.tagfunc" + end + end, + }) +< + *LspDetach* +Just before an LSP client detaches from a buffer. The |autocmd-pattern| is the +name of the buffer. When used from Lua, the client ID is passed to the +callback in the "data" table. Example: > + + vim.api.nvim_create_autocmd("LspDetach", { + callback = function(args) + local client = vim.lsp.get_client_by_id(args.data.client_id) + -- Do something with the client + vim.cmd("setlocal tagfunc< omnifunc<") + end, + }) +< +In addition, the following |User| |autocommands| are provided: + LspProgressUpdate *LspProgressUpdate* Upon receipt of a progress notification from the server. See |vim.lsp.util.get_progress_messages()|. @@ -498,14 +531,6 @@ buf_detach_client({bufnr}, {client_id}) *vim.lsp.buf_detach_client()* {bufnr} (number) Buffer handle, or 0 for current {client_id} (number) Client id -buf_get_clients({bufnr}) *vim.lsp.buf_get_clients()* - Gets a map of client_id:client pairs for the given buffer, - where each value is a |vim.lsp.client| object. - - Parameters: ~ - {bufnr} (optional, number): Buffer handle, or 0 for - current - buf_is_attached({bufnr}, {client_id}) *vim.lsp.buf_is_attached()* Checks if a buffer is attached for a particular client. @@ -696,11 +721,22 @@ formatexpr({opts}) *vim.lsp.formatexpr()* • timeout_ms (default 500ms). The timeout period for the formatting request. -get_active_clients() *vim.lsp.get_active_clients()* - Gets all active clients. +get_active_clients({filter}) *vim.lsp.get_active_clients()* + Get active clients. + + Parameters: ~ + {filter} (table|nil) A table with key-value pairs used to + filter the returned clients. The available keys + are: + • id (number): Only return clients with the + given id + • bufnr (number): Only return clients attached + to this buffer + • name (string): Only return clients with the + given name Return: ~ - Table of |vim.lsp.client| objects + (table) List of |vim.lsp.client| objects *vim.lsp.get_buffers_by_client_id()* get_buffers_by_client_id({client_id}) @@ -1015,15 +1051,25 @@ completion({context}) *vim.lsp.buf.completion()* See also: ~ |vim.lsp.protocol.constants.CompletionTriggerKind| -declaration() *vim.lsp.buf.declaration()* +declaration({options}) *vim.lsp.buf.declaration()* Jumps to the declaration of the symbol under the cursor. Note: Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. -definition() *vim.lsp.buf.definition()* + Parameters: ~ + {options} (table|nil) additional options + • reuse_win: (boolean) Jump to existing window + if buffer is already open. + +definition({options}) *vim.lsp.buf.definition()* Jumps to the definition of the symbol under the cursor. + Parameters: ~ + {options} (table|nil) additional options + • reuse_win: (boolean) Jump to existing window + if buffer is already open. + document_highlight() *vim.lsp.buf.document_highlight()* Send request to the server to resolve document highlights for the current text document position. This request can be @@ -1074,19 +1120,13 @@ format({options}) *vim.lsp.buf.format()* • bufnr (number|nil): Restrict formatting to the clients attached to the given buffer, defaults to the current buffer (0). - • filter (function|nil): Predicate to filter clients used - for formatting. Receives the list of clients attached to - bufnr as the argument and must return the list of - clients on which to request formatting. Example: • > + • filter (function|nil): Predicate used to filter clients. + Receives a client as argument and must return a boolean. + Clients matching the predicate are included. Example: • > -- Never request typescript-language-server for formatting vim.lsp.buf.format { - filter = function(clients) - return vim.tbl_filter( - function(client) return client.name ~= "tsserver" end, - clients - ) - end + filter = function(client) return client.name ~= "tsserver" end } < • async boolean|nil If true the method won't block. @@ -1231,10 +1271,10 @@ rename({new_name}, {options}) *vim.lsp.buf.rename()* prompted for a new name using |vim.ui.input()|. {options} (table|nil) additional options - • filter (function|nil): Predicate to filter - clients used for rename. Receives the - attached clients as argument and must return - a list of clients. + • filter (function|nil): Predicate used to + filter clients. Receives a client as + argument and must return a boolean. Clients + matching the predicate are included. • name (string|nil): Restrict clients used for rename to ones where client.name matches this field. @@ -1250,10 +1290,15 @@ signature_help() *vim.lsp.buf.signature_help()* Displays signature information about the symbol under the cursor in a floating window. -type_definition() *vim.lsp.buf.type_definition()* +type_definition({options}) *vim.lsp.buf.type_definition()* Jumps to the definition of the type of the symbol under the cursor. + Parameters: ~ + {options} (table|nil) additional options + • reuse_win: (boolean) Jump to existing window + if buffer is already open. + workspace_symbol({query}) *vim.lsp.buf.workspace_symbol()* Lists all symbols in the current workspace in the quickfix window. @@ -1539,12 +1584,14 @@ get_effective_tabstop({bufnr}) *vim.lsp.util.get_effective_tabstop()* |shiftwidth| *vim.lsp.util.jump_to_location()* -jump_to_location({location}, {offset_encoding}) +jump_to_location({location}, {offset_encoding}, {reuse_win}) Jumps to a location. Parameters: ~ {location} (table) (`Location`|`LocationLink`) {offset_encoding} (string) utf-8|utf-16|utf-32 (required) + {reuse_win} (boolean) Jump to existing window if + buffer is already opened. Return: ~ `true` if the jump succeeded diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index 056e6c3b56..98da68b76a 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -796,9 +796,8 @@ command. For example: > :noremap j k This will exchange the cursor up and down commands. -With the normal :map command, when the 'remap' option is on, mapping takes -place until the text is found not to be a part of a {lhs}. For example, if -you use: > +With the normal :map command mapping takes place until the text is found not +to be a part of a {lhs}. For example, if you use: > :map x y :map y x Vim will replace x with y, and then y with x, etc. When this has happened diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt index 49e29111c6..b19343e7ef 100644 --- a/runtime/doc/nvim_terminal_emulator.txt +++ b/runtime/doc/nvim_terminal_emulator.txt @@ -304,7 +304,7 @@ breakpoint, or use the "Clear breakpoint" right-click menu entry. Inspecting variables ~ *termdebug-variables* *:Evaluate* `:Evaluate` evaluate the expression under the cursor - `K` same + `K` same (see |termdebug_map_K| to disable) `:Evaluate` {expr} evaluate {expr} `:'<,'>Evaluate` evaluate the Visually selected text @@ -333,7 +333,7 @@ Four autocommands can be used: > *TermdebugStartPre* TermdebugStartPre Before starting debugging. Not triggered if the debugger is already - running or |g:termdebugger| cannot be + running or the debugger command cannot be executed. *TermdebugStartPost* TermdebugStartPost After debugging has initialized. @@ -362,14 +362,24 @@ This works slightly differently: *termdebug_use_prompt* Prompt mode can be used with: > + let g:termdebug_config['use_prompt'] = 1 +Or if there is no g:termdebug_config: > let g:termdebug_use_prompt = 1 - +< + *termdebug_map_K* +The K key is normally mapped to :Evaluate. If you do not want this use: > + let g:termdebug_config['map_K'] = 0 +Or if there is no g:termdebug_config: > + let g:termdebug_map_K = 0 < *termdebug_disasm_window* -If you want the Asm window shown by default, set this to 1. Setting to -any value greater than 1 will set the Asm window height to that value: > +If you want the Asm window shown by default, set the flag to 1. +the "disasm_window_height" entry can be used to set the window height: > + let g:termdebug_config['disasm_window'] = 1 + let g:termdebug_config['disasm_window_height'] = 15 +or, if there is no g:termdebug_config: > let g:termdebug_disasm_window = 15 -< +Any value greater than 1 will set the Asm window height to that value: > Communication ~ *termdebug-communication* @@ -386,13 +396,24 @@ communication channel. Customizing ~ + *termdebug-customizing* *g:termdebug_config* +In the past several global variables were used for configuration. These are +deprecated, using the g:termdebug_config dictionary is preferred. When +g:termdebug_config exists the other global variables will not be used. -GDB command *termdebug-customizing* -To change the name of the gdb command, set the "termdebugger" variable before -invoking `:Termdebug`: > - let termdebugger = "mygdb" +GDB command ~ + *g:termdebugger* +To change the name of the gdb command, set "debugger" entry in +g:termdebug_config or the "g:termdebugger" variable before invoking +`:Termdebug`: > + let g:termdebug_config['command'] = "mygdb" +Or if there is no g:termdebug_config: > + let g:termdebugger = "mygdb" + If the command needs an argument use a List: > + let g:termdebug_config['command'] = ['rr', 'replay', '--'] +Or if there is no g:termdebug_config: > let g:termdebugger = ['rr', 'replay', '--'] To not use neovim floating windows for previewing variable evaluation, set the @@ -406,7 +427,17 @@ cursor: > or set/unset a breakpoint: > nnoremap <RightMouse> :Break<CR> -< *gdb-version* + +Several arguments will be added to make gdb work well for the debugger. +If you want to modify them, add a function to filter the argument list: > + let g:termdebug_config['command_filter'] = MyDebugFilter + +If you do not want the arguments to be added, but you do need to set the +"pty", use a function to add the necessary arguments: > + let g:termdebug_config['command_add_args'] = MyAddArguments +The function will be called with the list of arguments so far, and a second +argument that is the name of the pty. + *gdb-version* Only debuggers fully compatible with gdb will work. Vim uses the GDB/MI interface. The "new-ui" command requires gdb version 7.12 or later. if you get this error: @@ -414,8 +445,8 @@ get this error: Then your gdb is too old. -Colors *hl-debugPC* *hl-debugBreakpoint* - +Colors~ + *hl-debugPC* *hl-debugBreakpoint* The color of the signs can be adjusted with these highlight groups: - debugPC the current position - debugBreakpoint a breakpoint @@ -439,16 +470,20 @@ The argument is the gdb command. Vim window width *termdebug_wide* -To change the width of the Vim window when debugging starts, and use a -vertical split: > - let g:termdebug_wide = 163 -This will set &columns to 163 when `:Termdebug` is used. The value is restored -when quitting the debugger. -If g:termdebug_wide is set and &columns is already larger than -g:termdebug_wide then a vertical split will be used without changing &columns. -Set it to 1 to get a vertical split without every changing &columns (useful -for when the terminal can't be resized by Vim). +To change the width of the Vim window when debugging starts and use a vertical +split: > + let g:termdebug_config['wide'] = 163 +Or if there is no g:termdebug_config: > + let g:termdebug_wide = 163 + +This will set 'columns' to 163 when `:Termdebug` is used. The value is +restored when quitting the debugger. + +If the wide value is set and 'columns' is already a greater value, then a +vertical split will be used without modifying 'columns'. +Set the wide value to 1 to use a vertical split without ever changing +'columns'. This is useful when the terminal can't be resized by Vim. vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 4d6f589714..77aa294027 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -776,7 +776,7 @@ A jump table for the options with a short description can be found at |Q_op|. oldest version of a file. *'backupcopy'* *'bkc'* -'backupcopy' 'bkc' string (Vi default for Unix: "yes", otherwise: "auto") +'backupcopy' 'bkc' string (default: "auto") global or local to buffer |global-local| When writing a file and a backup is made, this option tells how it's done. This is a comma-separated list of words. @@ -959,7 +959,6 @@ A jump table for the options with a short description can be found at |Q_op|. (mostly used in |Normal-mode| or |Cmdline-mode|). esc hitting <Esc> in |Normal-mode|. hangul Ignored. - insertmode Pressing <Esc> in 'insertmode'. lang Calling the beep module for Lua/Mzscheme/TCL. mess No output available for |g<|. showmatch Error occurred for 'showmatch' function. @@ -1192,7 +1191,7 @@ A jump table for the options with a short description can be found at |Q_op|. (parts of 'cdpath' can be passed to the shell to expand file names). *'cedit'* -'cedit' string (Vim default: CTRL-F, Vi default: "") +'cedit' string (default: CTRL-F) global The key used in Command-line Mode to open the command-line window. Only non-printable keys are allowed. @@ -1291,8 +1290,6 @@ A jump table for the options with a short description can be found at |Q_op|. *'cinscopedecls'* *'cinsd'* 'cinscopedecls' 'cinsd' string (default "public,protected,private") local to buffer - {not available when compiled without the |+cindent| - feature} Keywords that are interpreted as a C++ scope declaration by |cino-g|. Useful e.g. for working with the Qt framework that defines additional scope declarations "signals", "public slots" and "private slots": > @@ -1545,8 +1542,7 @@ A jump table for the options with a short description can be found at |Q_op|. See 'preserveindent'. *'cpoptions'* *'cpo'* *cpo* -'cpoptions' 'cpo' string (Vim default: "aABceFs_", - Vi default: all flags) +'cpoptions' 'cpo' string (default: "aABceFs_") global A sequence of single character flags. When a character is present this indicates Vi-compatible behavior. This is used for things where @@ -2115,7 +2111,7 @@ A jump table for the options with a short description can be found at |Q_op|. security reasons. *'display'* *'dy'* -'display' 'dy' string (default "lastline,msgsep", Vi default: "") +'display' 'dy' string (default "lastline,msgsep") global Change the way text is displayed. This is comma-separated list of flags: @@ -2361,9 +2357,8 @@ A jump table for the options with a short description can be found at |Q_op|. *'fileformats'* *'ffs'* 'fileformats' 'ffs' string (default: - Vim+Vi Win32: "dos,unix", - Vim Unix: "unix,dos", - Vi others: "") + Win32: "dos,unix", + Unix: "unix,dos") global This gives the end-of-line (<EOL>) formats that will be tried when starting to edit a new buffer and when reading a file into an existing @@ -2452,6 +2447,7 @@ A jump table for the options with a short description can be found at |Q_op|. item default Used for ~ stl:c ' ' or '^' statusline of the current window stlnc:c ' ' or '=' statusline of the non-current windows + wbr:c ' ' window bar horiz:c '─' or '-' horizontal separators |:split| horizup:c '┴' or '-' upwards facing horizontal separator horizdown:c '┬' or '-' downwards facing horizontal separator @@ -2492,6 +2488,7 @@ A jump table for the options with a short description can be found at |Q_op|. item highlight group ~ stl:c StatusLine |hl-StatusLine| stlnc:c StatusLineNC |hl-StatusLineNC| + wbr:c WinBar |hl-WinBar| or |hl-WinBarNC| horiz:c WinSeparator |hl-WinSeparator| horizup:c WinSeparator |hl-WinSeparator| horizdown:c WinSeparator |hl-WinSeparator| @@ -2719,7 +2716,7 @@ A jump table for the options with a short description can be found at |Q_op|. character and white space. *'formatoptions'* *'fo'* -'formatoptions' 'fo' string (default: "tcqj", Vi default: "vt") +'formatoptions' 'fo' string (default: "tcqj") local to buffer This is a sequence of letters which describes how automatic formatting is to be done. See |fo-table|. When the 'paste' option is @@ -3151,7 +3148,7 @@ A jump table for the options with a short description can be found at |Q_op|. 'hidden' is set for one command with ":hide {command}" |:hide|. *'history'* *'hi'* -'history' 'hi' number (Vim default: 10000, Vi default: 0) +'history' 'hi' number (default: 10000) global A history of ":" commands, and a history of previous search patterns is remembered. This option decides how many entries may be stored in @@ -3414,31 +3411,6 @@ A jump table for the options with a short description can be found at |Q_op|. and there is a letter before it, the completed part is made uppercase. With 'noinfercase' the match is used as-is. - *'insertmode'* *'im'* *'noinsertmode'* *'noim'* -'insertmode' 'im' boolean (default off) - global - Makes Vim work in a way that Insert mode is the default mode. Useful - if you want to use Vim as a modeless editor. - These Insert mode commands will be useful: - - Use the cursor keys to move around. - - Use CTRL-O to execute one Normal mode command |i_CTRL-O|. When - this is a mapping, it is executed as if 'insertmode' was off. - Normal mode remains active until the mapping is finished. - - Use CTRL-L to execute a number of Normal mode commands, then use - <Esc> to get back to Insert mode. Note that CTRL-L moves the cursor - left, like <Esc> does when 'insertmode' isn't set. |i_CTRL-L| - - These items change when 'insertmode' is set: - - when starting to edit of a file, Vim goes to Insert mode. - - <Esc> in Insert mode is a no-op and beeps. - - <Esc> in Normal mode makes Vim go to Insert mode. - - CTRL-L in Insert mode is a command, it is not inserted. - - CTRL-Z in Insert mode suspends Vim, see |CTRL-Z|. *i_CTRL-Z* - However, when <Esc> is used inside a mapping, it behaves like - 'insertmode' was not set. This was done to be able to use the same - mappings with 'insertmode' set or not set. - When executing commands with |:normal| 'insertmode' is not used. - *'isfname'* *'isf'* 'isfname' 'isf' string (default for Windows: "@,48-57,/,\,.,-,_,+,,,#,$,%,{,},[,],:,@-@,!,~,=" @@ -3506,8 +3478,7 @@ A jump table for the options with a short description can be found at |Q_op|. change 'iskeyword' instead. *'iskeyword'* *'isk'* -'iskeyword' 'isk' string (default: @,48-57,_,192-255 - Vi default: @,48-57,_) +'iskeyword' 'isk' string (default: @,48-57,_,192-255) local to buffer Keywords are used in searching and recognizing with many commands: "w", "*", "[i", etc. It is also used for "\k" in a |pattern|. See @@ -3777,8 +3748,7 @@ A jump table for the options with a short description can be found at |Q_op|. changing the way tabs are displayed. *'listchars'* *'lcs'* -'listchars' 'lcs' string (default: "tab:> ,trail:-,nbsp:+" - Vi default: "eol:$") +'listchars' 'lcs' string (default: "tab:> ,trail:-,nbsp:+") global or local to window |global-local| Strings to use in 'list' mode and for the |:list| command. It is a comma-separated list of string settings. @@ -4046,8 +4016,7 @@ A jump table for the options with a short description can be found at |Q_op|. This option cannot be set from a |modeline| or in the |sandbox|. *'modeline'* *'ml'* *'nomodeline'* *'noml'* -'modeline' 'ml' boolean (Vim default: on (off for root), - Vi default: off) +'modeline' 'ml' boolean (default: on (off for root)) local to buffer If 'modeline' is on 'modelines' gives the number of lines that is checked for set commands. If 'modeline' is off or 'modelines' is zero @@ -4102,7 +4071,7 @@ A jump table for the options with a short description can be found at |Q_op|. when using "rA" on an "A". *'more'* *'nomore'* -'more' boolean (Vim default: on, Vi default: off) +'more' boolean (default: on) global When on, listings pause when the whole screen is filled. You will get the |more-prompt|. When this option is off there are no pauses, the @@ -4357,7 +4326,7 @@ A jump table for the options with a short description can be found at |Q_op|. |there | 4 there | 1 there | 1 there *'numberwidth'* *'nuw'* -'numberwidth' 'nuw' number (Vim default: 4 Vi default: 8) +'numberwidth' 'nuw' number (default: 4) local to window Minimal number of columns to use for the line number. Only relevant when the 'number' or 'relativenumber' option is set or printing lines @@ -4798,15 +4767,6 @@ A jump table for the options with a short description can be found at |Q_op|. 'number', see |number_relativenumber| for all combinations of the two options. - *'remap'* *'noremap'* -'remap' boolean (default on) - global - Allows for mappings to work recursively. If you do not want this for - a single entry, use the :noremap[!] command. - NOTE: To avoid portability problems with Vim scripts, always keep - this option at the default "on". Only switch it off when working with - old Vi scripts. - *'report'* 'report' number (default 2) global @@ -5122,9 +5082,7 @@ A jump table for the options with a short description can be found at |Q_op|. *'sessionoptions'* *'ssop'* 'sessionoptions' 'ssop' string (default: "blank,buffers,curdir,folds, - help,tabpages,winsize" - Vi default: "blank,buffers,curdir,folds, - help,options,tabpages,winsize") + help,tabpages,winsize") global Changes the effect of the |:mksession| command. It is a comma- separated list of words. Each word enables saving and restoring @@ -5164,10 +5122,9 @@ A jump table for the options with a short description can be found at |Q_op|. If you leave out "options" many things won't work well after restoring the session. *'shada'* *'sd'* *E526* *E527* *E528* -'shada' 'sd' string (Vim default for +'shada' 'sd' string (default for Win32: !,'100,<50,s10,h,rA:,rB: - others: !,'100,<50,s10,h - Vi default: "") + others: !,'100,<50,s10,h) global When non-empty, the shada file is read upon startup and written when exiting Vim (see |shada-file|). The string should be a comma- @@ -5445,7 +5402,7 @@ A jump table for the options with a short description can be found at |Q_op|. < Also see 'completeslash'. *'shelltemp'* *'stmp'* *'noshelltemp'* *'nostmp'* -'shelltemp' 'stmp' boolean (Vim default on, Vi default off) +'shelltemp' 'stmp' boolean (default on) global When on, use temp files for shell commands. When off use a pipe. When using a pipe is not possible temp files are used anyway. @@ -5494,7 +5451,7 @@ A jump table for the options with a short description can be found at |Q_op|. function to get the effective shiftwidth value. *'shortmess'* *'shm'* -'shortmess' 'shm' string (Vim default "filnxtToOF", Vi default: "S") +'shortmess' 'shm' string (default "filnxtToOF") global This option helps to avoid all the |hit-enter| prompts caused by file messages, for example with CTRL-G, and to avoid some other messages. @@ -5568,7 +5525,7 @@ A jump table for the options with a short description can be found at |Q_op|. :setlocal showbreak=NONE < *'showcmd'* *'sc'* *'noshowcmd'* *'nosc'* -'showcmd' 'sc' boolean (Vim default: on, Vi default: off) +'showcmd' 'sc' boolean (default: on) global Show (partial) command in the last line of the screen. Set this option off if your terminal is slow. @@ -5614,7 +5571,7 @@ A jump table for the options with a short description can be found at |Q_op|. Note: Use of the short form is rated PG. *'showmode'* *'smd'* *'noshowmode'* *'nosmd'* -'showmode' 'smd' boolean (Vim default: on, Vi default: off) +'showmode' 'smd' boolean (default: on) global If in Insert, Replace or Visual mode put a message on the last line. The |hl-ModeMsg| highlight group determines the highlighting. @@ -6052,7 +6009,7 @@ A jump table for the options with a short description can be found at |Q_op|. the label, e.g.: %3Xclose%X. Use %999X for a "close current tab" label. Clicking this label with left mouse button closes specified tab page. - @ N For 'tabline': start of execute function label. Use %X or %T to + @ N Start of execute function label. Use %X or %T to end the label, e.g.: %10@SwitchBuffer@foo.c%X. Clicking this label runs specified function: in the example when clicking once using left mouse button on "foo.c" "SwitchBuffer(10, 1, 'l', @@ -6076,8 +6033,6 @@ A jump table for the options with a short description can be found at |Q_op|. is a bug that denotes that new mouse button recognition was added without modifying code that reacts on mouse clicks on this label. - Note: to test whether your version of Neovim contains this - feature use `has('tablineat')`. < - Where to truncate line if too long. Default is at the start. No width fields allowed. = - Separation point between alignment sections. Each section will @@ -6398,7 +6353,7 @@ A jump table for the options with a short description can be found at |Q_op|. If non-zero, tags are significant up to this number of characters. *'tagrelative'* *'tr'* *'notagrelative'* *'notr'* -'tagrelative' 'tr' boolean (Vim default: on, Vi default: off) +'tagrelative' 'tr' boolean (default: on) global If on and using a tags file in another directory, file names in that tags file are relative to the directory where the tags file is. @@ -6478,13 +6433,6 @@ A jump table for the options with a short description can be found at |Q_op|. C1 Control characters 0x80...0x9F - *'terse'* *'noterse'* -'terse' boolean (default off) - global - When set: Add 's' flag to 'shortmess' option (this makes the message - for a search that hits the start or end of the file not being - displayed). When reset: Remove 's' flag from 'shortmess' option. - *'textwidth'* *'tw'* 'textwidth' 'tw' number (default 0) local to buffer @@ -6853,7 +6801,7 @@ A jump table for the options with a short description can be found at |Q_op|. has been changed. *'whichwrap'* *'ww'* -'whichwrap' 'ww' string (Vim default: "b,s", Vi default: "") +'whichwrap' 'ww' string (default: "b,s") global Allow specified keys that move the cursor left/right to move to the previous/next line when the cursor is on the first/last character in @@ -6883,7 +6831,7 @@ A jump table for the options with a short description can be found at |Q_op|. makes "dl", "cl", "yl" etc. work normally. *'wildchar'* *'wc'* -'wildchar' 'wc' number (Vim default: <Tab>, Vi default: CTRL-E) +'wildchar' 'wc' number (default: <Tab>) global Character you have to type to start wildcard expansion in the command-line, as specified with 'wildmode'. @@ -7045,6 +6993,19 @@ A jump table for the options with a short description can be found at |Q_op|. key is never used for the menu. This option is not used for <F10>; on Win32. + *'winbar'* *'wbr'* +'winbar' 'wbr' string (default empty) + global or local to window |global-local| + When non-empty, this option enables the window bar and determines its + contents. The window bar is a bar that's shown at the top of every + window with it enabled. The value of 'winbar' is evaluated like with + 'statusline'. + + When changing something that is used in 'winbar' that does not trigger + it to be updated, use |:redrawstatus|. + + This option cannot be set in a modeline when 'modelineexpr' is off. + *'winblend'* *'winbl'* 'winblend' 'winbl' number (default 0) local to window @@ -7186,7 +7147,7 @@ A jump table for the options with a short description can be found at |Q_op|. starts. When typing text beyond this limit, an <EOL> will be inserted and inserting continues on the next line. Options that add a margin, such as 'number' and 'foldcolumn', cause - the text width to be further reduced. This is Vi compatible. + the text width to be further reduced. When 'textwidth' is non-zero, this option is not used. See also 'formatoptions' and |ins-textwidth|. diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index 961d734bfe..1716ea025d 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -741,7 +741,6 @@ Short explanation of each option: *option-list* 'indentexpr' 'inde' expression used to obtain the indent of a line 'indentkeys' 'indk' keys that trigger indenting with 'indentexpr' 'infercase' 'inf' adjust case of match for keyword completion -'insertmode' 'im' start the edit of a file in Insert mode 'isfname' 'isf' characters included in file names and pathnames 'isident' 'isi' characters included in identifiers 'iskeyword' 'isk' characters included in keywords @@ -824,7 +823,6 @@ Short explanation of each option: *option-list* 'redrawtime' 'rdt' timeout for 'hlsearch' and |:match| highlighting 'regexpengine' 're' default regexp engine to use 'relativenumber' 'rnu' show relative line number in front of each line -'remap' allow mappings to work recursively 'report' threshold for reporting nr. of lines changed 'revins' 'ri' inserting characters will work backwards 'rightleft' 'rl' window is right-to-left oriented @@ -896,7 +894,6 @@ Short explanation of each option: *option-list* 'tagstack' 'tgst' push tags onto the tag stack 'term' name of the terminal 'termbidi' 'tbidi' terminal takes care of bi-directionality -'terse' shorten some messages 'textwidth' 'tw' maximum width of text that is being inserted 'thesaurus' 'tsr' list of thesaurus files for keyword completion 'thesaurusfunc' 'tsrfu' function to be used for thesaurus completion diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index f542f33451..8b88fa9363 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -527,7 +527,6 @@ accordingly, proceeding as follows: 16. Execute startup commands If a |-t| flag was given, the tag is jumped to. Commands given with |-c| and |+cmd| are executed. - If the 'insertmode' option is set, Insert mode is entered. The starting flag is reset, has("vim_starting") will now return zero. The |v:vim_did_enter| variable is set to 1. The |VimEnter| autocommands are executed. diff --git a/runtime/doc/syntax.txt b/runtime/doc/syntax.txt index 0aceb30ce0..4122f4ad9c 100644 --- a/runtime/doc/syntax.txt +++ b/runtime/doc/syntax.txt @@ -1476,7 +1476,7 @@ modes Conditional, Number, Statement, Comment, PreProc, Type, and String, following the language specifications in 'Symbolic Manipulation with FORM' by J.A.M. Vermaseren, CAN, Netherlands, 1991. -If you want include your own changes to the default colors, you have to +If you want to include your own changes to the default colors, you have to redefine the following syntax groups: - formConditional @@ -5244,6 +5244,10 @@ Whitespace "nbsp", "space", "tab", "multispace", "lead" and "trail" in 'listchars'. *hl-WildMenu* WildMenu Current match in 'wildmenu' completion. + *hl-WinBar* +WinBar Window bar of current window. + *hl-WinBarNC* +WinBarNC Window bar of not-current windows. *hl-User1* *hl-User1..9* *hl-User9* The 'statusline' syntax allows the use of 9 different highlights in the diff --git a/runtime/doc/treesitter.txt b/runtime/doc/treesitter.txt index bc264bd971..339ae0c2ed 100644 --- a/runtime/doc/treesitter.txt +++ b/runtime/doc/treesitter.txt @@ -616,8 +616,6 @@ LanguageTree:children({self}) *LanguageTree:children()* LanguageTree:contains({self}, {range}) *LanguageTree:contains()* Determines whether {range} is contained in this language tree - This goes down the tree to recursively check children. - Parameters: ~ {range} A range, that is a `{ start_line, start_col, end_line, end_col }` table. diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 75ee0fdfdf..562faeaa2c 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -30,10 +30,10 @@ CTRL-L Clears and redraws the screen. The redraw may happen function (or a mapping if 'lazyredraw' set). *:redraws* *:redrawstatus* -:redraws[tatus][!] Redraws the status line of the current window, or all - status lines if "!" is included. - Useful if 'statusline' includes an item that doesn't - cause automatic updating. +:redraws[tatus][!] Redraws the status line and window bar of the current + window, or all status lines and window bars if "!" is + included. Useful if 'statusline' or 'winbar' includes + an item that doesn't cause automatic updating. *:redrawt* *:redrawtabline* :redrawt[abline] Redraw the tabline. Useful to update the tabline when @@ -208,8 +208,6 @@ g8 Print the hex values of the bytes used in the {commands} cannot start with a space. Put a count of 1 (one) before it, "1 " is one space. - The 'insertmode' option is ignored for {commands}. - This command cannot be followed by another command, since any '|' is considered part of the command. diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index fc98331697..85b44e3b51 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -543,16 +543,25 @@ Options: *'imactivatefunc'* *'imaf'* *'imactivatekey'* *'imak'* *'imstatusfunc'* *'imsf'* + *'insertmode'* *'im'* Use the following script to emulate 'insertmode': +> + autocmd VimEnter,CmdlineLeave,WinEnter,WinScrolled,BufEnter * silent! if &modifiable | startinsert | endif + inoremap <Esc> <Nop> + inoremap <C-L> <Esc> + nnoremap <Esc> i +< *'macatsui'* 'maxmem' Nvim delegates memory-management to the OS. 'maxmemtot' Nvim delegates memory-management to the OS. 'maxcombine' (6 is always used) *'prompt'* *'noprompt'* + *'remap'* *'noremap'* *'restorescreen'* *'rs'* *'norestorescreen'* *'nors'* 'shelltype' *'shortname'* *'sn'* *'noshortname'* *'nosn'* *'swapsync'* *'sws'* *'termencoding'* *'tenc'* (Vim 7.4.852 also removed this for Windows) + *'terse'* *'noterse'* (Add "s" to 'shortmess' instead) 'textauto' 'textmode' *'toolbar'* *'tb'* diff --git a/runtime/filetype.vim b/runtime/filetype.vim index b8f40bbef0..c73f5f6cb7 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -405,7 +405,7 @@ au BufNewFile,BufRead *.cu,*.cuh setf cuda " Dockerfile; Podman uses the same syntax with name Containerfile " Also see Dockerfile.* below. -au BufNewFile,BufRead Containerfile,Dockerfile,*.Dockerfile setf dockerfile +au BufNewFile,BufRead Containerfile,Dockerfile,dockerfile,*.[dD]ockerfile setf dockerfile " WildPackets EtherPeek Decoder au BufNewFile,BufRead *.dcd setf dcd @@ -815,6 +815,9 @@ au BufNewFile,BufRead *.hjson setf hjson " Hollywood au BufRead,BufNewFile *.hws setf hollywood +" Hoon +au BufRead,BufNewFile *.hoon setf hoon + " Tilde (must be before HTML) au BufNewFile,BufRead *.t.html setf tilde @@ -1168,6 +1171,9 @@ au BufNewFile,BufRead *.isc,*.monk,*.ssc,*.tsc setf monk " MOO au BufNewFile,BufRead *.moo setf moo +" Moonscript +au BufNewFile,BufRead *.moon setf moonscript + " Modconf au BufNewFile,BufRead */etc/modules.conf,*/etc/modules,*/etc/conf.modules setf modconf diff --git a/runtime/ftplugin/spec.vim b/runtime/ftplugin/spec.vim index ce00021a69..9040e19ce1 100644 --- a/runtime/ftplugin/spec.vim +++ b/runtime/ftplugin/spec.vim @@ -3,6 +3,7 @@ " Maintainer: Igor Gnatenko i.gnatenko.brain@gmail.com " Former Maintainer: Gustavo Niemeyer <niemeyer@conectiva.com> (until March 2014) " Last Change: Mon Jun 01 21:15 MSK 2015 Igor Gnatenko +" Update by Zdenek Dohnal, 2022 May 17 if exists("b:did_ftplugin") finish @@ -41,8 +42,8 @@ else: headers = spec.sourceHeader version = headers["Version"] release = headers["Release"] - vim.command("let ver = " + version) - vim.command("let rel = " + release) + vim.command("let ver = '" + version + "'") + vim.command("let rel = '" + release + "'") PYEND endif endfunction diff --git a/runtime/indent/fortran.vim b/runtime/indent/fortran.vim index 26ed33a54d..9623014818 100644 --- a/runtime/indent/fortran.vim +++ b/runtime/indent/fortran.vim @@ -1,13 +1,13 @@ " Vim indent file " Language: Fortran 2008 (and older: Fortran 2003, 95, 90, and 77) -" Version: (v48) 2020 October 07 -" Maintainer: Ajit J. Thakkar <ajit@unb.ca>; <http://www2.unb.ca/~ajit/> +" Version: (v49) 2022 May 14 +" Maintainer: Ajit J. Thakkar <thakkar.ajit@gmail.com>; <http://www2.unb.ca/~ajit/> " Usage: For instructions, do :help fortran-indent from Vim " Credits: " Version 0.1 was created in September 2000 by Ajit Thakkar. " Since then, useful suggestions and contributions have been made, in order, by: " Albert Oliver Serra, Takuya Fujiwara, Philipp Edelmann, Eisuke Kawashima, -" and Louis Cochen. +" Louis Cochen, and Doug Kearns. " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -17,6 +17,7 @@ let b:did_indent = 1 let s:cposet=&cpoptions set cpoptions&vim +let b:undo_indent = "setl inde< indk<" setlocal indentkeys+==~end,=~case,=~if,=~else,=~do,=~where,=~elsewhere,=~select setlocal indentkeys+==~endif,=~enddo,=~endwhere,=~endselect,=~elseif diff --git a/runtime/indent/postscr.vim b/runtime/indent/postscr.vim index 66094e3ed0..8430ccf8b8 100644 --- a/runtime/indent/postscr.vim +++ b/runtime/indent/postscr.vim @@ -1,10 +1,8 @@ " PostScript indent file " Language: PostScript -" Maintainer: Mike Williams <mrw@netcomuk.co.uk> (Invalid email address) -" Doug Kearns <dougkearns@gmail.com> +" Maintainer: Mike Williams <mrw@eandem.co.uk> " Last Change: 2022 Apr 06 - " Only load this indent file when no other was loaded. if exists("b:did_indent") finish diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index dc25d68f61..e6ab48f30d 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -406,7 +406,6 @@ function vim.defer_fn(fn, timeout) timeout, 0, vim.schedule_wrap(function() - timer:stop() timer:close() fn() diff --git a/runtime/lua/vim/filetype.lua b/runtime/lua/vim/filetype.lua index fed0231ae9..c26a43f776 100644 --- a/runtime/lua/vim/filetype.lua +++ b/runtime/lua/vim/filetype.lua @@ -283,6 +283,7 @@ local extension = { hjson = 'hjson', hog = 'hog', hws = 'hollywood', + hoon = 'hoon', htt = 'httest', htb = 'httest', iba = 'ibasic', @@ -418,6 +419,7 @@ local extension = { tsc = 'monk', isc = 'monk', moo = 'moo', + moon = 'moonscript', mp = 'mp', mof = 'msidl', odl = 'msidl', @@ -786,8 +788,8 @@ local extension = { zut = 'zimbutempl', zsh = 'zsh', vala = 'vala', - E = function() - vim.fn['dist#ft#FTe']() + E = function(path, bufnr) + return require('vim.filetype.detect').e(bufnr) end, EU = function(path, bufnr) return require('vim.filetype.detect').euphoria(bufnr) @@ -804,68 +806,68 @@ local extension = { EXW = function(path, bufnr) return require('vim.filetype.detect').euphoria(bufnr) end, - PL = function() - vim.fn['dist#ft#FTpl']() + PL = function(path, bufnr) + return require('vim.filetype.detect').pl(bufnr) end, R = function(path, bufnr) - require('vim.filetype.detect').r(bufnr) + return require('vim.filetype.detect').r(bufnr) end, - asm = function() - vim.fn['dist#ft#FTasm']() + asm = function(path, bufnr) + return require('vim.filetype.detect').asm(bufnr) end, - bas = function() - vim.fn['dist#ft#FTbas']() + bas = function(path, bufnr) + return require('vim.filetype.detect').bas(bufnr) end, - bi = function() - vim.fn['dist#ft#FTbas']() + bi = function(path, bufnr) + return require('vim.filetype.detect').bas(bufnr) end, - bm = function() - vim.fn['dist#ft#FTbas']() + bm = function(path, bufnr) + return require('vim.filetype.detect').bas(bufnr) end, - bash = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + bash = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, btm = function(path, bufnr) return require('vim.filetype.detect').btm(bufnr) end, - c = function() - vim.fn['dist#ft#FTlpc']() + c = function(path, bufnr) + return require('vim.filetype.detect').lpc(bufnr) end, - ch = function() - vim.fn['dist#ft#FTchange']() + ch = function(path, bufnr) + return require('vim.filetype.detect').change(bufnr) end, - com = function() - vim.fn['dist#ft#BindzoneCheck']('dcl') + com = function(path, bufnr) + return require('vim.filetype.detect').bindzone(bufnr, 'dcl') end, - cpt = function() - vim.fn['dist#ft#FThtml']() + cpt = function(path, bufnr) + return require('vim.filetype.detect').html(bufnr) end, - csh = function() - vim.fn['dist#ft#CSH']() + csh = function(path, bufnr) + return require('vim.filetype.detect').csh(path, bufnr) end, - d = function() - vim.fn['dist#ft#DtraceCheck']() + d = function(path, bufnr) + return require('vim.filetype.detect').dtrace(bufnr) end, - db = function() - vim.fn['dist#ft#BindzoneCheck']('') + db = function(path, bufnr) + return require('vim.filetype.detect').bindzone(bufnr, '') end, - dtml = function() - vim.fn['dist#ft#FThtml']() + dtml = function(path, bufnr) + return require('vim.filetype.detect').html(bufnr) end, - e = function() - vim.fn['dist#ft#FTe']() + e = function(path, bufnr) + return require('vim.filetype.detect').e(bufnr) end, - ebuild = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + ebuild = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, - eclass = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + eclass = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, ent = function(path, bufnr) return require('vim.filetype.detect').ent(bufnr) end, - env = function() - vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1)) + env = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, getline(bufnr, 1)) end, eu = function(path, bufnr) return require('vim.filetype.detect').euphoria(bufnr) @@ -883,55 +885,55 @@ local extension = { return require('vim.filetype.detect').euphoria(bufnr) end, frm = function(path, bufnr) - require('vim.filetype.detect').frm(bufnr) + return require('vim.filetype.detect').frm(bufnr) end, - fs = function() - vim.fn['dist#ft#FTfs']() + fs = function(path, bufnr) + return require('vim.filetype.detect').fs(bufnr) end, h = function(path, bufnr) - require('vim.filetype.detect').header(bufnr) + return require('vim.filetype.detect').header(bufnr) end, - htm = function() - vim.fn['dist#ft#FThtml']() + htm = function(path, bufnr) + return require('vim.filetype.detect').html(bufnr) end, - html = function() - vim.fn['dist#ft#FThtml']() + html = function(path, bufnr) + return require('vim.filetype.detect').html(bufnr) end, - i = function() - vim.fn['dist#ft#FTprogress_asm']() + i = function(path, bufnr) + return require('vim.filetype.detect').progress_asm(bufnr) end, idl = function(path, bufnr) - require('vim.filetype.detect').idl(bufnr) + return require('vim.filetype.detect').idl(bufnr) end, - inc = function() - vim.fn['dist#ft#FTinc']() + inc = function(path, bufnr) + return require('vim.filetype.detect').inc(bufnr) end, inp = function(path, bufnr) - require('vim.filetype.detect').inp(bufnr) + return require('vim.filetype.detect').inp(bufnr) end, - ksh = function() - vim.fn['dist#ft#SetFileTypeSH']('ksh') + ksh = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'ksh') end, - lst = function() - vim.fn['dist#ft#FTasm']() + lst = function(path, bufnr) + return require('vim.filetype.detect').asm(bufnr) end, - m = function() - vim.fn['dist#ft#FTm']() + m = function(path, bufnr) + return require('vim.filetype.detect').m(bufnr) end, - mac = function() - vim.fn['dist#ft#FTasm']() + mac = function(path, bufnr) + return require('vim.filetype.detect').asm(bufnr) end, mc = function(path, bufnr) - require('vim.filetype.detect').mc(bufnr) + return require('vim.filetype.detect').mc(bufnr) end, - mm = function() - vim.fn['dist#ft#FTmm']() + mm = function(path, bufnr) + return require('vim.filetype.detect').mm(bufnr) end, mms = function(path, bufnr) - require('vim.filetype.detect').mms(bufnr) + return require('vim.filetype.detect').mms(bufnr) end, - p = function() - vim.fn['dist#ft#FTprogress_pascal']() + p = function(path, bufnr) + return require('vim.filetype.detect').progress_pascal(bufnr) end, patch = function(path, bufnr) local firstline = getline(bufnr, 1) @@ -941,65 +943,65 @@ local extension = { return 'diff' end end, - pl = function() - vim.fn['dist#ft#FTpl']() + pl = function(path, bufnr) + return require('vim.filetype.detect').pl(bufnr) end, - pp = function() - vim.fn['dist#ft#FTpp']() + pp = function(path, bufnr) + return require('vim.filetype.detect').pp(bufnr) end, - pro = function() - vim.fn['dist#ft#ProtoCheck']('idlang') + pro = function(path, bufnr) + return require('vim.filetype.detect').proto(bufnr, 'idlang') end, - pt = function() - vim.fn['dist#ft#FThtml']() + pt = function(path, bufnr) + return require('vim.filetype.detect').html('idlang') end, r = function(path, bufnr) - require('vim.filetype.detect').r(bufnr) + return require('vim.filetype.detect').r(bufnr) end, rdf = function(path, bufnr) - require('vim.filetype.detect').redif(bufnr) + return require('vim.filetype.detect').redif(bufnr) end, - rules = function() - vim.fn['dist#ft#FTRules']() + rules = function(path, bufnr) + return require('vim.filetype.detect').rules(path, bufnr) end, sc = function(path, bufnr) - require('vim.filetype.detect').sc(bufnr) + return require('vim.filetype.detect').sc(bufnr) end, scd = function(path, bufnr) - require('vim.filetype.detect').scd(bufnr) + return require('vim.filetype.detect').scd(bufnr) end, - sh = function() - vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1)) + sh = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, getline(bufnr, 1)) end, - shtml = function() - vim.fn['dist#ft#FThtml']() + shtml = function(path, bufnr) + return require('vim.filetype.detect').html(bufnr) end, sql = function(path, bufnr) - require('vim.filetype.detect').sql(bufnr) + return require('vim.filetype.detect').sql(bufnr) end, - stm = function() - vim.fn['dist#ft#FThtml']() + stm = function(path, bufnr) + return require('vim.filetype.detect').html(bufnr) end, - tcsh = function() - vim.fn['dist#ft#SetFileTypeShell']('tcsh') + tcsh = function(path, bufnr) + return require('vim.filetype.detect').shell(path, bufnr, 'tcsh') end, - tex = function() - vim.fn['dist#ft#FTtex']() + tex = function(path, bufnr) + return require('vim.filetype.detect').tex(path, bufnr) end, tf = function(path, bufnr) - require('vim.filetype.detect').tf(bufnr) + return require('vim.filetype.detect').tf(bufnr) end, w = function(path, bufnr) - require('vim.filetype.detect').progress_cweb(bufnr) + return require('vim.filetype.detect').progress_cweb(bufnr) end, xml = function(path, bufnr) - require('vim.filetype.detect').xml(bufnr) + return require('vim.filetype.detect').xml(bufnr) end, y = function(path, bufnr) - require('vim.filetype.detect').y(bufnr) + return require('vim.filetype.detect').y(bufnr) end, zsql = function(path, bufnr) - require('vim.filetype.detect').sql(bufnr) + return require('vim.filetype.detect').sql(bufnr) end, txt = function(path, bufnr) --helpfiles match *.txt, but should have a modeline as last line @@ -1058,6 +1060,7 @@ local filename = { ['.dircolors'] = 'dircolors', ['/etc/dnsmasq.conf'] = 'dnsmasq', Containerfile = 'dockerfile', + dockerfile = 'dockerfile', Dockerfile = 'dockerfile', npmrc = 'dosini', ['/etc/yum.conf'] = 'dosini', @@ -1075,16 +1078,16 @@ local filename = { exports = 'exports', ['.fetchmailrc'] = 'fetchmail', fvSchemes = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, fvSolution = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, fvConstraints = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, fvModels = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, fstab = 'fstab', mtab = 'fstab', @@ -1300,63 +1303,63 @@ local filename = { ['.zcompdump'] = 'zsh', ['.zshenv'] = 'zsh', ['.zfbfmarks'] = 'zsh', - ['.alias'] = function() - vim.fn['dist#ft#CSH']() + ['.alias'] = function(path, bufnr) + return require('vim.filetype.detect').csh(path, bufnr) end, - ['.bashrc'] = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + ['.bashrc'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, - ['.cshrc'] = function() - vim.fn['dist#ft#CSH']() + ['.cshrc'] = function(path, bufnr) + return require('vim.filetype.detect').csh(path, bufnr) end, - ['.env'] = function() - vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1)) + ['.env'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, getline(bufnr, 1)) end, - ['.kshrc'] = function() - vim.fn['dist#ft#SetFileTypeSH']('ksh') + ['.kshrc'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'ksh') end, - ['.login'] = function() - vim.fn['dist#ft#CSH']() + ['.login'] = function(path, bufnr) + return require('vim.filetype.detect').csh(path, bufnr) end, - ['.profile'] = function() - vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1)) + ['.profile'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, getline(bufnr, 1)) end, - ['.tcshrc'] = function() - vim.fn['dist#ft#SetFileTypeShell']('tcsh') + ['.tcshrc'] = function(path, bufnr) + return require('vim.filetype.detect').shell(path, bufnr, 'tcsh') end, - ['/etc/profile'] = function() - vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1)) + ['/etc/profile'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, getline(bufnr, 1)) end, - APKBUILD = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + APKBUILD = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, - PKGBUILD = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + PKGBUILD = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, - ['bash.bashrc'] = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + ['bash.bashrc'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, - bashrc = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + bashrc = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, crontab = starsetf('crontab'), - ['csh.cshrc'] = function() - vim.fn['dist#ft#CSH']() + ['csh.cshrc'] = function(path, bufnr) + return require('vim.filetype.detect').csh(path, bufnr) end, - ['csh.login'] = function() - vim.fn['dist#ft#CSH']() + ['csh.login'] = function(path, bufnr) + return require('vim.filetype.detect').csh(path, bufnr) end, - ['csh.logout'] = function() - vim.fn['dist#ft#CSH']() + ['csh.logout'] = function(path, bufnr) + return require('vim.filetype.detect').csh(path, bufnr) end, - ['indent.pro'] = function() - vim.fn['dist#ft#ProtoCheck']('indent') + ['indent.pro'] = function(path, bufnr) + return require('vim.filetype.detect').proto(bufnr, 'indent') end, - ['tcsh.login'] = function() - vim.fn['dist#ft#SetFileTypeShell']('tcsh') + ['tcsh.login'] = function(path, bufnr) + return require('vim.filetype.detect').shell(path, bufnr, 'tcsh') end, - ['tcsh.tcshrc'] = function() - vim.fn['dist#ft#SetFileTypeShell']('tcsh') + ['tcsh.tcshrc'] = function(path, bufnr) + return require('vim.filetype.detect').shell(path, bufnr, 'tcsh') end, -- END FILENAME } @@ -1528,32 +1531,32 @@ local pattern = { ['.*/etc/xdg/menus/.*%.menu'] = 'xml', ['.*Xmodmap'] = 'xmodmap', ['.*/etc/zprofile'] = 'zsh', - ['%.bash[_-]aliases'] = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + ['%.bash[_-]aliases'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, - ['%.bash[_-]logout'] = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + ['%.bash[_-]logout'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, - ['%.bash[_-]profile'] = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + ['%.bash[_-]profile'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, - ['%.cshrc.*'] = function() - vim.fn['dist#ft#CSH']() + ['%.cshrc.*'] = function(path, bufnr) + return require('vim.filetype.detect').csh(path, bufnr) end, ['%.gtkrc.*'] = starsetf('gtkrc'), - ['%.kshrc.*'] = function() - vim.fn['dist#ft#SetFileTypeSH']('ksh') + ['%.kshrc.*'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'ksh') end, - ['%.login.*'] = function() - vim.fn['dist#ft#CSH']() + ['%.login.*'] = function(path, bufnr) + return require('vim.filetype.detect').csh(path, bufnr) end, ['%.neomuttrc.*'] = starsetf('neomuttrc'), - ['%.profile.*'] = function() - vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1)) + ['%.profile.*'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, getline(bufnr, 1)) end, ['%.reminders.*'] = starsetf('remind'), - ['%.tcshrc.*'] = function() - vim.fn['dist#ft#SetFileTypeShell']('tcsh') + ['%.tcshrc.*'] = function(path, bufnr) + return require('vim.filetype.detect').shell(path, bufnr, 'tcsh') end, ['%.zcompdump.*'] = starsetf('zsh'), ['%.zlog.*'] = starsetf('zsh'), @@ -1561,11 +1564,11 @@ local pattern = { ['.*%.[1-9]'] = function(path, bufnr) return require('vim.filetype.detect').nroff(bufnr) end, - ['.*%.[aA]'] = function() - vim.fn['dist#ft#FTasm']() + ['.*%.[aA]'] = function(path, bufnr) + return require('vim.filetype.detect').asm(bufnr) end, - ['.*%.[sS]'] = function() - vim.fn['dist#ft#FTasm']() + ['.*%.[sS]'] = function(path, bufnr) + return require('vim.filetype.detect').asm(bufnr) end, ['.*%.properties_.._.._.*'] = starsetf('jproperties'), ['.*%.vhdl_[0-9].*'] = starsetf('vhdl'), @@ -1575,8 +1578,8 @@ local pattern = { ['.*/Xresources/.*'] = starsetf('xdefaults'), ['.*/app%-defaults/.*'] = starsetf('xdefaults'), ['.*/bind/db%..*'] = starsetf('bindzone'), - ['.*/debian/patches/.*'] = function() - vim.fn['dist#ft#Dep3patch']() + ['.*/debian/patches/.*'] = function(path, bufnr) + return require('vim.filetype.detect').dep3patch(path, bufnr) end, ['.*/etc/Muttrc%.d/.*'] = starsetf('muttrc'), ['.*/etc/apache2/.*%.conf.*'] = starsetf('apache'), @@ -1592,8 +1595,8 @@ local pattern = { ['.*/etc/logcheck/.*%.d.*/.*'] = starsetf('logcheck'), ['.*/etc/modprobe%..*'] = starsetf('modconf'), ['.*/etc/pam%.d/.*'] = starsetf('pamconf'), - ['.*/etc/profile'] = function() - vim.fn['dist#ft#SetFileTypeSH'](vim.fn.getline(1)) + ['.*/etc/profile'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, getline(bufnr, 1)) end, ['.*/etc/proftpd/.*%.conf.*'] = starsetf('apachestyle'), ['.*/etc/proftpd/conf%..*/.*'] = starsetf('apachestyle'), @@ -1621,8 +1624,8 @@ local pattern = { ['access%.conf.*'] = starsetf('apache'), ['apache%.conf.*'] = starsetf('apache'), ['apache2%.conf.*'] = starsetf('apache'), - ['bash%-fc[-%.]'] = function() - vim.fn['dist#ft#SetFileTypeSH']('bash') + ['bash%-fc[-%.]'] = function(path, bufnr) + return require('vim.filetype.detect').sh(path, bufnr, 'bash') end, ['cabal%.project%..*'] = starsetf('cabalproject'), ['crontab%..*'] = starsetf('crontab'), @@ -1650,28 +1653,28 @@ local pattern = { ['neomutt' .. string.rep('[%w_-]', 6)] = 'mail', ['/tmp/SLRN[0-9A-Z.]+'] = 'mail', ['[a-zA-Z0-9].*Dict'] = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, ['[a-zA-Z0-9].*Dict%..*'] = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, ['[a-zA-Z].*Properties'] = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, ['[a-zA-Z].*Properties%..*'] = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, ['.*Transport%..*'] = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, ['.*/constant/g'] = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, ['.*/0/.*'] = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, ['.*/0%.orig/.*'] = function(path, bufnr) - require('vim.filetype.detect').foam(bufnr) + return require('vim.filetype.detect').foam(bufnr) end, ['.*/etc/sensors%.d/[^.].*'] = starsetf('sensors'), ['.*%.git/.*'] = function(path, bufnr) @@ -1680,24 +1683,29 @@ local pattern = { return 'git' end end, - ['.*%.[Cc][Ff][Gg]'] = function() - vim.fn['dist#ft#FTcfg']() - end, - ['.*%.[Dd][Aa][Tt]'] = function() - vim.fn['dist#ft#FTdat']() + ['.*%.[Cc][Ff][Gg]'] = { + function(path, bufnr) + return require('vim.filetype.detect').cfg(bufnr) + end, + -- Decrease the priority to avoid conflicts with more specific patterns + -- such as '.*/etc/a2ps/.*%.cfg', '.*enlightenment/.*%.cfg', etc. + { priority = -1 }, + }, + ['.*%.[Dd][Aa][Tt]'] = function(path, bufnr) + return require('vim.filetype.detect').dat(bufnr) end, - ['.*%.[Mm][Oo][Dd]'] = function() - vim.fn['dist#ft#FTmod']() + ['.*%.[Mm][Oo][Dd]'] = function(path, bufnr) + return require('vim.filetype.detect').mod(path, bufnr) end, - ['.*%.[Ss][Rr][Cc]'] = function() - vim.fn['dist#ft#FTsrc']() + ['.*%.[Ss][Rr][Cc]'] = function(path, bufnr) + return require('vim.filetype.detect').src(bufnr) end, ['.*%.[Ss][Uu][Bb]'] = 'krl', - ['.*%.[Pp][Rr][Gg]'] = function() - vim.fn['dist#ft#FTprg']() + ['.*%.[Pp][Rr][Gg]'] = function(path, bufnr) + return require('vim.filetype.detect').prg(bufnr) end, - ['.*%.[Ss][Yy][Ss]'] = function() - vim.fn['dist#ft#FTsys']() + ['.*%.[Ss][Yy][Ss]'] = function(path, bufnr) + return require('vim.filetype.detect').sys(bufnr) end, -- Neovim only ['.*/queries/.*%.scm'] = 'query', -- tree-sitter queries diff --git a/runtime/lua/vim/filetype/detect.lua b/runtime/lua/vim/filetype/detect.lua index 4c363e7403..f195693dcf 100644 --- a/runtime/lua/vim/filetype/detect.lua +++ b/runtime/lua/vim/filetype/detect.lua @@ -1,19 +1,35 @@ +-- Contains filetype detection functions converted to Lua from Vim's autoload/runtime/dist/ft.vim file. + +-- Here are a few guidelines to follow when porting a new function: +-- * Sort the function alphabetically and omit 'ft' or 'check' from the new function name. +-- * Use ':find' instead of ':match' / ':sub' if possible. +-- * When '=~' is used to match a pattern, there are two possibilities: +-- - If the pattern only contains lowercase characters, treat the comparison as case-insensitive. +-- - Otherwise, treat it as case-sensitive. +-- (Basically, we apply 'smartcase': if upper case characters are used in the original pattern, then +-- it's likely that case does matter). +-- * When '\k', '\<' or '\>' is used in a pattern, use the 'matchregex' function. +-- Note that vim.regex is case-sensitive by default, so add the '\c' flag if only lowercase letters +-- are present in the pattern: +-- Example: +-- `if line =~ '^\s*unwind_protect\>'` => `if matchregex(line, [[\c^\s*unwind_protect\>]])` + local M = {} ---@private -local function getlines(bufnr, start_lnum, end_lnum, opts) +local function getlines(bufnr, start_lnum, end_lnum) if not end_lnum then -- Return a single line as a string return vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, start_lnum, false)[1] end - - local lines = vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false) - opts = opts or {} - return opts.concat and (table.concat(lines) or '') or lines + return vim.api.nvim_buf_get_lines(bufnr, start_lnum - 1, end_lnum, false) end ---@private local function findany(s, patterns) + if s == nil then + return false + end for _, v in ipairs(patterns) do if s:find(v) then return true @@ -22,22 +38,117 @@ local function findany(s, patterns) return false end +---@private +local function nextnonblank(bufnr, start_lnum) + for _, line in ipairs(getlines(bufnr, start_lnum, -1)) do + if not line:find('^%s*$') then + return line + end + end + return nil +end + +---@private +local matchregex = (function() + local cache = {} + return function(line, pattern) + if line == nil then + return nil + end + if not cache[pattern] then + cache[pattern] = vim.regex(pattern) + end + return cache[pattern]:match_str(line) + end +end)() + +---@private +local did_filetype = function() + return vim.fn.did_filetype() ~= 0 +end + -- luacheck: push no unused args -- luacheck: push ignore 122 -function M.asm(path, bufnr) end +-- This function checks for the kind of assembly that is wanted by the user, or +-- can be detected from the first five lines of the file. +function M.asm(bufnr) + -- Make sure b:asmsyntax exists + if not vim.b[bufnr].asmsyntax then + vim.b[bufnr].asmsyntax = '' + end + + if vim.b[bufnr].asmsyntax == '' then + M.asm_syntax(bufnr) + end + + -- If b:asmsyntax still isn't set, default to asmsyntax or GNU + if vim.b[bufnr].asmsyntax == '' then + if vim.g.asmsyntax and vim.g.asmsyntax ~= 0 then + vim.b[bufnr].asmsyntax = vim.g.asmsyntax + else + vim.b[bufnr].asmsyntax = 'asm' + end + end + return vim.fn.fnameescape(vim.b[bufnr].asmsyntax) +end + +-- Checks the first 5 lines for a asmsyntax=foo override. +-- Only whitespace characters can be present immediately before or after this statement. +function M.asm_syntax(bufnr) + local lines = table.concat(getlines(bufnr, 1, 5), ' '):lower() + local match = lines:match('%sasmsyntax=([a-zA-Z0-9]+)%s') + if match then + vim.b['asmsyntax'] = match + elseif findany(lines, { '%.title', '%.ident', '%.macro', '%.subtitle', '%.library' }) then + vim.b['asmsyntax'] = 'vmasm' + end +end -function M.asm_syntax(path, bufnr) end +local visual_basic_content = { 'vb_name', 'begin vb%.form', 'begin vb%.mdiform', 'begin vb%.usercontrol' } + +-- See frm() for Visual Basic form file detection +function M.bas(bufnr) + if vim.g.filetype_bas then + return vim.g.filetype_bas + end -function M.bas(path, bufnr) end + -- Most frequent FreeBASIC-specific keywords in distro files + local fb_keywords = + [[\c^\s*\%(extern\|var\|enum\|private\|scope\|union\|byref\|operator\|constructor\|delete\|namespace\|public\|property\|with\|destructor\|using\)\>\%(\s*[:=(]\)\@!]] + local fb_preproc = + [[\c^\s*\%(#\a\+\|option\s\+\%(byval\|dynamic\|escape\|\%(no\)\=gosub\|nokeyword\|private\|static\)\>\)]] -function M.bindzone(path, bufnr) end + local fb_comment = "^%s*/'" + -- OPTION EXPLICIT, without the leading underscore, is common to many dialects + local qb64_preproc = [[\c^\s*\%($\a\+\|option\s\+\%(_explicit\|_\=explicitarray\)\>\)]] + + for _, line in ipairs(getlines(bufnr, 1, 100)) do + if line:find(fb_comment) or matchregex(line, fb_preproc) or matchregex(line, fb_keywords) then + return 'freebasic' + elseif matchregex(line, qb64_preproc) then + return 'qb64' + elseif findany(line:lower(), visual_basic_content) then + return 'vb' + end + end + return 'basic' +end + +function M.bindzone(bufnr, default) + local lines = table.concat(getlines(bufnr, 1, 4)) + if findany(lines, { '^; <<>> DiG [0-9%.]+.* <<>>', '%$ORIGIN', '%$TTL', 'IN%s+SOA' }) then + return 'bindzone' + else + return default + end +end function M.btm(bufnr) if vim.g.dosbatch_syntax_for_btm and vim.g.dosbatch_syntax_for_btm ~= 0 then - vim.bo[bufnr].filetype = 'dosbatch' + return 'dosbatch' else - vim.bo[bufnr].filetype = 'btm' + return 'btm' end end @@ -47,38 +158,131 @@ local function is_rapid(bufnr, extension) local line = getlines(bufnr, 1):lower() return findany(line, { 'eio:cfg', 'mmc:cfg', 'moc:cfg', 'proc:cfg', 'sio:cfg', 'sys:cfg' }) end - local first = '^%s*module%s+%S+%s*' - -- Called from mod, prg or sys functions - for _, line in ipairs(getlines(bufnr, 1, -1)) do - if not line:find('^%s*$') then - return findany(line:lower(), { '^%s*%%%%%%', first .. '(', first .. '$' }) - end + local line = nextnonblank(bufnr, 1) + if line then + -- Called from mod, prg or sys functions + return matchregex(line:lower(), [[\c\v^\s*%(\%{3}|module\s+\k+\s*%(\(|$))]]) end - -- Only found blank lines return false end function M.cfg(bufnr) if vim.g.filetype_cfg then - vim.bo[bufnr].filetype = vim.g.filetype_cfg + return vim.g.filetype_cfg elseif is_rapid(bufnr, 'cfg') then - vim.bo[bufnr].filetype = 'rapid' + return 'rapid' else - vim.bo[bufnr].filetype = 'cfg' + return 'cfg' end end -function M.change(path, bufnr) end +-- This function checks if one of the first ten lines start with a '@'. In +-- that case it is probably a change file. +-- If the first line starts with # or ! it's probably a ch file. +-- If a line has "main", "include", "//" or "/*" it's probably ch. +-- Otherwise CHILL is assumed. +function M.change(bufnr) + local first_line = getlines(bufnr, 1) + if findany(first_line, { '^#', '^!' }) then + return 'ch' + end + for _, line in ipairs(getlines(bufnr, 1, 10)) do + if line:find('^@') then + return 'change' + end + if line:find('MODULE') then + return 'chill' + elseif findany(line:lower(), { 'main%s*%(', '#%s*include', '//' }) then + return 'ch' + end + end + return 'chill' +end + +function M.csh(path, bufnr) + if did_filetype() then + -- Filetype was already detected + return + end + if vim.g.filetype_csh then + return M.shell(path, bufnr, vim.g.filetype_csh) + elseif string.find(vim.o.shell, 'tcsh') then + return M.shell(path, bufnr, 'tcsh') + else + return M.shell(path, bufnr, 'csh') + end +end -function M.csh(path, bufnr) end +-- Determine if a *.dat file is Kuka Robot Language +function M.dat(bufnr) + if vim.g.filetype_dat then + return vim.g.filetype_dat + end + local line = nextnonblank(bufnr, 1) + if matchregex(line, [[\c\v^\s*%(\&\w+|defdat>)]]) then + return 'krl' + end +end -function M.dat(path, bufnr) end +-- This function is called for all files under */debian/patches/*, make sure not +-- to non-dep3patch files, such as README and other text files. +function M.dep3patch(path, bufnr) + local file_name = vim.fn.fnamemodify(path, ':t') + if file_name == 'series' then + return + end -function M.dep3patch(path, bufnr) end + for _, line in ipairs(getlines(bufnr, 1, 100)) do + if + findany(line, { + '^Description:', + '^Subject:', + '^Origin:', + '^Bug:', + '^Forwarded:', + '^Author:', + '^From:', + '^Reviewed%-by:', + '^Acked%-by:', + '^Last%-Updated:', + '^Applied%-Upstream:', + }) + then + return 'dep3patch' + elseif line:find('^%-%-%-') then + -- End of headers found. stop processing + return + end + end +end -function M.dtrace(path, bufnr) end +function M.dtrace(bufnr) + if did_filetype() then + -- Filetype was already detected + return + end + for _, line in ipairs(getlines(bufnr, 1, 100)) do + if matchregex(line, [[\c^module\>\|^import\>]]) then + -- D files often start with a module and/or import statement. + return 'd' + elseif findany(line, { '^#!%S+dtrace', '#pragma%s+D%s+option', ':%S-:%S-:' }) then + return 'dtrace' + end + end + return 'd' +end -function M.e(path, bufnr) end +function M.e(bufnr) + if vim.g.filetype_euphoria then + return vim.g.filetype_euphoria + end + for _, line in ipairs(getlines(bufnr, 1, 100)) do + if findany(line, { "^%s*<'%s*$", "^%s*'>%s*$" }) then + return 'specman' + end + end + return 'eiffel' +end -- This function checks for valid cl syntax in the first five lines. -- Look for either an opening comment, '#', or a block start, '{'. @@ -86,37 +290,34 @@ function M.e(path, bufnr) end function M.ent(bufnr) for _, line in ipairs(getlines(bufnr, 1, 5)) do if line:find('^%s*[#{]') then - vim.bo[bufnr].filetype = 'cl' - return + return 'cl' elseif not line:find('^%s*$') then -- Not a blank line, not a comment, and not a block start, -- so doesn't look like valid cl code. break end end - vim.bo[bufnr].filetype = 'dtd' + return 'dtd' end function M.euphoria(bufnr) if vim.g.filetype_euphoria then - vim.bo[bufnr].filetype = vim.g.filetype_euphoria + return vim.g.filetype_euphoria else - vim.bo[bufnr].filetype = 'euphoria3' + return 'euphoria3' end end function M.ex(bufnr) if vim.g.filetype_euphoria then - vim.bo[bufnr].filetype = vim.g.filetype_euphoria + return vim.g.filetype_euphoria else for _, line in ipairs(getlines(bufnr, 1, 100)) do - -- TODO: in the Vim regex, \> is used to match the end of the word, can this be omitted? - if findany(line, { '^%-%-', '^ifdef', '^include' }) then - vim.bo[bufnr].filetype = 'euphoria3' - return + if matchregex(line, [[\c^--\|^ifdef\>\|^include\>]]) then + return 'euphoria3' end end - vim.bo[bufnr].filetype = 'elixir' + return 'elixir' end end @@ -129,80 +330,185 @@ function M.foam(bufnr) if line:find('^FoamFile') then foam_file = true elseif foam_file and line:find('^%s*object') then - vim.bo[bufnr].filetype = 'foam' - return + return 'foam' end end end function M.frm(bufnr) if vim.g.filetype_frm then - vim.bo[bufnr].filetype = vim.g.filetype_frm + return vim.g.filetype_frm + end + local lines = table.concat(getlines(bufnr, 1, 5)):lower() + if findany(lines, visual_basic_content) then + return 'vb' else - -- Always ignore case - local lines = getlines(bufnr, 1, 5, { concat = true }):lower() - if findany(lines, { 'vb_name', 'begin vb%.form', 'begin vb%.mdiform' }) then - vim.bo[bufnr].filetype = 'vb' - else - vim.bo[bufnr].filetype = 'form' - end + return 'form' end end -function M.fs(path, bufnr) end +-- Distinguish between Forth and F#. +function M.fs(bufnr) + if vim.g.filetype_fs then + return vim.g.filetype_fs + end + local line = nextnonblank(bufnr, 1) + if findany(line, { '^%s*%.?%( ', '^%s*\\G? ', '^\\$', '^%s*: %S' }) then + return 'forth' + else + return 'fsharp' + end +end function M.header(bufnr) for _, line in ipairs(getlines(bufnr, 1, 200)) do - if findany(line, { '^@interface', '^@end', '^@class' }) then + if findany(line:lower(), { '^@interface', '^@end', '^@class' }) then if vim.g.c_syntax_for_h then - vim.bo[bufnr].filetype = 'objc' + return 'objc' else - vim.bo[bufnr].filetype = 'objcpp' + return 'objcpp' end - return end end if vim.g.c_syntax_for_h then - vim.bo[bufnr].filetype = 'c' + return 'c' elseif vim.g.ch_syntax_for_h then - vim.bo[bufnr].filetype = 'ch' + return 'ch' else - vim.bo[bufnr].filetype = 'cpp' + return 'cpp' + end +end + +function M.html(bufnr) + for _, line in ipairs(getlines(bufnr, 1, 10)) do + if matchregex(line, [[\<DTD\s\+XHTML\s]]) then + return 'xhtml' + elseif matchregex(line, [[\c{%\s*\(extends\|block\|load\)\>\|{#\s\+]]) then + return 'htmldjango' + end end + return 'html' end function M.idl(bufnr) for _, line in ipairs(getlines(bufnr, 1, 50)) do - -- Always ignore case - line = line:lower() - if findany(line, { '^%s*import%s+"unknwn"%.idl', '^%s*import%s+"objidl"%.idl' }) then - vim.bo[bufnr].filetype = 'msidl' - return + if findany(line:lower(), { '^%s*import%s+"unknwn"%.idl', '^%s*import%s+"objidl"%.idl' }) then + return 'msidl' end end - vim.bo[bufnr].filetype = 'idl' + return 'idl' end -function M.inc(path, bufnr) end +local pascal_comments = { '^%s*{', '^%s*%(%*', '^%s*//' } +local pascal_keywords = [[\c^\s*\%(program\|unit\|library\|uses\|begin\|procedure\|function\|const\|type\|var\)\>]] + +function M.inc(bufnr) + if vim.g.filetype_inc then + return vim.g.filetype_inc + end + local lines = table.concat(getlines(bufnr, 1, 3)) + if lines:lower():find('perlscript') then + return 'aspperl' + elseif lines:find('<%%') then + return 'aspvbs' + elseif lines:find('<%?') then + return 'php' + -- Pascal supports // comments but they're vary rarely used for file + -- headers so assume POV-Ray + elseif findany(lines, { '^%s{', '^%s%(%*' }) or matchregex(lines, pascal_keywords) then + return 'pascal' + else + M.asm_syntax(bufnr) + if vim.b[bufnr].asm_syntax then + return vim.fn.fnameescape(vim.b[bufnr].asm_syntax) + else + return 'pov' + end + end +end function M.inp(bufnr) if getlines(bufnr, 1):find('^%*') then - vim.bo[bufnr].filetype = 'abaqus' + return 'abaqus' else for _, line in ipairs(getlines(bufnr, 1, 500)) do if line:lower():find('^header surface data') then - vim.bo[bufnr].filetype = 'trasys' - return + return 'trasys' + end + end + end +end + +function M.lpc(bufnr) + if vim.g.lpc_syntax_for_c then + for _, line in ipairs(getlines(bufnr, 1, 12)) do + if + findany(line, { + '^//', + '^inherit', + '^private', + '^protected', + '^nosave', + '^string', + '^object', + '^mapping', + '^mixed', + }) + then + return 'lpc' end end end + return 'c' end -function M.lpc(path, bufnr) end +function M.m(bufnr) + if vim.g.filetype_m then + return vim.g.filetype_m + end -function M.lprolog(path, bufnr) end + -- Excluding end(for|function|if|switch|while) common to Murphi + local octave_block_terminators = + [[\<end\%(_try_catch\|classdef\|enumeration\|events\|methods\|parfor\|properties\)\>]] + local objc_preprocessor = [[\c^\s*#\s*\%(import\|include\|define\|if\|ifn\=def\|undef\|line\|error\|pragma\)\>]] -function M.m(path, bufnr) end + -- Whether we've seen a multiline comment leader + local saw_comment = false + for _, line in ipairs(getlines(bufnr, 1, 100)) do + if line:find('^%s*/%*') then + -- /* ... */ is a comment in Objective C and Murphi, so we can't conclude + -- it's either of them yet, but track this as a hint in case we don't see + -- anything more definitive. + saw_comment = true + end + if line:find('^%s*//') or matchregex(line, [[\c^\s*@import\>]]) or matchregex(line, objc_preprocessor) then + return 'objc' + end + if + findany(line, { '^%s*#', '^%s*%%!' }) + or matchregex(line, [[\c^\s*unwind_protect\>]]) + or matchregex(line, [[\c\%(^\|;\)\s*]] .. octave_block_terminators) + then + return 'octave' + elseif line:find('^%s*%%') then + return 'matlab' + elseif line:find('^%s*%(%*') then + return 'mma' + elseif matchregex(line, [[\c^\s*\(\(type\|var\)\>\|--\)]]) then + return 'murphi' + end + end + + if saw_comment then + -- We didn't see anything definitive, but this looks like either Objective C + -- or Murphi based on the comment leader. Assume the former as it is more + -- common. + return 'objc' + else + -- Default is Matlab + return 'matlab' + end +end -- Rely on the file to start with a comment. -- MS message text files use ';', Sendmail files use '#' or 'dnl' @@ -210,112 +516,273 @@ function M.mc(bufnr) for _, line in ipairs(getlines(bufnr, 1, 20)) do if findany(line:lower(), { '^%s*#', '^%s*dnl' }) then -- Sendmail .mc file - vim.bo[bufnr].filetype = 'm4' - return + return 'm4' elseif line:find('^%s*;') then - vim.bo[bufnr].filetype = 'msmessages' - return + return 'msmessages' end end -- Default: Sendmail .mc file - vim.bo[bufnr].filetype = 'm4' + return 'm4' end -function M.mm(path, bufnr) end +function M.mm(bufnr) + for _, line in ipairs(getlines(bufnr, 1, 20)) do + if matchregex(line, [[\c^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)]]) then + return 'objcpp' + end + end + return 'nroff' +end function M.mms(bufnr) for _, line in ipairs(getlines(bufnr, 1, 20)) do if findany(line, { '^%s*%%', '^%s*//', '^%*' }) then - vim.bo[bufnr].filetype = 'mmix' - return + return 'mmix' elseif line:find('^%s*#') then - vim.bo[bufnr].filetype = 'make' - return + return 'make' + end + end + return 'mmix' +end + +-- Returns true if file content looks like LambdaProlog +local function is_lprolog(bufnr) + -- Skip apparent comments and blank lines, what looks like + -- LambdaProlog comment may be RAPID header + for _, line in ipairs(getlines(bufnr, 1, -1)) do + -- The second pattern matches a LambdaProlog comment + if not findany(line, { '^%s*$', '^%s*%%' }) then + -- The pattern must not catch a go.mod file + return matchregex(line, [[\c\<module\s\+\w\+\s*\.\s*\(%\|$\)]]) ~= nil end end - vim.bo[bufnr].filetype = 'mmix' end -function M.mod(path, bufnr) end +-- Determine if *.mod is ABB RAPID, LambdaProlog, Modula-2, Modsim III or go.mod +function M.mod(path, bufnr) + if vim.g.filetype_mod then + return vim.g.filetype_mod + elseif is_lprolog(bufnr) then + return 'lprolog' + elseif matchregex(nextnonblank(bufnr, 1), [[\%(\<MODULE\s\+\w\+\s*;\|^\s*(\*\)]]) then + return 'modula2' + elseif is_rapid(bufnr) then + return 'rapid' + elseif matchregex(path, [[\c\<go\.mod$]]) then + return 'gomod' + else + -- Nothing recognized, assume modsim3 + return 'modsim3' + end +end -- This function checks if one of the first five lines start with a dot. In --- that case it is probably an nroff file: 'filetype' is set and 1 is returned. +-- that case it is probably an nroff file: 'filetype' is set and true is returned. function M.nroff(bufnr) for _, line in ipairs(getlines(bufnr, 1, 5)) do if line:find('^%.') then - vim.bo[bufnr].filetype = 'nroff' - return 1 + return true + end + end + return false +end + +-- If the file has an extension of 't' and is in a directory 't' or 'xt' then +-- it is almost certainly a Perl test file. +-- If the first line starts with '#' and contains 'perl' it's probably a Perl file. +-- (Slow test) If a file contains a 'use' statement then it is almost certainly a Perl file. +function M.perl(path, bufnr) + local dirname = vim.fn.expand(path, '%:p:h:t') + if vim.fn.expand(dirname, '%:e') == 't' and (dirname == 't' or dirname == 'xt') then + return true + end + local first_line = getlines(bufnr, 1) + if first_line:find('^#') and first_line:lower():find('perl') then + return true + end + for _, line in ipairs(getlines(bufnr, 1, 30)) do + if matchregex(line, [[\c^use\s\s*\k]]) then + return true end end - return 0 + return false end -function M.perl(path, bufnr) end +function M.pl(bufnr) + if vim.g.filetype_pl then + return vim.g.filetype_pl + end + -- Recognize Prolog by specific text in the first non-empty line; + -- require a blank after the '%' because Perl uses "%list" and "%translate" + local line = nextnonblank(bufnr, 1) + if + line and line:find(':%-') + or matchregex(line, [[\c\<prolog\>]]) + or findany(line, { '^%s*%%+%s', '^%s*%%+$', '^%s*/%*' }) + then + return 'prolog' + else + return 'perl' + end +end -function M.pl(path, bufnr) end +function M.pp(bufnr) + if vim.g.filetype_pp then + return vim.g.filetype_pp + end + local line = nextnonblank(bufnr, 1) + if findany(line, pascal_comments) or matchregex(line, pascal_keywords) then + return 'pascal' + else + return 'puppet' + end +end -function M.pp(path, bufnr) end +function M.prg(bufnr) + if vim.g.filetype_prg then + return vim.g.filetype_prg + elseif is_rapid(bufnr) then + return 'rapid' + else + -- Nothing recognized, assume Clipper + return 'clipper' + end +end -function M.prg(path, bufnr) end +-- This function checks for an assembly comment in the first ten lines. +-- If not found, assume Progress. +function M.progress_asm(bufnr) + if vim.g.filetype_i then + return vim.g.filetype_i + end -function M.progress_asm(path, bufnr) end + for _, line in ipairs(getlines(bufnr, 1, 10)) do + if line:find('^%s*;') or line:find('^/%*') then + return M.asm(bufnr) + elseif not line:find('^%s*$') or line:find('^/%*') then + -- Not an empty line: doesn't look like valid assembly code + -- or it looks like a Progress /* comment. + break + end + end + return 'progress' +end function M.progress_cweb(bufnr) if vim.g.filetype_w then - vim.bo[bufnr].filetype = vim.g.filetype_w + return vim.g.filetype_w else - if getlines(bufnr, 1):find('^&ANALYZE') or getlines(bufnr, 3):find('^&GLOBAL%-DEFINE') then - vim.bo[bufnr].filetype = 'progress' + if getlines(bufnr, 1):lower():find('^&analyze') or getlines(bufnr, 3):lower():find('^&global%-define') then + return 'progress' else - vim.bo[bufnr].filetype = 'cweb' + return 'cweb' end end end -function M.progress_pascal(path, bufnr) end +-- This function checks for valid Pascal syntax in the first 10 lines. +-- Look for either an opening comment or a program start. +-- If not found, assume Progress. +function M.progress_pascal(bufnr) + if vim.g.filetype_p then + return vim.g.filetype_p + end + for _, line in ipairs(getlines(bufnr, 1, 10)) do + if findany(line, pascal_comments) or matchregex(line, pascal_keywords) then + return 'pascal' + elseif not line:find('^%s*$') or line:find('^/%*') then + -- Not an empty line: Doesn't look like valid Pascal code. + -- Or it looks like a Progress /* comment + break + end + end + return 'progress' +end -function M.proto(path, bufnr) end +-- Distinguish between "default" and Cproto prototype file. +function M.proto(bufnr, default) + -- Cproto files have a comment in the first line and a function prototype in + -- the second line, it always ends in ";". Indent files may also have + -- comments, thus we can't match comments to see the difference. + -- IDL files can have a single ';' in the second line, require at least one + -- character before the ';'. + if getlines(bufnr, 2):find('.;$') then + return 'cpp' + else + return default + end +end function M.r(bufnr) local lines = getlines(bufnr, 1, 50) - -- TODO: \< / \> which match the beginning / end of a word -- Rebol is easy to recognize, check for that first - if table.concat(lines):lower():find('rebol') then - vim.bo[bufnr].filetype = 'rebol' - return + if matchregex(table.concat(lines), [[\c\<rebol\>]]) then + return 'rebol' end for _, line in ipairs(lines) do -- R has # comments if line:find('^%s*#') then - vim.bo[bufnr].filetype = 'r' - return + return 'r' end -- Rexx has /* comments */ if line:find('^%s*/%*') then - vim.bo[bufnr].filetype = 'rexx' - return + return 'rexx' end end -- Nothing recognized, use user default or assume R if vim.g.filetype_r then - vim.bo[bufnr].filetype = vim.g.filetype_r + return vim.g.filetype_r else -- Rexx used to be the default, but R appears to be much more popular. - vim.bo[bufnr].filetype = 'r' + return 'r' end end function M.redif(bufnr) for _, line in ipairs(getlines(bufnr, 1, 5)) do if line:lower():find('^template%-type:') then - vim.bo[bufnr].filetype = 'redif' + return 'redif' end end end -function M.rules(path, bufnr) end +local udev_rules_pattern = '^%s*udev_rules%s*=%s*"([%^"]+)/*".*' +function M.rules(path, bufnr) + path = path:lower() + if + findany(path, { + '/etc/udev/.*%.rules$', + '/etc/udev/rules%.d/.*$.rules$', + '/usr/lib/udev/.*%.rules$', + '/usr/lib/udev/rules%.d/.*%.rules$', + '/lib/udev/.*%.rules$', + '/lib/udev/rules%.d/.*%.rules$', + }) + then + return 'udevrules' + elseif path:find('^/etc/ufw/') then + -- Better than hog + return 'conf' + elseif findany(path, { '^/etc/polkit%-1/rules%.d', '/usr/share/polkit%-1/rules%.d' }) then + return 'javascript' + else + local ok, config_lines = pcall(vim.fn.readfile, '/etc/udev/udev.conf') + if not ok then + return 'hog' + end + local dir = vim.fn.expand(path, ':h') + for _, line in ipairs(config_lines) do + local match = line:match(udev_rules_pattern) + local udev_rules = line:gsub(udev_rules_pattern, match, 1) + if dir == udev_rules then + return 'udevrules' + end + end + return 'hog' + end +end -- This function checks the first 25 lines of file extension "sc" to resolve -- detection between scala and SuperCollider @@ -327,11 +794,10 @@ function M.sc(bufnr) { '[A-Za-z0-9]*%s:%s[A-Za-z0-9]', 'var%s<', 'classvar%s<', '%^this.*', '|%w*|', '%+%s%w*%s{', '%*ar%s' } ) then - vim.bo[bufnr].filetype = 'supercollider' - return + return 'supercollider' end end - vim.bo[bufnr].filetype = 'scala' + return 'scala' end -- This function checks the first line of file extension "scd" to resolve @@ -341,29 +807,140 @@ function M.scd(bufnr) local opt = [[%s+"[^"]*"]] local line = getlines(bufnr, 1) if findany(line, { first .. '$', first .. opt .. '$', first .. opt .. opt .. '$' }) then - vim.bo[bufnr].filetype = 'scdoc' + return 'scdoc' else - vim.bo[bufnr].filetype = 'supercollider' + return 'supercollider' end end -function M.sh(path, bufnr) end +-- Also called from filetype.lua +function M.sh(path, bufnr, name) + if did_filetype() or path:find(vim.g.ft_ignore_pat) then + -- Filetype was already detected or detection should be skipped + return + end + + if matchregex(name, [[\<csh\>]]) then + -- Some .sh scripts contain #!/bin/csh. + return M.shell(path, bufnr, 'csh') + -- Some .sh scripts contain #!/bin/tcsh. + elseif matchregex(name, [[\<tcsh\>]]) then + return M.shell(path, bufnr, 'tcsh') + -- Some .sh scripts contain #!/bin/zsh. + elseif matchregex(name, [[\<zsh\>]]) then + return M.shell(path, bufnr, 'zsh') + elseif matchregex(name, [[\<ksh\>]]) then + vim.b[bufnr].is_kornshell = 1 + vim.b[bufnr].is_bash = nil + vim.b[bufnr].is_sh = nil + elseif vim.g.bash_is_sh or matchregex(name, [[\<bash\>]]) or matchregex(name, [[\<bash2\>]]) then + vim.b[bufnr].is_bash = 1 + vim.b[bufnr].is_kornshell = nil + vim.b[bufnr].is_sh = nil + elseif matchregex(name, [[\<sh\>]]) then + vim.b[bufnr].is_sh = 1 + vim.b[bufnr].is_kornshell = nil + vim.b[bufnr].is_bash = nil + end + return M.shell(path, bufnr, 'sh') +end -function M.shell(path, bufnr) end +-- For shell-like file types, check for an "exec" command hidden in a comment, as used for Tcl. +-- Also called from scripts.vim, thus can't be local to this script. [TODO] +function M.shell(path, bufnr, name) + if did_filetype() or matchregex(path, vim.g.ft_ignore_pat) then + -- Filetype was already detected or detection should be skipped + return + end + local prev_line = '' + for _, line in ipairs(getlines(bufnr, 2, -1)) do + line = line:lower() + if line:find('%s*exec%s') and not prev_line:find('^%s*#.*\\$') then + -- Found an "exec" line after a comment with continuation + local n = line:gsub('%s*exec%s+([^ ]*/)?', '', 1) + if matchregex(n, [[\c\<tclsh\|\<wish]]) then + return 'tcl' + end + end + prev_line = line + end + return name +end function M.sql(bufnr) if vim.g.filetype_sql then - vim.bo[bufnr].filetype = vim.g.filetype_sql + return vim.g.filetype_sql else - vim.bo[bufnr].filetype = 'sql' + return 'sql' end end -function M.src(path, bufnr) end +-- Determine if a *.src file is Kuka Robot Language +function M.src(bufnr) + if vim.g.filetype_src then + return vim.g.filetype_src + end + local line = nextnonblank(bufnr, 1) + if matchregex(line, [[\c\v^\s*%(\&\w+|%(global\s+)?def%(fct)?>)]]) then + return 'krl' + end +end -function M.sys(path, bufnr) end +function M.sys(bufnr) + if vim.g.filetype_sys then + return vim.g.filetype_sys + elseif is_rapid(bufnr) then + return 'rapid' + else + return 'bat' + end +end -function M.tex(path, bufnr) end +-- Choose context, plaintex, or tex (LaTeX) based on these rules: +-- 1. Check the first line of the file for "%&<format>". +-- 2. Check the first 1000 non-comment lines for LaTeX or ConTeXt keywords. +-- 3. Default to "plain" or to g:tex_flavor, can be set in user's vimrc. +function M.tex(path, bufnr) + local format = getlines(bufnr, 1):find('^%%&%s*(%a+)') + if format then + format = format:lower():gsub('pdf', '', 1) + if format == 'tex' then + return 'tex' + elseif format == 'plaintex' then + return 'plaintex' + end + elseif path:lower():find('tex/context/.*/.*%.tex') then + return 'context' + else + local lpat = [[documentclass\>\|usepackage\>\|begin{\|newcommand\>\|renewcommand\>]] + local cpat = + [[start\a\+\|setup\a\+\|usemodule\|enablemode\|enableregime\|setvariables\|useencoding\|usesymbols\|stelle\a\+\|verwende\a\+\|stel\a\+\|gebruik\a\+\|usa\a\+\|imposta\a\+\|regle\a\+\|utilisemodule\>]] + + for i, l in ipairs(getlines(bufnr, 1, 1000)) do + -- Find first non-comment line + if not l:find('^%s*%%%S') then + -- Check the next thousand lines for a LaTeX or ConTeXt keyword. + for _, line in ipairs(getlines(bufnr, i + 1, i + 1000)) do + local lpat_match, cpat_match = matchregex(line, [[\c^\s*\\\%(]] .. lpat .. [[\)\|^\s*\\\(]] .. cpat .. [[\)]]) + if lpat_match then + return 'tex' + elseif cpat_match then + return 'context' + end + end + end + end + -- TODO: add AMSTeX, RevTex, others? + if not vim.g.tex_flavor or vim.g.tex_flavor == 'plain' then + return 'plaintex' + elseif vim.g.tex_flavor == 'context' then + return 'context' + else + -- Probably LaTeX + return 'tex' + end + end +end -- Determine if a *.tf file is TF mud client or terraform function M.tf(bufnr) @@ -371,45 +948,39 @@ function M.tf(bufnr) -- Assume terraform file on a non-empty line (not whitespace-only) -- and when the first non-whitespace character is not a ; or / if not line:find('^%s*$') and not line:find('^%s*[;/]') then - vim.bo[bufnr].filetype = 'terraform' - return + return 'terraform' end end - vim.bo[bufnr].filetype = 'tf' + return 'tf' end function M.xml(bufnr) for _, line in ipairs(getlines(bufnr, 1, 100)) do + local is_docbook4 = line:find('<!DOCTYPE.*DocBook') line = line:lower() - local is_docbook4 = line:find('<!doctype.*docbook') local is_docbook5 = line:find([[ xmlns="http://docbook.org/ns/docbook"]]) if is_docbook4 or is_docbook5 then vim.b[bufnr].docbk_type = 'xml' vim.b[bufnr].docbk_ver = is_docbook4 and 4 or 5 - vim.bo[bufnr].filetype = 'docbk' - return + return 'docbk' end if line:find([[xmlns:xbl="http://www.mozilla.org/xbl"]]) then - vim.bo[bufnr].filetype = 'xbl' - return + return 'xbl' end end - vim.bo[bufnr].filetype = 'xml' + return 'xml' end function M.y(bufnr) for _, line in ipairs(getlines(bufnr, 1, 100)) do if line:find('^%s*%%') then - vim.bo[bufnr].filetype = 'yacc' - return + return 'yacc' end - -- TODO: in the Vim regex, \> is used to match the end of the word after "class", - -- can this be omitted? - if findany(line, { '^%s*#', '^%class', '^%s*#%s*include' }) then - vim.bo[bufnr].filetype = 'racc' + if matchregex(line, [[\c^\s*\(#\|class\>\)]]) and not line:lower():find('^%s*#%s*include') then + return 'racc' end end - vim.bo[bufnr].filetype = 'yacc' + return 'yacc' end -- luacheck: pop diff --git a/runtime/lua/vim/lsp.lua b/runtime/lua/vim/lsp.lua index e99a7c282c..dac2860690 100644 --- a/runtime/lua/vim/lsp.lua +++ b/runtime/lua/vim/lsp.lua @@ -1,5 +1,3 @@ -local if_nil = vim.F.if_nil - local default_handlers = require('vim.lsp.handlers') local log = require('vim.lsp.log') local lsp_rpc = require('vim.lsp.rpc') @@ -8,11 +6,16 @@ local util = require('vim.lsp.util') local sync = require('vim.lsp.sync') local vim = vim -local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option = - vim.api.nvim_err_writeln, vim.api.nvim_buf_get_lines, vim.api.nvim_command, vim.api.nvim_buf_get_option +local nvim_err_writeln, nvim_buf_get_lines, nvim_command, nvim_buf_get_option, nvim_exec_autocmds = + vim.api.nvim_err_writeln, + vim.api.nvim_buf_get_lines, + vim.api.nvim_command, + vim.api.nvim_buf_get_option, + vim.api.nvim_exec_autocmds local uv = vim.loop local tbl_isempty, tbl_extend = vim.tbl_isempty, vim.tbl_extend local validate = vim.validate +local if_nil = vim.F.if_nil local lsp = { protocol = protocol, @@ -867,15 +870,27 @@ function lsp.start_client(config) pcall(config.on_exit, code, signal, client_id) end + for bufnr, client_ids in pairs(all_buffer_active_clients) do + if client_ids[client_id] then + vim.schedule(function() + nvim_exec_autocmds('LspDetach', { + buffer = bufnr, + modeline = false, + data = { client_id = client_id }, + }) + + local namespace = vim.lsp.diagnostic.get_namespace(client_id) + vim.diagnostic.reset(namespace, bufnr) + end) + + client_ids[client_id] = nil + end + end + active_clients[client_id] = nil uninitialized_clients[client_id] = nil - lsp.diagnostic.reset(client_id, all_buffer_active_clients) changetracking.reset(client_id) - for _, client_ids in pairs(all_buffer_active_clients) do - client_ids[client_id] = nil - end - if code ~= 0 or (signal ~= 0 and signal ~= 15) then local msg = string.format('Client %s quit with exit code %s and signal %s', client_id, code, signal) vim.schedule(function() @@ -1173,12 +1188,6 @@ function lsp.start_client(config) --- ---@param force (bool, optional) function client.stop(force) - lsp.diagnostic.reset(client_id, all_buffer_active_clients) - changetracking.reset(client_id) - for _, client_ids in pairs(all_buffer_active_clients) do - client_ids[client_id] = nil - end - local handle = rpc.handle if handle:is_closing() then return @@ -1213,6 +1222,13 @@ function lsp.start_client(config) ---@param bufnr (number) Buffer number function client._on_attach(bufnr) text_document_did_open_handler(bufnr, client) + + nvim_exec_autocmds('LspAttach', { + buffer = bufnr, + modeline = false, + data = { client_id = client.id }, + }) + if config.on_attach then -- TODO(ashkan) handle errors. pcall(config.on_attach, client, bufnr) @@ -1359,6 +1375,12 @@ function lsp.buf_detach_client(bufnr, client_id) return end + nvim_exec_autocmds('LspDetach', { + buffer = bufnr, + modeline = false, + data = { client_id = client_id }, + }) + changetracking.reset_buf(client, bufnr) if vim.tbl_get(client.server_capabilities, 'textDocumentSync', 'openClose') then @@ -1435,11 +1457,29 @@ function lsp.stop_client(client_id, force) end end ---- Gets all active clients. +--- Get active clients. --- ----@returns Table of |vim.lsp.client| objects -function lsp.get_active_clients() - return vim.tbl_values(active_clients) +---@param filter (table|nil) A table with key-value pairs used to filter the +--- returned clients. The available keys are: +--- - id (number): Only return clients with the given id +--- - bufnr (number): Only return clients attached to this buffer +--- - name (string): Only return clients with the given name +---@returns (table) List of |vim.lsp.client| objects +function lsp.get_active_clients(filter) + validate({ filter = { filter, 't', true } }) + + filter = filter or {} + + local clients = {} + + local t = filter.bufnr and (all_buffer_active_clients[resolve_bufnr(filter.bufnr)] or {}) or active_clients + for client_id in pairs(t) do + local client = active_clients[client_id] + if (filter.id == nil or client.id == filter.id) and (filter.name == nil or client.name == filter.name) then + clients[#clients + 1] = client + end + end + return clients end function lsp._vim_exit_handler() @@ -1814,12 +1854,13 @@ end --- is a |vim.lsp.client| object. --- ---@param bufnr (optional, number): Buffer handle, or 0 for current +---@returns (table) Table of (client_id, client) pairs +---@deprecated Use |vim.lsp.get_active_clients()| instead. function lsp.buf_get_clients(bufnr) - bufnr = resolve_bufnr(bufnr) local result = {} - for_each_buffer_client(bufnr, function(client, client_id) - result[client_id] = client - end) + for _, client in ipairs(lsp.get_active_clients({ bufnr = resolve_bufnr(bufnr) })) do + result[client.id] = client + end return result end diff --git a/runtime/lua/vim/lsp/buf.lua b/runtime/lua/vim/lsp/buf.lua index b0bf2c6e5b..bcfaecdfcc 100644 --- a/runtime/lua/vim/lsp/buf.lua +++ b/runtime/lua/vim/lsp/buf.lua @@ -63,26 +63,45 @@ function M.hover() request('textDocument/hover', params) end +---@private +local function request_with_options(name, params, options) + local req_handler + if options then + req_handler = function(err, result, ctx, config) + local client = vim.lsp.get_client_by_id(ctx.client_id) + local handler = client.handlers[name] or vim.lsp.handlers[name] + handler(err, result, ctx, vim.tbl_extend('force', config or {}, options)) + end + end + request(name, params, req_handler) +end + --- Jumps to the declaration of the symbol under the cursor. ---@note Many servers do not implement this method. Generally, see |vim.lsp.buf.definition()| instead. --- -function M.declaration() +---@param options table|nil additional options +--- - reuse_win: (boolean) Jump to existing window if buffer is already open. +function M.declaration(options) local params = util.make_position_params() - request('textDocument/declaration', params) + request_with_options('textDocument/declaration', params, options) end --- Jumps to the definition of the symbol under the cursor. --- -function M.definition() +---@param options table|nil additional options +--- - reuse_win: (boolean) Jump to existing window if buffer is already open. +function M.definition(options) local params = util.make_position_params() - request('textDocument/definition', params) + request_with_options('textDocument/definition', params, options) end --- Jumps to the definition of the type of the symbol under the cursor. --- -function M.type_definition() +---@param options table|nil additional options +--- - reuse_win: (boolean) Jump to existing window if buffer is already open. +function M.type_definition(options) local params = util.make_position_params() - request('textDocument/typeDefinition', params) + request_with_options('textDocument/typeDefinition', params, options) end --- Lists all the implementations for the symbol under the cursor in the @@ -158,20 +177,15 @@ end --- - bufnr (number|nil): --- Restrict formatting to the clients attached to the given buffer, defaults to the current --- buffer (0). +--- --- - filter (function|nil): ---- Predicate to filter clients used for formatting. Receives the list of clients attached ---- to bufnr as the argument and must return the list of clients on which to request ---- formatting. Example: +--- Predicate used to filter clients. Receives a client as argument and must return a +--- boolean. Clients matching the predicate are included. Example: --- --- <pre> --- -- Never request typescript-language-server for formatting --- vim.lsp.buf.format { ---- filter = function(clients) ---- return vim.tbl_filter( ---- function(client) return client.name ~= "tsserver" end, ---- clients ---- ) ---- end +--- filter = function(client) return client.name ~= "tsserver" end --- } --- </pre> --- @@ -188,18 +202,14 @@ end function M.format(options) options = options or {} local bufnr = options.bufnr or vim.api.nvim_get_current_buf() - local clients = vim.lsp.buf_get_clients(bufnr) + local clients = vim.lsp.get_active_clients({ + id = options.id, + bufnr = bufnr, + name = options.name, + }) if options.filter then - clients = options.filter(clients) - elseif options.id then - clients = vim.tbl_filter(function(client) - return client.id == options.id - end, clients) - elseif options.name then - clients = vim.tbl_filter(function(client) - return client.name == options.name - end, clients) + clients = vim.tbl_filter(options.filter, clients) end clients = vim.tbl_filter(function(client) @@ -367,23 +377,20 @@ end --- name using |vim.ui.input()|. ---@param options table|nil additional options --- - filter (function|nil): ---- Predicate to filter clients used for rename. ---- Receives the attached clients as argument and must return a list of ---- clients. +--- Predicate used to filter clients. Receives a client as argument and +--- must return a boolean. Clients matching the predicate are included. --- - name (string|nil): --- Restrict clients used for rename to ones where client.name matches --- this field. function M.rename(new_name, options) options = options or {} local bufnr = options.bufnr or vim.api.nvim_get_current_buf() - local clients = vim.lsp.buf_get_clients(bufnr) - + local clients = vim.lsp.get_active_clients({ + bufnr = bufnr, + name = options.name, + }) if options.filter then - clients = options.filter(clients) - elseif options.name then - clients = vim.tbl_filter(function(client) - return client.name == options.name - end, clients) + clients = vim.tbl_filter(options.filter, clients) end -- Clients must at least support rename, prepareRename is optional @@ -844,7 +851,8 @@ function M.code_action(options) end local context = options.context or {} if not context.diagnostics then - context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics() + local bufnr = vim.api.nvim_get_current_buf() + context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics(bufnr) end local params = util.make_range_params() params.context = context @@ -870,7 +878,8 @@ function M.range_code_action(context, start_pos, end_pos) validate({ context = { context, 't', true } }) context = context or {} if not context.diagnostics then - context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics() + local bufnr = vim.api.nvim_get_current_buf() + context.diagnostics = vim.lsp.diagnostic.get_line_diagnostics(bufnr) end local params = util.make_given_range_params(start_pos, end_pos) params.context = context diff --git a/runtime/lua/vim/lsp/handlers.lua b/runtime/lua/vim/lsp/handlers.lua index b3a253c118..61cc89dcac 100644 --- a/runtime/lua/vim/lsp/handlers.lua +++ b/runtime/lua/vim/lsp/handlers.lua @@ -327,18 +327,20 @@ M['textDocument/hover'] = M.hover ---@param result (table) result of LSP method; a location or a list of locations. ---@param ctx (table) table containing the context of the request, including the method ---(`textDocument/definition` can return `Location` or `Location[]` -local function location_handler(_, result, ctx, _) +local function location_handler(_, result, ctx, config) if result == nil or vim.tbl_isempty(result) then local _ = log.info() and log.info(ctx.method, 'No location found') return nil end local client = vim.lsp.get_client_by_id(ctx.client_id) + config = config or {} + -- textDocument/definition can return Location or Location[] -- https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_definition if vim.tbl_islist(result) then - util.jump_to_location(result[1], client.offset_encoding) + util.jump_to_location(result[1], client.offset_encoding, config.reuse_win) if #result > 1 then vim.fn.setqflist({}, ' ', { @@ -348,7 +350,7 @@ local function location_handler(_, result, ctx, _) api.nvim_command('botright copen') end else - util.jump_to_location(result, client.offset_encoding) + util.jump_to_location(result, client.offset_encoding, config.reuse_win) end end diff --git a/runtime/lua/vim/lsp/health.lua b/runtime/lua/vim/lsp/health.lua index 74714ebc6b..bf8fe0932e 100644 --- a/runtime/lua/vim/lsp/health.lua +++ b/runtime/lua/vim/lsp/health.lua @@ -17,7 +17,8 @@ function M.check() local log_path = vim.lsp.get_log_path() report_info(string.format('Log path: %s', log_path)) - local log_size = vim.loop.fs_stat(log_path).size + local log_file = vim.loop.fs_stat(log_path) + local log_size = log_file and log_file.size or 0 local report_fn = (log_size / 1000000 > 100 and report_warn or report_info) report_fn(string.format('Log size: %d KB', log_size / 1000)) diff --git a/runtime/lua/vim/lsp/rpc.lua b/runtime/lua/vim/lsp/rpc.lua index 2dcafc92bc..ad2498fb6f 100644 --- a/runtime/lua/vim/lsp/rpc.lua +++ b/runtime/lua/vim/lsp/rpc.lua @@ -4,6 +4,8 @@ local log = require('vim.lsp.log') local protocol = require('vim.lsp.protocol') local validate, schedule, schedule_wrap = vim.validate, vim.schedule, vim.schedule_wrap +local is_win = uv.os_uname().version:find('Windows') + ---@private --- Checks whether a given path exists and is a directory. ---@param filename (string) path to check @@ -321,7 +323,7 @@ local function start(cmd, cmd_args, dispatchers, extra_spawn_params) local spawn_params = { args = cmd_args, stdio = { stdin, stdout, stderr }, - detached = true, + detached = not is_win, } if extra_spawn_params then spawn_params.cwd = extra_spawn_params.cwd diff --git a/runtime/lua/vim/lsp/util.lua b/runtime/lua/vim/lsp/util.lua index e8a8e06f46..63e9342b1a 100644 --- a/runtime/lua/vim/lsp/util.lua +++ b/runtime/lua/vim/lsp/util.lua @@ -684,6 +684,16 @@ function M.text_document_completion_list_to_complete_items(result, prefix) return matches end +---@private +--- Like vim.fn.bufwinid except it works across tabpages. +local function bufwinid(bufnr) + for _, win in ipairs(api.nvim_list_wins()) do + if api.nvim_win_get_buf(win) == bufnr then + return win + end + end +end + --- Rename old_fname to new_fname --- ---@param opts (table) @@ -708,10 +718,9 @@ function M.rename(old_fname, new_fname, opts) assert(ok, err) local newbuf = vim.fn.bufadd(new_fname) - for _, win in pairs(api.nvim_list_wins()) do - if api.nvim_win_get_buf(win) == oldbuf then - api.nvim_win_set_buf(win, newbuf) - end + local win = bufwinid(oldbuf) + if win then + api.nvim_win_set_buf(win, newbuf) end api.nvim_buf_delete(oldbuf, { force = true }) end @@ -1004,8 +1013,9 @@ end --- ---@param location table (`Location`|`LocationLink`) ---@param offset_encoding string utf-8|utf-16|utf-32 (required) +---@param reuse_win boolean Jump to existing window if buffer is already opened. ---@returns `true` if the jump succeeded -function M.jump_to_location(location, offset_encoding) +function M.jump_to_location(location, offset_encoding, reuse_win) -- location may be Location or LocationLink local uri = location.uri or location.targetUri if uri == nil then @@ -1024,8 +1034,13 @@ function M.jump_to_location(location, offset_encoding) vim.fn.settagstack(vim.fn.win_getid(), { items = items }, 't') --- Jump to new location (adjusting for UTF-16 encoding of characters) - api.nvim_set_current_buf(bufnr) - api.nvim_buf_set_option(bufnr, 'buflisted', true) + local win = reuse_win and bufwinid(bufnr) + if win then + api.nvim_set_current_win(win) + else + api.nvim_set_current_buf(bufnr) + api.nvim_buf_set_option(bufnr, 'buflisted', true) + end local range = location.range or location.targetSelectionRange local row = range.start.line local col = get_line_byte_from_position(bufnr, range.start, offset_encoding) @@ -1462,7 +1477,7 @@ function M.open_floating_preview(contents, syntax, opts) }) opts = opts or {} opts.wrap = opts.wrap ~= false -- wrapping by default - opts.stylize_markdown = opts.stylize_markdown ~= false + opts.stylize_markdown = opts.stylize_markdown ~= false and vim.g.syntax_on ~= nil opts.focus = opts.focus ~= false opts.close_events = opts.close_events or { 'CursorMoved', 'CursorMovedI', 'InsertCharPre' } @@ -1676,7 +1691,7 @@ end --- ---@param items (table) list of items function M.set_loclist(items, win_id) - vim.api.nvim_echo({ { 'vim.lsp.util.set_loclist is deprecated. See :h deprecated', 'WarningMsg' } }, true, {}) + vim.deprecate('vim.lsp.util.set_loclist', 'setloclist', '0.8') vim.fn.setloclist(win_id or 0, {}, ' ', { title = 'Language Server', items = items, @@ -1690,7 +1705,7 @@ end --- ---@param items (table) list of items function M.set_qflist(items) - vim.api.nvim_echo({ { 'vim.lsp.util.set_qflist is deprecated. See :h deprecated', 'WarningMsg' } }, true, {}) + vim.deprecate('vim.lsp.util.set_qflist', 'setqflist', '0.8') vim.fn.setqflist({}, ' ', { title = 'Language Server', items = items, diff --git a/runtime/lua/vim/treesitter/languagetree.lua b/runtime/lua/vim/treesitter/languagetree.lua index 2157112d2f..57d8c5fd21 100644 --- a/runtime/lua/vim/treesitter/languagetree.lua +++ b/runtime/lua/vim/treesitter/languagetree.lua @@ -519,17 +519,11 @@ local function tree_contains(tree, range) local start_fits = start_row < range[1] or (start_row == range[1] and start_col <= range[2]) local end_fits = end_row > range[3] or (end_row == range[3] and end_col >= range[4]) - if start_fits and end_fits then - return true - end - - return false + return start_fits and end_fits end --- Determines whether {range} is contained in this language tree --- ---- This goes down the tree to recursively check children. ---- ---@param range A range, that is a `{ start_line, start_col, end_line, end_col }` table. function LanguageTree:contains(range) for _, tree in pairs(self._trees) do diff --git a/runtime/optwin.vim b/runtime/optwin.vim index a13e945098..54f57a260c 100644 --- a/runtime/optwin.vim +++ b/runtime/optwin.vim @@ -229,8 +229,6 @@ call append("$", "compatible\tbehave very Vi compatible (not advisable)") call <SID>BinOptionG("cp", &cp) call append("$", "cpoptions\tlist of flags to specify Vi compatibility") call <SID>OptionG("cpo", &cpo) -call append("$", "insertmode\tuse Insert mode as the default mode") -call <SID>BinOptionG("im", &im) call append("$", "paste\tpaste mode, insert typed text literally") call <SID>BinOptionG("paste", &paste) call append("$", "pastetoggle\tkey sequence to toggle paste mode") @@ -956,7 +954,6 @@ call <SID>Header("mapping") call append("$", "maxmapdepth\tmaximum depth of mapping") call append("$", " \tset mmd=" . &mmd) call append("$", "remap\trecognize mappings in mapped keys") -call <SID>BinOptionG("remap", &remap) call append("$", "timeout\tallow timing out halfway into a mapping") call <SID>BinOptionG("to", &to) call append("$", "ttimeout\tallow timing out halfway into a key code") diff --git a/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim b/runtime/pack/dist/opt/termdebug/plugin/termdebug.vim index 4f2f7b942d..4cd4a200dd 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 May 09 +" Last Change: 2022 May 23 " " WORK IN PROGRESS - The basics works stable, more to come " Note: In general you need at least GDB 7.12 because this provides the @@ -71,11 +71,6 @@ set cpo&vim command -nargs=* -complete=file -bang Termdebug call s:StartDebug(<bang>0, <f-args>) command -nargs=+ -complete=file -bang TermdebugCommand call s:StartDebugCommand(<bang>0, <f-args>) -" Name of the gdb command, defaults to "gdb". -if !exists('g:termdebugger') - let g:termdebugger = 'gdb' -endif - let s:pc_id = 12 let s:asm_id = 13 let s:break_id = 14 " breakpoint number is added to this @@ -105,8 +100,17 @@ call s:Highlight(1, '', &background) hi default debugBreakpoint term=reverse ctermbg=red guibg=red hi default debugBreakpointDisabled term=reverse ctermbg=gray guibg=gray +" Get the command to execute the debugger as a list, defaults to ["gdb"]. func s:GetCommand() - return type(g:termdebugger) == v:t_list ? copy(g:termdebugger) : [g:termdebugger] + if exists('g:termdebug_config') + let cmd = get(g:termdebug_config, 'command', 'gdb') + elseif exists('g:termdebugger') + let cmd = g:termdebugger + else + let cmd = 'gdb' + endif + + return type(cmd) == v:t_list ? copy(cmd) : [cmd] endfunc func s:StartDebug(bang, ...) @@ -177,12 +181,10 @@ func s:StartDebug_internal(dict) call s:StartDebug_term(a:dict) endif - if exists('g:termdebug_disasm_window') - if g:termdebug_disasm_window - let curwinid = win_getid(winnr()) - call s:GotoAsmwinOrCreateIt() - call win_gotoid(curwinid) - endif + if s:GetDisasmWindow() + let curwinid = win_getid(winnr()) + call s:GotoAsmwinOrCreateIt() + call win_gotoid(curwinid) endif if exists('#User#TermdebugStartPost') @@ -252,18 +254,28 @@ func s:StartDebug_term(dict) let proc_args = get(a:dict, 'proc_args', []) let gdb_cmd = s:GetCommand() - " Add -quiet to avoid the intro message causing a hit-enter prompt. - let gdb_cmd += ['-quiet'] - " Disable pagination, it causes everything to stop at the gdb - let gdb_cmd += ['-iex', 'set pagination off'] - " Interpret commands while the target is running. This should usually only - " be exec-interrupt, since many commands don't work properly while the - " target is running (so execute during startup). - let gdb_cmd += ['-iex', 'set mi-async on'] - " Open a terminal window to run the debugger. - let gdb_cmd += ['-tty', pty] - " Command executed _after_ startup is done, provides us with the necessary feedback - let gdb_cmd += ['-ex', 'echo startupdone\n'] + + if exists('g:termdebug_config') && has_key(g:termdebug_config, 'command_add_args') + let gdb_cmd = g:termdebug_config.command_add_args(gdb_cmd, pty) + else + " Add -quiet to avoid the intro message causing a hit-enter prompt. + let gdb_cmd += ['-quiet'] + " Disable pagination, it causes everything to stop at the gdb + let gdb_cmd += ['-iex', 'set pagination off'] + " Interpret commands while the target is running. This should usually only + " be exec-interrupt, since many commands don't work properly while the + " target is running (so execute during startup). + let gdb_cmd += ['-iex', 'set mi-async on'] + " Open a terminal window to run the debugger. + let gdb_cmd += ['-tty', pty] + " Command executed _after_ startup is done, provides us with the necessary + " feedback + let gdb_cmd += ['-ex', 'echo startupdone\n'] + endif + + if exists('g:termdebug_config') && has_key(g:termdebug_config, 'command_filter') + let gdb_cmd = g:termdebug_config.command_filter(gdb_cmd) + endif " Adding arguments requested by the user let gdb_cmd += gdb_args @@ -871,7 +883,13 @@ func s:InstallCommands() command Asm call s:GotoAsmwinOrCreateIt() command Winbar call s:InstallWinbar() - if !exists('g:termdebug_map_K') || g:termdebug_map_K + let map = 1 + if exists('g:termdebug_config') + let map = get(g:termdebug_config, 'map_K', 1) + elseif exists('g:termdebug_map_K') + let map = g:termdebug_map_K + endif + if map " let s:k_map_saved = maparg('K', 'n', 0, 1) let s:k_map_saved = {} for map in nvim_get_keymap('n') @@ -1280,6 +1298,26 @@ func s:GotoSourcewinOrCreateIt() endif endfunc +func s:GetDisasmWindow() + if exists('g:termdebug_config') + return get(g:termdebug_config, 'disasm_window', 0) + endif + if exists('g:termdebug_disasm_window') + return g:termdebug_disasm_window + endif + return 0 +endfunc + +func s:GetDisasmWindowHeight() + if exists('g:termdebug_config') + return get(g:termdebug_config, 'disasm_window_height', 0) + endif + if exists('g:termdebug_disasm_window') && g:termdebug_disasm_window > 1 + return g:termdebug_disasm_window + endif + return 0 +endfunc + func s:GotoAsmwinOrCreateIt() if !win_gotoid(s:asmwin) if win_gotoid(s:sourcewin) @@ -1303,10 +1341,8 @@ func s:GotoAsmwinOrCreateIt() exe 'file Termdebug-asm-listing' endif - if exists('g:termdebug_disasm_window') - if g:termdebug_disasm_window > 1 - exe 'resize ' . g:termdebug_disasm_window - endif + if s:GetDisasmWindowHeight() > 0 + exe 'resize ' .. s:GetDisasmWindowHeight() endif endif |