Bash generate DOC
⏳ Doba čtení: ~15 min (1954 slov)Odkaz na github
Script umožnuje generovat dokumentaci z bash skriptů. Využívá komentáře a strukturu kódu pro extrakci informací o funkcích, jejich argumentech, návratových hodnotách a popisech.
Dokumentační komentáře by měly být umístěny přímo nad deklarací funkce a měly by začínat znakem #. První řádek komentáře by měl obsahovat stručný popis funkce, zatímco další řádky mohou obsahovat podrobnější informace.
Argumenty funkce jsou extrahovány z komentáře, který by měl být ve formátu # function_name(arg1, arg2) > return_value, na konci řádku deklarace hlavičky funkce. Návratová hodnota je volitelná a může být uvedena za znakem >.
#!/bin/bash
# By Pytel
# Description:
# Script for generating documentation out of bash scripts.
# colors
source ../tools/colors.sh > /dev/null
source IO_prints.shlib
# Help print
function printHelp () {
echo -e "USE:"
echo -e " $(echo "$0" | tr "/" "\n" | tail -n 1) -f FILE"
echo ""
echo -e "FILE:"
echo -e " path to the file"
echo -e "COMMANDS:"
echo -e " -h, --help \t\t print this text"
echo -e " -d, --debug\t\t enable debug output"
echo -e " -v, --verbose\t\t increase verbosity"
echo -e " -f, --file FILE\t set file"
}
# find all functions in a file
function find_functions () { # ( file )
local file=$1
# check if argument is set
if [ -z $file ]; then
printErrorAndExit "No file specified."
fi
# check if file exists
if [ ! -f $file ]; then
printErrorAndExit "File ${Blue}$file${NC} does not exist."
fi
local functions=$(cat $file | grep "^function " | cut -d " " -f 2)
echo $functions
}
# find arguments of a function
function find_arguments () { # ( file function ) -> arguments
local file=$1
local function=$2
local function_header=$(cat $file | grep "function $function")
local comment=$(echo $function_header | cut -d "#" -f 2)
local arguments=$(echo $comment | cut -d "(" -f 2 | cut -d ")" -f 1)
echo $arguments
}
# find return of a function
function find_return () { # ( file function ) -> return
local file=$1
local function=$2
local function_header=$(cat $file | grep "function $function")
local comment=$(echo $function_header | cut -d "#" -f 2)
local return=""
# test is ">" in comment
if [ $(echo $comment | grep ">" | wc -l) -eq 0 ]; then
return=""
else
return=$(echo $comment | cut -d ">" -f 2-)
fi
echo $return
}
# print function lines
function print_function_lines () { # ( file function ) -> code
local file=$1
local function=$2
local len=$(cat $file | wc -l)
local start=$(cat -n $file | grep "function $function" | tr "\t" " " | tr -s " " | cut -d " " -f 2)
local func_len=$(sed -n ${start},${len}p $file | grep -n "^}" | head -n 1 | cut -d ":" -f 1)
local index_of_last_line=$(( $start + $func_len ))
local end=$(( $index_of_last_line - 1 ))
if $DEBUG; then
echo -e "start: $start"
echo -e "func_len: $func_len"
echo -e "index_of_last_line: $index_of_last_line"
echo -e "end: $end"
fi
code=$(sed -n ${start},${end}p $file)
echo -e "$code"
}
# print description
function print_description () { # ( file ) -> description
local file=$1
local line=""
local line_with_description=$(cat $file | grep -n "^#" | grep "Description:" | head -n 1 | cut -d ":" -f 1)
if [ ! -z $line_with_description ]; then
echo -e "## Description: "
while true; do
line_with_description=$(( $line_with_description + 1 ))
line=$(sed -n ${line_with_description}p $file) # get line
if [[ $line == \#* ]]; then # if line starts with #
echo -e "${line:1}" # print line without #
else
break
fi
done
echo ""
fi
}
# print function description
function print_function_description () { # ( file function ) -> description
local file=$1
local function=$2
local line=""
local line_with_declaration=$(cat $file | grep -n "function $function" | head -n 1 | cut -d ":" -f 1)
local line_with_description=$line_with_declaration
while true; do
line_with_description=$(( $line_with_description - 1 ))
line=$(sed -n ${line_with_description}p $file)
if [[ $line != \#* ]]; then
break
fi
done
start=$(( $line_with_description + 1 ))
end=$(( $line_with_declaration - 1 ))
if $DEBUG; then
echo -e "line_with_description: $start"
echo -e "line_with_declaration: $end"
fi
comment=$(sed -n ${start},${end}p $file)
comment=$(echo -e "$comment" | sed 's/^# //')
echo -e "$comment"
}
# print help
function print_help () { # ( file ) -> help
local file=$1
local text=""
local functions=$(find_functions $file)
local help_exists=$(echo $functions | tr " " "\n" | grep $HELP_FUNCTION | wc -l)
if [[ $help_exists -eq 1 ]]; then
text=$(./$file -h)
echo -e "## Help: "
echo '```bash'
echo -e "$text"
echo '```'
fi
echo ""
}
# print the function documentation:
# - Description,
# - Arguments,
# - Return.
function print_function_doc () { # ( file function ) -> doc
local file=$1
local function=$2
echo -e "### $function()"
echo -e "\n> [!info] \n> Description:"
local description=$(print_function_description $file $function)
echo -e "$description" | sed 's/^/> /'
echo -e "\nArguments: "
local arguments=$(find_arguments $file $function)
if [ -z "${arguments}" ]; then
echo -e " - No arguments."
else
for argument in $arguments; do
echo -e " - \`${argument}\`"
done
fi
echo -e "\nReturn: "
local return=$(find_return $file $function)
if [ -z "${return}" ]; then
echo -e " - No return."
else
echo -e " - \`${return}\`"
fi
echo ""
}
# set file
function setFile () { # ( file ) -> bool
file=$1
if [ ! -f $file ]; then
printErrorAndExit "File ${Blue}$file${NC} does not exist." 1
fi
return 0
}
# main
file="generate_doc.sh"
HELP_FUNCTION="printHelp"
#DEBUG=true
DEBUG=false
# input args
case $# in
0) printHelp; exit 2;;
*) arg=$1;;
esac
# parse input
while [ $# -gt 0 ] ; do
$DEBUG && echo "Arg: $arg remain: $#"
# vyhodnoceni
case $arg in
-h | --help) printHelp; exit 2;;
-d | --debug) DEBUG=true;;
-v | --verbose) VERBOSE=true;;
-f | --file) shift; setFile "$1" || exit 3;;
*) echo -e "Unknown parametr: $arg"; exit 1;;
esac
# next arg
shift
arg=$1
done
# file name
echo -e "# File: $file"
echo ""
# get description
print_description $file
# if printHelp exists
print_help $file
echo -e "## Functions: "
echo ""
functions=$(find_functions $file)
for function in $functions; do
print_function_doc $file $function
done
exit 0