onBuildinganApp

Table of Contents

The other papers

1 intro

  1. Building an app

    The challenge in building an application around a library is rounding up the functions the library uses from other libraries.

    Today, Saturday 4/5/14, I discovered the key to the resources in Learning the bash Shell , by Newham and Rosenblatt, they show the value of the type builtin:

    $ type -f command
    

    where command may be a file, function, built-in, alias,/ or /keyword.

    So, given a list of tokens used in a function (or script), only focus on those "commands" which don't return a result or return a the function result. I use this command to identify the candidates:

    fun_type       () { 
        tpl ${1:-$(which programlib)} |
           sed 's/;$//; s/^$(//' | sort -u |
               grep '^[a-z][0-9A-Za-z_][0-9A-Za-z_]*$'
    }
    alltype () 
    { 
        function _alltype () 
        { 
            echo $(type -t $1) $1
        };
        foreach _alltype $* | sort -u
    }
    $ alltype $(fun_type nameLIB)
    
  2. The types from the command

    I use the command (or builtin, in its own parlance) type to determine where the command is defined. A command is either an alias, builtin, file, function,* or *keyword. I've added the class loner to the list, for those candidate words which are none of the above. The command

    $ type -t {candidate}
    

    returns two words, usually one of the standard five types, or nothing at all. The function alltype returns the type and the name of the candidate. So a series of candidate names returns either one or two names. Those returning only the candidate are what I call /loner/s.

    And, when wrapping up a library into an *app*lication, the dependent functions need to be collected and added to a separate shell library, which depends on no other function libraries. So, of the five types, the only one of interest is the function type, since the file, builtin, and keyword are presumably available on any conforming system, and, noting McGowan's Alternate Shell Maxim: What purpose an alias when you are using functions? i.e. I have yet to find a use for an alias that a function doesn't better serve.

    In the tools I use to distinguish the /type/s, I recognize two of my programming facilities:

    • I use a semantic comment, which is called comment; those are removed,

2 I use function names

e.g. programlib\doc, to supply a text-formatted bit of documentation, other than a MANual page or Quick Reference Form; such function's tokens are exempt from consideration.

> So, we are looking to identify the list of functions used in a function library which are not defined in the function library, but elsewhere.

  1. The funtype function.

    This function: fun\type is the workhorse. In a few crucial places, it defaults to searching my cmdlib, which isn't a particularly useful choice, since it, along with programlib is meant to be at the bottom of the pile. I've yet to sort out which is which; the decision rests on distinguishing use only on the command line, and more likely used in another function library.

    Also, function is the default type, as just explained above. Three internal functions: /fun/typeN, where N = , handle zero, one, or two respectively. Calling funtype with more than two arguments, or not using either a command type nor a function library, displays the help message.

    With no arguments, funtype defaults to the function type and the cmdlib function library.

    With one argument, e.g.

    $ fun_type type         # unlikely, but a good test, OR more likely
    $ fun_type {libname}   
    

    the built-in function tests to see if the argument is a type, in which case, the default library is the cmdlib, or alternatively uses the default function type on the named library. This latter is the most likely use.

    With two arguments, the function expects a legitimate type, or the special loner followed by a function library name. Notice, the built-in function \/fun\/type1 does the path lookup for the library name, saving the user from having to do that or remember the location.

    Notice, the main function only defines the separate local functions including the help message. The working functions are entered by the argument vector:

    _fun_type$#
    

    i.e. with no arguments, call \/fun\/type0. The actual argument vector: $* maybe superfluous, but not harmful, nor incorrect.

    fun_type () 
    { 
        function _fun_type_help () 
        { 
            comment USAGE fun_type [[type, file] file];
            comment where type is [function], alias, builtin, file, keyword, loner
        };
        function _fun_type0 () 
        { 
            trace_call $*;
            _fun_type2 function $(which cmdlib)
        };
        function _fun_type1 () 
        { 
            trace_call $*;
            set -- $1 $(which $(basename $1));
            case $1 in 
                alias | builtin | file | function | keyword | loner)
                    _fun_type2 $1 $(which cmdlib)
                ;;
                *)
                    [[ -f $2 ]] && _fun_type2 function $2 || _fun_type_help
                ;;
            esac
        };
        function _fun_type2 () 
        { 
            trace_call $*;
            case $1 in 
                loner)
                    alltype $(fun_list $2) | awk "NF < 1"
                ;;
                *)
                    alltype $(fun_list $2) | awk "\$1 ~ /$1/ { print \$2 }"
                ;;
            esac
        };
        trace_call $*;
        case $# in 
            0 | 1 | 2)
                _fun_type$# $*
            ;;
            *)
                _fun_type_help
            ;;
        esac
    }
    
  2. Routine usage

    The funneed function identies the functions a library uses from outside it's list of functions. Since funtype, with one library name argument produces the list of all functions, then the set-subtraction of comm -23 leaves just this list found by funtype, not in common with the list of functions in the library.

    fun_need () 
    { 
        set -- ${1:-cmdlib};
        comm -23 <(fun_type $1) <(functions $(which $1) | sort)
    }
    

    Armed with that list, it's appropriate to go on a search for their definitions:

    $ foreach dowhf $(fun_need bkplib)
    

    Where the whf functions:

    whf () { grep "^$1[         ][      ]*()" $(funclocn) | sed 's/ .*//; s/:.*//'; }
    dowhf       () { echo $1 $(whf $1); }
    

    And funclocn returns a list of function libraries found on the PATH.

  3. The first application

    How about a challenge? How about using funtype to sort out the functions in cmdlib which use other functions, and move them to programlib? The one exception I'd allow is their use of tracecall. Time for an exploration.

    The first factor we'll need to make is allow the input on stdin or a user-defined function list.

Author: Marty

Created: 2016-02-20 Sat 15:49

Emacs 24.4.1 (Org mode 8.2.10)

Validate