From 2ec568579823c991b919fa3a2c8583a8db21cb81 Mon Sep 17 00:00:00 2001 From: Robin Haberkorn Date: Wed, 30 Jul 2025 23:58:32 +0300 Subject: implemented ^T command: allows typing by code and getting characters from stdin or the user * n:^T always prints bytes (cf. :^A) * ^T without arguments returns a codepoint or byte from stdin. In interactive mode, this currentply places a cursor in the message line and waits for a keypress. --- src/stdio-commands.c | 82 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 1 deletion(-) (limited to 'src/stdio-commands.c') diff --git a/src/stdio-commands.c b/src/stdio-commands.c index 2d5da62..3a1b320 100644 --- a/src/stdio-commands.c +++ b/src/stdio-commands.c @@ -292,7 +292,7 @@ TECO_DEFINE_STATE_EXPECTSTRING(teco_state_print_string, * * Type out the next or previous number of from the buffer * as a message, i.e. in the message line in interactive mode - * and if possible on the terminal (stdout) as well.. + * and if possible on the terminal (stdout) as well. * If is omitted, the sign prefix is implied. * If two arguments are specified, the characters beginning * at position up to the character at position @@ -320,3 +320,83 @@ teco_state_start_typeout(teco_machine_main_t *ctx, GError **error) const gchar *str = (const gchar *)teco_interface_ssm(SCI_GETRANGEPOINTER, from, len); teco_interface_msg_literal(TECO_MSG_USER, str, len); } + +/*$ "^T" ":^T" "typeout glyph" "get char" + * ^T -- Type out the numeric arguments as a message or get character from user + * :^T + * ^T -> codepoint + * :^T -> byte + * + * Types out characters for all the values + * on the argument stack (interpreted as codepoints) as messages, + * i.e. in the message line in interactive mode + * and if possible on the terminal (stdout) as well. + * It does so in the order of the arguments, i.e. + * is inserted before , ecetera. + * By default the codepoints are expected to be in the default + * codepage, but you can force raw ANSI encoding (for arbitrary + * bytes) by colon-modifying the command. + * + * When called without any argument, \fB^T\fP reads a key from the + * user (or from stdin) and returns the corresponding codepoint. + * If the default encoding is UTF-8, this will not work + * for function keys. + * If the default encoding is raw ANSI or if the command is + * colon-modified, \fB^T\fP returns raw bytes. + * When run in batch mode, this will return whatever byte is + * delivered by the attached terminal. + * In case stdin is closed, -1 is returned. + * In interactive mode, pressing CTRL+D or CTRL+C will also + * return -1. + */ +void +teco_state_control_typeout(teco_machine_main_t *ctx, GError **error) +{ + if (!teco_expressions_eval(FALSE, error)) + return; + + gboolean utf8 = !teco_machine_main_eval_colon(ctx) && + teco_default_codepage() == SC_CP_UTF8; + + guint args = teco_expressions_args(); + if (!args) { + teco_expressions_push(teco_interface_getch(utf8)); + return; + } + + if (!utf8) { + /* assume raw ANSI byte output */ + g_autofree gchar *buf = g_malloc(args); + gchar *p = buf+args; + + for (gint i = 0; i < args; i++) { + teco_int_t chr = teco_expressions_pop_num(0); + if (chr < 0 || chr > 0xFF) { + teco_error_codepoint_set(error, "^T"); + return; + } + *--p = chr; + } + + teco_interface_msg_literal(TECO_MSG_USER, p, args); + return; + } + + /* 4 bytes should be enough for UTF-8, but we better follow the documentation */ + g_autofree gchar *buf = g_malloc(args*6); + gchar *p = buf; + + for (gint i = args; i > 0; i--) { + teco_int_t chr = teco_expressions_peek_num(i-1); + if (chr < 0 || !g_unichar_validate(chr)) { + teco_error_codepoint_set(error, "^T"); + return; + } + p += g_unichar_to_utf8(chr, p); + } + /* we pop only now since we had to peek in reverse order */ + for (gint i = 0; i < args; i++) + teco_expressions_pop_num(0); + + teco_interface_msg_literal(TECO_MSG_USER, buf, p-buf); +} -- cgit v1.2.3