diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2013-01-30 19:47:06 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2013-02-03 18:48:04 +0100 |
commit | 8816b7c7aded7ef8defca0bc6a78b2f5887faea6 (patch) | |
tree | f125e81fa8433da2f3ebd5af7b0d17d2a540cb67 | |
parent | 1d768b53295d71705fd1618f936240ed5428cb87 (diff) | |
download | sciteco-8816b7c7aded7ef8defca0bc6a78b2f5887faea6.tar.gz |
first draft of commandline-editing commands ({ and } as in VideoTECO)
* simplified traditional commandline editing. no need to extend cmdline string one character
at a time when inserting multiple. instead there's a marker (cmdline_pos) specifying the macro
length to execute in a "step" and also the anchor for generating undo tokens
* implementation does not yet work in macro calls
* while editing the commandline, other buffers/registers may not be edited
(need push-down-list and auxiliary q-register)
-rw-r--r-- | src/cmdline.cpp | 33 | ||||
-rw-r--r-- | src/cmdline.h | 1 | ||||
-rw-r--r-- | src/parser.cpp | 78 | ||||
-rw-r--r-- | src/parser.h | 2 | ||||
-rw-r--r-- | src/undo.cpp | 3 |
5 files changed, 89 insertions, 28 deletions
diff --git a/src/cmdline.cpp b/src/cmdline.cpp index 4d9cfd6..6e4c9d3 100644 --- a/src/cmdline.cpp +++ b/src/cmdline.cpp @@ -49,6 +49,7 @@ static const gchar *last_occurrence(const gchar *str, static inline gboolean filename_is_dir(const gchar *filename); gchar *cmdline = NULL; +gint cmdline_pos = 0; static gchar *last_cmdline = NULL; bool quit_requested = false; @@ -60,7 +61,6 @@ namespace States { void cmdline_keypress(gchar key) { - gchar *cmdline_p; const gchar *insert; gchar *echo; @@ -76,28 +76,15 @@ cmdline_keypress(gchar key) insert = process_edit_cmd(key); /* - * Parse/execute characters - */ - if (cmdline) { - gint len = strlen(cmdline); - cmdline = (gchar *)g_realloc(cmdline, len + strlen(insert) + 1); - cmdline_p = cmdline + len; - } else { - cmdline = (gchar *)g_malloc(strlen(insert) + 1); - *cmdline = '\0'; - cmdline_p = cmdline; - } - - /* - * Execute one insertion character, extending cmdline, at a time so + * Parse/execute characters, one at a time so * undo tokens get emitted for the corresponding characters. */ - for (const gchar *p = insert; *p; p++) { - *cmdline_p++ = *p; - *cmdline_p = '\0'; + cmdline_pos = cmdline ? strlen(cmdline)+1 : 1; + String::append(cmdline, insert); + while (cmdline_pos <= (gint)strlen(cmdline)) { try { - Execute::step(cmdline); + Execute::step((const gchar *&)cmdline, cmdline_pos); } catch (...) { /* * Undo tokens may have been emitted (or had to be) @@ -105,12 +92,14 @@ cmdline_keypress(gchar key) * executed so as if the character had never been * inserted. */ - undo.pop(cmdline_p - cmdline); - cmdline_p[-1] = '\0'; + undo.pop(cmdline_pos); + cmdline[cmdline_pos-1] = '\0'; /* program counter could be messed up */ - macro_pc = cmdline_p - cmdline - 1; + macro_pc = cmdline_pos - 1; break; } + + cmdline_pos++; } /* diff --git a/src/cmdline.h b/src/cmdline.h index b88599a..8747f63 100644 --- a/src/cmdline.h +++ b/src/cmdline.h @@ -25,6 +25,7 @@ #include "qregisters.h" extern gchar *cmdline; +extern gint cmdline_pos; extern bool quit_requested; void cmdline_keypress(gchar key); diff --git a/src/parser.cpp b/src/parser.cpp index 37dd055..cb4180e 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -71,9 +71,9 @@ gchar *strings[2] = {NULL, NULL}; gchar escape_char = '\x1B'; void -Execute::step(const gchar *macro) throw (State::Error) +Execute::step(const gchar *¯o, gint &stop_pos) throw (State::Error) { - while (macro[macro_pc]) { + while (macro_pc < stop_pos) { #ifdef DEBUG g_printf("EXEC(%d): input='%c'/%x, state=%p, mode=%d\n", macro_pc, macro[macro_pc], macro[macro_pc], @@ -91,6 +91,8 @@ Execute::step(const gchar *macro) throw (State::Error) void Execute::macro(const gchar *macro, bool locals) throw (State::Error) { + gint macro_len = strlen(macro); + GotoTable *parent_goto_table = Goto::table; GotoTable macro_goto_table(false); @@ -114,7 +116,7 @@ Execute::macro(const gchar *macro, bool locals) throw (State::Error) } try { - step(macro); + step(macro, macro_len); if (Goto::skip_label) throw State::Error("Label \"%s\" not found", Goto::skip_label); @@ -819,6 +821,76 @@ StateStart::custom(gchar chr) throw (Error) break; /* + * Command-line editing + */ + case '{': { + void *document; + + BEGIN_EXEC(this); + if (!undo.enabled) + throw Error("Command-line editing only possible in " + "interactive mode"); + + current_save_dot(); + + if (ring.current) + ring.current->undo_edit(); + else if (QRegisters::current) + QRegisters::current->undo_edit(); + + document = (void *)interface.ssm(SCI_CREATEDOCUMENT); + interface.ssm(SCI_SETDOCPOINTER, 0, (sptr_t)document); + interface.ssm(SCI_ADDTEXT, cmdline_pos-1, (sptr_t)cmdline); + + undo.push_msg(SCI_RELEASEDOCUMENT, 0, (sptr_t)document); + break; + } + + case '}': { + gint size, i; + gchar *old_cmdline, *new_cmdline; + + BEGIN_EXEC(this); + if (!undo.enabled) + throw Error("Command-line editing only possible in " + "interactive mode"); + + size = interface.ssm(SCI_GETLENGTH) + 1; + new_cmdline = (gchar *)g_malloc(size); + interface.ssm(SCI_GETTEXT, size, (sptr_t)new_cmdline); + + for (i = 0; cmdline[i] && cmdline[i] == new_cmdline[i]; i++); + undo.pop(i+1); + + old_cmdline = cmdline; + cmdline = new_cmdline; + cmdline_pos = i+1; + macro_pc = i; /* FIXME */ + + while (cmdline_pos <= (gint)strlen(cmdline)) { + try { + Execute::step((const gchar *&)cmdline, cmdline_pos); + } catch (...) { + undo.pop(i+1); + cmdline = old_cmdline; + cmdline[strlen(cmdline)-1] = '\0'; + g_free(new_cmdline); + old_cmdline = NULL; + cmdline_pos = i; + macro_pc = i-1; /* FIXME */ + break; + } + + cmdline_pos++; + } + + g_free(old_cmdline); + + /* state may have changed due to undoing */ + return States::current; + } + + /* * modifiers */ case '@': diff --git a/src/parser.h b/src/parser.h index 69a6d93..8ee15d7 100644 --- a/src/parser.h +++ b/src/parser.h @@ -253,7 +253,7 @@ extern gchar *strings[2]; extern gchar escape_char; namespace Execute { - void step(const gchar *macro) throw (State::Error); + void step(const gchar *¯o, gint &stop_pos) throw (State::Error); void macro(const gchar *macro, bool locals = true) throw (State::Error); bool file(const gchar *filename, bool locals = true); } diff --git a/src/undo.cpp b/src/undo.cpp index 82f1eda..1ee7cb4 100644 --- a/src/undo.cpp +++ b/src/undo.cpp @@ -20,7 +20,6 @@ #endif #include <stdio.h> -#include <string.h> #include <bsd/sys/queue.h> #include <glib.h> @@ -50,7 +49,7 @@ UndoStack::push(UndoToken *token) #ifdef DEBUG g_printf("UNDO PUSH %p\n", token); #endif - token->pos = strlen(cmdline); + token->pos = cmdline_pos; SLIST_INSERT_HEAD(&head, token, tokens); } else { delete token; |