# http://ocaml.org # ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ # Detection # ‾‾‾‾‾‾‾‾‾ hook global BufCreate .*\.(ml|mli|mll|mly)$ %{ set-option buffer filetype ocaml } # Initialization # ‾‾‾‾‾‾‾‾‾‾‾‾‾‾ hook global WinSetOption filetype=ocaml %{ require-module ocaml set-option window static_words %opt{ocaml_static_words} hook window InsertChar -group ocaml-insert '\*' ocaml-insert-closing-comment-bracket hook window InsertChar \n -group ocaml-insert ocaml-insert-on-new-line hook window ModeChange pop:insert:.* -group ocaml-trim-indent ocaml-trim-indent } hook -group ocaml-highlight global WinSetOption filetype=ocaml %{ add-highlighter window/ocaml ref ocaml alias window alt ocaml-alternative-file hook -once -always window WinSetOption filetype=.* %{ unalias window alt ocaml-alternative-file remove-highlighter window/ocaml } } provide-module ocaml %{ # Highlighters # ‾‾‾‾‾‾‾‾‾‾‾‾ add-highlighter shared/ocaml regions add-highlighter shared/ocaml/code default-region group add-highlighter shared/ocaml/string region (?/?]+ 0:operator # Macro # ‾‾‾‾‾ evaluate-commands %sh{ keywords="and|as|asr|assert|begin|class|constraint|do|done|downto|else|end|exception|external|false" keywords="${keywords}|for|fun|function|functor|if|in|include|inherit|initializer|land|lazy|let|lor" keywords="${keywords}|lsl|lsr|lxor|match|method|mod|module|mutable|new|nonrec|object|of|open|or" keywords="${keywords}|private|rec|sig|struct|then|to|true|try|type|val|virtual|when|while|with" printf %s\\n "declare-option str-list ocaml_static_words ${keywords}" | tr '|' ' ' # must be put at last, since we have highlighted some keywords ('type' in 'module type') to other things printf %s " add-highlighter shared/ocaml/code/ regex \b(${keywords})\b 0:keyword " } # Conveniences # ‾‾‾‾‾‾‾‾‾‾‾‾ # C has header and source files and you need to often switch between them. # Similarly OCaml has .ml (implementation) and .mli (interface files) and # one often needs to switch between them. # # This command provides a simple functionality that allows you to accomplish this. define-command ocaml-alternative-file -docstring 'Switch between .ml and .mli file or vice versa' %{ evaluate-commands %sh{ if [ "${kak_buffile##*.}" = 'ml' ]; then printf "edit -- '%s'" "$(printf %s "${kak_buffile}i" | sed "s/'/''/g")" elif [ "${kak_buffile##*.}" = 'mli' ]; then printf "edit -- '%s'" "$(printf %s "${kak_buffile%i}" | sed "s/'/''/g")" fi } } } # Remove trailing whitespaces define-command -hidden ocaml-trim-indent %{ evaluate-commands -no-hooks -draft -itersel %{ try %{ execute-keys -draft x s \h+$ d } } } # Preserve indentation when creating new line define-command -hidden ocaml-insert-on-new-line %{ evaluate-commands -draft -itersel %{ # copy white spaces at the beginnig of the previous line try %{ execute-keys -draft k x s ^\h+ y jgh P x s \h+$ } # increase indentation if the previous line ended with either '=' sign or do keyword try %{ execute-keys -draft k x s (=|\bdo)$ j } } } # The OCaml comment is `(* Some comment *)`. Like the C-family this can be a multiline comment. # # Recognize when the user is trying to commence a comment when they type `(*` and # then automatically insert `*)` on behalf of the user. A small convenience. define-command -hidden ocaml-insert-closing-comment-bracket %{ try %{ execute-keys -draft 'HH\(\*' execute-keys ' *)' } }