emacs-devel
[Top][All Lists]
Advanced

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

Convert a keyboard macro to equivalent Lisp code


From: Juri Linkov
Subject: Convert a keyboard macro to equivalent Lisp code
Date: Sat, 05 Jun 2010 22:57:04 +0300
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/24.0.50 (x86_64-pc-linux-gnu)

There is no progress in implementing the task of conversion
a keyboard macro to equivalent Lisp code because we approached
this task with the "all-or-nothing" attitude.  We tried to find
the most difficult and controversial cases to justify not doing
even basic and straightforward things.

I propose to install the basic support for recording all commands
and their arguments that will allow everyone to experiment with
post-processing to convert the plain trace of executed Lisp commands
into something more useful.  (It's mainly the function
`kmacro-convert-command-history' that could be modified to produce
better results).

=== modified file 'lisp/macros.el'
--- lisp/macros.el      2010-03-03 17:31:50 +0000
+++ lisp/macros.el      2010-06-05 19:32:24 +0000
@@ -280,6 +280,41 @@
 
 ;;;###autoload (define-key ctl-x-map "q" 'kbd-macro-query)
 
+;;; Convert a keyboard macro to Lisp code.
+
+;;;###autoload
+(defun insert-last-kbd-macro-command-history ()
+  (interactive)
+  (insert
+   "(defun last-kbd-macro-command-history ()\n"
+   "  \"Command created from the last keyboard macro.\"\n")
+  (comment-region (prog1 (point)
+                   (insert "  Original keys: ")
+                   (insert-kbd-macro (intern "")))
+                 (point))
+  (insert "  (interactive)\n")
+  (dolist (s (kmacro-convert-command-history
+             last-kbd-macro-command-history))
+    (insert "  " (pp-to-string s)))
+  (insert ")\n"))
+
+(defun kmacro-convert-command-history (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 kmacro-end-macro
+                    universal-argument universal-argument-other-key
+                    digit-argument
+                    execute-extended-command
+                    )))
+       (t (push cmd ret)))
+      (setq cmds (cdr cmds)))
+    (nreverse ret)))
+
 (provide 'macros)
 
 ;; arch-tag: 346ed1a5-1220-4bc8-b533-961ee704361f

=== modified file 'src/callint.c'
--- src/callint.c       2010-03-23 16:25:12 +0000
+++ src/callint.c       2010-06-05 19:45:36 +0000
@@ -43,6 +43,7 @@
 
 extern Lisp_Object Vhistory_length;
 extern Lisp_Object Vthis_original_command, real_this_command;
+extern Lisp_Object Vthis_command_args;
 extern int history_delete_duplicates;
 
 Lisp_Object Vcommand_debug_status, Qcommand_debug_status;
@@ -326,7 +327,7 @@
 
   specs = Qnil;
   string = 0;
-  /* The idea of FILTER_SPECS is to provide away to
+  /* The idea of FILTER_SPECS is to provide a way to
      specify how to represent the arguments in command history.
      The feature is not fully implemented.  */
   filter_specs = Qnil;
@@ -357,23 +358,24 @@
     }
   else
     {
-      Lisp_Object input;
+      Lisp_Object input, values;
       i = num_input_events;
       input = specs;
       /* Compute the arg values using the user's expression.  */
       GCPRO2 (input, filter_specs);
       specs = Feval (specs);
       UNGCPRO;
+
+      /* 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);
+      Vthis_command_args = values;
+
       if (i != num_input_events || !NILP (record_flag))
        {
          /* We should record this command on the command history.  */
-         Lisp_Object values;
-         Lisp_Object this_cmd;
-         /* 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);
-         this_cmd = Fcons (function, values);
+         Lisp_Object this_cmd = Fcons (function, values);
          if (history_delete_duplicates)
            Vcommand_history = Fdelete (this_cmd, Vcommand_history);
          Vcommand_history = Fcons (this_cmd, Vcommand_history);
@@ -387,6 +389,15 @@
            }
        }
 
+      if (!NILP (current_kboard->defining_kbd_macro)
+         && ! (minibuf_level > 0))
+       {
+         /* We should record this command on the macro command history.  */
+         current_kboard->Vlast_kbd_macro_command_history
+           = Fcons (Fcons (function, values),
+                    current_kboard->Vlast_kbd_macro_command_history);
+       }
+
       Vthis_command = save_this_command;
       Vthis_original_command = save_this_original_command;
       real_this_command= save_real_this_command;
@@ -831,18 +842,24 @@
 
   args[0] = function;
 
+  /* Make a list of values, for the command history.  */
+  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]);
+    }
+  Vthis_command_args = Fcdr (Flist (count + 1, visargs));
+
   if (arg_from_tty || !NILP (record_flag))
     {
-      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]);
-       }
-      Vcommand_history = Fcons (Flist (count + 1, visargs),
-                               Vcommand_history);
+      /* We should record this command on the command history.  */
+      Lisp_Object this_cmd = Fcons (function, Vthis_command_args);
+      if (history_delete_duplicates)
+       Vcommand_history = Fdelete (this_cmd, Vcommand_history);
+      Vcommand_history = Fcons (this_cmd, Vcommand_history);
       /* Don't keep command history around forever.  */
       if (INTEGERP (Vhistory_length) && XINT (Vhistory_length) > 0)
        {
@@ -852,6 +869,14 @@
        }
     }
 
+  if (!NILP (current_kboard->defining_kbd_macro)
+      && ! (minibuf_level > 0))
+    {
+      current_kboard->Vlast_kbd_macro_command_history
+       = Fcons (Fcons (function, Vthis_command_args),
+                current_kboard->Vlast_kbd_macro_command_history);
+    }
+
   /* 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++)

=== modified file 'src/keyboard.c'
--- src/keyboard.c      2010-05-25 09:36:21 +0000
+++ src/keyboard.c      2010-06-05 19:33:02 +0000
@@ -339,6 +339,9 @@
    command is stored in this-original-command.  It is nil otherwise.  */
 Lisp_Object Vthis_original_command;
 
+/* 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;
 
@@ -1630,6 +1633,7 @@
       Vthis_command = Qnil;
       real_this_command = Qnil;
       Vthis_original_command = Qnil;
+      Vthis_command_args = Qnil;
       Vthis_command_keys_shift_translated = Qnil;
 
       /* Read next key sequence; i gets its length.  */
@@ -11471,6 +11475,7 @@
   kb->kbd_macro_bufsize = 0;
   kb->defining_kbd_macro = Qnil;
   kb->Vlast_kbd_macro = Qnil;
+  kb->Vlast_kbd_macro_command_history = Qnil;
   kb->reference_count = 0;
   kb->Vsystem_key_alist = Qnil;
   kb->system_key_syms = Qnil;
@@ -11990,6 +11995,10 @@
 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.  */);
@@ -12477,6 +12486,7 @@
       mark_object (kb->kbd_queue);
       mark_object (kb->defining_kbd_macro);
       mark_object (kb->Vlast_kbd_macro);
+      mark_object (kb->Vlast_kbd_macro_command_history);
       mark_object (kb->Vsystem_key_alist);
       mark_object (kb->system_key_syms);
       mark_object (kb->Vwindow_system);

=== modified file 'src/keyboard.h'
--- src/keyboard.h      2010-01-13 08:35:10 +0000
+++ src/keyboard.h      2010-06-05 19:32:07 +0000
@@ -122,6 +122,9 @@
     /* Last anonymous kbd macro defined.  */
     Lisp_Object Vlast_kbd_macro;
 
+    /* Command history of last anonymous kbd macro defined.  */
+    Lisp_Object Vlast_kbd_macro_command_history;
+
     /* Alist of system-specific X windows key symbols.  */
     Lisp_Object Vsystem_key_alist;
 

=== modified file 'src/macros.c'
--- src/macros.c        2010-01-13 08:35:10 +0000
+++ src/macros.c        2010-06-05 19:35:19 +0000
@@ -133,6 +133,7 @@
       message ("Appending to kbd macro...");
     }
   current_kboard->defining_kbd_macro = Qt;
+  current_kboard->Vlast_kbd_macro_command_history = Qnil;
 
   return Qnil;
 }
@@ -148,6 +149,8 @@
     = make_event_array ((current_kboard->kbd_macro_end
                         - current_kboard->kbd_macro_buffer),
                        current_kboard->kbd_macro_buffer);
+  current_kboard->Vlast_kbd_macro_command_history
+    = Fnreverse (current_kboard->Vlast_kbd_macro_command_history);
 }
 
 DEFUN ("end-kbd-macro", Fend_kbd_macro, Send_kbd_macro, 0, 2, "p",
@@ -402,6 +405,9 @@
 
   DEFVAR_KBOARD ("last-kbd-macro", Vlast_kbd_macro,
                 doc: /* Last kbd macro defined, as a string or vector; nil if 
none defined.  */);
+
+  DEFVAR_KBOARD ("last-kbd-macro-command-history", 
Vlast_kbd_macro_command_history,
+                doc: /* Command history of last kbd macro defined, as a list; 
nil if none defined.  */);
 }
 
 /* arch-tag: d293fcc9-2266-4163-9198-7fa0de12ec9e

-- 
Juri Linkov
http://www.jurta.org/emacs/



reply via email to

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