Skip to content

Commit 97dc65c

Browse files
author
Vasiliy Polyakov
committed
save
1 parent 68ae121 commit 97dc65c

File tree

10 files changed

+151
-168
lines changed

10 files changed

+151
-168
lines changed

.gitattributes

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
* text=auto
22

3-
*.sh eol=lf
4-
*.bash eol=lf
5-
*.bats eol=lf
3+
*.sh text eol=lf
4+
*.bash text eol=lf
5+
*.bats text eol=lf
6+
*.awk text eol=lf
67

78
*.md text
89

lib.bash

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ title() { false; }
4141
## @retval 0 Sourced.
4242
## @retval 1 Not sourced.
4343
is_sourced() {
44-
[[ ${FUNCNAME[${1:-1}]} == 'source' ]]
44+
local -i frame="${1:-1}"
45+
[[ ${FUNCNAME[frame]} == 'source' ]]
4546
}
4647

4748
## @brief Is this script imported?
@@ -55,21 +56,22 @@ is_imported() {
5556
}
5657

5758
## @brief Import a library file only once.
58-
## @detail Use `import_once || return $?`
59+
## @detail Use `import_once || return $(($?-1))`
5960
## at the beginning of the Bash library file (@c lib/*.sh).
6061
## @return Import error.
6162
## @retval 0 OK.
62-
## @retval 1 Bash lib was not initialized correctly.
63-
## @retval 2 This lib was not imported correctly.
63+
## @retval 1 Library has been imported already.
64+
## @retval 2 Bash lib was not initialized correctly.
65+
## @retval 3 This library was not imported correctly.
6466
## @retval 127 import_once: command not found (retured by Bash).
6567
import_once() {
66-
[ x"$BASH_LIB" = x ] && return 1
68+
[ x"$BASH_LIB" = x ] && return 2
6769

6870
local name="$(relpath "${BASH_SOURCE[1]}" "$BASH_LIB")"
6971
name="${name%.*}"; name="_BASH_${name^^}_"
7072

71-
eval "(($name))" && return 0
72-
is_imported 2 || return 2
73+
eval "(($name))" && return 1
74+
is_imported 2 || return 3
7375

7476
local -i version="${1:-1}"
7577
eval "declare -gri $name='$version'"

lib/colors.sh

Lines changed: 65 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -5,89 +5,86 @@
55
## @pre lib.bash (Bash scripting library).
66
## @pre ncurses (tput).
77

8-
import_once || return $?
8+
import_once || return $(($?-1))
99

10-
declare -gi COLORS
11-
declare -ga FG BG
12-
declare -gA SGR
10+
if ! type -p tput >/dev/null || [[ $1 == '0' ]]; then
11+
declare -gir COLORS=0
12+
declare -gr SGR0=''
13+
SGR() { :; }
14+
return 0
15+
fi
1316

14-
local -i arrays=0 funcs=0 terminfo=0
15-
while (( $# )); do
16-
case $1 in
17-
0) declare -r COLORS=0 FG=() BG=() SGR=(); return 0 ;;
18-
funcs) funcs=1 ;;
19-
arrays) arrays=1 ;;
20-
terminfo) terminfo=1 ;;
21-
esac; shift
22-
do
17+
declare -gir COLORS="$(tput colors)"
18+
declare -gr SGR0=$'\e[m'
2319

24-
COLORS="$(tput colors)"
20+
_colors::to_attr() {
21+
local OPT OPTARG
22+
local -i OPTIND color bg=0
2523

26-
_colors::get() {
27-
24+
while getopts ':bf' OPT; do
25+
case $OPT in
26+
f) bg=0 ;;
27+
b) bg=10 ;;
28+
esac
29+
done; shift $(( OPTIND - 1 ))
30+
31+
color="$1"
32+
33+
if (( color < 8 && color >= 0 )); then
34+
echo $(( color + 30 + bg ))
35+
elif (( color < 16 )); then
36+
echo $(( color + 82 + bg ))
37+
elif (( color < 256 )); then
38+
echo $(( 38 + bg )) 5 $color
39+
fi
2840
}
2941

