How does `C-x z` work?












4














Specifically, the keyboard event C-x, following by N z characters, will repeat the previous command N times.



I do not understand how this can work. As far as I understand, after the input event C-x z, for the behavior to be as specified, Emacs would need to somehow remap the z character to the command repeat in order for the next z to actually again execute `repeat'. Is this correct? If so, I do not understand how Emacs can change the keymap immediately after executing a command. If not, what is going on?










share|improve this question









New contributor




extremeaxe5 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

























    4














    Specifically, the keyboard event C-x, following by N z characters, will repeat the previous command N times.



    I do not understand how this can work. As far as I understand, after the input event C-x z, for the behavior to be as specified, Emacs would need to somehow remap the z character to the command repeat in order for the next z to actually again execute `repeat'. Is this correct? If so, I do not understand how Emacs can change the keymap immediately after executing a command. If not, what is going on?










    share|improve this question









    New contributor




    extremeaxe5 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
    Check out our Code of Conduct.























      4












      4








      4







      Specifically, the keyboard event C-x, following by N z characters, will repeat the previous command N times.



      I do not understand how this can work. As far as I understand, after the input event C-x z, for the behavior to be as specified, Emacs would need to somehow remap the z character to the command repeat in order for the next z to actually again execute `repeat'. Is this correct? If so, I do not understand how Emacs can change the keymap immediately after executing a command. If not, what is going on?










      share|improve this question









      New contributor




      extremeaxe5 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      Specifically, the keyboard event C-x, following by N z characters, will repeat the previous command N times.



      I do not understand how this can work. As far as I understand, after the input event C-x z, for the behavior to be as specified, Emacs would need to somehow remap the z character to the command repeat in order for the next z to actually again execute `repeat'. Is this correct? If so, I do not understand how Emacs can change the keymap immediately after executing a command. If not, what is going on?







      keymap commands






      share|improve this question









      New contributor




      extremeaxe5 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.











      share|improve this question









      New contributor




      extremeaxe5 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      share|improve this question




      share|improve this question








      edited Jan 7 at 1:02









      Drew

      47.2k462104




      47.2k462104






      New contributor




      extremeaxe5 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.









      asked Jan 7 at 0:48









      extremeaxe5extremeaxe5

      1211




      1211




      New contributor




      extremeaxe5 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.





      New contributor





      extremeaxe5 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






      extremeaxe5 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
      Check out our Code of Conduct.






















          2 Answers
          2






          active

          oldest

          votes


















          5














          The code is in repeat.el. See command repeat, which is what C-x z is bound to.



          The code uses the fact that Emacs records the current command and the last command in variables. The repeat code resets the variable this-command to what it records as the command that was previous to command repeat.



          Note that you can define your own repeatable command by using code such as this:



          (defun my-repeat-command (command)
          "Repeat COMMAND."
          (require 'repeat)
          (let ((repeat-previous-repeated-command command)
          (repeat-message-function #'ignore)
          (last-repeatable-command 'repeat))
          (repeat nil)))

          (defun some-command (...)
          (interactive...)
          ...)

          (defun some-command-repeat ()
          "Invoke `some-command' in a repeatable way."
          (interactive)
          (my-repeat-command 'some-command))


          repeat does kind of "remap the key" on the fly. It uses set-transient-map, defining the key in a transient map, and then it calls itself again.



          Prior to Emacs 24 it didn't use a new (transient) keymap (such a thing didn't exist as such back then). It just checked whether the next key/command was the same as the last.



          Essentially, repeat fools Emacs into thinking that the current command is whatever command was used last.






          share|improve this answer



















          • 1




            Looking at the repeat defun, it also uses set-transient-map to allow repeated taps of the last character in the binding to continue to repeat.
            – glucas
            Jan 7 at 1:46










          • @glucas: Yes. I edited the answer to be clearer about this. A transient map wasn't used originally. Using it is cleaner that what was done originally, but it's not a necessary part of the general approach behind repeat.
            – Drew
            Jan 7 at 5:17





















          3














          As you guessed, for this to work, the repeat command needs to be able to "change the keymap" immediately after executing a command. And indeed, repeat ends with a call to set-transient-map which makes a new keymap active (rather than modify in-place one of the currently active keymaps, it works by changing the set of active keymaps) with a binding for z which shadows the normal binding of z. This keymap needs to be short-lived, so set-transient-map internally uses pre-command-hook to deactivate that special keymap as soon as you hit something else than z.






          share|improve this answer





















            Your Answer








            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "583"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });






            extremeaxe5 is a new contributor. Be nice, and check out our Code of Conduct.










            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2femacs.stackexchange.com%2fquestions%2f46948%2fhow-does-c-x-z-work%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            2 Answers
            2






            active

            oldest

            votes








            2 Answers
            2






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            5














            The code is in repeat.el. See command repeat, which is what C-x z is bound to.



            The code uses the fact that Emacs records the current command and the last command in variables. The repeat code resets the variable this-command to what it records as the command that was previous to command repeat.



            Note that you can define your own repeatable command by using code such as this:



            (defun my-repeat-command (command)
            "Repeat COMMAND."
            (require 'repeat)
            (let ((repeat-previous-repeated-command command)
            (repeat-message-function #'ignore)
            (last-repeatable-command 'repeat))
            (repeat nil)))

            (defun some-command (...)
            (interactive...)
            ...)

            (defun some-command-repeat ()
            "Invoke `some-command' in a repeatable way."
            (interactive)
            (my-repeat-command 'some-command))


            repeat does kind of "remap the key" on the fly. It uses set-transient-map, defining the key in a transient map, and then it calls itself again.



            Prior to Emacs 24 it didn't use a new (transient) keymap (such a thing didn't exist as such back then). It just checked whether the next key/command was the same as the last.



            Essentially, repeat fools Emacs into thinking that the current command is whatever command was used last.






            share|improve this answer



















            • 1




              Looking at the repeat defun, it also uses set-transient-map to allow repeated taps of the last character in the binding to continue to repeat.
              – glucas
              Jan 7 at 1:46










            • @glucas: Yes. I edited the answer to be clearer about this. A transient map wasn't used originally. Using it is cleaner that what was done originally, but it's not a necessary part of the general approach behind repeat.
              – Drew
              Jan 7 at 5:17


















            5














            The code is in repeat.el. See command repeat, which is what C-x z is bound to.



            The code uses the fact that Emacs records the current command and the last command in variables. The repeat code resets the variable this-command to what it records as the command that was previous to command repeat.



            Note that you can define your own repeatable command by using code such as this:



            (defun my-repeat-command (command)
            "Repeat COMMAND."
            (require 'repeat)
            (let ((repeat-previous-repeated-command command)
            (repeat-message-function #'ignore)
            (last-repeatable-command 'repeat))
            (repeat nil)))

            (defun some-command (...)
            (interactive...)
            ...)

            (defun some-command-repeat ()
            "Invoke `some-command' in a repeatable way."
            (interactive)
            (my-repeat-command 'some-command))


            repeat does kind of "remap the key" on the fly. It uses set-transient-map, defining the key in a transient map, and then it calls itself again.



            Prior to Emacs 24 it didn't use a new (transient) keymap (such a thing didn't exist as such back then). It just checked whether the next key/command was the same as the last.



            Essentially, repeat fools Emacs into thinking that the current command is whatever command was used last.






            share|improve this answer



















            • 1




              Looking at the repeat defun, it also uses set-transient-map to allow repeated taps of the last character in the binding to continue to repeat.
              – glucas
              Jan 7 at 1:46










            • @glucas: Yes. I edited the answer to be clearer about this. A transient map wasn't used originally. Using it is cleaner that what was done originally, but it's not a necessary part of the general approach behind repeat.
              – Drew
              Jan 7 at 5:17
















            5












            5








            5






            The code is in repeat.el. See command repeat, which is what C-x z is bound to.



            The code uses the fact that Emacs records the current command and the last command in variables. The repeat code resets the variable this-command to what it records as the command that was previous to command repeat.



            Note that you can define your own repeatable command by using code such as this:



            (defun my-repeat-command (command)
            "Repeat COMMAND."
            (require 'repeat)
            (let ((repeat-previous-repeated-command command)
            (repeat-message-function #'ignore)
            (last-repeatable-command 'repeat))
            (repeat nil)))

            (defun some-command (...)
            (interactive...)
            ...)

            (defun some-command-repeat ()
            "Invoke `some-command' in a repeatable way."
            (interactive)
            (my-repeat-command 'some-command))


            repeat does kind of "remap the key" on the fly. It uses set-transient-map, defining the key in a transient map, and then it calls itself again.



            Prior to Emacs 24 it didn't use a new (transient) keymap (such a thing didn't exist as such back then). It just checked whether the next key/command was the same as the last.



            Essentially, repeat fools Emacs into thinking that the current command is whatever command was used last.






            share|improve this answer














            The code is in repeat.el. See command repeat, which is what C-x z is bound to.



            The code uses the fact that Emacs records the current command and the last command in variables. The repeat code resets the variable this-command to what it records as the command that was previous to command repeat.



            Note that you can define your own repeatable command by using code such as this:



            (defun my-repeat-command (command)
            "Repeat COMMAND."
            (require 'repeat)
            (let ((repeat-previous-repeated-command command)
            (repeat-message-function #'ignore)
            (last-repeatable-command 'repeat))
            (repeat nil)))

            (defun some-command (...)
            (interactive...)
            ...)

            (defun some-command-repeat ()
            "Invoke `some-command' in a repeatable way."
            (interactive)
            (my-repeat-command 'some-command))


            repeat does kind of "remap the key" on the fly. It uses set-transient-map, defining the key in a transient map, and then it calls itself again.



            Prior to Emacs 24 it didn't use a new (transient) keymap (such a thing didn't exist as such back then). It just checked whether the next key/command was the same as the last.



            Essentially, repeat fools Emacs into thinking that the current command is whatever command was used last.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jan 7 at 5:21

























            answered Jan 7 at 1:01









            DrewDrew

            47.2k462104




            47.2k462104








            • 1




              Looking at the repeat defun, it also uses set-transient-map to allow repeated taps of the last character in the binding to continue to repeat.
              – glucas
              Jan 7 at 1:46










            • @glucas: Yes. I edited the answer to be clearer about this. A transient map wasn't used originally. Using it is cleaner that what was done originally, but it's not a necessary part of the general approach behind repeat.
              – Drew
              Jan 7 at 5:17
















            • 1




              Looking at the repeat defun, it also uses set-transient-map to allow repeated taps of the last character in the binding to continue to repeat.
              – glucas
              Jan 7 at 1:46










            • @glucas: Yes. I edited the answer to be clearer about this. A transient map wasn't used originally. Using it is cleaner that what was done originally, but it's not a necessary part of the general approach behind repeat.
              – Drew
              Jan 7 at 5:17










            1




            1




            Looking at the repeat defun, it also uses set-transient-map to allow repeated taps of the last character in the binding to continue to repeat.
            – glucas
            Jan 7 at 1:46




            Looking at the repeat defun, it also uses set-transient-map to allow repeated taps of the last character in the binding to continue to repeat.
            – glucas
            Jan 7 at 1:46












            @glucas: Yes. I edited the answer to be clearer about this. A transient map wasn't used originally. Using it is cleaner that what was done originally, but it's not a necessary part of the general approach behind repeat.
            – Drew
            Jan 7 at 5:17






            @glucas: Yes. I edited the answer to be clearer about this. A transient map wasn't used originally. Using it is cleaner that what was done originally, but it's not a necessary part of the general approach behind repeat.
            – Drew
            Jan 7 at 5:17













            3














            As you guessed, for this to work, the repeat command needs to be able to "change the keymap" immediately after executing a command. And indeed, repeat ends with a call to set-transient-map which makes a new keymap active (rather than modify in-place one of the currently active keymaps, it works by changing the set of active keymaps) with a binding for z which shadows the normal binding of z. This keymap needs to be short-lived, so set-transient-map internally uses pre-command-hook to deactivate that special keymap as soon as you hit something else than z.






            share|improve this answer


























              3














              As you guessed, for this to work, the repeat command needs to be able to "change the keymap" immediately after executing a command. And indeed, repeat ends with a call to set-transient-map which makes a new keymap active (rather than modify in-place one of the currently active keymaps, it works by changing the set of active keymaps) with a binding for z which shadows the normal binding of z. This keymap needs to be short-lived, so set-transient-map internally uses pre-command-hook to deactivate that special keymap as soon as you hit something else than z.






              share|improve this answer
























                3












                3








                3






                As you guessed, for this to work, the repeat command needs to be able to "change the keymap" immediately after executing a command. And indeed, repeat ends with a call to set-transient-map which makes a new keymap active (rather than modify in-place one of the currently active keymaps, it works by changing the set of active keymaps) with a binding for z which shadows the normal binding of z. This keymap needs to be short-lived, so set-transient-map internally uses pre-command-hook to deactivate that special keymap as soon as you hit something else than z.






                share|improve this answer












                As you guessed, for this to work, the repeat command needs to be able to "change the keymap" immediately after executing a command. And indeed, repeat ends with a call to set-transient-map which makes a new keymap active (rather than modify in-place one of the currently active keymaps, it works by changing the set of active keymaps) with a binding for z which shadows the normal binding of z. This keymap needs to be short-lived, so set-transient-map internally uses pre-command-hook to deactivate that special keymap as soon as you hit something else than z.







                share|improve this answer












                share|improve this answer



                share|improve this answer










                answered Jan 7 at 3:39









                StefanStefan

                18.7k2461




                18.7k2461






















                    extremeaxe5 is a new contributor. Be nice, and check out our Code of Conduct.










                    draft saved

                    draft discarded


















                    extremeaxe5 is a new contributor. Be nice, and check out our Code of Conduct.













                    extremeaxe5 is a new contributor. Be nice, and check out our Code of Conduct.












                    extremeaxe5 is a new contributor. Be nice, and check out our Code of Conduct.
















                    Thanks for contributing an answer to Emacs Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2femacs.stackexchange.com%2fquestions%2f46948%2fhow-does-c-x-z-work%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    "Incorrect syntax near the keyword 'ON'. (on update cascade, on delete cascade,)

                    Alcedinidae

                    RAC Tourist Trophy