Add Lua REPL mode and multiline edit function in the mode.

Typing "@repl" after Ctrl-t r, enter Lua REPL mode.
Typing "@exit" in REPL mode will return you to normal mode.

Note:
- the determination of continuation lines is not done automatically, and
  if the end of a line is \, it is determined to be a continuation
  instruction.
- In REPL mode, tio's main loop is blocked. (Ctrl-t q works.)

Example:
>> t = {1,2,3,4,5}
>> for _,v in ipairs(t) do\
>>     print(v,"\r")\
>> end

Implementation improvements:
- Add tty_init() and script_interp_init() in order to only once
  initialization.
- Fix script function to work without device_fd.
This commit is contained in:
yabu76 2025-12-30 11:41:39 +09:00
parent c25a379fbb
commit 266338a926
5 changed files with 155 additions and 37 deletions

View file

@ -147,6 +147,8 @@ typedef enum
SUBCOMMAND_MAP,
} sub_command_t;
#define MLINE_MAX 4096
// clang-format off
const char random_array[] =
{
@ -183,7 +185,7 @@ static char *tty_buffer_write_ptr = tty_buffer;
static pthread_t thread;
static int pipefd[2];
static pthread_mutex_t mutex_input_ready = PTHREAD_MUTEX_INITIALIZER;
static char line[PATH_MAX];
static char line[PATH_MAX], mline[MLINE_MAX];
static size_t listing_device_name_length_max = 0;
static readline_t *readline_ctx = NULL;
static readline_t *subcmd_readline_ctx = NULL;
@ -593,7 +595,9 @@ static void tty_line_poke(int fd, int mask, tty_line_mode_t mode, unsigned int d
static int tio_subcmd_readln(const char *title_prompt)
{
tio_printf_raw("%s\r\n", title_prompt);
if (title_prompt && (title_prompt[0] != '\0')) {
tio_printf_raw("%s\r\n", title_prompt);
}
readline_prompt_for_input(subcmd_readline_ctx);
/* Read line with line edit and history. */
@ -660,6 +664,50 @@ static void mappings_print(void)
// clang-format on
}
static void handle_script_repl(void)
{
bool local_echo_bkup = option.local_echo;
int line_len;
int mline_len = 0;
option.local_echo = true;
tio_printf("Enter Lua REPL mode (@exit to exit)");
strcpy(mline, "");
while (true)
{
tio_subcmd_readln("");
if (strcmp(line, "@exit") == 0)
break;
line_len = strlen(line);
if (line_len > 0)
{
if (mline_len + line_len + 1 > MLINE_MAX)
{
tio_printf("Too long lines. The size should be lesser then %d bytes", MLINE_MAX);
strcpy(mline, "");
mline_len = 0;
continue;
}
strcat(&mline[mline_len], line);
mline_len += line_len;
if (mline_len > 0 && mline[mline_len - 1] == '\\')
{
mline[mline_len - 1] = '\n';
continue;
}
}
script_do_line(mline);
strcpy(mline, "");
mline_len = 0;
}
option.local_echo = local_echo_bkup;
}
void handle_command_sequence(char input_char, char *output_char, bool *forward)
{
char unused_char;
@ -1079,8 +1127,15 @@ void handle_command_sequence(char input_char, char *output_char, bool *forward)
/* Run script */
tio_printf("Run Lua script");
tio_subcmd_readln("Enter file name or \"!\" lua commands or \"@\" direction to interpreter: ");
clear_line();
script_run(device_fd, line);
if (strcmp(line, "@repl") == 0)
{
handle_script_repl();
}
else
{
clear_line();
script_run(line);
}
break;
case KEY_SHIFT_R:
@ -2545,6 +2600,21 @@ void forward_to_tty(int fd, char output_char)
}
}
void tty_init(void)
{
// Initialize readline like history
readline_ctx = readline_create();
subcmd_readline_ctx = readline_create();
if (readline_ctx == NULL || subcmd_readline_ctx == NULL)
{
tio_error_printf("Could not allocate readline buffer.");
exit(EXIT_FAILURE);
}
readline_set_prompt(readline_ctx, "> ");
readline_set_prompt(subcmd_readline_ctx, ">> ");
}
int tty_connect(void)
{
fd_set rdfs; /* Read file descriptor set */
@ -2676,9 +2746,11 @@ int tty_connect(void)
}
/* Manage script activation */
script_device_bind(device_fd);
if (option.script_run != SCRIPT_RUN_NEVER)
{
script_run_as_specified_by_options(device_fd);
script_run_as_specified_by_options();
if (option.script_run == SCRIPT_RUN_ONCE)
{
@ -2698,17 +2770,6 @@ int tty_connect(void)
exit(status);
}
// Initialize readline like history
readline_ctx = readline_create();
subcmd_readline_ctx = readline_create();
if (readline_ctx == NULL || subcmd_readline_ctx == NULL)
{
tio_error_printf("Could not allocate readline buffer.");
exit(EXIT_FAILURE);
}
readline_set_prompt(readline_ctx, "> ");
readline_set_prompt(subcmd_readline_ctx, ">> ");
/* Input loop */
while (true)
{
@ -3035,6 +3096,7 @@ error_setspeed:
error_tcsetattr:
error_tcgetattr:
error_read:
script_device_unbind();
tty_disconnect();
error_open:
return TIO_ERROR;