diff --git a/src/global.c b/src/global.c index ebfe2242..7085263c 100644 --- a/src/global.c +++ b/src/global.c @@ -634,6 +634,8 @@ void shortcut_init(void) const char *nano_savefile_msg = N_("Save file without prompting"); const char *nano_findprev_msg = N_("Search next occurrence backward"); const char *nano_findnext_msg = N_("Search next occurrence forward"); + const char *nano_recordmacro_msg = N_("Start/stop recording a macro"); + const char *nano_runmacro_msg = N_("Run the last recorded macro"); #endif const char *nano_case_msg = N_("Toggle the case sensitivity of the search"); @@ -976,6 +978,11 @@ void shortcut_init(void) N_("Comment Lines"), IFSCHELP(nano_comment_msg), BLANKAFTER, NOVIEW); #endif #ifndef NANO_TINY + add_to_funcs(record_macro, MMAIN, + N_("Record"), IFSCHELP(nano_recordmacro_msg), TOGETHER, VIEW); + add_to_funcs(run_macro, MMAIN, + N_("Run Macro"), IFSCHELP(nano_runmacro_msg), BLANKAFTER, VIEW); + add_to_funcs(do_search_backward, MMAIN, N_("Where Was"), IFSCHELP(N_(nano_wherewas_msg)), BLANKAFTER, VIEW); @@ -1140,6 +1147,8 @@ void shortcut_init(void) add_to_sclist(MMAIN, "M-^", 0, do_copy_text, 0); add_to_sclist(MMAIN, "M-}", 0, do_indent, 0); add_to_sclist(MMAIN, "M-{", 0, do_unindent, 0); + add_to_sclist(MMAIN, "M-:", 0, record_macro, 0); + add_to_sclist(MMAIN, "M-;", 0, run_macro, 0); add_to_sclist(MMAIN, "M-U", 0, do_undo, 0); add_to_sclist(MMAIN, "M-E", 0, do_redo, 0); #endif @@ -1543,6 +1552,10 @@ sc *strtosc(const char *input) s->scfunc = do_find_bracket; else if (!strcasecmp(input, "wordcount")) s->scfunc = do_wordlinechar_count; + else if (!strcasecmp(input, "recordmacro")) + s->scfunc = record_macro; + else if (!strcasecmp(input, "runmacro")) + s->scfunc = run_macro; else if (!strcasecmp(input, "undo")) s->scfunc = do_undo; else if (!strcasecmp(input, "redo")) diff --git a/src/proto.h b/src/proto.h index 617a2da3..2bc7fe7a 100644 --- a/src/proto.h +++ b/src/proto.h @@ -627,6 +627,8 @@ void dump_filestruct_reverse(void); #endif /* Most functions in winio.c. */ +void record_macro(void); +void run_macro(void); void get_key_buffer(WINDOW *win); size_t get_key_buffer_len(void); void unget_kbinput(int kbinput, bool metakey); diff --git a/src/winio.c b/src/winio.c index f90d23dc..dd717b4c 100644 --- a/src/winio.c +++ b/src/winio.c @@ -51,6 +51,67 @@ static bool seen_wide = FALSE; #endif static bool reveal_cursor = FALSE; /* Whether the cursor should be shown when waiting for input. */ +#ifndef NANO_TINY +static bool recording = FALSE; + /* Whether we are in the process of recording a macro. */ +static int *macro_buffer = NULL; + /* A buffer where the recorded key codes are stored. */ +static size_t macro_length = 0; + /* The current length of the macro. */ + +/* Add the given code to the macro buffer. */ +void add_to_macrobuffer(int code) +{ + macro_length++; + macro_buffer = (int*)nrealloc(macro_buffer, macro_length * sizeof(int)); + macro_buffer[macro_length - 1] = code; +} + +/* Remove the last key code plus any trailing Esc codes from macro buffer. */ +void snip_last_keystroke(void) +{ + macro_length--; + while (macro_length > 0 && macro_buffer[macro_length - 1] == '\x1b') + macro_length--; +} + +/* Start or stop the recording of keystrokes. */ +void record_macro(void) +{ + recording = !recording; + + if (recording) { + macro_length = 0; + statusbar(_("Recording a macro...")); + } else { + snip_last_keystroke(); + statusbar(_("Stopped recording")); + } +} + +/* Copy the stored sequence of codes into the regular key buffer, + * so they will be "executed" again. */ +void run_macro(void) +{ + size_t i; + + if (recording) { + statusline(HUSH, _("Cannot run macro while recording")); + snip_last_keystroke(); + return; + } + + if (macro_length == 0) + return; + + free(key_buffer); + key_buffer = (int *)nmalloc(macro_length * sizeof(int)); + key_buffer_len = macro_length; + + for (i = 0; i < macro_length; i++) + key_buffer[i] = macro_buffer[i]; +} +#endif /* !NANO_TINY */ /* Control character compatibility: * @@ -167,6 +228,10 @@ void get_key_buffer(WINDOW *win) nodelay(win, TRUE); while (TRUE) { +#ifndef NANO_TINY + if (recording) + add_to_macrobuffer(input); +#endif input = wgetch(win); /* If there aren't any more characters, stop reading. */