Last active
April 10, 2022 01:56
-
-
Save adrusi/5ec619d06ebe55746bb49422071a7206 to your computer and use it in GitHub Desktop.
andreyorst/powerline.kak: resize modeline dynamically base on window size
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
kakquote() { | |
out= | |
for text; do | |
out=$out"'" | |
while :; do | |
case "$text" in | |
*\'*) | |
out=$out${text%%\'*}\'\' | |
text=${text#*\'} | |
;; | |
*) | |
out=$out$text"' " | |
break | |
;; | |
esac | |
done | |
done | |
printf '%s' "$out" | |
} | |
kakcork() { | |
for arg; do | |
printf '%s ' "$(kakquote "$arg")" | |
done | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
readonly _nl_=" | |
" | |
if printf '%q' _ >/dev/null 2>/dev/null; then | |
cork() { | |
printf '%q \\\n' "$@" | |
printf ' ' | |
} | |
quote() { | |
printf '%q\n' "$1" | |
} | |
else | |
cork() { | |
for prelude_arg do | |
printf '%s' "$prelude_arg" | | |
tr '\n' '\033' | | |
sed "s/'/'\\\\''/g;s/"$(printf '\033')"/'\"\$_nl_\"'/g;1s/^/'/;\$s/\$/' \\\\/" | |
printf '\n' | |
done | |
} | |
quote() { | |
printf '%s' "$1" | | |
tr '\n' '\033' | | |
sed "s/'/'\\\\''/g;s/"$(printf '\033')"/'\"\$_nl_\"'/g;1s/^/'/;\$s/\$/'/" | |
printf '\n' | |
} | |
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require-module powerline | |
declare-option -docstring "a list of powerline modules in descending priority | |
order. lower-priority modules will be preferentially removed when there isn't | |
space enough for the whole set." \ | |
str-list powerline_module_priority mode_info bufname position filetype client \ | |
session line_column lsp git codepoint custom-static | |
declare-option -docstring "interval without any hooks that trigger | |
powerline-resize firing, in milliseconds." \ | |
int powerline_resize_delay 50 | |
define-command -docstring "install the necessary hooks to trigger | |
powerline-resize" \ | |
powerline-resize-enable %{ | |
remove-hooks buffer powerline-resize | |
hook -group powerline-resize buffer WinResize .* schedule-powerline-resize | |
hook -group powerline-resize buffer WinDisplay .* schedule-powerline-resize | |
hook -group powerline-resize buffer User PowerlineChange schedule-powerline-resize | |
} | |
declare-option -hidden str approximate_modeline "" | |
declare-option -hidden str powerline_format_orig %opt{powerline_format} | |
define-command -hidden -params 0..2 resize-powerline %{ | |
# There's no way to know the precise width of the powerline since kakoune | |
# doesn't provide any way of knowing what {{mode_info}} or {{context_info}} | |
# expand to. Fortunately we only need an approximation, and we want to err | |
# towards overestimation. | |
evaluate-commands %sh{ | |
printf 'set-option buffer approximate_modeline "' | |
printf %s\\n "$kak_opt_modelinefmt" | sed -E ' | |
s/%(opt|val|sh|arg|reg)\{/%\1{'$(printf '\033')'/g; | |
s/\{[a-z-]+(,[a-z-]+)?(,[a-z]+)?(\+[rbBdisFfga]+)?(@[a-zA-Z_]+)?\}//g | |
s/'$(printf '\033')'//g | |
s/\{\{(mode_info|context_info)\}\}/ /g | |
s/"/""/g | |
' | |
# }} | |
printf '"\n' | |
} | |
evaluate-commands %sh{ | |
. prelude.inc.sh | |
. kak.inc.sh | |
width=$(printf '%s' "$kak_opt_approximate_modeline" | wc -m) | |
normalize() { | |
printf %s\\n "$*" | |
} | |
shrink() { | |
[ "$kak_window_width" -le "$width" ] || return | |
once=false | |
[ "$1" = once ] && once=true | |
eval set -- $kak_opt_powerline_module_priority | |
reversed="" | |
for module; do reversed="$module $reversed"; done | |
eval set -- $reversed | |
for module; do | |
if printf %s\\n "$kak_opt_powerline_format" | | |
grep $module >/dev/null | |
then | |
newfmt="$(printf %s\\n "$kak_opt_powerline_format" | | |
sed "s/$module//")" | |
printf 'set-option buffer powerline_format %s\n' \ | |
"$(kakquote "$newfmt")" | |
printf 'powerline-rebuild-buffer\n' | |
$once || printf 'resize-powerline shrink\n' | |
return | |
fi | |
done | |
} | |
grow() { | |
[ "$width" -le "$kak_window_width" ] || return | |
[ "$(normalize $kak_opt_powerline_format)" \ | |
= "$(normalize $kak_opt_powerline_format_orig)" ] \ | |
&& return | |
eval set -- $kak_quoted_opt_powerline_module_priority | |
for m1; do | |
if ! printf %s\\n "$kak_opt_powerline_format" | | |
grep "$m1" >/dev/null | |
then | |
( | |
oldfmt="$kak_opt_powerline_format" | |
newfmt="" | |
eval set -- $kak_opt_powerline_format_orig | |
for m2; do | |
if [ "$m1" = "$m2" ]; then | |
newfmt="$newfmt "$m1" $oldfmt" | |
printf 'set-option buffer powerline_format %s\n' \ | |
"$(kakquote "$newfmt")" | |
printf 'powerline-rebuild-buffer\n' | |
printf 'resize-powerline grow\n' | |
return | |
fi | |
read -r head_old tail_old <<EOF | |
$oldfmt | |
EOF | |
if [ "$head_old" = "$m2" ]; then | |
newfmt="$newfmt $head_old" | |
oldfmt="$tail_old" | |
fi | |
done | |
) | |
return | |
fi | |
done | |
} | |
if [ "$kak_window_width" -le "$width" ] | |
then if [ "$1" = grow ] | |
then shrink once | |
else shrink | |
fi | |
else [ "$1" != shrink ] && grow | |
fi | |
} | |
} | |
# When resize hooks fire, a lot fire at once, and resizing the powerline is slow. | |
# Instead of letting a bunch of calls to resize-powerline queue up, we wait for | |
# hooks to stop firing for powerline_resize_delay ms before doing anything. | |
declare-option -hidden int-list powerline_resize_jobs | |
declare-option -hidden int-list powerline_resize_jobs_tmp | |
define-command -hidden schedule-powerline-resize %{ | |
evaluate-commands %sh{ | |
( | |
sleep $(printf %s $kak_opt_powerline_resize_delay | | |
sed -E 's/^([0-9]{1,3})$/0.\1/;s/^([0-9]+)([0-9]{3})$/\1.\2/') | |
printf 'evaluate-commands -buffer %s "resize-powerline-wrapper %s"\n' \ | |
"$kak_bufname" $$ | kak -p "$kak_session" | |
) >/dev/null 2>&1 </dev/null & | |
printf 'set-option -add buffer powerline_resize_jobs %s\n' $! | |
eval set -- $kak_opt_powerline_resize_jobs | |
for job; do | |
kill "$job" >/dev/null 2>&1 </dev/null & | |
done | |
printf 'set-option buffer powerline_resize_jobs\n' | |
} | |
} | |
# Window resizing is a property of the window, but unfortunately modelines | |
# are the property of the buffer. We need to find the narrowest client that's | |
# open to a window bound to the same buffer as the resized window, and then | |
# perform the resize computation on THAT window, otherwise if a window is | |
# resized while a narrower window is displaying the same buffer, the powerline | |
# will grow too large for the smaller one. Also there's a concurrency mess here. | |
declare-option -hidden bool powerline_resize_locked false | |
declare-option -hidden str-to-str-map powerline_resize_client_widths | |
declare-option -hidden str powerline_resize_narrowest_client | |
define-command -hidden -params 1 resize-powerline-wrapper %{ | |
set-option buffer powerline_resize_jobs_tmp %opt{powerline_resize_jobs} | |
set-option buffer powerline_resize_jobs | |
try %{ | |
evaluate-commands %sh{ | |
invoking_job="$1" | |
eval set -- $kak_opt_powerline_resize_jobs_tmp | |
for job; do | |
case "$job" in | |
0|"$invoking_job") : ;; | |
*) kill "$job" >/dev/null 2>&1 </dev/null & ;; | |
esac | |
done | |
if $kak_opt_powerline_resize_locked; then | |
printf 'fail "powerline-resize locked"\n' | |
else | |
printf 'set-option buffer powerline_resize_locked true\n' | |
fi | |
} | |
echo -debug 'init_resize' | |
set-option buffer powerline_resize_client_widths | |
evaluate-commands %sh{ | |
. kak.inc.sh | |
. prelude.inc.sh | |
eval set -- $kak_quoted_client_list | |
for client; do | |
printf 'evaluate-commands -client %s %%{ | |
evaluate-commands %%sh{ | |
if [ "$kak_bufname" = %s ]; then | |
printf %s "$kak_client" $kak_window_width | |
fi | |
} | |
}\n' "$(kakquote "$client")" "$(quote "$kak_bufname")" \ | |
"'set-option -add buffer powerline_resize_client_widths %%{%s=%s}'" | |
done | |
} | |
evaluate-commands %sh{ | |
eval set -- $kak_quoted_opt_powerline_resize_client_widths | |
if [ $# = 0 ]; then | |
printf 'fail "no clients?"\n' | |
return | |
fi | |
min=9999999 | |
min_client= | |
for entry; do | |
client="${entry%%=*}" | |
width="${entry#*=}" | |
if [ "$width" -lt "$min" ]; then | |
min="$width" | |
min_client="$client" | |
fi | |
done | |
printf 'set-option buffer powerline_resize_narrowest_client %s\n' "$min_client" | |
} | |
evaluate-commands -client %opt{powerline_resize_narrowest_client} %{ | |
remove-hooks buffer powerline-resize | |
resize-powerline whatever %arg{@} | |
powerline-resize-enable | |
} | |
set-option buffer powerline_resize_locked false | |
} catch %{ | |
evaluate-commands %sh{ | |
if [ "$kak_error" != "powerline-resize locked" ]; then | |
printf 'set-option buffer powerline_resize_locked false\n' | |
printf 'fail %%val{error}\n' | |
fi | |
} | |
} | |
} | |
evaluate-commands %sh{ | |
. kak.inc.sh | |
eval set -- $kak_quoted_buflist | |
for buf; do | |
printf 'evaluate-commands -buffer %s powerline-resize-enable\n' \ | |
"$(kakquote "$buf")" | |
done | |
} | |
hook -group init-powerline-resize global BufCreate .* powerline-resize-enable |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment