Skip to content

Commit dcea509

Browse files
author
Vasiliy Polyakov
committed
save
1 parent 7f7bae9 commit dcea509

File tree

6 files changed

+48
-41
lines changed

6 files changed

+48
-41
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,5 @@
2525
## Links
2626

2727
- [GNU Bash Manual](https://www.gnu.org/software/bash/manual/)
28+
- [Advanced Bash-Scripting Guide](https://tldp.org/LDP/abs/html/)
2829
- [Google Shell Style Guide](https://google.github.io/styleguide/shell.xml)

lib.bash

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
## @file $XDG_DATA_HOME/bash/lib.bash
22
## @brief Bash scripting library.
33
## @author Vasiliy Polyakov
4-
## @date 2016-2019
4+
## @date 2016-2020
55
## @pre bash>=4.0 (GNU Bourne again shell).
66
## @pre coreutils (@c dirname, @c realpath).
77
## @pre doxygen (for API reference, optional).
88

99
#### Source guard #######################################################@{1
10-
[ x"$BASH_VERSION" = x ] && return 1 # Current shell is not Bash
11-
[[ -n $BASH_LIB ]] && return 0 # Library was already sourced
12-
(( BASH_VERSINFO[0] < 4 )) && return 2 # Bash version is not supported
10+
[ x"$BASH_VERSION" = x ] && return 1 # Current shell is not Bash
11+
[[ -n $BASH_LIB ]] && return 0 # Library was already sourced
12+
(( BASH_VERSINFO[0] < 4 )) && return 2 # Bash version is not supported
1313
type -p dirname realpath &>/dev/null || return 3 # Coreutils are not installed
1414

1515
# shellcheck disable=SC2155
@@ -35,7 +35,7 @@ _lib::init() {
3535
## @retval 1 Library was already imported.
3636
## @retval 125 This library was not imported correctly.
3737
## @retval 126 Bash lib was not initialized correctly.
38-
## @retval 127 'library: command not found' (returned by Bash itself).
38+
## @retval 127 'bash_lib: command not found' (returned by Bash itself).
3939
bash_lib() {
4040
[ x"$BASH_LIB" = x ] && return 126
4141

@@ -70,9 +70,9 @@ import() {
7070
# Try to add a filename suffix
7171
[[ ! -f "$lib" ]] && lib+='.sh'
7272

73-
[[ -r $lib ]] || return 2
73+
[[ -r "$lib" ]] || return 2
7474

75-
# shellcheck source=lib/*.sh
75+
# shellcheck source=/dev/null
7676
source "$lib" "$@"
7777
}
7878

lib/colors.sh

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ SGR() {
4343
local OPT OPTARG E='-e' P0='' P1=''
4444
local -i OPTIND
4545
local -a A C C8 C16 C256
46-
46+
4747
while getopts ':Ep' OPT; do
4848
case $OPT in
4949
E) E='' ;;
@@ -67,21 +67,21 @@ SGR() {
6767
bold|b) A+=(1) ;;
6868
dim) A+=(2) ;;
6969
italics|i) A+=(3) ;;
70-
underline|undescore|uline|ul|u) A+=(4) ;;
70+
underline|underscore|uline|ul|u) A+=(4) ;;
7171
blink) A+=(5) ;;
7272
reverse|inverse) A+=(7) ;;
7373
normal|n) A+=(22) ;;
7474
+([0-9])) A+=($1)
7575
esac; shift
7676
done
77-
77+
7878
local -n c="C$COLORS"
7979
if (( ${#c[@]} )); then
8080
A+=("${c[@]}")
8181
else
8282
A+=("${C[@]}")
8383
fi
84-
84+
8585
if (( ${#A[@]} )); then
8686
local IFS=';'
8787
echo -n $E "$P0\e[${A[*]}m$P1"

lib/exceptions.sh

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ bash_lib || return $(($?-1))
1010
import sysexits
1111

1212
#### Private functions ##################################################@{1
13+
# shellcheck disable=SC1004
1314
_exceptions::init() {
14-
## Throw exception if there is non-zero status.
15-
declare -gi EXCEPTIONS_ERREXIT="${1:-0}"
15+
# shellcheck disable=SC2034
16+
declare -gi EXCEPTIONS_ERREXIT="${1:-0}" ##< Throw exception if there is non-zero status.
1617

1718
declare -gA _error ##< Error info. Set by ERR trap handler.
1819
_error[code]=0 ##< Exit/return code (0..255) (@see sysexits.bash).
@@ -79,11 +80,11 @@ _exceptions::match() {
7980

8081
local n c conditions=0 # Sic! It's a zero here. Don't touch!
8182

82-
for n in ${1//*([ \t]);*([ \t])/ }; do
83+
for n in ${1//*([ ]);*([ ])/ }; do
8384
case $n in
8485
$EX_NAMES) c="(_exc[code]==${EX[$n]})" ;;
8586
+([0-9])) c="(_exc[code]==$n)" ;;
86-
+([0-9])*([ \t])-*([ \t])+([0-9]))
87+
+([0-9])*([ ])-*([ ])+([0-9]))
8788
c="(_exc[code]>=${n%%*([ \t])-*([ \t])+([0-9])}&&"
8889
c+="_exc[code]<=${n##+([0-9])*([ \t])-*([ \t])})"
8990
;;
@@ -118,6 +119,7 @@ _exceptions::handler() {
118119
return 0
119120
}
120121

122+
# shellcheck disable=SC2034
121123
_exceptions::try() {
122124
(( _try_level++ ))
123125
_try_source[_try_level]="${BASH_SOURCE[1]}"
@@ -130,9 +132,9 @@ _exceptions::try() {
130132
}
131133

132134
_exceptions::end_try() {
133-
(( _try_level )) || return ${EX[SOFTWARE]}
135+
(( _try_level )) || return "${EX[SOFTWARE]}"
134136

135-
unset _try_source[_try_level] _try_func[_try_level] _try_line[_try_level]
137+
unset '_try_source[_try_level]' '_try_func[_try_level]' '_try_line[_try_level]'
136138
(( _try_level-- ))
137139

138140
_exc_patterns=() _exc_handlers=()
@@ -146,9 +148,9 @@ alias end_try='break; done; _exceptions::end_try '
146148

147149
catch() {
148150
if (( _try_level == 0 )); then
149-
return ${EX[SOFTWARE]}
151+
return "${EX[SOFTWARE]}"
150152
elif [[ -z $1 || -z $2 ]]; then
151-
return ${EX[USAGE]}
153+
return "${EX[USAGE]}"
152154
fi
153155

154156
_exc_patterns+=("$1"); shift
@@ -158,12 +160,12 @@ catch() {
158160
}
159161

160162
throw() {
161-
local -- OPT OPTARG k r=
162-
local -i OPTIND depth=1 i
163+
local -- OPT OPTARG r=
164+
local -i OPTIND OPTERR=0 depth=1 i
163165

164166
# Default values for exception parameters
165167
_exc[code]=1 _exc[continue]=0 _exc[handled]=0
166-
_exc[msg]= _exc[arg]= _exc[source]= _exc[func]= _exc[line]=
168+
_exc[msg]='' _exc[arg]='' _exc[source]='' _exc[func]='' _exc[line]=''
167169
_exc_callstack=()
168170

169171
# Process options
@@ -184,9 +186,9 @@ throw() {
184186
(( OPTIND > 1 )) && shift $(( OPTIND - 1 ))
185187

186188
if (( depth >= 1 )); then
187-
: ${_exc[source]:=${BASH_SOURCE[depth]}}
188-
: ${_exc[func]:=${FUNCNAME[depth]}}
189-
: ${_exc[line]:=${BASH_LINENO[depth-1]}}
189+
: "${_exc[source]:=${BASH_SOURCE[depth]}}"
190+
: "${_exc[func]:=${FUNCNAME[depth]}}"
191+
: "${_exc[line]:=${BASH_LINENO[depth-1]}}"
190192
fi
191193

192194
# Error message (format string).
@@ -212,13 +214,14 @@ throw() {
212214
perror() {
213215
(( _exc[code] )) || return 0
214216

215-
local source= msg
217+
local source='' msg
216218

217219
if [[ $1 == '-s' ]]; then
218220
source=" <${_exc[code]}> at '$(relpath "${_exc[source]}")':${_exc[line]}"
219221
shift
220222
fi
221223

224+
# shellcheck disable=SC2059
222225
msg="$(printf "${_exc[msg]}" "${_exc_args[@]}")"
223226
echo -e "${1:+$1: }$msg$source" >&2
224227

@@ -228,7 +231,7 @@ perror() {
228231
confess() {
229232
(( _exc[code] )) || return 0
230233

231-
local func caller s=
234+
local func caller s=''
232235

233236
perror -s "$1"
234237
for func in "${_exc_callstack[@]}"; do

lib/git.sh

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
## @file $XDG_DATA_HOME/bash/lib/git.sh
22
## @brief Bash functions for Git.
33
## @author Vasiliy Polyakov
4-
## @date 2019
4+
## @date 2019-2020
55
## @pre lib.bash (Bash scripting library).
66
## @pre Git (Git VCS).
77

@@ -15,15 +15,15 @@ git::in_work_tree() {
1515
git::in_git_dir() {
1616
local inside="$(git rev-parse --is-inside-git-dir 2>/dev/null)"
1717
[[ $inside == 'true' ]]
18-
1918
}
2019

2120
git::dir() {
2221
git rev-parse --git-dir 2>/dev/null
2322
}
2423

2524
git::branch() {
26-
git rev-parse --abbrev-ref --symbolic-full-name @
25+
local branch="$(git rev-parse --abbrev-ref --symbolic-full-name @ 2>/dev/null)"
26+
[[ $branch == '@' ]] && echo "$(_ "<no commits>")" || echo "$branch"
2727
}
2828

2929
git::remote() {

lib/prompt.sh

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -73,38 +73,41 @@ prompt::vcs() {
7373
prompt::cmd() {
7474
history -a
7575

76-
if [[ -n $MC_SID ]]; then
77-
# In Midnight Commander
76+
if [[ -n $MC_SID ]]; then # in Midnight Commander
7877
PS1='\u@\h:\w\$ '
7978
return
8079
fi
8180

82-
local R="\[$SGR0\]" TSL='\[\e]2;' FSL='\e\\\]' x u='user'
81+
local R="\[$SGR0\]" TSL='\[\e]2;' FSL='\e\\\]' u='user'
8382
local user at host dir venv char title chroot
84-
(( EUID )) || u='root' # Superuser
83+
(( EUID )) || u='root' # Superuser
8584

8685
# Set prompt fragments
8786
user="${PROMPT_COLOR[$u]}\u$R"
8887
at="${PROMPT_CHAR[at]}"
8988
host="${PROMPT_COLOR[host]}\h$R"
9089
dir="${PROMPT_COLOR[dir]}\w$R"
9190
char="${PROMPT_COLOR[$u]}${PROMPT_CHAR[$u]}$R"
91+
title="$PROMPT_TITLE"
9292

93-
if [[ -n $SSH_TTY ]]; then
94-
# Connected over SSH
93+
if [[ -n $SSH_TTY ]]; then # connected over SSH
9594
at="${PROMPT_COLOR[ssh]}${PROMPT_CHAR[at]}$R"
96-
[[ -n $PROMPT_TITLE ]] && PROMPT_TITLE="[SSH] $PROMPT_TITLE"
95+
[[ -n $title ]] && title="[SSH] $title"
9796
fi
98-
if [[ -n $VIRTUAL_ENV ]]; then
99-
# Python virtual environment is activated
97+
if [[ -n $VIRTUAL_ENV ]]; then # in Python virtual environment
10098
venv=" (${PROMPT_COLOR[venv]}$(relpath "$VIRTUAL_ENV")$R)"
10199
fi
102100

103-
title="${PROMPT_TITLE:+$TSL$PROMPT_TITLE$FSL}"
101+
title="${title:+$TSL$title$FSL}"
104102
chroot="${debian_chroot:+($debian_chroot) }"
105103

106104
# Set prompt
107105
PS1="$title$chroot$user$at$host:$dir$(prompt::vcs)$venv\n╰$char "
108106

109-
echo -en '\e[6n' && read -sdR x && (( ${x##*;} > 1 )) && echo
107+
local stty column
108+
stty="$(stty -g)" && stty raw -echo min 0 \
109+
&& echo -en '\e[6n' && read -sdR column \
110+
&& stty "$stty" && (( ${column##*;} > 1 )) && echo
110111
}
112+
113+
# vim: set et sw=2 ts=2:

0 commit comments

Comments
 (0)