Changeset - 5ebeba51e2ff
[Not reviewed]
0 1 0
Branko Majic (branko) - 8 months ago 2025-03-19 21:35:57
branko@majic.rs
[cheatsheet_viewer.sh] Added support for displaying cheatsheet in overlay mode:

- Current window focus is preserved. Cheatsheet is shown as
always-on-top.
- Fix inconsitency in pqiv window title naming between display and
toggle commands.
1 file changed with 56 insertions and 5 deletions:
0 comments (0 inline, 0 general)
utils/cheatsheet_viewer.sh
Show inline comments
 
@@ -101,24 +101,30 @@ toggle [PROFILE]
 

	
 
    PROFILE (profile name)
 

	
 
  Toggles display of cheatsheets from the specified profile (default
 
  profile name is 'default'). Unlike the display command, the toggle
 
  command is more intelligent and ensures that only one instance of
 
  cheatsheet-specific pqiv is present. Thex toggle command also keeps
 
  track of which cheatsheet was last selected, and will update the
 
  image viewer to point to it when opened.
 

	
 
$PROGRAM accepts the following options:
 

	
 
    -o
 
        Display cheatsheets in "overlay" mode, keeping the current
 
        window in focus, and making the cheatsheet window
 
        always-on-top. Useful when playing games and similar. The
 
        cheatsheet window can still be focused using keyboard and
 
        mouse-clicks.
 
    -q
 
        Quiet mode.
 
    -d
 
        Enable debug mode.
 
    -v
 
        Show script version and licensing information.
 
    -h
 
        Show full help.
 

	
 
Please report bugs and send feature requests to <branko@majic.rs>.
 
EOF
 
}
 
@@ -236,84 +242,110 @@ function command_info() {
 

	
 
#
 
# Displays configured cheatsheets from a profile.
 
#
 
# Arguments:
 
#
 
#   $1 (config_dir)
 
#     Base directory under which all configuration files are stored.
 
#
 
#   $2 (profile)
 
#     Profile name.
 
#
 
#   $3 (overlay_mode)
 
#     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 caller_window_id
 
    local cheatsheets=()
 

	
 
    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 (( ${#cheatsheets[@]} == 0 )); then
 
        warning "No cheatsheets are defined under $cheatsheets_file"
 
        return 0
 
    fi
 

	
 
    if (( overlay_mode )); then
 
        caller_window_id=$(xprop -root | grep '^_NET_ACTIVE_WINDOW(WINDOW)' | sed -e 's/.*window id # //')
 
    fi
 

	
 

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

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

	
 
    if (( overlay_mode )); 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
 
}
 

	
 

	
 
#
 
# Toggles display of configured cheatsheets from a profile.
 
#
 
# Arguments:
 
#
 
#   $1 (config_dir)
 
#     Base directory under which all configuration files are stored.
 
#
 
#   $2 (profile)
 
#     Profile name.
 
#
 
#   $3 (overlay_mode)
 
#     Specify if cheatsheets should be shown in overlay mode.
 
#
 
# 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 current_process_id current_profile last_cheatsheet
 
    local current_process_id current_profile last_cheatsheet caller_window_id
 

	
 
    local cheatsheets=()
 

	
 
    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
 

	
 
@@ -331,44 +363,59 @@ function command_toggle() {
 
    # 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
 
            caller_window_id=$(xprop -root | grep '^_NET_ACTIVE_WINDOW(WINDOW)' | sed -e 's/.*window id # //')
 
        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
 
            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
 
}
 

	
 

	
 
# Set-up colours for message printing if we're not piping and terminal is
 
# capable of outputting the colors.
 
_COLOR_TERMINAL=$(tput colors 2>&1)
 
if [[ -t 1 ]] && (( _COLOR_TERMINAL > 0 )); then
 
    _TEXT_BOLD=$(tput bold)
 
    _TEXT_WHITE=$(tput setaf 7)
 
    _TEXT_BLUE=$(tput setaf 6)
 
    _TEXT_GREEN=$(tput setaf 2)
 
@@ -415,33 +462,37 @@ function error() {
 

	
 
# Define error codes.
 
SUCCESS=0
 
ERROR_ARGUMENTS=1
 

	
 
# Disable debug and quiet modes by default.
 
DEBUG=0
 
QUIET=0
 

	
 
# Default paths, directories etc.
 
CONFIG_DIR="$HOME/.config/cheatsheet_viewer"
 

	
 
# Default option values.
 
OVERLAY_MODE=0
 

	
 
# If no arguments were given, just show usage help.
 
if [[ -z ${1-} ]]; then
 
    short_help
 
    exit "$SUCCESS"
 
fi
 

	
 
# Parse the arguments
 
while getopts "qdvh" opt; do
 
while getopts "oqdvh" opt; do
 
    case "$opt" in
 
        o) OVERLAY_MODE=1;;
 
        q) QUIET=1;;
 
        d) DEBUG=1;;
 
        v) version
 
           exit "$SUCCESS";;
 
        h) long_help
 
           exit "$SUCCESS";;
 
        *) short_help
 
           exit "$ERROR_ARGUMENTS";;
 
    esac
 
done
 
i=$OPTIND
 
shift $(( i-1 ))
 
@@ -467,27 +518,27 @@ elif [[ $COMMAND == info ]]; then
 
    if [[ -z $PROFILE ]]; then
 
        error "Profile name must be specified."
 
        exit "$ERROR_ARGUMENTS"
 
    fi
 

	
 
    command_info "$CONFIG_DIR" "$PROFILE"
 

	
 
elif [[ $COMMAND == display ]]; then
 

	
 
    PROFILE="${1-default}"
 
    shift
 

	
 
    command_display "$CONFIG_DIR" "$PROFILE"
 
    command_display "$CONFIG_DIR" "$PROFILE" "$OVERLAY_MODE"
 

	
 
elif [[ $COMMAND == toggle ]]; then
 

	
 
    PROFILE="${1-default}"
 
    shift
 

	
 
    command_toggle "$CONFIG_DIR" "$PROFILE"
 
    command_toggle "$CONFIG_DIR" "$PROFILE" "$OVERLAY_MODE"
 

	
 
else
 

	
 
    error "Unsupported command: $COMMAND"
 
    exit "$ERROR_ARGUMENTS"
 

	
 
fi
0 comments (0 inline, 0 general)