diff options
author | Marc Coquand <marc@mccd.space> | 2024-05-15 19:47:21 -0500 |
---|---|---|
committer | Marc Coquand <marc@mccd.space> | 2024-05-15 19:47:21 -0500 |
commit | 9536a4c2b46e6851db41bab2806c7bdeee8edbb8 (patch) | |
tree | 5a7be6c2376ed92884557d0257d0ed8c3dc1e796 /config | |
parent | d09be0d5ced1b31e40a1114581abfce0db06c540 (diff) | |
download | rcm-9536a4c2b46e6851db41bab2806c7bdeee8edbb8.tar.gz rcm-9536a4c2b46e6851db41bab2806c7bdeee8edbb8.tar.bz2 rcm-9536a4c2b46e6851db41bab2806c7bdeee8edbb8.zip |
Add kak and more
Diffstat (limited to '')
-rw-r--r-- | config/kak/auto-pairs.kak | 185 | ||||
-rw-r--r-- | config/kak/colors/simple-dark.kak | 57 | ||||
-rw-r--r-- | config/kak/colors/simple.kak | 66 | ||||
-rw-r--r-- | config/kak/kakrc | 248 | ||||
-rw-r--r-- | config/kak/ocaml-snippets.kak | 35 | ||||
-rw-r--r-- | config/kak/palette.kak | 102 | ||||
-rw-r--r-- | config/kak/phantom-selection.kak | 84 | ||||
-rw-r--r-- | config/kak/smarttab.kak | 119 | ||||
-rw-r--r-- | config/kak/snippets.kak | 295 |
9 files changed, 1191 insertions, 0 deletions
diff --git a/config/kak/auto-pairs.kak b/config/kak/auto-pairs.kak new file mode 100644 index 0000000..16798d2 --- /dev/null +++ b/config/kak/auto-pairs.kak @@ -0,0 +1,185 @@ +# Auto-pairing of characters +# Heavily based on Visual Studio Code. +# https://code.visualstudio.com +# +# Public commands: ["enable-auto-pairs", "disable-auto-pairs"] +# Public options: ["auto_pairs"] +# +# Usage: +# +# enable-auto-pairs +# +# Configuration: +# +# set-option global auto_pairs ( ) { } [ ] '"' '"' "'" "'" ` ` “ ” ‘ ’ « » ‹ › +# +# How does it work? +# +# The script installs insert hooks on opening pair characters, such as brackets and quotes. +# When auto-closing has been triggered, it activates the following functionalities: +# +# – {closing-pair} ⇒ Insert closing pair or move right in pair +# – Enter ⇒ Insert a new indented line in pair (only for the next key) +# – Control+Enter ⇒ Prompt a count for new indented lines in pair (only for the next key) +# +# When moving or leaving insert mode, the functionalities deactivate. +# +# Technical details: +# +# – Insert hooks are added on opening pair characters from %opt{auto_pairs} option. +# – Evaluates %opt{auto_close_trigger} option to activate auto-pairing. +# – Provides %opt{opening_pair} expansion in expressions. +# – Uses %opt{inserted_pairs} count to keep track of inserted pairs for inserting or moving in pair. +# – Uses the same implementation for nestable (such as brackets) and non-nestable (such as quotes) pairs. +# Since insert hooks are added on opening pair characters (for auto-pairing) and mappings on closing pair characters (for moving in pair), +# we can distinguish same pair characters once auto-pairing has been activated. + +# Configuration ──────────────────────────────────────────────────────────────── + +# List of surrounding pairs +declare-option -docstring 'list of surrounding pairs' str-list auto_pairs ( ) { } [ ] '"' '"' "'" "'" ` ` “ ” ‘ ’ « » ‹ › + +# Auto-pairing of characters activates only when this expression does not fail. +# By default, it avoids non-nestable pairs (such as quotes), escaped pairs and word characters. +declare-option -docstring 'auto-pairing of characters activates only when this expression does not fail' str auto_close_trigger '<a-h><a-K>(\w["''`]|""|''''|``).\z<ret><a-k>[^\\]?\Q%opt{opening_pair}<a-!>\E\W\z<ret>' + +# Internal variables ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ + +# Retain inserted pairs +declare-option -hidden str opening_pair +declare-option -hidden int inserted_pairs + +# Commands ───────────────────────────────────────────────────────────────────── + +define-command -override enable-auto-pairs -docstring 'enable auto-pairs' %{ + remove-hooks global auto-pairs + evaluate-commands %sh{ + set -- ${kak_opt_auto_pairs} + while [ "$2" ] + do + printf 'auto-close-pair %%<%s> %%<%s>\n' "$1" "$2" + shift 2 + done + } +} + +define-command -override disable-auto-pairs -docstring 'disable auto-pairs' %{ + remove-hooks global auto-pairs +} + +# Internal commands ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ + +define-command -override -hidden auto-close-pair -params 2 %{ + hook -group auto-pairs global InsertChar "\Q%arg{1}" "handle-inserted-opening-pair %%<%arg{1}> %%<%arg{2}>" + hook -group auto-pairs global InsertDelete "\Q%arg{1}" "handle-deleted-opening-pair %%<%arg{1}> %%<%arg{2}>" +} + +# Internal hooks ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ + +define-command -override -hidden handle-inserted-opening-pair -params 2 %{ + try %{ + # Test whether the commands contained in the option pass. + # If not, it will throw an exception and execution will jump to + # the “catch” block below. + set-option window opening_pair %arg{1} + execute-keys -draft %opt{auto_close_trigger} + + # Action: Close pair + execute-keys %arg{2} + + # Keep the track of inserted pairs + increment-inserted-pairs-count + + # Move back in pair (preserve selected text): + try %{ + execute-keys -draft '<a-k>..<ret>' + execute-keys '<a-;>H' + } catch %{ + execute-keys '<a-;>h' + } + + # Add insert mappings + map -docstring 'insert closing pair or move right in pair' window insert %arg{2} "<a-;>:insert-closing-pair-or-move-right-in-pair %%🐈%arg{2}🐈<ret>" + map -docstring 'insert a new indented line in pair' window insert <ret> '<a-;>:insert-new-line-in-pair<ret>' + map -docstring 'prompt a count for new indented lines in pair' window insert <c-ret> '<a-;>:prompt-insert-new-line-in-pair<ret>' + + # Enter is only available on next key. + hook -group auto-pairs -once window InsertChar '.*' %{ + unmap window insert <ret> + unmap window insert <c-ret> + } + + # Clean insert mappings and remove hooks + hook -group auto-pairs -once window WinSetOption 'inserted_pairs=0' " + unmap window insert %%🐈%arg{2}🐈 + unmap window insert <ret> + unmap window insert <c-ret> + remove-hooks window auto-pairs + " + + # Clean state when moving or leaving insert mode + hook -group auto-pairs -once window InsertMove '.*' %{ + reset-inserted-pairs-count + } + + hook -always -once window ModeChange 'pop:insert:normal' %{ + reset-inserted-pairs-count + } + } +} + +# Backspace ⇒ Erases the whole bracket +define-command -override -hidden handle-deleted-opening-pair -params 2 %{ + try %{ + execute-keys -draft "<space>;<a-k>\Q%arg{2}<ret>" + execute-keys '<del>' + decrement-inserted-pairs-count + } +} + +# Internal mappings ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ + +# {closing-pair} ⇒ Insert closing pair or move right in pair +define-command -override -hidden insert-closing-pair-or-move-right-in-pair -params 1 %{ + try %{ + execute-keys -draft "<space>;<a-k>\Q%arg{1}<ret>" + # Move right in pair + execute-keys '<a-;>l' + decrement-inserted-pairs-count + } catch %{ + # Insert character with hooks + execute-keys -with-hooks %arg{1} + } +} + +# Enter ⇒ Insert a new indented line in pair (only for the next key) +define-command -override -hidden insert-new-line-in-pair %{ + execute-keys '<a-;>;<ret><ret><esc>KK<a-&>j<a-gt>' + execute-keys -with-hooks A + reset-inserted-pairs-count +} + +# Control+Enter ⇒ Prompt a count for new indented lines in pair (only for the next key) +define-command -override -hidden prompt-insert-new-line-in-pair %{ + prompt count: %{ + execute-keys '<a-;>;<ret><ret><esc>KK<a-&>j<a-gt>' + execute-keys "xHyx<a-d>%val{text}O<c-r>""<esc>" + execute-keys -with-hooks A + reset-inserted-pairs-count + } +} + +# ┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈ + +# Increment and decrement inserted pairs count +define-command -override -hidden increment-inserted-pairs-count %{ + set-option -add window inserted_pairs 1 +} + +define-command -override -hidden decrement-inserted-pairs-count %{ + set-option -remove window inserted_pairs 1 +} + +define-command -override -hidden reset-inserted-pairs-count %{ + set-option window inserted_pairs 0 +} diff --git a/config/kak/colors/simple-dark.kak b/config/kak/colors/simple-dark.kak new file mode 100644 index 0000000..2d5a3e9 --- /dev/null +++ b/config/kak/colors/simple-dark.kak @@ -0,0 +1,57 @@ +# code + +face global value rgb:ffffff,default +face global type rgb:dedede,default +face global identifier rgb:dedede,default +face global string rgb:eeffff,default +face global DiagnosticError rgb:fecece,default +face global keyword rgb:dedede,default+b +face global builtin rgb:dedede,default +face global module rgb:dedede,default +face global operator rgb:dedede,default +face global attribute rgb:ffffff,default +face global comment rgb:787878,default +face global meta rgb:878787,default +face global function rgb:dedede,default +face global argument rgb:dedede,default +face global comma rgb:dedede,default +face global constant rgb:dedede,default +face global class rgb:dedede,default +face global variable rgb:dedede,default + +# text + +face global title rgb:ffffff,default+b +face global header rgb:ffffff,default +face global bold rgb:ffffff,default+b +face global italic rgb:ededed,default+i +face global mono rgb:cccccc,rgb:212121 +face global block rgb:cccccc,rgb:212121 +face global link rgb:ffffff,default +face global bullet rgb:ffffff,default +face global list rgb:dedede,default + +# kakoune UI + +face global Default rgb:cccccc,rgb:000000 +face global PrimarySelection rgb:000000,rgb:cccccc +face global SecondarySelection rgb:121212,rgb:ababab +face global PrimaryCursor rgb:000000,rgb:ffffff+b +face global SecondaryCursor rgb:121212,rgb:dedede+b +face global MatchingChar default,rgb:333333 +face global Search default,rgb:333333 +face global Whitespace default,rgb:333333 +face global BufferPadding rgb:333333,default +face global LineNumbers rgb:333333,default +face global LineNumberCursor rgb:666666,default +face global MenuForeground rgb:121212,rgb:dedede +face global MenuBackground rgb:ededed,rgb:212121 +face global MenuInfo rgb:ededed,rgb:545454 +face global Information rgb:ededed,rgb:454545 +face global Error rgb:fecece,default +face global StatusLine rgb:cccccc,rgb:212121 +face global StatusLineMode rgb:121212,rgb:dedede +face global StatusLineInfo rgb:ffffff,rgb:333333 +face global StatusLineValue rgb:ffffff,rgb:454545 +face global StatusCursor default,rgb:787878 +face global Prompt rgb:121212,rgb:dedede diff --git a/config/kak/colors/simple.kak b/config/kak/colors/simple.kak new file mode 100644 index 0000000..31fe659 --- /dev/null +++ b/config/kak/colors/simple.kak @@ -0,0 +1,66 @@ + +face global value rgb:000000,default +face global type rgb:212121,default +face global identifier rgb:212121,default +face global string rgb:41486c,default +face global error default,rgb:000000 +face global keyword rgb:212121,default+b +face global builtin rgb:212121,default+b +face global module rgb:212121,default +face global operator rgb:212121,default +face global attribute rgb:000000,default +face global comment rgb:878787,default +face global meta rgb:787878,default +face global function rgb:787878,default +face global argument rgb:787878,default +face global comma rgb:212121,default +face global constant rgb:212121,default +face global class rgb:212121,default +face global variable rgb:212121,default +face global builtin rgb:212121,default+b + +face global title rgb:000000,default+b +face global header rgb:000000,default +face global bold rgb:000000,default+b +face global italic rgb:121212,default+i +face global mono rgb:111111,rgb:dedede +face global block rgb:111111,rgb:dedede +face global link rgb:000000,default +face global bullet rgb:000000,default +face global list rgb:212121,default + +face global Default rgb:111111,rgb:FFFFFF +face global PrimarySelection rgb:111111,rgb:cecece +face global SecondarySelection rgb:333333,rgb:EEEEEE +face global PrimaryCursor rgb:ffffff,rgb:111111+b +face global SecondaryCursor rgb:ededed,rgb:212121+b +face global MatchingChar default,rgb:cccccc +face global Search default,rgb:cccccc +face global Whitespace default,rgb:cccccc +face global BufferPadding rgb:cccccc,default +face global LineNumbers rgb:cccccc,default +face global LineNumberCursor rgb:999999,default +face global MenuForeground rgb:ededed,rgb:212121 +face global MenuBackground default,rgb:dedede +face global MenuInfo default,rgb:ababab +face global Information default,rgb:bababa +face global Error rgb:ededed,rgb:212121 +face global StatusLine rgb:333333,rgb:dedede +face global StatusLineMode rgb:ededed,rgb:212121 +face global StatusLineInfo rgb:000000,rgb:cccccc +face global StatusLineValue rgb:000000,rgb:bababa +face global StatusCursor default,rgb:878787 +face global Prompt rgb:ededed,rgb:212121 + +face global InfoBlock Information +face global InfoBlockQuote Information +face global InfoBullet Information +face global InfoHeader Information +face global InfoLink Information +face global InfoLinkMono Information +face global InfoMono Information +face global InfoRule Information +face global InfoDiagnosticError Information +face global InfoDiagnosticHint Information +face global InfoDiagnosticInformation Information +face global InfoDiagnosticWarning Information diff --git a/config/kak/kakrc b/config/kak/kakrc new file mode 100644 index 0000000..26b0a88 --- /dev/null +++ b/config/kak/kakrc @@ -0,0 +1,248 @@ +# --- PLUGINS +source "~/.config/kak/smarttab.kak" +source "~/.config/kak/palette.kak" +source "~/.config/kak/auto-pairs.kak" +source "~/.config/kak/snippets.kak" +source "~/.config/kak/phantom-selection.kak" + +# --- Auto pairs +enable-auto-pairs + +# --- LSP & FORMATTING +# https://discuss.kakoune.com/t/sane-kak-lsp-config-hook/2019 +hook global WinSetOption filetype=(rust|python|nim|go|javascript|typescript|c|cpp|ocaml|haskell|markdown|elixir|nix) %{ + set global lsp_hover_anchor true + lsp-enable-window + lsp-auto-hover-insert-mode-enable +} +hook global WinSetOption filetype=(eml|markdown) %{ + spell +} +hook global BufSetOption filetype=(javascript|typescript) %{ + set-option buffer formatcmd "prettier --stdin-filepath=%val{buffile}" + hook buffer BufWritePre .* %{format} +} + +hook global BufSetOption filetype=(javascript|typescript|elixir|haskell|rust|markdown|c|cpp) %{ + lsp-auto-signature-help-enable +} + +hook global BufSetOption filetype=(terraform|ocaml|elixir|nix) %{ + hook buffer BufWritePre .* %{lsp-formatting-sync} +} + +eval %sh{kak-lsp --kakoune -s $kak_session} +lsp-enable + +# --- GREP +set-option global grepcmd 'rg --column' + +# --- Line number +add-highlighter global/ number-lines + +# --- COMMANDS +define-command fd -docstring "find files" -params 1 %{ edit %arg{1} } +complete-command fd shell-script-candidates %{ fd -t f } + +map global goto f '<esc>:prompt -menu -shell-script-candidates %{ fd -t f } fd: %{ edit %val{text} }<ret>' -docstring "Goto file" + +define-command z -docstring "Change Directory (Z)" -params 1 %{ change-directory %sh{zoxide query $1} } +complete-command z shell-script-candidates %{ zoxide query -l } + + +# --- KEYMAPS +map global user l %{:enter-user-mode lsp<ret>} -docstring "LSP mode" +map global insert <tab> '<a-;>:try lsp-snippets-select-next-placeholders catch %{ execute-keys -with-hooks <lt>tab> }<ret>' -docstring 'Select next snippet placeholder' +map global object a '<a-semicolon>lsp-object<ret>' -docstring 'LSP any symbol' +map global object <a-a> '<a-semicolon>lsp-object<ret>' -docstring 'LSP any symbol' +map global object e '<a-semicolon>lsp-object Function Method<ret>' -docstring 'LSP function or method' +map global object k '<a-semicolon>lsp-object Class Interface Struct<ret>' -docstring 'LSP class interface or struct' +map global object d '<a-semicolon>lsp-diagnostic-object --include-warnings<ret>' -docstring 'LSP errors and warnings' +map global object D '<a-semicolon>lsp-diagnostic-object<ret>' -docstring 'LSP errors' +map global object h '<a-semicolon>lsp-diagnostic-object<ret>' -docstring 'LSP errors' +map global user k ':lsp-hover<ret>' -docstring 'LSP errors' +map global normal \; ":" +map global insert <a-k> "<a-;>:lsp-signature-help<ret>" + +# --- Hunks +declare-user-mode hunk + +map global hunk ] ':git next-hunk<ret>' -docstring 'Git hunk next' +map global hunk [ ':git prev-hunk<ret>' -docstring 'Git hunk prev' +map -docstring 'Goto hunk' global user h ': enter-user-mode hunk<ret>' + +# --- Surround + +declare-user-mode surround + +define-command declare-surrounding-pair -params 4 -docstring 'declare-surrounding-pair <description> <alias> <opening> <closing>: declare surrounding pair' %{ + map -docstring %arg{1} global surround %arg{2} "Z\i%arg{3}<esc>\a%arg{4}<esc>Hz" + map -docstring %arg{1} global surround %arg{3} "Z\i%arg{3}<esc>\a%arg{4}<esc>Hz" + map -docstring %arg{1} global surround %arg{4} "Z\i%arg{3}<esc>\a%arg{4}<esc>Hz" +} + +declare-surrounding-pair 'parenthesis block' b ( ) +declare-surrounding-pair 'brace block' B { } +declare-surrounding-pair 'bracket block' r [ ] +declare-surrounding-pair 'quotation' \' \' \' +declare-surrounding-pair 'double quotation' \" \" \" +declare-surrounding-pair 'angle block' a <lt> <gt> + +map -docstring 'enter surround mode' global user c ': enter-user-mode surround<ret>' +set-option -add global ui_options terminal_padding_char=. +set-option -add global ui_options terminal_assistant=off + +# --- Git +hook global WinCreate .* %{git show-diff} + +hook global BufWritePost .* %{git update-diff} + +declare-user-mode conflict-resolve +map -docstring 'enter conflict resolution' global user u ': enter-user-mode conflict-resolve<ret>' + +map global object m %{c^[<lt>=]{4\,}[^\n]*\n,^[<gt>=]{4\,}[^\n]*\n<ret>} -docstring 'conflict markers' +define-command conflict-use-1 %{ + evaluate-commands -draft %{ + execute-keys <a-h>h/^<lt>{4}<ret><a-x>d + execute-keys h/^={4}<ret>j + execute-keys -with-maps <a-a>m + execute-keys d + } +} -docstring "resolve a conflict by using the first version" +define-command conflict-use-2 %{ + evaluate-commands -draft %{ + execute-keys j + execute-keys -with-maps <a-a>m + execute-keys dh/^>{4}<ret><a-x>d + } +} -docstring "resolve a conflict by using the second version" +map global conflict-resolve a conflict-use-1 -docstring "resolve conflict using first version" +map global conflict-resolve b conflict-use-2 -docstring "resolve conflict using second version" + +# --- VISUAL + +colorscheme simple + +# Width of a tab +set-option global tabstop 2 + +# Indent with 4 spaces +set-option global indentwidth 2 + +# Use spaces instead of tabs +hook global WinCreate .* %{ expandtab } + +# Enable spelling for markdown +hook global WinCreate filetype=(markdown) %{ spell } + +# Softwrap long lines +add-highlighter global/ wrap -word -indent + +# Show git branch in statusline +declare-option -docstring "name of the git branch holding the current buffer" \ + str modeline_git_branch + +hook global WinCreate .* %{ + hook window NormalIdle .* %{ evaluate-commands %sh{ + branch=$(cd "$(dirname "${kak_buffile}")" && git rev-parse --abbrev-ref HEAD 2>/dev/null) + if [ -n "${branch}" ]; then + printf 'set window modeline_git_branch %%{%s}' "${branch}" + fi + } } +} + +hook global WinCreate .* %{ evaluate-commands %sh{ + is_work_tree=$(cd "$(dirname "${kak_buffile}")" && git rev-parse --is-inside-work-tree 2>/dev/null) + if [ "${is_work_tree}" = 'true' ]; then + printf 'set-option window modelinefmt %%{%s}' "%opt{modeline_git_branch} ${kak_opt_modelinefmt}" + fi +}} + +## Yanking writes to wayland +hook global RegisterModified '"' %{ nop %sh{ + case $(uname) in + Linux) + wl-copy -n "$kak_main_reg_dquote" > /dev/null 2>&1 & ;; + Darwin) + printf "%s" "$kak_main_reg_dquote" | pbcopy ;; + esac +}} + + +# --- CODING ASSISTANT +declare-user-mode assistant + +# Chatgpt +map global assistant -docstring "Replace selection with code assistant's answer" r '<a-!>tee /tmp/kak-tmp-code.txt; cat /tmp/kak-tmp-code.txt | chatgpt "You are a code generator.\nWriting comments is forbidden.\nWriting test code is forbidden.\nWriting English explanations is forbidden.\nMax 10 lines\nWrap new code in markdown code block\nComplete the $kak_bufname code\n" | filter-code-blocks<ret>' + +map global assistant -docstring "Ask chatgpt about the selection!" q '<a-|>(tee /tmp/chatgpt.txt; echo "\nWhat is this code in my $kak_bufname file?" >> /tmp/chatgpt.txt)<ret>:info -title "chatgpt" "%sh{cat /tmp/chatgpt.txt | xargs -I _ chatgpt -q _ --set-max-tokens 500}"<ret>' + + +# Ollama +map global assistant -docstring "Replace selection with code assistant's answer" o '<a-!>tee /tmp/kak-tmp-code.txt;echo "You are a code generator.\nWriting comments is forbidden.\nWriting test code is forbidden.\nWriting English explanations is forbidden.\nMax 10 lines\nContinue this $kak_bufname code:\n" > /tmp/kak-gpt-prompt.txt;cat /tmp/kak-tmp-code.txt >> /tmp/kak-gpt-prompt.txt;ollama-cli -p -s -f /tmp/kak-gpt-prompt.txt<ret>' + +map -docstring 'enter assistant mode' global user a ': enter-user-mode assistant<ret>' + + +hook global BufSetOption filetype=(ocaml) %{ + map buffer assistant -docstring "Add rapper definitions to selected code" u '<a-|>tee /tmp/ocaml-rapper.txt;ocaml-rapper-helper /tmp/ocaml-rapper.txt<ret>' +} + + +# --- SNIPPETS + +map global insert <a-f> "<esc>: phantom-selection-iterate-next<ret>i" +map global insert <a-F> "<esc>: phantom-selection-iterate-prev<ret>i" +map global user f ":phantom-selection-select-all; phantom-selection-clear<ret>," + +hook global BufSetOption filetype=(ocaml) %{ + set buffer snippets %opt{snippets} # keep global snippets (if any) + set -add buffer snippets 'Import Html libs' 'imp-h' %{ snippets-insert %{let open Dream_html in +let open HTML in + } + } + set -add buffer snippets '[letform-] Create Web Form' 'letform-' \ + %{ phantom-selection-clear ; snippets-insert %{let form ~csrf req = + match%lwt Dream.form ~csrf req with + | `Ok [ ("${}", ${}); ] -> + Lwt_result.return (${}) + | e -> Lwt_result.fail (`Form e) + ${} +}; phantom-selection-add-selection ; phantom-selection-iterate-next } + + set -add buffer snippets '[form-n] Create user form (base)' 'form-n' \ + %{ phantom-selection-clear ; snippets-insert %{null + [ h3 [] [txt "${}"] + ; form + [ id "${}"; action "/${}"; method_ `POST ] + [ csrf_tag req + ; br [] + ] + ] +}; phantom-selection-add-selection ; phantom-selection-iterate-next } + + set -add buffer snippets '[form-tf] Create user form (text field)' 'form-tf' \ + %{phantom-selection-clear ; snippets-insert %{; label [ for_ "${}" ] [ txt "${}" ] + ; input [ id "${}"; name "${}"; type_ "text" ] + ; br [] +}; phantom-selection-add-selection ; phantom-selection-iterate-next } + + set -add buffer snippets '[form-b] Create user form (submit)' 'form-b' \ + %{ snippets-insert %{; button [type_ "submit"] [ txt "${}" ] +}; } + + set -add buffer snippets '[let-e] Expect test' 'let-e' \ + %{ phantom-selection-clear ; snippets-insert %{let%expect_test "${}" = + Printf.printf ; + [%expect {| |}] |> Lwt.return + }; phantom-selection-add-selection ; phantom-selection-iterate-next } + + set -add buffer snippets '[let-c] controller' 'let-c' \ + %{ phantom-selection-clear ; snippets-insert %{let controller ?(csrf=true) = + User.Session.auth_middleware + @@ fun req -> + match%lwt logic ~csrf req with + | Ok ${} -> ${} + | Error e -> Components.Errors.handle log e + }; phantom-selection-add-selection ; phantom-selection-iterate-next } +} diff --git a/config/kak/ocaml-snippets.kak b/config/kak/ocaml-snippets.kak new file mode 100644 index 0000000..0d48bee --- /dev/null +++ b/config/kak/ocaml-snippets.kak @@ -0,0 +1,35 @@ +set buffer snippets %opt{snippets} # keep global snippets (if any) +set -add buffer snippets 'Import Html libs' 'html-imp' %{ snippets-insert %{let open Dream_html in +let open HTML in + } + } +set -add buffer snippets 'Create form' 'letform-' \ + %{ phantom-selection-clear ; snippets-insert %{let form ~csrf req = + match%lwt Dream.form ~csrf req with + | `Ok [ ("${}", ${}); ] -> + Lwt_result.return (${}) + | e -> Lwt_result.fail (`Form e) + ${} +}; phantom-selection-add-selection ; phantom-selection-iterate-next } + +set -add buffer snippets 'Create user form (base)' 'form-b' \ + %{ snippets-insert %{null + [ h2 [] [txt "${}"] + ; form + [ id "${}"; action "/${}"; method_ `POST ] + [ csrf_tag req + ; br [] + ] + ] +}; } + +set -add buffer snippets 'Create user form (text field)' 'form-tf' \ + %{ snippets-insert %{; label [ for_ "${}" ] [ txt "${}" ] + ; input [ id "${}"; name "${}"; type_ "text" ] + ; br [] +}; } + +set -add buffer snippets 'Create user form (submit)' 'form-s' \ + %{ snippets-insert %{; button [type_ "submit"] [ txt "${}" ] +}; } + diff --git a/config/kak/palette.kak b/config/kak/palette.kak new file mode 100644 index 0000000..66272de --- /dev/null +++ b/config/kak/palette.kak @@ -0,0 +1,102 @@ +define-command palette-status -docstring 'show main selection color in status bar' %{ + evaluate-commands %sh{ + awk_script='{ + if ((x=index($1,"#")) > 0) + $1 = substr($1, x+1) + if (length($1) == 8) + $1 = substr($1, 1, 6) + if (length($1) == 4) + $1 = substr($1, 1, 3) + if (length($1) == 3) { + r = substr($1, 1, 1) + g = substr($1, 2, 1) + b = substr($1, 3, 1) + $1 = r r g g b b + } + print "try %{ evaluate-commands -client " client " echo -markup {rgb:" $1 "} ██████ }" + }' + printf %s\\n "$kak_selection" | awk -v client="$kak_client" "$awk_script" | kak -p "$kak_session" + } +} + +# use this palette command in a colorscheme kak file or the output of 'debug faces' +# it will add a color preview in a new column on the left for each line with a face declaration + +define-command palette-gutter -docstring 'show faces in gutter' %{ + set-face global Palette default + # palette_flags is undefined for now, but will be populated by the set command generated by awk + # it must follow this format: 1486635122:1|Foo:3|{red,yellow+b}Bar + # which is a timestamp, then a list of line number|text tuples separated by colons + declare-option line-specs palette_flags + # from previous call + remove-highlighter window/palette + add-highlighter window/palette flag-lines Palette palette_flags + + # populate $kak_selection to feed the whole buffer content to awk + execute-keys '%' + + # awk quick survival guide: + # - NR is line number + # - substr starts at 1 + # - the v flag is used to assign argument + # - gsub() returns 0 or 1, but mutates 3rd arg + evaluate-commands %sh{ + case "$kak_opt_filetype" in + + 'kak') + awk_script=' + /face / { + flags = flags NR "|{" $3 "}" $3 " " + } + ' + ;; + + 'css'|'less'|'sass'|'scss'|'stylus') + awk_script=' + function toKakColor(hex) { + if (length(hex) == 7) { + return "rgb:" substr(hex, 2, 6) + } else if (length(hex) == 4) { + r = substr(hex, 2, 1) + g = substr(hex, 3, 1) + b = substr(hex, 4, 1) + return "rgb:" r r g g b b + } else { + return "rgb:000000" + } + } + /color: / { + flags = flags NR "|{" toKakColor($2) "," toKakColor($2) "}██████ " + } + ' + ;; + + *) + # parse the output of 'debug faces' command + if [ "$kak_bufname" = '*debug*' ]; then + awk_script=' + / \* / { + gsub(":", " ", $2) + flags = flags NR "|{" $3 "}" $2 + } + ' + else + echo 'echo -markup "{Error}filetype not supported by palette"' + fi + ;; + + esac + + if [ -n "$awk_script" ]; then + awk_script=$awk_script' + END { + print "set-option \"buffer=" file "\" palette_flags " stamp " " substr(flags, 1, length(flags)-1) + } + ' + printf %s\\n "$kak_selection" | awk -v file="$kak_buffile" -v stamp="$kak_timestamp" "$awk_script" | kak -p "$kak_session" + fi + } + + # back to normal after '%' + execute-keys ';' +} diff --git a/config/kak/phantom-selection.kak b/config/kak/phantom-selection.kak new file mode 100644 index 0000000..e64c468 --- /dev/null +++ b/config/kak/phantom-selection.kak @@ -0,0 +1,84 @@ +provide-module phantom-selection %{ + +set-face global PhantomSelection black,green+F + +declare-option -hidden str-list phantom_selections +declare-option -hidden range-specs phantom_selections_ranges + +add-highlighter global/ ranges phantom_selections_ranges + +define-command -hidden phantom-selection-store-and-highlight %{ + set window phantom_selections %reg{^} + set window phantom_selections_ranges %val{timestamp} + eval -no-hooks -draft -itersel %{ + set -add window phantom_selections_ranges "%val{selection_desc}|PhantomSelection" + } +} + +define-command -hidden phantom-selection-iterate-impl -params 1 %{ + eval -save-regs ^ %{ + reg ^ %opt{phantom_selections} + try %{ + exec z + exec %arg{1} + # keep the main selection and put all the other in the mark + # a recent change to Kakoune swaps <space> with "," (and + # <a-space> with <a-,>). Try both to make sure we clear selections + # both with and without this breaking change. Pad them with <esc> + # to cancel out the key with the other behavior. + exec -save-regs '' 'Z' + phantom-selection-store-and-highlight + exec '<space><esc><,><esc>' + } catch %{ + fail 'No phantom selections' + } + } +} + +define-command phantom-selection-iterate-next -docstring " +Turn secondary selections into phantoms and select the next phantom +" %{ + phantom-selection-iterate-impl ')' +} + +define-command phantom-selection-iterate-prev -docstring " +Turn secondary selections into phantoms and select the previous phantom +" %{ + phantom-selection-iterate-impl '(' +} + +define-command phantom-selection-clear -docstring " +Remove all phantom selections +" %{ + unset window phantom_selections + unset window phantom_selections_ranges +} + +define-command phantom-selection-select-all -docstring " +Select all phantom selections +" %{ + eval -save-regs ^ %{ + reg ^ %opt{phantom_selections} + try %{ + exec z + echo "" + } catch %{ + fail 'No phantom selections' + } + } +} + +define-command phantom-selection-add-selection -docstring " +Create phantoms out of the current selections +" %{ + eval -draft -save-regs ^ %{ + reg ^ %opt{phantom_selections} + try %{ exec "<a-z>a" } + exec -save-regs '' "Z" + phantom-selection-store-and-highlight + } +} + +} + +require-module phantom-selection diff --git a/config/kak/smarttab.kak b/config/kak/smarttab.kak new file mode 100644 index 0000000..53b53b6 --- /dev/null +++ b/config/kak/smarttab.kak @@ -0,0 +1,119 @@ +# ╭─────────────╥──────────────────────╮ +# │ Author: ║ File: │ +# │ Andrey Orst ║ smarttab.kak │ +# ╞═════════════╩══════════════════════╡ +# │ Extends tab handling by adding │ +# │ three different commands for │ +# │ each mode. │ +# ╞════════════════════════════════════╡ +# │ Rest of .dotfiles: │ +# │ GitHub.com/andreyorst/smarttab.kak │ +# ╰────────────────────────────────────╯ + +define-command -docstring "noexpandtab: use tab character to indent and align" \ +noexpandtab %{ require-module smarttab; noexpandtab-impl } + +define-command -docstring "expandtab: use space character to indent and align" \ +expandtab %{ require-module smarttab; expandtab-impl } + +define-command -docstring "smarttab: use tab character for indentation and space character for alignment" \ +smarttab %{ require-module smarttab; smarttab-impl } + +# note: there is no space-indent, tab-align setting; this is assumed to be equivalent to noexpandtab +define-command -docstring "autoconfigtab: use tab or space character to indent and align based upon existing settings (e.g. via editorconfig)" \ +autoconfigtab %{ require-module smarttab; autoconfigtab-impl } + +provide-module smarttab %§ + +# Options +# ‾‾‾‾‾‾‾ + +declare-option -docstring "amount of spaces that should be treated as single tab character when deleting spaces" \ +int softtabstop 0 + +declare-option -docstring "displays current tab handling mode" \ +str smarttab_mode '' + +declare-option -docstring 'what text to display in ''%opt{smarttab_mode}'' when expandtab mode is on' \ +str smarttab_expandtab_mode_name 'expandtab' + +declare-option -docstring 'what text to display in ''%opt{smarttab_mode}'' when expandtab mode is on' \ +str smarttab_noexpandtab_mode_name 'noexpandtab' + +declare-option -docstring 'what text to display in ''%opt{smarttab_mode}'' when expandtab mode is on' \ +str smarttab_smarttab_mode_name 'smarttab' + +declare-option -hidden int oldindentwidth %opt{indentwidth} + +# Commands +# ‾‾‾‾‾‾‾‾ + +define-command -hidden noexpandtab-impl %{ + set-option buffer smarttab_mode %opt{smarttab_noexpandtab_mode_name} + remove-hooks buffer smarttab-mode + smarttab-set + set-option buffer indentwidth 0 + set-option buffer aligntab true + hook -group smarttab-mode buffer InsertDelete ' ' %{ try %sh{ + if [ $kak_opt_softtabstop -gt 1 ]; then + printf "%s\n" 'execute-keys -draft "<a-h><a-k>^\h+.\z<ret>I<space><esc><lt>"' + fi + } catch %{ try %{ + execute-keys -itersel -draft "h%opt{softtabstop}<s-h>2<s-l>s\h+\z<ret>d" + }}} +} + +define-command -hidden expandtab-impl %{ + set-option buffer smarttab_mode %opt{smarttab_expandtab_mode_name} + remove-hooks buffer smarttab-mode + smarttab-set + set-option buffer aligntab false + hook -group smarttab-mode buffer InsertChar '\t' %{ execute-keys -draft "h%opt{indentwidth}@" } + hook -group smarttab-mode buffer InsertDelete ' ' %{ try %sh{ + if [ $kak_opt_softtabstop -gt 1 ]; then + printf "%s\n" 'execute-keys -draft -itersel "<a-h><a-k>^\h+.\z<ret>I<space><esc><lt>"' + fi + } catch %{ try %{ + execute-keys -itersel -draft "h%opt{softtabstop}<s-h>2<s-l>s\h+\z<ret>d" + }}} +} + +define-command -hidden smarttab-impl %{ + set-option buffer smarttab_mode %opt{smarttab_smarttab_mode_name} + remove-hooks buffer smarttab-mode + smarttab-set + set-option buffer indentwidth 0 + set-option buffer aligntab false + hook -group smarttab-mode buffer InsertChar '\t' %{ try %{ + execute-keys -draft "<a-h><a-k>^\h*.\z<ret>" + } catch %{ + execute-keys -draft "h@" + }} + hook -group smarttab-mode buffer InsertDelete ' ' %{ try %sh{ + if [ $kak_opt_softtabstop -gt 1 ]; then + printf "%s\n" 'execute-keys -draft "<a-h><a-k>^\h+.\z<ret>I<space><esc><lt>"' + fi + } catch %{ try %{ + execute-keys -itersel -draft "h%opt{softtabstop}<s-h>2<s-l>s\h+\z<ret>d" + }}} +} + +define-command -hidden autoconfigtab-impl %{ evaluate-commands %sh{ + if [ $kak_opt_aligntab = true ]; then + echo "noexpandtab" + elif [ $kak_opt_indentwidth -eq 0 ]; then + echo "smarttab" + else + echo "expandtab" + fi +}} + +define-command -hidden smarttab-set %{ evaluate-commands %sh{ + if [ $kak_opt_indentwidth -eq 0 ]; then + printf "%s\n" "set-option buffer indentwidth $kak_opt_oldindentwidth" + else + printf "%s\n" "set-option buffer oldindentwidth $kak_opt_indentwidth" + fi +}} + +§ diff --git a/config/kak/snippets.kak b/config/kak/snippets.kak new file mode 100644 index 0000000..6c5020c --- /dev/null +++ b/config/kak/snippets.kak @@ -0,0 +1,295 @@ +provide-module snippets %§ + +declare-option -hidden regex snippets_triggers_regex "\A\z" # doing <a-k>\A\z<ret> will always fail + +hook global WinSetOption 'snippets=$' %{ + set window snippets_triggers_regex "\A\z" +} +hook global WinSetOption 'snippets=.+$' %{ + set window snippets_triggers_regex %sh{ + eval set -- "$kak_quoted_opt_snippets" + if [ $(($#%3)) -ne 0 ]; then printf '\A\z'; exit; fi + res="" + while [ $# -ne 0 ]; do + if [ -n "$2" ]; then + if [ -z "$res" ]; then + res="$2" + else + res="$res|$2" + fi + fi + shift 3 + done + if [ -z "$res" ]; then + printf '\A\z' + else + printf '(?:%s)' "$res" + fi + } +} + +define-command snippets-expand-trigger -params ..1 %{ + eval -save-regs '/snc' %{ + # -draft so that we don't modify anything in case of failure + eval -draft %{ + # ideally early out in here to avoid going to the (expensive) shell scope + eval %arg{1} + # this shell scope generates a block that looks like this + # except with single quotes instead of %{..} + # + # try %{ + # reg / "\Atrig1\z" + # exec -draft <a-k><ret>d + # reg c "snipcommand1" + # } catch %{ + # reg / "\Atrig2\z" + # exec -draft <a-k><ret>d + # reg c "snipcommand2" + # } catch %{ + # .. + # } + + eval %sh{ + quadrupleupsinglequotes() + { + rest="$1" + while :; do + beforequote="${rest%%"'"*}" + if [ "$rest" = "$beforequote" ]; then + printf %s "$rest" + break + fi + printf "%s''''" "$beforequote" + rest="${rest#*"'"}" + done + } + + eval set -- "$kak_quoted_opt_snippets" + if [ $(($#%3)) -ne 0 ]; then exit; fi + first=0 + while [ $# -ne 0 ]; do + if [ -z "$2" ]; then + shift 3 + continue + fi + if [ $first -eq 0 ]; then + printf "try '\n" + first=1 + else + printf "' catch '\n" + fi + # put the trigger into %reg{/} as \Atrig\z + printf "reg / ''\\\A" + # we're at two levels of nested single quotes (one for try ".." catch "..", one for reg "..") + # in the arbitrary user input (snippet trigger and snippet name) + quadrupleupsinglequotes "$2" + printf "\\\z''\n" + printf "exec -draft <a-k><ret>d\n" + printf "reg n ''" + quadrupleupsinglequotes "$1" + printf "''\n" + printf "reg c ''" + quadrupleupsinglequotes "$3" + printf "''\n" + shift 3 + done + printf "'" + } + # preserve the selections generated by the snippet, since -draft will discard them + eval %reg{c} + reg s %val{selections_desc} + } + eval select %reg{s} + echo "Snippet '%reg{n}' expanded" + } +} + +hook global WinSetOption 'snippets_auto_expand=false$' %{ + rmhooks window snippets-auto-expand +} +hook global WinSetOption 'snippets_auto_expand=true$' %{ + rmhooks window snippets-auto-expand + hook -group snippets-auto-expand window InsertChar .* %{ + try %{ + snippets-expand-trigger %{ + reg / "(%opt{snippets_triggers_regex})|." + exec -save-regs '' ';<a-/><ret>' + eval -draft -verbatim menu "%reg{1}" '' + } + } + } +} + +declare-option str-list snippets +# this one must be declared after the hook, otherwise it might not be enabled right away +declare-option bool snippets_auto_expand true + +define-command snippets-impl -hidden -params 1.. %{ + eval %sh{ + use=$1 + shift 1 + index=4 + while [ $# -ne 0 ]; do + if [ "$1" = "$use" ]; then + printf "eval %%arg{%s}" "$index" + exit + fi + index=$((index + 3)) + shift 3 + done + printf "fail 'Snippet not found'" + } +} + +define-command snippets -params 1 -shell-script-candidates %{ + eval set -- "$kak_quoted_opt_snippets" + if [ $(($#%3)) -ne 0 ]; then exit; fi + while [ $# -ne 0 ]; do + printf '%s\n' "$1" + shift 3 + done +} %{ + snippets-impl %arg{1} %opt{snippets} +} + +define-command snippets-menu-impl -hidden -params .. %{ + eval %sh{ + if [ $(($#%3)) -ne 0 ]; then exit; fi + printf 'menu' + i=1 + while [ $# -ne 0 ]; do + printf " %%arg{%s}" $i + printf " 'snippets %%arg{%s}'" $i + i=$((i+3)) + shift 3 + done + } +} + +define-command snippets-menu %{ + snippets-menu-impl %opt{snippets} +} + +define-command snippets-info %{ + info -title Snippets %sh{ + eval set -- "$kak_quoted_opt_snippets" + if [ $(($#%3)) -ne 0 ]; then printf "Invalid 'snippets' value"; exit; fi + if [ $# -eq 0 ]; then printf 'No snippets defined'; exit; fi + maxtriglen=0 + while [ $# -ne 0 ]; do + if [ ${#2} -gt $maxtriglen ]; then + maxtriglen=${#2} + fi + shift 3 + done + eval set -- "$kak_quoted_opt_snippets" + while [ $# -ne 0 ]; do + if [ $maxtriglen -eq 0 ]; then + printf '%s\n' "$1" + else + if [ "$2" = "" ]; then + printf "%${maxtriglen}s %s\n" "" "$1" + else + printf "%${maxtriglen}s ➡ %s\n" "$2" "$1" + fi + fi + shift 3 + done + } +} + +define-command snippets-insert -hidden -params 1 %< + eval -save-regs 's' %< + eval -draft -save-regs '"' %< + # paste the snippet + reg dquote %arg{1} + exec P + + # replace leading tabs with the appropriate indent + try %< + reg dquote %sh< + if [ $kak_opt_indentwidth -eq 0 ]; then + printf '\t' + else + printf "%${kak_opt_indentwidth}s" + fi + > + exec -draft '<a-s>s\A\t+<ret>s.<ret>R' + > + + # align everything with the current line + eval -draft -itersel -save-regs '"' %< + try %< + exec -draft -save-regs '/' '<a-s>),xs^\s+<ret>y' + exec -draft '<a-s>)<a-,>P' + > + > + + reg s %val{selections_desc} + # process placeholders + try %< + # select all placeholders ${..} and escaped-$ (== $$) + exec 's\$\$|\$\{(\}\}|[^}])*\}<ret>' + # nonsense test text to check the regex + # qwldqwld {qldwlqwld} qlwdl$qwld {qwdlqwld}}qwdlqwldl} + # lqlwdl$qwldlqwdl$qwdlqwld {qwd$$lqwld} $qwdlqwld$ + # ${asd.as.d.} lqwdlqwld $$${as.dqdqw} + + # remove one $ from all $$, and leading $ from ${..} + exec -draft '<a-:><a-;>;d' + # unselect the $ + exec '<a-K>\A\$\z<ret>' + # we're left with only {..} placeholders, process them... + eval reg dquote %sh< + eval set -- "$kak_quoted_selections" + for sel do + # remove trailing } + sel="${sel%\}}" + # and leading { + sel="${sel#{}" + # de-double }} + tmp="$sel" + sel="" + while true; do + case "$tmp" in + *}}*) + sel="${sel}${tmp%%\}\}*}}" + tmp=${tmp#*\}\}} + ;; + *) + sel="${sel}${tmp}" + break + ;; + esac + done + # and quote the result in '..', with escaping (== doubling of ') + tmp="$sel" + sel="" + while true; do + case "$tmp" in + *\'*) + sel="${sel}${tmp%%\'*}''" + tmp=${tmp#*\'} + ;; + *) + sel="${sel}${tmp}" + break + ;; + esac + done + # all done, print it + # nothing like some good old posix-shell text processing + printf "'%s' " "$sel" + done + > + exec R + reg s %val{selections_desc} + > + > + try %{ select %reg{s} } + > +> + +§ + +require-module snippets |