summaryrefslogtreecommitdiffstats
path: root/src/getchar.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2020-11-12 14:21:06 +0100
committerBram Moolenaar <Bram@vim.org>2020-11-12 14:21:06 +0100
commit957cf67d50516ba98716f59c9e1cb6412ec1535d (patch)
treea1f287aee01e4cbb023b2531a5a4b90e9728a8bf /src/getchar.c
parentea2d407f9c144bb634c59017944e4930ed7f80a2 (diff)
patch 8.2.1978: making a mapping work in all modes is complicatedv8.2.1978
Problem: Making a mapping work in all modes is complicated. Solution: Add the <Cmd> special key. (Yegappan Lakshmanan, closes #7282, closes 4784, based on patch by Bjorn Linse)
Diffstat (limited to 'src/getchar.c')
-rw-r--r--src/getchar.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/src/getchar.c b/src/getchar.c
index b0cc8c2317..3d73a6c7b6 100644
--- 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;
+}