diff --git a/src/global.c b/src/global.c index 46633e38..ae108807 100644 --- a/src/global.c +++ b/src/global.c @@ -959,6 +959,12 @@ void shortcut_init(void) add_to_funcs(do_suspend_void, MMAIN, N_("Suspend"), IFSCHELP(nano_suspend_msg), BLANKAFTER, VIEW); + add_to_funcs(record_macro, MMAIN, + N_("Macro"), IFSCHELP(nano_suspend_msg), BLANKAFTER, VIEW); + + add_to_funcs(run_macro, MMAIN, + N_("Play Macro"), IFSCHELP(nano_suspend_msg), BLANKAFTER, VIEW); + #ifndef NANO_TINY add_to_funcs(do_indent, MMAIN, N_("Indent Text"), IFSCHELP(nano_indent_msg), TOGETHER, NOVIEW); @@ -1431,6 +1437,52 @@ const char *flagtostr(int flag) } #endif /* !NANO_TINY */ +static bool recording = 0; +static size_t macro_length = 0; +static int *macro_buffer = NULL; + +void macro_add_key(int key) +{ + if (!recording) + return; + + macro_length++; + // Remember to deallocate it on exit! + if (macro_buffer == NULL) + macro_buffer = (int*)nmalloc(sizeof(int)); + else + macro_buffer = (int*)nrealloc(macro_buffer, macro_length* + sizeof(int)); + macro_buffer[macro_length - 1] = key; +} + +void record_macro(void) +{ + //Do nothing if macro is playing! + if (recording) + statusline(ALERT, _("Stopped recording macro")); + else { + statusline(ALERT, _("Recording macro")); + free(macro_buffer); + macro_buffer = NULL; + macro_length = 0; + } + + recording = 1 - recording; +} + +void run_macro(void) +{ + if (recording){ + statusline(ALERT, _("Can not run macro while recording")); + return; + } + statusline(ALERT, _("Playing macro")); + // Do not send the last keystroke (stop recording macro) + copy_to_key_buffer(macro_buffer, macro_length - 1); + edit_refresh(); +} + #ifdef ENABLE_NANORC /* Interpret a function string given in the rc file, and return a * shortcut struct with the corresponding function filled in. */ @@ -1449,6 +1501,10 @@ sc *strtosc(const char *input) #endif if (!strcasecmp(input, "cancel")) s->scfunc = do_cancel; + else if (!strcasecmp(input, "macro")) + s->scfunc = record_macro; + else if (!strcasecmp(input, "play")) + s->scfunc = run_macro; else if (!strcasecmp(input, "exit")) s->scfunc = do_exit; else if (!strcasecmp(input, "discardbuffer")) diff --git a/src/nano.h b/src/nano.h index 7960d3be..e14c78d5 100644 --- a/src/nano.h +++ b/src/nano.h @@ -507,6 +507,8 @@ enum NO_COLOR_SYNTAX, PRESERVE, HISTORYLOG, + MACRO, + PLAY, RESTRICTED, SMART_HOME, WHITESPACE_DISPLAY, diff --git a/src/proto.h b/src/proto.h index 71c12d40..9c4bb0ae 100644 --- a/src/proto.h +++ b/src/proto.h @@ -700,6 +700,10 @@ void do_credits(void); /* These are just name definitions. */ void do_cancel(void); +void copy_to_key_buffer(int *buffer, size_t length); +void macro_add_key(int key); +void record_macro(void); +void run_macro(void); void case_sens_void(void); void regexp_void(void); void backwards_void(void); diff --git a/src/rcfile.c b/src/rcfile.c index 2988d4fc..c2a41b86 100644 --- a/src/rcfile.c +++ b/src/rcfile.c @@ -50,6 +50,8 @@ static const rcoption rcopts[] = { #ifndef DISABLE_HISTORIES {"historylog", HISTORYLOG}, #endif + {"macro", MACRO}, + {"play", PLAY}, {"morespace", MORE_SPACE}, #ifdef ENABLE_MOUSE {"mouse", USE_MOUSE}, diff --git a/src/winio.c b/src/winio.c index f90d23dc..28807c35 100644 --- a/src/winio.c +++ b/src/winio.c @@ -52,6 +52,16 @@ static bool seen_wide = FALSE; static bool reveal_cursor = FALSE; /* Whether the cursor should be shown when waiting for input. */ +void copy_to_key_buffer(int *buffer, size_t length) +{ + int i; + free(key_buffer); + key_buffer = (int*)nmalloc(length*sizeof(int)); + for(i = 0; i < length; i++) + key_buffer[i] = buffer[i]; + key_buffer_len = length; +} + /* Control character compatibility: * * - Ctrl-H is Backspace under ASCII, ANSI, VT100, and VT220. @@ -155,6 +165,7 @@ void get_key_buffer(WINDOW *win) key_buffer_len++; key_buffer = (int *)nmalloc(sizeof(int)); key_buffer[0] = input; + macro_add_key(input); #ifndef NANO_TINY /* If we got SIGWINCH, get out immediately since the win argument is @@ -179,6 +190,7 @@ void get_key_buffer(WINDOW *win) key_buffer = (int *)nrealloc(key_buffer, key_buffer_len * sizeof(int)); key_buffer[key_buffer_len - 1] = input; + macro_add_key(input); } /* Restore waiting mode if it was on. */