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:

  • shell scripts, and the usually unnecessary sh-bang feature
  • cron jobs, stand-alone operation

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:

  1. is named {something}lib, without a suffix. e.g. setpathlib
  2. is 'source'd by the shell. e.g.
    source setpathlib  # or
    . setpathlib
    

    with the strong implication it is found on the PATH

  3. when 'source'd leaves nothing on stdout
  4. is not an application. It may have multiple functions used principally from the command line.
  5. must have an _init function, conventionally named for its basename. e.g. setpathlib has a function setpath_init
  6. 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.

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

  1. has two or more characters in an alpha-numeric name, which matches the regular expression:
    [a-zA-Z][a-zA-Z0-9_]+
    
  2. has a preference for a family group, e.g. {family}_{subfunction} such as setpath_init. (see the om, object and methods family of functions)
  3. 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).

  4. 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
    
  5. 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.
    ...
    
  6. 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.

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

Search for:

Email: mcgowan@alum.mit.edu

Twitter: @applemcg

Author: Marty McGowan

Created: 2016-06-08 Wed 17:45

Emacs 24.4.1 (Org mode 8.2.10)

Validate