diff --git a/.config/kak/autoload/byline.kak b/.config/kak/autoload/byline.kak new file mode 100644 index 00000000..0ab13b75 --- /dev/null +++ b/.config/kak/autoload/byline.kak @@ -0,0 +1,146 @@ +provide-module byline %{ + + # Mappings + + map global "normal" "x" ": byline-drag-down" + map global "normal" "X" ": byline-drag-up" + + # High-level selection expanding and contracting, based on selection direction + + define-command -hidden byline-drag-down %{ + evaluate-commands -itersel -no-hooks %{ + try %{ + byline-assert-selection-forwards + byline-expand-below + } catch %{ + byline-contract-above + } + } + } + + define-command -hidden byline-drag-up %{ + evaluate-commands -itersel -no-hooks %{ + try %{ + byline-assert-selection-forwards + byline-contract-below + } catch %{ + byline-expand-above + } + } + } + + # Assertions + + define-command -hidden byline-assert-selection-reduced %{ + # Selections on blank lines are not considered reduced + execute-keys -draft "^$" + # Single-character selections are reduced + execute-keys -draft "\A.{,1}\z" + } + + define-command -hidden byline-assert-selection-forwards %{ + try %{ + # If the selection is just the cursor or blank line + # , we treat it as being in the forwards + # direction, and can exit early + byline-assert-selection-reduced + } catch %{ + evaluate-commands -no-hooks -draft -save-regs 'ab' %{ + # store current cursor pos + set-register a %val{cursor_byte_offset} + # force cursor forward + execute-keys + # store second cursor pos + set-register b %val{cursor_byte_offset} + # if the sel faces forward, the cursor hasn't moved + # So we paste reg a. the pasted content is now selected. + # We can use to check whether it matches register b. + try %{ + execute-keys %exp{"aP%reg{b}u} + } catch %{ + # clean up the pasted content if the above + # assertion failed + execute-keys 'u' + # propogate failure to caller + fail + } + } + } + } + + define-command -hidden byline-assert-selection-full-lines %{ + # Starts at beginning of line + execute-keys -draft ";\A^" + # Ends at end of line + execute-keys -draft ";$" + } + + # Low-level selection expanding and contracting primitives + + define-command -hidden byline-expand-above %{ + try %{ + byline-assert-selection-full-lines + execute-keys "%val{count}Kx" + } catch %{ + execute-keys "x" + evaluate-commands -no-hooks %sh{ + if [ "$kak_count" -gt 1 ]; then + echo "execute-keys '$((kak_count - 1))Kx'" + fi + } + } + } + + define-command -hidden byline-contract-above %{ + try %{ + byline-assert-selection-full-lines + execute-keys "%val{count}Jx" + } catch %{ + try %{ + execute-keys "" + } catch %{ + execute-keys "x" + } + execute-keys "" + evaluate-commands -no-hooks %sh{ + if [ "$kak_count" -gt 1 ]; then + echo "execute-keys '$((kak_count - 1))Jx'" + fi + } + } + } + + define-command -hidden byline-expand-below %{ + try %{ + byline-assert-selection-full-lines + execute-keys "%val{count}Jx" + } catch %{ + execute-keys "x" + evaluate-commands -no-hooks %sh{ + if [ "$kak_count" -gt 1 ]; then + echo "execute-keys '$((kak_count - 1))Jx'" + fi + } + } + } + + define-command -hidden byline-contract-below %{ + try %{ + byline-assert-selection-full-lines + execute-keys "%val{count}Kx" + } catch %{ + try %{ + execute-keys "" + } catch %{ + execute-keys "x" + } + execute-keys "" + evaluate-commands -no-hooks %sh{ + if [ "$kak_count" -gt 1 ]; then + echo "execute-keys '$((kak_count - 1))Kx'" + fi + } + } + } + +}