emacs-devel
[Top][All Lists]
Advanced

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

Re: bug: "C-x z" ("repeat") no longer works correctly with M-x


From: Aaron S. Hawley
Subject: Re: bug: "C-x z" ("repeat") no longer works correctly with M-x
Date: Sat, 2 Jun 2012 18:07:52 -0400

On 6/2/12, Chong Yidong <address@hidden> wrote:
> "Aaron S. Hawley" <address@hidden> writes:
>
>> I had given a more literal translation of the C command to the
>> gnu-emacs-sources mailing list back in March.  Stefan and I discussed
>> it but hadn't run across this issue with repeat.  He later made some
>> modifications to my submission and committed it in May.  I have only
>> now run it and can confirm this bug with repeat.  I'm not sure what's
>> causing it though, but found the following fixes it.  Again, I'm not
>> sure why.  Nor am I sure if it's a wholly appropriate fix.
>
> No, tweaking the interactive spec does not really fix the problem.
>
> The problem is that the old execute-extended-command sets the
> real_this_command internal variable, which causes the Emacs command loop
> to record the command that was actually executed into real-last-command
> and last-repeatable-command.
>
> In other words, it's not just the fact that `C-x z' doesn't work
> properly.  Moving execute-extended-command to Lisp produces a
> backward-incompatible change in the values of the real-last-command and
> last-repeatable-command variables for M-x.  I suspect this may break
> things other than `C-x z'.  I guess we could fix this by exposing
> real_this_command to Lisp too, but that kinda defeats the point of that
> variable...
>
> Is there a strong rationale for moving execute-extended-command to Lisp,
> other than the general principle that we want as much functionality
> implemented Lisp as possible?  If not, it may not be worth making this
> change, at least in Emacs 24.2, due to the risk of gratuitous
> incompatibilities.

I agree, it's not worth it if things break.  As I wrote to
gnu-emacs-sources, I've been using a Lisp version of M-x for several
years.  Obviously, I ran into issues when I first tried writing the
code, but haven't run into any issues since.  I am a big user of
repeat and repeat-complex-command and keyboard macros.  I think it's
possible to get this Lisp version to work as well as the C version.

I understand your concern about real_this_command in command_loop and
call-interactively.  However, it's not clear if there's any reason for
it for M-x.  I'd be interested to know if there other issues.  Perhaps
the timeline of 24.2 won't allow for it?

I've made sure repeat works if M-x is a mouse event by adding it to
the tool-bar or the menu-bar.

(define-key menu-bar-tools-menu [m-x]
  `(menu-item ,(purecopy "M-x") execute-extended-command
              :enable (menu-bar-non-minibuffer-window-p)
              :help ,(purecopy "Execute extended command")))

(tool-bar-add-item-from-menu 'execute-extended-command "mpc/add"
                             nil :label "Execute extended command"
                             :vert-only t)

I do suggest the following fixes to rework Stefan's revision,
including the change to the interactive spec.  Some of it is white
space changes and a comment that no longer applies.

2012-05-29  Aaron S. Hawley  <address@hidden>

        * simple.el (execute-extended-command): Reading command-name in
        interactive form breaks the repeat command.  Improve error message
        for empty command-name.

--- simple.el   2012-05-29 08:21:45.000000000 -0400
+++ simple.el   2012-05-29 18:46:04.836717200 -0400
@@ -1373,17 +1373,20 @@

 Noninteractively, the argument PREFIXARG is the prefix argument to
 give to the command you invoke, if it asks for an argument."
-  (interactive (list current-prefix-arg (read-extended-command)))
+  (interactive "P")
   ;; Emacs<24 calling-convention was with a single `prefixarg' argument.
-  (if (null command-name) (setq command-name (read-extended-command)))
+  (when (null command-name)
+    ;; Could be in `interactive' as well, but it breaks `repeat'.
+    (setq command-name (read-extended-command)))
   (let* ((function (and (stringp command-name) (intern-soft command-name)))
          (binding (and suggest-key-bindings
-                        (not executing-kbd-macro)
-                        (where-is-internal function overriding-local-map t))))
+                       (not executing-kbd-macro)
+                       (where-is-internal function overriding-local-map t))))
+    (when (and (stringp command-name)
+               (= 0 (length command-name)))
+      (error "No command name given"))
     (unless (commandp function)
       (error "`%s' is not a valid command name" command-name))
-    ;; Set this_command_keys to the concatenation of saved-keys and
-    ;; function, followed by a RET.
     (setq this-command function)
     (let ((prefix-arg prefixarg))
       (command-execute function 'record))

-- 
In general, we reserve the right to have a poor
memory--the computer, however, is supposed to
remember!  Poor computer.  -- Guy Lewis Steele Jr.



reply via email to

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