aboutsummaryrefslogtreecommitdiffstats
path: root/desktop
diff options
context:
space:
mode:
Diffstat (limited to 'desktop')
-rw-r--r--desktop/modules/sbbuilder/README.md6
-rw-r--r--desktop/modules/sbbuilder/SbbVmModule.qml1
-rw-r--r--desktop/modules/sbbuilder/Store.qml26
-rw-r--r--desktop/modules/sbbuilder/Toml.js3
-rw-r--r--desktop/modules/sbbuilder/test_toml.js7
5 files changed, 37 insertions, 6 deletions
diff --git a/desktop/modules/sbbuilder/README.md b/desktop/modules/sbbuilder/README.md
index 73bfe51..ddb5b75 100644
--- a/desktop/modules/sbbuilder/README.md
+++ b/desktop/modules/sbbuilder/README.md
@@ -19,7 +19,11 @@ Both follow the settings window's draft rules (`desktop/README.md`). A field
is typed after its default: lists are words split on spaces (a list entry
holding a space is a `ponytail:` ceiling: edit the file), numbers are
range-checked. An emptied manifest URL holds Save back rather than unsetting
-the key, which would remove the row being typed in. The desktop defaults are
+the key, which would remove the row being typed in. The helper takes a
+`[manifests]` table whole, in place of its default one, so a file without
+one lists the helper's default rows, and the first add, remove or edit
+writes them all first: adding one row once silently dropped the default
+neovim manifest. The desktop defaults are
copied from sb-builder's `config.py`, a `ponytail:` ceiling in `Sbb.qml`;
the VM ones come from the helper.
diff --git a/desktop/modules/sbbuilder/SbbVmModule.qml b/desktop/modules/sbbuilder/SbbVmModule.qml
index 45c7216..97e7983 100644
--- a/desktop/modules/sbbuilder/SbbVmModule.qml
+++ b/desktop/modules/sbbuilder/SbbVmModule.qml
@@ -114,6 +114,7 @@ Module {
width: col.width
wrapMode: Text.Wrap
text: "A package's upstream deps list; {VERSION} is the new version. A hint update moves the package's extra downloads to the versions listed there."
+ + (col.st.manifestsDefault ? " These are the helper's defaults, not in the file: the first change writes them all, then adds or removes its own." : "")
color: Theme.subtext
font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 }
}
diff --git a/desktop/modules/sbbuilder/Store.qml b/desktop/modules/sbbuilder/Store.qml
index c2afa5d..7036f36 100644
--- a/desktop/modules/sbbuilder/Store.qml
+++ b/desktop/modules/sbbuilder/Store.qml
@@ -32,20 +32,35 @@ QtObject {
// Assigned only when the set changes, as Qtm does: a Repeater bound to a
// fresh array per keystroke rebuilds the row being typed in.
property var manifests: []
+ // The helper takes a [manifests] table whole, in place of its default
+ // one, so with none in the file the default rows are the ones in effect
+ // and are listed; the first edit writes them all before its own.
+ readonly property bool manifestsDefault: !T.sections(st.draft).includes("manifests")
onDraftChanged: {
- const k = T.entries(st.draft, "manifests").map(e => e.key);
+ const k = st.manifestsDefault ? Object.keys(st.fallback("manifests") ?? {})
+ : T.entries(st.draft, "manifests").map(e => e.key);
if (JSON.stringify(k) !== JSON.stringify(st.manifests)) st.manifests = k;
}
+ function seedManifests(section) {
+ if (section !== "manifests" || !st.manifestsDefault) return;
+ const d = st.fallback("manifests") ?? {};
+ for (const k in d) st.draft = T.set(st.draft, "manifests", k, d[k]);
+ }
- function fallback(section, key) { return (st.defaults[section] || {})[key]; }
+ function fallback(section, key) { return key === undefined ? st.defaults[section] : (st.defaults[section] || {})[key]; }
function show(v) { return v === undefined ? undefined : Array.isArray(v) ? v.join(" ") : String(v); }
function placeholder(section, key) { return st.show(st.fallback(section, key)) ?? ""; }
- function get(section, key) { return st.show(T.get(st.draft, section, key)); }
+ function get(section, key) {
+ const v = T.get(st.draft, section, key);
+ // A listed default manifest shows its URL, so editing starts from it.
+ return st.show(v === undefined && section === "manifests" && st.manifestsDefault ? st.fallback(section, key) : v);
+ }
// The effective value, typed: the file's, else the default.
function value(section, key) { return T.get(st.draft, section, key) ?? st.fallback(section, key); }
function entries(section) { return T.entries(st.draft, section); }
function put(section, key, v) {
+ st.seedManifests(section);
try { st.draft = T.set(st.draft, section, key, v); } catch (e) {
st.error = e.message;
st.markInvalid(section + "/" + key, true); // hold Save back
@@ -63,7 +78,10 @@ QtObject {
: typeof d === "number" ? Number(t)
: typeof d === "boolean" ? t === "true" : t);
}
- function remove(section, key) { st.draft = T.remove(st.draft, section, key); }
+ function remove(section, key) {
+ st.seedManifests(section);
+ st.draft = T.remove(st.draft, section, key);
+ }
function markInvalid(id, bad) {
if (!!st.invalid[id] === bad) return;
diff --git a/desktop/modules/sbbuilder/Toml.js b/desktop/modules/sbbuilder/Toml.js
index 46b9914..dddb6f7 100644
--- a/desktop/modules/sbbuilder/Toml.js
+++ b/desktop/modules/sbbuilder/Toml.js
@@ -92,6 +92,9 @@ function ranges(lines) {
return out;
}
+// The [section] names present, in file order; "" is not one.
+function sections(text) { return ranges(text.split("\n")).slice(1).map(r => r.name); }
+
// [{key, value}] for the active keys of a section, in file order.
function entries(text, section) {
const lines = text.split("\n");
diff --git a/desktop/modules/sbbuilder/test_toml.js b/desktop/modules/sbbuilder/test_toml.js
index 8378519..c86741d 100644
--- a/desktop/modules/sbbuilder/test_toml.js
+++ b/desktop/modules/sbbuilder/test_toml.js
@@ -18,7 +18,7 @@ const assert = require("assert");
const src = fs.readFileSync(__dirname + "/Toml.js", "utf8")
.replace(/^\.pragma library$/m, "");
-const T = new Function(src + "\nreturn { entries, get, set, remove };")();
+const T = new Function(src + "\nreturn { sections, entries, get, set, remove };")();
const file = [
"# helper config",
@@ -97,4 +97,9 @@ t = T.remove(file, "manifests", "gtk+3");
assert.deepStrictEqual(T.entries(t, "manifests").map(e => e.key), ["neovim"]);
assert.strictEqual(T.remove(file, "manifests", "nope"), file);
+// sections tells a missing table from an empty one, which entries cannot.
+assert.deepStrictEqual(T.sections(file), ["manifests", "refresh"]);
+assert.deepStrictEqual(T.sections("a = 1\n[manifests]\n"), ["manifests"]);
+assert.deepStrictEqual(T.sections("a = 1\n"), []);
+
console.log("test_toml: ok");