Skip to content

Commit

Permalink
chore: update uv.tty_set_mode, and add tty test
Browse files Browse the repository at this point in the history
  • Loading branch information
zhaozg committed Aug 13, 2023
1 parent d15a473 commit ad725c2
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 1 deletion.
10 changes: 10 additions & 0 deletions src/constants.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,16 @@ static int luv_constants(lua_State* L) {
lua_pushinteger(L, UV_PIPE_NO_TRUNCATE);
lua_setfield(L, -2, "PIPE_NO_TRUNCATE");
#endif

#if LUV_UV_VERSION_GEQ(1, 2, 0)
lua_pushinteger(L, UV_TTY_MODE_NORMAL);
lua_setfield(L, -2, "TTY_MODE_NORMAL");
lua_pushinteger(L, UV_TTY_MODE_RAW);
lua_setfield(L, -2, "TTY_MODE_RAW");
lua_pushinteger(L, UV_TTY_MODE_IO);
lua_setfield(L, -2, "TTY_MODE_IO");
#endif

return 1;
}

Expand Down
18 changes: 17 additions & 1 deletion src/tty.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,25 @@ static int luv_new_tty(lua_State* L) {
return 1;
}

static int luv_check_tty_mode(lua_State *L, int i) {
const char* modes[] = { "normal", "raw", "io", NULL};
int mode;

if (lua_isnumber(L, i))
mode = lua_tonumber(L, i);
else
mode = luaL_checkoption(L, i, NULL, modes);

#if LUV_UV_VERSION_GEQ(1, 2, 0)
luaL_argcheck(L, mode >= UV_TTY_MODE_NORMAL && mode <= UV_TTY_MODE_IO,
i, "Out of accept range");
#endif
return mode;
}

static int luv_tty_set_mode(lua_State* L) {
uv_tty_t* handle = luv_check_tty(L, 1);
int mode = luaL_checkinteger(L, 2);
int mode = luv_check_tty_mode(L, 2);
int ret = uv_tty_set_mode(handle, mode);
return luv_result(L, ret);
}
Expand Down
113 changes: 113 additions & 0 deletions tests/test-tty.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
-- come from https://github.com/libuv/libuv/blob/v1.x/test/test-tty.c
local _, ffi = pcall(require, 'ffi')
if not ffi then
print('skip, without luajit ffi')
return
end

if not (ffi.os == "Linux" or ffi.os == "OSX") then
print('skip, not on linux or macos')
return
end

return require('lib/tap')(function (test)

test("tty normal", function (print, p, expect, uv)
-- uv.tty_set_vterm_state("supported")
-- print(uv.tty_get_vterm_state())

local stdin = uv.new_tty(0, true)
local stdout = uv.new_tty(1, false)

local stype = os.getenv('GITHUB_ACTION') and 'pipe' or 'tty'

assert(stype == uv.guess_handle(0))
assert(stype == uv.guess_handle(1))
assert(uv.is_readable(stdin))
assert(uv.is_writable(stdout))

uv.close(stdin)
uv.close(stdout)
end)

test("tty pty", function (print, p, expect, uv)
ffi.cdef[[
struct winsize {
unsigned short ws_row;
unsigned short ws_col;
unsigned short ws_xpixel; /* unused */
unsigned short ws_ypixel; /* unused */
};
int openpty(int *amaster, int *aslave, char *name,
const void* termp, const struct winsize* winp);
]]

local master_fd = ffi.new('int[1]')
local slave_fd = ffi.new('int[1]')
local winp = ffi.new('struct winsize[1]')

local r, util = pcall(ffi.load, 'util')
if r then
r = util.openpty(master_fd, slave_fd, nil, nil, winp);
else
r = ffi.C.openpty(master_fd, slave_fd, nil, nil, winp);
end
assert(tonumber(r)==0)

local master_tty = uv.new_tty(tonumber(master_fd[0]), false)
local slave_tty = uv.new_tty(tonumber(slave_fd[0]), false)

assert(uv.is_readable(master_tty))
assert(uv.is_writable(master_tty))
assert(uv.is_readable(slave_tty))
assert(uv.is_writable(slave_tty))

master_tty:close()
slave_tty:close()
end)

test("tty device", function (print, p, expect, uv)
ffi.cdef[[
typedef unsigned mode_t;
int open(const char *pathname, int flags, mode_t mode);
]]

local ttyin_fd = ffi.C.open("/dev/tty", uv.constants.O_RDONLY, 0);
if tonumber(ttyin_fd) == -1 and ffi.errno() == 6 then
print("Skip, open /dev/tty fail")
return
end

assert(tonumber(ttyin_fd) >= 0, ffi.errno())

local ttyout_fd = ffi.C.open("/dev/tty", uv.constants.O_WRONLY, 0);
assert(tonumber(ttyout_fd) >= 0, ffi.errno())

assert('tty' == uv.guess_handle(ttyin_fd));
assert('tty' == uv.guess_handle(ttyout_fd));

local tty_in = uv.new_tty(ttyin_fd, true)
assert(uv.is_readable(tty_in))
assert(not uv.is_writable(tty_in))

local tty_out = uv.new_tty(ttyout_fd, false)
assert(not uv.is_readable(tty_out))
assert(uv.is_writable(tty_out))

local width, height = uv.tty_get_winsize(tty_out)
print(string.format("width=%d height=%d\n", width, height));

assert(width >= 0)
assert(height >= 0)

assert(uv.tty_set_mode(tty_in, "raw"))
assert(uv.tty_set_mode(tty_in, "normal"))

assert(uv.tty_reset_mode())
assert(uv.tty_reset_mode())
assert(uv.tty_reset_mode())

uv.close(tty_in)
uv.close(tty_out)
end)
end)

0 comments on commit ad725c2

Please sign in to comment.