#
# Kakoune, one of our main editors.
#
{ pkgs, deprekages, ... }:
{
  programs.kakoune = {
    enable = true;

    config = {
      tabStop = 2;
      numberLines.enable = true;

      hooks = [

        # Automatically enable the LSP when a supported file is found.
        {
          name = "WinSetOption";
          option = "filetype=(python|nix|c|cpp|rust|ruby)";
          commands = ''
            	  lsp-enable-window

               # Finally, inject our buffer name in front of the modeline, so tabs are named correctly.
               set global -remove modelinefmt "%val{bufname}"
               set global modelinefmt "%val{bufname} - %opt{modelinefmt}"
          '';
        }

        # Additional file types.
        {
          name = "BufCreate";
          option = ".*\\.typ";
          commands = ''
              		set-option buffer filetype typst
              		addhl buffer/ wrap -word
            		'';
        }

        # Spell checking.
        {
          name = "ModeChange";
          option = "push:[^:]*:next-key\\[user.spell\\]";
          commands = ''
            hook -once -always window NormalIdle .* spell-clear
            spell en_US
          '';
        }
      ];

      keyMappings = [
        # Vertical selections.
        {
          mode = "user";
          key = "v";
          effect = ":vertical-selection-down<ret>";
          docstring = "select matching lines down";
        }
        {
          mode = "user";
          key = "<a-v>";
          effect = ":vertical-selection-up<ret>";
          docstring = "select matching lines up";
        }
        {
          mode = "user";
          key = "V";
          effect = ":vertical-selection-up-and-down<ret>";
          docstring = "select matching lines (bidirectional)";
        }

        # Shortcuts.
        {
          mode = "user";
          key = "a";
          effect = "<a-a>";
          docstring = "select around";
        }
        {
          mode = "user";
          key = "i";
          effect = "<a-i>";
          docstring = "select inside";
        }
        {
          mode = "user";
          key = "q";
          effect = "<a-i>Q";
          docstring = "select inside double quotes";
        }
        {
          mode = "user";
          key = "Q";
          effect = "<a-i>QC";
          docstring = "change inside double quotes";
        }

        # Spell-checking.
        {
          mode = "user";
          key = "s";
          effect = ": enter-user-mode -lock spell<ret>";
          docstring = "enter spelling mode";
        }
        {
          mode = "spell";
          key = "a";
          effect = ":spell-add; spell en_US<ret>";
          docstring = "add word to spell-checker";
        }
        {
          mode = "spell";
          key = "r";
          effect = ":_spell-replace<ret>";
          docstring = "suggest spelling replacements";
        }
        {
          mode = "spell";
          key = "n";
          effect = ":spell-next<ret>";
          docstring = "move to the next word";
        }
      ];
    };

    extraConfig = ''

      # Set up our LSP host.
      eval %sh{kak-lsp --kakoune -s $kak_session}

      # Use a cat assistant, which puck think is cute.
      set global ui_options terminal_assistant=cat

      # Use tree-sitter for coloring.
      eval %sh{ ${deprekages.kak-tree-sitter}/bin/kak-tree-sitter -dks --init $kak_session }
      colorscheme solarized-darker

      # Use wezterm when possible, and tmux otherwise.
      source ${../../../kak/wezterm-tab.kak}
      set global windowing_modules 'wezterm-tab' 'tmux'

      # Enable auotmatic hovering.
      lsp-auto-hover-enable
      set global lsp_hover_anchor true

      # Rainbow brackets.
      require-module rainbow

      # Editorconfig.
      hook global BufOpenFile .* editorconfig-load
      hook global BufNewFile .* editorconfig-load

      # Set up spellchecking.
      define-command -hidden -params 0 _spell-replace %{
        hook -always -once window ModeChange push:prompt:next-key\[user.spell\] %{
            execute-keys <esc>
        }
        hook -once -always window NormalIdle .* %{
            enter-user-mode -lock spell
            spell en_US
        }
        spell-replace
      }

      # Misc plugins.
      source ${../../../kak/sudo-write.kak}
    '';

    plugins = with pkgs.kakounePlugins; [
      connect-kak
      kak-ansi
      kak-prelude
      kakoune-extra-filetypes
      kakoune-lsp
      kakoune-rainbow
      kakoune-state-save
      kakoune-vertical-selection
      deprekages.kak-tree-sitter
      parinfer-rust
    ];
  };
}
