Skip to content

Commit 8993591

Browse files
zdykstraahesford
andcommitted
Enable global help system
Enable a global help system, bind alt-h by default to all instances of fzf and sk. The bind executes zfsbootmenu-help -L $HELP_SECTION. Before invoking each instance of fzf/sk, set HELP_SECTION to the appropriate value (MAIN, SNAPSHOT, ...). zfsbootmenu-help then uses this argument to pre-sort the list of topics, pushing that topic to the head of the list / pre-selecting it. The documentation is internal to zfsbootmenu-help, and is created using a very simple templating system with basic colors and text centering. fold is used to word wrap based on the size of the preview window. The preview window size is calculated based on the number of columns minus 26 characters (the longest topic title + fzf marker ). When adding new help sections, care should be taken with colorizing text. Because ANSI escape sequences are used, fold is not able to correctly calculate the length of given word, so it word wraps incorrectly. Closes #92 Co-authored-by: Zach Dykstra <[email protected]> Co-authored-by: Andrew J. Hesford <[email protected]>
1 parent 7879876 commit 8993591

File tree

4 files changed

+216
-13
lines changed

4 files changed

+216
-13
lines changed

90zfsbootmenu/module-setup.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ install() {
8080
"tac"
8181
"blkid"
8282
"awk"
83+
"fold"
8384
)
8485

