How does `C-x z` work?

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP












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




























    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


























      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
















      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















      share|improve this question













      share|improve this question




      share|improve this question








      edited Jan 7 at 1:02









      Drew

      47.5k462104




      47.5k462104










      asked Jan 7 at 0:48









      extremeaxe5extremeaxe5

      1483




      1483




















          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
            );



            );













            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.5k462104




            47.5k462104







            • 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.9k2461




                18.9k2461



























                    draft saved

                    draft discarded
















































                    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.




                    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

                    How to check contact read email or not when send email to Individual?

                    Displaying single band from multi-band raster using QGIS

                    How many registers does an x86_64 CPU actually have?