* Is there a plan to record kbd macro as elisp code? @ 2007-10-27 9:28 yzhh 2007-10-27 15:48 ` Robert J. Chassell ` (2 more replies) 0 siblings, 3 replies; 37+ messages in thread From: yzhh @ 2007-10-27 9:28 UTC (permalink / raw) To: emacs-devel Hi, Recording kbd macro as elisp code can be useful. The following are some benefits: 1. Editing elisp code is more clear than editing key sequences, and supports complex controlstructures. 2. elisp code is more portable than key sequences. Sharing with others who have different key bindings is ok for elisp, but not for key sequences. 3. It can be used as a means ot learn emacs commands in elisp form. I tried to build a modified emacs that stores every command sent to 'execute-command' into a list, when 'defining-kbd-macro' is on. But the result is a list that still leaves out things like horizontal movements. And isearch is not recorded right (one search recorded as many isearch commands, without information of what's being searched). So I know the modification required is not simple, far beyond a quick and dirty patch. Out of curiosity I want to know whether there is a plan for this feature in the future. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 9:28 Is there a plan to record kbd macro as elisp code? yzhh @ 2007-10-27 15:48 ` Robert J. Chassell 2007-10-27 17:30 ` yzhh 2007-10-27 19:26 ` Jay Belanger 2007-10-27 16:20 ` Drew Adams 2007-10-29 6:41 ` Klaus Zeitler 2 siblings, 2 replies; 37+ messages in thread From: Robert J. Chassell @ 2007-10-27 15:48 UTC (permalink / raw) To: emacs-devel yezonghui@gmail.com wrote: Recording kbd macro as elisp code can be useful. It certainly can be. More than a dozen years ago an early distribution of Calc mode did this. Unfortunately, as far as I remember, its functionality did no more than you have done. Worse, it vanished from my distribution a decade or so ago and by the time I looked again, perhaps five years ago, it was gone. Even the little bit you have done could be helpful. Please write up what you have as an Emacs Lisp library that can be loaded by `emacs -q', with a name such as yzhh-define-elisp-interactively.el, and submit it. Thank you! (Jay Belanger: do you have really old copies of Calc mode, such as the first that Dave Gillespie distributed? I think that has the capability, but I could be wrong. It has been a very long time.) -- Robert J. Chassell GnuPG Key ID: 004B4AC8 bob@rattlesnake.com bob@gnu.org http://www.rattlesnake.com http://www.teak.cc ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 15:48 ` Robert J. Chassell @ 2007-10-27 17:30 ` yzhh 2007-10-27 18:01 ` Drew Adams 2007-10-27 20:04 ` Stefan Monnier 2007-10-27 19:26 ` Jay Belanger 1 sibling, 2 replies; 37+ messages in thread From: yzhh @ 2007-10-27 17:30 UTC (permalink / raw) To: emacs-devel Robert J. Chassell <bob <at> rattlesnake.com> writes: > It certainly can be. More than a dozen years ago an early > distribution of Calc mode did this. Unfortunately, as far as I > remember, its functionality did no more than you have done. Worse, it > vanished from my distribution a decade or so ago and by the time I > looked again, perhaps five years ago, it was gone. I didn't find things relating to Calc mode when I searched the web on this topic. Hope you remember it right and get it back. Please let me known when you do. > Even the little bit you have done could be helpful. > > Please write up what you have as an Emacs Lisp library that can be > loaded by `emacs -q', with a name such as > yzhh-define-elisp-interactively.el, and submit it. > Thank you for your appreciation. But my modification is in the C code of emacs, because 'execute-command' and 'call-interactively' are in C code. And I don't think my dirty code would be a valid patch for the emacs developers. As far as I can see, recording everything including isearch, query-replace and alike in a general way would need modification in C code. And that modification very probably require quite some re-design of emacs internal control structure (the command loop and kbd macro implementation). All these are out of my reach for the moment. > Thank you! Thank you too. And please read my reply to Drew. ^ permalink raw reply [flat|nested] 37+ messages in thread
* RE: Is there a plan to record kbd macro as elisp code? 2007-10-27 17:30 ` yzhh @ 2007-10-27 18:01 ` Drew Adams 2007-10-28 13:50 ` Richard Stallman 2007-10-27 20:04 ` Stefan Monnier 1 sibling, 1 reply; 37+ messages in thread From: Drew Adams @ 2007-10-27 18:01 UTC (permalink / raw) To: yzhh, emacs-devel > > Even the little bit you have done could be helpful. > > > > Please write up what you have as an Emacs Lisp library that can be > > loaded by `emacs -q', with a name such as > > yzhh-define-elisp-interactively.el, and submit it. > > > > Thank you for your appreciation. But my modification is in the C code of > emacs, because 'execute-command' and 'call-interactively' are in C code. > And I don't think my dirty code would be a valid patch for the emacs > developers. > > As far as I can see, recording everything including isearch, query-replace > and alike in a general way would need modification in C code. And that > modification very probably require quite some re-design of emacs internal > control structure (the command loop and kbd macro implementation). All > these are out of my reach for the moment. Are you sure what you want is worth messing with the C code? If so, why couldn't it be a valid C patch to Emacs? Other people here (not I) can perhaps help you with the coding style (e.g. vs "dirty"). Why is it important to handle the cases you mentioned: isearch and horizontal movement? I can see that it would be good to handle them better, but if that means code that no one else can take advantage of, then the benefit is limited. Maybe you could, as Robert suggested, at least post the Lisp code part, unless it absolutely depends on the "dirty" C code part. Wrt isearch, I think you said that the problem was that the code generated multiple little searches (with missing search strings) instead of a single big search (or something like that). Couldn't the tiny searches be combined into an overall search, by hand (given knowledge of the search string)? I don't mean to discourage you; I'm just looking for a way for you to make your work into a useful contribution. Perhaps aim for something less than 100% complete, something that helps a user define a command based on a keyboard macro, but doesn't do that completely automatically. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 18:01 ` Drew Adams @ 2007-10-28 13:50 ` Richard Stallman 0 siblings, 0 replies; 37+ messages in thread From: Richard Stallman @ 2007-10-28 13:50 UTC (permalink / raw) To: Drew Adams; +Cc: yezonghui, emacs-devel There is no need to change the C code to convert a keyboard macro into Lisp. The keyboard macro is already a sequence of events. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 17:30 ` yzhh 2007-10-27 18:01 ` Drew Adams @ 2007-10-27 20:04 ` Stefan Monnier 2007-10-27 21:22 ` Kim F. Storm 2007-10-27 21:45 ` Juri Linkov 1 sibling, 2 replies; 37+ messages in thread From: Stefan Monnier @ 2007-10-27 20:04 UTC (permalink / raw) To: yzhh; +Cc: emacs-devel > Thank you for your appreciation. But my modification is in the C code of > emacs, because 'execute-command' and 'call-interactively' are in C code. > And I don't think my dirty code would be a valid patch for the emacs > developers. I think what was expected was to first record a keyboard macro and later to turn that into elisp code. Another approach is to use a pre-command-hook to record the value of `this-command' for each command run. Stefan ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 20:04 ` Stefan Monnier @ 2007-10-27 21:22 ` Kim F. Storm 2007-10-28 13:50 ` Richard Stallman 2007-10-27 21:45 ` Juri Linkov 1 sibling, 1 reply; 37+ messages in thread From: Kim F. Storm @ 2007-10-27 21:22 UTC (permalink / raw) To: Stefan Monnier; +Cc: yzhh, emacs-devel Stefan Monnier <monnier@iro.umontreal.ca> writes: >> Thank you for your appreciation. But my modification is in the C code of >> emacs, because 'execute-command' and 'call-interactively' are in C code. >> And I don't think my dirty code would be a valid patch for the emacs >> developers. > > I think what was expected was to first record a keyboard macro and later to > turn that into elisp code. Another approach is to use a pre-command-hook to > record the value of `this-command' for each command run. Which reminds me that there is a big difference between replaying a keyboard macro and running the corresponding functions as a single command: - the pre-command-hook and post-command-hook are run for each key in the keyboard macro, but only once for the single command. This doesn't mean that the elisp code cannot be equivalent to the keyboard macro, but it may be much harder to do right. E.g. if you use modes like delete-selection-mode or cua-mode which do major work in the hooks. -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 21:22 ` Kim F. Storm @ 2007-10-28 13:50 ` Richard Stallman 2007-10-28 22:00 ` Kim F. Storm 0 siblings, 1 reply; 37+ messages in thread From: Richard Stallman @ 2007-10-28 13:50 UTC (permalink / raw) To: Kim F. Storm; +Cc: yezonghui, monnier, emacs-devel Which reminds me that there is a big difference between replaying a keyboard macro and running the corresponding functions as a single command: - the pre-command-hook and post-command-hook are run for each key in the keyboard macro, but only once for the single command. This doesn't mean that the elisp code cannot be equivalent to the keyboard macro, but it may be much harder to do right. There are various ideas of what is "right" for such a conversion. I think the converted code should ignore these hooks, and if the results are different, in most cases that will make sense. Delete Selection mode is an exception. In Delete Selection mode, if these hooks are not run, the results will clearly be wrong. The same may be true of CUA mode. The conversion program could test for the presence of these specific hook functions in pre-command-hook, and generate appropriate code in the output Lisp function. Rather than calling these hook functions before each command, it should call them only in the places where they would do real work. And it wouldn't call the same function, but rather a related one. Here's what it could look like: (put 'delete-selection-pre-hook 'lisp-conversion-function (lambda (function) (let ((type (and (symbolp this-command) (get this-command 'delete-selection)))) (when type `(delete-selection-pre-command-processing ,type))))) where `delete-selection-pre-command-processing' would be a new function that does the same work as `delete-selection-pre-hook' but gets `type' as an argument. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 13:50 ` Richard Stallman @ 2007-10-28 22:00 ` Kim F. Storm 2007-10-29 5:20 ` yzhh ` (2 more replies) 0 siblings, 3 replies; 37+ messages in thread From: Kim F. Storm @ 2007-10-28 22:00 UTC (permalink / raw) To: rms; +Cc: yezonghui, monnier, emacs-devel Richard Stallman <rms@gnu.org> writes: > Which reminds me that there is a big difference between replaying a keyboard > macro and running the corresponding functions as a single command: > > - the pre-command-hook and post-command-hook are run for each key in > the keyboard macro, but only once for the single command. > > This doesn't mean that the elisp code cannot be equivalent to the keyboard > macro, but it may be much harder to do right. > > There are various ideas of what is "right" for such a conversion. > I think the converted code should ignore these hooks, and if the > results are different, in most cases that will make sense. Maybe, but there are many things that can go wrong... Perhaps some of the work could be done by analyzing the undo history ... > Delete Selection mode is an exception. In Delete Selection mode, > if these hooks are not run, the results will clearly be wrong. > The same may be true of CUA mode. It is even more complex I think: With CUA mode, the interpretation of C-x and C-c depends on whether the region is active or not. That is not done through pre-command-hook (but setting/extending the region is), but rather through the keymaps which are active at the time. > The conversion program could test for the presence of these specific > hook functions in pre-command-hook, and generate appropriate code in > the output Lisp function. This will only work if the conversion is done while recording the keyboard macro - as one keystroke may modify the hooks. > Rather than calling these hook functions > before each command, it should call them only in the places where they > would do real work. And it wouldn't call the same function, but > rather a related one. Here's what it could look like: > > (put 'delete-selection-pre-hook 'lisp-conversion-function > (lambda (function) > (let ((type (and (symbolp this-command) > (get this-command 'delete-selection)))) > (when type > `(delete-selection-pre-command-processing ,type))))) > > where `delete-selection-pre-command-processing' would be > a new function that does the same work as `delete-selection-pre-hook' > but gets `type' as an argument. That might work. IMO, the only real solution is to record the elisp code while recording the keyboard macro - as it is possible to cather for changes in the mark-active state and insert suitable set-mark commands etc. Still, I fail to see the real need for the functionality. It may be ok as a way to get a starting point for an editing command, but only very trivial functions can be written that way anyway - and they are just as well written and saved as a series of keystrokes as they do now. -- Kim F. Storm <storm@cua.dk> http://www.cua.dk ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 22:00 ` Kim F. Storm @ 2007-10-29 5:20 ` yzhh 2007-10-29 9:22 ` Richard Stallman 2007-10-29 9:22 ` Richard Stallman 2 siblings, 0 replies; 37+ messages in thread From: yzhh @ 2007-10-29 5:20 UTC (permalink / raw) To: emacs-devel Kim F. Storm <storm <at> cua.dk> writes: > IMO, the only real solution is to record the elisp code while recording > the keyboard macro - as it is possible to cather for changes in > the mark-active state and insert suitable set-mark commands etc. I agree. > Still, I fail to see the real need for the functionality. > > It may be ok as a way to get a starting point for an editing command, > but only very trivial functions can be written that way anyway - and > they are just as well written and saved as a series of keystrokes as > they do now. These are some benefits I thought of: 1. When modifying these trivial functions, non-sequential control flow (conditional branches and loops) are available for elisp code, but not for keystrokes. In such cases a user who's familiar with elisp grammar but not with emacs command names/args is well served by recorded elisp code. 2. Trivial functions in the form of elisp code is more suitable for sharing with others - it's not dependent on the keymaps. (Not everyone use standard key bindings and many have added bindings here and there.) ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 22:00 ` Kim F. Storm 2007-10-29 5:20 ` yzhh @ 2007-10-29 9:22 ` Richard Stallman 2007-10-29 9:22 ` Richard Stallman 2 siblings, 0 replies; 37+ messages in thread From: Richard Stallman @ 2007-10-29 9:22 UTC (permalink / raw) To: Kim F. Storm; +Cc: yezonghui, monnier, emacs-devel With CUA mode, the interpretation of C-x and C-c depends on whether the region is active or not. That is not done through pre-command-hook (but setting/extending the region is), but rather through the keymaps which are active at the time. I don't see any easy way to handle that, except the method of recording the commands that are run. Perhaps this is a good reason to use the method of converting by executing the macro. If we do, it remains better to do so by replaying the macro than by making the user type the definition again. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 22:00 ` Kim F. Storm 2007-10-29 5:20 ` yzhh 2007-10-29 9:22 ` Richard Stallman @ 2007-10-29 9:22 ` Richard Stallman 2 siblings, 0 replies; 37+ messages in thread From: Richard Stallman @ 2007-10-29 9:22 UTC (permalink / raw) To: Kim F. Storm; +Cc: yezonghui, monnier, emacs-devel Still, I fail to see the real need for the functionality. It may be ok as a way to get a starting point for an editing command, but only very trivial functions can be written that way anyway - and they are just as well written and saved as a series of keystrokes as they do now. This feature would not be useful for people like you and me. It is meant for people who are just starting to use Lisp. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 20:04 ` Stefan Monnier 2007-10-27 21:22 ` Kim F. Storm @ 2007-10-27 21:45 ` Juri Linkov 2007-10-28 1:14 ` Stefan Monnier ` (2 more replies) 1 sibling, 3 replies; 37+ messages in thread From: Juri Linkov @ 2007-10-27 21:45 UTC (permalink / raw) To: Stefan Monnier; +Cc: yzhh, emacs-devel >> Thank you for your appreciation. But my modification is in the C code of >> emacs, because 'execute-command' and 'call-interactively' are in C code. >> And I don't think my dirty code would be a valid patch for the emacs >> developers. > > I think what was expected was to first record a keyboard macro and later to > turn that into elisp code. That's was exactly my first attempt when I tried to implement this feature. However, this approach doesn't work because a macro highly depends on its context, and will fail when repeating it in different buffers, modes, etc. > Another approach is to use a pre-command-hook to record the value of > `this-command' for each command run. After failing with the first approach, I tried to do this, but this doesn't work because `this-command' doesn't record the arguments of the last command. So when I added a new variable `this-command-args' that records the arguments of the command being executed, this approach produced good results. Also I added a new variable `last-kbd-macro-commands', and a new command `insert-last-kbd-macro-commands' to convert the recorded commands with their arguments to a Lisp function. A change in isearch was also required to convert all isearch subcommands into one search function. Since yzhh doesn't want to post his code, I will post mine. I ask yzhh to comment on this code, compare with his own, and suggest further improvements: Index: src/callint.c =================================================================== RCS file: /sources/emacs/emacs/src/callint.c,v retrieving revision 1.157 diff -c -r1.157 callint.c *** src/callint.c 13 Sep 2007 05:50:11 -0000 1.157 --- src/callint.c 27 Oct 2007 21:44:37 -0000 *************** *** 42,47 **** --- 42,48 ---- extern Lisp_Object Vhistory_length; extern Lisp_Object Vthis_original_command, real_this_command; + extern Lisp_Object Vthis_command_args; Lisp_Object Vcommand_debug_status, Qcommand_debug_status; Lisp_Object Qenable_recursive_minibuffers; *************** *** 364,369 **** --- 365,373 ---- and turn them into things we can eval. */ values = quotify_args (Fcopy_sequence (specs)); fix_command (input, values); + + Vthis_command_args = values; + Vcommand_history = Fcons (Fcons (function, values), Vcommand_history); *************** *** 808,813 **** --- 812,820 ---- else visargs[i] = quotify_arg (args[i]); } + + Vthis_command_args = XCDR (Flist (count + 1, visargs)); + Vcommand_history = Fcons (Flist (count + 1, visargs), Vcommand_history); /* Don't keep command history around forever. */ *************** *** 832,837 **** --- 839,846 ---- Vthis_original_command = save_this_original_command; real_this_command= save_real_this_command; current_kboard->Vlast_command = save_last_command; + if (NILP (Vthis_command_args)) + Vthis_command_args = XCDR (Flist (count + 1, args)); { Lisp_Object val; Index: src/keyboard.c =================================================================== RCS file: /sources/emacs/emacs/src/keyboard.c,v retrieving revision 1.924 diff -c -r1.924 keyboard.c *** src/keyboard.c 18 Oct 2007 22:07:33 -0000 1.924 --- src/keyboard.c 27 Oct 2007 21:44:41 -0000 *************** *** 371,376 **** --- 371,379 ---- command is stored in this-original-command. It is nil otherwise. */ Lisp_Object Vthis_original_command; + /* The arguments of the command being executed by the command loop. */ + Lisp_Object Vthis_command_args; + /* The value of point when the last command was started. */ int last_point_position; *************** *** 1765,1770 **** --- 1768,1774 ---- Vthis_command = cmd; real_this_command = cmd; + Vthis_command_args = Qnil; /* Note that the value cell will never directly contain nil if the symbol is a local variable. */ if (!NILP (Vpre_command_hook) && !NILP (Vrun_hooks)) *************** *** 1798,1803 **** --- 1802,1808 ---- = window_display_table (XWINDOW (selected_window)); lose = FETCH_CHAR (PT_BYTE); SET_PT (PT + 1); + Vthis_command_args = Fcons (Vcurrent_prefix_arg, Qnil); if (! NILP (Vpost_command_hook)) /* Put this before calling adjust_point_for_property so it will only get called once in any case. */ *************** *** 1838,1843 **** --- 1843,1849 ---- = window_display_table (XWINDOW (selected_window)); SET_PT (PT - 1); lose = FETCH_CHAR (PT_BYTE); + Vthis_command_args = Fcons (Vcurrent_prefix_arg, Qnil); if (! NILP (Vpost_command_hook)) goto directly_done; if (current_buffer == prev_buffer *************** *** 1905,1910 **** --- 1911,1917 ---- if (value == 2) nonundocount = 0; + Vthis_command_args = Fcons (make_number (c), Fcons (Vcurrent_prefix_arg, Qnil)); if (! NILP (Vpost_command_hook)) /* Put this before calling adjust_point_for_property so it will only get called once in any case. */ *************** *** 3183,3189 **** #endif last_input_char = c; ! Fcommand_execute (tem, Qnil, Fvector (1, &last_input_char), Qt); if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time) /* We stopped being idle for this event; undo that. This --- 3190,3197 ---- #endif last_input_char = c; ! Fcommand_execute (tem, Qnil, /* Qt, */ ! Fvector (1, &last_input_char), Qt); if (CONSP (c) && EQ (XCAR (c), Qselect_window) && !end_time) /* We stopped being idle for this event; undo that. This *************** *** 12000,12005 **** --- 12008,12017 ---- result of looking up the original command in the active keymaps. */); Vthis_original_command = Qnil; + DEFVAR_LISP ("this-command-args", &Vthis_command_args, + doc: /* Arguments of the command being executed. */); + Vthis_command_args = Qnil; + DEFVAR_INT ("auto-save-interval", &auto_save_interval, doc: /* *Number of input events between auto-saves. Zero means disable autosaving due to number of characters typed. */); Index: lisp/kmacro.el =================================================================== RCS file: /sources/emacs/emacs/lisp/kmacro.el,v retrieving revision 1.40 diff -c -r1.40 kmacro.el *** lisp/kmacro.el 26 Jul 2007 05:26:27 -0000 1.40 --- lisp/kmacro.el 27 Oct 2007 21:44:40 -0000 *************** *** 538,545 **** (put 'kmacro-delete-ring-head 'kmacro-repeat 'head) ! ;;; Traditional bindings: ;;;###autoload (defun kmacro-start-macro (arg) --- 538,548 ---- (put 'kmacro-delete-ring-head 'kmacro-repeat 'head) ! (defvar last-kbd-macro-commands nil ! "List of recorded commands executed during macro definition. ! Each command is represented as a form to evaluate.") + ;;; Traditional bindings: ;;;###autoload (defun kmacro-start-macro (arg) *************** *** 580,592 **** kmacro-counter-format kmacro-default-counter-format kmacro-counter-format-start kmacro-default-counter-format)) (start-kbd-macro append (and append (if kmacro-execute-before-append (> (car arg) 4) (= (car arg) 4)))) (if (and defining-kbd-macro append) ! (setq defining-kbd-macro 'append))))) ;;;###autoload --- 583,599 ---- kmacro-counter-format kmacro-default-counter-format kmacro-counter-format-start kmacro-default-counter-format)) + (add-hook 'post-command-hook 'kmacro-record-command t) + (add-hook 'kbd-macro-termination-hook 'kmacro-record-termination) + (start-kbd-macro append (and append (if kmacro-execute-before-append (> (car arg) 4) (= (car arg) 4)))) (if (and defining-kbd-macro append) ! (setq defining-kbd-macro 'append) ! (setq last-kbd-macro-commands nil))))) ;;;###autoload *************** *** 605,610 **** --- 612,618 ---- ;; Just ignore it when executing the macro. (unless executing-kbd-macro (end-kbd-macro arg #'kmacro-loop-setup-function) + (kmacro-record-termination) (when (and last-kbd-macro (= (length last-kbd-macro) 0)) (setq last-kbd-macro nil) (message "Ignore empty macro") *************** *** 901,906 **** --- 909,955 ---- (kmacro-push-ring) (edit-kbd-macro "\C-hl")) + ;;; Macro commands recording + + (defun kmacro-record-command () + (unless (active-minibuffer-window) + (setq last-kbd-macro-commands (cons (cons this-command this-command-args) + last-kbd-macro-commands)))) + + (defun kmacro-record-termination () + (remove-hook 'post-command-hook 'kmacro-record-command) + (remove-hook 'kbd-macro-termination-hook 'kmacro-record-termination)) + + (defun insert-last-kbd-macro-commands () + (interactive) + (insert (pp-to-string + `(defun last-kbd-macro-commands () + "Command created from the last keyboard macro." + (interactive) + ,@(kmacro-convert-macro-commands last-kbd-macro-commands))))) + + (defun kmacro-convert-macro-commands (commands) + (let ((cmds commands) cmd name ret) + (while cmds + (setq cmd (car cmds)) + (setq name (car cmd)) + (cond + ;; skip next commands + ((memq name '(kmacro-start-macro + universal-argument universal-argument-other-key + digit-argument + isearch-forward isearch-backward + isearch-forward-regexp isearch-backward-regexp + isearch-printing-char isearch-other-control-char + isearch-repeat-forward isearch-repeat-backward + isearch-delete-char isearch-exit + ))) + ((eq name 'self-insert-command) + (push `(insert-char ,(nth 1 cmd) ,(or (nth 2 cmd) 1) ) ret)) + (t (push cmd ret))) + (setq cmds (cdr cmds))) + ret)) ;;; Single-step editing of keyboard macros Index: lisp/isearch.el =================================================================== RCS file: /sources/emacs/emacs/lisp/isearch.el,v retrieving revision 1.304 diff -u -r1.304 isearch.el --- lisp/isearch.el 22 Oct 2007 23:44:29 -0000 1.304 +++ lisp/isearch.el 27 Oct 2007 21:44:03 -0000 *** 761,766 **** --- 761,768 ---- ;; part of the composition has just been searched. (setq disable-point-adjustment t)) + (defvar last-kbd-macro-commands) + (defun isearch-done (&optional nopush edit) "Exit Isearch mode. For successful search, pass no args. *************** *** 776,781 **** --- 778,794 ---- (unless (equal (car command-history) command) (setq command-history (cons command command-history))))) + (if (and (boundp 'last-kbd-macro-commands) defining-kbd-macro) + (push (list + (cond (isearch-regexp + (if isearch-forward 're-search-forward 're-search-backward)) + (isearch-word + (if isearch-forward 'word-search-forward 'word-search-backward)) + (t + (if isearch-forward 'search-forward 'search-backward))) + isearch-string nil t) + last-kbd-macro-commands)) + (remove-hook 'mouse-leave-buffer-hook 'isearch-done) (remove-hook 'kbd-macro-termination-hook 'isearch-done) (setq isearch-lazy-highlight-start nil) -- Juri Linkov http://www.jurta.org/emacs/ ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 21:45 ` Juri Linkov @ 2007-10-28 1:14 ` Stefan Monnier 2007-10-28 1:34 ` Juri Linkov 2007-10-28 6:49 ` yzhh 2007-10-28 13:50 ` Richard Stallman 2 siblings, 1 reply; 37+ messages in thread From: Stefan Monnier @ 2007-10-28 1:14 UTC (permalink / raw) To: Juri Linkov; +Cc: yzhh, emacs-devel >>> Thank you for your appreciation. But my modification is in the C code of >>> emacs, because 'execute-command' and 'call-interactively' are in C code. >>> And I don't think my dirty code would be a valid patch for the emacs >>> developers. >> >> I think what was expected was to first record a keyboard macro and later to >> turn that into elisp code. > That's was exactly my first attempt when I tried to implement this feature. > However, this approach doesn't work because a macro highly depends on its > context, and will fail when repeating it in different buffers, modes, etc. I think this doesn't matter: the same holds for the keyboard macros themselves and yet they're quite usable. The limitation of the approach (that the macro needs to be converted to Elisp in the same context where it was recorded) doesn't seem to be too serious: at least not a show-stopper. OTOH I do expect that it can be very tricky to recover the structure from just the key sequence: e.g. after a keybinding that may or may not present a minibuffer prompt, figuring out whether the rest of the keys were sent to the minibuffer or to the next command can be impossible without guessing. >> Another approach is to use a pre-command-hook to record the value of >> `this-command' for each command run. > After failing with the first approach, I tried to do this, but this doesn't > work because `this-command' doesn't record the arguments of the last > command. So when I added a new variable `this-command-args' that records > the arguments of the command being executed, this approach produced > good results. > Also I added a new variable `last-kbd-macro-commands', and a new command > `insert-last-kbd-macro-commands' to convert the recorded commands with > their arguments to a Lisp function. A change in isearch was also required > to convert all isearch subcommands into one search function. > Since yzhh doesn't want to post his code, I will post mine. > I ask yzhh to comment on this code, compare with his own, > and suggest further improvements: This doesn't sound too bad. Another approach would be to advise `call-interactively'. This may require changes at the C level so as to make sure that calls to Fcall_interactively are never made directly but always go through the `call-interactively' symbol. With an exhaustive around advice on call-interactively, you should be able to get a fairly reliable trace. But even a reliable trace will encounter the problems mentioned by Kim, and in order to get /good/ Elisp code (rather than just /working/ Elisp code), a fair bit of post-processing will be needed with ad-hoc rewrites. Stefan ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 1:14 ` Stefan Monnier @ 2007-10-28 1:34 ` Juri Linkov 2007-10-29 0:11 ` Richard Stallman 0 siblings, 1 reply; 37+ messages in thread From: Juri Linkov @ 2007-10-28 1:34 UTC (permalink / raw) To: Stefan Monnier; +Cc: yzhh, emacs-devel > OTOH I do expect that it can be very tricky to recover the structure from > just the key sequence: e.g. after a keybinding that may or may not present > a minibuffer prompt, figuring out whether the rest of the keys were sent to > the minibuffer or to the next command can be impossible without guessing. Yes, and in the converted Lisp programs emulating the logic of minibuffer processing is useless. What would be useful to generate in Lisp programs are executed commands with their arguments no matter how these arguments were specified by the user. > This doesn't sound too bad. Another approach would be to advise > `call-interactively'. > > This may require changes at the C level so as to make sure that calls to > Fcall_interactively are never made directly but always go through the > `call-interactively' symbol. > > With an exhaustive around advice on call-interactively, you should be > able to get a fairly reliable trace. But `call-interactively' doesn't have an argument that contains the arguments of the called command. I think we should avoid generating Lisp code that read command arguments. > But even a reliable trace will encounter the problems mentioned by Kim, and > in order to get /good/ Elisp code (rather than just /working/ Elisp code), > a fair bit of post-processing will be needed with ad-hoc rewrites. I think the goal is not to produce Lisp code exactly equivalent to the keyboard macro, but a useful basis for writing a new Lisp function. -- Juri Linkov http://www.jurta.org/emacs/ ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 1:34 ` Juri Linkov @ 2007-10-29 0:11 ` Richard Stallman 0 siblings, 0 replies; 37+ messages in thread From: Richard Stallman @ 2007-10-29 0:11 UTC (permalink / raw) To: Juri Linkov; +Cc: yezonghui, monnier, emacs-devel I think the goal is not to produce Lisp code exactly equivalent to the keyboard macro, but a useful basis for writing a new Lisp function. That is right. Thus, we don't want all the effects of all pre-command-hooks and post-command-hooks to be included. We want that only for cases like Delete Selection mode where the user will think of them as part of the meaning of the command. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 21:45 ` Juri Linkov 2007-10-28 1:14 ` Stefan Monnier @ 2007-10-28 6:49 ` yzhh 2007-10-28 7:13 ` yzhh 2007-10-28 10:54 ` Juri Linkov 2007-10-28 13:50 ` Richard Stallman 2 siblings, 2 replies; 37+ messages in thread From: yzhh @ 2007-10-28 6:49 UTC (permalink / raw) To: emacs-devel Juri Linkov <juri <at> jurta.org> writes: > > I think what was expected was to first record a keyboard macro and later to > > turn that into elisp code. > > That's was exactly my first attempt when I tried to implement this feature. > However, this approach doesn't work because a macro highly depends on its > context, and will fail when repeating it in different buffers, modes, etc. I agree. Keymap changes caused by mode/buffer changes DURING the recording can messup the "translation". So I didn't try this in the first place :) > > Another approach is to use a pre-command-hook to record the value of > > `this-command' for each command run. > > After failing with the first approach, I tried to do this, but this doesn't > work because `this-command' doesn't record the arguments of the last > command. So when I added a new variable `this-command-args' that records > the arguments of the command being executed, this approach produced > good results. > > Also I added a new variable `last-kbd-macro-commands', and a new command > `insert-last-kbd-macro-commands' to convert the recorded commands with > their arguments to a Lisp function. A change in isearch was also required > to convert all isearch subcommands into one search function. This approach looks quite promising. I vote for this. > Since yzhh doesn't want to post his code, I will post mine. > I ask yzhh to comment on this code, compare with his own, > and suggest further improvements: Great work Juri! I'm actually busy on work these days. As soon as I have time I'll investigate your code and give any suggestion I can. Hope this will progress into something in the emacs CVS. And inspired by you and others, I post my code here. Basically, I did these: Add a variable (V)kbd-macro-command-history, insert commands into it on ervey ocurrence of possible insertion into command-history (that's guarded by record_flag), when defining-kbd-macro is on. So it's not complete. You have to M-x eval-expression kbd-macro-command-history to see the recorded thing, in reverse order. And its length is guarded by history-length. regards, yzhh ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 6:49 ` yzhh @ 2007-10-28 7:13 ` yzhh 2007-10-28 10:54 ` Juri Linkov 1 sibling, 0 replies; 37+ messages in thread From: yzhh @ 2007-10-28 7:13 UTC (permalink / raw) To: emacs-devel Ah, I forgot the code: Index: src/keyboard.c =================================================================== --- src/keyboard.c (revision 4) +++ src/keyboard.c (revision 7) @@ -10020,6 +10020,24 @@ } } This approach looks quite promising. Index: src/keyboard.c =================================================================== --- src/keyboard.c (revision 4) +++ src/keyboard.c (revision 7) @@ -10020,6 +10020,24 @@ } } + /* Record every command for kbd macro's purpose. */ + if (!NILP (current_kboard->defining_kbd_macro) + && NILP (Vexecuting_kbd_macro)) + { + Vkbd_macro_command_history + = Fcons (Fcons (Qexecute_kbd_macro, + Fcons (final, Fcons (prefixarg, Qnil))), + Vkbd_macro_command_history); + + /* Don't keep command history around forever. */ + if (NUMBERP (Vhistory_length) && XINT (Vhistory_length) > 0) + { + tem = Fnthcdr (Vhistory_length, Vkbd_macro_command_history); + if (CONSP (tem)) + XSETCDR (tem, Qnil); + } + } + return Fexecute_kbd_macro (final, prefixarg, Qnil); } Index: src/lisp.h =================================================================== --- src/lisp.h (revision 4) +++ src/lisp.h (revision 7) @@ -2945,6 +2945,7 @@ extern Lisp_Object Qminus, Qplus, Vcurrent_prefix_arg; extern Lisp_Object Vcommand_history; +extern Lisp_Object Vkbd_macro_command_history; extern Lisp_Object Qcall_interactively, Qmouse_leave_buffer_hook; EXFUN (Fcall_interactively, 3); EXFUN (Fprefix_numeric_value, 1); Index: src/callint.c =================================================================== --- src/callint.c (revision 4) +++ src/callint.c (revision 7) @@ -39,6 +39,7 @@ Lisp_Object Vcurrent_prefix_arg, Qminus, Qplus; Lisp_Object Qcall_interactively; Lisp_Object Vcommand_history; +Lisp_Object Vkbd_macro_command_history; extern Lisp_Object Vhistory_length; extern Lisp_Object Vthis_original_command, real_this_command; @@ -377,6 +378,7 @@ GCPRO2 (input, filter_specs); specs = Feval (specs); UNGCPRO; + if (i != num_input_events || !NILP (record_flag)) { /* We should record this command on the command history. */ @@ -397,6 +399,28 @@ } } + /* Record every command for kbd macro's purpose. */ + if ((i != num_input_events) + || (!NILP (current_kboard->defining_kbd_macro) + && NILP (Vexecuting_kbd_macro))) + { + Lisp_Object values; + /* Make a copy of the list of values, for the command history, + and turn them into things we can eval. */ + values = quotify_args (Fcopy_sequence (specs)); + fix_command (input, values); + Vkbd_macro_command_history + = Fcons (Fcons (function, values), Vkbd_macro_command_history); + + /* Don't keep command history around forever. */ + if (INTEGERP (Vhistory_length) && XINT (Vhistory_length) > 0) + { + teml = Fnthcdr (Vhistory_length, Vkbd_macro_command_history); + if (CONSP (teml)) + XSETCDR (teml, Qnil); + } + } + Vthis_command = save_this_command; Vthis_original_command = save_this_original_command; real_this_command= save_real_this_command; @@ -837,6 +861,30 @@ } } + /* Record every command for kbd macro's purpose. */ + if (arg_from_tty || (!NILP (current_kboard->defining_kbd_macro) + && NILP (Vexecuting_kbd_macro))) + { + visargs[0] = function; + for (i = 1; i < count + 1; i++) + { + if (varies[i] > 0) + visargs[i] = Fcons (intern (callint_argfuns[varies[i]]), Qnil); + else + visargs[i] = quotify_arg (args[i]); + } + Vkbd_macro_command_history = Fcons (Flist (count + 1, visargs), + Vkbd_macro_command_history); + /* Don't keep command history around forever. */ + if (INTEGERP (Vhistory_length) && XINT (Vhistory_length) > 0) + { + teml = Fnthcdr (Vhistory_length, Vkbd_macro_command_history); + if (CONSP (teml)) + XSETCDR (teml, Qnil); + } + } + + /* If we used a marker to hold point, mark, or an end of the region, temporarily, convert it to an integer now. */ for (i = 1; i <= count; i++) @@ -963,6 +1011,11 @@ Each command is represented as a form to evaluate. */); Vcommand_history = Qnil; + DEFVAR_LISP ("kbd-macro-command-history", &Vkbd_macro_command_history, + doc: /* List of commands recorded in the last keyboard macro. +Each command is represented as a form to evaluate. */); + Vkbd_macro_command_history = Qnil; + DEFVAR_LISP ("command-debug-status", &Vcommand_debug_status, doc: /* Debugging status of current interactive command. Bound each time `call-interactively' is called; ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 6:49 ` yzhh 2007-10-28 7:13 ` yzhh @ 2007-10-28 10:54 ` Juri Linkov 1 sibling, 0 replies; 37+ messages in thread From: Juri Linkov @ 2007-10-28 10:54 UTC (permalink / raw) To: yzhh; +Cc: emacs-devel > Basically, I did these: > Add a variable (V)kbd-macro-command-history, insert commands into it on ervey > ocurrence of possible insertion into command-history (that's guarded by > record_flag), when defining-kbd-macro is on. So it's not complete. You have to > M-x eval-expression kbd-macro-command-history to see the recorded thing, in > reverse order. And its length is guarded by history-length. Thanks for your code! I see you collect executed commands together with their arguments into a new list of commands. This is fine. But I think it's better to add a new variable `this-command-args' that contains the arguments of the current command because this variable could be useful for other purposes as well, and it allows collecting commands with their arguments in Lisp that improves the flexibility of this approach. -- Juri Linkov http://www.jurta.org/emacs/ ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 21:45 ` Juri Linkov 2007-10-28 1:14 ` Stefan Monnier 2007-10-28 6:49 ` yzhh @ 2007-10-28 13:50 ` Richard Stallman 2007-10-28 15:09 ` Juri Linkov 2007-10-28 16:13 ` yzhh 2 siblings, 2 replies; 37+ messages in thread From: Richard Stallman @ 2007-10-28 13:50 UTC (permalink / raw) To: Juri Linkov; +Cc: yezonghui, monnier, emacs-devel That's was exactly my first attempt when I tried to implement this feature. However, this approach doesn't work because a macro highly depends on its context, and will fail when repeating it in different buffers, modes, etc. We expect this conversion to use the keymaps that Emacs has when you do the conversion. That is a feature, not a bug. Also I added a new variable `last-kbd-macro-commands', and a new command `insert-last-kbd-macro-commands' to convert the recorded commands with their arguments to a Lisp function. The way you have written this, it looks like it cannot convert an existing keyboard macro. The user has to type the definition over again. That is a big drawback. Can you make this work by replaying the macro? At least then it would be possible to convert an existing macro. We want to do more simplification of the generated Lisp code; for instance, to combine multiple calls to self-insert-command into something more elegant. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 13:50 ` Richard Stallman @ 2007-10-28 15:09 ` Juri Linkov 2007-10-29 9:21 ` Richard Stallman 2007-10-28 16:13 ` yzhh 1 sibling, 1 reply; 37+ messages in thread From: Juri Linkov @ 2007-10-28 15:09 UTC (permalink / raw) To: rms; +Cc: yezonghui, monnier, emacs-devel > Also I added a new variable `last-kbd-macro-commands', and a new command > `insert-last-kbd-macro-commands' to convert the recorded commands with > their arguments to a Lisp function. > > The way you have written this, it looks like it cannot convert an > existing keyboard macro. The user has to type the definition over > again. That is a big drawback. It preserves Lisp code of the last defined macro. I think this is enough for this feature to be useful. If not, we could keep the converted Lisp code with every macro definition. > Can you make this work by replaying the macro? At least then > it would be possible to convert an existing macro. This is easy to implement, but replaying the macro is not always possible. > We want to do more simplification of the generated Lisp code; > for instance, to combine multiple calls to self-insert-command > into something more elegant. I agree. A function `kmacro-convert-macro-commands' in my patch is intended for such simplifications. -- Juri Linkov http://www.jurta.org/emacs/ ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 15:09 ` Juri Linkov @ 2007-10-29 9:21 ` Richard Stallman 0 siblings, 0 replies; 37+ messages in thread From: Richard Stallman @ 2007-10-29 9:21 UTC (permalink / raw) To: Juri Linkov; +Cc: yezonghui, monnier, emacs-devel > Can you make this work by replaying the macro? At least then > it would be possible to convert an existing macro. This is easy to implement, but replaying the macro is not always possible. Why not? It seems to me that if you can define the macro over again, you can replay it. (Either way, it will carry out the actions of the macro.) Replaying the macro is less work than typing it again. Therefore, if this feature operates by executing the commands in the macro, it should do so by replaying. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 13:50 ` Richard Stallman 2007-10-28 15:09 ` Juri Linkov @ 2007-10-28 16:13 ` yzhh 2007-10-28 16:48 ` Juri Linkov 2007-10-29 9:21 ` Richard Stallman 1 sibling, 2 replies; 37+ messages in thread From: yzhh @ 2007-10-28 16:13 UTC (permalink / raw) To: emacs-devel Richard Stallman <rms <at> gnu.org> writes: > We expect this conversion to use the keymaps that Emacs has when you > do the conversion. That is a feature, not a bug. I can give an example that reveals another complication of the "translate using keymaps" approach. The following: M-x ;; execute-extended-command repla ;; self-insert-command * 5 2*TAB ;; lisp-indent-line str ;; self-insert-command * 3 TAB ;; lisp-indent-line RET ;; newline is ;; self-insert-command * 2 RET ;; newline IS ;; self-insert-command * 2 RET ;; newline is a kbd macro I recorded for M-x replace-string is -> IS. The complication is with the TAB completion - it would require total knowledge about TAB completion to reconstruct the command name - what edit-kbd-macro doesn't do. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 16:13 ` yzhh @ 2007-10-28 16:48 ` Juri Linkov 2007-10-29 9:21 ` Richard Stallman 1 sibling, 0 replies; 37+ messages in thread From: Juri Linkov @ 2007-10-28 16:48 UTC (permalink / raw) To: yzhh; +Cc: emacs-devel > I can give an example that reveals another complication of the "translate using > keymaps" approach. The following: > > M-x ;; execute-extended-command > repla ;; self-insert-command * 5 > 2*TAB ;; lisp-indent-line > str ;; self-insert-command * 3 > TAB ;; lisp-indent-line > RET ;; newline > is ;; self-insert-command * 2 > RET ;; newline > IS ;; self-insert-command * 2 > RET ;; newline > > is a kbd macro I recorded for M-x replace-string is -> IS. The complication is > with the TAB completion - it would require total knowledge about TAB completion > to reconstruct the command name - what edit-kbd-macro doesn't do. I agree. It makes no sense to generate Lisp code for minibuffer completion and other minibuffer reading functions. What would be useful to generate in Lisp code is the final command with its arguments: (replace-string "is" "IS") -- Juri Linkov http://www.jurta.org/emacs/ ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 16:13 ` yzhh 2007-10-28 16:48 ` Juri Linkov @ 2007-10-29 9:21 ` Richard Stallman 2007-10-30 14:14 ` Juri Linkov 1 sibling, 1 reply; 37+ messages in thread From: Richard Stallman @ 2007-10-29 9:21 UTC (permalink / raw) To: yzhh; +Cc: emacs-devel is a kbd macro I recorded for M-x replace-string is -> IS. The complication is with the TAB completion - it would require total knowledge about TAB completion to reconstruct the command name - what edit-kbd-macro doesn't do. That is a real issue, which I had not thought about before. This is a case which is easier to handle if you record the actual arguments. On the other hand, just recording the actual value of the argument is also sometimes wrong. Suppose you mark text in a buffer and copy it into the minibuffer as part of the macro. The Lisp program ought to copy the text too. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-29 9:21 ` Richard Stallman @ 2007-10-30 14:14 ` Juri Linkov 2007-10-31 7:46 ` Richard Stallman 0 siblings, 1 reply; 37+ messages in thread From: Juri Linkov @ 2007-10-30 14:14 UTC (permalink / raw) To: rms; +Cc: yzhh, emacs-devel > is a kbd macro I recorded for M-x replace-string is -> IS. The > complication is with the TAB completion - it would require total > knowledge about TAB completion to reconstruct the command name - > what edit-kbd-macro doesn't do. > > That is a real issue, which I had not thought about before. This is a > case which is easier to handle if you record the actual arguments. > > On the other hand, just recording the actual value of the argument > is also sometimes wrong. Suppose you mark text in a buffer and > copy it into the minibuffer as part of the macro. The Lisp program > ought to copy the text too. Recording the actual arguments is a useful and clean solution, but trying to emulate the logic of minibuffer processing will produce ugly and complicated Lisp code. -- Juri Linkov http://www.jurta.org/emacs/ ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-30 14:14 ` Juri Linkov @ 2007-10-31 7:46 ` Richard Stallman 0 siblings, 0 replies; 37+ messages in thread From: Richard Stallman @ 2007-10-31 7:46 UTC (permalink / raw) To: Juri Linkov; +Cc: yezonghui, emacs-devel > On the other hand, just recording the actual value of the argument > is also sometimes wrong. Suppose you mark text in a buffer and > copy it into the minibuffer as part of the macro. The Lisp program > ought to copy the text too. Recording the actual arguments is a useful and clean solution, but trying to emulate the logic of minibuffer processing will produce ugly and complicated Lisp code. We need to give it a try. If we avoid being perfectionist, it may be easy to give good results in simple usual cases. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 15:48 ` Robert J. Chassell 2007-10-27 17:30 ` yzhh @ 2007-10-27 19:26 ` Jay Belanger 1 sibling, 0 replies; 37+ messages in thread From: Jay Belanger @ 2007-10-27 19:26 UTC (permalink / raw) To: emacs-devel; +Cc: jay.p.belanger "Robert J. Chassell" <bob@rattlesnake.com> writes: ... > (Jay Belanger: do you have really old copies of Calc mode, such as > the first that Dave Gillespie distributed? No, but in the past I've looked for old copies. comp.sources.misc, at least the Google archives, have Calc 2.00 sources, and patches between earlier versions, but not the sources for any earlier version. If anyone knows where to get old copies of Calc, please let me know. > I think that has the capability, but I could be wrong. It has been > a very long time. The files README and README.prev, which mention the changes between the various Calc versions, sometimes mention things that are removed. Those files don't mention any macro to lisp features, but that certainly isn't conclusive. The removal of macedit.el in favor of Emacs's edmacro is mentioned. Jay ^ permalink raw reply [flat|nested] 37+ messages in thread
* RE: Is there a plan to record kbd macro as elisp code? 2007-10-27 9:28 Is there a plan to record kbd macro as elisp code? yzhh 2007-10-27 15:48 ` Robert J. Chassell @ 2007-10-27 16:20 ` Drew Adams 2007-10-27 17:13 ` yzhh 2007-10-28 13:50 ` Richard Stallman 2007-10-29 6:41 ` Klaus Zeitler 2 siblings, 2 replies; 37+ messages in thread From: Drew Adams @ 2007-10-27 16:20 UTC (permalink / raw) To: yzhh, emacs-devel > Recording kbd macro as elisp code can be useful. The following are some > benefits: > 1. Editing elisp code is more clear than editing key sequences, > and supports complex controlstructures. > 2. elisp code is more portable than key sequences. Sharing with > others who have different key bindings is ok for elisp, but not > for key sequences. > 3. It can be used as a means ot learn emacs commands in elisp form. > > I tried to build a modified emacs that stores every command sent to > 'execute-command' into a list, when 'defining-kbd-macro' is on. But the > result is a list that still leaves out things like horizontal movements. > And isearch is not recorded right (one search recorded as many isearch > commands, without information of what's being searched). > > So I know the modification required is not simple, far beyond a quick and > dirty patch. > > Out of curiosity I want to know whether there is a plan for this > feature in the future. IIRC, there used to be such a feature, bound to `C-x [' and `C-x ]' I think. It generated Elisp for the defined macro. Worked pretty well - gave you at least a skeleton you could complete to make a proper command definition. Unless it was in Epoch or Gosling Emacs. It's been a while... I think the command name was `gen-' something, but I can't find anything about this in Google - perhaps I'm not a good googler. The Emacs Lisp List has this entry, but the link appears to be dead: macro-generate.el --- [Turn a keyboard macro into lisp code.] Contact: [unknown]. Perhaps that was what I was thinking of. This is the (dead?) URL: http://www.dtek.chalmers.se/~d3rydma/Hack/emacs/Archive/macro-generate.el. And this page (http://www.bookshelf.jp/soft/meadow_46.html#SEC669) mentions in connection with macro-generate.el, commands `gen-start-generating', `gen-stop-generating', and `gen-expand-macro'. I think this was what I used to use. Perhaps you can find it somewhere else on the Web - I couldn't. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 16:20 ` Drew Adams @ 2007-10-27 17:13 ` yzhh 2007-10-27 17:40 ` Drew Adams 2007-10-28 13:50 ` Richard Stallman 1 sibling, 1 reply; 37+ messages in thread From: yzhh @ 2007-10-27 17:13 UTC (permalink / raw) To: emacs-devel Drew Adams <drew.adams <at> oracle.com> writes: > IIRC, there used to be such a feature, bound to `C-x [' and `C-x ]' I think. > It generated Elisp for the defined macro. Worked pretty well - gave you at > least a skeleton you could complete to make a proper command definition. > > Unless it was in Epoch or Gosling Emacs. It's been a while... > > I think the command name was `gen-' something, but I can't find anything > about this in Google - perhaps I'm not a good googler. > > The Emacs Lisp List has this entry, but the link appears to be dead: > macro-generate.el --- [Turn a keyboard macro into lisp code.] Contact: > [unknown]. Perhaps that was what I was thinking of. This is the (dead?) URL: > http://www.dtek.chalmers.se/~d3rydma/Hack/emacs/Archive/macro-generate.el. > > And this page (http://www.bookshelf.jp/soft/meadow_46.html#SEC669) mentions > in connection with macro-generate.el, commands `gen-start-generating', > `gen-stop-generating', and `gen-expand-macro'. I think this was what I used > to use. Perhaps you can find it somewhere else on the Web - I couldn't. > I'm sorry I didn't mention the path I've gone through. Actually I've found a version of generate.el, which is made in 1989. It includes those functions with similar names you cited (without 'gen-' prefix). And I runs without an error in emacs22. But it leaves out too much commands in the generated code. I looked into generated.el's implementation, and found it actually reads command-history to get the code. And command-history itself is leaving out a lot commands. That's why I made those modifications, trying to get a complete command history. And then the story you've read. Please also read my reply to Robert. ^ permalink raw reply [flat|nested] 37+ messages in thread
* RE: Is there a plan to record kbd macro as elisp code? 2007-10-27 17:13 ` yzhh @ 2007-10-27 17:40 ` Drew Adams 2007-10-27 18:05 ` yzhh 2007-10-27 19:22 ` Robert J. Chassell 0 siblings, 2 replies; 37+ messages in thread From: Drew Adams @ 2007-10-27 17:40 UTC (permalink / raw) To: yzhh, emacs-devel > I'm sorry I didn't mention the path I've gone through. Actually > I've found a version of generate.el, which is made in 1989. It includes > those functions with similar names you cited (without 'gen-' prefix). > And I runs without an error in emacs22. But it leaves out too much > commands in the generated code. I looked into generated.el's > implementation, and found it actually reads command-history to get the > code. And command-history itself is leaving out a lot commands. > > That's why I made those modifications, trying to get a complete command > history. And then the story you've read. > > Please also read my reply to Robert. I didn't see your reply to Robert. Yes, I think now that it was generate.el I was thinking of. There appear to be different kinds of files with this same name, however (e.g. one that generates MPEG files). I guess the one you found is this? http://mirrors.wikifusion.info/gnu/elisp-archive/as-is/generate.el.Z Doesn't generate.el give you enough of a code skeleton to complete the command? You mention missing horizontal movement commands and a fragmented treatment of isearch, but it should be possible to patch up the code in those areas, no? Of course, if you could improve it, that would be even better. Good luck, and please post what you've got when you're done somewhere (e.g. gnu-emacs-sources, Emacs Wiki). ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 17:40 ` Drew Adams @ 2007-10-27 18:05 ` yzhh 2007-10-27 19:22 ` Robert J. Chassell 1 sibling, 0 replies; 37+ messages in thread From: yzhh @ 2007-10-27 18:05 UTC (permalink / raw) To: emacs-devel Drew Adams <drew.adams <at> oracle.com> writes: > I didn't see your reply to Robert. I wrote the one for you first. And you are so quick... > Yes, I think now that it was generate.el I was thinking of. There appear to > be different kinds of files with this same name, however (e.g. one that > generates MPEG files). I guess the one you found is this? > http://mirrors.wikifusion.info/gnu/elisp-archive/as-is/generate.el.Z Yes, that's exactly the one I have. > Doesn't generate.el give you enough of a code skeleton to complete the > command? You mention missing horizontal movement commands and a fragmented > treatment of isearch, but it should be possible to patch up the code in > those areas, no? Of course, if you could improve it, that would be even > better. Good luck, and please post what you've got when you're done > somewhere (e.g. gnu-emacs-sources, Emacs Wiki). > Yes, it's a good skeleton, which relies on command history. Now you should have saw my reply to Robert and understand the difficulties I see is not in generate.el. It's about a complete and correct command history that emacs seems not having been designed to provide. ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 17:40 ` Drew Adams 2007-10-27 18:05 ` yzhh @ 2007-10-27 19:22 ` Robert J. Chassell 2007-10-27 20:11 ` Drew Adams 1 sibling, 1 reply; 37+ messages in thread From: Robert J. Chassell @ 2007-10-27 19:22 UTC (permalink / raw) To: emacs-devel Thanks, Drew -- it turned out I had it, but I never thought of the name generate.el so I never discovered it. yzhh, I am glad you brought this up. It was not part of Calc but earlier. I was wrong to think it was part of Calc -- my apologies. My copy says ;;; module: generate.el ;;;; version: 2.0 ;;;; author: Ciaran A Byrne ciaran@gec-rl-hrc.co.uk ;;;; date: 2:Sept:87 That is 20 years ago! http://mirrors.wikifusion.info/gnu/elisp-archive/as-is/generate.el.Z provides the same library. It works both in Emacs 22 and in this morning's CVS snapshot of GNU Emacs 23.0.50! As Drew says, ... I'm just looking for a way for you to make your work into a useful contribution. Perhaps aim for something less than 100% complete, something that helps a user define a command based on a keyboard macro, but doesn't do that completely automatically. yzhh, doing that would be helpful. Many of my macros involve searches, but in Emacs Lisp I can change those instances to search-forward and re-search-forward. -- Robert J. Chassell GnuPG Key ID: 004B4AC8 bob@rattlesnake.com bob@gnu.org http://www.rattlesnake.com http://www.teak.cc ^ permalink raw reply [flat|nested] 37+ messages in thread
* RE: Is there a plan to record kbd macro as elisp code? 2007-10-27 19:22 ` Robert J. Chassell @ 2007-10-27 20:11 ` Drew Adams 0 siblings, 0 replies; 37+ messages in thread From: Drew Adams @ 2007-10-27 20:11 UTC (permalink / raw) To: bob, emacs-devel > Thanks, Drew -- it turned out I had it, but I never thought of the > name generate.el so I never discovered it. De nada. Bits and pieces of collective oldbie memory can be almost as good as a single newbie memory sometimes. I remembered the key bindings and the "gen" part of the command names; that's all. And I was wrong about the key bindings - I had probably bound them to `C-x [' and `C-x ]' because of the conflict with (the suggested) `C-x (' and `C-x )'. I no longer had the file myself. I tossed all Emacs files that weren't my own when I swam across the Atlantic many moon ago - too much baggage, and some of the files would have attracted sharks. I was thinking that this feature was part of Emacs, but that was mistaken. Perhaps Yzhh will fix up something that could be added to Emacs. I remember using this quite a bit back in the Middle Ages. > That is 20 years ago! Yup. We should get a gold medal just for surviving Emacs this long. Emacs should get a medal for surviving us this long too... Hey, I hear Richard's having a big 35th birthday party for Emacs in 2011 at his house! Ya'll come! ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 16:20 ` Drew Adams 2007-10-27 17:13 ` yzhh @ 2007-10-28 13:50 ` Richard Stallman 2007-10-28 16:45 ` Juri Linkov 1 sibling, 1 reply; 37+ messages in thread From: Richard Stallman @ 2007-10-28 13:50 UTC (permalink / raw) To: Drew Adams; +Cc: yezonghui, emacs-devel I think someone said within the past year that he had written such a feature. We did not install it at the time because we wanted to release 22.1. But we could install it now. Can anyone find old mail about that? ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-28 13:50 ` Richard Stallman @ 2007-10-28 16:45 ` Juri Linkov 0 siblings, 0 replies; 37+ messages in thread From: Juri Linkov @ 2007-10-28 16:45 UTC (permalink / raw) To: rms; +Cc: yezonghui, emacs-devel > I think someone said within the past year that he had written > such a feature. We did not install it at the time because > we wanted to release 22.1. But we could install it now. > > Can anyone find old mail about that? If no one else will replay to your request, then perhaps it was me. And I already sent a patch that implements this feature. -- Juri Linkov http://www.jurta.org/emacs/ ^ permalink raw reply [flat|nested] 37+ messages in thread
* Re: Is there a plan to record kbd macro as elisp code? 2007-10-27 9:28 Is there a plan to record kbd macro as elisp code? yzhh 2007-10-27 15:48 ` Robert J. Chassell 2007-10-27 16:20 ` Drew Adams @ 2007-10-29 6:41 ` Klaus Zeitler 2 siblings, 0 replies; 37+ messages in thread From: Klaus Zeitler @ 2007-10-29 6:41 UTC (permalink / raw) To: emacs-devel There's also a package called power-macros.el from Jesper K. Pedersen. http://www.blackie.dk/emacs/power-macros.el Cheers Klaus -- -------------------------------------------------- | Klaus Zeitler Alcatel-Lucent | | Email: kzeitler@alcatel-lucent.com | -------------------------------------------------- --- God put me on earth to accomplish a certain number of things. Right now I am so far behind I will never die. -- Bill Waterson, Calvin and Hobbes ^ permalink raw reply [flat|nested] 37+ messages in thread
end of thread, other threads:[~2007-10-31 7:46 UTC | newest] Thread overview: 37+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-10-27 9:28 Is there a plan to record kbd macro as elisp code? yzhh 2007-10-27 15:48 ` Robert J. Chassell 2007-10-27 17:30 ` yzhh 2007-10-27 18:01 ` Drew Adams 2007-10-28 13:50 ` Richard Stallman 2007-10-27 20:04 ` Stefan Monnier 2007-10-27 21:22 ` Kim F. Storm 2007-10-28 13:50 ` Richard Stallman 2007-10-28 22:00 ` Kim F. Storm 2007-10-29 5:20 ` yzhh 2007-10-29 9:22 ` Richard Stallman 2007-10-29 9:22 ` Richard Stallman 2007-10-27 21:45 ` Juri Linkov 2007-10-28 1:14 ` Stefan Monnier 2007-10-28 1:34 ` Juri Linkov 2007-10-29 0:11 ` Richard Stallman 2007-10-28 6:49 ` yzhh 2007-10-28 7:13 ` yzhh 2007-10-28 10:54 ` Juri Linkov 2007-10-28 13:50 ` Richard Stallman 2007-10-28 15:09 ` Juri Linkov 2007-10-29 9:21 ` Richard Stallman 2007-10-28 16:13 ` yzhh 2007-10-28 16:48 ` Juri Linkov 2007-10-29 9:21 ` Richard Stallman 2007-10-30 14:14 ` Juri Linkov 2007-10-31 7:46 ` Richard Stallman 2007-10-27 19:26 ` Jay Belanger 2007-10-27 16:20 ` Drew Adams 2007-10-27 17:13 ` yzhh 2007-10-27 17:40 ` Drew Adams 2007-10-27 18:05 ` yzhh 2007-10-27 19:22 ` Robert J. Chassell 2007-10-27 20:11 ` Drew Adams 2007-10-28 13:50 ` Richard Stallman 2007-10-28 16:45 ` Juri Linkov 2007-10-29 6:41 ` Klaus Zeitler
Code repositories for project(s) associated with this public inbox https://git.savannah.gnu.org/cgit/emacs.git This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).