Last active
March 3, 2025 18:19
-
-
Save the-solipsist/38fa498c0cdc9c858ed104cbb10a0338 to your computer and use it in GitHub Desktop.
hledger-jj converted from ysh to bash by Gemini 2.0
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# -*- sh -*- | |
# Improved version of hledger-jj bash script, created by Gemini 2.0 | |
# Original version of hledger-jj ysh script, created by Simon Michael | |
# --- Error Handling and Setup --- | |
if [[ -z "$LEDGER_FILE" ]]; then | |
echo "Error: LEDGER_FILE environment variable is not set." >&2 | |
exit 1 | |
fi | |
FILE1="${LEDGER_FILE}" | |
DIR="$(dirname "$FILE1")" | |
if [[ ! -d "$DIR" ]]; then | |
echo "Error: Directory '$DIR' (derived from LEDGER_FILE) does not exist or is not a directory." >&2 | |
exit 1 | |
fi | |
# Check if hledger is installed | |
if ! command -v hledger >/dev/null 2>&1; then | |
echo "Error: hledger is not installed or not in PATH." >&2 | |
exit 1 | |
fi | |
# Check if jj is installed | |
if ! command -v jj >/dev/null 2>&1; then | |
echo "Error: jj (Jujutsu) is not installed or not in PATH." >&2 | |
echo "Please install it: https://jj-vcs.github.io" >&2 | |
exit 1 | |
fi | |
# Get journal files and handle potential hledger errors | |
FILES_STR=$(hledger -f "$FILE1" files 2>/dev/null) # Capture stderr to discard hledger warnings | |
if [[ -z "$FILES_STR" ]]; then | |
echo "Error: hledger files command failed or returned no files. Check your LEDGER_FILE." >&2 | |
exit 1 | |
fi | |
IFS=$'\n' read -r -d '' -a FILES <<< "$FILES_STR" | |
unset IFS | |
HELP=$(cat <<'EOF' | |
------------------------------------------------------------------------------- | |
hledger-jj [COMMAND [OPTS]] - easy version control for hledger journals | |
An easy CLI for keeping your data in version control, using jj and a git repo. | |
Works for \$LEDGER_FILE and its subfiles only (-f is not yet supported). | |
A repo will be created if needed, in \$LEDGER_FILE's directory. | |
You can run this tool from any directory. Commands may be abbreviated. | |
Options are passed to jj; you may need to write -- first. | |
Commands: | |
help Show help message | |
status [OPTS] Show status of journal files | |
diff [OPTS] Show unrecorded changes in journal files | |
commit [MSG [OPTS]] Record changes to journal files | |
log [OPTS] List recorded changes to journal files | |
Examples: | |
hledger jj status | |
hledger jj diff | |
hledger jj commit "Added rent transaction" | |
hledger jj c "Minor fixes" -- -q 'account:Assets:Bank' | |
hledger jj log -n 5 --stat | |
EOF | |
) | |
help() { | |
echo -e "$HELP" | |
} | |
setup() { | |
ensure_journal_repo | |
} | |
ensure_journal_repo() { | |
# Change to journal directory and back using pushd/popd for efficiency | |
pushd "$DIR" > /dev/null || { | |
echo "Error: Could not change directory to '$DIR'." >&2 | |
exit 1 | |
} | |
trap 'popd > /dev/null' EXIT # Ensure we return to original dir even on errors | |
if ! jj status >/dev/null 2>&1; then | |
if ! jj git init --colocate; then | |
echo "Error: Failed to initialize jj/git repo in '$DIR'." >&2 | |
exit 1 | |
fi | |
echo "Created new colocated jj/git repo in $DIR" | |
fi | |
} | |
status() { | |
pushd "$DIR" > /dev/null || { echo "Error: Could not change directory to '$DIR'." >&2; return 1; } | |
trap 'popd > /dev/null' EXIT | |
jj status --color=always "$@" "${FILES[@]}" | grep -vE '^Untracked paths:|\?' | |
} | |
diff() { | |
pushd "$DIR" > /dev/null || { echo "Error: Could not change directory to '$DIR'." >&2; return 1; } | |
trap 'popd > /dev/null' EXIT | |
jj diff "$@" "${FILES[@]}" | |
} | |
commit() { | |
pushd "$DIR" > /dev/null || { echo "Error: Could not change directory to '$DIR'." >&2; return 1; } | |
trap 'popd > /dev/null' EXIT | |
if ! jj file track "${FILES[@]}"; then | |
echo "Error: Failed to track files using jj." >&2 | |
return 1 | |
fi | |
msg="${2:-$(date +'%Y-%m-%d %H:%M')}" | |
if ! jj commit -m "$msg" "$@" "${FILES[@]}"; then | |
echo "Error: jj commit command failed." >&2 | |
return 1 | |
fi | |
} | |
log() { | |
pushd "$DIR" > /dev/null || { echo "Error: Could not change directory to '$DIR'." >&2; return 1; } | |
trap 'popd > /dev/null' EXIT | |
jj log "$@" "${FILES[@]}" | |
} | |
if [ "$#" -lt 1 ]; then | |
help | |
else | |
command="$1" | |
args=("${@:2}") | |
case "$command" in | |
help | -h | --help ) help ;; # More explicit help matching | |
status* | s | st ) setup; status "${args[@]}" ;; # More explicit command prefixes | |
diff* | d ) setup; diff "${args[@]}" ;; | |
commit* | c ) setup; commit "${args[@]}" ;; | |
log* | l ) setup; log "${args[@]}" ;; | |
* ) echo "Unknown command: $command"; return 1 ;; # Default case for unknown commands | |
esac | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment