AutoYADM commit: 2025-03-28 14:50:17

This commit is contained in:
Daniel Fichtinger 2025-03-28 14:50:17 -04:00
parent 7826b4a80c
commit fb7662f40a
5 changed files with 787 additions and 0 deletions

View file

@ -0,0 +1,433 @@
# FIXME this can't be called in sequence in general case,
# because of unsynchronized `commandline -f` and `commandline -C`
function fish_helix_command
argparse 'h/help' -- $argv
or return 1
if test -n "$_flag_help"
echo "Helper function to handle modal key bindings mostly outside of insert mode"
return
end
# TODO only single command allowed really yet,
# because `commandline -f` queues actions, while `commandline -C` is immediate
for command in $argv
set -f count (fish_bind_count -r)
set -f count_defined $status
switch $command
case {move,extend}_char_left
commandline -C (math max\(0, (commandline -C) - $count\))
__fish_helix_extend_by_command $command
case {move,extend}_char_right
commandline -C (math (commandline -C) + $count)
__fish_helix_extend_by_command $command
case char_up
__fish_helix_char_up $fish_bind_mode $count
case char_down
__fish_helix_char_down $fish_bind_mode $count
case next_word_start
# https://regex101.com/r/KXrl1x/1
set -l regex (string join '' \
'(?:.?\\n+|' \
'[[:alnum:]_](?=[^[:alnum:]_\\s])|' \
'[^[:alnum:]_\\s](?=[[:alnum:]_])|' \
'[^\\S\\n](?=[\\S\\n])|)' \
'((?:[[:alnum:]_]+|[^[:alnum:]_\\s]+|)[^\\S\\n]*)' \
)
__fish_helix_next_word $fish_bind_mode $count $regex
case next_long_word_start
set -l regex (string join '' \
'(?:.?\\n+|' \
'[^\\S\\n](?=[\\S\\n])|)' \
'(\\S*[^\\S\\n]*)' \
)
__fish_helix_next_word $fish_bind_mode $count $regex
case next_word_end
# https://regex101.com/r/Gl0KP2/1
set -l regex ' (?:
.?\\n+ |
[[:alnum:]_](?=[^[:alnum:]_]) |
[^[:alnum:]_\\s](?=[[:alnum:]_\\s]) | )
( [^\\S\\n]*
(?: [[:alnum:]_]+ | [^[:alnum:]_\\s]+ | ) ) '
__fish_helix_next_word $fish_bind_mode $count $regex
case next_long_word_end
set -l regex ' (?: .?\\n+ | \\S(?=\\s) | )
( [^\\S\\n]* \\S* ) '
__fish_helix_next_word $fish_bind_mode $count $regex
case prev_word_start
set -l regex ' ( (?:
[[:alnum:]_]+ |
[^[:alnum:]_\\s]+ | )
[^\\S\\n]* )
(?: \\n+.? |
(?<=[^[:alnum:]_])[[:alnum:]_] |
(?<=[[:alnum:]_\\s])[^[:alnum:]_\\s] | ) '
__fish_helix_prev_word $fish_bind_mode $count $regex
case prev_long_word_start
set -l regex '
( \\S* [^\\S\\n]* )
(?: \\n+.? | (?<=\\s)\\S | ) '
__fish_helix_prev_word $fish_bind_mode $count $regex
case till_next_char
__fish_helix_find_char $fish_bind_mode $count forward-jump-till forward-char
case find_next_char
__fish_helix_find_char $fish_bind_mode $count forward-jump
case till_prev_char
__fish_helix_find_char $fish_bind_mode $count backward-jump-till backward-char
case find_prev_char
__fish_helix_find_char $fish_bind_mode $count backward-jump
case till_next_cr
__fish_helix_find_next_cr $fish_bind_mode $count 2
case find_next_cr
__fish_helix_find_next_cr $fish_bind_mode $count 1
case till_prev_cr
__fish_helix_find_prev_cr $fish_bind_mode $count 1
case find_prev_cr
__fish_helix_find_prev_cr $fish_bind_mode $count 0
case goto_line_start
commandline -f beginning-of-line
__fish_helix_extend_by_mode
case goto_line_end
__fish_helix_goto_line_end
__fish_helix_extend_by_mode
case goto_first_nonwhitespace
__fish_helix_goto_first_nonwhitespace
__fish_helix_extend_by_mode
case goto_file_start
__fish_helix_goto_line $count
case goto_line
if test "$count_defined" = 0 # if true
__fish_helix_goto_line $count
end
case goto_last_line
commandline -f end-of-buffer beginning-of-line
__fish_helix_extend_by_mode
case insert_mode
commandline -C (commandline -B)
set fish_bind_mode insert
commandline -f end-selection repaint-mode
case append_mode
commandline -C (commandline -E)
set fish_bind_mode insert
commandline -f end-selection repaint-mode
case prepend_to_line
__fish_helix_goto_first_nonwhitespace
set fish_bind_mode insert
commandline -f end-selection repaint-mode
case append_to_line
set fish_bind_mode insert
commandline -f end-selection end-of-line repaint-mode
case delete_selection
commandline -f kill-selection begin-selection
case delete_selection_noyank
__fish_helix_delete_selection
case yank
__fish_helix_yank
case paste_before
__fish_helix_paste_before "commandline -f yank"
case paste_after
__fish_helix_paste_after "commandline -f yank"
case replace_selection
__fish_helix_replace_selection "$fish_killring[1]" "true"
case paste_before_clip
__fish_helix_paste_before "fish_clipboard_paste"
case paste_after_clip
__fish_helix_paste_after "fish_clipboard_paste" --clip
case replace_selection_clip
__fish_helix_replace_selection "" "fish_clipboard_paste" --clip
case select_all
commandline -f beginning-of-buffer begin-selection end-of-buffer end-of-line backward-char
case '*'
echo "[fish-helix]" Unknown command $command >&2
end
end
end
function __fish_helix_extend_by_command -a piece
if not string match -qr extend_ $piece
commandline -f begin-selection
end
end
function __fish_helix_extend_by_mode
if test $fish_bind_mode = default
commandline -f begin-selection
end
end
function __fish_helix_find_char -a mode count fish_cmdline till
# FIXME don't reset selection if N/A
if test $mode = default
commandline -f begin-selection
end
commandline -f $till $fish_cmdline
for i in (seq 2 $count)
commandline -f $till repeat-jump
end
end
function __fish_helix_find_next_cr -a mode count skip
set -l cursor (commandline -C)
commandline | # Include endling newline intentionally
# Skip until cursor:
sed -z 's/^.\{'(math $cursor + $skip)'\}\(.*\)$/\\1/' |
# Count characters up to the target newline:
sed -z 's/^\(\([^\\n]*\\n\)\{0,'$count'\}\).*/\\1/' |
read -zl chars
if test $mode = default -a -n "$chars"
commandline -f begin-selection
end
for i in (seq 1 (string length -- "$chars"))
commandline -f forward-char
end
end
function __fish_helix_find_prev_cr -a mode count skip
set -l cursor (commandline -C)
commandline --cut-at-cursor |
sed -z 's/.\{'$skip'\}\n$//' |
read -zl buffer
echo -n $buffer |
# Drop characters up to the target newline:
sed -z 's/\(\(\\n[^\\n]*\)\{0,'$count'\}\)$//' |
read -zl chars
set -l n_chars (math (string length -- "$buffer") - (string length -- "$chars"))
if test $mode = default -a $n_chars != 0
commandline -f begin-selection
end
for i in (seq 1 $n_chars)
commandline -f backward-char
end
end
function __fish_helix_goto_line_end
# check if we are on an empty line first
commandline | sed -n (commandline -L)'!b;/^$/q;q5' && return
commandline -f end-of-line backward-char
end
function __fish_helix_goto_first_nonwhitespace
# check if we are on whitespace line first
commandline | sed -n (commandline -L)'!b;/^\\s*$/q;q5' && return
commandline -f beginning-of-line forward-bigword backward-bigword
end
function __fish_helix_goto_line -a number
set -l lines (math min\($number, (commandline | wc -l)\))
commandline -f beginning-of-buffer
for i in (seq 2 $lines)
commandline -f down-line
end
__fish_helix_extend_by_mode
end
function __fish_helix_char_up -a mode count
if commandline --paging-mode && not commandline --search-mode
for i in (seq 1 $count)
commandline -f up-line
end
return
end
set -l line (commandline -L)
if commandline --search-mode || test $line = 1
for i in (seq 1 (math min \($count, (count $history)\)))
commandline -f history-search-backward
end
return
end
set -l count (math min\($count, $line-1\))
for i in (seq 1 $count)
commandline -f up-line
end
__fish_helix_extend_by_mode
end
function __fish_helix_char_down -a mode count
if commandline --paging-mode && not commandline --search-mode
for i in (seq 1 $count)
commandline -f down-line
end
return
end
set -l line (commandline -L)
set -l total (count (commandline))
if commandline --search-mode || test $line = $total
for i in (seq 1 (math min \($count, (count $history)\)))
commandline -f history-search-forward
end
return
end
set -l count (math min\($count, $total - $line\))
for i in (seq 1 $count)
commandline -f down-line
end
__fish_helix_extend_by_mode
end
function __fish_helix_next_word -a mode count regex
set -f cursor (commandline -C)
commandline |
perl -e '
use open qw(:std :utf8);
do { local $/; substr <>, '$cursor' } =~ m/(?:'$regex'){0,'$count'}/ux;
print $-[1], " ", $+[1];' |
read -f left right
test "$left" = "$right" && return
if test $mode = default
commandline -C (math $cursor + $left)
commandline -f begin-selection
for i in (seq $left (math $right - 2))
commandline -f forward-char
end
else
commandline -C (math $cursor + $right - 1)
end
end
function __fish_helix_prev_word -a mode count regex
set -f left (math (commandline -C) + 1)
set -f updated 0
for i in (seq 1 $count)
commandline |
perl -e '
use open qw(:std :utf8);
do { local $/; substr <>, 0, '$left' } =~ /(?:'$regex')$/ux;
print $-[1], " ", $+[1];' |
read -l l r
test "$l" = "$r" -o "$l" = 0 -a "$r" = 1 && break
set -f left $l
set -f right $r
set -f updated 1
end
test $updated -eq 0; and return
if test $mode = default
commandline -C (math $right - 1)
commandline -f begin-selection
for i in (seq $left (math $right - 2))
commandline -f backward-char
end
else
commandline -C (math $left)
end
end
function __fish_helix_delete_selection
set start (commandline -B)
set end (commandline -E)
commandline |
sed -zE 's/^(.{'$start'})(.{0,'(math $end - $start)'})(.*)\\n$/\\1\\3/' |
read -l result
commandline "$result"
commandline -C $start
commandline -f begin-selection
end
function __fish_helix_yank
set -l end (commandline -E)
set -l cursor (commandline -C)
commandline -f kill-selection yank backward-char
for i in (seq $cursor (math $end - 2))
commandline -f backward-char
end
end
function __fish_helix_paste_before -a cmd_paste
set -l cmd_paste $(string split " " $cmd_paste)
set -l cursor (commandline -C)
set -l start (commandline -B)
set -l end (commandline -E)
commandline -C $start
$cmd_paste
commandline -f begin-selection
for i in (seq $start (math $end - 2))
commandline -f forward-char
end
if test $cursor = $start
commandline -f swap-selection-start-stop
end
end
function __fish_helix_paste_after -a cmd_paste
set -l cmd_paste $(string split " " $cmd_paste)
set -l cursor (commandline -C)
set -l start (commandline -B)
set -l end (commandline -E)
commandline -C $end
$cmd_paste
if test "$argv[2]" = "--clip"
commandline -C (math $end - 1)
else
for i in (seq 0 (string length "$fish_killring[1]"))
commandline -f backward-char
end
end
commandline -f begin-selection
for i in (seq $start (math $end - 2))
commandline -f backward-char
end
if test $cursor != $start
commandline -f swap-selection-start-stop
end
end
function __fish_helix_replace_selection -a replacement cmd_paste
set -l cmd_paste $(string split " " $cmd_paste)
set cursor (commandline -C)
set start (commandline -B)
set end (commandline -E)
commandline |
sed -zE 's/^(.{'$start'})(.{0,'(math $end - $start)'})(.*)\\n$/\\1'"$(string escape --style=regex "$replacement")"'\\3/' |
read -l result
commandline "$result"
commandline -C $start
$cmd_paste
if test "$argv[3]" = --clip
commandline -f backward-char begin-selection
for i in (seq (math $start + 2) (commandline -C))
commandline -f backward-char
end
if test $cursor != $start
commandline -f swap-selection-start-stop
end
else
commandline -f begin-selection
for i in (seq 2 (string length "$replacement"))
commandline -f forward-char
end
if test $cursor = $start
commandline -f swap-selection-start-stop
end
end
end