aboutsummaryrefslogtreecommitdiff
path: root/sh/shrc.d/path.sh
blob: 23eec75b3ed1c2682b6f105d70611bb22a01e29a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
# Function to manage contents of PATH variable within the current shell
path() {

    # The second argument, the directory, can never have a colon
    case $2 in
        *:*)
            printf >&2 'path(): %s illegal colon\n' "$2"
            return 2
            ;;
    esac

    # Check first argument to figure out operation
    case $1 in

        # List current directories in PATH
        list|'') (
            # shellcheck disable=SC2030
            path=$PATH:
            while [ -n "$path" ] ; do
                dir=${path%%:*}
                path=${path#*:}
                [ -n "$dir" ] || continue
                printf '%s\n' "$dir"
            done
            ) ;;

        # Helper function checks directory argument makes sense
        _argcheck)
            shift
            if [ "$#" -gt 2 ] ; then
                printf >&2 'path(): %s: too many arguments\n' "$1"
                return 2
            fi
            case $2 in
                *:*)
                    printf >&2 'path(): %s: %s contains colon\n' "$@"
                    return 2
                    ;;
            esac
            return 0
            ;;

        # Add a directory at the start of $PATH
        insert)
            [ "$#" -eq 2 ] || set -- "$1" "$PWD"
            path _argcheck "$@" || return
            if path check "$2" ; then
                printf >&2 'path(): %s: %s already in PATH\n' "$@"
                return 1
            fi
            PATH=${2}${PATH:+:"$PATH"}
            ;;

        # Add a directory to the end of $PATH
        append)
            [ "$#" -eq 2 ] || set -- "$1" "$PWD"
            path _argcheck "$@" || return
            if path check "$2" ; then
                printf >&2 'path(): %s: %s already in PATH\n' "$@"
                return 1
            fi
            PATH=${PATH:+"$PATH":}${2}
            ;;

        # Remove a directory from $PATH
        remove)
            [ "$#" -eq 2 ] || set -- "$1" "$PWD"
            path _argcheck "$@" || return
            if ! path check "$2" ; then
                printf >&2 'path(): %s: %s not in PATH\n' "$@"
                return 1
            fi
            PATH=$(
                path=:$PATH:
                path=${path%%:"$2":*}:${path#*:"$2":}
                path=${path#:}
                printf '%s:' "$path"
            )
            PATH=${PATH%%:}
            ;;

        # Check whether a directory is in PATH
        check)
            path _argcheck "$@" || return
            [ "$#" -eq 2 ] || set -- "$1" "$PWD"
            case :$PATH: in
                *:"$2":*) return 0 ;;
            esac
            return 1
            ;;

        # Print help output (also done if command not found)
        help)
            cat <<'EOF'
path(): Manage contents of PATH variable

USAGE:
  path [list]
    Print the current directories in PATH, one per line (default command)
  path insert [DIR]
    Add directory DIR (default $PWD) to the front of PATH
  path append [DIR]
    Add directory DIR (default $PWD) to the end of PATH
  path remove [DIR]
    Remove directory DIR (default $PWD) from PATH
  path check [DIR]
    Return whether directory DIR (default $PWD) is a component of PATH
  path help
    Print this help message
EOF
            ;;

        # Command not found
        *)
            printf >&2 'path(): %s: Unknown command (try "help")\n' "$1"
            return 2
            ;;
    esac
}