diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-08-30 20:38:57 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-08-30 20:51:39 +0300 |
commit | e82dc6639e829490cb11267fa4a49ef97c6459ae (patch) | |
tree | 7625e231f06a47c0bcbb79b64f2a5c6bab811498 | |
parent | 2070d7faf66425c72677c02616a087d30a9aa863 (diff) | |
download | sciteco-e82dc6639e829490cb11267fa4a49ef97c6459ae.tar.gz |
the computed go-to command (O) is now 0-indexed and all invalid indexes and empty labels are ignored
* This has long been a TECO-11 incompatibility.
* The first label in a list has index 0, i.e. `1Ofoo,bar$` jumps to label `!bar!`.
Consequently 0 is also implied, so `Olabel$` continues to do what you expect.
* `0Ofoo$` was previously also jumping to `!foo!` which was inconsistent:
All invalid indexes should do nothing, i.e. execution continues after the go-to command.
* Fixed handling of empty labels as in `1Ofoo,,bar$` - execution should also continue
after the command.
This eases writing "default" clauses immediately after the go-to.
* The ED hook values now also begin at 0, so most existing ED hook macros should
continue to work.
* Similarily, the mouse events returned by -EJ also begin at 0 now,
so fnkeys.tes continues to work as expected.
* It's still very possible of course that this breaks existing code.
-rw-r--r-- | doc/sciteco.7.template | 16 | ||||
-rw-r--r-- | src/core-commands.c | 8 | ||||
-rw-r--r-- | src/goto-commands.c | 31 | ||||
-rw-r--r-- | src/interface.h | 2 | ||||
-rw-r--r-- | src/qreg.c | 8 | ||||
-rw-r--r-- | src/qreg.h | 2 | ||||
-rw-r--r-- | tests/testsuite.at | 8 |
7 files changed, 50 insertions, 25 deletions
diff --git a/doc/sciteco.7.template b/doc/sciteco.7.template index 9f0557e..066deb7 100644 --- a/doc/sciteco.7.template +++ b/doc/sciteco.7.template @@ -1262,12 +1262,12 @@ stack are discarded. This way, \fPED\fP hooks should not interfere with the stack-semantics of commands triggering them. .LP -Possible arguments to the \(lqED\(rq macro begin with 1 and +Possible arguments to the \(lqED\(rq macro begin with 0 and are defined consecutively so the macro can branch to the operation using a computed goto. The different values are defined as follows: .TP -.B 1 +.B 0 A file has been \fBadded\fP to the buffer ring. It may or may not already exist in the file system. This file is \*(ST's current document when this hook @@ -1275,7 +1275,7 @@ executes. Scintilla lexing may be configured in this hook \(em it usually only has to be done once. .TP -.B 2 +.B 1 A buffer has been \fBedited\fP (made the current file). This hook is not executed when a file is freshly added to the buffer ring, since this can be simulated easily @@ -1283,13 +1283,13 @@ by branching within the \(lqED\(rq macro. In this hook you may want to define language-specific auxiliary macros, for instance. .TP -.B 3 +.B 2 A buffer is about to be \fBclosed\fP (removed from the buffer ring). The buffer that is about to be closed, is still the current document when this hook runs. .TP -.B 4 +.B 3 \*(ST is about to \fBquit\fP, i.e. exit normally. This is \*(ST's equivalent of .BR atexit (3) @@ -2185,11 +2185,13 @@ in classic TECOs. . .SS Gotos and Labels . -The most basic flow control command in \*(ST is the Go-to command. +An important flow control command in \*(ST is the Go-to command. Since it is really an ordinary command, exceptional only in setting the program counter and influencing parsing, it is described in this document's command reference. -\*(ST can perform simple unconditional and computed gotos. +\*(ST can perform simple unconditional and computed gotos +which are just as powerful as switch-case statements in other +languages. .LP .SCITECO_TOPIC "!" label Labels are symbolic and are defined with the following syntax: diff --git a/src/core-commands.c b/src/core-commands.c index 6d0a3dc..5fe960b 100644 --- a/src/core-commands.c +++ b/src/core-commands.c @@ -2142,13 +2142,13 @@ teco_state_ecommand_flags(teco_machine_main_t *ctx, GError **error) * Type of the last mouse event (\fBread-only\fP). * One of the following values will be returned: * .RS - * . IP 1: 4 + * . IP 0: 4 * Some button has been pressed - * . IP 2: + * . IP 1: * Some button has been released - * . IP 3: + * . IP 2: * Scroll up - * . IP 4: + * . IP 3: * Scroll down * .RE * .IP -2: diff --git a/src/goto-commands.c b/src/goto-commands.c index d95886d..ac98b70 100644 --- a/src/goto-commands.c +++ b/src/goto-commands.c @@ -24,6 +24,7 @@ #include <glib.h> #include "sciteco.h" +#include "error.h" #include "string-utils.h" #include "expressions.h" #include "parser.h" @@ -110,15 +111,22 @@ teco_state_goto_done(teco_machine_main_t *ctx, const teco_string_t *str, GError if (ctx->flags.mode > TECO_MODE_NORMAL) return &teco_state_start; + if (!str->len) { + /* you can still write @O/,/, though... */ + g_set_error_literal(error, TECO_ERROR, TECO_ERROR_FAILED, + "No labels given for <O>"); + return NULL; + } + teco_int_t value; - if (!teco_expressions_pop_num_calc(&value, 1, error)) + if (!teco_expressions_pop_num_calc(&value, 0, error)) return NULL; /* * Find the comma-separated substring in str indexed by `value`. */ teco_string_t label = {NULL, 0}; - while (value > 0) { + while (value >= 0) { label.data = label.data ? label.data+label.len+1 : str->data; const gchar *p = label.data ? memchr(label.data, ',', str->len - (label.data - str->data)) : NULL; label.len = p ? p - label.data : str->len - (label.data - str->data); @@ -129,7 +137,7 @@ teco_state_goto_done(teco_machine_main_t *ctx, const teco_string_t *str, GError break; } - if (value == 0) { + if (value < 0 && label.len > 0) { gssize pc = teco_goto_table_find(&ctx->goto_table, label.data, label.len); if (pc >= 0) { @@ -156,19 +164,22 @@ gboolean teco_state_goto_insert_completion(teco_machine_main_t *ctx, const teco_ /*$ "O" goto * Olabel$ -- Go to label - * [n]Olabel1[,label2,...]$ + * [n]Olabel0[,label1,...]$ * * Go to <label>. * The simple go-to command is a special case of the * computed go-to command. * A comma-separated list of labels may be specified * in the string argument. - * The label to jump to is selected by <n> (1 is <label1>, - * 2 is <label2>, etc.). - * If <n> is omitted, 1 is implied. + * The label to jump to is selected by <n> (0 is <label0>, + * 1 is <label1>, etc.). + * If <n> is omitted, 0 is implied. + * Computed go-tos can be used like switch-case statements + * other languages. * * If the label selected by <n> is does not exist in the - * list of labels, the command does nothing. + * list of labels or is empty, the command does nothing + * and execution continues normally. * Label definitions are cached in a table, so that * if the label to go to has already been defined, the * go-to command will jump immediately. @@ -179,6 +190,10 @@ gboolean teco_state_goto_insert_completion(teco_machine_main_t *ctx, const teco_ * is terminated. * In the latter case, the user will not be able to * terminate the command-line. + * + * String building constructs are enabled in \fBO\fP + * which allows for a second kind of computed go-to, + * where the label name contains the value to select. */ TECO_DEFINE_STATE_EXPECTSTRING(teco_state_goto, .process_edit_cmd_cb = (teco_state_process_edit_cmd_cb_t)teco_state_goto_process_edit_cmd, diff --git a/src/interface.h b/src/interface.h index c0c41bd..9531d37 100644 --- a/src/interface.h +++ b/src/interface.h @@ -155,7 +155,7 @@ gboolean teco_interface_is_interrupted(void); typedef struct { enum { - TECO_MOUSE_PRESSED = 1, + TECO_MOUSE_PRESSED = 0, TECO_MOUSE_RELEASED, TECO_MOUSE_SCROLLUP, TECO_MOUSE_SCROLLDOWN @@ -1334,10 +1334,10 @@ teco_ed_hook(teco_ed_hook_t type, GError **error) teco_expressions_brace_close(error); static const gchar *const type2name[] = { - [TECO_ED_HOOK_ADD-1] = "ADD", - [TECO_ED_HOOK_EDIT-1] = "EDIT", - [TECO_ED_HOOK_CLOSE-1] = "CLOSE", - [TECO_ED_HOOK_QUIT-1] = "QUIT" + [TECO_ED_HOOK_ADD] = "ADD", + [TECO_ED_HOOK_EDIT] = "EDIT", + [TECO_ED_HOOK_CLOSE] = "CLOSE", + [TECO_ED_HOOK_QUIT] = "QUIT" }; error_add_frame: @@ -239,7 +239,7 @@ gboolean teco_qreg_stack_pop(teco_qreg_t *qreg, GError **error); void teco_qreg_stack_clear(void); typedef enum { - TECO_ED_HOOK_ADD = 1, + TECO_ED_HOOK_ADD = 0, TECO_ED_HOOK_EDIT, TECO_ED_HOOK_CLOSE, TECO_ED_HOOK_QUIT diff --git a/tests/testsuite.at b/tests/testsuite.at index 3728723..3cca113 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -114,6 +114,14 @@ TE_CHECK([[3<%a:>-3"N(0/0)' $]], 0, ignore, ignore) TE_CHECK([[3<%a :F>(0/0):>-3"N(0/0)' $]], 0, ignore, ignore) AT_CLEANUP +AT_SETUP([Gotos and labels]) +TE_CHECK([[@O//]], 1, ignore, ignore) +TE_CHECK([[^^XUq @O/s.^EUq/ (0/0) !s.X!]], 0, ignore, ignore) +TE_CHECK([[1@O/foo,bar/ (0/0) !bar!]], 0, ignore, ignore) +# No-op gotos +TE_CHECK([[-1@O/foo/ 1@O/foo/ @O/,foo/]], 0, ignore, ignore) +AT_CLEANUP + AT_SETUP([String arguments]) TE_CHECK([[Ifoo^Q]]TE_ESCAPE[[(0/0)]]TE_ESCAPE, 0, ignore, ignore) TE_CHECK([[@I"foo^Q"(0/0)"]], 0, ignore, ignore) |