shapi

Artifact [de846e257a]
Login

Artifact de846e257aee7da6a94c68eff9cbf6da5e6dee6141b5e3e1492c83a9cc248e37:


# shapi

`shapi`, or **sh**ell **API**, is a Lua module which implements some kind of
eDSL[^1] to work with the shell/CLI[^2] environment. It depends on
[luaposix](https://github.com/luaposix/luaposix).

[^1]: Embedded Domain Specific Language
[^2]: Command-line interface

The incentive is to have an alternative to a shell language like **bash**, as an
API.  
E.g. for scripting purposes, if one already uses Lua at the heart of its
methodology, or to be embedded into an existing application.

## Overview

```lua
local sh = require "shapi"

print("HEAD: "..sh:git("rev-parse", "HEAD"))

print(sh:__in("foo/bar.txt"):md5sum())

sh:__p("my-command", "--foo", "bar"):__out("foo/bar.txt")()

sh:sleep(2):__return()
sh:sleep(2)()
```

## Install

See `src/`, `rockspecs/` or
[luarocks](https://luarocks.org/modules/imagicthecat-0a6b669a3a/shapi).

## API

A command object is created and then chain methods are applied to it. This
chaining pattern is similar to **bash** pipes, making `:` behave like `|`. For
most methods, it means linking **stdout** from the previous step to **stdin** of
the next one while keeping **stderr** of the parent process (unless `__err` is
used).

Methods will directly spawn sub-processes as they are called, there is no build
phase of the command.

Special methods start with `__` and other strings will be interpreted as shell
process names.

Calling on the command object is an alias to `__return(...)`. String conversion
and concatenation will call `__return()`.

**Note:** The chain starts from the module, the first method is called on it,
but the `self` parameter will be replaced with the command object.

### __str_in(data)

Input raw string data into the chain (create a new process).

### __in(file, [mode])

Input a file into the chain.

If `file` is a string, `file, [mode]` is the path and mode for `io.open()`. The
`mode` defaults to `rb`.

If `file` is a number, it indicates a file descriptor[^fd].

[^fd]: A file descriptor of the current process, the one constructing the
    command.

### __out(file, [mode])

Output the chain to a file (create a new process).

If `file` is a string, `file, [mode]` is the path and mode for `io.open()`. The
`mode` defaults to `wb`.

If `file` is a number, it indicates a file descriptor[^fd].

### __err(file, [mode])

Setup **stderr** for subsequent processes of the chain.

If `file` is a string, `file, [mode]` is the path and mode for `io.open()`. The
`mode` defaults to `wb`.

If `file` is a number, it indicates a file descriptor[^fd].

Example: Discard **stderr**

```lua
local cmd = sh:__err("/dev/null"):cat("foo/missing.txt")
local ok, out = pcall(cmd)
```

### __p(name, ...)

Chain a shell process.

Can be used to chain a shell process with a name which cannot be represented
with a Lua name/identifier.

- name: shell process name/path (see luaposix **execp**)
- ...: process arguments

### \<shell-process>(...)

Alias for `__p(<shell-process>, ...)`.

### __lua(fproc, ...)

Chain a Lua function (create a new process).

- fproc: Lua function
- ...: function arguments

Example: Implementation of `__str_in`

```lua
-- __str_in is equivalent to:
sh:__lua(function() assert(io.stdout:write(data)) end)
```

### __wait()

Wait/end the command.

It waits on the command processes and returns the command internal state.

state (table):

- output: unprocessed final output (stdout), string
- children: list of children `{}` (follows the chain order)
  - pid
  - kind: `"exited"`, `"killed"` or `"stopped"`
  - status: exit status, or signal number responsible for `"killed"` or
    `"stopped"`

### __return([mode])

Return/end the command.

It waits on the command processes, propagates exit errors or returns the final
output (stdout) as a string.

By default, trailing new lines are removed, but this can be disabled using the
mode parameter.

- mode: string, `"binary"` to prevent processing of the output

### __do()

Do/end the command (outputs to stdout).

It waits on the command processes and propagates exit errors.

### __(f, ...)

Chain custom method.

- f(self, ...): method
- ...: method arguments

Example: Abstraction of multiple steps

```lua
local function my_md5sum(self, file)
  return self:md5sum(file):cut("-d", " ", "-f", 1)
end

print(sh:__in("foo/bar.txt"):__(my_md5sum))
print(sh:__(my_md5sum, "foo/bar.txt"))
```