@kecan0406/ttheme 0.1.3 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +21 -15
- package/bin/ttheme.js +792 -230
- package/dist/manifest.json +1 -1
- package/dist/shell/palettes.zsh +3 -3
- package/package.json +1 -1
- package/shell/adapters/_osc.zsh +4 -0
- package/shell/adapters/ghostty.zsh +26 -0
- package/shell/launch-tab.zsh +1 -1
- package/shell/ttheme.zsh +35 -18
package/bin/ttheme.js
CHANGED
|
@@ -4098,6 +4098,9 @@ var require_src = __commonJS((exports, module) => {
|
|
|
4098
4098
|
module.exports = { cursor, scroll, erase, beep };
|
|
4099
4099
|
});
|
|
4100
4100
|
|
|
4101
|
+
// src/bin.ts
|
|
4102
|
+
import { isMainThread as isMainThread2 } from "node:worker_threads";
|
|
4103
|
+
|
|
4101
4104
|
// node_modules/commander/lib/error.js
|
|
4102
4105
|
class CommanderError extends Error {
|
|
4103
4106
|
constructor(exitCode, code, message) {
|
|
@@ -6144,7 +6147,7 @@ var program = new Command;
|
|
|
6144
6147
|
// package.json
|
|
6145
6148
|
var package_default = {
|
|
6146
6149
|
name: "@kecan0406/ttheme",
|
|
6147
|
-
version: "0.1.
|
|
6150
|
+
version: "0.1.5",
|
|
6148
6151
|
type: "module",
|
|
6149
6152
|
bin: {
|
|
6150
6153
|
ttheme: "bin/ttheme.js"
|
|
@@ -6790,8 +6793,8 @@ function zshrcBlock(tthemeDir) {
|
|
|
6790
6793
|
var CONFIG_HEADER = "# ttheme settings — exported variables win over this file";
|
|
6791
6794
|
var CONFIG_SETTINGS = {
|
|
6792
6795
|
TTHEME_TAB_PALETTE: {
|
|
6793
|
-
doc: "# new tabs:
|
|
6794
|
-
default: "
|
|
6796
|
+
doc: "# new tabs: off keeps the configured terminal theme, seq rotates through the palettes (default off)",
|
|
6797
|
+
default: "off"
|
|
6795
6798
|
},
|
|
6796
6799
|
TTHEME_ANNOUNCE: {
|
|
6797
6800
|
doc: '# the palette notice under "Last login:": 1 shows it, 0 silences it (default 1)',
|
|
@@ -7042,12 +7045,12 @@ ${themes.length} themes (${rotation(themes).length} in the new-tab rotation) ->
|
|
|
7042
7045
|
|
|
7043
7046
|
// src/find.ts
|
|
7044
7047
|
import { spawn as spawn2 } from "node:child_process";
|
|
7045
|
-
import { existsSync as existsSync3, mkdirSync as
|
|
7048
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync5, mkdtempSync, readFileSync as readFileSync6, rmSync as rmSync5, statSync as statSync3, writeFileSync as writeFileSync5 } from "node:fs";
|
|
7046
7049
|
import { tmpdir } from "node:os";
|
|
7047
|
-
import { dirname as
|
|
7050
|
+
import { dirname as dirname4, join as join7 } from "node:path";
|
|
7048
7051
|
|
|
7049
7052
|
// src/backdrop.ts
|
|
7050
|
-
import { mkdirSync, readdirSync as readdirSync2, rmSync as rmSync2, statSync, writeFileSync } from "node:fs";
|
|
7053
|
+
import { mkdirSync, readdirSync as readdirSync2, readFileSync as readFileSync2, renameSync, rmSync as rmSync2, statSync, utimesSync, writeFileSync } from "node:fs";
|
|
7051
7054
|
import { join as join3 } from "node:path";
|
|
7052
7055
|
|
|
7053
7056
|
// src/png.ts
|
|
@@ -7231,7 +7234,11 @@ var FILL = { width: 2560, height: 1550 };
|
|
|
7231
7234
|
var FIGURE = 2560;
|
|
7232
7235
|
var FAINT = 0.1;
|
|
7233
7236
|
var HEADROOM = 0.15;
|
|
7237
|
+
var KEEP = 0.55;
|
|
7238
|
+
var PLACE = 0.65;
|
|
7239
|
+
var STANDS = 3;
|
|
7234
7240
|
var PEAK = luminance(mix("#19161e", "#9b86c8", 0.2));
|
|
7241
|
+
var SHELF = "shelf";
|
|
7235
7242
|
function mix(a, b, t) {
|
|
7236
7243
|
const from = rgb(a);
|
|
7237
7244
|
const to = rgb(b);
|
|
@@ -7321,11 +7328,14 @@ function figureBox(image) {
|
|
|
7321
7328
|
function headAnchor(box) {
|
|
7322
7329
|
return Math.min(0.5, (HEADROOM + 0.5) * (box.w * FILL.height / FILL.width / box.h));
|
|
7323
7330
|
}
|
|
7331
|
+
function band(box, h, anchor) {
|
|
7332
|
+
const top = Math.min(Math.max(0, anchor * box.h - h / 2), box.h - h);
|
|
7333
|
+
return { x: box.x, y: box.y + top, w: box.w, h };
|
|
7334
|
+
}
|
|
7324
7335
|
function fillBox(box, width, height, anchor) {
|
|
7325
7336
|
const h = box.w * height / width;
|
|
7326
7337
|
if (h <= box.h) {
|
|
7327
|
-
|
|
7328
|
-
return { x: box.x, y: box.y + top, w: box.w, h };
|
|
7338
|
+
return band(box, h, anchor);
|
|
7329
7339
|
}
|
|
7330
7340
|
const w = box.h * width / height;
|
|
7331
7341
|
return { x: box.x + (box.w - w) / 2, y: box.y, w, h: box.h };
|
|
@@ -7342,20 +7352,66 @@ function figure(image, box) {
|
|
|
7342
7352
|
const k = Math.min(1, FIGURE / Math.max(box.w, box.h));
|
|
7343
7353
|
return resample(image, box, Math.round(box.w * k), Math.round(box.h * k));
|
|
7344
7354
|
}
|
|
7345
|
-
function
|
|
7346
|
-
|
|
7355
|
+
function fillFrame(box, width, height, anchor, clear) {
|
|
7356
|
+
const keep = KEEP * box.h;
|
|
7357
|
+
const span = box.w * height / width;
|
|
7358
|
+
if (clear < STANDS || span > keep) {
|
|
7359
|
+
return { crop: fillBox(box, width, height, anchor), at: { x: 0, y: 0, w: width, h: height }, inset: false };
|
|
7360
|
+
}
|
|
7361
|
+
const short = 1 - span / keep;
|
|
7362
|
+
const h = height * (1 - HEADROOM * short);
|
|
7363
|
+
const w = box.w * h / keep;
|
|
7364
|
+
return {
|
|
7365
|
+
crop: band(box, keep, anchor),
|
|
7366
|
+
at: { x: (width - w) * PLACE, y: height - h, w, h },
|
|
7367
|
+
inset: true
|
|
7368
|
+
};
|
|
7369
|
+
}
|
|
7370
|
+
function paint(image, frame, width, height) {
|
|
7371
|
+
const w = Math.max(1, Math.round(frame.at.w));
|
|
7372
|
+
const h = Math.max(1, Math.round(frame.at.h));
|
|
7373
|
+
const cut = resample(image, frame.crop, w, h);
|
|
7374
|
+
const out = new Uint8Array(width * height * 4);
|
|
7375
|
+
const ox = Math.round(frame.at.x);
|
|
7376
|
+
const oy = Math.round(frame.at.y);
|
|
7377
|
+
for (let y = 0;y < h; y++) {
|
|
7378
|
+
const ty = oy + y;
|
|
7379
|
+
const from = Math.max(0, -ox);
|
|
7380
|
+
const to = Math.min(w, width - ox);
|
|
7381
|
+
if (ty < 0 || ty >= height || to <= from) {
|
|
7382
|
+
continue;
|
|
7383
|
+
}
|
|
7384
|
+
out.set(cut.data.subarray((y * w + from) * 4, (y * w + to) * 4), (ty * width + ox + from) * 4);
|
|
7385
|
+
}
|
|
7386
|
+
return { width, height, data: out };
|
|
7387
|
+
}
|
|
7388
|
+
function fill(image, box, anchor, clear) {
|
|
7389
|
+
const frame = fillFrame(box, FILL.width, FILL.height, anchor, clear);
|
|
7390
|
+
return frame.inset ? paint(image, frame, FILL.width, FILL.height) : resample(image, frame.crop, FILL.width, FILL.height);
|
|
7347
7391
|
}
|
|
7348
|
-
function tryOn(image, colors, tone, width, height) {
|
|
7392
|
+
function tryOn(image, colors, tone, width, height, clear) {
|
|
7349
7393
|
const box = figureBox(image);
|
|
7350
|
-
const
|
|
7351
|
-
|
|
7394
|
+
const frame = fillFrame(box, FILL.width, FILL.height, headAnchor(box), clear);
|
|
7395
|
+
let shown;
|
|
7396
|
+
if (frame.inset) {
|
|
7397
|
+
const view = coverBox({ x: 0, y: 0, w: FILL.width, h: FILL.height }, width, height);
|
|
7398
|
+
const k = width / view.w;
|
|
7399
|
+
shown = paint(image, {
|
|
7400
|
+
...frame,
|
|
7401
|
+
at: { x: (frame.at.x - view.x) * k, y: (frame.at.y - view.y) * k, w: frame.at.w * k, h: frame.at.h * k }
|
|
7402
|
+
}, width, height);
|
|
7403
|
+
} else {
|
|
7404
|
+
shown = resample(image, coverBox(frame.crop, width, height), width, height);
|
|
7405
|
+
}
|
|
7406
|
+
return composite(tint(shown, colors.background, tone.color), colors.background, tone.opacity);
|
|
7352
7407
|
}
|
|
7353
7408
|
function backgroundsDir(configHome) {
|
|
7354
7409
|
return join3(configHome, "ttheme", "backgrounds");
|
|
7355
7410
|
}
|
|
7356
|
-
function backdropConf(name, fillPath, opacity, from) {
|
|
7411
|
+
function backdropConf(name, fillPath, opacity, from, key) {
|
|
7357
7412
|
return [
|
|
7358
7413
|
...from ? [`# from ${from}`] : [],
|
|
7414
|
+
...key ? [`# image ${key}`] : [],
|
|
7359
7415
|
`background-image = ${fillPath}`,
|
|
7360
7416
|
"background-image-fit = cover",
|
|
7361
7417
|
"background-image-position = center",
|
|
@@ -7373,26 +7429,139 @@ function clearBackdrop(dir, name) {
|
|
|
7373
7429
|
}
|
|
7374
7430
|
}
|
|
7375
7431
|
}
|
|
7432
|
+
function imageKey(origin) {
|
|
7433
|
+
return `${origin.site}_${origin.id}`;
|
|
7434
|
+
}
|
|
7435
|
+
function shelfDir(dir, name) {
|
|
7436
|
+
return join3(dir, SHELF, name);
|
|
7437
|
+
}
|
|
7438
|
+
function belongs(file, name) {
|
|
7439
|
+
const rest = file.slice(name.length);
|
|
7440
|
+
return file.startsWith(name) && (rest === ".png" || rest === ".conf" || /^@fill-\d+\.png$/.test(rest));
|
|
7441
|
+
}
|
|
7442
|
+
function activeKey(dir, name) {
|
|
7443
|
+
try {
|
|
7444
|
+
return /^# image (\S+)$/m.exec(readFileSync2(join3(dir, `${name}.conf`), "utf8"))?.[1];
|
|
7445
|
+
} catch {
|
|
7446
|
+
return;
|
|
7447
|
+
}
|
|
7448
|
+
}
|
|
7449
|
+
function shelved(dir, name) {
|
|
7450
|
+
try {
|
|
7451
|
+
return readdirSync2(shelfDir(dir, name));
|
|
7452
|
+
} catch {
|
|
7453
|
+
return [];
|
|
7454
|
+
}
|
|
7455
|
+
}
|
|
7456
|
+
function imageKeys(dir, name) {
|
|
7457
|
+
const active = activeKey(dir, name);
|
|
7458
|
+
return [...active ? [active] : [], ...shelved(dir, name)].sort();
|
|
7459
|
+
}
|
|
7460
|
+
function shelve(dir, name) {
|
|
7461
|
+
const key = activeKey(dir, name);
|
|
7462
|
+
if (!key) {
|
|
7463
|
+
return;
|
|
7464
|
+
}
|
|
7465
|
+
const to = join3(shelfDir(dir, name), key);
|
|
7466
|
+
rmSync2(to, { recursive: true, force: true });
|
|
7467
|
+
mkdirSync(to, { recursive: true });
|
|
7468
|
+
for (const file of readdirSync2(dir)) {
|
|
7469
|
+
if (belongs(file, name)) {
|
|
7470
|
+
renameSync(join3(dir, file), join3(to, file.slice(name.length)));
|
|
7471
|
+
}
|
|
7472
|
+
}
|
|
7473
|
+
clearBackdrop(dir, name);
|
|
7474
|
+
}
|
|
7475
|
+
function unshelve(dir, name, key) {
|
|
7476
|
+
const from = join3(shelfDir(dir, name), key);
|
|
7477
|
+
for (const file of readdirSync2(from)) {
|
|
7478
|
+
renameSync(join3(from, file), join3(dir, `${name}${file}`));
|
|
7479
|
+
}
|
|
7480
|
+
rmSync2(from, { recursive: true });
|
|
7481
|
+
}
|
|
7482
|
+
function originalOf(dir, name, key) {
|
|
7483
|
+
try {
|
|
7484
|
+
return readdirSync2(join3(dir, "originals")).find((file) => file.startsWith(`${name}-${key}.`));
|
|
7485
|
+
} catch {
|
|
7486
|
+
return;
|
|
7487
|
+
}
|
|
7488
|
+
}
|
|
7489
|
+
function newest(dir, name, key) {
|
|
7490
|
+
const file = originalOf(dir, name, key);
|
|
7491
|
+
if (file) {
|
|
7492
|
+
const now = new Date;
|
|
7493
|
+
utimesSync(join3(dir, "originals", file), now, now);
|
|
7494
|
+
}
|
|
7495
|
+
}
|
|
7496
|
+
function switchImage(configHome, name, step) {
|
|
7497
|
+
const dir = backgroundsDir(configHome);
|
|
7498
|
+
const keys = imageKeys(dir, name);
|
|
7499
|
+
const now = activeKey(dir, name);
|
|
7500
|
+
if (!now || keys.length < 2) {
|
|
7501
|
+
throw new Error(`${name} has no other image`);
|
|
7502
|
+
}
|
|
7503
|
+
const at2 = (keys.indexOf(now) + step + keys.length) % keys.length;
|
|
7504
|
+
const key = keys[at2];
|
|
7505
|
+
shelve(dir, name);
|
|
7506
|
+
unshelve(dir, name, key);
|
|
7507
|
+
newest(dir, name, key);
|
|
7508
|
+
return { key, at: at2 + 1, of: keys.length };
|
|
7509
|
+
}
|
|
7510
|
+
function dropImage(configHome, name) {
|
|
7511
|
+
const dir = backgroundsDir(configHome);
|
|
7512
|
+
const files = readdirSync2(dir).filter((file) => belongs(file, name));
|
|
7513
|
+
if (files.length === 0) {
|
|
7514
|
+
throw new Error(`${name} has no image`);
|
|
7515
|
+
}
|
|
7516
|
+
const keys = imageKeys(dir, name);
|
|
7517
|
+
const now = activeKey(dir, name);
|
|
7518
|
+
const original = now && originalOf(dir, name, now);
|
|
7519
|
+
if (original) {
|
|
7520
|
+
rmSync2(join3(dir, "originals", original));
|
|
7521
|
+
}
|
|
7522
|
+
for (const file of files) {
|
|
7523
|
+
rmSync2(join3(dir, file));
|
|
7524
|
+
}
|
|
7525
|
+
clearBackdrop(dir, name);
|
|
7526
|
+
const rest = keys.filter((key) => key !== now);
|
|
7527
|
+
const next = rest[(now ? keys.indexOf(now) : 0) % rest.length];
|
|
7528
|
+
if (next) {
|
|
7529
|
+
unshelve(dir, name, next);
|
|
7530
|
+
newest(dir, name, next);
|
|
7531
|
+
}
|
|
7532
|
+
return { key: now, left: rest.length };
|
|
7533
|
+
}
|
|
7534
|
+
function retire(dir, name, key) {
|
|
7535
|
+
if (activeKey(dir, name) !== key) {
|
|
7536
|
+
shelve(dir, name);
|
|
7537
|
+
}
|
|
7538
|
+
if (key) {
|
|
7539
|
+
rmSync2(join3(shelfDir(dir, name), key), { recursive: true, force: true });
|
|
7540
|
+
}
|
|
7541
|
+
clearBackdrop(dir, name);
|
|
7542
|
+
}
|
|
7376
7543
|
function installBackdrop(configHome, colors, tone, image, original) {
|
|
7377
7544
|
const dir = backgroundsDir(configHome);
|
|
7378
7545
|
const name = colors.name;
|
|
7546
|
+
const key = imageKey(original);
|
|
7379
7547
|
mkdirSync(join3(dir, "originals"), { recursive: true });
|
|
7380
|
-
|
|
7548
|
+
retire(dir, name, key);
|
|
7381
7549
|
const box = figureBox(image);
|
|
7382
7550
|
const anchor = headAnchor(box);
|
|
7551
|
+
const clear = transparency(image);
|
|
7383
7552
|
const whole = join3(dir, `${name}.png`);
|
|
7384
7553
|
const fillPath = join3(dir, `${name}@fill-${Math.round(anchor * 100)}.png`);
|
|
7385
7554
|
const conf = join3(dir, `${name}.conf`);
|
|
7386
7555
|
const source = join3(dir, "originals", `${name}-${original.site}_${original.id}.${original.ext}`);
|
|
7387
7556
|
writeFileSync(whole, encodePng(tint(figure(image, box), colors.background, tone.color)));
|
|
7388
|
-
writeFileSync(fillPath, encodePng(tint(fill(image, box, anchor), colors.background, tone.color)));
|
|
7389
|
-
writeFileSync(conf, backdropConf(name, fillPath, tone.opacity, original.from));
|
|
7557
|
+
writeFileSync(fillPath, encodePng(tint(fill(image, box, anchor, clear), colors.background, tone.color)));
|
|
7558
|
+
writeFileSync(conf, backdropConf(name, fillPath, tone.opacity, original.from, key));
|
|
7390
7559
|
writeFileSync(source, original.bytes);
|
|
7391
7560
|
return [whole, fillPath, conf, source];
|
|
7392
7561
|
}
|
|
7393
7562
|
function origins(configHome) {
|
|
7394
7563
|
const dir = join3(backgroundsDir(configHome), "originals");
|
|
7395
|
-
const
|
|
7564
|
+
const newest2 = new Map;
|
|
7396
7565
|
let files;
|
|
7397
7566
|
try {
|
|
7398
7567
|
files = readdirSync2(dir);
|
|
@@ -7406,21 +7575,23 @@ function origins(configHome) {
|
|
|
7406
7575
|
continue;
|
|
7407
7576
|
}
|
|
7408
7577
|
const at2 = statSync(join3(dir, file)).mtimeMs;
|
|
7409
|
-
const known =
|
|
7578
|
+
const known = newest2.get(name);
|
|
7410
7579
|
if (!known || at2 > known.at) {
|
|
7411
|
-
|
|
7580
|
+
newest2.set(name, { site, id: Number(id), at: at2 });
|
|
7412
7581
|
}
|
|
7413
7582
|
}
|
|
7414
|
-
return new Map([...
|
|
7583
|
+
return new Map([...newest2].map(([name, { site, id }]) => [name, { site, id }]));
|
|
7415
7584
|
}
|
|
7416
7585
|
|
|
7417
7586
|
// src/booru.ts
|
|
7587
|
+
import { readdirSync as readdirSync3, rmSync as rmSync3, statSync as statSync2 } from "node:fs";
|
|
7418
7588
|
import { setDefaultAutoSelectFamilyAttemptTimeout } from "node:net";
|
|
7419
7589
|
import { homedir } from "node:os";
|
|
7420
7590
|
import { join as join4 } from "node:path";
|
|
7421
7591
|
import { setTimeout as sleep } from "node:timers/promises";
|
|
7422
7592
|
var PAGE = 100;
|
|
7423
7593
|
var MAX_PIXELS = 25000000;
|
|
7594
|
+
var CACHE_BYTES = 512 * 1024 * 1024;
|
|
7424
7595
|
var RATINGS = ["safe", "questionable", "explicit"];
|
|
7425
7596
|
var BLOCKS = ["nudity", "underwear"];
|
|
7426
7597
|
var EXPOSED = {
|
|
@@ -7435,10 +7606,18 @@ var CONNECT = 3000;
|
|
|
7435
7606
|
var MAX_WAIT = 60000;
|
|
7436
7607
|
var TRIES = 3;
|
|
7437
7608
|
var AGENT = `ttheme/${package_default.version} (+${package_default.homepage})`;
|
|
7609
|
+
var HELD = ["orig", "tile", "thumb", "cut"];
|
|
7438
7610
|
var paused = new Map;
|
|
7439
7611
|
var HOSTS = hostMap(process.env.TTHEME_FIND_HOSTS);
|
|
7440
7612
|
var CUTOUTS = cutoutMap(process.env.TTHEME_FIND_CUTOUTS);
|
|
7441
7613
|
setDefaultAutoSelectFamilyAttemptTimeout(CONNECT);
|
|
7614
|
+
function listing(dir) {
|
|
7615
|
+
try {
|
|
7616
|
+
return readdirSync3(dir);
|
|
7617
|
+
} catch {
|
|
7618
|
+
return [];
|
|
7619
|
+
}
|
|
7620
|
+
}
|
|
7442
7621
|
function absolute(url) {
|
|
7443
7622
|
return url.startsWith("//") ? `https:${url}` : url;
|
|
7444
7623
|
}
|
|
@@ -7762,8 +7941,38 @@ function mates(owners) {
|
|
|
7762
7941
|
}
|
|
7763
7942
|
return byOwner;
|
|
7764
7943
|
}
|
|
7944
|
+
function cacheRoot() {
|
|
7945
|
+
return join4(process.env.XDG_CACHE_HOME ?? join4(homedir(), ".cache"), "ttheme");
|
|
7946
|
+
}
|
|
7765
7947
|
function cacheDir(site) {
|
|
7766
|
-
return join4(
|
|
7948
|
+
return join4(cacheRoot(), site.key);
|
|
7949
|
+
}
|
|
7950
|
+
function sweepCache(limit = CACHE_BYTES, root2 = cacheRoot()) {
|
|
7951
|
+
const files = [];
|
|
7952
|
+
let total = 0;
|
|
7953
|
+
for (const site of listing(root2)) {
|
|
7954
|
+
for (const kind of HELD) {
|
|
7955
|
+
const dir = join4(root2, site, kind);
|
|
7956
|
+
for (const name of listing(dir)) {
|
|
7957
|
+
const path2 = join4(dir, name);
|
|
7958
|
+
try {
|
|
7959
|
+
const { size, mtimeMs } = statSync2(path2);
|
|
7960
|
+
files.push({ path: path2, size, at: mtimeMs });
|
|
7961
|
+
total += size;
|
|
7962
|
+
} catch {}
|
|
7963
|
+
}
|
|
7964
|
+
}
|
|
7965
|
+
}
|
|
7966
|
+
files.sort((a, b) => a.at - b.at);
|
|
7967
|
+
for (const file of files) {
|
|
7968
|
+
if (total <= limit) {
|
|
7969
|
+
return;
|
|
7970
|
+
}
|
|
7971
|
+
try {
|
|
7972
|
+
rmSync3(file.path, { force: true });
|
|
7973
|
+
total -= file.size;
|
|
7974
|
+
} catch {}
|
|
7975
|
+
}
|
|
7767
7976
|
}
|
|
7768
7977
|
function retryAfter(value, now) {
|
|
7769
7978
|
if (value !== null && /^\s*\d+\s*$/.test(value)) {
|
|
@@ -7846,7 +8055,7 @@ async function fetchBytes(site, url, signal, progress) {
|
|
|
7846
8055
|
}
|
|
7847
8056
|
|
|
7848
8057
|
// src/catalog.ts
|
|
7849
|
-
import { existsSync, mkdirSync as mkdirSync2, readFileSync as
|
|
8058
|
+
import { existsSync, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "node:fs";
|
|
7850
8059
|
import { dirname, join as join5 } from "node:path";
|
|
7851
8060
|
var REGISTRY_URL = "https://kecan0406.github.io/ttheme/manifest.json";
|
|
7852
8061
|
function catalogPath(configHome) {
|
|
@@ -7863,7 +8072,7 @@ function readCatalog(configHome) {
|
|
|
7863
8072
|
if (!existsSync(path2)) {
|
|
7864
8073
|
throw new Error(`no catalog at ${path2} — run \`ttheme init\` first`);
|
|
7865
8074
|
}
|
|
7866
|
-
return parseCatalog(
|
|
8075
|
+
return parseCatalog(readFileSync3(path2, "utf8"));
|
|
7867
8076
|
}
|
|
7868
8077
|
function parseCatalog(source) {
|
|
7869
8078
|
let doc;
|
|
@@ -7925,7 +8134,6 @@ function search(palettes, query) {
|
|
|
7925
8134
|
|
|
7926
8135
|
// src/cutout.ts
|
|
7927
8136
|
import { spawn } from "node:child_process";
|
|
7928
|
-
import { readFileSync as readFileSync3 } from "node:fs";
|
|
7929
8137
|
var TIMEOUT2 = 30000;
|
|
7930
8138
|
var LEAST = 3;
|
|
7931
8139
|
var MOST = 97;
|
|
@@ -7967,16 +8175,12 @@ function removeBackground(input, output, signal) {
|
|
|
7967
8175
|
});
|
|
7968
8176
|
child.on("error", reject);
|
|
7969
8177
|
child.on("close", (code) => {
|
|
7970
|
-
if (code
|
|
7971
|
-
|
|
7972
|
-
`).at(-1) || `osascript exited ${code}`));
|
|
8178
|
+
if (code === 0) {
|
|
8179
|
+
resolve();
|
|
7973
8180
|
return;
|
|
7974
8181
|
}
|
|
7975
|
-
|
|
7976
|
-
|
|
7977
|
-
} catch (error) {
|
|
7978
|
-
reject(error);
|
|
7979
|
-
}
|
|
8182
|
+
reject(new Error(failure.trim().split(`
|
|
8183
|
+
`).at(-1) || `osascript exited ${code}`));
|
|
7980
8184
|
});
|
|
7981
8185
|
});
|
|
7982
8186
|
}
|
|
@@ -8108,9 +8312,10 @@ function dims(tile) {
|
|
|
8108
8312
|
}
|
|
8109
8313
|
function foot(line, cols, accent, spec) {
|
|
8110
8314
|
const keys = [...spec.keys ?? []];
|
|
8315
|
+
let lead = spec.lead;
|
|
8111
8316
|
let right = spec.right;
|
|
8112
8317
|
const size = () => {
|
|
8113
|
-
const segs2 = [...
|
|
8318
|
+
const segs2 = [...lead ? [width(lead[0])] : [], ...keys.map(([k, l]) => width(k) + 1 + width(l))];
|
|
8114
8319
|
const left = (spec.badge ? width(spec.badge) + 4 : 0) + segs2.reduce((n, w) => n + w, 0) + 3 * Math.max(0, segs2.length - 1);
|
|
8115
8320
|
return left + (right ? 3 + width(right[0]) + 1 + width(right[1]) : 0);
|
|
8116
8321
|
};
|
|
@@ -8125,12 +8330,16 @@ function foot(line, cols, accent, spec) {
|
|
|
8125
8330
|
break;
|
|
8126
8331
|
}
|
|
8127
8332
|
}
|
|
8333
|
+
if (lead && size() > cols) {
|
|
8334
|
+
const keep = Math.max(0, width(lead[0]) - (size() - cols) - 1);
|
|
8335
|
+
lead = [`${Array.from(lead[0]).slice(0, keep).join("")}…`, lead[1]];
|
|
8336
|
+
}
|
|
8128
8337
|
let c = 0;
|
|
8129
8338
|
if (spec.badge) {
|
|
8130
8339
|
c = line.put(0, ` ${spec.badge} `, `\x1B[7;1m${accent}`) + 2;
|
|
8131
8340
|
}
|
|
8132
8341
|
const segs = [
|
|
8133
|
-
...
|
|
8342
|
+
...lead ? [[lead]] : [],
|
|
8134
8343
|
...keys.map(([k, l]) => [
|
|
8135
8344
|
[k, B],
|
|
8136
8345
|
[` ${l}`, D]
|
|
@@ -8530,7 +8739,7 @@ function renderFind(view, cols, rows) {
|
|
|
8530
8739
|
}
|
|
8531
8740
|
|
|
8532
8741
|
// src/palettes.ts
|
|
8533
|
-
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, rmSync as
|
|
8742
|
+
import { existsSync as existsSync2, mkdirSync as mkdirSync3, readFileSync as readFileSync4, rmSync as rmSync4, writeFileSync as writeFileSync3 } from "node:fs";
|
|
8534
8743
|
import { homedir as homedir2 } from "node:os";
|
|
8535
8744
|
import { dirname as dirname2, join as join6 } from "node:path";
|
|
8536
8745
|
var EMITTERS = { ghostty, kitty, alacritty };
|
|
@@ -8552,6 +8761,7 @@ function readInstalled(configHome2) {
|
|
|
8552
8761
|
return {
|
|
8553
8762
|
terminals: doc.terminals.filter((t) => INIT_TERMINALS.includes(t)),
|
|
8554
8763
|
...doc.startup ? { startup: doc.startup } : {},
|
|
8764
|
+
...doc.keepTheme ? { keepTheme: true } : {},
|
|
8555
8765
|
palettes: doc.palettes
|
|
8556
8766
|
};
|
|
8557
8767
|
}
|
|
@@ -8632,7 +8842,7 @@ function sync(configHome2, catalog, state) {
|
|
|
8632
8842
|
writeFileSync3(path2, content);
|
|
8633
8843
|
written.push(path2);
|
|
8634
8844
|
};
|
|
8635
|
-
const startup = startupPalette(state);
|
|
8845
|
+
const startup = state.keepTheme ? undefined : startupPalette(state);
|
|
8636
8846
|
for (const terminal of state.terminals) {
|
|
8637
8847
|
for (const entry of entries) {
|
|
8638
8848
|
for (const { file: file2, content } of themeFiles(terminal, toTheme(entry, catalog))) {
|
|
@@ -8658,7 +8868,7 @@ function forget(configHome2, catalog, terminals, names) {
|
|
|
8658
8868
|
for (const { file } of themeFiles(terminal, toTheme(entry, catalog))) {
|
|
8659
8869
|
const path2 = join6(configHome2, terminal, "themes", file);
|
|
8660
8870
|
if (existsSync2(path2)) {
|
|
8661
|
-
|
|
8871
|
+
rmSync4(path2, { force: true });
|
|
8662
8872
|
removed.push(path2);
|
|
8663
8873
|
}
|
|
8664
8874
|
}
|
|
@@ -8667,6 +8877,117 @@ function forget(configHome2, catalog, terminals, names) {
|
|
|
8667
8877
|
return removed;
|
|
8668
8878
|
}
|
|
8669
8879
|
|
|
8880
|
+
// src/render.ts
|
|
8881
|
+
import { mkdirSync as mkdirSync4, readFileSync as readFileSync5, writeFileSync as writeFileSync4 } from "node:fs";
|
|
8882
|
+
import { dirname as dirname3 } from "node:path";
|
|
8883
|
+
import { isMainThread, parentPort, Worker } from "node:worker_threads";
|
|
8884
|
+
var LANES = { thumb: "tile", show: "view", backdrop: "view" };
|
|
8885
|
+
function work(task) {
|
|
8886
|
+
const image = decodeImage(new Uint8Array(readFileSync5(task.from)), MAX_PIXELS);
|
|
8887
|
+
if (task.job === "backdrop") {
|
|
8888
|
+
installBackdrop(task.home, task.colors, task.tone, image, {
|
|
8889
|
+
...task.origin,
|
|
8890
|
+
bytes: new Uint8Array(readFileSync5(task.source))
|
|
8891
|
+
});
|
|
8892
|
+
return 0;
|
|
8893
|
+
}
|
|
8894
|
+
if (task.job === "thumb") {
|
|
8895
|
+
mkdirSync4(dirname3(task.to), { recursive: true });
|
|
8896
|
+
writeFileSync4(task.to, encodePng(contain(image, task.width, task.height)));
|
|
8897
|
+
return 0;
|
|
8898
|
+
}
|
|
8899
|
+
const clear = transparency(image);
|
|
8900
|
+
mkdirSync4(dirname3(task.to), { recursive: true });
|
|
8901
|
+
writeFileSync4(task.to, encodePng(tryOn(image, task.colors, task.tone, task.width, task.height, clear)));
|
|
8902
|
+
return clear;
|
|
8903
|
+
}
|
|
8904
|
+
function serveRenders(port) {
|
|
8905
|
+
port.on("message", (task) => {
|
|
8906
|
+
try {
|
|
8907
|
+
port.postMessage({ id: task.id, value: work(task) });
|
|
8908
|
+
} catch (error) {
|
|
8909
|
+
port.postMessage({ id: task.id, error: error instanceof Error ? error.message : String(error) });
|
|
8910
|
+
}
|
|
8911
|
+
});
|
|
8912
|
+
}
|
|
8913
|
+
|
|
8914
|
+
class Line2 {
|
|
8915
|
+
worker;
|
|
8916
|
+
next = 1;
|
|
8917
|
+
waiting = new Map;
|
|
8918
|
+
send(task) {
|
|
8919
|
+
const id = this.next++;
|
|
8920
|
+
return new Promise((ok, no) => {
|
|
8921
|
+
const worker = this.open();
|
|
8922
|
+
this.waiting.set(id, { ok, no });
|
|
8923
|
+
worker.ref();
|
|
8924
|
+
worker.postMessage({ ...task, id });
|
|
8925
|
+
});
|
|
8926
|
+
}
|
|
8927
|
+
close() {
|
|
8928
|
+
this.worker?.terminate();
|
|
8929
|
+
this.worker = undefined;
|
|
8930
|
+
this.drop(new Error("renderer closed"));
|
|
8931
|
+
}
|
|
8932
|
+
open() {
|
|
8933
|
+
if (this.worker) {
|
|
8934
|
+
return this.worker;
|
|
8935
|
+
}
|
|
8936
|
+
const worker = new Worker(import.meta.filename);
|
|
8937
|
+
worker.unref();
|
|
8938
|
+
worker.on("message", ({ id, value, error }) => {
|
|
8939
|
+
const held = this.waiting.get(id);
|
|
8940
|
+
this.waiting.delete(id);
|
|
8941
|
+
if (this.waiting.size === 0) {
|
|
8942
|
+
worker.unref();
|
|
8943
|
+
}
|
|
8944
|
+
if (error !== undefined) {
|
|
8945
|
+
held?.no(new Error(error));
|
|
8946
|
+
} else {
|
|
8947
|
+
held?.ok(value);
|
|
8948
|
+
}
|
|
8949
|
+
});
|
|
8950
|
+
const lost = (error) => {
|
|
8951
|
+
if (this.worker === worker) {
|
|
8952
|
+
this.worker = undefined;
|
|
8953
|
+
}
|
|
8954
|
+
this.drop(error instanceof Error ? error : new Error("renderer stopped"));
|
|
8955
|
+
};
|
|
8956
|
+
worker.on("error", lost);
|
|
8957
|
+
worker.on("exit", () => lost(undefined));
|
|
8958
|
+
this.worker = worker;
|
|
8959
|
+
return worker;
|
|
8960
|
+
}
|
|
8961
|
+
drop(error) {
|
|
8962
|
+
for (const held of this.waiting.values()) {
|
|
8963
|
+
held.no(error);
|
|
8964
|
+
}
|
|
8965
|
+
this.waiting.clear();
|
|
8966
|
+
}
|
|
8967
|
+
}
|
|
8968
|
+
|
|
8969
|
+
class Renderer {
|
|
8970
|
+
lines = new Map;
|
|
8971
|
+
run(task) {
|
|
8972
|
+
const lane = LANES[task.job];
|
|
8973
|
+
let line = this.lines.get(lane);
|
|
8974
|
+
if (!line) {
|
|
8975
|
+
line = new Line2;
|
|
8976
|
+
this.lines.set(lane, line);
|
|
8977
|
+
}
|
|
8978
|
+
return line.send(task);
|
|
8979
|
+
}
|
|
8980
|
+
close() {
|
|
8981
|
+
for (const line of this.lines.values()) {
|
|
8982
|
+
line.close();
|
|
8983
|
+
}
|
|
8984
|
+
this.lines.clear();
|
|
8985
|
+
}
|
|
8986
|
+
}
|
|
8987
|
+
if (!isMainThread && parentPort) {
|
|
8988
|
+
serveRenders(parentPort);
|
|
8989
|
+
}
|
|
8990
|
+
|
|
8670
8991
|
// src/unblock.ts
|
|
8671
8992
|
import { connect, createServer } from "node:net";
|
|
8672
8993
|
var SPLIT = 20;
|
|
@@ -8801,12 +9122,13 @@ function initial(setting, raw) {
|
|
|
8801
9122
|
}
|
|
8802
9123
|
return setting.choices.find((choice) => choice === raw) ?? setting.choices[0];
|
|
8803
9124
|
}
|
|
8804
|
-
var
|
|
9125
|
+
var PROBE = 12;
|
|
9126
|
+
var THUMB = 12;
|
|
8805
9127
|
var PRELOAD = 2;
|
|
8806
9128
|
var SETTLE = 150;
|
|
8807
9129
|
var ESCAPE = 30;
|
|
8808
9130
|
var TRY_WIDTH = 1280;
|
|
8809
|
-
var LOOKAHEAD =
|
|
9131
|
+
var LOOKAHEAD = 2;
|
|
8810
9132
|
function blank(key, searching) {
|
|
8811
9133
|
return {
|
|
8812
9134
|
key,
|
|
@@ -8845,19 +9167,16 @@ function incomplete(input) {
|
|
|
8845
9167
|
const at2 = input.lastIndexOf("\x1B");
|
|
8846
9168
|
return at2 !== -1 && /^\[?[0-9;]*$/.test(input.slice(at2 + 1));
|
|
8847
9169
|
}
|
|
8848
|
-
function tick() {
|
|
8849
|
-
return new Promise((resolve2) => setImmediate(resolve2));
|
|
8850
|
-
}
|
|
8851
9170
|
function readCache(site, name) {
|
|
8852
9171
|
try {
|
|
8853
|
-
return JSON.parse(
|
|
9172
|
+
return JSON.parse(readFileSync6(join7(cacheDir(site), name), "utf8"));
|
|
8854
9173
|
} catch {
|
|
8855
9174
|
return {};
|
|
8856
9175
|
}
|
|
8857
9176
|
}
|
|
8858
9177
|
function writeCache(site, name, data) {
|
|
8859
|
-
|
|
8860
|
-
|
|
9178
|
+
mkdirSync5(cacheDir(site), { recursive: true });
|
|
9179
|
+
writeFileSync5(join7(cacheDir(site), name), `${JSON.stringify(data)}
|
|
8861
9180
|
`);
|
|
8862
9181
|
}
|
|
8863
9182
|
|
|
@@ -8884,6 +9203,8 @@ class Finder {
|
|
|
8884
9203
|
unsaved = new Set;
|
|
8885
9204
|
thumbQueue = [];
|
|
8886
9205
|
thumbing = 0;
|
|
9206
|
+
clarity = new Map;
|
|
9207
|
+
renders = new Renderer;
|
|
8887
9208
|
sent = new Map;
|
|
8888
9209
|
placed = new Map;
|
|
8889
9210
|
current;
|
|
@@ -8955,7 +9276,7 @@ class Finder {
|
|
|
8955
9276
|
return `${site.key}:${id}`;
|
|
8956
9277
|
}
|
|
8957
9278
|
origPath(site, id, ext) {
|
|
8958
|
-
return join7(
|
|
9279
|
+
return join7(cacheDir(site), "orig", `${id}.${ext}`);
|
|
8959
9280
|
}
|
|
8960
9281
|
tileOf(site, post2, variants) {
|
|
8961
9282
|
const version2 = rendition(post2) ?? post2;
|
|
@@ -9024,7 +9345,10 @@ class Finder {
|
|
|
9024
9345
|
this.write("\x1B_Ga=d,d=A,q=2\x1B\\\x1B[H\x1B[J");
|
|
9025
9346
|
stdin.setRawMode(false);
|
|
9026
9347
|
stdin.pause();
|
|
9027
|
-
|
|
9348
|
+
this.saveProbes();
|
|
9349
|
+
this.renders.close();
|
|
9350
|
+
rmSync5(this.scratch, { recursive: true, force: true });
|
|
9351
|
+
sweepCache();
|
|
9028
9352
|
return code;
|
|
9029
9353
|
}
|
|
9030
9354
|
write(text) {
|
|
@@ -9085,7 +9409,7 @@ class Finder {
|
|
|
9085
9409
|
this.rows = process.stdout.rows || this.rows;
|
|
9086
9410
|
this.scroll();
|
|
9087
9411
|
if (this.view.mode === "try" && this.current) {
|
|
9088
|
-
this.
|
|
9412
|
+
this.reveal();
|
|
9089
9413
|
}
|
|
9090
9414
|
this.pump();
|
|
9091
9415
|
this.draw();
|
|
@@ -9260,9 +9584,9 @@ class Finder {
|
|
|
9260
9584
|
save(changed) {
|
|
9261
9585
|
const path2 = join7(this.home, "ttheme", "config.zsh");
|
|
9262
9586
|
try {
|
|
9263
|
-
const before = existsSync3(path2) ?
|
|
9587
|
+
const before = existsSync3(path2) ? readFileSync6(path2, "utf8") : "";
|
|
9264
9588
|
const after = changed.reduce((text, setting) => withSetting(text, setting.name, this.setting(setting.name)), before);
|
|
9265
|
-
|
|
9589
|
+
writeFileSync5(path2, after);
|
|
9266
9590
|
} catch (error) {
|
|
9267
9591
|
this.view.error = error instanceof Error ? error.message : String(error);
|
|
9268
9592
|
}
|
|
@@ -9489,12 +9813,12 @@ class Finder {
|
|
|
9489
9813
|
this.show();
|
|
9490
9814
|
this.draw();
|
|
9491
9815
|
const tags = this.query(site);
|
|
9816
|
+
this.tally(gen, site, board, tags);
|
|
9492
9817
|
try {
|
|
9493
|
-
const
|
|
9818
|
+
const owners = await this.mateOwners(site);
|
|
9494
9819
|
if (gen !== this.gen) {
|
|
9495
9820
|
return;
|
|
9496
9821
|
}
|
|
9497
|
-
board.total = total;
|
|
9498
9822
|
const room = tagsOf(tags) + 1 <= site.tagBudget;
|
|
9499
9823
|
board.sources = [
|
|
9500
9824
|
...room ? [...owners.keys()].map((owner) => ({ tags: `${tags} user:${owner}`, page: 0, done: false })) : [],
|
|
@@ -9507,6 +9831,16 @@ class Finder {
|
|
|
9507
9831
|
this.fail(gen, error);
|
|
9508
9832
|
}
|
|
9509
9833
|
}
|
|
9834
|
+
async tally(gen, site, board, tags) {
|
|
9835
|
+
try {
|
|
9836
|
+
const total = await fetchCount(site, tags, this.signal);
|
|
9837
|
+
if (gen === this.gen) {
|
|
9838
|
+
board.total = total;
|
|
9839
|
+
this.show();
|
|
9840
|
+
this.draw();
|
|
9841
|
+
}
|
|
9842
|
+
} catch {}
|
|
9843
|
+
}
|
|
9510
9844
|
fail(gen, error) {
|
|
9511
9845
|
if (gen !== this.gen || this.signal.aborted) {
|
|
9512
9846
|
return;
|
|
@@ -9521,6 +9855,24 @@ class Finder {
|
|
|
9521
9855
|
const { perRow, rowsVis } = gridShape(this.cols, this.rows);
|
|
9522
9856
|
return this.view.tiles.length < (this.board.top + rowsVis + LOOKAHEAD) * perRow;
|
|
9523
9857
|
}
|
|
9858
|
+
async nextPage(site, board, gen) {
|
|
9859
|
+
const source = board.sources.find((s) => !s.done);
|
|
9860
|
+
if (!source) {
|
|
9861
|
+
return;
|
|
9862
|
+
}
|
|
9863
|
+
const posts = await fetchPosts(site, source.tags, source.page, this.signal);
|
|
9864
|
+
if (gen !== this.gen) {
|
|
9865
|
+
return;
|
|
9866
|
+
}
|
|
9867
|
+
source.page++;
|
|
9868
|
+
source.done = posts.length < PAGE;
|
|
9869
|
+
for (const post2 of posts) {
|
|
9870
|
+
if (!board.seen.has(post2.id)) {
|
|
9871
|
+
board.seen.add(post2.id);
|
|
9872
|
+
board.queue.push(post2);
|
|
9873
|
+
}
|
|
9874
|
+
}
|
|
9875
|
+
}
|
|
9524
9876
|
async pump() {
|
|
9525
9877
|
const gen = this.gen;
|
|
9526
9878
|
const board = this.board;
|
|
@@ -9529,40 +9881,40 @@ class Finder {
|
|
|
9529
9881
|
}
|
|
9530
9882
|
this.pumping = gen;
|
|
9531
9883
|
const site = this.site;
|
|
9884
|
+
const flight = [];
|
|
9885
|
+
let page;
|
|
9532
9886
|
try {
|
|
9533
9887
|
board.searching = true;
|
|
9534
|
-
while (gen === this.gen
|
|
9535
|
-
|
|
9536
|
-
const
|
|
9537
|
-
|
|
9538
|
-
|
|
9539
|
-
|
|
9540
|
-
const
|
|
9541
|
-
|
|
9542
|
-
|
|
9543
|
-
}
|
|
9544
|
-
source.page++;
|
|
9545
|
-
source.done = posts.length < PAGE;
|
|
9546
|
-
for (const post2 of posts) {
|
|
9547
|
-
if (!board.seen.has(post2.id)) {
|
|
9548
|
-
board.seen.add(post2.id);
|
|
9549
|
-
board.queue.push(post2);
|
|
9888
|
+
while (gen === this.gen) {
|
|
9889
|
+
while (flight.length < PROBE && board.queue.length > 0 && this.wants()) {
|
|
9890
|
+
const post2 = board.queue.shift();
|
|
9891
|
+
flight.push({ post: post2, passed: this.passes(site, post2) });
|
|
9892
|
+
}
|
|
9893
|
+
if (!page && board.queue.length < PROBE && board.sources.some((s) => !s.done) && this.wants()) {
|
|
9894
|
+
const job = this.nextPage(site, board, gen).then(() => {
|
|
9895
|
+
if (page === job) {
|
|
9896
|
+
page = undefined;
|
|
9550
9897
|
}
|
|
9898
|
+
});
|
|
9899
|
+
job.catch(() => {});
|
|
9900
|
+
page = job;
|
|
9901
|
+
}
|
|
9902
|
+
const head = flight.shift();
|
|
9903
|
+
if (!head) {
|
|
9904
|
+
if (!page) {
|
|
9905
|
+
break;
|
|
9551
9906
|
}
|
|
9907
|
+
await page;
|
|
9552
9908
|
continue;
|
|
9553
9909
|
}
|
|
9554
|
-
const
|
|
9555
|
-
const passed = await Promise.all(batch.map((post2) => this.passes(site, post2)));
|
|
9556
|
-
this.saveProbes(site);
|
|
9910
|
+
const passed = await head.passed;
|
|
9557
9911
|
if (gen !== this.gen) {
|
|
9558
9912
|
return;
|
|
9559
9913
|
}
|
|
9560
|
-
|
|
9561
|
-
|
|
9562
|
-
|
|
9563
|
-
|
|
9564
|
-
}
|
|
9565
|
-
});
|
|
9914
|
+
board.checked++;
|
|
9915
|
+
if (passed) {
|
|
9916
|
+
this.admit(site, head.post);
|
|
9917
|
+
}
|
|
9566
9918
|
this.show();
|
|
9567
9919
|
this.draw();
|
|
9568
9920
|
}
|
|
@@ -9574,6 +9926,7 @@ class Finder {
|
|
|
9574
9926
|
} catch (error) {
|
|
9575
9927
|
this.fail(gen, error);
|
|
9576
9928
|
} finally {
|
|
9929
|
+
this.saveProbes();
|
|
9577
9930
|
if (this.pumping === gen) {
|
|
9578
9931
|
this.pumping = 0;
|
|
9579
9932
|
}
|
|
@@ -9615,10 +9968,14 @@ class Finder {
|
|
|
9615
9968
|
return false;
|
|
9616
9969
|
}
|
|
9617
9970
|
}
|
|
9618
|
-
saveProbes(
|
|
9619
|
-
|
|
9620
|
-
|
|
9971
|
+
saveProbes() {
|
|
9972
|
+
for (const key of this.unsaved) {
|
|
9973
|
+
const site = SITES.find((s) => s.key === key);
|
|
9974
|
+
if (site) {
|
|
9975
|
+
writeCache(site, "probes.json", this.probes(site));
|
|
9976
|
+
}
|
|
9621
9977
|
}
|
|
9978
|
+
this.unsaved.clear();
|
|
9622
9979
|
}
|
|
9623
9980
|
admit(site, post2) {
|
|
9624
9981
|
this.posts.set(this.mark(site, post2.id), post2);
|
|
@@ -9644,22 +10001,27 @@ class Finder {
|
|
|
9644
10001
|
}
|
|
9645
10002
|
const found = origins(this.home);
|
|
9646
10003
|
const known = readCache(site, "owners.json");
|
|
9647
|
-
const
|
|
9648
|
-
for (const sibling of this.catalog.palettes) {
|
|
10004
|
+
const siblings = this.catalog.palettes.flatMap((sibling) => {
|
|
9649
10005
|
const origin = found.get(sibling.name);
|
|
9650
|
-
|
|
9651
|
-
|
|
10006
|
+
return sibling.group === this.entry.group && sibling.name !== this.entry.name && origin?.site === site.key ? [{ name: sibling.name, id: origin.id }] : [];
|
|
10007
|
+
});
|
|
10008
|
+
const asked = await Promise.all(siblings.map(async (sibling) => {
|
|
10009
|
+
const owner = known[sibling.id];
|
|
10010
|
+
if (owner !== undefined) {
|
|
10011
|
+
return { ...sibling, owner };
|
|
9652
10012
|
}
|
|
9653
|
-
|
|
9654
|
-
|
|
9655
|
-
|
|
9656
|
-
|
|
9657
|
-
|
|
9658
|
-
|
|
9659
|
-
|
|
9660
|
-
|
|
10013
|
+
try {
|
|
10014
|
+
return { ...sibling, owner: (await fetchPost(site, sibling.id, this.signal))?.owner ?? "" };
|
|
10015
|
+
} catch {
|
|
10016
|
+
return;
|
|
10017
|
+
}
|
|
10018
|
+
}));
|
|
10019
|
+
const byPalette = new Map;
|
|
10020
|
+
for (const sibling of asked) {
|
|
10021
|
+
if (sibling) {
|
|
10022
|
+
known[sibling.id] = sibling.owner;
|
|
10023
|
+
byPalette.set(sibling.name, sibling.owner);
|
|
9661
10024
|
}
|
|
9662
|
-
byPalette.set(sibling.name, owner);
|
|
9663
10025
|
}
|
|
9664
10026
|
writeCache(site, "owners.json", known);
|
|
9665
10027
|
const owners = mates(byPalette);
|
|
@@ -9668,7 +10030,7 @@ class Finder {
|
|
|
9668
10030
|
}
|
|
9669
10031
|
async cached(site, path2, url, progress2) {
|
|
9670
10032
|
if (existsSync3(path2)) {
|
|
9671
|
-
return
|
|
10033
|
+
return statSync3(path2).size;
|
|
9672
10034
|
}
|
|
9673
10035
|
const running = this.inflight.get(path2);
|
|
9674
10036
|
if (running) {
|
|
@@ -9676,9 +10038,9 @@ class Finder {
|
|
|
9676
10038
|
}
|
|
9677
10039
|
const job = (async () => {
|
|
9678
10040
|
const bytes = await fetchBytes(site, url, this.signal, progress2);
|
|
9679
|
-
|
|
9680
|
-
|
|
9681
|
-
return bytes;
|
|
10041
|
+
mkdirSync5(dirname4(path2), { recursive: true });
|
|
10042
|
+
writeFileSync5(path2, bytes);
|
|
10043
|
+
return bytes.length;
|
|
9682
10044
|
})();
|
|
9683
10045
|
this.inflight.set(path2, job);
|
|
9684
10046
|
try {
|
|
@@ -9688,7 +10050,7 @@ class Finder {
|
|
|
9688
10050
|
}
|
|
9689
10051
|
}
|
|
9690
10052
|
thumbs() {
|
|
9691
|
-
while (this.thumbing <
|
|
10053
|
+
while (this.thumbing < THUMB && this.thumbQueue.length > 0) {
|
|
9692
10054
|
const { site, post: post2 } = this.thumbQueue.shift();
|
|
9693
10055
|
this.thumbing++;
|
|
9694
10056
|
this.thumb(site, post2).catch(() => {}).finally(() => {
|
|
@@ -9700,12 +10062,11 @@ class Finder {
|
|
|
9700
10062
|
async thumb(site, post2) {
|
|
9701
10063
|
const w = TILE.cols * this.cell.w;
|
|
9702
10064
|
const h = TILE.rows * this.cell.h;
|
|
9703
|
-
const path2 = join7(
|
|
10065
|
+
const path2 = join7(cacheDir(site), "tile", `${post2.id}-${w}x${h}.png`);
|
|
9704
10066
|
if (!existsSync3(path2)) {
|
|
9705
10067
|
const thumb = join7(cacheDir(site), "thumb", `${post2.id}.${extension(post2.preview)}`);
|
|
9706
|
-
|
|
9707
|
-
|
|
9708
|
-
writeFileSync4(path2, encodePng(contain(decodeImage(bytes, MAX_PIXELS), w, h)));
|
|
10068
|
+
await this.cached(site, thumb, post2.preview);
|
|
10069
|
+
await this.renders.run({ job: "thumb", from: thumb, to: path2, width: w, height: h });
|
|
9709
10070
|
}
|
|
9710
10071
|
this.thumbPath.set(this.mark(site, post2.id), path2);
|
|
9711
10072
|
this.show();
|
|
@@ -9721,8 +10082,7 @@ class Finder {
|
|
|
9721
10082
|
return;
|
|
9722
10083
|
}
|
|
9723
10084
|
if (this.current?.id === tile.id) {
|
|
9724
|
-
this.
|
|
9725
|
-
this.draw();
|
|
10085
|
+
this.reveal();
|
|
9726
10086
|
return;
|
|
9727
10087
|
}
|
|
9728
10088
|
this.settle = setTimeout(() => void this.load(tile), SETTLE);
|
|
@@ -9744,9 +10104,9 @@ class Finder {
|
|
|
9744
10104
|
view.fetching = { id: tile.id, got: 0, size: 0 };
|
|
9745
10105
|
this.draw();
|
|
9746
10106
|
}
|
|
9747
|
-
const
|
|
10107
|
+
const size = await this.cached(site, path2, version2.file, (got, total) => {
|
|
9748
10108
|
if (view.fetching?.id === tile.id) {
|
|
9749
|
-
view.fetching = { id: tile.id, got, size };
|
|
10109
|
+
view.fetching = { id: tile.id, got, size: total };
|
|
9750
10110
|
this.draw();
|
|
9751
10111
|
}
|
|
9752
10112
|
});
|
|
@@ -9754,42 +10114,48 @@ class Finder {
|
|
|
9754
10114
|
return;
|
|
9755
10115
|
}
|
|
9756
10116
|
view.fetching = undefined;
|
|
10117
|
+
if (site !== this.site) {
|
|
10118
|
+
return;
|
|
10119
|
+
}
|
|
10120
|
+
const current = { site, id: tile.id, path: path2, ext: version2.ext, size, using: "plain", failed: false };
|
|
9757
10121
|
view.preparing = tile.id;
|
|
9758
10122
|
this.flush();
|
|
9759
|
-
await
|
|
9760
|
-
|
|
9761
|
-
if (site !== this.site) {
|
|
10123
|
+
const plain2 = await this.render(current, "plain");
|
|
10124
|
+
if (control.signal.aborted || site !== this.site) {
|
|
9762
10125
|
return;
|
|
9763
10126
|
}
|
|
9764
|
-
|
|
9765
|
-
site,
|
|
9766
|
-
id: tile.id,
|
|
9767
|
-
image,
|
|
9768
|
-
plain: image,
|
|
9769
|
-
failed: false,
|
|
9770
|
-
bytes,
|
|
9771
|
-
ext: version2.ext,
|
|
9772
|
-
clear: transparency(image)
|
|
9773
|
-
};
|
|
9774
|
-
if (current.clear === 0 && canRemoveBackground() && this.setting("TTHEME_FIND_REMOVE_BG") !== "off") {
|
|
10127
|
+
if (plain2.clear === 0 && canRemoveBackground() && this.setting("TTHEME_FIND_REMOVE_BG") !== "off") {
|
|
9775
10128
|
view.preparing = undefined;
|
|
9776
10129
|
view.cutting = tile.id;
|
|
9777
10130
|
this.flush();
|
|
9778
|
-
|
|
10131
|
+
current.cut = await this.cutOut(site, tile.id, path2, control.signal);
|
|
9779
10132
|
if (control.signal.aborted || site !== this.site) {
|
|
9780
10133
|
return;
|
|
9781
10134
|
}
|
|
9782
|
-
|
|
9783
|
-
|
|
9784
|
-
|
|
9785
|
-
|
|
10135
|
+
view.cutting = undefined;
|
|
10136
|
+
if (current.cut) {
|
|
10137
|
+
view.preparing = tile.id;
|
|
10138
|
+
this.flush();
|
|
10139
|
+
const made = await this.render(current, "cut").catch(() => {
|
|
10140
|
+
return;
|
|
10141
|
+
});
|
|
10142
|
+
if (control.signal.aborted || site !== this.site) {
|
|
10143
|
+
return;
|
|
10144
|
+
}
|
|
10145
|
+
if (made && keepable(made.clear)) {
|
|
10146
|
+
current.using = "cut";
|
|
10147
|
+
} else {
|
|
10148
|
+
rmSync5(current.cut, { force: true });
|
|
10149
|
+
current.cut = undefined;
|
|
10150
|
+
current.failed = true;
|
|
10151
|
+
}
|
|
9786
10152
|
} else {
|
|
9787
10153
|
current.failed = true;
|
|
9788
10154
|
}
|
|
9789
10155
|
}
|
|
9790
10156
|
this.current = current;
|
|
9791
10157
|
if (view.tiles[view.focus]?.id === tile.id) {
|
|
9792
|
-
this.present();
|
|
10158
|
+
await this.present();
|
|
9793
10159
|
}
|
|
9794
10160
|
this.preload();
|
|
9795
10161
|
} catch (error) {
|
|
@@ -9810,13 +10176,16 @@ class Finder {
|
|
|
9810
10176
|
}
|
|
9811
10177
|
}
|
|
9812
10178
|
async cutOut(site, id, path2, signal) {
|
|
9813
|
-
const out = join7(
|
|
10179
|
+
const out = join7(cacheDir(site), "cut", `${id}.png`);
|
|
10180
|
+
if (existsSync3(out)) {
|
|
10181
|
+
return out;
|
|
10182
|
+
}
|
|
9814
10183
|
try {
|
|
9815
|
-
|
|
9816
|
-
|
|
9817
|
-
return
|
|
10184
|
+
mkdirSync5(dirname4(out), { recursive: true });
|
|
10185
|
+
await removeBackground(path2, out, signal);
|
|
10186
|
+
return out;
|
|
9818
10187
|
} catch {
|
|
9819
|
-
|
|
10188
|
+
rmSync5(out, { force: true });
|
|
9820
10189
|
return;
|
|
9821
10190
|
}
|
|
9822
10191
|
}
|
|
@@ -9825,10 +10194,8 @@ class Finder {
|
|
|
9825
10194
|
if (!current?.cut || this.view.shown?.id !== current.id) {
|
|
9826
10195
|
return;
|
|
9827
10196
|
}
|
|
9828
|
-
current.
|
|
9829
|
-
|
|
9830
|
-
this.present();
|
|
9831
|
-
this.draw();
|
|
10197
|
+
current.using = current.using === "cut" ? "plain" : "cut";
|
|
10198
|
+
this.reveal();
|
|
9832
10199
|
}
|
|
9833
10200
|
preload() {
|
|
9834
10201
|
const view = this.view;
|
|
@@ -9847,30 +10214,65 @@ class Finder {
|
|
|
9847
10214
|
continue;
|
|
9848
10215
|
}
|
|
9849
10216
|
const path2 = this.origPath(site, post2.id, version2.ext);
|
|
9850
|
-
if (existsSync3(path2)) {
|
|
9851
|
-
continue;
|
|
9852
|
-
}
|
|
9853
10217
|
this.prefetching++;
|
|
9854
|
-
this.cached(site, path2, version2.file).catch(() => {}).finally(() => {
|
|
10218
|
+
this.cached(site, path2, version2.file).then(() => this.render({ site, id: post2.id, path: path2, ext: version2.ext, size: 0, using: "plain", failed: false }, "plain")).catch(() => {}).finally(() => {
|
|
9855
10219
|
this.prefetching--;
|
|
9856
10220
|
});
|
|
9857
10221
|
}
|
|
9858
10222
|
}
|
|
9859
|
-
|
|
9860
|
-
const current = this.current;
|
|
9861
|
-
if (!current) {
|
|
9862
|
-
return;
|
|
9863
|
-
}
|
|
10223
|
+
async render(current, using) {
|
|
9864
10224
|
const W = this.cols * this.cell.w;
|
|
9865
10225
|
const H = this.rows * this.cell.h;
|
|
9866
10226
|
const width2 = Math.min(W, TRY_WIDTH);
|
|
9867
10227
|
const height = Math.max(1, Math.round(H * width2 / W));
|
|
9868
|
-
const
|
|
9869
|
-
const
|
|
9870
|
-
|
|
9871
|
-
|
|
10228
|
+
const path2 = join7(this.scratch, `${current.site.key}-${current.id}${using === "cut" ? "c" : ""}-${width2}x${height}.png`);
|
|
10229
|
+
const key = `${current.site.key}:${current.id}:${using}`;
|
|
10230
|
+
const known = this.clarity.get(key);
|
|
10231
|
+
if (known !== undefined && existsSync3(path2)) {
|
|
10232
|
+
return { clear: known, path: path2 };
|
|
10233
|
+
}
|
|
10234
|
+
const clear = await this.renders.run({
|
|
10235
|
+
job: "show",
|
|
10236
|
+
from: using === "cut" ? current.cut : current.path,
|
|
10237
|
+
to: path2,
|
|
10238
|
+
width: width2,
|
|
10239
|
+
height,
|
|
10240
|
+
colors: this.entry,
|
|
10241
|
+
tone: this.tone
|
|
10242
|
+
});
|
|
10243
|
+
this.clarity.set(key, clear);
|
|
10244
|
+
return { clear, path: path2 };
|
|
10245
|
+
}
|
|
10246
|
+
async present() {
|
|
10247
|
+
const current = this.current;
|
|
10248
|
+
if (!current) {
|
|
10249
|
+
return;
|
|
10250
|
+
}
|
|
10251
|
+
const using = current.using;
|
|
10252
|
+
const { clear, path: path2 } = await this.render(current, using);
|
|
10253
|
+
if (this.current !== current || current.using !== using) {
|
|
10254
|
+
return;
|
|
9872
10255
|
}
|
|
9873
|
-
this.view.shown = {
|
|
10256
|
+
this.view.shown = {
|
|
10257
|
+
id: current.id,
|
|
10258
|
+
clear,
|
|
10259
|
+
bytes: current.size,
|
|
10260
|
+
path: path2,
|
|
10261
|
+
cut: current.cut ? using === "cut" ? "on" : "off" : current.failed ? "failed" : "none"
|
|
10262
|
+
};
|
|
10263
|
+
}
|
|
10264
|
+
reveal() {
|
|
10265
|
+
const view = this.view;
|
|
10266
|
+
view.preparing = this.current?.id;
|
|
10267
|
+
this.flush();
|
|
10268
|
+
this.present().catch((error) => {
|
|
10269
|
+
view.error = error instanceof Error ? error.message : String(error);
|
|
10270
|
+
}).finally(() => {
|
|
10271
|
+
if (view.preparing === this.current?.id) {
|
|
10272
|
+
view.preparing = undefined;
|
|
10273
|
+
}
|
|
10274
|
+
this.draw();
|
|
10275
|
+
});
|
|
9874
10276
|
}
|
|
9875
10277
|
async install() {
|
|
9876
10278
|
const view = this.view;
|
|
@@ -9882,15 +10284,24 @@ class Finder {
|
|
|
9882
10284
|
view.installing = tile.id;
|
|
9883
10285
|
view.error = undefined;
|
|
9884
10286
|
this.flush();
|
|
9885
|
-
await tick();
|
|
9886
10287
|
try {
|
|
9887
|
-
|
|
9888
|
-
|
|
9889
|
-
|
|
9890
|
-
|
|
9891
|
-
|
|
9892
|
-
|
|
10288
|
+
await this.renders.run({
|
|
10289
|
+
job: "backdrop",
|
|
10290
|
+
from: current.using === "cut" ? current.cut : current.path,
|
|
10291
|
+
source: current.path,
|
|
10292
|
+
home: this.home,
|
|
10293
|
+
colors: this.entry,
|
|
10294
|
+
tone: this.tone,
|
|
10295
|
+
origin: {
|
|
10296
|
+
site: current.site.key,
|
|
10297
|
+
id: current.id,
|
|
10298
|
+
ext: current.ext,
|
|
10299
|
+
from: `${current.site.name} ${current.id} ${current.site.pageUrl(current.id)}`
|
|
10300
|
+
}
|
|
9893
10301
|
});
|
|
10302
|
+
const known = readCache(current.site, "owners.json");
|
|
10303
|
+
known[current.id] = this.posts.get(this.mark(current.site, current.id))?.owner ?? "";
|
|
10304
|
+
writeCache(current.site, "owners.json", known);
|
|
9894
10305
|
process.stderr.write(`background · ${this.entry.name} ← ${current.site.name} ${current.id}
|
|
9895
10306
|
`);
|
|
9896
10307
|
this.finish(0);
|
|
@@ -9981,19 +10392,38 @@ async function runFind(name) {
|
|
|
9981
10392
|
return new Finder(home, catalog, entry, entry.booru ?? "").run();
|
|
9982
10393
|
}
|
|
9983
10394
|
|
|
10395
|
+
// src/images.ts
|
|
10396
|
+
function runImage(name, action) {
|
|
10397
|
+
const home = configHome();
|
|
10398
|
+
find2(readCatalog(home).palettes, name);
|
|
10399
|
+
if (action === "next" || action === "prev") {
|
|
10400
|
+
const { key, at: at2, of } = switchImage(home, name, action === "next" ? 1 : -1);
|
|
10401
|
+
process.stderr.write(`background · ${name} ${at2}/${of} ${key}
|
|
10402
|
+
`);
|
|
10403
|
+
return 0;
|
|
10404
|
+
}
|
|
10405
|
+
if (action === "drop") {
|
|
10406
|
+
const { key, left } = dropImage(home, name);
|
|
10407
|
+
process.stderr.write(`background · ${name} removed ${key ?? "the picture"} · ${left} left
|
|
10408
|
+
`);
|
|
10409
|
+
return 0;
|
|
10410
|
+
}
|
|
10411
|
+
throw new Error(`unknown image action ${action} — next, prev or drop`);
|
|
10412
|
+
}
|
|
10413
|
+
|
|
9984
10414
|
// src/init.ts
|
|
9985
10415
|
import {
|
|
9986
10416
|
chmodSync,
|
|
9987
10417
|
copyFileSync,
|
|
9988
10418
|
existsSync as existsSync5,
|
|
9989
|
-
mkdirSync as
|
|
9990
|
-
readdirSync as
|
|
9991
|
-
readFileSync as
|
|
9992
|
-
rmSync as
|
|
9993
|
-
writeFileSync as
|
|
10419
|
+
mkdirSync as mkdirSync6,
|
|
10420
|
+
readdirSync as readdirSync4,
|
|
10421
|
+
readFileSync as readFileSync7,
|
|
10422
|
+
rmSync as rmSync6,
|
|
10423
|
+
writeFileSync as writeFileSync6
|
|
9994
10424
|
} from "node:fs";
|
|
9995
10425
|
import { homedir as homedir3 } from "node:os";
|
|
9996
|
-
import { dirname as
|
|
10426
|
+
import { dirname as dirname5, join as join8 } from "node:path";
|
|
9997
10427
|
|
|
9998
10428
|
// node_modules/@clack/core/dist/index.mjs
|
|
9999
10429
|
import { styleText } from "node:util";
|
|
@@ -11107,6 +11537,34 @@ class a extends V {
|
|
|
11107
11537
|
});
|
|
11108
11538
|
}
|
|
11109
11539
|
}
|
|
11540
|
+
var n$1 = class n extends V {
|
|
11541
|
+
options;
|
|
11542
|
+
cursor = 0;
|
|
11543
|
+
get _selectedValue() {
|
|
11544
|
+
return this.options[this.cursor];
|
|
11545
|
+
}
|
|
11546
|
+
changeValue() {
|
|
11547
|
+
const e = this._selectedValue;
|
|
11548
|
+
this.value = e === undefined ? undefined : e.value;
|
|
11549
|
+
}
|
|
11550
|
+
constructor(e) {
|
|
11551
|
+
super(e, false), this.options = e.options;
|
|
11552
|
+
const o2 = this.options.findIndex(({ value: s }) => s === e.initialValue), t2 = o2 === -1 ? 0 : o2;
|
|
11553
|
+
this.cursor = this.options[t2]?.disabled ? findCursor(t2, 1, this.options) : t2, this.changeValue(), this.on("cursor", (s) => {
|
|
11554
|
+
switch (s) {
|
|
11555
|
+
case "left":
|
|
11556
|
+
case "up":
|
|
11557
|
+
this.cursor = findCursor(this.cursor, -1, this.options);
|
|
11558
|
+
break;
|
|
11559
|
+
case "down":
|
|
11560
|
+
case "right":
|
|
11561
|
+
this.cursor = findCursor(this.cursor, 1, this.options);
|
|
11562
|
+
break;
|
|
11563
|
+
}
|
|
11564
|
+
this.changeValue();
|
|
11565
|
+
});
|
|
11566
|
+
}
|
|
11567
|
+
};
|
|
11110
11568
|
|
|
11111
11569
|
// node_modules/@clack/prompts/dist/index.mjs
|
|
11112
11570
|
import { styleText as styleText2, stripVTControlCharacters as stripVTControlCharacters3 } from "node:util";
|
|
@@ -11209,7 +11667,7 @@ var limitOptions = ({
|
|
|
11209
11667
|
d && g2++, c2 && g2++;
|
|
11210
11668
|
const T3 = f2 + (d ? 1 : 0), y = W - (c2 ? 1 : 0);
|
|
11211
11669
|
for (let t2 = T3;t2 < y; t2++) {
|
|
11212
|
-
const
|
|
11670
|
+
const n3 = e[t2], o2 = n3 ? w(n3, t2 === l) : "", h2 = wrapAnsi(o2, i, {
|
|
11213
11671
|
hard: true,
|
|
11214
11672
|
trim: false
|
|
11215
11673
|
}).split(`
|
|
@@ -11217,17 +11675,17 @@ var limitOptions = ({
|
|
|
11217
11675
|
s.push(h2), g2 += h2.length;
|
|
11218
11676
|
}
|
|
11219
11677
|
if (g2 > v) {
|
|
11220
|
-
let t2 = 0,
|
|
11678
|
+
let t2 = 0, n3 = 0, o2 = g2;
|
|
11221
11679
|
const h2 = l - T3;
|
|
11222
11680
|
let u3 = v;
|
|
11223
11681
|
const L = () => I(s, o2, 0, h2, u3), E = () => I(s, o2, h2 + 1, s.length, u3, true);
|
|
11224
|
-
d ? ({ lineCount: o2, removals: t2 } = L(), o2 > u3 && (c2 || (u3 -= 1), { lineCount: o2, removals:
|
|
11682
|
+
d ? ({ lineCount: o2, removals: t2 } = L(), o2 > u3 && (c2 || (u3 -= 1), { lineCount: o2, removals: n3 } = E())) : (c2 || (u3 -= 1), { lineCount: o2, removals: n3 } = E(), o2 > u3 && (u3 -= 1, { lineCount: o2, removals: t2 } = L())), t2 > 0 && (d = true, s.splice(0, t2)), n3 > 0 && (c2 = true, s.splice(s.length - n3, n3));
|
|
11225
11683
|
}
|
|
11226
11684
|
const x = [];
|
|
11227
11685
|
d && x.push(M2);
|
|
11228
11686
|
for (const t2 of s)
|
|
11229
|
-
for (const
|
|
11230
|
-
x.push(
|
|
11687
|
+
for (const n3 of t2)
|
|
11688
|
+
x.push(n3);
|
|
11231
11689
|
return c2 && x.push(M2), x;
|
|
11232
11690
|
};
|
|
11233
11691
|
var confirm = (i) => {
|
|
@@ -11294,58 +11752,58 @@ ${styleText2("reset", styleText2("dim", `Press ${styleText2(["gray", "bgWhite",
|
|
|
11294
11752
|
render() {
|
|
11295
11753
|
const t2 = i.withGuide ?? settings.withGuide, a2 = wrapTextWithPrefix(i.output, i.message, t2 ? `${symbolBar(this.state)} ` : "", `${symbol(this.state)} `), r2 = `${t2 ? `${styleText2("gray", S_BAR)}
|
|
11296
11754
|
` : ""}${a2}
|
|
11297
|
-
`, o2 = this.value ?? [], p2 = (
|
|
11298
|
-
if (
|
|
11299
|
-
return u3(
|
|
11300
|
-
const s = o2.includes(
|
|
11301
|
-
return l && s ? u3(
|
|
11755
|
+
`, o2 = this.value ?? [], p2 = (n3, l) => {
|
|
11756
|
+
if (n3.disabled)
|
|
11757
|
+
return u3(n3, "disabled");
|
|
11758
|
+
const s = o2.includes(n3.value);
|
|
11759
|
+
return l && s ? u3(n3, "active-selected") : s ? u3(n3, "selected") : u3(n3, l ? "active" : "inactive");
|
|
11302
11760
|
};
|
|
11303
11761
|
switch (this.state) {
|
|
11304
11762
|
case "submit": {
|
|
11305
|
-
const
|
|
11763
|
+
const n3 = this.options.filter(({ value: s }) => o2.includes(s)).map((s) => u3(s, "submitted")).join(styleText2("dim", ", ")) || styleText2("dim", "none"), l = wrapTextWithPrefix(i.output, n3, t2 ? `${styleText2("gray", S_BAR)} ` : "");
|
|
11306
11764
|
return `${r2}${l}`;
|
|
11307
11765
|
}
|
|
11308
11766
|
case "cancel": {
|
|
11309
|
-
const
|
|
11310
|
-
if (
|
|
11767
|
+
const n3 = this.options.filter(({ value: s }) => o2.includes(s)).map((s) => u3(s, "cancelled")).join(styleText2("dim", ", "));
|
|
11768
|
+
if (n3.trim() === "")
|
|
11311
11769
|
return `${r2}${styleText2("gray", S_BAR)}`;
|
|
11312
|
-
const l = wrapTextWithPrefix(i.output,
|
|
11770
|
+
const l = wrapTextWithPrefix(i.output, n3, t2 ? `${styleText2("gray", S_BAR)} ` : "");
|
|
11313
11771
|
return `${r2}${l}${t2 ? `
|
|
11314
11772
|
${styleText2("gray", S_BAR)}` : ""}`;
|
|
11315
11773
|
}
|
|
11316
11774
|
case "error": {
|
|
11317
|
-
const
|
|
11775
|
+
const n3 = t2 ? `${styleText2("yellow", S_BAR)} ` : "", l = this.error.split(`
|
|
11318
11776
|
`).map(($, C2) => C2 === 0 ? `${t2 ? `${styleText2("yellow", S_BAR_END)} ` : ""}${styleText2("yellow", $)}` : ` ${$}`).join(`
|
|
11319
11777
|
`), s = r2.split(`
|
|
11320
11778
|
`).length, h2 = l.split(`
|
|
11321
11779
|
`).length + 1;
|
|
11322
|
-
return `${r2}${
|
|
11780
|
+
return `${r2}${n3}${limitOptions({
|
|
11323
11781
|
output: i.output,
|
|
11324
11782
|
options: this.options,
|
|
11325
11783
|
cursor: this.cursor,
|
|
11326
11784
|
maxItems: i.maxItems,
|
|
11327
|
-
columnPadding:
|
|
11785
|
+
columnPadding: n3.length,
|
|
11328
11786
|
rowPadding: s + h2,
|
|
11329
11787
|
style: p2
|
|
11330
11788
|
}).join(`
|
|
11331
|
-
${
|
|
11789
|
+
${n3}`)}
|
|
11332
11790
|
${l}
|
|
11333
11791
|
`;
|
|
11334
11792
|
}
|
|
11335
11793
|
default: {
|
|
11336
|
-
const
|
|
11794
|
+
const n3 = t2 ? `${styleText2("cyan", S_BAR)} ` : "", l = r2.split(`
|
|
11337
11795
|
`).length, s = v ? formatInstructionFooter(MULTISELECT_INSTRUCTIONS, t2) : t2 ? [styleText2("cyan", S_BAR_END)] : [], h2 = s.join(`
|
|
11338
11796
|
`), $ = s.length + 1;
|
|
11339
|
-
return `${r2}${
|
|
11797
|
+
return `${r2}${n3}${limitOptions({
|
|
11340
11798
|
output: i.output,
|
|
11341
11799
|
options: this.options,
|
|
11342
11800
|
cursor: this.cursor,
|
|
11343
11801
|
maxItems: i.maxItems,
|
|
11344
|
-
columnPadding:
|
|
11802
|
+
columnPadding: n3.length,
|
|
11345
11803
|
rowPadding: l + $,
|
|
11346
11804
|
style: p2
|
|
11347
11805
|
}).join(`
|
|
11348
|
-
${
|
|
11806
|
+
${n3}`)}
|
|
11349
11807
|
${h2}
|
|
11350
11808
|
`;
|
|
11351
11809
|
}
|
|
@@ -11377,18 +11835,18 @@ var C2 = (o2, e, s) => {
|
|
|
11377
11835
|
hard: true,
|
|
11378
11836
|
trim: false
|
|
11379
11837
|
}, i = wrapAnsi(o2, e, a2).split(`
|
|
11380
|
-
`), c2 = i.reduce((
|
|
11838
|
+
`), c2 = i.reduce((n3, t2) => Math.max(dist_default2(t2), n3), 0), u3 = i.map(s).reduce((n3, t2) => Math.max(dist_default2(t2), n3), 0), g2 = e - (u3 - c2);
|
|
11381
11839
|
return wrapAnsi(o2, g2, a2);
|
|
11382
11840
|
};
|
|
11383
11841
|
var note = (o2 = "", e = "", s) => {
|
|
11384
11842
|
const a2 = s?.output ?? process$1.stdout, i = s?.withGuide ?? settings.withGuide, c2 = s?.format ?? W$1, g2 = ["", ...C2(o2, getColumns(a2) - 6, c2).split(`
|
|
11385
|
-
`).map(c2), ""],
|
|
11843
|
+
`).map(c2), ""], n3 = dist_default2(e), t2 = Math.max(g2.reduce((m3, F) => {
|
|
11386
11844
|
const O = dist_default2(F);
|
|
11387
11845
|
return O > m3 ? O : m3;
|
|
11388
|
-
}, 0),
|
|
11846
|
+
}, 0), n3) + 2, h2 = g2.map((m3) => `${styleText2("gray", S_BAR)} ${m3}${" ".repeat(t2 - dist_default2(m3))}${styleText2("gray", S_BAR)}`).join(`
|
|
11389
11847
|
`), T3 = i ? `${styleText2("gray", S_BAR)}
|
|
11390
11848
|
` : "", l$1 = i ? S_CONNECT_LEFT : S_CORNER_BOTTOM_LEFT;
|
|
11391
|
-
a2.write(`${T3}${styleText2("green", S_STEP_SUBMIT)} ${styleText2("reset", e)} ${styleText2("gray", S_BAR_H.repeat(Math.max(t2 -
|
|
11849
|
+
a2.write(`${T3}${styleText2("green", S_STEP_SUBMIT)} ${styleText2("reset", e)} ${styleText2("gray", S_BAR_H.repeat(Math.max(t2 - n3 - 1, 1)) + S_CORNER_TOP_RIGHT)}
|
|
11392
11850
|
${h2}
|
|
11393
11851
|
${styleText2("gray", l$1 + S_BAR_H.repeat(t2 + 2) + S_CORNER_BOTTOM_RIGHT)}
|
|
11394
11852
|
`);
|
|
@@ -11402,6 +11860,69 @@ var SELECT_INSTRUCTIONS = [
|
|
|
11402
11860
|
`${styleText2("dim", "↑/↓")} to navigate`,
|
|
11403
11861
|
`${styleText2("dim", "Enter:")} confirm`
|
|
11404
11862
|
];
|
|
11863
|
+
var c2 = (t2, o2) => t2.includes(`
|
|
11864
|
+
`) ? t2.split(`
|
|
11865
|
+
`).map((d) => o2(d)).join(`
|
|
11866
|
+
`) : o2(t2);
|
|
11867
|
+
var select = (t2) => {
|
|
11868
|
+
const o2 = (n3, m3) => {
|
|
11869
|
+
if (n3 === undefined)
|
|
11870
|
+
return "";
|
|
11871
|
+
const s = n3.label ?? String(n3.value);
|
|
11872
|
+
switch (m3) {
|
|
11873
|
+
case "disabled":
|
|
11874
|
+
return `${styleText2("gray", S_RADIO_INACTIVE)} ${c2(s, (i) => styleText2("gray", i))}${n3.hint ? ` ${styleText2("dim", `(${n3.hint ?? "disabled"})`)}` : ""}`;
|
|
11875
|
+
case "selected":
|
|
11876
|
+
return `${c2(s, (i) => styleText2("dim", i))}`;
|
|
11877
|
+
case "active":
|
|
11878
|
+
return `${styleText2("green", S_RADIO_ACTIVE)} ${s}${n3.hint ? ` ${styleText2("dim", `(${n3.hint})`)}` : ""}`;
|
|
11879
|
+
case "cancelled":
|
|
11880
|
+
return `${c2(s, (i) => styleText2(["strikethrough", "dim"], i))}`;
|
|
11881
|
+
default:
|
|
11882
|
+
return `${styleText2("dim", S_RADIO_INACTIVE)} ${c2(s, (i) => styleText2("dim", i))}`;
|
|
11883
|
+
}
|
|
11884
|
+
}, d = t2.showInstructions ?? true;
|
|
11885
|
+
return new n$1({
|
|
11886
|
+
options: t2.options,
|
|
11887
|
+
signal: t2.signal,
|
|
11888
|
+
input: t2.input,
|
|
11889
|
+
output: t2.output,
|
|
11890
|
+
initialValue: t2.initialValue,
|
|
11891
|
+
render() {
|
|
11892
|
+
const n3 = t2.withGuide ?? settings.withGuide, m3 = `${symbol(this.state)} `, s = `${symbolBar(this.state)} `, i = wrapTextWithPrefix(t2.output, t2.message, s, m3), u4 = `${n3 ? `${styleText2("gray", S_BAR)}
|
|
11893
|
+
` : ""}${i}
|
|
11894
|
+
`;
|
|
11895
|
+
switch (this.state) {
|
|
11896
|
+
case "submit": {
|
|
11897
|
+
const r2 = n3 ? `${styleText2("gray", S_BAR)} ` : "", a2 = wrapTextWithPrefix(t2.output, o2(this.options[this.cursor], "selected"), r2);
|
|
11898
|
+
return `${u4}${a2}`;
|
|
11899
|
+
}
|
|
11900
|
+
case "cancel": {
|
|
11901
|
+
const r2 = n3 ? `${styleText2("gray", S_BAR)} ` : "", a2 = wrapTextWithPrefix(t2.output, o2(this.options[this.cursor], "cancelled"), r2);
|
|
11902
|
+
return `${u4}${a2}${n3 ? `
|
|
11903
|
+
${styleText2("gray", S_BAR)}` : ""}`;
|
|
11904
|
+
}
|
|
11905
|
+
default: {
|
|
11906
|
+
const r2 = n3 ? `${styleText2("cyan", S_BAR)} ` : "", a2 = u4.split(`
|
|
11907
|
+
`).length, p2 = d ? formatInstructionFooter(SELECT_INSTRUCTIONS, n3) : n3 ? [styleText2("cyan", S_BAR_END)] : [], b2 = p2.join(`
|
|
11908
|
+
`), f2 = p2.length + 1;
|
|
11909
|
+
return `${u4}${r2}${limitOptions({
|
|
11910
|
+
output: t2.output,
|
|
11911
|
+
cursor: this.cursor,
|
|
11912
|
+
options: this.options,
|
|
11913
|
+
maxItems: t2.maxItems,
|
|
11914
|
+
columnPadding: r2.length,
|
|
11915
|
+
rowPadding: a2 + f2,
|
|
11916
|
+
style: (g2, x) => o2(g2, g2.disabled ? "disabled" : x ? "active" : "inactive")
|
|
11917
|
+
}).join(`
|
|
11918
|
+
${r2}`)}
|
|
11919
|
+
${b2}
|
|
11920
|
+
`;
|
|
11921
|
+
}
|
|
11922
|
+
}
|
|
11923
|
+
}
|
|
11924
|
+
}).prompt();
|
|
11925
|
+
};
|
|
11405
11926
|
var i = `${styleText2("gray", S_BAR)} `;
|
|
11406
11927
|
|
|
11407
11928
|
// src/market.ts
|
|
@@ -11412,7 +11933,7 @@ import { openSync, writeSync } from "node:fs";
|
|
|
11412
11933
|
import { ReadStream } from "node:tty";
|
|
11413
11934
|
var QUERY_CODES = ["10", "11", "12", "17", ...Array.from({ length: 16 }, (_2, i2) => `4;${i2}`)];
|
|
11414
11935
|
function paletteOsc(entry) {
|
|
11415
|
-
const osc4 = entry.ansi.map((
|
|
11936
|
+
const osc4 = entry.ansi.map((c3, i2) => `;${i2};${c3}`).join("");
|
|
11416
11937
|
return [
|
|
11417
11938
|
`\x1B]11;${entry.background}\x1B\\`,
|
|
11418
11939
|
`\x1B]10;${entry.foreground}\x1B\\`,
|
|
@@ -11468,7 +11989,7 @@ async function queryTerminalColors() {
|
|
|
11468
11989
|
// src/ansi.ts
|
|
11469
11990
|
function rgb2(hex2) {
|
|
11470
11991
|
const h2 = hex2.replace("#", "");
|
|
11471
|
-
return [h2.slice(0, 2), h2.slice(2, 4), h2.slice(4, 6)].map((
|
|
11992
|
+
return [h2.slice(0, 2), h2.slice(2, 4), h2.slice(4, 6)].map((c3) => Number.parseInt(c3, 16)).join(";");
|
|
11472
11993
|
}
|
|
11473
11994
|
function ansiChip(text, bg2) {
|
|
11474
11995
|
return `\x1B[48;2;${rgb2(bg2)}m ${text} \x1B[0m`;
|
|
@@ -11480,7 +12001,7 @@ function ansiFg(color2) {
|
|
|
11480
12001
|
return `\x1B[38;2;${rgb2(color2)}m`;
|
|
11481
12002
|
}
|
|
11482
12003
|
function ansiSwatch(colors, bg2) {
|
|
11483
|
-
return `\x1B[48;2;${rgb2(bg2)}m${colors.map((
|
|
12004
|
+
return `\x1B[48;2;${rgb2(bg2)}m${colors.map((c3) => `\x1B[38;2;${rgb2(c3)}m▄`).join("")} \x1B[0m`;
|
|
11484
12005
|
}
|
|
11485
12006
|
|
|
11486
12007
|
// src/palette-prompt.ts
|
|
@@ -11624,12 +12145,12 @@ class PalettePrompt extends V {
|
|
|
11624
12145
|
if (names.length === 0) {
|
|
11625
12146
|
return;
|
|
11626
12147
|
}
|
|
11627
|
-
const add = names.some((
|
|
11628
|
-
for (const
|
|
12148
|
+
const add = names.some((n3) => !this.picked.has(n3));
|
|
12149
|
+
for (const n3 of names) {
|
|
11629
12150
|
if (add) {
|
|
11630
|
-
this.picked.add(
|
|
12151
|
+
this.picked.add(n3);
|
|
11631
12152
|
} else {
|
|
11632
|
-
this.picked.delete(
|
|
12153
|
+
this.picked.delete(n3);
|
|
11633
12154
|
}
|
|
11634
12155
|
}
|
|
11635
12156
|
}
|
|
@@ -11816,8 +12337,8 @@ function runAdd(names) {
|
|
|
11816
12337
|
const home = configHome();
|
|
11817
12338
|
const catalog = readCatalog(home);
|
|
11818
12339
|
const state = readInstalled(home);
|
|
11819
|
-
const already = names.filter((
|
|
11820
|
-
const fresh = names.filter((
|
|
12340
|
+
const already = names.filter((n3) => state.palettes.includes(n3));
|
|
12341
|
+
const fresh = names.filter((n3) => !state.palettes.includes(n3));
|
|
11821
12342
|
if (fresh.length === 0) {
|
|
11822
12343
|
console.log(`already installed: ${already.join(", ")}`);
|
|
11823
12344
|
return;
|
|
@@ -11834,12 +12355,12 @@ function runRemove(names) {
|
|
|
11834
12355
|
const home = configHome();
|
|
11835
12356
|
const catalog = readCatalog(home);
|
|
11836
12357
|
const state = readInstalled(home);
|
|
11837
|
-
const gone = names.filter((
|
|
12358
|
+
const gone = names.filter((n3) => state.palettes.includes(n3));
|
|
11838
12359
|
if (gone.length === 0) {
|
|
11839
12360
|
console.log(`not installed: ${names.join(", ")}`);
|
|
11840
12361
|
return;
|
|
11841
12362
|
}
|
|
11842
|
-
const next = { ...state, palettes: state.palettes.filter((
|
|
12363
|
+
const next = { ...state, palettes: state.palettes.filter((n3) => !gone.includes(n3)) };
|
|
11843
12364
|
sync(home, catalog, next);
|
|
11844
12365
|
forget(home, catalog, state.terminals, gone);
|
|
11845
12366
|
writeInstalled(home, next);
|
|
@@ -11855,7 +12376,8 @@ function runDefault(name) {
|
|
|
11855
12376
|
if (!state.palettes.includes(name)) {
|
|
11856
12377
|
throw new Error(`${name} is not installed — \`ttheme add ${name}\` first`);
|
|
11857
12378
|
}
|
|
11858
|
-
const
|
|
12379
|
+
const { keepTheme: _2, ...rest } = state;
|
|
12380
|
+
const next = { ...rest, startup: name };
|
|
11859
12381
|
sync(home, catalog, next);
|
|
11860
12382
|
writeInstalled(home, next);
|
|
11861
12383
|
console.log(`new tabs open with ${name} — reload your terminal config to pick it up`);
|
|
@@ -11911,8 +12433,8 @@ async function runBrowse() {
|
|
|
11911
12433
|
console.log("nothing changed");
|
|
11912
12434
|
return;
|
|
11913
12435
|
}
|
|
11914
|
-
const dropped = state.palettes.filter((
|
|
11915
|
-
const added = wanted.filter((
|
|
12436
|
+
const dropped = state.palettes.filter((n3) => !wanted.includes(n3));
|
|
12437
|
+
const added = wanted.filter((n3) => !state.palettes.includes(n3));
|
|
11916
12438
|
if (added.length === 0 && dropped.length === 0) {
|
|
11917
12439
|
console.log("nothing changed");
|
|
11918
12440
|
return;
|
|
@@ -11932,12 +12454,12 @@ async function runBrowse() {
|
|
|
11932
12454
|
|
|
11933
12455
|
// src/init.ts
|
|
11934
12456
|
function copyDir(copies, from, to) {
|
|
11935
|
-
for (const f2 of
|
|
12457
|
+
for (const f2 of readdirSync4(from)) {
|
|
11936
12458
|
copies.push({ from: join8(from, f2), to: join8(to, f2) });
|
|
11937
12459
|
}
|
|
11938
12460
|
}
|
|
11939
12461
|
function loadManifest(root2) {
|
|
11940
|
-
return JSON.parse(
|
|
12462
|
+
return JSON.parse(readFileSync7(join8(root2, "dist", "manifest.json"), "utf8"));
|
|
11941
12463
|
}
|
|
11942
12464
|
function planInit(opts, paths) {
|
|
11943
12465
|
const dist = join8(paths.root, "dist");
|
|
@@ -11951,9 +12473,10 @@ function planInit(opts, paths) {
|
|
|
11951
12473
|
copyDir(copies, join8(paths.root, "shell", "adapters"), join8(home, "adapters"));
|
|
11952
12474
|
const edits = [{ file: join8(paths.zdotdir, ".zshrc"), block: zshrcBlock(home) }];
|
|
11953
12475
|
const configPath = join8(home, "config.zsh");
|
|
12476
|
+
const seeded = configFile(existsSync5(configPath) ? readFileSync7(configPath, "utf8") : "");
|
|
11954
12477
|
const settings2 = {
|
|
11955
12478
|
file: configPath,
|
|
11956
|
-
content:
|
|
12479
|
+
content: opts.wear ? withSetting(seeded, "TTHEME_TAB_PALETTE", opts.wear === "rotate" ? "seq" : "off") : seeded
|
|
11957
12480
|
};
|
|
11958
12481
|
const notes = [];
|
|
11959
12482
|
if (opts.terminals.includes("ghostty")) {
|
|
@@ -11961,33 +12484,37 @@ function planInit(opts, paths) {
|
|
|
11961
12484
|
}
|
|
11962
12485
|
if (opts.terminals.includes("alacritty")) {
|
|
11963
12486
|
const config = join8(paths.configHome, "alacritty", "alacritty.toml");
|
|
11964
|
-
if (existsSync5(config) && !
|
|
12487
|
+
if (existsSync5(config) && !readFileSync7(config, "utf8").includes("# ttheme begin")) {
|
|
11965
12488
|
notes.push("alacritty.toml already exists — ttheme left it alone; add its themes/ import yourself");
|
|
11966
12489
|
}
|
|
11967
12490
|
}
|
|
11968
12491
|
notes.push("wezterm and iterm2: import the palettes you install from the release archive");
|
|
11969
|
-
const installed = {
|
|
12492
|
+
const installed = {
|
|
12493
|
+
terminals: opts.terminals,
|
|
12494
|
+
palettes: opts.palettes,
|
|
12495
|
+
...opts.wear === "keep" ? { keepTheme: true } : {}
|
|
12496
|
+
};
|
|
11970
12497
|
return { copies, edits, settings: settings2, catalog: loadManifest(paths.root), installed, notes };
|
|
11971
12498
|
}
|
|
11972
12499
|
function applyInit(plan) {
|
|
11973
|
-
for (const
|
|
11974
|
-
|
|
11975
|
-
|
|
11976
|
-
copyFileSync(
|
|
11977
|
-
if (
|
|
11978
|
-
chmodSync(
|
|
12500
|
+
for (const c3 of plan.copies) {
|
|
12501
|
+
mkdirSync6(dirname5(c3.to), { recursive: true });
|
|
12502
|
+
rmSync6(c3.to, { force: true });
|
|
12503
|
+
copyFileSync(c3.from, c3.to);
|
|
12504
|
+
if (c3.executable) {
|
|
12505
|
+
chmodSync(c3.to, 493);
|
|
11979
12506
|
}
|
|
11980
12507
|
}
|
|
11981
|
-
|
|
11982
|
-
|
|
11983
|
-
const configHome2 =
|
|
12508
|
+
mkdirSync6(dirname5(plan.settings.file), { recursive: true });
|
|
12509
|
+
writeFileSync6(plan.settings.file, plan.settings.content);
|
|
12510
|
+
const configHome2 = dirname5(dirname5(plan.settings.file));
|
|
11984
12511
|
writeCatalog(configHome2, plan.catalog);
|
|
11985
12512
|
writeInstalled(configHome2, plan.installed);
|
|
11986
12513
|
sync(configHome2, plan.catalog, plan.installed);
|
|
11987
12514
|
for (const e of plan.edits) {
|
|
11988
|
-
|
|
11989
|
-
const current = existsSync5(e.file) ?
|
|
11990
|
-
|
|
12515
|
+
mkdirSync6(dirname5(e.file), { recursive: true });
|
|
12516
|
+
const current = existsSync5(e.file) ? readFileSync7(e.file, "utf8") : "";
|
|
12517
|
+
writeFileSync6(e.file, upsertBlock(current, e.block));
|
|
11991
12518
|
}
|
|
11992
12519
|
}
|
|
11993
12520
|
function accepted(value) {
|
|
@@ -12005,11 +12532,28 @@ async function askTerminals(detected, preselected) {
|
|
|
12005
12532
|
required: true
|
|
12006
12533
|
}));
|
|
12007
12534
|
}
|
|
12535
|
+
function wearSummary(wear, startup) {
|
|
12536
|
+
if (wear === "keep") {
|
|
12537
|
+
return "leave the terminal colors as they are";
|
|
12538
|
+
}
|
|
12539
|
+
return wear === "rotate" ? `paint every new tab with the next palette, this tab with ${startup} now` : `paint every tab with ${startup}, this one now`;
|
|
12540
|
+
}
|
|
12541
|
+
async function askWear(startup) {
|
|
12542
|
+
return accepted(await select({
|
|
12543
|
+
message: "how should the terminal wear them?",
|
|
12544
|
+
options: [
|
|
12545
|
+
{ value: "default", label: "default", hint: `every tab wears ${startup}` },
|
|
12546
|
+
{ value: "rotate", label: "rotate", hint: "every new tab wears the next palette" },
|
|
12547
|
+
{ value: "keep", label: "keep", hint: "leave my terminal colors alone" }
|
|
12548
|
+
],
|
|
12549
|
+
initialValue: "default"
|
|
12550
|
+
}));
|
|
12551
|
+
}
|
|
12008
12552
|
function verify(plan) {
|
|
12009
12553
|
const missing = [
|
|
12010
|
-
...plan.copies.filter((
|
|
12554
|
+
...plan.copies.filter((c3) => !existsSync5(c3.to)).map((c3) => c3.to),
|
|
12011
12555
|
...existsSync5(plan.settings.file) ? [] : [plan.settings.file],
|
|
12012
|
-
...plan.edits.filter((e) => !
|
|
12556
|
+
...plan.edits.filter((e) => !readFileSync7(e.file, "utf8").includes("# ttheme begin")).map((e) => e.file)
|
|
12013
12557
|
];
|
|
12014
12558
|
if (missing.length > 0) {
|
|
12015
12559
|
throw new Error(`init left gaps:
|
|
@@ -12029,13 +12573,23 @@ function paintStartup(catalog, installed) {
|
|
|
12029
12573
|
process.stdout.write(paletteOsc(startup));
|
|
12030
12574
|
return true;
|
|
12031
12575
|
}
|
|
12032
|
-
function
|
|
12576
|
+
function wearLines(wear, startup, painted) {
|
|
12577
|
+
if (wear === "keep") {
|
|
12578
|
+
return [
|
|
12579
|
+
"terminal colors left alone — paint a tab with `ttheme <palette>`",
|
|
12580
|
+
" `ttheme default <palette>` sets the terminal default"
|
|
12581
|
+
];
|
|
12582
|
+
}
|
|
12583
|
+
return [
|
|
12584
|
+
`default ${startup}${painted ? " — this tab wears it already" : ""}`,
|
|
12585
|
+
wear === "rotate" ? "new tabs rotate through the palettes — change with `ttheme config`" : `new tabs all wear ${startup} — change with \`ttheme config\``
|
|
12586
|
+
];
|
|
12587
|
+
}
|
|
12588
|
+
function receipt(plan, opts, wear, painted) {
|
|
12033
12589
|
const series = seriesOf(plan.catalog, opts.palettes);
|
|
12034
|
-
const startup = startupPalette(plan.installed);
|
|
12035
12590
|
note([
|
|
12036
12591
|
`${series.join(", ")} (${opts.palettes.length})`,
|
|
12037
|
-
|
|
12038
|
-
"new tabs rotate through the palettes — change with `ttheme config`"
|
|
12592
|
+
...wearLines(wear, startupPalette(plan.installed), painted)
|
|
12039
12593
|
].join(`
|
|
12040
12594
|
`), `installed ${opts.palettes.length} palettes`);
|
|
12041
12595
|
const next = ["exec zsh the ttheme command in this tab"];
|
|
@@ -12102,13 +12656,16 @@ async function runInit(flags = {}) {
|
|
|
12102
12656
|
cancel("nothing changed");
|
|
12103
12657
|
process.exit(1);
|
|
12104
12658
|
}
|
|
12105
|
-
const
|
|
12659
|
+
const startup = startupPalette({ terminals, palettes });
|
|
12660
|
+
const wear = await askWear(startup);
|
|
12661
|
+
const opts = { terminals, palettes, wear };
|
|
12106
12662
|
const plan = planInit(opts, paths);
|
|
12107
12663
|
note([
|
|
12108
12664
|
`install ${palettes.length} palettes — ${seriesOf(plan.catalog, palettes).join(", ")}`,
|
|
12109
12665
|
`copy ${plan.copies.length} files under ${configHome2}`,
|
|
12110
12666
|
`write ${plan.settings.file}`,
|
|
12111
|
-
...plan.edits.map((e) => `edit ${e.file}`)
|
|
12667
|
+
...plan.edits.map((e) => `edit ${e.file}`),
|
|
12668
|
+
wearSummary(wear, startup)
|
|
12112
12669
|
].join(`
|
|
12113
12670
|
`), `wiring ${terminals.join(", ")}`);
|
|
12114
12671
|
if (!accepted(await confirm({ message: "apply these changes?" }))) {
|
|
@@ -12117,7 +12674,7 @@ async function runInit(flags = {}) {
|
|
|
12117
12674
|
}
|
|
12118
12675
|
applyInit(plan);
|
|
12119
12676
|
verify(plan);
|
|
12120
|
-
receipt(plan, opts, paintStartup(plan.catalog, plan.installed));
|
|
12677
|
+
receipt(plan, opts, wear, wear !== "keep" && paintStartup(plan.catalog, plan.installed));
|
|
12121
12678
|
}
|
|
12122
12679
|
|
|
12123
12680
|
// src/cli.ts
|
|
@@ -12134,6 +12691,9 @@ function createProgram() {
|
|
|
12134
12691
|
program2.command("find", { hidden: true }).argument("<palette>").description("pick a safebooru background for a palette — preview opens this on tab").action(async (name) => {
|
|
12135
12692
|
process.exitCode = await runFind(name);
|
|
12136
12693
|
});
|
|
12694
|
+
program2.command("image", { hidden: true }).argument("<palette>").argument("<action>", "next, prev or drop").description("switch a palette between its saved backgrounds, or remove the one shown — preview calls this").action((name, action) => {
|
|
12695
|
+
process.exitCode = runImage(name, action);
|
|
12696
|
+
});
|
|
12137
12697
|
program2.command("update").description("refresh the catalog from the registry").action(() => runUpdate());
|
|
12138
12698
|
return program2;
|
|
12139
12699
|
}
|
|
@@ -12152,4 +12712,6 @@ ${error instanceof Error ? error.message : String(error)}`);
|
|
|
12152
12712
|
}
|
|
12153
12713
|
|
|
12154
12714
|
// src/bin.ts
|
|
12155
|
-
|
|
12715
|
+
if (isMainThread2) {
|
|
12716
|
+
process.exitCode = await runCli(process.argv);
|
|
12717
|
+
}
|