diff --git a/rc/base/lint.kak b/rc/base/lint.kak new file mode 100644 index 00000000..dc8bb4f7 --- /dev/null +++ b/rc/base/lint.kak @@ -0,0 +1,100 @@ +# your linter should output in this format: +# {filename}:{line}:{column}: {kind}: {message} +decl str lintcmd + +decl -hidden line-flags lint_flags +decl -hidden str lint_errors + +def lint -docstring 'Parse the current buffer with a linter' %{ + %sh{ + dir=$(mktemp -d -t kak-lint.XXXXXXXX) + mkfifo "$dir"/fifo + printf '%s\n' "eval -no-hooks write $dir/buf" + + printf '%s\n' "eval -draft %{ + edit! -fifo $dir/fifo *lint-output* + set buffer filetype make + set buffer _make_current_error_line 0 + hook -group fifo buffer BufCloseFifo .* %{ + nop %sh{ rm -r '$dir' } + rmhooks buffer fifo + } + }" + + { # do the parsing in the background and when ready send to the session + + eval "$kak_opt_lintcmd '$dir'/buf" | sort -t: -k2 -n > "$dir"/stderr + printf '%s\n' "eval -client $kak_client echo 'linting done'" | kak -p "$kak_session" + + # Flags for the gutter: + # line3|{red}:line11|{yellow} + # Contextual error messages: + # l1,c1,err1 + # ln,cn,err2 + awk -F: -v file="$kak_buffile" -v stamp="$kak_timestamp" ' + /:[0-9]+:[0-9]+: ([Ff]atal )?[Ee]rror/ { + flags = flags $2 "|{red}█:" + } + /:[0-9]+:[0-9]+:/ { + if ($4 !~ /[Ee]rror/) { + flags = flags $2 "|{yellow}█:" + } + } + /:[0-9]+:[0-9]+:/ { + errors = errors $2 "," $3 "," substr($4,2) ":" + # fix case where $5 is not the last field because of extra :s in the message + for (i=5; i<=NF; i++) errors = errors $i ":" + errors = substr(errors, 1, length(errors)-1) "\n" + } + END { + print "set \"buffer=" file "\" lint_flags %{" stamp ":" substr(flags, 1, length(flags)-1) "}" + print "set \"buffer=" file "\" lint_errors %{" substr(errors, 1, length(errors)-1) "}" + } + ' "$dir"/stderr | kak -p "$kak_session" + + cut -d: -f2- "$dir"/stderr | sed "s@^@$kak_bufname:@" > "$dir"/fifo + + } >/dev/null 2>&1