|
1 | 1 | ---Will contain either `s`, a plain string, |
2 | 2 | ---or `c`, an input command string |
3 | | ----@class Shelua.PipeInput |
| 3 | +---@class Shelua.PipeInputStdin |
4 | 4 | ---string stdin to combine |
5 | 5 | ---@field s? string|any |
6 | 6 | ---if string input came from a command, |
7 | 7 | ---`e` will contain a table of all other command result fields |
8 | 8 | ---such as `__exitcode` |
9 | 9 | ---@field e? table |
| 10 | + |
| 11 | +---@class Shelua.PipeInputClass |
10 | 12 | ---cmd to combine |
11 | 13 | ---@field c? string|any |
12 | 14 | ---optional 2nd return of concat_cmd |
13 | 15 | ---@field m? any |
14 | 16 |
|
| 17 | +---@alias Shelua.PipeInput Shelua.PipeInputStdin | Shelua.PipeInputClass |
| 18 | + |
15 | 19 | ---@class Shelua.Repr |
16 | 20 | ---escapes a string for the shell |
17 | 21 | ---@field escape fun(arg: any, opts: Shelua.Opts?): string |
|
20 | 24 | ---@field arg_tbl fun(opts: Shelua.Opts, k: string, a: any): string|string[]? |
21 | 25 | ---adds args to the command |
22 | 26 | ---@field add_args fun(opts: Shelua.Opts, cmd: string, args: string[]): string|any |
23 | | ----returns cmd and an optional item such as path to a tempfile to be passed to post_5_2_run or pre_5_2_run |
| 27 | +---returns cmd and an optional item such as path to a tempfile to be passed to run_cmd |
24 | 28 | ---called when proper_pipes is false |
25 | 29 | ---cmd is the result of add_args |
26 | 30 | ---codes is the list of codes that correspond with each input such as `__exitcode`, empty if none |
|
30 | 34 | ---@field concat_cmd fun(opts: Shelua.Opts, cmd: string|any, input: Shelua.PipeInput[]): (string|any, any?) |
31 | 35 | ---a list of functions to run in order on the command before running it. |
32 | 36 | ---each one recieves the previous value and returns a new one. |
33 | | ----they are ran after concat_cmd or single_stdin and before the post_5_2_run and pre_5_2_run functions |
| 37 | +---they are ran after concat_cmd or single_stdin and before the run_cmd functions |
34 | 38 | ---@field transforms? (fun(cmd: string|any): string|any)[] |
35 | 39 | ---runs the command and returns the result and exit code and signal |
36 | | ----@field post_5_2_run fun(opts: Shelua.Opts, cmd: string|any, msg: any?): { __input: string, __exitcode: number, __signal: number } |
37 | | ----runs the command and returns the result and exit code and signal |
38 | | ----@field pre_5_2_run fun(opts: Shelua.Opts, cmd: string|any, msg: any?): { __input: string, __exitcode: number, __signal: number } |
39 | | ----if your pre_5_2_run or post_5_2_run returns a table with extra keys, e.g. `__stderr` |
| 40 | +---@field run_cmd fun(opts: Shelua.Opts, cmd: string|any, msg: any?): { __input: string, __exitcode: number, __signal: number } |
| 41 | +---if your run_cmd returns a table with extra keys, e.g. `__stderr` |
40 | 42 | ---proper_pipes will need to know that accessing them should be a trigger to resolve the pipe. |
41 | 43 | ---each string in this table must begin with '__' or it will be ignored |
42 | 44 | ---@field extra_cmd_results string[]|fun(opts: Shelua.Opts): string[] |
@@ -134,10 +136,34 @@ local function tbl_get(t, default, ...) |
134 | 136 | return t or default |
135 | 137 | end |
136 | 138 |
|
| 139 | +local warned_run_cmd_shim = false |
| 140 | + |
137 | 141 | ---@param opts Shelua.Opts |
138 | 142 | ---@param attr string |
139 | 143 | ---@return function |
140 | 144 | local get_repr_fn = function(opts, attr) |
| 145 | + if attr == "run_cmd" then |
| 146 | + local shell = opts.shell or "posix" |
| 147 | + local shell_repr = tbl_get(opts, nil, "repr", shell) |
| 148 | + if shell_repr and not shell_repr.run_cmd then |
| 149 | + local old_post = shell_repr.post_5_2_run |
| 150 | + local old_pre = shell_repr.pre_5_2_run |
| 151 | + if old_post or old_pre then |
| 152 | + if not warned_run_cmd_shim then |
| 153 | + warned_run_cmd_shim = true |
| 154 | + io.stderr:write("shelua: post_5_2_run/pre_5_2_run are deprecated. ") |
| 155 | + io.stderr:write("Use run_cmd(opts, cmd, msg) instead.\n") |
| 156 | + end |
| 157 | + shell_repr.run_cmd = function(o, cmd, msg) |
| 158 | + if is_5_2_plus and old_post then |
| 159 | + return old_post(o, cmd, msg) |
| 160 | + else |
| 161 | + return (old_pre or old_post)(o, cmd, msg) |
| 162 | + end |
| 163 | + end |
| 164 | + end |
| 165 | + end |
| 166 | + end |
141 | 167 | return tbl_get(opts, tbl_get(opts, function() |
142 | 168 | error("Shelua Repr Error: " .. |
143 | 169 | tostring(attr) .. " function required for shell: " .. tostring(opts.shell or "posix")) |
@@ -222,39 +248,40 @@ local posix = { |
222 | 248 | return cmd |
223 | 249 | end |
224 | 250 | end, |
225 | | - post_5_2_run = function(opts, cmd, tmp) |
226 | | - local p = io.popen(cmd, 'r') |
227 | | - local output, _, exit, status |
228 | | - if p then |
229 | | - output = p:read('*a') |
230 | | - _, exit, status = p:close() |
231 | | - end |
232 | | - pcall(os.remove, tmp) |
| 251 | + run_cmd = function(opts, cmd, tmp) |
| 252 | + if is_5_2_plus then |
| 253 | + local p = io.popen(cmd, 'r') |
| 254 | + local output, _, exit, status |
| 255 | + if p then |
| 256 | + output = p:read('*a') |
| 257 | + _, exit, status = p:close() |
| 258 | + end |
| 259 | + pcall(os.remove, tmp) |
233 | 260 |
|
234 | | - return { |
235 | | - __input = output, |
236 | | - __exitcode = exit == 'exit' and status or 127, |
237 | | - __signal = exit == 'signal' and status or 0, |
238 | | - } |
239 | | - end, |
240 | | - pre_5_2_run = function(opts, cmd, tmp) |
241 | | - local p = io.popen(cmd .. "\necho __EXITCODE__$?", 'r') |
242 | | - local output |
243 | | - if p then |
244 | | - output = p:read('*a') |
245 | | - p:close() |
| 261 | + return { |
| 262 | + __input = output, |
| 263 | + __exitcode = exit == 'exit' and status or 127, |
| 264 | + __signal = exit == 'signal' and status or 0, |
| 265 | + } |
| 266 | + else |
| 267 | + local p = io.popen(cmd .. "\necho __EXITCODE__$?", 'r') |
| 268 | + local output |
| 269 | + if p then |
| 270 | + output = p:read('*a') |
| 271 | + p:close() |
| 272 | + end |
| 273 | + pcall(os.remove, tmp) |
| 274 | + local exit |
| 275 | + output = (output or ""):gsub("__EXITCODE__(%d*)\r?\n?$", function(code) |
| 276 | + exit = tonumber(code) |
| 277 | + return "" |
| 278 | + end) |
| 279 | + return { |
| 280 | + __input = output, |
| 281 | + __exitcode = exit or 127, |
| 282 | + __signal = (exit and exit > 128) and (exit - 128) or 0 |
| 283 | + } |
246 | 284 | end |
247 | | - pcall(os.remove, tmp) |
248 | | - local exit |
249 | | - output = (output or ""):gsub("__EXITCODE__(%d*)\r?\n?$", function(code) |
250 | | - exit = tonumber(code) |
251 | | - return "" |
252 | | - end) |
253 | | - return { |
254 | | - __input = output, |
255 | | - __exitcode = exit or 127, |
256 | | - __signal = (exit and exit > 128) and (exit - 128) or 0 |
257 | | - } |
258 | 285 | end, |
259 | 286 | extra_cmd_results = {}, |
260 | 287 | transforms = {}, |
@@ -362,21 +389,14 @@ local cmd_mt = { |
362 | 389 | end |
363 | 390 | if check_if_cmd_result(opts, c) then |
364 | 391 | local apply = function(com) |
365 | | - local transforms = opts.transforms |
366 | | - if transforms then print("Shelua Deprecation: transforms option moved to be a repr-specific option") end |
367 | | - transforms = tbl_get(opts, transforms or {}, "repr", opts.shell or "posix", "transforms") |
| 392 | + local transforms = tbl_get(opts, {}, "repr", opts.shell or "posix", "transforms") |
368 | 393 | for _, f in ipairs(transforms) do |
369 | 394 | com = f(com) |
370 | 395 | end |
371 | 396 | return com |
372 | 397 | end |
373 | 398 | local cmd, msg = resolve(self, opts) |
374 | | - local res |
375 | | - if is_5_2_plus then |
376 | | - res = get_repr_fn(opts, "post_5_2_run")(opts, apply(cmd), msg) |
377 | | - else |
378 | | - res = get_repr_fn(opts, "pre_5_2_run")(opts, apply(cmd), msg) |
379 | | - end |
| 399 | + local res = get_repr_fn(opts, "run_cmd")(opts, apply(cmd), msg) |
380 | 400 | for k, v in pairs(res or {}) do |
381 | 401 | rawset(self, k, v) |
382 | 402 | end |
@@ -494,25 +514,16 @@ command = function(self, cmdstr, ...) |
494 | 514 | unresolved[t] = { cmd = cmd, unres = unres, input = input, codes = codes } |
495 | 515 | else |
496 | 516 | local apply = function(com) |
497 | | - local transforms = shmt.transforms |
498 | | - if transforms then print("Shelua Deprecation: transforms option moved to be a repr-specific option") end |
499 | | - transforms = tbl_get(shmt, transforms or {}, "repr", shmt.shell or "posix", "transforms") |
| 517 | + local transforms = tbl_get(shmt, {}, "repr", shmt.shell or "posix", "transforms") |
500 | 518 | for _, f in ipairs(transforms) do |
501 | 519 | com = f(com) |
502 | 520 | end |
503 | 521 | return com |
504 | 522 | end |
505 | | - if is_5_2_plus then |
506 | | - local msg |
507 | | - cmd, msg = get_repr_fn(shmt, "single_stdin")(shmt, cmd, #input > 0 and input or nil, |
508 | | - #codes > 0 and codes or nil) |
509 | | - t = get_repr_fn(shmt, "post_5_2_run")(shmt, apply(cmd), msg) |
510 | | - else |
511 | | - local msg |
512 | | - cmd, msg = get_repr_fn(shmt, "single_stdin")(shmt, cmd, #input > 0 and input or nil, |
513 | | - #codes > 0 and codes or nil) |
514 | | - t = get_repr_fn(shmt, "pre_5_2_run")(shmt, apply(cmd), msg) |
515 | | - end |
| 523 | + local msg |
| 524 | + cmd, msg = get_repr_fn(shmt, "single_stdin")(shmt, cmd, #input > 0 and input or nil, |
| 525 | + #codes > 0 and codes or nil) |
| 526 | + t = get_repr_fn(shmt, "run_cmd")(shmt, apply(cmd), msg) |
516 | 527 | if shmt.assert_zero and t.__exitcode ~= 0 then |
517 | 528 | error("Command " .. tostring(cmd) .. " exited with non-zero status: " .. tostring(t.__exitcode)) |
518 | 529 | end |
|
0 commit comments