8586
for _exec in "${essential_execs[@]}"; do
@@ -132,6 +133,7 @@ install() {
132133
inst_simple "${moddir}/zfs-chroot" "/bin/zfs-chroot" || _ret=$?
133134
inst_simple "${moddir}/zfsbootmenu.sh" "/bin/zfsbootmenu" || _ret=$?
134135
inst_simple "${moddir}/zfsbootmenu-input.sh" "/bin/zfsbootmenu-input" || _ret=$?
136+
inst_simple "${moddir}/zfsbootmenu-help.sh" "/bin/zfsbootmenu-help" || _ret=$?
135137
inst_hook cmdline 95 "${moddir}/zfsbootmenu-parse-commandline.sh" || _ret=$?
136138
inst_hook pre-mount 90 "${moddir}/zfsbootmenu-exec.sh" || _ret=$?
137139

90zfsbootmenu/zfsbootmenu-help.sh

Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
#!/bin/bash
2+
# vim: softtabstop=2 shiftwidth=2 expandtab
3+
WIDTH="$( tput cols )"
4+
PREVIEW_SIZE=$(( WIDTH - 26 ))
5+
[ ${PREVIEW_SIZE} -lt 10 ] && PREVIEW_SIZE=10
6+
7+
[ -z "${FUZZYSEL}" ] && FUZZYSEL="fzf"
8+
9+
center() {
10+
printf "%*s" $(( (${#1} + WIDTH ) / 2)) "${1}"
11+
}
12+
13+
colorize() {
14+
color="${1}"
15+
shift
16+
case "${color}" in
17+
black) echo -e -n '\033[0;30m' ;;
18+
red) echo -e -n '\033[0;31m' ;;
19+
green) echo -e -n '\033[0;32m' ;;
20+
orange) echo -e -n '\033[0;33m' ;;
21+
blue) echo -e -n '\033[0;34m' ;;
22+
magenta) echo -e -n '\033[0;35m' ;;
23+
cyan) echo -e -n '\033[0;36m' ;;
24+
lightgray) echo -e -n '\033[0;37m' ;;
25+
darkgray) echo -e -n '\033[1;30m' ;;
26+
lightred) echo -e -n '\033[1;31m' ;;
27+
lightgreen) echo -e -n '\033[1;32m' ;;
28+
yellow) echo -e -n '\033[1;33m' ;;
29+
lightblue) echo -e -n '\033[1;34m' ;;
30+
lightmagenta) echo -e -n '\033[1;35m' ;;
31+
lightcyan) echo -e -n '\033[1;36m' ;;
32+
white) echo -e -n '\033[1;37m' ;;
33+
*) echo -e -n '\033[0m' ;;
34+
esac
35+
echo -e -n "$@"
36+
echo -e -n '\033[0m'
37+
}
38+
39+
help_pager() {
40+
WANTED="${1}"
41+
42+
SORTED=()
43+
for SECTION in "${SECTIONS[@]}"; do
44+
if ! [[ $SECTION =~ ${WANTED} ]]; then
45+
SORTED+=("${SECTION}")
46+
else
47+
FINAL="${SECTION}"
48+
fi
49+
done
50+
SORTED+=("${FINAL}")
51+
52+
printf '%s\n' "${SORTED[@]}" | ${FUZZYSEL} \
53+
--prompt 'Topic >' \
54+
--with-nth=2.. \
55+
--bind pgup:preview-up,pgdn:preview-down \
56+
--preview="$0 -s {1}" \
57+
--preview-window="right:${PREVIEW_SIZE}:sharp:wrap" \
58+
--tac \
59+
--color='border:6'
60+
}
61+
62+
# shellcheck disable=SC2034
63+
read -r -d '' MAIN <<EOF
64+
$( colorize magenta "$( center "Main Menu")" )
65+
$( colorize lightblue "[ENTER] boot" )
66+
Boot the selected boot environment, with the listed kernel and kernel command line visible at the top of the screen.
67+
68+
$( colorize lightblue "[ALT+K] kernel" )
69+
Access a list of kernels available in the boot environment.
70+
71+
$( colorize lightblue "[ALT+D] set bootfs" )
72+
Set the selected boot environment as the default for the pool.
73+
74+
The operation will fail gracefully if the pool can not be set $( colorize red "read/write" ).
75+
76+
$( colorize lightblue "[ALT+S] snapshots" )
77+
Access a list of snapshots of the selected boot environment. New boot environments can be created here.
78+
79+
$( colorize lightblue "[ALT+C] cmdline" )
80+
Temporarily edit the kernel command line that will be used to boot the chosen kernel in the selected boot environment. This change does not persist across reboots.
81+
82+
$( colorize lightblue "[ALT+P] Pool status" )
83+
View the health and status of each imported pool.
84+
EOF
85+
SECTIONS+=("MAIN Main Menu")
86+
87+
# shellcheck disable=SC2034
88+
read -r -d '' SNAPSHOT <<EOF
89+
$( colorize magenta "$( center "Snapshot Management")" )
90+
$( colorize lightblue "[ENTER] duplicate" )
91+
Creation method: $( colorize red "zfs send | zfs recv" )
92+
93+
This creates a boot environment that does not depend on any other snapshots, allowing it to be destroyed at will. The new boot environment will immediately consume space on the pool equal to the $( colorize lightgray "REFER" ) value of the snapshot.
94+
95+
A duplicated boot environment is commonly used if you need a new boot environment without any associated snapshots.
96+
97+
The operation will fail gracefully if the pool can not be set $( colorize red "read/write" ).
98+
99+
If $( colorize red "mbuffer" ) is available, it is used to provide feedback.
100+
101+
$( colorize lightblue "[ALT+X] clone and promote" )
102+
Creation method: $( colorize red "zfs clone" ) , $( colorize red "zfs promote" )
103+
104+
This creates a boot environment that is not dependent on the origin snapshot, allowing you to destroy the file system that the clone was created from. A cloned and promoted boot environment is commonly used when you've done an upgrade but want to preserve historical snapshots.
105+
106+
The operation will fail gracefully if the pool can not be set $( colorize red "read/write" ).
107+
108+
$( colorize lightblue "[ALT+C] clone" )
109+
Creation method: $( colorize red "zfs clone" )
110+
111+
This creates a boot environment from a snapshot with out modifying snapshot inheritence. A cloned boot environment is commonly used if you need to boot a previous system state for a short time and then discard the environment.
112+
113+
The operation will fail gracefully if the pool can not be set $( colorize red "read/write" ).
114+
115+
$( colorize lightblue "[ALT+D] diff" )
116+
Compare the differences between the selected snapshot and the current state of the boot environment.
117+
118+
The operation will fail gracefully if the pool can not be set $( colorize red "read/write" ).
119+
EOF
120+
SECTIONS+=("SNAPSHOT Snapshot Management")
121+
122+
# shellcheck disable=SC2034
123+
read -r -d '' KERNEL <<EOF
124+
$( colorize magenta "$( center "Kernel Management")" )
125+
$( colorize lightblue "[ENTER] boot" )
126+
Immediately boot the chosen kernel in the selected boot environment, with the kernel command line shown at the top of the screen.
127+
128+
$( colorize lightblue "[ALT+D] set default" )
129+
Set the selected kernel as the default for the boot environment.
130+
131+
The ZFS property $( colorize green "org.zfsbootmenu:kernel" ) is used to store the default kernel for the boot environment.
132+
133+
The operation will fail gracefully if the pool can not be set $( colorize red "read/write" ).
134+
135+
EOF
136+
SECTIONS+=("KERNEL Kernel Management")
137+
138+
# shellcheck disable=SC2034
139+
read -r -d '' DIFF <<EOF
140+
$( colorize magenta "$( center "Diff Viewer")" )
141+
$( colorize lightblue "Column 1 descriptions" )
142+
$( colorize orange "-") The path has been removed
143+
$( colorize orange "+") The path has been created
144+
$( colorize orange "M") The path has been modified
145+
$( colorize orange "R") The path has been renamed
146+
147+
$( colorize lightblue "Column 2 descriptions" )
148+
$( colorize orange "B") Block device
149+
$( colorize orange "C") Character device
150+
$( colorize orange "/") Directory
151+
$( colorize orange ">") Door
152+
$( colorize orange "|") Named pipe
153+
$( colorize orange "@") Symbolic link
154+
$( colorize orange "P") Event port
155+
$( colorize orange "=") Socket
156+
$( colorize orange "F") Regular file
157+
158+
EOF
159+
SECTIONS+=("DIFF Diff Viewer")
160+
161+
# shellcheck disable=SC2034
162+
read -r -d '' POOL <<EOF
163+
$( colorize magenta "$( center "zpool Health")" )
164+
$( colorize lightblue "[ALT+R] Rewind checkpoint" )
165+
If a pool checkpoint is available, the selected pool is exported and then imported with the $( colorize red "--rewind-to-checkpoint" ) flag set.
166+
167+
The operation will fail gracefully if the pool can not be set $( colorize red "read/write" ).
168+
EOF
169+
SECTIONS+=("POOL ZPOOL Health")
170+
171+
while getopts "lL:s:" opt; do
172+
case "${opt}" in
173+
l)
174+
printf '%s\n' "${SECTIONS[@]}"
175+
exit
176+
;;
177+
L)
178+
help_pager "${OPTARG}"
179+
exit
180+
;;
181+
s)
182+
section="${OPTARG}"
183+
echo "${!section}" | fold -s -w "${FZF_PREVIEW_COLUMNS}"
184+
exit
185+
;;
186+
?)
187+
exit
188+
;;
189+
*)
190+
exit
191+
;;
192+
esac
193+
done
194+
195+
# No options detected, show the main help section
196+
help_pager "MAIN"

