From 904cec3c4a329cf89fc3219d359239910d61f3f6 Mon Sep 17 00:00:00 2001 From: thing1 Date: Tue, 28 Jan 2025 09:14:32 +0000 Subject: init commit --- autoload/detection/editorconfig.kak | 60 ++++++++++++++++++ autoload/detection/file.kak | 26 ++++++++ autoload/detection/modeline.kak | 123 ++++++++++++++++++++++++++++++++++++ 3 files changed, 209 insertions(+) create mode 100644 autoload/detection/editorconfig.kak create mode 100644 autoload/detection/file.kak create mode 100644 autoload/detection/modeline.kak (limited to 'autoload/detection') diff --git a/autoload/detection/editorconfig.kak b/autoload/detection/editorconfig.kak new file mode 100644 index 0000000..e836c3e --- /dev/null +++ b/autoload/detection/editorconfig.kak @@ -0,0 +1,60 @@ +# http://editorconfig.org/#file-format-details +# ‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾‾ + +# Detection +# ‾‾‾‾‾‾‾‾‾ + +hook global BufCreate .*[.](editorconfig) %{ + set-option buffer filetype ini + set-option buffer static_words indent_style indent_size tab_width \ + end_of_line charset insert_final_newline trim_trailing_whitespace root \ + latin1 utf-8 utf-8-bom utf-16be utf-16le lf cr crlf unset space tab max_line_length +} + +define-command editorconfig-load -params ..1 -docstring "editorconfig-load [file]: set formatting behavior according to editorconfig" %{ + evaluate-commands %sh{ + command -v editorconfig >/dev/null 2>&1 || { echo "fail editorconfig could not be found"; exit 1; } + + file="${1:-$kak_buffile}" + case $file in + /*) # $kak_buffile is a full path that starts with a '/' + printf %s\\n "remove-hooks buffer editorconfig-hooks" + editorconfig "$file" | awk -v file="$file" -F= -- ' + $1 == "indent_style" { indent_style = $2 } + $1 == "indent_size" { indent_size = $2 == "tab" ? 4 : $2 } + $1 == "tab_width" { tab_width = $2 } + $1 == "end_of_line" { end_of_line = $2 } + $1 == "charset" { charset = $2 } + $1 == "trim_trailing_whitespace" { trim_trailing_whitespace = $2 } + $1 == "max_line_length" { max_line_length = $2 } + + END { + if (indent_style == "tab") { + print "set-option buffer indentwidth 0" + } + if (indent_style == "space") { + print "set-option buffer indentwidth " indent_size + } + if (indent_size || tab_width) { + print "set-option buffer tabstop " (tab_width ? tab_width : indent_size) + } + if (end_of_line == "lf" || end_of_line == "crlf") { + print "set-option buffer eolformat " end_of_line + } + if (charset == "utf-8-bom") { + print "set-option buffer BOM utf8" + } + if (trim_trailing_whitespace == "true") { + print "hook buffer BufWritePre \"" file "\" -group editorconfig-hooks %{ try %{ execute-keys -draft %{%s\\h+$|\\n+\\zd} } }" + } + if (max_line_length && max_line_length != "off") { + print "set window autowrap_column " max_line_length + print "autowrap-enable" + print "add-highlighter window/ column %sh{ echo $((" max_line_length "+1)) } default,bright-black" + } + } + ' ;; + esac + } +} +complete-command editorconfig-load file diff --git a/autoload/detection/file.kak b/autoload/detection/file.kak new file mode 100644 index 0000000..c707386 --- /dev/null +++ b/autoload/detection/file.kak @@ -0,0 +1,26 @@ +define-command -hidden file-detection %{ evaluate-commands %sh{ + if [ -z "${kak_opt_filetype}" ]; then + mime=$(file -b --mime-type -L "${kak_buffile}") + mime=${mime%;*} + case "${mime}" in + application/*+xml) filetype="xml" ;; + image/*+xml) filetype="xml" ;; #SVG + message/rfc822) filetype="mail" ;; + text/x-shellscript) filetype="sh" ;; + text/x-script.*) filetype="${mime#text/x-script.}" ;; + text/x-*) filetype="${mime#text/x-}" ;; + text/plain) exit ;; + text/*) filetype="${mime#text/}" ;; + application/x-shellscript) filetype="sh" ;; + application/x-*) filetype="${mime#application/x-}" ;; + application/*) filetype="${mime#application/}" ;; + *) exit ;; + esac + if [ -n "${filetype}" ]; then + printf "set-option buffer filetype '%s'\n" "${filetype}" + fi + fi +} } + +hook -group file-detection global BufOpenFile .* file-detection +hook -group file-detection global BufWritePost .* file-detection diff --git a/autoload/detection/modeline.kak b/autoload/detection/modeline.kak new file mode 100644 index 0000000..6e067b1 --- /dev/null +++ b/autoload/detection/modeline.kak @@ -0,0 +1,123 @@ +## +## modeline.kak by lenormf +## + +## Currently supported modeline format: vim +## Also supports kakoune options with a 'kak' or 'kakoune' prefix +## Only a few options are supported, in order to prevent the +## buffers from poking around the configuration too much + +declare-option -docstring "amount of lines that will be checked at the beginning and the end of the buffer" \ + int modelines 5 + +define-command -hidden modeline-parse-impl %{ + evaluate-commands %sh{ + kakquote() { printf "%s" "$*" | sed "s/'/''/g; 1s/^/'/; \$s/\$/'/"; } + + # Translate a vim option into the corresponding kakoune one + translate_opt_vim() { + local key="$1" + local value="$2" + + case "${key}" in + so|scrolloff) + key="scrolloff"; + value="${value},${kak_opt_scrolloff##*,}";; + siso|sidescrolloff) + key="scrolloff"; + value="${kak_opt_scrolloff%%,*},${value}";; + ts|tabstop) key="tabstop";; + sw|shiftwidth) key="indentwidth";; + tw|textwidth) key="autowrap_column";; + ff|fileformat) + key="eolformat"; + case "${value}" in + unix) value="lf";; + dos) value="crlf";; + *) + printf '%s\n' "Unsupported file format: ${value}" >&2 + return;; + esac + ;; + ft|filetype) key="filetype";; + bomb) + key="BOM"; + value="utf8";; + nobomb) + key="BOM"; + value="none";; + spelllang|spl) + key="spell_lang"; + value="${value%%,*}";; + *) + printf '%s\n' "Unsupported vim variable: ${key}" >&2 + return;; + esac + + printf 'set-option buffer %s %s\n' "${key}" "$(kakquote "${value}")" + } + + # Pass a few whitelisted options to kakoune directly + translate_opt_kakoune() { + local readonly key="$1" + local readonly value="$2" + + case "${key}" in + scrolloff|tabstop|indentwidth|autowrap_column|eolformat|filetype|BOM|spell_lang);; + *) printf 'echo -debug %s' "$(kakquote "Unsupported kakoune variable: ${key}")" \ + | kak -p "${kak_session}" + return;; + esac + + printf 'set-option buffer %s %s\n' "${key}" "$(kakquote "${value}")" + } + + case "${kak_selection}" in + *vi:*|*vim:*) type_selection="vim";; + *kak:*|*kakoune:*) type_selection="kakoune";; + *) + printf 'fail %s\n' "$(kakquote "Unsupported modeline format: ${kak_selection}")" + exit 1 ;; + esac + + # The following subshell will keep the actual options of the modeline, and strip: + # - the text that leads the first option, according to the official vim modeline format + # - the trailing text after the last option, and an optional ':' sign before it + # It will also convert the ':' seperators beween the option=value pairs + # More info: http://vimdoc.sourceforge.net/htmldoc/options.html#modeline + printf %s "${kak_selection}" | sed \ + -e 's/^[^:]\{1,\}://' \ + -e 's/[ \t]*set\{0,1\}[ \t]\([^:]*\).*$/\1/' \ + -e 's/:[^a-zA-Z0-9_=-]*$//' \ + -e 's/:/ /g' \ + | tr ' ' '\n' \ + | while read -r option; do + name_option="${option%%=*}" + value_option="${option#*=}" + + if [ -z "${option}" ]; then + continue + fi + + case "${type_selection}" in + vim) translate_opt_vim "${name_option}" "${value_option}";; + kakoune) translate_opt_kakoune "${name_option}" "${value_option}";; + *) exit 1;; + esac + done + } +} + +# Add the following function to a hook on BufOpenFile to automatically parse modelines +# Select the first and last `modelines` lines in the buffer, only keep modelines +# ref. options.txt (in vim `:help options`) : 2 forms of modelines: +# [text]{white}{vi:|vim:|ex:}[white]{options} +# [text]{white}{vi:|vim:|Vim:|ex:}[white]se[t] {options}:[text] +define-command modeline-parse -docstring "Read and interpret vi-format modelines at the beginning/end of the buffer" %{ + try %{ evaluate-commands -draft -save-regs ^ %{ + execute-keys -save-regs "" gk %opt{modelines} JK x Z + execute-keys gj %opt{modelines} KJ x a + execute-keys s^\S*?\s+?\w+:\s?[^\n]+ x + evaluate-commands -draft -itersel modeline-parse-impl + } } +} -- cgit v1.2.3