Add Lua API tio.inkey,input,set_keymap,receive and etc.

Add following functions to Lua API

tio.inkey()
tio.input()
tio.inputline()
tio.set_keymap()
tio.receive()
tio.subcmd_println()
tio.subcmd_warning_println()
tio.subcmd_error_println()
tio.subcmd_puts()
tio.subcmd_warning_puts()
tio.subcmd_error_puts()
This commit is contained in:
yabu76 2026-04-04 16:20:22 +09:00
parent c8df45ceff
commit e3b8724479
4 changed files with 415 additions and 2 deletions

View file

@ -417,7 +417,6 @@ Tio suppots Lua scripting to easily automate interaction with the tty device.
In addition to the standard Lua API tio makes the functions and variables available In addition to the standard Lua API tio makes the functions and variables available
The following are representative. See the man page for the complete list.: The following are representative. See the man page for the complete list.:
#### `tio.expect(pattern, timeout)` #### `tio.expect(pattern, timeout)`
Waits for the Lua pattern to match or timeout before continuing. Waits for the Lua pattern to match or timeout before continuing.
@ -468,6 +467,13 @@ Send file using x/y-modem protocol.
Protocol can be any of `XMODEM_1K`, `XMODEM_CRC`, `XMODEM_SUM`, `YMODEM`. Protocol can be any of `XMODEM_1K`, `XMODEM_CRC`, `XMODEM_SUM`, `YMODEM`.
Alternatively, it can be one of tio.C.XM_1K, tio.C.XM_CRC, tio.C.XM_SUM, or tio.C.YM_NORMAL. Alternatively, it can be one of tio.C.XM_1K, tio.C.XM_CRC, tio.C.XM_SUM, or tio.C.YM_NORMAL.
#### `tio.receive(file, protocol)`
eceive a file using the XMODEM protocol.
protocol can be one of XMODEM_CRC or XMODEM_SUM.
Alternatively, use tio.C.XM_CRC or tio.C.XM_SUM.
#### `tio.ttysearch()` #### `tio.ttysearch()`
Search for serial devices. Search for serial devices.
@ -495,6 +501,45 @@ Sleep for seconds.
Sleep for milliseconds. Sleep for milliseconds.
#### `tio.inkey(timeout)`
Read a key press as a string.
timeout is specified in milliseconds.
Defaults to tio.C.NOWAIT (==-1), meaning the call returns immediately.
If set to tio.C.WAIT_FOREVER (==0), the function blocks until a key is pressed.
Returns nil on timeout.
#### `tio.input(prompt)`
Display a prompt and read user input until Enter is pressed.
Basic editing is supported (Backspace key).
If prompt is omitted, no prompt is displayed.
Returns the entered string.
#### `tio.inputline(prompt)`
Display a prompt and read a line of input until Enter is pressed.
Supports line editing (cursor keys, Backspace) and command history.
Returns the entered string.
#### `tio.set_keymap(keymaps)`
Add, update, or remove key mappings.
#### `tio.subcmd_println(fmt, ...)`
Print a formatted line using sub-command style output
(e.g. [<timestamp>] <message>).
#### `tio.subcmd_puts(string)`
Print string using sub-command style output.
(e.g. [<time-stamp>] <string>).
#### `tio.alwaysecho` #### `tio.alwaysecho`
A boolean value, defaults to `true`. A boolean value, defaults to `true`.

View file

