aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/sisudoc/ocda
diff options
context:
space:
mode:
authorRalph Amissah <ralph.amissah@gmail.com>2026-09-21 11:42:42 -0400
committerRalph Amissah <ralph.amissah@gmail.com>2026-09-22 14:54:32 -0400
commit3f87aa600b5080135557d846ee1ba7daef9d3155 (patch)
treefed92ba22b9baa0b8f3acfbb1eda46f5f5fa5d67 /src/sisudoc/ocda
parentocda db: one <doc>.ocda.db holding every language (diff)
ocda.db: read a document language of a database
A database now holds every language of its document, so reading one means naming a language. Three small pieces: - spineDbLanguages says what languages a file holds. Its own template rather than part of the reader (asking a file what it holds does not instantiate the object setter and the markup regexes with it). - abstractionLoad and spineDocFromArtefact take a language and pass it to dbReadFile, which resolves it to a doc_id, takes that language document where there is one, and lists the languages and stops where there is a choice. - spineArtefactLanguages turns an artefact into the documents to build: one for a .ssp, and for a database the languages it holds filtered by --lang. The artefact loop then has a language loop inside it, so a single .ocda.db argument builds every language, as the pod it came from would. --db-round-trip takes --lang for the same reason, and ocda-db looses --parallel (would cause a race). (assisted by Claude-Code)
Diffstat (limited to 'src/sisudoc/ocda')
-rw-r--r--src/sisudoc/ocda/abstraction/db_in.d30
-rw-r--r--src/sisudoc/ocda/abstraction/doc_from_artefact.d31
-rw-r--r--src/sisudoc/ocda/abstraction/load.d10
3 files changed, 67 insertions, 4 deletions
diff --git a/src/sisudoc/ocda/abstraction/db_in.d b/src/sisudoc/ocda/abstraction/db_in.d
index a8a216c..5535870 100644
--- a/src/sisudoc/ocda/abstraction/db_in.d
+++ b/src/sisudoc/ocda/abstraction/db_in.d
@@ -60,6 +60,36 @@ module sisudoc.ocda.abstraction.db_in;
writer's own record definition, and require the result to equal the .ssp
written from the same document.
+/
+/+ ↓ the languages a database holds, in the order they were written.
+ a caller that wants every language of a document has to be told what
+ they are, and this is the only place that knows: the file is named for
+ the document and says nothing about its languages.
+ .
+ an unreadable or unexpected file gives an empty list rather than an
+ exception, and the caller then treats the artefact as it would any other
+ it could not read.
+ .
+ its own template, and not part of spineAbstractionDbRead: asking a file
+ what languages it holds should not instantiate the whole reader, which
+ brings the object setter and the markup regexes with it.
++/
+template spineDbLanguages() {
+ @trusted string[] spineDbLanguages(string db_file) {
+ import std.file : exists;
+ import d2sqlite3;
+ string[] _out;
+ if (!db_file.exists) { return _out; }
+ try {
+ auto db = Database(db_file, SQLITE_OPEN_READONLY);
+ foreach (row; db.execute("SELECT lang FROM documents ORDER BY id")) {
+ _out ~= row["lang"].as!string;
+ }
+ } catch (Exception ex) {
+ return string[].init;
+ }
+ return _out;
+ }
+}
template spineAbstractionDbRead() {
import std.conv : to;
import std.file;
diff --git a/src/sisudoc/ocda/abstraction/doc_from_artefact.d b/src/sisudoc/ocda/abstraction/doc_from_artefact.d
index 7cbc73a..fa620f8 100644
--- a/src/sisudoc/ocda/abstraction/doc_from_artefact.d
+++ b/src/sisudoc/ocda/abstraction/doc_from_artefact.d
@@ -74,6 +74,34 @@ module sisudoc.ocda.abstraction.doc_from_artefact;
so a pod cannot be rebuilt from one, and the empty list is the truthful
answer rather than a gap.
+/
+/+ ↓ which languages of an artefact there are to build, and in what order.
+ a .ssp is one language and answers [""], meaning "the one it holds".
+ a .ocda.db holds every language of its document, so each one named in it
+ is a document to build, filtered by --lang where that was given. --lang
+ naming a language the database does not hold leaves an empty list, and
+ the caller says so rather than silently building nothing.
+ .
+ Its own template rather than a function inside spineDocFromArtefact:
+ that one is eponymous, so nothing beside the function of the same name
+ can be reached from outside it. The listing itself is db_in's
+ spineDbLanguages, which is separate from the reader for the same reason:
+ asking what languages a file holds should not instantiate the reader.
++/
+template spineArtefactLanguages() {
+ string[] spineArtefactLanguages(string _artefact, string[] _langs_wanted) {
+ import std.algorithm : endsWith;
+ import sisudoc.ocda.abstraction.db_in : spineDbLanguages;
+ if (!_artefact.endsWith(".db")) { return [""]; }
+ string[] _held = spineDbLanguages!()(_artefact);
+ if (_held.length == 0) { return [""]; } // let the read report why
+ if (_langs_wanted.length == 0 || _langs_wanted[0] == "all") { return _held; }
+ string[] _out;
+ foreach (_l; _held) {
+ foreach (_w; _langs_wanted) { if (_l == _w) { _out ~= _l; break; } }
+ }
+ return _out;
+ }
+}
template spineDocFromArtefact() {
import std.algorithm : endsWith;
import std.array;
@@ -332,8 +360,9 @@ template spineDocFromArtefact() {
O _opt_action,
E _env,
ConfComposite _site_conf,
+ string _lang = "",
) {
- auto _loaded = abstractionLoad(_artefact);
+ auto _loaded = abstractionLoad(_artefact, _lang);
auto _ssp = _loaded.doc;
auto _pths = artefactPaths(_artefact, _ssp);
/+ ↓ the images.
diff --git a/src/sisudoc/ocda/abstraction/load.d b/src/sisudoc/ocda/abstraction/load.d
index 2072aae..ae6c673 100644
--- a/src/sisudoc/ocda/abstraction/load.d
+++ b/src/sisudoc/ocda/abstraction/load.d
@@ -139,13 +139,17 @@ template spineAbstractionLoad() {
}
/+ ↓ load what can be loaded from the path alone.
-
.ssp and .ocda.db come back filled. the three source forms come back
with loaded = false and a note saying where they are handled, because
reading them needs the manifest, environment and configuration that
spine.d builds, not a file path.
+ .
+ _lang names which language of a .ocda.db to take, a database holding
+ every language of its document. With none named it takes the only one
+ there is, and where there is a choice it says so rather than choosing.
+ A .ssp is one language by construction and ignores it.
+/
- LoadedAbstraction abstractionLoad(string _path) {
+ LoadedAbstraction abstractionLoad(string _path, string _lang = "") {
LoadedAbstraction _out;
_out.path = _path;
_out.source = abstractionSourceOf(_path);
@@ -160,7 +164,7 @@ template spineAbstractionLoad() {
if (!_out.loaded) { _out.note = "no object sections found"; }
break;
case AbstractionSource.ocda_db:
- _out.doc = dbReadFile(_path);
+ _out.doc = dbReadFile(_path, _lang);
_out.loaded = (_out.doc.section_order.length > 0);
if (!_out.loaded) { _out.note = "no object sections found"; }
break;