blob: 083b7a26e6b76681e7d4b3079991b33c63930c0c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
# Bash Function Patterns
## Function Naming and Namespacing
- Prefer the POSIX-compatible form: `name() { ... }`
- Emulate namespaces with `::`, e.g. `pkg::lang::action`.
- Use `FUNCNAME[0]` for self-aware logging.
```bash
log() {
local -r callee=${FUNCNAME[1]}
echo "$callee: $*" >&2
}
```
## Private / Internal Functions
Mark internal helpers with a leading underscore so the public API is obvious: `module::_helper`. This matches the convention used by many Bash projects.
```bash
# Public
foo::generate () { ... }
# Internal only
foo::_sort_entries () { ... }
```
## Function Arguments: Assign-then-Shift
Assign function arguments to named `local` variables immediately using `$1`, then `shift`. This makes adding and removing arguments easy without renumbering.
```bash
some_function () {
local -r param_foo="$1"; shift
local -r param_bar="$1"; shift
local -r param_baz="$1"; shift
}
```
## Scope and Functions
- Functions declared inside other functions are global once defined.
- `export -f function_name` makes a function available in subshells (e.g. `xargs -P`).
- `local` variables have dynamic scope: they are visible down the call stack.
## Chaining Conditionals
Functions return exit statuses and can be chained in conditionals.
```bash
if deploy_check || smoke_test; then
echo "All good."
else
echo "Something failed." >&2
fi
```
## `case` for Multi-Branch String Dispatch
Replace long `if/elif` chains with `case ... esac` when matching literal string patterns. It is more readable, avoids quoting pitfalls, and performs exact matching.
```bash
case "$line" in
'* ')
html::make_list_item "$line"
;;
'# '*)
html::make_heading "$line" 1
;;
'## '*)
html::make_heading "$line" 2
;;
*)
html::make_paragraph "$line"
;;
esac
```
|