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;
+}