diff options
30 files changed, 933 insertions, 479 deletions
diff --git a/.ci/before_script.sh b/.ci/before_script.sh index 6babc582ea..23940ab2e2 100755 --- a/.ci/before_script.sh +++ b/.ci/before_script.sh @@ -29,10 +29,10 @@ if [[ "${TRAVIS_OS_NAME}" == osx ]]; then # That allows to test changing the group of the file by `os_fchown`. sudo dscl . -create /Groups/chown_test sudo dscl . -append /Groups/chown_test GroupMembership "${USER}" -else - # Compile dependencies. - build_deps fi +# Compile dependencies. +build_deps + rm -rf "${LOG_DIR}" mkdir -p "${LOG_DIR}" diff --git a/.ci/common/build.sh b/.ci/common/build.sh index 06bdab707f..c89d4c559b 100644 --- a/.ci/common/build.sh +++ b/.ci/common/build.sh @@ -14,10 +14,15 @@ build_deps() { # If there is a valid cache and we're not forced to recompile, # use cached third-party dependencies. if [[ -f "${CACHE_MARKER}" ]] && [[ "${BUILD_NVIM_DEPS}" != true ]]; then - echo "Using third-party dependencies from Travis's cache (last updated: $(stat -c '%y' "${CACHE_MARKER}"))." + if [[ "${TRAVIS_OS_NAME}" == osx ]]; then + local statcmd="stat -f '%Sm'" + else + local statcmd="stat -c '%y'" + fi + echo "Using third-party dependencies from Travis's cache (last updated: $(${statcmd} "${CACHE_MARKER}"))." mkdir -p "$(dirname "${DEPS_BUILD_DIR}")" - mv -T "${HOME}/.cache/nvim-deps" "${DEPS_BUILD_DIR}" + mv "${HOME}/.cache/nvim-deps" "${DEPS_BUILD_DIR}" else mkdir -p "${DEPS_BUILD_DIR}" fi @@ -26,7 +31,7 @@ build_deps() { # update CMake configuration and update to newer deps versions. cd "${DEPS_BUILD_DIR}" echo "Configuring with '${DEPS_CMAKE_FLAGS}'." - cmake ${DEPS_CMAKE_FLAGS} "${TRAVIS_BUILD_DIR}/third-party/" + CC= cmake ${DEPS_CMAKE_FLAGS} "${TRAVIS_BUILD_DIR}/third-party/" if ! ${MAKE_CMD}; then exit 1 diff --git a/.ci/common/test.sh b/.ci/common/test.sh index 1e66ecb239..dc59f4f793 100644 --- a/.ci/common/test.sh +++ b/.ci/common/test.sh @@ -49,11 +49,11 @@ asan_check() { } run_unittests() { - ${MAKE_CMD} unittest + ${MAKE_CMD} -C "${BUILD_DIR}" unittest } run_functionaltests() { - if ! ${MAKE_CMD} ${FUNCTIONALTEST}; then + if ! ${MAKE_CMD} -C "${BUILD_DIR}" ${FUNCTIONALTEST}; then asan_check "${LOG_DIR}" valgrind_check "${LOG_DIR}" exit 1 @@ -63,7 +63,8 @@ run_functionaltests() { } run_oldtests() { - if ! make oldtest; then + ${MAKE_CMD} -C "${BUILD_DIR}" helptags + if ! make -C "${TRAVIS_BUILD_DIR}/src/nvim/testdir"; then reset asan_check "${LOG_DIR}" valgrind_check "${LOG_DIR}" diff --git a/.ci/install.sh b/.ci/install.sh index 93c9a930ac..f809bb06ea 100755 --- a/.ci/install.sh +++ b/.ci/install.sh @@ -9,6 +9,7 @@ fi if [[ "${TRAVIS_OS_NAME}" == osx ]]; then brew install gettext + brew reinstall -s libtool elif [[ "${BUILD_MINGW}" == ON ]]; then # TODO: When Travis gets a recent version of Mingw-w64 use packages: # binutils-mingw-w64-i686 gcc-mingw-w64-i686 g++-mingw-w64-i686 mingw-w64-dev mingw-w64-tools @@ -16,7 +17,6 @@ elif [[ "${BUILD_MINGW}" == ON ]]; then echo "Downloading MinGW..." curl -sSL "https://github.com/neovim/deps/raw/master/opt/i686-w64-mingw32-gcc-4.8.0-linux64_rubenvb.tar.xz" \ | tar xJf - -C "${HOME}/.local" - fi # Use default CC to avoid compilation problems when installing Python modules. diff --git a/.ci/script.sh b/.ci/script.sh index c3c7b8dfa9..46c4eecf38 100755 --- a/.ci/script.sh +++ b/.ci/script.sh @@ -12,9 +12,6 @@ fi # as $USER, while retaining the environment variables defined and belonging # to secondary groups given above in usermod. if [[ "${TRAVIS_OS_NAME}" == osx ]]; then - # Set up precompiled third-party dependencies. - eval "$(curl -Ss https://raw.githubusercontent.com/neovim/bot-ci/master/scripts/travis-setup.sh) deps-x64" - sudo -E su "${USER}" -c ".ci/run_tests.sh" else .ci/run_tests.sh @@ -89,7 +89,7 @@ oldtest: | nvim helptags +$(SINGLE_MAKE) -C src/nvim/testdir $(MAKEOVERRIDES) helptags: | nvim - +$(BUILD_CMD) -C build runtime/doc/tags + +$(BUILD_CMD) -C build helptags functionaltest: | nvim +$(BUILD_CMD) -C build functionaltest diff --git a/man/nvim.1 b/man/nvim.1 index 2fa3ab8ff5..70bf480f2b 100644 --- a/man/nvim.1 +++ b/man/nvim.1 @@ -353,7 +353,7 @@ Like but used to store data not generally edited by the user, namely swap, backup, and ShaDa files. Defaults to -.Pa ~/.local/share/nvim +.Pa ~/.local/share if not set. .It Ev VIMINIT A string of Ex commands to be executed at startup. diff --git a/runtime/autoload/remote/host.vim b/runtime/autoload/remote/host.vim index 4ec2eeb5b7..eb5e87d7e1 100644 --- a/runtime/autoload/remote/host.vim +++ b/runtime/autoload/remote/host.vim @@ -121,7 +121,7 @@ endfunction function! s:GetManifest() abort let prefix = exists('$MYVIMRC') \ ? $MYVIMRC - \ : matchstr(get(split(capture('scriptnames'), '\n'), 0, ''), '\f\+$') + \ : matchstr(get(split(execute('scriptnames'), '\n'), 0, ''), '\f\+$') return fnamemodify(expand(prefix, 1), ':h') \.'/.'.fnamemodify(prefix, ':t').'-rplugin~' endfunction diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt index ba38a140d1..9ff97436bb 100644 --- a/runtime/doc/eval.txt +++ b/runtime/doc/eval.txt @@ -1809,7 +1809,6 @@ byteidx({expr}, {nr}) Number byte index of {nr}'th char in {expr} byteidxcomp({expr}, {nr}) Number byte index of {nr}'th char in {expr} call({func}, {arglist} [, {dict}]) any call {func} with arguments {arglist} -capture({command}) String capture output of {command} ceil({expr}) Float round {expr} up changenr() Number current change number char2nr({expr}[, {utf8}]) Number ASCII/UTF8 value of first char in {expr} @@ -1845,6 +1844,7 @@ escape({string}, {chars}) String escape {chars} in {string} with '\' eval({string}) any evaluate {string} into its value eventhandler() Number TRUE if inside an event handler executable({expr}) Number 1 if executable {expr} exists +execute({command}) String execute and capture output of {command} exepath({expr}) String full path of the command {expr} exists({expr}) Number TRUE if {expr} exists extend({expr1}, {expr2} [, {expr3}]) @@ -2524,21 +2524,6 @@ call({func}, {arglist} [, {dict}]) *call()* *E699* {dict} is for functions with the "dict" attribute. It will be used to set the local variable "self". |Dictionary-function| -capture({command}) *capture()* - Capture output of {command}. - If {command} is a |String|, returns {command} output. - If {command} is a |List|, returns concatenated outputs. - Examples: > - echo capture('echon "foo"') -< foo > - echo capture(['echon "foo"', 'echon "bar"']) -< foobar - This function is not available in the |sandbox|. - Note: {command} executes as if prepended with |:silent| - (output is collected, but not displayed). If nested, an outer - capture() will not observe the output of inner calls. - Note: Text attributes (highlights) are not captured. - ceil({expr}) *ceil()* Return the smallest integral value greater than or equal to {expr} as a |Float| (round up). @@ -2989,6 +2974,21 @@ executable({expr}) *executable()* 0 does not exist -1 not implemented on this system +execute({command}) *execute()* + Execute {command} and capture its output. + If {command} is a |String|, returns {command} output. + If {command} is a |List|, returns concatenated outputs. + Examples: > + echo execute('echon "foo"') +< foo > + echo execute(['echon "foo"', 'echon "bar"']) +< foobar + This function is not available in the |sandbox|. + Note: {command} executes as if prepended with |:silent| + (output is collected but not displayed). If nested, an outer + execute() will not observe output of the inner calls. + Note: Text attributes (highlights) are not captured. + exepath({expr}) *exepath()* If {expr} is an executable and is either an absolute path, a relative path or found in $PATH, return the full path. diff --git a/runtime/doc/nvim.txt b/runtime/doc/nvim.txt index 904fb3c16c..7dfbbd0cf0 100644 --- a/runtime/doc/nvim.txt +++ b/runtime/doc/nvim.txt @@ -18,10 +18,13 @@ Transitioning from Vim *nvim-from-vim* To start the transition, link your previous configuration so Nvim can use it: > - mkdir -p ${XDG_CONFIG_HOME:=$HOME/.config} - ln -s ~/.vim $XDG_CONFIG_HOME/nvim - ln -s ~/.vimrc $XDG_CONFIG_HOME/nvim/init.vim + mkdir ~/.config + ln -s ~/.vim ~/.config/nvim + ln -s ~/.vimrc ~/.config/nvim/init.vim < +Note: If your system sets `$XDG_CONFIG_HOME`, use that instead of `~/.config` +in the code above. Nvim follows the XDG |base-directories| convention. + See |provider-python| and |provider-clipboard| for additional software you might need to use some features. diff --git a/runtime/doc/starting.txt b/runtime/doc/starting.txt index 236ed65f46..8249f8e71f 100644 --- a/runtime/doc/starting.txt +++ b/runtime/doc/starting.txt @@ -14,6 +14,7 @@ Starting Vim *starting* 6. Saving settings |save-settings| 7. Views and Sessions |views-sessions| 8. The ShaDa file |shada-file| +9. Base Directories |base-directories| ============================================================================== 1. Vim arguments *vim-arguments* @@ -382,7 +383,7 @@ accordingly. Vim proceeds in this order: name, "init.vim" is Neovim specific location for vimrc file. Also see |vimrc-intro|. - Places for your personal initializations: + Places for your personal initializations (see |base-directories|): Unix $XDG_CONFIG_HOME/nvim/init.vim (default for $XDG_CONFIG_HOME is ~/.config) Windows $XDG_CONFIG_HOME/nvim/init.vim @@ -1083,7 +1084,7 @@ even if other entries (with known name/type/etc) are merged. |shada-merging| SHADA FILE NAME *shada-file-name* - The default name of the ShaDa file is "$XDG_DATA_HOME/nvim/shada/main.shada" - for Unix. Default for $XDG_DATA_HOME is ~/.local/share. + for Unix. Default for $XDG_DATA_HOME is ~/.local/share. |base-directories| - The 'n' flag in the 'shada' option can be used to specify another ShaDa file name |'shada'|. - The "-i" Vim argument can be used to set another file name, |-i|. When the @@ -1370,4 +1371,40 @@ file when reading and include: either contains more then one MessagePack object or it does not contain complete MessagePack object. +============================================================================== +9. Base Directories *base-directories* *xdg* + +Nvim conforms to the XDG Base Directory Specification for application +configuration and data file locations. This just means Nvim looks for some +optional settings and uses them if they exist, otherwise defaults are chosen. +https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html + +CONFIGURATION DIRECTORY *$XDG_CONFIG_HOME* + + Base directory default: + Unix: ~/.config + Windows: ~/AppData/Local + + Nvim directory: + Unix: ~/.config/nvim/ + Windows: ~/AppData/Local/nvim/ + +DATA DIRECTORY *$XDG_DATA_HOME* + + Base directory default: + Unix: ~/.local/share + Windows: ~/AppData/Local + + Nvim directory: + Unix: ~/.local/share/nvim/ + Windows: ~/AppData/Local/nvim-data/ + +Note on Windows the configuration and data directory defaults are the same +(for lack of an alternative), but the sub-directory for data is named +"nvim-data" to separate it from the configuration sub-directory "nvim". + +Throughout other sections of the user manual, the defaults are used as generic +placeholders, e.g. where "~/.config" is mentioned it should be understood to +mean "$XDG_CONFIG_HOME or ~/.config". + vim:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/various.txt b/runtime/doc/various.txt index eb813866da..a1bf379d86 100644 --- a/runtime/doc/various.txt +++ b/runtime/doc/various.txt @@ -417,7 +417,7 @@ m *+xpm_w32* Win32 GUI only: pixmap support |w32-xpm-support| the screen, put the commands in a function and call it with ":silent call Function()". Alternatives are the 'verbosefile' option or - |capture()| function, these can be used in combination + |execute()| function, these can be used in combination with ":redir". :redi[r] >> {file} Redirect messages to file {file}. Append if {file} diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index a5b1cbf9b1..937ed9e8ba 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -98,7 +98,7 @@ Commands: |:CheckHealth| Functions: - |capture()| + |execute()| works with |:redir| Events: |TabNew| diff --git a/runtime/plugin/matchit.vim b/runtime/plugin/matchit.vim index 70867b1f93..8053b080e1 100644 --- a/runtime/plugin/matchit.vim +++ b/runtime/plugin/matchit.vim @@ -1,7 +1,8 @@ " matchit.vim: (global plugin) Extended "%" matching -" Last Change: Fri Jan 25 10:00 AM 2008 EST +" Last Change: Fri Jul 29 01:20 AM 2016 EST " Maintainer: Benji Fisher PhD <benji@member.AMS.org> " Version: 1.13.2, for Vim 6.3+ +" Fix from Tommy Allen included. " URL: http://www.vim.org/script.php?script_id=39 " Documentation: @@ -254,12 +255,7 @@ function! s:Match_wrapper(word, forward, mode) range " Fifth step: actually start moving the cursor and call searchpair(). " Later, :execute restore_cursor to get to the original screen. - let restore_cursor = virtcol(".") . "|" - normal! g0 - let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor - normal! H - let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor - execute restore_cursor + let view = winsaveview() call cursor(0, curcol + 1) " normal! 0 " if curcol @@ -273,7 +269,7 @@ function! s:Match_wrapper(word, forward, mode) range let sp_return = searchpair(ini, mid, fin, flag, skip) let final_position = "call cursor(" . line(".") . "," . col(".") . ")" " Restore cursor position and original screen. - execute restore_cursor + call winrestview(view) normal! m' if sp_return > 0 execute final_position @@ -634,7 +630,7 @@ endfun " idea to give it its own matching patterns. fun! s:MultiMatch(spflag, mode) if !exists("b:match_words") || b:match_words == "" - return "" + return {} end let restore_options = (&ic ? "" : "no") . "ignorecase" if exists("b:match_ignorecase") @@ -694,15 +690,7 @@ fun! s:MultiMatch(spflag, mode) let skip = 's:comment\|string' endif let skip = s:ParseSkip(skip) - " let restore_cursor = line(".") . "G" . virtcol(".") . "|" - " normal! H - " let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor - let restore_cursor = virtcol(".") . "|" - normal! g0 - let restore_cursor = line(".") . "G" . virtcol(".") . "|zs" . restore_cursor - normal! H - let restore_cursor = "normal!" . line(".") . "Gzt" . restore_cursor - execute restore_cursor + let view = winsaveview() " Third step: call searchpair(). " Replace '\('--but not '\\('--with '\%(' and ',' with '\|'. @@ -720,14 +708,14 @@ fun! s:MultiMatch(spflag, mode) while level if searchpair(openpat, '', closepat, a:spflag, skip) < 1 call s:CleanUp(restore_options, a:mode, startline, startcol) - return "" + return {} endif let level = level - 1 endwhile - " Restore options and return a string to restore the original position. + " Restore options and return view dict to restore the original position. call s:CleanUp(restore_options, a:mode, startline, startcol) - return restore_cursor + return view endfun " Search backwards for "if" or "while" or "<tag>" or ... diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 7fb7969783..824b298592 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -6727,7 +6727,6 @@ static struct fst { { "byteidx", 2, 2, f_byteidx }, { "byteidxcomp", 2, 2, f_byteidxcomp }, { "call", 2, 3, f_call }, - { "capture", 1, 1, f_capture }, { "ceil", 1, 1, f_ceil }, { "changenr", 0, 0, f_changenr }, { "char2nr", 1, 2, f_char2nr }, @@ -6756,6 +6755,7 @@ static struct fst { { "eval", 1, 1, f_eval }, { "eventhandler", 0, 0, f_eventhandler }, { "executable", 1, 1, f_executable }, + { "execute", 1, 1, f_execute }, { "exepath", 1, 1, f_exepath }, { "exists", 1, 1, f_exists }, { "exp", 1, 1, f_exp }, @@ -8153,38 +8153,6 @@ static void f_call(typval_T *argvars, typval_T *rettv) (void)func_call(func, &argvars[1], selfdict, rettv); } -// "capture(command)" function -static void f_capture(typval_T *argvars, typval_T *rettv) -{ - int save_msg_silent = msg_silent; - garray_T *save_capture_ga = capture_ga; - - if (check_secure()) { - return; - } - - garray_T capture_local; - capture_ga = &capture_local; - ga_init(capture_ga, (int)sizeof(char), 80); - - msg_silent++; - if (argvars[0].v_type != VAR_LIST) { - do_cmdline_cmd((char *)get_tv_string(&argvars[0])); - } else if (argvars[0].vval.v_list != NULL) { - for (listitem_T *li = argvars[0].vval.v_list->lv_first; - li != NULL; li = li->li_next) { - do_cmdline_cmd((char *)get_tv_string(&li->li_tv)); - } - } - msg_silent = save_msg_silent; - - ga_append(capture_ga, NUL); - rettv->v_type = VAR_STRING; - rettv->vval.v_string = capture_ga->ga_data; - - capture_ga = save_capture_ga; -} - /* * "ceil({float})" function */ @@ -8869,6 +8837,38 @@ static void f_executable(typval_T *argvars, typval_T *rettv) || (gettail_dir(name) != name && os_can_exe(name, NULL, false)); } +// "execute(command)" function +static void f_execute(typval_T *argvars, typval_T *rettv) +{ + int save_msg_silent = msg_silent; + garray_T *save_capture_ga = capture_ga; + + if (check_secure()) { + return; + } + + garray_T capture_local; + capture_ga = &capture_local; + ga_init(capture_ga, (int)sizeof(char), 80); + + msg_silent++; + if (argvars[0].v_type != VAR_LIST) { + do_cmdline_cmd((char *)get_tv_string(&argvars[0])); + } else if (argvars[0].vval.v_list != NULL) { + for (listitem_T *li = argvars[0].vval.v_list->lv_first; + li != NULL; li = li->li_next) { + do_cmdline_cmd((char *)get_tv_string(&li->li_tv)); + } + } + msg_silent = save_msg_silent; + + ga_append(capture_ga, NUL); + rettv->v_type = VAR_STRING; + rettv->vval.v_string = capture_ga->ga_data; + + capture_ga = save_capture_ga; +} + /// "exepath()" function static void f_exepath(typval_T *argvars, typval_T *rettv) { diff --git a/src/nvim/globals.h b/src/nvim/globals.h index f2610ac868..950ceb4c74 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -986,7 +986,7 @@ EXTERN int redir_off INIT(= false); // no redirection for a moment EXTERN FILE *redir_fd INIT(= NULL); // message redirection file EXTERN int redir_reg INIT(= 0); // message redirection register EXTERN int redir_vname INIT(= 0); // message redirection variable -EXTERN garray_T *capture_ga INIT(= NULL); // capture() buffer +EXTERN garray_T *capture_ga INIT(= NULL); // captured output for execute() EXTERN char_u langmap_mapchar[256]; /* mapping for language keys */ diff --git a/src/nvim/memline.c b/src/nvim/memline.c index 673205f08f..08e82071d7 100644 --- a/src/nvim/memline.c +++ b/src/nvim/memline.c @@ -3165,9 +3165,10 @@ attention_message ( } /* Some of these messages are long to allow translation to * other languages. */ - MSG_PUTS(_( - "\n(1) Another program may be editing the same file. If this is the case,\n be careful not to end up with two different instances of the same\n file when making changes.")); - MSG_PUTS(_(" Quit, or continue with caution.\n")); + MSG_PUTS(_("\n(1) Another program may be editing the same file. If this is" + " the case,\n be careful not to end up with two different" + " instances of the same\n file when making changes." + " Quit, or continue with caution.\n")); MSG_PUTS(_("(2) An edit session for this file crashed.\n")); MSG_PUTS(_(" If this is the case, use \":recover\" or \"vim -r ")); msg_outtrans(buf->b_fname); diff --git a/src/nvim/message.c b/src/nvim/message.c index 77e8f0e4f2..3c310ed309 100644 --- a/src/nvim/message.c +++ b/src/nvim/message.c @@ -2396,7 +2396,7 @@ static void redir_write(char_u *str, int maxlen) return; } - // Append output to capture(). + // Append output for execute(). if (capture_ga) { size_t len = 0; while (str[len] && (maxlen < 0 ? 1 : (len < (size_t)maxlen))) { diff --git a/src/nvim/mouse.c b/src/nvim/mouse.c index 2f499e477c..5efac2623c 100644 --- a/src/nvim/mouse.c +++ b/src/nvim/mouse.c @@ -6,6 +6,7 @@ #include "nvim/window.h" #include "nvim/strings.h" #include "nvim/screen.h" +#include "nvim/syntax.h" #include "nvim/ui.h" #include "nvim/os_unix.h" #include "nvim/fold.h" @@ -303,6 +304,10 @@ retnomove: mouse_past_bottom = true; } + if (!(flags & MOUSE_RELEASED) && which_button == MOUSE_LEFT) { + col = mouse_adjust_click(curwin, row, col); + } + // Start Visual mode before coladvance(), for when 'sel' != "old" if ((flags & MOUSE_MAY_VIS) && !VIsual_active) { check_visual_highlight(); @@ -597,3 +602,74 @@ bool mouse_scroll_horiz(int dir) return leftcol_changed(); } + +// Adjust the clicked column position if there are concealed characters +// before the current column. But only when it's absolutely necessary. +static int mouse_adjust_click(win_T *wp, int row, int col) +{ + if (!(wp->w_p_cole > 0 && curbuf->b_p_smc > 0 + && wp->w_leftcol < curbuf->b_p_smc && conceal_cursor_line(wp))) { + return col; + } + + int end = (colnr_T)STRLEN(ml_get(wp->w_cursor.lnum)); + int vend = getviscol2(end, 0); + + if (col >= vend) { + return col; + } + + int i = wp->w_leftcol; + + if (row > 0) { + i += row * (wp->w_width - win_col_off(wp) - win_col_off2(wp) + - wp->w_leftcol) + wp->w_skipcol; + } + + int start_col = i; + int matchid; + int last_matchid; + int bcol = end - (vend - col); + + while (i < bcol) { + matchid = syn_get_concealed_id(wp, wp->w_cursor.lnum, i); + + if (matchid != 0) { + if (wp->w_p_cole == 3) { + bcol++; + } else { + if (row > 0 && i == start_col) { + // Check if the current concealed character is actually part of + // the previous wrapped row's conceal group. + last_matchid = syn_get_concealed_id(wp, wp->w_cursor.lnum, + i - 1); + if (last_matchid == matchid) { + bcol++; + } + } else if (wp->w_p_cole == 1 + || (wp->w_p_cole == 2 + && (lcs_conceal != NUL + || syn_get_sub_char() != NUL))) { + // At least one placeholder character will be displayed. + bcol--; + } + + last_matchid = matchid; + + // Adjust for concealed text that spans more than one character. + do { + i++; + bcol++; + matchid = syn_get_concealed_id(wp, wp->w_cursor.lnum, i); + } while (last_matchid == matchid); + + continue; + } + } + + i++; + } + + return getviscol2(bcol, 0); +} + diff --git a/src/nvim/os/fileio.c b/src/nvim/os/fileio.c index 6cee102305..cf5bfd60ae 100644 --- a/src/nvim/os/fileio.c +++ b/src/nvim/os/fileio.c @@ -4,7 +4,6 @@ /// Neovim stuctures for buffer, with autocommands, etc: just fopen/fread/fwrite /// replacement. -#include <unistd.h> #include <assert.h> #include <stddef.h> #include <stdbool.h> diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c index d12d34d595..8c1c80bfad 100644 --- a/src/nvim/os/fs.c +++ b/src/nvim/os/fs.c @@ -3,7 +3,6 @@ #include <stddef.h> #include <assert.h> #include <limits.h> -#include <unistd.h> #include <fcntl.h> #include <errno.h> diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index 436de030ba..b57a69b82b 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -3,7 +3,6 @@ #include <stdlib.h> #include <string.h> -#include <unistd.h> #include <termios.h> #include <sys/types.h> #include <sys/wait.h> diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c index 27855184df..3215f7ea14 100644 --- a/src/nvim/syntax.c +++ b/src/nvim/syntax.c @@ -5661,6 +5661,24 @@ int get_syntax_info(int *seqnrp) return current_flags; } + +/// Get the sequence number of the concealed file position. +/// +/// @return seqnr if the file position is concealed, 0 otherwise. +int syn_get_concealed_id(win_T *wp, linenr_T lnum, colnr_T col) +{ + int seqnr; + int syntax_flags; + + (void)syn_get_id(wp, lnum, col, false, NULL, false); + syntax_flags = get_syntax_info(&seqnr); + + if (syntax_flags & HL_CONCEAL) { + return seqnr; + } + return 0; +} + /* * Return conceal substitution character */ diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index fb0079111c..9a0bba83fe 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -14,7 +14,6 @@ SCRIPTS := \ test14.out \ test17.out \ test24.out \ - test30.out \ test32.out \ test37.out \ test40.out \ diff --git a/src/nvim/testdir/test30.in b/src/nvim/testdir/test30.in deleted file mode 100644 index 56d5d5c6c2..0000000000 --- a/src/nvim/testdir/test30.in +++ /dev/null @@ -1,230 +0,0 @@ -Test for a lot of variations of the 'fileformats' option - -Note: This test will fail if "cat" is not available. - -STARTTEST -:" first write three test files, one in each format -:set fileformat=unix -:set fileformats= -:/^unix/;/eof/-1w! XXUnix -:/^dos/;/eof/-1w! XXDos -:set bin noeol -:$w! XXMac -Gonoeol -:$w! XXEol -:set nobin eol -:enew! -:bwipe XXUnix XXDos XXMac -:" create mixed format files -:if has("win32") -: !copy /b XXUnix+XXDos XXUxDs -: !copy /b XXUnix+XXMac XXUxMac -: !copy /b XXDos+XXMac XXDosMac -: !copy /b XXMac+XXEol XXMacEol -: !copy /b XXUnix+XXDos+XXMac XXUxDsMc -:else -: !cat XXUnix XXDos >XXUxDs -: !cat XXUnix XXMac >XXUxMac -: !cat XXDos XXMac >XXDosMac -: !cat XXMac XXEol >XXMacEol -: !cat XXUnix XXDos XXMac >XXUxDsMc -:endif -:" -:" try reading and writing with 'fileformats' empty -:set fileformat=unix -:e! XXUnix -:w! test.out -:e! XXDos -:w! XXtt01 -:e! XXMac -:w! XXtt02 -:bwipe XXUnix XXDos XXMac -:set fileformat=dos -:e! XXUnix -:w! XXtt11 -:e! XXDos -:w! XXtt12 -:e! XXMac -:w! XXtt13 -:bwipe XXUnix XXDos XXMac -:set fileformat=mac -:e! XXUnix -:w! XXtt21 -:e! XXDos -:w! XXtt22 -:e! XXMac -:w! XXtt23 -:bwipe XXUnix XXDos XXMac -:" -:" try reading and writing with 'fileformats' set to one format -:set fileformats=unix -:e! XXUxDsMc -:w! XXtt31 -:bwipe XXUxDsMc -:set fileformats=dos -:e! XXUxDsMc -:w! XXtt32 -:bwipe XXUxDsMc -:set fileformats=mac -:e! XXUxDsMc -:w! XXtt33 -:bwipe XXUxDsMc -:" -:" try reading and writing with 'fileformats' set to two formats -:set fileformats=unix,dos -:e! XXUxDsMc -:w! XXtt41 -:bwipe XXUxDsMc -:e! XXUxMac -:w! XXtt42 -:bwipe XXUxMac -:e! XXDosMac -:w! XXtt43 -:bwipe XXDosMac -:set fileformats=unix,mac -:e! XXUxDs -:w! XXtt51 -:bwipe XXUxDs -:e! XXUxDsMc -:w! XXtt52 -:bwipe XXUxDsMc -:e! XXDosMac -:w! XXtt53 -:bwipe XXDosMac -:e! XXEol -ggO=&ffs -:=&ff -:w! XXtt54 -:bwipe XXEol -:set fileformats=dos,mac -:e! XXUxDs -:w! XXtt61 -:bwipe XXUxDs -:e! XXUxMac -ggO=&ffs -:=&ff -:w! XXtt62 -:bwipe XXUxMac -:e! XXUxDsMc -:w! XXtt63 -:bwipe XXUxDsMc -:e! XXMacEol -ggO=&ffs -:=&ff -:w! XXtt64 -:bwipe XXMacEol -:" -:" try reading and writing with 'fileformats' set to three formats -:set fileformats=unix,dos,mac -:e! XXUxDsMc -:w! XXtt71 -:bwipe XXUxDsMc -:e! XXEol -ggO=&ffs -:=&ff -:w! XXtt72 -:bwipe XXEol -:set fileformats=mac,dos,unix -:e! XXUxDsMc -:w! XXtt81 -:bwipe XXUxDsMc -:e! XXEol -ggO=&ffs -:=&ff -:w! XXtt82 -:bwipe XXEol -:" try with 'binary' set -:set fileformats=mac,unix,dos -:set binary -:e! XXUxDsMc -:w! XXtt91 -:bwipe XXUxDsMc -:set fileformats=mac -:e! XXUxDsMc -:w! XXtt92 -:bwipe XXUxDsMc -:set fileformats=dos -:e! XXUxDsMc -:w! XXtt93 -:" -:" Append "END" to each file so that we can see what the last written char was. -:set fileformat=unix nobin -ggdGaEND:w >>XXtt01 -:w >>XXtt02 -:w >>XXtt11 -:w >>XXtt12 -:w >>XXtt13 -:w >>XXtt21 -:w >>XXtt22 -:w >>XXtt23 -:w >>XXtt31 -:w >>XXtt32 -:w >>XXtt33 -:w >>XXtt41 -:w >>XXtt42 -:w >>XXtt43 -:w >>XXtt51 -:w >>XXtt52 -:w >>XXtt53 -:w >>XXtt54 -:w >>XXtt61 -:w >>XXtt62 -:w >>XXtt63 -:w >>XXtt64 -:w >>XXtt71 -:w >>XXtt72 -:w >>XXtt81 -:w >>XXtt82 -:w >>XXtt91 -:w >>XXtt92 -:w >>XXtt93 -:" -:" Concatenate the results. -:" Make fileformat of test.out the native fileformat. -:" Add a newline at the end. -:set binary -:e! test.out -:$r XXtt01 -:$r XXtt02 -Go1:$r XXtt11 -:$r XXtt12 -:$r XXtt13 -Go2:$r XXtt21 -:$r XXtt22 -:$r XXtt23 -Go3:$r XXtt31 -:$r XXtt32 -:$r XXtt33 -Go4:$r XXtt41 -:$r XXtt42 -:$r XXtt43 -Go5:$r XXtt51 -:$r XXtt52 -:$r XXtt53 -:$r XXtt54 -Go6:$r XXtt61 -:$r XXtt62 -:$r XXtt63 -:$r XXtt64 -Go7:$r XXtt71 -:$r XXtt72 -Go8:$r XXtt81 -:$r XXtt82 -Go9:$r XXtt91 -:$r XXtt92 -:$r XXtt93 -Go10:$r XXUnix -:set nobinary ff& -:w -:qa! -ENDTEST - -unix -unix -eof - -dos
-dos
-eof - -mac
mac
diff --git a/src/nvim/testdir/test30.ok b/src/nvim/testdir/test30.ok deleted file mode 100644 index b35f4f5904..0000000000 --- a/src/nvim/testdir/test30.ok +++ /dev/null @@ -1,130 +0,0 @@ -unix -unix -dos
-dos
-END -mac
mac
-END -1 -unix
-unix
-END -dos
-dos
-END -mac
mac
-END -2 -unix -unix -
END -dos
-dos
-
END -mac
mac
END -3 -unix -unix -dos
-dos
-mac
mac
-END -unix
-unix
-dos
-dos
-mac
mac
-END -unix -unix -dos
-dos
-mac
mac
END -4 -unix -unix -dos
-dos
-mac
mac
-END -unix -unix -mac
mac
-END -dos
-dos
-mac
mac
-END -5 -unix -unix -dos
-dos
-END -unix -unix -dos
-dos
-mac
mac
-END -dos
-dos
-mac
mac
END -unix,mac:unix -noeol -END -6 -unix
-unix
-dos
-dos
-END -dos,mac:dos
-unix
-unix
-mac
mac
-END -unix
-unix
-dos
-dos
-mac
mac
-END -dos,mac:mac
mac
mac
noeol
END -7 -unix -unix -dos
-dos
-mac
mac
-END -unix,dos,mac:unix -noeol -END -8 -unix -unix -dos
-dos
-mac
mac
-END -mac,dos,unix:mac
noeol
END -9 -unix -unix -dos
-dos
-mac
mac
END -unix -unix -dos
-dos
-mac
mac
END -unix -unix -dos
-dos
-mac
mac
END -10 -unix -unix diff --git a/src/nvim/version.c b/src/nvim/version.c index 4cb3717133..d0af76ac8b 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -1040,7 +1040,7 @@ static int included_patches[] = { // 1240 NA // 1239 NA // 1238 NA - // 1237, + 1237, 1236, // 1235 NA // 1234 NA diff --git a/test/functional/eval/capture_spec.lua b/test/functional/eval/execute_spec.lua index d9265f1b5b..a91a04341f 100644 --- a/test/functional/eval/capture_spec.lua +++ b/test/functional/eval/execute_spec.lua @@ -9,16 +9,16 @@ local funcs = helpers.funcs local Screen = require('test.functional.ui.screen') local feed = helpers.feed -describe('capture()', function() +describe('execute()', function() before_each(clear) it('returns the same result with :redir', function() - eq(redir_exec('messages'), funcs.capture('messages')) + eq(redir_exec('messages'), funcs.execute('messages')) end) it('returns the output of the commands if the argument is List', function() - eq("foobar", funcs.capture({'echon "foo"', 'echon "bar"'})) - eq("\nfoo\nbar", funcs.capture({'echo "foo"', 'echo "bar"'})) + eq("foobar", funcs.execute({'echon "foo"', 'echon "bar"'})) + eq("\nfoo\nbar", funcs.execute({'echo "foo"', 'echo "bar"'})) end) it('supports the nested redirection', function() @@ -38,34 +38,34 @@ describe('capture()', function() return a endfunction ]]) - eq('foo', funcs.capture('call g:Bar()')) + eq('foo', funcs.execute('call g:Bar()')) - eq('42', funcs.capture([[echon capture("echon capture('echon 42')")]])) + eq('42', funcs.execute([[echon execute("echon execute('echon 42')")]])) end) it('returns the transformed string', function() - eq('^A', funcs.capture('echon "\\<C-a>"')) + eq('^A', funcs.execute('echon "\\<C-a>"')) end) it('returns the empty string if the argument list is empty', function() - eq('', funcs.capture({})) - eq(0, exc_exec('let g:ret = capture(v:_null_list)')) + eq('', funcs.execute({})) + eq(0, exc_exec('let g:ret = execute(v:_null_list)')) eq('', eval('g:ret')) end) it('returns the errors', function() local ret - ret = exc_exec('call capture(0.0)') + ret = exc_exec('call execute(0.0)') eq('Vim(call):E806: using Float as a String', ret) - ret = exc_exec('call capture(v:_null_dict)') + ret = exc_exec('call execute(v:_null_dict)') eq('Vim(call):E731: using Dictionary as a String', ret) - ret = exc_exec('call capture(function("tr"))') + ret = exc_exec('call execute(function("tr"))') eq('Vim(call):E729: using Funcref as a String', ret) - ret = exc_exec('call capture(["echo 42", 0.0, "echo 44"])') + ret = exc_exec('call execute(["echo 42", 0.0, "echo 44"])') eq('Vim(call):E806: using Float as a String', ret) - ret = exc_exec('call capture(["echo 42", v:_null_dict, "echo 44"])') + ret = exc_exec('call execute(["echo 42", v:_null_dict, "echo 44"])') eq('Vim(call):E731: using Dictionary as a String', ret) - ret = exc_exec('call capture(["echo 42", function("tr"), "echo 44"])') + ret = exc_exec('call execute(["echo 42", function("tr"), "echo 44"])') eq('Vim(call):E729: using Funcref as a String', ret) end) @@ -73,7 +73,7 @@ describe('capture()', function() local screen = Screen.new(20, 5) screen:attach() screen:set_default_attr_ignore({{bold=true, foreground=255}}) - feed(':let g:mes = capture("echon 42")<CR>') + feed(':let g:mes = execute("echon 42")<CR>') screen:expect([[ ^ | ~ | diff --git a/test/functional/legacy/030_fileformats_spec.lua b/test/functional/legacy/030_fileformats_spec.lua new file mode 100644 index 0000000000..9bc62a375e --- /dev/null +++ b/test/functional/legacy/030_fileformats_spec.lua @@ -0,0 +1,375 @@ +-- Test for a lot of variations of the 'fileformats' option + +local helpers = require('test.functional.helpers')(after_each) +local feed, clear, execute = helpers.feed, helpers.clear, helpers.execute +local eq, write_file = helpers.eq, helpers.write_file + +describe('fileformats option', function() + setup(function() + clear() + local dos = 'dos\r\ndos\r\n' + local mac = 'mac\rmac\r' + local unix = 'unix\nunix\n' + local eol = 'noeol' + write_file('XXDos', dos) + write_file('XXMac', mac) + write_file('XXUnix', unix) + write_file('XXEol', eol) + write_file('XXDosMac', dos..mac) + write_file('XXMacEol', mac..eol) + write_file('XXUxDs', unix..dos) + write_file('XXUxDsMc', unix..dos..mac) + write_file('XXUxMac', unix..mac) + end) + + teardown(function() + os.remove('test.out') + os.remove('XXDos') + os.remove('XXMac') + os.remove('XXUnix') + os.remove('XXEol') + os.remove('XXDosMac') + os.remove('XXMacEol') + os.remove('XXUxDs') + os.remove('XXUxDsMc') + os.remove('XXUxMac') + for i = 0, 9 do + for j = 1, 4 do + os.remove('XXtt'..i..j) + end + end + end) + + it('is working', function() + + -- Try reading and writing with 'fileformats' empty. + execute('set fileformats=') + execute('set fileformat=unix') + execute('e! XXUnix') + execute('w! test.out') + execute('e! XXDos') + execute('w! XXtt01') + execute('e! XXMac') + execute('w! XXtt02') + execute('bwipe XXUnix XXDos XXMac') + execute('set fileformat=dos') + execute('e! XXUnix') + execute('w! XXtt11') + execute('e! XXDos') + execute('w! XXtt12') + execute('e! XXMac') + execute('w! XXtt13') + execute('bwipe XXUnix XXDos XXMac') + execute('set fileformat=mac') + execute('e! XXUnix') + execute('w! XXtt21') + execute('e! XXDos') + execute('w! XXtt22') + execute('e! XXMac') + execute('w! XXtt23') + execute('bwipe XXUnix XXDos XXMac') + + -- Try reading and writing with 'fileformats' set to one format. + execute('set fileformats=unix') + execute('e! XXUxDsMc') + execute('w! XXtt31') + execute('bwipe XXUxDsMc') + execute('set fileformats=dos') + execute('e! XXUxDsMc') + execute('w! XXtt32') + execute('bwipe XXUxDsMc') + execute('set fileformats=mac') + execute('e! XXUxDsMc') + execute('w! XXtt33') + execute('bwipe XXUxDsMc') + + -- Try reading and writing with 'fileformats' set to two formats. + execute('set fileformats=unix,dos') + execute('e! XXUxDsMc') + execute('w! XXtt41') + execute('bwipe XXUxDsMc') + execute('e! XXUxMac') + execute('w! XXtt42') + execute('bwipe XXUxMac') + execute('e! XXDosMac') + execute('w! XXtt43') + execute('bwipe XXDosMac') + execute('set fileformats=unix,mac') + execute('e! XXUxDs') + execute('w! XXtt51') + execute('bwipe XXUxDs') + execute('e! XXUxDsMc') + execute('w! XXtt52') + execute('bwipe XXUxDsMc') + execute('e! XXDosMac') + execute('w! XXtt53') + execute('bwipe XXDosMac') + execute('e! XXEol') + feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>') + execute('w! XXtt54') + execute('bwipe XXEol') + execute('set fileformats=dos,mac') + execute('e! XXUxDs') + execute('w! XXtt61') + execute('bwipe XXUxDs') + execute('e! XXUxMac') + feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>') + execute('w! XXtt62') + execute('bwipe XXUxMac') + execute('e! XXUxDsMc') + execute('w! XXtt63') + execute('bwipe XXUxDsMc') + execute('e! XXMacEol') + feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>') + execute('w! XXtt64') + execute('bwipe XXMacEol') + + -- Try reading and writing with 'fileformats' set to three formats. + execute('set fileformats=unix,dos,mac') + execute('e! XXUxDsMc') + execute('w! XXtt71') + execute('bwipe XXUxDsMc') + execute('e! XXEol') + feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>') + execute('w! XXtt72') + execute('bwipe XXEol') + execute('set fileformats=mac,dos,unix') + execute('e! XXUxDsMc') + execute('w! XXtt81') + execute('bwipe XXUxDsMc') + execute('e! XXEol') + feed('ggO<C-R>=&ffs<CR>:<C-R>=&ff<CR><ESC>') + execute('w! XXtt82') + execute('bwipe XXEol') + -- Try with 'binary' set. + execute('set fileformats=mac,unix,dos') + execute('set binary') + execute('e! XXUxDsMc') + execute('w! XXtt91') + execute('bwipe XXUxDsMc') + execute('set fileformats=mac') + execute('e! XXUxDsMc') + execute('w! XXtt92') + execute('bwipe XXUxDsMc') + execute('set fileformats=dos') + execute('e! XXUxDsMc') + execute('w! XXtt93') + + -- Append "END" to each file so that we can see what the last written + -- char was. + execute('set fileformat=unix nobin') + feed('ggdGaEND<esc>') + execute('w >>XXtt01') + execute('w >>XXtt02') + execute('w >>XXtt11') + execute('w >>XXtt12') + execute('w >>XXtt13') + execute('w >>XXtt21') + execute('w >>XXtt22') + execute('w >>XXtt23') + execute('w >>XXtt31') + execute('w >>XXtt32') + execute('w >>XXtt33') + execute('w >>XXtt41') + execute('w >>XXtt42') + execute('w >>XXtt43') + execute('w >>XXtt51') + execute('w >>XXtt52') + execute('w >>XXtt53') + execute('w >>XXtt54') + execute('w >>XXtt61') + execute('w >>XXtt62') + execute('w >>XXtt63') + execute('w >>XXtt64') + execute('w >>XXtt71') + execute('w >>XXtt72') + execute('w >>XXtt81') + execute('w >>XXtt82') + execute('w >>XXtt91') + execute('w >>XXtt92') + execute('w >>XXtt93') + + -- Concatenate the results. + -- Make fileformat of test.out the native fileformat. + -- Add a newline at the end. + execute('set binary') + execute('e! test.out') + execute('$r XXtt01') + execute('$r XXtt02') + feed('Go1<esc>') + execute('$r XXtt11') + execute('$r XXtt12') + execute('$r XXtt13') + feed('Go2<esc>') + execute('$r XXtt21') + execute('$r XXtt22') + execute('$r XXtt23') + feed('Go3<esc>') + execute('$r XXtt31') + execute('$r XXtt32') + execute('$r XXtt33') + feed('Go4<esc>') + execute('$r XXtt41') + execute('$r XXtt42') + execute('$r XXtt43') + feed('Go5<esc>') + execute('$r XXtt51') + execute('$r XXtt52') + execute('$r XXtt53') + execute('$r XXtt54') + feed('Go6<esc>') + execute('$r XXtt61') + execute('$r XXtt62') + execute('$r XXtt63') + execute('$r XXtt64') + feed('Go7<esc>') + execute('$r XXtt71') + execute('$r XXtt72') + feed('Go8<esc>') + execute('$r XXtt81') + execute('$r XXtt82') + feed('Go9<esc>') + execute('$r XXtt91') + execute('$r XXtt92') + execute('$r XXtt93') + feed('Go10<esc>') + execute('$r XXUnix') + execute('set nobinary ff&') + + -- Assert buffer contents. This has to be done manually as + -- helpers.expect() calls helpers.dedent() which messes up the white space + -- and carrige returns. + eq( + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'END\n'.. + 'mac\rmac\r\n'.. + 'END\n'.. + '1\n'.. + 'unix\r\n'.. + 'unix\r\n'.. + 'END\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'END\n'.. + 'mac\rmac\r\r\n'.. + 'END\n'.. + '2\n'.. + 'unix\n'.. + 'unix\n'.. + '\rEND\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + '\rEND\n'.. + 'mac\rmac\rEND\n'.. + '3\n'.. + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\r\n'.. + 'END\n'.. + 'unix\r\n'.. + 'unix\r\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\r\r\n'.. + 'END\n'.. + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\rEND\n'.. + '4\n'.. + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\r\n'.. + 'END\n'.. + 'unix\n'.. + 'unix\n'.. + 'mac\rmac\r\n'.. + 'END\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\r\r\n'.. + 'END\n'.. + '5\n'.. + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'END\n'.. + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\r\n'.. + 'END\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\rEND\n'.. + 'unix,mac:unix\n'.. + 'noeol\n'.. + 'END\n'.. + '6\n'.. + 'unix\r\n'.. + 'unix\r\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'END\n'.. + 'dos,mac:dos\r\n'.. + 'unix\r\n'.. + 'unix\r\n'.. + 'mac\rmac\r\r\n'.. + 'END\n'.. + 'unix\r\n'.. + 'unix\r\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\r\r\n'.. + 'END\n'.. + 'dos,mac:mac\rmac\rmac\rnoeol\rEND\n'.. + '7\n'.. + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\r\n'.. + 'END\n'.. + 'unix,dos,mac:unix\n'.. + 'noeol\n'.. + 'END\n'.. + '8\n'.. + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\r\n'.. + 'END\n'.. + 'mac,dos,unix:mac\rnoeol\rEND\n'.. + '9\n'.. + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\rEND\n'.. + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\rEND\n'.. + 'unix\n'.. + 'unix\n'.. + 'dos\r\n'.. + 'dos\r\n'.. + 'mac\rmac\rEND\n'.. + '10\n'.. + 'unix\n'.. + 'unix', + helpers.curbuf_contents()) + end) +end) diff --git a/test/functional/ui/mouse_spec.lua b/test/functional/ui/mouse_spec.lua index a433143266..7b820347ac 100644 --- a/test/functional/ui/mouse_spec.lua +++ b/test/functional/ui/mouse_spec.lua @@ -462,4 +462,321 @@ describe('Mouse input', function() | ]]) end) + + describe('on concealed text', function() + -- Helpful for reading the test expectations: + -- :match Error /\^/ + local concealed = { + c = { foreground = Screen.colors.LightGrey, background = Screen.colors.DarkGray } + } + + before_each(function() + screen:try_resize(25, 7) + feed('ggdG') + + execute('set concealcursor=n') + execute('set nowrap') + execute('syntax match NonText "\\<amet\\>" conceal') + execute('syntax match NonText "\\cs\\|g." conceal cchar=X') + execute('syntax match NonText "\\%(lo\\|cl\\)." conceal') + execute('syntax match NonText "Lo" conceal cchar=Y') + + insert([[ + Lorem ipsum dolor sit amet, consetetur sadipscing elitr. + Stet clita kasd gubergren, no sea takimata sanctus est. + ]]) + + feed('gg') + end) + + it('(level 1) click on non-wrapped lines', function() + execute('let &conceallevel=1', 'echo') + + feed('<esc><LeftMouse><0,0>') + screen:expect([[ + {c:^Y}rem ip{c:X}um do{c: } {c:X}it {c: }, con| + {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en, no| + | + ~ | + ~ | + ~ | + | + ]], concealed) + + feed('<esc><LeftMouse><1,0>') + screen:expect([[ + {c:Y}^rem ip{c:X}um do{c: } {c:X}it {c: }, con| + {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en, no| + | + ~ | + ~ | + ~ | + | + ]], concealed) + + feed('<esc><LeftMouse><15,0>') + screen:expect([[ + {c:Y}rem ip{c:X}um do{c: } {c:^X}it {c: }, con| + {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en, no| + | + ~ | + ~ | + ~ | + | + ]], concealed) + + feed('<esc><LeftMouse><15,1>') + screen:expect([[ + {c:Y}rem ip{c:X}um do{c: } {c:X}it {c: }, con| + {c:X}tet {c: }ta ka{c:X}d {c:X}^ber{c:X}en, no| + | + ~ | + ~ | + ~ | + | + ]], concealed) + end) -- level 1 - non wrapped + + it('(level 1) click on wrapped lines', function() + execute('let &conceallevel=1', 'let &wrap=1', 'echo') + + feed('<esc><LeftMouse><0,0>') + screen:expect([[ + {c:^Y}rem ip{c:X}um do{c: } {c:X}it {c: } | + , con{c:X}etetur {c:X}adip{c:X}cin{c:X} | + elitr. | + {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en | + , no {c:X}ea takimata {c:X}anctu{c:X}| + e{c:X}t. | + | + ]], concealed) + + feed('<esc><LeftMouse><6,1>') + screen:expect([[ + {c:Y}rem ip{c:X}um do{c: } {c:X}it {c: } | + , con{c:X}^etetur {c:X}adip{c:X}cin{c:X} | + elitr. | + {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en | + , no {c:X}ea takimata {c:X}anctu{c:X}| + e{c:X}t. | + | + ]], concealed) + + feed('<esc><LeftMouse><15,1>') + screen:expect([[ + {c:Y}rem ip{c:X}um do{c: } {c:X}it {c: } | + , con{c:X}etetur {c:X}a^dip{c:X}cin{c:X} | + elitr. | + {c:X}tet {c: }ta ka{c:X}d {c:X}ber{c:X}en | + , no {c:X}ea takimata {c:X}anctu{c:X}| + e{c:X}t. | + | + ]], concealed) + + feed('<esc><LeftMouse><15,3>') + screen:expect([[ + {c:Y}rem ip{c:X}um do{c: } {c:X}it {c: } | + , con{c:X}etetur {c:X}adip{c:X}cin{c:X} | + elitr. | + {c:X}tet {c: }ta ka{c:X}d {c:X}^ber{c:X}en | + , no {c:X}ea takimata {c:X}anctu{c:X}| + e{c:X}t. | + | + ]], concealed) + end) -- level 1 - wrapped + + + it('(level 2) click on non-wrapped lines', function() + execute('let &conceallevel=2', 'echo') + + feed('<esc><LeftMouse><0,0>') + screen:expect([[ + {c:^Y}rem ip{c:X}um do {c:X}it , con{c:X}e| + {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en, no | + | + ~ | + ~ | + ~ | + | + ]], concealed) + + feed('<esc><LeftMouse><1,0>') + screen:expect([[ + {c:Y}^rem ip{c:X}um do {c:X}it , con{c:X}e| + {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en, no | + | + ~ | + ~ | + ~ | + | + ]], concealed) + + feed('<esc><LeftMouse><15,0>') + screen:expect([[ + {c:Y}rem ip{c:X}um do {c:X}^it , con{c:X}e| + {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en, no | + | + ~ | + ~ | + ~ | + | + ]], concealed) + + feed('<esc><LeftMouse><15,1>') + screen:expect([[ + {c:Y}rem ip{c:X}um do {c:X}it , con{c:X}e| + {c:X}tet ta ka{c:X}d {c:X}b^er{c:X}en, no | + | + ~ | + ~ | + ~ | + | + ]], concealed) + end) -- level 2 - non wrapped + + it('(level 2) click on wrapped lines', function() + execute('let &conceallevel=2', 'let &wrap=1', 'echo') + + feed('<esc><LeftMouse><0,0>') + screen:expect([[ + {c:^Y}rem ip{c:X}um do {c:X}it | + , con{c:X}etetur {c:X}adip{c:X}cin{c:X} | + elitr. | + {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en | + , no {c:X}ea takimata {c:X}anctu{c:X}| + e{c:X}t. | + | + ]], concealed) + + feed('<esc><LeftMouse><6,1>') + screen:expect([[ + {c:Y}rem ip{c:X}um do {c:X}it | + , con{c:X}^etetur {c:X}adip{c:X}cin{c:X} | + elitr. | + {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en | + , no {c:X}ea takimata {c:X}anctu{c:X}| + e{c:X}t. | + | + ]], concealed) + + feed('<esc><LeftMouse><15,1>') + screen:expect([[ + {c:Y}rem ip{c:X}um do {c:X}it | + , con{c:X}etetur {c:X}a^dip{c:X}cin{c:X} | + elitr. | + {c:X}tet ta ka{c:X}d {c:X}ber{c:X}en | + , no {c:X}ea takimata {c:X}anctu{c:X}| + e{c:X}t. | + | + ]], concealed) + + feed('<esc><LeftMouse><15,3>') + screen:expect([[ + {c:Y}rem ip{c:X}um do {c:X}it | + , con{c:X}etetur {c:X}adip{c:X}cin{c:X} | + elitr. | + {c:X}tet ta ka{c:X}d {c:X}b^er{c:X}en | + , no {c:X}ea takimata {c:X}anctu{c:X}| + e{c:X}t. | + | + ]], concealed) + end) -- level 2 - wrapped + + + it('(level 3) click on non-wrapped lines', function() + execute('let &conceallevel=3', 'echo') + + feed('<esc><LeftMouse><0,0>') + screen:expect([[ + ^rem ipum do it , conetetu| + tet ta kad beren, no ea t| + | + ~ | + ~ | + ~ | + | + ]], concealed) + + feed('<esc><LeftMouse><1,0>') + screen:expect([[ + r^em ipum do it , conetetu| + tet ta kad beren, no ea t| + | + ~ | + ~ | + ~ | + | + ]], concealed) + + feed('<esc><LeftMouse><15,0>') + screen:expect([[ + rem ipum do it ^, conetetu| + tet ta kad beren, no ea t| + | + ~ | + ~ | + ~ | + | + ]], concealed) + + feed('<esc><LeftMouse><15,1>') + screen:expect([[ + rem ipum do it , conetetu| + tet ta kad bere^n, no ea t| + | + ~ | + ~ | + ~ | + | + ]], concealed) + end) -- level 3 - non wrapped + + it('(level 3) click on wrapped lines', function() + execute('let &conceallevel=3', 'let &wrap=1', 'echo') + + feed('<esc><LeftMouse><0,0>') + screen:expect([[ + ^rem ipum do it | + , conetetur adipcin | + elitr. | + tet ta kad beren | + , no ea takimata anctu | + et. | + | + ]], concealed) + + feed('<esc><LeftMouse><6,1>') + screen:expect([[ + rem ipum do it | + , cone^tetur adipcin | + elitr. | + tet ta kad beren | + , no ea takimata anctu | + et. | + | + ]], concealed) + + feed('<esc><LeftMouse><15,1>') + screen:expect([[ + rem ipum do it | + , conetetur adi^pcin | + elitr. | + tet ta kad beren | + , no ea takimata anctu | + et. | + | + ]], concealed) + + feed('<esc><LeftMouse><15,3>') + screen:expect([[ + rem ipum do it | + , conetetur adipcin | + elitr. | + tet ta kad bere^n | + , no ea takimata anctu | + et. | + | + ]], concealed) + end) -- level 3 - wrapped + end) end) |