diff options
40 files changed, 480 insertions, 423 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 6c54e5749b..caf9658699 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -675,6 +675,19 @@ add_dependencies(lintcommit nvim) add_custom_target(lint) add_dependencies(lint check-single-includes lintc lintlua lintpy lintsh lintcommit lintuncrustify) +# +# Format +# +add_custom_target(formatlua + COMMAND ${CMAKE_COMMAND} + -D FORMAT_PRG=${STYLUA_PRG} + -D LANG=lua + -P ${PROJECT_SOURCE_DIR}/cmake/Format.cmake + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) + +add_custom_target(format) +add_dependencies(format formatc formatlua) + install_helper( FILES ${CMAKE_SOURCE_DIR}/src/man/nvim.1 DESTINATION ${CMAKE_INSTALL_MANDIR}/man1) @@ -797,4 +810,3 @@ add_custom_target(uninstall if(${CMAKE_SOURCE_DIR} STREQUAL ${CMAKE_CURRENT_SOURCE_DIR}) add_subdirectory(cmake.packaging) endif() - diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e26d0d63c5..17622fa33a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -218,6 +218,11 @@ You can lint a single file (but this will _not_ exclude legacy errors): ### Style +- You can format files by using: +``` + make format +``` +This will format changed Lua and C files with all appropriate flags set. - Style rules are (mostly) defined by `src/uncrustify.cfg` which tries to match the [style-guide]. To use the Nvim `gq` command with `uncrustify`: ``` @@ -137,7 +137,7 @@ helphtml: | nvim build/runtime/doc/tags functionaltest functionaltest-lua unittest benchmark: | nvim $(BUILD_TOOL) -C build $@ -lintlua lintsh lintpy lintuncrustify lintc lintcfull check-single-includes generated-sources lintcommit lint: | build/.ran-cmake +lintlua lintsh lintpy lintuncrustify lintc lintcfull check-single-includes generated-sources lintcommit lint formatc formatlua format: | build/.ran-cmake $(CMAKE_PRG) --build build --target $@ test: functionaltest unittest @@ -174,4 +174,4 @@ $(DEPS_BUILD_DIR)/%: phony_force $(BUILD_TOOL) -C $(DEPS_BUILD_DIR) $(patsubst $(DEPS_BUILD_DIR)/%,%,$@) endif -.PHONY: test lintlua lintpy lintsh functionaltest unittest lint lintc clean distclean nvim libnvim cmake deps install appimage checkprefix lintcommit +.PHONY: test lintlua lintpy lintsh functionaltest unittest lint lintc clean distclean nvim libnvim cmake deps install appimage checkprefix lintcommit formatc formatlua format diff --git a/cmake/Format.cmake b/cmake/Format.cmake new file mode 100644 index 0000000000..4115e66705 --- /dev/null +++ b/cmake/Format.cmake @@ -0,0 +1,67 @@ +# Returns a list of all files that has been changed in current branch compared +# to master branch. This includes unstaged, staged and committed files. +function(get_changed_files outvar) + set(default_branch master) + + execute_process( + COMMAND git branch --show-current + OUTPUT_VARIABLE current_branch + OUTPUT_STRIP_TRAILING_WHITESPACE) + + execute_process( + COMMAND git merge-base ${default_branch} ${current_branch} + OUTPUT_VARIABLE ancestor_commit + OUTPUT_STRIP_TRAILING_WHITESPACE) + + # Changed files that have been committed + execute_process( + COMMAND git diff --name-only ${ancestor_commit}...${current_branch} + OUTPUT_VARIABLE committed_files + OUTPUT_STRIP_TRAILING_WHITESPACE) + separate_arguments(committed_files NATIVE_COMMAND ${committed_files}) + + # Unstaged files + execute_process( + COMMAND git diff --name-only + OUTPUT_VARIABLE unstaged_files + OUTPUT_STRIP_TRAILING_WHITESPACE) + separate_arguments(unstaged_files NATIVE_COMMAND ${unstaged_files}) + + # Staged files + execute_process( + COMMAND git diff --cached --name-only + OUTPUT_VARIABLE staged_files + OUTPUT_STRIP_TRAILING_WHITESPACE) + separate_arguments(staged_files NATIVE_COMMAND ${staged_files}) + + set(files ${committed_files} ${unstaged_files} ${staged_files}) + list(REMOVE_DUPLICATES files) + + set(${outvar} "${files}" PARENT_SCOPE) +endfunction() + +get_changed_files(changed_files) + +if(LANG STREQUAL c) + list(FILTER changed_files INCLUDE REGEX "\\.[ch]$") + list(FILTER changed_files INCLUDE REGEX "^src/nvim/") + + if(changed_files) + if(FORMAT_PRG) + execute_process(COMMAND ${FORMAT_PRG} -c "src/uncrustify.cfg" --replace --no-backup ${changed_files}) + else() + message(STATUS "Uncrustify not found. Skip formatting C files.") + endif() + endif() +elseif(LANG STREQUAL lua) + list(FILTER changed_files INCLUDE REGEX "\\.lua$") + list(FILTER changed_files INCLUDE REGEX "^runtime/") + + if(changed_files) + if(FORMAT_PRG) + execute_process(COMMAND ${FORMAT_PRG} ${changed_files}) + else() + message(STATUS "Stylua not found. Skip formatting lua files.") + endif() + endif() +endif() diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index 827d0318ab..be42b7c14e 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -348,7 +348,7 @@ callbacks. These callbacks are called frequently in various contexts; |nvim_buf_attach()| will take keyword args for the callbacks. "on_lines" will receive parameters ("lines", {buf}, {changedtick}, {firstline}, {lastline}, -{new_lastline}, {old_byte_size}[, {old_utf32_size}, {old_utf16_size}]). +{new_lastline}, {old_byte_size} [, {old_utf32_size}, {old_utf16_size}]). Unlike remote channel events the text contents are not passed. The new text can be accessed inside the callback as diff --git a/runtime/doc/builtin.txt b/runtime/doc/builtin.txt index e2a8e098d2..f0f47cddf4 100644 --- a/runtime/doc/builtin.txt +++ b/runtime/doc/builtin.txt @@ -5311,6 +5311,7 @@ mode([expr]) Return a string that indicates the current mode. niV Normal using |i_CTRL-O| in |Virtual-Replace-mode| nt Normal in |terminal-emulator| (insert goes to Terminal mode) + ntT Normal using |t_CTRL-\_CTRL-O| in |Terminal-mode| v Visual by character vs Visual by character using |v_CTRL-O| in Select mode V Visual by line diff --git a/runtime/doc/index.txt b/runtime/doc/index.txt index 25b98ae4ab..7d8a89887a 100644 --- a/runtime/doc/index.txt +++ b/runtime/doc/index.txt @@ -1101,8 +1101,11 @@ tag command action in Command-line editing mode ~ 5. Terminal mode *terminal-mode-index* In a |terminal| buffer all keys except CTRL-\ are forwarded to the terminal -job. If CTRL-\ is pressed, the next key is forwarded unless it is CTRL-N. +job. If CTRL-\ is pressed, the next key is forwarded unless it is CTRL-N +or CTRL-O. Use |CTRL-\_CTRL-N| to go to Normal mode. +Use |t_CTRL-\_CTRL-O| to execute one normal mode command and then return +to terminal mode. You found it, Arthur! *holy-grail* diff --git a/runtime/doc/intro.txt b/runtime/doc/intro.txt index 92ba7b4079..ae80935032 100644 --- a/runtime/doc/intro.txt +++ b/runtime/doc/intro.txt @@ -458,7 +458,7 @@ Ex mode Like Command-line mode, but after entering a command Terminal mode In Terminal mode all input (except CTRL-\) is sent to the process running in the current |terminal| buffer. If CTRL-\ is pressed, the next key is sent unless it - is CTRL-N (|CTRL-\_CTRL-N|). + is CTRL-N (|CTRL-\_CTRL-N|) or CTRL-O (|t_CTRL-\_CTRL-O|). If the 'showmode' option is on "-- TERMINAL --" is shown at the bottom of the window. @@ -550,7 +550,8 @@ Ex :vi -- -- -- -- -- *6 Go from Select mode to Insert mode by typing a printable character. The selection is deleted and the character is inserted. - *CTRL-\_CTRL-N* *i_CTRL-\_CTRL-N* *c_CTRL-\_CTRL-N* *v_CTRL-\_CTRL-N* + *CTRL-\_CTRL-N* *i_CTRL-\_CTRL-N* *c_CTRL-\_CTRL-N* + *v_CTRL-\_CTRL-N* *t_CTRL-\_CTRL-N* Additionally the command CTRL-\ CTRL-N or <C-\><C-N> can be used to go to Normal mode from any other mode. This can be used to make sure Vim is in Normal mode, without causing a beep like <Esc> would. However, this does not diff --git a/runtime/doc/lua.txt b/runtime/doc/lua.txt index c9505429c6..4062a35735 100644 --- a/runtime/doc/lua.txt +++ b/runtime/doc/lua.txt @@ -704,7 +704,7 @@ regex:match_str({str}) *regex:match_str()* As any integer is truth-y, `regex:match()` can be directly used as a condition in an if-statement. -regex:match_line({bufnr}, {line_idx}[, {start}, {end}]) *regex:match_line()* +regex:match_line({bufnr}, {line_idx} [, {start}, {end}]) *regex:match_line()* Match line {line_idx} (zero-based) in buffer {bufnr}. If {start} and {end} are supplied, match only this byte index range. Otherwise see |regex:match_str()|. If {start} is used, then the returned byte @@ -855,13 +855,13 @@ vim.empty_dict() *vim.empty_dict()* Note: If numeric keys are present in the table, Nvim ignores the metatable marker and converts the dict to a list/array anyway. -vim.rpcnotify({channel}, {method}[, {args}...]) *vim.rpcnotify()* +vim.rpcnotify({channel}, {method} [, {args}...]) *vim.rpcnotify()* Sends {event} to {channel} via |RPC| and returns immediately. If {channel} is 0, the event is broadcast to all channels. This function also works in a fast callback |lua-loop-callbacks|. -vim.rpcrequest({channel}, {method}[, {args}...]) *vim.rpcrequest()* +vim.rpcrequest({channel}, {method} [, {args}...]) *vim.rpcrequest()* Sends a request to {channel} to invoke {method} via |RPC| and blocks until a response is received. @@ -873,7 +873,7 @@ vim.stricmp({a}, {b}) *vim.stricmp()* are equal, {a} is greater than {b} or {a} is lesser than {b}, respectively. -vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()* +vim.str_utfindex({str} [, {index}]) *vim.str_utfindex()* Convert byte index to UTF-32 and UTF-16 indices. If {index} is not supplied, the length of the string is used. All indices are zero-based. Returns two values: the UTF-32 and UTF-16 indices respectively. @@ -883,7 +883,7 @@ vim.str_utfindex({str}[, {index}]) *vim.str_utfindex()* point each. An {index} in the middle of a UTF-8 sequence is rounded upwards to the end of that sequence. -vim.str_byteindex({str}, {index}[, {use_utf16}]) *vim.str_byteindex()* +vim.str_byteindex({str}, {index} [, {use_utf16}]) *vim.str_byteindex()* Convert UTF-32 or UTF-16 {index} to byte index. If {use_utf16} is not supplied, it defaults to false (use UTF-32). Returns the byte index. @@ -1315,7 +1315,7 @@ cmd({command}) *vim.cmd()* vim.cmd('write! myfile.txt') vim.cmd { cmd = 'write', args = { "myfile.txt" }, bang = true } vim.cmd.write { args = { "myfile.txt" }, bang = true } - vim.cmd.write {"myfile.txt", bang = true }) + vim.cmd.write { "myfile.txt", bang = true } -- Ex command :colorscheme blue vim.cmd('colorscheme blue') @@ -2229,7 +2229,8 @@ set({mode}, {lhs}, {rhs}, {opts}) *vim.keymap.set()* • remap: (boolean) Make the mapping recursive. This is the inverse of the "noremap" option from |nvim_set_keymap()|. Default `false`. - • replace_keycodes: (boolean) defaults to true. + • replace_keycodes: (boolean) defaults to true if + "expr" is true. See also: ~ |nvim_set_keymap()| diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt index a7be9ff98f..546f92e92f 100644 --- a/runtime/doc/nvim_terminal_emulator.txt +++ b/runtime/doc/nvim_terminal_emulator.txt @@ -47,8 +47,10 @@ Input *terminal-input* To send input, enter |Terminal-mode| with |i|, |I|, |a|, |A| or |:startinsert|. In this mode all keys except <C-\> are sent to the underlying -program. If <C-\> is pressed, the next key is sent unless it is <C-N>. Use -<C-\><C-N> to return to normal-mode. |CTRL-\_CTRL-N| +program. If <C-\> is pressed, the next key is sent unless it is <C-N> or <C-O>. +Use <C-\><C-N> to return to normal mode. |CTRL-\_CTRL-N| +Use <C-\><C-O> to execute one normal mode command and then return to terminal +mode. *t_CTRL-\_CTRL-O* Terminal-mode forces these local options: diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index ffeed6f977..9d03397821 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -4210,7 +4210,7 @@ A jump table for the options with a short description can be found at |Q_op|. The 'mousemodel' option is set by the |:behave| command. - *'mousescroll'* + *'mousescroll'* 'mousescroll' string (default "ver:3,hor:6") global This option controls the number of lines / columns to scroll by when diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index 9eb6470962..cae9c76030 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -239,7 +239,8 @@ g8 Print the hex values of the bytes used in the Type |i| to enter |Terminal-mode|, then keys are sent to the job running in the terminal. Type <C-\><C-N> to - leave Terminal-mode. |CTRL-\_CTRL-N| + leave Terminal-mode. |CTRL-\_CTRL-N|. Type <C-\><C-O> + to execute a single normal mode command |t_CTRL-\_CTRL-O| Fails if changes have been made to the current buffer, unless 'hidden' is set. diff --git a/runtime/lua/vim/_editor.lua b/runtime/lua/vim/_editor.lua index 094fb2f909..b8a7f71145 100644 --- a/runtime/lua/vim/_editor.lua +++ b/runtime/lua/vim/_editor.lua @@ -312,7 +312,7 @@ end --- vim.cmd('write! myfile.txt') --- vim.cmd { cmd = 'write', args = { "myfile.txt" }, bang = true } --- vim.cmd.write { args = { "myfile.txt" }, bang = true } ---- vim.cmd.write {"myfile.txt", bang = true }) +--- vim.cmd.write { "myfile.txt", bang = true } --- --- -- Ex command :colorscheme blue --- vim.cmd('colorscheme blue') diff --git a/runtime/lua/vim/keymap.lua b/runtime/lua/vim/keymap.lua index 0549f63180..7265beb56b 100644 --- a/runtime/lua/vim/keymap.lua +++ b/runtime/lua/vim/keymap.lua @@ -43,7 +43,7 @@ local keymap = {} --- - remap: (boolean) Make the mapping recursive. This is the --- inverse of the "noremap" option from |nvim_set_keymap()|. --- Default `false`. ---- - replace_keycodes: (boolean) defaults to true. +--- - replace_keycodes: (boolean) defaults to true if "expr" is true. ---@see |nvim_set_keymap()| function keymap.set(mode, lhs, rhs, opts) vim.validate({ diff --git a/scripts/uncrustify.sh b/scripts/uncrustify.sh deleted file mode 100755 index ac5d542c29..0000000000 --- a/scripts/uncrustify.sh +++ /dev/null @@ -1,11 +0,0 @@ -#!/usr/bin/env bash - -set -e - -# Check that you have uncrustify -hash uncrustify - -COMMITISH="${1:-master}" -for file in $(git diff --diff-filter=d --name-only $COMMITISH | grep '\.[ch]$'); do - uncrustify -c src/uncrustify.cfg -l C --replace --no-backup "$file" -done diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index f302f25ad6..017883a913 100755 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -778,9 +778,16 @@ add_glob_targets( FLAGS -c "${PROJECT_SOURCE_DIR}/src/uncrustify.cfg" -q --check FILES ${LINT_NVIM_SOURCES} ) - add_dependencies(lintuncrustify uncrustify-version) +add_custom_target(formatc + COMMAND ${CMAKE_COMMAND} + -D FORMAT_PRG=${UNCRUSTIFY_PRG} + -D LANG=c + -P ${PROJECT_SOURCE_DIR}/cmake/Format.cmake + WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}) +add_dependencies(formatc uncrustify-version) + add_custom_target( lintcfull COMMAND diff --git a/src/nvim/api/ui.c b/src/nvim/api/ui.c index aa7bed1132..6239e414a7 100644 --- a/src/nvim/api/ui.c +++ b/src/nvim/api/ui.c @@ -27,7 +27,7 @@ typedef struct { uint64_t channel_id; #define UI_BUF_SIZE 4096 ///< total buffer size for pending msgpack data. - /// guranteed size available for each new event (so packing of simple events + /// guaranteed size available for each new event (so packing of simple events /// and the header of grid_line will never fail) #define EVENT_BUF_SIZE 256 char buf[UI_BUF_SIZE]; ///< buffer of packed but not yet sent msgpack data @@ -43,7 +43,7 @@ typedef struct { // We start packing the two outermost msgpack arrays before knowing the total // number of elements. Thus track the location where array size will need - // to be written in the msgpack buffer, once the specifc array is finished. + // to be written in the msgpack buffer, once the specific array is finished. char *nevents_pos; char *ncalls_pos; uint32_t nevents; ///< number of distinct events (top-level args to "redraw" diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 328a72476a..6dd71e92a6 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -3288,7 +3288,7 @@ void maketitle(void) len = (int)STRLEN(buf_p); if (len > 100) { len -= 100; - len += mb_tail_off(buf_p, buf_p + len) + 1; + len += utf_cp_tail_off(buf_p, buf_p + len) + 1; buf_p += len; } STRCPY(icon_str, buf_p); diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index aeba3acbc3..3ef5ea7e02 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -947,16 +947,15 @@ struct diffblock_S { typedef struct tabpage_S tabpage_T; struct tabpage_S { handle_T handle; - tabpage_T *tp_next; ///< next tabpage or NULL - frame_T *tp_topframe; ///< topframe for the windows - win_T *tp_curwin; ///< current window in this Tab page - win_T *tp_prevwin; ///< previous window in this Tab page - win_T *tp_firstwin; ///< first window in this Tab page - win_T *tp_lastwin; ///< last window in this Tab page - long tp_old_Rows; ///< Rows when Tab page was left - long tp_old_Columns; ///< Columns when Tab page was left - long tp_ch_used; ///< value of 'cmdheight' when frame size - ///< was set + tabpage_T *tp_next; ///< next tabpage or NULL + frame_T *tp_topframe; ///< topframe for the windows + win_T *tp_curwin; ///< current window in this Tab page + win_T *tp_prevwin; ///< previous window in this Tab page + win_T *tp_firstwin; ///< first window in this Tab page + win_T *tp_lastwin; ///< last window in this Tab page + long tp_old_Rows_avail; ///< ROWS_AVAIL when Tab page was left + long tp_old_Columns; ///< Columns when Tab page was left + long tp_ch_used; ///< value of 'cmdheight' when frame size was set diff_T *tp_first_diff; buf_T *(tp_diffbuf[DB_COUNT]); diff --git a/src/nvim/cursor_shape.c b/src/nvim/cursor_shape.c index 62cf60e03b..9c33b1a806 100644 --- a/src/nvim/cursor_shape.c +++ b/src/nvim/cursor_shape.c @@ -43,7 +43,7 @@ cursorentry_T shape_table[SHAPE_IDX_COUNT] = }; /// Converts cursor_shapes into an Array of Dictionaries -/// @param arena initialized arena where memory will be alocated +/// @param arena initialized arena where memory will be allocated /// /// @return Array of the form {[ "cursor_shape": ... ], ...} Array mode_style_array(Arena *arena) diff --git a/src/nvim/edit.c b/src/nvim/edit.c index e7a8f81813..5861e4c52b 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -1223,10 +1223,10 @@ bool edit(int cmdchar, bool startln, long count) // the value of `restart_edit` before `ex_normal` returns. restart_edit = 'i'; force_restart_edit = true; + return false; } else { - terminal_enter(); + return terminal_enter(); } - return false; } // Don't allow inserting in the sandbox. diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 5ff1a9dd47..23e7660606 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -5054,7 +5054,7 @@ int find_help_tags(const char *arg, int *num_matches, char ***matches, bool keep int i; // Specific tags that either have a specific replacement or won't go - // throught the generic rules. + // through the generic rules. static char *(except_tbl[][2]) = { { "*", "star" }, { "g*", "gstar" }, diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 4a5841ca6e..28ff0cbd59 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -1737,7 +1737,7 @@ static bool at_ins_compl_key(void) || ((compl_cont_status & CONT_LOCAL) && (c == Ctrl_N || c == Ctrl_P)); } -/// Check if typebuf.tb_buf[] contains a modifer plus key that can be changed +/// Check if typebuf.tb_buf[] contains a modifier plus key that can be changed /// into just a key, apply that. /// Check from typebuf.tb_buf[typebuf.tb_off] to typebuf.tb_buf[typebuf.tb_off + "max_offset"]. /// @return the length of the replaced bytes, 0 if nothing changed, -1 for error. diff --git a/src/nvim/indent_c.c b/src/nvim/indent_c.c index b89ab19226..c5e030ce25 100644 --- a/src/nvim/indent_c.c +++ b/src/nvim/indent_c.c @@ -2002,7 +2002,7 @@ int get_c_indent(void) } // #defines and so on go at the left when included in 'cinkeys', - // exluding pragmas when customized in 'cinoptions' + // excluding pragmas when customized in 'cinoptions' if (*theline == '#' && (*linecopy == '#' || in_cinkeys('#', ' ', true))) { const char_u *const directive = (char_u *)skipwhite((char *)theline + 1); if (curbuf->b_ind_pragma == 0 || STRNCMP(directive, "pragma", 6) != 0) { diff --git a/src/nvim/keycodes.h b/src/nvim/keycodes.h index f6c576f6ee..c4d984ee17 100644 --- a/src/nvim/keycodes.h +++ b/src/nvim/keycodes.h @@ -7,10 +7,8 @@ // // Any special key code sequences are replaced by these codes. -// -// For MS-DOS some keys produce codes larger than 0xff. They are split into two -// chars, the first one is K_NUL. -// +/// For MS-DOS some keys produce codes larger than 0xff. They are split into two +/// chars, the first one is K_NUL. #define K_NUL (0xce) // for MS-DOS: special key follows /// K_SPECIAL is the first byte of a special key code and is always followed by @@ -59,13 +57,13 @@ #define KS_SELECT 245 #define K_SELECT_STRING (char_u *)"\200\365X" -// Used a termcap entry that produces a normal character. +/// Used a termcap entry that produces a normal character. #define KS_KEY 242 -// Used for click in a tab pages label. +/// Used for click in a tab pages label. #define KS_TABLINE 240 -// Used for menu in a tab pages line. +/// Used for menu in a tab pages line. #define KS_TABMENU 239 /// Filler used after KS_SPECIAL and others @@ -89,18 +87,19 @@ #define TO_SPECIAL(a, b) ((a) == KS_SPECIAL ? K_SPECIAL : (a) == \ KS_ZERO ? K_ZERO : TERMCAP2KEY(a, b)) -// Codes for keys that do not have a termcap name. -// The numbers are fixed to make sure that recorded key sequences remain valid. -// Add new entries at the end, not halfway. -// -// K_SPECIAL KS_EXTRA KE_xxx -// -// Entries must be in the range 0x02-0x7f (see comment at K_SPECIAL). +/// Codes for keys that do not have a termcap name. +/// The numbers are fixed to make sure that recorded key sequences remain valid. +/// Add new entries at the end, not halfway. +/// +/// K_SPECIAL KS_EXTRA KE_xxx +/// +/// Entries must be in the range 0x02-0x7f (see comment at K_SPECIAL). enum key_extra { KE_S_UP = 4, // shift-up - KE_S_DOWN = 5, // shift-down + KE_S_DOWN = 5, // shift-down - KE_S_F1 = 6, // shifted function keys + // shifted function keys + KE_S_F1 = 6, KE_S_F2 = 7, KE_S_F3 = 8, KE_S_F4 = 9, @@ -141,7 +140,7 @@ enum key_extra { KE_S_F36 = 41, KE_S_F37 = 42, - KE_MOUSE = 43, // mouse event start + KE_MOUSE = 43, // mouse event start // Symbols for pseudo keys which are translated from the real key symbols // above. @@ -153,14 +152,14 @@ enum key_extra { KE_MIDDLERELEASE = 49, // Middle mouse button release KE_RIGHTMOUSE = 50, // Right mouse button click KE_RIGHTDRAG = 51, // Drag with right mouse button down - KE_RIGHTRELEASE = 52, // Right mouse button release + KE_RIGHTRELEASE = 52, // Right mouse button release - KE_IGNORE = 53, // Ignored mouse drag/release + KE_IGNORE = 53, // Ignored mouse drag/release KE_TAB = 54, // unshifted TAB key - KE_S_TAB_OLD = 55, // shifted TAB key (no longer used) + KE_S_TAB_OLD = 55, // shifted TAB key (no longer used) - // , KE_SNIFF_UNUSED = 56 // obsolete + // KE_SNIFF_UNUSED = 56, // obsolete KE_XF1 = 57, // extra vt100 function keys for xterm KE_XF2 = 58, KE_XF3 = 59, @@ -175,7 +174,7 @@ enum key_extra { KE_XRIGHT = 68, KE_LEFTMOUSE_NM = 69, // non-mappable Left mouse button click - KE_LEFTRELEASE_NM = 70, // non-mappable left mouse button release + KE_LEFTRELEASE_NM = 70, // non-mappable left mouse button release KE_S_XF1 = 71, // vt100 shifted function keys for xterm KE_S_XF2 = 72, @@ -188,20 +187,20 @@ enum key_extra { KE_MOUSEDOWN = 75, // scroll wheel pseudo-button Down KE_MOUSEUP = 76, // scroll wheel pseudo-button Up KE_MOUSELEFT = 77, // scroll wheel pseudo-button Left - KE_MOUSERIGHT = 78, // scroll wheel pseudo-button Right + KE_MOUSERIGHT = 78, // scroll wheel pseudo-button Right KE_KINS = 79, // keypad Insert key - KE_KDEL = 80, // keypad Delete key + KE_KDEL = 80, // keypad Delete key // KE_CSI = 81, // Nvim doesn't need escaping CSI KE_SNR = 82, // <SNR> KE_PLUG = 83, // <Plug> - KE_CMDWIN = 84, // open command-line window from Command-line Mode + KE_CMDWIN = 84, // open command-line window from Command-line Mode KE_C_LEFT = 85, // control-left KE_C_RIGHT = 86, // control-right KE_C_HOME = 87, // control-home - KE_C_END = 88, // control-end + KE_C_END = 88, // control-end KE_X1MOUSE = 89, // X1/X2 mouse-buttons KE_X1DRAG = 90, @@ -210,16 +209,16 @@ enum key_extra { KE_X2DRAG = 93, KE_X2RELEASE = 94, - KE_DROP = 95, // DnD data is available - // , KE_CURSORHOLD = 96 // CursorHold event - KE_NOP = 97, // no-op: does nothing - // , KE_FOCUSGAINED = 98 // focus gained - // , KE_FOCUSLOST = 99 // focus lost - KE_MOUSEMOVE = 100, // mouse moved with no button down - // , KE_CANCEL = 101 // return from vgetc + KE_DROP = 95, // DnD data is available + // KE_CURSORHOLD = 96, // CursorHold event + KE_NOP = 97, // no-op: does nothing + // KE_FOCUSGAINED = 98, // focus gained + // KE_FOCUSLOST = 99, // focus lost + KE_MOUSEMOVE = 100, // mouse moved with no button down + // KE_CANCEL = 101, // return from vgetc() KE_EVENT = 102, // event - KE_LUA = 103, // lua special key - KE_COMMAND = 104, // <Cmd> special key + KE_LUA = 103, // Lua special key + KE_COMMAND = 104, // <Cmd> special key }; // the three byte codes are replaced with the following int when using vgetc() @@ -259,7 +258,8 @@ enum key_extra { #define K_XLEFT TERMCAP2KEY(KS_EXTRA, KE_XLEFT) #define K_XRIGHT TERMCAP2KEY(KS_EXTRA, KE_XRIGHT) -#define K_F1 TERMCAP2KEY('k', '1') // function keys +// function keys +#define K_F1 TERMCAP2KEY('k', '1') #define K_F2 TERMCAP2KEY('k', '2') #define K_F3 TERMCAP2KEY('k', '3') #define K_F4 TERMCAP2KEY('k', '4') @@ -463,13 +463,13 @@ enum key_extra { /// Current longest is <M-C-S-T-D-A-4-ScrollWheelRight> (length includes '<' and '>'). #define MAX_KEY_NAME_LEN 32 -// Maximum length of a special key event as tokens. This includes modifiers. -// The longest event is something like <M-C-S-T-4-LeftDrag> which would be the -// following string of tokens: -// -// <K_SPECIAL> <KS_MODIFIER> bitmask <K_SPECIAL> <KS_EXTRA> <KE_LEFTDRAG>. -// -// This is a total of 6 tokens, and is currently the longest one possible. +/// Maximum length of a special key event as tokens. This includes modifiers. +/// The longest event is something like <M-C-S-T-4-LeftDrag> which would be the +/// following string of tokens: +/// +/// <K_SPECIAL> <KS_MODIFIER> bitmask <K_SPECIAL> <KS_EXTRA> <KE_LEFTDRAG>. +/// +/// This is a total of 6 tokens, and is currently the longest one possible. #define MAX_KEY_CODE_LEN 6 #define FLAG_CPO_BSLASH 0x01 @@ -477,7 +477,7 @@ enum key_extra { ? 0 \ : FLAG_CPO_BSLASH) -// Flags for replace_termcodes() +/// Flags for replace_termcodes() enum { REPTERM_FROM_PART = 1, REPTERM_DO_LT = 2, @@ -485,7 +485,7 @@ enum { REPTERM_NO_SIMPLIFY = 8, }; -// Flags for find_special_key() +/// Flags for find_special_key() enum { FSK_KEYCODE = 0x01, ///< prefer key code, e.g. K_DEL in place of DEL FSK_KEEP_X_KEY = 0x02, ///< don’t translate xHome to Home key diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c index 8fde85b163..6ba0056f48 100644 --- a/src/nvim/lua/stdlib.c +++ b/src/nvim/lua/stdlib.c @@ -232,7 +232,7 @@ static int nlua_str_utf_start(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL if (offset < 0 || offset > (intptr_t)s1_len) { return luaL_error(lstate, "index out of range"); } - int head_offset = mb_head_off((char_u *)s1, (char_u *)s1 + offset - 1); + int head_offset = utf_cp_head_off((char_u *)s1, (char_u *)s1 + offset - 1); lua_pushinteger(lstate, head_offset); return 1; } @@ -252,7 +252,7 @@ static int nlua_str_utf_end(lua_State *const lstate) FUNC_ATTR_NONNULL_ALL if (offset < 0 || offset > (intptr_t)s1_len) { return luaL_error(lstate, "index out of range"); } - int tail_offset = mb_tail_off(s1, s1 + offset - 1); + int tail_offset = utf_cp_tail_off(s1, s1 + offset - 1); lua_pushinteger(lstate, tail_offset); return 1; } diff --git a/src/nvim/mapping.c b/src/nvim/mapping.c index 520a91491a..1797bb0365 100644 --- a/src/nvim/mapping.c +++ b/src/nvim/mapping.c @@ -235,7 +235,7 @@ static void showmap(mapblock_T *mp, bool local) /// @param[in] orig_lhs Original mapping LHS, with characters to replace. /// @param[in] orig_lhs_len `strlen` of orig_lhs. /// @param[in] orig_rhs Original mapping RHS, with characters to replace. -/// @param[in] rhs_lua Lua reference for Lua maps. +/// @param[in] rhs_lua Lua reference for Lua mappings. /// @param[in] orig_rhs_len `strlen` of orig_rhs. /// @param[in] cpo_flags See param docs for @ref replace_termcodes. /// @param[out] mapargs MapArguments struct holding the replaced strings. @@ -1633,7 +1633,7 @@ int makemap(FILE *fd, buf_T *buf) continue; } - // skip lua mappings and mappings that contain a <SNR> (script-local thing), + // skip Lua mappings and mappings that contain a <SNR> (script-local thing), // they probably don't work when loaded again if (mp->m_luaref != LUA_NOREF) { continue; @@ -2601,7 +2601,7 @@ fail_and_free: /// /// @param mode The abbreviation for the mode /// @param buf The buffer to get the mapping array. NULL for global -/// @param from_lua Whether it is called from internal lua api. +/// @param from_lua Whether it is called from internal Lua api. /// @returns Array of maparg()-like dictionaries describing mappings ArrayOf(Dictionary) keymap_array(String mode, buf_T *buf, bool from_lua) { diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index cf4ac27d1a..223b4d6845 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1837,10 +1837,10 @@ int mb_off_next(const char_u *base, const char_u *p) return i; } -/// Return the offset from "p" to the last byte of the character it points -/// into. Can start anywhere in a stream of bytes. -/// Composing characters are not included. -int mb_tail_off(const char *base, const char *p_in) +/// Return the offset from `p_in` to the last byte of the codepoint it points +/// to. Can start anywhere in a stream of bytes. +/// Note: Counts individual codepoints of composed characters separately. +int utf_cp_tail_off(const char *base, const char *p_in) { const uint8_t *p = (uint8_t *)p_in; int i; @@ -1866,15 +1866,16 @@ int mb_tail_off(const char *base, const char *p_in) return i; } -/// Return the offset from "p" to the first byte of the character it points -/// into. Can start anywhere in a stream of bytes. -/// Unlike utf_head_off() this doesn't include composing characters and returns a negative value. +/// Return the offset from "p" to the first byte of the codepoint it points +/// to. Can start anywhere in a stream of bytes. +/// Note: Unlike `utf_head_off`, this counts individual codepoints of composed characters +/// separately and returns a negative offset. /// /// @param[in] base Pointer to start of string /// @param[in] p Pointer to byte for which to return the offset to the previous codepoint // /// @return 0 if invalid sequence, else offset to previous codepoint -int mb_head_off(const char_u *base, const char_u *p) +int utf_cp_head_off(const char_u *base, const char_u *p) { int i; int j; diff --git a/src/nvim/memory.c b/src/nvim/memory.c index a74fcf6137..5ae7f7bbe3 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -546,7 +546,7 @@ void arena_start(Arena *arena, ArenaMem *reuse_blk) /// Finnish the allocations in an arena. /// -/// This does not immedately free the memory, but leaves existing allocated +/// This does not immediately free the memory, but leaves existing allocated /// objects valid, and returns an opaque ArenaMem handle, which can be used to /// free the allocations using `arena_mem_free`, when the objects allocated /// from the arena are not needed anymore. diff --git a/src/nvim/ops.c b/src/nvim/ops.c index 0bcc5ecd0e..53612be697 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -1828,7 +1828,7 @@ static void mb_adjust_opend(oparg_T *oap) { if (oap->inclusive) { char *p = (char *)ml_get(oap->end.lnum); - oap->end.col += mb_tail_off(p, p + oap->end.col); + oap->end.col += utf_cp_tail_off(p, p + oap->end.col); } } @@ -4889,7 +4889,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd) linenr_T amount = Prenum1; // do_addsub() might trigger re-evaluation of 'foldexpr' halfway, when the - // buffer is not completly updated yet. Postpone updating folds until before + // buffer is not completely updated yet. Postpone updating folds until before // the call to changed_lines(). disable_fold_update++; diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 03d81d586e..9b46fad67a 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -270,10 +270,8 @@ static qf_delq_T *qf_delq_head = NULL; static int qf_init_process_nextline(qf_list_T *qfl, efm_T *fmt_first, qfstate_T *state, qffields_T *fields) { - int status; - // Get the next line from a file/buffer/list/string - status = qf_get_nextline(state); + int status = qf_get_nextline(state); if (status != QF_OK) { return status; } @@ -547,9 +545,7 @@ static void free_efm_list(efm_T **efm_first) /// a regular expression pattern. static size_t efm_regpat_bufsz(char *efm) { - size_t sz; - - sz = (FMT_PATTERNS * 3) + (STRLEN(efm) << 2); + size_t sz = (FMT_PATTERNS * 3) + (STRLEN(efm) << 2); for (int i = FMT_PATTERNS - 1; i >= 0;) { sz += STRLEN(fmt_pat[i--].pattern); } @@ -581,10 +577,8 @@ static int efm_option_part_len(char *efm) /// the parsed 'errorformat' option. static efm_T *parse_efm_option(char *efm) { - efm_T *fmt_ptr = NULL; efm_T *fmt_first = NULL; efm_T *fmt_last = NULL; - int len; // Get some space to modify the format string into. size_t sz = efm_regpat_bufsz(efm); @@ -592,7 +586,7 @@ static efm_T *parse_efm_option(char *efm) while (efm[0] != NUL) { // Allocate a new eformat structure and put it at the end of the list - fmt_ptr = (efm_T *)xcalloc(1, sizeof(efm_T)); + efm_T *fmt_ptr = (efm_T *)xcalloc(1, sizeof(efm_T)); if (fmt_first == NULL) { // first one fmt_first = fmt_ptr; } else { @@ -601,7 +595,7 @@ static efm_T *parse_efm_option(char *efm) fmt_last = fmt_ptr; // Isolate one part in the 'errorformat' option - len = efm_option_part_len(efm); + int len = efm_option_part_len(efm); if (efm_to_regpat(efm, len, fmt_ptr, fmtstr) == FAIL) { goto parse_efm_error; @@ -649,19 +643,13 @@ static int qf_get_next_str_line(qfstate_T *state) { // Get the next line from the supplied string char *p_str = state->p_str; - char *p; - size_t len; if (*p_str == NUL) { // Reached the end of the string return QF_END_OF_INPUT; } - p = vim_strchr(p_str, '\n'); - if (p != NULL) { - len = (size_t)(p - p_str) + 1; - } else { - len = STRLEN(p_str); - } + char *p = vim_strchr(p_str, '\n'); + size_t len = (p != NULL) ? (size_t)(p - p_str) + 1 : STRLEN(p_str); if (len > IOSIZE - 2) { state->linebuf = qf_grow_linebuf(state, len); @@ -684,7 +672,6 @@ static int qf_get_next_str_line(qfstate_T *state) static int qf_get_next_list_line(qfstate_T *state) { listitem_T *p_li = state->p_li; - size_t len; // Get the next line from the supplied list while (p_li != NULL @@ -698,7 +685,7 @@ static int qf_get_next_list_line(qfstate_T *state) return QF_END_OF_INPUT; } - len = STRLEN(TV_LIST_ITEM_TV(p_li)->vval.v_string); + size_t len = STRLEN(TV_LIST_ITEM_TV(p_li)->vval.v_string); if (len > IOSIZE - 2) { state->linebuf = qf_grow_linebuf(state, len); } else { @@ -716,17 +703,14 @@ static int qf_get_next_list_line(qfstate_T *state) /// Get the next string from state->buf. static int qf_get_next_buf_line(qfstate_T *state) { - char *p_buf = NULL; - size_t len; - // Get the next line from the supplied buffer if (state->buflnum > state->lnumlast) { return QF_END_OF_INPUT; } - p_buf = (char *)ml_get_buf(state->buf, state->buflnum, false); + char *p_buf = (char *)ml_get_buf(state->buf, state->buflnum, false); state->buflnum += 1; - len = STRLEN(p_buf); + size_t len = STRLEN(p_buf); if (len > IOSIZE - 2) { state->linebuf = qf_grow_linebuf(state, len); } else { @@ -741,8 +725,6 @@ static int qf_get_next_buf_line(qfstate_T *state) /// Get the next string from file state->fd. static int qf_get_next_file_line(qfstate_T *state) { - size_t growbuflen; - retry: errno = 0; if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL) { @@ -765,7 +747,7 @@ retry: // Copy the read part of the line, excluding null-terminator memcpy(state->growbuf, IObuff, IOSIZE - 1); - growbuflen = state->linelen; + size_t growbuflen = state->linelen; for (;;) { errno = 0; @@ -1071,16 +1053,11 @@ static int qf_init_ext(qf_info_T *qi, int qf_idx, const char *restrict efile, bu linenr_T lnumlast, const char *restrict qf_title, char *restrict enc) FUNC_ATTR_NONNULL_ARG(1) { - qf_list_T *qfl; qfstate_T state = { 0 }; qffields_T fields = { 0 }; - qfline_T *old_last = NULL; - bool adding = false; static efm_T *fmt_first = NULL; - char *efm; static char *last_efm = NULL; int retval = -1; // default: return error flag - int status; // Do not used the cached buffer, it may have been wiped out. XFREE_CLEAR(qf_last_bufname); @@ -1090,6 +1067,9 @@ static int qf_init_ext(qf_info_T *qi, int qf_idx, const char *restrict efile, bu goto qf_init_end; } + qf_list_T *qfl; + qfline_T *old_last = NULL; + bool adding = false; if (newlist || qf_idx == qi->qf_listcount) { // make place for a new list qf_new_list(qi, qf_title); @@ -1104,6 +1084,8 @@ static int qf_init_ext(qf_info_T *qi, int qf_idx, const char *restrict efile, bu } } + char *efm; + // Use the local value of 'errorformat' if it's set. if (errorformat == p_efm && tv == NULL && buf && *buf->b_p_efm != NUL) { efm = (char *)buf->b_p_efm; @@ -1136,7 +1118,7 @@ static int qf_init_ext(qf_info_T *qi, int qf_idx, const char *restrict efile, bu // Read the lines in the error file one by one. // Try to recognize one of the error formats in each line. while (!got_int) { - status = qf_init_process_nextline(qfl, fmt_first, &state, &fields); + int status = qf_init_process_nextline(qfl, fmt_first, &state, &fields); if (status == QF_END_OF_INPUT) { // end of input break; } @@ -1223,9 +1205,6 @@ static qf_list_T *qf_get_curlist(qf_info_T *qi) /// the new list is added. static void qf_new_list(qf_info_T *qi, const char *qf_title) { - int i; - qf_list_T *qfl; - // If the current entry is not the last entry, delete entries beyond // the current entry. This makes it possible to browse in a tree-like // way with ":grep". @@ -1237,14 +1216,14 @@ static void qf_new_list(qf_info_T *qi, const char *qf_title) // Otherwise, add a new entry. if (qi->qf_listcount == LISTCOUNT) { qf_free(&qi->qf_lists[0]); - for (i = 1; i < LISTCOUNT; i++) { + for (int i = 1; i < LISTCOUNT; i++) { qi->qf_lists[i - 1] = qi->qf_lists[i]; } qi->qf_curlist = LISTCOUNT - 1; } else { qi->qf_curlist = qi->qf_listcount++; } - qfl = qf_get_curlist(qi); + qf_list_T *qfl = qf_get_curlist(qi); memset(qfl, 0, sizeof(qf_list_T)); qf_store_title(qfl, qf_title); qfl->qfl_type = qi->qfl_type; @@ -1255,14 +1234,12 @@ static void qf_new_list(qf_info_T *qi, const char *qf_title) /// Return the matched value in "fields->namebuf". static int qf_parse_fmt_f(regmatch_T *rmp, int midx, qffields_T *fields, int prefix) { - char c; - if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) { return QF_FAIL; } // Expand ~/file and $HOME/file to full path. - c = (char)(*rmp->endp[midx]); + char c = (char)(*rmp->endp[midx]); *rmp->endp[midx] = NUL; expand_env(rmp->startp[midx], (char_u *)fields->namebuf, CMDBUFFSIZE); *rmp->endp[midx] = (char_u)c; @@ -1360,12 +1337,10 @@ static void qf_parse_fmt_plus(const char *linebuf, size_t linelen, qffields_T *f /// Return the matched value in "fields->errmsg". static int qf_parse_fmt_m(regmatch_T *rmp, int midx, qffields_T *fields) { - size_t len; - if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) { return QF_FAIL; } - len = (size_t)(rmp->endp[midx] - rmp->startp[midx]); + size_t len = (size_t)(rmp->endp[midx] - rmp->startp[midx]); if (len >= fields->errmsglen) { // len + null terminator fields->errmsg = xrealloc(fields->errmsg, len + 1); @@ -1390,13 +1365,11 @@ static int qf_parse_fmt_r(regmatch_T *rmp, int midx, char **tail) /// Return the matched value in "fields->col". static int qf_parse_fmt_p(regmatch_T *rmp, int midx, qffields_T *fields) { - char *match_ptr; - if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) { return QF_FAIL; } fields->col = 0; - for (match_ptr = (char *)rmp->startp[midx]; (char_u *)match_ptr != rmp->endp[midx]; + for (char *match_ptr = (char *)rmp->startp[midx]; (char_u *)match_ptr != rmp->endp[midx]; match_ptr++) { fields->col++; if (*match_ptr == TAB) { @@ -1425,12 +1398,10 @@ static int qf_parse_fmt_v(regmatch_T *rmp, int midx, qffields_T *fields) /// Return the matched value in "fields->pattern". static int qf_parse_fmt_s(regmatch_T *rmp, int midx, qffields_T *fields) { - size_t len; - if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) { return QF_FAIL; } - len = (size_t)(rmp->endp[midx] - rmp->startp[midx]); + size_t len = (size_t)(rmp->endp[midx] - rmp->startp[midx]); if (len > CMDBUFFSIZE - 5) { len = CMDBUFFSIZE - 5; } @@ -1446,14 +1417,11 @@ static int qf_parse_fmt_s(regmatch_T *rmp, int midx, qffields_T *fields) /// Return the matched value in "fields->module". static int qf_parse_fmt_o(regmatch_T *rmp, int midx, qffields_T *fields) { - size_t len; - size_t dsize; - if (rmp->startp[midx] == NULL || rmp->endp[midx] == NULL) { return QF_FAIL; } - len = (size_t)(rmp->endp[midx] - rmp->startp[midx]); - dsize = STRLEN(fields->module) + len + 1; + size_t len = (size_t)(rmp->endp[midx] - rmp->startp[midx]); + size_t dsize = STRLEN(fields->module) + len + 1; if (dsize > CMDBUFFSIZE) { dsize = CMDBUFFSIZE; } @@ -1489,9 +1457,6 @@ static int qf_parse_match(char *linebuf, size_t linelen, efm_T *fmt_ptr, regmatc qffields_T *fields, int qf_multiline, int qf_multiscan, char **tail) { char idx = fmt_ptr->prefix; - int i; - int midx; - int status; if ((idx == 'C' || idx == 'Z') && !qf_multiline) { return QF_FAIL; @@ -1505,9 +1470,9 @@ static int qf_parse_match(char *linebuf, size_t linelen, efm_T *fmt_ptr, regmatc // Extract error message data from matched line. // We check for an actual submatch, because "\[" and "\]" in // the 'errorformat' may cause the wrong submatch to be used. - for (i = 0; i < FMT_PATTERNS; i++) { - status = QF_OK; - midx = (int)fmt_ptr->addr[i]; + for (int i = 0; i < FMT_PATTERNS; i++) { + int status = QF_OK; + int midx = (int)fmt_ptr->addr[i]; if (i == 0 && midx > 0) { // %f status = qf_parse_fmt_f(regmatch, midx, fields, idx); } else if (i == FMT_PATTERN_M) { @@ -1537,10 +1502,6 @@ static int qf_parse_match(char *linebuf, size_t linelen, efm_T *fmt_ptr, regmatc static int qf_parse_get_fields(char *linebuf, size_t linelen, efm_T *fmt_ptr, qffields_T *fields, int qf_multiline, int qf_multiscan, char **tail) { - regmatch_T regmatch; - int status = QF_FAIL; - int r; - if (qf_multiscan && vim_strchr("OPQ", fmt_ptr->prefix) == NULL) { return QF_FAIL; } @@ -1560,11 +1521,13 @@ static int qf_parse_get_fields(char *linebuf, size_t linelen, efm_T *fmt_ptr, qf fields->type = 0; *tail = NULL; + regmatch_T regmatch; // Always ignore case when looking for a matching error. regmatch.rm_ic = true; regmatch.regprog = fmt_ptr->prog; - r = vim_regexec(®match, linebuf, (colnr_T)0); + int r = vim_regexec(®match, linebuf, (colnr_T)0); fmt_ptr->prog = regmatch.regprog; + int status = QF_FAIL; if (r) { status = qf_parse_match(linebuf, linelen, fmt_ptr, ®match, fields, qf_multiline, qf_multiscan, tail); @@ -1689,9 +1652,7 @@ static int qf_parse_multiline_pfx(int idx, qf_list_T *qfl, qffields_T *fields) /// Queue location list stack delete request. static void locstack_queue_delreq(qf_info_T *qi) { - qf_delq_T *q; - - q = xmalloc(sizeof(qf_delq_T)); + qf_delq_T *q = xmalloc(sizeof(qf_delq_T)); q->qi = qi; q->next = qf_delq_head; qf_delq_head = q; @@ -1722,10 +1683,7 @@ static void wipe_qf_buffer(qf_info_T *qi) /// Free a location list stack static void ll_free_all(qf_info_T **pqi) { - int i; - qf_info_T *qi; - - qi = *pqi; + qf_info_T *qi = *pqi; if (qi == NULL) { return; } @@ -1744,7 +1702,7 @@ static void ll_free_all(qf_info_T **pqi) // If the quickfix window buffer is loaded, then wipe it wipe_qf_buffer(qi); - for (i = 0; i < qi->qf_listcount; i++) { + for (int i = 0; i < qi->qf_listcount; i++) { qf_free(qf_get_list(qi, i)); } xfree(qi); @@ -1754,16 +1712,14 @@ static void ll_free_all(qf_info_T **pqi) /// Free all the quickfix/location lists in the stack. void qf_free_all(win_T *wp) { - int i; - qf_info_T *qi = &ql_info; - if (wp != NULL) { // location list ll_free_all(&wp->w_llist); ll_free_all(&wp->w_llist_ref); } else { // quickfix list - for (i = 0; i < qi->qf_listcount; i++) { + qf_info_T *qi = &ql_info; + for (int i = 0; i < qi->qf_listcount; i++) { qf_free(qf_get_list(qi, i)); } } @@ -1837,7 +1793,6 @@ static int qf_add_entry(qf_list_T *qfl, char *dir, char *fname, char *module, in char vis_col, char *pattern, int nr, char type, char valid) { qfline_T *qfp = xmalloc(sizeof(qfline_T)); - qfline_T **lastp; // pointer to qf_last or NULL if (bufnum != 0) { buf_T *buf = buflist_findnr(bufnum); @@ -1873,7 +1828,7 @@ static int qf_add_entry(qf_list_T *qfl, char *dir, char *fname, char *module, in qfp->qf_type = type; qfp->qf_valid = valid; - lastp = &qfl->qf_last; + qfline_T **lastp = &qfl->qf_last; if (qf_list_empty(qfl)) { // first element in the list qfl->qf_start = qfp; @@ -2060,16 +2015,10 @@ static int copy_loclist(qf_list_T *from_qfl, qf_list_T *to_qfl) void copy_loclist_stack(win_T *from, win_T *to) FUNC_ATTR_NONNULL_ALL { - qf_info_T *qi; - // When copying from a location list window, copy the referenced // location list. For other windows, copy the location list for // that window. - if (IS_LL_WINDOW(from)) { - qi = from->w_llist_ref; - } else { - qi = from->w_llist; - } + qf_info_T *qi = IS_LL_WINDOW(from) ? from->w_llist_ref : from->w_llist; if (qi == NULL) { // no location list to copy return; @@ -2213,14 +2162,12 @@ static char *qf_push_dir(char *dirbuf, struct dir_stack_T **stackptr, bool is_fi // stack is empty static char *qf_pop_dir(struct dir_stack_T **stackptr) { - struct dir_stack_T *ds_ptr; - // TODO(vim): Should we check if dirbuf is the directory on top of the stack? // What to do if it isn't? // pop top element and free it if (*stackptr != NULL) { - ds_ptr = *stackptr; + struct dir_stack_T *ds_ptr = *stackptr; *stackptr = (*stackptr)->next; xfree(ds_ptr->dirname); xfree(ds_ptr); @@ -2262,17 +2209,13 @@ static void qf_clean_dir_stack(struct dir_stack_T **stackptr) /// qf_guess_filepath will return NULL. static char *qf_guess_filepath(qf_list_T *qfl, char *filename) { - struct dir_stack_T *ds_ptr; - struct dir_stack_T *ds_tmp; - char *fullname; - // no dirs on the stack - there's nothing we can do if (qfl->qf_dir_stack == NULL) { return NULL; } - ds_ptr = qfl->qf_dir_stack->next; - fullname = NULL; + struct dir_stack_T *ds_ptr = qfl->qf_dir_stack->next; + char *fullname = NULL; while (ds_ptr) { xfree(fullname); fullname = concat_fnames(ds_ptr->dirname, filename, true); @@ -2288,7 +2231,7 @@ static char *qf_guess_filepath(qf_list_T *qfl, char *filename) // clean up all dirs we already left while (qfl->qf_dir_stack->next != ds_ptr) { - ds_tmp = qfl->qf_dir_stack->next; + struct dir_stack_T *ds_tmp = qfl->qf_dir_stack->next; qfl->qf_dir_stack->next = qfl->qf_dir_stack->next->next; xfree(ds_tmp->dirname); xfree(ds_tmp); @@ -2392,13 +2335,11 @@ static qfline_T *get_nth_valid_entry(qf_list_T *qfl, int errornr, int dir, int * { qfline_T *qf_ptr = qfl->qf_ptr; int qf_idx = qfl->qf_index; - qfline_T *prev_qf_ptr; - int prev_index; char *err = e_no_more_items; while (errornr--) { - prev_qf_ptr = qf_ptr; - prev_index = qf_idx; + qfline_T *prev_qf_ptr = qf_ptr; + int prev_index = qf_idx; if (dir == FORWARD || dir == FORWARD_FILE) { qf_ptr = get_next_valid_entry(qfl, qf_ptr, &qf_idx, dir); @@ -2802,11 +2743,9 @@ static int qf_jump_edit_buffer(qf_info_T *qi, qfline_T *qf_ptr, int forceit, int /// a search pattern. static void qf_jump_goto_line(linenr_T qf_lnum, int qf_col, char qf_viscol, char *qf_pattern) { - linenr_T i; - if (qf_pattern == NULL) { // Go to line with error, unless qf_lnum is 0. - i = qf_lnum; + linenr_T i = qf_lnum; if (i > 0) { if (i > curbuf->b_ml.ml_line_count) { i = curbuf->b_ml.ml_line_count; @@ -2933,14 +2872,11 @@ static int qf_jump_open_window(qf_info_T *qi, qfline_T *qf_ptr, bool newwin, int static int qf_jump_to_buffer(qf_info_T *qi, int qf_index, qfline_T *qf_ptr, int forceit, int prev_winid, int *opened_window, int openfold, int print_message) { - buf_T *old_curbuf; - linenr_T old_lnum; - int retval = OK; - // If there is a file name, read the wanted file if needed, and check // autowrite etc. - old_curbuf = curbuf; - old_lnum = curwin->w_cursor.lnum; + buf_T *old_curbuf = curbuf; + linenr_T old_lnum = curwin->w_cursor.lnum; + int retval = OK; if (qf_ptr->qf_fnum != 0) { retval = qf_jump_edit_buffer(qi, qf_ptr, forceit, prev_winid, @@ -2984,18 +2920,9 @@ void qf_jump(qf_info_T *qi, int dir, int errornr, int forceit) // If 'newwin' is true, then open the file in a new window. static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, bool newwin) { - qf_list_T *qfl; - qfline_T *qf_ptr; - qfline_T *old_qf_ptr; - int qf_index; - int old_qf_index; char *old_swb = (char *)p_swb; unsigned old_swb_flags = swb_flags; - int prev_winid; - int opened_window = false; - int print_message = true; const bool old_KeyTyped = KeyTyped; // getting file may reset it - int retval = OK; if (qi == NULL) { qi = &ql_info; @@ -3008,12 +2935,12 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo incr_quickfix_busy(); - qfl = qf_get_curlist(qi); + qf_list_T *qfl = qf_get_curlist(qi); - qf_ptr = qfl->qf_ptr; - old_qf_ptr = qf_ptr; - qf_index = qfl->qf_index; - old_qf_index = qf_index; + qfline_T *qf_ptr = qfl->qf_ptr; + qfline_T *old_qf_ptr = qf_ptr; + int qf_index = qfl->qf_index; + int old_qf_index = qf_index; qf_ptr = qf_get_entry(qfl, errornr, dir, &qf_index); if (qf_ptr == NULL) { @@ -3024,15 +2951,14 @@ static void qf_jump_newwin(qf_info_T *qi, int dir, int errornr, int forceit, boo qfl->qf_index = qf_index; qfl->qf_ptr = qf_ptr; - if (qf_win_pos_update(qi, old_qf_index)) { - // No need to print the error message if it's visible in the error - // window - print_message = false; - } - prev_winid = curwin->handle; + // No need to print the error message if it's visible in the error window + bool print_message = !qf_win_pos_update(qi, old_qf_index); - retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window); + int prev_winid = curwin->handle; + + int opened_window = false; + int retval = qf_jump_open_window(qi, qf_ptr, newwin, &opened_window); if (retval == FAIL) { goto failed; } @@ -3085,13 +3011,11 @@ static int qfLineAttr; /// quickfix list. static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel) { - char *fname; - buf_T *buf; - - fname = NULL; + char *fname = NULL; if (qfp->qf_module != NULL && *qfp->qf_module != NUL) { vim_snprintf((char *)IObuff, IOSIZE, "%2d %s", qf_idx, qfp->qf_module); } else { + buf_T *buf; if (qfp->qf_fnum != 0 && (buf = buflist_findnr(qfp->qf_fnum)) != NULL) { fname = buf->b_fname; @@ -3175,17 +3099,11 @@ static void qf_list_entry(qfline_T *qfp, int qf_idx, bool cursel) // ":llist": list all locations void qf_list(exarg_T *eap) { - qf_list_T *qfl; - qfline_T *qfp; - int i; - int idx1 = 1; - int idx2 = -1; char *arg = eap->arg; - int all = eap->forceit; // if not :cl!, only show - // recognised errors - qf_info_T *qi; + int all = eap->forceit; // if not :cl!, only show recognised errors + qf_info_T *qi = qf_cmd_get_stack(eap, true); - if ((qi = qf_cmd_get_stack(eap, true)) == NULL) { + if (qi == NULL) { return; } @@ -3199,11 +3117,14 @@ void qf_list(exarg_T *eap) arg++; plus = true; } + int idx1 = 1; + int idx2 = -1; if (!get_list_range((char_u **)&arg, &idx1, &idx2) || *arg != NUL) { emsg(_(e_trailing)); return; } - qfl = qf_get_curlist(qi); + qf_list_T *qfl = qf_get_curlist(qi); + int i; if (plus) { i = qfl->qf_index; idx2 = i + idx1; @@ -3239,6 +3160,7 @@ void qf_list(exarg_T *eap) if (qfl->qf_nonevalid) { all = true; } + qfline_T *qfp; FOR_ALL_QFL_ITEMS(qfl, qfp, i) { if ((qfp->qf_valid || all) && idx1 <= i && i <= idx2) { qf_list_entry(qfp, i, i == qfl->qf_index); @@ -3326,17 +3248,12 @@ static void qf_msg(qf_info_T *qi, int which, char *lead) void qf_age(exarg_T *eap) { qf_info_T *qi; - int count; if ((qi = qf_cmd_get_stack(eap, true)) == NULL) { return; } - if (eap->addr_count != 0) { - count = (int)eap->line2; - } else { - count = 1; - } + int count = (eap->addr_count != 0) ? (int)eap->line2 : 1; while (count--) { if (eap->cmdidx == CMD_colder || eap->cmdidx == CMD_lolder) { if (qi->qf_curlist == 0) { @@ -3360,7 +3277,6 @@ void qf_age(exarg_T *eap) void qf_history(exarg_T *eap) { qf_info_T *qi = qf_cmd_get_stack(eap, false); - int i; if (eap->addr_count > 0) { if (qi == NULL) { @@ -3383,7 +3299,7 @@ void qf_history(exarg_T *eap) if (qf_stack_empty(qi)) { msg(_("No entries")); } else { - for (i = 0; i < qi->qf_listcount; i++) { + for (int i = 0; i < qi->qf_listcount; i++) { qf_msg(qi, i, i == qi->qf_curlist ? "> " : " "); } } @@ -3393,13 +3309,11 @@ void qf_history(exarg_T *eap) /// associated with the list like context and title are not freed. static void qf_free_items(qf_list_T *qfl) { - qfline_T *qfp; - qfline_T *qfpnext; bool stop = false; while (qfl->qf_count && qfl->qf_start != NULL) { - qfp = qfl->qf_start; - qfpnext = qfp->qf_next; + qfline_T *qfp = qfl->qf_start; + qfline_T *qfpnext = qfp->qf_next; if (!stop) { xfree(qfp->qf_module); xfree(qfp->qf_text); @@ -3452,11 +3366,7 @@ static void qf_free(qf_list_T *qfl) bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, linenr_T amount, linenr_T amount_after) { - int i; - qfline_T *qfp; - int idx; qf_info_T *qi = &ql_info; - bool found_one = false; int buf_has_flag = wp == NULL ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; if (!(curbuf->b_has_qf_entry & buf_has_flag)) { @@ -3469,7 +3379,10 @@ bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, linenr_T amount, qi = wp->w_llist; } - for (idx = 0; idx < qi->qf_listcount; idx++) { + int i; + qfline_T *qfp; + bool found_one = false; + for (int idx = 0; idx < qi->qf_listcount; idx++) { qf_list_T *qfl = qf_get_list(qi, idx); if (!qf_list_empty(qfl)) { FOR_ALL_QFL_ITEMS(qfl, qfp, i) { @@ -3509,7 +3422,6 @@ bool qf_mark_adjust(win_T *wp, linenr_T line1, linenr_T line2, linenr_T amount, // 1 x "" :helpgrep static char *qf_types(int c, int nr) { - static char buf[20]; static char cc[3]; char *p; @@ -3534,6 +3446,7 @@ static char *qf_types(int c, int nr) return p; } + static char buf[20]; snprintf((char *)buf, sizeof(buf), "%s %3d", p, nr); return buf; } @@ -3572,17 +3485,15 @@ void qf_view_result(bool split) void ex_cwindow(exarg_T *eap) { qf_info_T *qi; - qf_list_T *qfl; - win_T *win; if ((qi = qf_cmd_get_stack(eap, true)) == NULL) { return; } - qfl = qf_get_curlist(qi); + qf_list_T *qfl = qf_get_curlist(qi); // Look for an existing quickfix window. - win = qf_find_win(qi); + win_T *win = qf_find_win(qi); // If a quickfix window is open but we have no errors to display, // close the window. If a quickfix window is not open, then open @@ -3602,7 +3513,6 @@ void ex_cwindow(exarg_T *eap) // ":lclose": close the window showing the location list void ex_cclose(exarg_T *eap) { - win_T *win = NULL; qf_info_T *qi; if ((qi = qf_cmd_get_stack(eap, false)) == NULL) { @@ -3610,7 +3520,7 @@ void ex_cclose(exarg_T *eap) } // Find existing quickfix window and close it. - win = qf_find_win(qi); + win_T *win = qf_find_win(qi); if (win != NULL) { win_close(win, false, false); } @@ -3740,10 +3650,6 @@ static void qf_set_title_var(qf_list_T *qfl) void ex_copen(exarg_T *eap) { qf_info_T *qi; - qf_list_T *qfl; - int height; - int status = FAIL; - int lnum; if ((qi = qf_cmd_get_stack(eap, true)) == NULL) { return; @@ -3751,6 +3657,7 @@ void ex_copen(exarg_T *eap) incr_quickfix_busy(); + int height; if (eap->addr_count != 0) { height = (int)eap->line2; } else { @@ -3759,6 +3666,7 @@ void ex_copen(exarg_T *eap) reset_VIsual_and_resel(); // stop Visual mode // Find an existing quickfix window, or open a new one. + int status = FAIL; if (cmdmod.cmod_tab == 0) { status = qf_goto_cwindow(qi, eap->addr_count != 0, height, cmdmod.cmod_split & WSP_VERT); @@ -3770,11 +3678,11 @@ void ex_copen(exarg_T *eap) } } - qfl = qf_get_curlist(qi); + qf_list_T *qfl = qf_get_curlist(qi); qf_set_title_var(qfl); // Save the current index here, as updating the quickfix buffer may free // the quickfix list - lnum = qfl->qf_index; + int lnum = qfl->qf_index; // Fill the buffer with the quickfix list. qf_fill_buffer(qfl, curbuf, NULL, curwin->handle); @@ -3839,14 +3747,13 @@ linenr_T qf_current_entry(win_T *wp) /// Return TRUE if there is a quickfix window. /// /// @param old_qf_index previous qf_index or zero -static int qf_win_pos_update(qf_info_T *qi, int old_qf_index) +static bool qf_win_pos_update(qf_info_T *qi, int old_qf_index) { - win_T *win; int qf_index = qf_get_curlist(qi)->qf_index; // Put the cursor on the current error in the quickfix window, so that // it's viewable. - win = qf_find_win(qi); + win_T *win = qf_find_win(qi); if (win != NULL && qf_index <= win->w_buffer->b_ml.ml_line_count && old_qf_index != qf_index) { @@ -3923,14 +3830,12 @@ static buf_T *qf_find_buf(qf_info_T *qi) // Process the 'quickfixtextfunc' option value. bool qf_process_qftf_option(void) { - typval_T *tv; - Callback cb; - if (p_qftf == NULL || *p_qftf == NUL) { callback_free(&qftf_cb); return true; } + typval_T *tv; if (*p_qftf == '{') { // Lambda expression tv = eval_expr((char *)p_qftf); @@ -3944,6 +3849,7 @@ bool qf_process_qftf_option(void) tv->vval.v_string = (char *)vim_strsave(p_qftf); } + Callback cb; if (!callback_from_typval(&cb, tv)) { tv_free(tv); return false; @@ -3975,16 +3881,13 @@ static void qf_update_win_titlevar(qf_info_T *qi) // Find the quickfix buffer. If it exists, update the contents. static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) { - buf_T *buf; - win_T *win; - aco_save_T aco; - // Check if a buffer for the quickfix list exists. Update it. - buf = qf_find_buf(qi); + buf_T *buf = qf_find_buf(qi); if (buf != NULL) { linenr_T old_line_count = buf->b_ml.ml_line_count; int qf_winid = 0; + win_T *win; if (IS_LL_STACK(qi)) { if (curwin->w_llist == qi) { win = curwin; @@ -3997,6 +3900,8 @@ static void qf_update_buffer(qf_info_T *qi, qfline_T *old_last) qf_winid = (int)win->handle; } + aco_save_T aco; + if (old_last == NULL) { // set curwin/curbuf to buf and save a few things aucmd_prepbuf(&aco, buf); @@ -4027,14 +3932,13 @@ static int qf_buf_add_line(qf_list_T *qfl, buf_T *buf, linenr_T lnum, const qfli char *dirname, char *qftf_str, bool first_bufline) FUNC_ATTR_NONNULL_ARG(1, 2, 4, 5) { - int len; - buf_T *errbuf; - // If the 'quickfixtextfunc' function returned a non-empty custom string // for this entry, then use it. if (qftf_str != NULL && *qftf_str != NUL) { STRLCPY(IObuff, qftf_str, IOSIZE); } else { + buf_T *errbuf; + int len; if (qfp->qf_module != NULL) { STRLCPY(IObuff, qfp->qf_module, IOSIZE); len = (int)STRLEN(IObuff); @@ -4123,8 +4027,6 @@ static list_T *call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long args[0].v_type = VAR_DICT; args[0].vval.v_dict = dict; - qftf_list = NULL; - if (callback_call(cb, 1, args, &rettv)) { if (rettv.v_type == VAR_LIST) { qftf_list = rettv.vval.v_list; @@ -4146,11 +4048,7 @@ static list_T *call_qftf_func(qf_list_T *qfl, int qf_winid, long start_idx, long static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int qf_winid) FUNC_ATTR_NONNULL_ARG(2) { - linenr_T lnum; - qfline_T *qfp; const bool old_KeyTyped = KeyTyped; - list_T *qftf_list = NULL; - listitem_T *qftf_li = NULL; if (old_last == NULL) { if (buf != curbuf) { @@ -4167,11 +4065,12 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q // Check if there is anything to display if (qfl != NULL) { char dirname[MAXPATHL]; - int prev_bufnr = -1; - bool invalid_val = false; *dirname = NUL; + linenr_T lnum; + qfline_T *qfp; + // Add one line for each error if (old_last == NULL) { qfp = qfl->qf_start; @@ -4185,8 +4084,11 @@ static void qf_fill_buffer(qf_list_T *qfl, buf_T *buf, qfline_T *old_last, int q lnum = buf->b_ml.ml_line_count; } - qftf_list = call_qftf_func(qfl, qf_winid, lnum + 1, (long)qfl->qf_count); - qftf_li = tv_list_first(qftf_list); + list_T *qftf_list = call_qftf_func(qfl, qf_winid, lnum + 1, (long)qfl->qf_count); + listitem_T *qftf_li = tv_list_first(qftf_list); + + int prev_bufnr = -1; + bool invalid_val = false; while (lnum < qfl->qf_count) { char *qftf_str = NULL; @@ -4363,10 +4265,6 @@ static char *make_get_fullcmd(const char *makecmd, const char *fname) // Used for ":make", ":lmake", ":grep", ":lgrep", ":grepadd", and ":lgrepadd" void ex_make(exarg_T *eap) { - char *fname; - win_T *wp = NULL; - qf_info_T *qi = &ql_info; - int res; char *enc = (*curbuf->b_p_menc != NUL) ? (char *)curbuf->b_p_menc : (char *)p_menc; // Redirect ":grep" to ":vimgrep" if 'grepprg' is "internal". @@ -4383,12 +4281,13 @@ void ex_make(exarg_T *eap) } } + win_T *wp = NULL; if (is_loclist_cmd(eap->cmdidx)) { wp = curwin; } autowrite_all(); - fname = get_mef_name(); + char *fname = get_mef_name(); if (fname == NULL) { return; } @@ -4400,10 +4299,12 @@ void ex_make(exarg_T *eap) incr_quickfix_busy(); - res = qf_init(wp, fname, (eap->cmdidx != CMD_make - && eap->cmdidx != CMD_lmake) ? p_gefm : p_efm, - (eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd), - qf_cmdtitle(*eap->cmdlinep), enc); + int res = qf_init(wp, fname, (eap->cmdidx != CMD_make + && eap->cmdidx != CMD_lmake) ? p_gefm : p_efm, + (eap->cmdidx != CMD_grepadd && eap->cmdidx != CMD_lgrepadd), + qf_cmdtitle(*eap->cmdlinep), enc); + + qf_info_T *qi = &ql_info; if (wp != NULL) { qi = GET_LOC_LIST(wp); if (qi == NULL) { @@ -4437,7 +4338,6 @@ cleanup: // Returns NULL for error. static char *get_mef_name(void) { - char *p; char *name; static int start = -1; static int off = 0; @@ -4450,6 +4350,8 @@ static char *get_mef_name(void) return name; } + char *p; + for (p = p_mef; *p; ++p) { if (p[0] == '#' && p[1] == '#') { break; @@ -4498,7 +4400,6 @@ size_t qf_get_size(exarg_T *eap) size_t qf_get_valid_size(exarg_T *eap) { qf_info_T *qi; - qf_list_T *qfl; if ((qi = qf_cmd_get_stack(eap, false)) == NULL) { return 0; @@ -4509,7 +4410,7 @@ size_t qf_get_valid_size(exarg_T *eap) qfline_T *qfp; int i; assert(qf_get_curlist(qi)->qf_count >= 0); - qfl = qf_get_curlist(qi); + qf_list_T *qfl = qf_get_curlist(qi); FOR_ALL_QFL_ITEMS(qfl, qfp, i) { if (!qfp->qf_valid) { continue; @@ -4908,12 +4809,10 @@ static qfline_T *qf_find_closest_entry(qf_list_T *qfl, int bnr, const pos_T *pos bool linewise, int *errornr) FUNC_ATTR_NONNULL_ALL { - qfline_T *qfp; - *errornr = 0; // Find the first entry in this file - qfp = qf_find_first_entry_in_buf(qfl, bnr, errornr); + qfline_T *qfp = qf_find_first_entry_in_buf(qfl, bnr, errornr); if (qfp == NULL) { return NULL; // no entry in this file } @@ -5011,48 +4910,39 @@ static int qf_find_nth_adj_entry(qf_list_T *qfl, int bnr, pos_T *pos, linenr_T n /// ":lafter" and ":lbefore" commands void ex_cbelow(exarg_T *eap) { - qf_info_T *qi; - qf_list_T *qfl; - int dir; - int buf_has_flag; - if (eap->addr_count > 0 && eap->line2 <= 0) { emsg(_(e_invrange)); return; } // Check whether the current buffer has any quickfix entries - if (eap->cmdidx == CMD_cabove || eap->cmdidx == CMD_cbelow - || eap->cmdidx == CMD_cbefore || eap->cmdidx == CMD_cafter) { - buf_has_flag = BUF_HAS_QF_ENTRY; - } else { - buf_has_flag = BUF_HAS_LL_ENTRY; - } + int buf_has_flag = (eap->cmdidx == CMD_cabove + || eap->cmdidx == CMD_cbelow + || eap->cmdidx == CMD_cbefore + || eap->cmdidx == CMD_cafter) ? BUF_HAS_QF_ENTRY : BUF_HAS_LL_ENTRY; + if (!(curbuf->b_has_qf_entry & buf_has_flag)) { emsg(_(e_quickfix)); return; } + qf_info_T *qi; if ((qi = qf_cmd_get_stack(eap, true)) == NULL) { return; } - qfl = qf_get_curlist(qi); + qf_list_T *qfl = qf_get_curlist(qi); // check if the list has valid errors if (!qf_list_has_valid_entries(qfl)) { emsg(_(e_quickfix)); return; } - if (eap->cmdidx == CMD_cbelow - || eap->cmdidx == CMD_lbelow - || eap->cmdidx == CMD_cafter - || eap->cmdidx == CMD_lafter) { - // Forward motion commands - dir = FORWARD; - } else { - dir = BACKWARD; - } + // Forward motion commands + int dir = (eap->cmdidx == CMD_cbelow + || eap->cmdidx == CMD_lbelow + || eap->cmdidx == CMD_cafter + || eap->cmdidx == CMD_lafter) ? FORWARD : BACKWARD; pos_T pos = curwin->w_cursor; // A quickfix entry column number is 1 based whereas cursor column @@ -5703,18 +5593,14 @@ static void restore_start_dir(char *dirname_start) /// @return NULL if it fails. static buf_T *load_dummy_buffer(char *fname, char *dirname_start, char *resulting_dir) { - buf_T *newbuf; - bufref_T newbufref; - bufref_T newbuf_to_wipe; - int failed = true; - aco_save_T aco; - int readfile_result; - // Allocate a buffer without putting it in the buffer list. - newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); + buf_T *newbuf = buflist_new(NULL, NULL, (linenr_T)1, BLN_DUMMY); if (newbuf == NULL) { return NULL; } + + int failed = true; + bufref_T newbufref; set_bufref(&newbufref, newbuf); // Init the options. @@ -5725,6 +5611,7 @@ static buf_T *load_dummy_buffer(char *fname, char *dirname_start, char *resultin // Make sure this buffer isn't wiped out by autocommands. newbuf->b_locked++; // set curwin/curbuf to buf and save a few things + aco_save_T aco; aucmd_prepbuf(&aco, newbuf); // Need to set the filename for autocommands. @@ -5737,10 +5624,11 @@ static buf_T *load_dummy_buffer(char *fname, char *dirname_start, char *resultin // work. curbuf->b_flags &= ~BF_DUMMY; + bufref_T newbuf_to_wipe; newbuf_to_wipe.br_buf = NULL; - readfile_result = readfile(fname, NULL, (linenr_T)0, (linenr_T)0, - (linenr_T)MAXLNUM, NULL, - READ_NEW | READ_DUMMY, false); + int readfile_result = readfile(fname, NULL, (linenr_T)0, (linenr_T)0, + (linenr_T)MAXLNUM, NULL, + READ_NEW | READ_DUMMY, false); newbuf->b_locked--; if (readfile_result == OK && !got_int @@ -5844,11 +5732,8 @@ static void unload_dummy_buffer(buf_T *buf, char *dirname_start) /// to 'list'. Returns OK on success. static int get_qfline_items(qfline_T *qfp, list_T *list) { - char buf[2]; - int bufnum; - // Handle entries with a non-existing buffer number. - bufnum = qfp->qf_fnum; + int bufnum = qfp->qf_fnum; if (bufnum != 0 && (buflist_findnr(bufnum) == NULL)) { bufnum = 0; } @@ -5856,6 +5741,7 @@ static int get_qfline_items(qfline_T *qfp, list_T *list) dict_T *const dict = tv_dict_alloc(); tv_list_append_dict(list, dict); + char buf[2]; buf[0] = qfp->qf_type; buf[1] = NUL; if (tv_dict_add_nr(dict, S_LEN("bufnr"), (varnumber_T)bufnum) == FAIL @@ -5896,9 +5782,6 @@ static int get_qfline_items(qfline_T *qfp, list_T *list) int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, int eidx, list_T *list) { qf_info_T *qi = qi_arg; - qf_list_T *qfl; - qfline_T *qfp; - int i; if (qi == NULL) { qi = &ql_info; @@ -5922,11 +5805,13 @@ int get_errorlist(qf_info_T *qi_arg, win_T *wp, int qf_idx, int eidx, list_T *li return FAIL; } - qfl = qf_get_list(qi, qf_idx); + qf_list_T *qfl = qf_get_list(qi, qf_idx); if (qf_list_empty(qfl)) { return FAIL; } + qfline_T *qfp; + int i; FOR_ALL_QFL_ITEMS(qfl, qfp, i) { if (eidx > 0) { if (eidx == i) { @@ -5963,11 +5848,11 @@ enum { static int qf_get_list_from_lines(dict_T *what, dictitem_T *di, dict_T *retdict) { int status = FAIL; - char *errorformat = p_efm; - dictitem_T *efm_di; // Only a List value is supported if (di->di_tv.v_type == VAR_LIST && di->di_tv.vval.v_list != NULL) { + char *errorformat = p_efm; + dictitem_T *efm_di; // If errorformat is supplied then use it, otherwise use the 'efm' // option setting if ((efm_di = tv_dict_find(what, S_LEN("efm"))) != NULL) { @@ -6267,11 +6152,9 @@ static int qf_getprop_qftf(qf_list_T *qfl, dict_T *retdict) int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict) { qf_info_T *qi = &ql_info; - qf_list_T *qfl; dictitem_T *di = NULL; int status = OK; int qf_idx = INVALID_QFIDX; - int eidx = 0; if ((di = tv_dict_find(what, S_LEN("lines"))) != NULL) { return qf_get_list_from_lines(what, di, retdict); @@ -6292,7 +6175,8 @@ int qf_get_properties(win_T *wp, dict_T *what, dict_T *retdict) return qf_getprop_defaults(qi, flags, wp != NULL, retdict); } - qfl = qf_get_list(qi, qf_idx); + qf_list_T *qfl = qf_get_list(qi, qf_idx); + int eidx = 0; // If an entry index is specified, use that if ((di = tv_dict_find(what, S_LEN("idx"))) != NULL) { @@ -6679,9 +6563,6 @@ static int qf_setprop_curidx(qf_info_T *qi, qf_list_T *qfl, const dictitem_T *di static int qf_set_properties(qf_info_T *qi, const dict_T *what, int action, char *title) FUNC_ATTR_NONNULL_ALL { - qf_list_T *qfl; - dictitem_T *di; - int retval = FAIL; bool newlist = action == ' ' || qf_stack_empty(qi); int qf_idx = qf_setprop_get_qfidx(qi, what, action, &newlist); if (qf_idx == INVALID_QFIDX) { // List not found @@ -6694,7 +6575,9 @@ static int qf_set_properties(qf_info_T *qi, const dict_T *what, int action, char qf_idx = qi->qf_curlist; } - qfl = qf_get_list(qi, qf_idx); + qf_list_T *qfl = qf_get_list(qi, qf_idx); + dictitem_T *di; + int retval = FAIL; if ((di = tv_dict_find(what, S_LEN("title"))) != NULL) { retval = qf_setprop_title(qi, qf_idx, what, di); } @@ -6775,7 +6658,6 @@ static void qf_free_stack(win_T *wp, qf_info_T *qi) int set_errorlist(win_T *wp, list_T *list, int action, char *title, dict_T *what) { qf_info_T *qi = &ql_info; - int retval = OK; if (wp != NULL) { qi = ll_get_or_alloc_list(wp); @@ -6795,6 +6677,7 @@ int set_errorlist(win_T *wp, list_T *list, int action, char *title, dict_T *what incr_quickfix_busy(); + int retval = OK; if (what != NULL) { retval = qf_set_properties(qi, what, action, title); } else { @@ -6925,14 +6808,7 @@ static int cbuffer_process_args(exarg_T *eap, buf_T **bufp, linenr_T *line1, lin // ":[range]lgetbuffer [bufnr]" command. void ex_cbuffer(exarg_T *eap) { - buf_T *buf = NULL; - char *au_name = NULL; - win_T *wp = NULL; - char *qf_title; - linenr_T line1; - linenr_T line2; - - au_name = cbuffer_get_auname(eap->cmdidx); + char *au_name = cbuffer_get_auname(eap->cmdidx); if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, curbuf->b_fname, true, curbuf)) { if (aborting()) { @@ -6941,13 +6817,17 @@ void ex_cbuffer(exarg_T *eap) } // Must come after autocommands. + win_T *wp = NULL; qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp); + buf_T *buf = NULL; + linenr_T line1; + linenr_T line2; if (cbuffer_process_args(eap, &buf, &line1, &line2) == FAIL) { return; } - qf_title = qf_cmdtitle(*eap->cmdlinep); + char *qf_title = qf_cmdtitle(*eap->cmdlinep); if (buf->b_sfname) { vim_snprintf((char *)IObuff, IOSIZE, "%s (%s)", qf_title, buf->b_sfname); @@ -7015,10 +6895,7 @@ static char *cexpr_get_auname(cmdidx_T cmdidx) /// ":lexpr {expr}", ":lgetexpr {expr}", ":laddexpr {expr}" command. void ex_cexpr(exarg_T *eap) { - char *au_name = NULL; - win_T *wp = NULL; - - au_name = cexpr_get_auname(eap->cmdidx); + char *au_name = cexpr_get_auname(eap->cmdidx); if (au_name != NULL && apply_autocmds(EVENT_QUICKFIXCMDPRE, au_name, curbuf->b_fname, true, curbuf)) { if (aborting()) { @@ -7026,6 +6903,7 @@ void ex_cexpr(exarg_T *eap) } } + win_T *wp = NULL; qf_info_T *qi = qf_cmd_get_or_alloc_stack(eap, &wp); // Evaluate the expression. When the result is a string or a list we can @@ -7074,22 +6952,10 @@ cleanup: static qf_info_T *hgr_get_ll(bool *new_ll) FUNC_ATTR_NONNULL_ALL FUNC_ATTR_NONNULL_RET { - win_T *wp; - qf_info_T *qi; - - // If the current window is a help window, then use it - if (bt_help(curwin->w_buffer)) { - wp = curwin; - } else { - // Find an existing help window - wp = qf_find_help_win(); - } + // If the current window is a help window, then use it, else find an existing help window + win_T *wp = bt_help(curwin->w_buffer) ? curwin : qf_find_help_win(); - if (wp == NULL) { // Help window not found - qi = NULL; - } else { - qi = wp->w_llist; - } + qf_info_T *qi = wp == NULL ? NULL : wp->w_llist; if (qi == NULL) { // Allocate a new location list for help text matches qi = qf_alloc_stack(QFLT_LOCATION); @@ -7203,7 +7069,6 @@ static void hgr_search_in_rtp(qf_list_T *qfl, regmatch_T *p_regmatch, const char void ex_helpgrep(exarg_T *eap) { qf_info_T *qi = &ql_info; - bool new_qi = false; char *au_name = NULL; switch (eap->cmdidx) { @@ -7225,6 +7090,7 @@ void ex_helpgrep(exarg_T *eap) char *const save_cpo = p_cpo; p_cpo = (char *)empty_option; + bool new_qi = false; if (is_loclist_cmd(eap->cmdidx)) { qi = hgr_get_ll(&new_qi); } diff --git a/src/nvim/rbuffer.c b/src/nvim/rbuffer.c index 6407ac172e..2f718e9c2e 100644 --- a/src/nvim/rbuffer.c +++ b/src/nvim/rbuffer.c @@ -156,7 +156,7 @@ void rbuffer_consumed(RBuffer *buf, size_t count) /// Use instead of rbuffer_consumed to use rbuffer in a linear, non-cyclic fashion. /// -/// This is generally usefull if we can guarantee to parse all input +/// This is generally useful if we can guarantee to parse all input /// except some small incomplete token, like when parsing msgpack. void rbuffer_consumed_compact(RBuffer *buf, size_t count) FUNC_ATTR_NONNULL_ALL diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index c2a9c90dda..fbbf904f8b 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -1649,7 +1649,7 @@ static void clear_submatch_list(staticList10_T *sl) /// vim_regexec_multi() match. /// /// If "flags" has REGSUB_COPY really copy into "dest[destlen]". -/// Oterwise nothing is copied, only compue the length of the result. +/// Otherwise nothing is copied, only compute the length of the result. /// /// If "flags" has REGSUB_MAGIC then behave like 'magic' is set. /// diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 80f6f75fea..0d3b936c48 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -6026,7 +6026,11 @@ int showmode(void) msg_puts_attr(_(" INSERT"), attr); } else if (restart_edit == 'I' || restart_edit == 'i' || restart_edit == 'a' || restart_edit == 'A') { - msg_puts_attr(_(" (insert)"), attr); + if (curbuf->terminal) { + msg_puts_attr(_(" (terminal)"), attr); + } else { + msg_puts_attr(_(" (insert)"), attr); + } } else if (restart_edit == 'R') { msg_puts_attr(_(" (replace)"), attr); } else if (restart_edit == 'V') { diff --git a/src/nvim/state.c b/src/nvim/state.c index be8017ea83..d6cca71ad8 100644 --- a/src/nvim/state.c +++ b/src/nvim/state.c @@ -211,12 +211,15 @@ void get_mode(char *buf) buf[i++] = 'o'; // to be able to detect force-linewise/blockwise/charwise operations buf[i++] = (char)motion_force; + } else if (curbuf->terminal) { + buf[i++] = 't'; + if (restart_edit == 'I') { + buf[i++] = 'T'; + } } else if (restart_edit == 'I' || restart_edit == 'R' || restart_edit == 'V') { buf[i++] = 'i'; buf[i++] = (char)restart_edit; - } else if (curbuf->terminal) { - buf[i++] = 't'; } } diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index fc02d9d53a..c23aff00cb 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -82,6 +82,7 @@ typedef struct terminal_state { int save_rd; // saved value of RedrawingDisabled bool close; bool got_bsl; // if the last input was <C-\> + bool got_bsl_o; // if left terminal mode with <c-\><c-o> } TerminalState; #ifdef INCLUDE_GENERATED_DECLARATIONS @@ -388,12 +389,11 @@ void terminal_check_size(Terminal *term) } /// Implements MODE_TERMINAL state. :help Terminal-mode -void terminal_enter(void) +bool terminal_enter(void) { buf_T *buf = curbuf; assert(buf->terminal); // Should only be called when curbuf has a terminal. - TerminalState state, *s = &state; - memset(s, 0, sizeof(TerminalState)); + TerminalState s[1] = { 0 }; s->term = buf->terminal; stop_insert_mode = false; @@ -443,7 +443,9 @@ void terminal_enter(void) s->state.check = terminal_check; state_enter(&s->state); - restart_edit = 0; + if (!s->got_bsl_o) { + restart_edit = 0; + } State = save_state; RedrawingDisabled = s->save_rd; apply_autocmds(EVENT_TERMLEAVE, NULL, NULL, false, curbuf); @@ -467,7 +469,11 @@ void terminal_enter(void) if (curbuf->terminal == s->term && !s->close) { terminal_check_cursor(); } - unshowmode(true); + if (restart_edit) { + showmode(); + } else { + unshowmode(true); + } ui_busy_stop(); if (s->close) { bool wipe = s->term->buf_handle != 0; @@ -477,6 +483,8 @@ void terminal_enter(void) do_cmdline_cmd("bwipeout!"); } } + + return s->got_bsl_o; } static void terminal_check_cursor(void) @@ -564,6 +572,14 @@ static int terminal_execute(VimState *state, int key) } FALLTHROUGH; + case Ctrl_O: + if (s->got_bsl) { + s->got_bsl_o = true; + restart_edit = 'I'; + return 0; + } + FALLTHROUGH; + default: if (key == Ctrl_BSL && !s->got_bsl) { s->got_bsl = true; diff --git a/src/nvim/ui_client.c b/src/nvim/ui_client.c index 09e971f03f..a586fec3bf 100644 --- a/src/nvim/ui_client.c +++ b/src/nvim/ui_client.c @@ -53,7 +53,7 @@ UIClientHandler ui_client_get_redraw_handler(const char *name, size_t name_len, /// Placeholder for _sync_ requests with 'redraw' method name /// /// async 'redraw' events, which are expected when nvim acts as an ui client. -/// get handled in msgpack_rpc/unpacker.c and directy dispatched to handlers +/// get handled in msgpack_rpc/unpacker.c and directly dispatched to handlers /// of specific ui events, like ui_client_event_grid_resize and so on. Object handle_ui_client_redraw(uint64_t channel_id, Array args, Error *error) { diff --git a/src/nvim/window.c b/src/nvim/window.c index e820be626c..c7f038850e 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -4293,7 +4293,7 @@ static int leave_tabpage(buf_T *new_curbuf, bool trigger_leave_autocmds) tp->tp_prevwin = prevwin; tp->tp_firstwin = firstwin; tp->tp_lastwin = lastwin; - tp->tp_old_Rows = Rows; + tp->tp_old_Rows_avail = ROWS_AVAIL; tp->tp_old_Columns = Columns; firstwin = NULL; lastwin = NULL; @@ -4333,10 +4333,7 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a const int row = win_comp_pos(); // recompute w_winrow for all windows diff_need_scrollbind = true; - // The tabpage line may have appeared or disappeared, may need to resize - // the frames for that. When the Vim window was resized need to update - // frame sizes too. Use the stored value of p_ch, so that it can be - // different for each tab page. + // Use the stored value of p_ch, so that it can be different for each tab page. if (p_ch != curtab->tp_ch_used) { clear_cmdline = true; } @@ -4349,7 +4346,9 @@ static void enter_tabpage(tabpage_T *tp, buf_T *old_curbuf, bool trigger_enter_a clear_cmdline = true; } - if (curtab->tp_old_Rows != Rows || (old_off != firstwin->w_winrow)) { + // The tabpage line may have appeared or disappeared, may need to resize the frames for that. + // When the Vim window was resized or ROWS_AVAIL changed need to update frame sizes too. + if (curtab->tp_old_Rows_avail != ROWS_AVAIL || (old_off != firstwin->w_winrow)) { win_new_screen_rows(); } if (curtab->tp_old_Columns != Columns && starting == 0) { diff --git a/test/functional/editor/tabpage_spec.lua b/test/functional/editor/tabpage_spec.lua index 3b2c1db350..7dd0b9f154 100644 --- a/test/functional/editor/tabpage_spec.lua +++ b/test/functional/editor/tabpage_spec.lua @@ -1,4 +1,5 @@ local helpers = require('test.functional.helpers')(after_each) +local Screen = require('test.functional.ui.screen') local clear = helpers.clear local command = helpers.command @@ -53,6 +54,46 @@ describe('tabpage', function() neq(999, eval('g:win_closed')) end) + it('switching tabpage after setting laststatus=3 #19591', function() + local screen = Screen.new(40, 8) + screen:set_default_attr_ids({ + [0] = {bold = true, foreground = Screen.colors.Blue}, + [1] = {bold = true, reverse = true}, -- StatusLine + [2] = {reverse = true}, -- StatusLineNC, TabLineFill + [3] = {bold = true}, -- TabLineSel + [4] = {background = Screen.colors.LightGrey, underline = true}, -- TabLine + [5] = {bold = true, foreground = Screen.colors.Magenta}, + }) + screen:attach() + + command('tabnew') + command('tabprev') + command('set laststatus=3') + command('tabnext') + feed('<C-G>') + screen:expect([[ + {4: [No Name] }{3: [No Name] }{2: }{4:X}| + ^ | + {0:~ }| + {0:~ }| + {0:~ }| + {0:~ }| + {1:[No Name] }| + "[No Name]" --No lines in buffer-- | + ]]) + command('vnew') + screen:expect([[ + {4: [No Name] }{3: }{5:2}{3: [No Name] }{2: }{4:X}| + ^ │ | + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {0:~ }│{0:~ }| + {1:[No Name] }| + "[No Name]" --No lines in buffer-- | + ]]) + end) + it(":tabmove handles modifiers and addr", function() command('tabnew | tabnew | tabnew') eq(4, funcs.nvim_tabpage_get_number(0)) diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua index ec3066c20d..23430a620b 100644 --- a/test/functional/terminal/buffer_spec.lua +++ b/test/functional/terminal/buffer_spec.lua @@ -13,6 +13,7 @@ local exc_exec = helpers.exc_exec local matches = helpers.matches local exec_lua = helpers.exec_lua local sleep = helpers.sleep +local funcs = helpers.funcs describe(':terminal buffer', function() local screen @@ -300,6 +301,44 @@ describe(':terminal buffer', function() feed_command('put a') -- register a is empty helpers.assert_alive() end) + + it([[can use temporary normal mode <c-\><c-o>]], function() + eq('t', funcs.mode(1)) + feed [[<c-\><c-o>]] + screen:expect{grid=[[ + tty ready | + {2:^ } | + | + | + | + | + {3:-- (terminal) --} | + ]]} + eq('ntT', funcs.mode(1)) + + feed [[:let g:x = 17]] + screen:expect{grid=[[ + tty ready | + {2: } | + | + | + | + | + :let g:x = 17^ | + ]]} + + feed [[<cr>]] + screen:expect{grid=[[ + tty ready | + {1: } | + | + | + | + | + {3:-- TERMINAL --} | + ]]} + eq('t', funcs.mode(1)) + end) end) describe('No heap-buffer-overflow when using', function() |