summaryrefslogtreecommitdiff
path: root/autoload/detection
diff options
context:
space:
mode:
authorthing1 <thing1@seacrossedlovers.xyz>2025-01-28 09:14:32 +0000
committerthing1 <thing1@seacrossedlovers.xyz>2025-01-28 09:14:32 +0000
commit904cec3c4a329cf89fc3219d359239910d61f3f6 (patch)
tree8d113899921dfbaca0e77c49ab5fc827362d1091 /autoload/detection
init commitHEADmaster
Diffstat (limited to 'autoload/detection')
-rw-r--r--autoload/detection/editorconfig.kak60
-rw-r--r--autoload/detection/file.kak26
-rw-r--r--autoload/detection/modeline.kak123
3 files changed, 209 insertions, 0 deletions
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+\\z<ret>d} } }"
+ }
+ 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-z> a
+ execute-keys s^\S*?\s+?\w+:\s?[^\n]+<ret> x
+ evaluate-commands -draft -itersel modeline-parse-impl
+ } }
+}