Mercurial > vim
diff src/getchar.c @ 22862:6d50182e7e24 v8.2.1978
patch 8.2.1978: making a mapping work in all modes is complicated
Commit: https://github.com/vim/vim/commit/957cf67d50516ba98716f59c9e1cb6412ec1535d
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Nov 12 14:21:06 2020 +0100
patch 8.2.1978: making a mapping work in all modes is complicated
Problem: Making a mapping work in all modes is complicated.
Solution: Add the <Cmd> special key. (Yegappan Lakshmanan, closes https://github.com/vim/vim/issues/7282,
closes 4784, based on patch by Bjorn Linse)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Thu, 12 Nov 2020 14:30:04 +0100 |
parents | 8e7cbf73c3a0 |
children | 7ac9dea21baa |
line wrap: on
line diff
--- a/src/getchar.c +++ b/src/getchar.c @@ -3619,3 +3619,96 @@ input_available(void) ); } #endif + +/* + * Function passed to do_cmdline() to get the command after a <Cmd> key from + * typeahead. + */ + char_u * +getcmdkeycmd( + int promptc UNUSED, + void *cookie UNUSED, + int indent UNUSED, + getline_opt_T do_concat UNUSED) +{ + garray_T line_ga; + int c1 = -1; + int c2; + int cmod = 0; + int aborted = FALSE; + + ga_init2(&line_ga, 1, 32); + + // no mapping for these characters + no_mapping++; + + got_int = FALSE; + while (c1 != NUL && !aborted) + { + ga_grow(&line_ga, 32); + + if (vgetorpeek(FALSE) == NUL) + { + // incomplete <Cmd> is an error, because there is not much the user + // could do in this state. + emsg(_(e_cmd_mapping_must_end_with_cr)); + aborted = TRUE; + break; + } + + // Get one character at a time. + c1 = vgetorpeek(TRUE); + + // Get two extra bytes for special keys + if (c1 == K_SPECIAL) + { + c1 = vgetorpeek(TRUE); + c2 = vgetorpeek(TRUE); + if (c1 == KS_MODIFIER) + { + cmod = c2; + continue; + } + c1 = TO_SPECIAL(c1, c2); + } + + if (got_int) + aborted = TRUE; + else if (c1 == '\r' || c1 == '\n') + c1 = NUL; // end the line + else if (c1 == ESC) + aborted = TRUE; + else if (c1 == K_COMMAND) + { + // give a nicer error message for this special case + emsg(_(e_cmd_mapping_must_end_with_cr_before_second_cmd)); + aborted = TRUE; + } + else if (IS_SPECIAL(c1)) + { + if (c1 == K_SNR) + { + ga_append(&line_ga, (char)K_SPECIAL); + ga_append(&line_ga, (char)KS_EXTRA); + ga_append(&line_ga, (char)KE_SNR); + } + else + { + semsg(e_cmd_maping_must_not_include_str_key, + get_special_key_name(c1, cmod)); + aborted = TRUE; + } + } + else + ga_append(&line_ga, (char)c1); + + cmod = 0; + } + + no_mapping--; + + if (aborted) + ga_clear(&line_ga); + + return (char_u *)line_ga.ga_data; +}