From 7217c7749e5403c9c7856c1d12c7986eb9c3b460 Mon Sep 17 00:00:00 2001 From: Yaroslav Date: Tue, 31 Mar 2020 17:52:49 +0300 Subject: Goodbye vim, been using neovim for ages now; home directory cleanup --- .../.local/share/nvim/site/contrib/highlight-log | 144 +++++++++++++++++++++ .../.local/share/nvim/site/contrib/run-tests-watch | 127 ++++++++++++++++++ dotfiles/.local/share/nvim/site/contrib/vim-checks | 123 ++++++++++++++++++ .../.local/share/nvim/site/contrib/vimhelplint | 46 +++++++ 4 files changed, 440 insertions(+) create mode 100755 dotfiles/.local/share/nvim/site/contrib/highlight-log create mode 100755 dotfiles/.local/share/nvim/site/contrib/run-tests-watch create mode 100755 dotfiles/.local/share/nvim/site/contrib/vim-checks create mode 100755 dotfiles/.local/share/nvim/site/contrib/vimhelplint (limited to 'dotfiles/.local/share/nvim/site/contrib') diff --git a/dotfiles/.local/share/nvim/site/contrib/highlight-log b/dotfiles/.local/share/nvim/site/contrib/highlight-log new file mode 100755 index 0000000..c4697fd --- /dev/null +++ b/dotfiles/.local/share/nvim/site/contrib/highlight-log @@ -0,0 +1,144 @@ +#!/usr/bin/env bash + +# This script adds color highlighting to the output from Neomake's Vader tests +# (when called with "vader"), or to the file that gets written into according +# to `neomake_logfile`. +# +# You can use the following to watch colored logs in a terminal window, after +# having used `let g:neomake_logfile = '/tmp/neomake.log'` in Neovim/Vim: +# +# tail -f /tmp/neomake.log | /path/to/neomake/contrib/highlight-log + +bold="" # $(tput bold) +bold_off="" +debug_color="" # $(tput dim), does not work in urxvt (although in infocmp/terminfo). +debug_color_off="" +color_off="" +log_color="" +log_color_off="$bold_off$color_off" +error_color="" +error_color_off="$bold_off$color_off" + +# compact: display test headers, but not inner output for successful ones. +compact=0 + +while [ $# -ne 0 ]; do + case $1 in + --compact) compact=1; shift ;; + --) shift; break ;; + -?*) echo "Unknown option: $1" 1>&2; exit 64 ;; + *) break ;; + esac +done + +if [ "$1" = vader ]; then + # Match non-log lines (i.e. keep output from :Log, which should cause + # all messages from a case to be visible). + # This should also ignore empty lines and lines starting with a character + # (e.g. via NVIM_LOG_FILE:=/dev/stderr, and from :echom). + re_log_line='^(.*( )? )(> .*)$' + re_ignore_log_line='^.*( )? > \[(debug |verbose|warning|error )|((D|V|W|E) +\+[.0-9]+)\]' + + colorize() { + # Only colorize if stdout is connected to a tty (not with :!make). + if ! [ -t 1 ]; then + cat - + return + fi + + # sed: add coloring to Vader's output: + # 1. failures (includes pending) in red "(X)" + # 2. test case header in bold "(2/2)" + # 3. Neomake's error log messages + # 4. Neomake's debug log messages + # 5. non-Neomake log lines (e.g. from :Log) + sed -E -e 's/^(([^ ].*)? +)\([ [:digit:]]+\/[[:digit:]]+\) \[[ [:alpha:]]+\] \(X\).*/'"$error_color"'\0'"$error_color_off"'/' \ + -e 's/^(([^ ].*)? +)(\([ [:digit:]]+\/[[:digit:]]+\))/\1'"$bold"'\3'"$bold_off"'/' \ + -e 's/^ +> \[(error |E +[.[:digit:]]+)\]: .*/'"$bold"'\0'"$bold_off"'/' \ + -e 's/^ +> \[(debug |D +[.[:digit:]]+)\]: .*/'"$debug_color"'\0'"$debug_color_off"'/' \ + -e '/'"$re_ignore_log_line"'/! s/'"$re_log_line"'/\1'"$log_color"'\3'"$log_color_off"'/' + } + + if ((compact)); then + # Do not display output for successful tests (i.e. the log statements). + last_start_match= + # Match Vader header ("( 1/33) [EXECUTE] …"), but also if there is output + # from Vim, e.g. with ":colder". + re_vader_header='^([^ ].*)?\ +(\(\ *[0-9]+/[0-9]+\))' + filtering=0 + finished_reading=0 + stopped_filtering=0 + while [ "$finished_reading" = 0 ]; do + if ! read -r; then + if [ -z "$REPLY" ]; then + break + finished_reading=1 + fi + fi + if [[ "$REPLY" == *'Vader error:'* ]] || [[ "$REPLY" == 'Error'* ]] || [[ "$REPLY" == 'Traceback'* ]]; then + printf "\r" >&2 + printf "%s\n" "$REPLY" + continue + fi + if (( stopped_filtering )); then + echo "$REPLY" + continue + fi + if [[ "$REPLY" == *'Starting Vader:'* ]]; then + echo "$REPLY" + elif [[ "$REPLY" == ' Duration: '* ]]; then + echo "$REPLY" + elif [[ "$REPLY" == *'(X)'* ]]; then + # Should also match "(1/1) [EXECUTE] (X) Error: Vim(function):E126: Missing :endfunction" already. + if [[ -n "$filtered" ]]; then + echo "$filtered" + fi + echo "$REPLY" + filtered= + filtering=0 + elif [[ "$REPLY" =~ $re_vader_header ]]; then + filtering=1 + if [[ ${BASH_REMATCH[2]} == "$last_start_match" ]]; then + filtered="$filtered"$'\n'"$REPLY" + else + echo "$REPLY" + filtered= + fi + last_start_match="${BASH_REMATCH[2]}" + elif [[ "$REPLY" == *'Success/Total: '* || "$REPLY" == ' Slowest tests:' ]]; then + echo "$REPLY" + filtering=0 + filtered= + stopped_filtering=1 + elif ! ((filtering)); then + echo "$REPLY" + elif [[ "$REPLY" =~ $re_log_line && ! "$REPLY" =~ $re_ignore_log_line ]]; then + if [[ "$REPLY" =~ '> SKIP:' ]]; then + echo "$REPLY" + continue + fi + if [[ -n "$filtered" ]]; then + echo "$filtered" + fi + echo "$REPLY" + filtered= + filtering=0 + elif [[ -n "$filtered" ]]; then + filtered="$filtered"$'\n'"$REPLY" + else + filtered="$REPLY" + fi + done + else + cat - + fi | colorize + +else + # Output from neomake_logfile. + error='^[:[:digit:]]\+ \[E .*' + warn='^[:[:digit:]]\+ \[W .*' + debug='^[:[:digit:]]\+ \[D .*' + sed -e "s/$error/\0/" \ + -e "s/$warn/w:\0/" \ + -e "s/$debug/$debug_color\\0$debug_color_off/" +fi diff --git a/dotfiles/.local/share/nvim/site/contrib/run-tests-watch b/dotfiles/.local/share/nvim/site/contrib/run-tests-watch new file mode 100755 index 0000000..11edbdf --- /dev/null +++ b/dotfiles/.local/share/nvim/site/contrib/run-tests-watch @@ -0,0 +1,127 @@ +#!/bin/sh -x +# +# Wrapper around inotifywait to run tests on file changes. +# If a test file changes, only this file is run (first), while the whole test +# suite is run afterwards (and initially). +# +# The recommended way to run it is via `make testwatch`, or `make testwatchx` +# (to exit on first failure). +# +# # Internal documentation: +# The default run command is "make %s" (where %s gets replaced with the test +# file(s)), and can be given as first argument. +# +# You can specify VADER_OPTIONS=-x to exit on the first test failure: +# VADER_OPTIONS=-x contrib/run-tests-watch +# or use the following: +# contrib/run-tests-watch 'make %s VADER_OPTIONS=-x' +# +# VADER_ARGS gets used to focus on a specific test file initially, until +# another test file gets changed. + +watch="autoload plugin tests" +echo "Watching: $watch" + +if [ -n "$1" ]; then + cmdpattern="$1" +else + cmdpattern="make %s VADER_OPTIONS='$VADER_OPTIONS'" +fi + +title() { + printf '\e]1;%s\a' "$*" + printf '\e]2;%s\a' "$*" +} + +status_file=$(mktemp) +handle_cmd_result() { + if [ "$1" = 0 ]; then + last_test_succeeded=1 + title "✔ $2" + if [ "${2#*${alltestsfile}*}" != "$2" ]; then + alltests_succeeded=1 + fi + else + last_test_succeeded=0 + title "✘ $2" + if [ "${2#*${alltestsfile}*}" != "$2" ]; then + alltests_succeeded=0 + fi + fi + echo "$last_test_succeeded $alltests_succeeded" > "$status_file" +} + +# Recursively kill childs - required to get out of a running pdb. +kill_with_childs() { + for p in $(pgrep -P "$1"); do + kill_with_childs "$p" + done + if kill -0 "$1" 2>/dev/null; then + kill "$1" || true + fi +} + +alltestsfile='tests/all.vader' +alltests_succeeded=0 +pid= +changed_files= +set -e +last_changed_testsfile="${VADER_ARGS:-$alltestsfile}" + +while true; do + testfiles="$last_changed_testsfile" + if [ -n "$changed_files" ]; then + # There was a previous run + echo "=================================================================" + echo "changed file: $changed_files" + + read -r last_test_succeeded alltests_succeeded < "$status_file" || alltests_succeeded=0 + + if [ "${changed_files#tests/}" != "$changed_files" ] \ + && [ "${changed_files#tests/include/}" = "$changed_files" ]; then + # A test file was changed (but not an include file). + last_changed_testsfile="$changed_files" + testfiles="$last_changed_testsfile" + + # Run full tests afterwards (if not successful before). + if [ "$testfiles" != "$alltestsfile" ] && [ "$alltests_succeeded" = 0 ]; then + testfiles="$testfiles $alltestsfile" + fi + + elif [ "$last_test_succeeded" = 1 ]; then + # Run all tests. + alltests_succeeded=0 + testfiles="$alltestsfile" + + if [ "${VADER_OPTIONS#*-x*}" != "$VADER_OPTIONS" ]; then + # Run tests matching the changed file first, e.g. tests/config.vader for + # autoload/neomake/config.vim. + test_file_for_changed_file="tests/${changed_files#autoload/neomake/}" + test_file_for_changed_file="${test_file_for_changed_file%.vim}.vader" + declare -p test_file_for_changed_file + if [ -f "$test_file_for_changed_file" ]; then + testfiles="$test_file_for_changed_file $testfiles" + fi + fi + fi + + if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then + echo 'Killing previous run…' + kill_with_childs "$pid" + fi + fi + + # shellcheck disable=SC2059 + cmd="$(printf "$cmdpattern" "$testfiles")" + echo "Running $cmd" + title "… $testfiles" + # shellcheck disable=SC2015 + (set +e; eval "$cmd"; handle_cmd_result "$?" "$testfiles") +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +RETURN_CODE=0 + +function print_help() { + echo "Usage: ./custom-checks FILE|DIRECTORY…" 1>&2 + echo 1>&2 + echo " -h, --help Print this help text" 1>&2 + exit 1 +} + +while [ $# -ne 0 ]; do + case $1 in + -h) ;& --help) + print_help + ;; + --) + shift + break + ;; + -?*) + echo "Invalid argument: $1" 1>&2 + exit 1 + ;; + *) + break + ;; + esac +done + +if [ $# -eq 0 ] || [ -z "$1" ]; then + print_help +fi + +shopt -s globstar + +args=("$@") + +expand_arg() { + if [[ -d $arg ]]; then + expanded_arg=("$arg"/**/*.vim) + else + expanded_arg=("$arg") + fi +} + +check_errors() { + regex="$1"; shift + message="$1"; shift + + for arg in "${args[@]}"; do + expand_arg "$arg" + # Ensure that errors from grep are not ignored, i.e. busybox's grep + # does not have "--with-filename". + set +e + output="$(grep "$@" --with-filename -n "$regex" "${expanded_arg[@]}" 2>&1)" + ret=$? + set -e + if (( ret > 1 )); then + echo "$output" + RETURN_CODE=2 + continue + fi + if [[ -z "$output" ]]; then + continue + fi + + while IFS= read -r match; do + RETURN_CODE=1 + echo "$match $message" + done < <(echo "$output" \ + | grep -o '^[^:]\+\(:[0-9]\+\)\?:' \ + | sed 's:^\./::') + done +} + +check_errors \ + '^\s*function.*) *$' \ + 'Function without abort keyword (See :help except-compat)' +check_errors ' \+$' 'Trailing whitespace' +check_errors '^ * end\?i\? *$' 'Write endif, not en, end, or endi' +check_errors '^(( )*([^ ]|$)|\s+\\)' 'Use four spaces for indentation' -v -E +check_errors $'\t' 'Do not use tabs for indentation' +check_errors '^\s*[^" ].*[^&]l:[a-z]' 'Do not use l: prefix for local variables' +for arg in "${args[@]}"; do + expand_arg "$arg" + grep --files-without-match '^"[ ]vim: ts=4 sw=4 et' "${expanded_arg[@]}" \ + | while read -r f; do + echo "$f:$(( $(wc -l "$f" | cut -f1 -d\ ) + 1)): Missing modeline" + done +done + +exit $RETURN_CODE diff --git a/dotfiles/.local/share/nvim/site/contrib/vimhelplint b/dotfiles/.local/share/nvim/site/contrib/vimhelplint new file mode 100755 index 0000000..3a87e2c --- /dev/null +++ b/dotfiles/.local/share/nvim/site/contrib/vimhelplint @@ -0,0 +1,46 @@ +#!/bin/sh +# A wrapper around vim-vimhelp (https://github.com/machakann/vim-vimhelplint). +# +# This file is automatically used by autoload/neomake/makers/ft/help.vim, if +# vimhelplint is installed in Neomake's build dir (and `vimhelplint` is not +# found as an executable). +# +# You can run `make build/vimhelplint` (from Neomake's root) to +# download/install it into Neomake's build dir, and Neomake will use this for +# help files then. + +if [ -z "$VIMHELPLINT_DIR" ]; then + # Change to parent dir (not POSIXly, but resolving symlinks). + CDPATH='' cd -P -- "$(dirname -- "$(readlink -f -- "$0" 2>/dev/null || echo "$0")")/.." || exit + VIMHELPLINT_DIR=$PWD/build/vimhelplint + cd - >/dev/null || exit +fi +vimhelplint=${VIMHELPLINT_DIR}/ftplugin/help_lint.vim + +if ! [ -f "$vimhelplint" ]; then + echo "$vimhelplint not found." >&2 + echo "Run 'make build/vimhelplint' Neomake's root directory to install it." >&2 + exit 64 +fi + +file="$1" +if [ -z "$file" ]; then + echo 'No input file specified.' >&2 + exit 64 +fi +if ! [ -e "$file" ]; then + echo "File $file is not readable." >&2 + exit 1 +fi + +out=$(${VIMHELPLINT_VIM:-vim} -esN -u NONE -i NONE \ + -c "silent edit $1" \ + -c 'set ft=help' \ + -c "source $vimhelplint" \ + -c 'verb VimhelpLintEcho' \ + -c 'qall!' 2>&1) +if [ -z "$out" ]; then + exit 0 +fi +echo "$out" +exit 1 -- cgit v1.2.3