From e233e7f028366ce8f5d58fe1cc8a88210664ddb3 Mon Sep 17 00:00:00 2001 From: Marc Coquand Date: Thu, 5 Sep 2024 12:27:17 -0500 Subject: add kak --- config/kak-lsp/kak-lsp.core | Bin 0 -> 11702272 bytes config/kak-lsp/kak-lsp.toml | 498 ++++++++++++++++++++++++++++++++++++++ config/kak/auto-pairs.kak | 185 ++++++++++++++ config/kak/colors/simple-dark.kak | 57 +++++ config/kak/colors/simple.kak | 68 ++++++ config/kak/go-snippets.kak | 7 + config/kak/kak-lsp.core | Bin 0 -> 11702272 bytes config/kak/kakrc | 281 +++++++++++++++++++++ config/kak/ocaml-snippets.kak | 35 +++ config/kak/palette.kak | 102 ++++++++ config/kak/phantom-selection.kak | 84 +++++++ config/kak/smarttab.kak | 119 +++++++++ config/kak/snippets.kak | 295 ++++++++++++++++++++++ 13 files changed, 1731 insertions(+) create mode 100644 config/kak-lsp/kak-lsp.core create mode 100644 config/kak-lsp/kak-lsp.toml create mode 100644 config/kak/auto-pairs.kak create mode 100644 config/kak/colors/simple-dark.kak create mode 100644 config/kak/colors/simple.kak create mode 100644 config/kak/go-snippets.kak create mode 100644 config/kak/kak-lsp.core create mode 100644 config/kak/kakrc create mode 100644 config/kak/ocaml-snippets.kak create mode 100644 config/kak/palette.kak create mode 100644 config/kak/phantom-selection.kak create mode 100644 config/kak/smarttab.kak create mode 100644 config/kak/snippets.kak diff --git a/config/kak-lsp/kak-lsp.core b/config/kak-lsp/kak-lsp.core new file mode 100644 index 0000000..2e51a13 Binary files /dev/null and b/config/kak-lsp/kak-lsp.core 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 '(\w["''`]|""|''''|``).\z[^\\]?\Q%opt{opening_pair}\E\W\z' + +# 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 '..' + execute-keys 'H' + } catch %{ + execute-keys 'h' + } + + # Add insert mappings + map -docstring 'insert closing pair or move right in pair' window insert %arg{2} ":insert-closing-pair-or-move-right-in-pair %%🐈%arg{2}🐈" + map -docstring 'insert a new indented line in pair' window insert ':insert-new-line-in-pair' + map -docstring 'prompt a count for new indented lines in pair' window insert ':prompt-insert-new-line-in-pair' + + # Enter is only available on next key. + hook -group auto-pairs -once window InsertChar '.*' %{ + unmap window insert + unmap window insert + } + + # Clean insert mappings and remove hooks + hook -group auto-pairs -once window WinSetOption 'inserted_pairs=0' " + unmap window insert %%🐈%arg{2}🐈 + unmap window insert + unmap window insert + 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 ";\Q%arg{2}" + execute-keys '' + 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 ";\Q%arg{1}" + # Move right in pair + execute-keys '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 ';KKj' + 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 ';KKj' + execute-keys "xHyx%val{text}O""" + 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 Binary files /dev/null and b/config/kak/kak-lsp.core 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 + map window insert +} + +hook global InsertCompletionHide .* %{ + unmap window insert + unmap window insert +} + +# --- 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 ':prompt -menu -shell-script-candidates %{ fd -t f } fd: %{ edit %val{text} }' -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' -docstring "LSP Format" +map global user w '|fmt ' -docstring "Wrap to 80 columns" +map global user l %{:enter-user-mode lsp} -docstring "LSP mode" +map global insert ':try lsp-snippets-select-next-placeholders catch %{ execute-keys -with-hooks tab> }' -docstring 'Select next snippet placeholder' +map global object a 'lsp-object' -docstring 'LSP any symbol' +map global object 'lsp-object' -docstring 'LSP any symbol' +map global object e 'lsp-object Function Method' -docstring 'LSP function or method' +map global object k 'lsp-object Class Interface Struct' -docstring 'LSP class interface or struct' +map global object d 'lsp-diagnostic-object --include-warnings' -docstring 'LSP errors and warnings' +map global object D 'lsp-diagnostic-object' -docstring 'LSP errors' +map global object h 'lsp-diagnostic-object' -docstring 'LSP errors' +map global user k ':lsp-hover' -docstring 'LSP errors' +map global normal \' ":" +map global insert ":lsp-signature-help" +map global user m ':make' -docstring "Run make" + +# --- Hunks +declare-user-mode hunk + + +map global hunk s ':git apply --cached:git update-diff' -docstring 'Stage hunk at cursor' +map global hunk r ':git apply --reverse:git update-diff' -docstring 'Remove hunk at cursor' +map global hunk ] ':git next-hunk' -docstring 'Git hunk next' +map global hunk [ ':git prev-hunk' -docstring 'Git hunk prev' +map -docstring 'Goto hunk' global user h ': enter-user-mode hunk' + +# --- Surround + +declare-user-mode surround + +define-command declare-surrounding-pair -params 4 -docstring 'declare-surrounding-pair : declare surrounding pair' %{ + map -docstring %arg{1} global surround %arg{2} "Z\i%arg{3}\a%arg{4}Hz" + map -docstring %arg{1} global surround %arg{3} "Z\i%arg{3}\a%arg{4}Hz" + map -docstring %arg{1} global surround %arg{4} "Z\i%arg{3}\a%arg{4}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 + +map -docstring 'enter surround mode' global user c ': enter-user-mode surround' +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' + +map global object m %{c^[=]{4\,}[^\n]*\n,^[=]{4\,}[^\n]*\n} -docstring 'conflict markers' +define-command conflict-use-1 %{ + evaluate-commands -draft %{ + execute-keys h/^{4}d + execute-keys h/^={4}j + execute-keys -with-maps 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 m + execute-keys dh/^>{4}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 'tee /tmp/ocaml-rapper.txt;ocaml-rapper-helper /tmp/ocaml-rapper.txt' +} + + +# --- SNIPPETS + +map global insert ": phantom-selection-iterate-nexti" +map global insert ": phantom-selection-iterate-previ" +map global user f ":phantom-selection-select-all; phantom-selection-clear," +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 with "," (and + # with ). Try both to make sure we clear selections + # both with and without this breaking change. Pad them with + # to cancel out the key with the other behavior. + exec -save-regs '' 'Z' + phantom-selection-store-and-highlight + exec '<,>' + } 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" } + 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 "^\h+.\zI"' + fi + } catch %{ try %{ + execute-keys -itersel -draft "h%opt{softtabstop}2s\h+\zd" + }}} +} + +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 "^\h+.\zI"' + fi + } catch %{ try %{ + execute-keys -itersel -draft "h%opt{softtabstop}2s\h+\zd" + }}} +} + +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 "^\h*.\z" + } 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 "^\h+.\zI"' + fi + } catch %{ try %{ + execute-keys -itersel -draft "h%opt{softtabstop}2s\h+\zd" + }}} +} + +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\z 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 d + # reg c "snipcommand1" + # } catch %{ + # reg / "\Atrig2\z" + # exec -draft 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 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 '' ';' + 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 's\A\t+s.R' + > + + # align everything with the current line + eval -draft -itersel -save-regs '"' %< + try %< + exec -draft -save-regs '/' '),xs^\s+y' + exec -draft ')P' + > + > + + reg s %val{selections_desc} + # process placeholders + try %< + # select all placeholders ${..} and escaped-$ (== $$) + exec 's\$\$|\$\{(\}\}|[^}])*\}' + # 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 ';d' + # unselect the $ + exec '\A\$\z' + # 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 -- cgit v1.2.3