From 51156aa2d3cfa3303e6a866bfd5be1e9fa6a74b9 Mon Sep 17 00:00:00 2001
From: Mitchel Humpherys <mitch.special@gmail.com>
Date: Fri, 14 Oct 2011 01:12:47 -0700
Subject: [PATCH] initial whack at printing keyboard macros

---
 AUTHORS                      |    2 +-
 lib/readline/doc/rluser.texi |    4 ++
 lib/readline/funmap.c        |    1 +
 lib/readline/macro.c         |   88 ++++++++++++++++++++++++++++++++++++++++++
 lib/readline/readline.h      |    1 +
 5 files changed, 95 insertions(+), 1 deletions(-)

diff --git a/AUTHORS b/AUTHORS
index a7fa8f2..42da060 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -199,7 +199,7 @@ lib/readline/signals.c	Brian Fox, Chet Ramey
 lib/readline/kill.c	Brian Fox, Chet Ramey
 lib/readline/undo.c	Brian Fox, Chet Ramey
 lib/readline/input.c	Brian Fox, Chet Ramey
-lib/readline/macro.c	Brian Fox, Chet Ramey
+lib/readline/macro.c	Brian Fox, Chet Ramey, Mitchel Humpherys
 lib/readline/util.c	Brian Fox, Chet Ramey
 lib/readline/callback.c	Chet Ramey
 lib/readline/readline.h	Brian Fox, Chet Ramey
diff --git a/lib/readline/doc/rluser.texi b/lib/readline/doc/rluser.texi
index 4a367ed..a477416 100644
--- a/lib/readline/doc/rluser.texi
+++ b/lib/readline/doc/rluser.texi
@@ -1375,6 +1375,10 @@ and save the definition.
 Re-execute the last keyboard macro defined, by making the characters
 in the macro appear as if typed at the keyboard.
 
+@item print-last-kbd-macro ()
+Print the last keyboard macro defined in a format suitable for the
+@var{inputrc} file.
+
 @end ftable
 
 @node Miscellaneous Commands
diff --git a/lib/readline/funmap.c b/lib/readline/funmap.c
index 06d2b92..e3fbbfd 100644
--- a/lib/readline/funmap.c
+++ b/lib/readline/funmap.c
@@ -116,6 +116,7 @@ static const FUNMAP default_funmap[] = {
 #endif
   { "possible-completions", rl_possible_completions },
   { "previous-history", rl_get_previous_history },
+  { "print-last-kbd-macro", rl_print_last_kbd_macro },
   { "quoted-insert", rl_quoted_insert },
   { "re-read-init-file", rl_re_read_init_file },
   { "redraw-current-line", rl_refresh_line},
diff --git a/lib/readline/macro.c b/lib/readline/macro.c
index c2fac8a..10701f4 100644
--- a/lib/readline/macro.c
+++ b/lib/readline/macro.c
@@ -263,6 +263,94 @@ rl_call_last_kbd_macro (count, ignore)
   return 0;
 }
 
+
+/* Convert a saved macro into a string suitable for ~/.inputrc.
+   keyseq should have enough space for the resulting sequence. */
+int _rl_macro_to_keyseq(macro, keyseq)
+  char *macro;
+  char *keyseq;
+{
+  int i,ind;
+  char current[5];
+
+  keyseq[0] = '\0';
+
+  for (i=0; i < strlen(current_macro); i++) {
+    ind=0;
+    /* assume for now it's an escape sequence (we'll take this off
+       later if it turns out not to be true) */
+    current[ind++] = '\\';
+    switch (current_macro[i]) {
+    case '\007':
+      current[ind++] = 'a';
+      goto next_iter;
+    case '\b':
+      current[ind++] = 'b';
+      goto next_iter;
+    case RUBOUT:
+      current[ind++] = 'd';
+      goto next_iter;
+    case ESC:
+      current[ind++] = 'e';
+      current[ind++] = current_macro[++i];
+      goto next_iter;
+    case '\f':
+      current[ind++] = 'f';
+      goto next_iter;
+    case NEWLINE:
+      current[ind++] = 'n';
+      goto next_iter;
+    case RETURN:
+      current[ind++] = 'r';
+      goto next_iter;
+    case TAB:
+      current[ind++] = 't';
+      goto next_iter;
+    case 0x0B:
+      current[ind++] = 'v';
+      goto next_iter;
+    case '\\':
+      current[ind++] = '\\';
+      goto next_iter;
+    }
+
+    if(current_macro[i] > 0 && current_macro[i] < control_character_threshold) {
+      current[ind++] = 'C';
+      current[ind++] = '-';
+      current[ind++] = 'a' + current_macro[i] - 1;
+    } else {
+      ind=0;
+      current[ind++] = current_macro[i];
+    }
+
+  next_iter:
+    current[ind] = '\0';
+    strcat(keyseq, current);
+  }
+  return 1;
+}
+
+/* Print the most recently defined keyboard macro
+   in a format suitable for ~/.inputrc */
+int
+rl_print_last_kbd_macro(ignore1, ignore2)
+  int ignore1, ignore2;
+{
+  int i;
+  char *printable;
+
+  if (current_macro == 0)
+    _rl_abort_internal();
+
+  printable = (char *)xmalloc (1 + (current_macro_size*2));
+  _rl_macro_to_keyseq(current_macro, printable);
+  puts(printable);
+  FREE (printable);
+
+  return 0;
+}
+
+
 void
 rl_push_macro_input (macro)
      char *macro;
diff --git a/lib/readline/readline.h b/lib/readline/readline.h
index ba0d5d6..2e4841f 100644
--- a/lib/readline/readline.h
+++ b/lib/readline/readline.h
@@ -182,6 +182,7 @@ extern int rl_forward_search_history PARAMS((int, int));
 extern int rl_start_kbd_macro PARAMS((int, int));
 extern int rl_end_kbd_macro PARAMS((int, int));
 extern int rl_call_last_kbd_macro PARAMS((int, int));
+extern int rl_print_last_kbd_macro PARAMS((int, int));
 
 /* Bindable undo commands. */
 extern int rl_revert_line PARAMS((int, int));
-- 
1.7.7

