Changeset - 41ee6a32070a
[Not reviewed]
master
0 1 0
Branko Majic (branko) - 8 months ago 2025-03-19 23:08:05
branko@majic.rs
[cheatsheet_viewer.sh] Added support for automatically activating overlay mode based on current window title.
1 file changed with 45 insertions and 7 deletions:
0 comments (0 inline, 0 general)
utils/cheatsheet_viewer.sh
Show inline comments
 
@@ -60,24 +60,26 @@ All configuration is stored under user's own home directory at:
 
Individual profiles are stored as sub-directories, with each
 
sub-directory representing an individual profile that can be
 
activated. Base directory for profiles is:
 

	
 
  - ~/.config/cheatsheet_viewer/profiles/
 

	
 
Each profile definition consists out of a number of configuration
 
files:
 

	
 
  - ~/.config/cheatsheet_viewer/profiles/PROFILE/cheatsheets (list of
 
    cheatsheet files, one per line, blank lines are ignored, lines
 
    starting with '#' are ignored)
 
  - ~/.config/cheatsheet_viewer/profiles/PROFILE/overlay (list of
 
    window titles for which to automatically apply the overlay mode)
 

	
 
Multiple commands are provided for working with the profiles and
 
displaying the cheatsheets.
 

	
 
list
 

	
 
  Lists the available profiles.
 

	
 
info PROFILE
 

	
 
  Arguments:
 

	
 
