From b5b67397d93235ec59a91e06c5cfc0bc5bf85750 Mon Sep 17 00:00:00 2001 From: Raphael Eguchi Date: Thu, 1 Jan 2026 01:43:45 -0500 Subject: [PATCH 1/7] added custom selection keys --- README.md | 29 ++++-- install.sh | 17 ++++ nix/flake.nix | 20 +++- src/functions.sh | 91 +++++++++++++++--- tests/common.sh | 2 + tests/test_config.bats | 207 +++++++++++++++++++++++++++++++++++++++++ uninstall.sh | 11 +++ 7 files changed, 356 insertions(+), 21 deletions(-) create mode 100755 tests/test_config.bats diff --git a/README.md b/README.md index 06c9ddd..4236f72 100644 --- a/README.md +++ b/README.md @@ -43,12 +43,29 @@ Commands `sd`: "Dive" down to a child directory. #### Selection: -`0~9`: Select an option. -`n`: Next page. -`p`: Previous page. -`b`: Move selection back to parent directory. (For `sd` only.) -`Enter`: Navigate to selected directory (For `sd` only.) - +`0~9`: Select an option. +`n`: Next page. +`p`: Previous page. +`b`: Move selection back to parent directory. (For `sd` only.) +`Enter`: Navigate to selected directory (For `sd` only.) + +Customization +---- +You can customize the selection keys by editing the config file at `~/.config/shunpo/config`: + +```bash +# Selection keys (exactly 10 characters, one per menu item) +SHUNPO_SELECTION_KEYS="asdfghjkl;" +``` + +**Rules:** +- Must be exactly 10 characters (one for each menu item) +- Cannot contain `n`, `p`, or `b` (reserved for navigation) +- No duplicate characters allowed +- Invalid configs fall back to the default `1234567890` + +**Note:** CLI arguments (e.g., `sg 3`, `sj 1`) always use numeric indices 0-9, regardless of your custom keys. + Uninstalling ---- Run `uninstall.sh` diff --git a/install.sh b/install.sh index 3ae4a35..a23ed5e 100755 --- a/install.sh +++ b/install.sh @@ -10,6 +10,10 @@ BASHRC="$HOME/.bashrc" # File containing command definitions. SHUNPO_CMD="$INSTALL_DIR/shunpo_cmd" +# Config file path. +CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/shunpo" +CONFIG_FILE="$CONFIG_DIR/config" + setup() { mkdir -p $INSTALL_DIR mkdir -p $SCRIPT_DIR @@ -55,6 +59,19 @@ install() { echo "Added to BASHRC: $install_dir_line" add_commands + + # Create default config file if it doesn't exist. + if [ ! -f "$CONFIG_FILE" ]; then + mkdir -p "$CONFIG_DIR" + cat >"$CONFIG_FILE" < "$SHUNPO_INIT" + cat > "$SHUNPO_INIT" <<'INIT_EOF' +# Create default config file if it doesn't exist. +SHUNPO_CONFIG_DIR=''${XDG_CONFIG_HOME:-$HOME/.config}/shunpo +SHUNPO_CONFIG_FILE=$SHUNPO_CONFIG_DIR/config +if [ ! -f "$SHUNPO_CONFIG_FILE" ]; then + mkdir -p "$SHUNPO_CONFIG_DIR" + cat >"$SHUNPO_CONFIG_FILE" <<'CONFIG_EOF' +# Shunpo Configuration +# Selection keys (exactly 10 characters, one per menu item) +# Reserved keys that cannot be used: n, p, b +# Note: CLI arguments (e.g., sg 3, sj 1) always use numeric indices 0-9 +SHUNPO_SELECTION_KEYS="1234567890" +CONFIG_EOF +fi +unset SHUNPO_CONFIG_DIR SHUNPO_CONFIG_FILE +INIT_EOF + echo "source $SHUNPO_CMD" >> "$SHUNPO_INIT" chmod +x $SHUNPO_INIT # not necessary, but keep for auto-complete. ''; diff --git a/src/functions.sh b/src/functions.sh index 30bacc2..5abf1ef 100644 --- a/src/functions.sh +++ b/src/functions.sh @@ -1,5 +1,65 @@ #!/usr/bin/env bash +# Configuration Path. +SHUNPO_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/shunpo" +SHUNPO_CONFIG_FILE="$SHUNPO_CONFIG_DIR/config" + +# Default selection keys (can be overridden in config). +SHUNPO_SELECTION_KEYS="1234567890" + +# Load and validate user configuration. +function shunpo_load_config() { + if [ -f "$SHUNPO_CONFIG_FILE" ]; then + local user_keys + # Source the config to get SHUNPO_SELECTION_KEYS + source "$SHUNPO_CONFIG_FILE" + user_keys="$SHUNPO_SELECTION_KEYS" + + # Validate: exactly 10 characters + if [ ${#user_keys} -ne 10 ]; then + echo -e "${SHUNPO_BOLD}${SHUNPO_ORANGE}Warning: SHUNPO_SELECTION_KEYS must be exactly 10 characters. Using defaults.${SHUNPO_RESET}" + SHUNPO_SELECTION_KEYS="1234567890" + return + fi + + # Validate: no reserved keys (n, p, b) + if [[ $user_keys == *n* ]] || [[ $user_keys == *p* ]] || [[ $user_keys == *b* ]]; then + echo -e "${SHUNPO_BOLD}${SHUNPO_ORANGE}Warning: SHUNPO_SELECTION_KEYS cannot contain 'n', 'p', or 'b'. Using defaults.${SHUNPO_RESET}" + SHUNPO_SELECTION_KEYS="1234567890" + return + fi + + # Validate: no duplicate characters + local seen="" + for ((i = 0; i < ${#user_keys}; i++)); do + local char="${user_keys:i:1}" + if [[ $seen == *"$char"* ]]; then + echo -e "${SHUNPO_BOLD}${SHUNPO_ORANGE}Warning: SHUNPO_SELECTION_KEYS cannot contain duplicates. Using defaults.${SHUNPO_RESET}" + SHUNPO_SELECTION_KEYS="1234567890" + return + fi + seen+="$char" + done + + SHUNPO_SELECTION_KEYS="$user_keys" + fi +} + +# Get the index (0-9) for a given key, or return 1 if not found. +function shunpo_get_key_index() { + local key="$1" + for ((i = 0; i < ${#SHUNPO_SELECTION_KEYS}; i++)); do + if [[ ${SHUNPO_SELECTION_KEYS:i:1} == "$key" ]]; then + echo "$i" + return 0 + fi + done + return 1 +} + +# Load configuration on source. +shunpo_load_config + # Default Bookmarks Path. SHUNPO_BOOKMARKS_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/shunpo/" if [ ! -d "$SHUNPO_BOOKMARKS_DIR" ]; then @@ -80,7 +140,7 @@ function shunpo_interact_bookmarks() { # Display bookmarks for the current page. for ((i = start_index; i < end_index; i++)); do - echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}$((i - start_index))${SHUNPO_RESET}] ${bookmarks[i]}" + echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}${SHUNPO_SELECTION_KEYS:$((i - start_index)):1}${SHUNPO_RESET}] ${bookmarks[i]}" done if [ $last_page -gt 1 ]; then @@ -101,9 +161,9 @@ function shunpo_interact_bookmarks() { fi shunpo_clear_output - elif [[ $input =~ ^[0-9]+$ ]] && [ "$input" -ge 0 ] && [ "$input" -lt $max_per_page ]; then + elif key_index=$(shunpo_get_key_index "$input"); then # Process bookmark selection input. - shunpo_selected_bookmark_index=$((current_page * max_per_page + input)) + shunpo_selected_bookmark_index=$((current_page * max_per_page + key_index)) if [[ $shunpo_selected_bookmark_index -lt $total_bookmarks ]]; then shunpo_selected_dir="${bookmarks[$shunpo_selected_bookmark_index]}" shunpo_clear_output @@ -201,9 +261,9 @@ function shunpo_jump_to_parent_dir() { # Display the current page of parent directories. for ((i = start_index; i < end_index; i++)); do if [[ $i -eq $((end_index - 1)) && $current_page -eq $((last_page - 1)) ]]; then - echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}$((i - start_index))${SHUNPO_RESET}] $(basename ${parent_dirs[i]})" + echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}${SHUNPO_SELECTION_KEYS:$((i - start_index)):1}${SHUNPO_RESET}] $(basename ${parent_dirs[i]})" else - echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}$((i - start_index))${SHUNPO_RESET}] /$(basename ${parent_dirs[i]})" + echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}${SHUNPO_SELECTION_KEYS:$((i - start_index)):1}${SHUNPO_RESET}] /$(basename ${parent_dirs[i]})" fi done @@ -225,17 +285,17 @@ function shunpo_jump_to_parent_dir() { fi shunpo_clear_output - elif [[ $input =~ ^[0-9]+$ ]] && [ "$input" -gt 0 ] && [ "$input" -le "$max_per_page" ]; then - selected_index=$((start_index + input)) - if [[ $selected_index -lt $total_parents ]]; then + elif key_index=$(shunpo_get_key_index "$input"); then + selected_index=$((start_index + key_index)) + # Skip index 0 (current directory) - only allow selecting actual parents + if [[ $selected_index -gt 0 ]] && [[ $selected_index -lt $total_parents ]]; then shunpo_clear_output tput cnorm cd "${parent_dirs[$selected_index]}" || exit echo -e "${SHUNPO_GREEN}${SHUNPO_BOLD}Changed to:${SHUNPO_RESET} ${parent_dirs[$selected_index]}" return 0 - else - shunpo_clear_output fi + shunpo_clear_output else shunpo_clear_output tput cnorm @@ -345,7 +405,7 @@ function shunpo_jump_to_child_dir() { else # Print child directories. for ((i = start_index; i < end_index; i++)); do - echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}$((i - start_index))${SHUNPO_RESET}] ${child_dirs[i]#$selected_path}" + echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}${SHUNPO_SELECTION_KEYS:$((i - start_index)):1}${SHUNPO_RESET}] ${child_dirs[i]#$selected_path}" done if [ $last_page -gt 1 ]; then @@ -391,8 +451,8 @@ function shunpo_jump_to_child_dir() { fi break - elif [[ $input =~ ^[0-9]+$ ]] && [[ $input -ge 0 ]] && [[ $input -lt $max_per_page ]]; then - selected_index=$((start_index + input)) + elif key_index=$(shunpo_get_key_index "$input"); then + selected_index=$((start_index + key_index)) if [[ $selected_index -lt $total_child_dirs ]]; then selected_path="${child_dirs[selected_index]}" is_start_dir=0 @@ -448,6 +508,9 @@ function shunpo_cleanup() { # Clean up to avoid namespace pollution. unset SHUNPO_BOOKMARKS_FILE unset SHUNPO_BOOKMARKS_DIR + unset SHUNPO_CONFIG_DIR + unset SHUNPO_CONFIG_FILE + unset SHUNPO_SELECTION_KEYS unset IFS unset shunpo_selected_dir unset shunpo_selected_bookmark_index @@ -459,6 +522,8 @@ function shunpo_cleanup() { unset -f shunpo_jump_to_child_dir unset -f shunpo_is_cached unset -f shunpo_handle_kill + unset -f shunpo_load_config + unset -f shunpo_get_key_index unset -f shunpo_cleanup tput cnorm stty echo diff --git a/tests/common.sh b/tests/common.sh index 5c026e8..585e44e 100755 --- a/tests/common.sh +++ b/tests/common.sh @@ -11,6 +11,8 @@ function setup_env { mkdir -p $HOME XDG_DATA_HOME=${SHUNPO_TEST_DIR}/home/.local/share mkdir -p $XDG_DATA_HOME + XDG_CONFIG_HOME=${SHUNPO_TEST_DIR}/home/.config + mkdir -p $XDG_CONFIG_HOME } function cleanup_env { diff --git a/tests/test_config.bats b/tests/test_config.bats new file mode 100755 index 0000000..b5267aa --- /dev/null +++ b/tests/test_config.bats @@ -0,0 +1,207 @@ +#!/usr/bin/env bats + +load common.sh +load bats/assert.sh +load bats/error.sh +load bats/lang.sh +load bats/output.sh + +setup() { + echo "Setting Up Test." + setup_env + printf '\n' | ./install.sh + working_dir=$(pwd) + source ${SHUNPO_TEST_DIR}/home/.bashrc +} + +teardown() { + echo "Shutting Down Test." + cd "$working_dir" + ./uninstall.sh +} + +@test "Test Config File Created During Install." { + # Check that config file was created. + assert [ -f "${XDG_CONFIG_HOME}/shunpo/config" ] +} + +@test "Test Config File Removed During Uninstall." { + # Verify config exists before uninstall. + assert [ -f "${XDG_CONFIG_HOME}/shunpo/config" ] + + # Run uninstall. + cd "$working_dir" + ./uninstall.sh + + # Verify config is removed. + refute [ -f "${XDG_CONFIG_HOME}/shunpo/config" ] + refute [ -d "${XDG_CONFIG_HOME}/shunpo" ] + + # Reinstall for teardown. + printf '\n' | ./install.sh + source ${SHUNPO_TEST_DIR}/home/.bashrc +} + +@test "Test Default Selection Keys." { + # Source functions to load config. + source ${SHUNPO_DIR}/scripts/colors.sh + source ${SHUNPO_DIR}/scripts/functions.sh + + # Check default keys. + assert_equal "$SHUNPO_SELECTION_KEYS" "1234567890" +} + +@test "Test Custom Selection Keys." { + # Write custom config. + echo 'SHUNPO_SELECTION_KEYS="asdfghjkl;"' >"${XDG_CONFIG_HOME}/shunpo/config" + + # Source functions to load config. + source ${SHUNPO_DIR}/scripts/colors.sh + source ${SHUNPO_DIR}/scripts/functions.sh + + # Check custom keys loaded. + assert_equal "$SHUNPO_SELECTION_KEYS" "asdfghjkl;" + + # Restore default config. + cat >"${XDG_CONFIG_HOME}/shunpo/config" <"${XDG_CONFIG_HOME}/shunpo/config" + + # Source functions. + source ${SHUNPO_DIR}/scripts/colors.sh + source ${SHUNPO_DIR}/scripts/functions.sh + + # Test key lookup with custom keys. + result=$(shunpo_get_key_index "a") + assert_equal "$result" "0" + + result=$(shunpo_get_key_index "g") + assert_equal "$result" "4" + + result=$(shunpo_get_key_index ";") + assert_equal "$result" "9" + + # Test that old numeric keys no longer work. + run shunpo_get_key_index "1" + assert_failure + + # Restore default config. + cat >"${XDG_CONFIG_HOME}/shunpo/config" <"${XDG_CONFIG_HOME}/shunpo/config" + + # Source functions (should show warning and use defaults). + source ${SHUNPO_DIR}/scripts/colors.sh + run source ${SHUNPO_DIR}/scripts/functions.sh + + # Re-source to get the variable. + source ${SHUNPO_DIR}/scripts/colors.sh + source ${SHUNPO_DIR}/scripts/functions.sh + + # Should fall back to defaults. + assert_equal "$SHUNPO_SELECTION_KEYS" "1234567890" + + # Restore default config. + cat >"${XDG_CONFIG_HOME}/shunpo/config" <"${XDG_CONFIG_HOME}/shunpo/config" + + # Source functions. + source ${SHUNPO_DIR}/scripts/colors.sh + source ${SHUNPO_DIR}/scripts/functions.sh + + # Should fall back to defaults. + assert_equal "$SHUNPO_SELECTION_KEYS" "1234567890" + + # Test with 'p'. + echo 'SHUNPO_SELECTION_KEYS="abcdefghip"' >"${XDG_CONFIG_HOME}/shunpo/config" + source ${SHUNPO_DIR}/scripts/colors.sh + source ${SHUNPO_DIR}/scripts/functions.sh + assert_equal "$SHUNPO_SELECTION_KEYS" "1234567890" + + # Test with 'b'. + echo 'SHUNPO_SELECTION_KEYS="abcdefghib"' >"${XDG_CONFIG_HOME}/shunpo/config" + source ${SHUNPO_DIR}/scripts/colors.sh + source ${SHUNPO_DIR}/scripts/functions.sh + assert_equal "$SHUNPO_SELECTION_KEYS" "1234567890" + + # Restore default config. + cat >"${XDG_CONFIG_HOME}/shunpo/config" <"${XDG_CONFIG_HOME}/shunpo/config" + + # Source functions. + source ${SHUNPO_DIR}/scripts/colors.sh + source ${SHUNPO_DIR}/scripts/functions.sh + + # Should fall back to defaults. + assert_equal "$SHUNPO_SELECTION_KEYS" "1234567890" + + # Restore default config. + cat >"${XDG_CONFIG_HOME}/shunpo/config" <"${XDG_CONFIG_HOME}/shunpo/config" + + # Source functions. + source ${SHUNPO_DIR}/scripts/colors.sh + source ${SHUNPO_DIR}/scripts/functions.sh + + # Should use defaults. + assert_equal "$SHUNPO_SELECTION_KEYS" "1234567890" + + # Restore default config. + cat >"${XDG_CONFIG_HOME}/shunpo/config" </dev/null && echo "Removed $SHUNPO_CONFIG_DIR" + fi + # Remove scripts and directories. if [ -z "$SHUNPO_DIR" ]; then echo "No Installation Found." From 0f05c48f402e69abb1f7812af03776eb3e857158 Mon Sep 17 00:00:00 2001 From: "R. Eguchi" Date: Thu, 1 Jan 2026 01:47:14 -0500 Subject: [PATCH 2/7] Update README.md --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4236f72..4d51001 100644 --- a/README.md +++ b/README.md @@ -59,10 +59,10 @@ SHUNPO_SELECTION_KEYS="asdfghjkl;" ``` **Rules:** -- Must be exactly 10 characters (one for each menu item) -- Cannot contain `n`, `p`, or `b` (reserved for navigation) -- No duplicate characters allowed -- Invalid configs fall back to the default `1234567890` +- Must be exactly 10 characters (one for each menu item). +- Cannot contain `n`, `p`, or `b` (reserved for navigation). +- No duplicate characters allowed. +- Invalid configs fall back to the default `1234567890`. **Note:** CLI arguments (e.g., `sg 3`, `sj 1`) always use numeric indices 0-9, regardless of your custom keys. From 85dbbcf20967745c7ac672f68bf5bd1a3bb0541b Mon Sep 17 00:00:00 2001 From: Raphael Eguchi Date: Thu, 1 Jan 2026 02:06:41 -0500 Subject: [PATCH 3/7] added quotes and merged changes from main --- install.sh | 16 ++++++++-------- src/functions.sh | 12 ++++++------ src/jump_to_parent.sh | 8 ++++---- tests/common.sh | 18 +++++++++--------- uninstall.sh | 8 ++++---- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/install.sh b/install.sh index a23ed5e..08398c1 100755 --- a/install.sh +++ b/install.sh @@ -15,12 +15,12 @@ CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/shunpo" CONFIG_FILE="$CONFIG_DIR/config" setup() { - mkdir -p $INSTALL_DIR - mkdir -p $SCRIPT_DIR - if [ -f $SHUNPO_CMD ]; then - rm $SHUNPO_CMD + mkdir -p "$INSTALL_DIR" + mkdir -p "$SCRIPT_DIR" + if [ -f "$SHUNPO_CMD" ]; then + rm "$SHUNPO_CMD" fi - touch $SHUNPO_CMD + touch "$SHUNPO_CMD" } add_commands() { @@ -40,10 +40,10 @@ EOF install() { # Store scripts in SCRIPTS_DIR. - cp src/* $SCRIPT_DIR + cp src/* "$SCRIPT_DIR" # Add sourcing for shunpo_cmd (overwrite). - source_rc_line="source $SHUNPO_CMD" + source_rc_line="source \"$SHUNPO_CMD\"" temp_file=$(mktemp) sed '/^source.*\shunpo_cmd/d' "$BASHRC" >"$temp_file" mv "$temp_file" "$BASHRC" @@ -51,7 +51,7 @@ install() { echo "Added to BASHRC: $source_rc_line" # Record SHUNPO_DIR for uninstallation (overwrite). - install_dir_line="export SHUNPO_DIR=$INSTALL_DIR" >>"$BASHRC$" + install_dir_line="export SHUNPO_DIR=\"$INSTALL_DIR\"" temp_file=$(mktemp) grep -v '^export SHUNPO_DIR=' "$BASHRC" >"$temp_file" mv "$temp_file" "$BASHRC" diff --git a/src/functions.sh b/src/functions.sh index 5abf1ef..08e9415 100644 --- a/src/functions.sh +++ b/src/functions.sh @@ -220,7 +220,7 @@ function shunpo_jump_to_parent_dir() { return 1 else if [[ $1 -lt $total_parents ]]; then - cd "${parent_dirs[$1]}" || exit + cd "${parent_dirs[$1]}" || return 1 tput cnorm echo -e "${SHUNPO_GREEN}${SHUNPO_BOLD}Changed to:${SHUNPO_RESET} ${parent_dirs[$1]}" return 0 @@ -261,9 +261,9 @@ function shunpo_jump_to_parent_dir() { # Display the current page of parent directories. for ((i = start_index; i < end_index; i++)); do if [[ $i -eq $((end_index - 1)) && $current_page -eq $((last_page - 1)) ]]; then - echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}${SHUNPO_SELECTION_KEYS:$((i - start_index)):1}${SHUNPO_RESET}] $(basename ${parent_dirs[i]})" + echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}${SHUNPO_SELECTION_KEYS:$((i - start_index)):1}${SHUNPO_RESET}] $(basename "${parent_dirs[i]}")" else - echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}${SHUNPO_SELECTION_KEYS:$((i - start_index)):1}${SHUNPO_RESET}] /$(basename ${parent_dirs[i]})" + echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}${SHUNPO_SELECTION_KEYS:$((i - start_index)):1}${SHUNPO_RESET}] /$(basename "${parent_dirs[i]}")" fi done @@ -291,7 +291,7 @@ function shunpo_jump_to_parent_dir() { if [[ $selected_index -gt 0 ]] && [[ $selected_index -lt $total_parents ]]; then shunpo_clear_output tput cnorm - cd "${parent_dirs[$selected_index]}" || exit + cd "${parent_dirs[$selected_index]}" || return 1 echo -e "${SHUNPO_GREEN}${SHUNPO_BOLD}Changed to:${SHUNPO_RESET} ${parent_dirs[$selected_index]}" return 0 fi @@ -405,7 +405,7 @@ function shunpo_jump_to_child_dir() { else # Print child directories. for ((i = start_index; i < end_index; i++)); do - echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}${SHUNPO_SELECTION_KEYS:$((i - start_index)):1}${SHUNPO_RESET}] ${child_dirs[i]#$selected_path}" + echo -e "[${SHUNPO_BOLD}${SHUNPO_ORANGE}${SHUNPO_SELECTION_KEYS:$((i - start_index)):1}${SHUNPO_RESET}] ${child_dirs[i]#"$selected_path"}" done if [ $last_page -gt 1 ]; then @@ -446,7 +446,7 @@ function shunpo_jump_to_child_dir() { elif [[ $input == "" ]]; then shunpo_clear_output if [[ $is_start_dir -ne 1 ]]; then - cd "$selected_path" || exit + cd "$selected_path" || return 1 echo -e "${SHUNPO_GREEN}${SHUNPO_BOLD}Changed to:${SHUNPO_RESET} $selected_path" fi break diff --git a/src/jump_to_parent.sh b/src/jump_to_parent.sh index 2c9d0e5..8c44a0f 100755 --- a/src/jump_to_parent.sh +++ b/src/jump_to_parent.sh @@ -16,16 +16,16 @@ function shunpo_handle_kill() { trap 'shunpo_handle_kill; return 1' SIGINT -shunpo_jump_to_parent_dir $1 +shunpo_jump_to_parent_dir "$1" +shunpo_exit_code=$? # Handle case where bookmark is not set. -if [ $? -eq 1 ]; then - +if [ $shunpo_exit_code -eq 1 ]; then if declare -f shunpo_cleanup >/dev/null; then shunpo_cleanup fi return 1 -elif [ $? -eq 2 ]; then +elif [ $shunpo_exit_code -eq 2 ]; then if declare -f shunpo_cleanup >/dev/null; then shunpo_cleanup fi diff --git a/tests/common.sh b/tests/common.sh index 585e44e..f02fd6e 100755 --- a/tests/common.sh +++ b/tests/common.sh @@ -8,24 +8,24 @@ fi function setup_env { HOME=${SHUNPO_TEST_DIR}/home - mkdir -p $HOME + mkdir -p "$HOME" XDG_DATA_HOME=${SHUNPO_TEST_DIR}/home/.local/share - mkdir -p $XDG_DATA_HOME + mkdir -p "$XDG_DATA_HOME" XDG_CONFIG_HOME=${SHUNPO_TEST_DIR}/home/.config - mkdir -p $XDG_CONFIG_HOME + mkdir -p "$XDG_CONFIG_HOME" } function cleanup_env { - rm $SHUNPO_TEST_DIR/home/.bashrc - rm $SHUNPO_TEST_DIR/home/.bashrc$ + rm "$SHUNPO_TEST_DIR/home/.bashrc" + rm "$SHUNPO_TEST_DIR/home/.bashrc$" if [ -d "${SHUNPO_TEST_DIR}/home" ]; then - rmdir ${SHUNPO_TEST_DIR}/home/ + rmdir "${SHUNPO_TEST_DIR}/home/" fi if [ -d "${SHUNPO_TEST_DIR}" ]; then - find ${SHUNPO_TEST_DIR} -type d -empty -delete - rmdir $SHUNPO_TEST_DIR + find "${SHUNPO_TEST_DIR}" -type d -empty -delete + rmdir "$SHUNPO_TEST_DIR" fi } @@ -49,5 +49,5 @@ make_directories() { get_num_bookmarks() { SHUNPO_BOOKMARKS_FILE="${XDG_DATA_HOME:-$HOME/.local/share}/shunpo/.shunpo_bookmarks" - echo $(wc -l <$SHUNPO_BOOKMARKS_FILE | tr -d '[:space:]') + echo $(wc -l <"$SHUNPO_BOOKMARKS_FILE" | tr -d '[:space:]') } diff --git a/uninstall.sh b/uninstall.sh index 7664288..910891d 100755 --- a/uninstall.sh +++ b/uninstall.sh @@ -1,7 +1,7 @@ #!/usr/bin/env bash BASHRC="$HOME/.bashrc" -source $BASHRC +source "$BASHRC" uninstall() { # Remove commands file. @@ -15,8 +15,8 @@ uninstall() { # Remove bookmarks file. SHUNPO_BOOKMARKS_DIR="${XDG_DATA_HOME:-$HOME/.local/share}/shunpo" SHUNPO_BOOKMARKS_FILE="$SHUNPO_BOOKMARKS_DIR/.shunpo_bookmarks" - if [ -f $SHUNPO_BOOKMARKS_FILE ]; then - rm $SHUNPO_BOOKMARKS_FILE + if [ -f "$SHUNPO_BOOKMARKS_FILE" ]; then + rm "$SHUNPO_BOOKMARKS_FILE" echo "Removed $SHUNPO_BOOKMARKS_FILE" fi @@ -49,7 +49,7 @@ uninstall() { cd .. rmdir "${SHUNPO_DIR}"/scripts cd .. - rmdir $SHUNPO_DIR + rmdir "$SHUNPO_DIR" echo "Removed $SHUNPO_DIR" unset SHUNPO_DIR fi From 5aeca5d3f98286fe8323c9db99bf886d6b82ead6 Mon Sep 17 00:00:00 2001 From: Raphael Eguchi Date: Thu, 1 Jan 2026 02:13:06 -0500 Subject: [PATCH 4/7] use the original default selection keys --- README.md | 2 +- install.sh | 2 +- nix/flake.nix | 2 +- src/functions.sh | 11 +++++------ tests/test_config.bats | 34 +++++++++++++++++----------------- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 4d51001..7afde3b 100644 --- a/README.md +++ b/README.md @@ -62,7 +62,7 @@ SHUNPO_SELECTION_KEYS="asdfghjkl;" - Must be exactly 10 characters (one for each menu item). - Cannot contain `n`, `p`, or `b` (reserved for navigation). - No duplicate characters allowed. -- Invalid configs fall back to the default `1234567890`. +- Invalid configs fall back to the default `0123456789`. **Note:** CLI arguments (e.g., `sg 3`, `sj 1`) always use numeric indices 0-9, regardless of your custom keys. diff --git a/install.sh b/install.sh index 08398c1..cdaeed2 100755 --- a/install.sh +++ b/install.sh @@ -68,7 +68,7 @@ install() { # Selection keys (exactly 10 characters, one per menu item) # Reserved keys that cannot be used: n, p, b # Note: CLI arguments (e.g., sg 3, sj 1) always use numeric indices 0-9 -SHUNPO_SELECTION_KEYS="1234567890" +SHUNPO_SELECTION_KEYS="0123456789" EOF echo "Created config: $CONFIG_FILE" fi diff --git a/nix/flake.nix b/nix/flake.nix index c2dc589..b6b1af2 100644 --- a/nix/flake.nix +++ b/nix/flake.nix @@ -61,7 +61,7 @@ if [ ! -f "$SHUNPO_CONFIG_FILE" ]; then # Selection keys (exactly 10 characters, one per menu item) # Reserved keys that cannot be used: n, p, b # Note: CLI arguments (e.g., sg 3, sj 1) always use numeric indices 0-9 -SHUNPO_SELECTION_KEYS="1234567890" +SHUNPO_SELECTION_KEYS="0123456789" CONFIG_EOF fi unset SHUNPO_CONFIG_DIR SHUNPO_CONFIG_FILE diff --git a/src/functions.sh b/src/functions.sh index 08e9415..09b7d52 100644 --- a/src/functions.sh +++ b/src/functions.sh @@ -5,7 +5,7 @@ SHUNPO_CONFIG_DIR="${XDG_CONFIG_HOME:-$HOME/.config}/shunpo" SHUNPO_CONFIG_FILE="$SHUNPO_CONFIG_DIR/config" # Default selection keys (can be overridden in config). -SHUNPO_SELECTION_KEYS="1234567890" +SHUNPO_SELECTION_KEYS="0123456789" # Load and validate user configuration. function shunpo_load_config() { @@ -18,14 +18,14 @@ function shunpo_load_config() { # Validate: exactly 10 characters if [ ${#user_keys} -ne 10 ]; then echo -e "${SHUNPO_BOLD}${SHUNPO_ORANGE}Warning: SHUNPO_SELECTION_KEYS must be exactly 10 characters. Using defaults.${SHUNPO_RESET}" - SHUNPO_SELECTION_KEYS="1234567890" + SHUNPO_SELECTION_KEYS="0123456789" return fi # Validate: no reserved keys (n, p, b) if [[ $user_keys == *n* ]] || [[ $user_keys == *p* ]] || [[ $user_keys == *b* ]]; then echo -e "${SHUNPO_BOLD}${SHUNPO_ORANGE}Warning: SHUNPO_SELECTION_KEYS cannot contain 'n', 'p', or 'b'. Using defaults.${SHUNPO_RESET}" - SHUNPO_SELECTION_KEYS="1234567890" + SHUNPO_SELECTION_KEYS="0123456789" return fi @@ -35,7 +35,7 @@ function shunpo_load_config() { local char="${user_keys:i:1}" if [[ $seen == *"$char"* ]]; then echo -e "${SHUNPO_BOLD}${SHUNPO_ORANGE}Warning: SHUNPO_SELECTION_KEYS cannot contain duplicates. Using defaults.${SHUNPO_RESET}" - SHUNPO_SELECTION_KEYS="1234567890" + SHUNPO_SELECTION_KEYS="0123456789" return fi seen+="$char" @@ -287,8 +287,7 @@ function shunpo_jump_to_parent_dir() { elif key_index=$(shunpo_get_key_index "$input"); then selected_index=$((start_index + key_index)) - # Skip index 0 (current directory) - only allow selecting actual parents - if [[ $selected_index -gt 0 ]] && [[ $selected_index -lt $total_parents ]]; then + if [[ $selected_index -ge 0 ]] && [[ $selected_index -lt $total_parents ]]; then shunpo_clear_output tput cnorm cd "${parent_dirs[$selected_index]}" || return 1 diff --git a/tests/test_config.bats b/tests/test_config.bats index b5267aa..a20265d 100755 --- a/tests/test_config.bats +++ b/tests/test_config.bats @@ -48,7 +48,7 @@ teardown() { source ${SHUNPO_DIR}/scripts/functions.sh # Check default keys. - assert_equal "$SHUNPO_SELECTION_KEYS" "1234567890" + assert_equal "$SHUNPO_SELECTION_KEYS" "0123456789" } @test "Test Custom Selection Keys." { @@ -65,7 +65,7 @@ teardown() { # Restore default config. cat >"${XDG_CONFIG_HOME}/shunpo/config" <"${XDG_CONFIG_HOME}/shunpo/config" <"${XDG_CONFIG_HOME}/shunpo/config" <"${XDG_CONFIG_HOME}/shunpo/config" source ${SHUNPO_DIR}/scripts/colors.sh source ${SHUNPO_DIR}/scripts/functions.sh - assert_equal "$SHUNPO_SELECTION_KEYS" "1234567890" + assert_equal "$SHUNPO_SELECTION_KEYS" "0123456789" # Test with 'b'. echo 'SHUNPO_SELECTION_KEYS="abcdefghib"' >"${XDG_CONFIG_HOME}/shunpo/config" source ${SHUNPO_DIR}/scripts/colors.sh source ${SHUNPO_DIR}/scripts/functions.sh - assert_equal "$SHUNPO_SELECTION_KEYS" "1234567890" + assert_equal "$SHUNPO_SELECTION_KEYS" "0123456789" # Restore default config. cat >"${XDG_CONFIG_HOME}/shunpo/config" <"${XDG_CONFIG_HOME}/shunpo/config" <"${XDG_CONFIG_HOME}/shunpo/config" < Date: Thu, 1 Jan 2026 13:41:06 -0500 Subject: [PATCH 5/7] Fix formatting in README --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7afde3b..1bb524b 100644 --- a/README.md +++ b/README.md @@ -43,10 +43,10 @@ Commands `sd`: "Dive" down to a child directory. #### Selection: -`0~9`: Select an option. -`n`: Next page. -`p`: Previous page. -`b`: Move selection back to parent directory. (For `sd` only.) +`0~9`: Select an option. +`n`: Next page. +`p`: Previous page. +`b`: Move selection back to parent directory. (For `sd` only.) `Enter`: Navigate to selected directory (For `sd` only.) Customization From a4eb2c6c8056154aa8ef3208b37a1500234bbddd Mon Sep 17 00:00:00 2001 From: Raphael Eguchi Date: Wed, 14 Jan 2026 14:54:25 -0500 Subject: [PATCH 6/7] fixed autocomplete issue and made cleanup more robust --- src/functions.sh | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/functions.sh b/src/functions.sh index 09b7d52..08dc233 100644 --- a/src/functions.sh +++ b/src/functions.sh @@ -342,7 +342,8 @@ function shunpo_jump_to_child_dir() { # Attempt to retrieve from cache. if cache_index=$(shunpo_is_cached "$selected_path"); then # Use cached value. - IFS='|' read -r -a child_dirs <<<"${cache_values[$cache_index]}" + local IFS='|' + read -r -a child_dirs <<<"${cache_values[$cache_index]}" else # Collect directories if not cached. child_dirs=() @@ -505,14 +506,22 @@ function shunpo_assert_bookmarks_exist() { function shunpo_cleanup() { # Clean up to avoid namespace pollution. + # + # Restore terminal state. + [ -t 0 ] && tput cnorm 2>/dev/null + trap - SIGINT + + # Clean up variables. unset SHUNPO_BOOKMARKS_FILE unset SHUNPO_BOOKMARKS_DIR unset SHUNPO_CONFIG_DIR unset SHUNPO_CONFIG_FILE unset SHUNPO_SELECTION_KEYS - unset IFS + IFS=$' \t\n' # Restore IFS to default. unset shunpo_selected_dir unset shunpo_selected_bookmark_index + + # Clean up functions. unset -f shunpo_interact_bookmarks unset -f shunpo_add_space unset -f shunpo_clear_output @@ -524,7 +533,4 @@ function shunpo_cleanup() { unset -f shunpo_load_config unset -f shunpo_get_key_index unset -f shunpo_cleanup - tput cnorm - stty echo - trap - SIGINT } From e502e5216acf7b10a06e296e8138e102dde90bdb Mon Sep 17 00:00:00 2001 From: Raphael Eguchi Date: Wed, 14 Jan 2026 14:54:36 -0500 Subject: [PATCH 7/7] incremented nix version --- nix/flake.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nix/flake.nix b/nix/flake.nix index b6b1af2..e0ab3d5 100644 --- a/nix/flake.nix +++ b/nix/flake.nix @@ -18,7 +18,7 @@ default = self.packages.${pkgs.system}.shunpo; shunpo = pkgs.stdenv.mkDerivation { pname = "shunpo"; - version = "1.0.4"; + version = "1.0.5"; src = builtins.path { path = ../src; }; buildInputs = [ pkgs.bash pkgs.shfmt ];