Shell Library-Function Standard – SHELF
Table of Contents
1 Scope
This document is a draft for a Shell Library-Function Standard, a SHELF, for easy recall. As such it sets a practice for organizing shell functions into re-usable libraries. It introduces standards for a library, and for functions in the library. A library may contain one or more families, the organizing principal for functions.
A section of the standard suggests steps for verifying conformance.
In an attempt to keep the standard concise, here is the SHELF Rationale and Practice.
1.1 What's it about
The standard offers:
- conventions for organizing, collecting and re-using shell functions
- naming libraries and functions according to collections
- coding conventions within a function
It offers strong suggestions pointing to specific function libraries supporting a number of areas in the library-function practice. The ubiquity of the bash shell makes it the implementation choice.
At the moment, these function families are featured as supporting the standard:
- om – the object-model, or object-method for naming functions
- report – or assert for verifying function arguments
- shdoc – a subset, the Shell DOCumentation standard, after JavaDoc, etc.
- trace – function execution tracing, and
- util – a few programming functions, .e.g. foreach
This document has been adapted from the shdoc user guide, and puts that function family as a companion of all those referenced here.
1.2 What it's not about
The shell library-function standard has nothing to say about:
The practice from which the standard has been derived suggests composing a script is a small after-thought of the design process. With standard libraries, an application may first appear as a function. These may be turned in to a stand-alone application, cron-job or script.
1.3 About requirements
Since this is a draft standard, requirements are not put forward in 'requirement-speak'. It should be clear from the tense of the verbs how strong a requirement is. The purpose of the requirements and recommendations should become clear on reading.
The requirements are organized first for Libraries, then Families, and then for the Functions in a library.
2 Libraries
A library:
- is named {something}lib, without a suffix. e.g.
setpathlib
- is 'source'd by the shell. e.g.
source setpathlib # or . setpathlib
with the strong implication it is found on the PATH
- when 'source'd leaves nothing on stdout
- is not an application. It may have multiple functions used principally from the command line.
- must have an _init function, conventionally named for its
basename. e.g. setpathlib has a function
setpath_init
- must have no more than one directly executable statement, calling
the initialization function, which certainly causes other execution.
setpath_init 1>&2
Here, the re-direction is to comply with the earlier requirement.
- may have multiple families in the library, each of which may have its own _init function
3 Families
A family is a group of functions sharing a common first component, before the first underscore in a name:
family_subfunction
is the name of a function in the named family.
This standard specifies certain required behavior for sub-functions:
- help – may write any useful instructions on stdout
- init – mandatory behavior calls om_iam to identify the family, and
any other necessary features when the family library is
sourced
- list – returns a list of the family function names.
4 Functions
A function included in a SHELF library:
- has two or more characters in an alpha-numeric name, which matches
the regular expression:
[a-zA-Z][a-zA-Z0-9_]+
- has a preference for a family group, e.g. {family}_{subfunction}
such as
setpath_init
. (see the om, object and methods family of functions) - is formatted in the canonical format:
declare -f fun_method
since ordinary shell "#" comments are lost to this format, an alternate comment format is available (see the shdoc function).
- should test any assertions capable of begin made on it's arguments
(see the reporting functions). At the current moment, there are
these two alternatives:
assert_isfile $1 || return 1 # is the first arg a file?, OR report_notfile $1 && return 1 # the current practice
- is encouraged to make liberal use of positional parameters, and the
set facility. e.g. where a conventional use of file suffixes is
at the heart of the process, rather than this:
call_me file.txt. file.out file.err
use this instead:
call_me file # or call_me file.txt # and therefore be defined as: ... call_me () { set ${1%.*} # strip any suffix, or not! set $1.txt $1.out $1.err # $1, $2, and $3 are as before. ...
- should trace its entry:
- after positional parameters are set, and
- after assertion checking is complete.
which may occur interchangeably. For example, a reliable first assertion is on the number of arguments:
report_notargcount 1 $# No file or basename && return 1
might be used as the first assertion in a function.
- should limit control structures to one level. (see foreach in the collection of utilities).
5 Verification
A set of not-too-automated functions and procedures may be supplied here used to verify a library's conformance to this standard.
5.1 test points
5.2 demonstrating failure
Since a good test is one which has a high probability of detecting an otherwise undetected error. A successful test is one which does. – Glenford Myers, The Art of Software Testing
6 References
- the standard, online: http://mcgowans.org/marty3/commonplace/software/shelf.html
- my Commonplace Book
- the SHELF Rationale and Practice.
Search for:
Email: mcgowan@alum.mit.edu
Twitter: @applemcg