@@ -255,58 +257,76 @@ function command_info() {
 
#     Specify if cheatsheets should be shown in overlay mode.
 
#
 
# Returns:
 
#   0 on success, 1 otherwise.
 
#
 
function command_display() {
 
    local config_dir="$1"
 
    local profile="$2"
 
    local overlay_mode="$3"
 

	
 
    local profile_dir="$config_dir/profiles/$profile"
 
    local cheatsheets_file="$profile_dir/cheatsheets"
 
    local overlay_limits_file="$profile_dir/overlay"
 

	
 
    local caller_window_id caller_window_title window_title
 

	
 
    local caller_window_id
 
    local cheatsheets=()
 
    local -A overlay_limits
 

	
 
    if [[ ! -d $profile_dir ]]; then
 
        error "No such profile found under $profile_dir"
 
        return 1
 
    fi
 

	
 
    if [[ -e $cheatsheets_file ]]; then
 
        readarray -t cheatsheets < <(grep --invert-match --extended-regexp "(^[[:blank:]]*#|^[[:blank:]]*$)" "$cheatsheets_file")
 
    fi
 

	
 
    if (( overlay_mode )); then
 
        overlay_limits[_ALL_]=1
 
    elif [[ -e $overlay_limits_file ]]; then
 
        while read -r window_title; do
 
            if [[ -n $window_title ]]; then
 
                overlay_limits[$window_title]=1
 
            fi
 
        done < <(grep --invert-match --extended-regexp "(^[[:blank:]]*#|^[[:blank:]]*$)" "$overlay_limits_file")
 
    else
 
        # Means that cheatsheets are not shown as overlays. Assignment
 
        # introduced to avoid unbound variable errors in checks.
 
        overlay_limits[_DISABLED_]=1
 
    fi
 

	
 
    if (( ${#cheatsheets[@]} == 0 )); then
 
        warning "No cheatsheets are defined under $cheatsheets_file"
 
        return 0
 
    fi
 

	
 
    if (( overlay_mode )); then
 
    if (( ! overlay_limits[_DISABLED_] )); then
 
        caller_window_id=$(xprop -root | grep '^_NET_ACTIVE_WINDOW(WINDOW)' | sed -e 's/.*window id # //')
 
        caller_window_title=$(xprop -id "$caller_window_id" _NET_WM_NAME | sed -Ee 's/^[^=]+ = "//;s/"$//')
 
    fi
 

	
 

	
 
    local pqiv_options=(
 
        "--scale-mode-screen-fraction=1.0"
 
        "--zoom-level=1.0"
 
        "--transparent-background"
 
        "--hide-info-box"
 
        "--window-title=cheatsheet-viewer-$profile"
 
    )
 

	
 
    pqiv "${pqiv_options[@]}" "${cheatsheets[@]}" &
 

	
 
    if (( overlay_mode )); then
 
    # The ${caller_window_title-_} is used to avoid invalid array subscript.
 
    if (( overlay_limits[_ALL_] || overlay_limits[${caller_window_title-_}] )); then
 
        local counter=0
 
        while (( counter < 10 )) && ! wmctrl -l | grep -q "cheatsheet-viewer-$profile"; do
 
            sleep 0.05
 
            (( counter+=1 ))
 
        done
 

	
 
        wmctrl -F -r "cheatsheet-viewer-$profile" -b add,above
 
        wmctrl -i -a "$caller_window_id"
 
    fi
 
}
 

	
 

	
 
@@ -326,87 +346,105 @@ function command_display() {
 
#
 
# Returns:
 
#   0 on success, 1 otherwise.
 
#
 
function command_toggle() {
 
    local config_dir="$1"
 
    local profile="$2"
 
    local overlay_mode="$3"
 

	
 
    local profile_dir="$config_dir/profiles/$profile"
 
    local cheatsheets_file="$profile_dir/cheatsheets"
 
    local last_cheatsheet_file="$profile_dir/last"
 
    local overlay_limits_file="$profile_dir/overlay"
 

	
 
    local current_process_id current_profile last_cheatsheet caller_window_id
 
    local current_process_id current_profile last_cheatsheet caller_window_id caller_window_title window_title
 

	
 
    local cheatsheets=()
 
    local -A overlay_limits
 

	
 
    if [[ ! -d $profile_dir ]]; then
 
        error "No such profile found under $profile_dir"
 
        return 1
 
    fi
 

	
 
    if [[ -e $cheatsheets_file ]]; then
 
        readarray -t cheatsheets < <(grep --invert-match --extended-regexp "(^[[:blank:]]*#|^[[:blank:]]*$)" "$cheatsheets_file")
 
    fi
 

	
 
    if (( overlay_mode )); then
 
        overlay_limits[_ALL_]=1
 
    elif [[ -e $overlay_limits_file ]]; then
 
        while read -r window_title; do
 
            if [[ -n $window_title ]]; then
 
                overlay_limits[$window_title]=1
 
            fi
 
        done < <(grep --invert-match --extended-regexp "(^[[:blank:]]*#|^[[:blank:]]*$)" "$overlay_limits_file")
 
    else
 
        # Means that cheatsheets are not shown as overlays. Assignment
 
        # introduced to avoid unbound variable errors in checks.
 
        overlay_limits[_DISABLED_]=1
 
    fi
 

	
 
    if (( ${#cheatsheets[@]} == 0 )); then
 
        warning "No cheatsheets are defined under $cheatsheets_file"
 
        return 0
 
    fi
 

	
 
    if [[ -e $last_cheatsheet_file ]]; then
 
        last_cheatsheet=$(< "$last_cheatsheet_file")
 
    else
 
        last_cheatsheet=""
 
    fi
 

	
 
    # Get information about existing running cheatsheet viewer pqiv instance (if any).
 
    current_process_id=$(wmctrl -lp | grep 'cheatsheet-viewer-' | awk '{print $3}')
 
    current_profile=$(wmctrl -lp | grep 'cheatsheet-viewer-' | awk '{print $5}' | sed -e 's/cheatsheet-viewer-//')
 

	
 
    # Kill off the existing running process.
 
    if [[ -n $current_process_id ]]; then
 
        kill "$current_process_id"
 
    fi
 

	
 
    # If requested profile is not the same as current one, we want to
 
    # show cheatsheets from requested profile.
 
    if [[ $current_profile != "$profile" ]]; then
 
        if (( overlay_mode )); then
 
        if (( ! overlay_limits[_DISABLED_] )); then
 
            caller_window_id=$(xprop -root | grep '^_NET_ACTIVE_WINDOW(WINDOW)' | sed -e 's/.*window id # //')
 
            caller_window_title=$(xprop -id "$caller_window_id" _NET_WM_NAME | sed -Ee 's/^[^=]+ = "//;s/"$//')
 
        fi
 

	
 
        local pqiv_options=(
 
            "--scale-mode-screen-fraction=1.0"
 
            "--zoom-level=1.0"
 
            "--transparent-background"
 
            "--hide-info-box"
 
            "--window-title=cheatsheet-viewer-$profile"
 
        )
 

	
 
        if [[ -n $last_cheatsheet && -f $last_cheatsheet ]]; then
 
            pqiv_options+=("--action=goto_file_byname($last_cheatsheet); set_status_output(1)")
 
        else
 
            pqiv_options+=("--action=set_status_output(1)")
 
        fi
 

	
 
        (
 
            while read -r line; do
 
                eval "$line"
 
                echo "$CURRENT_FILE_NAME" > "$profile_dir/last"
 
            done < <(pqiv "${pqiv_options[@]}" "${cheatsheets[@]}" | grep --line-buffered '^CURRENT_FILE_NAME=')
 
        ) &
 

	
 
        if (( overlay_mode )); then
 
        # The ${caller_window_title-_} is used to avoid invalid array subscript.
 
        if (( overlay_limits[_ALL_] || overlay_limits[${caller_window_title-_}] )); then
 
            local counter=0
 
            while (( counter < 10 )) && ! wmctrl -l | grep -q "cheatsheet-viewer-$profile"; do
 
                sleep 0.05
 
                (( counter+=1 ))
 
            done
 

	
 
            wmctrl -F -r "cheatsheet-viewer-$profile" -b add,above
 
            wmctrl -i -a "$caller_window_id"
 
        fi
 
    fi
 
}
 

	
0 comments (0 inline, 0 general)