aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore3
-rw-r--r--runtime/doc/windows.txt59
-rwxr-xr-xscripts/vim-patch.sh123
-rw-r--r--src/nvim/ex_cmds.lua34
-rw-r--r--src/nvim/ex_cmds_defs.h2
-rw-r--r--src/nvim/ex_docmd.c66
-rw-r--r--src/nvim/getchar.c22
-rw-r--r--src/nvim/globals.h3
-rw-r--r--src/nvim/misc1.c15
-rw-r--r--src/nvim/os/shell.c1
-rw-r--r--src/nvim/version.c10
-rw-r--r--test/functional/legacy/mapping_spec.lua26
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)