90zfsbootmenu/zfsbootmenu-lib.sh

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -76,8 +76,9 @@ draw_kernel() {
7676

7777
benv="${1}"
7878

79-
selected="$( ${FUZZYSEL} --prompt "${benv} > " --tac --expect=alt-d \
80-
--with-nth=2 --header="[ENTER] boot [ALT+D] set default [ESC] back" \
79+
selected="$( HELP_SECTION=KERNEL ${FUZZYSEL} --prompt "${benv} > " \
80+
--tac --expect=alt-d --with-nth=2 \
81+
--header="[ENTER] boot [ALT+D] set default [ESC] back" \
8182
--preview-window="up:${PREVIEW_HEIGHT}" \
8283
--preview="zfsbootmenu-preview.sh ${BASE} ${benv} ${BOOTFS}" < "${BASE}/${benv}/kernels" )"
8384
ret=$?
@@ -96,10 +97,11 @@ draw_snapshots() {
9697
benv="${1}"
9798

9899
selected="$( zfs list -t snapshot -H -o name "${benv}" |
99-
${FUZZYSEL} --prompt "Snapshot > " --tac --expect=alt-x,alt-c,alt-d \
100-
--preview="zfsbootmenu-preview.sh ${BASE} ${benv} ${BOOTFS}" \
101-
--preview-window="up:${PREVIEW_HEIGHT}" \
102-
--header="[ENTER] duplicate [ALT+X] clone and promote [ALT+C] clone only [ALT+D] show diff [ESC] back" )"
100+
HELP_SECTION=SNAPSHOT ${FUZZYSEL} --prompt "Snapshot > " \
101+
--tac --expect=alt-x,alt-c,alt-d \
102+
--preview="zfsbootmenu-preview.sh ${BASE} ${benv} ${BOOTFS}" \
103+
--preview-window="up:${PREVIEW_HEIGHT}" \
104+
--header="[ENTER] duplicate [ALT+X] clone and promote [ALT+C] clone only [ALT+D] show diff [ESC] back" )"
103105
ret=$?
104106
# shellcheck disable=SC2119
105107
csv_cat <<< "${selected}"
@@ -131,13 +133,14 @@ draw_diff() {
131133
# shellcheck disable=SC2016
132134
( zfs diff -F -H "${snapshot}" "${diff_target}" & echo $! >&3 ) 3>/tmp/diff.pid | \
133135
sed "s,${mnt},," | \
134-
${FUZZYSEL} --prompt "Files > " \
136+
HELP_SECTION=DIFF ${FUZZYSEL} --prompt "${snapshot} > " \
135137
--preview="zfsbootmenu-preview.sh ${BASE} ${diff_target} ${BOOTFS}" \
136138
--preview-window="up:${PREVIEW_HEIGHT}" \
137139
--bind 'esc:execute-silent( kill $( cat /tmp/diff.pid ) )+abort'
138140

139141
test -f /tmp/diff.pid && rm /tmp/diff.pid
140142
umount "${mnt}"
143+
141144
return
142145
}
143146

