aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorRobin Haberkorn <robin.haberkorn@googlemail.com>2025-07-26 00:37:43 +0300
committerRobin Haberkorn <robin.haberkorn@googlemail.com>2025-07-26 00:42:15 +0300
commiteb6f7a82045ad78553fca98c54a51366c55bd7a4 (patch)
treeff0cca8d3dfb71afe832e73616867cd09fdac22c /src
parent574b46657cd5b752597384b31f37dd6a07f063d8 (diff)
downloadsciteco-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.c65
-rw-r--r--src/core-commands.h2
-rw-r--r--src/qreg-commands.c33
-rw-r--r--src/stdio-commands.c36
-rw-r--r--src/stdio-commands.h4
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);