new feature: the ability to record and play back a series of keystrokes
Allow the user to record and run a single macro. The default binding for starting and stopping the recording is M-: (Alt + colon) and for running the macro M-; (Alt + semicolon). This fulfills https://savannah.gnu.org/bugs/?50314. Requested-by: Peter Passchier <peter@passchier.net> Signed-off-by: Marco Diego Aurélio Mesquita <marcodiegomesquita@gmail.com> Signed-off-by: Benno Schulenberg <bensberg@telfort.nl>master
parent
fc36ff7275
commit
501d05c5d1
13
src/global.c
13
src/global.c
|
@ -634,6 +634,8 @@ void shortcut_init(void)
|
||||||
const char *nano_savefile_msg = N_("Save file without prompting");
|
const char *nano_savefile_msg = N_("Save file without prompting");
|
||||||
const char *nano_findprev_msg = N_("Search next occurrence backward");
|
const char *nano_findprev_msg = N_("Search next occurrence backward");
|
||||||
const char *nano_findnext_msg = N_("Search next occurrence forward");
|
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
|
#endif
|
||||||
const char *nano_case_msg =
|
const char *nano_case_msg =
|
||||||
N_("Toggle the case sensitivity of the search");
|
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);
|
N_("Comment Lines"), IFSCHELP(nano_comment_msg), BLANKAFTER, NOVIEW);
|
||||||
#endif
|
#endif
|
||||||
#ifndef NANO_TINY
|
#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,
|
add_to_funcs(do_search_backward, MMAIN,
|
||||||
N_("Where Was"), IFSCHELP(N_(nano_wherewas_msg)), BLANKAFTER, VIEW);
|
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_copy_text, 0);
|
||||||
add_to_sclist(MMAIN, "M-}", 0, do_indent, 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, 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-U", 0, do_undo, 0);
|
||||||
add_to_sclist(MMAIN, "M-E", 0, do_redo, 0);
|
add_to_sclist(MMAIN, "M-E", 0, do_redo, 0);
|
||||||
#endif
|
#endif
|
||||||
|
@ -1543,6 +1552,10 @@ sc *strtosc(const char *input)
|
||||||
s->scfunc = do_find_bracket;
|
s->scfunc = do_find_bracket;
|
||||||
else if (!strcasecmp(input, "wordcount"))
|
else if (!strcasecmp(input, "wordcount"))
|
||||||
s->scfunc = do_wordlinechar_count;
|
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"))
|
else if (!strcasecmp(input, "undo"))
|
||||||
s->scfunc = do_undo;
|
s->scfunc = do_undo;
|
||||||
else if (!strcasecmp(input, "redo"))
|
else if (!strcasecmp(input, "redo"))
|
||||||
|
|
|
@ -627,6 +627,8 @@ void dump_filestruct_reverse(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Most functions in winio.c. */
|
/* Most functions in winio.c. */
|
||||||
|
void record_macro(void);
|
||||||
|
void run_macro(void);
|
||||||
void get_key_buffer(WINDOW *win);
|
void get_key_buffer(WINDOW *win);
|
||||||
size_t get_key_buffer_len(void);
|
size_t get_key_buffer_len(void);
|
||||||
void unget_kbinput(int kbinput, bool metakey);
|
void unget_kbinput(int kbinput, bool metakey);
|
||||||
|
|
65
src/winio.c
65
src/winio.c
|
@ -51,6 +51,67 @@ static bool seen_wide = FALSE;
|
||||||
#endif
|
#endif
|
||||||
static bool reveal_cursor = FALSE;
|
static bool reveal_cursor = FALSE;
|
||||||
/* Whether the cursor should be shown when waiting for input. */
|
/* 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:
|
/* Control character compatibility:
|
||||||
*
|
*
|
||||||
|
@ -167,6 +228,10 @@ void get_key_buffer(WINDOW *win)
|
||||||
nodelay(win, TRUE);
|
nodelay(win, TRUE);
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
|
#ifndef NANO_TINY
|
||||||
|
if (recording)
|
||||||
|
add_to_macrobuffer(input);
|
||||||
|
#endif
|
||||||
input = wgetch(win);
|
input = wgetch(win);
|
||||||
|
|
||||||
/* If there aren't any more characters, stop reading. */
|
/* If there aren't any more characters, stop reading. */
|
||||||
|
|
Loading…
Reference in New Issue