aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2024-12-04 16:43:51 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2024-12-04 16:43:51 +0300
commit48308687979f26a3498e7af94eacc8fe34307a78 (patch)
treeafc05823788bc2985f29e33c667e631be2554cad
parent3a823fb43ba0abe52f3152d337675e9ed9a3f175 (diff)
downloadsciteco-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.template16
-rw-r--r--src/core-commands.c4
-rw-r--r--src/parser.c20
-rw-r--r--src/parser.h1
-rw-r--r--src/qreg-commands.c45
-rw-r--r--tests/testsuite.at5
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.