AGENTS.md, add coding conventions and layout logistics including code snippets and example programs.
This commit is contained in:
1 parent
d0970f5971
commit
7f986e51d3
1 file changed
+184
@@ -306,6 +306,190 @@
|
|||||||
# Run all tests
|
# Run all tests
|
||||||
./gradlew allTests
|
./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
|
backup: false
|
||||||
owner: "{{ user }}"
|
owner: "{{ user }}"
|
||||||
group: "{{ user }}"
|
group: "{{ user }}"
|
||||||
|
|||||||
Reference in new issue
Block a user