Verbatim-safe typography, ^-punctuation quoting, full-range ^UUUU^, polyglot html
Typographic transforms (---, quote pairs, ~) no longer touch verbatim text: @c/@code/@source_listing content and ^'...'^ spans show exactly the characters written. "^" before any punctuation character quotes it in every target (the apostrophe excepted: ^' opens a literal span), with the new :resolve option on @@@target declaring per-target renderings. The ^UUUU^ code-point form accepts 4-6 hex digits, the full Unicode range. The html output and transform spellings are polyglot (XML-valid), in preparation for an EPUB target. New suites: transform_test, character_test (engine), typography_test (SKS). (from dev 07ce5ea86a0a)
This commit is contained in:
@@ -131,15 +131,32 @@ Register one with `klammertext-add-literal-klammer', e.g. in your init file:
|
||||
;; doc/edit/sublime/Klammertext.sublime-syntax
|
||||
;; * the @NAME verbatim region in doc/edit/vim/syntax/klammertext.vim
|
||||
;; * the @NAME rule in doc/edit/vscode/syntaxes/klammertext.tmLanguage.json
|
||||
;; All are currently seeded with just "code".
|
||||
;; All are currently seeded with "code" and "c" (@c is the inline form of
|
||||
;; @code and took a literal argument 2026-08-16; the miscounted stack from an
|
||||
;; unrecognized "@c ... c@" shifted a whole document's indentation by one).
|
||||
|
||||
(defun klammertext-add-literal-klammer (name)
|
||||
"Register NAME as a klammer whose literal content must not be interpreted.
|
||||
NAME is the klammer name without the leading @ (e.g. \"code\")."
|
||||
(add-to-list 'klammertext-literal-klammers name))
|
||||
|
||||
(defun klammertext--search-literal-close (name &optional bound)
|
||||
"Move point past the exact close token NAME@ at or after point.
|
||||
Return the position after the close, or nil if there is none before BOUND.
|
||||
NAME@ preceded by a name character is verbatim content, not a close --
|
||||
\"basic@\" does not close @c, and \"barcode@\" does not close @code
|
||||
\(the engine's close is a whole katom). Mirrors the shared core's
|
||||
find_literal_close."
|
||||
(let ((close (concat (regexp-quote name) "@")) (found nil))
|
||||
(while (and (setq found (re-search-forward close bound t))
|
||||
(let ((b (match-beginning 0)))
|
||||
(and (> b (point-min))
|
||||
(klammertext--name-char-p (char-before b))))))
|
||||
found))
|
||||
|
||||
;; Seed the list through the same entry point future users will use.
|
||||
(klammertext-add-literal-klammer "code")
|
||||
(klammertext-add-literal-klammer "c")
|
||||
|
||||
;; --- Helpers -----------------------------------------------------------
|
||||
|
||||
@@ -275,13 +292,12 @@ BEFORE is the character before POS."
|
||||
;; BEFORE `klammertext--set-match', because `re-search-forward'
|
||||
;; clobbers the match data.
|
||||
(if (member name klammertext-literal-klammers)
|
||||
(let ((close (concat (regexp-quote name) "@")))
|
||||
(if (re-search-forward close nil t)
|
||||
(let ((close-end (point)))
|
||||
(put-text-property pos close-end 'font-lock-multiline t)
|
||||
(goto-char (- close-end (length name) 1)))
|
||||
(put-text-property pos (point-max) 'font-lock-multiline t)
|
||||
(goto-char (point-max))))
|
||||
(if (klammertext--search-literal-close name)
|
||||
(let ((close-end (point)))
|
||||
(put-text-property pos close-end 'font-lock-multiline t)
|
||||
(goto-char (- close-end (length name) 1)))
|
||||
(put-text-property pos (point-max) 'font-lock-multiline t)
|
||||
(goto-char (point-max)))
|
||||
(goto-char name-end))
|
||||
;; Set the match data for the opening LAST, so it survives to the
|
||||
;; highlight step.
|
||||
@@ -478,8 +494,8 @@ delimiter (or skipped region) and return (POS . KIND) with KIND `open or
|
||||
(let ((name (buffer-substring-no-properties (1+ hit) (point))))
|
||||
(cond
|
||||
((member name klammertext-literal-klammers) ; literal span: skip
|
||||
(let ((close (concat (regexp-quote name) "@")))
|
||||
(unless (re-search-forward close nil t) (goto-char (point-max)))))
|
||||
(unless (klammertext--search-literal-close name)
|
||||
(goto-char (point-max))))
|
||||
((eq (char-after) ?-)) ; @name-arg : no span
|
||||
(t (throw 'found (cons hit 'open))))))
|
||||
(t ; name@ / bare @ : closing
|
||||
@@ -574,7 +590,7 @@ name, not by depth counting."
|
||||
The verbatim content is opaque, so we search for the literal close string."
|
||||
(save-excursion
|
||||
(goto-char (+ open-pos 1 (length name)))
|
||||
(when (search-forward (concat name "@") nil t)
|
||||
(when (klammertext--search-literal-close name)
|
||||
(1- (point)))))
|
||||
|
||||
(defun klammertext--literal-match-backward (close-pos name)
|
||||
@@ -586,7 +602,11 @@ CLOSE-POS, or nil. Literal spans do not nest, so the nearest preceding real
|
||||
(let ((open-str (concat "@" name)) (result nil))
|
||||
(while (and (not result) (search-backward open-str nil t))
|
||||
(let ((op (point)))
|
||||
;; The name must end where the token ends: "@c" found inside
|
||||
;; "@caption" is not an opener of @c.
|
||||
(unless (or (eq (char-before op) ?@) ; @@NAME = definition
|
||||
(klammertext--name-char-p
|
||||
(char-after (+ op 1 (length name))))
|
||||
(klammertext--escaped-p op))
|
||||
(setq result op))))
|
||||
result)))
|
||||
|
||||
Reference in New Issue
Block a user