Skip to content

Commit

Permalink
path_insert_*: Add -p prepend flag, make GLOB optional
Browse files Browse the repository at this point in the history
  • Loading branch information
andsens committed Dec 4, 2024
1 parent df1c6be commit 08ba9bc
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 34 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,17 @@ Append `ELM` or move it to the end if present.

Append `ELM` or move it to the beginning if present.

#### `path_insert_after ELM GLOB`
#### `path_insert_after [-p] ELM [GLOB]`

Insert/move `ELM` immediately after the last occurrence of `GLOB`.
Append `ELM` if no `GLOB` matches were found.
Append `ELM` if no `GLOB` matches were found, prepend if `-p` is set.
`GLOB` is compared using `[[ ${path%/} = $GLOB ]]`, meaning globs
like `/usr/**/bin?(/)` work.

#### `path_insert_before ELM GLOB`
#### `path_insert_before [-p] ELM [GLOB]`

Insert/move `ELM` immediately before the first occurrence of `GLOB`.
**Append** `ELM` if no `GLOB` matches were found.
**Append** `ELM` if no `GLOB` matches were found, prepend if `-p` is set.
`GLOB` is compared using `[[ ${path%/} = $GLOB ]]`, meaning globs
like `/usr/**/bin?(/)` work.

Expand Down
78 changes: 48 additions & 30 deletions path-tools.sh
Original file line number Diff line number Diff line change
Expand Up @@ -13,41 +13,59 @@ path_prepend() {
}

path_insert_after() {
[[ -n $1 && -n $2 && $# -eq 2 ]] || { printf "Usage: path_insert_after ELM GLOB\n" >&2; return 1; }
local new_path new_path_inner path rev_path matched=false
new_path=$(path_remove "$1")
while IFS= read -r -d ':' rev_path; do
path=$(rev <<<"$rev_path")
# shellcheck disable=2053
if [[ ${path%/} != $2 ]] || $matched; then
new_path_inner=$new_path_inner:$rev_path
else
new_path_inner=$new_path_inner:$(rev <<<"$1"):$rev_path
matched=true
local new_path new_path_inner path rev_path prepend=false matched=false
if [[ $1 == '-p' ]]; then prepend=true; shift; fi
[[ -n $1 && $# -le 2 ]] || { printf "Usage: path_insert_after [-p] ELM [GLOB]\n" >&2; return 1; }
if [[ -n $2 ]]; then
new_path=$(path_remove "$1")
while IFS= read -r -d ':' rev_path; do
path=$(rev <<<"$rev_path")
# shellcheck disable=2053
if [[ ${path%/} != $2 ]] || $matched; then
new_path_inner=$new_path_inner:$rev_path
else
new_path_inner=$new_path_inner:$(rev <<<"$1"):$rev_path
matched=true
fi
done < <(rev <<<":$new_path")
new_path_inner=$(rev <<<"$new_path_inner")
new_path=${new_path_inner%:}
if ! $matched; then
if $prepend; then new_path=$1:$new_path
else new_path=$new_path:$1; fi
fi
done < <(rev <<<":$new_path")
new_path_inner=$(rev <<<"$new_path_inner")
new_path=${new_path_inner%:}
$matched || new_path=$new_path:$1
printf "%s\n" "$new_path"
printf "%s\n" "$new_path"
else
if $prepend; then path_prepend "$1"
else path_append "$1"; fi
fi
}

path_insert_before() {
[[ -n $1 && -n $2 && $# -eq 2 ]] || { printf "Usage: path_insert_before ELM GLOB\n" >&2; return 1; }
local new_path new_path_inner path matched=false
new_path=$(path_remove "$1")
while IFS= read -r -d ':' path; do
# shellcheck disable=2053
if [[ ${path%/} != $2 ]] || $matched; then
new_path_inner=$new_path_inner:$path
else
new_path_inner=$new_path_inner:$1:$path
matched=true
local new_path new_path_inner path prepend=false matched=false
if [[ $1 == '-p' ]]; then prepend=true; shift; fi
[[ -n $1 && $# -le 2 ]] || { printf "Usage: path_insert_before [-p] ELM [GLOB]\n" >&2; return 1; }
if [[ -n $2 ]]; then
new_path=$(path_remove "$1")
while IFS= read -r -d ':' path; do
# shellcheck disable=2053
if [[ ${path%/} != $2 ]] || $matched; then
new_path_inner=$new_path_inner:$path
else
new_path_inner=$new_path_inner:$1:$path
matched=true
fi
done <<<"$new_path:"
new_path=${new_path_inner#:}
if ! $matched; then
if $prepend; then new_path=$1:$new_path
else new_path=$new_path:$1; fi
fi
done <<<"$new_path:"
new_path=${new_path_inner#:}
$matched || new_path=$new_path:$1
printf "%s\n" "$new_path"
printf "%s\n" "$new_path"
else
if $prepend; then path_prepend "$1"
else path_append "$1"; fi
fi
}

path_remove() {
Expand Down
20 changes: 20 additions & 0 deletions test.bats
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ setup_file() {
[ "$output" = "$BATS_TEST_DIRNAME/bin:$HOME/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:TEST" ]
}

@test 'path_insert_after -p without match prepends' {
run path_insert_after -p TEST UNMATCHED
[ "$output" = "TEST:$BATS_TEST_DIRNAME/bin:$HOME/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
}

@test 'path_insert_after empty glob appends' {
run path_insert_after TEST
[ "$output" = "$BATS_TEST_DIRNAME/bin:$HOME/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:TEST" ]
}

@test 'path_insert_after with glob match inserts after last match' {
run path_insert_after TEST '*/?(.)local/*'
[ "$output" = "$BATS_TEST_DIRNAME/bin:$HOME/.local/bin:/usr/local/sbin:/usr/local/bin:TEST:/usr/sbin:/usr/bin:/sbin:/bin" ]
Expand All @@ -47,6 +57,16 @@ setup_file() {
[ "$output" = "$BATS_TEST_DIRNAME/bin:$HOME/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:TEST" ]
}

@test 'path_insert_before -p without match prepends' {
run path_insert_before -p TEST UNMATCHED
[ "$output" = "TEST:$BATS_TEST_DIRNAME/bin:$HOME/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" ]
}

@test 'path_insert_before with empty glob appends' {
run path_insert_before TEST
[ "$output" = "$BATS_TEST_DIRNAME/bin:$HOME/.local/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:TEST" ]
}

@test 'path_remove removes literal match' {
run path_remove /usr/local/bin
[ "$output" = "$BATS_TEST_DIRNAME/bin:$HOME/.local/bin:/usr/local/sbin:/usr/sbin:/usr/bin:/sbin:/bin" ]
Expand Down

0 comments on commit 08ba9bc

Please sign in to comment.