3042
SGR() {
43+
local OPT OPTARG E='-e' P0='' P1=''
3144
local -i OPTIND
32-
local OPT OPTARG
33-
local -a a
45+
local -a A C C8 C16 C256
46+
47+
while getopts ':Ep' OPT; do
48+
case $OPT in
49+
E) E='' ;;
50+
p) P0='\[' P1='\]' ;;
51+
esac
52+
done; shift $(( OPTIND - 1 ))
3453

35-
shopt -qs extglob
3654
while (( $# )); do
3755
case $1 in
38-
fg=+([0-9])) a+=() ;;
56+
fg=+([0-9])) C+=($(_colors::to_attr -f "${1#*=}")) ;;
57+
bg=+([0-9])) C+=($(_colors::to_attr -b "${1#*=}")) ;;
58+
fg8=+([0-9])) C8+=($(_colors::to_attr -f "${1#*=}")) ;;
59+
bg8=+([0-9])) C8+=($(_colors::to_attr -b "${1#*=}")) ;;
60+
fg16=+([0-9])) C16+=($(_colors::to_attr -f "${1#*=}")) ;;
61+
bg16=+([0-9])) C16+=($(_colors::to_attr -b "${1#*=}")) ;;
62+
fg256=+([0-9])) C256+=($(_colors::to_attr -f "${1#*=}")) ;;
63+
bg256=+([0-9])) C256+=($(_colors::to_attr -b "${1#*=}")) ;;
64+
fg=@(default|def|d)) A+=(39) ;;
65+
bg=@(default|def|d)) A+=(49) ;;
66+
reset|r) A+=(0) ;;
67+
bold|b) A+=(1) ;;
68+
dim) A+=(2) ;;
69+
italics|i) A+=(3) ;;
70+
underline|undescore|uline|ul|u) A+=(4) ;;
71+
blink) A+=(5) ;;
72+
reverse|inverse) A+=(7) ;;
73+
normal|n) A+=(22) ;;
74+
+([0-9])) A+=($1)
3975
esac; shift
4076
done
41-
}
42-
43-
_colors::init_arrays() {
44-
local -i c
45-
46-
if (( terminfo )); then
47-
for (( c = 0; c < COLORS; c++ )); do
48-
FG[c]="$(tput setaf "$c")"
49-
BG[c]="$(tput setab "$c")"
50-
done
51-
SGR[bold]="$(tput bold)"
52-
SGR[dim]="$(tput dim)"
53-
SGR[italics]="$(tput sitm)"
54-
SGR[uline]="$(tput smul)"
55-
SGR[blink]="$(tput blink)"
56-
SGR[reverse]="$(tput rev)"
57-
SGR[reset]="$(tput sgr0)"
77+
78+
local -n c="C$COLORS"
79+
if (( ${#c[@]} )); then
80+
A+=("${c[@]}")
5881
else
59-
local CSI=$'\e['
60-
for (( c = 0; c < 8 && COLORS >= 8; c++ )); do
61-
FG[c]="${CSI}$((30+c))m"
62-
BG[c]="${CSI}$((40+c))m"
63-
done
64-
for (( c = 8; c < 16 && COLORS >= 16; c++ )); do
65-
FG[c]="${CSI}$((82+c))m"
66-
BG[c]="${CSI}$((92+c))m"
67-
done
68-
for (( c = 16; c < 256 && COLORS >= 256; c++ )); do
69-
FG[c]="${CSI}38;5;${c}m"
70-
BG[c]="${CSI}48;5;${c}m"
71-
done
72-
SGR[bold]="${CSI}1m"
73-
SGR[dim]="${CSI}2m"
74-
SGR[italics]="${CSI}3m"
75-
SGR[uline]="${CSI}4m"
76-
SGR[blink]="${CSI}5m"
77-
SGR[reverse]="${CSI}7m"
78-
SGR[reset]="${CSI}m"
79-
unset CSI
82+
A+=("${C[@]}")
8083
fi
81-
# TODO: add one-letter and digit aliases for SGR
82-
SGR[rev]="${SGR[reverse]}"
83-
SGR[exit]="${SGR[reset]}"
84-
SGR[0]="${SGR[reset]}"
85-
SGR[1]="${SGR[bold]}"
86-
}
87-
88-
colors::unset() {
8984

85+
if (( ${#A[@]} )); then
86+
local IFS=';'
87+
echo -n $E "$P0\e[${A[*]}m$P1"
88+
fi
9089
}
9190

92-
declare -r COLORS FG BG SGR
93-

lib/exceptions.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
## @pre lib.bash (Bash scripting library).
66
## @pre sysexits.sh (exit/return code constants).
77

8-
import_once || return $?
8+
import_once || return $(($?-1))
99
import sysexits
1010

1111
#### Private functions ##################################################@{1

lib/git.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
## @pre lib.bash (Bash scripting library).
66
## @pre Git (Git VCS).
77

8-
import_once || return $?
8+
import_once || return $(($?-1))
99

1010
git::in_work_tree() {
1111
local inside="$(git rev-parse --is-inside-work-tree 2>/dev/null)"

lib/prompt.sh

Lines changed: 62 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,25 @@
88
## @see https://www.askapache.com/linux/bash-power-prompt/
99
## @see https://gitweb.gentoo.org/repo/gentoo.git/tree/app-shells/bash/files/bashrc
1010

11-
import_once || return $?
11+
import_once || return $(($?-1))
1212
import colors
13+
import title
1314
import git
1415

1516
declare -gA PROMPT_COLOR PROMPT_CHAR
17+
declare -gi PROMPT_TITLE=1
1618

17-
PROMPT_COLOR[user]=10
18-
PROMPT_COLOR[root]=9
19-
PROMPT_COLOR[host]='6 6 36'
20-
PROMPT_COLOR[branch]='5 13 207'
21-
PROMPT_COLOR[changed]=3
22-
PROMPT_COLOR[staged]=11
23-
PROMPT_COLOR[action]=9
24-
PROMPT_COLOR[venv]='3 3 190'
19+
PROMPT_COLOR[user]='fg=10 bold'
20+
PROMPT_COLOR[root]='fg=9 bold'
21+
PROMPT_COLOR[host]='fg=6 fg256=36 bold'
22+
PROMPT_COLOR[dir]='fg=15 bold'
23+
PROMPT_COLOR[git]='fg=10'
24+
PROMPT_COLOR[branch]='fg8=5 fg16=13 fg256=207'
25+
PROMPT_COLOR[changed]='fg=3'
26+
PROMPT_COLOR[staged]='fg=11'
27+
PROMPT_COLOR[action]='fg=9'
28+
PROMPT_COLOR[ssh]='fg=9 bold'
29+
PROMPT_COLOR[venv]='fg=3 fg256=190'
2530

2631
PROMPT_CHAR[user]='>'
2732
PROMPT_CHAR[root]='#'
@@ -35,58 +40,68 @@ PROMPT_CHAR[staged]='⊛'
3540
PROMPT_CHAR[stashed]='+'
3641

3742
prompt::init() {
38-
declare -g PROMPT_COMMAND='prompt::cmd'
39-
40-
for k in "${!PROMPT_COLOR[@]}"; do
41-
local -a c=(${PROMPT_COLOR[$k]})
42-
PROMPT_COLOR[$k]="$(tput setaf "${c[${#c[@]}==1||COLORS==8?0:COLORS==16?1:2]}")"
43+
local name
44+
45+
for name in "${!PROMPT_COLOR[@]}"; do
46+
PROMPT_COLOR[$name]="$(SGR -p ${PROMPT_COLOR[$name]})"
4347
done
44-
45-
prompt='\[\e[1;38;5;$((EUID?10:9))m\]\u\[\e[m\]@\[\e[1;38;5;36m\]\h\[\e[m\]:\[\e[1;38;5;12m\]\w\[\e[m\]'
46-
char='\[\e[1;38;5;$((EUID?10:9))m\]$(prompt::char)\[\e[m\]'
47-
if [[ -n $MC_SID ]]; then # Bash is inside of Midnight Commander
48-
PS1="$prompt$char "
49-
else
50-
PS1="$prompt\$(prompt::vcs)\$(prompt::venv)\n╰$char "
48+
49+
if [[ -z $debian_chroot && -r /etc/debian_chroot ]]; then
50+
debian_chroot="$(cat /etc/debian_chroot)"
5151
fi
52-
unset prompt char
52+
53+
declare -r PROMPT_COLOR PROMPT_CHAR
54+
declare -g PROMPT_COMMAND='prompt::cmd;'
5355
export VIRTUAL_ENV_DISABLE_PROMPT=1
5456
}
5557

5658
prompt::vcs() {
57-
local status
59+
local status action
60+
5861
if git::in_work_tree || git::in_git_dir; then
59-
status="git:${PROMPT_COLOR[branch]}$(git::branch)${PROMPT_COLOR[reset]}"
60-
git::is_changed && status+="${PROMPT_COLOR[changed]}*${PROMPT_COLOR[reset]}"
61-
git::is_staged && status+="${PROMPT_COLOR[staged]}${PROMPT_COLOR[reset]}"
62-
local action="$(git::action)"
63-
[[ -n $action ]] && status+="\e[38;5;9m $action${PROMPT_COLOR[reset]}"
62+
status="${PROMPT_COLOR[git]}${PROMPT_CHAR[git]}$R"
63+
status+="${PROMPT_COLOR[branch]}$(git::branch)$R"
64+
git::is_changed && status+="${PROMPT_COLOR[changed]}${PROMPT_CHAR[changed]}$R"
65+
git::is_staged && status+="${PROMPT_COLOR[staged]}${PROMPT_CHAR[staged]}$R"
66+
action="$(git::action)"
67+
[[ -n $action ]] && status+="${PROMPT_COLOR[action]} $action$R"
68+
69+
echo -n " [$status]"
6470
fi
65-
[[ -n $status ]] && echo -ne " [$status]"
6671
}
6772

68-
prompt::venv() {
69-
[[ -n $VIRTUAL_ENV ]] || return
73+
prompt::cmd() {
74+
history -a
7075

71-
72-
echo -en " (${PROMPT_COLOR[venv]}${VIRTUAL_ENV##*/}${PROMPT_COLOR[reset]})"
73-
}
76+
if [[ -n $MC_SID ]]; then
77+
# In Midnight Commander
78+
PS1='\u@\h:\w\$ '
79+
return
80+
fi
7481

75-
prompt::user_color() {
76-
(( EUID )) && echo -en "${PROMPT_COLOR[user]}" || echo -en "${PROMPT_COLOR[root]}"
77-
}
82+
local R="\[$SGR0\]" x u='user' user at host dir venv char chroot
83+
(( EUID )) || u='root' # Superuser
7884

79-
prompt::user_char() {
80-
(( EUID )) && echo -en "${PROMPT_CHAR[user]}" || echo -en "${PROMPT_CHAR[root]}"
81-
}
85+
# Set prompt fragments
86+
user="${PROMPT_COLOR[$u]}\u$R"
87+
at="${PROMPT_CHAR[at]}"
88+
host="${PROMPT_COLOR[host]}\h$R"
89+
dir="${PROMPT_COLOR[dir]}\w$R"
90+
char="${PROMPT_COLOR[$u]}${PROMPT_CHAR[$u]}$R"
91+
chroot="${debian_chroot:+($debian_chroot) }"
8292

83-
prompt::ssh_color() {
84-
[[ -n $SSH_TTY ]] && echo -en "${PROMPT_COLOR[ssh]}" || echo -en "${PROMPT_COLOR[host]}"
85-
}
93+
if [[ -n $SSH_TTY ]]; then
94+
# Connected over SSH
95+
at="${PROMPT_COLOR[ssh]}${PROMPT_CHAR[at]}$R"
96+
fi
97+
if [[ -n $VIRTUAL_ENV ]]; then
98+
# Python virtual environment is activated
99+
venv=" (${PROMPT_COLOR[venv]}$(relpath "$VIRTUAL_ENV")$R)"
100+
fi
86101

87-
prompt::cmd() {
88-
local x
89-
history -a
90-
[[ -z $MC_SID ]] && echo -en '\e[6n' && read -sdR x && (( ${x##*;} > 1 )) && echo
102+
# Set prompt
103+
PS1="$chroot$user$at$host:$dir$(prompt::vcs)$venv\n╰$char "
104+
105+
echo -en '\e[6n' && read -sdR x && (( ${x##*;} > 1 )) && echo
91106
}
92107

lib/sysexits.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
## (/usr/include/sysexits.h
1212
## or http://linux.die.net/include/sysexits.h)
1313

14-
import_once || return $?
14+
import_once || return $(($?-1))
1515

1616
#### Functions ##########################################################@{1
1717
_sysexits::from_h() {

lib/test.sh

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)