shapi

shapi
Login

shapi, or shell API, is a Lua module which implements some kind of eDSL1 to work with the shell/CLI2 environment. It depends on luaposix.

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

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.

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 descriptor3.

__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 descriptor3.

__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 descriptor3.

Example: Discard stderr

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.

<shell-process>(...)

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

__lua(fproc, ...)

Chain a Lua function (create a new process).

Example: Implementation of __str_in

-- __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):

__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.

__do()

Do/end the command (outputs to stdout).

It waits on the command processes and propagates exit errors.

__(f, ...)

Chain custom method.

Example: Abstraction of multiple steps

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"))

  1. ^ Embedded Domain Specific Language
  2. ^ Command-line interface
  3. ^ a b c A file descriptor of the current process, the one constructing the command.