@ -547,6 +547,14 @@ Send file using x/y-modem protocol.
Protocol can be any of XMODEM_1K, XMODEM_CRC, XMODEM_SUM, YMODEM. Protocol can be any of XMODEM_1K, XMODEM_CRC, XMODEM_SUM, YMODEM.
It can alternatively be one of tio.C.XM_1K, tio.C.XM_CRC, tio.C.XM_SUM, tio.C.YM_NORMAL. It can alternatively be one of tio.C.XM_1K, tio.C.XM_CRC, tio.C.XM_SUM, tio.C.YM_NORMAL.
.IP "\fBtio.receive(file, protocol)"
Receive a file using the XMODEM protocol.
Protocol can be any of XMODEM_CRC or XMODEM_SUM.
It can alternatively be one of tio.C.XM_CRC or tio.C.XM_SUM.
Returns the tio table on success or nil on error.
.IP "\fBtio.ttysearch()" .IP "\fBtio.ttysearch()"
Search for serial devices. Search for serial devices.
@ -643,6 +651,82 @@ Return value is one of tio.C.SA_INTERACTIVE, tio.C.SA_STARTING, tio.C.SA_PIPED_I
Return the version of tio as a string. Return the version of tio as a string.
It is equivalent to the key command ctrl-t v. It is equivalent to the key command ctrl-t v.
.IP "\fBtio.inkey(timeout)"
Read a key press and return it as a string.
Timeout is in milliseconds. If timeout is tio.C.WAIT_FOREVER(==0),
the function blocks until a key is pressed. If timeout is
tio.C.NOWAIT (==-1) or not provided, the function returns
immediately.
Returns the key as a string on success, or nil on timeout.
.IP "\fBtio.input(prompt)"
Display a prompt and read user input until Enter is pressed.
Basic line editing is supported (Backspace key).
If prompt is not provided, no prompt is displayed.
Returns the entered string.
.IP "\fBtio.inputline(prompt)"
Display a prompt and read a line of input until Enter is pressed.
Supports line editing (cursor keys, Backspace) and command history.
Returns the entered string.
.IP "\fBtio.set_keymap(keymaps)"
Add, update, or remove key mappings.
The keymaps argument uses the same syntax as the --keymap option:
@<key-1>=<script-description-1>
@<key-2>=<script-description-2>
...
@<key-N>=<script-description-N>
Each <script-description> must be either a script filename or an
inline script prefixed with '!'.
When a mapping is defined, pressing Ctrl-t followed by <key-n>
executes the corresponding script.
If a key already has a mapping, it is updated. If
<script-description> is empty, the mapping is removed.
User-defined key mappings take precedence over default key bindings,
except for "Ctrl-t q", which is always reserved.
This function allows key mappings to be modified at runtime after tio
has started.
.IP "\fBtio.subcmd_println(fmt, ...)"
Print a formatted line using sub-command style output.
The output format is:
[<timestamp>] <formatted message>
.IP "\fBtio.subcmd_warning_println(fmt, ...)"
Print a formatted warning line using sub-command style output.
.IP "\fBtio.subcmd_error_println(fmt, ...)"
Print a formatted error line using sub-command style output.
.IP "\fBtio.subcmd_error_println(fmt, ...)"
.IP "\fBtio.subcmd_puts(string)"
Print a string using sub-command style output.
The output format is:
[<timestamp>] <string>
.IP "\fBtio.subcmd_warning_puts(string)"
Print a warning string using sub-command style output.
.IP "\fBtio.subcmd_error_puts(string)"
Print an error string using sub-command style output.
.IP "\fBtio.alwaysecho" .IP "\fBtio.alwaysecho"
A boolean value, defaults to true. A boolean value, defaults to true.
@ -958,7 +1042,6 @@ Receive file from device by gkermit command:
$ tio --exec '?gkermit -XSr' /dev/ttyUSB0 $ tio --exec '?gkermit -XSr' /dev/ttyUSB0
.SH "WEBSITE" .SH "WEBSITE"
.PP .PP
Visit https://tio.github.io Visit https://tio.github.io

View file

