1- < img src = " assets/logo.png " />
1+ ![ Executing the hello command ] ( assets/logo.png )
22
3- # shkeleton - Bash Script Library
3+ # skeleton: bash - Bash Script Framework
4+
5+ ** skeleton: bash ** is a small, declarative framework that aims at providing the look-and-feel of
6+ any other * nix tool you and your users are used to.
7+ It offers a convenient way to structure and organize your bash scripts and assists
8+ you in writing versatile and easy-to-use programs.
49
5- ** shkeleton** is a library that provides a convenient way to structure and
6- organize your bash scripts and assists you in writing versatile and easy-to-use programs.
710Whats most important: it generates usage information for you and your scripts users.
811
912## Features
1013
11- ** shkeleton ** makes it easy to
12- - [ parse flag and argument options] ( #parsing-options )
14+ ** skeleton : bash ** makes it easy to
15+ - [ parse and validate flag and parameter options] ( #parsing-options )
1316- generate extensive usage information
14- - write scripts with different commands
15- - setup and cleanup the environment
17+ - [ write scripts with different sub commands] ( #adding-commands-and-subcommands )
18+ - [ setup and cleanup the environment] ( #helper-functions )
1619- [ debug and trace your script] ( #debugging-and-tracing )
1720
1821In addition to that, it offers functions to [ colorize output and emit error messages] ( #helper-functions ) .
1922
20- ## Minimal Example
21- Suppose this executable (chmod +x) ` minimal- example.sh` :
23+ ## Examples
24+ Suppose this executable (chmod +x) ` example.sh ` :
2225
2326``` bash
24- #! /bin/bash
27+ #! /usr/ bin/env bash
2528
26- app_version=" 1.0.0"
27- app_description=" Example shkeleton Script"
29+ source skeleton.sh
2830
29- source shkeleton.sh
31+ function @greet() {
32+ description " Displays a greeting"
33+ param " name" " n" " name" " greets <name> instead of the current user" ; name=" $param "
3034
31- function setup() {
32- cmd " hello" " hello_world" " Displays 'hello world'"
35+ execute () {
36+ echo " Hello ${name:- $(whoami)} "
37+ }
3338}
39+ ```
3440
35- function hello_world() {
36- arg " n" " name" " string" " Greets <name> instead of 'world'"
37- name=${arg:- world}
41+ ** Executing the greet command**
3842
39- if $flag_help ; then
40- printf " Displays the message 'hello world'.\n\n"
41- print_usage && exit 0; # Print usage and exit
42- fi
43-
44- debug " Debug log message"
45-
46- echo " hello ${name} " | green
43+ The ** greet** command will receive the parameter ` name|n ` and also shows them when
44+ running ` ./example.sh greet --help ` .
45+
46+ ![ Executing the greet command] ( assets/example-1.gif )
47+
48+ Also, the ** greet** command is listed in the global help page:
49+
50+ ![ Showing the script help] ( assets/example-2.png )
51+
52+ Instead of using named parameters, your commands can also be configured to receive
53+ arguments:
54+
55+ ``` bash
56+ function @greet() {
57+ description " Displays a greeting"
58+ args " NAME"
59+
60+ execute () {
61+ echo " Hello ${1} "
62+ }
63+
64+ help () {
65+ echo " Greets the given NAME"
66+ }
4767}
4868```
4969
50- ** Executing the hello command**
70+ Since we added the ` help ` function, a help message other than the default description
71+ tells the user that he can provide the ** NAME** argument.
72+
73+ ![ Using options] ( assets/example-3.png )
74+
75+ ## Adding Commands and Subcommands
76+
77+ Every ` @function ` will be added as a command to your script. The script will fail, if
78+ you don't provide a description. Nesting commands is a matter of renaming the command:
79+
80+ ``` bash
81+ function @books() {
82+ description " Book Management"
83+ }
5184
52- ![ Executing the hello command] ( assets/example-1.gif )
85+ function @books-list() {
86+ command " books list"
87+ description " Lists books"
5388
54- ** Showing the hello help**
89+ execute () {
90+ :
91+ }
92+ }
5593
56- ![ Showing the hello help] ( assets/example-2.png )
94+ function @books-create() {
95+ command " books create"
96+ description " Creates a book"
5797
58- ** Showing the script help**
98+ execute () {
99+ :
100+ }
101+ }
102+ ```
59103
60- ![ Showing the script help ] ( assets/example-3 .png )
104+ ![ Adding subcommands ] ( assets/example-4 .png )
61105
62106## Parsing Options
63107
64- Defining options is pretty easy in ** shkeleton ** :
108+ Defining options is pretty straightforward in ** skeleton : bash ** :
65109``` bash
66- flag " s" " silent" " silences output"
67- local silent=$flag # true if either -s or --silent is present, false otherwise
110+ function @command {
111+ flag " s" " silent" " silences output"
112+ declare silent=$flag # true if either -s or --silent is present, false otherwise
113+
114+ flag " v" " increases verbosity"
115+ declare verbose=$flag # only true, when -v is set; short and long args are interchangeable
116+
117+ param " n" " name" " string" " sets the name"
118+ declare name=${param:- default} # the value of -n or --name or just 'default'
119+ # multiple values may be read with ${param[*]} or ${param[@]}
120+
121+ param " max-age" " integer" " sets max-age"
122+ local max_age=${arg:- } # the value of --max-age if present
68123
69- flag " v" " increases verbosity"
70- local verbose=$flag # only true, when -v is set; short and long args are interchangeable
124+ # ...
125+ }
126+ ```
71127
72- arg " n " " name " " string " " sets the name "
73- local name= ${arg :- default} # the value of -n or --name or just 'default'
128+ Short options can be passed with the shorthand syntax ` -abc ` . If you provide an
129+ option, that is not declared in your command an error message will be shown:
74130
75- arg " max-age" " integer" " sets max-age"
76- local max_age=${arg:- } # the value of --max-age if present
77- ````
131+ ![ Unknown options error] ( assets/example-5.png )
78132
79- The global variables ` $flag ` and ` $arg ` will hold the value directly after the
133+ The global variables ` $flag ` and ` $param ` will hold the value directly after the
80134respective registering function has been called.
81135
82- Options from the ` setup` functions are treated as global flags and should therefore
83- be written to global variables (just like ` $flag_help ` ), whereas options from
84- command functions should be saved as local variables like shown in the example above.
85-
86- * Notice* : Options should be stated at the top of the command function,
87- so that ` print_usage` shows them.
136+ Options from command functions should be saved as global variables to remain usable
137+ for the ` execute ` function like shown in the example above.
88138
89139## Commands and special Functions
90140
91- The ` cmd` command will add a named command, maps it to the given function and adds it
92- to the usage page. Commands should be defined in the ` setup` function.
93- The ` version` command is added per default.
94-
95- There are a few special script workflow functions:
141+ There are a few special functions:
96142
97143| Function| Description|
98144| ---| ---|
99- | ` setup` | Bootstraps the script and adds commands and global flags |
100- | ` teardown` | (Optional) Will be called when the script exits|
101- | ` main` | (Optional) Will be called instead of usage page when script is being called without command |
145+ | ` setup ` | Bootstraps the script, can be used to define global options |
146+ | ` teardown ` | Will be called when the script exits|
147+ | ` main ` | Will be called instead of usage page when script is being called without command |
102148
103- Also, there are internal versions of these functions (` _setup` , ` _teardown` and ` _main` ),
104- that can be extended when using ** shkeleton** as a library and common logic applies to all
105- your programs.
149+ * Notice* : When using the ` teardown ` function, it is necessary to call ` __main ` at the bottom
150+ of your script!
106151
107152### Helper Functions
108153
109154| Function| Description|
110155| ---| ---|
111- | ` error` | Emits red error messages to stderr along with its root and exits |
156+ | ` error ` | Emits red error messages to stderr along with its origin function name |
112157| ` debug ` | Logs an orange/brown debug message|
113158| ` colorize ` | Colorizes output; can also be used as pipe|
114159| ` red ` , ` green ` , ` blue ` , ...| * see above* |
115- | ` print_usage` | Prints usage information, should be called only after all options are set|
116160| ` has_flag ` | Sets ` $flag ` to ` true ` when the flag option exists, false otherwise|
117- | ` get_arg` | Sets ` $arg ` to the argument options value if present|
161+ | ` get_param ` | Sets ` $param ` to the param values if present|
162+ | ` array_contains ` | Returns ` true ` if the array ` $2 ` contains ` $1 ` |
118163
119164## Debugging and Tracing
120165
@@ -127,9 +172,15 @@ Since debugging of bash script can be pretty hard, you can also enable tracing b
127172supplying the ` TRACE ` parameter just like the debug parameter, which will enable
128173tracing as soon as the script enters your command.
129174
130- # # TODO
175+ ``` bash
176+ function @hello() {
177+ description " Hello world"
178+
179+ execute () {
180+ debug " Command @hello started"
181+ echo " Hello world"
182+ }
183+ }
184+ ```
131185
132- - parse concatenated flag arguments (` $ ./script -qts` )
133- - validate unknown options
134- - use associative arrays
135- - parse multiline input from stdin in ` colorize`
186+ ![ Debugging and tracing] ( assets/example-6.png )
0 commit comments