diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2015-03-01 23:49:59 +0100 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2015-03-02 00:03:49 +0100 |
commit | 482c0e7fbd5ea28bd32e968d7c027fdc9fbbbe23 (patch) | |
tree | 0e40a82c06526cc4a33b46adc7f3a66d787229a9 /src/cmdline.cpp | |
parent | 83ebaea1abc39cae990e0fd22b6e4b428abfa95f (diff) | |
download | sciteco-482c0e7fbd5ea28bd32e968d7c027fdc9fbbbe23.tar.gz |
introduced the ^G immediate editing command for toggling the undo/redo mode (also replaces ^T)
* CTRL+G toggles the behaviour of the rubout (Backspace, ^W, ^U) commands:
When the so called immediate editing command modifier is enabled/active,
the rubout commands will do the opposite and insert from the rubbed out
command line.
This command is somewhat similar to Emacs' C-g command.
* The CTRL+G command also replaces the ^T immediate editing command
for auto-completing filenames in any string argument.
Now the TAB key can be used for that purpose after activating the
^G modifier.
^T is a classic TECO command that will be supported sooner or later
by SciTECO, so it's good to have it available directly.
Diffstat (limited to 'src/cmdline.cpp')
-rw-r--r-- | src/cmdline.cpp | 243 |
1 files changed, 158 insertions, 85 deletions
diff --git a/src/cmdline.cpp b/src/cmdline.cpp index b1f3805..83a90b4 100644 --- a/src/cmdline.cpp +++ b/src/cmdline.cpp @@ -59,6 +59,15 @@ Cmdline cmdline; /** Last terminated command line */ static Cmdline last_cmdline; +/** + * Specifies whether the immediate editing modifier + * is enabled/disabled. + * It can be toggled with the ^G immediate editing command + * and influences the undo/redo direction and function of the + * TAB key. + */ +static bool modifier_enabled = false; + bool quit_requested = false; namespace States { @@ -111,32 +120,50 @@ Cmdline::replace(void) throw new_cmdline; } +/** + * Insert string into command line and execute + * it immediately. + * It already handles command line replacement and will + * only throw SciTECO::Error. + * + * @param src String to insert (null-terminated). + * NULL inserts a character from the previously + * rubbed out command line. + */ void -Cmdline::keypress(gchar key) +Cmdline::insert(const gchar *src) { Cmdline old_cmdline; + guint repl_pc; - gsize old_len = len; - guint repl_pc = 0; + macro_pc = pc = len; - /* - * Cleanup messages,etc... - */ - interface.msg_clear(); + if (!src) { + if (rubout_len) { + len++; + rubout_len--; + } + } else { + size_t src_len = strlen(src); - /* - * Process immediate editing commands, inserting - * characters as necessary into the command line. - */ - if (process_edit_cmd(key)) - interface.popup_clear(); + if (src_len <= rubout_len && !strncmp(str+len, src, src_len)) { + len += src_len; + rubout_len -= src_len; + } else { + if (rubout_len) + /* automatically disable immediate editing modifier */ + modifier_enabled = false; + + String::append(str, len, src); + len += src_len; + rubout_len = 0; + } + } /* * Parse/execute characters, one at a time so * undo tokens get emitted for the corresponding characters. */ - macro_pc = pc = MIN(old_len, len); - while (pc < len) { try { Execute::step(str, pc+1); @@ -178,111 +205,154 @@ Cmdline::keypress(gchar key) continue; } - /* - * Undo tokens may have been emitted - * (or had to be) before the exception - * is thrown. They must be executed so - * as if the character had never been - * inserted. - */ - undo.pop(pc); - rubout_len += len-pc; - len = pc; - /* program counter could be messed up */ - macro_pc = len; - break; + /* error is handled in Cmdline::keypress() */ + throw; } pc++; } - - /* - * Echo command line - */ - interface.cmdline_update(this); } void -Cmdline::insert(const gchar *src) +Cmdline::keypress(gchar key) { - size_t src_len = strlen(src); + /* + * Cleanup messages,etc... + */ + interface.msg_clear(); - if (src_len <= rubout_len && !strncmp(str+len, src, src_len)) { - len += src_len; - rubout_len -= src_len; - } else { - String::append(str, len, src); - len += src_len; - rubout_len = 0; + /* + * Process immediate editing commands, inserting + * characters as necessary into the command line. + */ + try { + if (process_edit_cmd(key)) + interface.popup_clear(); + } catch (Error &error) { + /* + * NOTE: Error message already displayed in + * Cmdline::insert(). + * + * Undo tokens may have been emitted + * (or had to be) before the exception + * is thrown. They must be executed so + * as if the character had never been + * inserted. + */ + undo.pop(pc); + rubout_len += len-pc; + len = pc; + /* program counter could be messed up */ + macro_pc = len; } + + /* + * Echo command line + */ + interface.cmdline_update(this); } bool Cmdline::process_edit_cmd(gchar key) { switch (key) { - case '\b': /* rubout character */ - if (len) + case CTL_KEY('G'): /* toggle immediate editing modifier */ + modifier_enabled = !modifier_enabled; + interface.msg(InterfaceCurrent::MSG_INFO, + "Immediate editing modifier is now %s.", + modifier_enabled ? "enabled" : "disabled"); + break; + + case '\b': /* rubout/reinsert character */ + if (modifier_enabled) + /* re-insert character */ + insert(); + else + /* rubout character */ rubout(); break; - case CTL_KEY('W'): /* rubout word */ + case CTL_KEY('W'): /* rubout/reinsert word/command */ if (States::is_string()) { gchar wchars[interface.ssm(SCI_GETWORDCHARS)]; interface.ssm(SCI_GETWORDCHARS, 0, (sptr_t)wchars); - /* rubout non-word chars */ - while (strings[0] && strlen(strings[0]) > 0 && - !strchr(wchars, str[len-1])) - rubout(); + if (modifier_enabled) { + while (States::is_string() && rubout_len && + strchr(wchars, str[len])) + insert(); - /* rubout word chars */ - while (strings[0] && strlen(strings[0]) > 0 && - strchr(wchars, str[len-1])) - rubout(); - } else if (len) { + while (States::is_string() && rubout_len && + !strchr(wchars, str[len])) + insert(); + } else { + /* rubout non-word chars */ + while (strings[0] && strlen(strings[0]) > 0 && + !strchr(wchars, str[len-1])) + rubout(); + + /* rubout word chars */ + while (strings[0] && strlen(strings[0]) > 0 && + strchr(wchars, str[len-1])) + rubout(); + } + } else if (modifier_enabled) { + /* reinsert command */ do - rubout(); + insert(); while (States::current != &States::start); - } - break; - - case CTL_KEY('U'): /* rubout string */ - if (States::is_string()) { - while (strings[0] && strlen(strings[0]) > 0) - rubout(); } else { - insert(key); + /* rubout command */ + do + rubout(); + while (States::current != &States::start); } break; - case CTL_KEY('T'): /* autocomplete file name */ - /* - * TODO: In insertion commands, we can autocomplete - * the string at the buffer cursor. - */ + case CTL_KEY('U'): /* rubout/reinsert string */ if (States::is_string()) { - if (interface.popup_is_shown()) { - /* cycle through popup pages */ - interface.popup_show(); - return false; + if (modifier_enabled) { + /* reinsert string */ + while (States::is_string() && rubout_len) + insert(); + } else { + /* rubout string */ + while (strings[0] && strlen(strings[0]) > 0) + rubout(); } - - const gchar *filename = last_occurrence(strings[0]); - gchar *new_chars = filename_complete(filename); - - insert(new_chars); - g_free(new_chars); - - if (interface.popup_is_shown()) - return false; } else { insert(key); } break; case '\t': /* autocomplete symbol or file name */ - if (States::is_insertion() && !interface.ssm(SCI_GETUSETABS)) { + if (modifier_enabled) { + /* + * TODO: In insertion commands, we can autocomplete + * the string at the buffer cursor. + */ + if (States::is_string()) { + /* autocomplete filename using string argument */ + if (interface.popup_is_shown()) { + /* cycle through popup pages */ + interface.popup_show(); + return false; + } + + const gchar *filename = last_occurrence(strings[0]); + gchar *new_chars = filename_complete(filename); + + if (new_chars) + insert(new_chars); + g_free(new_chars); + + if (interface.popup_is_shown()) + return false; + } else { + insert(key); + } + } else if (States::is_insertion() && !interface.ssm(SCI_GETUSETABS)) { + /* insert soft tabs */ gint spaces = interface.ssm(SCI_GETTABWIDTH); spaces -= interface.ssm(SCI_GETCOLUMN, @@ -300,7 +370,8 @@ Cmdline::process_edit_cmd(gchar key) gchar complete = escape_char == '{' ? ' ' : escape_char; gchar *new_chars = filename_complete(strings[0], complete); - insert(new_chars); + if (new_chars) + insert(new_chars); g_free(new_chars); if (interface.popup_is_shown()) @@ -320,7 +391,8 @@ Cmdline::process_edit_cmd(gchar key) const gchar *filename = last_occurrence(strings[0]); gchar *new_chars = filename_complete(filename); - insert(new_chars); + if (new_chars) + insert(new_chars); g_free(new_chars); if (interface.popup_is_shown()) @@ -338,7 +410,8 @@ Cmdline::process_edit_cmd(gchar key) : Symbols::scilexer; gchar *new_chars = symbol_complete(list, symbol, ','); - insert(new_chars); + if (new_chars) + insert(new_chars); g_free(new_chars); if (interface.popup_is_shown()) |