Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hyprctl: add shell completions #3535

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ result*
*.so

hyprctl/hyprctl
completions/generated/*.usage

gmon.out
*.out
Expand Down
7 changes: 7 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ install:
mkdir -p ${PREFIX}/share/hyprland
cp ./assets/wall_* ${PREFIX}/share/hyprland

install -m644 -D ./completions/generated/hyprctl.bash ${PREFIX}/share/bash-completion/completions/hyprctl
install -m644 -D ./completions/generated/hyprctl.fish ${PREFIX}/share/fish/vendor_completions.d/
install -m644 -D ./completions/generated/hyprctl.zsh ${PREFIX}/share/zsh/site-functions/_hyprctl

mkdir -p ${PREFIX}/share/man/man1
install -m644 ./docs/*.1 ${PREFIX}/share/man/man1

Expand Down Expand Up @@ -84,6 +88,9 @@ uninstall:
rm -rf ${PREFIX}/share/hyprland
rm -f ${PREFIX}/share/man/man1/Hyprland.1
rm -f ${PREFIX}/share/man/man1/hyprctl.1
rm -f ${PREFIX}/share/bash-completion/completions/hyprctl
rm -f ${PREFIX}/share/fish/vendor_completions.d/hyprctl.fish
rm -f ${PREFIX}/share/zsh/site-functions/_hyprctl

fixwlr:
sed -E -i -e 's/(soversion = 12)([^032]|$$)/soversion = 12032/g' subprojects/wlroots/meson.build
Expand Down
17 changes: 17 additions & 0 deletions completions/build_completions.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#!/bin/sh

generate_grammar() {
cat hyprctl.usage
echo
printf '<CONFIG_OPTION> ::= '
sed -n 's/.*configValues\["\(.*\)"\].*/ | \1/p' ../src/config/ConfigManager.cpp |
sort | uniq | sed 's/\./\\./g' | tail -c +7
echo ';'
}

generate_grammar > generated/hyprctl.usage

cd generated || exit 1
complgen compile --bash-script hyprctl.bash hyprctl.usage
complgen compile --zsh-script hyprctl.zsh hyprctl.usage
complgen compile --fish-script hyprctl.fish hyprctl.usage
141 changes: 141 additions & 0 deletions completions/generated/hyprctl.bash
Original file line number Diff line number Diff line change
@@ -0,0 +1,141 @@
_hyprctl_cmd_0 () {
hyprctl instances -j | sed -n 's/.*"instance": "\(.*\)".*/\1/p'
}

_hyprctl_cmd_1 () {
printf '%s\n' /usr/share/icons/*/cursors | cut -d/ -f5
}

_hyprctl_cmd_2 () {
hyprctl devices -j | awk '/^"keyboards"/,/^\],$/' | sed -n 's/.*"name": "\(.*\)".*/\1/p'
}

_hyprctl_cmd_3 () {
hyprctl monitors | sed -n 's/^Monitor \(.*\) (ID .*/\1/p'
}

_hyprctl_spec_1 () {
compgen -A file "$1"
}

_hyprctl () {
if [[ $(type -t _get_comp_words_by_ref) != function ]]; then
echo _get_comp_words_by_ref: function not defined. Make sure the bash-completions system package is installed
return 1
fi

local words cword
_get_comp_words_by_ref -n =:@ words cword

local -a literals=("misc:enable_swallow" "dwindle:split_width_multiplier" "3" "debug:suppress_errors" "input:touchpad:drag_lock" "decoration:blur:special" "alterzorder" "misc:groupbar_gradients" "misc:swallow_regex" "setprop" "resizeactive" "dwindle:preserve_split" "dwindle:smart_split" "misc:group_insert_after_current" "misc:key_press_enables_dpms" "preload" "next" "centerwindow" "wayland" "fullscreen" "pass" "execr" "misc:focus_on_activate" "input:tablet:output" "gestures:workspace_swipe_create_new" "general:hover_icon_on_border" "debug:log_damage" "general:col.nogroup_border_active" "general:max_fps" "misc:cursor_zoom_factor" "binds:focus_preferred_method" "misc:close_special_on_empty" "debug:watchdog_timeout" "misc:layers_hog_keyboard_focus" "blurls" "resizewindowpixel" "binds" "decoration:dim_inactive" "dwindle:use_active_for_splits" "cursorpos" "input:touchdevice:output" "workspaces" "input:tablet:transform" "misc:always_follow_on_dnd" "misc:vfr" "list" "gestures:workspace_swipe_distance" "devices" "decoration:dim_around" "input:numlock_by_default" "general:allow_tearing" "input:kb_variant" "misc:animate_mouse_windowdragging" "decoration:shadow_ignore_window" "exit" "gestures:workspace_swipe_invert" "misc:mouse_move_focuses_monitor" "general:cursor_inactive_timeout" "top" "decoration:col.shadow_inactive" "unbind" "movewindoworgroup" "exec" "remove" "layerrule" "autogenerated" "xwayland:force_zero_scaling" "plugin" "lockactivegroup" "general:col.inactive_border" "input:touchpad:clickfinger_behavior" "closewindow" "input:touchdevice:transform" "monitor" "animation" "debug:enable_stdout_logs" "general:col.nogroup_border" "misc:no_direct_scanout" "input:repeat_rate" "dwindle:no_gaps_when_only" "togglegroup" "input:scroll_method" "movecursor" "dwindle:permanent_direction_override" "gestures:workspace_swipe_direction_lock_threshold" "input:touchpad:tap-and-drag" "swapactiveworkspaces" "gestures:workspace_swipe" "decoration:col.shadow" "master:mfact" "setcursor" "gestures:workspace_swipe_forever" "input:sensitivity" "input:touchpad:tap-to-click" "misc:swallow_exception_regex" "misc:cursor_zoom_rigid" "activeworkspace" "debug:int" "decoration:active_opacity" "misc:force_hypr_chan" "togglespecialworkspace" "binds:allow_workspace_cycles" "dwindle:smart_resizing" "general:sensitivity" "misc:group_focus_removed_window" "-j" "prev" "pseudo" "load" "decoration:shadow_offset" "decoration:fullscreen_opacity" "togglefloating" "dwindle:pseudotile" "input:touchpad:tap_button_map" "source" "input:tablet:region_size" "decoration:shadow_render_power" "moveactive" "moveworkspacetomonitor" "general:layout" "mfact" "changegroupactive" "0" "decoration:shadow_range" "instances" "general:extend_border_grab_area" "debug:damage_tracking" "misc:render_ahead_of_time" "bezier" "decoration:screen_shader" "input:tablet:region_position" "togglesplit" "globalshortcuts" "decoration:blur:noise" "input:kb_model" "master:allow_small_split" "decoration:blur:enabled" "master:new_is_master" "killactive" "windowrule" "clients" "gestures:workspace_swipe_fingers" "master:no_gaps_when_only" "fakefullscreen" "env" "x11" "general:col.group_border_locked_active" "mouse" "bottom" "notify" "pin" "animations" "gestures:workspace_swipe_direction_lock" "wallpaper" "master:smart_resizing" "general:no_border_on_floating" "input:follow_mouse" "wsbind" "debug:disable_time" "general:no_cursor_warps" "layoutmsg" "1" "master:always_center_master" "cyclenext" "movecursortocorner" "keyword" "general:apply_sens_to_raw" "general:col.group_border_active" "movewindowpixel" "input:accel_profile" "auto" "input:natural_scroll" "activewindow" "swapwindow" "decoration:blur:contrast" "master:inherit_fullscreen" "misc:allow_session_lock_restore" "input:scroll_button_lock" "5" "input:mouse_refocus" "decoration:blur:new_optimizations" "--instance" "decoration:inactive_opacity" "misc:disable_splash_rendering" "forcerendererreload" "master:orientation" "misc:force_default_wallpaper" "xwayland:use_nearest_neighbor" "hyprpaper" "input:touchpad:scroll_factor" "movecurrentworkspacetomonitor" "toggleopaque" "monitors" "input:kb_options" "focuswindow" "renameworkspace" "misc:render_ahead_safezone" "misc:render_titles_in_groupbar" "workspace" "switchxkblayout" "input:force_no_accel" "misc:groupbar_titles_font_size" "create" "general:border_size" "master:new_on_top" "movewindow" "input:scroll_button" "general:col.group_border_locked" "misc:vrr" "decoration:rounding" "misc:groupbar_text_color" "decoration:blur:ignore_opacity" "general:resize_on_border" "dpms" "submap" "general:gaps_out" "output" "workspaceopt" "misc:disable_autoreload" "debug:overlay" "input:touchpad:disable_while_typing" "input:repeat_delay" "dwindle:special_scale_factor" "-i" "moveintogroup" "layers" "focuswindowbyclass" "misc:new_window_takes_over_fullscreen" "unload" "headless" "input:touchpad:middle_button_emulation" "bind" "input:touchpad:natural_scroll" "general:gaps_in" "seterror" "focusmonitor" "input:kb_rules" "misc:background_color" "decoration:blur:brightness" "binds:pass_mouse_when_bound" "splitratio" "binds:ignore_group_lock" "2" "dwindle:default_split_ratio" "misc:mouse_move_enables_dpms" "misc:animate_manual_resizes" "gestures:workspace_swipe_use_r" "misc:disable_hyprland_logo" "decoration:drop_shadow" "debug:manual_crash" "version" "input:left_handed" "exec-once" "dwindle:force_split" "misc:groupbar_scrolling" "misc:hide_cursor_on_touch" "decoration:blur:xray" "gestures:workspace_swipe_min_speed_to_force" "debug:disable_logs" "input:float_switch_override_focus" "-1" "lockgroups" "binds:scroll_event_delay" "decoration:blur:passes" "windowrulev2" "reload" "animations:enabled" "general:col.active_border" "general:no_focus_fallback" "swapnext" "kill" "input:kb_file" "gestures:workspace_swipe_cancel_ratio" "dispatch" "bringactivetotop" "moveoutofgroup" "getoption" "movetoworkspace" "master:drop_at_cursor" "movetoworkspacesilent" "master:special_scale_factor" "binds:workspace_back_and_forth" "4" "decoration:no_blur_on_oversized" "--batch" "debug:damage_blink" "all" "decoration:shadow_scale" "disable" "global" "focusurgentorlast" "splash" "input:kb_layout" "decoration:blur:size" "movefocus" "decoration:dim_strength" "gestures:workspace_swipe_numbered" "general:col.group_border" "focuscurrentorlast" "decoration:dim_special")

declare -A literal_transitions
literal_transitions[0]="([105]=0 [67]=1 [36]=2 [149]=8 [39]=2 [151]=2 [41]=2 [265]=2 [9]=2 [234]=7 [47]=2 [270]=2 [124]=2 [273]=9 [165]=10 [276]=6 [90]=11 [172]=2 [216]=12 [284]=2 [132]=2 [291]=2 [96]=2 [140]=2 [181]=13 [250]=2 [223]=13 [188]=4 [225]=2 [199]=14 [192]=2)"
literal_transitions[1]="([45]=2 [108]=3 [228]=3)"
literal_transitions[4]="([15]=3 [153]=2 [228]=5)"
literal_transitions[5]="([286]=2)"
literal_transitions[6]="([146]=2 [1]=2 [3]=2 [4]=2 [5]=2 [7]=2 [152]=2 [154]=2 [8]=2 [155]=2 [156]=2 [11]=2 [12]=2 [158]=2 [159]=2 [162]=2 [13]=2 [14]=2 [166]=2 [167]=2 [169]=2 [171]=2 [174]=2 [175]=2 [176]=2 [22]=2 [177]=2 [23]=2 [24]=2 [25]=2 [179]=2 [26]=2 [27]=2 [28]=2 [29]=2 [30]=2 [180]=2 [182]=2 [31]=2 [183]=2 [185]=2 [32]=2 [189]=2 [197]=2 [33]=2 [193]=2 [187]=2 [196]=2 [186]=2 [37]=2 [38]=2 [200]=2 [40]=2 [42]=2 [43]=2 [44]=2 [201]=2 [203]=2 [46]=2 [204]=2 [206]=2 [207]=2 [208]=2 [209]=2 [48]=2 [49]=2 [50]=2 [51]=2 [52]=2 [53]=2 [210]=2 [211]=2 [212]=2 [215]=2 [55]=2 [56]=2 [57]=2 [218]=2 [59]=2 [219]=2 [220]=2 [221]=2 [222]=2 [65]=2 [227]=2 [66]=2 [69]=2 [70]=2 [72]=2 [230]=2 [77]=2 [75]=2 [76]=2 [232]=2 [233]=2 [78]=2 [79]=2 [81]=2 [236]=2 [83]=2 [237]=2 [84]=2 [238]=2 [85]=2 [239]=2 [87]=2 [88]=2 [89]=2 [241]=2 [243]=2 [91]=2 [92]=2 [93]=2 [94]=2 [95]=2 [244]=2 [245]=2 [246]=2 [97]=2 [247]=2 [98]=2 [248]=2 [249]=2 [99]=2 [251]=2 [101]=2 [253]=2 [102]=2 [103]=2 [104]=2 [254]=2 [255]=2 [256]=2 [257]=2 [109]=2 [258]=2 [110]=2 [112]=2 [113]=2 [259]=2 [262]=2 [115]=2 [263]=2 [266]=2 [116]=2 [267]=2 [268]=2 [119]=2 [271]=2 [272]=2 [280]=2 [123]=2 [125]=2 [278]=2 [126]=2 [281]=2 [127]=2 [129]=2 [283]=2 [130]=2 [285]=2 [287]=2 [133]=2 [134]=2 [135]=2 [136]=2 [137]=2 [292]=2 [141]=2 [293]=2 [142]=2 [295]=2 [296]=2 [297]=2 [0]=2 [299]=2)"
literal_transitions[7]="([288]=2)"
literal_transitions[8]="([2]=2 [122]=2 [242]=2 [161]=2 [260]=2 [282]=2 [178]=2)"
literal_transitions[9]="([107]=2 [147]=2 [68]=2 [35]=2 [194]=2 [111]=2 [195]=2 [6]=15 [71]=2 [150]=2 [198]=2 [261]=2 [205]=2 [226]=2 [235]=2 [10]=2 [269]=2 [80]=2 [117]=2 [82]=2 [118]=2 [120]=2 [121]=2 [160]=2 [163]=2 [86]=2 [164]=2 [213]=2 [168]=2 [214]=2 [17]=2 [54]=2 [173]=2 [240]=2 [131]=2 [20]=2 [19]=2 [21]=2 [217]=2 [274]=2 [275]=2 [61]=2 [277]=2 [138]=2 [279]=2 [289]=2 [290]=2 [62]=2 [184]=2 [100]=2 [143]=2 [224]=2 [294]=2 [190]=2 [298]=2 [191]=2)"
literal_transitions[10]="([67]=2 [128]=2 [198]=2 [73]=2 [60]=2 [264]=2 [74]=2 [114]=3 [139]=2 [231]=2 [62]=2 [157]=2 [64]=2 [252]=2 [214]=2 [144]=2 [34]=2)"
literal_transitions[12]="([202]=16 [63]=18)"
literal_transitions[15]="([58]=2 [148]=2)"
literal_transitions[16]="([170]=2 [18]=2 [145]=2 [229]=2)"
literal_transitions[17]="([16]=2 [106]=2)"

declare -A match_anything_transitions
match_anything_transitions=([3]=2 [13]=0 [11]=2 [5]=2 [14]=17 [18]=2)
declare -A subword_transitions

local state=0
local word_index=1
while [[ $word_index -lt $cword ]]; do
local word=${words[$word_index]}

if [[ -v "literal_transitions[$state]" ]]; then
local state_transitions_initializer=${literal_transitions[$state]}
declare -A state_transitions
eval "state_transitions=$state_transitions_initializer"

local word_matched=0
for literal_id in $(seq 0 $((${#literals[@]} - 1))); do
if [[ ${literals[$literal_id]} = "$word" ]]; then
if [[ -v "state_transitions[$literal_id]" ]]; then
state=${state_transitions[$literal_id]}
word_index=$((word_index + 1))
word_matched=1
break
fi
fi
done
if [[ $word_matched -ne 0 ]]; then
continue
fi
fi

if [[ -v "match_anything_transitions[$state]" ]]; then
state=${match_anything_transitions[$state]}
word_index=$((word_index + 1))
continue
fi

return 1
done


local prefix="${words[$cword]}"

local suffix=${word##*:}
local candidate=${word##*=}
if [[ ${#candidate} -lt ${#suffix} ]]; then
suffix=$candidate
fi
local superfluous_prefix=${word%$suffix}

if [[ -v "literal_transitions[$state]" ]]; then
local state_transitions_initializer=${literal_transitions[$state]}
declare -A state_transitions
eval "state_transitions=$state_transitions_initializer"

for literal_id in "${!state_transitions[@]}"; do
local literal="${literals[$literal_id]}"
if [[ $literal = "${prefix}"* ]]; then
local completion=${literal#"$superfluous_prefix"}
COMPREPLY+=("$completion")
fi
done
fi
declare -A commands
commands=([18]=3 [11]=1 [13]=0 [14]=2)
if [[ -v "commands[$state]" ]]; then
local command_id=${commands[$state]}
local completions=()
mapfile -t completions < <(_hyprctl_cmd_${command_id} "$prefix" | cut -f1)
for item in "${completions[@]}"; do
if [[ $item = "${prefix}"* ]]; then
COMPREPLY+=("$item")
fi
done
fi


declare -A specialized_commands
specialized_commands=([5]=1 [3]=1)
if [[ -v "specialized_commands[$state]" ]]; then
local command_id=${specialized_commands[$state]}
local completions=()
mapfile -t completions < <(_hyprctl_spec_"${command_id}" "$prefix" | cut -f1)
for item in "${completions[@]}"; do
if [[ $item = "${prefix}"* ]]; then
COMPREPLY+=("$item")
fi
done
fi

__ltrim_colon_completions "$prefix"

return 0
}

complete -o nospace -F _hyprctl hyprctl
Loading