diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2024-12-04 16:43:51 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2024-12-04 16:43:51 +0300 |
commit | 48308687979f26a3498e7af94eacc8fe34307a78 (patch) | |
tree | afc05823788bc2985f29e33c667e631be2554cad | |
parent | 3a823fb43ba0abe52f3152d337675e9ed9a3f175 (diff) | |
download | sciteco-48308687979f26a3498e7af94eacc8fe34307a78.tar.gz |
the <Xq> command now supports the @ modifier for cutting into the register
* Can be freely combined with the colon-modifier as well.
:@Xq cut-appends to register q.
* This simply deletes the given buffer range after the copy or append operation
as if followed by another <K> command.
* This has indeed been a very annoying missing feature, as you often have to retype the
range for a K or D command.
At the same time, this cannot be reasonably solved with a macro since macros
do not accept Q-Register arguments -- so we would have to restrict ourselves to one or a few
selected registers.
I was also considering to solve this with a special stack operation that duplicates the
top values, so that Xq leaves arguments for K, but this couldn't work for cutting lines
and would also be longer to type.
* It's the first non-string command that accepts @.
Others may follow in the future.
We're approaching ITS TECO madness levels.
-rw-r--r-- | doc/sciteco.7.template | 16 | ||||
-rw-r--r-- | src/core-commands.c | 4 | ||||
-rw-r--r-- | src/parser.c | 20 | ||||
-rw-r--r-- | src/parser.h | 1 | ||||
-rw-r--r-- | src/qreg-commands.c | 45 | ||||
-rw-r--r-- | tests/testsuite.at | 5 |
6 files changed, 79 insertions, 12 deletions
diff --git a/doc/sciteco.7.template b/doc/sciteco.7.template index e5d9683..1777d54 100644 --- a/doc/sciteco.7.template +++ b/doc/sciteco.7.template @@ -1330,7 +1330,9 @@ are handled interactively. . A command's behaviour or syntax may be influenced by so called modifiers written in front of commands. -When specifying more than one modifier their order is insignificant. +Their specific influence of a modifier always depends on the concrete +command following it. +When specifying more than one modifier, their order is insignificant. .LP .SCITECO_TOPIC : colon The colon (\fB:\fP) modifier usually prevents a command from @@ -1345,8 +1347,9 @@ For instance if \(lq1000C\(rq would fail, \(lq1000:C\(rq will return 0 instead. .LP .SCITECO_TOPIC @ at -The at (\fB@\fP) modifier allows the string termination character -to be changed for individual commands. +When put in front of a command with string arguments, +the at (\fB@\fP) modifier always allows the string termination character +to be changed for that particular command. The alternative termination character must be specified just before the first string argument. For instance: @@ -1375,6 +1378,13 @@ The termination character can be \fIquoted\fP if you want to handle it like any regular character. For instance, you could write \(lqS^Q\fB$$\fP\(rq to search for the escape character itself. +.LP +The at (\fB@\fP) modifier may also sometimes be supported by commands, +that do not accept string arguments. +For instance, \fB@X\fIq\fR cuts text into Q-Register \fIq\fP. +\# But there is no common semantics for @ on regular commands, yet. +\# We may some day add @Mq/.../ for passing string arguments to macro calls, +\# but it will be yet another special case. . .SH Q-REGISTERS .SCITECO_TOPIC Q-Register diff --git a/src/core-commands.c b/src/core-commands.c index 752a8e8..4523923 100644 --- a/src/core-commands.c +++ b/src/core-commands.c @@ -1253,7 +1253,9 @@ teco_state_start_input(teco_machine_main_t *ctx, gunichar chr, GError **error) case '@': /* * @ modifier has syntactic significance, so set it even - * in PARSE_ONLY* modes + * in PARSE_ONLY* modes. + * Unfortunately, it means that it must be evaluated and cleared + * everywhere, even where it has no syntactic significance. */ if (ctx->parent.must_undo) teco_undo_guint(ctx->__flags); diff --git a/src/parser.c b/src/parser.c index 729fe42..e1bf576 100644 --- a/src/parser.c +++ b/src/parser.c @@ -332,6 +332,18 @@ teco_machine_main_eval_colon(teco_machine_main_t *ctx) return TRUE; } +gboolean +teco_machine_main_eval_at(teco_machine_main_t *ctx) +{ + if (!ctx->modifier_at) + return FALSE; + + if (ctx->parent.must_undo) + teco_undo_guint(ctx->__flags); + ctx->modifier_at = FALSE; + return TRUE; +} + teco_state_t * teco_machine_main_transition_input(teco_machine_main_t *ctx, teco_machine_main_transition_t *transitions, @@ -935,11 +947,9 @@ teco_state_expectstring_input(teco_machine_main_t *ctx, gunichar chr, GError **e * String termination handling */ if (ctx->modifier_at) { - if (current->expectstring.last) { - if (ctx->parent.must_undo) - teco_undo_guint(ctx->__flags); - ctx->modifier_at = FALSE; - } + if (current->expectstring.last) + /* also clears the "@" modifier flag */ + teco_machine_main_eval_at(ctx); /* * FIXME: Exclude setting at least whitespace characters as the diff --git a/src/parser.h b/src/parser.h index 3d69013..1127dcd 100644 --- a/src/parser.h +++ b/src/parser.h @@ -504,6 +504,7 @@ void teco_machine_main_init(teco_machine_main_t *ctx, gboolean must_undo); gboolean teco_machine_main_eval_colon(teco_machine_main_t *ctx); +gboolean teco_machine_main_eval_at(teco_machine_main_t *ctx); gboolean teco_machine_main_step(teco_machine_main_t *ctx, const gchar *macro, gsize stop_pos, GError **error); diff --git a/src/qreg-commands.c b/src/qreg-commands.c index 9f22de9..c36a6b7 100644 --- a/src/qreg-commands.c +++ b/src/qreg-commands.c @@ -746,6 +746,14 @@ teco_state_copytoqreg_got_register(teco_machine_main_t *ctx, teco_qreg_t *qreg, { teco_state_expectqreg_reset(ctx); + /* + * NOTE: "@" has syntactic significance in most contexts, so it's set + * in parse-only mode. + * Therefore, it must also be evaluated in parse-only mode, even though + * it has no syntactic significance for Xq. + */ + gboolean modifier_at = teco_machine_main_eval_at(ctx); + if (ctx->mode > TECO_MODE_NORMAL) return &teco_state_start; @@ -806,16 +814,42 @@ teco_state_copytoqreg_got_register(teco_machine_main_t *ctx, teco_qreg_t *qreg, return NULL; } + if (!modifier_at || len == 0) + return &teco_state_start; + + /* + * If @-modified, cut into the register + */ + if (teco_current_doc_must_undo()) { + sptr_t pos = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0); + undo__teco_interface_ssm(SCI_GOTOPOS, pos, 0); + undo__teco_interface_ssm(SCI_UNDO, 0, 0); + } + + /* + * Should always generate an undo action. + */ + teco_interface_ssm(SCI_BEGINUNDOACTION, 0, 0); + teco_interface_ssm(SCI_DELETERANGE, from, len); + teco_interface_ssm(SCI_ENDUNDOACTION, 0, 0); + teco_ring_dirtify(); + return &teco_state_start; } /*$ X Xq - * [lines]Xq -- Copy into or append to Q-Register + * [lines]Xq -- Copy into or append or cut to Q-Register * -Xq * from,toXq * [lines]:Xq * -:Xq * from,to:Xq + * [lines]@Xq + * -@Xq + * from,to@Xq + * [lines]:@Xq + * -:@Xq + * from,to:@Xq * * Copy the next or previous number of <lines> from the buffer * into the Q-Register <q> string. @@ -823,10 +857,15 @@ teco_state_copytoqreg_got_register(teco_machine_main_t *ctx, teco_qreg_t *qreg, * If two arguments are specified, the characters beginning * at position <from> up to the character at position <to> * are copied. - * The semantics of the arguments is analogous to the K + * The semantics of the arguments is analogous to the \fBK\fP * command's arguments. - * If the command is colon-modified, the characters will be + * + * If the command is colon-modified (\fB:\fP), the characters will be * appended to the end of register <q> instead. + * If the command is at-modified (\fB@\fP), the text will be + * removed from the buffer after copying or appending to the + * Q-Register, thus performing a cut operation. + * The order of modifiers is as always insignificant. * * Register <q> will be created if it is undefined. */ diff --git a/tests/testsuite.at b/tests/testsuite.at index bef270c..0bb0c08 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -97,6 +97,11 @@ AT_CHECK([$SCITECO -e '0U[[AB^Q@:>@(0/0)]]'], 0, ignore, ignore) # TODO: String building in Q-Register definitions AT_CLEANUP +AT_SETUP([Copy, append and cut to Q-Registers]) +AT_CHECK([$SCITECO -e "@I/12^J123/J Xa :Xa L-:@Xa :Qa-9\"N(0/0)' Z-3\"N(0/0)'"], 0, ignore, ignore) +AT_CHECK([$SCITECO -e "@I/ABCDE/ 1,4Xa 0,3:Xa 3,5:@Xa :Qa-8\"N(0/0)' Z-3\"N(0/0)'"], 0, ignore, ignore) +AT_CLEANUP + AT_SETUP([Q-Register stack]) AT_CHECK([$SCITECO -e "[[a 23Ub ]]b Qb\"N(0/0)'"], 0, ignore, ignore) # FG will temporarily change the working directory to tests/testsuite.dir. |