2026-07-27 01:59:29 +02:00
|
|
|
#!/bin/bash
|
|
|
|
|
#
|
|
|
|
|
# editor_test.sh — Regression tests for the Klammertext editor support
|
2026-07-27 15:01:49 +02:00
|
|
|
# (doc/edit/: the shared Python core, the language server, and the Emacs,
|
|
|
|
|
# Sublime Text, Vim, and VS Code integrations built on them).
|
2026-07-27 01:59:29 +02:00
|
|
|
#
|
|
|
|
|
# Why this lives in tst/: the editor code implements the LANGUAGE's structural
|
|
|
|
|
# layer — @-run length, bar-run dimension, ^-escapes, # removal, literal
|
|
|
|
|
# spans, nesting depth — independently of both the SKS and the Klammermachine.
|
|
|
|
|
# tst/ is the SKS-independent tier, and these suites check that the
|
2026-07-27 15:01:49 +02:00
|
|
|
# implementations of Klammertext's structure agree with the canonical
|
|
|
|
|
# formatting conventions AND with each other. The klammer names that appear
|
2026-08-23 20:48:26 +02:00
|
|
|
# in the fixtures (@ol, @table, @document, @code, @c) are seeded configuration of
|
2026-07-27 15:01:49 +02:00
|
|
|
# the editor tools, not SKS dependencies; nothing here runs ktext or loads a
|
|
|
|
|
# klammer set.
|
2026-07-27 01:59:29 +02:00
|
|
|
#
|
|
|
|
|
# What is checked, for every fixture pair <name>.kt / <name>_expected.kt in
|
|
|
|
|
# tst/editor/:
|
2026-07-27 15:01:49 +02:00
|
|
|
# * the shared core's output equals the expected file — through the Python
|
|
|
|
|
# API (what Sublime uses) AND through the core's CLI (what Vim uses)
|
2026-07-27 01:59:29 +02:00
|
|
|
# * idempotence: the tool applied to the expected file leaves it unchanged
|
2026-07-27 15:01:49 +02:00
|
|
|
# * the three Sublime adapter plugins import outside Sublime and resolve
|
|
|
|
|
# to the shared core
|
|
|
|
|
# * the language server passes its protocol test (tst/editor/ls_test.py:
|
|
|
|
|
# handshake, diagnostics, formatting, matching, alignTable — the VS Code
|
|
|
|
|
# extension's whole surface)
|
|
|
|
|
# * when Emacs is installed: the Emacs units' output equals the expected
|
|
|
|
|
# file, and equals the shared core's output byte for byte (the sync
|
|
|
|
|
# check across the independent elisp implementation) — skipped otherwise
|
|
|
|
|
# * when a Vim with +eval is installed: the Vim plugin's commands produce
|
|
|
|
|
# the same bytes (exercising the CLI shell-out glue) — skipped otherwise
|
2026-07-27 01:59:29 +02:00
|
|
|
#
|
2026-07-27 15:01:49 +02:00
|
|
|
# The editor code lives in doc/edit/ (same layout in the development tree and
|
|
|
|
|
# the distribution).
|
2026-07-27 01:59:29 +02:00
|
|
|
#
|
2026-07-27 15:01:49 +02:00
|
|
|
# Usage: ./editor_test.sh Requires python3; Emacs and Vim optional.
|
2026-07-27 01:59:29 +02:00
|
|
|
# Exit code: 0 if all tests pass, 1 otherwise.
|
|
|
|
|
|
|
|
|
|
PASS=0
|
|
|
|
|
FAIL=0
|
|
|
|
|
|
|
|
|
|
red=$'\033[31m'
|
|
|
|
|
green=$'\033[32m'
|
|
|
|
|
bold=$'\033[1m'
|
|
|
|
|
reset=$'\033[0m'
|
|
|
|
|
|
|
|
|
|
HERE="$(cd "$(dirname "$0")" && pwd)"
|
|
|
|
|
ROOT="$(cd "$HERE/.." && pwd)"
|
2026-07-27 15:01:49 +02:00
|
|
|
EDIT_DIR="$ROOT/doc/edit"
|
|
|
|
|
if [ ! -d "$EDIT_DIR/emacs" ]; then
|
|
|
|
|
echo "editor_test.sh: cannot locate the editor support (doc/edit)" >&2
|
2026-07-27 01:59:29 +02:00
|
|
|
exit 1
|
|
|
|
|
fi
|
2026-07-27 15:01:49 +02:00
|
|
|
EMACS_DIR="$EDIT_DIR/emacs"
|
|
|
|
|
SUBLIME_DIR="$EDIT_DIR/sublime"
|
|
|
|
|
SHARED_DIR="$EDIT_DIR/shared"
|
|
|
|
|
VIM_DIR="$EDIT_DIR/vim"
|
2026-07-27 01:59:29 +02:00
|
|
|
FIX="$HERE/editor"
|
|
|
|
|
OUT="$(mktemp -d)"
|
|
|
|
|
trap 'rm -rf "$OUT"' EXIT
|
|
|
|
|
|
2026-09-25 18:43:22 +02:00
|
|
|
# A path written INSIDE a Python string must be one the interpreter can open.
|
|
|
|
|
# Under MSYS2 the shell's /c/... form is converted only for standalone
|
|
|
|
|
# arguments to a native program, never inside a string, so those get the
|
|
|
|
|
# Windows form (forward slashes; a backslash in a Python literal is an escape).
|
|
|
|
|
native() {
|
|
|
|
|
if command -v cygpath >/dev/null 2>&1; then cygpath -m "$1"; else printf '%s' "$1"; fi
|
|
|
|
|
}
|
|
|
|
|
SHARED_NATIVE="$(native "$SHARED_DIR")"
|
|
|
|
|
SUBLIME_NATIVE="$(native "$SUBLIME_DIR")"
|
|
|
|
|
OUT_NATIVE="$(native "$OUT")"
|
|
|
|
|
|
2026-07-27 01:59:29 +02:00
|
|
|
INDENT_FIXTURES="indent_list indent_document indent_table indent_untouched
|
2026-08-23 20:48:26 +02:00
|
|
|
indent_defs indent_escapes indent_named_close indent_literal_c"
|
2026-07-27 01:59:29 +02:00
|
|
|
ALIGN_FIXTURES="align_mixed align_empty_cells align_boundary align_colspan
|
|
|
|
|
align_escapes align_too_wide"
|
|
|
|
|
|
|
|
|
|
# Build the (MODE INFILE OUTFILE) triples: each fixture is run from its input
|
|
|
|
|
# and from its expected file (the idempotence check).
|
|
|
|
|
py_args=()
|
|
|
|
|
el_args=()
|
|
|
|
|
add_fixture() { # add_fixture MODE NAME
|
|
|
|
|
local mode="$1" name="$2"
|
2026-07-27 15:01:49 +02:00
|
|
|
py_args+=("$mode" "$FIX/$name.kt" "$OUT/$name.py.out")
|
|
|
|
|
py_args+=("$mode" "$FIX/${name}_expected.kt" "$OUT/$name.py.idem")
|
|
|
|
|
py_args+=("$mode-cli" "$FIX/$name.kt" "$OUT/$name.cli.out")
|
|
|
|
|
el_args+=("$mode" "$FIX/$name.kt" "$OUT/$name.el.out")
|
|
|
|
|
el_args+=("$mode" "$FIX/${name}_expected.kt" "$OUT/$name.el.idem")
|
2026-07-27 01:59:29 +02:00
|
|
|
}
|
|
|
|
|
for f in $INDENT_FIXTURES; do add_fixture indent "$f"; done
|
|
|
|
|
for f in $ALIGN_FIXTURES; do add_fixture align "$f"; done
|
|
|
|
|
|
2026-07-27 15:01:49 +02:00
|
|
|
check() { # check NAME FILE_A FILE_B
|
|
|
|
|
if diff -q "$2" "$3" >/dev/null 2>&1; then
|
|
|
|
|
echo "${green}PASS${reset} $1"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo "${red}FAIL${reset} $1"
|
|
|
|
|
diff "$2" "$3" | head -10
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# --- the shared core: API and CLI (required) -------------------------------
|
2026-09-25 00:32:55 +02:00
|
|
|
# The interpreter's name: python3 on Linux and macOS; on Windows python.org
|
|
|
|
|
# installs "python" only, and env/runtime.env exports PYTHON there.
|
|
|
|
|
PYTHON=${PYTHON:-python3}
|
|
|
|
|
if ! command -v "$PYTHON" >/dev/null 2>&1; then
|
|
|
|
|
echo "editor_test.sh: $PYTHON not found" >&2
|
2026-07-27 01:59:29 +02:00
|
|
|
exit 1
|
|
|
|
|
fi
|
2026-09-25 00:32:55 +02:00
|
|
|
if ! PYTHONDONTWRITEBYTECODE=1 "$PYTHON" "$FIX/editor_driver.py" "$SHARED_DIR" "${py_args[@]}"; then
|
2026-07-27 01:59:29 +02:00
|
|
|
echo "editor_test.sh: the Python driver failed" >&2
|
|
|
|
|
exit 1
|
|
|
|
|
fi
|
|
|
|
|
|
2026-07-27 15:01:49 +02:00
|
|
|
# --- the Sublime adapters resolve to the shared core -----------------------
|
2026-09-25 00:32:55 +02:00
|
|
|
if PYTHONDONTWRITEBYTECODE=1 "$PYTHON" -c "
|
2026-09-25 18:43:22 +02:00
|
|
|
import os, sys
|
|
|
|
|
sys.path.insert(0, '$SUBLIME_NATIVE')
|
2026-07-27 15:01:49 +02:00
|
|
|
import Klammertext, Klammertext_indent, Klammertext_align
|
2026-09-25 18:43:22 +02:00
|
|
|
assert os.path.normpath(Klammertext.KE.__file__).startswith(os.path.normpath('$SHARED_NATIVE'))
|
2026-07-27 15:01:49 +02:00
|
|
|
" 2>"$OUT/sublime.log"; then
|
|
|
|
|
echo "${green}PASS${reset} sublime adapters import the shared core"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo "${red}FAIL${reset} sublime adapters import the shared core"
|
|
|
|
|
cat "$OUT/sublime.log"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
|
2026-09-25 18:43:22 +02:00
|
|
|
# --- the Notepad++ UDL: well-formed, and it restates the literal klammer -----
|
|
|
|
|
# (a static artifact of the SYNC set; nothing else can check it)
|
|
|
|
|
if PYTHONDONTWRITEBYTECODE=1 "$PYTHON" -c "
|
|
|
|
|
import sys, xml.etree.ElementTree as ET
|
|
|
|
|
u = ET.parse('$(native "$EDIT_DIR")/notepadpp/Klammertext.udl.xml').getroot().find('UserLang')
|
|
|
|
|
assert u.get('name') == 'Klammertext' and set(u.get('ext').split()) == {'kt', 'k'}, u.attrib
|
|
|
|
|
lists = {k.get('name'): (k.text or '') for k in u.find('KeywordLists')}
|
|
|
|
|
assert '00@code' in lists['Delimiters'].split() and '02code@' in lists['Delimiters'].split(), lists['Delimiters']
|
|
|
|
|
assert lists['Keywords1'].strip() == '@@@' and lists['Keywords2'].strip() == '@@' and lists['Keywords3'].strip() == '@'
|
|
|
|
|
assert '03#[' in lists['Comments'].split() and '04]#' in lists['Comments'].split()
|
|
|
|
|
" 2>"$OUT/udl.log"; then
|
|
|
|
|
echo "${green}PASS${reset} notepad++ UDL is well-formed and restates the literal klammer"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo "${red}FAIL${reset} notepad++ UDL is well-formed and restates the literal klammer"
|
|
|
|
|
cat "$OUT/udl.log"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
|
2026-07-27 15:01:49 +02:00
|
|
|
# --- the language server protocol test -------------------------------------
|
2026-09-25 00:32:55 +02:00
|
|
|
if PYTHONDONTWRITEBYTECODE=1 "$PYTHON" "$FIX/ls_test.py" "$SHARED_DIR" "$FIX" >"$OUT/ls.log" 2>&1; then
|
2026-07-27 15:01:49 +02:00
|
|
|
echo "${green}PASS${reset} language server protocol ($(grep -c '^PASS' "$OUT/ls.log") checks)"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo "${red}FAIL${reset} language server protocol:"
|
|
|
|
|
cat "$OUT/ls.log"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
|
2026-09-07 22:37:05 +02:00
|
|
|
# run_bounded SECONDS CMD... -- run CMD with a wall-clock limit, returning
|
|
|
|
|
# 137 if it had to be killed. An external editor that is INSTALLED BUT
|
|
|
|
|
# NON-FUNCTIONAL is not hypothetical: Olion's Homebrew emacs blocks forever
|
|
|
|
|
# on "emacs --batch" with no CPU used, and because this suite had no bound it
|
|
|
|
|
# sat for 2h43m producing nothing (2026-09-05). A hang is worse than a
|
|
|
|
|
# failure -- it is indistinguishable from slowness, so nobody investigates.
|
|
|
|
|
#
|
|
|
|
|
# No "timeout(1)": macOS does not have it (nor gtimeout without coreutils),
|
|
|
|
|
# and this suite ships. Background the command, race a killer against it.
|
|
|
|
|
# "set -m" makes the job its own PROCESS GROUP so the whole group can be
|
|
|
|
|
# killed. Killing only the pid leaves the children: a hung editor's orphaned
|
|
|
|
|
# child still holds the inherited stdout, and anything reading this suite
|
|
|
|
|
# through a pipe then blocks anyway -- the timeout fires and the hang
|
|
|
|
|
# continues, which is the worst of both. Measured while writing this.
|
|
|
|
|
run_bounded() {
|
|
|
|
|
local secs="$1"; shift
|
|
|
|
|
set -m
|
|
|
|
|
"$@" & local pid=$!
|
|
|
|
|
set +m
|
|
|
|
|
( sleep "$secs"; kill -9 -"$pid" 2>/dev/null || kill -9 "$pid" 2>/dev/null ) \
|
|
|
|
|
>/dev/null 2>&1 & local killer=$!
|
|
|
|
|
wait "$pid" 2>/dev/null; local st=$?
|
|
|
|
|
kill "$killer" 2>/dev/null; wait "$killer" 2>/dev/null
|
|
|
|
|
return $st
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
EDITOR_TIMEOUT=${EDITOR_TIMEOUT:-120}
|
|
|
|
|
|
2026-07-27 15:01:49 +02:00
|
|
|
# --- the Emacs units (optional) --------------------------------------------
|
2026-07-27 01:59:29 +02:00
|
|
|
HAVE_EMACS=0
|
|
|
|
|
if command -v emacs >/dev/null 2>&1; then
|
2026-09-07 22:37:05 +02:00
|
|
|
run_bounded "$EDITOR_TIMEOUT" \
|
|
|
|
|
emacs --batch -L "$EMACS_DIR" \
|
2026-07-27 01:59:29 +02:00
|
|
|
-l klammertext-mode -l klammertext-indent -l klammertext-align \
|
2026-09-07 22:37:05 +02:00
|
|
|
-l "$FIX/editor_driver.el" "${el_args[@]}" 2>"$OUT/emacs.log"
|
|
|
|
|
emacs_status=$?
|
|
|
|
|
if [ "$emacs_status" = 0 ]; then
|
2026-07-27 01:59:29 +02:00
|
|
|
HAVE_EMACS=1
|
2026-09-07 22:37:05 +02:00
|
|
|
elif [ "$emacs_status" = 137 ]; then
|
|
|
|
|
# Distinguished from a failure on purpose: "it hung" and "it said no"
|
|
|
|
|
# need different investigations, and only one of them is about
|
|
|
|
|
# Klammertext.
|
|
|
|
|
echo "${red}FAIL${reset} the Emacs driver did not finish within" \
|
|
|
|
|
"${EDITOR_TIMEOUT}s and was killed (emacs is installed but not" \
|
|
|
|
|
"working on this machine)" >&2
|
|
|
|
|
FAIL=$((FAIL + 1))
|
2026-07-27 01:59:29 +02:00
|
|
|
else
|
|
|
|
|
echo "${red}FAIL${reset} the Emacs driver failed:" >&2
|
|
|
|
|
cat "$OUT/emacs.log" >&2
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
else
|
2026-07-27 15:01:49 +02:00
|
|
|
echo "(Emacs not installed — the Emacs half is skipped; the shared core still runs)"
|
2026-07-27 01:59:29 +02:00
|
|
|
fi
|
|
|
|
|
|
2026-07-27 15:01:49 +02:00
|
|
|
# --- the Vim plugin (optional) ---------------------------------------------
|
|
|
|
|
HAVE_VIM=0
|
|
|
|
|
VIM_BIN="$(command -v vim || true)"
|
|
|
|
|
if [ -n "$VIM_BIN" ] && "$VIM_BIN" --version 2>/dev/null | grep -q '+eval'; then
|
|
|
|
|
HAVE_VIM=1
|
|
|
|
|
run_vim() { # run_vim MODE INFILE OUTFILE
|
|
|
|
|
local cmd
|
|
|
|
|
if [ "$1" = indent ]; then
|
|
|
|
|
cmd='KlammertextReindent'
|
|
|
|
|
else
|
|
|
|
|
cmd='call search("|") | KlammertextAlign'
|
|
|
|
|
fi
|
|
|
|
|
"$VIM_BIN" -N -n -u NONE -i NONE -es --not-a-term \
|
|
|
|
|
--cmd "set rtp^=$VIM_DIR" \
|
|
|
|
|
-c 'filetype plugin on' \
|
|
|
|
|
-c "edit! $2" -c 'set ft=klammertext' \
|
|
|
|
|
-c "$cmd" -c "saveas! $3" -c 'qa!' </dev/null >/dev/null 2>&1
|
|
|
|
|
}
|
|
|
|
|
for f in $INDENT_FIXTURES; do
|
|
|
|
|
run_vim indent "$FIX/$f.kt" "$OUT/$f.vim.out"
|
|
|
|
|
run_vim indent "$FIX/${f}_expected.kt" "$OUT/$f.vim.idem"
|
|
|
|
|
done
|
|
|
|
|
for f in $ALIGN_FIXTURES; do
|
|
|
|
|
run_vim align "$FIX/$f.kt" "$OUT/$f.vim.out"
|
|
|
|
|
run_vim align "$FIX/${f}_expected.kt" "$OUT/$f.vim.idem"
|
|
|
|
|
done
|
|
|
|
|
# The comprehensive plugin checks: ftdetect (Kotlin override), syntax
|
|
|
|
|
# token classes, jump-to-match (incl. multibyte columns), the location-
|
|
|
|
|
# list check, and — with +python3 — indentexpr (gg=G) and the live
|
|
|
|
|
# match highlighter. Sections skip inside the driver per Vim feature.
|
|
|
|
|
if KT_FIX="$FIX" KT_OUT="$OUT/vim_feature.txt" \
|
|
|
|
|
"$VIM_BIN" -N -n -u NONE -i NONE -es --not-a-term \
|
|
|
|
|
--cmd "set rtp^=$VIM_DIR" \
|
|
|
|
|
-c "source $FIX/vim_feature_test.vim" </dev/null >/dev/null 2>&1; then
|
|
|
|
|
echo "${green}PASS${reset} vim plugin features ($(grep -c '^PASS' "$OUT/vim_feature.txt") checks$(
|
|
|
|
|
grep -q '^SKIP' "$OUT/vim_feature.txt" && printf '; %s' "$(grep -c '^SKIP' "$OUT/vim_feature.txt") section(s) skipped"))"
|
2026-07-27 01:59:29 +02:00
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
2026-07-27 15:01:49 +02:00
|
|
|
echo "${red}FAIL${reset} vim plugin features:"
|
|
|
|
|
grep -v '^PASS' "$OUT/vim_feature.txt" 2>/dev/null || echo " (the Vim driver itself failed)"
|
2026-07-27 01:59:29 +02:00
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
2026-07-27 15:01:49 +02:00
|
|
|
else
|
|
|
|
|
echo "(no Vim with +eval installed — the Vim half is skipped; the shared core still runs)"
|
|
|
|
|
fi
|
|
|
|
|
|
|
|
|
|
# --- the VS Code extension (optional: needs a Node runtime) ----------------
|
2026-09-25 18:43:22 +02:00
|
|
|
# node itself, or VS Code's Electron binary run as Node, wherever an
|
|
|
|
|
# installed VS Code keeps it: the Linux package, the macOS app bundle, the
|
|
|
|
|
# Windows per-user install (LOCALAPPDATA is a Windows variable, so the shell
|
|
|
|
|
# is MSYS2 there and cygpath exists).
|
|
|
|
|
CODE_BIN=""
|
|
|
|
|
if [ -x /usr/share/code/code ]; then
|
|
|
|
|
CODE_BIN=/usr/share/code/code
|
|
|
|
|
elif [ -x "/Applications/Visual Studio Code.app/Contents/MacOS/Electron" ]; then
|
|
|
|
|
CODE_BIN="/Applications/Visual Studio Code.app/Contents/MacOS/Electron"
|
|
|
|
|
elif [ -n "$LOCALAPPDATA" ] && command -v cygpath >/dev/null 2>&1; then
|
|
|
|
|
c="$(cygpath -u "$LOCALAPPDATA")/Programs/Microsoft VS Code/Code.exe"
|
|
|
|
|
[ -x "$c" ] && CODE_BIN="$c"
|
|
|
|
|
fi
|
2026-07-27 15:01:49 +02:00
|
|
|
run_node() {
|
|
|
|
|
if command -v node >/dev/null 2>&1; then
|
|
|
|
|
node "$@"
|
2026-09-25 18:43:22 +02:00
|
|
|
elif [ -n "$CODE_BIN" ]; then
|
|
|
|
|
ELECTRON_RUN_AS_NODE=1 "$CODE_BIN" "$@"
|
2026-07-27 15:01:49 +02:00
|
|
|
else
|
|
|
|
|
return 127
|
|
|
|
|
fi
|
2026-07-27 01:59:29 +02:00
|
|
|
}
|
2026-09-25 18:43:22 +02:00
|
|
|
if command -v node >/dev/null 2>&1 || [ -n "$CODE_BIN" ]; then
|
2026-07-27 15:01:49 +02:00
|
|
|
if run_node "$FIX/vscode_ext_test.js" "$EDIT_DIR/vscode" "$FIX" >"$OUT/vscode.log" 2>&1; then
|
|
|
|
|
echo "${green}PASS${reset} vscode extension ($(grep -c '^PASS' "$OUT/vscode.log") checks)"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo "${red}FAIL${reset} vscode extension:"
|
|
|
|
|
cat "$OUT/vscode.log"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
else
|
|
|
|
|
echo "(no Node runtime — the VS Code extension test is skipped; the language server is still tested)"
|
|
|
|
|
fi
|
2026-07-27 01:59:29 +02:00
|
|
|
|
2026-07-27 15:14:57 +02:00
|
|
|
# --- the VS Code .vsix package builds with the full payload ----------------
|
|
|
|
|
# (the no-marketplace install path; needs only bash + python3)
|
|
|
|
|
mkdir -p "$OUT/vsix"
|
|
|
|
|
cp -R "$EDIT_DIR/vscode" "$EDIT_DIR/shared" "$OUT/vsix/"
|
|
|
|
|
if ( cd "$OUT/vsix/vscode" && ./make_vsix.sh >/dev/null 2>&1 ) && \
|
2026-09-25 00:32:55 +02:00
|
|
|
PYTHONDONTWRITEBYTECODE=1 "$PYTHON" -c "
|
2026-07-27 15:14:57 +02:00
|
|
|
import sys, zipfile
|
2026-09-25 18:43:22 +02:00
|
|
|
names = set(zipfile.ZipFile('$OUT_NATIVE/vsix/vscode/klammertext.vsix').namelist())
|
2026-07-27 15:14:57 +02:00
|
|
|
need = {'extension.vsixmanifest', '[Content_Types].xml',
|
|
|
|
|
'extension/package.json', 'extension/extension.js',
|
|
|
|
|
'extension/language-configuration.json', 'extension/README.md',
|
|
|
|
|
'extension/klammertext_edit.py', 'extension/klammertext_ls.py',
|
|
|
|
|
'extension/syntaxes/klammertext.tmLanguage.json'}
|
|
|
|
|
sys.exit(1 if need - names else 0)
|
|
|
|
|
"; then
|
|
|
|
|
echo "${green}PASS${reset} vscode .vsix package builds (make_vsix.sh)"
|
|
|
|
|
PASS=$((PASS + 1))
|
|
|
|
|
else
|
|
|
|
|
echo "${red}FAIL${reset} vscode .vsix package builds (make_vsix.sh)"
|
|
|
|
|
FAIL=$((FAIL + 1))
|
|
|
|
|
fi
|
|
|
|
|
|
2026-07-27 15:01:49 +02:00
|
|
|
# --- compare ---------------------------------------------------------------
|
2026-07-27 01:59:29 +02:00
|
|
|
for f in $INDENT_FIXTURES $ALIGN_FIXTURES; do
|
|
|
|
|
check "$f (python)" "$OUT/$f.py.out" "$FIX/${f}_expected.kt"
|
|
|
|
|
check "$f (python idempotent)" "$OUT/$f.py.idem" "$FIX/${f}_expected.kt"
|
2026-07-27 15:01:49 +02:00
|
|
|
check "$f (cli)" "$OUT/$f.cli.out" "$FIX/${f}_expected.kt"
|
2026-07-27 01:59:29 +02:00
|
|
|
if [ "$HAVE_EMACS" = 1 ]; then
|
|
|
|
|
check "$f (emacs)" "$OUT/$f.el.out" "$FIX/${f}_expected.kt"
|
|
|
|
|
check "$f (emacs idempotent)" "$OUT/$f.el.idem" "$FIX/${f}_expected.kt"
|
|
|
|
|
check "$f (emacs == python)" "$OUT/$f.el.out" "$OUT/$f.py.out"
|
|
|
|
|
fi
|
2026-07-27 15:01:49 +02:00
|
|
|
if [ "$HAVE_VIM" = 1 ]; then
|
|
|
|
|
check "$f (vim)" "$OUT/$f.vim.out" "$FIX/${f}_expected.kt"
|
|
|
|
|
check "$f (vim idempotent)" "$OUT/$f.vim.idem" "$FIX/${f}_expected.kt"
|
|
|
|
|
fi
|
2026-07-27 01:59:29 +02:00
|
|
|
done
|
|
|
|
|
|
|
|
|
|
echo
|
|
|
|
|
echo "${bold}editor_test: $PASS passed, $FAIL failed${reset}"
|
|
|
|
|
[ "$FAIL" -eq 0 ]
|