fix: -o validation, multiple-arg warning, missing-file error, precise residual match, add --help/Makefile/tests
ober
4f3e89cc4f8dbc988dd76b3cb9db3ec9329e16fa
new file mode 100644 --- /dev/null +++ b/Makefile @@ -0,0 +1,14 @@ +GXI ?= gxi + +# Parent of the package dir, so :jerboa-gerbil/convert resolves on the loadpath. +REPO_DIR := $(abspath $(dir $(lastword $(MAKEFILE_LIST)))) +LOADPATH := $(dir $(REPO_DIR)) + +.PHONY: test lint + +test: + GERBIL_LOADPATH='$(LOADPATH)' $(GXI) test/convert-test.ss + +lint: + GERBIL_LOADPATH='$(LOADPATH)' $(GXI) -e '(import :jerboa-gerbil/convert)' \ + -e '(displayln "lint OK: convert.ss loads and expands cleanly")' --- a/convert.ss +++ b/convert.ss @@ -8,6 +8,7 @@ ;;; references that need a human (e.g. libraries not yet ported to Gerbil). ;;; ;;; gxi convert.ss INPUT.ss [-o OUTPUT.ss] # default: write to stdout +;;; gxi convert.ss --help # print usage ;;; ;;; Library use: (import :jerboa-gerbil/convert) then (convert-string text). @@ -45,8 +46,10 @@ (def (convert-string text) (let loop ((rules +rename-rules+) (s text) (report '())) (if (null? rules) - ;; residual = leftover :jerboa-* refs, excluding our intended :jerboa-compat target - (values s (reverse report) (- (count-sub ":jerboa-" s) (count-sub ":jerboa-compat" s))) + ;; residual = leftover :jerboa-* refs, excluding our intended :jerboa-compat/ target. + ;; Match the package prefix ":jerboa-compat/" precisely (note the slash) so a + ;; hypothetical ":jerboa-compatibility" is still counted as residual. + (values s (reverse report) (- (count-sub ":jerboa-" s) (count-sub ":jerboa-compat/" s))) (let* ((rule (car rules)) (name (car rule)) (old (cadr rule)) (new (caddr rule)) (c (count-sub old s))) @@ -61,11 +64,17 @@ (display txt)) (values report residual))) +(def +usage+ + "usage: gxi convert.ss INPUT.ss [-o OUTPUT.ss] # default: write to stdout + gxi convert.ss --help") + (def (main . args) (let loop ((args args) (out #f) (in #f)) (cond ((null? args) - (unless in (error "usage: gxi convert.ss INPUT.ss [-o OUTPUT.ss]")) + (unless in (error +usage+)) + (unless (file-exists? in) + (error (format "jerboa-gerbil: input file not found: ~a" in))) (let-values (((report residual) (convert-file! in out))) (let (ep (current-error-port)) (fprintf ep "jerboa-gerbil: converted ~a~a\n" in (if out (format " -> ~a" out) "")) @@ -76,5 +85,14 @@ (when (> residual 0) (fprintf ep " WARNING: ~a residual :jerboa-* reference(s) need manual review\n" residual))))) - ((equal? (car args) "-o") (loop (cddr args) (cadr args) in)) - (else (loop (cdr args) out (car args)))))) + ((or (equal? (car args) "--help") (equal? (car args) "-h")) + (displayln +usage+)) + ((equal? (car args) "-o") + (when (null? (cdr args)) + (error (format "-o requires an output filename\n~a" +usage+))) + (loop (cddr args) (cadr args) in)) + (else + (when in + (error (format "jerboa-gerbil: multiple input files: ~a and ~a\n~a" + in (car args) +usage+))) + (loop (cdr args) out (car args)))))) new file mode 100644 --- /dev/null +++ b/test/convert-test.ss @@ -0,0 +1,54 @@ +;;; -*- Gerbil -*- +;;; jerboa-gerbil/test/convert-test — minimal tests for convert-string. +;;; +;;; Run via `make test` (or: GERBIL_LOADPATH=<parent-of-package> gxi test/convert-test.ss). + +(import :std/srfi/13 (only-in :jerboa-gerbil/convert convert-string)) + +(def failures (box 0)) + +(def (check name ok?) + (if ok? + (displayln "PASS: " name) + (begin + (displayln "FAIL: " name) + (set-box! failures (+ (unbox failures) 1))))) + +;; rename rule fires: :jerboa-emacs/chez-powers -> :jerboa-compat/powers +(let-values (((txt report residual) + (convert-string "(import :jerboa-emacs/chez-powers)\n"))) + (check "chez-powers rewritten to :jerboa-compat/powers" + (string-contains txt ":jerboa-compat/powers")) + (check "chez-powers rule reports 1 application" + (= 1 (cdr (assoc "chez-powers" report)))) + (check "clean rename leaves no residual" + (= 0 residual))) + +;; generic emacs rule: :jerboa-emacs/foo -> :gemacs/foo +(let-values (((txt report residual) + (convert-string "(import :jerboa-emacs/foo)\n"))) + (check "generic :jerboa-emacs/ rewritten to :gemacs/" + (string-contains txt ":gemacs/foo"))) + +;; residual detection: an unported :jerboa-* ref is counted +(let-values (((txt report residual) + (convert-string "(import :jerboa-unknown/thing)\n"))) + (check "unported :jerboa-* ref counted as residual" + (= 1 residual))) + +;; precise exclusion: the intended :jerboa-compat/ target is NOT residual +(let-values (((txt report residual) + (convert-string "(import :jerboa-compat/powers)\n"))) + (check "intended :jerboa-compat/ target not counted as residual" + (= 0 residual))) + +;; precise exclusion: a hypothetical :jerboa-compatibility IS still residual +(let-values (((txt report residual) + (convert-string "(import :jerboa-compatibility/x)\n"))) + (check ":jerboa-compatibility counted as residual (precise match)" + (= 1 residual))) + +(let (n (unbox failures)) + (if (> n 0) + (begin (displayln n " failure(s)") (exit 1)) + (displayln "all tests passed")))