Skip to content

Instantly share code, notes, and snippets.

@imaami
Last active August 18, 2024 18:15
Show Gist options
  • Save imaami/5acdbca38b1f49468f680a1aa04493fe to your computer and use it in GitHub Desktop.
Save imaami/5acdbca38b1f49468f680a1aa04493fe to your computer and use it in GitHub Desktop.
Let GPT describe how your code sucks.
#!/usr/bin/env bash
#
# IMPORTANT: The HTTP authorization header must be found
# in ~/.openai in full, not just the API key.
#
# Usage: ./documentarist.sh [options] /path/to/file.c
#
# Requirements: dos2unix, cpp, clang-format, jq, curl
#
unset a arg blind files name src sym tmp
declare -i blind=0
declare -A arg
declare -a files
while (( $# )); do
a="$1"
while ((1)); do
case "$a" in
--blind|-b|-b[sx]*)
a="${a/#--/-}" ;
arg["${a:1:1}"]=1 ;
[[ ! "${a:2:1}" =~ [sx] ]] ||
{ a="-${a:2}"; continue; } ;;
--symbol|-[sx])
shift; a="${a/#--/-}" ;
arg["${a:1:1}"]="$1" ;;
--symbol=*)
a="${a:1:2}${a#*=}" ;
continue ;;
-[sx]*)
arg["${a:1:1}"]="${a:2}" ;;
*)
files+=("$1") ;;
esac
shift
break
done
done
blind="${arg['b']}"
lang="${arg['x']}"
sym="${arg['s']}"
[[ -f "${files[0]}" ]] &&
name="${files[0]##*/}" &&
{
[[ "$lang" ]] || {
case "${name##*\.}" in
[ch]pp) lang=c++ ;;
*) lang=c ;;
esac
}
} &&
tmp=$(mktemp -d) && [[ -d "$tmp" ]] || exit 1
src="$tmp/$name"
dos2unix < "${files[0]}" > "$src"
if (( blind )); then
cpp -fpreprocessed -dD -P -o "$src.i" "$src" 2>/dev/null
if [[ -f "$src.i" ]]; then
mv "$src.i" "$src"
fi
fi
[[ -f "$src" ]] || { rm -fr "$tmp"; exit 1; }
clang-format --style='{BasedOnStyle: webkit, IndentWidth: 8,
TabWidth: 8, UseTab: ForIndentation}' -i "$src"
if [[ "$sym" ]]; then
sym="$(sed -E 's/([[:blank:]]*\.)?[[:blank:]]*$//' <<< "$sym")"
if [[ "$sym" ]]; then
sym=",{\"role\":\"user\",\"content\":\"Document \`${sym//\"/\\\"}\`.\"}"
fi
fi
jq --rawfile source <(
printf '```\n/** @file %s\n */\n' "$name"
cat "$src"
printf '\n```'
) -Mnc --rawfile system <(cat << EOF
You document C/C++ code using Doxygen syntax. You are given the code and told which function, type, macro, etc. to document. Write the requested documentation and print the documented declarations.
To be clear: you read code that contains full definitions, but you print only declarations with documentation added on top. For example
\`\`\`$lang
int foo (int *bar) {
*bar *= 9;
return *bar ^ ~0;
}
\`\`\`
might become
\`\`\`$lang
/**
* @brief Toggle bar.
* @param bar The bar to modify.
* @return Result status.
* @retval 0 no error.
* @retval EFAULT @p bar is an invalid address.
*/
int foo (int *bar);
\`\`\`
Important:
- Always read and reason about the code itself, describe what it actually does.
- Symbol names aren't guaranteed to be descriptive, don't assume they reflect code behavior.
- Existing comments may be substandard, always verify by reading the code before trusting them.
- Read and understand the program flow, describe all possible results given all possible inputs.
About formatting:
- Not all things that you are asked to document will be functions. Pay attention to what the symbol actually is.
- Your output will be placed in header files. Do not waste space by repeating lines from the input other than the relevant declaration.
- Do not print a function body when documenting a function. Output stops after the argument list's closing parenthesis and a semicolon.
- Macro documentation can include a definition if it is short. Otherwise the documentation, macro name, and args list (if any) suffice.
- Each "@retval" describes one possible return value, no more. Add multiple "@retval" lines if necessary.
- "@retval" does not exclude "@return".
EOF
) '{
"model": "gpt-4o-2024-08-06",
"stream": false,
"messages": [
{"role":"system","content":$system},
{"role":"user","content":$source}'"$sym"'
]
}' \
| curl https://api.openai.com/v1/chat/completions -s -S -d @- \
-H @"$HOME/.openai" -H Content-Type:\ application/json \
| jq -r '.choices[0].message.content' \
| tee "documented_$(date -u -Isec).h"
rm -fr "$tmp"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment