Compare commits

...

4 Commits

Author SHA1 Message Date
John Beard f395956232
Merge e7539d954d into 9b6e70b365 2024-04-19 06:26:59 +02:00
Dave Davenport 9b6e70b365 [IconFetcher] Don't check for extension for image file.
Issue: 1977
2024-04-18 22:32:50 +02:00
martinsifrar 4f098751cd
[IconFetcher] Fix failing decode of animated GIFs. (#1975) 2024-04-15 12:56:09 +02:00
John Beard e7539d954d Bash completion: add a rofi bash-completion script
Adds a basic bash completion script for the rofi(1) command.
Most parameters are handled to some extent, with some extra
logic for things like modi, windows, X11 displays, key bindings
and arguments with known options.
2020-05-12 09:36:59 +01:00
2 changed files with 266 additions and 0 deletions

253
script/bash-completion/rofi Normal file
View File

@ -0,0 +1,253 @@
# rofi(1) completion -*- shell-script -*-
# Prints all registered modi (by parsing the help text)
_rofi_list_modi()
{
rofi -help | awk '/Detected modi/ {do_print=1}
NF==0 {do_print=0}
do_print==1 {print}' | tail -n +2 | sed 's/+//g' | awk '{print $2}'
}
_rofi_get_window_code_list()
{
# if no wmctrl, give up
command -v wmctrl > /dev/null 2>&1 || return
wmctrl -l | awk '{print $1}'
}
_rofi_get_xdisplays()
{
# if no w, give up
command -v w > /dev/null 2>&1 || return
w -ush | awk '{print $5}'
}
# Get the available xrandr monitors
_rofi_get_monitors()
{
# if no xrandr, give up
command -v xrandr > /dev/null 2>&1 || return
xrandr --listmonitors | awk 'NR<2 {next} {gsub(/:/, "")} {print $1}'
}
# Get valid formats for the -format command
_rofi_get_formats()
{
echo "s i d q p f F" | tr ' ' "\n"
}
# Parse out flags that look like keys and mouse options from the help text
_rofi_get_keys()
{
rofi -help | grep -E "[-](kb|me|ml)-" | awk '{print $1}'
}
# Get a list of all installed font families
_rofi_get_all_fonts()
{
# if no fc-list, give up
command -v fc-list > /dev/null 2>&1 || return
# list of installed font families
fc-list --format="%{family[0]}\n"
}
_rofi_complete_fonts()
{
# don't split on spaces in a font name
local IFS=$'\n'
local fonts=($(_rofi_get_all_fonts))
# the word in progress, if any
local cur=$1
# strip trailing numeric suffix, if any (e.g. Font 12 -> Font)
local root=$(echo $cur | sed 's/\\ / /g' | sed -E 's/ +[0-9]+$//')
# if that is a font name, suggest that font plus a selection of likely sizes
[[ " ${fonts[@]} " == *" ${root} "* ]] && fonts+=("$root "{8..14})
# Return the entire font list, plus the sizes for a complete font name
printf "%s\n" "${fonts[@]}"
}
_rofi_construct_bindings()
{
local mods=(Control+ Control+Shift+ Control+Shift+Alt+ Control+Alt+
Shift+ Shift+Alt+ Alt+)
local cur=$1
# Add bare modifiers as completion candidates
printf "%s\n" "${mods[@]}"
# find the "root" of the current word-in-progress and add all the keys to that
# as completion candidates.
# This avoids spamming the user with N_mods * N_keys
local root=$(echo $cur | grep -o ".*+")
printf "${root}%s\n" "${keys[@]}"
}
# Get a list of bindings compatible with the given prefix ($1)
_rofi_get_key_bindings()
{
# GTK keynames
local IFS=$'\n'
local keys=($(xmodmap -pk | awk 'NF>2 {gsub(/[()]/,""); print $3} '))
_rofi_construct_bindings "$1" $keys
}
_rofi_get_mouse_bindings()
{
# GTK keynames
local keys=(MousePrimary MouseDPrimary MouseSecondary MouseDSecondary
ScrollUp ScrollLeft ScrollRight ScrollDown
Back Forward)
_rofi_construct_bindings "$1" $keys
}
# Main completion function
_rofi_completions()
{
local cur prev words cword
_init_completion || return
# These are flags that are always valid
local gen_flags='-no-config -version -dmenu -display -help -e
-dump-config -dump-theme -dump-xresources
-markup -normal-window -show -modi -combi-modi -eh
-no-lazy-grab -no-plugins -plugin-path
-width -lines -columns -font -bw -location -padding
-yoffset -xoffset
-fixed-num-lines -no-fixed-num-lines
-show-icons -no-show-icons
-terminal -ssh-client -run-command -run-shell-command
-window-command -window-match-fields
-icon-theme -drun-match-fields
-drun-show-actions -no-drun-show-actions
-drun-display-format
-disable-history -no-disable-history -ignored-prefixes
-sort -no-sort -sorting-method -case-sensitive -no-case-sensitive
-cycle -no-cycle -sidebar-mode -no-sidebar-mode
-auto-select -no-auto-select -parse-hosts -no-parse-hosts
-parse-known-hosts -no-parse-known-hosts
-matching -tokenize -no-tokenize -m
-filter -fullscreen -no-fullscreen -dpi
-threads -scroll-method -window-format
-click-to-exit -no-click-to-exit -show-match -no-show-match
-theme -color-normal -color-urgent -color-active -color-window
-max-history-size -combi-hide-mode-prefix -no-combi-hide-mode-prefix
-matching-negate-char -cache-dir -pid '
local dmenu_flags='-mesg -p -selected_row -format -u -a -l -i
-only-match -no-custom -select -password -markup-rows
-sep -input -sync -async-pre-read -w'
# installed modi
local modis=$(_rofi_list_modi)
# every modi gets a -display-<modi> option
gen_flags+=$(printf "%s\n" ${modis} | sed -e 's/^/-display-/')
# append the supported key/mouse opts
gen_flags+=$(_rofi_get_keys)
case $cur in
-*|'')
# these flags always apply
COMPREPLY=($(compgen -W '${gen_flags[*]}' -- "$cur"))
[[ $COMPREPLY == *= ]] && compopt -o nospace
;;
esac
local have_dmenu=0
# Check for modal trigger arguments
local word
for word in ${words[@]};
do
case ${word} in
-dmenu) have_dmenu=1 ;;
esac
done
case $prev in
-cache-dir|-plugin-path)
COMPREPLY=($(compgen -d -- "$cur"))
;;
-input|-pid)
COMPREPLY=($(compgen -f -- "$cur"))
;;
-show|-modi)
# This can be smarter by merging into a comma-separated list
# for -modi
COMPREPLY=($(compgen -W '${modis[*]}' -- "$cur"))
;;
-w)
local windows=$(_rofi_get_window_code_list)
COMPREPLY=($(compgen -W '${windows[*]}' -- "$cur"))
;;
-m)
local monitors=$(_rofi_get_monitors)
COMPREPLY=($(compgen -W '${monitors[*]}' -- "$cur"))
;;
-display)
local displays=$(_rofi_get_xdisplays)
COMPREPLY=($(compgen -W '${displays[*]}' -- "$cur"))
;;
-format)
local formats=$(_rofi_get_formats)
COMPREPLY=($(compgen -W '${formats[*]}' -- "$cur"))
;;
-matching)
COMPREPLY=($(compgen -W 'normal regex glob fuzzy' -- "$cur"))
;;
-sorting-method)
COMPREPLY=($(compgen -W 'levenshtein fzf normal' -- "$cur"))
;;
-font)
# this isn't quite complete, as not having a number is invalid
local fonts=$(_rofi_complete_fonts "$cur")
local IFS=$'\n' # don't split on fonts with spaces
COMPREPLY=($(compgen -W '${fonts[*]}' -- "$cur"))
compopt -o nospace
;;
-kb*)
local bindings=$(_rofi_get_key_bindings "$cur")
COMPREPLY=($(compgen -W '${bindings[*]}' -- "$cur"))
compopt -o nospace
;;
-me*)
local bindings=$(_rofi_get_mouse_bindings "$cur")
COMPREPLY=($(compgen -W '${bindings[*]}' -- "$cur"))
compopt -o nospace
;;
*)
[ ${have_dmenu} -eq 1 ] && COMPREPLY+=($(compgen -W '${dmenu_flags[*]}' -- "$cur"))
esac
# Handle completions with spaces
if [ ${#COMPREPLY[*]} -eq 0 ]; then
COMPREPLY=()
else
COMPREPLY=($(printf '%q\n' "${COMPREPLY[@]}"))
fi
}
complete -F _rofi_completions rofi

View File

@ -354,6 +354,7 @@ static void rofi_icon_fetcher_worker(thread_state *sdata,
}
cairo_surface_t *icon_surf = NULL;
#if 0 // unsure why added in past?
const char *suf = strrchr(icon_path, '.');
if (suf == NULL) {
sentry->query_done = TRUE;
@ -361,10 +362,22 @@ static void rofi_icon_fetcher_worker(thread_state *sdata,
rofi_view_reload();
return;
}
#endif
GError *error = NULL;
GdkPixbuf *pb = gdk_pixbuf_new_from_file_at_scale(
icon_path, sentry->wsize, sentry->hsize, TRUE, &error);
/*
* The GIF codec throws GDK_PIXBUF_ERROR_INCOMPLETE_ANIMATION if it's closed
* without decoding all the frames. Since gdk_pixbuf_new_from_file_at_scale
* only decodes the first frame, this specific error needs to be ignored.
*/
if (error != NULL && g_error_matches(error, GDK_PIXBUF_ERROR,
GDK_PIXBUF_ERROR_INCOMPLETE_ANIMATION)) {
g_clear_error(&error);
}
if (error != NULL) {
g_warning("Failed to load image: |%s| %d %d %s (%p)", icon_path,
sentry->wsize, sentry->hsize, error->message, (void *)pb);