diff options
| -rw-r--r-- | runtime/doc/api.txt | 105 | ||||
| -rw-r--r-- | runtime/doc/deprecated.txt | 8 | ||||
| -rw-r--r-- | runtime/doc/gui.txt | 15 | ||||
| -rw-r--r-- | runtime/doc/map.txt | 25 | ||||
| -rw-r--r-- | runtime/doc/options.txt | 18 | ||||
| -rw-r--r-- | runtime/doc/tips.txt | 10 | ||||
| -rw-r--r-- | runtime/doc/vim_diff.txt | 2 | ||||
| -rw-r--r-- | runtime/doc/visual.txt | 6 | ||||
| -rw-r--r-- | src/nvim/api/vim.c | 12 | ||||
| -rw-r--r-- | src/nvim/eval.c | 2 | ||||
| -rw-r--r-- | src/nvim/ex_docmd.c | 2 | ||||
| -rw-r--r-- | src/nvim/getchar.c | 24 | ||||
| -rw-r--r-- | src/nvim/keymap.c | 17 | ||||
| -rw-r--r-- | src/nvim/keymap.h | 10 | ||||
| -rw-r--r-- | src/nvim/menu.c | 5 | ||||
| -rw-r--r-- | src/nvim/option.c | 2 | ||||
| -rw-r--r-- | src/nvim/option_defs.h | 70 | ||||
| -rw-r--r-- | test/functional/api/keymap_spec.lua | 18 | ||||
| -rw-r--r-- | test/functional/api/vim_spec.lua | 13 | 
19 files changed, 204 insertions, 160 deletions
| diff --git a/runtime/doc/api.txt b/runtime/doc/api.txt index ebc2a40561..7c6b8a3c1a 100644 --- a/runtime/doc/api.txt +++ b/runtime/doc/api.txt @@ -165,7 +165,16 @@ nvim_input({keys})                                              *nvim_input()*                                                      *nvim_replace_termcodes()*  nvim_replace_termcodes({str}, {from_part}, {do_lt}, {special}) -                Replaces any terminal codes with the internal representation +                Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a +                string with the internal representation. + +                Parameters:~ +                    {str}        String to be converted. +                    {from_part}  Legacy Vim parameter. Usually true. +                    {do_lt}      Also translate <lt>. Does nothing if +                                 `special` is false. +                    {special}    Replace |keycodes|, e.g. <CR> becomes a "\n" +                                 char.  nvim_command_output({str})                             *nvim_command_output()*                  TODO: Documentation @@ -182,8 +191,10 @@ nvim_eval({expr})                                                *nvim_eval()*                      Evaluation result or expanded object  nvim_call_function({fname}, {args})                     *nvim_call_function()* -                Calls a VimL function with the given arguments. On VimL error: -                Returns a generic error; v:errmsg is not updated. +                Calls a VimL function with the given arguments + +                On VimL error: Returns a generic error; v:errmsg is not +                updated.                  Parameters:~                      {fname}  Function to call @@ -192,6 +203,23 @@ nvim_call_function({fname}, {args})                     *nvim_call_function()*                  Return:~                      Result of the function call +nvim_execute_lua({code}, {args})                          *nvim_execute_lua()* +                Execute lua code. Parameters might be passed, they are +                available inside the chunk as `...`. The chunk can return a +                value. + +                To evaluate an expression, it must be prefixed with "return ". +                For instance, to call a lua function with arguments sent in +                and get its return value back, use the code "return +                my_function(...)". + +                Parameters:~ +                    {code}  lua code to execute +                    {args}  Arguments to the code + +                Return:~ +                    Return value of lua code if present or NIL. +  nvim_strwidth({str})                                         *nvim_strwidth()*                  Calculates the number of display cells occupied by `text`.                  <Tab> counts as one cell. @@ -382,6 +410,17 @@ nvim_get_mode()                                              *nvim_get_mode()*                  Return:~                      Dictionary { "mode": String, "blocking": Boolean } +nvim_get_keymap({mode})                                    *nvim_get_keymap()* +                Get a list of dictionaries describing global (i.e. non-buffer) +                mappings Note that the "buffer" key will be 0 to represent +                false. + +                Parameters:~ +                    {mode}  The abbreviation for the mode + +                Return:~ +                    An array of maparg() like dictionaries describing mappings +  nvim_get_api_info()                                      *nvim_get_api_info()*                  TODO: Documentation @@ -414,6 +453,54 @@ nvim_call_atomic({calls})                                 *nvim_call_atomic()*                      error ocurred, the values from all preceding calls will                      still be returned. +nvim__id({obj})                                                   *nvim__id()* +                Returns object given as argument + +                This API function is used for testing. One should not rely on +                its presence in plugins. + +                Parameters:~ +                    {obj}  Object to return. + +                Return:~ +                    its argument. + +nvim__id_array({arr})                                       *nvim__id_array()* +                Returns array given as argument + +                This API function is used for testing. One should not rely on +                its presence in plugins. + +                Parameters:~ +                    {arr}  Array to return. + +                Return:~ +                    its argument. + +nvim__id_dictionary({dct})                             *nvim__id_dictionary()* +                Returns dictionary given as argument + +                This API function is used for testing. One should not rely on +                its presence in plugins. + +                Parameters:~ +                    {dct}  Dictionary to return. + +                Return:~ +                    its argument. + +nvim__id_float({flt})                                       *nvim__id_float()* +                Returns floating-point value given as argument + +                This API function is used for testing. One should not rely on +                its presence in plugins. + +                Parameters:~ +                    {flt}  Value to return. + +                Return:~ +                    its argument. +  ==============================================================================  Buffer Functions                                                  *api-buffer* @@ -492,6 +579,18 @@ nvim_buf_get_changedtick({buffer})                *nvim_buf_get_changedtick()*                  Return:~                      b:changedtickvalue. +nvim_buf_get_keymap({buffer}, {mode})                  *nvim_buf_get_keymap()* +                Get a list of dictionaries describing buffer-local mappings +                Note that the buffer key in the dictionary will represent the +                buffer handle where the mapping is present + +                Parameters:~ +                    {mode}       The abbreviation for the mode +                    {buffer_id}  Buffer handle + +                Return:~ +                    An array of maparg() like dictionaries describing mappings +  nvim_buf_set_var({buffer}, {name}, {value})               *nvim_buf_set_var()*                  Sets a buffer-scoped (b:) variable diff --git a/runtime/doc/deprecated.txt b/runtime/doc/deprecated.txt index 26cd5b24cc..b3e2f7a92f 100644 --- a/runtime/doc/deprecated.txt +++ b/runtime/doc/deprecated.txt @@ -39,10 +39,16 @@ Functions ~  *highlightID()*		Obsolete name for |hlID()|.  *last_buffer_nr()*	Obsolete name for bufnr("$"). +Modifiers ~ +*:menu-<special>* +*:menu-special*		<> notation is always enabled. |cpo-<| +*:map-<special>* +*:map-special*		<> notation is always enabled. |cpo-<| +  Options ~  *'fe'*			'fenc'+'enc' before Vim 6.0; no longer used.  *'langnoremap'*		Deprecated alias to 'nolangremap'.  *'vi'*  *'viminfo'*		Deprecated alias to 'shada' option. - vim:tw=78:ts=8:ft=help:norl: + vim:noet:tw=78:ts=8:ft=help:norl: diff --git a/runtime/doc/gui.txt b/runtime/doc/gui.txt index 0bd3a40a7c..b66a60c860 100644 --- a/runtime/doc/gui.txt +++ b/runtime/doc/gui.txt @@ -490,9 +490,6 @@ expression register: >     :amenu Insert.foobar   "='foobar'<CR>P -Note that the '<' and 'k' flags in 'cpoptions' also apply here (when -included they make the <> form and raw key codes not being recognized). -  Note that <Esc> in Cmdline mode executes the command, like in a mapping.  This  is Vi compatible.  Use CTRL-C to quit Cmdline mode. @@ -504,21 +501,13 @@ The ":set ic" will not be echoed when using this menu.  Messages from the  executed command are still given though.  To shut them up too, add a ":silent"  in the executed command: >  	:menu <silent> Search.Header :exe ":silent normal /Header\r"<CR> -"<silent>" may also appear just after "<special>" or "<script>". - -					*:menu-<special>* *:menu-special* -Define a menu with <> notation for special keys, even though the "<" flag -may appear in 'cpoptions'.  This is useful if the side effect of setting -'cpoptions' is not desired.  Example: > -	:menu <special> Search.Header /Header<CR> -"<special>" must appear as the very first argument to the ":menu" command or -just after "<silent>" or "<script>". +"<silent>" may also appear just after "<script>".  						*:menu-<script>* *:menu-script*  The "to" part of the menu will be inspected for mappings.  If you don't want  this, use the ":noremenu" command (or the similar one for a specific mode).  If you do want to use script-local mappings, add "<script>" as the very first -argument to the ":menu" command or just after "<silent>" or "<special>". +argument to the ":menu" command or just after "<silent>".  							*menu-priority*  You can give a priority to a menu.  Menus with a higher priority go more to diff --git a/runtime/doc/map.txt b/runtime/doc/map.txt index f5b0233e6c..bfcf621cb8 100644 --- a/runtime/doc/map.txt +++ b/runtime/doc/map.txt @@ -149,7 +149,7 @@ type "a", then "bar" will get inserted.  1.2 SPECIAL ARGUMENTS					*:map-arguments* -"<buffer>", "<nowait>", "<silent>", "<special>", "<script>", "<expr>" and +"<buffer>", "<nowait>", "<silent>", "<script>", "<expr>" and  "<unique>" can be used in any order.  They must appear right after the  command, before any other arguments. @@ -189,12 +189,6 @@ Prompts will still be given, e.g., for inputdialog().  Using "<silent>" for an abbreviation is possible, but will cause redrawing of  the command line to fail. -						*:map-<special>* *:map-special* -Define a mapping with <> notation for special keys, even though the "<" flag -may appear in 'cpoptions'.  This is useful if the side effect of setting -'cpoptions' is not desired.  Example: > -	:map <special> <F12> /Header<CR> -<  						*:map-<script>* *:map-script*  If the first argument to one of these commands is "<script>" and it is used to  define a new mapping or abbreviation, the mapping will only remap characters @@ -444,16 +438,14 @@ There are two ways to map a special key:     starts with <Esc>.  To enter a mapping like this you type ":map " and then     you have to type CTRL-V before hitting the function key.  Note that when     the key code for the key is in the |terminfo| entry, it will automatically -   be translated into the internal code and become the second way of mapping -   (unless the 'k' flag is included in 'cpoptions'). +   be translated into the internal code and become the second way of mapping.  2. The second method is to use the internal code for the function key.  To     enter such a mapping type CTRL-K and then hit the function key, or use     the form "#1", "#2", .. "#9", "#0", "<Up>", "<S-Down>", "<S-F7>", etc.     (see table of keys |key-notation|, all keys from <Up> can be used).  The     first ten function keys can be defined in two ways: Just the number, like     "#2", and with "<F>", like "<F2>".  Both stand for function key 2.  "#0" -   refers to function key 10.  The <> form cannot be used when 'cpoptions' -   includes the '<' flag. +   refers to function key 10.  DETAIL: Vim first checks if a sequence from the keyboard is mapped.  If it  isn't the terminal key codes are tried.  If a terminal code is found it is @@ -571,9 +563,9 @@ Since the '|' character is used to separate a map command from the next  command, you will have to do something special to include  a '|' in {rhs}.  There are three methods:     use	     works when			   example	~ -   <Bar>     '<' is not in 'cpoptions'	   :map _l :!ls <Bar> more^M +   <Bar>     always			   :map _l :!ls <Bar> more^M     \|	     'b' is not in 'cpoptions'	   :map _l :!ls \| more^M -   ^V|	     always, in Vim and Vi	   :map _l :!ls ^V| more^M +   ^V|	     always			   :map _l :!ls ^V| more^M  (here ^V stands for CTRL-V; to get one CTRL-V you have to type it twice; you  cannot use the <> notation "<C-V>" here). @@ -628,8 +620,7 @@ out about, ^D is CTRL-D).  1.8 EXAMPLES						*map-examples* -A few examples (given as you type them, for "<CR>" you type four characters; -the '<' flag must not be present in 'cpoptions' for this to work). > +A few examples (as you type them: for "<CR>" you type four characters). >     :map <F3>  o#include     :map <M-g> /foo<CR>cwbar<Esc> @@ -881,7 +872,6 @@ character is mostly ignored otherwise.  It is possible to move the cursor after an abbreviation: >     :iab if if ()<Left> -This does not work if 'cpoptions' includes the '<' flag. |<>|  You can even do more complicated things.  For example, to consume the space  typed after an abbreviation: > @@ -1029,8 +1019,7 @@ functions used in one script use the same name as in other scripts.  To avoid  this, they can be made local to the script.  						*<SID>* *<SNR>* *E81* -The string "<SID>" can be used in a mapping or menu.  This requires that the -'<' flag is not present in 'cpoptions'. +The string "<SID>" can be used in a mapping or menu.     When executing the map command, Vim will replace "<SID>" with the special  key code <SNR>, followed by a number that's unique for the script, and an  underscore.  Example: > diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index ca126f5a79..dc968cd666 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -1568,7 +1568,6 @@ A jump table for the options with a short description can be found at |Q_op|.  			results in X being mapped to:  				'B' included:	"\^["	 (^[ is a real <Esc>)  				'B' excluded:	"<Esc>"  (5 characters) -				('<' excluded in both cases)  								*cpo-c*  		c	Searching continues at the end of any match at the  			cursor position, but not further than the start of the @@ -1618,15 +1617,6 @@ A jump table for the options with a short description can be found at |Q_op|.  		J	A |sentence| has to be followed by two spaces after  			the '.', '!' or '?'.  A <Tab> is not recognized as  			white space. -								*cpo-k* -		k	Disable the recognition of raw key codes in -			mappings, abbreviations, and the "to" part of menu -			commands.  For example, if <Key> sends ^[OA (where ^[ -			is <Esc>), the command ":map X ^[OA" results in X -			being mapped to: -				'k' included:	"^[OA"	 (3 characters) -				'k' excluded:	"<Key>"  (one key code) -			Also see the '<' flag below.  								*cpo-K*  		K	Don't wait for a key code to complete when it is  			halfway through a mapping.  This breaks mapping @@ -1760,14 +1750,6 @@ A jump table for the options with a short description can be found at |Q_op|.  		+	When included, a ":write file" command will reset the  			'modified' flag of the buffer, even though the buffer  			itself may still be different from its file. -								*cpo-<* -		<	Disable the recognition of special key codes in |<>| -			form in mappings, abbreviations, and the "to" part of -			menu commands.  For example, the command -			":map X <Tab>" results in X being mapped to: -				'<' included:	"<Tab>"  (5 characters) -				'<' excluded:	"^I"	 (^I is a real <Tab>) -			Also see the 'k' flag above.  								*cpo->*  		>	When appending to a register, put a line break before  			the appended text. diff --git a/runtime/doc/tips.txt b/runtime/doc/tips.txt index 9b34cd7599..0ac9a8303d 100644 --- a/runtime/doc/tips.txt +++ b/runtime/doc/tips.txt @@ -113,7 +113,6 @@ screen, you can use CTRL-X CTRL-E and CTRL-X CTRL-Y to scroll the screen.  To make this easier, you could use these mappings: >  	:inoremap <C-E> <C-X><C-E>  	:inoremap <C-Y> <C-X><C-Y> -(Type this literally, make sure the '<' flag is not in 'cpoptions').  You then lose the ability to copy text from the line above/below the cursor  |i_CTRL-E|. @@ -129,8 +128,6 @@ If you like the scrolling to go a bit smoother, you can use these mappings: >  	:map <C-U> <C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y><C-Y>  	:map <C-D> <C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E><C-E> -(Type this literally, make sure the '<' flag is not in 'cpoptions'). -  ==============================================================================  Correcting common typing mistakes			*type-mistakes* @@ -282,9 +279,7 @@ For Emacs-style editing on the command-line: >  	:cnoremap <Esc><C-B>	<S-Left>  	" forward one word  	:cnoremap <Esc><C-F>	<S-Right> - -NOTE: This requires that the '<' flag is excluded from 'cpoptions'. |<>| - +<  							*format-bullet-list*  This mapping will format any bullet list.  It requires that there is an empty  line above and below each list entry.  The expression commands are used to @@ -300,8 +295,7 @@ be able to give comments to the parts of the mapping. >  	:execute m			      |" define the mapping  (<> notation |<>|.  Note that this is all typed literally.  ^W is "^" "W", not -CTRL-W.  You can copy/paste this into Vim if '<' is not included in -'cpoptions'.) +CTRL-W.)  Note that the last comment starts with |", because the ":execute" command  doesn't accept a comment directly. diff --git a/runtime/doc/vim_diff.txt b/runtime/doc/vim_diff.txt index ca07e613ed..d906b874f0 100644 --- a/runtime/doc/vim_diff.txt +++ b/runtime/doc/vim_diff.txt @@ -332,7 +332,7 @@ Test functions:  Other options:    'antialias' -  'cpoptions' ("g", "w", "H", "*", "-", "j", and all POSIX flags were removed) +  'cpoptions' (g j k H w < * - and all POSIX flags were removed)    'encoding' ("utf-8" is always used)    'esckeys'    'guioptions' "t" flag was removed diff --git a/runtime/doc/visual.txt b/runtime/doc/visual.txt index e9f5bf91f8..cf804444e5 100644 --- a/runtime/doc/visual.txt +++ b/runtime/doc/visual.txt @@ -271,7 +271,7 @@ mode.  For example, if you would like the "/" command not to extend the Visual  area, but instead take the highlighted text and search for that: >  	:vmap / y/<C-R>"<CR>  (In the <> notation |<>|, when typing it you should type it literally; you -need to remove the 'B' and '<' flags from 'cpoptions'.) +need to remove the 'B' flag from 'cpoptions'.)  If you want to give a register name using the """ command, do this just before  typing the operator character: "v{move-around}"xd". @@ -375,7 +375,7 @@ Here is an example, to replace the selected text with the output of "date": >  	:vmap _a <Esc>`>a<CR><Esc>`<i<CR><Esc>!!date<CR>kJJ  (In the <> notation |<>|, when typing it you should type it literally; you -need to remove the 'B' and '<' flags from 'cpoptions') +need to remove the 'B' flag from 'cpoptions')  What this does is:  <Esc>		stop Visual mode @@ -392,7 +392,7 @@ selected text: >  	:vmap X y/<C-R>"<CR>  (In the <> notation |<>|, when typing it you should type it literally; you -need to remove the 'B' and '<' flags from 'cpoptions') +need to remove the 'B' flag from 'cpoptions')  Note that special characters (like '.' and '*') will cause problems. diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 80efe86ea3..2bc31b2812 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -136,9 +136,13 @@ Integer nvim_input(String keys)    return (Integer)input_enqueue(keys);  } -/// Replaces terminal codes and key codes (<CR>, <Esc>, ...) in a string with +/// Replaces terminal codes and |keycodes| (<CR>, <Esc>, ...) in a string with  /// the internal representation.  /// +/// @param str        String to be converted. +/// @param from_part  Legacy Vim parameter. Usually true. +/// @param do_lt      Also translate <lt>. Ignored if `special` is false. +/// @param special    Replace |keycodes|, e.g. <CR> becomes a "\n" char.  /// @see replace_termcodes  /// @see cpoptions  String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt, @@ -151,12 +155,6 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,    }    char *ptr = NULL; -  // Set 'cpoptions' the way we want it. -  //    FLAG_CPO_BSLASH  set - backslashes are *not* treated specially -  //    FLAG_CPO_KEYCODE set - keycodes are *not* reverse-engineered -  //    FLAG_CPO_SPECI unset - <Key> sequences *are* interpreted -  //  The third from end parameter of replace_termcodes() is true so that the -  //  <lt> sequence is recognised - needed for a real backslash.    replace_termcodes((char_u *)str.data, str.size, (char_u **)&ptr,                      from_part, do_lt, special, CPO_TO_CPO_FLAGS);    return cstr_as_string(ptr); diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 662270e788..7e9c006f33 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -12111,7 +12111,7 @@ static void get_maparg(typval_T *argvars, typval_T *rettv, int exact)    mode = get_map_mode((char_u **)&which, 0); -  keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, false, +  keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, true,                             CPO_TO_CPO_FLAGS);    rhs = check_map(keys, mode, exact, false, abbr, &mp, &buffer_local);    xfree(keys_buf); diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index af8845de87..5d7246581c 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -4747,7 +4747,7 @@ static int uc_add_command(char_u *name, size_t name_len, char_u *rep,    char_u      *rep_buf = NULL;    garray_T    *gap; -  replace_termcodes(rep, STRLEN(rep), &rep_buf, false, false, false, +  replace_termcodes(rep, STRLEN(rep), &rep_buf, false, false, true,                      CPO_TO_CPO_FLAGS);    if (rep_buf == NULL) {      /* Can't replace termcodes - try using the string as is */ diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index fc1b8ccfcb..a22b716bb6 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -2537,7 +2537,6 @@ do_map (    bool unique = false;    bool nowait = false;    bool silent = false; -  bool special = false;    bool expr = false;    int noremap;    char_u      *orig_rhs; @@ -2583,12 +2582,9 @@ do_map (        continue;      } -    /* -     * Check for "<special>": accept special keys in <> -     */ +    // Ignore obsolete "<special>" modifier.      if (STRNCMP(keys, "<special>", 9) == 0) {        keys = skipwhite(keys + 9); -      special = true;        continue;      } @@ -2657,7 +2653,7 @@ do_map (    // needs to be freed later (*keys_buf and *arg_buf).    // replace_termcodes() also removes CTRL-Vs and sometimes backslashes.    if (haskey) { -    keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, special, +    keys = replace_termcodes(keys, STRLEN(keys), &keys_buf, true, true, true,                               CPO_TO_CPO_FLAGS);    }    orig_rhs = rhs; @@ -2665,7 +2661,7 @@ do_map (      if (STRICMP(rhs, "<nop>") == 0) {  // "<Nop>" means nothing        rhs = (char_u *)"";      } else { -      rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, false, true, special, +      rhs = replace_termcodes(rhs, STRLEN(rhs), &arg_buf, false, true, true,                                CPO_TO_CPO_FLAGS);      }    } @@ -3245,7 +3241,7 @@ bool map_to_exists(const char *const str, const char *const modechars,    char_u *buf;    char_u *const rhs = replace_termcodes((const char_u *)str, strlen(str), &buf, -                                        false, true, false, +                                        false, true, true,                                          CPO_TO_CPO_FLAGS);  #define MAPMODE(mode, modechars, chr, modeflags) \ @@ -4158,8 +4154,7 @@ void add_map(char_u *map, int mode)  }  // Translate an internal mapping/abbreviation representation into the -// corresponding external one recognized by :map/:abbrev commands; -// respects the current B/k/< settings of 'cpoption'. +// corresponding external one recognized by :map/:abbrev commands.  //  // This function is called when expanding mappings/abbreviations on the  // command-line, and for building the "Ambiguous mapping..." error message. @@ -4179,7 +4174,6 @@ static char_u * translate_mapping (    ga_init(&ga, 1, 40);    bool cpo_bslash = !(cpo_flags&FLAG_CPO_BSLASH); -  bool cpo_special = !(cpo_flags&FLAG_CPO_SPECI);    for (; *str; ++str) {      int c = *str; @@ -4192,7 +4186,7 @@ static char_u * translate_mapping (        }        if (c == K_SPECIAL && str[1] != NUL && str[2] != NUL) { -        if (expmap && cpo_special) { +        if (expmap) {            ga_clear(&ga);            return NULL;          } @@ -4203,8 +4197,8 @@ static char_u * translate_mapping (          }          str += 2;        } -      if (IS_SPECIAL(c) || modifiers) {         /* special key */ -        if (expmap && cpo_special) { +      if (IS_SPECIAL(c) || modifiers) {         // special key +        if (expmap) {            ga_clear(&ga);            return NULL;          } @@ -4214,7 +4208,7 @@ static char_u * translate_mapping (      }      if (c == ' ' || c == '\t' || c == Ctrl_J || c == Ctrl_V -        || (c == '<' && !cpo_special) || (c == '\\' && !cpo_bslash)) { +        || (c == '\\' && !cpo_bslash)) {        ga_append(&ga, cpo_bslash ? Ctrl_V : '\\');      } diff --git a/src/nvim/keymap.c b/src/nvim/keymap.c index ee67b4c19d..3d7ebb6382 100644 --- a/src/nvim/keymap.c +++ b/src/nvim/keymap.c @@ -756,9 +756,9 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag)  /// Replace any terminal code strings with the equivalent internal  /// representation  /// -/// This is used for the "from" and "to" part of a mapping, and the "to" part of +/// Used for the "from" and "to" part of a mapping, and the "to" part of  /// a menu command. Any strings like "<C-UP>" are also replaced, unless -/// 'cpoptions' contains '<'. K_SPECIAL by itself is replaced by K_SPECIAL +/// `special` is false. K_SPECIAL by itself is replaced by K_SPECIAL  /// KS_SPECIAL KE_FILLER.  ///  /// @param[in]  from  What characters to replace. @@ -771,7 +771,7 @@ int get_mouse_button(int code, bool *is_click, bool *is_drag)  ///                        When cpo_flags contains #FLAG_CPO_BSLASH, a backslash  ///                        can be used in place of <C-v>. All other <C-v>  ///                        characters are removed. -/// @param[in]  special  If true, always accept <key> notation. +/// @param[in]  special    Replace keycodes, e.g. <CR> becomes a "\n" char.  /// @param[in]  cpo_flags  Relevant flags derived from p_cpo, see  ///                        #CPO_TO_CPO_FLAGS.  /// @@ -790,11 +790,9 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len,    const char_u *src;    const char_u *const end = from + from_len - 1;    int do_backslash;             // backslash is a special character -  int do_special;               // recognize <> key codes    char_u      *result;          // buffer for resulting string    do_backslash = !(cpo_flags&FLAG_CPO_BSLASH); -  do_special = !(cpo_flags&FLAG_CPO_SPECI) || special;    // Allocate space for the translation.  Worst case a single character is    // replaced by 6 bytes (shifted special key), plus a NUL at the end. @@ -817,10 +815,9 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len,    // Copy each byte from *from to result[dlen]    while (src <= end) { -    // If 'cpoptions' does not contain '<', check for special key codes, -    // like "<C-S-LeftMouse>" -    if (do_special && (do_lt || ((end - src) >= 3 -                                 && STRNCMP(src, "<lt>", 4) != 0))) { +    // Check for special <> keycodes, like "<C-S-LeftMouse>" +    if (special && (do_lt || ((end - src) >= 3 +                              && STRNCMP(src, "<lt>", 4) != 0))) {        // Replace <SID> by K_SNR <script-nr> _.        // (room: 5 * 6 = 30 bytes; needed: 3 + <nr> + 1 <= 14)        if (end - src >= 4 && STRNICMP(src, "<SID>", 5) == 0) { @@ -846,7 +843,7 @@ char_u *replace_termcodes(const char_u *from, const size_t from_len,        }      } -    if (do_special) { +    if (special) {        char_u  *p, *s, len;        // Replace <Leader> by the value of "mapleader". diff --git a/src/nvim/keymap.h b/src/nvim/keymap.h index bb8ba84a6a..b8fed77a90 100644 --- a/src/nvim/keymap.h +++ b/src/nvim/keymap.h @@ -464,13 +464,9 @@ enum key_extra {  #define MAX_KEY_CODE_LEN    6  #define FLAG_CPO_BSLASH    0x01 -#define FLAG_CPO_SPECI     0x02 -#define CPO_TO_CPO_FLAGS   (((vim_strchr(p_cpo, CPO_BSLASH) == NULL) \ -                             ? 0 \ -                             : FLAG_CPO_BSLASH)| \ -                            (vim_strchr(p_cpo, CPO_SPECI) == NULL \ -                             ? 0 \ -                             : FLAG_CPO_SPECI)) +#define CPO_TO_CPO_FLAGS   ((vim_strchr(p_cpo, CPO_BSLASH) == NULL) \ +                            ? 0 \ +                            : FLAG_CPO_BSLASH)  #ifdef INCLUDE_GENERATED_DECLARATIONS  # include "keymap.h.generated.h" diff --git a/src/nvim/menu.c b/src/nvim/menu.c index 7e9e9e9e5c..c8e6012e5c 100644 --- a/src/nvim/menu.c +++ b/src/nvim/menu.c @@ -60,7 +60,6 @@ ex_menu (    char_u      *map_to;    int noremap;    bool silent = false; -  bool special = false;    int unmenu;    char_u      *map_buf;    char_u      *arg; @@ -86,7 +85,7 @@ ex_menu (        continue;      }      if (STRNCMP(arg, "<special>", 9) == 0) { -      special = true; +      // Ignore obsolete "<special>" modifier.        arg = skipwhite(arg + 9);        continue;      } @@ -222,7 +221,7 @@ ex_menu (        map_buf = NULL;  // Menu tips are plain text.      } else {        map_to = replace_termcodes(map_to, STRLEN(map_to), &map_buf, false, true, -                                 special, CPO_TO_CPO_FLAGS); +                                 true, CPO_TO_CPO_FLAGS);      }      menuarg.modes = modes;      menuarg.noremap[0] = noremap; diff --git a/src/nvim/option.c b/src/nvim/option.c index ed058c420d..37b37e2859 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3034,7 +3034,7 @@ did_set_string_option (    /* 'pastetoggle': translate key codes like in a mapping */    else if (varp == &p_pt) {      if (*p_pt) { -      (void)replace_termcodes(p_pt, STRLEN(p_pt), &p, true, true, false, +      (void)replace_termcodes(p_pt, STRLEN(p_pt), &p, true, true, true,                                CPO_TO_CPO_FLAGS);        if (p != NULL) {          if (new_value_alloced) diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index e68dba734e..a2fe90b3c2 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -81,58 +81,56 @@  #define DFLT_FO_VIM     "tcqj"  #define FO_ALL          "tcroq2vlb1mMBn,awj"    /* for do_set() */ -/* characters for the p_cpo option: */ -#define CPO_ALTREAD     'a'     /* ":read" sets alternate file name */ -#define CPO_ALTWRITE    'A'     /* ":write" sets alternate file name */ -#define CPO_BAR         'b'     /* "\|" ends a mapping */ -#define CPO_BSLASH      'B'     /* backslash in mapping is not special */ +// characters for the p_cpo option: +#define CPO_ALTREAD     'a'     // ":read" sets alternate file name +#define CPO_ALTWRITE    'A'     // ":write" sets alternate file name +#define CPO_BAR         'b'     // "\|" ends a mapping +#define CPO_BSLASH      'B'     // backslash in mapping is not special  #define CPO_SEARCH      'c' -#define CPO_CONCAT      'C'     /* Don't concatenate sourced lines */ -#define CPO_DOTTAG      'd'     /* "./tags" in 'tags' is in current dir */ -#define CPO_DIGRAPH     'D'     /* No digraph after "r", "f", etc. */ +#define CPO_CONCAT      'C'     // Don't concatenate sourced lines +#define CPO_DOTTAG      'd'     // "./tags" in 'tags' is in current dir +#define CPO_DIGRAPH     'D'     // No digraph after "r", "f", etc.  #define CPO_EXECBUF     'e' -#define CPO_EMPTYREGION 'E'     /* operating on empty region is an error */ -#define CPO_FNAMER      'f'     /* set file name for ":r file" */ -#define CPO_FNAMEW      'F'     /* set file name for ":w file" */ -#define CPO_INTMOD      'i'     /* interrupt a read makes buffer modified */ -#define CPO_INDENT      'I'     /* remove auto-indent more often */ -#define CPO_ENDOFSENT   'J'     /* need two spaces to detect end of sentence */ -#define CPO_KEYCODE     'k'     /* don't recognize raw key code in mappings */ -#define CPO_KOFFSET     'K'     /* don't wait for key code in mappings */ -#define CPO_LITERAL     'l'     /* take char after backslash in [] literal */ -#define CPO_LISTWM      'L'     /* 'list' changes wrapmargin */ +#define CPO_EMPTYREGION 'E'     // operating on empty region is an error +#define CPO_FNAMER      'f'     // set file name for ":r file" +#define CPO_FNAMEW      'F'     // set file name for ":w file" +#define CPO_INTMOD      'i'     // interrupt a read makes buffer modified +#define CPO_INDENT      'I'     // remove auto-indent more often +#define CPO_ENDOFSENT   'J'     // need two spaces to detect end of sentence +#define CPO_KOFFSET     'K'     // don't wait for key code in mappings +#define CPO_LITERAL     'l'     // take char after backslash in [] literal +#define CPO_LISTWM      'L'     // 'list' changes wrapmargin  #define CPO_SHOWMATCH   'm' -#define CPO_MATCHBSL    'M'     /* "%" ignores use of backslashes */ -#define CPO_NUMCOL      'n'     /* 'number' column also used for text */ +#define CPO_MATCHBSL    'M'     // "%" ignores use of backslashes +#define CPO_NUMCOL      'n'     // 'number' column also used for text  #define CPO_LINEOFF     'o' -#define CPO_OVERNEW     'O'     /* silently overwrite new file */ -#define CPO_LISP        'p'     /* 'lisp' indenting */ -#define CPO_FNAMEAPP    'P'     /* set file name for ":w >>file" */ -#define CPO_JOINCOL     'q'     /* with "3J" use column after first join */ +#define CPO_OVERNEW     'O'     // silently overwrite new file +#define CPO_LISP        'p'     // 'lisp' indenting +#define CPO_FNAMEAPP    'P'     // set file name for ":w >>file" +#define CPO_JOINCOL     'q'     // with "3J" use column after first join  #define CPO_REDO        'r' -#define CPO_REMMARK     'R'     /* remove marks when filtering */ +#define CPO_REMMARK     'R'     // remove marks when filtering  #define CPO_BUFOPT      's'  #define CPO_BUFOPTGLOB  'S'  #define CPO_TAGPAT      't' -#define CPO_UNDO        'u'     /* "u" undoes itself */ -#define CPO_BACKSPACE   'v'     /* "v" keep deleted text */ -#define CPO_FWRITE      'W'     /* "w!" doesn't overwrite readonly files */ +#define CPO_UNDO        'u'     // "u" undoes itself +#define CPO_BACKSPACE   'v'     // "v" keep deleted text +#define CPO_FWRITE      'W'     // "w!" doesn't overwrite readonly files  #define CPO_ESC         'x' -#define CPO_REPLCNT     'X'     /* "R" with a count only deletes chars once */ +#define CPO_REPLCNT     'X'     // "R" with a count only deletes chars once  #define CPO_YANK        'y' -#define CPO_KEEPRO      'Z'     /* don't reset 'readonly' on ":w!" */ +#define CPO_KEEPRO      'Z'     // don't reset 'readonly' on ":w!"  #define CPO_DOLLAR      '$'  #define CPO_FILTER      '!'  #define CPO_MATCH       '%' -#define CPO_PLUS        '+'     /* ":write file" resets 'modified' */ -#define CPO_SPECI       '<'     /* don't recognize <> in mappings */ -#define CPO_REGAPPEND   '>'     /* insert NL when appending to a register */ -#define CPO_SCOLON      ';'     /* using "," and ";" will skip over char if -                                 * cursor would not move */ +#define CPO_PLUS        '+'     // ":write file" resets 'modified' +#define CPO_REGAPPEND   '>'     // insert NL when appending to a register +#define CPO_SCOLON      ';'     // using "," and ";" will skip over char if +                                // cursor would not move  #define CPO_CHANGEW     '_'     // "cw" special-case  // default values for Vim and Vi  #define CPO_VIM         "aABceFs_" -#define CPO_VI          "aAbBcCdDeEfFiIJkKlLmMnoOpPqrRsStuvWxXyZ$!%+<>;_" +#define CPO_VI          "aAbBcCdDeEfFiIJKlLmMnoOpPqrRsStuvWxXyZ$!%+>;_"  /* characters for p_ww option: */  #define WW_ALL          "bshl<>[],~" diff --git a/test/functional/api/keymap_spec.lua b/test/functional/api/keymap_spec.lua index aa556b563d..3a10f9c60f 100644 --- a/test/functional/api/keymap_spec.lua +++ b/test/functional/api/keymap_spec.lua @@ -256,40 +256,38 @@ describe('get_keymap', function()        return ret      end -    command('set cpo-=< cpo+=B') +    command('set cpo+=B')      command('nnoremap \\<C-a><C-a><LT>C-a>\\  \\<C-b><C-b><LT>C-b>\\')      command('nnoremap <special> \\<C-c><C-c><LT>C-c>\\  \\<C-d><C-d><LT>C-d>\\') -    command('set cpo+=B<') +    command('set cpo+=B')      command('xnoremap \\<C-a><C-a><LT>C-a>\\  \\<C-b><C-b><LT>C-b>\\')      command('xnoremap <special> \\<C-c><C-c><LT>C-c>\\  \\<C-d><C-d><LT>C-d>\\') -    command('set cpo-=B<') +    command('set cpo-=B')      command('snoremap \\<C-a><C-a><LT>C-a>\\  \\<C-b><C-b><LT>C-b>\\')      command('snoremap <special> \\<C-c><C-c><LT>C-c>\\  \\<C-d><C-d><LT>C-d>\\') -    command('set cpo-=B cpo+=<') +    command('set cpo-=B')      command('onoremap \\<C-a><C-a><LT>C-a>\\  \\<C-b><C-b><LT>C-b>\\')      command('onoremap <special> \\<C-c><C-c><LT>C-c>\\  \\<C-d><C-d><LT>C-d>\\')      for _, cmd in ipairs({ -      'set cpo-=B cpo+=<', -      'set cpo-=B<', -      'set cpo+=B<', -      'set cpo-=< cpo+=B', +      'set cpo-=B', +      'set cpo+=B',      }) do        command(cmd)        eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'n'),            cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'n')},           meths.get_keymap('n'))        eq({cpomap('\\<C-C><C-C><lt>C-c>\\', '\\<C-D><C-D><lt>C-d>\\', 'x'), -          cpomap('\\<lt>C-a><lt>C-a><lt>LT>C-a>\\', '\\<lt>C-b><lt>C-b><lt>LT>C-b>\\', 'x')}, +          cpomap('\\<C-A><C-A><lt>C-a>\\', '\\<C-B><C-B><lt>C-b>\\', 'x')},           meths.get_keymap('x'))        eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 's'),            cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 's')},           meths.get_keymap('s'))        eq({cpomap('<lt>C-c><C-C><lt>C-c> ', '<lt>C-d><C-D><lt>C-d>', 'o'), -          cpomap('<lt>C-a><lt>C-a><lt>LT>C-a> ', '<lt>C-b><lt>C-b><lt>LT>C-b>', 'o')}, +          cpomap('<lt>C-a><C-A><lt>C-a> ', '<lt>C-b><C-B><lt>C-b>', 'o')},           meths.get_keymap('o'))      end    end) diff --git a/test/functional/api/vim_spec.lua b/test/functional/api/vim_spec.lua index c531d4af46..e59b5d712d 100644 --- a/test/functional/api/vim_spec.lua +++ b/test/functional/api/vim_spec.lua @@ -373,6 +373,11 @@ describe('api', function()           '<NL>x<Esc>x<CR>x<lt>x', true, true, true))      end) +    it('does not convert keycodes if special=false', function() +      eq('<NL>x<Esc>x<CR>x<lt>x', helpers.nvim('replace_termcodes', +         '<NL>x<Esc>x<CR>x<lt>x', true, true, false)) +    end) +      it('does not crash when transforming an empty string', function()        -- Actually does not test anything, because current code will use NULL for        -- an empty string. @@ -391,13 +396,13 @@ describe('api', function()          -- notice the special char(…) \xe2\80\xa6          nvim('feedkeys', ':let x1="…"\n', '', true) -        -- Both replace_termcodes and feedkeys escape \x80 +        -- Both nvim_replace_termcodes and nvim_feedkeys escape \x80          local inp = helpers.nvim('replace_termcodes', ':let x2="…"<CR>', true, true, true) -        nvim('feedkeys', inp, '', true) +        nvim('feedkeys', inp, '', true)   -- escape_csi=true -        -- Disabling CSI escaping in feedkeys +        -- nvim_feedkeys with CSI escaping disabled          inp = helpers.nvim('replace_termcodes', ':let x3="…"<CR>', true, true, true) -        nvim('feedkeys', inp, '', false) +        nvim('feedkeys', inp, '', false)  -- escape_csi=false          helpers.stop()        end | 
