home/rc/detection/modeline.kak
Frank LENORMAND 2d78b0760d rc modeline: Error out on unsupported formats
This commit makes `:modeline-parse` grab all lines that look like
modelines, and lets the parser deal with invalid formats.

This allows actually printing an error on unsupported modelines
formats, instead of ignoring them upfront.
2020-09-18 14:54:57 +03:00

116 lines
4.9 KiB
Plaintext

##
## 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() {
readonly key="$1"
readonly value="$2"
tr=""
case "${key}" in
so|scrolloff) tr=$(kakquote scrolloff "${value},${kak_opt_scrolloff##*,}");;
siso|sidescrolloff) tr=$(kakquote scrolloff "${kak_opt_scrolloff%%,*},${value}");;
ts|tabstop) tr=$(kakquote tabstop "${value}");;
sw|shiftwidth) tr=$(kakquote indentwidth "${value}");;
tw|textwidth) tr=$(kakquote autowrap_column "${value}");;
ff|fileformat)
case "${value}" in
unix) tr="eolformat lf";;
dos) tr="eolformat crlf";;
*) printf 'echo -debug %s' "$(kakquote "Unsupported file format: ${value}")" \
| kak -p "${kak_session}";;
esac
;;
ft|filetype) tr=$(kakquote filetype "{value}");;
bomb) tr="BOM utf8";;
nobomb) tr="BOM none";;
spelllang|spl) tr=$(kakquote spell_lang "{value%%,*}");;
*) printf 'echo -debug %s' "$(kakquote "Unsupported vim variable: ${key}")" \
| kak -p "${kak_session}";;
esac
if [ -n "${tr}" ]; then
printf 'set-option buffer %s\n' "${tr}"
fi
}
# Pass a few whitelisted options to kakoune directly
translate_opt_kakoune() {
readonly key="$1"
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' "$(kakquote "${key}" "${value}")"
}
case "${kak_selection}" in
*vi:*|*vim:*) type_selection="vim";;
*kak:*|*kakoune:*) type_selection="kakoune";;
*) printf 'echo -debug %s' "$(kakquote "Unsupported modeline format: ${kak_selection}")" \
| kak -p "${kak_session}"; 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]//' \
-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) tr=$(translate_opt_vim "${name_option}" "${value_option}");;
kakoune) tr=$(translate_opt_kakoune "${name_option}" "${value_option}");;
*) tr="";;
esac
if [ -n "${tr}" ]; then
printf %s\\n "${tr}"
fi
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 %{
execute-keys <percent> "s(?S)\A(.+\n){,%opt{modelines}}|(.+\n){,%opt{modelines}}\z<ret>" \
s^\S*?\s+?\w+:\s?[^\n]+<ret> <a-x>
evaluate-commands -draft -itersel modeline-parse-impl
} }
}