├── .github
├── dependabot.yml
└── workflows
│ └── ci.yml
├── .gitignore
├── LICENSE
├── README.md
├── completion
└── bash
│ ├── up
│ └── up.bats
├── up
├── up.bats
├── up.gif
└── up.tape
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 | updates:
3 | - package-ecosystem: github-actions
4 | directory: /
5 | schedule:
6 | interval: daily
7 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: ci
2 | on:
3 | push:
4 | branches:
5 | - main
6 | paths-ignore:
7 | - README.md
8 | pull_request:
9 | branches:
10 | - main
11 | paths-ignore:
12 | - README.md
13 | jobs:
14 | test:
15 | runs-on: ubuntu-22.04
16 | permissions:
17 | checks: write
18 | statuses: write
19 | steps:
20 | - name: Check out repository
21 | uses: actions/checkout@v4
22 | - name: Check code style
23 | uses: reviewdog/action-shfmt@v1.0.4
24 | - name: Run static analysis
25 | uses: reviewdog/action-shellcheck@v1.30.0
26 | - name: Run tests
27 | run: |
28 | # workaround for https://github.com/actions/runner-images/issues/9644
29 | mkdir ~/.npm-global
30 | npm config set prefix '~/.npm-global'
31 | export PATH=~/.npm-global/bin:$PATH
32 | npm install -g bats@1.11.0
33 | bats --report-formatter junit . completion/bash
34 | - name: Create test report
35 | uses: dorny/test-reporter@v2.1.0
36 | if: always()
37 | with:
38 | name: Test report
39 | path: report.xml
40 | reporter: java-junit
41 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | report.xml
2 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 Oliver Weiler
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # :climbing: up
2 |
3 | [](https://github.com/helpermethod/up/actions/workflows/ci.yml)
4 | [](https://github.com/helpermethod/up/blob/main/LICENSE)
5 |
6 | > Tired of repeatedly typing `cd ..` to walk up the directory tree? Fed up with defining aliases to jump to the first, second or nth parent directory? `up` to the rescue!
7 |
8 | `up` is a shell function for jumping to a parent directory by name.
9 |
10 |
11 |
12 | ## :sparkles: Features
13 |
14 | * :zap: Lightning fast
15 | * :keyboard: Shell completion for parent directory names
16 | * :shell: Works with Bash and Zsh
17 |
18 | ## :hammer_and_wrench: Installation
19 |
20 | ### :shell: Git & Bash
21 |
22 | Clone `up`'s Git repository.
23 |
24 | ```sh
25 | $ git clone https://github.com/helpermethod/up ~/.up
26 | ```
27 |
28 | Add the following to your `.bashrc` (Linux) or `.bash_profile` (macOS) to install `up`.
29 |
30 | ```sh
31 | . "$HOME/.up/up"
32 | ```
33 |
34 | Add the following to your `.bashrc` (Linux) or `.bash_profile` (macOS) to enable `up`'s shell completion.
35 |
36 | ```sh
37 | . "$HOME/.up/completion/bash/up"
38 | ```
39 |
40 | ### :shell: Git & Zsh
41 |
42 | Clone `up`'s Git repository.
43 |
44 | ```sh
45 | $ git clone https://github.com/helpermethod/up ~/.up
46 | ```
47 |
48 | Add the following to your `.zshrc` to install `up`.
49 |
50 | ```sh
51 | . "$HOME/.up/up"
52 | ```
53 |
54 | Add the following to your `.zshrc` to enable `up`'s shell completion.
55 |
56 | ```sh
57 | autoload -U +X compinit && compinit
58 | autoload -U +X bashcompinit && bashcompinit
59 | . "$HOME/.up/completion/bash/up"
60 | ```
61 |
62 | ## :mag: Usage
63 |
64 | ### Get a list of parent directory names
65 |
66 | ```sh
67 | $ up
68 | .up / Users completion weilero
69 | ```
70 |
71 | ### Jump to a parent directory by name
72 |
73 | ```sh
74 | $ up weilero
75 | ```
76 |
77 | ### Jump to a parent directory by prefix
78 |
79 | ```sh
80 | $ up we
81 | ```
82 |
--------------------------------------------------------------------------------
/completion/bash/up:
--------------------------------------------------------------------------------
1 | _up() {
2 | local -r current_word=${COMP_WORDS[COMP_CWORD]}
3 | local -r pwd_without_leading_slash=${PWD:1}
4 |
5 | local basenames=()
6 | while IFS= read -r -d/; do
7 | basenames+=("$REPLY")
8 | done <<<"$pwd_without_leading_slash"
9 |
10 | [[ $PWD != / ]] && basenames+=(/)
11 |
12 | local candidate
13 |
14 | for basename in "${basenames[@]}"; do
15 | if [[ $basename == "$current_word"* ]]; then
16 | printf -v candidate '%q' "$basename"
17 |
18 | COMPREPLY+=("$candidate")
19 | fi
20 | done
21 | }
22 |
23 | complete -o default -F _up up
24 |
--------------------------------------------------------------------------------
/completion/bash/up.bats:
--------------------------------------------------------------------------------
1 | load up
2 |
3 | assert_contains() {
4 | local -r expected=$1
5 |
6 | shift
7 |
8 | for e; do
9 | [[ $e == "$expected" ]] && return
10 | done
11 |
12 | return 1
13 | }
14 |
15 | @test '_up should autocomplete the list of parent directory names when given no arguments' {
16 | mkdir -p "${BATS_TEST_TMPDIR}"/src/main/java
17 | cd "${BATS_TEST_TMPDIR}"/src/main/java
18 |
19 | COMP_WORDS=(up)
20 | COMP_CWORD=1
21 | _up
22 |
23 | assert_contains / "${COMPREPLY[@]}"
24 | assert_contains src "${COMPREPLY[@]}"
25 | assert_contains main "${COMPREPLY[@]}"
26 | }
27 |
28 | @test '_up should not autocomplete the current directory name when given no arguments' {
29 | mkdir -p "${BATS_TEST_TMPDIR}"/src/main/java
30 | cd "${BATS_TEST_TMPDIR}"/src/main/java
31 |
32 | COMP_WORDS=(up)
33 | COMP_CWORD=1
34 | _up
35 |
36 | ! assert_contains java "${COMPREPLY[@]}"
37 | }
38 |
39 | @test '_up should autocomplete the parent directory name' {
40 | mkdir -p "${BATS_TEST_TMPDIR}"/src/main/java
41 | cd "${BATS_TEST_TMPDIR}"/src/main/java
42 |
43 | COMP_WORDS=(up ma)
44 | COMP_CWORD=1
45 | _up
46 |
47 | assert_contains main "${COMPREPLY[@]}"
48 | }
49 |
50 | @test '_up should autocomplete the parent directory name containing whitespace' {
51 | mkdir -p "${BATS_TEST_TMPDIR}"/com/git\ hub/helpermethod
52 | cd "${BATS_TEST_TMPDIR}"/com/git\ hub/helpermethod
53 |
54 | COMP_WORD=(up gi)
55 | COMP_CWORD=1
56 | _up
57 |
58 | assert_contains "git\ hub" "${COMPREPLY[@]}"
59 | }
60 |
--------------------------------------------------------------------------------
/up:
--------------------------------------------------------------------------------
1 | up() {
2 | (($# == 0)) && cd .. && return
3 | [[ $1 == / ]] && cd / && return
4 |
5 | # shellcheck disable=SC2164
6 | cd "${PWD%"${PWD##*/"$1"/}"}"
7 | }
8 |
--------------------------------------------------------------------------------
/up.bats:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | load up
4 |
5 | @test 'up should jump to the parent directory when called without arguments' {
6 | local -r path=${BATS_TEST_TMPDIR}/src/main/java
7 | mkdir -p "$path"
8 | cd "$path"
9 |
10 | up
11 |
12 | [[ $PWD == "${BATS_TEST_TMPDIR}/src/main" ]]
13 | }
14 |
15 | @test 'up should jump to the parent directory with the given name' {
16 | local -r path=${BATS_TEST_TMPDIR}/src/main/java
17 | mkdir -p "$path"
18 | cd "$path"
19 |
20 | up src
21 |
22 | [[ $PWD == "${BATS_TEST_TMPDIR}/src" ]]
23 | }
24 |
25 | @test 'up should jump to the root directory when called with /' {
26 | cd "${BATS_TEST_TEMPDIR}"
27 |
28 | up /
29 |
30 | [[ $PWD == / ]]
31 | }
32 |
33 | @test 'up should jump to the first parent directory with the given name' {
34 | local -r path=${BATS_TEST_TMPDIR}/java/src/main/java/com/github/helpermethod
35 | mkdir -p "$path"
36 | cd "$path"
37 |
38 | up java
39 |
40 | [[ $PWD == "${BATS_TEST_TMPDIR}/java/src/main/java" ]]
41 | }
42 |
43 | @test 'up should jump to the parent directory with the given name containing whitespace' {
44 | local -r path=${BATS_TEST_TMPDIR}/com/git\ hub/helpermethod
45 | mkdir -p "$path"
46 | cd "$path"
47 |
48 | up git\ hub
49 |
50 | [[ $PWD == "${BATS_TEST_TMPDIR}/com/git hub" ]]
51 | }
52 |
53 | @test 'up should jump to the parent directory with the exact given name' {
54 | local -r path=${BATS_TEST_TMPDIR}/java/build/libs/java-0.0.1-SNAPSHOT
55 | mkdir -p "$path"
56 | cd "$path"
57 |
58 | up java
59 |
60 | [[ $PWD == "${BATS_TEST_TMPDIR}/java" ]]
61 | }
62 |
--------------------------------------------------------------------------------
/up.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/helpermethod/up/a4da4da41434af9b3b210ebeb9615307a6032325/up.gif
--------------------------------------------------------------------------------
/up.tape:
--------------------------------------------------------------------------------
1 | Output up.gif
2 |
3 | Set Width 1024
4 | Set Height 480
5 | Set TypingSpeed 150ms
6 |
7 | Hide
8 | Type "cd ~"
9 | Enter
10 | Type ". .up/up"
11 | Enter
12 | Type ". .up/completion/bash/up"
13 | Enter
14 | Type "clear"
15 | Enter
16 | Show
17 |
18 | Type "cd .up/completion/bash
19 | Enter
20 |
21 | Sleep 2s
22 |
23 | Type "pwd"
24 | Enter
25 |
26 | Sleep 2s
27 |
28 | Type "up "
29 | Tab@2s 2
30 |
31 | Sleep 2s
32 |
33 | Type "we"
34 | Tab@2s 2
35 | Enter
36 |
37 | Sleep 2s
38 |
39 | Type "pwd"
40 | Enter
41 |
42 | Sleep 5s
43 |
--------------------------------------------------------------------------------