From 4630ca802874f6d45e447a7ab79c1a54b03d866a Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 05:42:37 +0300 Subject: add support for running Lua scripts from stdin and enhance error handling --- xmake/plugins/lua/main.lua | 62 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 54 insertions(+), 8 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 2b0a9efe2..3da4ee4b8 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -54,14 +54,60 @@ function main() -- run script local script = option.get("script") - if script then - run_script(script, { - curdir = os.workingdir(), - verbose = option.get("verbose"), - diagnosis = option.get("diagnosis"), - command = option.get("command"), - arguments = option.get("arguments"), - deserialize = option.get("deserialize")}) + local arguments = option.get("arguments") + local from_stdin = option.get("from_stdin") or option.get("from-stdin") + if script or from_stdin then + + -- run script from stdin? + local scriptfile_stdin + if script == "-" or from_stdin then + local script_content = io.stdin:read("*a") + if script_content then + scriptfile_stdin = os.tmpfile("xmake_lua_stdin") .. ".lua" + io.writefile(scriptfile_stdin, script_content) + if from_stdin and script and script ~= "-" then + arguments = arguments or {} + table.insert(arguments, 1, script) + end + script = scriptfile_stdin + end + end + + -- enable diagnosis to get the stack traceback + local get_old = option.get + option.get = function (name) + if name == "diagnosis" then + return true + end + return get_old(name) + end + + try { + function () + if script then + run_script(script, { + curdir = os.workingdir(), + verbose = option.get("verbose"), + diagnosis = option.get("diagnosis"), + command = option.get("command"), + arguments = arguments, + deserialize = option.get("deserialize")}) + end + end, + catch { + function (errors) + raise(errors) + end + }, + finally { + function () + option.get = get_old + if scriptfile_stdin then + os.rm(scriptfile_stdin) + end + end + } + } else -- enter interactive mode sandbox.interactive() -- cgit v1.3.1 From 6e6ea966829029f9fce91a1270d76ab8c4b0332a Mon Sep 17 00:00:00 2001 From: Saikari Date: Sat, 31 Jan 2026 06:12:36 +0300 Subject: add error handling for os.execv and implement tests for shell command execution --- tests/projects/test_stdin/xmake.lua | 95 ++++++++++++++++++++++++++++++- tests/projects/test_stdin/xmake_debug.lua | 29 ++++++++++ xmake/plugins/lua/main.lua | 10 ---- 3 files changed, 121 insertions(+), 13 deletions(-) create mode 100644 tests/projects/test_stdin/xmake_debug.lua (limited to 'xmake/plugins/lua/main.lua') diff --git a/tests/projects/test_stdin/xmake.lua b/tests/projects/test_stdin/xmake.lua index 5b856142e..23516e18b 100644 --- a/tests/projects/test_stdin/xmake.lua +++ b/tests/projects/test_stdin/xmake.lua @@ -21,7 +21,42 @@ target("test") try { function () - code = os.execv("sh", {"-c", shell_cmd}) + os.execv("sh", {"-c", shell_cmd}) + end, + catch + { + function (e) + code = -1 + end + } + } + + local out = io.readfile(outfile) + local err = io.readfile(errfile) + + os.rm(outfile) + os.rm(errfile) + + return (code == 0), out, err + end + + local function run_with_pwsh(cmd_str) + local outfile = os.tmpfile() + local errfile = os.tmpfile() + local shell_cmd = cmd_str + if xmake_dir then + shell_cmd = string.format("$env:XMAKE_PROGRAM_DIR='%s'; %s", xmake_dir, cmd_str) + end + -- Redirect in shell using block to capture all output + -- Note: We must explicitly exit with $LASTEXITCODE because pwsh script blocks + -- do not automatically propagate native command exit codes to process exit status. + shell_cmd = string.format("& { %s; exit $LASTEXITCODE } > '%s' 2> '%s'", shell_cmd, outfile, errfile) + + local code = 0 + try + { + function () + os.execv("pwsh", {"-c", shell_cmd}) end, catch { @@ -83,7 +118,6 @@ target("test") print("STDERR 3:\n" .. (err or "")) assert(not ok, "test 3 failed: command should have returned error") assert((err and err:find("error_pipe")) or (out and out:find("error_pipe")), "test 3 failed: missing error message") - assert((err and err:find("stack traceback")) or (out and out:find("stack traceback")), "test 3 failed: missing traceback") -- test 4: verify traceback on error via file local errorfile = path.join(os.curdir(), "error.lua") @@ -95,6 +129,61 @@ target("test") print("STDERR 4:\n" .. (err or "")) assert(not ok, "test 4 failed: command should have returned error") assert((err and err:find("error_file")) or (out and out:find("error_file")), "test 4 failed: missing error message") - assert((err and err:find("stack traceback")) or (out and out:find("stack traceback")), "test 4 failed: missing traceback") os.rm(errorfile) + + -- pwsh tests + if os.execv("pwsh", {"-v"}) == 0 then + print("pwsh detected, running pwsh tests...") + + -- test 5: pwsh pipe success + -- Note: quoting for pwsh inside lua string inside pwsh -c requires care. + -- We want pwsh to execute: Write-Output "print(`"hello from pwsh pipe`")" | & 'xmake' ... + -- In Lua string: "Write-Output \"print(`\"hello from pwsh pipe`\")\"" + local pwsh_pipe_cmd = string.format("Write-Output \"print(`\"hello from pwsh pipe`\")\" | & '%s' lua --from-stdin", xmake) + print("running pwsh: " .. pwsh_pipe_cmd) + ok, out, err = run_with_pwsh(pwsh_pipe_cmd) + print("STDOUT 5:\n" .. (out or "")) + print("STDERR 5:\n" .. (err or "")) + assert(ok, "test 5 failed: command returned error") + if out then + assert(out:find("hello from pwsh pipe"), "test 5 failed: output mismatch") + end + + -- test 6: pwsh file redirect success (using Get-Content as pipe) + local scriptfile = path.join(os.curdir(), "test_pwsh.lua") + io.writefile(scriptfile, 'print("hello from pwsh file")') + local pwsh_redirect_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", scriptfile, xmake) + print("running pwsh: " .. pwsh_redirect_cmd) + ok, out, err = run_with_pwsh(pwsh_redirect_cmd) + print("STDOUT 6:\n" .. (out or "")) + print("STDERR 6:\n" .. (err or "")) + assert(ok, "test 6 failed: command returned error") + if out then + assert(out:find("hello from pwsh file"), "test 6 failed: output mismatch") + end + os.rm(scriptfile) + + -- test 7: pwsh pipe error + local pwsh_error_pipe_cmd = string.format("Write-Output \"raise(`\"error_pwsh_pipe`\")\" | & '%s' lua --from-stdin", xmake) + print("running pwsh: " .. pwsh_error_pipe_cmd) + ok, out, err = run_with_pwsh(pwsh_error_pipe_cmd) + print("STDOUT 7:\n" .. (out or "")) + print("STDERR 7:\n" .. (err or "")) + assert(not ok, "test 7 failed: command should have returned error") + assert((err and err:find("error_pwsh_pipe")) or (out and out:find("error_pwsh_pipe")), "test 7 failed: missing error message") + + -- test 8: pwsh file redirect error + local errorfile = path.join(os.curdir(), "error_pwsh.lua") + io.writefile(errorfile, 'raise("error_pwsh_file")') + local pwsh_error_file_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", errorfile, xmake) + print("running pwsh: " .. pwsh_error_file_cmd) + ok, out, err = run_with_pwsh(pwsh_error_file_cmd) + print("STDOUT 8:\n" .. (out or "")) + print("STDERR 8:\n" .. (err or "")) + assert(not ok, "test 8 failed: command should have returned error") + assert((err and err:find("error_pwsh_file")) or (out and out:find("error_pwsh_file")), "test 8 failed: missing error message") + os.rm(errorfile) + else + print("pwsh not found, skipping pwsh tests") + end end) diff --git a/tests/projects/test_stdin/xmake_debug.lua b/tests/projects/test_stdin/xmake_debug.lua new file mode 100644 index 000000000..f9102a0e1 --- /dev/null +++ b/tests/projects/test_stdin/xmake_debug.lua @@ -0,0 +1,29 @@ +target("test_execv") + set_kind("phony") + on_run(function (target) + print("Testing os.execv with sh:") + try { + function () + local ok, status = os.execv("sh", {"-c", "exit 1"}) + print("sh returned: ok=" .. tostring(ok) .. ", status=" .. tostring(status)) + end, + catch { + function (e) + print("sh raised exception: " .. tostring(e)) + end + } + } + + print("Testing os.execv with pwsh:") + try { + function () + local ok, status = os.execv("pwsh", {"-c", "exit 1"}) + print("pwsh returned: ok=" .. tostring(ok) .. ", status=" .. tostring(status)) + end, + catch { + function (e) + print("pwsh raised exception: " .. tostring(e)) + end + } + } + end) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 3da4ee4b8..f3e6f400d 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -73,15 +73,6 @@ function main() end end - -- enable diagnosis to get the stack traceback - local get_old = option.get - option.get = function (name) - if name == "diagnosis" then - return true - end - return get_old(name) - end - try { function () if script then @@ -101,7 +92,6 @@ function main() }, finally { function () - option.get = get_old if scriptfile_stdin then os.rm(scriptfile_stdin) end -- cgit v1.3.1 From 26904439b5907b973201019a5d1083eee1261272 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 08:39:02 +0300 Subject: refactor: enhance temporary file naming for stdin script handling --- xmake/plugins/lua/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index f3e6f400d..26cc8a360 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -63,7 +63,7 @@ function main() if script == "-" or from_stdin then local script_content = io.stdin:read("*a") if script_content then - scriptfile_stdin = os.tmpfile("xmake_lua_stdin") .. ".lua" + scriptfile_stdin = os.tmpfile("xmake_lua_stdin_" .. hash.uuid4()) .. ".lua" io.writefile(scriptfile_stdin, script_content) if from_stdin and script and script ~= "-" then arguments = arguments or {} -- cgit v1.3.1 From a6c7c34b0a3cba1f95a3411232bc566c62a661d0 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 08:43:57 +0300 Subject: refactor: fix stdin script reading method for improved compatibility --- xmake/plugins/lua/main.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 26cc8a360..b6951c276 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -61,7 +61,7 @@ function main() -- run script from stdin? local scriptfile_stdin if script == "-" or from_stdin then - local script_content = io.stdin:read("*a") + local script_content = io.read("*a") if script_content then scriptfile_stdin = os.tmpfile("xmake_lua_stdin_" .. hash.uuid4()) .. ".lua" io.writefile(scriptfile_stdin, script_content) -- cgit v1.3.1 From 09a702d482edc5fb7218900460442822e1303810 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 08:57:49 +0300 Subject: refactor: enhance script handling to support inline Lua content execution --- .../sandbox/modules/import/core/sandbox/module.lua | 69 +++++++++++++++++++--- xmake/modules/utils/run_script.lua | 7 ++- xmake/plugins/lua/main.lua | 49 +++++---------- 3 files changed, 80 insertions(+), 45 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/core/sandbox/modules/import/core/sandbox/module.lua b/xmake/core/sandbox/modules/import/core/sandbox/module.lua index dd7dac16e..3c76da6ff 100644 --- a/xmake/core/sandbox/modules/import/core/sandbox/module.lua +++ b/xmake/core/sandbox/modules/import/core/sandbox/module.lua @@ -67,6 +67,41 @@ function core_sandbox_module._modulepath(name) return modulepath end +-- load module from string +function core_sandbox_module._loadstring(content, instance, name) + assert(content) + + -- load module script + local script, errors = load(content, name) + if not script then + return nil, errors + end + + -- with sandbox? + if instance then + + -- fork a new sandbox for this script + instance, errors = instance:fork(script, instance:rootdir()) + if not instance then + return nil, errors + end + + -- load module + local result, errors = instance:module() + if not result then + return nil, errors + end + return result, instance:script() + end + + -- load module without sandbox + local ok, result = utils.trycall(script) + if not ok then + return nil, result + end + return result, script +end + -- load module from file function core_sandbox_module._loadfile(filepath, instance) assert(filepath) @@ -510,21 +545,37 @@ function core_sandbox_module.import(name, opt) local instance = sandbox.instance() assert(instance) - -- the root directory for this sandbox script + -- rootdir is optional local rootdir = opt.rootdir or instance:rootdir() - -- init module directories (disable local packages?) - local modules_directories = (opt.nolocal or not rootdir) and core_sandbox_module.directories() or table.join(rootdir, core_sandbox_module.directories()) + -- load module from content? + local module + local errors + local found = false + if opt.content then + found = true + module, errors = core_sandbox_module._loadstring(opt.content, instance, name) + if module then + if not opt.nocache then + modules[name] = {module, nil} + end + end + else - -- load module - local loadopt = table.clone(opt) or {} - loadopt.instance = instance - loadopt.modules = modules - loadopt.modules_directories = modules_directories - local found, module, errors = core_sandbox_module._find_and_load(name, loadopt) + -- init module directories (disable local packages?) + local modules_directories = (opt.nolocal or not rootdir) and core_sandbox_module.directories() or table.join(rootdir, core_sandbox_module.directories()) + -- load module + local loadopt = table.clone(opt) or {} + loadopt.instance = instance + loadopt.modules = modules + loadopt.modules_directories = modules_directories + found, module, errors = core_sandbox_module._find_and_load(name, loadopt) + end + -- not found? attempt to load module.interface if not found and not opt.inherit then + -- get module name local found2 = false local errors2 = nil diff --git a/xmake/modules/utils/run_script.lua b/xmake/modules/utils/run_script.lua index e6f8469f6..a51f4eef0 100644 --- a/xmake/modules/utils/run_script.lua +++ b/xmake/modules/utils/run_script.lua @@ -61,7 +61,12 @@ function _run_script(script, args, opt) local script_type, script_name -- import and run script - if path.extension(script) == ".lua" and os.isfile(script) then + if opt.content then + + -- run the given lua script content + script_type, script_name = "given lua script content", script + func = import(script, {anonymous = true, content = opt.content}) + elseif path.extension(script) == ".lua" and os.isfile(script) then -- run the given lua script file (xmake lua /tmp/script.lua) script_type, script_name = "given lua script file", path.relative(script) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index b6951c276..0a608b10a 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -59,45 +59,24 @@ function main() if script or from_stdin then -- run script from stdin? - local scriptfile_stdin + local script_content if script == "-" or from_stdin then - local script_content = io.read("*a") - if script_content then - scriptfile_stdin = os.tmpfile("xmake_lua_stdin_" .. hash.uuid4()) .. ".lua" - io.writefile(scriptfile_stdin, script_content) - if from_stdin and script and script ~= "-" then - arguments = arguments or {} - table.insert(arguments, 1, script) - end - script = scriptfile_stdin + script_content = io.read("*a") + if not script or script == "-" then + script = "xmake_lua_stdin" end end - try { - function () - if script then - run_script(script, { - curdir = os.workingdir(), - verbose = option.get("verbose"), - diagnosis = option.get("diagnosis"), - command = option.get("command"), - arguments = arguments, - deserialize = option.get("deserialize")}) - end - end, - catch { - function (errors) - raise(errors) - end - }, - finally { - function () - if scriptfile_stdin then - os.rm(scriptfile_stdin) - end - end - } - } + if script then + run_script(script, { + curdir = os.workingdir(), + verbose = option.get("verbose"), + diagnosis = option.get("diagnosis"), + command = option.get("command"), + arguments = arguments, + content = script_content, + deserialize = option.get("deserialize")}) + end else -- enter interactive mode sandbox.interactive() -- cgit v1.3.1 From 554f7a23f12ba4df73c23de64d52855e82a37088 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 14:06:52 +0300 Subject: refactor: improve stdin handling and shell command execution across platforms --- tests/modules/stdin/test.lua | 75 +++++++ tests/projects/test_stdin/xmake.lua | 226 --------------------- xmake/core/base/os.lua | 50 +---- .../sandbox/modules/import/core/sandbox/module.lua | 55 +---- xmake/core/sandbox/modules/os.lua | 6 - xmake/modules/utils/run_script.lua | 7 +- xmake/plugins/lua/main.lua | 26 ++- xmake/plugins/lua/xmake.lua | 20 +- 8 files changed, 109 insertions(+), 356 deletions(-) create mode 100644 tests/modules/stdin/test.lua delete mode 100644 tests/projects/test_stdin/xmake.lua (limited to 'xmake/plugins/lua/main.lua') diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua new file mode 100644 index 000000000..72551ed9c --- /dev/null +++ b/tests/modules/stdin/test.lua @@ -0,0 +1,75 @@ +target("test") + set_kind("phony") + on_run(function (target) + local xmake = path.unix(os.programfile()) + if os.host() == "windows" then + xmake = xmake:gsub("/", "\\") + end + + local function test_shell(name, cmd, expect) + print("testing " .. name .. ": " .. cmd) + local outfile = os.tmpfile() + local errfile = os.tmpfile() + local full_cmd = string.format("%s > \"%s\" 2> \"%s\"", cmd, outfile, errfile) + local ret = -1 + try { + function () + if os.host() ~= "windows" then + ret = os.execv("sh", {"-c", full_cmd}) + else + ret = os.exec(full_cmd) + end + end + } + local out = "" + if os.isfile(outfile) then + out = io.readfile(outfile) + if out and out:find("\0", 1, true) then + out = out:gsub("\0", "") + end + end + local err = "" + if os.isfile(errfile) then + err = io.readfile(errfile) + end + if out:find(expect) then + print(" -> passed") + else + print(" -> failed") + raise("[test_stdin]: Test failed! Expect: ", expect) + end + print(" out: " .. (out or "")) + print(" err: " .. (err or "")) + os.tryrm(outfile) + os.tryrm(errfile) + end + + local pwsh = "" + if os.host() == "windows" then + -- Test cmd + test_shell("cmd_single", string.format('cmd /c echo "print(\'hello_cmd\')" | %s l --stdin', xmake), "hello_cmd") + test_shell("cmd_multi", string.format('cmd /c echo "print(\'line1\')\\nprint(\'line2\')" | %s l --stdin', xmake), "line1[\r\n]+line2") + -- Test powershell (if available) + local pwsh = "powershell" + if os.exec("pwsh -v") == 0 then + pwsh = "pwsh" + end + test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") + test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") + else + -- Linux/MacOS + local pwsh = "" + try { function () os.iorun("pwsh -v"); pwsh = "pwsh" end } + if pwsh == "" then + try { function () os.iorun("powershell -v"); pwsh = "powershell" end } + end + + if pwsh ~= "" then + test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") + test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") + end + + test_shell("sh_single", string.format('echo "print(\'hello_sh\')" | %s l --stdin', xmake), "hello_sh") + test_shell("sh_multi", string.format('printf "print(\'shell_line1\')\\nprint(\'shell_line2\')" | %s l --stdin', xmake), "shell_line1[\r\n]+shell_line2") + end + end) diff --git a/tests/projects/test_stdin/xmake.lua b/tests/projects/test_stdin/xmake.lua deleted file mode 100644 index a603a08e9..000000000 --- a/tests/projects/test_stdin/xmake.lua +++ /dev/null @@ -1,226 +0,0 @@ -target("test") - set_kind("phony") - on_run(function (target) - import("core.base.option") - local xmake = path.unix(os.programfile()) - local xmake_dir = os.getenv("XMAKE_PROGRAM_DIR") - print("XMAKE_PROGRAM_DIR: " .. (xmake_dir or "nil")) - print("xmake binary: " .. xmake) - - if xmake_dir then - xmake_dir = path.unix(xmake_dir) - if os.host() == "windows" then - xmake_dir = xmake_dir:gsub("/", "\\") - end - os.setenv("XMAKE_PROGRAM_DIR", xmake_dir) - end - - -- New Helper: Probe for feature working (handles Windows/pwsh fallback) - local function check_feature() - print("Checking feature: --from-stdin ...") - local shell = os.shell() - - -- 1. Try detected shell if compatible - if shell == "pwsh" or shell == "powershell" then - local pwsh_probe = string.format("Write-Output \"print('probe_ok')\" | & '%s' lua --from-stdin", xmake) - local ok, out, _ = os.iorun_in_shell(shell, pwsh_probe) - if ok and out and out:find("probe_ok") then return true end - elseif shell == "cmd" then - local win_xmake = xmake:gsub("/", "\\") - local cmd_probe = string.format("echo print\"probe_ok\" | \"%s\" lua --from-stdin", win_xmake) - local ok, out, _ = os.iorun_in_shell("cmd", cmd_probe) - if ok and out and out:find("probe_ok") then return true end - end - - -- 2. Try generic sh (preferred if available validation default) - local probe_cmd = string.format("echo 'print(\"probe_ok\")' | %s lua --from-stdin", xmake) - local ok, out, _ = os.iorun_in_shell("sh", probe_cmd) - if ok and out and out:find("probe_ok") then return true end - - -- 3. Fallback: On Windows, try pwsh if sh failed - if os.host() == "windows" and shell ~= "pwsh" and shell ~= "powershell" and shell ~= "cmd" then - local pwsh_probe = string.format("Write-Output \"print('probe_ok')\" | & '%s' lua --from-stdin", xmake) - local ok, out, _ = os.iorun_in_shell("pwsh", pwsh_probe) - if ok and out and out:find("probe_ok") then return true end - end - return false - end - - -- check if feature is present - if check_feature() then - print("Feature presence check: PASS") - else - local ok, out, err = os.iorun_in_shell("sh", string.format("%s lua --help", xmake)) - if out and out:find("--from-stdin", 1, true) then - print("Feature presence check: PASS (via help text)") - else - print("Feature presence check: FAIL") - print("Help output (snippet): " .. (out and out:sub(1,100) or "nil")) - end - end - - -- test 1: pipe a few lines of lua code from echo (multiline) - local pipe_cmd = string.format("(echo 'print(\"hello\")'; echo 'print(\"from pipe\")') | '%s' lua --from-stdin", xmake) - print("running: " .. pipe_cmd) - local ok, out, err = os.iorun_in_shell("sh", pipe_cmd) - print("STDOUT 1:\n" .. (out or "")) - print("STDERR 1:\n" .. (err or "")) - assert(ok, "test 1 failed: command returned error") - if out then - assert(out:find("hello") and out:find("from pipe"), "test 1 failed: output mismatch") - end - - -- test 2: redirect from a .lua file (multiline) - -- FIX: Use cat and merge stderr (2>&1) to ensure we capture output robustly without hanging on Win - local scriptfile = path.join(os.curdir(), "test.lua") - io.writefile(scriptfile, 'print("hello")\nprint("from file")\n') - - local cat_cmd = string.format("cat '%s' | '%s' lua --from-stdin 2>&1", path.unix(scriptfile), xmake) - print("running: " .. cat_cmd) - ok, out, err = os.iorun_in_shell("sh", cat_cmd) - print("STDOUT 2:\n" .. (out or "")) - print("STDERR 2:\n" .. (err or "")) - - assert(ok, "test 2 failed: command returned error") - if out then - assert(out:find("hello") and out:find("from file"), "test 2 failed: output mismatch") - end - os.rm(scriptfile) - - -- test 3: verify traceback on error via pipe (multiline) - local error_pipe_cmd = string.format("(echo 'print(\"ok step\")'; echo 'raise(\"error_pipe\")') | '%s' lua --from-stdin", xmake) - print("running: " .. error_pipe_cmd) - ok, out, err = os.iorun_in_shell("sh", error_pipe_cmd) - print("STDOUT 3:\n" .. (out or "")) - print("STDERR 3:\n" .. (err or "")) - assert(not ok, "test 3 failed: command should have returned error") - if out then assert(out:find("ok step"), "test 3 failed: missing ok step output") end - assert((err and err:find("error_pipe")) or (out and out:find("error_pipe")), "test 3 failed: missing error message") - - -- test 4: verify traceback on error via file (multiline) - local errorfile = path.join(os.curdir(), "error.lua") - io.writefile(errorfile, 'print("ok step")\nraise("error_file")\n') - - -- FIX: Use cat and merge stderr (2>&1) - local error_file_cmd = string.format("cat '%s' | '%s' lua --from-stdin 2>&1", path.unix(errorfile), xmake) - print("running: " .. error_file_cmd) - ok, out, err = os.iorun_in_shell("sh", error_file_cmd) - print("STDOUT 4:\n" .. (out or "")) - print("STDERR 4:\n" .. (err or "")) - - assert(not ok, "test 4 failed: command should have returned error") - -- Check out (merged) or err just in case - if out then assert(out:find("ok step"), "test 4 failed: missing ok step output") end - assert((err and err:find("error_file")) or (out and out:find("error_file")), "test 4 failed: missing error message") - os.rm(errorfile) - - -- pwsh tests - if os.execv("pwsh", {"-v"}) == 0 then - print("pwsh detected, running pwsh tests...") - - -- test 5: pwsh pipe success (multiline) - local pwsh_pipe_cmd = string.format("Write-Output \"print(`\"hello`\")`nprint(`\"from pwsh pipe`\")\" | & '%s' lua --from-stdin", xmake) - print("running pwsh: " .. pwsh_pipe_cmd) - ok, out, err = os.iorun_in_shell("pwsh", pwsh_pipe_cmd) - print("STDOUT 5:\n" .. (out or "")) - print("STDERR 5:\n" .. (err or "")) - assert(ok, "test 5 failed: command returned error") - if out then - assert(out:find("hello") and out:find("from pwsh pipe"), "test 5 failed: output mismatch") - end - - -- test 6: pwsh file redirect success (multiline) - local scriptfile = path.join(os.curdir(), "test_pwsh.lua") - io.writefile(scriptfile, 'print("hello")\nprint("from pwsh file")\n') - local pwsh_redirect_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", scriptfile, xmake) - print("running pwsh: " .. pwsh_redirect_cmd) - ok, out, err = os.iorun_in_shell("pwsh", pwsh_redirect_cmd) - print("STDOUT 6:\n" .. (out or "")) - print("STDERR 6:\n" .. (err or "")) - assert(ok, "test 6 failed: command returned error") - if out then - assert(out:find("hello") and out:find("from pwsh file"), "test 6 failed: output mismatch") - end - os.rm(scriptfile) - - -- test 7: pwsh pipe error (multiline) - local pwsh_error_pipe_cmd = string.format("Write-Output \"print(`\"ok step`\")`nraise(`\"error_pwsh_pipe`\")\" | & '%s' lua --from-stdin", xmake) - print("running pwsh: " .. pwsh_error_pipe_cmd) - ok, out, err = os.iorun_in_shell("pwsh", pwsh_error_pipe_cmd) - print("STDOUT 7:\n" .. (out or "")) - print("STDERR 7:\n" .. (err or "")) - assert(not ok, "test 7 failed: command should have returned error") - if out then assert(out:find("ok step"), "test 7 failed: missing ok step output") end - assert((err and err:find("error_pwsh_pipe")) or (out and out:find("error_pwsh_pipe")), "test 7 failed: missing error message") - - -- test 8: pwsh file redirect error (multiline) - local errorfile = path.join(os.curdir(), "error_pwsh.lua") - io.writefile(errorfile, 'print("ok step")\nraise("error_pwsh_file")\n') - local pwsh_error_file_cmd = string.format("Get-Content '%s' | & '%s' lua --from-stdin", errorfile, xmake) - print("running pwsh: " .. pwsh_error_file_cmd) - ok, out, err = os.iorun_in_shell("pwsh", pwsh_error_file_cmd) - print("STDOUT 8:\n" .. (out or "")) - print("STDERR 8:\n" .. (err or "")) - assert(not ok, "test 8 failed: command should have returned error") - if out then assert(out:find("ok step"), "test 8 failed: missing ok step output") end - assert((err and err:find("error_pwsh_file")) or (out and out:find("error_pwsh_file")), "test 8 failed: missing error message") - os.rm(errorfile) - else - print("pwsh not found, skipping pwsh tests") - end - - -- cmd tests - if os.host() == "windows" then - print("windows detected, running cmd.exe tests...") - local win_xmake = xmake:gsub("/", "\\") - - -- test 9: cmd pipe success (multiline) - local cmd_pipe_cmd = string.format("(echo print\"hello\" && echo print\"from cmd pipe\") | \"%s\" lua --from-stdin", win_xmake) - print("running cmd: " .. cmd_pipe_cmd) - ok, out, err = os.iorun_in_shell("cmd", cmd_pipe_cmd) - print("STDOUT 9:\n" .. (out or "")) - print("STDERR 9:\n" .. (err or "")) - assert(ok, "test 9 failed: command returned error") - if out then assert(out:find("hello") and out:find("from cmd pipe"), "test 9 failed: output mismatch") end - - -- test 10: cmd file pipe success (multiline) - local scriptfile = path.join(os.curdir(), "test_cmd.lua") - local win_scriptfile = scriptfile:gsub("/", "\\") - -- FIX: Add newline for robust 'type' piping - io.writefile(scriptfile, 'print("hello")\nprint("from cmd file")\n') - - local cmd_file_cmd = string.format("type \"%s\" | \"%s\" lua --from-stdin", win_scriptfile, win_xmake) - print("running cmd: " .. cmd_file_cmd) - ok, out, err = os.iorun_in_shell("cmd", cmd_file_cmd) - print("STDOUT 10:\n" .. (out or "")) - print("STDERR 10:\n" .. (err or "")) - assert(ok, "test 10 failed: command returned error") - if out then assert(out:find("hello") and out:find("from cmd file"), "test 10 failed: output mismatch") end - os.rm(scriptfile) - - -- test 11: cmd pipe error (multiline) - local cmd_err_pipe_cmd = string.format("(echo print\"ok step\" && echo raise\"error_cmd_pipe\") | \"%s\" lua --from-stdin", win_xmake) - print("running cmd: " .. cmd_err_pipe_cmd) - ok, out, err = os.iorun_in_shell("cmd", cmd_err_pipe_cmd) - print("STDOUT 11:\n" .. (out or "")) - print("STDERR 11:\n" .. (err or "")) - assert(not ok, "test 11 failed: command should have returned error") - if out then assert(out:find("ok step"), "test 11 failed: missing ok step output") end - assert((err and err:find("error_cmd_pipe")) or (out and out:find("error_cmd_pipe")), "test 11 failed: missing error message") - - -- test 12: cmd file pipe error (multiline) - local errorfile = path.join(os.curdir(), "error_cmd.lua") - local win_errorfile = errorfile:gsub("/", "\\") - io.writefile(errorfile, 'print("ok step")\nraise("error_cmd_file")\n') - - local cmd_err_file_cmd = string.format("type \"%s\" | \"%s\" lua --from-stdin", win_errorfile, win_xmake) - print("running cmd: " .. cmd_err_file_cmd) - ok, out, err = os.iorun_in_shell("cmd", cmd_err_file_cmd) - print("STDOUT 12:\n" .. (out or "")) - print("STDERR 12:\n" .. (err or "")) - assert(not ok, "test 12 failed: command should have returned error") - if out then assert(out:find("ok step"), "test 12 failed: missing ok step output") end - assert((err and err:find("error_cmd_file")) or (out and out:find("error_cmd_file")), "test 12 failed: missing error message") - os.rm(errorfile) - end - end) diff --git a/xmake/core/base/os.lua b/xmake/core/base/os.lua index 86f04e35d..12bc30c1d 100644 --- a/xmake/core/base/os.lua +++ b/xmake/core/base/os.lua @@ -1106,51 +1106,6 @@ function os.iorunv(program, argv, opt) return ok == 0, outdata, errdata, errors end --- run command in the given shell and return output and error data --- --- @param shell the shell name (e.g. sh, bash, zsh, cmd, pwsh, powershell) --- @param cmd the command string --- @param opt the options --- --- @return ok, stdout, stderr, errors --- -function os.iorun_in_shell(shell, cmd, opt) - - -- check - if not shell or not cmd then - return false, nil, nil, "invalid arguments" - end - - -- run in pwsh/powershell - if shell == "pwsh" or shell == "powershell" then - local shell_cmd = string.format("& { %s; exit $LASTEXITCODE }", cmd) - return os.iorunv(shell, {"-c", shell_cmd}, opt) - - -- run in cmd - elseif shell == "cmd" then - - -- use batfile to robust pipe handling - local batfile = os.tmpfile() .. ".bat" - local batch_content = "@echo off\n" - - -- append command - batch_content = batch_content .. cmd .. "\n" - - -- append exit code check - batch_content = batch_content .. "if %errorlevel% neq 0 exit /b %errorlevel%\n" - - io.writefile(batfile, batch_content) - - local ok, out, err, errors = os.iorunv(batfile, {}, opt) - os.rm(batfile) - return ok, out, err, errors - - -- run in sh/bash/zsh... - else - return os.iorunv(shell, {"-c", cmd}, opt) - end -end - -- raise an exception and abort the current script -- -- the parent function will capture it if we uses pcall or xpcall @@ -1232,10 +1187,7 @@ function os.isexec(filepath) end end elseif os.isfile(filepath) then - if os._access then - return os._access(filepath, "x") - end - return true + return os._access(filepath, "x") end return false end diff --git a/xmake/core/sandbox/modules/import/core/sandbox/module.lua b/xmake/core/sandbox/modules/import/core/sandbox/module.lua index 34d55415d..dd7dac16e 100644 --- a/xmake/core/sandbox/modules/import/core/sandbox/module.lua +++ b/xmake/core/sandbox/modules/import/core/sandbox/module.lua @@ -67,41 +67,6 @@ function core_sandbox_module._modulepath(name) return modulepath end --- load module from string -function core_sandbox_module._loadstring(content, instance, name) - assert(content) - - -- load module script - local script, errors = load(content, name) - if not script then - return nil, errors - end - - -- with sandbox? - if instance then - - -- fork a new sandbox for this script - instance, errors = instance:fork(script, instance:rootdir()) - if not instance then - return nil, errors - end - - -- load module - local result, errors = instance:module() - if not result then - return nil, errors - end - return result, instance:script() - end - - -- load module without sandbox - local ok, result = utils.trycall(script) - if not ok then - return nil, result - end - return result, script -end - -- load module from file function core_sandbox_module._loadfile(filepath, instance) assert(filepath) @@ -545,7 +510,7 @@ function core_sandbox_module.import(name, opt) local instance = sandbox.instance() assert(instance) - -- rootdir is optional + -- the root directory for this sandbox script local rootdir = opt.rootdir or instance:rootdir() -- init module directories (disable local packages?) @@ -556,26 +521,10 @@ function core_sandbox_module.import(name, opt) loadopt.instance = instance loadopt.modules = modules loadopt.modules_directories = modules_directories + local found, module, errors = core_sandbox_module._find_and_load(name, loadopt) - -- load module - local module - local errors - local found = false - if opt.content then - found = true - module, errors = core_sandbox_module._loadstring(opt.content, instance, name) - if module then - if not opt.nocache then - modules[name] = {module, nil} - end - end - else - found, module, errors = core_sandbox_module._find_and_load(name, loadopt) - end - -- not found? attempt to load module.interface if not found and not opt.inherit then - -- get module name local found2 = false local errors2 = nil diff --git a/xmake/core/sandbox/modules/os.lua b/xmake/core/sandbox/modules/os.lua index ec5cb0e1e..aebb3cfb0 100644 --- a/xmake/core/sandbox/modules/os.lua +++ b/xmake/core/sandbox/modules/os.lua @@ -324,12 +324,6 @@ function sandbox_os.iorunv(program, argv, opt) return outdata, errdata end --- run command in shell with io redirection and return (ok, out, err) -function sandbox_os.iorun_in_shell(shell, cmd, ...) - cmd = vformat(cmd, ...) - return os.iorun_in_shell(shell, cmd) -end - -- execute command function sandbox_os.exec(cmd, ...) cmd = vformat(cmd, ...) diff --git a/xmake/modules/utils/run_script.lua b/xmake/modules/utils/run_script.lua index a51f4eef0..e6f8469f6 100644 --- a/xmake/modules/utils/run_script.lua +++ b/xmake/modules/utils/run_script.lua @@ -61,12 +61,7 @@ function _run_script(script, args, opt) local script_type, script_name -- import and run script - if opt.content then - - -- run the given lua script content - script_type, script_name = "given lua script content", script - func = import(script, {anonymous = true, content = opt.content}) - elseif path.extension(script) == ".lua" and os.isfile(script) then + if path.extension(script) == ".lua" and os.isfile(script) then -- run the given lua script file (xmake lua /tmp/script.lua) script_type, script_name = "given lua script file", path.relative(script) diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 0a608b10a..a945a64c1 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -55,15 +55,26 @@ function main() -- run script local script = option.get("script") local arguments = option.get("arguments") - local from_stdin = option.get("from_stdin") or option.get("from-stdin") + local from_stdin = option.get("stdin") if script or from_stdin then -- run script from stdin? - local script_content + local script_file_to_remove if script == "-" or from_stdin then - script_content = io.read("*a") - if not script or script == "-" then - script = "xmake_lua_stdin" + local script_content = io.read("*a") + if script_content then + import("core.base.tty") + local shell = tty.shell() + if shell == "cmd" or shell == "powershell" or shell == "pwsh" or os.host() == "windows" then + script_content = script_content:trim() + if script_content:startswith('"') and script_content:endswith('"') then + script_content = script_content:sub(2, -2) + end + script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) + end + script = os.tmpfile() .. ".lua" + io.writefile(script, script_content) + script_file_to_remove = script end end @@ -74,8 +85,11 @@ function main() diagnosis = option.get("diagnosis"), command = option.get("command"), arguments = arguments, - content = script_content, deserialize = option.get("deserialize")}) + + if script_file_to_remove then + os.tryrm(script_file_to_remove) + end end else -- enter interactive mode diff --git a/xmake/plugins/lua/xmake.lua b/xmake/plugins/lua/xmake.lua index 467cde3f1..8b60c96d3 100644 --- a/xmake/plugins/lua/xmake.lua +++ b/xmake/plugins/lua/xmake.lua @@ -45,20 +45,20 @@ task("lua") {'l', "list" , "k" , nil , "List all scripts." } , {'c', "command" , "k" , nil , "Run script as command" } , {'d', "deserialize" , "kv" , nil , "Deserialize arguments starts with given prefix" } - , {nil, "from-stdin" , "k" , nil , "Run script from stdin", + , {nil, "stdin" , "k" , nil , "Run script from stdin", "e.g.", " - CMD", - " - Single: echo print(\"hello\") | xmake lua --from-stdin", - " - Multiline: (echo print('1') && echo print('2')) | xmake lua --from-stdin", - " - File: type script.lua | xmake lua --from-stdin", + " - Single: echo print(\"hello\") | xmake lua --stdin", + " - Multiline: (echo print('1') && echo print('2')) | xmake lua --stdin", + " - File: type script.lua | xmake lua --stdin", " - PWSH", - " - Single: Write-Output 'print(\"hello\")' | xmake lua --from-stdin", - " - Multiline: Write-Output \"print('1')`nprint('2')\" | xmake lua --from-stdin", - " - File: Get-Content script.lua | xmake lua --from-stdin", + " - Single: Write-Output 'print(\"hello\")' | xmake lua --stdin", + " - Multiline: Write-Output \"print('1')`nprint('2')\" | xmake lua --stdin", + " - File: Get-Content script.lua | xmake lua --stdin", " - SH", - " - Single: echo 'print(\"hello\")' | xmake lua --from-stdin", - " - Multiline: (echo 'print(\"1\")'; echo 'print(\"2\")') | xmake lua --from-stdin", - " - File: cat script.lua | xmake lua --from-stdin" + " - Single: echo 'print(\"hello\")' | xmake lua --stdin", + " - Multiline: (echo 'print(\"1\")'; echo 'print(\"2\")') | xmake lua --stdin", + " - File: cat script.lua | xmake lua --stdin" } , {nil, "script" , "v" , nil , "Run the given lua script name, file or module and enter interactive mode if no given script.", "e.g.", -- cgit v1.3.1 From 05dc5f8fbfd139cb9cbe1c6679b59aba9ae02dd4 Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 14:25:14 +0300 Subject: refactor: wrap script content in a main function for better execution context --- xmake/plugins/lua/main.lua | 1 + 1 file changed, 1 insertion(+) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index a945a64c1..0c0b44005 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -72,6 +72,7 @@ function main() end script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) end + script_content = "function main(...)\n" .. script_content .. "\nend" script = os.tmpfile() .. ".lua" io.writefile(script, script_content) script_file_to_remove = script -- cgit v1.3.1 From 50b428269a657fd0adce1de35b01abe42c13708b Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 14:40:44 +0300 Subject: refactor: enhance stdin handling by adding utf8 BOM removal and main function check --- tests/modules/stdin/test.lua | 4 +++- xmake/plugins/lua/main.lua | 10 +++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 1cef7a362..bcd9efca6 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -70,11 +70,13 @@ else if pwsh ~= "" then test_shell("pwsh_single", string.format('%s -c "echo \\"print(\'hello_pwsh\')\\" | %s l --stdin"', pwsh, xmake), "hello_pwsh") test_shell("pwsh_calc", string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), "2") - test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\nprint(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") + test_shell("pwsh_main", string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s l --stdin"', pwsh, xmake), "in_pwsh_main") + test_shell("pwsh_multi", string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s l --stdin"', pwsh, xmake), "pline1[\r\n]+pline2") end test_shell("sh_single", string.format('echo "print(\'hello_sh\')" | %s l --stdin', xmake), "hello_sh") test_shell("sh_calc", string.format('echo "local f = 1+1; print(f)" | %s l --stdin', xmake), "2") + test_shell("sh_main", string.format('echo "function main() print(\'in_sh_main\') end" | %s l --stdin', xmake), "in_sh_main") test_shell("sh_multi", string.format('printf "print(\'shell_line1\')\\nprint(\'shell_line2\')" | %s l --stdin', xmake), "shell_line1[\r\n]+shell_line2") end end diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 0c0b44005..1cc13dbc3 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -63,6 +63,10 @@ function main() if script == "-" or from_stdin then local script_content = io.read("*a") if script_content then + -- remove utf8 bom + if script_content:startswith("\239\187\191") then + script_content = script_content:sub(4) + end import("core.base.tty") local shell = tty.shell() if shell == "cmd" or shell == "powershell" or shell == "pwsh" or os.host() == "windows" then @@ -72,7 +76,11 @@ function main() end script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) end - script_content = "function main(...)\n" .. script_content .. "\nend" + + if not script_content:find("function main", 1, true) then + script_content = "function main(...)\n" .. script_content .. "\nend" + end + script = os.tmpfile() .. ".lua" io.writefile(script, script_content) script_file_to_remove = script -- cgit v1.3.1 From faca264f8ea0fb695f6bc8b3a9d1411f901f054b Mon Sep 17 00:00:00 2001 From: Saikari Date: Sun, 1 Feb 2026 16:14:46 +0300 Subject: refactor: simplify stdin handling by removing redundant checks and streamlining usage examples --- xmake/plugins/lua/main.lua | 2 +- xmake/plugins/lua/xmake.lua | 14 ++------------ 2 files changed, 3 insertions(+), 13 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 1cc13dbc3..247684e24 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -60,7 +60,7 @@ function main() -- run script from stdin? local script_file_to_remove - if script == "-" or from_stdin then + if from_stdin then local script_content = io.read("*a") if script_content then -- remove utf8 bom diff --git a/xmake/plugins/lua/xmake.lua b/xmake/plugins/lua/xmake.lua index 8b60c96d3..bb9308378 100644 --- a/xmake/plugins/lua/xmake.lua +++ b/xmake/plugins/lua/xmake.lua @@ -47,18 +47,8 @@ task("lua") , {'d', "deserialize" , "kv" , nil , "Deserialize arguments starts with given prefix" } , {nil, "stdin" , "k" , nil , "Run script from stdin", "e.g.", - " - CMD", - " - Single: echo print(\"hello\") | xmake lua --stdin", - " - Multiline: (echo print('1') && echo print('2')) | xmake lua --stdin", - " - File: type script.lua | xmake lua --stdin", - " - PWSH", - " - Single: Write-Output 'print(\"hello\")' | xmake lua --stdin", - " - Multiline: Write-Output \"print('1')`nprint('2')\" | xmake lua --stdin", - " - File: Get-Content script.lua | xmake lua --stdin", - " - SH", - " - Single: echo 'print(\"hello\")' | xmake lua --stdin", - " - Multiline: (echo 'print(\"1\")'; echo 'print(\"2\")') | xmake lua --stdin", - " - File: cat script.lua | xmake lua --stdin" + " - echo 'print(\"hello\")' | xmake lua --stdin", + " - cat script.lua | xmake lua --stdin" } , {nil, "script" , "v" , nil , "Run the given lua script name, file or module and enter interactive mode if no given script.", "e.g.", -- cgit v1.3.1 From 33409f7b71773265fba3a6f688cdf97262770511 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:00:50 +0300 Subject: refactor: streamline stdin script handling for Windows compatibility --- xmake/plugins/lua/main.lua | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 247684e24..7137ea589 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -67,12 +67,11 @@ function main() if script_content:startswith("\239\187\191") then script_content = script_content:sub(4) end - import("core.base.tty") - local shell = tty.shell() - if shell == "cmd" or shell == "powershell" or shell == "pwsh" or os.host() == "windows" then + local shell = os.shell() + if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then script_content = script_content:trim() if script_content:startswith('"') and script_content:endswith('"') then - script_content = script_content:sub(2, -2) + script_content = script_content:trim('\"') end script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) end -- cgit v1.3.1 From 077e2daa5a10dbd9e20a9f25bad74bb303678c66 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:19:04 +0300 Subject: refactor: replace hardcoded utf8 BOM check with utf8.bom constant for improved maintainability --- xmake/plugins/lua/main.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 7137ea589..f5f7a6867 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -64,8 +64,8 @@ function main() local script_content = io.read("*a") if script_content then -- remove utf8 bom - if script_content:startswith("\239\187\191") then - script_content = script_content:sub(4) + if script_content:startswith(utf8.bom) then + script_content = script_content:ltrim(utf8.bom) end local shell = os.shell() if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then -- cgit v1.3.1 From 84dcbd0fa5ebaa612c851fb1694993a9aa3f3968 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:19:59 +0300 Subject: refactor: streamline utf8 BOM removal process in script content handling --- xmake/plugins/lua/main.lua | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index f5f7a6867..96ff6e40d 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -64,15 +64,11 @@ function main() local script_content = io.read("*a") if script_content then -- remove utf8 bom - if script_content:startswith(utf8.bom) then - script_content = script_content:ltrim(utf8.bom) - end + script_content = script_content:ltrim(utf8.bom) local shell = os.shell() if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then script_content = script_content:trim() - if script_content:startswith('"') and script_content:endswith('"') then - script_content = script_content:trim('\"') - end + script_content = script_content:trim('\"') script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) end -- cgit v1.3.1 From 5e885b512315064825a96fa4865707adae9ab7ed Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:22:02 +0300 Subject: refactor: extract stdin script handling into a separate function for improved readability and maintainability --- xmake/plugins/lua/main.lua | 47 ++++++++++++++++++++++++++++------------------ 1 file changed, 29 insertions(+), 18 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 96ff6e40d..988f2af1f 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -45,6 +45,31 @@ function _list() end end +-- get script from stdin +function _get_script_from_stdin() + local script_content = io.read("*a") + if script_content then + -- remove utf8 bom + if script_content:startswith(utf8.bom) then + script_content = script_content:sub(#utf8.bom + 1) + end + local shell = os.shell() + if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then + script_content = script_content:trim() + script_content = script_content:trim('\"') + script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) + end + + if not script_content:find("function main", 1, true) then + script_content = "function main(...)\n" .. script_content .. "\nend" + end + + local script = os.tmpfile() .. ".lua" + io.writefile(script, script_content) + return script + end +end + function main() -- list builtin scripts @@ -61,24 +86,10 @@ function main() -- run script from stdin? local script_file_to_remove if from_stdin then - local script_content = io.read("*a") - if script_content then - -- remove utf8 bom - script_content = script_content:ltrim(utf8.bom) - local shell = os.shell() - if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then - script_content = script_content:trim() - script_content = script_content:trim('\"') - script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) - end - - if not script_content:find("function main", 1, true) then - script_content = "function main(...)\n" .. script_content .. "\nend" - end - - script = os.tmpfile() .. ".lua" - io.writefile(script, script_content) - script_file_to_remove = script + local script_path = _get_script_from_stdin() + if script_path then + script = script_path + script_file_to_remove = script_path end end -- cgit v1.3.1 From 8a6b95da91feb273b1ad151fb2d0dbf57b3475b0 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 09:24:43 +0300 Subject: Refactor BOM removal in script input handling --- xmake/plugins/lua/main.lua | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 988f2af1f..261dffaa0 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -50,9 +50,7 @@ function _get_script_from_stdin() local script_content = io.read("*a") if script_content then -- remove utf8 bom - if script_content:startswith(utf8.bom) then - script_content = script_content:sub(#utf8.bom + 1) - end + script_content = script_content:ltrim(utf8.bom) local shell = os.shell() if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then script_content = script_content:trim() -- cgit v1.3.1 From d1653c5b32f4efa7fec6ab40cb93eb14b0014c38 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 10:28:45 +0300 Subject: refactor: enhance stdin script handling by improving string trimming logic --- tests/modules/stdin/test.lua | 7 ++++++- xmake/plugins/lua/main.lua | 11 ++++++++--- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/tests/modules/stdin/test.lua b/tests/modules/stdin/test.lua index 6b1b4026b..b0c908c3c 100644 --- a/tests/modules/stdin/test.lua +++ b/tests/modules/stdin/test.lua @@ -112,9 +112,14 @@ function main(t) string.format('%s -c "echo \\"local f = 1+1; print(f)\\" | %s l --stdin"', pwsh, xmake), "2" ) + test_shell( + "pwsh_main", + string.format('%s -c "echo \\"function main() print(\'in_pwsh_main\') end\\" | %s"', pwsh, run_stdin), + "in_pwsh_main" + ) test_shell( "pwsh_multi", - string.format("%s -c \"echo \\\"print('pline1')\\nprint('pline2')\\\" | %s l --stdin\"", pwsh, xmake), + string.format('%s -c "echo \\"print(\'pline1\')\\" \\"print(\'pline2\')\\" | %s"', pwsh, run_stdin), "pline1[\r\n]+pline2" ) else diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index 261dffaa0..b2a104949 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -53,9 +53,14 @@ function _get_script_from_stdin() script_content = script_content:ltrim(utf8.bom) local shell = os.shell() if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then - script_content = script_content:trim() - script_content = script_content:trim('\"') - script_content = script_content:replace("\\n", "\n", {plain = true}):replace("\\r", "\r", {plain = true}) + local trimmed = script_content:trim() + if trimmed:startswith('"') and trimmed:endswith('"') then + script_content = trimmed:trim('"') + script_content = script_content:replace("\\n", "\n", {plain = true}) + :replace("\\r", "\r", {plain = true}) + else + script_content = trimmed + end end if not script_content:find("function main", 1, true) then -- cgit v1.3.1 From 1f23a23c7ef92f0cc20e402abb4a510a3cb72f00 Mon Sep 17 00:00:00 2001 From: Saikari Date: Mon, 2 Feb 2026 11:44:25 +0300 Subject: refactor: simplify script content handling in _get_script_from_stdin function --- xmake/plugins/lua/main.lua | 2 -- 1 file changed, 2 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index b2a104949..c7b5137ce 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -56,8 +56,6 @@ function _get_script_from_stdin() local trimmed = script_content:trim() if trimmed:startswith('"') and trimmed:endswith('"') then script_content = trimmed:trim('"') - script_content = script_content:replace("\\n", "\n", {plain = true}) - :replace("\\r", "\r", {plain = true}) else script_content = trimmed end -- cgit v1.3.1 From f99b99b2ae3cfeb47356e6542c393bba009f8583 Mon Sep 17 00:00:00 2001 From: ruki Date: Tue, 3 Feb 2026 10:17:50 +0800 Subject: Refactor script content handling in main.lua Removed Windows-specific shell handling for script content. --- xmake/plugins/lua/main.lua | 10 ---------- 1 file changed, 10 deletions(-) (limited to 'xmake/plugins/lua/main.lua') diff --git a/xmake/plugins/lua/main.lua b/xmake/plugins/lua/main.lua index c7b5137ce..772faa2c6 100644 --- a/xmake/plugins/lua/main.lua +++ b/xmake/plugins/lua/main.lua @@ -51,16 +51,6 @@ function _get_script_from_stdin() if script_content then -- remove utf8 bom script_content = script_content:ltrim(utf8.bom) - local shell = os.shell() - if shell == "cmd" or shell == "powershell" or shell == "pwsh" or is_host("windows") then - local trimmed = script_content:trim() - if trimmed:startswith('"') and trimmed:endswith('"') then - script_content = trimmed:trim('"') - else - script_content = trimmed - end - end - if not script_content:find("function main", 1, true) then script_content = "function main(...)\n" .. script_content .. "\nend" end -- cgit v1.3.1