@ -454,6 +454,14 @@ SCRIPT API
Protocol can be any of XMODEM_1K, XMODEM_CRC, XMODEM_SUM, YMODEM. Protocol can be any of XMODEM_1K, XMODEM_CRC, XMODEM_SUM, YMODEM.
It can alternatively be one of tio.C.XM_1K, tio.C.XM_CRC, tio.C.XM_SUM, tio.C.YM_NORMAL. It can alternatively be one of tio.C.XM_1K, tio.C.XM_CRC, tio.C.XM_SUM, tio.C.YM_NORMAL.
tio.receive(file, protocol)
Receive a file using the XMODEM protocol.
Protocol can be any of XMODEM_CRC or XMODEM_SUM.
It can alternatively be one of tio.C.XM_CRC or tio.C.XM_SUM.
Returns the tio table on success or nil on error.
tio.ttysearch() tio.ttysearch()
Search for serial devices. Search for serial devices.
@ -548,6 +556,77 @@ SCRIPT API
Return the version of tio as a string. Return the version of tio as a string.
It is equivalent to the key command ctrl-t v. It is equivalent to the key command ctrl-t v.
tio.inkey(timeout)
Read a key press and return it as a string.
Timeout is in milliseconds. If timeout is tio.C.WAIT_FOREVER(==0),
the function blocks until a key is pressed. If timeout is
tio.C.NOWAIT (==-1) or not provided, the function returns
immediately.
Returns the key as a string on success, or nil on timeout.
tio.input(prompt)
Display a prompt and read user input until Enter is pressed.
Basic line editing is supported (Backspace key).
If prompt is not provided, no prompt is displayed.
Returns the entered string.
tio.inputline(prompt)
Display a prompt and read a line of input until Enter is pressed.
Supports line editing (cursor keys, Backspace) and command
history.
Returns the entered string.
tio.set_keymap(keymaps)
Add, update, or remove key mappings.
The <keymaps> argument uses the same syntax as the --keymap option:
@<key-1>=<script-description-1>
@<key-2>=<script-description-2>
...
@<key-N>=<script-description-N>
Each <script-description> must be either a script filename or an inline script prefixed with '!'.
When a mapping is defined, pressing Ctrl-T followed by <key-n> executes the corresponding script.
If a key already has a mapping, it will be updated. If <script-description> is empty, the mapping is removed.
User-defined key mappings take precedence over default key bindings, except for "Ctrl-T q", which is always reserved.
This function can be used to dynamically modify key mappings at runtime after tio has started.
tio.subcmd_println(fmt, ...)
Print a formatted line using sub-command style output.
The output format is:
[<timestamp>] <formatted message>
tio.subcmd_warning_println(fmt, ...)
Print a formatted warning line using sub-command style output.
tio.subcmd_error_println(fmt, ...)
Print a formatted error line using sub-command style output.
tio.subcmd_puts(string)
Print a string using sub-command style output.
The output format is:
[<timestamp>] <string>
tio.subcmd_warning_puts(string)
Print a warning string using sub-command style output.
tio.subcmd_error_puts(string)
Print an error string using sub-command style output.
tio.alwaysecho tio.alwaysecho
A boolean value, defaults to true. A boolean value, defaults to true.

View file

