Lua 提示符

lua-users home
wiki

luaprompt 既是一个可以替代官方解释器的交互式 Lua 提示符,也是一个可以嵌入到宿主应用程序中的 Lua 命令提示符模块。作为一个独立的解释器,它提供了许多官方 Lua 解释器所缺乏的便利功能。作为一个嵌入式提示符,它适用于将 Lua 用作配置或界面语言的应用程序,因此可以从交互式提示符中受益,用于调试或常规使用。

luaprompt 的特性

Prompt 模块

luaprompt(提示符模块)和 luap(独立的解释器)都可以通过 LuaRocks 进行安装:

luarocks install luaprompt

这将安装模块和解释器,并使用默认配置,但您也可以自定义 luaprompt 的行为。请查阅 [luaprompt 的 GitHub 页面] 以获取更多关于如何构建和使用提示符模块的信息。

独立使用

作为一个独立的解释器,luaprompt 尽可能地模仿标准的 Lua 解释器(目前仅不支持 -E 标志),同时提供了上述额外的功能集。下面是一些 luaprompt 会话的片段,旨在说明 luaprompt 提供的功能。

Tab 键补全的工作方式基本符合您的预期。它会尝试补全表键(以及因此的全局变量)、保留关键字和文件名。在下面的示例会话中,[tab] 代表一次 Tab 键敲击。在 [tab] 之后出现的任何字符都由补全器提供。

> band = [tab][tab]
_G              coroutine       error           in              math            package         rawset          table           until
_VERSION        debug           false           io              module          pairs           repeat          then            while
and             do              for             ipairs          next            pcall           require         tonumber        xpcall
assert          dofile          function        load            nil             print           return          tostring        
bit32           else            getmetatable    loadfile        not             rawequal        select          true            
break           elseif          goto            loadstring      or              rawget          setmetatable    type            
collectgarbage  end             if              local           os              rawlen          string          unpack          
> band = bi[tab]t32[tab].[tab][tab]
bit32.arshift  bit32.bnot     bit32.btest    bit32.extract  bit32.lshift   bit32.rrotate  
bit32.band     bit32.bor      bit32.bxor     bit32.lrotate  bit32.replace  bit32.rshift   

通常,luaprompt 会尽可能多地进行补全,但在这样做时它不会试图猜测您的意图。在补全 bit32 表时,它并没有立即添加点号,因为它可能会在您想将 bit32 用作函数参数等情况时引起不便。因此,您需要再按一次 Tab 键。根据表键的不同,luaprompt 可能会添加一个开方括号而不是点号,或者根本不添加任何内容。

> array = {1, 2, 3}
> a = ar[tab]ray[tab][[tab][tab]
array[1]  array[2]  array[3]  
> a = array[1[tab]]

对于函数值,情况也类似,在完全补全函数名后按一次 Tab 键会添加一个开括号。

如果 luaprompt 无法补全表键或关键字,它会尝试补全文件名。

> loadfile("./[tab]
ChangeLog  Makefile   README     luap       luap.c     patch      prompt.c   prompt.h   

您可以通过直接输入表达式来打印 luaprompt 中任何表达式的值。其行为与官方解释器相同,区别在于您不必在行的开头加上等号。

>  1 + 2
3
>  _VERSION 
"Lua 5.2"

与官方解释器一样,值中的 __tostring 元方法也会被遵循。

>  io.stdin
file (0x7f3d0aeb2240)

当打印值时,luaprompt 会尽力对其进行格式化,使其尽可能清晰易读。其背后使用了一套复杂的逻辑来实现这一点,但以下几个例子将说明其基本功能。(不幸的是,wiki 在格式化方面灵活性有限,因此很难传达 luaprompt 使用的不同字体颜色和粗细。)

数组以线性方式打印

>  a = {1, 2, 3, 4, 5}
>  a
{ 1, 2, 3, 4, 5,  }

当数组过大无法在一行内显示时,输出会分成多行

>  for i = 1, 100 do a[i] = i end
>  a
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 
  23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 
  43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 
  63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 
  83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100,  }

带有字符串键的表会格式化为每个键占一行

>  coroutine
{ 
  yield = <function: 0x7f98dd0956e0>,
  status = <function: 0x7f98dd095820>,
  create = <function: 0x7f98dd095970>,
  wrap = <function: 0x7f98dd0959d0>,
  resume = <function: 0x7f98dd095aa0>,
  running = <function: 0x7f98dd095950>,
}

混合表会按照预期进行处理。下面的例子说明了 luaprompt 如何处理混合表和嵌套表(以及多行语句)。

>  function recurse(n)
>> if n == 1 then return "foo" else
>> local a = {}
>> for i = 1, n do a[i] = i end
>> a.down = recurse(n - 1)
>> return a
>> end
>> end
>  recurse(2)
{ 1, 2, 
  down = "foo",
}

当然,n=2 的情况很容易处理,但 luaprompt 也会尽量优雅地处理甚至病态的情况。如果表嵌套过深,luaprompt 会在一段时间后放弃,但它会尽量传达有关表结构的信息,并竭力避免打印格式糟糕的输出。

下面是 n=30 的输出。将 n 设置为 500 同样有效,但输出会稍长一些。

>  recurse(30)
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 
  23, 24, 25, 26, 27, 28, 29, 30, 
  down = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 
           21, 22, 23, 24, 25, 26, 27, 28, 29, 
           down = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 
                    18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 
                    down = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 
                             16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 
                             down = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 
                                      14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 
                                      25, 26, 
                                      down = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 
                                               12, 13, 14, 15, 16, 17, 18, 19, 
                                               20, 21, 22, 23, 24, 25, 
                                               down = { 1, 2, 3, 4, 5, 6, 7, 8, 
                                                        9, 10, 11, 12, 13, 14, 
                                                        15, 16, 17, 18, 19, 20, 
                                                        21, 22, 23, 24, 
                                                        down = { 1, 2, 3, 4, 5, 
                                                                 6, 7, 8, 9, 10, 
                                                                 11, 12, 13, 14, 
                                                                 15, 16, 17, 18, 
                                                                 19, 20, 21, 22, 
                                                                 23, 
                                                                 down = { ... },
                                                        },
                                               },
                                      },
                             },
                    },
           },
  },
}

最后,luaprompt 通过打印嵌套级别而不是实际的表内容,避免了打印包含自身表的无限递归。在下面的例子中,键为 b 的嵌套表包含一个名为 self 的键,其值为

>  recursive = {a = {1, 2, 3}, b = coroutine}
>  recursive.b.self = recursive.b
>  recursive.b.parent = recursive
>  recursive
{ 
  a = { 1, 2, 3,  },
  b = { 
        wrap = <function: 0x7fec9b79f9d0>,
        yield = <function: 0x7fec9b79f6e0>,
        self = { [-1]... },
        parent = { [-2]... },
        running = <function: 0x7fec9b79f950>,
        create = <function: 0x7fec9b79f970>,
        status = <function: 0x7fec9b79f820>,
        resume = <function: 0x7fec9b79faa0>,
  },
}

一个包含上述所有功能的优秀大表示例是全局表 _G。luaprompt 对其的处理效果尽可能好,但输出太长无法在此引用。

源代码

luaprompt 的源代码根据 MIT/X11 许可证分发。您可以在 [GitHub 上的项目页面] 获取。

替代方案

LuaRepl


RecentChanges · preferences
编辑 · 历史
最后编辑于 2015年11月13日 下午2:31 GMT (差异)