#################################
# Convenience functions
#################################

define-command filetype-hook -params 2 %{
    hook global WinSetOption "filetype=(%arg{1})" "%arg(2)"
}

#################################
# Generic mappings
#################################

# Comments
map global normal '$'     -docstring 'Comment the selected lines' ': comment-line<ret>'
map global normal '<a-$>' -docstring 'Comment the selected block with begin/end characters' ': comment-block<ret>'
map global normal '#' -docstring 'duplicate and comment line' 'xyp: comment-line<ret>j'

map global normal '*' -docstring 'select all occurrences of the word under cursor' 'be*n<ret>'

map global normal '=' -docstring 'indent like the line above' '<a-C>gi<a-&><space>jgi'

map global normal '<c-up>'   -docstring 'move line down' 'xdkPk'
map global normal '<c-down>' -docstring 'move line down' 'xdpj'
map global insert '<c-up>'   -docstring 'move line down' '<esc>xdkPki'
map global insert '<c-down>' -docstring 'move line down' '<esc>xdpji'

map global insert '<c-right>' -docstring 'one word right in insert mode' '<esc>eli'
map global insert '<c-left>'  -docstring 'one word left in insert mode'  '<esc>bi'
map global insert '<c-u>' -docstring 'kill line in insert mode' '<esc>GIc'

map global normal 'è' -docstring 'select the inner sequence enclosed by matching characters' 'mL<a-;>H'

def -params 1 extend-line-up %{
    exec "<a-:><a-;>%arg{1}K<a-;>"
    try %{
        exec -draft ';<a-K>\n<ret>'
        exec X
    }
    exec '<a-;><a-X>'
}
map global normal Y -docstring 'Extend selection to the previous line' ':extend-line-up %val{count}<ret>'

define-command cq -docstring 'Quit with an (arbitrary) error code' %{q! 666}

# Use Tab and Shift-Tab to navigate completion in insert mode.
hook global InsertCompletionShow .* %{
    try %{
        execute-keys -draft 'h<a-K>\h<ret>'
        map window insert <tab> <c-n>
        map window insert <s-tab> <c-p>
        hook -once -always window InsertCompletionHide .* %{
            map window insert <tab> <tab>
            map window insert <s-tab> <s-tab>
        }
    }
}

# Cursor switch.
map global normal <tab>   -docstring 'Swap selections cursor and anchor'       '<a-;>'
map global normal <a-tab> -docstring 'Ensure selection cursor is after anchor' '<a-:>'

# Go to paragraph/indents.
map global goto 'p' -docstring 'select to next paragraph'   '<esc>]p'
map global goto 'P' -docstring 'extend to next paragraph'   '<esc>}p'
map global goto 'o' -docstring 'select to prev paragraph'   '<esc>[p'
map global goto 'O' -docstring 'extend to prev paragraph'   '<esc>{p'
map global goto 't' -docstring 'select to indent end'       '<esc>]i'
map global goto 'T' -docstring 'select to indent beginning' '<esc>[i'

# Paths.
map global prompt <a-?> -docstring 'Current buffer name' '<c-r>%'
map global prompt <a-/> -docstring 'Current buffer directory' '%sh(dirname "$kak_bufname")<a-!>/'

#################################
# Generic config
#################################

set-option -add global ui_options ncurses_assistant=none
set-option -add global ui_options ncurses_set_title=yes
set-option -add global ui_options ncurses_padding_fill=yes

# Indent with 2 spaces and make tabs appear as 2 spaces.
set-option global tabstop 4
set-option global indentwidth 4

# tabs to spaces
hook global InsertChar \t %{
    exec -draft h@
}

# Keep space around cursor when scrolling.
set-option global scrolloff 3,3

# Add characters as matching pairs.
set-option -add global matching_pairs ‹ › « » “ ” ‘ ’

hook global ModuleLoaded x11 %{
    set global termcmd 'terminator -e '
    alias global terminal x11-terminal
}

# Persistent history across sessions.
hook global KakEnd .* %{ echo -to-file ~/.kak_history -quoting kakoune reg : %reg{:} }
hook global KakBegin .* %{ try %{ source ~/.kak_history } }


#################################
# Highlighting
#################################

