Újra bash - Szines fájlnévkiegészítés!
Az alábbi szkript egy függvényt tartalmaz, amivel lehetőségünk van bash alatt a zsh-tól olyannyira irigyelt színes tab completion-t szimulálni. Telepítése két lépésből áll:
- beolvastatni a fájlt, létrehozva ezzel a ‘color_completion’ függvényt:
. color_completion.sh
ne felejtsük a .bash_profile / .bashrc megfelelő szakaszába is beszúrni, ha megtetszett és tartósan is használni akarjuk - társítani egy billentyűhöz, mint ahogyan a Tab megnyomásával a beépített kiegézítőt érjük el:
bind -x '"\234":color_completion $READLINE_POINT "$READLINE_LINE"'
bind '"\eOQ":"\234"'
A\234oktális szám egy szabadon választott keycode, ami még nincs lefoglalva; az\eOQpedig egy ANSI szekvencia, ami az én xterm-emen az F2-nek felel meg. Az egyes funkcióbillentyűk ANSI kódját úgy deríthetjük ki, hogy sima parancssorban megnyomjuk aCtrl-V-t, majd a vizsgált billentyűt. Fogunk látni két karaktert:~[, ez az ESC karakter megjelenése, a parancsban\e-t írjunk helyette. Biztos jobban kézreesik, ha a Tab-hoz rendeljük hozzá a szkriptünket (ekkor\eOQhelyett\C-Ikell) - elvileg lehetséges, de nem próbáltam. A beépített kiegészítőt meg mondjuk aShift-Tab-hoz (\e[Z) vagy fordítva…
Képességei:
- A bash-nél megszokott módon kezeli a symlinkeket
- A szinezés az ls(1) működését követi - ugyanis belsőleg azt hívja -, az
$LS_COLORSváltozó szerkesztésével módosítható
Hiányosságai:
- Kevésbé okos a mezőelválasztók ügyében (fixen szóköz és egyenlőségjel)
- Egyelőre még nem olyan funkciógazdag, mint a zsh vagy maga a bash tabkiegészítő alprogramja - mivel ez a függvény teljesen független a beépített completion képességtől, nem is pluginolható
Plusz funkciói:
- Kevés fájlnál részletes listát ad (
ls -l), sok fájl esetén többoszlopos üzemmódba vált - Tudja a tilde – home könyvtár behelyettesítést
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
#!/bin/bash
#
# Colour filename completion for bash.
# Release 6
#
# How To Install:
#
# + source this file implementing 'color_completion' function
#
# $ source color_completion.sh
#
# + bind a function key to run this command
#
# $ bind -x '"\234":color_completion $READLINE_POINT "$READLINE_LINE"'
# $ bind '"\eOQ":"\234"'
#
# where \234 is a random unused keycode, and \eOQ is the ANSI sequence
# of F2 under xterm. To find ANSI codes of each key, press Ctrl-V
# followed by the desired key in the commandline.
#
# Require bash version 4
#
color_completion() {
local rl_pos=\$1
shift
local rl_str=$@
local word=${rl_str:0:$rl_pos}
word=${word##* }
word=${word##*=}
local save_nullglob
local save_nocaseglob
shopt nullglob >/dev/null && save_nullglob=s || save_nullglob=u
shopt nocaseglob >/dev/null && save_nocaseglob=s || save_nocaseglob=u
shopt -s nullglob
shopt -u nocaseglob
local list
declare -a list
local xword=$word
local retrostute
declare -A retrostute
if expr "$word" : '~/'>/dev/null; then
xword="$HOME${word:1}"
retrostute[tilde]=${#HOME}
fi
list=("$xword"*)
if [ "${#list[@]}" = 0 ]; then
echo -ne "\a"
elif [ "${#list[@]}" = 1 ]; then
local match=${list[0]}
local newword=$match
local k
for k in "${!retrostute[@]}"; do
case "$k" in
tilde)
newword="~${newword:${retrostute[$k]}}"
;;
esac
done
if [ -d "$match" ]; then
if [ ! -L "$match" -o "$word" = "$newword" ]; then
newword="$newword/"
fi
else
newword="$newword "
fi
READLINE_LINE="${READLINE_LINE:0:$(($rl_pos - ${#word}))}$newword${READLINE_LINE:$rl_pos}"
READLINE_POINT=$(($rl_pos - ${#word} + ${#newword}))
else
local basedir=
expr "${list[0]}" : '.*/' >/dev/null && basedir=${list[0]%/*}
local dirname=`dirname "${list[0]}"`
local z=${#list[@]}
local i
local min=-1
for ((i=0; i<z; i++)); do
# save basenames
list[$i]=${list[$i]##*/}
# find shortest word
[ $min = -1 -o $min -gt ${#list[$i]} ] && min=${#list[$i]}
done
(
cd "$dirname"
echo -e "\033[;1mfiles:\033[m $word*"
if [ ${#list[@]} -lt "${LINES:-0}" ]; then
command ls $LS_OPTIONS -lFd "${list[@]}"
else
command ls $LS_OPTIONS -CFd "${list[@]}"
fi
)
# find common part of words
local k
for ((i=1; i<z; i++)); do
for ((k=0; k<min; k++)); do
[ "${list[$i]:$k:1}" != "${list[$((i-1))]:$k:1}" ] && break
done
[ $min -gt $k ] && min=$k
[ $min = 0 ] && break
done
local ngivenpart=${#xword}
[ -n "$basedir" ] && ngivenpart=$((ngivenpart - ${#basedir} - 1))
let min-=ngivenpart
[ $min -lt 0 ] && min=0
local commonpart=${list[0]:$ngivenpart:$min}
READLINE_LINE="${READLINE_LINE:0:$rl_pos}$commonpart${READLINE_LINE:$rl_pos}"
READLINE_POINT=$(($rl_pos + ${#commonpart}))
fi
shopt -$save_nullglob nullglob
shopt -$save_nocaseglob nocaseglob
}
A bejegyzést a szerző CC BY 4.0 licenc alatt engedélyezte.