declare-option -docstring %{shell command to which the path of a copy of the current buffer will be passed The output returned by this command is expected to comply with the following format: {filename}:{line}:{column}: {kind}: {message}} \ str lintcmd declare-option -hidden line-specs lint_flags declare-option -hidden range-specs lint_errors declare-option -hidden int lint_error_count declare-option -hidden int lint_warning_count define-command lint -docstring 'Parse the current buffer with a linter' %{ evaluate-commands %sh{ if [ -z "${kak_opt_lintcmd}" ]; then printf %s\\n 'echo -markup {Error}The `lintcmd` option is not set' exit 1 fi extension="" if printf %s "${kak_buffile}" | grep -qE '[^/.]\.[[:alnum:]]+$'; then extension=".${kak_buffile##*.}" fi dir=$(mktemp -d "${TMPDIR:-/tmp}"/kak-lint.XXXXXXXX) mkfifo "$dir"/fifo printf '%s\n' "evaluate-commands -no-hooks write -sync $dir/buf${extension}" printf '%s\n' "evaluate-commands -draft %{ edit! -fifo $dir/fifo -debug *lint-output* set-option buffer filetype make set-option buffer make_current_error_line 0 hook -always -group fifo buffer BufCloseFifo .* %{ nop %sh{ rm -r '$dir' } remove-hooks buffer fifo } }" { # do the parsing in the background and when ready send to the session eval "$kak_opt_lintcmd '$dir'/buf${extension}" | sort -t: -k2,2 -n > "$dir"/stderr # Flags for the gutter: # stamp l3|{red}█ l11|{yellow}█ # Contextual error messages: # stamp 'l1.c1,l1.c1|kind:message' 'l2.c2,l2.c2|kind:message' awk -F: -v file="$kak_buffile" -v stamp="$kak_timestamp" -v client="$kak_client" ' BEGIN { error_count = 0 warning_count = 0 } /:[1-9][0-9]*:[1-9][0-9]*: ([Ff]atal )?[Ee]rror/ { flags = flags " " $2 "|{red}█" error_count++ } /:[1-9][0-9]*:[1-9][0-9]*:/ { if ($4 !~ /[Ee]rror/) { flags = flags " " $2 "|{yellow}█" warning_count++ } } /:[1-9][0-9]*:[1-9][0-9]*:/ { kind = substr($4, 2) error = $2 "." $3 "," $2 "." $3 "|" kind msg = "" # fix case where $5 is not the last field because of extra colons in the message for (i=5; i<=NF; i++) msg = msg ":" $i gsub(/\|/, "\\|", msg) gsub("'\''", "'"''"'", msg) error = error msg " (col " $3 ")" errors = errors " '\''" error "'\''" } END { print "set-option \"buffer=" file "\" lint_flags " stamp flags gsub("~", "\\~", errors) print "set-option \"buffer=" file "\" lint_errors " stamp errors print "set-option \"buffer=" file "\" lint_error_count " error_count print "set-option \"buffer=" file "\" lint_warning_count " warning_count print "evaluate-commands -client " client " lint-show-counters" } ' "$dir"/stderr | kak -p "$kak_session" cut -d: -f2- "$dir"/stderr | awk -v bufname="${kak_bufname}" ' /^[1-9][0-9]*:[1-9][0-9]*:/ { print bufname ":" $0 } ' > "$dir"/fifo } >/dev/null 2>&1