Last active
September 26, 2021 15:51
-
-
Save SomajitDey/e39bdade20c46c7741b683432a45a3bf to your computer and use it in GitHub Desktop.
TODO list for any git branch. Read file header for installation and usage.
This file contains 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
#!/usr/bin/env bash | |
# Brief: TODO list specific to git branches. No effect on commits, staged or worktree | |
# Installation: | |
# chmod +x ./git-todo | |
# sudo mv ./git-todo /usr/local/bin | |
# git config --global alias.todo '!git-todo' | |
# Help: git todo -h | |
# Author: Somajit Dey <dey.somajit@gmail.com> 2021 [https://github.com/SomajitDey] | |
# Source: https://gist.github.com/SomajitDey | |
# GitHubGist Search Terms: username:SomajitDey filename:git-todo.bash | |
usage(){ | |
echo " Brief: TODO list specific to given git branch. If branch is not given, current branch is used. | |
Usage: git todo [-e] [-d] [-u] [-r] [-f] [-a \"new task to be appended\"] [branch] | |
Options: | |
-e Edit TODO list (through editor) | |
-a Quickly append given task to TODO list (without opening editor) | |
-u Undo last edit | |
-r Undo last undo | |
-d Delete TODO list | |
-f Delete current TODO list and create a fresh one" | |
} | |
while getopts heurdfa: opt; do | |
case "${opt}" in | |
h) usage; exit;; | |
e) mode="edit" ;; | |
d) mode="delete" ;; | |
u) mode="undo" ;; | |
r) mode="redo" ;; | |
f) mode="freshen" ;; | |
a) mode="${mode:-edit}"; task="${OPTARG}";; | |
*) exit 1;; | |
esac | |
done | |
mode="${mode:-show}" | |
git_dir=$(git rev-parse --absolute-git-dir) || exit 1 | |
todo_dir="${git_dir}/todo" ; mkdir -p "${todo_dir}" | |
branch="${!OPTIND:-"$(git branch --show-current)"}" | |
(git branch -a | grep -q "${branch}") || { echo "Given branch doesn't exist" >&2; exit 1;} | |
todo_file="${todo_dir}/${branch}" | |
[[ -e "${todo_file}" ]] || mode="edit" | |
header="### This is the TODO list for branch \"${branch}\". Write your tasks below. Separate tasks with blank line(s). ###" | |
show(){ | |
case "$(head -n1 "${todo_file}")" in | |
"${header}") local read_from=2;; | |
*) local read_from=1;; | |
esac | |
tail -q -n "+${read_from}" "${todo_file}" | cat -sb | fold -sw "$((COLUMNS-2))" | |
echo | |
} | |
edit(){ | |
local editor=$(git config core.editor) | |
[[ -e "${todo_file}" ]] || echo "${header}" > "${todo_file}" | |
cp -n "${todo_file}" "${todo_file}.undo.candidate" | |
if [[ -v task ]]; then | |
echo -e "\n${task}" >> "${todo_file}" | |
else | |
"${editor:=vi}" "${todo_file}" | |
fi | |
if diff -q "${todo_file}" "${todo_file}.undo.candidate" &>/dev/null; then | |
rm "${todo_file}.undo.candidate" | |
else | |
mv "${todo_file}.undo.candidate" "${todo_file}.undo" | |
# Remove trailing blank lines. We use awk which can't do in place edit. So, | |
# using the redo file which would have to be deleted anyway. | |
awk '/^$/ {nlstack=nlstack "\n";next;} {printf "%s",nlstack; nlstack=""; print;}' "${todo_file}" > "${todo_file}.redo" | |
# Ref: https://unix.stackexchange.com/a/81688 | |
# Credit: @HaukeLaging https://unix.stackexchange.com/users/32191/hauke-laging | |
mv "${todo_file}.redo" "${todo_file}" | |
fi | |
} | |
undo(){ | |
if [[ -e "${todo_file}.undo" ]]; then | |
mv "${todo_file}" "${todo_file}.redo" | |
mv "${todo_file}.undo" "${todo_file}" | |
else | |
echo "Nothing to undo" >&2 | |
return 1 | |
fi | |
} | |
redo(){ | |
if [[ -e "${todo_file}.redo" ]]; then | |
mv "${todo_file}" "${todo_file}.undo" | |
mv "${todo_file}.redo" "${todo_file}" | |
else | |
echo "Nothing to redo" >&2 | |
return 1 | |
fi | |
} | |
delete(){ | |
mv "${todo_file}" "${todo_file}.undo" | |
cp "${todo_file}.undo" "${todo_file}.undo.candidate" | |
} | |
freshen(){ | |
delete | |
edit | |
} | |
"${mode}" | |
exit |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment