AGENTS.md, add coding conventions and layout logistics including code snippets and example programs.

This commit is contained in:
me committed 2026-11-04 08:48:26 -07:00
1 parent d0970f5971
commit 7f986e51d3
1 file changed
+184
@@ -306,6 +306,190 @@
# Run all tests
./gradlew allTests
```
# Coding Conventions
Preferences related to how code should be written.
## All languages
If a value is going to be used more than once, even a small path or file
name, it should exist in a variable.
Relative shebangs such as `#!/usr/bin/env bash` and `#!/usr/bin/env node`
are always preferred over static shebangs such as `#!/bin/bash`, since
scripts are run across a multitude of different systems.
### Layout
Programs should be laid out in 5 sections.
- Variables
- Instantiate global variables and defaults used for parameters which
do not get passed an explicit value by the user.
- Functions
- Functions to be used throughout the program, including the Usage.
- Parameters / Validation
- Parse the parameters, validate the input, and assign any defaults.
- Main
- The primary logic of the program, completes the task at hand.
- Finish / Cleanup
- Typically just `exit 0`, but sometimes a summary of what was done.
All sections may not always apply, such as with Hugo websites. With
projects like Android apps this would apply to each individual function,
method, and class. If a section does not need anything, it can be blank.
```
public static void doThing(String thingName) {
// Variables //
String thingPrefix = "/place/for/thing/"
// Functions //
// Parameters //
if (thingName.isEmpty) {
Exception e = new Exception("No name passed!");
throw e;
}
// Main //
runStuff(thingPrefix + thingName);
// Finish //
}
```
The comments do not need to be included, this example is just as valid,
what maytters most is that the 5 section are done in order rather than
instantiating variable mid-scope.
```
public static void doThing(String thingName) {
String thingPrefix = "/place/for/thing/"
if (thingName.isEmpty) {
Exception e = new Exception("No name passed!");
throw e;
}
runStuff(thingPrefix + thingName);
}
```
`if` statements and loops start new scope, so they also need the layout
applied to them. Loops may sometimes require a variable assignment before
it begins which is completely okay and does not break the layout rule.
This example has a Variables, Validation, Main, and Finish section without
the use of labels or comments since the code itself is simple and small.
```
count=0
array="cats dogs giraffes rhinos horses"
last_animal=""
for animal in $array; do
if (( count >= 3 )); then
echo "That's enough! We finished at the ${last_animal}."
break;
fi
echo "We're looking at ${animal}."
last_animal=$animal
(( count++ ))
done
```
Providing the user's input in error messages is really helpful and can aid
their troubleshooting if things are not going according to expectations.
Example using Bash:
```
#!/usr/bin/env bash
### Variables ###
declare A B
typeset -i a b
### Functions ###
function usage() {
status="$1"
cat << EOF
Usage: add.sh -a NUM -b NUM [-h]
Adds two numbers and prints out the full equation.
Example:
$ add.sh -a 5 -b 25
5 + 25 = 30
EOF
exit $status
}
function add() {
num1="$1"
num2="$2"
sum=""
if [[ -z $num1 || -z $num2 ]]; then
echo "ERROR: Two numnbers must be passed."
fi
sum=$(( num1 + num2 ))
echo "${num1} + ${num2} = ${sum}"
}
### Parameters ###
while getopts ':a:b:h' opt; do
case $opt in
a) A="$OPTARG" ;;
b) B="$OPTARG" ;;
h) usage 0 ;;
*) echo "ERROR: Option $OPTARG not recognized." >&2 && usage 1 ;;
esac
done
if [[ -z "$A" || -z "$B" ]]; then
echo "ERROR: Both numbers need to be passed. A=${A} B=${B}" >&2
usage 2
fi
a="$A" b="$B"
if [[ "$a" != "$A" || "$b" != "$B" ]]; then
echo "ERROR: Values contain non-numeric data, please try again." >&2
echo "A=${A} B=${B}" >&2
usage 3
fi
### Main ###
add "$a" "$b"
### Finish ###
unset A B usage add
exit 0
```
## Bash
`[[ ]]` are preferred over `[ ]`, `test`, etc. `(( ))` are always fine.
When defining a function please use both the keyword `function` as well as
the `()`, such as `function myfunc() {}`.
When instantiating global variables, please use `typeset` or `declare`
rather than just `VAR1=""; VAR2=""`, such as:
```
declare VAR1="" VAR2="" BOOL="true" BOOL2="false"
typeset -i INT1=0 INT2=99
```
When doing colored output, `tput` is always preferred over literal values.
backup: false
owner: "{{ user }}"
group: "{{ user }}"