@ -108,6 +108,15 @@ static char script_init[] =
" end\n" " end\n"
" end\n" " end\n"
"end\n" "end\n"
"tio.subcmd_println = function(fmt, ...)\n"
" tio.subcmd_puts(string.format(fmt, select(1, ...)))\n"
"end\n"
"tio.subcmd_warning_println = function(fmt, ...)\n"
" tio.subcmd_warning_puts(fmt, string.format(fmt, select(1, ...)))\n"
"end\n"
"tio.subcmd_error_println = function(fmt, ...)\n"
" tio.subcmd_error_puts(fmt, string.format(fmt, select(1, ...)))\n"
"end\n"
"tio.alwaysecho = true\n" "tio.alwaysecho = true\n"
"setmetatable(tio, tio)\n"; "setmetatable(tio, tio)\n";
// clang-format on // clang-format on
@ -339,6 +348,54 @@ static int api_send(lua_State *L)
return 0; return 0;
} }
// lua: tio.receive(file, protocol)
static int api_receive(lua_State *L)
{
const char *file = luaL_checkstring(L, 1);
int protocol = luaL_checkinteger(L, 2);
int ret;
if (device_fd == 0)
{
return luaL_error(L, "tty device not ready");
}
if (file == NULL)
{
return 0;
}
state_t state_orig = state;
state = STATE_XYMODEM;
tty_tcsetattr(device_fd);
switch (protocol)
{
case XMODEM_CRC:
tio_printf("Receiving file '%s' using XMODEM-CRC", file);
ret = xymodem_receive(device_fd, file, XMODEM_CRC);
tio_printf("%s", ret < 0 ? "Aborted" : "Done");
break;
case XMODEM_SUM:
tio_printf("Receiving file '%s' using XMODEM-SUM", file);
ret = xymodem_receive(device_fd, file, XMODEM_SUM);
tio_printf("%s", ret < 0 ? "Aborted" : "Done");
break;
case XMODEM_1K:
case YMODEM:
default:
tio_error_printf("Not supported");
break;
}
state = state_orig;
tty_tcsetattr(device_fd);
return 0;
}
// lua: tio.write(string) // lua: tio.write(string)
static int api_write(lua_State *L) static int api_write(lua_State *L)
{ {
@ -497,6 +554,145 @@ static int api_readline(lua_State *L)
} }
} }
// lua: str = tio.inkey(mseconds)
static int api_inkey(lua_State *L)
{
extern char inkey_chars[];
int ret;
int mseconds;
int arg_num = lua_gettop(L);
int arg;
if (arg_num == 0)
{
arg = -1;
}
else
{
arg = lua_tointeger(L, 1);
}
if (arg == 0)
{
mseconds = POLL_FOREVER;
}
else if (arg < 0)
{
mseconds = POLL_NOWAIT;
}
else
{
mseconds = arg;
}
ret = tty_inkey(mseconds);
if (ret == 0)
{
/* Timeout */
lua_pushnil(L);
return 1;
}
else if (ret < 0) {
return luaL_error(L, "inkey failed");
}
lua_pushlstring(L, inkey_chars, ret);
return 1;
}
// lua: str = tio.input(prompt)
static int api_input(lua_State *L)
{
extern char line[];
int arg_num = lua_gettop(L);
const char *prompt = "";
if (arg_num > 0)
{
prompt = luaL_checkstring(L, 1);
}
tty_simple_readln(prompt);
lua_pushstring(L, line);
return 1;
}
// lua: str = tio.inputline(title_prompt)
static int api_input_line(lua_State *L)
{
extern char line[];
int arg_num = lua_gettop(L);
const char *prompt = "";
if (arg_num > 0)
{
prompt = luaL_checkstring(L, 1);
}
tty_subcmd_readln(prompt);
lua_pushstring(L, line);
return 1;
}
// lua: api_subcmd_puts(str)
static int api_subcmd_puts(lua_State *L)
{
int arg_num = lua_gettop(L);
const char *str;
if (arg_num != 1)
{
return luaL_error(L, "arguments error");
}
str = luaL_checkstring(L, 1);
tio_printf("%s", str);
return 0;
}
// lua: api_subcmd_warning_puts(str)
static int api_subcmd_warning_puts(lua_State *L)
{
int arg_num = lua_gettop(L);
const char *str;
if (arg_num != 1)
{
return luaL_error(L, "arguments error");
}
str = luaL_checkstring(L, 1);
tio_warning_printf("%s", str);
return 0;
}
// lua: api_subcmd_error_puts(str)
static int api_subcmd_error_puts(lua_State *L)
{
int arg_num = lua_gettop(L);
const char *str;
if (arg_num != 1)
{
return luaL_error(L, "arguments error");
}
str = luaL_checkstring(L, 1);
tio_error_printf("%s", str);
return 0;
}
// lua: true/false, error = tio.set_keymap(keymap_str)
static int api_set_keymap(lua_State *L)
{
int arg_num = lua_gettop(L);
const char *keymap_str;
if (arg_num != 1)
{
return luaL_error(L, "arguments error");
}
keymap_str = luaL_checkstring(L, 1);
#if 1
option_parse_key_mappings(keymap_str);
return 0;
#else
ret = option_parse_key_mappings(keymap_str);
if (ret < 0)
{
return luaL_error(L, "keymap setting failed");
}
lua_pushboolean(L, true);
return 1;
#endif
}
// lua: table = tio.ttysearch() // lua: table = tio.ttysearch()
static int api_ttysearch(lua_State *L) static int api_ttysearch(lua_State *L)
{ {
@ -797,6 +993,7 @@ static const struct luaL_Reg tio_lib[] =
{ "line_set", api_line_set}, { "line_set", api_line_set},
{ "line_get", api_line_get}, { "line_get", api_line_get},
{ "send", api_send}, { "send", api_send},
{ "receive", api_receive},
{ "write", api_write}, { "write", api_write},
{ "twrite", api_twrite}, { "twrite", api_twrite},
{ "read", api_read}, { "read", api_read},
@ -816,6 +1013,15 @@ static const struct luaL_Reg tio_lib[] =
{ "get_state", api_get_state}, { "get_state", api_get_state},
{ "get_version", api_get_version}, { "get_version", api_get_version},
{ "inkey", api_inkey},
{ "input", api_input},
{ "inputline", api_input_line},
{ "set_keymap", api_set_keymap},
{ "subcmd_puts", api_subcmd_puts},
{ "subcmd_warning_puts", api_subcmd_warning_puts},
{ "subcmd_error_puts", api_subcmd_error_puts},
{NULL, NULL} {NULL, NULL}
}; };
// clang-format on // clang-format on