summaryrefslogtreecommitdiff
path: root/config/kak
diff options
context:
space:
mode:
authorMarc Coquand <marc@mccd.space>2024-09-05 12:27:17 -0500
committerMarc Coquand <marc@mccd.space>2024-09-05 12:27:17 -0500
commite233e7f028366ce8f5d58fe1cc8a88210664ddb3 (patch)
tree2c1cec3a19866bc39706de8a38035e15813018ed /config/kak
parent3783cab095a9167256afcbfe987d11f35a7003b1 (diff)
downloadbsd-e233e7f028366ce8f5d58fe1cc8a88210664ddb3.tar.gz
bsd-e233e7f028366ce8f5d58fe1cc8a88210664ddb3.tar.bz2
bsd-e233e7f028366ce8f5d58fe1cc8a88210664ddb3.zip
add kak
Diffstat (limited to '')
-rw-r--r--config/kak-lsp/kak-lsp.corebin0 -> 11702272 bytes
-rw-r--r--config/kak-lsp/kak-lsp.toml498
-rw-r--r--config/kak/auto-pairs.kak185
-rw-r--r--config/kak/colors/simple-dark.kak57
-rw-r--r--config/kak/colors/simple.kak68
-rw-r--r--config/kak/go-snippets.kak7
-rw-r--r--config/kak/kak-lsp.corebin0 -> 11702272 bytes
-rw-r--r--config/kak/kakrc281
-rw-r--r--config/kak/ocaml-snippets.kak35
-rw-r--r--config/kak/palette.kak102
-rw-r--r--config/kak/phantom-selection.kak84
-rw-r--r--config/kak/smarttab.kak119
-rw-r--r--config/kak/snippets.kak295
13 files changed, 1731 insertions, 0 deletions
diff --git a/config/kak-lsp/kak-lsp.core b/config/kak-lsp/kak-lsp.core
new file mode 100644
index 0000000..2e51a13
--- /dev/null
+++ b/config/kak-lsp/kak-lsp.core
Binary files differ
diff --git a/config/kak-lsp/kak-lsp.toml b/config/kak-lsp/kak-lsp.toml
new file mode 100644
index 0000000..7994b0c
--- /dev/null
+++ b/config/kak-lsp/kak-lsp.toml
@@ -0,0 +1,498 @@
+file_watch_support = false
+snippet_support = false
+verbosity = 2
+
+[server]
+# exit session if no requests were received during given period in seconds
+# set to 0 to disable
+timeout = 1800 # seconds = 30 minutes
+
+# This section overrides language IDs.
+# By default, kakoune-lsp uses filetypes for the IDs.
+# See https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocumentItem
+[language_ids]
+c = "c_cpp"
+cpp = "c_cpp"
+javascript = "javascriptreact"
+typescript = "typescriptreact"
+protobuf = "proto"
+sh = "shellscript"
+
+[language_server.bash-language-server]
+filetypes = ["sh"]
+roots = [".git", ".hg"]
+command = "bash-language-server"
+args = ["start"]
+
+[language_server.clangd]
+filetypes = ["c", "cpp"]
+roots = ["compile_commands.json", ".clangd", ".git", ".hg"]
+command = "clangd"
+
+[language_server.clojure-lsp]
+filetypes = ["clojure"]
+roots = ["project.clj", ".git", ".hg"]
+command = "clojure-lsp"
+settings_section = "_"
+[language_server.clojure-lsp.settings._]
+# See https://clojure-lsp.io/settings/#all-settings
+# source-paths-ignore-regex = ["resources.*", "target.*"]
+
+[language_server.cmake-language-server]
+filetypes = ["cmake"]
+roots = ["CMakeLists.txt", ".git", ".hg"]
+command = "cmake-language-server"
+
+[language_server.crystalline]
+filetypes = ["crystal"]
+roots = ["shard.yml"]
+command = "crystalline"
+
+[language_server.css-language-server]
+filetypes = ["css"]
+roots = ["package.json", ".git", ".hg"]
+command = "vscode-css-language-server"
+args = ["--stdio"]
+
+# [language_server.deno-lsp]
+# filetypes = ["javascript", "typescript"]
+# roots = ["package.json", "tsconfig.json", ".git", ".hg"]
+# command = "deno"
+# args = ["lsp"]
+# settings_section = "deno"
+# [language_server.deno-lsp.settings.deno]
+# enable = true
+# lint = true
+
+[language_server.less-language-server]
+filetypes = ["less"]
+roots = ["package.json", ".git", ".hg"]
+command = "vscode-css-language-server"
+args = ["--stdio"]
+
+
+# See https://scalameta.org/metals/docs/integrations/new-editor
+[language_server.metals]
+filetypes = ["scala"]
+roots = ["build.sbt", ".scala-build"]
+command = "metals"
+args = ["-Dmetals.extensions=false"]
+settings_section = "metals"
+[language_server.metals.settings.metals]
+icons = "unicode"
+isHttpEnabled = true
+statusBarProvider = "show-message"
+compilerOptions = { overrideDefFormat = "unicode" }
+inlayHints.hintsInPatternMatch.enable = true
+inlayHints.implicitArguments.enable = true
+inlayHints.implicitConversions.enable = true
+inlayHints.inferredTypes.enable = true
+inlayHints.typeParameters.enable = true
+
+[language_server.nil]
+filetypes = ["nix"]
+command = "nil"
+roots = ["flake.nix", "shell.nix", ".git", ".hg"]
+
+[language_server.scss-language-server]
+filetypes = ["scss"]
+roots = ["package.json", ".git", ".hg"]
+command = "vscode-css-language-server"
+args = ["--stdio"]
+
+[language_server.dls]
+filetypes = ["d", "di"]
+roots = [".git", "dub.sdl", "dub.json"]
+command = "dls"
+
+[language_server.dart-lsp]
+# start shell to find path to dart analysis server source
+filetypes = ["dart"]
+roots = ["pubspec.yaml", ".git", ".hg"]
+command = "sh"
+args = ["-c", "dart $(dirname $(command -v dart))/snapshots/analysis_server.dart.snapshot --lsp"]
+
+[language_server.jdtls]
+filetypes = ["java"]
+roots = ["mvnw", "gradlew", ".git", ".hg"]
+command = "jdtls"
+[language_server.jdtls.settings]
+# See https://github.dev/eclipse/eclipse.jdt.ls
+# "java.format.insertSpaces" = true
+
+[language_server.elixir-ls]
+filetypes = ["elixir"]
+roots = ["mix.exs"]
+command = "elixir-ls"
+settings_section = "elixirLS"
+[language_server.elixir-ls.settings.elixirLS]
+# See https://github.com/elixir-lsp/elixir-ls/blob/master/apps/language_server/lib/language_server/server.ex
+# dialyzerEnable = true
+
+[language_server.elm-language-server]
+filetypes = ["elm"]
+roots = ["elm.json"]
+command = "elm-language-server"
+args = ["--stdio"]
+settings_section = "elmLS"
+[language_server.elm-language-server.settings.elmLS]
+# See https://github.com/elm-tooling/elm-language-server#server-settings
+runtime = "node"
+elmPath = "elm"
+elmFormatPath = "elm-format"
+elmTestPath = "elm-test"
+
+[language_server.elvish]
+filetypes = ["elvish"]
+roots = [".git", ".hg"]
+command = "elvish"
+args = ["-lsp"]
+
+[language_server.erlang-ls]
+filetypes = ["erlang"]
+# See https://github.com/erlang-ls/erlang_ls.git for more information and
+# how to configure. This default config should work in most cases though.
+roots = ["rebar.config", "erlang.mk", ".git", ".hg"]
+command = "erlang_ls"
+
+[language_server.gopls]
+filetypes = ["go"]
+roots = ["Gopkg.toml", "go.mod", ".git", ".hg"]
+command = "gopls"
+[language_server.gopls.settings.gopls]
+# See https://github.com/golang/tools/blob/master/gopls/doc/settings.md
+# "build.buildFlags" = []
+hints.assignVariableTypes = true
+hints.compositeLiteralFields = true
+hints.compositeLiteralTypes = true
+hints.constantValues = true
+hints.functionTypeParameters = true
+hints.parameterNames = true
+hints.rangeVariableTypes = true
+"ui.completion.usePlaceholders" = true
+
+[language_server.haskell-language-server]
+filetypes = ["haskell"]
+roots = ["hie.yaml", "cabal.project", "Setup.hs", "stack.yaml", "*.cabal"]
+command = "haskell-language-server-wrapper"
+args = ["--lsp"]
+settings_section = "_"
+[language_server.haskell-language-server.settings._]
+# See https://haskell-language-server.readthedocs.io/en/latest/configuration.html
+# haskell.formattingProvider = "ormolu"
+
+[language_server.html-language-server]
+filetypes = ["html"]
+roots = ["package.json"]
+command = "vscode-html-language-server"
+args = ["--stdio"]
+settings_section = "_"
+[language_server.html-language-server.settings._]
+# quotePreference = "single"
+# javascript.format.semicolons = "insert"
+
+[language_server.intelephense]
+filetypes = ["php"]
+roots = [".htaccess", "composer.json"]
+command = "intelephense"
+args = ["--stdio"]
+settings_section = "intelephense"
+[language_server.intelephense.settings.intelephense]
+storagePath = "/tmp/intelephense"
+
+[language_server.json-language-server]
+filetypes = ["json"]
+roots = ["package.json"]
+command = "vscode-json-language-server"
+args = ["--stdio"]
+
+# Requires Julia package "LanguageServer"
+# Run: `julia --project=@kak-lsp -e 'import Pkg; Pkg.add("LanguageServer")'` to install it
+# Configuration adapted from https://github.com/neovim/nvim-lspconfig/blob/bcebfac7429cd8234960197dca8de1767f3ef5d3/lua/lspconfig/julials.lua
+[language_server.julia-language-server]
+filetypes = ["julia"]
+roots = ["Project.toml", ".git", ".hg"]
+command = "julia"
+args = [
+ "--startup-file=no",
+ "--history-file=no",
+ "-e",
+ """
+ ls_install_path = joinpath(get(DEPOT_PATH, 1, joinpath(homedir(), ".julia")), "environments", "kak-lsp");
+ pushfirst!(LOAD_PATH, ls_install_path);
+ using LanguageServer;
+ popfirst!(LOAD_PATH);
+ depot_path = get(ENV, "JULIA_DEPOT_PATH", "");
+ server = LanguageServer.LanguageServerInstance(stdin, stdout, "", depot_path);
+ server.runlinter = true;
+ run(server);
+ """,
+]
+[language_server.julia-language-server.settings]
+# See https://github.com/julia-vscode/LanguageServer.jl/blob/master/src/requests/workspace.jl
+# Format options. See https://github.com/julia-vscode/DocumentFormat.jl/blob/master/src/DocumentFormat.jl
+# "julia.format.indent" = 4
+# Lint options. See https://github.com/julia-vscode/StaticLint.jl/blob/master/src/linting/checks.jl
+# "julia.lint.call" = true
+# Other options, see https://github.com/julia-vscode/LanguageServer.jl/blob/master/src/requests/workspace.jl
+# "julia.lint.run" = "true"
+
+[language_server.lua-language-server]
+filetypes = ["lua"]
+roots = [".git", ".hg"]
+command = "lua-language-server"
+settings_section = "Lua"
+[language_server.lua-language-server.settings.Lua]
+# See https://github.com/sumneko/vscode-lua/blob/master/setting/schema.json
+# diagnostics.enable = true
+
+[language_server.markdown]
+filetypes = ["markdown"]
+roots = [".marksman.toml"]
+command = "marksman"
+args = ["server"]
+
+# [language_server.zk]
+# filetypes = ["markdown"]
+# roots = [".zk"]
+# command = "zk"
+# args = ["lsp"]
+
+[language_server.nimlsp]
+filetypes = ["nim"]
+roots = ["*.nimble", ".git", ".hg"]
+command = "nimlsp"
+
+[language_server.ocamllsp]
+filetypes = ["ocaml"]
+# Often useful to simply do a `touch dune-workspace` in your project root folder if you have problems with root detection
+roots = ["dune-workspace", "dune-project", "Makefile", "opam", "*.opam", "esy.json", ".git", ".hg", "dune"]
+command = "ocamllsp"
+settings_section = "_"
+[language_server.ocamllsp.settings._]
+# codelens.enable = false
+
+[language_server.pls]
+filetypes = ["protobuf"]
+roots = [".git", ".hg"]
+command = "pls" # https://github.com/lasorda/protobuf-language-server
+
+[language_server.purescript-language-server]
+filetypes = ["purescript"]
+roots = ["spago.dhall", "spago.yaml", "package.json", ".git", ".hg"]
+command = "purescript-language-server"
+args = ["--stdio"]
+
+[language_server.pylsp]
+filetypes = ["python"]
+roots = ["requirements.txt", "setup.py", ".git", ".hg"]
+command = "pylsp"
+settings_section = "_"
+[language_server.pylsp.settings._]
+# See https://github.com/python-lsp/python-lsp-server#configuration
+# pylsp.configurationSources = ["flake8"]
+pylsp.plugins.jedi_completion.include_params = true
+
+# [language_server.pyright]
+# filetypes = ["python"]
+# roots = ["requirements.txt", "setup.py", "pyrightconfig.json", ".git", ".hg"]
+# command = "pyright-langserver"
+# args = ["--stdio"]
+
+# [language_server.ruff]
+# filetypes = ["python"]
+# roots = ["requirements.txt", "setup.py", ".git", ".hg"]
+# command = "ruff-lsp"
+# settings_section = "_"
+# [language_server.ruff.settings._.globalSettings]
+# organizeImports = true
+# fixAll = true
+
+[language_server.r-language-server]
+filetypes = ["r"]
+roots = ["DESCRIPTION", ".git", ".hg"]
+command = "R"
+args = ["--slave", "-e", "languageserver::run()"]
+
+[language_server.racket-language-server]
+filetypes = ["racket"]
+roots = ["info.rkt"]
+command = "racket"
+args = ["-l", "racket-langserver"]
+
+[language_server.reason-ocamllsp]
+filetypes = ["reason"]
+roots = ["package.json", "Makefile", ".git", ".hg"]
+command = "ocamllsp"
+
+# [language_server.rls]
+# filetypes = ["rust"]
+# roots = ["Cargo.toml"]
+# command = "sh"
+# args = [
+# "-c",
+# """
+# if path=$(rustup which rls 2>/dev/null); then
+# exec "$path"
+# else
+# exec rls
+# fi
+# """,
+# ]
+# settings_section = "rust"
+# [language_server.rls.settings.rust]
+# # See https://github.com/rust-lang/rls#configuration
+# # features = []
+
+
+[language_server.rust-analyzer]
+filetypes = ["rust"]
+roots = ["Cargo.toml"]
+command = "sh"
+args = [
+ "-c",
+ """
+ if path=$(rustup which rust-analyzer 2>/dev/null); then
+ exec "$path"
+ else
+ exec rust-analyzer
+ fi
+ """,
+]
+
+[language_server.rust-analyzer.settings.rust-analyzer]
+# See https://rust-analyzer.github.io/manual.html#configuration
+# cargo.features = []
+check.command = "clippy"
+
+[language_server.solargraph]
+filetypes = ["ruby"]
+roots = ["Gemfile"]
+command = "solargraph"
+args = ["stdio"]
+settings_section = "_"
+[language_server.solargraph.settings._]
+# See https://github.com/castwide/solargraph/blob/master/lib/solargraph/language_server/host.rb
+# diagnostics = false
+
+[language_server.svelte-language-server]
+filetypes = ["svelte"]
+roots = ["package.json", "tsconfig.json", "jsconfig.json", ".git", ".hg"]
+command = "svelteserver"
+args = ["--stdio"]
+
+[language_server.taplo]
+filetypes = ["toml"]
+roots = [".git", ".hg"]
+command = "taplo"
+args = ["lsp", "stdio"]
+
+[language_server.terraform-ls]
+filetypes = ["terraform"]
+roots = ["*.tf"]
+command = "terraform-ls"
+args = ["serve"]
+[language_server.terraform-ls.settings.terraform-ls]
+# See https://github.com/hashicorp/terraform-ls/blob/main/docs/SETTINGS.md
+# rootModulePaths = []
+
+[language_server.texlab]
+filetypes = ["latex"]
+roots = [".git", ".hg"]
+command = "texlab"
+[language_server.texlab.settings.texlab]
+# See https://github.com/latex-lsp/texlab/wiki/Configuration
+#
+# Preview configuration for zathura with SyncTeX search.
+# For other PDF viewers see https://github.com/latex-lsp/texlab/wiki/Previewing
+forwardSearch.executable = "zathura"
+forwardSearch.args = [
+ "%p",
+ "--synctex-forward", # Support texlab-forward-search
+ "%l:1:%f",
+ "--synctex-editor-command", # Inverse search: use Control+Left-Mouse-Button to jump to source.
+ """
+ sh -c '
+ echo "
+ evaluate-commands -client %%opt{texlab_client} %%{
+ evaluate-commands -try-client %%opt{jumpclient} %%{
+ edit -- %%{input} %%{line}
+ }
+ }
+ " | kak -p $kak_session
+ '
+ """,
+]
+
+[language_server.typescript-language-server]
+filetypes = ["javascript", "typescript"]
+roots = ["package.json", "tsconfig.json", "jsconfig.json", ".git", ".hg"]
+command = "typescript-language-server"
+args = ["--stdio"]
+settings_section = "_"
+[language_server.typescript-language-server.settings._]
+# quotePreference = "double"
+# typescript.format.semicolons = "insert"
+
+# [language_server.biome]
+# filetypes = ["typescript", "javascript"]
+# roots = ["biome.json", "package.json", "tsconfig.json", "jsconfig.json", ".git", ".hg"]
+# command = "biome"
+# args = ["lsp-proxy"]
+
+# [language_server.eslint]
+# filetypes = ["javascript", "typescript"]
+# roots = [".eslintrc", ".eslintrc.json"]
+# command = "eslint-language-server"
+# args = ["--stdio"]
+# workaround_eslint = true
+# [language_server.eslint.settings]
+# codeActionsOnSave = { mode = "all", "source.fixAll.eslint" = true }
+# format = { enable = true }
+# quiet = false
+# rulesCustomizations = []
+# run = "onType"
+# validate = "on"
+# experimental = {}
+# problems = { shortenToSingleLine = false }
+# codeAction.disableRuleComment = { enable = true, location = "separateLine" }
+# codeAction.showDocumentation = { enable = false }
+
+[language_server.yaml-language-server]
+filetypes = ["yaml"]
+roots = [".git", ".hg"]
+command = "yaml-language-server"
+args = ["--stdio"]
+settings_section = "yaml"
+[language_server.yaml-language-server.settings.yaml]
+# See https://github.com/redhat-developer/yaml-language-server#language-server-settings
+# Defaults are at https://github.com/redhat-developer/yaml-language-server/blob/master/src/yamlSettings.ts
+# format.enable = true
+
+[language_server.zls]
+filetypes = ["zig"]
+roots = ["build.zig"]
+command = "zls"
+
+# Semantic tokens support
+# See https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_semanticTokens
+# for the default list of tokens and modifiers.
+# However, many language servers implement their own values.
+# Make sure to check the output of `lsp-capabilities` and each server's documentation and source code as well.
+# Examples:
+# - TypeScript: https://github.com/microsoft/vscode-languageserver-node/blob/main/client/src/common/semanticTokens.ts
+# - Rust Analyzer: https://github.com/rust-analyzer/rust-analyzer/blob/master/crates/ide/src/syntax_highlighting.rs
+[semantic_tokens]
+faces = [
+ {face="documentation", token="comment", modifiers=["documentation"]},
+ {face="comment", token="comment"},
+ {face="function", token="function"},
+ {face="keyword", token="keyword"},
+ {face="module", token="namespace"},
+ {face="operator", token="operator"},
+ {face="string", token="string"},
+ {face="type", token="type"},
+ {face="default+d", token="variable", modifiers=["readonly"]},
+ {face="default+d", token="variable", modifiers=["constant"]},
+ {face="variable", token="variable"},
+]
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..f5bc26f
--- /dev/null
+++ b/config/kak/colors/simple.kak
@@ -0,0 +1,68 @@
+
+face global value default,default
+face global type rgb:212121,default
+face global identifier rgb:212121,default
+face global string rgb:212121,default+i
+face global error default,default
+face global keyword rgb:212121,default
+face global builtin rgb:212121,default
+face global module rgb:212121,default
+face global operator rgb:212121,default
+face global attribute default,default
+face global comment rgb:0000FF,default
+face global meta rgb:212121,default
+face global function rgb:212121,default
+face global argument rgb:212121,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
+
+face global title default,default+b
+face global header default,default
+face global bold default,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 default,default
+face global bullet default,default
+face global list rgb:212121,default
+
+face global Default default,default
+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 rgb:212121,rgb:dedede
+face global Error rgb:ededed,red
+face global StatusLine default,default
+face global StatusLineMode default,default
+face global StatusLineInfo default,default
+face global StatusLineValue default,default
+face global StatusCursor default,rgb:878787
+face global Prompt default,default
+
+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/go-snippets.kak b/config/kak/go-snippets.kak
new file mode 100644
index 0000000..b58a2cd
--- /dev/null
+++ b/config/kak/go-snippets.kak
@@ -0,0 +1,7 @@
+set buffer snippets %opt{snippets} # keep global snippets (if any)
+set -add buffer snippets 'err != nil' 'err@' %{ snippets-insert %{if err != nil {
+
+}
+ }
+ }
+
diff --git a/config/kak/kak-lsp.core b/config/kak/kak-lsp.core
new file mode 100644
index 0000000..3b00849
--- /dev/null
+++ b/config/kak/kak-lsp.core
Binary files differ
diff --git a/config/kak/kakrc b/config/kak/kakrc
new file mode 100644
index 0000000..6966eec
--- /dev/null
+++ b/config/kak/kakrc
@@ -0,0 +1,281 @@
+# --- 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
+
+# --- Make
+hook global BufSetOption filetype=(go) %{
+ set-option buffer makecmd "go build"
+}
+
+# --- 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|org) %{
+ spell
+}
+hook global BufSetOption filetype=(javascript|typescript|html) %{
+ set-option buffer formatcmd "prettier --stdin-filepath=%val{buffile}"
+ hook buffer BufWritePre .* %{format}
+}
+
+hook global BufSetOption filetype=(go) %{
+ set-option global make_error_pattern "^([^:\n]+):(\d+):(?:(\d+):)?"
+}
+
+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|go) %{
+ hook buffer BufWritePre .* %{lsp-formatting-sync}
+}
+
+eval %sh{kak-lsp --kakoune -s $kak_session}
+lsp-enable
+
+# --- GREP
+set-option global grepcmd 'rg --column'
+
+# --- Tab complete
+
+hook global InsertCompletionShow .* %{
+ map window insert <tab> <c-n>
+ map window insert <s-tab> <c-p>
+}
+
+hook global InsertCompletionHide .* %{
+ unmap window insert <tab> <c-n>
+ unmap window insert <s-tab> <c-p>
+}
+
+# --- Line number
+add-highlighter global/ number-lines -separator ' '
+
+# --- 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 = ':lsp-formatting<ret>' -docstring "LSP Format"
+map global user w '|fmt <ret>' -docstring "Wrap to 80 columns"
+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>"
+map global user m ':make<ret>' -docstring "Run make"
+
+# --- Hunks
+declare-user-mode hunk
+
+
+map global hunk s ':git apply --cached<ret>:git update-diff<ret>' -docstring 'Stage hunk at cursor'
+map global hunk r ':git apply --reverse<ret>:git update-diff<ret>' -docstring 'Remove hunk at cursor'
+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 'stars' * * *
+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
+
+#set-option global autocomplete prompt
+#set-option global autoinfo onkey
+
+# --- 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
+
+hook global ModeChange (push|pop):insert:.* %{
+ set-face global PrimaryCursor rgb:FFFFFF,rgb:000000+F
+}
+
+hook global ModeChange (push|pop):.*:insert %{
+ set-face global PrimaryCursor default,default+Bc
+}
+
+# Width of a tab
+set-option global tabstop 8
+
+# Indent with 4 spaces
+set-option global indentwidth 0
+
+# Use spaces instead of tabs
+#hook global WinCreate .* %{ expandtab }
+
+# Enable spelling for markdown
+hook global WinCreate filetype=(markdown|.org) %{ spell }
+
+# Wrap for org and markdown
+hook global WinCreate filetype=(markdown|.org) %{ autowrap-enable }
+
+# 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
+}}
+
+hook global RegisterModified '"' %{ nop %sh{
+ printf %s "$kak_main_reg_dquote" | xsel --input --clipboard
+}}
+
+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=(go) %{
+
+ set buffer snippets %opt{snippets} # keep global snippets (if any)
+ set -add buffer snippets 'err != nil' 'err@' %{ snippets-insert %{if err != nil {
+ ${}
+}
+ }}
+
+}
+
+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 }
+}
+
+# TAGS
+
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