diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | runtime/doc/windows.txt | 59 | ||||
-rwxr-xr-x | scripts/vim-patch.sh | 123 | ||||
-rw-r--r-- | src/nvim/ex_cmds.lua | 34 | ||||
-rw-r--r-- | src/nvim/ex_cmds_defs.h | 2 | ||||
-rw-r--r-- | src/nvim/ex_docmd.c | 66 | ||||
-rw-r--r-- | src/nvim/getchar.c | 22 | ||||
-rw-r--r-- | src/nvim/globals.h | 3 | ||||
-rw-r--r-- | src/nvim/misc1.c | 15 | ||||
-rw-r--r-- | src/nvim/os/shell.c | 1 | ||||
-rw-r--r-- | src/nvim/version.c | 10 | ||||
-rw-r--r-- | test/functional/legacy/mapping_spec.lua | 26 |
12 files changed, 239 insertions, 125 deletions
diff --git a/.gitignore b/.gitignore index 5332ef5c76..3ad1a352eb 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,9 @@ /src/nvim/po/vim.pot /src/nvim/po/*.ck +# Files generated by scripts/vim-patch.sh +/.vim-src/ + # Files generated by the tests /src/nvim/testdir/mbyte.vim /src/nvim/testdir/mzscheme.vim diff --git a/runtime/doc/windows.txt b/runtime/doc/windows.txt index 4ba28a3c08..00fe956dd4 100644 --- a/runtime/doc/windows.txt +++ b/runtime/doc/windows.txt @@ -1042,36 +1042,41 @@ list of buffers. |unlisted-buffer| a number). Insert a backslash before a space in a buffer name. -:[N]b[uffer][!] [N] *:b* *:bu* *:buf* *:buffer* *E86* +:[N]b[uffer][!] [+cmd] [N] *:b* *:bu* *:buf* *:buffer* *E86* Edit buffer [N] from the buffer list. If [N] is not given, the current buffer remains being edited. See |:buffer-!| for [!]. This will also edit a buffer that is not in the buffer list, without setting the 'buflisted' flag. + Also see ||+cmd|. -:[N]b[uffer][!] {bufname} +:[N]b[uffer][!] [+cmd] {bufname} Edit buffer for {bufname} from the buffer list. See |:buffer-!| for [!]. This will also edit a buffer that is not in the buffer list, without setting the 'buflisted' flag. + Also see ||+cmd|. -:[N]sb[uffer] [N] *:sb* *:sbuffer* +:[N]sb[uffer] [+cmd] [N] *:sb* *:sbuffer* Split window and edit buffer [N] from the buffer list. If [N] is not given, the current buffer is edited. Respects the "useopen" setting of 'switchbuf' when splitting. This will also edit a buffer that is not in the buffer list, without setting the 'buflisted' flag. + Also see ||+cmd|. -:[N]sb[uffer] {bufname} +:[N]sb[uffer] [+cmd] {bufname} Split window and edit buffer for {bufname} from the buffer list. This will also edit a buffer that is not in the buffer list, without setting the 'buflisted' flag. Note: If what you want to do is split the buffer, make a copy under another name, you can do it this way: > :w foobar | sp # +< Also see ||+cmd|. -:[N]bn[ext][!] [N] *:bn* *:bnext* *E87* +:[N]bn[ext][!] [+cmd] [N] *:bn* *:bnext* *E87* Go to [N]th next buffer in buffer list. [N] defaults to one. Wraps around the end of the buffer list. See |:buffer-!| for [!]. + Also see ||+cmd|. If you are in a help buffer, this takes you to the next help buffer (if there is one). Similarly, if you are in a normal (non-help) buffer, this takes you to the next normal buffer. @@ -1079,55 +1084,61 @@ list of buffers. |unlisted-buffer| the way when you're browsing code/text buffers. The next three commands also work like this. + *:sbn* *:sbnext* -:[N]sbn[ext] [N] +:[N]sbn[ext] [+cmd] [N] Split window and go to [N]th next buffer in buffer list. Wraps around the end of the buffer list. Uses 'switchbuf' + Also see ||+cmd|. -:[N]bN[ext][!] [N] *:bN* *:bNext* *:bp* *:bprevious* *E88* -:[N]bp[revious][!] [N] +:[N]bN[ext][!] [+cmd] [N] *:bN* *:bNext* *:bp* *:bprevious* *E88* +:[N]bp[revious][!] [+cmd] [N] Go to [N]th previous buffer in buffer list. [N] defaults to one. Wraps around the start of the buffer list. See |:buffer-!| for [!] and 'switchbuf'. + Also see ||+cmd|. -:[N]sbN[ext] [N] *:sbN* *:sbNext* *:sbp* *:sbprevious* -:[N]sbp[revious] [N] +:[N]sbN[ext] [+cmd] [N] *:sbN* *:sbNext* *:sbp* *:sbprevious* +:[N]sbp[revious] [+cmd] [N] Split window and go to [N]th previous buffer in buffer list. Wraps around the start of the buffer list. Uses 'switchbuf'. + Also see ||+cmd|. - *:br* *:brewind* -:br[ewind][!] Go to first buffer in buffer list. If the buffer list is +:br[ewind][!] [+cmd] *:br* *:brewind* + Go to first buffer in buffer list. If the buffer list is empty, go to the first unlisted buffer. See |:buffer-!| for [!]. - *:bf* *:bfirst* -:bf[irst] Same as ":brewind". +:bf[irst] [+cmd] *:bf* *:bfirst* + Same as |:brewind|. + Also see |+cmd|. - *:sbr* *:sbrewind* -:sbr[ewind] Split window and go to first buffer in buffer list. If the +:sbr[ewind] [+cmd] *:sbr* *:sbrewind* + Split window and go to first buffer in buffer list. If the buffer list is empty, go to the first unlisted buffer. Respects the 'switchbuf' option. + Also see |+cmd|. - *:sbf* *:sbfirst* -:sbf[irst] Same as ":sbrewind". +:sbf[irst] [+cmd] *:sbf* *:sbfirst* + Same as ":sbrewind". - *:bl* *:blast* -:bl[ast][!] Go to last buffer in buffer list. If the buffer list is +:bl[ast][!] [+cmd] *:bl* *:blast* + Go to last buffer in buffer list. If the buffer list is empty, go to the last unlisted buffer. See |:buffer-!| for [!]. - *:sbl* *:sblast* -:sbl[ast] Split window and go to last buffer in buffer list. If the +:sbl[ast] [+cmd] *:sbl* *:sblast* + Split window and go to last buffer in buffer list. If the buffer list is empty, go to the last unlisted buffer. Respects 'switchbuf' option. -:[N]bm[odified][!] [N] *:bm* *:bmodified* *E84* +:[N]bm[odified][!] [+cmd] [N] *:bm* *:bmodified* *E84* Go to [N]th next modified buffer. Note: this command also finds unlisted buffers. If there is no modified buffer the command fails. -:[N]sbm[odified] [N] *:sbm* *:sbmodified* +:[N]sbm[odified] [+cmd] [N] *:sbm* *:sbmodified* Split window and go to [N]th next modified buffer. Respects 'switchbuf' option. Note: this command also finds buffers not in the buffer list. diff --git a/scripts/vim-patch.sh b/scripts/vim-patch.sh index 6e098dd5eb..f6b4793184 100755 --- a/scripts/vim-patch.sh +++ b/scripts/vim-patch.sh @@ -1,27 +1,26 @@ -#!/bin/bash -e +#!/usr/bin/env bash + +set -e +set -o pipefail NEOVIM_SOURCE_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" -VIM_SOURCE_DIR_DEFAULT=${NEOVIM_SOURCE_DIR}/build/vim +VIM_SOURCE_DIR_DEFAULT=${NEOVIM_SOURCE_DIR}/.vim-src VIM_SOURCE_DIR="${VIM_SOURCE_DIR:-${VIM_SOURCE_DIR_DEFAULT}}" if [[ ${#} != 1 ]]; then >&2 echo "Helper script for porting Vim patches. For more information," >&2 echo "see https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim." >&2 echo - >&2 echo "Usage: ${0} vim-version" - >&2 echo "vim-version must be in format '7.4.xxx'." + >&2 echo "Usage: ${0} vim-revision" + >&2 echo "vim-revision can be a version number in format '7.4.xxx'" + >&2 echo "or a Mercurial commit hash." >&2 echo >&2 echo "Set VIM_SOURCE_DIR to change where Vim's sources are stored." >&2 echo "The default is '${VIM_SOURCE_DIR_DEFAULT}'." exit 1 fi -vim_version="${1}" -if [[ ! ${vim_version} =~ [0-9]\.[0-9]\.[0-9][0-9][0-9] ]]; then - >&2 echo "vim-version must be in format '7.4.xxx'." - exit 2 -fi - +echo "Retrieving Vim sources." if [[ ! -d ${VIM_SOURCE_DIR} ]]; then echo "Cloning Vim sources into '${VIM_SOURCE_DIR}'." hg clone https://code.google.com/p/vim ${VIM_SOURCE_DIR} @@ -29,53 +28,93 @@ if [[ ! -d ${VIM_SOURCE_DIR} ]]; then else echo "Updating Vim sources in '${VIM_SOURCE_DIR}'." cd ${VIM_SOURCE_DIR} - hg pull --update || echo 'Could not update Vim sources.' + hg pull --update || echo "✘ Could not update Vim sources." fi -vim_tag="v${vim_version//./-}" -echo "Using Vim tag '${vim_tag}'." +if [[ "${1}" =~ [0-9]\.[0-9]\.[0-9]{3,4} ]]; then + # Interpret parameter as version number. + vim_version="${1}" + vim_commit="v${1//./-}" + strip_commit_line=true +else + # Interpret parameter as commit hash. + vim_version="${1:0:7}" + vim_commit="${1}" + strip_commit_line=false +fi -hg log --rev ${vim_tag} >/dev/null 2>&1 || { - >&2 echo "Couldn't find Vim tag '${vim_tag}'." +hg log --rev ${vim_commit} >/dev/null 2>&1 || { + >&2 echo "✘ Couldn't find Vim revision '${vim_commit}'." exit 3 } - -vim_full="$(hg log --patch --git --verbose --rev ${vim_tag})" -vim_message="$(hg log --template "{desc}" --rev ${vim_tag} \ - | sed -e '1d')" # Remove first line of commit message. -vim_diff="$(hg diff --show-function --git --change ${vim_tag} \ +echo "✔ Found Vim revision '${vim_commit}'." + +# Collect patch details and store into variables. +vim_full="$(hg log --patch --git --verbose --rev ${vim_commit})" +vim_message="$(hg log --template "{desc}" --rev ${vim_commit})" +if [[ "${strip_commit_line}" == "true" ]]; then + # Remove first line of commit message. + vim_message="$(echo "${vim_message}" | sed -e '1d')" +fi +vim_diff="$(hg diff --show-function --git --change ${vim_commit} \ | sed -e 's/\( [ab]\/src\)/\1\/nvim/g')" # Change directory to src/nvim. +neovim_message=" +vim-patch:${vim_version} + +${vim_message} + +https://code.google.com/p/vim/source/detail?r=${vim_commit}" +neovim_pr=" +\`\`\` +${vim_message} +\`\`\` +https://code.google.com/p/vim/source/detail?r=${vim_commit} +Original patch: + +\`\`\`diff +${vim_diff} +\`\`\`" neovim_branch="vim-${vim_version}" + echo -echo "Creating Neovim branch '${neovim_branch}'." +echo "Creating Git branch." cd ${NEOVIM_SOURCE_DIR} -git checkout -b "${neovim_branch}" +echo -n "✘ " +# 'git checkout -b' writes to stderr in case of success :-( +# Re-add newline (stripped by echo -n) in error case. +git checkout -b "${neovim_branch}" 2>&1 | xargs echo -n || (echo; false) +echo -n "." # Add trailing dot. +echo -e "\r✔ " # Replace ✘ with ✔ echo -echo "Saving patch to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch'." -echo "${vim_diff}" > ${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch - -echo "Saving full commit details to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.commit'." -echo "${vim_full}" > ${NEOVIM_SOURCE_DIR}/${neovim_branch}.commit +echo "Creating empty commit with correct commit message." +echo -n "✘ " +git commit --allow-empty --file - <<< "${neovim_message}" | xargs echo -n +echo -e "\r✔ " # Replace ✘ with ✔ echo -echo "Creating empty Neovim commit with correct commit message." -neovim_message=" -vim-patch:${vim_version} - -${vim_message} - -https://code.google.com/p/vim/source/detail?r=${vim_tag}" - -git commit --allow-empty --file - <<< "${neovim_message}" +echo "Creating files." +echo "${vim_diff}" > ${NEOVIM_SOURCE_DIR}/${neovim_branch}.diff +echo "✔ Saved patch to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.diff'." +echo "${vim_full}" > ${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch +echo "✔ Saved full commit details to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.patch'." +echo "${neovim_pr}" > ${NEOVIM_SOURCE_DIR}/${neovim_branch}.pr +echo "✔ Saved suggested PR description to '${NEOVIM_SOURCE_DIR}/${neovim_branch}.pr'." +echo "You can use 'git clean' to remove these files when you're done." echo -echo "Proceed to port the patch and stage your changes ('git add ...')." -echo "Then use 'git commit --amend' to commit." -echo "Push your changes with 'git push origin ${neovim_branch}' and create a" -echo "pull request called '[RFC] vim-patch:${vim_version}'." +echo "Instructions:" +echo +echo " Proceed to port the patch." +echo " You might want to try 'patch -p1 < ${neovim_branch}.diff' first." +echo +echo " Stage your changes ('git add ...') and use 'git commit --amend' to commit." +echo +echo " Push your changes with 'git push origin ${neovim_branch}' and create a" +echo " pull request called '[RFC] vim-patch:${vim_version}'. You might want " +echo " to use the text in '${neovim_branch}.pr' as the description of this pull request." echo -echo "See https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim" -echo "for more information." +echo " See https://github.com/neovim/neovim/wiki/Merging-patches-from-upstream-vim" +echo " for more information." diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index d5d6d39616..c9dd974d11 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -127,12 +127,12 @@ return { }, { command='buffer', - flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, TRLBAR), + flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, EDITCMD, TRLBAR), func='ex_buffer', }, { command='bNext', - flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR), + flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR), func='ex_bprevious', }, { @@ -162,22 +162,22 @@ return { }, { command='bfirst', - flags=bit.bor(BANG, RANGE, NOTADR, TRLBAR), + flags=bit.bor(BANG, RANGE, NOTADR, EDITCMD, TRLBAR), func='ex_brewind', }, { command='blast', - flags=bit.bor(BANG, RANGE, NOTADR, TRLBAR), + flags=bit.bor(BANG, RANGE, NOTADR, EDITCMD, TRLBAR), func='ex_blast', }, { command='bmodified', - flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR), + flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR), func='ex_bmodified', }, { command='bnext', - flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR), + flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR), func='ex_bnext', }, { @@ -187,12 +187,12 @@ return { }, { command='bprevious', - flags=bit.bor(BANG, RANGE, NOTADR, COUNT, TRLBAR), + flags=bit.bor(BANG, RANGE, NOTADR, COUNT, EDITCMD, TRLBAR), func='ex_bprevious', }, { command='brewind', - flags=bit.bor(BANG, RANGE, NOTADR, TRLBAR), + flags=bit.bor(BANG, RANGE, NOTADR, EDITCMD, TRLBAR), func='ex_brewind', }, { @@ -1762,47 +1762,47 @@ return { }, { command='sbuffer', - flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, TRLBAR), + flags=bit.bor(BANG, RANGE, NOTADR, BUFNAME, BUFUNL, COUNT, EXTRA, EDITCMD, TRLBAR), func='ex_buffer', }, { command='sbNext', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), + flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR), func='ex_bprevious', }, { command='sball', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), + flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR), func='ex_buffer_all', }, { command='sbfirst', - flags=bit.bor(TRLBAR), + flags=bit.bor(EDITCMD, TRLBAR), func='ex_brewind', }, { command='sblast', - flags=bit.bor(TRLBAR), + flags=bit.bor(EDITCMD, TRLBAR), func='ex_blast', }, { command='sbmodified', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), + flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR), func='ex_bmodified', }, { command='sbnext', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), + flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR), func='ex_bnext', }, { command='sbprevious', - flags=bit.bor(RANGE, NOTADR, COUNT, TRLBAR), + flags=bit.bor(RANGE, NOTADR, COUNT, EDITCMD, TRLBAR), func='ex_bprevious', }, { command='sbrewind', - flags=bit.bor(TRLBAR), + flags=bit.bor(EDITCMD, TRLBAR), func='ex_brewind', }, { diff --git a/src/nvim/ex_cmds_defs.h b/src/nvim/ex_cmds_defs.h index abf7cc4587..0e13574321 100644 --- a/src/nvim/ex_cmds_defs.h +++ b/src/nvim/ex_cmds_defs.h @@ -88,8 +88,6 @@ typedef struct cmdname { long_u cmd_argt; ///< Relevant flags from the declared above. } CommandDefinition; -#define USER_CMDIDX(idx) ((int)(idx) < 0) - /// Arguments used for Ex commands. struct exarg { char_u *arg; ///< argument of the command diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index e4a8c2735b..359c4b31d1 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -92,6 +92,9 @@ static garray_T ucmds = {0, 0, sizeof(ucmd_T), 4, NULL}; #define USER_CMD(i) (&((ucmd_T *)(ucmds.ga_data))[i]) #define USER_CMD_GA(gap, i) (&((ucmd_T *)((gap)->ga_data))[i]) +/* Wether a command index indicates a user command. */ +# define IS_USER_CMDIDX(idx) ((int)(idx) < 0) + /* Struct for storing a line inside a while/for loop */ typedef struct { char_u *line; /* command line */ @@ -1489,11 +1492,10 @@ static char_u * do_one_cmd(char_u **cmdlinep, goto doend; } - ni = ( - !USER_CMDIDX(ea.cmdidx) && - (cmdnames[ea.cmdidx].cmd_func == ex_ni + ni = (!IS_USER_CMDIDX(ea.cmdidx) + && (cmdnames[ea.cmdidx].cmd_func == ex_ni #ifdef HAVE_EX_SCRIPT_NI - || cmdnames[ea.cmdidx].cmd_func == ex_script_ni + || cmdnames[ea.cmdidx].cmd_func == ex_script_ni #endif )); @@ -1509,8 +1511,9 @@ static char_u * do_one_cmd(char_u **cmdlinep, /* * 5. parse arguments */ - if (!USER_CMDIDX(ea.cmdidx)) + if (!IS_USER_CMDIDX(ea.cmdidx)) { ea.argt = (long)cmdnames[(int)ea.cmdidx].cmd_argt; + } if (!ea.skip) { #ifdef HAVE_SANDBOX @@ -1527,8 +1530,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, } if (text_locked() && !(ea.argt & CMDWIN) - && !USER_CMDIDX(ea.cmdidx) - ) { + && !IS_USER_CMDIDX(ea.cmdidx)) { /* Command not allowed when editing the command line. */ if (cmdwin_type != 0) errormsg = (char_u *)_(e_cmdwin); @@ -1542,7 +1544,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, if (!(ea.argt & CMDWIN) && ea.cmdidx != CMD_edit && ea.cmdidx != CMD_checktime - && !USER_CMDIDX(ea.cmdidx) + && !IS_USER_CMDIDX(ea.cmdidx) && curbuf_locked()) goto doend; @@ -1708,17 +1710,15 @@ static char_u * do_one_cmd(char_u **cmdlinep, if ( (ea.argt & REGSTR) && *ea.arg != NUL /* Do not allow register = for user commands */ - && (!USER_CMDIDX(ea.cmdidx) || *ea.arg != '=') + && (!IS_USER_CMDIDX(ea.cmdidx) || *ea.arg != '=') && !((ea.argt & COUNT) && VIM_ISDIGIT(*ea.arg))) { /* check these explicitly for a more specific error message */ if (*ea.arg == '*' || *ea.arg == '+') { errormsg = (char_u *)_(e_invalidreg); goto doend; } - if ( - valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put - && USER_CMDIDX(ea.cmdidx))) - ) { + if (valid_yank_reg(*ea.arg, (ea.cmdidx != CMD_put + && !IS_USER_CMDIDX(ea.cmdidx)))) { ea.regname = *ea.arg++; /* for '=' register: accept the rest of the line as an expression */ if (ea.arg[-1] == '=' && ea.arg[0] != NUL) { @@ -1868,7 +1868,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, * number. Don't do this for a user command. */ if ((ea.argt & BUFNAME) && *ea.arg != NUL && ea.addr_count == 0 - && !USER_CMDIDX(ea.cmdidx) + && !IS_USER_CMDIDX(ea.cmdidx) ) { /* * :bdelete, :bwipeout and :bunload take several arguments, separated @@ -1901,7 +1901,7 @@ static char_u * do_one_cmd(char_u **cmdlinep, ea.cookie = cookie; ea.cstack = cstack; - if (USER_CMDIDX(ea.cmdidx)) { + if (IS_USER_CMDIDX(ea.cmdidx)) { /* * Execute a user-defined command. */ @@ -1949,9 +1949,9 @@ doend: emsg(errormsg); } do_errthrow(cstack, - (ea.cmdidx != CMD_SIZE - && !USER_CMDIDX(ea.cmdidx) - ) ? cmdnames[(int)ea.cmdidx].cmd_name : (char_u *)NULL); + (ea.cmdidx != CMD_SIZE && !IS_USER_CMDIDX(ea.cmdidx)) + ? cmdnames[(int)ea.cmdidx].cmd_name + : (char_u *)NULL); if (verbose_save >= 0) p_verbose = verbose_save; @@ -2464,8 +2464,9 @@ set_one_cmd_context ( /* * 5. parse arguments */ - if (!USER_CMDIDX(ea.cmdidx)) + if (!IS_USER_CMDIDX(ea.cmdidx)) { ea.argt = (long)cmdnames[(int)ea.cmdidx].cmd_argt; + } arg = skipwhite(p); @@ -3958,13 +3959,17 @@ static void ex_bunload(exarg_T *eap) */ static void ex_buffer(exarg_T *eap) { - if (*eap->arg) + if (*eap->arg) { eap->errmsg = e_trailing; - else { - if (eap->addr_count == 0) /* default is current buffer */ + } else { + if (eap->addr_count == 0) { // default is current buffer goto_buffer(eap, DOBUF_CURRENT, FORWARD, 0); - else + } else { goto_buffer(eap, DOBUF_FIRST, FORWARD, (int)eap->line2); + } + if (eap->do_ecmd_cmd != NULL) { + do_cmdline_cmd(eap->do_ecmd_cmd); + } } } @@ -3975,6 +3980,9 @@ static void ex_buffer(exarg_T *eap) static void ex_bmodified(exarg_T *eap) { goto_buffer(eap, DOBUF_MOD, FORWARD, (int)eap->line2); + if (eap->do_ecmd_cmd != NULL) { + do_cmdline_cmd(eap->do_ecmd_cmd); + } } /* @@ -3984,6 +3992,9 @@ static void ex_bmodified(exarg_T *eap) static void ex_bnext(exarg_T *eap) { goto_buffer(eap, DOBUF_CURRENT, FORWARD, (int)eap->line2); + if (eap->do_ecmd_cmd != NULL) { + do_cmdline_cmd(eap->do_ecmd_cmd); + } } /* @@ -3995,6 +4006,9 @@ static void ex_bnext(exarg_T *eap) static void ex_bprevious(exarg_T *eap) { goto_buffer(eap, DOBUF_CURRENT, BACKWARD, (int)eap->line2); + if (eap->do_ecmd_cmd != NULL) { + do_cmdline_cmd(eap->do_ecmd_cmd); + } } /* @@ -4006,6 +4020,9 @@ static void ex_bprevious(exarg_T *eap) static void ex_brewind(exarg_T *eap) { goto_buffer(eap, DOBUF_FIRST, FORWARD, 0); + if (eap->do_ecmd_cmd != NULL) { + do_cmdline_cmd(eap->do_ecmd_cmd); + } } /* @@ -4015,6 +4032,9 @@ static void ex_brewind(exarg_T *eap) static void ex_blast(exarg_T *eap) { goto_buffer(eap, DOBUF_LAST, BACKWARD, 0); + if (eap->do_ecmd_cmd != NULL) { + do_cmdline_cmd(eap->do_ecmd_cmd); + } } int ends_excmd(int c) FUNC_ATTR_CONST diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 882d30388c..d0eebf8fea 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -15,6 +15,7 @@ * mappings and abbreviations */ +#include <assert.h> #include <stdbool.h> #include <string.h> #include <inttypes.h> @@ -3637,11 +3638,26 @@ int check_abbr(int c, char_u *ptr, int col, int mincol) for (; mp; mp->m_next == NULL ? (mp = mp2, mp2 = NULL) : (mp = mp->m_next)) { + int qlen = mp->m_keylen; + char_u *q = mp->m_keys; + int match; + + if (vim_strbyte(mp->m_keys, K_SPECIAL) != NULL) { + /* might have CSI escaped mp->m_keys */ + q = vim_strsave(mp->m_keys); + vim_unescape_csi(q); + qlen = (int)STRLEN(q); + } /* find entries with right mode and keys */ - if ( (mp->m_mode & State) - && mp->m_keylen == len - && !STRNCMP(mp->m_keys, ptr, (size_t)len)) + match = (mp->m_mode & State) + && qlen == len + && !STRNCMP(q, ptr, (size_t)len); + if (q != mp->m_keys) { + free(q); + } + if (match) { break; + } } if (mp != NULL) { /* diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 5f542eec0c..f53a780efe 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -606,9 +606,6 @@ EXTERN int exiting INIT(= FALSE); /* TRUE when planning to exit Vim. Might * still keep on running if there is a changed * buffer. */ -EXTERN int really_exiting INIT(= FALSE); -/* TRUE when we are sure to exit, e.g., after - * a deadly signal */ /* volatile because it is used in signal handler deathtrap(). */ EXTERN volatile int full_screen INIT(= FALSE); /* TRUE when doing full-screen output diff --git a/src/nvim/misc1.c b/src/nvim/misc1.c index fc848466c6..4f17f84e11 100644 --- a/src/nvim/misc1.c +++ b/src/nvim/misc1.c @@ -3329,32 +3329,35 @@ void prepare_to_exit(void) */ void preserve_exit(void) { + // 'true' when we are sure to exit, e.g., after a deadly signal + static bool really_exiting = false; + // Prevent repeated calls into this method. if (really_exiting) { exit(2); } - really_exiting = TRUE; + really_exiting = true; prepare_to_exit(); out_str(IObuff); - screen_start(); /* don't know where cursor is now */ + screen_start(); // don't know where cursor is now out_flush(); - ml_close_notmod(); /* close all not-modified buffers */ + ml_close_notmod(); // close all not-modified buffers FOR_ALL_BUFFERS(buf) { if (buf->b_ml.ml_mfp != NULL && buf->b_ml.ml_mfp->mf_fname != NULL) { OUT_STR("Vim: preserving files...\n"); - screen_start(); /* don't know where cursor is now */ + screen_start(); // don't know where cursor is now out_flush(); - ml_sync_all(FALSE, FALSE); /* preserve all swap files */ + ml_sync_all(false, false); // preserve all swap files break; } } - ml_close_all(FALSE); /* close all memfiles, without deleting */ + ml_close_all(false); // close all memfiles, without deleting OUT_STR("Vim: Finished.\n"); diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index c450e24284..d0f8442768 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -268,6 +268,7 @@ static int shell(const char *cmd, static void dynamic_buffer_ensure(DynamicBuffer *buf, size_t desired) { if (buf->cap >= desired) { + assert(buf->data); return; } diff --git a/src/nvim/version.c b/src/nvim/version.c index 6bbb5e6024..8e32dc54ef 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -250,12 +250,12 @@ static int included_patches[] = { 491, //490, 489, - //488, + 488, //487, - //486, - //485, + 486, + 485, //484 NA - //483, + 483, //482 NA //481 NA //480 NA @@ -287,7 +287,7 @@ static int included_patches[] = { //453 NA 452, //451, - //450, + 450, 449, //448 NA 447, diff --git a/test/functional/legacy/mapping_spec.lua b/test/functional/legacy/mapping_spec.lua new file mode 100644 index 0000000000..46d29d1692 --- /dev/null +++ b/test/functional/legacy/mapping_spec.lua @@ -0,0 +1,26 @@ +-- Test for mappings and abbreviations + +local helpers = require('test.functional.helpers') +local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert +local execute, expect = helpers.execute, helpers.expect + +describe('mapping', function() + setup(clear) + + it('is working', function() + insert([[ + test starts here: + ]]) + + execute('set encoding=utf-8') + + -- Abbreviations with р (0x80) should work. + execute('inoreab чкпр vim') + feed('GAчкпр <cr><esc>') + + -- Assert buffer contents. + expect([[ + test starts here: + vim]]) + end) +end) |