@@ -149,16 +152,16 @@ draw_pool_status() {
149152
local selected ret
150153

151154
selected="$( zpool list -H -o name |
152-
${FUZZYSEL} --prompt "Pool > " --tac --expect=alt-r \
153-
--preview="zpool status -v {}" \
154-
--header="[ALT+R] Rewind checkpoint [ESC] back" \
155+
HELP_SECTION=POOL ${FUZZYSEL} --prompt "Pool > " \
156+
--tac --expect=alt-r \
157+
--preview="zpool status -v {}" \
158+
--header="[ALT+R] Rewind checkpoint [ESC] back" \
155159
)"
156160
ret=$?
157161
csv_cat <<< "${selected}"
158162
return ${ret}
159163
}
160164

161-
162165
# arg1: bootfs kernel initramfs
163166
# prints: nothing
164167
# returns: 1 on error, otherwise does not return

90zfsbootmenu/zfsbootmenu.sh

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,13 @@ OLDIFS="$IFS"
2626

2727
if command -v fzf >/dev/null 2>&1; then
2828
export FUZZYSEL=fzf
29-
export FZF_DEFAULT_OPTS="--layout=reverse-list --cycle --inline-info --tac"
29+
#shellcheck disable=SC2016
30+
export FZF_DEFAULT_OPTS='--layout=reverse-list --cycle --inline-info --tac --color=16 --bind "alt-h:execute[ zfsbootmenu-help -L ${HELP_SECTION:-MAIN} ]"'
3031
export PREVIEW_HEIGHT=2
3132
elif command -v sk >/dev/null 2>&1; then
3233
export FUZZYSEL=sk
33-
export SKIM_DEFAULT_OPTIONS="--layout=reverse-list --inline-info --tac --color=16"
34+
#shellcheck disable=SC2016
35+
export SKIM_DEFAULT_OPTIONS='--layout=reverse-list --inline-info --tac --color=16 --bind "alt-h:execute[ zfsbootmenu-help -L ${HELP_SECTION:-MAIN} ]"'
3436
export PREVIEW_HEIGHT=3
3537
fi
3638

0 commit comments

Comments
 (0)