File: bash%2B.bash

package info (click to toggle)
git-subrepo 0.4.9-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,552 kB
  • sloc: sh: 7,074; makefile: 273; perl: 226
file content (139 lines) | stat: -rw-r--r-- 3,255 bytes parent folder | download | duplicates (2)
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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# bash+ - Modern Bash Programming
#
# Copyright (c) 2013-2020 Ingy döt Net

set -e

[[ ${BASHPLUS_VERSION-} ]] && return 0

BASHPLUS_VERSION=0.1.0

bash+:version-check() {
  local cmd want got out

  IFS=' ' read -r -a cmd <<< "${1:?}"
  IFS=. read -r -a want <<< "${2:?}"
  : "${want[0]:=0}"
  : "${want[1]:=0}"
  : "${want[2]:=0}"

  if [[ ${cmd[*]} == bash ]]; then
    got=("${BASH_VERSINFO[@]}")
    BASHPLUS_VERSION_CHECK=${BASH_VERSION-}
  else
    [[ ${#cmd[*]} -gt 1 ]] || cmd+=(--version)
    out=$("${cmd[@]}") ||
      { echo "Failed to run '${cmd[*]}'" >&2; exit 1; }
    [[ $out =~ ([0-9]+\.[0-9]+(\.[0-9]+)?) ]] ||
      { echo "Can't determine version number from '${cmd[*]}'" >&2; exit 1; }
    BASHPLUS_VERSION_CHECK=${BASH_REMATCH[1]}
    IFS=. read -r -a got <<< "$BASHPLUS_VERSION_CHECK"
  fi
  : "${got[2]:=0}"

  (( got[0] > want[0] || ((
     got[0] == want[0] && ((
       got[1] > want[1] || ((
       got[1] == want[1] && got[2] >= want[2]
  )) )) )) ))
}

bash+:version-check bash 3.2 ||
  { echo "The 'bashplus' library requires 'Bash 3.2+'." >&2; exit 1; }

@() (echo "$@")  # XXX do we want to keep this?

bash+:export:std() {
  set -o pipefail

  if bash+:version-check bash 4.4; then
    set -o nounset
    shopt -s inherit_errexit
  fi

  echo use die warn
}

# Source a bash library call import on it:
bash+:use() {
  local library_name=${1:?bash+:use requires library name}; shift
  local library_path=; library_path=$(bash+:findlib "$library_name") || true
  [[ $library_path ]] ||
    bash+:die "Can't find library '$library_name'." 1

  source "$library_path"
  if bash+:can "$library_name:import"; then
    "$library_name:import" "$@"
  else
    bash+:import "$@"
  fi
}

# Copy bash+: functions to unprefixed functions
bash+:import() {
  local arg=
  for arg; do
    if [[ $arg =~ ^: ]]; then
      # Word splitting required here
      # shellcheck disable=2046
      bash+:import $(bash+:export"$arg")
    else
      bash+:fcopy "bash+:$arg" "$arg"
    fi
  done
}

# Function copy
bash+:fcopy() {
  bash+:can "${1:?bash+:fcopy requires an input function name}" ||
    bash+:die "'$1' is not a function" 2
  local func
  func=$(type "$1" 3>/dev/null | tail -n+3)
  [[ ${3-} ]] && "$3"
  eval "${2:?bash+:fcopy requires an output function name}() $func"
}

# Find the path of a library
bash+:findlib() {
  local library_name
  library_name=$(tr '[:upper:]' '[:lower:]' <<< "${1//:://}").bash
  local lib=${BASHPLUSLIB:-${BASHLIB:-$PATH}}
  library_name=${library_name//+/\\+}
  IFS=':' read -r -a libs <<< "$lib"
  find "${libs[@]}" -name "${library_name##*/}" 2>/dev/null |
    grep -E "$library_name\$" |
    head -n1
}

bash+:die() {
  local msg=${1:-Died}
  msg=${msg//\\n/$'\n'}

  printf "%s" "$msg" >&2
  if [[ $msg == *$'\n' ]]; then
    exit 1
  else
    printf "\n"
  fi

  local c
  IFS=' ' read -r -a c <<< "$(caller "${DIE_STACK_LEVEL:-${2:-0}}")"
  if (( ${#c[@]} == 2 )); then
    msg=" at line %d of %s"
  else
    msg=" at line %d in %s of %s"
  fi

  # shellcheck disable=2059
  printf "$msg\n" "${c[@]}" >&2
  exit 1
}

bash+:warn() {
  local msg=${1:-Warning}
  printf "%s" "${msg//\\n/$'\n'}\n" >&2
}

bash+:can() {
  [[ $(type -t "${1:?bash+:can requires a function name}") == function ]]
}