diff options
-rw-r--r-- | doc/sciteco.7.template | 5 | ||||
-rw-r--r-- | lib/lexer.tes | bin | 719 -> 693 bytes | |||
-rw-r--r-- | lib/lexers/bash.tes | 2 | ||||
-rw-r--r-- | lib/lexers/lua.tes | 2 | ||||
-rw-r--r-- | lib/lexers/perl.tes | 2 | ||||
-rw-r--r-- | lib/lexers/python.tes | 2 | ||||
-rw-r--r-- | src/core-commands.c | 54 | ||||
-rw-r--r-- | src/error.h | 8 | ||||
-rw-r--r-- | src/glob.c | 2 | ||||
-rw-r--r-- | src/parser.c | 11 | ||||
-rw-r--r-- | src/parser.h | 9 | ||||
-rw-r--r-- | src/qreg-commands.c | 14 | ||||
-rw-r--r-- | src/search.c | 88 | ||||
-rw-r--r-- | src/spawn.c | 2 | ||||
-rw-r--r-- | tests/testsuite.at | 1 |
15 files changed, 130 insertions, 72 deletions
diff --git a/doc/sciteco.7.template b/doc/sciteco.7.template index 1777d54..8c049ee 100644 --- a/doc/sciteco.7.template +++ b/doc/sciteco.7.template @@ -1346,6 +1346,11 @@ boolean instead. For instance if \(lq1000C\(rq would fail, \(lq1000:C\(rq will return 0 instead. .LP +.SCITECO_TOPIC :: +Two colons (\fB::\fP) can sometimes further modify a command's behavior \(em +currently it is used by the \fB::S\fP search comparison command. +On all other commands it will behave like a single colon. +.LP .SCITECO_TOPIC @ at When put in front of a command with string arguments, the at (\fB@\fP) modifier always allows the string termination character diff --git a/lib/lexer.tes b/lib/lexer.tes Binary files differindex ce22a74..e807c80 100644 --- a/lib/lexer.tes +++ b/lib/lexer.tes diff --git a/lib/lexers/bash.tes b/lib/lexers/bash.tes index 5dce149..33d6664 100644 --- a/lib/lexers/bash.tes +++ b/lib/lexers/bash.tes @@ -3,7 +3,7 @@ internally ! @[lexer.test.bash]{ - _#!M[sh,bash,ksh]M[lexer.checkheader]"S -1 ' + _#!M[sh,bash,ksh]:M[lexer.checkheader]"S -1 ' :EN*.shQ*"S -1 ' :EN*.bshQ*"S -1 ' :EN*/configureQ*"S -1 ' diff --git a/lib/lexers/lua.tes b/lib/lexers/lua.tes index 7c14af8..7ffe54a 100644 --- a/lib/lexers/lua.tes +++ b/lib/lexers/lua.tes @@ -1,7 +1,7 @@ ! AUTO-GENERATED FROM SCITE PROPERTY SET ! @[lexer.test.lua]{ - _#!MluaM[lexer.checkheader]"S -1 ' + _#!Mlua:M[lexer.checkheader]"S -1 ' :EN*.luaQ* } diff --git a/lib/lexers/perl.tes b/lib/lexers/perl.tes index 3dd99ae..213dd4b 100644 --- a/lib/lexers/perl.tes +++ b/lib/lexers/perl.tes @@ -1,7 +1,7 @@ ! AUTO-GENERATED FROM SCITE PROPERTY SET ! @[lexer.test.perl]{ - _#!M[perl,pl]M[lexer.checkheader]"S -1 ' + _#!M[perl,pl]:M[lexer.checkheader]"S -1 ' :EN*.plQ*"S -1 ' :EN*.pmQ*"S -1 ' :EN*.podQ* diff --git a/lib/lexers/python.tes b/lib/lexers/python.tes index 0106f5c..f85f92b 100644 --- a/lib/lexers/python.tes +++ b/lib/lexers/python.tes @@ -1,7 +1,7 @@ !* Python lexer *! @[lexer.test.python]{ - _#!MpythonM[lexer.checkheader]"S -1 ' + _#!Mpython:M[lexer.checkheader]"S -1 ' :EN*.pyQ*"S -1 ' :EN*.pywQ*"S -1 ' :EN*.pyxQ*"S -1 ' diff --git a/src/core-commands.c b/src/core-commands.c index 4523923..6e39d9a 100644 --- a/src/core-commands.c +++ b/src/core-commands.c @@ -259,7 +259,7 @@ teco_state_start_loop_open(teco_machine_main_t *ctx, GError **error) !teco_expressions_pop_num_calc(&lctx.counter, -1, error)) return; lctx.brace_level = teco_brace_level; - lctx.pass_through = teco_machine_main_eval_colon(ctx); + lctx.pass_through = teco_machine_main_eval_colon(ctx) > 0; if (lctx.counter) { /* @@ -306,7 +306,7 @@ teco_state_start_loop_close(teco_machine_main_t *ctx, GError **error) return; } - gboolean colon_modified = teco_machine_main_eval_colon(ctx); + gboolean colon_modified = teco_machine_main_eval_colon(ctx) > 0; /* * Colon-modified loop ends can be used to @@ -387,7 +387,7 @@ teco_state_start_break(teco_machine_main_t *ctx, GError **error) teco_bool_t rc; if (!teco_expressions_pop_num_calc(&rc, v, error)) return; - if (teco_machine_main_eval_colon(ctx)) + if (teco_machine_main_eval_colon(ctx) > 0) rc = ~rc; if (teco_is_success(rc)) @@ -544,9 +544,9 @@ teco_state_start_jump(teco_machine_main_t *ctx, GError **error) teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0), 0); teco_interface_ssm(SCI_GOTOPOS, pos, 0); - if (teco_machine_main_eval_colon(ctx)) + if (teco_machine_main_eval_colon(ctx) > 0) teco_expressions_push(TECO_SUCCESS); - } else if (teco_machine_main_eval_colon(ctx)) { + } else if (teco_machine_main_eval_colon(ctx) > 0) { teco_expressions_push(TECO_FAILURE); } else { teco_error_move_set(error, "J"); @@ -588,7 +588,7 @@ teco_state_start_move(teco_machine_main_t *ctx, GError **error) return; teco_bool_t rc = teco_move_chars(v); - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { teco_expressions_push(rc); } else if (teco_is_failure(rc)) { teco_error_move_set(error, "C"); @@ -613,7 +613,7 @@ teco_state_start_reverse(teco_machine_main_t *ctx, GError **error) return; teco_bool_t rc = teco_move_chars(-v); - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { teco_expressions_push(rc); } else if (teco_is_failure(rc)) { teco_error_move_set(error, "R"); @@ -664,7 +664,7 @@ teco_state_start_line(teco_machine_main_t *ctx, GError **error) return; teco_bool_t rc = teco_move_lines(v); - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { teco_expressions_push(rc); } else if (teco_is_failure(rc)) { teco_error_move_set(error, "L"); @@ -690,7 +690,7 @@ teco_state_start_back(teco_machine_main_t *ctx, GError **error) return; teco_bool_t rc = teco_move_lines(-v); - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { teco_expressions_push(rc); } else if (teco_is_failure(rc)) { teco_error_move_set(error, "B"); @@ -745,7 +745,7 @@ teco_state_start_word(teco_machine_main_t *ctx, GError **error) if (v < 0) { if (teco_current_doc_must_undo()) undo__teco_interface_ssm(SCI_GOTOPOS, pos, 0); - if (teco_machine_main_eval_colon(ctx)) + if (teco_machine_main_eval_colon(ctx) > 0) teco_expressions_push(TECO_SUCCESS); } else { teco_interface_ssm(SCI_GOTOPOS, pos, 0); @@ -841,7 +841,7 @@ teco_state_start_delete_words(teco_machine_main_t *ctx, GError **error) return; teco_bool_t rc = teco_delete_words(v); - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { teco_expressions_push(rc); } else if (teco_is_failure(rc)) { teco_error_words_set(error, "V"); @@ -866,7 +866,7 @@ teco_state_start_delete_words_back(teco_machine_main_t *ctx, GError **error) return; teco_bool_t rc = teco_delete_words(-v); - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { teco_expressions_push(rc); } else if (teco_is_failure(rc)) { teco_error_words_set(error, "Y"); @@ -941,7 +941,7 @@ teco_state_start_kill(teco_machine_main_t *ctx, const gchar *cmd, gboolean by_li rc = teco_bool(len >= 0 && from >= 0 && to >= 0); } - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { teco_expressions_push(rc); } else if (teco_is_failure(rc)) { teco_error_range_set(error, cmd); @@ -1251,6 +1251,10 @@ teco_state_start_input(teco_machine_main_t *ctx, gunichar chr, GError **error) * Modifiers */ case '@': + if (ctx->modifier_at) { + teco_error_modifier_set(error, '@'); + return NULL; + } /* * @ modifier has syntactic significance, so set it even * in PARSE_ONLY* modes. @@ -1263,11 +1267,15 @@ teco_state_start_input(teco_machine_main_t *ctx, gunichar chr, GError **error) return &teco_state_start; case ':': - if (ctx->mode == TECO_MODE_NORMAL) { - if (ctx->parent.must_undo) - teco_undo_guint(ctx->__flags); - ctx->modifier_colon = TRUE; + if (ctx->mode > TECO_MODE_NORMAL) + return &teco_state_start; + if (ctx->modifier_colon >= 2) { + teco_error_modifier_set(error, ':'); + return NULL; } + if (ctx->parent.must_undo) + teco_undo_guint(ctx->__flags); + ctx->modifier_colon++; return &teco_state_start; default: @@ -1314,7 +1322,7 @@ teco_state_fcommand_loop_start(teco_machine_main_t *ctx, GError **error) teco_loop_context_t *lctx = &g_array_index(teco_loop_stack, teco_loop_context_t, teco_loop_stack->len-1); - gboolean colon_modified = teco_machine_main_eval_colon(ctx); + gboolean colon_modified = teco_machine_main_eval_colon(ctx) > 0; if (!lctx->pass_through) { if (colon_modified) { @@ -1816,7 +1824,7 @@ teco_state_control_glyphs2bytes(teco_machine_main_t *ctx, GError **error) if (!teco_expressions_eval(FALSE, error)) return; - gboolean colon_modified = teco_machine_main_eval_colon(ctx); + gboolean colon_modified = teco_machine_main_eval_colon(ctx) > 0; if (!teco_expressions_args()) { /* @@ -2487,7 +2495,7 @@ teco_state_ecommand_eol(teco_machine_main_t *ctx, GError **error) if (teco_expressions_args() > 0) { teco_int_t eol_mode; - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { teco_int_t v1, v2; if (!teco_expressions_pop_num_calc(&v1, 0, error)) return; @@ -2533,7 +2541,7 @@ teco_state_ecommand_eol(teco_machine_main_t *ctx, GError **error) undo__teco_interface_ssm(SCI_SETEOLMODE, teco_interface_ssm(SCI_GETEOLMODE, 0, 0), 0); teco_interface_ssm(SCI_SETEOLMODE, eol_mode, 0); - } else if (teco_machine_main_eval_colon(ctx)) { + } else if (teco_machine_main_eval_colon(ctx) > 0) { const gchar *eol_seq = teco_eol_get_seq(teco_interface_ssm(SCI_GETEOLMODE, 0, 0)); teco_expressions_push(eol_seq); } else { @@ -2644,7 +2652,7 @@ teco_state_ecommand_encoding(teco_machine_main_t *ctx, GError **error) if (!teco_expressions_eval(FALSE, error)) return; - gboolean colon_modified = teco_machine_main_eval_colon(ctx); + gboolean colon_modified = teco_machine_main_eval_colon(ctx) > 0; guint old_cp = teco_interface_get_codepage(); @@ -2829,7 +2837,7 @@ teco_state_ecommand_encoding(teco_machine_main_t *ctx, GError **error) static void teco_state_ecommand_exit(teco_machine_main_t *ctx, GError **error) { - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { if (!teco_ring_save_all_dirty_buffers(error)) return; } else { diff --git a/src/error.h b/src/error.h index 2df7b89..c51f528 100644 --- a/src/error.h +++ b/src/error.h @@ -39,6 +39,7 @@ typedef enum { * They will mainly be different in their error message. */ TECO_ERROR_SYNTAX, + TECO_ERROR_MODIFIER, TECO_ERROR_ARGEXPECTED, TECO_ERROR_CODEPOINT, TECO_ERROR_MOVE, @@ -74,6 +75,13 @@ teco_error_syntax_set(GError **error, gunichar chr) } static inline void +teco_error_modifier_set(GError **error, gchar modifier) +{ + g_set_error(error, TECO_ERROR, TECO_ERROR_MODIFIER, + "Excess \"%c\"-modifier", modifier); +} + +static inline void teco_error_argexpected_set(GError **error, const gchar *cmd) { g_set_error(error, TECO_ERROR, TECO_ERROR_ARGEXPECTED, @@ -466,7 +466,7 @@ teco_state_glob_filename_done(teco_machine_main_t *ctx, const teco_string_t *str GFileTest file_flags = G_FILE_TEST_EXISTS; gboolean matching = FALSE; - gboolean colon_modified = teco_machine_main_eval_colon(ctx); + gboolean colon_modified = teco_machine_main_eval_colon(ctx) > 0; teco_int_t teco_test_mode; diff --git a/src/parser.c b/src/parser.c index e1bf576..018e35f 100644 --- a/src/parser.c +++ b/src/parser.c @@ -320,16 +320,17 @@ teco_machine_main_init(teco_machine_main_t *ctx, teco_qreg_table_t *qreg_table_l teco_machine_stringbuilding_init(&ctx->expectstring.machine, '\e', qreg_table_locals, must_undo); } -gboolean +guint teco_machine_main_eval_colon(teco_machine_main_t *ctx) { - if (!ctx->modifier_colon) - return FALSE; + guint c = ctx->modifier_colon; + if (c == 0) + return 0; if (ctx->parent.must_undo) teco_undo_guint(ctx->__flags); - ctx->modifier_colon = FALSE; - return TRUE; + ctx->modifier_colon = 0; + return c; } gboolean diff --git a/src/parser.h b/src/parser.h index 1127dcd..20f73fb 100644 --- a/src/parser.h +++ b/src/parser.h @@ -460,7 +460,12 @@ struct teco_machine_main_t { struct { teco_mode_t mode : 8; - bool modifier_colon : 1; + /** number of `:`-modifiers detected */ + guint modifier_colon : 2; + /** + * Whether the `@`-modifier has been detected. + * This is tracked even in parse-only mode. + */ bool modifier_at : 1; }; guint __flags; @@ -503,7 +508,7 @@ void teco_machine_main_init(teco_machine_main_t *ctx, teco_qreg_table_t *qreg_table_locals, gboolean must_undo); -gboolean teco_machine_main_eval_colon(teco_machine_main_t *ctx); +guint 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, diff --git a/src/qreg-commands.c b/src/qreg-commands.c index c36a6b7..0a64b2f 100644 --- a/src/qreg-commands.c +++ b/src/qreg-commands.c @@ -256,7 +256,7 @@ teco_state_queryqreg_got_register(teco_machine_main_t *ctx, teco_qreg_t *qreg, if (!teco_expressions_eval(FALSE, error)) return NULL; - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { /* Query Q-Register's existence or string size */ if (qreg) { /* get_string() would return the size in bytes */ @@ -366,7 +366,7 @@ teco_state_setqregstring_nobuilding_done(teco_machine_main_t *ctx, if (ctx->mode > TECO_MODE_NORMAL) return &teco_state_start; - gboolean colon_modified = teco_machine_main_eval_colon(ctx); + gboolean colon_modified = teco_machine_main_eval_colon(ctx) > 0; if (!teco_expressions_eval(FALSE, error)) return NULL; @@ -578,9 +578,9 @@ teco_state_setqreginteger_got_register(teco_machine_main_t *ctx, teco_qreg_t *qr !qreg->vtable->set_integer(qreg, v, error)) return NULL; - if (teco_machine_main_eval_colon(ctx)) + if (teco_machine_main_eval_colon(ctx) > 0) teco_expressions_push(TECO_SUCCESS); - } else if (teco_machine_main_eval_colon(ctx)) { + } else if (teco_machine_main_eval_colon(ctx) > 0) { teco_expressions_push(TECO_FAILURE); } else { teco_error_argexpected_set(error, "U"); @@ -653,7 +653,7 @@ teco_state_macro_got_register(teco_machine_main_t *ctx, teco_qreg_t *qreg, if (ctx->mode > TECO_MODE_NORMAL) return &teco_state_start; - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { /* don't create new local Q-Registers if colon modifier is given */ if (!teco_qreg_execute(qreg, ctx->qreg_table_locals, error)) return NULL; @@ -710,7 +710,7 @@ teco_state_macrofile_done(teco_machine_main_t *ctx, const teco_string_t *str, GE g_autofree gchar *filename = teco_file_expand_path(str->data); - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { /* don't create new local Q-Registers if colon modifier is given */ if (!teco_execute_file(filename, ctx->qreg_table_locals, error)) return NULL; @@ -803,7 +803,7 @@ teco_state_copytoqreg_got_register(teco_machine_main_t *ctx, teco_qreg_t *qreg, }; teco_interface_ssm(SCI_GETTEXTRANGEFULL, 0, (sptr_t)&range); - if (teco_machine_main_eval_colon(ctx)) { + if (teco_machine_main_eval_colon(ctx) > 0) { if (!qreg->vtable->append_string(qreg, str, len, error)) return NULL; } else { diff --git a/src/search.c b/src/search.c index c0398dc..e05a6b9 100644 --- a/src/search.c +++ b/src/search.c @@ -686,6 +686,9 @@ teco_state_search_process(teco_machine_main_t *ctx, const teco_string_t *str, gs if (teco_is_failure(search_mode)) flags |= G_REGEX_CASELESS; + if (ctx->modifier_colon == 2) + flags |= G_REGEX_ANCHORED; + /* this is set in teco_state_search_initial() */ if (ctx->expectstring.machine.codepage != SC_CP_UTF8) { /* single byte encoding */ @@ -835,7 +838,7 @@ teco_state_search_done(teco_machine_main_t *ctx, const teco_string_t *str, GErro if (!search_reg->vtable->get_integer(search_reg, &search_state, error)) return FALSE; - if (teco_machine_main_eval_colon(ctx)) + if (teco_machine_main_eval_colon(ctx) > 0) teco_expressions_push(search_state); else if (teco_is_failure(search_state) && !teco_loop_stack->len /* not in loop */) @@ -860,19 +863,20 @@ teco_state_search_done(teco_machine_main_t *ctx, const teco_string_t *str, GErro ##__VA_ARGS__ \ ) -/*$ S search pattern - * S[pattern]$ -- Search for pattern - * [n]S[pattern]$ +/*$ S search pattern compare + * [n]S[pattern]$ -- Search for pattern * -S[pattern]$ * from,toS[pattern]$ - * :S[pattern]$ -> Success|Failure * [n]:S[pattern]$ -> Success|Failure * -:S[pattern]$ -> Success|Failure * from,to:S[pattern]$ -> Success|Failure + * [n]::S[pattern]$ -> Success|Failure + * -::S[pattern]$ -> Success|Failure + * from,to::S[pattern]$ -> Success|Failure * * Search for <pattern> in the current buffer/Q-Register. * Search order and range depends on the arguments given. - * By default without any arguments, S will search forward + * By default without any arguments, \fBS\fP will search forward * from dot till file end. * The optional single argument specifies the occurrence * to search (1 is the first occurrence, 2 the second, etc.). @@ -906,10 +910,23 @@ teco_state_search_done(teco_machine_main_t *ctx, const teco_string_t *str, GErro * .EX * <Sfoo$; ...> * .EE - * Alternatively, S may be colon-modified in which case it returns + * Alternatively, \fBS\fP may be colon-modified in which case it returns * a condition boolean that may be directly evaluated by a * conditional or break-command. * + * When modified with two colons, the search will be anchored in addition + * to returning a condition boolean, i.e. it can be used to perform a string + * comparison. + * \(lq::S\(rq without arguments compares the pattern against the current + * buffer position. + * With a single positive integer <n>, \(lq::S\(rq matches <n> repititions + * of the given pattern. + * With a negative integer <n>, \(lq::S\(rq will match the \fIn\fP-th last + * occurrence of the pattern from the beginning of the buffer + * (which is not really useful). + * With two integer arguments, \(lq::S\(rq compares the pattern against + * the corresponding part of the buffer. + * * In interactive mode, searching will be performed immediately * (\(lqsearch as you type\(rq) highlighting matched text * on the fly. @@ -996,12 +1013,12 @@ teco_state_search_all_done(teco_machine_main_t *ctx, const teco_string_t *str, G * * Search for <pattern> over buffer boundaries. * This command is similar to the regular search command - * (S) but will continue to search for occurrences of + * (\fBS\fP) but will continue to search for occurrences of * pattern when the end or beginning of the current buffer * is reached. * Occurrences of <pattern> spanning over buffer boundaries * will not be found. - * When searching forward N will start in the current buffer + * When searching forward \fBN\fP will start in the current buffer * at dot, continue with the next buffer in the ring searching * the entire buffer until it reaches the end of the buffer * ring, continue with the first buffer in the ring until @@ -1009,7 +1026,7 @@ teco_state_search_all_done(teco_machine_main_t *ctx, const teco_string_t *str, G * beginning of the buffer up to its current dot. * Searching backwards does the reverse. * - * N also differs from S in the interpretation of two arguments. + * \fBN\fP also differs from \fBS\fP in the interpretation of two arguments. * Using two arguments the search will be bounded between the * buffer with number <from>, up to the buffer with number * <to>. @@ -1024,6 +1041,13 @@ teco_state_search_all_done(teco_machine_main_t *ctx, const teco_string_t *str, G * buffer numbers greater than the number of buffers in the * ring. */ +/* + * Since N inherits the double-colon semantics from S, + * f,t::N will match at the beginning of the given buffers. + * [n]::N will behave similar to [n]::S, but can search across + * buffer boundaries. + * This is probably not very useful in practice, so it's not documented. + */ TECO_DEFINE_STATE_SEARCH(teco_state_search_all, .initial_cb = (teco_state_initial_cb_t)teco_state_search_all_initial ); @@ -1088,8 +1112,8 @@ teco_state_search_kill_done(teco_machine_main_t *ctx, const teco_string_t *str, * -:FK[pattern]$ -> Success|Failure * from,to:FK[pattern]$ -> Success|Failure * - * FK searches for <pattern> just like the regular search - * command (S) but when found deletes all text from dot + * \fBFK\fP searches for <pattern> just like the regular search + * command (\fBS\fP) but when found deletes all text from dot * up to but not including the found text instance. * When searching backwards the characters beginning after * the occurrence of <pattern> up to dot are deleted. @@ -1097,6 +1121,9 @@ teco_state_search_kill_done(teco_machine_main_t *ctx, const teco_string_t *str, * In interactive mode, deletion is not performed * as-you-type but only on command termination. */ +/* + * ::FK is possible but doesn't make much sense, so it's undocumented. + */ TECO_DEFINE_STATE_SEARCH(teco_state_search_kill); static teco_state_t * @@ -1127,17 +1154,18 @@ teco_state_search_delete_done(teco_machine_main_t *ctx, const teco_string_t *str } /*$ FD - * FD[pattern]$ -- Delete occurrence of pattern - * [n]FD[pattern]$ + * [n]FD[pattern]$ -- Delete occurrence of pattern * -FD[pattern]$ * from,toFD[pattern]$ - * :FD[pattern]$ -> Success|Failure * [n]:FD[pattern]$ -> Success|Failure * -:FD[pattern]$ -> Success|Failure * from,to:FD[pattern]$ -> Success|Failure + * [n]::FD[pattern]$ -> Success|Failure + * -::FD[pattern]$ -> Success|Failure + * from,to::FD[pattern]$ -> Success|Failure * * Searches for <pattern> just like the regular search command - * (S) but when found deletes the entire occurrence. + * (\fBS\fP) but when found deletes the entire occurrence. */ TECO_DEFINE_STATE_SEARCH(teco_state_search_delete); @@ -1187,22 +1215,23 @@ teco_state_replace_done(teco_machine_main_t *ctx, const teco_string_t *str, GErr } /*$ FS - * FS[pattern]$[string]$ -- Search and replace - * [n]FS[pattern]$[string]$ + * [n]FS[pattern]$[string]$ -- Search and replace * -FS[pattern]$[string]$ * from,toFS[pattern]$[string]$ - * :FS[pattern]$[string]$ -> Success|Failure * [n]:FS[pattern]$[string]$ -> Success|Failure * -:FS[pattern]$[string]$ -> Success|Failure * from,to:FS[pattern]$[string]$ -> Success|Failure + * [n]::FS[pattern]$[string]$ -> Success|Failure + * -::FS[pattern]$[string]$ -> Success|Failure + * from,to::FS[pattern]$[string]$ -> Success|Failure * * Search for <pattern> just like the regular search command - * (S) does but replace it with <string> if found. + * (\fBS\fP) does but replace it with <string> if found. * If <string> is empty, the occurrence will always be - * deleted so \(lqFS[pattern]$$\(rq is similar to + * deleted so \(lqFS[pattern]\fB$$\fP\(rq is similar to * \(lqFD[pattern]$\(rq. * The global replace register is \fBnot\fP touched - * by the FS command. + * by the \fBFS\fP command. * * In interactive mode, the replacement will be performed * immediately and interactively. @@ -1291,20 +1320,21 @@ teco_state_replace_default_done(teco_machine_main_t *ctx, const teco_string_t *s } /*$ FR - * FR[pattern]$[string]$ -- Search and replace with default - * [n]FR[pattern]$[string]$ + * [n]FR[pattern]$[string]$ -- Search and replace with default * -FR[pattern]$[string]$ * from,toFR[pattern]$[string]$ - * :FR[pattern]$[string]$ -> Success|Failure * [n]:FR[pattern]$[string]$ -> Success|Failure * -:FR[pattern]$[string]$ -> Success|Failure * from,to:FR[pattern]$[string]$ -> Success|Failure + * [n]::FR[pattern]$[string]$ -> Success|Failure + * -::FR[pattern]$[string]$ -> Success|Failure + * from,to::FR[pattern]$[string]$ -> Success|Failure * - * The FR command is similar to the FS command. + * The \fBFR\fP command is similar to the \fBFS\fP command. * It searches for <pattern> just like the regular search - * command (S) and replaces the occurrence with <string> - * similar to what FS does. - * It differs from FS in the fact that the replacement + * command (\fBS\fP) and replaces the occurrence with <string> + * similar to what \fBFS\fP does. + * It differs from \fBFS\fP in the fact that the replacement * string is saved in the global replacement register * \(lq-\(rq. * If <string> is empty the string in the global replacement diff --git a/src/spawn.c b/src/spawn.c index a0bc7a9..fb7a946 100644 --- a/src/spawn.c +++ b/src/spawn.c @@ -463,7 +463,7 @@ teco_state_execute_done(teco_machine_main_t *ctx, const teco_string_t *str, GErr goto gerror; } - if (teco_machine_main_eval_colon(ctx)) + if (teco_machine_main_eval_colon(ctx) > 0) teco_expressions_push(TECO_SUCCESS); goto cleanup; diff --git a/tests/testsuite.at b/tests/testsuite.at index 0bb0c08..00861dc 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -119,6 +119,7 @@ AT_CHECK([$SCITECO -e "@I/^Q\05/ J @:S/^Q^Q^Q\05/\"F(0/0)'"], 0, ignore, ignore) AT_CHECK([$SCITECO -e "@I/XXX/J -^X @:S/xxx/\"S(0/0)'"], 0, ignore, ignore) # Search mode should be local to the macro frame. AT_CHECK([$SCITECO -e "-^X @^Um{^X} Mm-0\"N(0/0)'"], 0, ignore, ignore) +AT_CHECK([$SCITECO -e "@I/XYZ/ J ::@S/X/\"F(0/0)' H::@S/Z/\"S(0/0)'"], 0, ignore, ignore) AT_CLEANUP AT_SETUP([Search and insertion ranges]) |