diff options
38 files changed, 530 insertions, 100 deletions
diff --git a/.travis.yml b/.travis.yml index 4bb5c00251..53faf29cc5 100644 --- a/.travis.yml +++ b/.travis.yml @@ -71,6 +71,7 @@ addons: - build-essential - clang - cmake + - cpanminus - cscope - gcc-multilib - gdb @@ -90,7 +91,9 @@ addons: - powershell packages: - ccache + - cpanminus - ninja + - perl jobs: include: diff --git a/appveyor.yml b/appveyor.yml index 7e2aef345b..01ca16f930 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -22,9 +22,6 @@ init: #- ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) matrix: fast_finish: true -install: [] -before_build: -- ps: Install-Product node 10 build_script: - powershell ci\build.ps1 after_build: diff --git a/ci/before_install.sh b/ci/before_install.sh index 5810bec71a..0303936bdd 100755 --- a/ci/before_install.sh +++ b/ci/before_install.sh @@ -44,7 +44,6 @@ fi source ~/.nvm/nvm.sh nvm install 10 -nvm use 10 if [[ -n "$CMAKE_URL" ]]; then echo "Installing custom CMake: $CMAKE_URL" diff --git a/ci/build.ps1 b/ci/build.ps1 index 524dabdf3e..627dc69e88 100644 --- a/ci/build.ps1 +++ b/ci/build.ps1 @@ -29,6 +29,30 @@ function exitIfFailed() { } } +# https://github.com/lukesampson/scoop#installation +$scoop = (New-Object System.Net.WebClient).DownloadString('https://get.scoop.sh') +& { + Set-StrictMode -Off + Invoke-Expression $scoop +} + +scoop install diffutils perl +diff3 --version +perl --version +cpanm.bat --version + +if (-not $NoTests) { + scoop install nodejs-lts + node --version + npm.cmd --version + + cpanm.bat -n Neovim::Ext + if ($LastExitCode -ne 0) { + Get-Content -Path "$env:USERPROFILE\.cpanm\build.log" + } + perl -W -e 'use Neovim::Ext; print $Neovim::Ext::VERSION'; exitIfFailed +} + if (-Not (Test-Path -PathType container $env:DEPS_BUILD_DIR)) { write-host "cache dir not found: $($env:DEPS_BUILD_DIR)" mkdir $env:DEPS_BUILD_DIR @@ -57,7 +81,7 @@ if ($compiler -eq 'MINGW') { # in MSYS2, but we cannot build inside the MSYS2 shell. $cmakeGenerator = 'Ninja' $cmakeGeneratorArgs = '-v' - $mingwPackages = @('ninja', 'cmake', 'perl', 'diffutils').ForEach({ + $mingwPackages = @('ninja', 'cmake').ForEach({ "mingw-w64-$arch-$_" }) @@ -115,7 +139,6 @@ if (-not $NoTests) { if (-Not (Test-Path -PathType Leaf "$env:TREE_SITTER_DIR\bin\c.dll")) { exit 1 } - } if ($compiler -eq 'MSVC') { diff --git a/ci/install.sh b/ci/install.sh index 3364edfe70..b3ec9e7f65 100755 --- a/ci/install.sh +++ b/ci/install.sh @@ -50,3 +50,6 @@ else gcc -m32 -o "$TREE_SITTER_DIR/bin/c.so" -shared parser.c -I. fi test -f "$TREE_SITTER_DIR/bin/c.so" + +sudo cpanm -n Neovim::Ext || cat "$HOME/.cpanm/build.log" +perl -W -e 'use Neovim::Ext; print $Neovim::Ext::VERSION' diff --git a/runtime/autoload/health/provider.vim b/runtime/autoload/health/provider.vim index ad7a614ff5..cc7d86d0c1 100644 --- a/runtime/autoload/health/provider.vim +++ b/runtime/autoload/health/provider.vim @@ -566,7 +566,7 @@ function! s:check_node() abort endif let node_v = get(split(s:system('node -v'), "\n"), 0, '') call health#report_info('Node.js: '. node_v) - if !s:shell_error && s:version_cmp(node_v[1:], '6.0.0') < 0 + if s:shell_error || s:version_cmp(node_v[1:], '6.0.0') < 0 call health#report_warn('Neovim node.js host does not support '.node_v) " Skip further checks, they are nonsense if nodejs is too old. return @@ -595,14 +595,12 @@ function! s:check_node() abort \ 'Are you behind a firewall or proxy?']) return endif - if !empty(latest_npm) - try - let pkg_data = json_decode(latest_npm) - catch /E474/ - return 'error: '.latest_npm - endtry - let latest_npm = get(get(pkg_data, 'dist-tags', {}), 'latest', 'unable to parse') - endif + try + let pkg_data = json_decode(latest_npm) + catch /E474/ + return 'error: '.latest_npm + endtry + let latest_npm = get(get(pkg_data, 'dist-tags', {}), 'latest', 'unable to parse') let current_npm_cmd = ['node', host, '--version'] let current_npm = s:system(current_npm_cmd) @@ -623,10 +621,68 @@ function! s:check_node() abort endif endfunction +function! s:check_perl() abort + call health#report_start('Perl provider (optional)') + + if s:disabled_via_loaded_var('perl') + return + endif + + if !executable('perl') || !executable('cpanm') + call health#report_warn( + \ '`perl` and `cpanm` must be in $PATH.', + \ ['Install Perl and cpanminus and verify that `perl` and `cpanm` commands work.']) + return + endif + let perl_v = get(split(s:system(['perl', '-W', '-e', 'print $^V']), "\n"), 0, '') + call health#report_info('Perl: '. perl_v) + if s:shell_error + call health#report_warn('Neovim perl host does not support '.perl_v) + " Skip further checks, they are nonsense if perl is too old. + return + endif + + let host = provider#perl#Detect() + if empty(host) + call health#report_warn('Missing "Neovim::Ext" cpan module.', + \ ['Run in shell: cpanm Neovim::Ext']) + return + endif + call health#report_info('Neovim perl host: '. host) + + let latest_cpan_cmd = 'cpanm --info Neovim::Ext' + let latest_cpan = s:system(latest_cpan_cmd) + if s:shell_error || empty(latest_cpan) + call health#report_error('Failed to run: '. latest_cpan_cmd, + \ ["Make sure you're connected to the internet.", + \ 'Are you behind a firewall or proxy?']) + return + endif + let latest_cpan = matchstr(latest_cpan, '\(\.\?\d\)\+') + + let current_cpan_cmd = [host, '-W', '-MNeovim::Ext', '-e', 'print $Neovim::Ext::VERSION'] + let current_cpan = s:system(current_cpan_cmd) + if s:shell_error + call health#report_error('Failed to run: '. string(current_cpan_cmd), + \ ['Report this issue with the output of: ', string(current_cpan_cmd)]) + return + endif + + if s:version_cmp(current_cpan, latest_cpan) == -1 + call health#report_warn( + \ printf('Module "Neovim::Ext" is out-of-date. Installed: %s, latest: %s', + \ current_cpan, latest_cpan), + \ ['Run in shell: cpanm Neovim::Ext']) + else + call health#report_ok('Latest "Neovim::Ext" cpan module is installed: '. current_cpan) + endif +endfunction + function! health#provider#check() abort call s:check_clipboard() call s:check_python(2) call s:check_python(3) call s:check_ruby() call s:check_node() + call s:check_perl() endfunction diff --git a/runtime/autoload/provider/perl.vim b/runtime/autoload/provider/perl.vim new file mode 100644 index 0000000000..36ca2bbf14 --- /dev/null +++ b/runtime/autoload/provider/perl.vim @@ -0,0 +1,69 @@ +if exists('s:loaded_perl_provider') + finish +endif + +let s:loaded_perl_provider = 1 + +function! provider#perl#Detect() abort + " use g:perl_host_prof if set or check if perl is on the path + let prog = exepath(get(g:, 'perl_host_prog', 'perl')) + if empty(prog) + return '' + endif + + " if perl is available, make sure the required module is available + call system([prog, '-W', '-MNeovim::Ext', '-e', '']) + return v:shell_error ? '' : prog +endfunction + +function! provider#perl#Prog() abort + return s:prog +endfunction + +function! provider#perl#Require(host) abort + if s:err != '' + echoerr s:err + return + endif + + let prog = provider#perl#Prog() + let args = [s:prog, '-e', 'use Neovim::Ext; start_host();'] + + " Collect registered perl plugins into args + let perl_plugins = remote#host#PluginsForHost(a:host.name) + for plugin in perl_plugins + call add(args, plugin.path) + endfor + + return provider#Poll(args, a:host.orig_name, '$NVIM_PERL_LOG_FILE') +endfunction + +function! provider#perl#Call(method, args) abort + if s:err != '' + echoerr s:err + return + endif + + if !exists('s:host') + try + let s:host = remote#host#Require('perl') + catch + let s:err = v:exception + echohl WarningMsg + echomsg v:exception + echohl None + return + endtry + endif + return call('rpcrequest', insert(insert(a:args, 'perl_'.a:method), s:host)) +endfunction + +let s:err = '' +let s:prog = provider#perl#Detect() +let g:loaded_perl_provider = empty(s:prog) ? 1 : 2 + +if g:loaded_perl_provider != 2 + let s:err = 'Cannot find perl or the required perl module' +endif + +call remote#host#RegisterPlugin('perl-provider', 'perl', []) diff --git a/runtime/autoload/remote/host.vim b/runtime/autoload/remote/host.vim index 1cf328e08d..c34ff4bee7 100644 --- a/runtime/autoload/remote/host.vim +++ b/runtime/autoload/remote/host.vim @@ -203,3 +203,7 @@ call remote#host#Register('ruby', '*.rb', " nodejs call remote#host#Register('node', '*', \ function('provider#node#Require')) + +" perl +call remote#host#Register('perl', '*', + \ function('provider#perl#Require')) diff --git a/runtime/doc/provider.txt b/runtime/doc/provider.txt index 46ff075cef..0a6cdc60e8 100644 --- a/runtime/doc/provider.txt +++ b/runtime/doc/provider.txt @@ -127,6 +127,31 @@ To use the RVM "system" Ruby installation: > let g:ruby_host_prog = 'rvm system do neovim-ruby-host' ============================================================================== +Perl integration *provider-perl* + +Nvim supports Perl |remote-plugin|s. +https://github.com/jacquesg/p5-Neovim-Ext + + +PERL QUICKSTART~ + +To use perl remote-plugins with Nvim, install the "Neovim::Ext" cpan package: > + cpanm -n Neovim::Ext + +Run |:checkhealth| to see if your system is up-to-date. + + +PERL PROVIDER CONFIGURATION~ + *g:loaded_perl_provider* +To disable Perl support: > + :let g:loaded_perl_provider = 0 +< + *g:perl_host_prog* +Command to start the Perl executable. Must be set before any +check for has("perl"). > + let g:perl_host_prog = '/path/to/perl' +< +============================================================================== Node.js integration *provider-nodejs* Nvim supports Node.js |remote-plugin|s. diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 3106011fe2..a666ed92da 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -26,7 +26,7 @@ #include "nvim/map_defs.h" #include "nvim/map.h" #include "nvim/mark.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/fileio.h" #include "nvim/move.h" #include "nvim/syntax.h" diff --git a/src/nvim/api/private/helpers.c b/src/nvim/api/private/helpers.c index 37e31e0807..a1745ef777 100644 --- a/src/nvim/api/private/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -24,7 +24,7 @@ #include "nvim/eval/typval.h" #include "nvim/map_defs.h" #include "nvim/map.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/option.h" #include "nvim/option_defs.h" #include "nvim/version.h" diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index baa0387fd8..9c58ce853b 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -40,7 +40,7 @@ #include "nvim/ops.h" #include "nvim/option.h" #include "nvim/state.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/syntax.h" #include "nvim/getchar.h" #include "nvim/os/input.h" diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 837fcb5cc1..5083780719 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -53,7 +53,7 @@ #include "nvim/indent_c.h" #include "nvim/main.h" #include "nvim/mark.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -3068,18 +3068,15 @@ void col_print(char_u *buf, size_t buflen, int col, int vcol) } } -/* - * put file name in title bar of window and in icon title - */ - static char_u *lasttitle = NULL; static char_u *lasticon = NULL; + +// Put the title name in the title bar and icon of the window. void maketitle(void) { - char_u *t_str = NULL; - char_u *i_name; - char_u *i_str = NULL; + char_u *title_str = NULL; + char_u *icon_str = NULL; int maxlen = 0; int len; int mustset; @@ -3093,7 +3090,7 @@ void maketitle(void) need_maketitle = false; if (!p_title && !p_icon && lasttitle == NULL && lasticon == NULL) { - return; + return; // nothing to do } if (p_title) { @@ -3114,14 +3111,14 @@ void maketitle(void) build_stl_str_hl(curwin, (char_u *)buf, sizeof(buf), p_titlestring, use_sandbox, 0, maxlen, NULL, NULL); - t_str = (char_u *)buf; + title_str = (char_u *)buf; if (called_emsg) { set_string_option_direct((char_u *)"titlestring", -1, (char_u *)"", OPT_FREE, SID_ERROR); } called_emsg |= save_called_emsg; } else { - t_str = p_titlestring; + title_str = p_titlestring; } } else { // Format: "fname + (path) (1 of 2) - VIM". @@ -3205,16 +3202,16 @@ void maketitle(void) trunc_string((char_u *)buf, (char_u *)buf, maxlen, sizeof(buf)); } } - t_str = (char_u *)buf; + title_str = (char_u *)buf; #undef SPACE_FOR_FNAME #undef SPACE_FOR_DIR #undef SPACE_FOR_ARGNR } } - mustset = ti_change(t_str, &lasttitle); + mustset = value_change(title_str, &lasttitle); if (p_icon) { - i_str = (char_u *)buf; + icon_str = (char_u *)buf; if (*p_iconstring != NUL) { if (stl_syntax & STL_IN_ICON) { int use_sandbox = false; @@ -3222,37 +3219,40 @@ void maketitle(void) use_sandbox = was_set_insecurely((char_u *)"iconstring", 0); called_emsg = false; - build_stl_str_hl(curwin, i_str, sizeof(buf), - p_iconstring, use_sandbox, - 0, 0, NULL, NULL); - if (called_emsg) + build_stl_str_hl(curwin, icon_str, sizeof(buf), + p_iconstring, use_sandbox, + 0, 0, NULL, NULL); + if (called_emsg) { set_string_option_direct((char_u *)"iconstring", -1, - (char_u *)"", OPT_FREE, SID_ERROR); + (char_u *)"", OPT_FREE, SID_ERROR); + } called_emsg |= save_called_emsg; - } else - i_str = p_iconstring; + } else { + icon_str = p_iconstring; + } } else { + char_u *buf_p; if (buf_spname(curbuf) != NULL) { - i_name = buf_spname(curbuf); + buf_p = buf_spname(curbuf); } else { // use file name only in icon - i_name = path_tail(curbuf->b_ffname); + buf_p = path_tail(curbuf->b_ffname); } - *i_str = NUL; + *icon_str = NUL; // Truncate name at 100 bytes. - len = (int)STRLEN(i_name); + len = (int)STRLEN(buf_p); if (len > 100) { len -= 100; if (has_mbyte) { - len += (*mb_tail_off)(i_name, i_name + len) + 1; + len += (*mb_tail_off)(buf_p, buf_p + len) + 1; } - i_name += len; + buf_p += len; } - STRCPY(i_str, i_name); - trans_characters(i_str, IOSIZE); + STRCPY(icon_str, buf_p); + trans_characters(icon_str, IOSIZE); } } - mustset |= ti_change(i_str, &lasticon); + mustset |= value_change(icon_str, &lasticon); if (mustset) { resettitle(); @@ -3266,8 +3266,8 @@ void maketitle(void) /// @param str desired title string /// @param[in,out] last current title string // -/// @return true when "*last" changed. -static bool ti_change(char_u *str, char_u **last) +/// @return true if resettitle() is to be called. +static bool value_change(char_u *str, char_u **last) FUNC_ATTR_WARN_UNUSED_RESULT { if ((str == NULL) != (*last == NULL) @@ -3275,10 +3275,11 @@ static bool ti_change(char_u *str, char_u **last) xfree(*last); if (str == NULL) { *last = NULL; + resettitle(); } else { *last = vim_strsave(str); + return true; } - return true; } return false; } diff --git a/src/nvim/change.c b/src/nvim/change.c index 7eb6ea7328..a341b8fce1 100644 --- a/src/nvim/change.c +++ b/src/nvim/change.c @@ -17,7 +17,7 @@ #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/mark.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/memline.h" #include "nvim/misc1.h" #include "nvim/move.h" diff --git a/src/nvim/edit.c b/src/nvim/edit.c index 0c183add16..68fa99484c 100644 --- a/src/nvim/edit.c +++ b/src/nvim/edit.c @@ -28,7 +28,7 @@ #include "nvim/indent.h" #include "nvim/indent_c.h" #include "nvim/main.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 5eec44a7b7..9379d94fa3 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -24611,6 +24611,7 @@ bool eval_has_provider(const char *feat) && !strequal(feat, "python_dynamic") && !strequal(feat, "python3_compiled") && !strequal(feat, "python3_dynamic") + && !strequal(feat, "perl") && !strequal(feat, "ruby") && !strequal(feat, "node")) { // Avoid autoload for non-provider has() features. diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 53caaa6a67..bc6821f60f 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -40,7 +40,7 @@ #include "nvim/buffer_updates.h" #include "nvim/main.h" #include "nvim/mark.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/message.h" diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index 6bda62594e..02bee838d5 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4651,6 +4651,8 @@ static int get_tabpage_arg(exarg_T *eap) if (relative == 0) { if (STRCMP(p, "$") == 0) { tab_number = LAST_TAB_NR; + } else if (STRCMP(p, "#") == 0) { + tab_number = tabpage_index(lastused_tabpage); } else if (p == p_save || *p_save == '-' || *p != NUL || tab_number > LAST_TAB_NR) { // No numbers as argument. diff --git a/src/nvim/ex_getln.c b/src/nvim/ex_getln.c index 551482dab3..e6b7bfaebf 100644 --- a/src/nvim/ex_getln.c +++ b/src/nvim/ex_getln.c @@ -941,8 +941,10 @@ static int command_line_execute(VimState *state, int key) // if 'wildmode' contains "list" may still need to list if (s->xpc.xp_numfiles > 1 && !s->did_wild_list - && (wim_flags[s->wim_index] & WIM_LIST)) { - (void)showmatches(&s->xpc, false); + && ((wim_flags[s->wim_index] & WIM_LIST) + || (p_wmnu && (wim_flags[s->wim_index] & WIM_FULL) != 0))) { + (void)showmatches(&s->xpc, p_wmnu + && ((wim_flags[s->wim_index] & WIM_LIST) == 0)); redrawcmd(); s->did_wild_list = true; } diff --git a/src/nvim/mark_extended.c b/src/nvim/extmark.c index b60d847676..d60723c755 100644 --- a/src/nvim/mark_extended.c +++ b/src/nvim/extmark.c @@ -32,7 +32,7 @@ #include "nvim/api/vim.h" #include "nvim/vim.h" #include "nvim/charset.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/buffer_updates.h" #include "nvim/memline.h" #include "nvim/pos.h" @@ -45,7 +45,7 @@ #include "nvim/highlight.h" #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "mark_extended.c.generated.h" +# include "extmark.c.generated.h" #endif static ExtmarkNs *buf_ns_ref(buf_T *buf, uint64_t ns_id, bool put) { diff --git a/src/nvim/mark_extended.h b/src/nvim/extmark.h index f809148d9b..829cbe0236 100644 --- a/src/nvim/mark_extended.h +++ b/src/nvim/extmark.h @@ -1,8 +1,8 @@ -#ifndef NVIM_MARK_EXTENDED_H -#define NVIM_MARK_EXTENDED_H +#ifndef NVIM_EXTMARK_H +#define NVIM_EXTMARK_H #include "nvim/buffer_defs.h" -#include "nvim/mark_extended_defs.h" +#include "nvim/extmark_defs.h" #include "nvim/marktree.h" EXTERN int extmark_splice_pending INIT(= 0); @@ -87,7 +87,7 @@ typedef struct { #ifdef INCLUDE_GENERATED_DECLARATIONS -# include "mark_extended.h.generated.h" +# include "extmark.h.generated.h" #endif -#endif // NVIM_MARK_EXTENDED_H +#endif // NVIM_EXTMARK_H diff --git a/src/nvim/mark_extended_defs.h b/src/nvim/extmark_defs.h index 439f7f0b36..c927048981 100644 --- a/src/nvim/mark_extended_defs.h +++ b/src/nvim/extmark_defs.h @@ -1,5 +1,5 @@ -#ifndef NVIM_MARK_EXTENDED_DEFS_H -#define NVIM_MARK_EXTENDED_DEFS_H +#ifndef NVIM_EXTMARK_DEFS_H +#define NVIM_EXTMARK_DEFS_H #include "nvim/pos.h" // for colnr_T #include "nvim/lib/kvec.h" @@ -34,4 +34,4 @@ typedef enum { kExtmarkUndoNoRedo, // Operation should be undoable, but not redoable } ExtmarkOp; -#endif // NVIM_MARK_EXTENDED_DEFS_H +#endif // NVIM_EXTMARK_DEFS_H diff --git a/src/nvim/fold.c b/src/nvim/fold.c index addfab8f08..0b14a6affb 100644 --- a/src/nvim/fold.c +++ b/src/nvim/fold.c @@ -22,7 +22,7 @@ #include "nvim/func_attr.h" #include "nvim/indent.h" #include "nvim/buffer_updates.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/mark.h" #include "nvim/memline.h" #include "nvim/memory.h" diff --git a/src/nvim/indent.c b/src/nvim/indent.c index 2c5fdd8ea6..f8018c039d 100644 --- a/src/nvim/indent.c +++ b/src/nvim/indent.c @@ -13,7 +13,7 @@ #include "nvim/charset.h" #include "nvim/cursor.h" #include "nvim/mark.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/memline.h" #include "nvim/memory.h" #include "nvim/misc1.h" diff --git a/src/nvim/map.h b/src/nvim/map.h index 761938776d..0ad7865bf0 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -4,7 +4,7 @@ #include <stdbool.h> #include "nvim/map_defs.h" -#include "nvim/mark_extended_defs.h" +#include "nvim/extmark_defs.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/dispatch.h" #include "nvim/highlight_defs.h" diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 4a7452493a..fa7c7d61c9 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -20,7 +20,7 @@ #include "nvim/ex_cmds.h" #include "nvim/fileio.h" #include "nvim/fold.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" diff --git a/src/nvim/mark.h b/src/nvim/mark.h index d8370c367a..b3d9b5d95a 100644 --- a/src/nvim/mark.h +++ b/src/nvim/mark.h @@ -6,7 +6,7 @@ #include "nvim/buffer_defs.h" #include "nvim/func_attr.h" #include "nvim/mark_defs.h" -#include "nvim/mark_extended_defs.h" +#include "nvim/extmark_defs.h" #include "nvim/memory.h" #include "nvim/pos.h" #include "nvim/os/time.h" diff --git a/src/nvim/ops.c b/src/nvim/ops.c index da2b81fd0a..641323ae5e 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -31,7 +31,7 @@ #include "nvim/indent.h" #include "nvim/log.h" #include "nvim/mark.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" diff --git a/src/nvim/option.c b/src/nvim/option.c index 2871a4b7de..f03dcc2bf2 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2021,13 +2021,10 @@ static char_u *check_cedit(void) // maketitle() to create and display it. // When switching the title or icon off, call ui_set_{icon,title}(NULL) to get // the old value back. -static void did_set_title( - int icon // Did set icon instead of title -) +static void did_set_title(void) { if (starting != NO_SCREEN) { maketitle(); - resettitle(); } } @@ -2986,7 +2983,7 @@ ambw_end: } else { stl_syntax &= ~flagval; } - did_set_title(varp == &p_iconstring); + did_set_title(); } else if (varp == &p_sel) { // 'selection' if (*p_sel == NUL @@ -4025,9 +4022,9 @@ static char *set_bool_option(const int opt_idx, char_u *const varp, (void)buf_init_chartab(curbuf, false); // ignore errors } else if ((int *)varp == &p_title) { // when 'title' changed, may need to change the title; same for 'icon' - did_set_title(false); + did_set_title(); } else if ((int *)varp == &p_icon) { - did_set_title(true); + did_set_title(); } else if ((int *)varp == &curbuf->b_changed) { if (!value) { save_file_ff(curbuf); // Buffer is unchanged diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 047af8db75..a451451726 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -87,7 +87,7 @@ #include "nvim/highlight.h" #include "nvim/main.h" #include "nvim/mark.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/mbyte.h" #include "nvim/memline.h" #include "nvim/memory.h" @@ -2130,11 +2130,11 @@ fill_foldcolumn( if (closed) { if (symbol != 0) { - // rollback length + // rollback previous write char_counter -= len; + memset(&p[char_counter], ' ', len); } - symbol = wp->w_p_fcs_chars.foldclosed; - len = utf_char2bytes(symbol, &p[char_counter]); + len = utf_char2bytes(wp->w_p_fcs_chars.foldclosed, &p[char_counter]); char_counter += len; } diff --git a/src/nvim/undo.c b/src/nvim/undo.c index fda647106d..1f74bada41 100644 --- a/src/nvim/undo.c +++ b/src/nvim/undo.c @@ -93,7 +93,7 @@ #include "nvim/buffer_updates.h" #include "nvim/pos.h" // MAXLNUM #include "nvim/mark.h" -#include "nvim/mark_extended.h" +#include "nvim/extmark.h" #include "nvim/memline.h" #include "nvim/message.h" #include "nvim/misc1.h" diff --git a/src/nvim/undo_defs.h b/src/nvim/undo_defs.h index 0fa3b415ec..cc2c39a711 100644 --- a/src/nvim/undo_defs.h +++ b/src/nvim/undo_defs.h @@ -4,7 +4,7 @@ #include <time.h> // for time_t #include "nvim/pos.h" -#include "nvim/mark_extended_defs.h" +#include "nvim/extmark_defs.h" #include "nvim/mark_defs.h" typedef struct u_header u_header_T; diff --git a/test/functional/api/mark_extended_spec.lua b/test/functional/api/extmark_spec.lua index 8aa8ed07c5..5bf3fa554f 100644 --- a/test/functional/api/mark_extended_spec.lua +++ b/test/functional/api/extmark_spec.lua @@ -548,7 +548,6 @@ describe('API/extmarks', function() end) it('deleting marks at end of line works', function() - -- mark_extended.c/extmark_col_adjust_delete set_extmark(ns, marks[1], 0, 4) feed('$x') check_undo_redo(ns, marks[1], 0, 4, 0, 4) diff --git a/test/functional/autocmd/tabnewentered_spec.lua b/test/functional/autocmd/tabnewentered_spec.lua index 123dbd0824..dc2fd3e97d 100644 --- a/test/functional/autocmd/tabnewentered_spec.lua +++ b/test/functional/autocmd/tabnewentered_spec.lua @@ -97,6 +97,7 @@ describe('tabpage/previous', function() switches_to_previous_after_new_tab_creation_at_end('g<Tab>')) it('switches to previous via <C-W>g<Tab>. after new tab creation at end', switches_to_previous_after_new_tab_creation_at_end('<C-W>g<Tab>')) it('switches to previous via <C-Tab>. after new tab creation at end', switches_to_previous_after_new_tab_creation_at_end('<C-Tab>')) + it('switches to previous via :tabn #<CR>. after new tab creation at end', switches_to_previous_after_new_tab_creation_at_end(':tabn #<CR>')) local function switches_to_previous_after_new_tab_creation_in_middle(characters) return function() @@ -140,6 +141,8 @@ describe('tabpage/previous', function() switches_to_previous_after_new_tab_creation_in_middle('<C-W>g<Tab>')) it('switches to previous via <C-Tab> after new tab creation in middle', switches_to_previous_after_new_tab_creation_in_middle('<C-Tab>')) + it('switches to previous via :tabn #<CR> after new tab creation in middle', + switches_to_previous_after_new_tab_creation_in_middle(':tabn #<CR>')) local function switches_to_previous_after_switching_to_next_tab(characters) return function() @@ -180,6 +183,8 @@ describe('tabpage/previous', function() switches_to_previous_after_switching_to_next_tab('<C-W>g<Tab>')) it('switches to previous via <C-Tab> after switching to next tab', switches_to_previous_after_switching_to_next_tab('<C-Tab>')) + it('switches to previous via :tabn #<CR> after switching to next tab', + switches_to_previous_after_switching_to_next_tab(':tabn #<CR>')) local function switches_to_previous_after_switching_to_last_tab(characters) return function() @@ -222,6 +227,8 @@ describe('tabpage/previous', function() switches_to_previous_after_switching_to_last_tab('<C-W>g<Tab>')) it('switches to previous after switching to last tab', switches_to_previous_after_switching_to_last_tab('<C-Tab>')) + it('switches to previous after switching to last tab', + switches_to_previous_after_switching_to_last_tab(':tabn #<CR>')) local function switches_to_previous_after_switching_to_previous_tab(characters) return function() @@ -262,6 +269,8 @@ describe('tabpage/previous', function() switches_to_previous_after_switching_to_previous_tab('<C-W>g<Tab>')) it('switches to previous via <C-Tab> after switching to previous tab', switches_to_previous_after_switching_to_previous_tab('<C-Tab>')) + it('switches to previous via :tabn #<CR> after switching to previous tab', + switches_to_previous_after_switching_to_previous_tab(':tabn #<CR>')) local function switches_to_previous_after_switching_to_first_tab(characters) return function() @@ -304,6 +313,8 @@ describe('tabpage/previous', function() switches_to_previous_after_switching_to_first_tab('<C-W>g<Tab>')) it('switches to previous via <C-Tab> after switching to first tab', switches_to_previous_after_switching_to_first_tab('<C-Tab>')) + it('switches to previous via :tabn #<CR> after switching to first tab', + switches_to_previous_after_switching_to_first_tab(':tabn #<CR>')) local function switches_to_previous_after_numbered_tab_switch(characters) return function() @@ -344,6 +355,8 @@ describe('tabpage/previous', function() switches_to_previous_after_numbered_tab_switch('<C-W>g<Tab>')) it('switches to previous via <C-Tab> after numbered tab switch', switches_to_previous_after_numbered_tab_switch('<C-Tab>')) + it('switches to previous via :tabn #<CR> after numbered tab switch', + switches_to_previous_after_numbered_tab_switch(':tabn #<CR>')) local function switches_to_previous_after_switching_to_previous(characters1, characters2) return function() @@ -386,18 +399,32 @@ describe('tabpage/previous', function() switches_to_previous_after_switching_to_previous('g<Tab>', '<C-W>g<Tab>')) it('switches to previous via <C-Tab> after switching to previous via g<Tab>', switches_to_previous_after_switching_to_previous('g<Tab>', '<C-Tab>')) + it('switches to previous via :tabn #<CR> after switching to previous via g<Tab>', + switches_to_previous_after_switching_to_previous('g<Tab>', ':tabn #<CR>')) it('switches to previous via g<Tab> after switching to previous via <C-W>g<Tab>', switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', 'g<Tab>')) it('switches to previous via <C-W>g<Tab> after switching to previous via <C-W>g<Tab>', switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-W>g<Tab>')) it('switches to previous via <C-Tab> after switching to previous via <C-W>g<Tab>', switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', '<C-Tab>')) + it('switches to previous via :tabn #<CR> after switching to previous via <C-W>g<Tab>', + switches_to_previous_after_switching_to_previous('<C-W>g<Tab>', ':tabn #<CR>')) it('switches to previous via g<Tab> after switching to previous via <C-Tab>', switches_to_previous_after_switching_to_previous('<C-Tab>', 'g<Tab>')) it('switches to previous via <C-W>g<Tab> after switching to previous via <C-Tab>', switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-W>g<Tab>')) it('switches to previous via <C-Tab> after switching to previous via <C-Tab>', switches_to_previous_after_switching_to_previous('<C-Tab>', '<C-Tab>')) + it('switches to previous via :tabn #<CR> after switching to previous via <C-Tab>', + switches_to_previous_after_switching_to_previous('<C-Tab>', ':tabn #<CR>')) + it('switches to previous via g<Tab> after switching to previous via :tabn #<CR>', + switches_to_previous_after_switching_to_previous(':tabn #<CR>', 'g<Tab>')) + it('switches to previous via <C-W>g<Tab> after switching to previous via :tabn #<CR>', + switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-W>g<Tab>')) + it('switches to previous via <C-Tab> after switching to previous via <C-Tab>', + switches_to_previous_after_switching_to_previous(':tabn #<CR>', '<C-Tab>')) + it('switches to previous via :tabn #<CR> after switching to previous via :tabn #<CR>', + switches_to_previous_after_switching_to_previous(':tabn #<CR>', ':tabn #<CR>')) local function does_not_switch_to_previous_after_closing_current_tab(characters) return function() @@ -437,6 +464,8 @@ describe('tabpage/previous', function() does_not_switch_to_previous_after_closing_current_tab('<C-W>g<Tab>')) it('does not switch to previous via <C-Tab> after closing current tab', does_not_switch_to_previous_after_closing_current_tab('<C-Tab>')) + it('does not switch to previous via :tabn #<CR> after closing current tab', + does_not_switch_to_previous_after_closing_current_tab(':tabn #<CR>')) local function does_not_switch_to_previous_after_entering_operator_pending(characters) return function() @@ -480,6 +509,11 @@ describe('tabpage/previous', function() -- does_not_switch_to_previous_after_entering_operator_pending('<C-W>g<Tab>')) it('does not switch to previous via <C-Tab> after entering operator pending', does_not_switch_to_previous_after_entering_operator_pending('<C-Tab>')) + -- NOTE: When in operator pending mode, pressing : leaves operator pending + -- mode and enters command mode, so :tabn #<CR> does in fact switch + -- tabs. + -- it('does not switch to previous via :tabn #<CR> after entering operator pending', + -- does_not_switch_to_previous_after_entering_operator_pending(':tabn #<CR>')) local function cmdline_win_prevents_tab_switch(characters, completion_visible) return function() @@ -516,6 +550,8 @@ describe('tabpage/previous', function() cmdline_win_prevents_tab_switch('<C-W>g<Tab>', 1)) it('cmdline-win prevents tab switch via <C-Tab>', cmdline_win_prevents_tab_switch('<C-Tab>', 0)) + it('cmdline-win prevents tab switch via :tabn #<CR>', + cmdline_win_prevents_tab_switch(':tabn #<CR>', 0)) it(':tabs indicates correct prevtab curwin', function() -- Add three tabs for a total of four diff --git a/test/functional/helpers.lua b/test/functional/helpers.lua index de61ff9cc8..3ffc6137d6 100644 --- a/test/functional/helpers.lua +++ b/test/functional/helpers.lua @@ -768,7 +768,7 @@ function module.new_pipename() end function module.missing_provider(provider) - if provider == 'ruby' or provider == 'node' then + if provider == 'ruby' or provider == 'node' or provider == 'perl' then local prog = module.funcs['provider#' .. provider .. '#Detect']() return prog == '' and (provider .. ' not detected') or false elseif provider == 'python' or provider == 'python3' then diff --git a/test/functional/provider/perl_spec.lua b/test/functional/provider/perl_spec.lua new file mode 100644 index 0000000000..7b446e4ab3 --- /dev/null +++ b/test/functional/provider/perl_spec.lua @@ -0,0 +1,80 @@ +local helpers = require('test.functional.helpers')(after_each) +local eq, clear = helpers.eq, helpers.clear +local missing_provider = helpers.missing_provider +local command = helpers.command +local write_file = helpers.write_file +local eval = helpers.eval +local retry = helpers.retry + +do + clear() + local reason = missing_provider('perl') + if reason then + pending(string.format("Missing perl host, or perl version is too old (%s)", reason), function() end) + return + end +end + +before_each(function() + clear() +end) + +describe('perl host', function() + if helpers.pending_win32(pending) then return end + teardown(function () + os.remove('Xtest-perl-hello.pl') + os.remove('Xtest-perl-hello-plugin.pl') + end) + + it('works', function() + local fname = 'Xtest-perl-hello.pl' + write_file(fname, [[ + package main; + use strict; + use warnings; + use Neovim::Ext; + use Neovim::Ext::MsgPack::RPC; + + my $session = Neovim::Ext::MsgPack::RPC::socket_session($ENV{NVIM_LISTEN_ADDRESS}); + my $nvim = Neovim::Ext::from_session($session); + $nvim->command('let g:job_out = "hello"'); + 1; + ]]) + command('let g:job_id = jobstart(["perl", "'..fname..'"])') + retry(nil, 3000, function() eq('hello', eval('g:job_out')) end) + end) + + it('plugin works', function() + local fname = 'Xtest-perl-hello-plugin.pl' + write_file(fname, [[ + package TestPlugin; + use strict; + use warnings; + use parent qw(Neovim::Ext::Plugin); + + __PACKAGE__->register; + + @{TestPlugin::commands} = (); + @{TestPlugin::specs} = (); + sub test_command :nvim_command('TestCommand') + { + my ($this) = @_; + $this->nvim->command('let g:job_out = "hello-plugin"'); + } + + package main; + use strict; + use warnings; + use Neovim::Ext; + use Neovim::Ext::MsgPack::RPC; + + my $session = Neovim::Ext::MsgPack::RPC::socket_session($ENV{NVIM_LISTEN_ADDRESS}); + my $nvim = Neovim::Ext::from_session($session); + my $plugin = TestPlugin->new($nvim); + $plugin->test_command(); + 1; + ]]) + command('let g:job_id = jobstart(["perl", "'..fname..'"])') + retry(nil, 3000, function() eq('hello-plugin', eval('g:job_out')) end) + end) +end) diff --git a/test/functional/ui/popupmenu_spec.lua b/test/functional/ui/popupmenu_spec.lua index a0e5c3ca63..b2ebf7af19 100644 --- a/test/functional/ui/popupmenu_spec.lua +++ b/test/functional/ui/popupmenu_spec.lua @@ -640,7 +640,7 @@ describe('builtin popupmenu', function() }) end) - it('works with preview-window above', function() + it('with preview-window above', function() feed(':ped<CR><c-w>4+') feed('iaa bb cc dd ee ff gg hh ii jj<cr>') feed('<c-x><c-n>') @@ -668,7 +668,7 @@ describe('builtin popupmenu', function() ]]) end) - it('works with preview-window below', function() + it('with preview-window below', function() feed(':ped<CR><c-w>4+<c-w>r') feed('iaa bb cc dd ee ff gg hh ii jj<cr>') feed('<c-x><c-n>') @@ -696,7 +696,7 @@ describe('builtin popupmenu', function() ]]) end) - it('works with preview-window above and tall and inverted', function() + it('with preview-window above and tall and inverted', function() feed(':ped<CR><c-w>8+') feed('iaa<cr>bb<cr>cc<cr>dd<cr>ee<cr>') feed('ff<cr>gg<cr>hh<cr>ii<cr>jj<cr>') @@ -726,7 +726,7 @@ describe('builtin popupmenu', function() ]]) end) - it('works with preview-window above and short and inverted', function() + it('with preview-window above and short and inverted', function() feed(':ped<CR><c-w>4+') feed('iaa<cr>bb<cr>cc<cr>dd<cr>ee<cr>') feed('ff<cr>gg<cr>hh<cr>ii<cr>jj<cr>') @@ -755,7 +755,7 @@ describe('builtin popupmenu', function() ]]) end) - it('works with preview-window below and inverted', function() + it('with preview-window below and inverted', function() feed(':ped<CR><c-w>4+<c-w>r') feed('iaa<cr>bb<cr>cc<cr>dd<cr>ee<cr>') feed('ff<cr>gg<cr>hh<cr>ii<cr>jj<cr>') @@ -784,7 +784,7 @@ describe('builtin popupmenu', function() ]]) end) - it('works with vsplits', function() + it('with vsplits', function() insert('aaa aab aac\n') feed(':vsplit<cr>') screen:expect([[ @@ -859,7 +859,7 @@ describe('builtin popupmenu', function() ]]) end) - it('works with split and scroll', function() + it('with split and scroll', function() screen:try_resize(60,14) command("split") command("set completeopt+=noinsert") @@ -1293,7 +1293,7 @@ describe('builtin popupmenu', function() ]]) end) - it('behaves correcty with VimResized autocmd', function() + it('with VimResized autocmd', function() feed('isome long prefix before the ') command("set completeopt+=noinsert,noselect") command("autocmd VimResized * redraw!") @@ -1337,7 +1337,7 @@ describe('builtin popupmenu', function() ]]) end) - it('works with rightleft window', function() + it('with rightleft window', function() command("set rl") feed('isome rightleft ') screen:expect([[ @@ -1437,7 +1437,7 @@ describe('builtin popupmenu', function() ]]) end) - it('works with multiline messages', function() + it('with multiline messages', function() screen:try_resize(40,8) feed('ixx<cr>') command('imap <f2> <cmd>echoerr "very"\\|echoerr "much"\\|echoerr "error"<cr>') @@ -1514,7 +1514,7 @@ describe('builtin popupmenu', function() ]], unchanged=true} end) - it('works with kind, menu and abbr attributes', function() + it('with kind, menu and abbr attributes', function() screen:try_resize(40,8) feed('ixx ') funcs.complete(4, {{word='wordey', kind= 'x', menu='extrainfo'}, 'thing', {word='secret', abbr='sneaky', menu='bar'}}) @@ -1566,7 +1566,7 @@ describe('builtin popupmenu', function() ]]) end) - it('works with wildoptions=pum', function() + it('wildoptions=pum', function() screen:try_resize(32,10) command('set wildmenu') command('set wildoptions=pum') @@ -1738,7 +1738,7 @@ describe('builtin popupmenu', function() ]]) end) - it('works with wildoptions=pum with scrolled mesages ', function() + it('wildoptions=pum with scrolled mesages ', function() screen:try_resize(40,10) command('set wildmenu') command('set wildoptions=pum') @@ -1786,6 +1786,39 @@ describe('builtin popupmenu', function() ]]} end) + it('wildoptions=pum and wildmode=longest,full #11622', function() + screen:try_resize(30,8) + command('set wildmenu') + command('set wildoptions=pum') + command('set wildmode=longest,full') + + feed(':sign u<tab>') + screen:expect{grid=[[ + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + :sign un^ | + ]]} + eq(0, funcs.wildmenumode()) + + feed('<tab>') + screen:expect{grid=[[ + | + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }| + {1:~ }{s: undefine }{1: }| + {1:~ }{n: unplace }{1: }| + :sign undefine^ | + ]]} + eq(1, funcs.wildmenumode()) + end) + it("'pumblend' RGB-color", function() screen:try_resize(60,14) screen:set_default_attr_ids({ diff --git a/test/functional/ui/wildmode_spec.lua b/test/functional/ui/wildmode_spec.lua index f3fa711fb1..56987d7bc2 100644 --- a/test/functional/ui/wildmode_spec.lua +++ b/test/functional/ui/wildmode_spec.lua @@ -221,6 +221,106 @@ describe("'wildmenu'", function() ]]) end) + it('wildmode=longest,list', function() + -- Need more than 5 rows, else tabline is covered and will be redrawn. + screen:try_resize(25, 7) + + command('set wildmenu wildmode=longest,list') + + -- give wildmode-longest something to expand to + feed(':sign u<tab>') + screen:expect([[ + | + ~ | + ~ | + ~ | + ~ | + ~ | + :sign un^ | + ]]) + feed('<tab>') -- trigger wildmode list + screen:expect([[ + | + ~ | + ~ | + | + :sign un | + undefine unplace | + :sign un^ | + ]]) + feed('<Esc>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + ~ | + ~ | + | + ]]) + + -- give wildmode-longest something it cannot expand, use list + feed(':sign un<tab>') + screen:expect([[ + | + ~ | + ~ | + | + :sign un | + undefine unplace | + :sign un^ | + ]]) + feed('<tab>') + screen:expect_unchanged() + feed('<Esc>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + ~ | + ~ | + | + ]]) + end) + + it('wildmode=list,longest', function() + -- Need more than 5 rows, else tabline is covered and will be redrawn. + screen:try_resize(25, 7) + + command('set wildmenu wildmode=list,longest') + feed(':sign u<tab>') + screen:expect([[ + | + ~ | + ~ | + | + :sign u | + undefine unplace | + :sign u^ | + ]]) + feed('<tab>') -- trigger wildmode longest + screen:expect([[ + | + ~ | + ~ | + | + :sign u | + undefine unplace | + :sign un^ | + ]]) + feed('<Esc>') + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + ~ | + ~ | + | + ]]) + end) + it('multiple <C-D> renders correctly', function() screen:try_resize(25, 7) |