add-highlighter global/matching show-matching
add-highlighter global/wrap wrap -word -indent -marker ⤷
add-highlighter global/suspicicous-whitespaces show-whitespaces -tab ⭲ -nbsp · -spc " " -lf " "
#add-highlighter global/trailing-whitespaces regex '\h+$' 0:error

define-command -hidden show-trailing-whitespaces %{ try %{ add-highlighter global/trailing-whitespaces regex '\h+$' 0:default,red } }
define-command -hidden hide-trailing-whitespaces %{ try %{ remove-highlighter global/trailing-whitespaces } }
hook global WinDisplay .*              show-trailing-whitespaces
hook global ModeChange 'insert:normal' show-trailing-whitespaces
hook global ModeChange 'normal:insert' hide-trailing-whitespaces


colorscheme kalolo

# Highlight generic tags
hook global WinSetOption comment_line=(.+) %{
    add-highlighter -override window/here  regex "\b(HERE)\b"   1:rgb:ffff00,rgb:ff0000+FB # WHERE
    add-highlighter -override window/fixme regex "\b(FIXME)\b"  1:rgb:ffff00,rgb:ff0000+Fb
    add-highlighter -override window/todo  regex "\b(TODO)\b"   1:rgb:000000,rgb:ff00ff+Fb
    add-highlighter -override window/note  regex "\b(NOTE)\b"   1:rgb:000000,rgb:a5c261+Fb
}

# Show line numbers (and highlight current cursor line)
hook global WinCreate ^[^*]+$ %{
    add-highlighter window/ number-lines -hlcursor -min-digits 3
}


#################################
# Language specifics
#################################

filetype-hook makefile %{
    set-option window indentwidth 0
}

filetype-hook latex %{
    set-option buffer autowrap_column 160
    autowrap-enable
}

filetype-hook markdown %{
    # set-option buffer autowrap_column 80
    # autowrap-enable
}

filetype-hook c|cpp %{
    clang-enable-autocomplete
    clang-enable-diagnostics
    alias window lint clang-parse
    alias window lint-next-error clang-diagnostics-next
    set-option buffer formatcmd "clang-format -style='WebKit'"
    map global normal A ': c-family-alternative-file'
}

filetype-hook python %{
    jedi-enable-autocomplete
    lint-enable
    set-option global lintcmd 'flake8'
}


#################################
# Plugins
#################################

# Autoinstall plug.kak if necessary.
evaluate-commands %sh{
    plugins="$HOME/.config/kak/plugins"
    mkdir -p $plugins
    [ ! -e "$plugins/plug.kak" ] && \
        git clone -q https://github.com/andreyorst/plug.kak "$plugins/plug.kak"
    printf "%s\n" "source '$plugins/plug.kak/rc/plug.kak'"
}
# Load the plugin manager.
plug "andreyorst/plug.kak" noload

# Buffers list.
plug 'delapouite/kakoune-buffers' %{
    hook global WinDisplay .* info-buffers
    map global normal à ': enter-buffers-mode<ret>' -docstring 'buffers'
    map global normal À ': enter-user-mode -lock buffers<ret>' -docstring 'buffers (lock)'
}

# Multi-select all identical characters in the column.
plug 'occivink/kakoune-vertical-selection' %{
    map global user <down> -docstring "Select all identical characters in the column downward" ': vertical-selection-down<ret>'
    map global user <up>   -docstring "Select all identical characters in the column upward"   ': vertical-selection-up<ret>'
}

# System clipboard integration.
plug "lePerdu/kakboard" %{
    hook global WinCreate .* %{ kakboard-enable }
}

# Fuzzy search
plug "andreyorst/fzf.kak" %{
    map global normal <c-p> ': fzf-mode<ret>'
}

plug "andreyorst/tagbar.kak" defer "tagbar" %{
    set-option global tagbar_sort false
    set-option global tagbar_size 40
    set-option global tagbar_display_anon false
    set-option global tagbar_show_details true
} config %{
    # if you have wrap highlighter enamled in you configuration
    # files it's better to turn it off for tagbar, using this hook:
    hook global WinSetOption filetype=tagbar %{
        remove-highlighter window/wrap
        # you can also disable rendering whitespaces here, line numbers, and
        # matching characters
    }
    # To see what filetypes are supported use `ctags --list-kinds | awk '/^\w+/'
    hook global WinSetOption filetype=(c|cpp|rust) %{
        tagbar-enable
    }
}

plug 'delapouite/kakoune-cd' %{
  # Suggested mapping
  map global user c ': enter-user-mode cd<ret>' -docstring 'cd'
  # Suggested aliases
  alias global cdb change-directory-current-buffer
  alias global cdr change-directory-project-root
  alias global ecd edit-current-buffer-directory
  alias global pwd print-working-directory
}
# Automatically change working directory to be the buffer's one.
hook global WinDisplay .* %{
    # require delapouite/kakoune-cd
    change-directory-current-buffer
}

# Like alexherbo2/search-highlighter.kak, but which actually works.
# face global Search white,yellow
def search-highlight-enable %{
  hook window -group search-highlight NormalKey [/?*nN]|<a-[/?*nN]> %{ try %{
    addhl window/search dynregex '%reg{/}' 0:Search
  }}
  hook window -group search-highlight NormalKey <esc> %{ rmhl window/search}
}
def search-highlight-disable %{
  rmhl window/search
  rmhooks window search-highlight
}
# Always highlight search.
hook global WinDisplay .* %{
    search-highlight-enable
}

plug "kak-lsp/kak-lsp" do %{
        cargo install --locked --force --path .
} config %{

    # uncomment to enable debugging
    # eval %sh{echo ${kak_opt_lsp_cmd} >> /tmp/kak-lsp.log}
    # set global lsp_cmd "kak-lsp -s %val{session} -vvv --log /tmp/kak-lsp.log"

    # ,l will display a specific menu for LSP
    map global user l %{: enter-user-mode lsp<ret>} -docstring "LSP mode"

    # lsp-enable
    set-option global lsp_server_configuration pyls.configurationSources=["flake8"]

    set global lsp_diagnostic_line_error_sign '║'
    set global lsp_diagnostic_line_warning_sign '┊'

    # define-command ne -docstring 'go to next error/warning from lsp' %{ lsp-find-error --include-warnings }
    # define-command pe -docstring 'go to previous error/warning from lsp' %{ lsp-find-error --previous --include-warnings }
    # define-command ee -docstring 'go to current error/warning from lsp' %{ lsp-find-error --include-warnings; lsp-find-error --previous --include-warnings }

    define-command lsp-restart -docstring 'restart lsp server' %{ lsp-stop; lsp-start }

    hook global WinSetOption filetype=(c|cpp|python) %{
        # Show matching objects?
        set-option window lsp_auto_highlight_references false
        map global '<s-*>' -docstring 'Highlight related references' ': lsp-highlight-references<ret>'

        # Hint window next to the cursor?
        set-option window lsp_hover_anchor false

        lsp-auto-hover-enable
        lsp-enable-window
    }

    hook global KakEnd .* lsp-exit
}

plug "dmerejkowsky/kak-spell" config %{
  declare-user-mode kak-spell
  map global user s ': enter-user-mode -lock kak-spell<ret>' -docstring 'enter spell user mode'
  map global kak-spell a ': kak-spell-add<ret>' -docstring 'add the selection to the user dict'
  map global kak-spell d ': kak-spell-disable<ret>' -docstring 'clear spelling highlighters'
  map global kak-spell e ': kak-spell-enable en_US<ret> :kak-spell <ret>' -docstring 'enable spell check in English'
  map global kak-spell f ': kak-spell-enable fr_FR<ret> :kak-spell <ret>' -docstring 'run spell check in French'
  map global kak-spell l ': kak-spell-list <ret>' -docstring 'list spelling errors in a buffer'
  map global kak-spell n ': kak-spell-next<ret>' -docstring 'go to next spell error'
  map global kak-spell p ': kak-spell-previous<ret>' -docstring 'go to next spell error'
  map global kak-spell r ': kak-spell-replace<ret>' -docstring 'suggest a list of replacements'
  map global kak-spell x ': kak-spell-remove<ret>' -docstring 'remove the selection from the user dict'
}

set-option -add global ui_options ncurses_padding_char=╱ # Examples: ▚ ╳ ╱ ┼ ╲

add-highlighter global/ scrollbar
add-highlighter global/scrollbar/ scrollbar-indicator red,default lsp_error_lines
add-highlighter global/scrollbar/ scrollbar-indicator yellow,default lint_flags
# add-highlighter global/scrollbar/ scrollbar-indicator red,default git_diff_flags
# git show-diff
