diff options
author | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-07-26 00:37:43 +0300 |
---|---|---|
committer | Robin Haberkorn <robin.haberkorn@googlemail.com> | 2025-07-26 00:42:15 +0300 |
commit | eb6f7a82045ad78553fca98c54a51366c55bd7a4 (patch) | |
tree | ff0cca8d3dfb71afe832e73616867cd09fdac22c /src | |
parent | 574b46657cd5b752597384b31f37dd6a07f063d8 (diff) | |
download | sciteco-eb6f7a82045ad78553fca98c54a51366c55bd7a4.tar.gz |
implemented the <T> (typeout) command for printing to the terminal from the current buffer
* refactored some code that is common with Xq into teco_get_range_args().
Diffstat (limited to 'src')
-rw-r--r-- | src/core-commands.c | 65 | ||||
-rw-r--r-- | src/core-commands.h | 2 | ||||
-rw-r--r-- | src/qreg-commands.c | 33 | ||||
-rw-r--r-- | src/stdio-commands.c | 36 | ||||
-rw-r--r-- | src/stdio-commands.h | 4 |
5 files changed, 108 insertions, 32 deletions
diff --git a/src/core-commands.c b/src/core-commands.c index 2669748..abd3a22 100644 --- a/src/core-commands.c +++ b/src/core-commands.c @@ -52,6 +52,68 @@ static teco_state_t *teco_state_control_input(teco_machine_main_t *ctx, gunichar chr, GError **error); static teco_state_t *teco_state_ctlc_control_input(teco_machine_main_t *ctx, gunichar chr, GError **error); +/** + * Translate buffer range arguments from the expression stack to + * a from-position and length in bytes. + * + * If only one argument is given, it is interpreted as a number of lines + * beginning with dot. + * If two arguments are given, it is interpreted as two buffer positions + * in glyphs. + * + * @param cmd Name of the command + * @param from_ret Where to store the from-position in bytes + * @param len_ret Where to store the length of the range in bytes + * @param error A GError + * @return FALSE if an error occurred + * + * @fixme There are still redundancies with teco_state_start_kill(). + * But it needs to discern between invalid ranges and other errors. + */ +gboolean +teco_get_range_args(const gchar *cmd, gsize *from_ret, gsize *len_ret, GError **error) +{ + gssize from, len; /* in bytes */ + + if (!teco_expressions_eval(FALSE, error)) + return FALSE; + + if (teco_expressions_args() <= 1) { + teco_int_t line; + + if (!teco_expressions_pop_num_calc(&line, teco_num_sign, error)) + return FALSE; + + from = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0); + line += teco_interface_ssm(SCI_LINEFROMPOSITION, from, 0); + + if (!teco_validate_line(line)) { + teco_error_range_set(error, cmd); + return FALSE; + } + + len = teco_interface_ssm(SCI_POSITIONFROMLINE, line, 0) - from; + + if (len < 0) { + from += len; + len *= -1; + } + } else { + gssize to = teco_interface_glyphs2bytes(teco_expressions_pop_num(0)); + from = teco_interface_glyphs2bytes(teco_expressions_pop_num(0)); + len = to - from; + + if (len < 0 || from < 0 || to < 0) { + teco_error_range_set(error, cmd); + return FALSE; + } + } + + *from_ret = from; + *len_ret = len; + return TRUE; +} + /* * NOTE: This needs some extra code in teco_state_start_input(). */ @@ -660,7 +722,8 @@ teco_state_start_input(teco_machine_main_t *ctx, gunichar chr, GError **error) .modifier_colon = 1}, ['D'] = {&teco_state_start, teco_state_start_delete_chars, .modifier_colon = 1}, - ['A'] = {&teco_state_start, teco_state_start_get} + ['A'] = {&teco_state_start, teco_state_start_get}, + ['T'] = {&teco_state_start, teco_state_start_typeout} }; switch (chr) { diff --git a/src/core-commands.h b/src/core-commands.h index 9ae508b..bf73b8c 100644 --- a/src/core-commands.h +++ b/src/core-commands.h @@ -25,6 +25,8 @@ /** non-operational characters in teco_state_start */ #define TECO_NOOPS " \f\r\n\v" +gboolean teco_get_range_args(const gchar *cmd, gsize *from_ret, gsize *len_ret, GError **error); + /* in cmdline.c */ gboolean teco_state_command_process_edit_cmd(teco_machine_main_t *ctx, teco_machine_t *parent_ctx, gunichar key, GError **error); diff --git a/src/qreg-commands.c b/src/qreg-commands.c index e9f80fb..5055058 100644 --- a/src/qreg-commands.c +++ b/src/qreg-commands.c @@ -780,39 +780,10 @@ teco_state_copytoqreg_got_register(teco_machine_main_t *ctx, teco_qreg_t *qreg, if (ctx->flags.mode > TECO_MODE_NORMAL) return &teco_state_start; - gssize from, len; /* in bytes */ + gsize from, len; - if (!teco_expressions_eval(FALSE, error)) + if (!teco_get_range_args("X", &from, &len, error)) return NULL; - if (teco_expressions_args() <= 1) { - teco_int_t line; - - from = teco_interface_ssm(SCI_GETCURRENTPOS, 0, 0); - if (!teco_expressions_pop_num_calc(&line, teco_num_sign, error)) - return NULL; - line += teco_interface_ssm(SCI_LINEFROMPOSITION, from, 0); - - if (!teco_validate_line(line)) { - teco_error_range_set(error, "X"); - return NULL; - } - - len = teco_interface_ssm(SCI_POSITIONFROMLINE, line, 0) - from; - - if (len < 0) { - from += len; - len *= -1; - } - } else { - gssize to = teco_interface_glyphs2bytes(teco_expressions_pop_num(0)); - from = teco_interface_glyphs2bytes(teco_expressions_pop_num(0)); - len = to - from; - - if (len < 0 || from < 0 || to < 0) { - teco_error_range_set(error, "X"); - return NULL; - } - } /* * NOTE: This does not use SCI_GETRANGEPOINTER+SCI_GETGAPPOSITION diff --git a/src/stdio-commands.c b/src/stdio-commands.c index 0c8d20c..1a64db9 100644 --- a/src/stdio-commands.c +++ b/src/stdio-commands.c @@ -261,3 +261,39 @@ teco_state_print_string_done(teco_machine_main_t *ctx, const teco_string_t *str, TECO_DEFINE_STATE_EXPECTSTRING(teco_state_print_string, .initial_cb = (teco_state_initial_cb_t)teco_state_print_string_initial ); + +/*$ T type typeout + * [lines]T -- Type out buffer contents as messages + * -T + * from,toT + * + * Type out the next or previous number of <lines> from the buffer + * as a message, i.e. in the message line in interactive mode + * and if possible on the terminal (stdout) as well.. + * If <lines> is omitted, the sign prefix is implied. + * 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 \fBK\fP + * command's arguments. + */ +void +teco_state_start_typeout(teco_machine_main_t *ctx, GError **error) +{ + gsize from, len; + + if (!teco_get_range_args("T", &from, &len, error)) + return; + + /* + * NOTE: This may remove the buffer gap since we need a consecutive + * piece of memory to log as a single message. + * FIXME: In batch mode even this could theoretically be avoided. + * Need to add a function like teco_interface_is_batch(). + * Still, this is probably more efficient than using a temporary + * allocation with SCI_GETTEXTRANGEFULL. + */ + const gchar *str = (const gchar *)teco_interface_ssm(SCI_GETRANGEPOINTER, from, len); + teco_interface_msg_literal(TECO_MSG_USER, str, len); +} diff --git a/src/stdio-commands.h b/src/stdio-commands.h index 33b2594..b6870e7 100644 --- a/src/stdio-commands.h +++ b/src/stdio-commands.h @@ -16,7 +16,11 @@ */ #pragma once +#include <glib.h> + #include "parser.h" TECO_DECLARE_STATE(teco_state_print_decimal); TECO_DECLARE_STATE(teco_state_print_string); + +void teco_state_start_typeout(teco_machine_main_t *ctx, GError **error); |