Some experimental changes. Mode aware help added. Boosted the original help document so that it contains the keybindings. Fixed super key for rat poison mode, you have to choose super_l or super_r.

This commit is contained in:
Storm Dragon
2025-12-02 00:14:43 -05:00
parent 9999306675
commit 10386114fc
4 changed files with 276 additions and 19 deletions

198
i38.sh
View File

@@ -437,15 +437,18 @@ done
# Ratpoison mode is enabled by default
export i3Mode=0
# Prevent setting ratpoison mode key to the same as default mode key
while [[ "$escapeKey" == "$mod" ]]; do
escapeKey="$(menulist "Ratpoison mode key:" Control+t Control+z Control+Escape Alt+Escape Control+space Super)"
while [[ "$escapeKey" == "$mod" ]] || [[ "$escapeKey" =~ ^Super_ && "$mod" == "Mod4" ]] || [[ "$mod" == "Mod4" && "$escapeKey" =~ ^Super_ ]]; do
escapeKey="$(menulist "Ratpoison mode key:" Control+t Control+z Control+Escape Alt+Escape Control+space "Super Left" "Super Right")"
escapeKey="${escapeKey//Alt/Mod1}"
escapeKey="${escapeKey//Super/Mod4}"
escapeKey="${escapeKey//Super Left/Super_L}"
escapeKey="${escapeKey//Super Right/Super_R}"
mod="$(menulist "I3 mod key, for top level bindings:" Alt Super)"
mod="${mod//Alt/Mod1}"
mod="${mod//Super/Mod4}"
if [ "$escapeKey" == "$mod" ]; then
dialog --title "I38" --msgbox "Ratpoison and mod key cannot be the same key." -1 -1
elif [[ "$escapeKey" =~ ^Super_ && "$mod" == "Mod4" ]]; then
dialog --title "I38" --msgbox "Ratpoison mode key cannot be a Super key when mod key is Super." -1 -1
fi
done
# Multiple keyboard layouts
@@ -613,8 +616,8 @@ focus_follows_mouse no
# is used in the bar {} block below.
font pango:monospace 8
# I38 help
bindsym \$mod+Shift+F1 exec ${i3Path}/scripts/i38-help.sh
# I38 help - Open comprehensive HTML guide
bindsym \$mod+Shift+F1 exec $webBrowser ${i3Path}/I38.html
# Run dialog
bindsym \$mod+F2 exec ${i3Path}/scripts/run_dialog.sh
@@ -629,19 +632,29 @@ bindsym \$mod+Control+c exec clipster -s
bindsym \$mod+Control+Delete exec --no-startup-id sgtk-bar
# Use pactl to adjust volume in PulseAudio.
# Increase system volume
bindsym \$mod+XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ +${volumeJump}% & play -qnG synth 0.03 sin 440
# Decrease system volume
bindsym \$mod+XF86AudioLowerVolume exec --no-startup-id pactl set-sink-volume @DEFAULT_SINK@ -${volumeJump}% & play -qnG synth 0.03 sin 440
# Mute/unmute system volume
bindsym \$mod+XF86AudioMute exec --no-startup-id ${i3Path}/scrip/ts/mute-unmute.sh
# Music player controls
# Requires playerctl.
# Increase music volume
bindsym XF86AudioRaiseVolume exec --no-startup-id ${i3Path}/scripts/music_controler.sh incvol $volumeJump
# Decrease music volume
bindsym XF86AudioLowerVolume exec --no-startup-id ${i3Path}/scripts/music_controler.sh decvol $volumeJump
# Previous track
bindsym XF86AudioPrev exec --no-startup-id play -qV0 "| sox -np synth 0.03 sin 2000 pad 0 .02" "| sox -np synth 0.03 sin 2000" norm 1.0 vol 0.4 & ${i3Path}/scripts/music_controler.sh prev
# Pause music playback
bindsym XF86AudioMute exec --no-startup-id play -qV0 "| sox -np synth 0.03 sin 2000 pad 0 .02" "| sox -np synth 0.03 sin 2000" norm 1.0 vol 0.4 & ${i3Path}/scripts/music_controler.sh pause
# Play music
bindsym XF86AudioPlay exec --no-startup-id play -qV0 "| sox -np synth 0.03 sin 2000 pad 0 .02" "| sox -np synth 0.03 sin 2000" norm 1.0 vol 0.4 & ${i3Path}/scripts/music_controler.sh play
# Get music player information
bindsym \$mod+XF86AudioPlay exec --no-startup-id play -qV0 "| sox -np synth 0.03 sin 2000 pad 0 .02" "| sox -np synth 0.03 sin 2000" norm 1.0 vol 0.4 & ${i3Path}/scripts/music_controler.sh info
# Stop music playback
bindsym XF86AudioStop exec --no-startup-id play -qV0 "| sox -np synth 0.03 sin 2000 pad 0 .02" "| sox -np synth 0.03 sin 2000" norm 1.0 vol 0.4 & ${i3Path}/scripts/music_controler.sh stop
# Next track
bindsym XF86AudioNext exec --no-startup-id play -qV0 "| sox -np synth 0.03 sin 2000 pad 0 .02" "| sox -np synth 0.03 sin 2000" norm 1.0 vol 0.4 & ${i3Path}/scripts/music_controler.sh next
# start a terminal
@@ -657,8 +670,9 @@ bindsym \$mod+F1 exec --no-startup-id "${i3Path}/scripts/menu.py"
bindsym \$mod+Control+d exec --no-startup-id ${i3Path}/scripts/desktop.sh
# change focus
# alt+tab and alt+shift+tab
# Focus previous window (alt+shift+tab)
bindsym Mod1+Shift+Tab focus left
# Focus next window (alt+tab)
bindsym Mod1+Tab focus right
# enter fullscreen mode for the focused container
@@ -690,32 +704,52 @@ set \$ws9 "9"
set \$ws10 "10"
# switch to workspace
# Switch to workspace 1
bindsym Control+F1 workspace number \$ws1, exec --no-startup-id ${i3Path}/scripts/announce_workspace.sh
# Switch to workspace 2
bindsym Control+F2 workspace number \$ws2, exec --no-startup-id ${i3Path}/scripts/announce_workspace.sh
# Switch to workspace 3
bindsym Control+F3 workspace number \$ws3, exec --no-startup-id ${i3Path}/scripts/announce_workspace.sh
# Switch to workspace 4
bindsym Control+F4 workspace number \$ws4, exec --no-startup-id ${i3Path}/scripts/announce_workspace.sh
# Switch to workspace 5
bindsym Control+F5 workspace number \$ws5, exec --no-startup-id ${i3Path}/scripts/announce_workspace.sh
# Switch to workspace 6
bindsym Control+F6 workspace number \$ws6, exec --no-startup-id ${i3Path}/scripts/announce_workspace.sh
# Switch to workspace 7
bindsym Control+F7 workspace number \$ws7, exec --no-startup-id ${i3Path}/scripts/announce_workspace.sh
# Switch to workspace 8
bindsym Control+F8 workspace number \$ws8, exec --no-startup-id ${i3Path}/scripts/announce_workspace.sh
# Switch to workspace 9
bindsym Control+F9 workspace number \$ws9, exec --no-startup-id ${i3Path}/scripts/announce_workspace.sh
# Switch to workspace 10
bindsym Control+F10 workspace number \$ws10, exec --no-startup-id ${i3Path}/scripts/announce_workspace.sh
# move focused container to workspace
# Move window to workspace 1
bindsym Control+Shift+F1 move container to workspace number \$ws1, exec spd-say -P important -Cw "moved to workspace 1"
# Move window to workspace 2
bindsym Control+Shift+F2 move container to workspace number \$ws2, exec spd-say -P important -Cw "moved to workspace 2"
# Move window to workspace 3
bindsym Control+Shift+F3 move container to workspace number \$ws3, exec spd-say -P important -Cw "moved to workspace 3"
# Move window to workspace 4
bindsym Control+Shift+F4 move container to workspace number \$ws4, exec spd-say -P important -Cw "moved to workspace 4"
# Move window to workspace 5
bindsym Control+Shift+F5 move container to workspace number \$ws5, exec spd-say -P important -Cw "moved to workspace 5"
# Move window to workspace 6
bindsym Control+Shift+F6 move container to workspace number \$ws6, exec spd-say -P important -Cw "moved to workspace 6"
# Move window to workspace 7
bindsym Control+Shift+F7 move container to workspace number \$ws7, exec spd-say -P important -Cw "moved to workspace 7"
# Move window to workspace 8
bindsym Control+Shift+F8 move container to workspace number \$ws8, exec spd-say -P important -Cw "moved to workspace 8"
# Move window to workspace 9
bindsym Control+Shift+F9 move container to workspace number \$ws9, exec spd-say -P important -Cw "moved to workspace 9"
# Move window to workspace 10
bindsym Control+Shift+F10 move container to workspace number \$ws10, exec spd-say -P important -Cw "moved to workspace 10"
# A mode that will pass all keys except $mod+shift+backspace to the current application.
# Use $mod+shift+backspace to exit the mode.
# Enter bypass mode
bindsym $mod+shift+BackSpace mode "bypass"
mode "bypass" {
# Exit bypass mode.
@@ -725,9 +759,9 @@ bindsym $mod+Shift+BackSpace mode "default"
EOF
# ocr through speech-dispatcher
echo "bindsym ${mod}+F5 exec ${i3Path}/scripts/ocr.py" >> ${i3Path}/config
# Interrupt speech-dispatcher output
# Perform OCR on screen
echo "bindsym ${mod}+F5 exec ${i3Path}/scripts/ocr.py" >> ${i3Path}/config
# Interrupt speech output
echo "bindsym ${mod}+Shift+F5 exec spd-say -C" >> ${i3Path}/config
# Multiple keyboard layouts if requested.
@@ -740,6 +774,9 @@ cat << EOF >> ${i3Path}/config
# Panel mode configuration
bindsym Control+Mod1+Tab mode "panel"
mode "panel" {
# Panel mode keybindings help bound to F1
bindsym F1 exec ${i3Path}/scripts/i38-help-panel.sh, mode "default"
# Weather information bound to w
bindsym w exec --no-startup-id ${i3Path}/scripts/weather.sh, mode "default"
@@ -776,12 +813,11 @@ EOF
# Create ratpoison mode if requested.
if [[ -n "${escapeKey}" ]]; then
cat << EOF >> ${i3Path}/config
# Enter ratpoison mode
bindsym $escapeKey mode "ratpoison"
mode "ratpoison" {
# I38 help bound to ?
bindsym Shift+slash exec ${i3Path}/scripts/i38-help.sh, mode "default"
# I38 HTML documentation bound to F1
bindsym F1 exec $webBrowser ${i3Path}/I38.html, mode "default"
# Ratpoison mode keybindings help bound to F1
bindsym F1 exec ${i3Path}/scripts/i38-help-rp.sh, mode "default"
# Terminal emulator bound to c
bindsym c exec $sensibleTerminal, mode "default"
# Text editor bound to e
@@ -952,7 +988,7 @@ else
fi)
# First run help documentation
exec --no-startup-id bash -c 'if [[ -f "${i3Path}/firstrun" ]]; then ${webBrowser} "${i3Path}/I38.html"& rm "${i3Path}/firstrun"; fi'
exec --no-startup-id bash -c 'if [[ -f "${i3Path}/firstrun" ]]; then ${webBrowser} "${i3Path}/I38.html" & sleep 1 && rm "${i3Path}/firstrun"; fi'
# If you want to add personal customizations to i3, add them in ${i3Path}/customizations
# It is not overwritten when the config file is recreated.
@@ -986,7 +1022,8 @@ fi
# More readable version of variables.
escapeKey="${escapeKey//Mod1/Alt}"
escapeKey="${escapeKey//Mod4/Super}"
escapeKey="${escapeKey//Super_L/Super Left}"
escapeKey="${escapeKey//Super_R/Super Right}"
mod="${mod//Mod1/Alt}"
mod="${mod//Mod4/Super}"
webBrowser="${webBrowser##*/}"
@@ -994,6 +1031,133 @@ screenReader="${screenReader##*/}"
textEditor="${textEditor##*/}"
fileBrowser="${fileBrowser##*/}"
# Extract and categorize top-level keybindings for documentation
# Generate HTML directly since we're inserting into an already-converted HTML file
# Extract comment+bindsym pairs from config (excluding mode blocks)
declare -a applications workspaceSwitch workspaceMove windowMgmt utilities modes media
# Read the config and extract top-level bindings with their comments
while IFS= read -r line; do
if [[ "$line" =~ ^#.*$ ]]; then
# This is a comment line - save it
lastComment="${line#\# }"
elif [[ "$line" =~ ^bindsym.*$ ]]; then
# This is a bindsym line - pair it with the last comment
keybinding="${line#bindsym }"
keybinding="${keybinding//\\$/}"
# Extract just the key combination (first 1-2 words before 'exec', 'workspace', etc)
keyCombo=$(echo "$keybinding" | awk '{print $1, $2}' | sed 's/workspace.*//' | sed 's/exec.*//' | sed 's/kill.*//' | sed 's/fullscreen.*//' | sed 's/scratchpad.*//' | sed 's/mode.*//' | sed 's/ *$//')
# Clean up key combo
keyCombo="${keyCombo//\$mod/$mod}"
keyCombo="${keyCombo//Mod1/Alt}"
keyCombo="${keyCombo//Mod4/Super}"
# Categorize based on the comment or the action
if [[ "$keybinding" =~ workspace.*number ]] && [[ "$keybinding" =~ Control+F ]]; then
# Switch to workspace
workspaceSwitch+=("$keyCombo|$lastComment")
elif [[ "$keybinding" =~ move.*container.*workspace ]] && [[ "$keybinding" =~ Control+Shift+F ]]; then
# Move to workspace
workspaceMove+=("$keyCombo|$lastComment")
elif [[ "$lastComment" =~ (menu|terminal|editor|browser|Run dialog) ]] || [[ "$keybinding" =~ (menu.py|sensible-terminal|run_dialog) ]]; then
applications+=("$keyCombo|$lastComment")
elif [[ "$lastComment" =~ (focus|window|fullscreen|scratchpad|kill|close) ]] || [[ "$keybinding" =~ (focus|kill|fullscreen|scratchpad) ]]; then
windowMgmt+=("$keyCombo|$lastComment")
elif [[ "$lastComment" =~ (mode|ratpoison|panel|bypass) ]] || [[ "$keybinding" =~ mode ]]; then
modes+=("$keyCombo|$lastComment")
elif [[ "$keybinding" =~ (Audio|music_controler|pactl) ]]; then
media+=("$keyCombo|$lastComment")
else
utilities+=("$keyCombo|$lastComment")
fi
lastComment=""
fi
done < <(sed -n '/^mode "/,/^}$/!p' "${i3Path}/config" | grep -E '^#|^bindsym')
# Build HTML tables
{
echo "<h4>Default Mode Keybindings</h4>"
# Applications
if [[ ${#applications[@]} -gt 0 ]]; then
echo "<p><strong>Applications:</strong></p>"
echo "<table><thead><tr><th>Key</th><th>Action</th></tr></thead><tbody>"
for item in "${applications[@]}"; do
IFS='|' read -r key desc <<< "$item"
echo "<tr><td><code>$key</code></td><td>$desc</td></tr>"
done
echo "</tbody></table>"
fi
# Workspace Navigation
if [[ ${#workspaceSwitch[@]} -gt 0 ]] || [[ ${#workspaceMove[@]} -gt 0 ]]; then
echo "<p><strong>Workspace Navigation:</strong></p>"
echo "<table><thead><tr><th>Key</th><th>Action</th></tr></thead><tbody>"
echo "<tr><td><code>Control+F1</code> through <code>F10</code></td><td>Switch to workspace 1-10</td></tr>"
echo "<tr><td><code>Control+Shift+F1</code> through <code>F10</code></td><td>Move window to workspace 1-10</td></tr>"
echo "</tbody></table>"
fi
# Window Management
if [[ ${#windowMgmt[@]} -gt 0 ]]; then
echo "<p><strong>Window Management:</strong></p>"
echo "<table><thead><tr><th>Key</th><th>Action</th></tr></thead><tbody>"
for item in "${windowMgmt[@]}"; do
IFS='|' read -r key desc <<< "$item"
echo "<tr><td><code>$key</code></td><td>$desc</td></tr>"
done
echo "</tbody></table>"
fi
# Utilities
if [[ ${#utilities[@]} -gt 0 ]]; then
echo "<p><strong>Utilities:</strong></p>"
echo "<table><thead><tr><th>Key</th><th>Action</th></tr></thead><tbody>"
for item in "${utilities[@]}"; do
IFS='|' read -r key desc <<< "$item"
echo "<tr><td><code>$key</code></td><td>$desc</td></tr>"
done
echo "</tbody></table>"
fi
# Modes
if [[ ${#modes[@]} -gt 0 ]]; then
echo "<p><strong>Modes:</strong></p>"
echo "<table><thead><tr><th>Key</th><th>Action</th></tr></thead><tbody>"
for item in "${modes[@]}"; do
IFS='|' read -r key desc <<< "$item"
echo "<tr><td><code>$key</code></td><td>$desc</td></tr>"
done
echo "</tbody></table>"
fi
# Media (if any)
if [[ ${#media[@]} -gt 0 ]]; then
echo "<p><strong>Media Controls:</strong></p>"
echo "<table><thead><tr><th>Key</th><th>Action</th></tr></thead><tbody>"
for item in "${media[@]}"; do
IFS='|' read -r key desc <<< "$item"
echo "<tr><td><code>$key</code></td><td>$desc</td></tr>"
done
echo "</tbody></table>"
fi
} > "${i3Path}/toplevel_temp.txt"
# Replace TOPLEVELKEYBINDINGS placeholder with the generated HTML content
awk '
/TOPLEVELKEYBINDINGS/ {
system("cat '"${i3Path}"'/toplevel_temp.txt")
next
}
{ print }
' "${i3Path}/I38.html" > "${i3Path}/I38.html.tmp" && mv "${i3Path}/I38.html.tmp" "${i3Path}/I38.html"
rm -f "${i3Path}/toplevel_temp.txt"
# Customize the html file to the user's choices.
sed -i -e "s|BROWSER|${webBrowser}|g" \
-e "s|MODKEY|${mod}|g" \