Change Ctrl-t r lua funtcion to start with the previous call state

When calling the Lua interpreter with Ctrl-t r, change to start with the
previous call state.

This allows you to use it like REPL:
(example)
  Ctrl-t r : my_library.lua
  Ctrl-t r : !result1 = my_func("test1"); result2 = my_func("test2")
  Ctrl-t r : !if (result1 == result2) then print("OK") else print("NG")
  Ctrl-t r : @new

When you enter strings using Ctrl-t r, the string is interpreted as
follows:
- If the string does not begin with either "!" or "@", the string is
assumed to be the file name of a script and is executed.
- If the string begins with "!", the string excluding the "!" is
interpreted as Lua commands.
- If the string begins with "@", Strings beginning with "@" are
considered instructions to the interpreter. Currently valid instructions
are:
@new: Clear the Lua state. (== reset the Lua interpreter.)
@doopt: Execute the Lua script action specified by the option that start
with clearing the Lua state.
@nuldo=opt: do @doopt action when an empty string is entered (default).
@nuldo=none: Do nothing when an empty string is entered.

And now, lua interpreter start with GC.
If you need to stop GC, do lua function collectgarbage("stop").
This commit is contained in:
yabu76 2025-11-29 18:03:30 +09:00
parent 0983ce6eeb
commit a9f05a66f7
3 changed files with 95 additions and 24 deletions

View file

@ -29,6 +29,7 @@
#include <lualib.h>
#include <sys/ioctl.h>
#include <ctype.h>
#include <assert.h>
#include "misc.h"
#include "print.h"
#include "options.h"
@ -44,6 +45,7 @@
#define READ_LINE_SIZE 4096 // read_line buffer length
static int device_fd;
static lua_State *script_interp = NULL;
// clang-format off
static char script_init[] =
@ -542,14 +544,26 @@ static int luaopen_tio(lua_State *L)
}
#endif
void script_run(int fd, const char *script_filename)
static lua_State *script_interp_new(void)
{
lua_State *L;
device_fd = fd;
if (script_interp != NULL) {
lua_close(script_interp);
}
L = luaL_newstate();
script_interp = L;
if (L == NULL) {
tio_error_printf("Can't allocate script buffer");
return NULL;
}
lua_gc(L, LUA_GCSTOP);
luaL_openlibs(L);
lua_gc(L, LUA_GCRESTART);
lua_gc(L, LUA_GCGEN, 0, 0);
#if LUA_VERSION_NUM >= 502
luaL_requiref(L, "tio", luaopen_tio, 1);
@ -564,31 +578,94 @@ void script_run(int fd, const char *script_filename)
// Initialize globals
script_set_globals(L);
if (script_filename != NULL)
return L;
}
void script_run(int fd, const char *script_filename)
{
tio_printf("Running script %s", script_filename);
// if filename starts with '!', do filename's remain parts as lua commands.
if (strlen(script_filename) >= 1 && script_filename[0] == '!')
static bool doopt_by_nul = true;
device_fd = fd;
assert(script_filename != NULL);
if (script_interp == NULL)
{
script_buffer_run(L, &script_filename[1]);
if (script_interp_new() == NULL)
return;
}
if (script_filename[0] == '\0')
{
if (doopt_by_nul)
{
script_run_as_specified_by_options(fd);
}
return;
}
else if (script_filename[0] == '@')
{
if (strcmp(script_filename, "@new") == 0)
{
tio_printf("Restart interpreter");
script_interp_new();
}
else if (strcmp(script_filename, "@doopt") == 0)
{
script_run_as_specified_by_options(fd);
}
else if (strcmp(script_filename, "@nuldo=opt") == 0)
{
doopt_by_nul = true;
}
else if (strcmp(script_filename, "@nuldo=none") == 0)
{
doopt_by_nul = false;
}
else
{
script_file_run(L, script_filename);
tio_printf("Unknown command");
}
return;
}
else
{
// if filename starts with '!', do filename's remain parts as lua commands.
tio_printf("Running script %s", script_filename);
if (script_filename[0] == '!')
{
script_buffer_run(script_interp, &script_filename[1]);
}
else
{
script_file_run(script_interp, script_filename);
}
return;
}
}
else if (option.script_filename != NULL)
void script_run_as_specified_by_options(int fd)
{
device_fd = fd;
if (script_interp == NULL)
{
if (script_interp_new() == NULL)
return;
}
if (option.script_filename != NULL)
{
tio_printf("Running script %s", option.script_filename);
script_file_run(L, option.script_filename);
if (script_interp_new())
script_file_run(script_interp, option.script_filename);
}
else if (option.script != NULL)
{
tio_printf("Running script");
script_buffer_run(L, option.script);
if (script_interp_new())
script_buffer_run(script_interp, option.script);
}
lua_close(L);
}
const char *script_run_state_to_string(script_run_t state)

View file

@ -30,4 +30,5 @@ typedef enum
} script_run_t;
void script_run(int fd, const char *script_filename);
void script_run_as_specified_by_options(int fd);
const char *script_run_state_to_string(script_run_t state);

View file

@ -1078,16 +1078,9 @@ void handle_command_sequence(char input_char, char *output_char, bool *forward)
case KEY_R:
/* Run script */
tio_printf("Run Lua script");
if (tio_subcmd_readln("Enter file name: "))
{
tio_subcmd_readln("Enter file name or \"!\" lua commands or \"@\" direction to interpreter: ");
clear_line();
script_run(device_fd, line);
}
else
{
clear_line();
script_run(device_fd, NULL);
}
break;
case KEY_SHIFT_R:
@ -2685,7 +2678,7 @@ int tty_connect(void)
/* Manage script activation */
if (option.script_run != SCRIPT_RUN_NEVER)
{
script_run(device_fd, NULL);
script_run_as_specified_by_options(device_fd);
if (option.script_run == SCRIPT_RUN_ONCE)
{