diff --git a/.github/CODEOWNERS_vim b/.github/CODEOWNERS_vim index 139a1b6611..0bfb1a9937 100644 --- a/.github/CODEOWNERS_vim +++ b/.github/CODEOWNERS_vim @@ -73,6 +73,7 @@ runtime/ftplugin/awk.vim @dkearns runtime/ftplugin/basic.vim @dkearns runtime/ftplugin/bst.vim @tpope runtime/ftplugin/cfg.vim @chrisbra +runtime/ftplugin/csh.vim @dkearns runtime/ftplugin/css.vim @dkearns runtime/ftplugin/cucumber.vim @tpope runtime/ftplugin/eiffel.vim @dkearns @@ -111,8 +112,10 @@ runtime/ftplugin/sass.vim @tpope runtime/ftplugin/scss.vim @tpope runtime/ftplugin/spec.vim @ignatenkobrain runtime/ftplugin/systemverilog.vim @Kocha +runtime/ftplugin/tcsh.vim @dkearns runtime/ftplugin/tidy.vim @dkearns runtime/ftplugin/tmux.vim @ericpruitt +runtime/ftplugin/toml.vim @averms runtime/ftplugin/typescript.vim @dkearns runtime/ftplugin/typescriptreact.vim @dkearns runtime/ftplugin/xml.vim @chrisbra @@ -151,6 +154,7 @@ runtime/indent/scss.vim @tpope runtime/indent/sh.vim @chrisbra runtime/indent/systemverilog.vim @Kocha runtime/indent/tcl.vim @dkearns +runtime/indent/tcsh.vim @dkearns runtime/indent/teraterm.vim @k-takata runtime/indent/xml.vim @chrisbra runtime/indent/zsh.vim @chrisbra @@ -238,10 +242,12 @@ runtime/syntax/sshdconfig.vim @Jakuje runtime/syntax/sudoers.vim @e-kwsm runtime/syntax/systemverilog.vim @Kocha runtime/syntax/tags.vim @cecamp +runtime/syntax/tcsh.vim @dkearns runtime/syntax/teraterm.vim @k-takata runtime/syntax/tex.vim @cecamp runtime/syntax/tidy.vim @dkearns runtime/syntax/tmux.vim @ericpruitt +runtime/syntax/toml.vim @averms runtime/syntax/vim.vim @cecamp runtime/syntax/wget.vim @dkearns runtime/syntax/xbl.vim @dkearns diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md deleted file mode 100644 index eb9ae4d0ce..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -name: Bug report -about: Create a report to help us improve Vim -title: '' -labels: '' - ---- - -_Instructions: Replace the template text and remove irrelevant text (including this line)_ - -**Describe the bug** -A clear and concise description of what the bug is. -(Issues related to the runtime files should be reported to their maintainer, check the file header.) - -**To Reproduce** -Detailed steps to reproduce the behavior: -1. Run `vim --clean` (or `gvim --clean`, etc.) -2. Edit `filename` -3. Type '....' -4. Describe the error - -**Expected behavior** -A clear and concise description of what you expected to happen. - -**Screenshots** -If applicable, copy/paste the text or add screenshots to help explain your problem. - -**Environment (please complete the following information):** - - Vim version [e.g. 8.1.1234] (Or paste the result of `vim --version`.) - - OS: [e.g. Ubuntu 18.04, Windows 10 1809, macOS 10.14] - - Terminal: [e.g. GNOME Terminal, mintty, iTerm2, tmux, GNU screen] (Use GUI if you use the GUI.) - -**Additional context** -Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 0000000000..b4e3128f3d --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,47 @@ +--- +name: Bug report +description: Create a report to help us improve Vim. +labels: [bug] + +body: + - type: markdown + attributes: + value: | + Thanks for reporting issues of Vim! + + To make it easier for us to help you please enter detailed information below. + - type: textarea + attributes: + label: Steps to reproduce + placeholder: | + 1. + 2. + 3. + 4. + validations: + required: true + - type: textarea + attributes: + label: Expected behaviour + placeholder: A clear and concise description of what you expected to happen. + validations: + required: true + - type: input + attributes: + label: Operating system + description: > + Your operating system name, version and desktop environment. + validations: + required: true + - type: input + attributes: + label: Version of Vim + description: > + The name of your development environment, version. [e.g. GNOME Terminal (v0.0.0000)] + validations: + required: true + - type: textarea + attributes: + label: Logs and stack traces + placeholder: Insert log or other text here (if necessary) + render: shell diff --git a/runtime/doc/autocmd.txt b/runtime/doc/autocmd.txt index 35b4589899..350bd99772 100644 --- a/runtime/doc/autocmd.txt +++ b/runtime/doc/autocmd.txt @@ -710,7 +710,7 @@ EncodingChanged Fires off after the 'encoding' option has been *FileAppendCmd* FileAppendCmd Before appending to a file. Should do the appending to the file. Use the '[ and '] - marks for the range of lines.|Cmd-event| + marks for the range of lines. |Cmd-event| *FileAppendPost* FileAppendPost After appending to a file. *FileAppendPre* @@ -838,7 +838,7 @@ FilterReadPre Before reading a file from a filter command. *FilterWritePost* FilterWritePost After writing a file for a filter command or making a diff with an external diff (see - DiffUpdated for internal diff). + |DiffUpdated| for internal diff). Vim checks the pattern against the name of the current buffer as with FilterWritePre. Not triggered when 'shelltemp' is off. @@ -1202,9 +1202,9 @@ TextYankPost After text has been yanked or deleted in the register, as a list of lines, like with: > getreg(r, 1, 1) -< regname Name of the |register| or - empty string for the unnamed - register. +< regname Name of the register or empty + string for the unnamed + register, see |registers|. regtype Type of the register, see |getregtype()|. visual True if the operation is diff --git a/runtime/doc/change.txt b/runtime/doc/change.txt index 084eed037d..14b2cb5a71 100644 --- a/runtime/doc/change.txt +++ b/runtime/doc/change.txt @@ -1184,9 +1184,6 @@ a register, a paste on a visual selected area will paste that single line on each of the selected lines (thus replacing the blockwise selected region by a block of the pasted line). -Use |zP|/|zp| to paste a blockwise yanked register without appending trailing -spaces. - *blockwise-register* If you use a blockwise Visual mode command to get the text into the register, the block of text will be inserted before ("P") or after ("p") the cursor @@ -1197,6 +1194,9 @@ this happen. However, if the width of the block is not a multiple of a width and the text after the inserted block contains s, that text may be misaligned. +Use |zP|/|zp| to paste a blockwise yanked register without appending trailing +spaces. + Note that after a characterwise yank command, Vim leaves the cursor on the first yanked character that is closest to the start of the buffer. This means that "yl" doesn't move the cursor, but "yh" moves the cursor one character diff --git a/runtime/doc/cmdline.txt b/runtime/doc/cmdline.txt index 0c472bb61a..bf61024875 100644 --- a/runtime/doc/cmdline.txt +++ b/runtime/doc/cmdline.txt @@ -803,7 +803,7 @@ three lines: > 3:d is translated into: .,.+2d < -Visual Mode and Range +Visual Mode and Range *v_:* {Visual}: Starts a command-line with the Visual selected lines as a range. The code `:'<,'>` is used for this range, which makes diff --git a/runtime/doc/digraph.txt b/runtime/doc/digraph.txt index 0801e3af15..3610380bee 100644 --- a/runtime/doc/digraph.txt +++ b/runtime/doc/digraph.txt @@ -351,8 +351,8 @@ $ DO 0x24 36 DOLLAR SIGN þ th 0xfe 254 LATIN SMALL LETTER THORN (Icelandic) ÿ y: 0xff 255 LATIN SMALL LETTER Y WITH DIAERESIS -If your Vim is compiled with |multibyte| support and you are using a multibyte -'encoding', Vim provides this enhanced set of additional digraphs: +If you are using a |multibyte| 'encoding', Vim provides this enhanced set of +additional digraphs: *digraph-table-mbyte* char digraph hex dec official name ~ diff --git a/runtime/doc/editing.txt b/runtime/doc/editing.txt index 858fc427f9..cea0e443d8 100644 --- a/runtime/doc/editing.txt +++ b/runtime/doc/editing.txt @@ -1,4 +1,4 @@ -*editing.txt* For Vim version 8.2. Last change: 2021 Oct 04 +*editing.txt* For Vim version 8.2. Last change: 2021 Oct 16 VIM REFERENCE MANUAL by Bram Moolenaar @@ -1329,26 +1329,26 @@ present in 'cpoptions' and "!" is not used in the command. other tabs and for windows in the current tab that have their own window-local directory. - *:tch* *:tchdir* -:tch[dir][!] Same as |:tcd|. - *:tcd-* :tc[d][!] - Change to the previous current directory, before the last ":tcd {path}" command. + *:tch* *:tchdir* +:tch[dir][!] Same as |:tcd|. + *:lc* *:lcd* :lc[d][!] {path} Like |:cd|, but only set the current directory when the cursor is in the current window. The current directory for other windows is not changed, switching to another window will stop using {path}. - *:lch* *:lchdir* -:lch[dir][!] Same as |:lcd|. - *:lcd-* :lcd[!] - Change to the previous current directory, before the last ":lcd {path}" command. + *:lch* *:lchdir* +:lch[dir][!] Same as |:lcd|. + *:pw* *:pwd* *E187* :pw[d] Print the current directory name. Also see |getcwd()|. @@ -1375,14 +1375,14 @@ change anything for the current directory. When a |:lcd| command has been used for a window, the specified directory becomes the current directory for that window. Windows where the |:lcd| command has not been used stick to the global or tab-local current directory. -When jumping to another window the current directory will become the last +When jumping to another window the current directory is changed to the last specified local current directory. If none was specified, the global or tab-local current directory is used. When a |:tcd| command has been used for a tab page, the specified directory becomes the current directory for the current tab page and the current window. The current directory of other tab pages is not affected. When jumping to -another tab page, the current directory will become the last specified local +another tab page, the current directory is changed to the last specified local directory for that tab page. If the current tab has no local current directory the global current directory is used. @@ -1676,6 +1676,11 @@ It is also possible that you modified the file yourself, from another edit session or with another command (e.g., a filter command). Then you will know which version of the file you want to keep. +The accuracy of the time check depends on the filesystem. On Unix it is +usually sub-second. With old file sytems and on MS-Windows it is normally one +second. Use has('nanotime') check if sub-second time stamp checks are +available. + There is one situation where you get the message while there is nothing wrong: On a Win32 system on the day daylight saving time starts. There is something in the Win32 libraries that confuses Vim about the hour time difference. The diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index 06df51163e..f594d6f97e 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1,4 +1,4 @@ -*eval.txt* For Vim version 8.2. Last change: 2021 Oct 04 +*eval.txt* For Vim version 8.2. Last change: 2021 Oct 14 VIM REFERENCE MANUAL by Bram Moolenaar @@ -2561,7 +2561,7 @@ deletebufline({buf}, {first} [, {last}]) did_filetype() Number |TRUE| if FileType autocmd event used diff_filler({lnum}) Number diff filler lines about {lnum} diff_hlID({lnum}, {col}) Number diff highlighting at {lnum}/{col} -digraph_get({chars}) String get the digraph of {chars} +digraph_get({chars}) String get the |digraph| of {chars} digraph_getlist([{listall}]) List get all |digraph|s digraph_set({chars}, {digraph}) Boolean register |digraph| digraph_setlist({digraphlist}) Boolean register multiple |digraph|s @@ -12250,6 +12250,7 @@ multi_byte_encoding 'encoding' is set to a multibyte encoding. multi_byte_ime Compiled with support for IME input method. multi_lang Compiled with support for multiple languages. mzscheme Compiled with MzScheme interface |mzscheme|. +nanotime Compiled with sub-second time stamp checks. netbeans_enabled Compiled with support for |netbeans| and connected. netbeans_intg Compiled with support for |netbeans|. num64 Compiled with 64-bit |Number| support. diff --git a/runtime/doc/help.txt b/runtime/doc/help.txt index 44e95e9ac0..3bf9ccc017 100644 --- a/runtime/doc/help.txt +++ b/runtime/doc/help.txt @@ -88,6 +88,7 @@ Tuning Vim ~ |usr_43.txt| Using filetypes |usr_44.txt| Your own syntax highlighted |usr_45.txt| Select your language +|usr_46.txt| Write plugins using Vim9 script Making Vim Run ~ |usr_90.txt| Installing Vim diff --git a/runtime/doc/insert.txt b/runtime/doc/insert.txt index 31b820f7b1..7788c0b717 100644 --- a/runtime/doc/insert.txt +++ b/runtime/doc/insert.txt @@ -824,6 +824,9 @@ CTRL-X CTRL-K Search the files given with the 'dictionary' option CTRL-P Search backwards for next matching keyword. This keyword replaces the previous matching keyword. + +Completing words in 'thesaurus' *compl-thesaurus* + *i_CTRL-X_CTRL-T* CTRL-X CTRL-T Works as CTRL-X CTRL-K, but in a special way. It uses the 'thesaurus' option instead of 'dictionary'. If a @@ -832,16 +835,6 @@ CTRL-X CTRL-T Works as CTRL-X CTRL-K, but in a special way. It uses matches, even though they don't complete the word. Thus a word can be completely replaced. - For an example, imagine the 'thesaurus' file has a - line like this: > - angry furious mad enraged -< Placing the cursor after the letters "ang" and typing - CTRL-X CTRL-T would complete the word "angry"; - subsequent presses would change the word to "furious", - "mad" etc. - Other uses include translation between two languages, - or grouping API functions by keyword. - CTRL-T or CTRL-N Search forward for next matching keyword. This keyword replaces the previous matching keyword. @@ -849,6 +842,61 @@ CTRL-X CTRL-T Works as CTRL-X CTRL-K, but in a special way. It uses CTRL-P Search backwards for next matching keyword. This keyword replaces the previous matching keyword. +In the file used by the 'thesaurus' option each line in the file should +contain words with similar meaning, separated by non-keyword characters (white +space is preferred). Maximum line length is 510 bytes. + +For an example, imagine the 'thesaurus' file has a line like this: > + angry furious mad enraged + + + func Thesaur(findstart, base) + if a:findstart + let line = getline('.') + let start = col('.') - 1 + while start > 0 && line[start - 1] =~ '\a' + let start -= 1 + endwhile + return start + else + let res = [] + let h = '' + for l in split(system('aiksaurus '.shellescape(a:base)), '\n') + if l[:3] == '=== ' + let h = substitute(l[4:], ' =*$', '', '') + elseif l[0] =~ '\a' + call extend(res, map(split(l, ', '), {_, val -> {'word': val, 'menu': '('.h.')'}})) + endif + endfor + return res + endif + endfunc + + if has('patch-8.2.3520') + set thesaurusfunc=Thesaur + endif + Completing keywords in the current and included files *compl-keyword* @@ -1052,7 +1100,7 @@ CTRL-X CTRL-Z Stop completion without changing the text. FUNCTIONS FOR FINDING COMPLETIONS *complete-functions* -This applies to 'completefunc' and 'omnifunc'. +This applies to 'completefunc', 'thesaurusfunc' and 'omnifunc'. The function is called in two different ways: - First the function is called to find the start of the text to be completed. diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 62c2b357f7..977655840b 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -2425,7 +2425,7 @@ A jump table for the options with a short description can be found at |Q_op|. xchacha20 XChaCha20 Cipher with Poly1305 Message Authentication Code. Medium strong till strong encryption. Encryption is provided by the libsodium library, it - requires Vim to be built with |+sodium| + requires Vim to be built with |+sodium|. It adds a seed and a message authentication code (MAC) to the file. This needs at least a Vim 8.2.3022 to read the encrypted file. @@ -3625,8 +3625,8 @@ A jump table for the options with a short description can be found at |Q_op|. systems without an fsync() implementation, this variable is always off. Also see 'swapsync' for controlling fsync() on swap files. - 'fsync' also applies to |writefile()|, unless a flag is used to - overrule it. + 'fsync' also applies to |writefile()| (unless a flag is used to + overrule it) and when writing undo files (see |undo-persistence|). This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. @@ -3883,6 +3883,18 @@ A jump table for the options with a short description can be found at |Q_op|. screen. Set it to a negative value to allow windows taller than the screen. + *'guiligatures'* *'gli'* *E1243* +'guiligatures' 'gli' string (default "") + global + {only for GTK GUI} + List of ASCII characters that, when combined together, can create more + complex shapes. Each character must be a printable ASCII character + with a value in the 32-127 range. + Example: > + :set guiligatures=!\"#$%&()*+-./:<=>?@[]^_{\|~ +< Changing this option updates screen output immediately. Set it to an + empty string to disable ligatures. + *'guioptions'* *'go'* 'guioptions' 'go' string (default "egmrLtT" (MS-Windows, "t" is removed in |defaults.vim|), @@ -5073,6 +5085,13 @@ A jump table for the options with a short description can be found at |Q_op|. be used when 'encoding' is "utf-8", otherwise only printable characters are allowed. All characters must be single width. + Each character can be specified as hex: > + set listchars=eol:\\x24 + set listchars=eol:\\u21b5 + set listchars=eol:\\U000021b5 +< Note that a double backslash is used. The number of hex characters + must be exactly 2 for \\x, 4 for \\u and 8 for \\U. + Examples: > :set lcs=tab:>-,trail:- :set lcs=tab:>-,eol:<,nbsp:% @@ -7538,13 +7557,13 @@ A jump table for the options with a short description can be found at |Q_op|. return value of expr contains % items they will get expanded. The expression can contain the } character, the end of expression is denoted by %}. - The For example: > + For example: > func! Stl_filename() abort return "%t" endfunc < `stl=%{Stl_filename()}` results in `"%t"` `stl=%{%Stl_filename()%}` results in `"Name of current file"` - } - End of `{%` expression + %} - End of `{%` expression ( - Start of item group. Can be used for setting the width and alignment of a section. Must be followed by %) somewhere. ) - End of item group. No width fields allowed. @@ -8141,25 +8160,30 @@ A jump table for the options with a short description can be found at |Q_op|. 'thesaurus' 'tsr' string (default "") global or local to buffer |global-local| List of file names, separated by commas, that are used to lookup words - for thesaurus completion commands |i_CTRL-X_CTRL-T|. + for thesaurus completion commands |i_CTRL-X_CTRL-T|. See + |compl-thesaurus|. - Each line in the file should contain words with similar meaning, - separated by non-keyword characters (white space is preferred). - Maximum line length is 510 bytes. - - An English word list was added to this github issue: - https://github.com/vim/vim/issues/629#issuecomment-443293282 - Unpack thesaurus_pkg.zip, put the thesaurus.txt file somewhere, e.g. - ~/.vim/thesaurus/english.txt, and the 'thesaurus' option to this file - name. + This option is not used if 'thesaurusfunc' is set, either for the + buffer or globally. To include a comma in a file name precede it with a backslash. Spaces after a comma are ignored, otherwise spaces are included in the file - name. See |option-backslash| about using backslashes. - The use of |:set+=| and |:set-=| is preferred when adding or removing - directories from the list. This avoids problems when a future version - uses another default. - Backticks cannot be used in this option for security reasons. + name. See |option-backslash| about using backslashes. The use of + |:set+=| and |:set-=| is preferred when adding or removing directories + from the list. This avoids problems when a future version uses + another default. Backticks cannot be used in this option for security + reasons. + + *'thesaurusfunc'* *tsrfu'* +'thesaurusfunc' 'tsrfu' string (default: empty) + global or local to buffer |global-local| + {not available when compiled without the |+eval| + feature} + This option specifies a function to be used for thesaurus completion + with CTRL-X CTRL-T. |i_CTRL-X_CTRL-T| See |compl-thesaurusfunc|. + + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. *'tildeop'* *'top'* *'notildeop'* *'notop'* 'tildeop' 'top' boolean (default off) diff --git a/runtime/doc/pattern.txt b/runtime/doc/pattern.txt index c52708e455..8f6d77e414 100644 --- a/runtime/doc/pattern.txt +++ b/runtime/doc/pattern.txt @@ -932,7 +932,7 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on): \%.l Matches at the cursor line. \%<.l Matches above the cursor line. \%>.l Matches below the cursor line. - These three can be used to match specific lines in a buffer. The "23" + These six can be used to match specific lines in a buffer. The "23" can be any line number. The first line is 1. WARNING: When inserting or deleting lines Vim does not automatically update the matches. This means Syntax highlighting quickly becomes @@ -953,16 +953,15 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on): \%.c Matches at the cursor column. \%<.c Matches before the cursor column. \%>.c Matches after the cursor column. - These three can be used to match specific columns in a buffer or - string. The "23" can be any column number. The first column is 1. - Actually, the column is the byte number (thus it's not exactly right - for multibyte characters). + These six can be used to match specific columns in a buffer or string. + The "23" can be any column number. The first column is 1. Actually, + the column is the byte number (thus it's not exactly right for + multibyte characters). WARNING: When inserting or deleting text Vim does not automatically update the matches. This means Syntax highlighting quickly becomes wrong. Also when referring to the cursor position (".") and the cursor moves the display isn't updated for this change. An update is done when using the |CTRL-L| command (the whole screen is updated). - Example, to highlight the column where the cursor currently is: > :exe '/\%' . col(".") . 'c' < Alternatively use: > @@ -980,8 +979,8 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on): \%.v Matches at the current virtual column. \%<.v Matches before the current virtual column. \%>.v Matches after the current virtual column. - These three can be used to match specific virtual columns in a buffer - or string. When not matching with a buffer in a window, the option + These six can be used to match specific virtual columns in a buffer or + string. When not matching with a buffer in a window, the option values of the current window are used (e.g., 'tabstop'). The "23" can be any column number. The first column is 1. Note that some virtual column positions will never match, because they @@ -1012,7 +1011,7 @@ $ At end of pattern or in front of "\|", "\)" or "\n" ('magic' on): /.*\%17v < Column 17 is highlighted by 'hlsearch' because there is another match where ".*" matches zero characters. -< + Character classes: \i identifier character (see 'isident' option) */\i* diff --git a/runtime/doc/quickref.txt b/runtime/doc/quickref.txt index f994261088..1f7ecb683e 100644 --- a/runtime/doc/quickref.txt +++ b/runtime/doc/quickref.txt @@ -955,6 +955,7 @@ Short explanation of each option: *option-list* 'textmode' 'tx' obsolete, use 'fileformat' '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 'tildeop' 'top' tilde command "~" behaves like an operator 'timeout' 'to' time out on mappings and key codes 'timeoutlen' 'tm' time out time in milliseconds diff --git a/runtime/doc/terminal.txt b/runtime/doc/terminal.txt index 2f2556a508..510f1c399b 100644 --- a/runtime/doc/terminal.txt +++ b/runtime/doc/terminal.txt @@ -168,9 +168,6 @@ terminal window will start with a white or black background. To use a different color the Terminal highlight group can be used, for example: > hi Terminal ctermbg=lightgrey ctermfg=blue guibg=lightgrey guifg=blue -The highlight needs to be defined before the terminal is created. Doing it -later, or setting 'wincolor', will only have effect when the program running -in the terminal displays text or clears the terminal. Instead of Terminal another group can be specified with the "term_highlight" option for `term_start()`. diff --git a/runtime/doc/testing.txt b/runtime/doc/testing.txt index 5094d51fdc..d064dc1bf0 100644 --- a/runtime/doc/testing.txt +++ b/runtime/doc/testing.txt @@ -85,14 +85,14 @@ test_getvalue({name}) *test_getvalue()* test_gui_drop_files({list}, {row}, {col}, {mods}) Drop one or more files in {list} in the window at {row}, {col}. This function only works when the GUI is running and the - |drag-n-drop| feature is present. - + |drop_file| feature is present. + The supported values for {mods} are: 0x4 Shift 0x8 Alt 0x10 Ctrl - The files are added to the argument list and the first file in - {list} is edited in the window. See |drag-n-drop| for more + The files are added to the |argument-list| and the first file + in {list} is edited in the window. See |drag-n-drop| for more information. *test_gui_mouse_event()* diff --git a/runtime/doc/todo.txt b/runtime/doc/todo.txt index 5959de360d..558493b53e 100644 --- a/runtime/doc/todo.txt +++ b/runtime/doc/todo.txt @@ -1,4 +1,4 @@ -*todo.txt* For Vim version 8.2. Last change: 2021 Sep 22 +*todo.txt* For Vim version 8.2. Last change: 2021 Oct 15 VIM REFERENCE MANUAL by Bram Moolenaar @@ -38,12 +38,13 @@ browser use: https://github.com/vim/vim/issues/1234 *known-bugs* -------------------- Known bugs and current work ----------------------- -Flaky test op Windows: -From test_vim9_script.vim: - Found errors in Test_no_unknown_error_after_error(): - command line..script D:/a/vim/vim/src2/testdir/runtest.vim[486]..function RunTheTest[44]..Test_no_unknown_error_after_error line 22: Expected 'E1012:' but got 'E684: list index out of range: 0': so Xdef +Remove s:flaky_tests from runtest.vim, set g:test_is_flaky in each test. Vim9 - Make everything work: +- "filter #pat# ls" should work, #pat# is not a comment + vim9script + edit foobar + filter #foobar# ls - Check TODO items in vim9compile.c and vim9execute.c - use CheckLegacyAndVim9Success(lines) in many more places - For builtin functions using tv_get_string*() use check_for_string() to be @@ -629,24 +630,27 @@ Window size changes after closing a tab. (#4741) Problem with colors in terminal window. (Jason Franklin, 2019 May 12) -Lifepillar: Updated/cleaned up color schemes: -https://github.com/lifepillar/vim8-colorschemes. - -Include a few color schemes, based on popularity: -http://www.vim.org/scripts/script_search_results.php?keywords=&script_type=color+scheme&order_by=rating&direction=descending&search=search +Color schemes: +NOTE: modernizing the default colorschemes _AND_ introducing new ones is now +a project in its own right: https://github.com/vim/colorschemes. Feel free to +reach out if you want to lend a hand. +- Lifepillar: Updated/cleaned up color schemes: + https://github.com/lifepillar/vim8-colorschemes. +- Include a few color schemes, based on popularity: + - http://www.vim.org/scripts/script_search_results.php?keywords=&script_type=color+scheme&order_by=rating&direction=descending&search=search http://vimawesome.com/?q=tag:color-scheme -Use names that indicate their appearance (Christian Brabandt, 2017 Aug 3) -- monokai - Xia Crusoe (2017 Aug 4) -- seoul256 - Christian Brabandt (2017 Aug 3) -- gruvbox - Christian Brabandt (2017 Aug 3) (simplified version from - Lifepillar, 2018 Jan 22, #2573) -- janah - Marco Hinz (2017 Aug 4) -- apprentice - Romain Lafourcade (2017 Aug 6) remarks about help file #1964 -Suggested by Hiroki Kokubun: -- [Iceberg](https://github.com/cocopon/iceberg.vim) (my one) -- [hybrid](https://github.com/w0ng/vim-hybrid) -Include solarized color scheme?, it does not support termguicolors. -- Sanitized version of pablo (Lifepillar, 2017 Nov 21) +- Use names that indicate their appearance (Christian Brabandt, 2017 Aug 3) + - monokai - Xia Crusoe (2017 Aug 4) + - seoul256 - Christian Brabandt (2017 Aug 3) + - gruvbox - Christian Brabandt (2017 Aug 3) (simplified version from + Lifepillar, 2018 Jan 22, #2573) + - janah - Marco Hinz (2017 Aug 4) + - apprentice - Romain Lafourcade (2017 Aug 6) remarks about help file #1964 +- Suggested by Hiroki Kokubun: + - [Iceberg](https://github.com/cocopon/iceberg.vim) (my one) + - [hybrid](https://github.com/w0ng/vim-hybrid) +- Include solarized color scheme?, it does not support termguicolors. + - Sanitized version of pablo (Lifepillar, 2017 Nov 21) Bug: "vipgw" does not put cursor back where it belongs. (Jason Franklin, 2019 Mar 5) diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 6bb50c05b4..21af06b13d 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -172,7 +172,7 @@ g8 Print the hex values of the bytes used in the *:z!* :[range]z![+-^.=][count] - Like ":z:", but when [count] is not specified, it + Like ":z", but when [count] is not specified, it defaults to the Vim window height minus one. :[range]z[!]#[+-^.=][count] *:z#* diff --git a/runtime/doc/vim9.txt b/runtime/doc/vim9.txt index b6feebf84f..576456af0e 100644 --- a/runtime/doc/vim9.txt +++ b/runtime/doc/vim9.txt @@ -103,7 +103,7 @@ script and `:def` functions; details are below: writefile(['done'], 'file.txt') - You cannot use `:xit`, `:t`, `:k`, `:append`, `:change`, `:insert`, `:open`, and `:s` or `:d` with only flags. - or curly-braces names. +- You cannot use curly-braces names. - A range before a command must be prefixed with a colon: > :%s/this/that - Executing a register with "@r" does not work, you can prepend a colon or use @@ -206,7 +206,7 @@ When a function argument is optional (it has a default value) passing `v:none` as the argument results in using the default value. This is useful when you want to specify a value for an argument that comes after an argument that should use its default value. Example: > - def MyFunc(one = 'one', last = 'last) + def MyFunc(one = 'one', last = 'last') ... enddef MyFunc(v:none, 'LAST') # first argument uses default value 'one' @@ -631,7 +631,7 @@ at the start of the line indicates line continuation: > | echo 'match' | endif -Note that this means that in heredoc the first line cannot be a bar: > +Note that this means that in heredoc the first line cannot start with a bar: > var lines =<< trim END | this doesn't work END @@ -639,7 +639,7 @@ Either use an empty line at the start or do not use heredoc. Or temporarily add the "C" flag to 'cpoptions': > set cpo+=C var lines =<< trim END - | this doesn't work + | this works END set cpo-=C If the heredoc is inside a function 'cpoptions' must be set before :def and @@ -942,9 +942,22 @@ Ex command ranges need to be prefixed with a colon. > Some Ex commands can be confused with assignments in Vim9 script: > g:name = value # assignment - g:pattern:cmd # invalid command - ERROR :g:pattern:cmd # :global command +To avoid confusion between a `:global` or `:substitute` command and an +expression or assignment, a few separators cannot be used when these commands +are abbreviated to a single character: ':', '-' and '.'. > + g:pattern:cmd # invalid command - ERROR + s:pattern:repl # invalid command - ERROR + g-pattern-cmd # invalid command - ERROR + s-pattern-repl # invalid command - ERROR + g.pattern.cmd # invalid command - ERROR + s.pattern.repl # invalid command - ERROR + +Also, there cannot be a space between the command and the separator: > + g /pattern/cmd # invalid command - ERROR + s /pattern/repl # invalid command - ERROR + Functions defined with `:def` compile the whole function. Legacy functions can bail out, and the following lines are not parsed: > func Maybe() @@ -1105,7 +1118,7 @@ The map argument is a string expression, which is evaluated without the function scope. Instead, use a lambda: > def MapList(): list var list = ['aa', 'bb', 'cc', 'dd'] - return range(1, 2)->map(( _, v) => list[v]) + return range(1, 2)->map((_, v) => list[v]) enddef The same is true for commands that are not compiled, such as `:global`. @@ -1309,16 +1322,16 @@ an error, thus breaking backwards compatibility. For example: - Using a string value when setting a number option. - Using a number where a string is expected. *E1024* -One consequence is that the item type of a list or dict given to map() must +One consequence is that the item type of a list or dict given to |map()| must not change. This will give an error in Vim9 script: > - vim9 echo map([1, 2, 3], (i, v) => 'item ' .. i) + echo map([1, 2, 3], (i, v) => 'item ' .. i) E1012: Type mismatch; expected number but got string -Instead use |mapnew(): > - vim9 echo mapnew([1, 2, 3], (i, v) => 'item ' .. i) +Instead use |mapnew()|: > + echo mapnew([1, 2, 3], (i, v) => 'item ' .. i) ['item 0', 'item 1', 'item 2'] If the item type was determined to be "any" it can change to a more specific -type. E.g. when a list of mixed types gets changed to a list of numbers: > +type. E.g. when a list of mixed types gets changed to a list of strings: > var mylist = [1, 2.0, '3'] # typename(mylist) == "list" map(mylist, (i, v) => 'item ' .. i) diff --git a/runtime/filetype.vim b/runtime/filetype.vim index 9b18b1b73a..3621f29e25 100644 --- a/runtime/filetype.vim +++ b/runtime/filetype.vim @@ -707,6 +707,7 @@ au BufNewFile,BufRead *.gpi setf gnuplot " Go (Google) au BufNewFile,BufRead *.go setf go +au BufNewFile,BufRead Gopkg.lock setf toml " GrADS scripts au BufNewFile,BufRead *.gs setf grads @@ -1290,7 +1291,7 @@ au BufNewFile,BufRead *.rcp setf pilrc au BufNewFile,BufRead .pinerc,pinerc,.pinercex,pinercex setf pine " Pipenv Pipfiles -au BufNewFile,BufRead Pipfile setf config +au BufNewFile,BufRead Pipfile setf toml au BufNewFile,BufRead Pipfile.lock setf json " PL/1, PL/I @@ -1524,6 +1525,7 @@ au BufNewFile,BufRead [rR]antfile,*.rant,[rR]akefile,*.rake setf ruby " Rust au BufNewFile,BufRead *.rs setf rust +au BufNewFile,BufRead Cargo.lock,*/.cargo/config,*/.cargo/credentials setf toml " S-lang (or shader language, or SmallLisp) au BufNewFile,BufRead *.sl setf slang @@ -2305,6 +2307,9 @@ au BufNewFile,BufRead .tcshrc* call dist#ft#SetFileTypeShell("tcsh") " csh scripts ending in a star au BufNewFile,BufRead .login*,.cshrc* call dist#ft#CSH() +" tmux configuration with arbitrary extension +au BufNewFile,BufRead {.,}tmux*.conf* setf tmux + " VHDL au BufNewFile,BufRead *.vhdl_[0-9]* call s:StarSetf('vhdl') diff --git a/runtime/ftplugin/context.vim b/runtime/ftplugin/context.vim index 10f1ae1648..37f7240d7b 100644 --- a/runtime/ftplugin/context.vim +++ b/runtime/ftplugin/context.vim @@ -2,7 +2,7 @@ " Language: ConTeXt typesetting engine " Maintainer: Nicola Vitacolonna " Former Maintainers: Nikolai Weibull -" Latest Revision: 2016 Oct 30 +" Latest Revision: 2021 Oct 15 if exists("b:did_ftplugin") finish @@ -17,7 +17,6 @@ if !exists('current_compiler') endif let b:undo_ftplugin = "setl com< cms< def< inc< sua< fo< ofu<" - \ . "| unlet! b:match_ignorecase b:match_words b:match_skip" setlocal comments=b:%D,b:%C,b:%M,:% commentstring=%\ %s formatoptions+=tjcroql2 if get(b:, 'context_metapost', get(g:, 'context_metapost', 1)) @@ -35,11 +34,12 @@ let &l:include = '^\s*\\\%(input\|component\|product\|project\|environment\)' setlocal suffixesadd=.tex -if exists("loaded_matchit") +if exists("loaded_matchit") && !exists("b:match_words") let b:match_ignorecase = 0 let b:match_skip = 'r:\\\@ [[ :call move_around(v:count1, "beginsection", "bW", v:false) -vnoremap [[ :call move_around(v:count1, "beginsection", "bW", v:true) -nnoremap ]] :call move_around(v:count1, "beginsection", "W", v:false) -vnoremap ]] :call move_around(v:count1, "beginsection", "W", v:true) -nnoremap [] :call move_around(v:count1, "endsection", "bW", v:false) -vnoremap [] :call move_around(v:count1, "endsection", "bW", v:true) -nnoremap ][ :call move_around(v:count1, "endsection", "W", v:false) -vnoremap ][ :call move_around(v:count1, "endsection", "W", v:true) -nnoremap [{ :call move_around(v:count1, "beginblock", "bW", v:false) -vnoremap [{ :call move_around(v:count1, "beginblock", "bW", v:true) -nnoremap ]} :call move_around(v:count1, "endblock", "W", v:false) -vnoremap ]} :call move_around(v:count1, "endblock", "W", v:true) +if !exists("no_plugin_maps") && !exists("no_context_maps") + " Move around macros. + nnoremap [[ :call move_around(v:count1, "beginsection", "bW", v:false) + vnoremap [[ :call move_around(v:count1, "beginsection", "bW", v:true) + nnoremap ]] :call move_around(v:count1, "beginsection", "W", v:false) + vnoremap ]] :call move_around(v:count1, "beginsection", "W", v:true) + nnoremap [] :call move_around(v:count1, "endsection", "bW", v:false) + vnoremap [] :call move_around(v:count1, "endsection", "bW", v:true) + nnoremap ][ :call move_around(v:count1, "endsection", "W", v:false) + vnoremap ][ :call move_around(v:count1, "endsection", "W", v:true) + nnoremap [{ :call move_around(v:count1, "beginblock", "bW", v:false) + vnoremap [{ :call move_around(v:count1, "beginblock", "bW", v:true) + nnoremap ]} :call move_around(v:count1, "endblock", "W", v:false) + vnoremap ]} :call move_around(v:count1, "endblock", "W", v:true) + + let b:undo_ftplugin .= " | sil! exe 'nunmap [[' | sil! exe 'vunmap [['" . + \ " | sil! exe 'nunmap ]]' | sil! exe 'vunmap ]]'" . + \ " | sil! exe 'nunmap []' | sil! exe 'vunmap []'" . + \ " | sil! exe 'nunmap ][' | sil! exe 'vunmap ]['" . + \ " | sil! exe 'nunmap [{' | sil! exe 'vunmap [{'" . + \ " | sil! exe 'nunmap ]}' | sil! exe 'vunmap ]}'" +end " Other useful mappings if get(g:, 'context_mappings', 1) @@ -81,16 +90,22 @@ if get(g:, 'context_mappings', 1) call cursor(search(s:tp_regex, 'W') - 1, 1) endf - " Reflow paragraphs with commands like gqtp ("gq TeX paragraph") - onoremap tp :call tp() - " Select TeX paragraph - vnoremap tp :call tp() + if !exists("no_plugin_maps") && !exists("no_context_maps") + " Reflow paragraphs with commands like gqtp ("gq TeX paragraph") + onoremap tp :call tp() + " Select TeX paragraph + vnoremap tp :call tp() - " $...$ text object - onoremap i$ :normal! T$vt$ - onoremap a$ :normal! F$vf$ - vnoremap i$ T$ot$ - vnoremap a$ F$of$ + " $...$ text object + onoremap i$ :normal! T$vt$ + onoremap a$ :normal! F$vf$ + vnoremap i$ T$ot$ + vnoremap a$ F$of$ + + let b:undo_ftplugin .= " | sil! exe 'ounmap tp' | sil! exe 'vunmap tp'" . + \ " | sil! exe 'ounmap i$' | sil! exe 'vunmap i$'" . + \ " | sil! exe 'ounmap a$' | sil! exe 'vunmap a$'" + endif endif " Commands for asynchronous typesetting diff --git a/runtime/ftplugin/csh.vim b/runtime/ftplugin/csh.vim index 4ae09f91be..929823219c 100644 --- a/runtime/ftplugin/csh.vim +++ b/runtime/ftplugin/csh.vim @@ -1,21 +1,23 @@ " Vim filetype plugin file -" Language: csh -" Maintainer: Dan Sharp -" Last Changed: 20 Jan 2009 -" URL: http://dwsharp.users.sourceforge.net/vim/ftplugin +" Language: csh +" Maintainer: Doug Kearns +" Previous Maintainer: Dan Sharp +" Contributor: Johannes Zellner +" Last Change: 2021 Oct 15 if exists("b:did_ftplugin") | finish | endif let b:did_ftplugin = 1 -" Make sure the continuation lines below do not cause problems in -" compatibility mode. let s:save_cpo = &cpo set cpo-=C +setlocal comments=:# setlocal commentstring=#%s setlocal formatoptions-=t setlocal formatoptions+=crql +let b:undo_ftplugin = "setlocal com< cms< fo<" + " Csh: thanks to Johannes Zellner " - Both foreach and end must appear alone on separate lines. " - The words else and endif must appear at the beginning of input lines; @@ -23,26 +25,27 @@ setlocal formatoptions+=crql " - Each case label and the default label must appear at the start of a " line. " - while and end must appear alone on their input lines. -if exists("loaded_matchit") - let b:match_words = - \ '^\s*\.*(.*).*\:'. - \ '^\s*\\s\+\.*(.*).*\:^\s*\:'. - \ '^\s*\,'. - \ '\%(^\s*\\s\+\S\+\|^s*\\).*(.*):'. - \ '\:\:^\s*\,'. - \ '^\s*\.*(.*):^\s*\\s\+:^\s*\:^\s*\' +if exists("loaded_matchit") && !exists("b:match_words") + let s:line_start = '\%(^\s*\)\@<=' + let b:match_words = + \ s:line_start .. 'if\s*(.*)\s*then\>:' .. + \ s:line_start .. 'else\s\+if\s*(.*)\s*then\>:' .. s:line_start .. 'else\>:' .. + \ s:line_start .. 'endif\>,' .. + \ s:line_start .. '\%(\:\:' .. + \ s:line_start .. 'end\>,' .. + \ s:line_start .. 'switch\s*(:' .. + \ s:line_start .. 'case\s\+:' .. s:line_start .. 'default\>:\:' .. + \ s:line_start .. 'endsw\>' + unlet s:line_start + let b:undo_ftplugin ..= " | unlet b:match_words" endif -" Change the :browse e filter to primarily show csh-related files. -if has("gui_win32") - let b:browsefilter="csh Scripts (*.csh)\t*.csh\n" . - \ "All Files (*.*)\t*.*\n" +if (has("gui_win32") || has("gui_gtk")) && !exists("b:browsefilter") + let b:browsefilter="csh Scripts (*.csh)\t*.csh\n" .. + \ "All Files (*.*)\t*.*\n" + let b:undo_ftplugin ..= " | unlet b:browsefilter" endif -" Undo the stuff we changed. -let b:undo_ftplugin = "setlocal commentstring< formatoptions<" . - \ " | unlet! b:match_words b:browsefilter" - -" Restore the saved compatibility options. let &cpo = s:save_cpo unlet s:save_cpo diff --git a/runtime/ftplugin/tcsh.vim b/runtime/ftplugin/tcsh.vim index 7e2d959932..33f1aabf68 100644 --- a/runtime/ftplugin/tcsh.vim +++ b/runtime/ftplugin/tcsh.vim @@ -1,19 +1,17 @@ " Vim filetype plugin file -" Language: tcsh -" Maintainer: Dan Sharp -" Last Changed: 20 Jan 2009 -" URL: http://dwsharp.users.sourceforge.net/vim/ftplugin +" Language: tcsh +" Maintainer: Doug Kearns +" Previous Maintainer: Dan Sharp +" Last Change: 2021 Oct 15 if exists("b:did_ftplugin") | finish | endif -" Make sure the continuation lines below do not cause problems in -" compatibility mode. let s:save_cpo = &cpo set cpo-=C " Define some defaults in case the included ftplugins don't set them. let s:undo_ftplugin = "" -let s:browsefilter = "csh Files (*.csh)\t*.csh\n" . +let s:browsefilter = "csh Files (*.csh)\t*.csh\n" .. \ "All Files (*.*)\t*.*\n" runtime! ftplugin/csh.vim ftplugin/csh_*.vim ftplugin/csh/*.vim @@ -27,14 +25,11 @@ if exists("b:browsefilter") let s:browsefilter = b:browsefilter endif -" Change the :browse e filter to primarily show tcsh-related files. -if has("gui_win32") - let b:browsefilter="tcsh Scripts (*.tcsh)\t*.tcsh\n" . s:browsefilter +if (has("gui_win32") || has("gui_gtk")) + let b:browsefilter="tcsh Scripts (*.tcsh)\t*.tcsh\n" .. s:browsefilter endif -" Undo the stuff we changed. -let b:undo_ftplugin = "unlet! b:browsefilter | " . s:undo_ftplugin +let b:undo_ftplugin = "unlet! b:browsefilter | " .. s:undo_ftplugin -" Restore the saved compatibility options. let &cpo = s:save_cpo unlet s:save_cpo diff --git a/runtime/ftplugin/tmux.vim b/runtime/ftplugin/tmux.vim index ed9154924b..5c3461fefb 100644 --- a/runtime/ftplugin/tmux.vim +++ b/runtime/ftplugin/tmux.vim @@ -9,4 +9,7 @@ if exists("b:did_ftplugin") endif let b:did_ftplugin = 1 +let b:undo_ftplugin = "setlocal comments< commentstring<" + +setlocal comments=:# setlocal commentstring=#\ %s diff --git a/runtime/ftplugin/toml.vim b/runtime/ftplugin/toml.vim new file mode 100644 index 0000000000..1ef09a16e3 --- /dev/null +++ b/runtime/ftplugin/toml.vim @@ -0,0 +1,23 @@ +" Vim filetype plugin +" Language: TOML +" Homepage: https://github.com/cespare/vim-toml +" Maintainer: Aman Verma +" Author: Kevin Ballard +" Last Change: Sep 21, 2021 + +if exists('b:did_ftplugin') + finish +endif +let b:did_ftplugin = 1 + +let s:save_cpo = &cpo +set cpo&vim +let b:undo_ftplugin = 'setlocal commentstring< comments<' + +setlocal commentstring=#\ %s +setlocal comments=:# + +let &cpo = s:save_cpo +unlet s:save_cpo + +" vim: et sw=2 sts=2 diff --git a/runtime/indent/hamster.vim b/runtime/indent/hamster.vim index b27a173924..ae5c3fdedd 100644 --- a/runtime/indent/hamster.vim +++ b/runtime/indent/hamster.vim @@ -1,8 +1,14 @@ " Vim indent file " Language: Hamster Script -" Version: 2.0.6.0 -" Last Change: Wed Nov 08 2006 12:02:42 PM -" Maintainer: David Fishburn +" Version: 2.0.6.1 +" Last Change: 2021 Oct 11 +" Maintainer: David Fishburn +" Download: https://www.vim.org/scripts/script.php?script_id=1099 +" +" 2.0.6.1 (Oct 2021) +" Added b:undo_indent +" Added cpo check +" " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -14,12 +20,17 @@ setlocal indentkeys+==~if,=~else,=~endif,=~endfor,=~endwhile setlocal indentkeys+==~do,=~until,=~while,=~repeat,=~for,=~loop setlocal indentkeys+==~sub,=~endsub +let b:undo_indent = "setl indentkeys<" + " Define the appropriate indent function but only once setlocal indentexpr=HamGetFreeIndent() if exists("*HamGetFreeIndent") finish endif +let s:keepcpo = &cpo +set cpo&vim + function HamGetIndent(lnum) let ind = indent(a:lnum) let prevline=getline(a:lnum) @@ -52,4 +63,8 @@ function HamGetFreeIndent() return ind endfunction +" Restore: +let &cpo = s:keepcpo +unlet s:keepcpo + " vim:sw=2 tw=80 diff --git a/runtime/indent/sqlanywhere.vim b/runtime/indent/sqlanywhere.vim index d39fa3240e..4772b5951b 100644 --- a/runtime/indent/sqlanywhere.vim +++ b/runtime/indent/sqlanywhere.vim @@ -1,9 +1,8 @@ " Vim indent file " Language: SQL " Maintainer: David Fishburn -" Last Change By Maintainer: 2017 Jun 13 -" Last Change: by Stephen Wall, #5578, 2020 Jun 07 -" Version: 3.0 +" Last Change: 2021 Oct 11 +" Version: 4.0 " Download: http://vim.sourceforge.net/script.php?script_id=495 " Notes: @@ -21,6 +20,9 @@ " it, this can leave the indent hanging to the right one too many. " " History: +" 4.0 (Oct 2021) +" Added b:undo_indent +" " 3.0 (Dec 2012) " Added cpo check " @@ -56,10 +58,13 @@ setlocal indentkeys+==~end,=~else,=~elseif,=~elsif,0=~when,0=) " in the indentkeys is typed setlocal indentexpr=GetSQLIndent() +let b:undo_indent = "setl indentexpr< indentkeys<" + " Only define the functions once. if exists("*GetSQLIndent") finish endif + let s:keepcpo= &cpo set cpo&vim @@ -68,14 +73,9 @@ set cpo&vim " IS is excluded, since it is difficult to determine when the " ending block is (especially for procedures/functions). let s:SQLBlockStart = '^\s*\%('. - \ 'if\>.*\\|'. - \ 'elseif\>.*\.(\.*\.*\.*\' let s:SQLBlockEnd = '^\s*\(end\)\>' diff --git a/runtime/indent/tcsh.vim b/runtime/indent/tcsh.vim index 025d9c805d..93d96e7789 100644 --- a/runtime/indent/tcsh.vim +++ b/runtime/indent/tcsh.vim @@ -1,7 +1,8 @@ " Vim indent file " Language: C-shell (tcsh) -" Maintainer: Doug Kearns where a=dougkearns, b=gmail -" Last Modified: Sun 26 Sep 2021 12:38:38 PM EDT +" Maintainer: Doug Kearns +" Previous Maintainer: Gautam Iyer where NoSpam=gmail (Original Author) +" Last Change: 2021 Oct 15 " Only load this indent file when no other was loaded. if exists("b:did_indent") @@ -11,7 +12,9 @@ endif let b:did_indent = 1 setlocal indentexpr=TcshGetIndent() -setlocal indentkeys+=e,0=end,0=endsw indentkeys-=0{,0},0),:,0# +setlocal indentkeys+=e,0=end +setlocal indentkeys-=0{,0},0),:,0# + let b:undo_indent = "setl inde< indk<" " Only define the function once. @@ -40,9 +43,9 @@ function TcshGetIndent() let ind = ind - shiftwidth() endif - " Subtract indent if current line has on end, endif, case commands + " Subtract indent if current line has on end, endif, endsw, case commands let line = getline(v:lnum) - if line =~ '\v^\s*%(else|end|endif)\s*$' + if line =~ '\v^\s*%(else|end|endif|endsw)\s*$' let ind = ind - shiftwidth() endif diff --git a/runtime/syntax/css.vim b/runtime/syntax/css.vim index 19326d01e4..67ad1ea335 100644 --- a/runtime/syntax/css.vim +++ b/runtime/syntax/css.vim @@ -2,12 +2,12 @@ " Language: Cascading Style Sheets " Previous Contributor List: " Jules Wang -" Claudio Fleiner (Maintainer) +" Claudio Fleiner " Yeti (Add full CSS2, HTML4 support) " Nikolai Weibull (Add CSS2 support) -" URL: https://github.com/jsit/css.vim +" URL: https://github.com/vim-language-dept/css-syntax.vim " Maintainer: Jay Sitter -" Last Change: 2019 Jul. 29 +" Last Change: 2021 Oct 15 " quit when a syntax file was already loaded if !exists("main_syntax") @@ -23,6 +23,8 @@ let s:cpo_save = &cpo set cpo&vim syn case ignore +" Add dash to allowed keyword characters. +syn iskeyword @,48-57,_,192-255,- " HTML4 tags syn keyword cssTagName abbr address area a b base @@ -32,7 +34,7 @@ syn keyword cssTagName dfn div dl dt em fieldset form syn keyword cssTagName h1 h2 h3 h4 h5 h6 head hr html img i syn keyword cssTagName iframe input ins isindex kbd label legend li syn keyword cssTagName link map menu meta noscript ol optgroup -syn keyword cssTagName option p param pre q s samp script small +syn keyword cssTagName option p param picture pre q s samp script small syn keyword cssTagName span strong sub sup tbody td syn keyword cssTagName textarea tfoot th thead title tr ul u var syn keyword cssTagName object svg @@ -127,7 +129,7 @@ syn region cssURL contained matchgroup=cssFunctionName start="\<\(uri\|url\|loca syn region cssFunction contained matchgroup=cssFunctionName start="\<\(var\|calc\)\s*(" end=")" contains=cssCustomProp,cssValue.*,cssFunction,cssColor,cssStringQ,cssStringQQ oneline syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgb\|clip\|attr\|counter\|rect\|cubic-bezier\|steps\)\s*(" end=")" oneline contains=cssValueInteger,cssValueNumber,cssValueLength,cssFunctionComma syn region cssFunction contained matchgroup=cssFunctionName start="\<\(rgba\|hsl\|hsla\|color-stop\|from\|to\)\s*(" end=")" oneline contains=cssColor,cssValueInteger,cssValueNumber,cssValueLength,cssFunctionComma,cssFunction -syn region cssFunction contained matchgroup=cssFunctionName start="\<\(linear-\|radial-\)\=\gradient\s*(" end=")" oneline contains=cssColor,cssValueInteger,cssValueNumber,cssValueLength,cssFunction,cssGradientAttr,cssFunctionComma +syn region cssFunction contained matchgroup=cssFunctionName start="\<\(linear-\|radial-\|conic-\)\=\gradient\s*(" end=")" oneline contains=cssColor,cssValueInteger,cssValueNumber,cssValueLength,cssFunction,cssGradientAttr,cssFunctionComma syn region cssFunction contained matchgroup=cssFunctionName start="\<\(matrix\(3d\)\=\|scale\(3d\|X\|Y\|Z\)\=\|translate\(3d\|X\|Y\|Z\)\=\|skew\(X\|Y\)\=\|rotate\(3d\|X\|Y\|Z\)\=\|perspective\)\s*(" end=")" oneline contains=cssValueInteger,cssValueNumber,cssValueLength,cssValueAngle,cssFunctionComma syn region cssFunction contained matchgroup=cssFunctionName start="\<\(blur\|brightness\|contrast\|drop-shadow\|grayscale\|hue-rotate\|invert\|opacity\|saturate\|sepia\)\s*(" end=")" oneline contains=cssValueInteger,cssValueNumber,cssValueLength,cssValueAngle,cssFunctionComma syn keyword cssGradientAttr contained top bottom left right cover center middle ellipse at @@ -220,7 +222,7 @@ syn keyword cssFlexibleBoxProp contained order syn match cssFlexibleBoxAttr contained "\<\(row\|column\|wrap\)\(-reverse\)\=\>" syn keyword cssFlexibleBoxAttr contained nowrap stretch baseline center syn match cssFlexibleBoxAttr contained "\" -syn match cssFlexibleBoxAttr contained "\" +syn match cssFlexibleBoxAttr contained "\" " CSS Fonts Module Level 3 " http://www.w3.org/TR/css-fonts-3/ @@ -234,9 +236,7 @@ syn keyword cssFontAttr contained larger smaller syn match cssFontAttr contained "\<\(x\{1,2\}-\)\=\(large\|small\)\>" syn match cssFontAttr contained "\" " font-family attributes -syn match cssFontAttr contained "\<\(sans-\)\=serif\>" -syn keyword cssFontAttr contained Antiqua Arial Black Book Charcoal Comic Courier Dingbats Gadget Geneva Georgia Grande Helvetica Impact Linotype Lucida MS Monaco Neue New Palatino Roboto Roman Symbol Tahoma Times Trebuchet Verdana Webdings Wingdings York Zapf -syn keyword cssFontAttr contained cursive fantasy monospace +syn keyword cssFontAttr contained sans-serif serif cursive fantasy monospace " font-feature-settings attributes syn keyword cssFontAttr contained on off " font-stretch attributes @@ -283,6 +283,7 @@ syn match cssGridProp contained "\" syn match cssGridProp contained "\" syn match cssGridProp contained "\" syn match cssGridProp contained "\" +syn match cssGridProp contained "\" syn match cssGridProp contained "\" syn match cssHyerlinkProp contained "\" @@ -294,6 +295,10 @@ syn match cssListAttr contained "\<\(decimal\(-leading-zero\)\=\|cjk-ideographic syn keyword cssListAttr contained disc circle square hebrew armenian georgian syn keyword cssListAttr contained inside outside +" object-fit https://www.w3.org/TR/css-images-3/#the-object-fit +syn match cssObjectProp contained "\" +syn keyword cssObjectAttr contained fill contain cover scale-down + syn keyword cssPositioningProp contained bottom clear clip display float left syn keyword cssPositioningProp contained position right top visibility syn match cssPositioningProp contained "\" @@ -303,7 +308,7 @@ syn keyword cssPositioningAttr contained left right both syn match cssPositioningAttr contained "\" syn match cssPositioningAttr contained "\" syn match cssPositioningAttr contained "\" -syn keyword cssPositioningAttr contained static relative absolute fixed subgrid +syn keyword cssPositioningAttr contained static relative absolute fixed subgrid sticky syn keyword cssPrintAttr contained landscape portrait crop cross always @@ -548,6 +553,7 @@ hi def link cssMarqueeProp cssProp hi def link cssMultiColumnProp cssProp hi def link cssPagedMediaProp cssProp hi def link cssPositioningProp cssProp +hi def link cssObjectProp cssProp hi def link cssPrintProp cssProp hi def link cssRubyProp cssProp hi def link cssSpeechProp cssProp @@ -581,6 +587,7 @@ hi def link cssMultiColumnAttr cssAttr hi def link cssPaddingAttr cssAttr hi def link cssPagedMediaAttr cssAttr hi def link cssPositioningAttr cssAttr +hi def link cssObjectAttr cssAttr hi def link cssGradientAttr cssAttr hi def link cssPrintAttr cssAttr hi def link cssRubyAttr cssAttr diff --git a/runtime/syntax/tcsh.vim b/runtime/syntax/tcsh.vim index 27c6417fd0..6837125129 100644 --- a/runtime/syntax/tcsh.vim +++ b/runtime/syntax/tcsh.vim @@ -1,8 +1,9 @@ -" tcsh.vim: Vim syntax file for tcsh scripts -" Maintainer: Doug Kearns where NoSpam=gmail -" Author: Gautam Iyer where NoSpam=gmail -" Modified: Sun 26 Sep 2021 12:40:55 PM EDT -" +" Vim syntax file +" Language: tcsh scripts +" Maintainer: Doug Kearns +" Previous Maintainer: Gautam Iyer where NoSpam=gmail (Original Author) +" Last Change: 2021 Oct 15 + " Description: We break up each statement into a "command" and an "end" part. " All groups are either a "command" or part of the "end" of a statement (ie " everything after the "command"). This is because blindly highlighting tcsh @@ -20,36 +21,36 @@ endif let s:oldcpo = &cpo set cpo&vim " Line continuation is used -setlocal iskeyword+=- +syn iskeyword @,48-57,_,192-255,- syn case match -" ----- Clusters ----- +" ----- Clusters ----- {{{1 syn cluster tcshModifiers contains=tcshModifier,tcshModifierError syn cluster tcshQuoteList contains=tcshDQuote,tcshSQuote,tcshBQuote -syn cluster tcshStatementEnds contains=@tcshQuoteList,tcshComment,@tcshVarList,tcshRedir,tcshMeta,tcshHereDoc,tcshSpecial,tcshArguement +syn cluster tcshStatementEnds contains=@tcshQuoteList,tcshComment,@tcshVarList,tcshRedir,tcshMeta,tcshHereDoc,tcshSpecial,tcshArgument syn cluster tcshStatements contains=tcshBuiltin,tcshCommands,tcshIf,tcshWhile syn cluster tcshVarList contains=tcshUsrVar,tcshArgv,tcshSubst syn cluster tcshConditions contains=tcshCmdSubst,tcshParenExpr,tcshOperator,tcshNumber,@tcshVarList -" ----- Errors ----- +" ----- Errors ----- {{{1 " Define first, so can be easily overridden. syn match tcshError contained '\v\S.+' -" ----- Statements ----- +" ----- Statements ----- {{{1 " Tcsh commands: Any filename / modifiable variable (must be first!) syn match tcshCommands '\v[a-zA-Z0-9\\./_$:-]+' contains=tcshSpecial,tcshUsrVar,tcshArgv,tcshVarError nextgroup=tcshStatementEnd " Builtin commands except those treated specially. Currently (un)set(env), " (un)alias, if, while, else, bindkey -syn keyword tcshBuiltin nextgroup=tcshStatementEnd alloc bg break breaksw builtins bye case cd chdir complete continue default dirs echo echotc end endif endsw eval exec exit fg filetest foreach getspath getxvers glob goto hashstat history hup inlib jobs kill limit log login logout ls ls-F migrate newgrp nice nohup notify onintr popd printenv pushd rehash repeat rootnode sched setpath setspath settc setty setxvers shift source stop suspend switch telltc time umask uncomplete unhash universe unlimit ver wait warp watchlog where which +syn keyword tcshBuiltin nextgroup=tcshStatementEnd alloc bg break breaksw builtins bye case cd chdir complete continue default dirs echo echotc end endif endsw eval exec exit fg filetest foreach getspath getxvers glob goto hashstat history hup inlib jobs kill limit log login logout ls ls-F migrate newgrp nice nohup notify onintr popd printenv pushd rehash repeat rootnode sched setpath setspath settc setty setxvers shift source stop suspend switch telltc termname time umask uncomplete unhash universe unlimit ver wait warp watchlog where which " StatementEnd is anything after a built-in / command till the lexical end of a " statement (;, |, ||, |&, && or end of line) syn region tcshStatementEnd transparent contained matchgroup=tcshBuiltin start='' end='\v\\@' -" ----- Strings ----- +" ----- Strings ----- {{{1 " Tcsh does not allow \" in strings unless the "backslash_quote" shell " variable is set. Set the vim variable "tcsh_backslash_quote" to 0 if you " want VIM to assume that no backslash quote constructs exist. " Backquotes are treated as commands, and are not contained in anything -if(exists('tcsh_backslash_quote') && tcsh_backslash_quote == 0) +if exists('tcsh_backslash_quote') && tcsh_backslash_quote == 0 syn region tcshSQuote keepend contained start="\v\\@, >>, >>&, >>!, >>&!] syn match tcshRedir contained '\v\<|\>\>?\&?!?' @@ -190,13 +192,13 @@ syn match tcshOperator contained '&&\|!\~\|!=\|<<\|<=\|==\|=\~\|>=\|>>\|\*\|\^\| syn match tcshNumber contained '\v<-?\d+>' " Arguments -syn match tcshArguement contained '\v\s@<=-(\w|-)*' +syn match tcshArgument contained '\v\s@<=-(\w|-)*' " Special characters. \xxx, or backslashed characters. "syn match tcshSpecial contained '\v\\@ " License: 2-Clause BSD (http://opensource.org/licenses/BSD-2-Clause) @@ -30,14 +30,14 @@ syn match tmuxVariable /\w\+=/ display syn match tmuxVariableExpansion /\${\=\w\+}\=/ display syn match tmuxControl /%\(if\|elif\|else\|endif\)/ -syn region tmuxComment start=/#/ skip=/\\\@ 231 && s:i < 235)) ? 15 : "none" - exec "syn match tmuxColour" . s:i . " /\\/ display" -\ " | highlight tmuxColour" . s:i . " ctermfg=" . s:i . " ctermbg=" . s:bg -endfor +if get(g:, "tmux_syntax_colors", 1) + for s:i in range(0, 255) + let s:bg = (!s:i || s:i == 16 || (s:i > 231 && s:i < 235)) ? 15 : "none" + exec "syn match tmuxColour" . s:i . " /\\/ display" +\ " | highlight tmuxColour" . s:i . " ctermfg=" . s:i . " ctermbg=" . s:bg + endfor +endif syn keyword tmuxOptions -\ backspace buffer-limit command-alias default-terminal escape-time -\ exit-empty activity-action assume-paste-time base-index bell-action -\ default-command default-shell default-size destroy-unattached +\ backspace buffer-limit command-alias copy-command default-terminal editor +\ escape-time exit-empty activity-action assume-paste-time base-index +\ bell-action default-command default-shell default-size destroy-unattached \ detach-on-destroy display-panes-active-colour display-panes-colour -\ display-panes-time display-time exit-unattached focus-events history-file -\ history-limit key-table lock-after-time lock-command message-command-style -\ message-limit message-style aggressive-resize allow-rename -\ alternate-screen automatic-rename automatic-rename-format -\ clock-mode-colour clock-mode-style main-pane-height main-pane-width -\ mode-keys mode-style monitor-activity monitor-bell monitor-silence mouse -\ other-pane-height other-pane-width pane-active-border-style -\ pane-base-index pane-border-format pane-border-status pane-border-style -\ prefix prefix2 remain-on-exit renumber-windows repeat-time set-clipboard -\ set-titles set-titles-string silence-action status status-bg status-fg -\ status-format status-interval status-justify status-keys status-left -\ status-left-length status-left-style status-position status-right -\ status-right-length status-right-style status-style synchronize-panes -\ terminal-overrides update-environment user-keys visual-activity -\ visual-bell visual-silence window-active-style window-size -\ window-status-activity-style window-status-bell-style +\ display-panes-time display-time exit-unattached extended-keys focus-events +\ history-file history-limit key-table lock-after-time lock-command +\ message-command-style message-limit message-style aggressive-resize +\ allow-rename alternate-screen automatic-rename automatic-rename-format +\ clock-mode-colour clock-mode-style copy-mode-current-match-style +\ copy-mode-mark-style copy-mode-match-style main-pane-height +\ main-pane-width mode-keys mode-style monitor-activity monitor-bell +\ monitor-silence mouse other-pane-height other-pane-width +\ pane-active-border-style pane-base-index pane-border-format +\ pane-border-lines pane-border-status pane-border-style pane-colours prefix +\ prefix2 prompt-history-limit remain-on-exit renumber-windows repeat-time +\ set-clipboard set-titles set-titles-string silence-action status status-bg +\ status-fg status-format status-interval status-justify status-keys +\ status-left status-left-length status-left-style status-position +\ status-right status-right-length status-right-style status-style +\ synchronize-panes terminal-features terminal-overrides update-environment +\ user-keys visual-activity visual-bell visual-silence window-active-style +\ window-size window-status-activity-style window-status-bell-style \ window-status-current-format window-status-current-style \ window-status-format window-status-last-style window-status-separator -\ window-status-style window-style word-separators wrap-search xterm-keys +\ window-status-style window-style word-separators wrap-search syn keyword tmuxCommands \ attach attach-session bind bind-key break-pane breakp capture-pane \ capturep choose-buffer choose-client choose-tree clear-history clearhist -\ clock-mode command-prompt confirm confirm-before copy-mode detach -\ detach-client display display-menu display-message display-panes displayp -\ find-window findw if if-shell join-pane joinp kill-pane kill-server -\ kill-session kill-window killp has-session has killw link-window linkw -\ list-buffers list-clients list-commands list-keys list-panes list-sessions -\ list-windows load-buffer loadb lock lock-client lock-server lock-session -\ lockc last-pane lastp locks ls last-window last lsb lsc delete-buffer -\ deleteb lscm lsk lsp lsw menu move-pane move-window movep movew new -\ new-session new-window neww next next-layout next-window nextl -\ paste-buffer pasteb pipe-pane pipep prev previous-layout previous-window -\ prevl refresh refresh-client rename rename-session rename-window renamew -\ resize-pane resize-window resizep resizew respawn-pane respawn-window -\ respawnp respawnw rotate-window rotatew run run-shell save-buffer saveb +\ clock-mode command-prompt confirm confirm-before copy-mode customize-mode +\ detach detach-client display display-menu display-message display-panes +\ display-popup displayp find-window findw if if-shell join-pane joinp +\ kill-pane kill-server kill-session kill-window killp has has-session killw +\ link-window linkw list-buffers list-clients list-commands list-keys +\ list-panes list-sessions list-windows load-buffer loadb lock lock-client +\ lock-server lock-session lockc last-pane lastp locks ls last last-window +\ lsb delete-buffer deleteb lsc lscm lsk lsp lsw menu move-pane move-window +\ clear-prompt-history clearphist movep movew new new-session new-window +\ neww next next-layout next-window nextl paste-buffer pasteb pipe-pane +\ pipep popup prev previous-layout previous-window prevl refresh +\ refresh-client rename rename-session rename-window renamew resize-pane +\ resize-window resizep resizew respawn-pane respawn-window respawnp +\ respawnw rotate-window rotatew run run-shell save-buffer saveb \ select-layout select-pane select-window selectl selectp selectw send \ send-keys send-prefix set set-buffer set-environment set-hook set-option \ set-window-option setb setenv setw show show-buffer show-environment -\ show-hooks show-messages show-options show-window-options showb showenv -\ showmsgs showw source source-file split-window splitw start start-server -\ suspend-client suspendc swap-pane swap-window swapp swapw switch-client -\ switchc unbind unbind-key unlink-window unlinkw wait wait-for +\ show-hooks show-messages show-options show-prompt-history +\ show-window-options showb showenv showmsgs showphist showw source +\ source-file split-window splitw start start-server suspend-client suspendc +\ swap-pane swap-window swapp swapw switch-client switchc unbind unbind-key +\ unlink-window unlinkw wait wait-for let &cpo = s:original_cpo unlet! s:original_cpo s:bg s:i diff --git a/runtime/syntax/toml.vim b/runtime/syntax/toml.vim new file mode 100644 index 0000000000..bcb1b0b9c9 --- /dev/null +++ b/runtime/syntax/toml.vim @@ -0,0 +1,81 @@ +" Vim syntax file +" Language: TOML +" Homepage: https://github.com/cespare/vim-toml +" Maintainer: Aman Verma +" Previous Maintainer: Caleb Spare +" Last Change: Oct 8, 2021 + +if exists('b:current_syntax') + finish +endif + +syn match tomlEscape /\\[btnfr"/\\]/ display contained +syn match tomlEscape /\\u\x\{4}/ contained +syn match tomlEscape /\\U\x\{8}/ contained +syn match tomlLineEscape /\\$/ contained + +" Basic strings +syn region tomlString oneline start=/"/ skip=/\\\\\|\\"/ end=/"/ contains=tomlEscape +" Multi-line basic strings +syn region tomlString start=/"""/ end=/"""/ contains=tomlEscape,tomlLineEscape +" Literal strings +syn region tomlString oneline start=/'/ end=/'/ +" Multi-line literal strings +syn region tomlString start=/'''/ end=/'''/ + +syn match tomlInteger /[+-]\=\<[1-9]\(_\=\d\)*\>/ display +syn match tomlInteger /[+-]\=\<0\>/ display +syn match tomlInteger /[+-]\=\<0x[[:xdigit:]]\(_\=[[:xdigit:]]\)*\>/ display +syn match tomlInteger /[+-]\=\<0o[0-7]\(_\=[0-7]\)*\>/ display +syn match tomlInteger /[+-]\=\<0b[01]\(_\=[01]\)*\>/ display +syn match tomlInteger /[+-]\=\<\(inf\|nan\)\>/ display + +syn match tomlFloat /[+-]\=\<\d\(_\=\d\)*\.\d\+\>/ display +syn match tomlFloat /[+-]\=\<\d\(_\=\d\)*\(\.\d\(_\=\d\)*\)\=[eE][+-]\=\d\(_\=\d\)*\>/ display + +syn match tomlBoolean /\<\%(true\|false\)\>/ display + +" https://tools.ietf.org/html/rfc3339 +syn match tomlDate /\d\{4\}-\d\{2\}-\d\{2\}/ display +syn match tomlDate /\d\{2\}:\d\{2\}:\d\{2\}\%(\.\d\+\)\?/ display +syn match tomlDate /\d\{4\}-\d\{2\}-\d\{2\}[T ]\d\{2\}:\d\{2\}:\d\{2\}\%(\.\d\+\)\?\%(Z\|[+-]\d\{2\}:\d\{2\}\)\?/ display + +syn match tomlDotInKey /\v[^.]+\zs\./ contained display +syn match tomlKey /\v(^|[{,])\s*\zs[[:alnum:]._-]+\ze\s*\=/ contains=tomlDotInKey display +syn region tomlKeyDq oneline start=/\v(^|[{,])\s*\zs"/ end=/"\ze\s*=/ contains=tomlEscape +syn region tomlKeySq oneline start=/\v(^|[{,])\s*\zs'/ end=/'\ze\s*=/ + +syn region tomlTable oneline start=/^\s*\[[^\[]/ end=/\]/ contains=tomlKey,tomlKeyDq,tomlKeySq,tomlDotInKey + +syn region tomlTableArray oneline start=/^\s*\[\[/ end=/\]\]/ contains=tomlKey,tomlKeyDq,tomlKeySq,tomlDotInKey + +syn region tomlKeyValueArray start=/=\s*\[\zs/ end=/\]/ contains=@tomlValue + +syn region tomlArray start=/\[/ end=/\]/ contains=@tomlValue contained + +syn cluster tomlValue contains=tomlArray,tomlString,tomlInteger,tomlFloat,tomlBoolean,tomlDate,tomlComment + +syn keyword tomlTodo TODO FIXME XXX BUG contained + +syn match tomlComment /#.*/ contains=@Spell,tomlTodo + +hi def link tomlComment Comment +hi def link tomlTodo Todo +hi def link tomlTableArray Title +hi def link tomlTable Title +hi def link tomlDotInKey Normal +hi def link tomlKeySq Identifier +hi def link tomlKeyDq Identifier +hi def link tomlKey Identifier +hi def link tomlDate Constant +hi def link tomlBoolean Boolean +hi def link tomlFloat Float +hi def link tomlInteger Number +hi def link tomlString String +hi def link tomlLineEscape SpecialChar +hi def link tomlEscape SpecialChar + +syn sync minlines=500 +let b:current_syntax = 'toml' + +" vim: et sw=2 sts=2 diff --git a/src/Makefile b/src/Makefile index c4a3ada37d..2b1ad77e4f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -533,6 +533,10 @@ CClink = $(CC) # CONF_OPT_CANBERRA = --enable-canberra # CONF_OPT_CANBERRA = --disable-canberra +# libsodium - For enhanced encryption. Default is on. +# Uncomment the next line to not use libsodium +# CONF_OPT_SODIUM = --disable-libsodium + # FEATURES - For creating Vim with more or less features # Uncomment one of these lines when you want to include few to many features. # The default is "huge" for most systems. @@ -615,7 +619,7 @@ CClink = $(CC) # Note: If you use -Wextra and get warnings in GTK code about function # parameters, you can add -Wno-cast-function-type (but not with clang) #CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wunreachable-code -Wno-cast-function-type -Wno-deprecated-declarations -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 -#CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wunreachable-code -Wno-deprecated-declarations -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 +#CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wunreachable-code -Wno-deprecated-declarations -D_REENTRANT -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 # Add -Wpedantic to find // comments and other C99 constructs. # Better disable Perl and Python to avoid a lot of warnings. #CFLAGS = -g -Wall -Wextra -Wshadow -Wmissing-prototypes -Wpedantic -Wunreachable-code -Wunused-result -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1 @@ -778,10 +782,6 @@ SANITIZER_LIBS = $(SANITIZER_CFLAGS) # needed to avoid a problem where strings.h gets included #CFLAGS = -qsrcmsg -O2 -qmaxmem=8192 -D__STR31__ -### (W) Solaris with multi-threaded libraries (-lthread): -### If suspending doesn't work properly, try using this line: -#EXTRA_DEFS = -D_REENTRANT - ### (7) Solaris 2.4/2.5 with Centerline compiler #CC = clcc #X_LIBS_DIR = -L/usr/openwin/lib -R/usr/openwin/lib @@ -1472,12 +1472,12 @@ CPP_DEPEND = $(CC) -I$(srcdir) -M$(CPP_MM) \ # -D"__attribute__\\(x\\)=" -D"__asm__\\(x\\)=" \ # -D__extension__= -D__restrict="" \ # -D__gnuc_va_list=char -D__builtin_va_list=char - # # This is for cproto 3 patchlevel 9 or above (currently 4.6, 4.7g) # __inline and __attribute__ are now recognized by cproto +# __attribute() is not recognized and used in X11/Intrinsic.h # -D"foo()=" is not supported by all compilers so do not use it -NO_ATTR= +NO_ATTR = -D"__attribute\\(x\\)=" # # Use this for cproto 3 patchlevel 6 or below (use "cproto -V" to check): # PROTO_FLAGS = -f4 -d -E"$(CPP)" $(NO_ATTR) @@ -2104,7 +2104,7 @@ config auto/config.mk: auto/configure config.mk.in config.h.in $(CONF_ARGS4) $(CONF_ARGS5) $(CONF_ARGS6) \ $(CONF_OPT_MZSCHEME) $(CONF_OPT_PLTHOME) \ $(CONF_OPT_LUA) $(CONF_OPT_LUA_PREFIX) \ - $(CONF_OPT_SYSMOUSE) $(CONF_OPT_CANBERRA); \ + $(CONF_OPT_SYSMOUSE) $(CONF_OPT_CANBERRA) $(CONF_OPT_SODIUM); \ fi # Use "make reconfig" to rerun configure without cached values. diff --git a/src/auto/configure b/src/auto/configure index 0eb4864dc7..fe6300a821 100755 --- a/src/auto/configure +++ b/src/auto/configure @@ -13379,6 +13379,52 @@ if test "x$vim_cv_stat_ignores_slash" = "xyes" ; then fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for nanoseconds field of struct stat" >&5 +$as_echo_n "checking for nanoseconds field of struct stat... " >&6; } +if ${ac_cv_struct_st_mtim_nsec+:} false; then : + $as_echo_n "(cached) " >&6 +else + ac_save_CPPFLAGS="$CPPFLAGS" + ac_cv_struct_st_mtim_nsec=no + # st_mtim.tv_nsec -- the usual case + # st_mtim._tv_nsec -- Solaris 2.6, if + # (defined _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1 + # && !defined __EXTENSIONS__) + # st_mtim.st__tim.tv_nsec -- UnixWare 2.1.2 + # st_mtime_n -- AIX 5.2 and above + # st_mtimespec.tv_nsec -- Darwin (Mac OSX) + for ac_val in st_mtim.tv_nsec st_mtim._tv_nsec st_mtim.st__tim.tv_nsec st_mtime_n st_mtimespec.tv_nsec; do + CPPFLAGS="$ac_save_CPPFLAGS -DST_MTIM_NSEC=$ac_val" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +#include +int +main () +{ +struct stat s; s.ST_MTIM_NSEC; + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + ac_cv_struct_st_mtim_nsec=$ac_val; break +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + done + CPPFLAGS="$ac_save_CPPFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_struct_st_mtim_nsec" >&5 +$as_echo "$ac_cv_struct_st_mtim_nsec" >&6; } +if test $ac_cv_struct_st_mtim_nsec != no; then + +cat >>confdefs.h <<_ACEOF +#define ST_MTIM_NSEC $ac_cv_struct_st_mtim_nsec +_ACEOF + +fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for iconv_open()" >&5 $as_echo_n "checking for iconv_open()... " >&6; } save_LIBS="$LIBS" diff --git a/src/buffer.c b/src/buffer.c index cd3169d6bd..0e7bcbfd99 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -327,6 +327,7 @@ open_buffer( // Set last_changedtick to avoid triggering a TextChanged autocommand right // after it was added. curbuf->b_last_changedtick = CHANGEDTICK(curbuf); + curbuf->b_last_changedtick_i = CHANGEDTICK(curbuf); curbuf->b_last_changedtick_pum = CHANGEDTICK(curbuf); // require "!" to overwrite the file, because it wasn't read completely @@ -2367,6 +2368,7 @@ free_buf_options( #ifdef FEAT_COMPL_FUNC clear_string_option(&buf->b_p_cfu); clear_string_option(&buf->b_p_ofu); + clear_string_option(&buf->b_p_tsrfu); #endif #ifdef FEAT_QUICKFIX clear_string_option(&buf->b_p_gp); @@ -3033,8 +3035,6 @@ buflist_setfpos( wip->wi_prev = NULL; if (wip->wi_next) wip->wi_next->wi_prev = wip; - - return; } #ifdef FEAT_DIFF diff --git a/src/bufwrite.c b/src/bufwrite.c index 03c7aef0b2..599d6e418f 100644 --- a/src/bufwrite.c +++ b/src/bufwrite.c @@ -527,7 +527,7 @@ buf_write_bytes(struct bw_info *ip) check_mtime(buf_T *buf, stat_T *st) { if (buf->b_mtime_read != 0 - && time_differs((long)st->st_mtime, buf->b_mtime_read)) + && time_differs(st, buf->b_mtime_read, buf->b_mtime_read_ns)) { msg_scroll = TRUE; // don't overwrite messages here msg_silent = 0; // must give this prompt @@ -2422,8 +2422,8 @@ restore_backup: && (overwriting || vim_strchr(p_cpo, CPO_PLUS) != NULL)) { unchanged(buf, TRUE, FALSE); - // b:changedtick is may be incremented in unchanged() but that - // should not trigger a TextChanged event. + // b:changedtick may be incremented in unchanged() but that should not + // trigger a TextChanged event. if (buf->b_last_changedtick + 1 == CHANGEDTICK(buf)) buf->b_last_changedtick = CHANGEDTICK(buf); u_unchanged(buf); @@ -2558,6 +2558,7 @@ nofail: { buf_store_time(buf, &st_old, fname); buf->b_mtime_read = buf->b_mtime; + buf->b_mtime_read_ns = buf->b_mtime_ns; } } } diff --git a/src/charset.c b/src/charset.c index fcaeedf757..2c46f7ad04 100644 --- a/src/charset.c +++ b/src/charset.c @@ -2013,8 +2013,6 @@ hex2nr(int c) return c - '0'; } -#if defined(FEAT_TERMRESPONSE) || defined(FEAT_GUI_GTK) \ - || defined(PROTO) || defined(FEAT_AUTOSHELLDIR) /* * Convert two hex characters to a byte. * Return -1 if one of the characters is not hex. @@ -2026,7 +2024,6 @@ hexhex2nr(char_u *p) return -1; return (hex2nr(p[0]) << 4) + hex2nr(p[1]); } -#endif /* * Return TRUE if "str" starts with a backslash that should be removed. diff --git a/src/cmdexpand.c b/src/cmdexpand.c index b6ddcefd3d..c567b0758d 100644 --- a/src/cmdexpand.c +++ b/src/cmdexpand.c @@ -48,6 +48,8 @@ ExpandEscape( { int i; char_u *p; + int vse_what = xp->xp_context == EXPAND_BUFFERS + ? VSE_BUFFER : VSE_NONE; // May change home directory back to "~" if (options & WILD_HOME_REPLACE) @@ -84,9 +86,10 @@ ExpandEscape( } } #ifdef BACKSLASH_IN_FILENAME - p = vim_strsave_fnameescape(files[i], FALSE); + p = vim_strsave_fnameescape(files[i], vse_what); #else - p = vim_strsave_fnameescape(files[i], xp->xp_shell); + p = vim_strsave_fnameescape(files[i], + xp->xp_shell ? VSE_SHELL : vse_what); #endif if (p != NULL) { diff --git a/src/config.h.in b/src/config.h.in index 0808cc3587..61b8b76a54 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -144,6 +144,9 @@ /* Define if stat() ignores a trailing slash */ #undef STAT_IGNORES_SLASH +/* Define to nanoseconds field of struct stat */ +#undef ST_MTIM_NSEC + /* Define if tgetstr() has a second argument that is (char *) */ #undef TGETSTR_CHAR_P diff --git a/src/configure.ac b/src/configure.ac index b7b89ca420..c8e284baa4 100644 --- a/src/configure.ac +++ b/src/configure.ac @@ -4028,6 +4028,31 @@ main() {struct stat st; exit(stat("configure/", &st) != 0); } if test "x$vim_cv_stat_ignores_slash" = "xyes" ; then AC_DEFINE(STAT_IGNORES_SLASH) fi + +dnl nanoseconds field of struct stat +AC_CACHE_CHECK([for nanoseconds field of struct stat], + ac_cv_struct_st_mtim_nsec, + [ac_save_CPPFLAGS="$CPPFLAGS" + ac_cv_struct_st_mtim_nsec=no + # st_mtim.tv_nsec -- the usual case + # st_mtim._tv_nsec -- Solaris 2.6, if + # (defined _XOPEN_SOURCE && _XOPEN_SOURCE_EXTENDED == 1 + # && !defined __EXTENSIONS__) + # st_mtim.st__tim.tv_nsec -- UnixWare 2.1.2 + # st_mtime_n -- AIX 5.2 and above + # st_mtimespec.tv_nsec -- Darwin (Mac OSX) + for ac_val in st_mtim.tv_nsec st_mtim._tv_nsec st_mtim.st__tim.tv_nsec st_mtime_n st_mtimespec.tv_nsec; do + CPPFLAGS="$ac_save_CPPFLAGS -DST_MTIM_NSEC=$ac_val" + AC_TRY_COMPILE([#include +#include ], [struct stat s; s.ST_MTIM_NSEC;], + [ac_cv_struct_st_mtim_nsec=$ac_val; break]) + done + CPPFLAGS="$ac_save_CPPFLAGS" +]) +if test $ac_cv_struct_st_mtim_nsec != no; then + AC_DEFINE_UNQUOTED([ST_MTIM_NSEC], [$ac_cv_struct_st_mtim_nsec], + [Define if struct stat contains a nanoseconds field]) +fi dnl Link with iconv for charset translation, if not found without library. dnl check for iconv() requires including iconv.h diff --git a/src/drawscreen.c b/src/drawscreen.c index 2740cbddad..eb58cbf209 100644 --- a/src/drawscreen.c +++ b/src/drawscreen.c @@ -464,13 +464,13 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED) *(p + len++) = ' '; if (bt_help(wp->w_buffer)) { - STRCPY(p + len, _("[Help]")); + vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[Help]")); len += (int)STRLEN(p + len); } #ifdef FEAT_QUICKFIX if (wp->w_p_pvw) { - STRCPY(p + len, _("[Preview]")); + vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[Preview]")); len += (int)STRLEN(p + len); } #endif @@ -480,12 +480,12 @@ win_redr_status(win_T *wp, int ignore_pum UNUSED) #endif ) { - STRCPY(p + len, "[+]"); - len += 3; + vim_snprintf((char *)p + len, MAXPATHL - len, "%s", "[+]"); + len += (int)STRLEN(p + len); } if (wp->w_buffer->b_p_ro) { - STRCPY(p + len, _("[RO]")); + vim_snprintf((char *)p + len, MAXPATHL - len, "%s", _("[RO]")); len += (int)STRLEN(p + len); } diff --git a/src/edit.c b/src/edit.c index 01fdf2ccb4..81692961d9 100644 --- a/src/edit.c +++ b/src/edit.c @@ -1486,9 +1486,9 @@ ins_redraw(int ready) // not busy with something last_cursormoved = curwin->w_cursor; } - // Trigger TextChangedI if b_changedtick differs. + // Trigger TextChangedI if b_changedtick_i differs. if (ready && has_textchangedI() - && curbuf->b_last_changedtick != CHANGEDTICK(curbuf) + && curbuf->b_last_changedtick_i != CHANGEDTICK(curbuf) && !pum_visible()) { aco_save_T aco; @@ -1498,15 +1498,15 @@ ins_redraw(int ready) // not busy with something aucmd_prepbuf(&aco, curbuf); apply_autocmds(EVENT_TEXTCHANGEDI, NULL, NULL, FALSE, curbuf); aucmd_restbuf(&aco); - curbuf->b_last_changedtick = CHANGEDTICK(curbuf); + curbuf->b_last_changedtick_i = CHANGEDTICK(curbuf); if (tick != CHANGEDTICK(curbuf)) // see ins_apply_autocmds() u_save(curwin->w_cursor.lnum, (linenr_T)(curwin->w_cursor.lnum + 1)); } - // Trigger TextChangedP if b_changedtick differs. When the popupmenu closes - // TextChangedI will need to trigger for backwards compatibility, thus use - // different b_last_changedtick* variables. + // Trigger TextChangedP if b_changedtick_pum differs. When the popupmenu + // closes TextChangedI will need to trigger for backwards compatibility, + // thus use different b_last_changedtick* variables. if (ready && has_textchangedP() && curbuf->b_last_changedtick_pum != CHANGEDTICK(curbuf) && pum_visible()) diff --git a/src/errors.h b/src/errors.h index a8ea33d170..12d00b724a 100644 --- a/src/errors.h +++ b/src/errors.h @@ -664,3 +664,11 @@ EXTERN char e_blob_required_for_argument_nr[] INIT(= N_("E1238: Blob required for argument %d")); EXTERN char e_invalid_value_for_blob_nr[] INIT(= N_("E1239: Invalid value for blob: %d")); +EXTERN char e_resulting_text_too_long[] + INIT(= N_("E1240: Resulting text too long")); +EXTERN char e_separator_not_supported_str[] + INIT(= N_("E1241: Separator not supported: %s")); +EXTERN char e_no_white_space_allowed_before_separator_str[] + INIT(= N_("E1242: No white space allowed before separator: %s")); +EXTERN char e_ascii_code_not_in_range[] + INIT(= N_("E1243: ASCII code not in 32-127 range")); diff --git a/src/evalfunc.c b/src/evalfunc.c index ca7e308350..5c2ae81118 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -3886,7 +3886,7 @@ f_fnameescape(typval_T *argvars, typval_T *rettv) return; rettv->vval.v_string = vim_strsave_fnameescape( - tv_get_string(&argvars[0]), FALSE); + tv_get_string(&argvars[0]), VSE_NONE); rettv->v_type = VAR_STRING; } @@ -5493,6 +5493,13 @@ f_has(typval_T *argvars, typval_T *rettv) 0 #endif }, + {"nanotime", +#ifdef ST_MTIM_NSEC + 1 +#else + 0 +#endif + }, {"num64", 1}, {"ole", #ifdef FEAT_OLE diff --git a/src/evalvars.c b/src/evalvars.c index 8e07aa3eb5..ec195ac437 100644 --- a/src/evalvars.c +++ b/src/evalvars.c @@ -3321,7 +3321,7 @@ set_var_const( goto failed; } - if (var_in_vim9script) + if (var_in_vim9script && (flags & ASSIGN_FOR_LOOP) == 0) { where_T where = WHERE_INIT; @@ -3333,7 +3333,8 @@ set_var_const( goto failed; } - if (var_check_permission(di, name) == FAIL) + if ((flags & ASSIGN_FOR_LOOP) == 0 + && var_check_permission(di, name) == FAIL) goto failed; } else diff --git a/src/ex_cmds.c b/src/ex_cmds.c index 5c92e094e1..ff915173f7 100644 --- a/src/ex_cmds.c +++ b/src/ex_cmds.c @@ -3724,6 +3724,11 @@ ex_substitute(exarg_T *eap) // don't accept alphanumeric for separator if (check_regexp_delim(*cmd) == FAIL) return; +#ifdef FEAT_EVAL + if (in_vim9script() && check_global_and_subst(eap->cmd, eap->arg) + == FAIL) + return; +#endif /* * undocumented vi feature: @@ -4899,6 +4904,11 @@ ex_global(exarg_T *eap) cmd = eap->arg; which_pat = RE_LAST; // default: use last used regexp +#ifdef FEAT_EVAL + if (in_vim9script() && check_global_and_subst(eap->cmd, eap->arg) == FAIL) + return; +#endif + /* * undocumented vi feature: * "\/" and "\?": use previous search pattern. diff --git a/src/ex_docmd.c b/src/ex_docmd.c index 6759745cb1..3bab0844c3 100644 --- a/src/ex_docmd.c +++ b/src/ex_docmd.c @@ -3606,6 +3606,15 @@ find_ex_command( } } + // "g:", "s:" and "l:" are always assumed to be a variable, thus start + // an expression. A global/substitute/list command needs to use a + // longer name. + if (vim_strchr((char_u *)"gsl", *p) != NULL && p[1] == ':') + { + eap->cmdidx = CMD_eval; + return eap->cmd; + } + // If it is an ID it might be a variable with an operator on the next // line, if the variable exists it can't be an Ex command. if (p > eap->cmd && ends_excmd(*skipwhite(p)) @@ -4235,8 +4244,10 @@ get_address( // When '/' or '?' follows another address, start from // there. - if (lnum != MAXLNUM) - curwin->w_cursor.lnum = lnum; + if (lnum > 0 && lnum != MAXLNUM) + curwin->w_cursor.lnum = + lnum > curbuf->b_ml.ml_line_count + ? curbuf->b_ml.ml_line_count : lnum; // Start a forward search at the end of the line (unless // before the first line). diff --git a/src/ex_getln.c b/src/ex_getln.c index 972b7f7537..caf40db77d 100644 --- a/src/ex_getln.c +++ b/src/ex_getln.c @@ -3906,27 +3906,32 @@ ccheck_abbr(int c) } /* - * Escape special characters in "fname" for when used as a file name argument - * after a Vim command, or, when "shell" is non-zero, a shell command. + * Escape special characters in "fname", depending on "what": + * VSE_NONE: for when used as a file name argument after a Vim command. + * VSE_SHELL: for a shell command. + * VSE_BUFFER: for the ":buffer" command. * Returns the result in allocated memory. */ char_u * -vim_strsave_fnameescape(char_u *fname, int shell UNUSED) +vim_strsave_fnameescape(char_u *fname, int what) { char_u *p; #ifdef BACKSLASH_IN_FILENAME char_u buf[20]; int j = 0; - // Don't escape '[', '{' and '!' if they are in 'isfname'. - for (p = PATH_ESC_CHARS; *p != NUL; ++p) + // Don't escape '[', '{' and '!' if they are in 'isfname' and for the + // ":buffer" command. + for (p = what == VSE_BUFFER ? BUFFER_ESC_CHARS : PATH_ESC_CHARS; + *p != NUL; ++p) if ((*p != '[' && *p != '{' && *p != '!') || !vim_isfilec(*p)) buf[j++] = *p; buf[j] = NUL; p = vim_strsave_escaped(fname, buf); #else - p = vim_strsave_escaped(fname, shell ? SHELL_ESC_CHARS : PATH_ESC_CHARS); - if (shell && csh_like_shell() && p != NULL) + p = vim_strsave_escaped(fname, what == VSE_SHELL ? SHELL_ESC_CHARS + : what == VSE_BUFFER ? BUFFER_ESC_CHARS : PATH_ESC_CHARS); + if (what == VSE_SHELL && csh_like_shell() && p != NULL) { char_u *s; diff --git a/src/fileio.c b/src/fileio.c index 5e48b7dfdd..3b6a34a69b 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -408,6 +408,7 @@ readfile( { buf_store_time(curbuf, &st, fname); curbuf->b_mtime_read = curbuf->b_mtime; + curbuf->b_mtime_read_ns = curbuf->b_mtime_ns; filesize_disk = st.st_size; #ifdef UNIX /* @@ -432,7 +433,9 @@ readfile( else { curbuf->b_mtime = 0; + curbuf->b_mtime_ns = 0; curbuf->b_mtime_read = 0; + curbuf->b_mtime_read_ns = 0; curbuf->b_orig_size = 0; curbuf->b_orig_mode = 0; } @@ -2569,6 +2572,7 @@ failed: { buf_store_time(curbuf, &st, fname); curbuf->b_mtime_read = curbuf->b_mtime; + curbuf->b_mtime_read_ns = curbuf->b_mtime_ns; } #endif } @@ -3115,16 +3119,21 @@ msg_add_eol(void) } int -time_differs(long t1, long t2) +time_differs(stat_T *st, long mtime, long mtime_ns UNUSED) { -#if defined(__linux__) || defined(MSWIN) - // On a FAT filesystem, esp. under Linux, there are only 5 bits to store - // the seconds. Since the roundoff is done when flushing the inode, the - // time may change unexpectedly by one second!!! - return (t1 - t2 > 1 || t2 - t1 > 1); -#else - return (t1 != t2); + return +#ifdef ST_MTIM_NSEC + (long)st->ST_MTIM_NSEC != mtime_ns || #endif +#if defined(__linux__) || defined(MSWIN) + // On a FAT filesystem, esp. under Linux, there are only 5 bits to store + // the seconds. Since the roundoff is done when flushing the inode, the + // time may change unexpectedly by one second!!! + (long)st->st_mtime - mtime > 1 || mtime - (long)st->st_mtime > 1 +#else + (long)st->st_mtime != mtime +#endif + ; } /* @@ -4082,7 +4091,7 @@ buf_check_timestamp( if ( !(buf->b_flags & BF_NOTEDITED) && buf->b_mtime != 0 && ((stat_res = mch_stat((char *)buf->b_ffname, &st)) < 0 - || time_differs((long)st.st_mtime, buf->b_mtime) + || time_differs(&st, buf->b_mtime, buf->b_mtime_ns) || st.st_size != buf->b_orig_size #ifdef HAVE_ST_MODE || (int)st.st_mode != buf->b_orig_mode @@ -4197,9 +4206,12 @@ buf_check_timestamp( mesg2 = _("See \":help W16\" for more info."); } else + { // Only timestamp changed, store it to avoid a warning // in check_mtime() later. buf->b_mtime_read = buf->b_mtime; + buf->b_mtime_read_ns = buf->b_mtime_ns; + } } } } @@ -4503,6 +4515,11 @@ buf_reload(buf_T *buf, int orig_mode) buf_store_time(buf_T *buf, stat_T *st, char_u *fname UNUSED) { buf->b_mtime = (long)st->st_mtime; +#ifdef ST_MTIM_NSEC + buf->b_mtime_ns = (long)st->ST_MTIM_NSEC; +#else + buf->b_mtime_ns = 0; +#endif buf->b_orig_size = st->st_size; #ifdef HAVE_ST_MODE buf->b_orig_mode = (int)st->st_mode; diff --git a/src/getchar.c b/src/getchar.c index c6a0f0ada0..7d356017d4 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -243,7 +243,6 @@ add_buff( buf->bh_curr->b_next = p; buf->bh_curr = p; } - return; } /* diff --git a/src/gui.c b/src/gui.c index 31594bbe0b..8e38296f88 100644 --- a/src/gui.c +++ b/src/gui.c @@ -460,6 +460,10 @@ gui_init_check(void) gui.scrollbar_width = gui.scrollbar_height = SB_DEFAULT_WIDTH; gui.prev_wrap = -1; +# ifdef FEAT_GUI_GTK + CLEAR_FIELD(gui.ligatures_map); +#endif + #if defined(ALWAYS_USE_GUI) || defined(VIMDLL) result = OK; #else @@ -1084,6 +1088,36 @@ gui_get_wide_font(void) return OK; } +#if defined(FEAT_GUI_GTK) || defined(PROTO) +/* + * Set list of ascii characters that combined can create ligature. + * Store them in char map for quick access from gui_gtk2_draw_string. + */ + void +gui_set_ligatures(void) +{ + char_u *p; + + if (*p_guiligatures != NUL) + { + // check for invalid characters + for (p = p_guiligatures; *p != NUL; ++p) + if (*p < 32 || *p > 127) + { + emsg(_(e_ascii_code_not_in_range)); + return; + } + + // store valid setting into ligatures_map + CLEAR_FIELD(gui.ligatures_map); + for (p = p_guiligatures; *p != NUL; ++p) + gui.ligatures_map[*p] = 1; + } + else + CLEAR_FIELD(gui.ligatures_map); +} +#endif + static void gui_set_cursor(int row, int col) { diff --git a/src/gui.h b/src/gui.h index e1330d5413..9945ab9ff6 100644 --- a/src/gui.h +++ b/src/gui.h @@ -418,6 +418,9 @@ typedef struct Gui char_u *browse_fname; // file name from filedlg guint32 event_time; + + char_u ligatures_map[256]; // ascii map for characters 0-255, value is + // 1 if in 'guiligatures' #endif // FEAT_GUI_GTK #if defined(FEAT_GUI_TABLINE) \ diff --git a/src/gui_gtk_x11.c b/src/gui_gtk_x11.c index 1a3eadad72..e107c5e060 100644 --- a/src/gui_gtk_x11.c +++ b/src/gui_gtk_x11.c @@ -5595,18 +5595,22 @@ draw_under(int flags, int row, int col, int cells) int gui_gtk2_draw_string(int row, int col, char_u *s, int len, int flags) { - GdkRectangle area; // area for clip mask - PangoGlyphString *glyphs; // glyphs of current item - int column_offset = 0; // column offset in cells - int i; - char_u *conv_buf = NULL; // result of UTF-8 conversion - char_u *new_conv_buf; - int convlen; - char_u *sp, *bp; - int plen; -#if GTK_CHECK_VERSION(3,0,0) - cairo_t *cr; -#endif + char_u *conv_buf = NULL; // result of UTF-8 conversion + char_u *new_conv_buf; + int convlen; + char_u *sp, *bp; + int plen; + int len_sum; // return value needs to add up since we are + // printing substrings + int byte_sum; // byte position in string + char_u *cs; // current *s pointer + int needs_pango; // look ahead, 0=ascii 1=unicode/ligatures + int should_need_pango = FALSE; + int slen; + int is_ligature; + int next_is_ligature; + int is_utf8; + char_u backup_ch; if (gui.text_context == NULL || gtk_widget_get_window(gui.drawarea) == NULL) return len; @@ -5652,6 +5656,125 @@ gui_gtk2_draw_string(int row, int col, char_u *s, int len, int flags) len = convlen; } + /* + * Ligature support and complex utf-8 char optimization: + * String received to output to screen can print using pre-cached glyphs + * (fast) or Pango (slow). Ligatures and multibype utf-8 must use Pango. + * Since we receive mixed content string, split it into logical segments + * that are guaranteed to go trough glyphs as much as possible. Since + * single ligature char prints as ascii, print it that way. + */ + len_sum = 0; // return value needs to add up since we are printing + // substrings + byte_sum = 0; + cs = s; + // look ahead, 0=ascii 1=unicode/ligatures + needs_pango = ((*cs & 0x80) || gui.ligatures_map[*cs]); + + // split string into ascii and non-ascii (ligatures + utf-8) substrings, + // print glyphs or use Pango + while (cs < s + len) + { + slen = 0; + while (slen < (len - byte_sum)) + { + is_ligature = gui.ligatures_map[*(cs + slen)]; + // look ahead, single ligature char between ascii is ascii + if (is_ligature && !needs_pango) + { + if ((slen + 1) < (len - byte_sum)) + { + next_is_ligature = gui.ligatures_map[*(cs + slen + 1)]; + if (!next_is_ligature) + is_ligature = 0; + } + else + { + is_ligature = 0; + } + } + is_utf8 = *(cs + slen) & 0x80; + should_need_pango = (is_ligature || is_utf8); + if (needs_pango != should_need_pango) // mode switch + break; + if (needs_pango) + { + if (is_ligature) + { + slen++; // ligature char by char + } + else + { + if ((*(cs + slen) & 0xC0) == 0x80) + { + // a continuation, find next 0xC0 != 0x80 but don't + // include it + while ((slen < (len - byte_sum)) + && ((*(cs + slen) & 0xC0) == 0x80)) + { + slen++; + } + } + else if ((*(cs + slen) & 0xE0) == 0xC0) + { + // + one byte utf8 + slen++; + } + else if ((*(cs + slen) & 0xF0) == 0xE0) + { + // + two bytes utf8 + slen += 2; + } + else if ((*(cs + slen) & 0xF8) == 0xF0) + { + // + three bytes utf8 + slen += 3; + } + else + { + // this should not happen, try moving forward, Pango + // will catch it + slen++; + } + } + } + else + { + slen++; // ascii + } + } + + // temporarily zero terminate substring, print, restore char, wrap + backup_ch = *(cs + slen); + *(cs + slen) = 0; + len_sum += gui_gtk2_draw_string_ext(row, col + len_sum, + cs, slen, flags, needs_pango); + *(cs + slen) = backup_ch; + cs += slen; + byte_sum += slen; + needs_pango = should_need_pango; + } + vim_free(conv_buf); + return len_sum; +} + + int +gui_gtk2_draw_string_ext( + int row, + int col, + char_u *s, + int len, + int flags, + int force_pango) +{ + GdkRectangle area; // area for clip mask + PangoGlyphString *glyphs; // glyphs of current item + int column_offset = 0; // column offset in cells + int i; +#if GTK_CHECK_VERSION(3,0,0) + cairo_t *cr; +#endif + /* * Restrict all drawing to the current screen line in order to prevent * fuzzy font lookups from messing up the screen. @@ -5679,7 +5802,8 @@ gui_gtk2_draw_string(int row, int col, char_u *s, int len, int flags) */ if (!(flags & DRAW_ITALIC) && !((flags & DRAW_BOLD) && gui.font_can_bold) - && gui.ascii_glyphs != NULL) + && gui.ascii_glyphs != NULL + && !force_pango) { char_u *p; @@ -5883,7 +6007,6 @@ skipitall: #endif pango_glyph_string_free(glyphs); - vim_free(conv_buf); #if GTK_CHECK_VERSION(3,0,0) cairo_destroy(cr); diff --git a/src/highlight.c b/src/highlight.c index 9cd2c3e117..82a345e622 100644 --- a/src/highlight.c +++ b/src/highlight.c @@ -641,9 +641,6 @@ do_highlight( int error = FALSE; int color; int is_normal_group = FALSE; // "Normal" group -#ifdef FEAT_TERMINAL - int is_terminal_group = FALSE; // "Terminal" group -#endif #ifdef FEAT_GUI_X11 int is_menu_group = FALSE; // "Menu" group int is_scrollbar_group = FALSE; // "Scrollbar" group @@ -883,10 +880,6 @@ do_highlight( if (STRCMP(HL_TABLE()[idx].sg_name_u, "NORMAL") == 0) is_normal_group = TRUE; -#ifdef FEAT_TERMINAL - else if (STRCMP(HL_TABLE()[idx].sg_name_u, "TERMINAL") == 0) - is_terminal_group = TRUE; -#endif #ifdef FEAT_GUI_X11 else if (STRCMP(HL_TABLE()[idx].sg_name_u, "MENU") == 0) is_menu_group = TRUE; @@ -1535,11 +1528,6 @@ do_highlight( control_console_color_rgb(); #endif } -#ifdef FEAT_TERMINAL - else if (is_terminal_group) - set_terminal_default_colors( - HL_TABLE()[idx].sg_cterm_fg, HL_TABLE()[idx].sg_cterm_bg); -#endif #ifdef FEAT_GUI_X11 # ifdef FEAT_MENU else if (is_menu_group) diff --git a/src/insexpand.c b/src/insexpand.c index 9766855e22..6d007a6db2 100644 --- a/src/insexpand.c +++ b/src/insexpand.c @@ -299,7 +299,11 @@ has_compl_option(int dict_opt) && !curwin->w_p_spell #endif ) - : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL)) + : (*curbuf->b_p_tsr == NUL && *p_tsr == NUL +#ifdef FEAT_COMPL_FUNC + && *curbuf->b_p_tsrfu == NUL && *p_tsrfu == NUL +#endif + )) { ctrl_x_mode = CTRL_X_NORMAL; edit_submode = NULL; @@ -2234,6 +2238,25 @@ ins_compl_next_buf(buf_T *buf, int flag) } #ifdef FEAT_COMPL_FUNC +/* + * Get the user-defined completion function name for completion 'type' + */ + static char_u * +get_complete_funcname(int type) +{ + switch (type) + { + case CTRL_X_FUNCTION: + return curbuf->b_p_cfu; + case CTRL_X_OMNI: + return curbuf->b_p_ofu; + case CTRL_X_THESAURUS: + return *curbuf->b_p_tsrfu == NUL ? p_tsrfu : curbuf->b_p_tsrfu; + default: + return (char_u *)""; + } +} + /* * Execute user defined complete function 'completefunc' or 'omnifunc', and * get matches in "matches". @@ -2251,7 +2274,7 @@ expand_by_function( typval_T rettv; int save_State = State; - funcname = (type == CTRL_X_FUNCTION) ? curbuf->b_p_cfu : curbuf->b_p_ofu; + funcname = get_complete_funcname(type); if (*funcname == NUL) return; @@ -2725,6 +2748,20 @@ f_complete_info(typval_T *argvars, typval_T *rettv) } #endif +/* + * Returns TRUE when using a user-defined function for thesaurus completion. + */ + static int +thesaurus_func_complete(int type UNUSED) +{ +#ifdef FEAT_COMPL_FUNC + return type == CTRL_X_THESAURUS + && (*curbuf->b_p_tsrfu != NUL || *p_tsrfu != NUL); +#else + return FALSE; +#endif +} + /* * Get the next expansion(s), using "compl_pattern". * The search starts at position "ini" in curbuf and in the direction @@ -2911,7 +2948,12 @@ ins_compl_get_exp(pos_T *ini) case CTRL_X_DICTIONARY: case CTRL_X_THESAURUS: - ins_compl_dictionaries( +#ifdef FEAT_COMPL_FUNC + if (thesaurus_func_complete(type)) + expand_by_function(type, compl_pattern); + else +#endif + ins_compl_dictionaries( dict != NULL ? dict : (type == CTRL_X_THESAURUS ? (*curbuf->b_p_tsr == NUL @@ -3765,7 +3807,9 @@ ins_complete(int c, int enable_pum) } // Work out completion pattern and original text -- webb - if (ctrl_x_mode == CTRL_X_NORMAL || (ctrl_x_mode & CTRL_X_WANT_IDENT)) + if (ctrl_x_mode == CTRL_X_NORMAL + || (ctrl_x_mode & CTRL_X_WANT_IDENT + && !thesaurus_func_complete(ctrl_x_mode))) { if ((compl_cont_status & CONT_SOL) || ctrl_x_mode == CTRL_X_PATH_DEFINES) @@ -3915,7 +3959,8 @@ ins_complete(int c, int enable_pum) compl_col = (int)(compl_xp.xp_pattern - compl_pattern); compl_length = curs_col - compl_col; } - else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI) + else if (ctrl_x_mode == CTRL_X_FUNCTION || ctrl_x_mode == CTRL_X_OMNI + || thesaurus_func_complete(ctrl_x_mode)) { #ifdef FEAT_COMPL_FUNC // Call user defined function 'completefunc' with "a:findstart" @@ -3928,8 +3973,7 @@ ins_complete(int c, int enable_pum) // Call 'completefunc' or 'omnifunc' and get pattern length as a // string - funcname = ctrl_x_mode == CTRL_X_FUNCTION - ? curbuf->b_p_cfu : curbuf->b_p_ofu; + funcname = get_complete_funcname(ctrl_x_mode); if (*funcname == NUL) { semsg(_(e_notset), ctrl_x_mode == CTRL_X_FUNCTION diff --git a/src/mark.c b/src/mark.c index d606763121..c708e07e48 100644 --- a/src/mark.c +++ b/src/mark.c @@ -181,10 +181,8 @@ checkpcmark(void) if (curwin->w_prev_pcmark.lnum != 0 && (EQUAL_POS(curwin->w_pcmark, curwin->w_cursor) || curwin->w_pcmark.lnum == 0)) - { curwin->w_pcmark = curwin->w_prev_pcmark; - curwin->w_prev_pcmark.lnum = 0; // Show it has been checked - } + curwin->w_prev_pcmark.lnum = 0; // it has been checked } #if defined(FEAT_JUMPLIST) || defined(PROTO) diff --git a/src/memline.c b/src/memline.c index b43f10e12e..bfbf4e2807 100644 --- a/src/memline.c +++ b/src/memline.c @@ -1032,6 +1032,7 @@ set_b0_fname(ZERO_BL *b0p, buf_T *buf) #endif buf_store_time(buf, &st, buf->b_ffname); buf->b_mtime_read = buf->b_mtime; + buf->b_mtime_read_ns = buf->b_mtime_ns; } else { @@ -1040,7 +1041,9 @@ set_b0_fname(ZERO_BL *b0p, buf_T *buf) long_to_char(0L, b0p->b0_ino); #endif buf->b_mtime = 0; + buf->b_mtime_ns = 0; buf->b_mtime_read = 0; + buf->b_mtime_read_ns = 0; buf->b_orig_size = 0; buf->b_orig_mode = 0; } @@ -1786,7 +1789,6 @@ theend: apply_autocmds(EVENT_BUFREADPOST, NULL, curbuf->b_fname, FALSE, curbuf); apply_autocmds(EVENT_BUFWINENTER, NULL, curbuf->b_fname, FALSE, curbuf); } - return; } /* @@ -2437,6 +2439,9 @@ ml_sync_all(int check_file, int check_char) */ if (mch_stat((char *)buf->b_ffname, &st) == -1 || st.st_mtime != buf->b_mtime_read +#ifdef ST_MTIM_NSEC + || st.ST_MTIM_NSEC != buf->b_mtime_read_ns +#endif || st.st_size != buf->b_orig_size) { ml_preserve(buf, FALSE); @@ -3930,7 +3935,6 @@ ml_clearmarked(void) } lowest_marked = 0; - return; } /* diff --git a/src/move.c b/src/move.c index 9e3a714fd0..8fe00bb678 100644 --- a/src/move.c +++ b/src/move.c @@ -2682,7 +2682,6 @@ get_scroll_overlap(lineoff_T *lp, int dir) *lp = loff1; // 1 line overlap else *lp = loff2; // 2 lines overlap - return; } /* diff --git a/src/netbeans.c b/src/netbeans.c index cffed9f976..648a1b6a8f 100644 --- a/src/netbeans.c +++ b/src/netbeans.c @@ -1760,7 +1760,10 @@ nb_do_cmd( if (buf == NULL || buf->bufp == NULL) nbdebug((" invalid buffer identifier in setModtime\n")); else + { buf->bufp->b_mtime = atoi((char *)args); + buf->bufp->b_mtime_ns = 0; + } // ===================================================================== } else if (streq((char *)cmd, "setReadOnly")) diff --git a/src/normal.c b/src/normal.c index 78c6cb853e..ff13ccc648 100644 --- a/src/normal.c +++ b/src/normal.c @@ -3753,7 +3753,7 @@ nv_ident(cmdarg_T *cap) ptr = vim_strnsave(ptr, n); if (kp_ex) // Escape the argument properly for an Ex command - p = vim_strsave_fnameescape(ptr, FALSE); + p = vim_strsave_fnameescape(ptr, VSE_NONE); else // Escape the argument properly for a shell command p = vim_strsave_shellescape(ptr, TRUE, TRUE); @@ -5683,8 +5683,7 @@ nv_visual(cmdarg_T *cap) { curwin->w_cursor.lnum += resel_VIsual_line_count * cap->count0 - 1; - if (curwin->w_cursor.lnum > curbuf->b_ml.ml_line_count) - curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count; + check_cursor(); } VIsual_mode = resel_VIsual_mode; if (VIsual_mode == 'v') diff --git a/src/option.c b/src/option.c index 1cca2a63fa..f27b278f91 100644 --- a/src/option.c +++ b/src/option.c @@ -5239,6 +5239,11 @@ unset_global_local_option(char_u *name, void *from) case PV_TSR: clear_string_option(&buf->b_p_tsr); break; +#ifdef FEAT_COMPL_FUNC + case PV_TSRFU: + clear_string_option(&buf->b_p_tsrfu); + break; +#endif case PV_FP: clear_string_option(&buf->b_p_fp); break; @@ -5333,6 +5338,9 @@ get_varp_scope(struct vimoption *p, int opt_flags) #endif case PV_DICT: return (char_u *)&(curbuf->b_p_dict); case PV_TSR: return (char_u *)&(curbuf->b_p_tsr); +#ifdef FEAT_COMPL_FUNC + case PV_TSRFU: return (char_u *)&(curbuf->b_p_tsrfu); +#endif #if defined(FEAT_BEVAL) && defined(FEAT_EVAL) case PV_BEXPR: return (char_u *)&(curbuf->b_p_bexpr); #endif @@ -5413,6 +5421,10 @@ get_varp(struct vimoption *p) ? (char_u *)&(curbuf->b_p_dict) : p->var; case PV_TSR: return *curbuf->b_p_tsr != NUL ? (char_u *)&(curbuf->b_p_tsr) : p->var; +#ifdef FEAT_COMPL_FUNC + case PV_TSRFU: return *curbuf->b_p_tsrfu != NUL + ? (char_u *)&(curbuf->b_p_tsrfu) : p->var; +#endif case PV_FP: return *curbuf->b_p_fp != NUL ? (char_u *)&(curbuf->b_p_fp) : p->var; #ifdef FEAT_QUICKFIX @@ -6191,6 +6203,9 @@ buf_copy_options(buf_T *buf, int flags) #endif buf->b_p_dict = empty_option; buf->b_p_tsr = empty_option; +#ifdef FEAT_COMPL_FUNC + buf->b_p_tsrfu = empty_option; +#endif #ifdef FEAT_TEXTOBJ buf->b_p_qe = vim_strsave(p_qe); COPY_OPT_SCTX(buf, BV_QE); @@ -6505,8 +6520,6 @@ set_context_in_set_cmd( } #endif } - - return; } int diff --git a/src/option.h b/src/option.h index d9fd25cc1c..27f13ce1b1 100644 --- a/src/option.h +++ b/src/option.h @@ -404,6 +404,7 @@ EXTERN char_u *p_cinw; // 'cinwords' #ifdef FEAT_COMPL_FUNC EXTERN char_u *p_cfu; // 'completefunc' EXTERN char_u *p_ofu; // 'omnifunc' +EXTERN char_u *p_tsrfu; // 'thesaurusfunc' #endif EXTERN int p_ci; // 'copyindent' #ifdef FEAT_ANTIALIAS @@ -633,6 +634,9 @@ EXTERN char_u *p_guifontset; // 'guifontset' EXTERN char_u *p_guifontwide; // 'guifontwide' EXTERN int p_guipty; // 'guipty' #endif +#ifdef FEAT_GUI_GTK +EXTERN char_u *p_guiligatures; // 'guiligatures' +# endif #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) EXTERN long p_ghr; // 'guiheadroom' #endif @@ -1246,6 +1250,9 @@ enum #endif , BV_TAGS , BV_TC +#ifdef FEAT_COMPL_FUNC + , BV_TSRFU +#endif , BV_TS , BV_TW , BV_TX diff --git a/src/optiondefs.h b/src/optiondefs.h index 0bccb81077..d913022b41 100644 --- a/src/optiondefs.h +++ b/src/optiondefs.h @@ -143,6 +143,9 @@ #ifdef FEAT_EVAL # define PV_TFU OPT_BUF(BV_TFU) #endif +#ifdef FEAT_COMPL_FUNC +# define PV_TSRFU OPT_BOTH(OPT_BUF(BV_TSRFU)) +#endif #define PV_TAGS OPT_BOTH(OPT_BUF(BV_TAGS)) #define PV_TC OPT_BOTH(OPT_BUF(BV_TC)) #define PV_TS OPT_BUF(BV_TS) @@ -1278,6 +1281,19 @@ static struct vimoption options[] = {(char_u *)NULL, (char_u *)0L} #endif SCTX_INIT}, + + + {"guiligatures", "gli", P_STRING|P_VI_DEF|P_RCLR|P_ONECOMMA|P_NODUP, +#if defined(FEAT_GUI_GTK) + (char_u *)&p_guiligatures, PV_NONE, + {(char_u *)"", (char_u *)0L} +#else + (char_u *)NULL, PV_NONE, + {(char_u *)NULL, (char_u *)0L} +#endif + SCTX_INIT}, + + {"guiheadroom", "ghr", P_NUM|P_VI_DEF, #if defined(FEAT_GUI_GTK) || defined(FEAT_GUI_X11) (char_u *)&p_ghr, PV_NONE, @@ -2728,6 +2744,15 @@ static struct vimoption options[] = {"thesaurus", "tsr", P_STRING|P_EXPAND|P_VI_DEF|P_ONECOMMA|P_NODUP|P_NDNAME, (char_u *)&p_tsr, PV_TSR, {(char_u *)"", (char_u *)0L} SCTX_INIT}, + {"thesaurusfunc", "tsrfu", P_STRING|P_ALLOCED|P_VI_DEF|P_SECURE, +#ifdef FEAT_COMPL_FUNC + (char_u *)&p_tsrfu, PV_TSRFU, + {(char_u *)"", (char_u *)0L} +#else + (char_u *)NULL, PV_NONE, + {(char_u *)0L, (char_u *)0L} +#endif + SCTX_INIT}, {"tildeop", "top", P_BOOL|P_VI_DEF|P_VIM, (char_u *)&p_to, PV_NONE, {(char_u *)FALSE, (char_u *)0L} SCTX_INIT}, diff --git a/src/optionstr.c b/src/optionstr.c index f85640fcea..3948ad1045 100644 --- a/src/optionstr.c +++ b/src/optionstr.c @@ -271,6 +271,7 @@ check_buf_options(buf_T *buf) #ifdef FEAT_COMPL_FUNC check_string_option(&buf->b_p_cfu); check_string_option(&buf->b_p_ofu); + check_string_option(&buf->b_p_tsrfu); #endif #ifdef FEAT_EVAL check_string_option(&buf->b_p_tfu); @@ -1569,6 +1570,13 @@ ambw_end: redraw_gui_only = TRUE; } #endif +# if defined(FEAT_GUI_GTK) + else if (varp == &p_guiligatures) + { + gui_set_ligatures(); + redraw_gui_only = TRUE; + } +# endif #ifdef CURSOR_SHAPE // 'guicursor' diff --git a/src/os_unix.c b/src/os_unix.c index d4197293bb..24aff353cc 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4824,6 +4824,11 @@ mch_call_shell_fork( // push stream discipline modules if (options & SHELL_COOKED) setup_slavepty(pty_slave_fd); +# ifdef TIOCSCTTY + // Try to become controlling tty (probably doesn't work, + // unless run by root) + ioctl(pty_slave_fd, TIOCSCTTY, (char *)NULL); +# endif } # endif set_default_child_environment(FALSE); diff --git a/src/proto/ex_getln.pro b/src/proto/ex_getln.pro index faecab2a74..d047e39dab 100644 --- a/src/proto/ex_getln.pro +++ b/src/proto/ex_getln.pro @@ -26,7 +26,7 @@ void redrawcmd(void); void compute_cmdrow(void); void cursorcmd(void); void gotocmdline(int clr); -char_u *vim_strsave_fnameescape(char_u *fname, int shell); +char_u *vim_strsave_fnameescape(char_u *fname, int what); void escape_fname(char_u **pp); void tilde_replace(char_u *orig_pat, int num_files, char_u **files); cmdline_info_T *get_cmdline_info(void); diff --git a/src/proto/fileio.pro b/src/proto/fileio.pro index cdf92743b5..da6054b509 100644 --- a/src/proto/fileio.pro +++ b/src/proto/fileio.pro @@ -12,7 +12,7 @@ void msg_add_fname(buf_T *buf, char_u *fname); int msg_add_fileformat(int eol_type); void msg_add_lines(int insert_space, long lnum, off_T nchars); void msg_add_eol(void); -int time_differs(long t1, long t2); +int time_differs(stat_T *st, long mtime, long mtime_ns); int need_conversion(char_u *fenc); int get_fio_flags(char_u *ptr); int get_win_fio_flags(char_u *ptr); diff --git a/src/proto/gui.pro b/src/proto/gui.pro index d762420264..209e7f12e4 100644 --- a/src/proto/gui.pro +++ b/src/proto/gui.pro @@ -7,6 +7,7 @@ void gui_exit(int rc); void gui_shell_closed(void); int gui_init_font(char_u *font_list, int fontset); int gui_get_wide_font(void); +void gui_set_ligatures(void); void gui_update_cursor(int force, int clear_selection); void gui_position_menu(void); int gui_get_base_width(void); diff --git a/src/proto/gui_gtk_x11.pro b/src/proto/gui_gtk_x11.pro index 1d0a78b092..3fa2ac96d6 100644 --- a/src/proto/gui_gtk_x11.pro +++ b/src/proto/gui_gtk_x11.pro @@ -43,6 +43,7 @@ void gui_mch_set_fg_color(guicolor_T color); void gui_mch_set_bg_color(guicolor_T color); void gui_mch_set_sp_color(guicolor_T color); int gui_gtk2_draw_string(int row, int col, char_u *s, int len, int flags); +int gui_gtk2_draw_string_ext(int row, int col, char_u *s, int len, int flags, int force_pango); int gui_mch_haskey(char_u *name); int gui_get_x11_windis(Window *win, Display **dis); Display *gui_mch_get_display(void); diff --git a/src/proto/terminal.pro b/src/proto/terminal.pro index d2e5992562..061a668bf8 100644 --- a/src/proto/terminal.pro +++ b/src/proto/terminal.pro @@ -19,7 +19,6 @@ cursorentry_T *term_get_cursor_shape(guicolor_T *fg, guicolor_T *bg); int term_use_loop(void); void term_win_entered(void); int terminal_loop(int blocking); -void set_terminal_default_colors(int cterm_fg, int cterm_bg); int may_close_term_popup(void); void term_channel_closed(channel_T *ch); void term_check_channel_closed_recently(void); diff --git a/src/proto/vim9compile.pro b/src/proto/vim9compile.pro index 2b62b6c88b..5910c67d6c 100644 --- a/src/proto/vim9compile.pro +++ b/src/proto/vim9compile.pro @@ -17,6 +17,7 @@ void fill_exarg_from_cctx(exarg_T *eap, cctx_T *cctx); int assignment_len(char_u *p, int *heredoc); void vim9_declare_error(char_u *name); int check_vim9_unlet(char_u *name); +int check_global_and_subst(char_u *cmd, char_u *arg); int compile_def_function(ufunc_T *ufunc, int check_return_type, compiletype_T compile_type, cctx_T *outer_cctx); void set_function_type(ufunc_T *ufunc); void delete_instr(isn_T *isn); diff --git a/src/register.c b/src/register.c index f034c645b0..9f179ea151 100644 --- a/src/register.c +++ b/src/register.c @@ -2011,8 +2011,15 @@ do_put( } do { - totlen = count * yanklen; - if (totlen > 0) + long multlen = count * yanklen; + + totlen = multlen; + if (totlen != multlen) + { + emsg(_(e_resulting_text_too_long)); + break; + } + else if (totlen > 0) { oldp = ml_get(lnum); if (lnum > start_lnum) diff --git a/src/screen.c b/src/screen.c index c913522edd..b0d35d649b 100644 --- a/src/screen.c +++ b/src/screen.c @@ -4817,6 +4817,35 @@ screen_screenrow(void) } #endif +/* + * Calls mb_ptr2char_adv(p) and returns the character. + * If "p" starts with "\x", "\u" or "\U" the hex or unicode value is used. + */ + static int +get_encoded_char_adv(char_u **p) +{ + char_u *s = *p; + + if (s[0] == '\\' && (s[1] == 'x' || s[1] == 'u' || s[1] == 'U')) + { + varnumber_T num = 0; + int bytes; + int n; + + for (bytes = s[1] == 'x' ? 1 : s[1] == 'u' ? 2 : 4; bytes > 0; --bytes) + { + *p += 2; + n = hexhex2nr(*p); + if (n < 0) + return 0; + num = num * 256 + n; + } + *p += 2; + return num; + } + return mb_ptr2char_adv(p); +} + /* * Handle setting 'listchars' or 'fillchars'. * Assume monocell characters. @@ -4925,19 +4954,19 @@ set_chars_option(win_T *wp, char_u **varp) { c2 = c3 = 0; s = p + len + 1; - c1 = mb_ptr2char_adv(&s); + c1 = get_encoded_char_adv(&s); if (mb_char2cells(c1) > 1) return e_invarg; if (tab[i].cp == &lcs_chars.tab2) { if (*s == NUL) return e_invarg; - c2 = mb_ptr2char_adv(&s); + c2 = get_encoded_char_adv(&s); if (mb_char2cells(c2) > 1) return e_invarg; if (!(*s == ',' || *s == NUL)) { - c3 = mb_ptr2char_adv(&s); + c3 = get_encoded_char_adv(&s); if (mb_char2cells(c3) > 1) return e_invarg; } @@ -4979,7 +5008,7 @@ set_chars_option(win_T *wp, char_u **varp) multispace_len = 0; while (*s != NUL && *s != ',') { - c1 = mb_ptr2char_adv(&s); + c1 = get_encoded_char_adv(&s); if (mb_char2cells(c1) > 1) return e_invarg; ++multispace_len; @@ -4995,7 +5024,7 @@ set_chars_option(win_T *wp, char_u **varp) while (*s != NUL && *s != ',') { - c1 = mb_ptr2char_adv(&s); + c1 = get_encoded_char_adv(&s); if (p == last_multispace) lcs_chars.multispace[multispace_pos++] = c1; } diff --git a/src/search.c b/src/search.c index 99fb9b76ee..d78b0a5eb9 100644 --- a/src/search.c +++ b/src/search.c @@ -84,15 +84,14 @@ static int lastc_bytelen = 1; // >1 for multi-byte char // copy of spats[], for keeping the search patterns while executing autocmds static spat_T saved_spats[2]; +static char_u *saved_mr_pattern = NULL; # ifdef FEAT_SEARCH_EXTRA static int saved_spats_last_idx = 0; static int saved_spats_no_hlsearch = 0; # endif -static char_u *mr_pattern = NULL; // pattern used by search_regcomp() -#ifdef FEAT_RIGHTLEFT -static int mr_pattern_alloced = FALSE; // mr_pattern was allocated -#endif +// allocated copy of pattern used by search_regcomp() +static char_u *mr_pattern = NULL; #ifdef FEAT_FIND_ID /* @@ -161,29 +160,13 @@ search_regcomp( else if (options & SEARCH_HIS) // put new pattern in history add_to_history(HIST_SEARCH, pat, TRUE, NUL); + vim_free(mr_pattern); #ifdef FEAT_RIGHTLEFT - if (mr_pattern_alloced) - { - vim_free(mr_pattern); - mr_pattern_alloced = FALSE; - } - if (curwin->w_p_rl && *curwin->w_p_rlc == 's') - { - char_u *rev_pattern; - - rev_pattern = reverse_text(pat); - if (rev_pattern == NULL) - mr_pattern = pat; // out of memory, keep normal pattern. - else - { - mr_pattern = rev_pattern; - mr_pattern_alloced = TRUE; - } - } + mr_pattern = reverse_text(pat); else #endif - mr_pattern = pat; + mr_pattern = vim_strsave(pat); /* * Save the currently used pattern in the appropriate place, @@ -298,6 +281,10 @@ save_search_patterns(void) saved_spats[1] = spats[1]; if (spats[1].pat != NULL) saved_spats[1].pat = vim_strsave(spats[1].pat); + if (mr_pattern == NULL) + saved_mr_pattern = NULL; + else + saved_mr_pattern = vim_strsave(mr_pattern); #ifdef FEAT_SEARCH_EXTRA saved_spats_last_idx = last_idx; saved_spats_no_hlsearch = no_hlsearch; @@ -317,6 +304,8 @@ restore_search_patterns(void) #endif vim_free(spats[1].pat); spats[1] = saved_spats[1]; + vim_free(mr_pattern); + mr_pattern = saved_mr_pattern; #ifdef FEAT_SEARCH_EXTRA last_idx = saved_spats_last_idx; set_no_hlsearch(saved_spats_no_hlsearch); @@ -330,15 +319,7 @@ free_search_patterns(void) { vim_free(spats[0].pat); vim_free(spats[1].pat); - -# ifdef FEAT_RIGHTLEFT - if (mr_pattern_alloced) - { - vim_free(mr_pattern); - mr_pattern_alloced = FALSE; - mr_pattern = NULL; - } -# endif + VIM_CLEAR(mr_pattern); } #endif diff --git a/src/session.c b/src/session.c index a40a8f4930..9d274a9d01 100644 --- a/src/session.c +++ b/src/session.c @@ -43,7 +43,7 @@ ses_put_fname(FILE *fd, char_u *name, unsigned *flagp) } // escape special characters - p = vim_strsave_fnameescape(sname, FALSE); + p = vim_strsave_fnameescape(sname, VSE_NONE); vim_free(sname); if (p == NULL) return FAIL; diff --git a/src/structs.h b/src/structs.h index 2f34ec851a..295c5356c3 100644 --- a/src/structs.h +++ b/src/structs.h @@ -2704,10 +2704,10 @@ struct file_buffer // incremented for each change, also for undo #define CHANGEDTICK(buf) ((buf)->b_ct_di.di_tv.vval.v_number) - varnumber_T b_last_changedtick; // b:changedtick when TextChanged or - // TextChangedI was last triggered. - varnumber_T b_last_changedtick_pum; // b:changedtick when TextChangedP was + varnumber_T b_last_changedtick; // b:changedtick when TextChanged was // last triggered. + varnumber_T b_last_changedtick_pum; // b:changedtick for TextChangedP + varnumber_T b_last_changedtick_i; // b:changedtick for TextChangedI int b_saving; // Set to TRUE if we are in the middle of // saving the buffer. @@ -2727,7 +2727,9 @@ struct file_buffer wininfo_T *b_wininfo; // list of last used info for each window long b_mtime; // last change time of original file + long b_mtime_ns; // nanoseconds of last change time long b_mtime_read; // last change time when reading + long b_mtime_read_ns; // nanoseconds of last read time off_T b_orig_size; // size of original file in bytes int b_orig_mode; // mode of original file #ifdef FEAT_VIMINFO @@ -2967,6 +2969,9 @@ struct file_buffer unsigned b_tc_flags; // flags for 'tagcase' char_u *b_p_dict; // 'dictionary' local value char_u *b_p_tsr; // 'thesaurus' local value +#ifdef FEAT_COMPL_FUNC + char_u *b_p_tsrfu; // 'thesaurusfunc' local value +#endif long b_p_ul; // 'undolevels' local value #ifdef FEAT_PERSISTENT_UNDO int b_p_udf; // 'undofile' diff --git a/src/terminal.c b/src/terminal.c index 945a9c21dc..35f4e2dd68 100644 --- a/src/terminal.c +++ b/src/terminal.c @@ -204,10 +204,6 @@ static void handle_postponed_scrollback(term_T *term); // backspace key. static int term_backspace_char = BS; -// "Terminal" highlight group colors. -static int term_default_cterm_fg = -1; -static int term_default_cterm_bg = -1; - // Store the last set and the desired cursor properties, so that we only update // them when needed. Doing it unnecessary may result in flicker. static char_u *last_set_cursor_color = NULL; @@ -671,7 +667,7 @@ term_start( if (s == NULL) break; - p = vim_strsave_fnameescape(s, FALSE); + p = vim_strsave_fnameescape(s, VSE_NONE); if (p == NULL) break; ga_concat(&ga, p); @@ -2726,48 +2722,6 @@ may_toggle_cursor(term_T *term) } } -/* - * Cache "Terminal" highlight group colors. - */ - void -set_terminal_default_colors(int cterm_fg, int cterm_bg) -{ - term_default_cterm_fg = cterm_fg - 1; - term_default_cterm_bg = cterm_bg - 1; -} - - static int -get_default_cterm_fg(term_T *term) -{ - if (term->tl_highlight_name != NULL) - { - int id = syn_name2id(term->tl_highlight_name); - int fg = -1; - int bg = -1; - - if (id > 0) - syn_id2cterm_bg(id, &fg, &bg); - return fg; - } - return term_default_cterm_fg; -} - - static int -get_default_cterm_bg(term_T *term) -{ - if (term->tl_highlight_name != NULL) - { - int id = syn_name2id(term->tl_highlight_name); - int fg = -1; - int bg = -1; - - if (id > 0) - syn_id2cterm_bg(id, &fg, &bg); - return bg; - } - return term_default_cterm_bg; -} - /* * Reverse engineer the RGB value into a cterm color index. * First color is 1. Return 0 if no match found (default color). @@ -2914,10 +2868,34 @@ cell2attr( #ifdef FEAT_TERMGUICOLORS if (p_tgc) { - guicolor_T fg, bg; + guicolor_T fg = INVALCOLOR; + guicolor_T bg = INVALCOLOR; - fg = gui_get_rgb_color_cmn(cellfg.red, cellfg.green, cellfg.blue); - bg = gui_get_rgb_color_cmn(cellbg.red, cellbg.green, cellbg.blue); + // Use the 'wincolor' or "Terminal" highlighting for the default + // colors. + if (VTERM_COLOR_IS_DEFAULT_FG(&cellfg) + || VTERM_COLOR_IS_DEFAULT_BG(&cellbg)) + { + int id = 0; + + if (wp != NULL && *wp->w_p_wcr != NUL) + id = syn_name2id(wp->w_p_wcr); + if (id == 0) + id = syn_name2id(term_get_highlight_name(term)); + if (id > 0) + syn_id2colors(id, &fg, &bg); + if (!VTERM_COLOR_IS_DEFAULT_FG(&cellfg)) + fg = gui_get_rgb_color_cmn(cellfg.red, cellfg.green, + cellfg.blue); + if (!VTERM_COLOR_IS_DEFAULT_BG(&cellbg)) + bg = gui_get_rgb_color_cmn(cellbg.red, cellbg.green, + cellbg.blue); + } + else + { + fg = gui_get_rgb_color_cmn(cellfg.red, cellfg.green, cellfg.blue); + bg = gui_get_rgb_color_cmn(cellbg.red, cellbg.green, cellbg.blue); + } return get_tgc_attr_idx(attr, fg, bg); } @@ -2932,41 +2910,20 @@ cell2attr( // colors. if ((fg == 0 || bg == 0) && t_colors >= 16) { - int wincolor_fg = -1; - int wincolor_bg = -1; + int cterm_fg = -1; + int cterm_bg = -1; + int id = 0; if (wp != NULL && *wp->w_p_wcr != NUL) - { - int id = syn_name2id(curwin->w_p_wcr); - - // Get the 'wincolor' group colors. - if (id > 0) - syn_id2cterm_bg(id, &wincolor_fg, &wincolor_bg); - } - if (fg == 0) - { - if (wincolor_fg >= 0) - fg = wincolor_fg + 1; - else - { - int cterm_fg = get_default_cterm_fg(term); - - if (cterm_fg >= 0) - fg = cterm_fg + 1; - } - } - if (bg == 0) - { - if (wincolor_bg >= 0) - bg = wincolor_bg + 1; - else - { - int cterm_bg = get_default_cterm_bg(term); - - if (cterm_bg >= 0) - bg = cterm_bg + 1; - } - } + id = syn_name2id(wp->w_p_wcr); + if (id == 0) + id = syn_name2id(term_get_highlight_name(term)); + if (id > 0) + syn_id2cterm_bg(id, &cterm_fg, &cterm_bg); + if (fg == 0 && cterm_fg >= 0) + fg = cterm_fg + 1; + if (bg == 0 && cterm_bg >= 0) + bg = cterm_bg + 1; } // with 8 colors set the bold attribute to get a bright foreground @@ -4046,8 +4003,9 @@ init_default_colors(term_T *term, win_T *wp) #endif if (id != 0 && t_colors >= 16) { - int cterm_fg = get_default_cterm_fg(term); - int cterm_bg = get_default_cterm_bg(term); + int cterm_fg = -1; + int cterm_bg = -1; + syn_id2cterm_bg(id, &cterm_fg, &cterm_bg); if (cterm_fg >= 0) cterm_color2vterm(cterm_fg, fg); diff --git a/src/testdir/check.vim b/src/testdir/check.vim index bdb9f6b054..da8da14def 100644 --- a/src/testdir/check.vim +++ b/src/testdir/check.vim @@ -217,6 +217,14 @@ func CheckNotAsan() endif endfunc +" Command to check for X11 based GUI +command CheckX11BasedGui call CheckX11BasedGui() +func CheckX11BasedGui() + if !g:x11_based_gui + throw 'Skipped: requires X11 based GUI' + endif +endfunc + " Command to check for satisfying any of the conditions. " e.g. CheckAnyOf Feature:bsd Feature:sun Linux command -nargs=+ CheckAnyOf call CheckAnyOf() diff --git a/src/testdir/runtest.vim b/src/testdir/runtest.vim index 8c80dd17cd..53233e82ed 100644 --- a/src/testdir/runtest.vim +++ b/src/testdir/runtest.vim @@ -404,42 +404,6 @@ else endtry endif -" Names of flaky tests. -let s:flaky_tests = [ - \ 'Test_BufWrite_lockmarks()', - \ 'Test_autocmd_SafeState()', - \ 'Test_bufunload_all()', - \ 'Test_client_server()', - \ 'Test_close_and_exit_cb()', - \ 'Test_close_output_buffer()', - \ 'Test_collapse_buffers()', - \ 'Test_cwd()', - \ 'Test_diff_screen()', - \ 'Test_exit_callback_interval()', - \ 'Test_map_timeout_with_timer_interrupt()', - \ 'Test_out_cb()', - \ 'Test_pipe_through_sort_all()', - \ 'Test_pipe_through_sort_some()', - \ 'Test_popup_and_window_resize()', - \ 'Test_quoteplus()', - \ 'Test_quotestar()', - \ 'Test_reltime()', - \ 'Test_state()', - \ 'Test_terminal_composing_unicode()', - \ 'Test_terminal_does_not_truncate_last_newlines()', - \ 'Test_terminal_no_cmd()', - \ 'Test_terminal_noblock()', - \ 'Test_terminal_redir_file()', - \ 'Test_termwinscroll()', - \ 'Test_timer_oneshot()', - \ 'Test_timer_paused()', - \ 'Test_timer_repeat_many()', - \ 'Test_timer_repeat_three()', - \ 'Test_timer_stop_all_in_callback()', - \ 'Test_timer_stop_in_callback()', - \ 'Test_timer_with_partial_callback()', - \ ] - " Locate Test_ functions and execute them. redir @q silent function /^Test_ @@ -491,8 +455,7 @@ for g:testfunc in sort(s:tests) " - it fails five times (with a different message) if len(v:errors) > 0 \ && $TEST_NO_RETRY == '' - \ && (index(s:flaky_tests, g:testfunc) >= 0 - \ || g:test_is_flaky) + \ && g:test_is_flaky while 1 call add(s:messages, 'Found errors in ' . g:testfunc . ':') call extend(s:messages, v:errors) diff --git a/src/testdir/setup_gui.vim b/src/testdir/setup_gui.vim index 90ef1f1de1..05e49997b8 100644 --- a/src/testdir/setup_gui.vim +++ b/src/testdir/setup_gui.vim @@ -5,7 +5,6 @@ let g:x11_based_gui = has('gui_athena') || has('gui_motif') " Reasons for 'skipped'. let g:not_supported = "Skipped: Feature/Option not supported by this GUI: " -let g:not_implemented = "Skipped: Test not implemented yet for this GUI" let g:not_hosted = "Skipped: Test not hosted by the system/environment" " For KDE set a font, empty 'guifont' may cause a hang. diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index 15a01fbc3a..a23ed34bba 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -1490,6 +1490,7 @@ endfunc " Test for BufUnload autocommand that unloads all the other buffers func Test_bufunload_all() + let g:test_is_flaky = 1 call writefile(['Test file Xxx1'], 'Xxx1')" call writefile(['Test file Xxx2'], 'Xxx2')" @@ -1929,6 +1930,7 @@ func Test_ChangedP() let g:autocmd .= a:char endfunc + " TextChanged will not be triggered, only check that it isn't. au! TextChanged :call TextChangedAutocmd('N') au! TextChangedI :call TextChangedAutocmd('I') au! TextChangedP :call TextChangedAutocmd('P') @@ -2377,6 +2379,7 @@ endfunc func Test_autocmd_SafeState() CheckRunVimInTerminal + let g:test_is_flaky = 1 let lines =<< trim END let g:safe = 0 @@ -2457,6 +2460,7 @@ func Test_autocmd_was_using_freed_memory() endfunc func Test_BufWrite_lockmarks() + let g:test_is_flaky = 1 edit! Xtest call setline(1, ['a', 'b', 'c', 'd']) @@ -2863,5 +2867,42 @@ func Test_autocmd_with_block() augroup END endfunc +" Test TextChangedI and TextChanged +func Test_Changed_ChangedI() + new + call test_override("char_avail", 1) + let [g:autocmd_i, g:autocmd_n] = ['',''] + + func! TextChangedAutocmdI(char) + let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick + endfunc + + augroup Test_TextChanged + au! + au TextChanged :call TextChangedAutocmdI('N') + au TextChangedI :call TextChangedAutocmdI('I') + augroup END + + call feedkeys("ifoo\", 'tnix') + " TODO: Test test does not seem to trigger TextChanged autocommand, this + " requires running Vim in a terminal window. + " call assert_equal('N3', g:autocmd_n) + call assert_equal('I3', g:autocmd_i) + + call feedkeys("yyp", 'tnix') + " TODO: Test test does not seem to trigger TextChanged autocommand. + " call assert_equal('N4', g:autocmd_n) + call assert_equal('I3', g:autocmd_i) + + " CleanUp + call test_override("char_avail", 0) + au! TextChanged + au! TextChangedI + augroup! Test_TextChanged + delfu TextChangedAutocmdI + unlet! g:autocmd_i g:autocmd_n + + bw! +endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_channel.vim b/src/testdir/test_channel.vim index fbe6a84287..f8cdef4fc7 100644 --- a/src/testdir/test_channel.vim +++ b/src/testdir/test_channel.vim @@ -795,6 +795,7 @@ func Test_pipe_to_buffer_name_nomsg() endfunc func Test_close_output_buffer() + let g:test_is_flaky = 1 enew! let test_lines = ['one', 'two'] call setline(1, test_lines) @@ -935,6 +936,7 @@ endfunc func Run_pipe_through_sort(all, use_buffer) CheckExecutable sort + let g:test_is_flaky = 1 let options = {'out_io': 'buffer', 'out_name': 'sortout'} if a:use_buffer @@ -1206,6 +1208,7 @@ func Test_reuse_channel() endfunc func Test_out_cb() + let g:test_is_flaky = 1 let dict = {'thisis': 'dict: '} func dict.outHandler(chan, msg) dict if type(a:msg) == v:t_string @@ -1333,6 +1336,7 @@ func Test_out_cb_lambda() endfunc func Test_close_and_exit_cb() + let g:test_is_flaky = 1 let g:retdict = {'ret': {}} func g:retdict.close_cb(ch) dict let self.ret['close_cb'] = a:ch->ch_getjob()->job_status() @@ -1560,6 +1564,7 @@ endfunction func Test_exit_callback_interval() CheckFunction reltimefloat + let g:test_is_flaky = 1 let g:exit_cb_val = {'start': reltime(), 'end': 0, 'process': 0} let job = [s:python, '-c', 'import time;time.sleep(0.5)']->job_start({'exit_cb': 'MyExitTimeCb'}) @@ -1742,6 +1747,7 @@ func Test_using_freed_memory() endfunc func Test_collapse_buffers() + let g:test_is_flaky = 1 CheckExecutable cat sp test_channel.vim @@ -1884,6 +1890,7 @@ func Test_env() endfunc func Test_cwd() + let g:test_is_flaky = 1 let g:envstr = '' if has('win32') let expect = $TEMP diff --git a/src/testdir/test_clientserver.vim b/src/testdir/test_clientserver.vim index 919f59b243..e253261e46 100644 --- a/src/testdir/test_clientserver.vim +++ b/src/testdir/test_clientserver.vim @@ -32,6 +32,7 @@ func Check_X11_Connection() endfunc func Test_client_server() + let g:test_is_flaky = 1 let cmd = GetVimCommand() if cmd == '' throw 'GetVimCommand() failed' diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim index a0f3ffda42..9c21a205f7 100644 --- a/src/testdir/test_cmdline.vim +++ b/src/testdir/test_cmdline.vim @@ -900,6 +900,15 @@ func Test_cmdline_complete_various() call feedkeys(":unlet one two\\\"\", 'xt') call assert_equal("\"unlet one two", @:) + " completion for the :buffer command with curlies + " FIXME: what should happen on MS-Windows? + if !has('win32') + edit \{someFile} + call feedkeys(":buf someFile\\\"\", 'xt') + call assert_equal("\"buf {someFile}", @:) + bwipe {someFile} + endif + " completion for the :bdelete command call feedkeys(":bdel a b c\\\"\", 'xt') call assert_equal("\"bdel a b c", @:) diff --git a/src/testdir/test_crypt.vim b/src/testdir/test_crypt.vim index 2e34c80a1d..f43c22af01 100644 --- a/src/testdir/test_crypt.vim +++ b/src/testdir/test_crypt.vim @@ -3,6 +3,13 @@ source check.vim CheckFeature cryptv +let s:xxd_cmd = '' +if empty($XXDPROG) && executable('..\xxd\xxd.exe') + let s:xxd_cmd = '..\xxd\xxd.exe' +elseif !empty($XXDPROG) && executable($XXDPROG) + let s:xxd_cmd = $XXDPROG +endif + func Common_head_only(text) " This was crashing Vim split Xtest.txt @@ -81,8 +88,11 @@ func Uncrypt_stable(method, crypted_text, key, uncrypted_text) endfunc func Uncrypt_stable_xxd(method, hex, key, uncrypted_text) + if empty(s:xxd_cmd) + throw 'Skipped: xxd program missing' + endif " use xxd to write the binary content - call system('xxd -r >Xtest.txt', a:hex) + call system(s:xxd_cmd .. ' -r >Xtest.txt', a:hex) call feedkeys(":split Xtest.txt\" . a:key . "\", 'xt') call assert_equal(a:uncrypted_text, getline(1, len(a:uncrypted_text))) bwipe! diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim index 268c3e9b54..08ec71b918 100644 --- a/src/testdir/test_diffmode.vim +++ b/src/testdir/test_diffmode.vim @@ -845,6 +845,7 @@ func VerifyInternal(buf, dumpfile, extra) endfunc func Test_diff_screen() + let g:test_is_flaky = 1 CheckScreendump CheckFeature menu diff --git a/src/testdir/test_edit.vim b/src/testdir/test_edit.vim index ebe8beea4a..76c63aa6b8 100644 --- a/src/testdir/test_edit.vim +++ b/src/testdir/test_edit.vim @@ -890,6 +890,56 @@ func Test_edit_CTRL_T() bw! endfunc +" Test 'thesaurusfunc' +func MyThesaurus(findstart, base) + let mythesaurus = [ + \ #{word: "happy", + \ synonyms: "cheerful,blissful,flying high,looking good,peppy"}, + \ #{word: "kind", + \ synonyms: "amiable,bleeding-heart,heart in right place"}] + if a:findstart + " locate the start of the word + let line = getline('.') + let start = col('.') - 1 + while start > 0 && line[start - 1] =~ '\a' + let start -= 1 + endwhile + return start + else + " find strings matching with "a:base" + let res = [] + for w in mythesaurus + if w.word =~ '^' . a:base + call add(res, w.word) + call extend(res, split(w.synonyms, ",")) + endif + endfor + return res + endif +endfunc + +func Test_thesaurus_func() + new + set thesaurus=notused + set thesaurusfunc=NotUsed + setlocal thesaurusfunc=MyThesaurus + call setline(1, "an ki") + call cursor(1, 1) + call feedkeys("A\\\\\", 'tnix') + call assert_equal(['an amiable', ''], getline(1, '$')) + + setlocal thesaurusfunc=NonExistingFunc + call assert_fails("normal $a\\", 'E117:') + + setlocal thesaurusfunc= + set thesaurusfunc=NonExistingFunc + call assert_fails("normal $a\\", 'E117:') + %bw! + + set thesaurusfunc= + set thesaurus= +endfunc + func Test_edit_CTRL_U() " Test 'completefunc' new diff --git a/src/testdir/test_filetype.vim b/src/testdir/test_filetype.vim index b1aa7cd256..ef2ac8474c 100644 --- a/src/testdir/test_filetype.vim +++ b/src/testdir/test_filetype.vim @@ -112,7 +112,7 @@ let s:filename_checks = { \ 'coco': ['file.atg'], \ 'conaryrecipe': ['file.recipe'], \ 'conf': ['auto.master'], - \ 'config': ['configure.in', 'configure.ac', 'Pipfile', '/etc/hostname.file'], + \ 'config': ['configure.in', 'configure.ac', '/etc/hostname.file'], \ 'context': ['tex/context/any/file.tex', 'file.mkii', 'file.mkiv', 'file.mkvi', 'file.mkxl', 'file.mklx'], \ 'cpp': ['file.cxx', 'file.c++', 'file.hh', 'file.hxx', 'file.hpp', 'file.ipp', 'file.moc', 'file.tcc', 'file.inl', 'file.tlh'], \ 'crm': ['file.crm'], @@ -504,8 +504,8 @@ let s:filename_checks = { \ 'tidy': ['.tidyrc', 'tidyrc', 'tidy.conf'], \ 'tilde': ['file.t.html'], \ 'tli': ['file.tli'], - \ 'tmux': ['tmuxfile.conf', '.tmuxfile.conf', '.tmux-file.conf', '.tmux.conf', 'tmux-file.conf', 'tmux.conf'], - \ 'toml': ['file.toml'], + \ 'tmux': ['tmuxfile.conf', '.tmuxfile.conf', '.tmux-file.conf', '.tmux.conf', 'tmux-file.conf', 'tmux.conf', 'tmux.conf.local'], + \ 'toml': ['file.toml', 'Gopkg.lock', 'Pipfile', '/home/user/.cargo/config'], \ 'tpp': ['file.tpp'], \ 'treetop': ['file.treetop'], \ 'trustees': ['trustees.conf'], @@ -555,6 +555,7 @@ let s:filename_checks = { \ 'xml': ['/etc/blkid.tab', '/etc/blkid.tab.old', 'file.xmi', 'file.csproj', 'file.csproj.user', 'file.ui', 'file.tpm', '/etc/xdg/menus/file.menu', 'fglrxrc', 'file.xlf', 'file.xliff', 'file.xul', 'file.wsdl', 'file.wpl', 'any/etc/blkid.tab', 'any/etc/blkid.tab.old', 'any/etc/xdg/menus/file.menu', 'file.atom', 'file.rss', 'file.cdxml', 'file.psc1', 'file.mpd'], \ 'xmodmap': ['anyXmodmap', 'Xmodmap', 'some-Xmodmap', 'some-xmodmap', 'some-xmodmap-file', 'xmodmap', 'xmodmap-file'], \ 'xf86conf': ['xorg.conf', 'xorg.conf-4'], + \ 'xpm': ['file.xpm'], \ 'xpm2': ['file.xpm2'], \ 'xquery': ['file.xq', 'file.xql', 'file.xqm', 'file.xquery', 'file.xqy'], \ 'xs': ['file.xs'], @@ -569,7 +570,6 @@ let s:filename_checks = { \ 'zsh': ['.zprofile', '/etc/zprofile', '.zfbfmarks', 'file.zsh', '.zcompdump', '.zlogin', '.zlogout', '.zshenv', '.zshrc', '.zcompdump-file', '.zlog', '.zlog-file', '.zsh', '.zsh-file', 'any/etc/zprofile', 'zlog', 'zlog-file', 'zsh', 'zsh-file'], \ \ 'help': [$VIMRUNTIME . '/doc/help.txt'], - \ 'xpm': ['file.xpm'], \ } let s:filename_case_checks = { @@ -943,4 +943,17 @@ func Test_m_file() call delete('Xfile.m') filetype off endfunc + +func Test_xpm_file() + filetype on + + call writefile(['this is XPM2'], 'file.xpm') + split file.xpm + call assert_equal('xpm2', &filetype) + bwipe! + + call delete('file.xpm') + filetype off +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index d060ac418f..7dd1894fa1 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -2286,6 +2286,7 @@ endfunc func Test_state() CheckRunVimInTerminal + let g:test_is_flaky = 1 let getstate = ":echo 'state: ' .. g:state .. '; mode: ' .. g:mode\" diff --git a/src/testdir/test_gui.vim b/src/testdir/test_gui.vim index aeae063313..90ed2af374 100644 --- a/src/testdir/test_gui.vim +++ b/src/testdir/test_gui.vim @@ -61,11 +61,9 @@ func Test_colorscheme() endfunc func Test_getfontname_with_arg() - let skipped = '' + CheckX11BasedGui - if !g:x11_based_gui - let skipped = g:not_implemented - elseif has('gui_athena') || has('gui_motif') + if has('gui_athena') || has('gui_motif') " Invalid font name. The result should be an empty string. call assert_equal('', getfontname('notexist')) @@ -82,20 +80,14 @@ func Test_getfontname_with_arg() let fname = 'Bitstream Vera Sans Mono 12' call assert_equal(fname, getfontname(fname)) endif - - if !empty(skipped) - throw skipped - endif endfunc func Test_getfontname_without_arg() - let skipped = '' + CheckX11BasedGui let fname = getfontname() - if !g:x11_based_gui - let skipped = g:not_implemented - elseif has('gui_kde') + if has('gui_kde') " 'expected' is the value specified by SetUp() above. call assert_equal('Courier 10 Pitch/8/-1/5/50/0/0/0/0/0', fname) elseif has('gui_athena') || has('gui_motif') @@ -106,10 +98,6 @@ func Test_getfontname_without_arg() " 'expected' is DEFAULT_FONT of gui_gtk_x11.c. call assert_equal('Monospace 10', fname) endif - - if !empty(skipped) - throw skipped - endif endfunc func Test_getwinpos() @@ -120,47 +108,41 @@ func Test_getwinpos() endfunc func Test_quoteplus() - let skipped = '' + CheckX11BasedGui - if !g:x11_based_gui - let skipped = g:not_supported . 'quoteplus' - else - let quoteplus_saved = @+ + let g:test_is_flaky = 1 - let test_call = 'Can you hear me?' - let test_response = 'Yes, I can.' - let vim_exe = GetVimCommand() - let testee = 'VIMRUNTIME=' . $VIMRUNTIME . '; export VIMRUNTIME;' - \ . vim_exe . ' --noplugin --not-a-term -c ''%s''' - " Ignore the "failed to create input context" error. - let cmd = 'call test_ignore_error("E285") | ' - \ . 'gui -f | ' - \ . 'call feedkeys("' - \ . '\"+p' - \ . ':s/' . test_call . '/' . test_response . '/\' - \ . '\"+yis' - \ . ':q!\", "tx")' - let run_vimtest = printf(testee, cmd) + let quoteplus_saved = @+ - " Set the quoteplus register to test_call, and another gvim will launched. - " Then, it first tries to paste the content of its own quotedplus register - " onto it. Second, it tries to substitute test_response for the pasted - " sentence. If the sentence is identical to test_call, the substitution - " should succeed. Third, it tries to yank the result of the substitution - " to its own quoteplus register, and last it quits. When system() - " returns, the content of the quoteplus register should be identical to - " test_response if those quoteplus registers are synchronized properly - " with/through the X11 clipboard. - let @+ = test_call - call system(run_vimtest) - call assert_equal(test_response, @+) + let test_call = 'Can you hear me?' + let test_response = 'Yes, I can.' + let vim_exe = GetVimCommand() + let testee = 'VIMRUNTIME=' . $VIMRUNTIME . '; export VIMRUNTIME;' + \ . vim_exe . ' --noplugin --not-a-term -c ''%s''' + " Ignore the "failed to create input context" error. + let cmd = 'call test_ignore_error("E285") | ' + \ . 'gui -f | ' + \ . 'call feedkeys("' + \ . '\"+p' + \ . ':s/' . test_call . '/' . test_response . '/\' + \ . '\"+yis' + \ . ':q!\", "tx")' + let run_vimtest = printf(testee, cmd) - let @+ = quoteplus_saved - endif + " Set the quoteplus register to test_call, and another gvim will launched. + " Then, it first tries to paste the content of its own quotedplus register + " onto it. Second, it tries to substitute test_response for the pasted + " sentence. If the sentence is identical to test_call, the substitution + " should succeed. Third, it tries to yank the result of the substitution + " to its own quoteplus register, and last it quits. When system() + " returns, the content of the quoteplus register should be identical to + " test_response if those quoteplus registers are synchronized properly + " with/through the X11 clipboard. + let @+ = test_call + call system(run_vimtest) + call assert_equal(test_response, @+) - if !empty(skipped) - throw skipped - endif + let @+ = quoteplus_saved endfunc func Test_set_background() @@ -332,8 +314,29 @@ func Test_set_guicursor() let &guicursor = guicursor_saved endfunc +func Test_set_guifont_errors() + if has('win32') + " Invalid font names are accepted in GTK GUI + call assert_fails('set guifont=xa1bc23d7f', 'E596:') + endif + + " This only works if 'renderoptions' exists and does not work for Windows XP + " and older. + if exists('+renderoptions') && windowsversion() !~ '^[345]\.' + " doing this four times used to cause a crash + set renderoptions=type:directx + for i in range(5) + set guifont= + endfor + set renderoptions= + for i in range(5) + set guifont= + endfor + endif +endfunc + func Test_set_guifont() - let skipped = '' + CheckX11BasedGui let guifont_saved = &guifont if has('xfontset') @@ -342,9 +345,7 @@ func Test_set_guifont() set guifontset= endif - if !g:x11_based_gui - let skipped = g:not_implemented - elseif has('gui_athena') || has('gui_motif') + if has('gui_athena') || has('gui_motif') " Non-empty font list with invalid font names. " " This test is twofold: (1) It checks if the command fails as expected @@ -383,33 +384,10 @@ func Test_set_guifont() call assert_equal('Monospace 10', getfontname()) endif - if has('win32') - " Invalid font names are accepted in GTK GUI - call assert_fails('set guifont=xa1bc23d7f', 'E596:') - endif - - " This only works if 'renderoptions' exists and does not work for Windows XP - " and older. - if exists('+renderoptions') && windowsversion() !~ '^[345]\.' - " doing this four times used to cause a crash - set renderoptions=type:directx - for i in range(5) - set guifont= - endfor - set renderoptions= - for i in range(5) - set guifont= - endfor - endif - if has('xfontset') let &guifontset = guifontset_saved endif let &guifont = guifont_saved - - if !empty(skipped) - throw skipped - endif endfunc func Test_set_guifontset() @@ -484,12 +462,11 @@ func Test_set_guifontset() endfunc func Test_set_guifontwide() - call assert_fails('set guifontwide=*', 'E533:') - let skipped = '' + CheckX11BasedGui - if !g:x11_based_gui - let skipped = g:not_implemented - elseif has('gui_gtk') + call assert_fails('set guifontwide=*', 'E533:') + + if has('gui_gtk') let guifont_saved = &guifont let guifontwide_saved = &guifontwide @@ -560,26 +537,31 @@ func Test_set_guifontwide() let &encoding = encoding_saved endif endif +endfunc - if !empty(skipped) - throw skipped +func Test_set_guiligatures() + CheckX11BasedGui + + if has('gui_gtk') || has('gui_gtk2') || has('gui_gnome') || has('gui_gtk3') + " Try correct value + set guiligatures=<>=ab + call assert_equal("<>=ab", &guiligatures) + " Try to throw error + try + set guiligatures=<>=šab + call assert_report("'set guiligatures=<>=šab should have failed") + catch + call assert_exception('E1243:') + endtry endif endfunc func Test_set_guiheadroom() - let skipped = '' + CheckX11BasedGui - if !g:x11_based_gui - let skipped = g:not_supported . 'guiheadroom' - else - " Since this script is to be read together with '-U NONE', the default - " value must be preserved. - call assert_equal(50, &guiheadroom) - endif - - if !empty(skipped) - throw skipped - endif + " Since this script is to be read together with '-U NONE', the default + " value must be preserved. + call assert_equal(50, &guiheadroom) endfunc func Test_set_guioptions() diff --git a/src/testdir/test_gui_init.vim b/src/testdir/test_gui_init.vim index 70f0414c6d..6f22013508 100644 --- a/src/testdir/test_gui_init.vim +++ b/src/testdir/test_gui_init.vim @@ -22,19 +22,11 @@ call test_ignore_error('E285:') gui -f func Test_set_guiheadroom() - let skipped = '' + CheckX11BasedGui - if !g:x11_based_gui - let skipped = g:not_supported . 'guiheadroom' - else - " The 'expected' value must be consistent with the value specified with - " gui_init.vim. - call assert_equal(0, &guiheadroom) - endif - - if !empty(skipped) - throw skipped - endif + " The 'expected' value must be consistent with the value specified with + " gui_init.vim. + call assert_equal(0, &guiheadroom) endfunc func Test_set_guioptions_for_M() @@ -44,19 +36,11 @@ func Test_set_guioptions_for_M() endfunc func Test_set_guioptions_for_p() - let skipped = '' + CheckX11BasedGui - if !g:x11_based_gui - let skipped = g:not_supported . '''p'' of guioptions' - else - sleep 200ms - " Check if the 'p' option is included. - call assert_match('.*p.*', &guioptions) - endif - - if !empty(skipped) - throw skipped - endif + sleep 200ms + " Check if the 'p' option is included. + call assert_match('.*p.*', &guioptions) endfunc " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_listchars.vim b/src/testdir/test_listchars.vim index 4cbd3650b4..cb947aa84b 100644 --- a/src/testdir/test_listchars.vim +++ b/src/testdir/test_listchars.vim @@ -288,6 +288,10 @@ func Test_listchars_unicode() call cursor(1, 1) call assert_equal(expected, ScreenLines(1, virtcol('$'))) + set listchars=eol:\\u21d4,space:\\u2423,multispace:≡\\u2262\\U00002263,nbsp:\\U00002260,tab:←↔\\u2192 + redraw! + call assert_equal(expected, ScreenLines(1, virtcol('$'))) + set listchars+=lead:⇨,trail:⇦ let expected = ['⇨⇨⇨⇨⇨⇨⇨⇨a←↔↔↔↔↔→b␣c≠d⇦⇦⇔'] redraw! diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim index a447ba32f3..d2b9f37d10 100644 --- a/src/testdir/test_mapping.vim +++ b/src/testdir/test_mapping.vim @@ -289,6 +289,7 @@ endfunc func Test_map_timeout_with_timer_interrupt() CheckFeature job CheckFeature timers + let g:test_is_flaky = 1 " Confirm the timer invoked in exit_cb of the job doesn't disturb mapped key " sequence. @@ -1155,7 +1156,7 @@ func Test_map_cmdkey_visual_mode() call feedkeys("v\", 'xt!') call assert_equal(['v', 1, 12], [mode(1), col('v'), col('.')]) - " can invoke an opeartor, ending the visual mode + " can invoke an operator, ending the visual mode let @a = '' call feedkeys("\", 'xt!') call assert_equal('n', mode(1)) diff --git a/src/testdir/test_marks.vim b/src/testdir/test_marks.vim index dcf4904d06..12501a3aba 100644 --- a/src/testdir/test_marks.vim +++ b/src/testdir/test_marks.vim @@ -26,6 +26,16 @@ func Test_Incr_Marks() enew! endfunc +func Test_previous_jump_mark() + new + call setline(1, ['']->repeat(6)) + normal Ggg + call assert_equal(6, getpos("''")[1]) + normal jjjjj + call assert_equal(6, getpos("''")[1]) + bwipe! +endfunc + func Test_setpos() new Xone let onebuf = bufnr('%') diff --git a/src/testdir/test_options.vim b/src/testdir/test_options.vim index 09f56f81fc..7d4f19f970 100644 --- a/src/testdir/test_options.vim +++ b/src/testdir/test_options.vim @@ -256,7 +256,7 @@ func Test_set_completion() " Expand abbreviation of options. call feedkeys(":set ts\\\"\", 'tx') - call assert_equal('"set tabstop thesaurus ttyscroll', @:) + call assert_equal('"set tabstop thesaurus thesaurusfunc ttyscroll', @:) " Expand current value call feedkeys(":set fileencodings=\\\"\", 'tx') diff --git a/src/testdir/test_paste.vim b/src/testdir/test_paste.vim index ef35cec806..c94fe7c357 100644 --- a/src/testdir/test_paste.vim +++ b/src/testdir/test_paste.vim @@ -136,6 +136,8 @@ endfunc func Test_xrestore() CheckFeature xterm_clipboard + let g:test_is_flaky = 1 + let display = $DISPLAY new call CheckCopyPaste() diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim index 0799df5480..2f29163ede 100644 --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -665,6 +665,7 @@ func Test_popup_and_window_resize() CheckFeature terminal CheckFeature quickfix CheckNotGui + let g:test_is_flaky = 1 let h = winheight(0) if h < 15 diff --git a/src/testdir/test_put.vim b/src/testdir/test_put.vim index f3a320f463..4e3294679c 100644 --- a/src/testdir/test_put.vim +++ b/src/testdir/test_put.vim @@ -1,5 +1,7 @@ " Tests for put commands, e.g. ":put", "p", "gp", "P", "gP", etc. +source check.vim + func Test_put_block() new call feedkeys("i\u2500\x\", 'x') @@ -134,4 +136,15 @@ func Test_gp_with_count_leaves_cursor_at_end() bwipe! endfunc +func Test_very_large_count() + " FIXME: should actually check if sizeof(int) == sizeof(long) + CheckNotMSWindows + + new + let @" = 'x' + call assert_fails('norm 44444444444444p', 'E1240:') + bwipe! +endfunc + + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_quotestar.vim b/src/testdir/test_quotestar.vim index 6b8aebfff7..b669019d8e 100644 --- a/src/testdir/test_quotestar.vim +++ b/src/testdir/test_quotestar.vim @@ -131,6 +131,7 @@ func Do_test_quotestar_for_x11() endfunc func Test_quotestar() + let g:test_is_flaky = 1 let skipped = '' let quotestar_saved = @* diff --git a/src/testdir/test_recover.vim b/src/testdir/test_recover.vim index 9d2588313e..d0129747bb 100644 --- a/src/testdir/test_recover.vim +++ b/src/testdir/test_recover.vim @@ -208,9 +208,11 @@ func Test_recover_corrupted_swap_file() " Not all fields are written in a system-independent manner. Detect whether " the test is running on a little or big-endian system, so the correct " corruption values can be set. - let little_endian = b[1008:1011] == 0z33323130 - " The swap file header fields can be either 32-bit or 64-bit. - let system_64bit = b[1012:1015] == 0z00000000 + " The B0_MAGIC_LONG field may be 32-bit or 64-bit, depending on the system, + " even though the value stored is only 32-bits. Therefore, need to check + " both the high and low 32-bits to compute these values. + let little_endian = (b[1008:1011] == 0z33323130) || (b[1012:1015] == 0z33323130) + let system_64bit = little_endian ? (b[1012:1015] == 0z00000000) : (b[1008:1011] == 0z00000000) " clear the B0_MAGIC_LONG field if system_64bit diff --git a/src/testdir/test_reltime.vim b/src/testdir/test_reltime.vim index c76d7a1684..2f2e7aed7e 100644 --- a/src/testdir/test_reltime.vim +++ b/src/testdir/test_reltime.vim @@ -5,6 +5,7 @@ CheckFeature reltime CheckFeature float func Test_reltime() + let g:test_is_flaky = 1 let now = reltime() sleep 10m let later = reltime() diff --git a/src/testdir/test_search.vim b/src/testdir/test_search.vim index bb4e45defa..eaf9c23269 100644 --- a/src/testdir/test_search.vim +++ b/src/testdir/test_search.vim @@ -1989,5 +1989,19 @@ func Test_no_last_search_pattern() call feedkeys("??\", 'xt') endfunc +func Test_search_with_invalid_range() + new + let lines =<< trim END + /\%.v + 5/ + c + END + call writefile(lines, 'Xrangesearch') + source Xrangesearch + + bwipe! + call delete('Xrangesearch') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_startup.vim b/src/testdir/test_startup.vim index deecde344f..3e8a017031 100644 --- a/src/testdir/test_startup.vim +++ b/src/testdir/test_startup.vim @@ -533,7 +533,14 @@ func Test_geometry() [CODE] if RunVim([], after, '-f -g -geometry 31x13+41+43') let lines = readfile('Xtest_geometry') - call assert_equal(['31', '13', '41', '43', '[41, 43]'], lines) + " Depending on the GUI library and the windowing system the final size + " might be a bit different, allow for some tolerance. Tuned based on + " actual failures. + call assert_inrange(31, 35, str2nr(lines[0])) + call assert_equal('13', lines[1]) + call assert_equal('41', lines[2]) + call assert_equal('43', lines[3]) + call assert_equal('[41, 43]', lines[4]) endif endif diff --git a/src/testdir/test_stat.vim b/src/testdir/test_stat.vim index 5cd82b8e2f..fa61c5c063 100644 --- a/src/testdir/test_stat.vim +++ b/src/testdir/test_stat.vim @@ -76,6 +76,42 @@ func Test_checktime() call delete(fname) endfunc +func Test_checktime_fast() + CheckFeature nanotime + + let fname = 'Xtest.tmp' + + let fl = ['Hello World!'] + call writefile(fl, fname) + set autoread + exec 'e' fname + let fl = readfile(fname) + let fl[0] .= ' - checktime' + call writefile(fl, fname) + checktime + call assert_equal(fl[0], getline(1)) + + call delete(fname) +endfunc + +func Test_autoread_fast() + CheckFeature nanotime + + " this is timing sensitive + let g:test_is_flaky = 1 + + new Xautoread + setlocal autoread + call setline(1, 'foo') + w! + silent !echo bar > Xautoread + sleep 10m + checktime + call assert_equal('bar', trim(getline(1))) + + call delete('Xautoread') +endfunc + func Test_autoread_file_deleted() new Xautoread set autoread diff --git a/src/testdir/test_statusline.vim b/src/testdir/test_statusline.vim index f3eea2e71e..a952de69b9 100644 --- a/src/testdir/test_statusline.vim +++ b/src/testdir/test_statusline.vim @@ -522,4 +522,14 @@ func Test_statusline_mbyte_fillchar() %bw! endfunc +" Used to write beyond allocated memory. This assumes MAXPATHL is 4096 bytes. +func Test_statusline_verylong_filename() + let fname = repeat('x', 4090) + exe "new " .. fname + set buftype=help + set previewwindow + redraw + bwipe! +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_terminal.vim b/src/testdir/test_terminal.vim index 16eda1f37b..6cb0619742 100644 --- a/src/testdir/test_terminal.vim +++ b/src/testdir/test_terminal.vim @@ -698,6 +698,7 @@ func Test_terminal_list_args() endfunction func Test_terminal_noblock() + let g:test_is_flaky = 1 let buf = term_start(&shell) let wait_time = 5000 let letters = 'abcdefghijklmnopqrstuvwxyz' @@ -805,6 +806,7 @@ func Test_terminal_duplicate_eof_arg() endfunc func Test_terminal_no_cmd() + let g:test_is_flaky = 1 let buf = term_start('NONE', {}) call assert_notequal(0, buf) @@ -855,6 +857,7 @@ func Test_terminal_wrong_options() endfunc func Test_terminal_redir_file() + let g:test_is_flaky = 1 let cmd = Get_cat_123_cmd() let buf = term_start(cmd, {'out_io': 'file', 'out_name': 'Xfile'}) call TermWait(buf) @@ -946,6 +949,7 @@ func Test_terminal_wqall() endfunc func Test_terminal_composing_unicode() + let g:test_is_flaky = 1 let save_enc = &encoding set encoding=utf-8 diff --git a/src/testdir/test_terminal2.vim b/src/testdir/test_terminal2.vim index 0f8dcb672e..68f9ad8682 100644 --- a/src/testdir/test_terminal2.vim +++ b/src/testdir/test_terminal2.vim @@ -217,6 +217,7 @@ func Test_termwinscroll() CheckUnix " TODO: Somehow this test sometimes hangs in the GUI CheckNotGui + let g:test_is_flaky = 1 " Let the terminal output more than 'termwinscroll' lines, some at the start " will be dropped. @@ -412,6 +413,7 @@ func Test_terminal_does_not_truncate_last_newlines() if has('conpty') throw 'Skipped: fail on ConPTY' endif + let g:test_is_flaky = 1 let contents = [ \ [ 'One', '', 'X' ], \ [ 'Two', '', '' ], diff --git a/src/testdir/test_timers.vim b/src/testdir/test_timers.vim index caeeed6e53..865a03b6d0 100644 --- a/src/testdir/test_timers.vim +++ b/src/testdir/test_timers.vim @@ -16,6 +16,7 @@ func MyHandlerWithLists(lists, timer) endfunc func Test_timer_oneshot() + let g:test_is_flaky = 1 let g:val = 0 let timer = timer_start(50, 'MyHandler') let slept = WaitFor('g:val == 1') @@ -34,6 +35,7 @@ func Test_timer_oneshot() endfunc func Test_timer_repeat_three() + let g:test_is_flaky = 1 let g:val = 0 let timer = timer_start(50, 'MyHandler', {'repeat': 3}) let slept = WaitFor('g:val == 3') @@ -51,6 +53,7 @@ func Test_timer_repeat_three() endfunc func Test_timer_repeat_many() + let g:test_is_flaky = 1 let g:val = 0 let timer = timer_start(50, 'MyHandler', {'repeat': -1}) sleep 200m @@ -64,6 +67,7 @@ func Test_timer_repeat_many() endfunc func Test_timer_with_partial_callback() + let g:test_is_flaky = 1 let g:val = 0 let meow = {'one': 1} function meow.bite(...) @@ -127,6 +131,7 @@ func Test_timer_stopall() endfunc func Test_timer_paused() + let g:test_is_flaky = 1 let g:val = 0 let id = timer_start(50, 'MyHandler') @@ -186,6 +191,7 @@ func StopTimer2(timer) endfunc func Test_timer_stop_in_callback() + let g:test_is_flaky = 1 call assert_equal(0, len(timer_info())) let g:timer1 = timer_start(10, 'StopTimer1') let slept = 0 @@ -205,6 +211,7 @@ func StopTimerAll(timer) endfunc func Test_timer_stop_all_in_callback() + let g:test_is_flaky = 1 call assert_equal(0, len(timer_info())) call timer_start(10, 'StopTimerAll') call assert_equal(1, len(timer_info())) @@ -471,4 +478,5 @@ func Test_timer_outputting_message() call delete('XTest_timermessage') endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/testdir/test_vim9_cmd.vim b/src/testdir/test_vim9_cmd.vim index 93b1295d4c..3bc13ade79 100644 --- a/src/testdir/test_vim9_cmd.vim +++ b/src/testdir/test_vim9_cmd.vim @@ -1489,5 +1489,86 @@ def Test_cmdwin_block() au! justTesting enddef +def Test_var_not_cmd() + var lines =<< trim END + g:notexist:cmd + END + CheckDefAndScriptFailure2(lines, 'E488: Trailing characters: :cmd', 'E121: Undefined variable: g:notexist', 1) + + lines =<< trim END + g-pat-cmd + END + CheckDefAndScriptFailure(lines, 'E1241:', 1) + lines =<< trim END + g.pat.cmd + END + CheckDefAndScriptFailure2(lines, 'E1001: Variable not found: g', 'E121: Undefined variable: g', 1) + + lines =<< trim END + s:notexist:repl + END + CheckDefAndScriptFailure2(lines, 'E488: Trailing characters: :repl', 'E121: Undefined variable: s:notexist', 1) + + lines =<< trim END + s-pat-repl + END + CheckDefAndScriptFailure(lines, 'E1241:', 1) + lines =<< trim END + s.pat.repl + END + CheckDefAndScriptFailure2(lines, 'E1001: Variable not found: s', 'E121: Undefined variable: s', 1) + + lines =<< trim END + w:notexist->len() + END + CheckDefExecAndScriptFailure(lines, 'E121: Undefined variable: w:notexist', 1) + + lines =<< trim END + b:notexist->len() + END + CheckDefExecAndScriptFailure(lines, 'E121: Undefined variable: b:notexist', 1) + + lines =<< trim END + t:notexist->len() + END + CheckDefExecAndScriptFailure(lines, 'E121: Undefined variable: t:notexist', 1) +enddef + +def Test_no_space_after_command() + var lines =<< trim END + g /pat/cmd + END + CheckDefAndScriptFailure(lines, 'E1242:', 1) + lines =<< trim END + g #pat#cmd + END + CheckDefAndScriptFailure(lines, 'E1242:', 1) + lines =<< trim END + g#pat#cmd + END + CheckDefAndScriptSuccess(lines) + lines =<< trim END + g# pat#cmd + END + CheckDefAndScriptSuccess(lines) + + lines =<< trim END + s /pat/repl + END + CheckDefAndScriptFailure(lines, 'E1242:', 1) + lines =<< trim END + s #pat#repl + END + CheckDefAndScriptFailure(lines, 'E1242:', 1) + lines =<< trim END + s#pat#repl + END + CheckDefExecAndScriptFailure(lines, 'E486:', 1) + lines =<< trim END + s# pat#repl + END + CheckDefExecAndScriptFailure(lines, 'E486:', 1) +enddef + " vim: ts=8 sw=2 sts=2 expandtab tw=80 fdm=marker diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim index 10929519b4..20eb4b43e8 100644 --- a/src/testdir/test_visual.vim +++ b/src/testdir/test_visual.vim @@ -1265,5 +1265,25 @@ func Test_visual_block_with_virtualedit() call delete('XTest_block') endfunc +func Test_visual_reselect_with_count() + " this was causing an illegal memory access + let lines =<< trim END + + + + : + r + exe "%norm e3\kr\t" + : + + : + END + call writefile(lines, 'XvisualReselect') + source XvisualReselect + + bwipe! + call delete('XvisualReselect') +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/undo.c b/src/undo.c index f2db83f2aa..08d4e613db 100644 --- a/src/undo.c +++ b/src/undo.c @@ -1786,6 +1786,11 @@ u_write_undo( write_ok = FALSE; #endif +#if defined(UNIX) && defined(HAVE_FSYNC) + if (p_fs && fflush(fp) == 0 && vim_fsync(fd) != 0) + write_ok = FALSE; +#endif + write_error: fclose(fp); if (!write_ok) diff --git a/src/version.c b/src/version.c index b617f12393..62eff710fe 100644 --- a/src/version.c +++ b/src/version.c @@ -772,6 +772,98 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ +/**/ + 3532, +/**/ + 3531, +/**/ + 3530, +/**/ + 3529, +/**/ + 3528, +/**/ + 3527, +/**/ + 3526, +/**/ + 3525, +/**/ + 3524, +/**/ + 3523, +/**/ + 3522, +/**/ + 3521, +/**/ + 3520, +/**/ + 3519, +/**/ + 3518, +/**/ + 3517, +/**/ + 3516, +/**/ + 3515, +/**/ + 3514, +/**/ + 3513, +/**/ + 3512, +/**/ + 3511, +/**/ + 3510, +/**/ + 3509, +/**/ + 3508, +/**/ + 3507, +/**/ + 3506, +/**/ + 3505, +/**/ + 3504, +/**/ + 3503, +/**/ + 3502, +/**/ + 3501, +/**/ + 3500, +/**/ + 3499, +/**/ + 3498, +/**/ + 3497, +/**/ + 3496, +/**/ + 3495, +/**/ + 3494, +/**/ + 3493, +/**/ + 3492, +/**/ + 3491, +/**/ + 3490, +/**/ + 3489, +/**/ + 3488, +/**/ + 3487, /**/ 3486, /**/ diff --git a/src/vim.h b/src/vim.h index 4ff59f201b..d087306ffa 100644 --- a/src/vim.h +++ b/src/vim.h @@ -292,6 +292,7 @@ #endif #ifdef BACKSLASH_IN_FILENAME # define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`%#'\"|!<") +# define BUFFER_ESC_CHARS ((char_u *)" \t\n*?[`%#'\"|!<") #else # ifdef VMS // VMS allows a lot of characters in the file name @@ -301,6 +302,7 @@ # define PATH_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<") # define SHELL_ESC_CHARS ((char_u *)" \t\n*?[{`$\\%#'\"|!<>();&") # endif +# define BUFFER_ESC_CHARS ((char_u *)" \t\n*?[`$\\%#'\"|!<") #endif // length of a buffer to store a number in ASCII (64 bits binary + NUL) @@ -2777,5 +2779,9 @@ long elapsed(DWORD start_tick); #define UC_BUFFER 1 // -buffer: local to current buffer #define UC_VIM9 2 // {} argument: Vim9 syntax. +// flags used by vim_strsave_escaped() +#define VSE_NONE 0 +#define VSE_SHELL 1 // escape for a shell command +#define VSE_BUFFER 2 // escape for a ":buffer" command #endif // VIM__H diff --git a/src/vim9compile.c b/src/vim9compile.c index e9931731cd..effd610ab8 100644 --- a/src/vim9compile.c +++ b/src/vim9compile.c @@ -9472,6 +9472,26 @@ compile_cexpr(char_u *line, exarg_T *eap, cctx_T *cctx) } #endif +/* + * Check if the separator for a :global or :substitute command is OK. + */ + int +check_global_and_subst(char_u *cmd, char_u *arg) +{ + if (arg == cmd + 1 && vim_strchr((char_u *)":-.", *arg) != NULL) + { + semsg(_(e_separator_not_supported_str), arg); + return FAIL; + } + if (VIM_ISWHITE(cmd[1])) + { + semsg(_(e_no_white_space_allowed_before_separator_str), cmd); + return FAIL; + } + return OK; +} + + /* * Add a function to the list of :def functions. * This sets "ufunc->uf_dfunc_idx" but the function isn't compiled yet. @@ -10066,6 +10086,8 @@ compile_def_function( break; case CMD_substitute: + if (check_global_and_subst(ea.cmd, p) == FAIL) + goto erret; if (cctx.ctx_skip == SKIP_YES) line = (char_u *)""; else @@ -10132,6 +10154,10 @@ compile_def_function( line = compile_script(line, &cctx); break; + case CMD_global: + if (check_global_and_subst(ea.cmd, p) == FAIL) + goto erret; + // FALLTHROUGH default: // Not recognized, execute with do_cmdline_cmd(). ea.arg = p; diff --git a/src/vim9execute.c b/src/vim9execute.c index 481c94fde6..8a14a856b1 100644 --- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -1147,7 +1147,8 @@ do_2string(typval_T *tv, int is_2string_any, int tolerant) while ((e = vim_strchr(s, '\n')) != NULL) { *e = NUL; - p = vim_strsave_fnameescape(s, FALSE); + p = vim_strsave_fnameescape(s, + VSE_NONE); if (p != NULL) { ga_concat(&ga, p); diff --git a/src/vim9script.c b/src/vim9script.c index ca245b2552..9696dfe812 100644 --- a/src/vim9script.c +++ b/src/vim9script.c @@ -978,8 +978,9 @@ find_typval_in_script(typval_T *dest) // legacy script doesn't store variable types return NULL; - // Find the svar_T in sn_var_vals. - for (idx = 0; idx < si->sn_var_vals.ga_len; ++idx) + // Find the svar_T in sn_var_vals. Start at the end, in a for loop the + // variable was added at the end. + for (idx = si->sn_var_vals.ga_len - 1; idx >= 0; --idx) { svar_T *sv = ((svar_T *)si->sn_var_vals.ga_data) + idx; diff --git a/src/xxd/xxd.c b/src/xxd/xxd.c index 94cc220bfb..4e352034ed 100644 --- a/src/xxd/xxd.c +++ b/src/xxd/xxd.c @@ -224,7 +224,7 @@ exit_with_usage(void) fprintf(stderr, " -c cols format octets per line. Default 16 (-i: 12, -ps: 30).\n"); fprintf(stderr, " -E show characters in EBCDIC. Default ASCII.\n"); fprintf(stderr, " -e little-endian dump (incompatible with -ps,-i,-r).\n"); - fprintf(stderr, " -g number of octets per group in normal output. Default 2 (-e: 4).\n"); + fprintf(stderr, " -g bytes number of octets per group in normal output. Default 2 (-e: 4).\n"); fprintf(stderr, " -h print this summary.\n"); fprintf(stderr, " -i output in C include file style.\n"); fprintf(stderr, " -l len stop after octets.\n"); @@ -346,16 +346,12 @@ huntype( n1 = -1; if ((++p >= cols) && !hextype) { - /* skip rest of line as garbage */ - want_off = 0; - while ((c = getc(fpi)) != '\n' && c != EOF) - ; - if (c == EOF && ferror(fpi)) - die(2); - ign_garb = 1; + /* skip the rest of the line as garbage */ + n2 = -1; + n3 = -1; } } - else if (n1 < 0 && n2 < 0 && n3 < 0) + if (n1 < 0 && n2 < 0 && n3 < 0) { /* already stumbled into garbage, skip line, wait and see */ if (!hextype)