Last active
July 19, 2025 11:46
-
-
Save ldotlopez/bc76bb40e662a2fa026326d0d389d842 to your computer and use it in GitHub Desktop.
Bash module to show README's on changing into directory.
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 | |
| if [[ ${BASH_VERSINFO[0]} -lt 4 ]]; then | |
| echo "[on-cd] You are using an ancient bash version" >&2 | |
| echo "[on-cd] bash >= 4 is required to use this shlib" >&2 | |
| return | |
| fi | |
| # | |
| # User configurable variables | |
| # | |
| ON_CD_PAGER="head -n 10" | |
| ON_CD_DEBUG="" | |
| ON_CD_TTL=$((60 * 60 * 8)) # 8 hours | |
| # | |
| # Don't change variables unless you know what are you doing | |
| # | |
| # In case of not running on "modern-ish" Linux | |
| XDG_CACHE_HOME="${XDG_CACHE_HOME:-"$HOME/.cache"}" | |
| ON_CD_CACHE_DIR="$XDG_CACHE_HOME/on-cd" | |
| ON_CD_TIMESTAMPS_FILE="$ON_CD_CACHE_DIR/timestamps" | |
| declare -A _ON_CD_TIMESTAMPS | |
| function cd() { | |
| # Store the arguments passed to the custom cd function. | |
| local args=("$@") | |
| # Get the current directory before changing. | |
| # local old_pwd="$PWD" | |
| # Execute the built-in 'cd' command with the provided arguments. | |
| # This ensures the actual directory change happens. | |
| debug "Executing builtin cd -- " "${args[@]}" | |
| builtin cd "${args[@]}" || return $? # If 'cd' fails, exit the function. | |
| debug "Running post cd on '$PWD'" | |
| post_cd "$PWD" | |
| } | |
| function post_cd { | |
| local dirpath="${1:-"$PWD"}" | |
| local notefile | |
| local notets | |
| local now | |
| # Check for dirpath note | |
| notepath="$(get_dirnote "$dirpath" || true)" | |
| [[ -f "$notepath" ]] || { | |
| debug "$dirpath: No note found" | |
| return | |
| } | |
| notets=$(get_timestamp_of "$notepath") | |
| debug "$dirpath: Found '$notepath' (ts=$notets)" | |
| # FIXME: Replace `date` call with a build-in solution | |
| now="$(date +%s)" | |
| if [[ $((now - notets)) -le $ON_CD_TTL ]]; then | |
| debug "$notepath: was recently displayed. skipping." | |
| return | |
| fi | |
| debug "$notepath: was not displayed, showing it." | |
| # shellcheck disable=SC1009 | |
| $ON_CD_PAGER "$notepath" | |
| set_timestamp_of "$notepath" "$now" | |
| } | |
| function get_dirnote { | |
| local dirpath="${1:-"$PWD"}" | |
| for basename in "README" "TODO" "WARNING" "INFO"; do | |
| for ext in "md" "txt"; do | |
| # Don't use a loop to here avoid inner calls to 'tr' and also | |
| # delegate the real 'print' of the filename to check_filepath | |
| check_filepath "${dirpath}/${basename}.${ext}" && return 0 | |
| check_filepath "${dirpath}/${basename}" && return 0 | |
| check_filepath "${dirpath}/${basename}.${ext^^}" && return 0 | |
| check_filepath "${dirpath}/${basename,,}.${ext}" && return 0 | |
| done | |
| done | |
| return 1 | |
| } | |
| function check_filepath() { | |
| [[ -f "$1" ]] && { | |
| printf "%s" "$1" | |
| return 0 | |
| } || return 1 | |
| } | |
| function set_timestamp_of { | |
| local filepath="$1" | |
| local ts="$2" | |
| _ON_CD_TIMESTAMPS[$filepath]="$ts" | |
| dump_timestamps | |
| } | |
| function get_timestamp_of { | |
| local notefile="$1" | |
| local ts | |
| load_timestamps | |
| ts=${_ON_CD_TIMESTAMPS["$notefile"]} | |
| [[ -z "$ts" ]] && ts=0 | |
| printf "%s" "$ts" | |
| } | |
| function load_timestamps() { | |
| # Check if the timestamp file exists. If not, create it. | |
| [[ -d "$ON_CD_CACHE_DIR" ]] || mkdir -p "$ON_CD_CACHE_DIR" | |
| [[ -f "$ON_CD_TIMESTAMPS_FILE" ]] || touch "$ON_CD_TIMESTAMPS_FILE" | |
| # Read each line from the timestamp file. | |
| # Each line is expected to be in the format: timestamp:/path/to/directory | |
| while IFS=: read -r timestamp file; do | |
| # Store the directory and its timestamp in the associative array. | |
| _ON_CD_TIMESTAMPS["$file"]="$timestamp" | |
| done <"$ON_CD_TIMESTAMPS_FILE" | |
| # debug "[timestamps]" | |
| # # shellcheck disable=SC2068 | |
| # for key in ${!_ON_CD_TIMESTAMPS[@]}; do | |
| # debug "${key}: ${_ON_CD_TIMESTAMPS[${key}]}" | |
| # done | |
| # debug "[/timestamps]" | |
| } | |
| # Function to save the current state of the associative array back to the file. | |
| function dump_timestamps() { | |
| # Clear the file content before writing to ensure only current data is present. | |
| : >"$ON_CD_TIMESTAMPS_FILE" | |
| # Iterate over all key-value pairs in the associative array. | |
| for file in "${!_ON_CD_TIMESTAMPS[@]}"; do | |
| # Write each directory and its timestamp to the file. | |
| builtin printf "%s:%s\n" "${_ON_CD_TIMESTAMPS[$file]}" "$file" >>"$ON_CD_TIMESTAMPS_FILE" | |
| done | |
| } | |
| function debug { | |
| [[ -z "$ON_CD_DEBUG" ]] && return | |
| builtin printf "[debug] %s\n" "${@}" >&2 | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment