mirror of
https://github.com/tio/tio.git
synced 2026-05-01 14:57:59 +02:00
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:
parent
c8df45ceff
commit
e3b8724479
4 changed files with 415 additions and 2 deletions
47
README.md
47
README.md
|
|
@ -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
|
||||
The following are representative. See the man page for the complete list.:
|
||||
|
||||
|
||||
#### `tio.expect(pattern, timeout)`
|
||||
|
||||
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`.
|
||||
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()`
|
||||
|
||||
Search for serial devices.
|
||||
|
|
@ -495,6 +501,45 @@ Sleep for seconds.
|
|||
|
||||
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`
|
||||
|
||||
A boolean value, defaults to `true`.
|
||||
|
|
|
|||
85
man/tio.1.in
85
man/tio.1.in
|
|
@ -547,6 +547,14 @@ Send file using x/y-modem protocol.
|
|||
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.
|
||||
|
||||
.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()"
|
||||
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.
|
||||
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"
|
||||
A boolean value, defaults to true.
|
||||
|
||||
|
|
@ -958,7 +1042,6 @@ Receive file from device by gkermit command:
|
|||
|
||||
$ tio --exec '?gkermit -XSr' /dev/ttyUSB0
|
||||
|
||||
|
||||
.SH "WEBSITE"
|
||||
.PP
|
||||
Visit https://tio.github.io
|
||||
|
|
|
|||
|
|
@ -454,6 +454,14 @@ SCRIPT API
|
|||
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.
|
||||
|
||||
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()
|
||||
Search for serial devices.
|
||||
|
||||
|
|
@ -548,6 +556,77 @@ SCRIPT API
|
|||
Return the version of tio as a string.
|
||||
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
|
||||
A boolean value, defaults to true.
|
||||
|
||||
|
|
|
|||
206
src/script.c
206
src/script.c
|
|
@ -108,6 +108,15 @@ static char script_init[] =
|
|||
" 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"
|
||||
"setmetatable(tio, tio)\n";
|
||||
// clang-format on
|
||||
|
|
@ -339,6 +348,54 @@ static int api_send(lua_State *L)
|
|||
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)
|
||||
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()
|
||||
static int api_ttysearch(lua_State *L)
|
||||
{
|
||||
|
|
@ -797,6 +993,7 @@ static const struct luaL_Reg tio_lib[] =
|
|||
{ "line_set", api_line_set},
|
||||
{ "line_get", api_line_get},
|
||||
{ "send", api_send},
|
||||
{ "receive", api_receive},
|
||||
{ "write", api_write},
|
||||
{ "twrite", api_twrite},
|
||||
{ "read", api_read},
|
||||
|
|
@ -816,6 +1013,15 @@ static const struct luaL_Reg tio_lib[] =
|
|||
{ "get_state", api_get_state},
|
||||
{ "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}
|
||||
};
|
||||
// clang-format on
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue