# Detection hook global BufCreate .*\.(cc|cpp|cxx|C|hh|hpp|hxx|H)$ %{ set-option buffer filetype cpp } hook global BufSetOption filetype=c\+\+ %{ hook -once buffer NormalIdle '' "set-option buffer filetype cpp" } hook global BufCreate .*\.c$ %{ set-option buffer filetype c } hook global BufCreate .*\.h$ %{ try %{ execute-keys -draft %{%s\b::\b|\btemplate\h*|\bclass\h+\w+|\b(typename|namespace)\b|\b(public|private|protected)\h*:} set-option buffer filetype cpp } catch %{ set-option buffer filetype c } } hook global BufCreate .*\.m %{ set-option buffer filetype objc } hook global WinSetOption filetype=(c|cpp|objc) %[ require-module c-family evaluate-commands "set-option window static_words %%opt{%val{hook_param_capture_1}_static_words}" hook -group "%val{hook_param_capture_1}-trim-indent" window ModeChange pop:insert:.* c-family-trim-indent hook -group "%val{hook_param_capture_1}-insert" window InsertChar \n c-family-insert-on-newline hook -group "%val{hook_param_capture_1}-indent" window InsertChar \n c-family-indent-on-newline hook -group "%val{hook_param_capture_1}-indent" window InsertChar \{ c-family-indent-on-opening-curly-brace hook -group "%val{hook_param_capture_1}-indent" window InsertChar \} c-family-indent-on-closing-curly-brace hook -group "%val{hook_param_capture_1}-insert" window InsertChar \} c-family-insert-on-closing-curly-brace alias window alt "%val{hook_param_capture_1}-alternative-file" hook -once -always window WinSetOption filetype=.* " remove-hooks window %val{hook_param_capture_1}-.+ unalias window alt %val{hook_param_capture_1}-alternative-file " ] hook -group c-highlight global WinSetOption filetype=c %{ add-highlighter window/c ref c hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/c } } hook -group cpp-highlight global WinSetOption filetype=cpp %{ add-highlighter window/cpp ref cpp hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/cpp } } hook -group objc-highlight global WinSetOption filetype=objc %{ add-highlighter window/objc ref objc hook -once -always window WinSetOption filetype=.* %{ remove-highlighter window/objc } } provide-module c-family %§ define-command -hidden c-family-trim-indent %{ # remove the line if it's empty when leaving the insert mode try %{ execute-keys -draft 1s^(\h+)$ d } } define-command -hidden c-family-indent-on-newline %< evaluate-commands -draft -itersel %< execute-keys try %< # if previous line is part of a comment, do nothing execute-keys -draft /\* ^\h*[^/*\h] > catch %< # else if previous line closed a paren (possibly followed by words and a comment), # copy indent of the opening paren line execute-keys -draft k 1s(\))(\h+\w+)*\h*(\;\h*)?(?://[^\n]+)?\n\z mJ 1 > catch %< # else indent new lines with the same level as the previous one execute-keys -draft K > # remove previous empty lines resulting from the automatic indent try %< execute-keys -draft k ^\h+$ Hd > # indent after an opening brace or parenthesis at end of line try %< execute-keys -draft k [{(]\h*$ j > # indent after a label try %< execute-keys -draft k s[a-zA-Z0-9_-]+:\h*$ j > # indent after a statement not followed by an opening brace try %< execute-keys -draft k s\)\h*(?://[^\n]+)?\n\z \ mB \A\b(if|for|while)\b j > try %< execute-keys -draft k s \belse\b\h*(?://[^\n]+)?\n\z \ j > # deindent after a single line statement end try %< execute-keys -draft K \;\h*(//[^\n]+)?$ \ K s\)(\h+\w+)*\h*(//[^\n]+)?\n([^\n]*\n){2}\z \ MB \A\b(if|for|while)\b 1 > try %< execute-keys -draft K \;\h*(//[^\n]+)?$ \ K s \belse\b\h*(?://[^\n]+)?\n([^\n]*\n){2}\z \ 1 > # deindent closing brace(s) when after cursor try %< execute-keys -draft ^\h*[})] gh / [})] m 1 > # align to the opening parenthesis or opening brace (whichever is first) # on a previous line if its followed by text on the same line try %< evaluate-commands -draft %< # Go to opening parenthesis and opening brace, then select the most nested one try %< execute-keys [c [({],[)}] > # Validate selection and get first and last char execute-keys \A[{(](\h*\S+)+\n "(([^"]*"){2})* '(([^']*'){2})* L # Remove possibly incorrect indent from new line which was copied from previous line try %< execute-keys -draft s\h+ d > # Now indent and align that new line with the opening parenthesis/brace execute-keys 1 & > > > > define-command -hidden c-family-indent-on-opening-curly-brace %[ # align indent with opening paren when { is entered on a new line after the closing paren try %[ execute-keys -draft -itersel h)M \A\(.*\)\h*\n\h*\{\z 1 ] # align indent with opening paren when { is entered on a new line after the else try %[ execute-keys -draft -itersel hK s \belse\b\h*(?://[^\n]+)?\n\h*\{ 1 ] ] define-command -hidden c-family-indent-on-closing-curly-brace %[ # align to opening curly brace when alone on a line try %[ # in case open curly brace follows a closing paren, align indent with opening paren execute-keys -itersel -draft ^\h+\}$hm )M \A\(.*\)\h\{.*\}\z 1 ] catch %[ # otherwise align with open curly brace execute-keys -itersel -draft ^\h+\}$hm1 ] catch %[] ] define-command -hidden c-family-insert-on-closing-curly-brace %[ # add a semicolon after a closing brace if part of a class, union or struct definition try %[ execute-keys -itersel -draft hmB \A[^\n]+\)\h*(\{|$) \A\h*(class|struct|union|enum) ';i;' ] ] define-command -hidden c-family-insert-on-newline %[ evaluate-commands -itersel -draft %[ execute-keys try %[ evaluate-commands -draft -save-regs '/"' %[ # copy the commenting prefix execute-keys -save-regs '' k 1s^\h*(//+\h*) y try %[ # if the previous comment isn't empty, create a new one execute-keys ^\h*//+\h*$ js^\h*P ] catch %[ # if there is no text in the previous comment, remove it completely execute-keys d ] ] ] try %[ # if the previous line isn't within a comment scope, break execute-keys -draft k ^(\h*/\*|\h+\*(?!/)) # find comment opening, validate it was not closed, and check its using star prefixes execute-keys -draft /\* \*/ \A\h*/\*([^\n]*\n\h*\*)*[^\n]*\n\h*.\z try %[ # if the previous line is opening the comment, insert star preceeded by space execute-keys -draft k^\h*/\* execute-keys -draft i* ] catch %[ try %[ # if the next line is a comment line insert a star execute-keys -draft j^\h+\* execute-keys -draft i* ] catch %[ try %[ # if the previous line is an empty comment line, close the comment scope execute-keys -draft k^\h+\*\h+$ 1s\*(\h*)c/ ] catch %[ # if the previous line is a non-empty comment line, add a star execute-keys -draft i* ] ] ] # trim trailing whitespace on the previous line try %[ execute-keys -draft s\h+$ d ] # align the new star with the previous one execute-keys K1s^[^*]*(\*)& ] ] ] # Regions definition are the same between c++ and objective-c evaluate-commands %sh{ for ft in c cpp objc; do if [ "${ft}" = "objc" ]; then maybe_at='@?' else maybe_at='' fi cat <<-EOF add-highlighter shared/$ft regions add-highlighter shared/$ft/code default-region group add-highlighter shared/$ft/string region %{$maybe_at(?%ggI/xs^.*/dxs\.c_A_INCLUDEDggxyppI#ifndefjI#definejI#endif//O' ;; pragma) echo 'execute-keys ggi#pragmaonce' ;; *);; esac } } hook -group c-family-insert global BufNewFile .*\.(h|hh|hpp|hxx|H) c-family-insert-include-guards declare-option -docstring "colon separated list of path in which header files will be looked for" \ str-list alt_dirs '.' '..' define-command -hidden c-family-alternative-file %{ evaluate-commands %sh{ file="${kak_buffile##*/}" file_noext="${file%.*}" dir=$(dirname "${kak_buffile}") # Set $@ to alt_dirs eval "set -- ${kak_quoted_opt_alt_dirs}" case ${file} in *.c|*.cc|*.cpp|*.cxx|*.C|*.inl|*.m) for alt_dir in "$@"; do for ext in h hh hpp hxx H; do case "$alt_dir" in /*) altname="${alt_dir}/${file_noext}.${ext}" ;; *) altname="${dir}/${alt_dir}/${file_noext}.${ext}" ;; esac if [ -f ${altname} ]; then printf 'edit %%{%s}\n' "${altname}" exit fi done done ;; *.h|*.hh|*.hpp|*.hxx|*.H) for alt_dir in "$@"; do for ext in c cc cpp cxx C m; do case "$alt_dir" in /*) altname="${alt_dir}/${file_noext}.${ext}" ;; *) altname="${dir}/${alt_dir}/${file_noext}.${ext}" ;; esac if [ -f ${altname} ]; then printf 'edit %%{%s}\n' "${altname}" exit fi done done ;; *) echo "fail 'extension not recognized'" exit ;; esac echo "fail 'alternative file not found'" } } define-command c-alternative-file -docstring "Jump to the alternate c file (header/implementation)" %{ c-family-alternative-file } define-command cpp-alternative-file -docstring "Jump to the alternate cpp file (header/implementation)" %{ c-family-alternative-file } define-command objc-alternative-file -docstring "Jump to the alternate objc file (header/implementation)" %{ c-family-alternative-file } § # Module aliases provide-module c %{ require-module c-family } provide-module cpp %{ require-module c-family } provide-module objc %{ require-module c-family }