Editor test suite ships in tst/ (from dev 4e8c3db2882d)
This commit is contained in:
@@ -1,10 +1,12 @@
|
||||
# Klammertext distribution test suite (subset).
|
||||
#
|
||||
# Runs the four shell regression suites:
|
||||
# Runs the five shell regression suites:
|
||||
# cond_test.sh — @cond argument delimitation
|
||||
# deftype_test.sh — the four klammer definition modes + redefinition table
|
||||
# escape_test.sh — target character escaping and quoted specials
|
||||
# filename_test.sh — filenames with spaces (quoting, " / " lists, rescue)
|
||||
# editor_test.sh — editor support (doc/edit): indentation and table
|
||||
# alignment; needs python3, uses Emacs when installed
|
||||
#
|
||||
# Requires KLAMMERTEXT_HOME set and `ktext` on PATH (build it with `make -C com`).
|
||||
|
||||
@@ -14,3 +16,4 @@ test:
|
||||
./deftype_test.sh
|
||||
./escape_test.sh
|
||||
./filename_test.sh
|
||||
./editor_test.sh
|
||||
|
||||
5
tst/editor/align_boundary.kt
Normal file
5
tst/editor/align_boundary.kt
Normal file
@@ -0,0 +1,5 @@
|
||||
@table
|
||||
123456789012345678901234567890 | x ||
|
||||
abcdefghijklmnopqrstuvwxyzabcde | y ||
|
||||
short | z ||
|
||||
@
|
||||
5
tst/editor/align_boundary_expected.kt
Normal file
5
tst/editor/align_boundary_expected.kt
Normal file
@@ -0,0 +1,5 @@
|
||||
@table
|
||||
123456789012345678901234567890 | x ||
|
||||
abcdefghijklmnopqrstuvwxyzabcde | y ||
|
||||
short | z ||
|
||||
@
|
||||
4
tst/editor/align_colspan.kt
Normal file
4
tst/editor/align_colspan.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
@table
|
||||
one | two | three ||
|
||||
spanning | wide ||
|
||||
@
|
||||
4
tst/editor/align_colspan_expected.kt
Normal file
4
tst/editor/align_colspan_expected.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
@table
|
||||
one | two | three ||
|
||||
spanning | wide ||
|
||||
@
|
||||
4
tst/editor/align_empty_cells.kt
Normal file
4
tst/editor/align_empty_cells.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
@table
|
||||
a | | b ||
|
||||
cc | dd | ee ||
|
||||
@
|
||||
4
tst/editor/align_empty_cells_expected.kt
Normal file
4
tst/editor/align_empty_cells_expected.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
@table
|
||||
a | | b ||
|
||||
cc | dd | ee ||
|
||||
@
|
||||
4
tst/editor/align_escapes.kt
Normal file
4
tst/editor/align_escapes.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
@table
|
||||
a ^| b | c ||
|
||||
dd | ee ||
|
||||
@
|
||||
4
tst/editor/align_escapes_expected.kt
Normal file
4
tst/editor/align_escapes_expected.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
@table
|
||||
a ^| b | c ||
|
||||
dd | ee ||
|
||||
@
|
||||
12
tst/editor/align_mixed.kt
Normal file
12
tst/editor/align_mixed.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
Some text before.
|
||||
@table :caption Test
|
||||
First item | Second | A third item that's longer ||
|
||||
Row 2 | Text | Not as long ||
|
||||
:column_width f f f
|
||||
A cell that is way way too long to align nicely here | x | y ||
|
||||
Multi | line cell
|
||||
continues here | z ||
|
||||
@b bold @ | @frac 1 | 2 @ ||
|
||||
Last | row | here
|
||||
@
|
||||
After.
|
||||
12
tst/editor/align_mixed_expected.kt
Normal file
12
tst/editor/align_mixed_expected.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
Some text before.
|
||||
@table :caption Test
|
||||
First item | Second | A third item that's longer ||
|
||||
Row 2 | Text | Not as long ||
|
||||
:column_width f f f
|
||||
A cell that is way way too long to align nicely here | x | y ||
|
||||
Multi | line cell
|
||||
continues here | z ||
|
||||
@b bold @ | @frac 1 | 2 @ ||
|
||||
Last | row | here
|
||||
@
|
||||
After.
|
||||
4
tst/editor/align_too_wide.kt
Normal file
4
tst/editor/align_too_wide.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
@table
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx ||
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx ||
|
||||
@
|
||||
4
tst/editor/align_too_wide_expected.kt
Normal file
4
tst/editor/align_too_wide_expected.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
@table
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx ||
|
||||
xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx | xxxxxxxxxxxxxxxxxxxxxxxxxxxx ||
|
||||
@
|
||||
30
tst/editor/editor_driver.el
Normal file
30
tst/editor/editor_driver.el
Normal file
@@ -0,0 +1,30 @@
|
||||
;;; editor_driver.el --- drive the Emacs editor units over fixtures -*- lexical-binding: t; -*-
|
||||
|
||||
;; Usage:
|
||||
;; emacs --batch -L EMACSDIR -l klammertext-mode -l klammertext-indent
|
||||
;; -l klammertext-align -l editor_driver.el MODE INFILE OUTFILE ...
|
||||
;;
|
||||
;; MODE is "indent" or "align"; each triple applies that tool to INFILE and
|
||||
;; writes the result to OUTFILE. Called by editor_test.sh.
|
||||
|
||||
(let ((args command-line-args-left))
|
||||
(setq command-line-args-left nil) ; keep batch Emacs from visiting them
|
||||
(while args
|
||||
(let ((mode (pop args))
|
||||
(in (pop args))
|
||||
(out (pop args)))
|
||||
(with-temp-buffer
|
||||
(insert-file-contents in)
|
||||
(klammertext-mode)
|
||||
(cond
|
||||
((string= mode "indent")
|
||||
(indent-region (point-min) (point-max)))
|
||||
((string= mode "align")
|
||||
(goto-char (point-min))
|
||||
(when (search-forward "|" nil t)
|
||||
(goto-char (1- (point))))
|
||||
(klammertext-align-table))
|
||||
(t (error "editor_driver.el: unknown mode %s" mode)))
|
||||
(write-region (point-min) (point-max) out nil 'silent)))))
|
||||
|
||||
;;; editor_driver.el ends here
|
||||
63
tst/editor/editor_driver.py
Normal file
63
tst/editor/editor_driver.py
Normal file
@@ -0,0 +1,63 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Drive the Sublime Text editor cores over fixture files, outside Sublime.
|
||||
|
||||
Usage: editor_driver.py SUBLIME_DIR (MODE INFILE OUTFILE)...
|
||||
|
||||
MODE is `indent` or `align`; each triple applies that tool to INFILE and
|
||||
writes the result to OUTFILE. The Sublime plugin files import without the
|
||||
`sublime` module (their try/except guard), so the pure cores run under plain
|
||||
python3. Also asserts the built-in error path (no enclosing table).
|
||||
Called by editor_test.sh; exits nonzero on an internal error.
|
||||
"""
|
||||
|
||||
import sys
|
||||
|
||||
|
||||
def apply_indent(KI, s):
|
||||
bols = [0] + [i + 1 for i, ch in enumerate(s)
|
||||
if ch == '\n' and i + 1 < len(s)]
|
||||
out = s
|
||||
for a, b, new in sorted(KI.reindent_lines(s, bols), reverse=True):
|
||||
out = out[:a] + new + out[b:]
|
||||
return out
|
||||
|
||||
|
||||
def apply_align(KA, s):
|
||||
caret = s.index('|') if '|' in s else 0
|
||||
span = KA.enclosing_span(s, caret, KA.ALIGN_KLAMMERS)
|
||||
if span is None:
|
||||
return s
|
||||
_name, cs, ce = span
|
||||
edits, _msg = KA.compute_edits(s[cs:ce])
|
||||
out = s
|
||||
for a, b, new in sorted(edits, reverse=True):
|
||||
out = out[:cs + a] + new + out[cs + b:]
|
||||
return out
|
||||
|
||||
|
||||
def main():
|
||||
sublime_dir = sys.argv[1]
|
||||
sys.path.insert(0, sublime_dir)
|
||||
import Klammertext_indent as KI
|
||||
import Klammertext_align as KA
|
||||
|
||||
args = sys.argv[2:]
|
||||
for k in range(0, len(args), 3):
|
||||
mode, infile, outfile = args[k:k + 3]
|
||||
with open(infile) as f:
|
||||
s = f.read()
|
||||
if mode == 'indent':
|
||||
out = apply_indent(KI, s)
|
||||
elif mode == 'align':
|
||||
out = apply_align(KA, s)
|
||||
else:
|
||||
sys.exit("editor_driver.py: unknown mode: " + mode)
|
||||
with open(outfile, 'w') as f:
|
||||
f.write(out)
|
||||
|
||||
# Error path: no enclosing table klammer.
|
||||
assert KA.enclosing_span("no table here\n", 3, KA.ALIGN_KLAMMERS) is None
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
12
tst/editor/indent_defs.kt
Normal file
12
tst/editor/indent_defs.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
@@note.k s :label Note :color 1.0,1.0,0.9
|
||||
:level.int 0
|
||||
: Rectangular block for a special note @@
|
||||
|
||||
@@quote.txt ::
|
||||
@eval block.block_indent(K) eval@
|
||||
@@
|
||||
|
||||
@@@state Word_max
|
||||
:desc Maximum words
|
||||
:value 7
|
||||
@@@
|
||||
12
tst/editor/indent_defs_expected.kt
Normal file
12
tst/editor/indent_defs_expected.kt
Normal file
@@ -0,0 +1,12 @@
|
||||
@@note.k s :label Note :color 1.0,1.0,0.9
|
||||
:level.int 0
|
||||
: Rectangular block for a special note @@
|
||||
|
||||
@@quote.txt ::
|
||||
@eval block.block_indent(K) eval@
|
||||
@@
|
||||
|
||||
@@@state Word_max
|
||||
:desc Maximum words
|
||||
:value 7
|
||||
@@@
|
||||
10
tst/editor/indent_document.kt
Normal file
10
tst/editor/indent_document.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
@document :structure plain :text
|
||||
This is a normal paragraph, at the left margin.
|
||||
|
||||
@ol
|
||||
One
|
||||
| Two
|
||||
@
|
||||
|
||||
More text after the list.
|
||||
@
|
||||
10
tst/editor/indent_document_expected.kt
Normal file
10
tst/editor/indent_document_expected.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
@document :structure plain :text
|
||||
This is a normal paragraph, at the left margin.
|
||||
|
||||
@ol
|
||||
One
|
||||
| Two
|
||||
@
|
||||
|
||||
More text after the list.
|
||||
@
|
||||
5
tst/editor/indent_escapes.kt
Normal file
5
tst/editor/indent_escapes.kt
Normal file
@@ -0,0 +1,5 @@
|
||||
@ol
|
||||
Item one
|
||||
| ^| a literal bar item
|
||||
^@ a literal at line
|
||||
@
|
||||
5
tst/editor/indent_escapes_expected.kt
Normal file
5
tst/editor/indent_escapes_expected.kt
Normal file
@@ -0,0 +1,5 @@
|
||||
@ol
|
||||
Item one
|
||||
| ^| a literal bar item
|
||||
^@ a literal at line
|
||||
@
|
||||
11
tst/editor/indent_list.kt
Normal file
11
tst/editor/indent_list.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
@ol
|
||||
Item one
|
||||
| Item two
|
||||
| Item three
|
||||
@ol
|
||||
Embedded item one
|
||||
| Embedded item two
|
||||
@
|
||||
| Item four
|
||||
| Item five
|
||||
@
|
||||
11
tst/editor/indent_list_expected.kt
Normal file
11
tst/editor/indent_list_expected.kt
Normal file
@@ -0,0 +1,11 @@
|
||||
@ol
|
||||
Item one
|
||||
| Item two
|
||||
| Item three
|
||||
@ol
|
||||
Embedded item one
|
||||
| Embedded item two
|
||||
@
|
||||
| Item four
|
||||
| Item five
|
||||
@
|
||||
10
tst/editor/indent_named_close.kt
Normal file
10
tst/editor/indent_named_close.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
@document :structure plain :text
|
||||
Text at the margin.
|
||||
@quote
|
||||
Quoted text.
|
||||
quote@
|
||||
document@
|
||||
|
||||
@@mydef arg :
|
||||
Body of the definition.
|
||||
mydef@@
|
||||
10
tst/editor/indent_named_close_expected.kt
Normal file
10
tst/editor/indent_named_close_expected.kt
Normal file
@@ -0,0 +1,10 @@
|
||||
@document :structure plain :text
|
||||
Text at the margin.
|
||||
@quote
|
||||
Quoted text.
|
||||
quote@
|
||||
document@
|
||||
|
||||
@@mydef arg :
|
||||
Body of the definition.
|
||||
mydef@@
|
||||
4
tst/editor/indent_table.kt
Normal file
4
tst/editor/indent_table.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
@table
|
||||
First item | Second | A third item that's longer ||
|
||||
Row 2 | Text | Not as long ||
|
||||
@
|
||||
4
tst/editor/indent_table_expected.kt
Normal file
4
tst/editor/indent_table_expected.kt
Normal file
@@ -0,0 +1,4 @@
|
||||
@table
|
||||
First item | Second | A third item that's longer ||
|
||||
Row 2 | Text | Not as long ||
|
||||
@
|
||||
14
tst/editor/indent_untouched.kt
Normal file
14
tst/editor/indent_untouched.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
@code
|
||||
def f(x):
|
||||
if x:
|
||||
return 1
|
||||
code@
|
||||
@eval
|
||||
def g(y):
|
||||
return y + 1
|
||||
g(2)
|
||||
@
|
||||
@@@state Word_max
|
||||
:desc A description line
|
||||
:value 7
|
||||
@@@
|
||||
14
tst/editor/indent_untouched_expected.kt
Normal file
14
tst/editor/indent_untouched_expected.kt
Normal file
@@ -0,0 +1,14 @@
|
||||
@code
|
||||
def f(x):
|
||||
if x:
|
||||
return 1
|
||||
code@
|
||||
@eval
|
||||
def g(y):
|
||||
return y + 1
|
||||
g(2)
|
||||
@
|
||||
@@@state Word_max
|
||||
:desc A description line
|
||||
:value 7
|
||||
@@@
|
||||
123
tst/editor_test.sh
Executable file
123
tst/editor_test.sh
Executable file
@@ -0,0 +1,123 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# editor_test.sh — Regression tests for the Klammertext editor support
|
||||
# (the Emacs mode's indentation/alignment units and their Sublime Text ports).
|
||||
#
|
||||
# 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
|
||||
# independent implementations of Klammertext's structure agree with the
|
||||
# canonical formatting conventions AND with each other. The klammer names
|
||||
# that appear in the fixtures (@ol, @table, @document, @code) are seeded
|
||||
# configuration of the editor tools, not SKS dependencies; nothing here runs
|
||||
# ktext or loads a klammer set.
|
||||
#
|
||||
# What is checked, for every fixture pair <name>.kt / <name>_expected.kt in
|
||||
# tst/editor/:
|
||||
# * the Sublime Python core's output equals the expected file
|
||||
# * idempotence: the tool applied to the expected file leaves it unchanged
|
||||
# * when Emacs is installed: the Emacs unit's output equals the expected
|
||||
# file, and equals the Python output byte for byte (the sync check across
|
||||
# the SYNC-noted policy lists) — skipped gracefully otherwise
|
||||
#
|
||||
# The editor code is located automatically: doc/emacs + doc/sublime in the
|
||||
# development tree, doc/edit/emacs + doc/edit/sublime in the distribution.
|
||||
#
|
||||
# Usage: ./editor_test.sh Requires python3; Emacs is optional.
|
||||
# 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)"
|
||||
if [ -d "$ROOT/doc/emacs" ]; then
|
||||
EMACS_DIR="$ROOT/doc/emacs"
|
||||
SUBLIME_DIR="$ROOT/doc/sublime"
|
||||
elif [ -d "$ROOT/doc/edit/emacs" ]; then
|
||||
EMACS_DIR="$ROOT/doc/edit/emacs"
|
||||
SUBLIME_DIR="$ROOT/doc/edit/sublime"
|
||||
else
|
||||
echo "editor_test.sh: cannot locate the editor support (doc/emacs or doc/edit/emacs)" >&2
|
||||
exit 1
|
||||
fi
|
||||
FIX="$HERE/editor"
|
||||
OUT="$(mktemp -d)"
|
||||
trap 'rm -rf "$OUT"' EXIT
|
||||
|
||||
INDENT_FIXTURES="indent_list indent_document indent_table indent_untouched
|
||||
indent_defs indent_escapes indent_named_close"
|
||||
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"
|
||||
py_args+=("$mode" "$FIX/$name.kt" "$OUT/$name.py.out")
|
||||
py_args+=("$mode" "$FIX/${name}_expected.kt" "$OUT/$name.py.idem")
|
||||
el_args+=("$mode" "$FIX/$name.kt" "$OUT/$name.el.out")
|
||||
el_args+=("$mode" "$FIX/${name}_expected.kt" "$OUT/$name.el.idem")
|
||||
}
|
||||
for f in $INDENT_FIXTURES; do add_fixture indent "$f"; done
|
||||
for f in $ALIGN_FIXTURES; do add_fixture align "$f"; done
|
||||
|
||||
# --- run the Sublime Python cores (required) -------------------------------
|
||||
if ! command -v python3 >/dev/null 2>&1; then
|
||||
echo "editor_test.sh: python3 not found" >&2
|
||||
exit 1
|
||||
fi
|
||||
if ! PYTHONDONTWRITEBYTECODE=1 python3 "$FIX/editor_driver.py" "$SUBLIME_DIR" "${py_args[@]}"; then
|
||||
echo "editor_test.sh: the Python driver failed" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- run the Emacs units (optional) ----------------------------------------
|
||||
HAVE_EMACS=0
|
||||
if command -v emacs >/dev/null 2>&1; then
|
||||
if emacs --batch -L "$EMACS_DIR" \
|
||||
-l klammertext-mode -l klammertext-indent -l klammertext-align \
|
||||
-l "$FIX/editor_driver.el" "${el_args[@]}" 2>"$OUT/emacs.log"; then
|
||||
HAVE_EMACS=1
|
||||
else
|
||||
echo "${red}FAIL${reset} the Emacs driver failed:" >&2
|
||||
cat "$OUT/emacs.log" >&2
|
||||
FAIL=$((FAIL + 1))
|
||||
fi
|
||||
else
|
||||
echo "(Emacs not installed — the Emacs half is skipped; the Python cores still run)"
|
||||
fi
|
||||
|
||||
# --- compare ---------------------------------------------------------------
|
||||
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
|
||||
}
|
||||
|
||||
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"
|
||||
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
|
||||
done
|
||||
|
||||
echo
|
||||
echo "${bold}editor_test: $PASS passed, $FAIL failed${reset}"
|
||||
[ "$FAIL" -eq 0 ]
|
||||
Reference in New Issue
Block a user