aboutsummaryrefslogtreecommitdiffhomepage
path: root/org/ocda_reserved.org
diff options
context:
space:
mode:
Diffstat (limited to 'org/ocda_reserved.org')
-rw-r--r--org/ocda_reserved.org212
1 files changed, 212 insertions, 0 deletions
diff --git a/org/ocda_reserved.org b/org/ocda_reserved.org
new file mode 100644
index 0000000..eddf455
--- /dev/null
+++ b/org/ocda_reserved.org
@@ -0,0 +1,212 @@
+-*- mode: org -*-
+#+TITLE: sisudoc spine (doc_reform) object-centric document abstraction
+#+DESCRIPTION: documents - structuring, publishing in multiple formats & search
+#+SUMMARY: process markup document, create document abstraction
+#+FILETAGS: :spine:abstraction:
+#+AUTHOR: Ralph Amissah
+#+EMAIL: [[mailto:ralph.amissah@gmail.com][ralph.amissah@gmail.com]]
+#+COPYRIGHT: Copyright (C) 2015 (continuously updated, current 2026) Ralph Amissah
+#+LANGUAGE: en
+#+STARTUP: content hideblocks hidestars noindent entitiespretty
+#+PROPERTY: header-args+ :eval never-export :exports code
+#+PROPERTY: header-args+ :noweb yes :padline no
+#+PROPERTY: header-args+ :results silent :cache no
+#+PROPERTY: header-args+ :mkdirp yes
+#+OPTIONS: H:3 num:nil toc:t \n:t ::t |:t ^:nil -:t f:t *:t
+- magic single double-quote → " ← FIX changes hilighting behavior (occuring
+ after it) in org document. INVESTIGATE (org-mode CONFIG?) FIND & FIX
+
+- [[./doc-reform.org][doc-reform.org]] [[./][org/]]
+
+* reserved file names
+
+#+HEADER: :tangle "../src/sisudoc/ocda/meta/reserved_names.d"
+#+HEADER: :noweb yes
+#+BEGIN_SRC d
+<<doc_header_including_copyright_and_license>>
+/++
+ the segment names spine keeps for itself<br><br>
+
+ the one list of them, and the check that says when a document's own
+ heading has claimed one<br><br>
+
+ [sisudoc.ocda.meta.reserved_names]
++/
+module sisudoc.ocda.meta.reserved_names;
+@safe:
+/+ ↓ spine names the sections it generates, these names are reserved.
+ .
+ The table of contents, the gathered endnotes, the glossary, the
+ bibliography, the book index and the blurb are not in the markup: spine
+ makes them, and gives each a segment name of its own. A document whose
+ own heading asks for one of those names ("1~endnotes Endnote") is asking
+ for a name that is already taken, and before this was noticed both wrote
+ into the same file: the generated section and the author's heading, with
+ the navigation listing that file twice, the second time behind its own
+ earlier entry in reading order.
+ .
+ The parser therefore seeds the set of heading anchor names it has seen
+ with these before it reads a document, so that a heading claiming one is
+ disambiguated by ocn suffix the same way a repeated anchor tag is, and
+ the generated section keeps the name the table of contents links to.
+ .
+ Two things live here rather than in the parser:
+ .
+ the list so that the parser's seeding and the check below cannot
+ come to hold different ideas of what is reserved;
+ .
+ the check which runs over a finished abstraction, names the
+ headings that were renamed, and is what tells an author
+ that a heading of theirs is not called what they wrote.
+ A warning: the document is correct and complete, and the
+ name it ends up with works. --strict makes it a failure,
+ for the run that is meant to be publishable.
+ .
+ The renaming is not something the author has to accept. A heading given
+ any other anchor name ("1~my-notes Endnote") keeps it, and the warning
+ goes away.
++/
+/+ ↓ mixed in as a named mixin (mixin spineReservedNames _name;) and its
+ imports are inside its functions rather than at template scope: what a
+ mixin template declares at its own scope is visible in the scope it is
+ mixed into, and an import there can hijack a name the host was already
+ resolving by UFCS.
++/
+template spineReservedNames() {
+ /+ ↓ the names spine makes for itself, in one place.
+ _the_title is the head section's own; the rest are the generated
+ sections, and are the section keys of the abstraction.
+ +/
+ string[] reservedHeadingAnchorNames() {
+ return [
+ "toc", "endnotes", "glossary", "bibliography", "bookindex", "blurb",
+ "_the_title",
+ ];
+ }
+ /+ ↓ the same, as the set the parser seeds itself with +/
+ bool[string] reservedHeadingAnchorTags() {
+ bool[string] _reserved;
+ foreach (_name; reservedHeadingAnchorNames()) { _reserved[_name] = true; }
+ return _reserved;
+ }
+ /+ ↓ one heading that asked for a name spine had already taken +/
+ struct ST_ReservedNameUse {
+ string section; // where in the abstraction it sits
+ string reserved; // the name it asked for
+ string anchor; // the name it was given instead
+ string level; // as marked up, :A :B 1 2 ...
+ int ocn;
+ }
+ /+ ↓ was this heading renamed out of the way of a reserved name?
+ .
+ Read off the anchor rather than reported by the parser: the parser
+ renames by appending the object's number, so "endnotes" becomes
+ "endnotes-135" on the object whose ocn is 135, and that pairing is what
+ identifies it. Requiring the number to be the object's own is what keeps
+ a heading an author really did call "endnotes-135" from being reported as
+ something it is not.
+ +/
+ private string _reservedNameClaimedBy(O)(O obj) {
+ import std.conv : to;
+ string _anchor = obj.tags.anchor_tag_html;
+ if (_anchor.length == 0) { return ""; }
+ string _suffix = "-" ~ obj.metainfo.ocn.to!string;
+ if (_anchor.length <= _suffix.length) { return ""; }
+ if (_anchor[($ - _suffix.length) .. $] != _suffix) { return ""; }
+ string _stem = _anchor[0 .. ($ - _suffix.length)];
+ foreach (_name; reservedHeadingAnchorNames()) {
+ if (_stem == _name) { return _name; }
+ }
+ return "";
+ }
+ /+ ↓ every heading of a document that claimed a reserved name.
+ document order, the section order the .ssp is written in, so that two
+ runs over the same document report it the same way round.
+ +/
+ ST_ReservedNameUse[] reservedNameHeadings(D)(D doc) {
+ import std.algorithm : canFind, sort;
+ import std.conv : to;
+ ST_ReservedNameUse[] _out;
+ string[] _sections = ["head", "toc", "body", "endnotes",
+ "glossary", "bibliography", "bookindex", "blurb", "tail"];
+ string[] _extra;
+ foreach (_k; doc.abstraction.byKey) {
+ if (!_sections.canFind(_k)) { _extra ~= _k; }
+ }
+ foreach (_k; _extra.sort) { _sections ~= _k; }
+ foreach (section; _sections) {
+ if (section !in doc.abstraction) { continue; }
+ foreach (obj; doc.abstraction[section]) {
+ if (obj.metainfo.is_a != "heading") { continue; }
+ string _claimed = _reservedNameClaimedBy(obj);
+ if (_claimed.length == 0) { continue; }
+ /+ ↓ the generated sections carry the reserved names themselves and are
+ not what this is about: they are headings spine made, and they keep
+ the plain name. Only an object that was renamed reaches here, and a
+ generated one never is.
+ +/
+ ST_ReservedNameUse _u;
+ _u.section = section;
+ _u.reserved = _claimed;
+ _u.anchor = obj.tags.anchor_tag_html;
+ _u.level = obj.metainfo.marked_up_level;
+ _u.ocn = obj.metainfo.ocn.to!int;
+ _out ~= _u;
+ }
+ }
+ return _out;
+ }
+ /+ ↓ the report, as the lines to print.
+ the document is named once and its headings indented under it, as the ocn
+ alignment check does, so that a run over a collection reads as a list of
+ documents.
+ +/
+ string[] reservedNameReportLines(
+ string doc_key,
+ string lang,
+ ST_ReservedNameUse[] _uses,
+ ) {
+ import std.conv : to;
+ string[] _out;
+ if (_uses.length == 0) { return _out; }
+ _out ~= "WARNING reserved segment name: " ~ doc_key
+ ~ ((lang.length > 0) ? " [" ~ lang ~ "]" : "");
+ foreach (_u; _uses) {
+ _out ~= " heading " ~ _u.level ~ " at ocn " ~ _u.ocn.to!string
+ ~ " asks for \"" ~ _u.reserved
+ ~ "\", which spine gives its own generated section";
+ _out ~= " it is named \"" ~ _u.anchor
+ ~ "\" instead; give the heading another name to keep one of your own";
+ }
+ return _out;
+ }
+}
+#+END_SRC
+
+* org includes
+** project version
+
+#+NAME: spine_version
+#+HEADER: :noweb yes
+#+BEGIN_SRC emacs-lisp
+<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_project_version()>>
+#+END_SRC
+
+** year
+
+#+NAME: year
+#+HEADER: :noweb yes
+#+BEGIN_SRC emacs-lisp
+<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:year()>>
+#+END_SRC
+
+** document header including copyright & license
+
+#+NAME: doc_header_including_copyright_and_license
+#+HEADER: :noweb yes
+#+BEGIN_SRC emacs-lisp
+<<./sisudoc_spine_version_info_and_doc_header_including_copyright_and_license.org:spine_doc_header_including_copyright_and_license()>>
+#+END_SRC
+
+* __END__
+