emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Setting "echoing prefix" from Elisp (was: other-frame, other-window pref


From: Stefan Monnier
Subject: Setting "echoing prefix" from Elisp (was: other-frame, other-window prefix keys)
Date: Tue, 11 Aug 2015 13:37:54 -0400
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/25.0.50 (gnu/linux)

>>> One other thing: I'd be neat if the echo-area could display the "C-x 7"
>>> prefix if you wait a couple seconds, like it does for C-u.  I have some
>>> experimental code around somewhere that moves some of that C-u code from
>>> C so it could be used for C-x 7.
>> Ok, please send the code; I have no idea how that works.
> I don't really have a good idea how it works either, mind you.
> I experimented with it specifically thinking of prefixes like C-x 4, but
> there are some non-trivial issues.
> I'll try and dig it up,

OK, found it.  Here's an updated version which should apply cleanly to
"master".  It's likely that this change will require adjustment in any code
which uses reset-this-command-lengths (aka cua-base.el and kmacro.el).


        Stefan


diff --git a/lisp/simple.el b/lisp/simple.el
index 2636777..e216794 100644
--- a/lisp/simple.el
+++ b/lisp/simple.el
@@ -3661,7 +3661,19 @@ see other processes running on the system, use 
`list-system-processes'."
   "Keymap used while processing \\[universal-argument].")
 
 (defun universal-argument--mode ()
-  (set-transient-map universal-argument-map))
+  (setq echo-keystrokes-prefix
+        (concat "C-u"
+                (pcase prefix-arg
+                  (`(-) " -")
+                  (`(,(and (pred integerp) n))
+                   (let ((str ""))
+                     (while (and (> n 4) (= (mod n 4) 0))
+                       (setq str (concat str " C-u"))
+                       (setq n (/ n 4)))
+                     (if (= n 4) str (format " %s" prefix-arg))))
+                  (_ (format " %s" prefix-arg)))))
+  (set-transient-map universal-argument-map nil
+                     (lambda () (setq echo-keystrokes-prefix nil))))
 
 (defun universal-argument ()
   "Begin a numeric argument for the following command.
diff --git a/src/keyboard.c b/src/keyboard.c
index f670da3..3c5ade2 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -441,10 +441,12 @@ echo_add_key (Lisp_Object c)
   ptrdiff_t size = sizeof initbuf;
   char *buffer = initbuf;
   char *ptr = buffer;
-  Lisp_Object echo_string;
+  Lisp_Object echo_string = KVAR (current_kboard, echo_string);
   USE_SAFE_ALLOCA;
 
-  echo_string = KVAR (current_kboard, echo_string);
+  if (STRINGP (echo_string) && SCHARS (echo_string) > 0)
+    /* Add a space at the end as a separator between keys.  */
+    ptr++[0] = ' ';
 
   /* If someone has passed us a composite event, use its head symbol.  */
   c = EVENT_HEAD (c);
@@ -475,6 +477,7 @@ echo_add_key (Lisp_Object c)
       int len = sizeof text - 1;
 
       if (size - (ptr - buffer) < len)
+       /* FIXME: I had "abort ();" here !?!  */
        {
          ptrdiff_t offset = ptr - buffer;
          size += len;
@@ -486,48 +489,12 @@ echo_add_key (Lisp_Object c)
       ptr += len;
     }
 
-  /* Replace a dash from echo_dash with a space, otherwise add a space
-     at the end as a separator between keys.  */
-  AUTO_STRING (space, " ");
-  if (STRINGP (echo_string) && SCHARS (echo_string) > 1)
-    {
-      Lisp_Object last_char, prev_char, idx;
-
-      idx = make_number (SCHARS (echo_string) - 2);
-      prev_char = Faref (echo_string, idx);
-
-      idx = make_number (SCHARS (echo_string) - 1);
-      last_char = Faref (echo_string, idx);
-
-      /* We test PREV_CHAR to make sure this isn't the echoing of a
-        minus-sign.  */
-      if (XINT (last_char) == '-' && XINT (prev_char) != ' ')
-       Faset (echo_string, idx, make_number (' '));
-      else
-       echo_string = concat2 (echo_string, space);
-    }
-  else if (STRINGP (echo_string) && SCHARS (echo_string) > 0)
-    echo_string = concat2 (echo_string, space);
-
   kset_echo_string
     (current_kboard,
      concat2 (echo_string, make_string (buffer, ptr - buffer)));
   SAFE_FREE ();
 }
 
-/* Add C to the echo string, if echoing is going on.  C can be a
-   character or a symbol.  */
-
-static void
-echo_char (Lisp_Object c)
-{
-  if (current_kboard->immediate_echo)
-    {
-      echo_add_key (c);
-      echo_now ();
-    }
-}
-
 /* Temporarily add a dash to the end of the echo string if it's not
    empty, so that it serves as a mini-prompt for the very next
    character.  */
@@ -539,9 +506,6 @@ echo_dash (void)
   if (NILP (KVAR (current_kboard, echo_string)))
     return;
 
-  if (this_command_key_count == 0)
-    return;
-
   if (!current_kboard->immediate_echo
       && SCHARS (KVAR (current_kboard, echo_string)) == 0)
     return;
@@ -574,16 +538,13 @@ echo_dash (void)
   echo_now ();
 }
 
-/* Display the current echo string, and begin echoing if not already
-   doing so.  */
-
 static void
-echo_now (void)
+echo_update (void)
 {
-  if (!current_kboard->immediate_echo)
+  if (current_kboard->immediate_echo)
     {
       ptrdiff_t i;
-      current_kboard->immediate_echo = 1;
+      kset_echo_string (current_kboard, Vecho_keystrokes_prefix);
 
       for (i = 0; i < this_command_key_count; i++)
        {
@@ -598,7 +559,7 @@ echo_now (void)
          c = AREF (this_command_keys, i);
          if (! (EVENT_HAS_PARAMETERS (c)
                 && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
-           echo_char (c);
+           echo_add_key (c);
        }
 
       /* Set before_command_echo_length to the value that would
@@ -607,10 +568,23 @@ echo_now (void)
       if (this_command_key_count == this_single_command_key_start)
        before_command_echo_length = echo_length ();
 
+      echo_now ();
+    }
+}
+
+/* Display the current echo string, and begin echoing if not already
+   doing so.  */
+
+static void
+echo_now (void)
+{
+  if (!current_kboard->immediate_echo)
+    {
+      current_kboard->immediate_echo = true;
+      echo_update ();
       /* Put a dash at the end to invite the user to type more.  */
       echo_dash ();
     }
-
   echoing = 1;
   /* FIXME: Use call (Qmessage) so it can be advised (e.g. emacspeak).  */
   message3_nolog (KVAR (current_kboard, echo_string));
@@ -1550,9 +1524,6 @@ command_loop_1 (void)
         2) we want to leave echoing on so that the prefix will be
         echoed as part of this key sequence, so don't call
         cancel_echoing, and
-        3) we want to leave this_command_key_count non-zero, so that
-        read_char will realize that it is re-reading a character, and
-        not echo it a second time.
 
         If the command didn't actually create a prefix arg,
         but is merely a frame event that is transparent to prefix args,
@@ -1565,9 +1536,17 @@ command_loop_1 (void)
          if (!CONSP (last_command_event))
            kset_last_repeatable_command (current_kboard, Vreal_this_command);
          cancel_echoing ();
-         this_command_key_count = 0;
-         this_command_key_count_reset = 0;
-         this_single_command_key_start = 0;
+       }
+
+      this_command_key_count = 0;
+      this_command_key_count_reset = false;
+      this_single_command_key_start = 0;
+
+      if (current_kboard->immediate_echo && !NILP (Vecho_keystrokes_prefix))
+       {
+         current_kboard->immediate_echo = false;
+         /* Refresh the echo message.  */
+         echo_now ();
        }
 
       if (!NILP (BVAR (current_buffer, mark_active))
@@ -2577,7 +2556,7 @@ read_char (int commandflag, Lisp_Object map,
 
      (3) There's only one place in 20.x where ok_to_echo_at_next_pause
      is set to a non-null value.  This is done in read_char and it is
-     set to echo_area_glyphs after a call to echo_char.  That means
+     set to echo_area_glyphs.  That means
      ok_to_echo_at_next_pause is either null or
      current_kboard->echobuf with the appropriate current_kboard at
      that time.
@@ -2684,7 +2663,7 @@ read_char (int commandflag, Lisp_Object map,
   if (minibuf_level == 0
       && !end_time
       && !current_kboard->immediate_echo
-      && this_command_key_count > 0
+      && (this_command_key_count > 0 || STRINGP (Vecho_keystrokes_prefix))
       && ! noninteractive
       && echo_keystrokes_p ()
       && (/* No message.  */
@@ -3172,22 +3151,18 @@ read_char (int commandflag, Lisp_Object map,
     {
 
       /* Don't echo mouse motion events.  */
-      if (echo_keystrokes_p ()
-         && ! (EVENT_HAS_PARAMETERS (c)
-               && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
-       {
-         echo_char (c);
-         if (! NILP (also_record))
-           echo_char (also_record);
-         /* Once we reread a character, echoing can happen
-            the next time we pause to read a new one.  */
-         ok_to_echo_at_next_pause = current_kboard;
-       }
+      if (! (EVENT_HAS_PARAMETERS (c)
+            && EQ (EVENT_HEAD_KIND (EVENT_HEAD (c)), Qmouse_movement)))
+       /* Once we reread a character, echoing can happen
+          the next time we pause to read a new one.  */
+       ok_to_echo_at_next_pause = current_kboard;
 
       /* Record this character as part of the current key.  */
       add_command_key (c);
       if (! NILP (also_record))
        add_command_key (also_record);
+
+      echo_update ();
     }
 
   last_input_event = c;
@@ -3248,18 +3223,13 @@ record_menu_key (Lisp_Object c)
   before_command_echo_length = echo_length ();
 #endif
 
-  /* Don't echo mouse motion events.  */
-  if (echo_keystrokes_p ())
-    {
-      echo_char (c);
-
-      /* Once we reread a character, echoing can happen
-        the next time we pause to read a new one.  */
-      ok_to_echo_at_next_pause = 0;
-    }
+  /* Once we reread a character, echoing can happen
+     the next time we pause to read a new one.  */
+  ok_to_echo_at_next_pause = NULL;
 
   /* Record this character as part of the current key.  */
   add_command_key (c);
+  echo_update ();
 
   /* Re-reading in the middle of a command.  */
   last_input_event = c;
@@ -9157,11 +9127,12 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, 
Lisp_Object prompt,
        {
          key = keybuf[t];
          add_command_key (key);
-         if (echo_keystrokes_p ()
-             && current_kboard->immediate_echo)
+         if (current_kboard->immediate_echo)
            {
-             echo_add_key (key);
-             echo_dash ();
+             /* Set immediate_echo to false so as to force echo_now to
+                redisplay (it will set immediate_echo right back to true).  */
+             current_kboard->immediate_echo = false;
+             echo_now ();
            }
        }
 
@@ -9833,11 +9804,8 @@ read_key_sequence (Lisp_Object *keybuf, int bufsize, 
Lisp_Object prompt,
 
      Better ideas?  */
   for (; t < mock_input; t++)
-    {
-      if (echo_keystrokes_p ())
-       echo_char (keybuf[t]);
-      add_command_key (keybuf[t]);
-    }
+    add_command_key (keybuf[t]);
+  echo_update ();
 
   UNGCPRO;
   return t;
@@ -10129,6 +10097,7 @@ The value is always a vector.  */)
 
 DEFUN ("reset-this-command-lengths", Freset_this_command_lengths,
        Sreset_this_command_lengths, 0, 0, 0,
+       /* FIXME: Bad&wrong docstring!  */
        doc: /* Make the unread events replace the last command and echo.
 Used in `universal-argument-other-key'.
 
@@ -11439,6 +11408,10 @@ The value may be integer or floating point.
 If the value is zero, don't echo at all.  */);
   Vecho_keystrokes = make_number (1);
 
+  DEFVAR_LISP ("echo-keystrokes-prefix", Vecho_keystrokes_prefix,
+              doc: /* String to prefix in front of unfinished key sequences.  
*/);
+  Vecho_keystrokes_prefix = Qnil;
+
   DEFVAR_INT ("polling-period", polling_period,
              doc: /* Interval between polling for input during Lisp execution.
 The reason for polling is to make C-g work to stop a running program.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]