From d24bc4a3670c253fad5bee380c35e8a45dd283a2 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Wed, 11 Feb 2015 06:01:25 +0100 Subject: implemented support for different indention styles * the ^I command was altered to insert indention characters rather than plain tabs always. * The immediate editing command was added for all insertion arguments (I, ^I but also FR and FS) * documentation was extended for a discussion of indention --- doc/sciteco.7.template | 12 ++++++- src/cmdline.cpp | 12 ++++++- src/parser.cpp | 90 ++++++++++++++++++++++++++++++++++++++------------ src/parser.h | 12 +++++++ 4 files changed, 103 insertions(+), 23 deletions(-) diff --git a/doc/sciteco.7.template b/doc/sciteco.7.template index aa65c8b..53b5578 100644 --- a/doc/sciteco.7.template +++ b/doc/sciteco.7.template @@ -314,6 +314,16 @@ commands), complete beginning with the symbol, terminating fully completed symbols with a comma. T} T{ +Indent to next tab stop +T};9;^I, Tab;T{ +Text insertion arguments +T};T{ +Expands to spaces so that following text is inserted +at the next tab stop into the buffer. +This takes Scintilla's indention policy into account +and results in the same indention as the \fB^I\fP command. +T} +T{ Terminate command line T};27;^[, Escape;T{ Immediately after regular command ^[ @@ -1156,7 +1166,7 @@ For instance the following macro inserts \fIn\fP tab characters (one by default): .EX @^Ut{ - "~1'<@^I//> + "~1'<9@I//> } .EE .TP diff --git a/src/cmdline.cpp b/src/cmdline.cpp index 39cec52..dc03d9c 100644 --- a/src/cmdline.cpp +++ b/src/cmdline.cpp @@ -219,7 +219,17 @@ process_edit_cmd(gchar key) break; case '\t': - if (States::is_file()) { + if (States::is_insertion()) { + if (!interface.ssm(SCI_GETUSETABS)) { + gint len = interface.ssm(SCI_GETTABWIDTH); + + len -= interface.ssm(SCI_GETCOLUMN, + interface.ssm(SCI_GETCURRENTPOS)) % len; + + memset(insert, ' ', len); + insert[len] = '\0'; + } + } else if (States::is_file()) { *insert = '\0'; if (interface.popup_is_shown()) { /* cycle through popup pages */ diff --git a/src/parser.cpp b/src/parser.cpp index aa02164..ddf934b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -58,6 +58,7 @@ namespace States { StateScintilla_lParam scintilla_lparam; StateInsert insert_building(true); StateInsert insert_nobuilding(false); + StateInsertIndent insert_indent; State *current = &start; } @@ -1647,6 +1648,7 @@ StateCondCommand::custom(gchar chr) StateControl::StateControl() : State() { transitions['\0'] = this; + transitions['I'] = &States::insert_indent; transitions['U'] = &States::ctlucommand; transitions['^'] = &States::ascii; } @@ -1688,27 +1690,6 @@ StateControl::custom(gchar chr) expressions.set_radix(expressions.pop_num_calc()); break; - /* - * Alternatives: ^i, ^I, , - */ - /*$ - * [char,...]^I[text]$ -- Insert with leading TAB - * - * ^I (usually typed using the Tab key), is equivalent - * to \(lq[char,...],9I[text]$\(rq. - * In other words after all the chars on the stack have - * been inserted into the buffer, a Tab-character is inserted - * and then the optional is inserted interactively. - * - * Like the I command, ^I has string building characters - * \fBenabled\fP. - */ - case 'I': - BEGIN_EXEC(&States::insert_building); - expressions.eval(); - expressions.push('\t'); - return &States::insert_building; - /* * Alternatives: ^[, , */ @@ -2201,4 +2182,71 @@ StateInsert::done(const gchar *str) return &States::start; } +/* + * Alternatives: ^i, ^I, , + */ +/*$ + * [char,...]^I[text]$ -- Insert with leading indention + * + * ^I (usually typed using the Tab key), first inserts + * all the chars on the stack into the buffer, then indention + * characters (one tab or multiple spaces) and eventually + * the optional is inserted interactively. + * It is thus a derivate of the \fBI\fP (insertion) command. + * + * \*(ST uses Scintilla settings to determine the indention + * characters. + * If tab use is enabled with the \fBSCI_SETUSETABS\fP message, + * a single tab character is inserted. + * Tab use is enabled by default. + * Otherwise, a number of spaces is inserted up to the + * next tab stop so that the command's argument + * is inserted at the beginning of the next tab stop. + * The size of the tab stops is configured by the + * \fBSCI_SETTABWIDTH\fP Scintilla message (8 by default). + * In combination with \*(ST's use of the tab key as an + * immediate editing command for all insertions, this + * implements support for different insertion styles. + * The Scintilla settings apply to the current Scintilla + * document and are thus local to the currently edited + * buffer or Q-Register. + * + * However for the same reason, the ^I command is not + * fully compatible with classic TECO which \fIalways\fP + * inserts a single tab character and should not be used + * for the purpose of inserting single tabs in generic + * macros. + * To insert a single tab character reliably, the idioms + * \(lq9I$\(rq or \(lqI^I$\(rq may be used. + * + * Like the I command, ^I has string building characters + * \fBenabled\fP. + */ +void +StateInsertIndent::initial(void) +{ + StateInsert::initial(); + + interface.ssm(SCI_BEGINUNDOACTION); + if (interface.ssm(SCI_GETUSETABS)) { + interface.ssm(SCI_ADDTEXT, 1, (sptr_t)"\t"); + } else { + gint len = interface.ssm(SCI_GETTABWIDTH); + + len -= interface.ssm(SCI_GETCOLUMN, + interface.ssm(SCI_GETCURRENTPOS)) % len; + + gchar spaces[len]; + + memset(spaces, ' ', sizeof(spaces)); + interface.ssm(SCI_ADDTEXT, sizeof(spaces), (sptr_t)spaces); + } + interface.ssm(SCI_SCROLLCARET); + interface.ssm(SCI_ENDUNDOACTION); + ring.dirtify(); + + if (current_doc_must_undo()) + interface.undo_ssm(SCI_UNDO); +} + } /* namespace SciTECO */ diff --git a/src/parser.h b/src/parser.h index 976b215..81099b9 100644 --- a/src/parser.h +++ b/src/parser.h @@ -243,6 +243,11 @@ protected: State *done(const gchar *str); }; +class StateInsertIndent : public StateInsert { +protected: + void initial(void); +}; + namespace States { extern StateStart start; extern StateControl control; @@ -254,6 +259,7 @@ namespace States { extern StateScintilla_lParam scintilla_lparam; extern StateInsert insert_building; extern StateInsert insert_nobuilding; + extern StateInsertIndent insert_indent; extern State *current; @@ -263,6 +269,12 @@ namespace States { return dynamic_cast(current); } + static inline bool + is_insertion() + { + return dynamic_cast(current); + } + static inline bool is_file() { -- cgit v1.2.3