擴充套件建議案

lua-users home
wiki

擴充套件建議案是一個 API 和實作,用於 os 和 io 名稱空間中的額外 non-ANSI 函數。

說明

最近(2006 年 1 月)在郵件清單中的討論促使我嘗試設計一個延伸 API,它透過將函數新增到 os 和 io 名稱空間來延伸 Lua API。

這並非修改 Lua 核心程式的建議案,而是一個延伸 Lua 核心的 API 設計建議案。此 API 旨在為現代流行作業系統(Windows、MacOSX 和 POSIX 平台)上的獨立 Lua 程式提供更完整的程式設計環境。

來源

LuaForge 上有存放 [適用於 POSIX 和 Windows 的實作]。這些都是非常實用的實作,但在 API 仍在標準化的過程中,只應視為測試目的而使用。

ex API

請注意,所有這些函數在失敗時都會傳回標準的 (nil、「錯誤訊息」),並且在未另行指定的情況下,它們在成功時會傳回 (true)。

初始化

require "ex"
標示某個使用此 API 的 Lua 程式

環境

os.getenv(name)
取得環境值

os.setenv(name, value)
設定/修改環境值

os.setenv(name, nil)
移除環境值

os.environ()
傳回環境的複本(一個簡單的 Lua 表格)

檔案系統(大部分取用自 LuaFilesystem?

os.chdir(pathname)
變更工作目錄

os.mkdir(pathname)
建立目錄

os.remove(pathname)
移除檔案或目錄

pathname = os.currentdir()
取得工作目錄路徑

for entry in os.dir(pathname) do ; end
反覆運算某個目錄中的項目。路徑名稱引數是選用的;如果沒有,就會使用目前的目錄。
特殊目錄項目(例如「.」和「..」)不會傳回。

entry = os.dirent(pathname)
entry = os.dirent(file)
透過路徑名稱或開啟的檔案取得目錄項目資訊

os.dir() 傳回的迭代器函數和 os.dirent() 函數都傳回一個「項目」表格。此表格至少包含以下欄位

entry.name= 檔案名稱(請注意,os.dirent() 不需要設定這個欄位)
entry.type= 「檔案」或「目錄」(或實作定義的字串)
entry.size= 檔案大小,以位元組為單位

實作可能會新增其他欄位,甚至方法。

輸入/輸出(封鎖和管線)

file:lock(mode, offset, length)
io.lock(file, mode, offset, length)
封鎖或解除封鎖檔案或檔案的一部分;「mode」是「r」或「w」或「u」;「offset」和「length」是選用的
「r」模式要求讀取鎖,「w」要求寫入鎖,而「u」會解除鎖。請注意,這些鎖可能是諮詢鎖或強制鎖。

file:unlock(offset, length)
io.unlock(file, offset, length)
等於 file:lock("u", offset, length) 或 io.lock(file, "u", offset, length)

請注意,file:lock() 和 file:unlock() 都會延伸 Lua 檔案物件的元表格。

rd, wr = io.pipe()
建立管線;「rd」和「wr」都是 Lua 檔案物件

處理控制

os.sleep(seconds)
os.sleep(interval, unit)
暫停程式執行一段時間,單位為秒;「unit」預設為 1,兩個參數都可以是小數。系統定義具體小數位精度。
os.sleep(3.8) -- sleep for 3.8 seconds
local microseconds = 1e6
os.sleep(3800000, microseconds) -- sleep for 3800000 �s
local ticks = 100
os.sleep(380, ticks) -- sleep for 380 ticks

proc = os.spawn(filename)
proc = os.spawn{filename, [args-opts]}
proc = os.spawn{command=filename, [args-opts]} 
建立子程式

「檔名」指定一個程式。如果(系統定義的)路徑名稱並非絕對路徑,便會透過系統定義的搜尋方法(在多數系統中為 PATH 環境變數)尋找程式。

如果指定,[args-opts] 會是下列其中一個或多個金鑰

[1]..[n]= 指令列參數

args= 指令列參數陣列

env= 環境變數表格

stdin= stdout= stderr= 分別為標準輸入、輸出和錯誤的 io.file 物件

如果同時指定整數金鑰和「args」金鑰,系統會傳回錯誤。

如果提供第 0 個參數 (options.args[0] 或 options[0]),系統可能會提供特殊行為。

傳回的「proc」使用者資料有下列方法

exitcode = proc:wait()
等待子程式終止;「exitcode」是子程式傳回的碼

摘要

所有函數也都在 ex 名稱空間中

ex.getenv(name)
ex.setenv(name, value)
ex.environ()
ex.chdir(pathname)
ex.mkdir(pathname)
ex.currentdir()
ex.dir(pathname)
ex.dirent(pathname)
ex.lock(file, mode, offset, length)
ex.unlock(file, offset, length)
ex.pipe()
ex.sleep(interval, [unit])
ex.spawn(...)
ex.wait(proc)

請注意,ex.getenv 在這裡主要是為了並行性,另外也是因為在 Windows 中,如果要使用 SetEnvironmentVariable?() API,則必須覆寫標準的 os.getenv,其會使用 getenv() 透過 GetEnvironmentVariable?() 來使用。

範例

require "ex"

-- run the echo command
proc = os.spawn"/bin/echo"
proc = os.spawn{"/bin/echo", "hello", "world"}
proc = os.spawn{command="/bin/echo", "hello", "world"}

-- run the id command
vars = { LANG="fr_FR" }
proc = os.spawn{"/bin/id", "-un", env=vars}
proc = os.spawn{command="/bin/id", "-un", env=vars)

-- Useless use of cat
local rd, wr = assert(io.pipe())
local proc = assert(os.spawn("/bin/cat", {stdin=rd}))
rd:close()
wr:write("Hello world\n")
wr:close()
proc:wait()

-- Run a program with a modified environment
local env = os.environ()
env.LUA_PATH = "/usr/share/lib/lua/?.lua"
env.LUA_CPATH = "/usr/share/lib/lua/?.so"
local proc = assert(os.spawn("lua", {args = {"-e", 'print"Hello world\n"'}, env=env }))
proc:wait()

-- popen2()
function popen2(...)
  local in_rd, in_wr = io.pipe()
  local out_rd, out_wr = io.pipe()
  local proc, err = os.spawn{stdin = in_rd, stdout = out_wr, ...}
  in_rd:close(); out_wr:close()
  if not proc then
    in_wr:close(); out_rd:close()
    return proc, err
  end
  return proc, out_rd, in_wr
end
-- usage:
local p, i, o = assert(popen2("wc", "-w"))
o:write("Hello world"); o:close()
print(i:read"*l"); i:close()
p:wait()

註解

Mark,與其將函數新增至標準函式庫名稱空間,我建議您將您的作品視為一個工具模組,為模組取一個名稱,並將函數置於新的模組名稱之下。如果您的函數像現在這樣流傳開來,將會造成混淆,特別是對於 Lua 初學者來說,因為他們可能會讀到範例程式碼,卻不明白為何標準模組中某些函數不在上游文件之中。--JohnBelmonte

我同意 John 的看法。或許可使用 ex.install() 或類似的模組將它安裝至 os 函式庫。但還是希望它是個別的函式庫。--Doug Rogers

我同意之前的評論。我不希望將函數注入「os」,而是希望有獨立的函式庫。'

env.getenv(name)
env.setenv(name, value)
env.environ()
--no unsetenv. It's meaningless.
--function env.unsetenv(name)
--    env.setenv(name, nil)
--end

fs.chdir(pathname)
fs.mkdir(pathname)
fs.currentdir()
fs.dir(pathname)
fs.dirent(pathname)
fs.lock(file, mode, offset, length)
fs.unlock(file, offset, length)

proc.pipe()
proc.sleep(seconds)
proc.spawn(...)
proc.wait(proc)
--ncopa

Mark,感謝您的實現。在此同意避免「污染」os 和 io 模組,至少在目前的實現中如此,如此一來,使用者就能在不會有衝突危險的狀況下於現有製作碼中使用這些模組(如果和何時擴充 os 和 io 名稱空間的介面被標準化)。正如所述,您的實現(而非建議的介面)可能有一個 ex.install() 或類似的函數,可根據介面建議更新 osio。這讓使用者可以暫時做出選擇。--DavidManura

進一步來說,如果要將其記錄到它自己的資料表(例如文件系統)中,這麼做可能是個好方法:從作業系統中複製有關檔案的條目。這有助於讓新程式碼更乾淨,並在呼叫這個延伸時「過時」作業系統資料表。


對最新版本的留言。

(1) 在預設的 conf.in 中,將「-llua51」改為「-llua5.1」,這樣做和 LuaBinaries 比較相符嗎?

這和 Lua 發行版本相符,不過我可以在 conf.in 中新增註解。-Mark

我一直感到納悶,Lua 和 LuaBinaries 之間為什麼有這種不一致性。

(2) os.sleep(math.huge) 立即傳回。它不應該傳回嗎?

我需要找出為什麼會這樣…-Mark

os.sleep(1e100) 也立即傳回。儘管 Win32 Sleep(INFINITE) 或任何龐大值似乎不太有用,不過誰知道呢(INFINTE 在 SleepEx 中似乎是有用的 ?)。 [1] Sleep(0) 的意思是「放棄時間片」。

(3) os.setenv 和 os.mkdir(1)-實作會自動將數值參數轉換成字串。這是故意的嗎?

很可能是的,它們預期得到的是字串。-Mark

我在 字串.lower(123) == "123"(為真)中也看到相同的行為。

(4) 這是故意的嗎?

> =os.setenv("a", {})
nil     203 (0xCB): The system could not find the environment option that was entered.
> =os.setenv("a", nil)
nil     203 (0xCB): The system could not find the environment option that was entered.

API 沒有說明如果將非字串傳遞為第二項論證,或者如果嘗試移除不存在的變數時,會發生什麼事。它應該這樣做嗎?

不知道,不過錯誤訊息很奇怪。

(5) 要讓 os.dir() 在沒有參數的情況下,使用目前的工作目錄嗎?

這是一個好點子;那時它需要成為 API 的一部份。-Mark

我呼叫 os.diren 時,entry.name 不見了。

是的,這是故意的,而且 API 的說明不正確。除非有不同的理由嗎?-Mark

(7) 這是故意的嗎?

> f = io.open("123")
> = io.lock(f, "w")
nil     6 (0x6): The handle is invalid.
> =f
file (0080F060)

是的,ex 沒有說明如果嘗試對唯讀檔案寫入鎖定時,會發生什麼事。它應該說明嗎?-Mark

也許不用。這在 Win32 中又是怎麼一回事?

Lua 5.1.1  Copyright (C) 1994-2006 Lua.org, PUC-Rio
> require "ex"
> f = assert(io.open("234", "w"))
> = f:lock("w")
nil     6 (0x6): The handle is invalid.

這是個 bug;我想現在已經修正了。-Mark

(8)

$ make mingw
make -C w32api ex.dll
make[1]: Entering directory `.../ex/w32api'
cc -W -Wall -Wno-missing-braces -DWIN32_LEAN_AND_MEAN -DNOGDI -...  -mno-cygwin -c -o ex.o ex.c
cc -W -Wall -Wno-missing-braces -DWIN32_LEAN_AND_MEAN -DNOGDI -...  -mno-cygwin -c -o spawn.o spawn.c
spawn.c: In function `spawn_param_init':
spawn.c:35: warning: missing initializer
spawn.c:35: warning: (near initialization for `si.lpReserved')
cc -W -Wall -Wno-missing-braces -DWIN32_LEAN_AND_MEAN -DNOGDI -I...  -mno-cygwin -c -o pusherror.o pusherror.c
cc -W -Wall -Wno-missing-braces -DWIN32_LEAN_AND_MEAN -DNOGDI -I...  -mno-cygwin -c -o dirent.o dirent.c
cc -mno-cygwin -shared -o ex.dll ex.o spawn.o pusherror.o dirent.o -L... -llua5.1
make[1]: Leaving directory `.../ex/w32api'

參閱 http://msdn2.microsoft.com/en-us/library/ms686331.aspx 可以使用 memset 初始化結構,以避免警告。

這個警告是 GCC 不幸的一個特點,C 保證其他的結構成員預設初始化為零,這是此處的目的。-Mark

可以透過以下方式避免這個警告:「static const STARTUPINFO si = {sizeof si, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};」

(9)

$ make cygwin
make -C posix T=ex.dll ex.dll
make[1]: Entering directory `...ex/posix'
cc -W -Wall -std=c89 -D_XOPEN_SOURCE=600 -DMISSING_POSIX_SPAWN -DENVIRON_DECL="e
xtern char **environ;" -I...   -c -o ex.o ex.c
ex.c: In function `ex_setenv':
ex.c:53: warning: implicit declaration of function `setenv'
ex.c:53: warning: implicit declaration of function `unsetenv'
ex.c: In function `new_file':
ex.c:131: warning: implicit declaration of function `fdopen'
ex.c:131: warning: assignment makes pointer from integer without a cast
ex.c: In function `ex_dirent':
ex.c:151: warning: implicit declaration of function `fileno'
cc -W -Wall -std=c89 -D_XOPEN_SOURCE=600 -DMISSING_POSIX_SPAWN -DENVIRON_DECL="e
xtern char **environ;" -I...   -c -o spawn.o spawn.c
cc -W -Wall -std=c89 -D_XOPEN_SOURCE=600 -DMISSING_POSIX_SPAWN -DENVIRON_DECL="e
xtern char **environ;" -I...   -c -o posix_spawn.o po
six_spawn.c
posix_spawn.c:49: warning: unused parameter 'act'
cc -shared -o ex.dll ex.o spawn.o posix_spawn.o -L...
make[1]: Leaving directory `...ex/posix'

請注意 cygwin 標準庫 h

#ifndef __STRICT_ANSI__
long    _EXFUN(a64l,(const char *__input));
char *  _EXFUN(l64a,(long __input));
char *  _EXFUN(_l64a_r,(struct _reent *,long __input));
int	_EXFUN(on_exit,(_VOID (*__func)(int, _PTR),_PTR __arg));
_VOID	_EXFUN(_Exit,(int __status) _ATTRIBUTE ((noreturn)));
int	_EXFUN(putenv,(char *__string));
int	_EXFUN(_putenv_r,(struct _reent *, char *__string));
int	_EXFUN(setenv,(const char *__string, const char *__value, int __overwrite));
int	_EXFUN(_setenv_r,(struct _reent *, const char *__string, const char *__value, int __overwrite))
#ifndef __STRICT_ANSI__
#ifndef _REENT_ONLY
FILE *	_EXFUN(fdopen, (int, const char *));
#endif
int	_EXFUN(fileno, (FILE *));

ExtensionProposal 的目的是提供非 ANSI 的函數,為什麼要使用 ANSI 編譯?

沒錯,-std=c89 不正確,我會修改 conf.in。-Mark

-- DavidManura

(10) ex.dir 似乎會開啟檔案,但不會關閉它。因此,這個程式碼

while true do for f in os.dir("./") do print(f.name) end end

會產生以下錯誤

stdin:2:嘗試呼叫 nil 值堆疊追蹤

stdin:2:在 main chunk 中
[C]:?

循環過幾次後,other 呼叫 to os.dir 給出

print(os.dir("./")) -> nil 開啟過多檔案

lsof 顯示有開啟該目錄的多個 (1020) 副本。

我理解開啟的檔案一定是多重呼叫 ex API 的一部分,但使用開啟的檔案呼叫 os.dir 的可能性可以提供暫時解決方法

while true do local d = io.open("./") for f in os.dir(d) do print(f.name) end d:close() end

順帶一提,此範例非常有用。棒透了 -- m.i.

快速搜尋過 POSIX 手冊後,這似乎不容易或完全不可能。相反地,修改 posix/ex.c 中的幾行 (在第 240 行 ex_dir 中) 將

if (!d) return push_error(L);

改為

if (!d) { diriter_close(L); return push_error(L); }

似乎解決了這個問題 (而且未製造出其他問題,但需要測試)。

抱歉沒有使用 diff,我從未學過...

再次感謝你的貢獻 -- m.i.

是的,檔案處理在記憶體耗盡前就已經用罄,所以你的方法是正確的解決方案。順便一提,這也許是個更好的習慣用語

for f in assert(os.dir".") do print f.name; end

-Mark


如果有多個參數,以下函數 (來自 w32api\spawn.c,目前版本) 會可靠地當掉。我認為 lua_pop() 是錯的。基本上,相同的錯誤似乎 (實際上兩次) 潛伏在 spawn_param_env() 中。我尚未研究 POSIX 實作... 愉快地尋找。-- ThomasLauer

是的,這是已知的錯誤,我已經找到解決方法,我只要把它張貼出來就好,抱歉。-Mark

很高興知道... 但你所知的這些錯誤是什麼?如果你知道這些錯誤,也許與更多人分享這些知識會是個好主意?比方說,就在這個頁面中?好吧... <搖頭> -- ThomasLauer

void spawn_param_args(struct spawn_params *p)
{
	 lua_State *L = p->L;
	 debug("spawn_param_args:"); debug_stack(L);
	 luaL_Buffer args;
	 luaL_buffinit(L, &args);
	 size_t i, n = lua_objlen(L, -1);
	 /* concatenate the arg array to a string */
	 for (i = 1; i <= n; i++) {
	 	 int quote;
	 	 lua_rawgeti(L, -1, i);     /* ... argtab arg */
	 	 /* XXX checkstring is confusing here */
	 	 quote = needs_quoting(luaL_checkstring(L, -1));
	 	 luaL_putchar(&args, ' ');
	 	 if (quote) luaL_putchar(&args, '"');
	 	 luaL_addvalue(&args);
	 	 if (quote) luaL_putchar(&args, '"');
--->	 lua_pop(L, 1);             /* ... argtab */
	 }
	 luaL_pushresult(&args);        /* ... argtab argstr */
	 lua_pushvalue(L, 1);           /* cmd opts ... argtab argstr cmd */
	 lua_insert(L, -2);             /* cmd opts ... argtab cmd argstr */
	 lua_concat(L, 2);              /* cmd opts ... argtab cmdline */
	 lua_replace(L, -2);            /* cmd opts ... cmdline */
	 p->cmdline = lua_tostring(L, -1);
}


我在 Lua 5.1.1 詮釋器中 (在 Gentoo、amd64、gcc-4.1.2 上) 執行時會遇到 SEGFAULT。
require 'ex'
ex.spawn{'ls'}

gdb 執行追蹤

#0  0x00002adc9351a885 in raise () from /lib/libc.so.6
#1  0x00002adc9351bb3e in abort () from /lib/libc.so.6
#2  0x00002adc93550a27 in ?? () from /lib/libc.so.6
#3  0x00002adc93555b1d in ?? () from /lib/libc.so.6
#4  0x00002adc935579b6 in ?? () from /lib/libc.so.6
#5  0x00002adc9355950d in malloc () from /lib/libc.so.6
#6  0x00002adc93177351 in ?? () from /usr/lib64/liblua.so.5
#7  0x00002adc9317add9 in ?? () from /usr/lib64/liblua.so.5
#8  0x00002adc93170237 in lua_getfield () from /usr/lib64/liblua.so.5
#9  0x00002adc938867e9 in ex_spawn (L=0x503010) at ex.c:412
#10 0x00002adc93173fc1 in ?? () from /usr/lib64/liblua.so.5
#11 0x00002adc9317d50e in ?? () from /usr/lib64/liblua.so.5
#12 0x00002adc9317440d in ?? () from /usr/lib64/liblua.so.5
#13 0x00002adc93173b77 in ?? () from /usr/lib64/liblua.so.5
#14 0x00002adc93173bf4 in ?? () from /usr/lib64/liblua.so.5
#15 0x00002adc9316fc75 in lua_pcall () from /usr/lib64/liblua.so.5
#16 0x0000000000401746 in ?? ()
#17 0x0000000000401b54 in ?? ()
#18 0x0000000000402137 in ?? ()
#19 0x00002adc93173fc1 in ?? () from /usr/lib64/liblua.so.5
#20 0x00002adc931743bd in ?? () from /usr/lib64/liblua.so.5
#21 0x00002adc93173b77 in ?? () from /usr/lib64/liblua.so.5
#22 0x00002adc93173bf4 in ?? () from /usr/lib64/liblua.so.5
#23 0x00002adc9316fc17 in lua_cpcall () from /usr/lib64/liblua.so.5
#24 0x000000000040167d in main ()

這是使用標準的 (Gentoo 發布的) Lua 5.1.1。

我編譯了 Lua 5.1.2,結果相同 (更多符號)。

使用 -O0 編譯 Lua 也會導致相同的錯誤。只不過有更多資訊。

#0  0x00002b8a1dc7a885 in raise () from /lib/libc.so.6
#1  0x00002b8a1dc7bb3e in abort () from /lib/libc.so.6
#2  0x00002b8a1dcb0a27 in ?? () from /lib/libc.so.6
#3  0x00002b8a1dcb5b1d in ?? () from /lib/libc.so.6
#4  0x00002b8a1dcb79b6 in ?? () from /lib/libc.so.6
#5  0x00002b8a1dcb950d in malloc () from /lib/libc.so.6
#6  0x0000000000419c8d in l_alloc (ud=0x0, ptr=0x0, osize=0, nsize=29) at lauxlib.c:636
#7  0x000000000040d519 in luaM_realloc_ (L=0x533010, block=0x0, osize=0, nsize=29) at lmem.c:79
#8  0x0000000000411e3b in newlstr (L=0x533010, str=0x2b8a1de8c235 "args", l=4, h=7976507) at lstring.c:56
#9  0x00000000004120ab in luaS_newlstr (L=0x533010, str=0x2b8a1de8c235 "args", l=4) at lstring.c:92
#10 0x00000000004060f4 in lua_getfield (L=0x533010, idx=2, k=0x2b8a1de8c235 "args") at lapi.c:546
#11 0x00002b8a1de8b4be in ex_spawn (L=0x533010) at ex.c:379
#12 0x0000000000409e92 in luaD_precall (L=0x533010, func=0x533410, nresults=0) at ldo.c:319
#13 0x00000000004175b9 in luaV_execute (L=0x533010, nexeccalls=1) at lvm.c:589
#14 0x000000000040a106 in luaD_call (L=0x533010, func=0x533400, nResults=-1) at ldo.c:377
#15 0x0000000000406a30 in f_call (L=0x533010, ud=0x7fff8d573bb0) at lapi.c:796
#16 0x0000000000409192 in luaD_rawrunprotected (L=0x533010, f=0x406a01 <f_call>, ud=0x7fff8d573bb0) at ldo.c:116
#17 0x000000000040a49d in luaD_pcall (L=0x533010, func=0x406a01 <f_call>, u=0x7fff8d573bb0, old_top=48, ef=32) at ldo.c:461
#18 0x0000000000406ad6 in lua_pcall (L=0x533010, nargs=0, nresults=-1, errfunc=1) at lapi.c:817
#19 0x0000000000403dfa in docall (L=0x533010, narg=0, clear=0) at lua.c:100
#20 0x00000000004043d0 in dotty (L=0x533010) at lua.c:219
#21 0x0000000000404b3f in pmain (L=0x533010) at lua.c:367
#22 0x0000000000409e92 in luaD_precall (L=0x533010, func=0x5333e0, nresults=0) at ldo.c:319
#23 0x000000000040a0f4 in luaD_call (L=0x533010, func=0x5333e0, nResults=0) at ldo.c:376
#24 0x0000000000406be0 in f_Ccall (L=0x533010, ud=0x7fff8d573f50) at lapi.c:842
#25 0x0000000000409192 in luaD_rawrunprotected (L=0x533010, f=0x406b11 <f_Ccall>, ud=0x7fff8d573f50) at ldo.c:116
#26 0x000000000040a49d in luaD_pcall (L=0x533010, func=0x406b11 <f_Ccall>, u=0x7fff8d573f50, old_top=16, ef=0) at ldo.c:461
#27 0x0000000000406c37 in lua_cpcall (L=0x533010, func=0x404973 <pmain>, ud=0x7fff8d573fa0) at lapi.c:852
#28 0x0000000000404bb4 in main (argc=1, argv=0x7fff8d5740b8) at lua.c:385

ex.spawn'ls' 語法也會失敗,不過是在 spawn_param_execute 中失敗。

我不了解原因。

傳遞給 realloc 的參數應該是正確的 (gdb 將它們視為 ptr=0x0、nsz=48),但從偵錯輸出中看起來,它卻呼叫了 malloc 取而代之 (這正常嗎?)。在我一般使用 Lua 時不會遇到這種失敗,所以我假設這不是它的錯。

--m.i.

這是已知的錯誤,目前已經修正,但尚未提供。很快就推出!我保證。- MarkEdgar

不知道這一點,我重新實作了大多數功能。這會某種程度地複製程式碼,所以從現在開始,我將簡單地使用您的實作。儘管如此,我仍對 API 進行了一些調整,我认为這會很有用。我在頁面上發布說明,因為說明蠻長的 -- MauroIazzi

我認為可以利用 os.isatty 來讓使用者在「cat myfile | lua myapp.lua -」中避開輸入明確的「-」。Lua 本身會呼叫 isatty,儘管它在 luaconf.h 中 --DavidManura

在這裡可能需要使用全域函式。另請參閱 FileGlob。--DavidManura


最近變更 · 偏好設定
編輯 · 歷史記錄
最後編輯時間為 2009 年 10 月 31 日下午 8:01 GMT (差異)