From 0d1584121904dfc8dacac19087460e6614a73f95 Mon Sep 17 00:00:00 2001 From: Jintin Date: Sat, 25 Apr 2026 15:13:31 +0800 Subject: [PATCH 1/2] feat: add dynamic argument substitution and placeholders --- aliasme.sh | 42 ++++++++++++++++--- test/aliastest.sh | 100 ++++++++++++++++++++++++++++++++-------------- 2 files changed, 108 insertions(+), 34 deletions(-) diff --git a/aliasme.sh b/aliasme.sh index 1e01fa5..4a48eda 100644 --- a/aliasme.sh +++ b/aliasme.sh @@ -58,11 +58,42 @@ _remove() { } _excute() { + local alias_name="$1" if [ -s "$ALIASME_CMD" ];then while read -u9 -r line; do - if [ "$1" = "$line" ]; then - read -u9 -r line - eval "$line" + if [ "$alias_name" = "$line" ]; then + read -u9 -r cmd + shift # Remove alias name, $@ now has arguments + + local final_cmd="$cmd" + local has_placeholder=false + + # Handle ?1, ?2, etc. (Positional) + local i=1 + for arg in "$@"; do + if [[ "$final_cmd" == *"?"$i* ]]; then + final_cmd="${final_cmd//\?$i/$arg}" + has_placeholder=true + fi + ((i++)) + done + + # Handle ? (All arguments) + if [[ "$final_cmd" == *"?"* ]]; then + # Double check it's not a positional one we missed (e.g. ?99) + local tmp_cmd="${final_cmd//\?[0-9]/}" + if [[ "$tmp_cmd" == *"?"* ]]; then + final_cmd="${final_cmd//\?/"$*"}" + has_placeholder=true + fi + fi + + if [ "$has_placeholder" = true ]; then + eval "$final_cmd" + else + # Default: append arguments if any + eval "$cmd" "$@" + fi return 0 fi done 9< "$ALIASME_CMD" @@ -124,14 +155,15 @@ al(){ echo "al add [name] [command] # add alias command with name" echo "al rm [name] # remove alias by name" echo "al ls # alias list" - echo "al [name] # execute alias associate with [name]" + echo "al [name] [args] # execute alias associate with [name]" + echo " # use ? for all args, ?1, ?2 for positional args" echo "al -v # version information" echo "al -h # help" elif [ "$1" = "-v" ]; then echo "aliasme 3.1.0" echo "visit https://github.com/Jintin/aliasme for more information" else - if ! _excute "$1" ; then + if ! _excute "$@"; then echo "not found" fi fi diff --git a/test/aliastest.sh b/test/aliastest.sh index abd081e..f5cdda3 100755 --- a/test/aliastest.sh +++ b/test/aliastest.sh @@ -1,45 +1,87 @@ #!/bin/bash . test/assert.sh +# Mock ALIASME_DIR for testing to avoid touching user's real aliases +export ALIASME_DIR="/tmp/aliasme_test_$(date +%s)" +export ALIASME_CMD="$ALIASME_DIR/cmd" +mkdir -p "$ALIASME_DIR" + . aliasme.sh -testInit() { - if [[ ! -f ~/.aliasme/path ]]; then - mkdir -p ~/.aliasme && touch ~/.aliasme/path +testAdd() { + local name="$1" + local cmd="$2" + _add "$name" "$cmd" > /dev/null + if [[ $(_list) = *"$name : $cmd"* ]]; then + log_success "Add $name success" + else + log_failure "Add $name failure" + exit 1 fi } -testAlias() { - - name1=testaaa - cmd1=cmdaaa - testAdd "$name1" "$cmd1" - - name2=testbbb - cmd2=cmdbbb - testAdd "$name2" "$cmd2" - - testRemove "$name1" - testRemove "$name2" -} - -testAdd() { - _add "$1" "$2" - if [[ $(_list) = *"$1 : $2"* ]]; then - log_success "path test success" +testRemove() { + local name="$1" + _remove "$name" > /dev/null + if [[ $(_list) = *"$name"* ]]; then + log_failure "Remove $name failure" + exit 1 else - log_failure "path test failure" + log_success "Remove $name success" fi } -testRemove() { - _remove "$1" - if [[ $(_list) = *"$1"* ]]; then - log_failure "remove test failure" +testExecute() { + local name="$1" + shift + local expected="${@: -1}" # last argument is expected output + # All arguments except the last one are passed to 'al' + local args=("${@:1:$#-1}") + + # Capture output of execution + local actual + actual=$(al "$name" "${args[@]}") + + if [ "$actual" == "$expected" ]; then + log_success "Execute $name with args [${args[*]}] -> $actual" else - log_success "remove test success" + log_failure "Execute $name: expected [$expected], but got [$actual]" + exit 1 fi } -testInit -testAlias +# Cleanup function +cleanup() { + rm -rf "$ALIASME_DIR" +} +trap cleanup EXIT + +log_header "Basic Operations" +testAdd "hello" "echo hello" +testAdd "world" "echo world" +testRemove "hello" +testRemove "world" + +log_header "Dynamic Arguments (Append)" +testAdd "say" "echo" +testExecute "say" "hello" "hello" +testExecute "say" "hello world" "hello world" + +log_header "Dynamic Arguments (Fill ?)" +testAdd "greet" "echo hello ?" +testExecute "greet" "Alice" "hello Alice" +testExecute "greet" "Alice and Bob" "hello Alice and Bob" + +log_header "Dynamic Arguments (Multi-Fill ?1 ?2)" +testAdd "swap" "echo ?2 ?1" +testExecute "swap" "A" "B" "B A" +testExecute "swap" "first" "second" "second first" + +log_header "Mixed Dynamic Arguments" +testAdd "mix" "echo ?2 ? ?1" +testExecute "mix" "one" "two" "three" "two one two three one" +# Note: ? replaces with all arguments "$*", so "one two three" +# ?2 is "two", ?1 is "one" +# Result: "two one two three one" + +log_success "All tests passed!" From 33af1f679872f5b6378bee341ed1b263c603ebe0 Mon Sep 17 00:00:00 2001 From: Jintin Date: Sat, 25 Apr 2026 15:19:24 +0800 Subject: [PATCH 2/2] fix: address shellcheck warnings and improve test robustness --- aliasme.sh | 1 + test/aliastest.sh | 18 ++++++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/aliasme.sh b/aliasme.sh index 4a48eda..8aa6d3d 100644 --- a/aliasme.sh +++ b/aliasme.sh @@ -92,6 +92,7 @@ _excute() { eval "$final_cmd" else # Default: append arguments if any + # shellcheck disable=SC2294 eval "$cmd" "$@" fi return 0 diff --git a/test/aliastest.sh b/test/aliastest.sh index f5cdda3..0178698 100755 --- a/test/aliastest.sh +++ b/test/aliastest.sh @@ -2,8 +2,10 @@ . test/assert.sh # Mock ALIASME_DIR for testing to avoid touching user's real aliases -export ALIASME_DIR="/tmp/aliasme_test_$(date +%s)" -export ALIASME_CMD="$ALIASME_DIR/cmd" +ALIASME_DIR="/tmp/aliasme_test_$(date +%s)" +export ALIASME_DIR +ALIASME_CMD="$ALIASME_DIR/cmd" +export ALIASME_CMD mkdir -p "$ALIASME_DIR" . aliasme.sh @@ -34,9 +36,17 @@ testRemove() { testExecute() { local name="$1" shift - local expected="${@: -1}" # last argument is expected output + local expected + expected="${*:$#:1}" # last argument is expected output # All arguments except the last one are passed to 'al' - local args=("${@:1:$#-1}") + local args=() + local i=1 + for arg in "$@"; do + if [ $i -lt "$#" ]; then + args+=("$arg") + fi + ((i++)) + done # Capture output of execution local actual