You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenWRT环境下基于luaposix的curses文本UI开发示例求助

luaposix实现OpenWRT平台curses文本菜单方案

适配说明

  • 运行环境完全匹配需求:OpenWRT内置Lua 5.1.5、opkg源官方luaposix 35.1.1版本,无任何额外第三方依赖
  • 所有curses能力直接调用luaposix内置的curses模块,不需要单独安装ncurses的其他Lua绑定
  • 内置终端状态还原逻辑,避免程序异常退出后终端显示错乱

最小可运行示例代码

-- 适配Lua 5.1 + luaposix 35.1.1 无额外依赖
local curses = require "posix.curses"

-- 菜单配置
local menu_items = {
    "查看系统信息",
    "查看网络状态",
    "重启设备",
    "退出菜单"
}
local selected = 1
local stdscr

-- 安全退出,保证终端状态还原
local function safe_exit(code)
    if stdscr then
        curses.echo()
        curses.nocbreak()
        stdscr:keypad(false)
        stdscr:endwin()
    end
    os.exit(code or 0)
end

-- 初始化curses环境
local function init_curses()
    stdscr = curses.initscr()
    if not stdscr then
        io.stderr:write("当前终端不支持curses模式\n")
        os.exit(1)
    end
    -- 异常捕获,任何报错都先还原终端
    local ok = pcall(function()
        curses.cbreak()
        curses.noecho()
        stdscr:keypad(true)
        stdscr:clear()
    end)
    if not ok then safe_exit(1) end
end

-- 绘制菜单界面
local function draw_menu()
    stdscr:clear()
    -- 绘制边框
    stdscr:border(0,0,0,0,0,0,0,0)
    -- 绘制标题
    local title = " OpenWRT 操作菜单 "
    stdscr:mvaddstr(1, (curses.cols() - #title)/2, title)
    -- 绘制菜单项
    local start_y = 4
    for i, item in ipairs(menu_items) do
        local prefix = "  "
        if i == selected then
            prefix = "> "
            -- 选中项加反显高亮
            stdscr:attron(curses.A_REVERSE)
        end
        stdscr:mvaddstr(start_y + i -1, 10, prefix .. item)
        if i == selected then
            stdscr:attroff(curses.A_REVERSE)
        end
    end
    -- 绘制底部提示
    local tip = " 方向键选择 | 回车确认 | q退出 "
    stdscr:mvaddstr(curses.lines()-2, (curses.cols() - #tip)/2, tip)
    -- 刷新显示
    stdscr:refresh()
end

-- 主逻辑循环
local function main_loop()
    while true do
        draw_menu()
        local key = stdscr:getch()
        if key == string.byte('q') then
            break
        elseif key == curses.KEY_UP then
            selected = selected -1
            if selected < 1 then selected = #menu_items end
        elseif key == curses.KEY_DOWN then
            selected = selected +1
            if selected > #menu_items then selected = 1 end
        elseif key == 10 then -- 回车键
            stdscr:clear()
            stdscr:border(0,0,0,0,0,0,0,0)
            local tip = "你选中了选项:" .. menu_items[selected] .. ",按任意键返回"
            stdscr:mvaddstr(curses.lines()/2, (curses.cols() - #tip)/2, tip)
            stdscr:refresh()
            stdscr:getch()
            -- 选中最后一个退出项直接退出
            if selected == #menu_items then break end
        end
    end
end

-- 程序入口
init_curses()
local ok, err = pcall(main_loop)
if not ok then
    io.stderr:write("运行错误:" .. tostring(err) .. "\n")
end
safe_exit(0)

核心接口入门参考(对应luaposix 35.1.1版本)

luaposix的curses是对标准ncurses C接口的轻量封装,接口命名、常量定义和C版本完全一致,不需要专门查找luaposix专属教程,对照ncurses基础开发逻辑调整为Lua语法即可,常用接口如下:

  • 初始化与清理
    • curses.initscr():初始化curses环境,返回主窗口对象
    • stdscr:endwin():退出前必须调用,还原终端默认状态
  • 输入模式配置
    • curses.cbreak():禁用行缓冲,用户按键后立即返回不需要等回车
    • curses.noecho():关闭用户输入的自动回显
    • stdscr:keypad(true):启用功能键识别,支持方向键、翻页键等特殊按键
  • 绘制操作
    • stdscr:clear():清空整个窗口内容
    • stdscr:mvaddstr(y, x, 文本):移动光标到(y,x)坐标位置打印文本,坐标以窗口左上角为(0,0)原点,y轴向下递增
    • stdscr:attron(属性常量)/stdscr:attroff(属性常量):开启/关闭文本显示属性,常用属性包括curses.A_REVERSE(反显高亮)、curses.A_BOLD(粗体)
    • stdscr:border():绘制窗口边框
    • stdscr:refresh():所有绘制操作完成后必须调用,才会把内容实际渲染到终端
  • 输入获取
    • stdscr:getch():阻塞等待用户按键,返回按键对应数值;方向键对应常量为curses.KEY_UP、curses.KEY_DOWN,回车键对应数值10,普通字符键对应string.byte('字符')的返回值

注意:如果需要适配不同尺寸的终端,可通过curses.lines()获取终端当前行数,curses.cols()获取终端当前列数,动态调整元素绘制位置。

OpenWRT部署运行步骤

  1. 安装官方源依赖:执行opkg update && opkg install luaposix
  2. 将示例代码保存为text_menu.lua,上传到OpenWRT设备可写目录
  3. 执行lua text_menu.lua即可启动菜单,操作逻辑为:上下方向键切换选项,回车确认选择,按q键退出

内容的提问来源于stack exchange,提问作者Sina S.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.27 18:45:42