@athrio/loom 0.0.12 → 0.0.14

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.
Files changed (31) hide show
  1. package/dist/{LanguageLoader-BzlRnQhO.js → LanguageLoader-BAPSmTv0.js} +19 -11
  2. package/dist/{LanguageLoader-BzlRnQhO.js.map → LanguageLoader-BAPSmTv0.js.map} +1 -1
  3. package/dist/LanguageLoader-BF5irHbe.js +3 -0
  4. package/dist/{LanguageService-BTCvgdWm.js → LanguageService-C3_9lh8E.js} +2 -2
  5. package/dist/{LanguageService-BTCvgdWm.js.map → LanguageService-C3_9lh8E.js.map} +1 -1
  6. package/dist/{LoomFormatter-Bu8L8cdR.js → LoomFormatter-CcAXsbSL.js} +13 -5
  7. package/dist/{LoomFormatter-Bu8L8cdR.js.map → LoomFormatter-CcAXsbSL.js.map} +1 -1
  8. package/dist/{LoomServer-DXIree_1.js → LoomServer-DpleSkxj.js} +28 -12
  9. package/dist/{LoomServer-DXIree_1.js.map → LoomServer-DpleSkxj.js.map} +1 -1
  10. package/dist/{LoomStore-pA-ohGNX.js → LoomStore-Bcx6V9HH.js} +106 -22
  11. package/dist/LoomStore-Bcx6V9HH.js.map +1 -0
  12. package/dist/{Runtime-XT-nb-2w.js → Runtime-B-1DeuX_.js} +1 -1
  13. package/dist/{Runtime-Byw6clui.js → Runtime-CE2kCsKX.js} +3 -3
  14. package/dist/{Runtime-Byw6clui.js.map → Runtime-CE2kCsKX.js.map} +1 -1
  15. package/dist/_virtual_tree-sitter-loom-CFLf84Ng.js +15 -0
  16. package/dist/{dist-D3YSXNOO.js → dist-NXZtp5_0.js} +2 -2
  17. package/dist/{dist-D3YSXNOO.js.map → dist-NXZtp5_0.js.map} +1 -1
  18. package/dist/main.js +375 -52
  19. package/dist/main.js.map +1 -1
  20. package/package.json +3 -1
  21. package/dist/LanguageLoader-DJZBFaqF.js +0 -3
  22. package/dist/LoomStore-pA-ohGNX.js.map +0 -1
  23. package/dist/tree-sitter-loom/editors/helix/queries/loom/highlights.scm +0 -120
  24. package/dist/tree-sitter-loom/editors/helix/queries/loom/injections.scm +0 -413
  25. package/dist/tree-sitter-loom/queries/highlights.scm +0 -120
  26. package/dist/tree-sitter-loom/queries/injections.scm +0 -85
  27. package/dist/tree-sitter-loom/src/parser.c +0 -4689
  28. package/dist/tree-sitter-loom/src/scanner.c +0 -293
  29. package/dist/tree-sitter-loom/src/tree_sitter/alloc.h +0 -54
  30. package/dist/tree-sitter-loom/src/tree_sitter/array.h +0 -330
  31. package/dist/tree-sitter-loom/src/tree_sitter/parser.h +0 -286
package/dist/main.js CHANGED
@@ -1,16 +1,18 @@
1
1
  #!/usr/bin/env node
2
- import { $ as transduce, $n as scoped, $t as optionalKey, A as FileSystem, Ai as exists, An as forever, Ar as TaggedError$1, At as Defect, B as fromEffect, Bi as isNone, Bn as mapError, Bt as Struct, Ci as Reference, Cn as effectify, Cr as fail$2, D as log, Di as make$7, Dn as flatMap$1, Dr as done, Dt as ArraySchema, E as error, Ei as getUnsafe, En as filter$2, Er as UnknownError, Et as nominal, F as concat, Fi as fromUndefinedOr, Fn as interrupt, G as mapEffect$1, Gi as none, Gn as orElseSucceed, H as isStream, Hi as liftThrowable, Hn as matchEffect, Hr as findFirst, Ht as TrueLiterals, I as decodeText, Ii as getOrElse, In as isEffect, J as orDie$1, Jn as provideContext, K as merge, Ki as orElse, Kn as promise, Kt as decodeUnknownEffect, L as empty$2, M as WatchBackend, Mi as flatMap$2, Mr as toMillis, Mt as Int$4, N as make$10, Nn as gen, Nt as Literal, O as Path$3, On as fnUntraced, Or as fail$3, P as callback$1, Pi as fromNullishOr, Pn as ignore, Pr as dedupe, Q as splitLines, Qn as runFork, Qt as optional$3, R as filter$1, Rr as empty, Si as succeed$2, Sr as makeUnsafe$1, T as make$9, Ti as empty$1, Tn as fail, Tr as Done, Ui as map$4, Un as option, Ur as findFirstIndex, V as groupedWithin, Vi as isSome, Vn as match$2, Vr as filter, Vt as TaggedError, Wi as match$1, Wn as orDie, Wr as findLast, Wt as Union, X as runCollect, Xi as String$6, Xn as raceFirst, Y as run$3, Yn as provideService, Yt as is, Z as runForEach, Zn as result, _n as catchCause, _r as MinimumLogLevel, _t as poll, a as make$15, aa as hasProperty, ar as tryPromise, at as fromChannel, bn as catchTags, br as isDone, bt as makeUnsafe, c as errorExitCode, ca as isNullish, ci as match, cn as toNumber, cr as void_, ct as badArgument, da as identity, dn as all, dr as effect, dt as mapDone, er as serviceOption, fa as pipe, fi as reduce, fn as andThen, fr as mergeAll, ft as endUnsafe, gn as callback, gr as addFinalizer, gt as offerUnsafe, hi as sort, hn as cached, hr as succeed$4, ht as offer, i as isQuitError, ia as format$1, in as value, ir as tap, it as drain, j as FileTypeId, jn as forkScoped, jr as taggedEnum, jt as FalseLiterals, k as make$11, ki as contains, kn as forEach, kr as pretty, kt as BooleanLiterals, l as errorReported, la as isUndefined, ln as acquireRelease, lr as catchDone, lt as systemError, mr as provideMerge, mt as make$13, n as QuitError, na as assignProperty, ni as isReadonlyArrayNonEmpty, nr as suspend, nt as get, o as Stdio, oa as isNotNull, oi as map$3, or as try_, ot as isSink, pa as pipeArguments, pn as as, pr as provide, pt as failCauseUnsafe, q as mkString, qi as some, qn as provide$1, r as Terminal, ra as BaseProto, rn as make$6, rr as sync, rt as make$14, s as make$12, sa as isNotUndefined, sn as bytes, sr as uninterruptible, st as BadArgument, ta as Prototype, tn as toCodecStringTree, tr as succeed$1, tt as unwrap, u as makeRunMain, ua as dual, ui as of, un as addFinalizer$1, ur as round, ut as fromTransform, vn as catchFilter, vr as _await, vt as take, w as Crypto, wi as Service, wn as ensuring, wr as succeed$3, xi as match$3, xn as catch_, xr as isDoneUnsafe, yi as fail$1, yn as catchTag, yr as doneUnsafe, yt as make$8, z as fromChannel$1, zi as getOrUndefined, zn as map$2, zt as String$5 } from "./dist-D3YSXNOO.js";
3
- import { a as holds, c as storeDirs, l as PackageConfig, n as DocumentSource, o as loomsIn, r as LoomCompiler, s as projectIn, t as LoomFormatter, u as LoomConfig } from "./LoomFormatter-Bu8L8cdR.js";
4
- import { a as servicePackage, i as removeService, l as workspaceRoot, n as addService, o as serviceVersion, r as installedVersion, s as storeDir, t as ServiceInstall } from "./LoomStore-pA-ohGNX.js";
2
+ import { $ as transduce, $i as Array_, $n as result, $t as optionalKey, A as FileSystem, Ai as getUnsafe, An as forEach, Ar as done, At as Defect, B as fromEffect, Bi as getOrElse, Bt as Struct, Ci as fail$1, Cn as effectify, Cr as isDone, D as log, Di as Reference, Dn as filterOrFail, Dr as succeed$3, Dt as ArraySchema, E as error, Ei as succeed$2, En as filter$2, Er as fail$2, Et as nominal, F as concat, Fi as filter$3, Fn as ignore, Fr as toMillis, G as mapEffect$1, Gi as isSome, Gn as option, Gr as filter, H as isStream, Hn as mapError, Hr as empty, Ht as TrueLiterals, I as decodeText, Ii as flatMap$2, In as interrupt, J as orDie$1, Ji as match$1, Jn as promise, Jr as findLast, K as merge, Ki as liftThrowable, Kn as orDie, Kr as findFirst, Kt as decodeUnknownEffect, L as empty$2, Ln as isEffect, Lr as dedupe, M as WatchBackend, Mn as forkScoped, Mr as pretty, Mt as Int$4, N as make$10, Ni as contains, Nr as TaggedError$1, Nt as Literal, O as Path$3, Oi as Service, On as flatMap$1, Or as Done, P as callback$1, Pi as exists, Pn as gen, Pr as taggedEnum, Q as splitLines, Qn as raceFirst, Qt as optional$3, R as filter$1, Ri as fromNullishOr, Rr as dedupeWith, Sr as doneUnsafe, T as make$9, Ti as match$3, Tn as fail, Tr as makeUnsafe$1, Ui as getOrUndefined, Un as match$2, V as groupedWithin, Vn as map$2, Vt as TaggedError, Wi as isNone, Wn as matchEffect, Wt as Union, X as runCollect, Xi as orElse, Xn as provideContext, Xr as flatMap$3, Y as run$3, Yi as none, Yn as provide$1, Yt as is, Z as runForEach, Zi as some, Zn as provideService, _ as orElse$1, _a as dual, _n as catchCause, _r as provideMerge, _t as poll, a as make$15, aa as isGreaterThan, ar as sync, at as fromChannel, b as when, ba as pipeArguments, bn as catchTags, br as MinimumLogLevel, bt as makeUnsafe, c as errorExitCode, ca as assignProperty, cn as toNumber, cr as tryPromise, ct as badArgument, da as equals, dn as all, dr as void_, dt as mapDone, ea as Number$2, er as runFork, fa as hasProperty, fi as match, fn as andThen, fr as catchDone, ft as endUnsafe, ga as isUndefined, gi as reduce, gn as callback, gr as provide, gt as offerUnsafe, ha as isNullish, hn as cached, hr as mergeAll, ht as offer, i as isQuitError, in as value, ir as suspend, it as drain, j as FileTypeId, ji as make$7, jn as forever, jr as fail$3, jt as FalseLiterals, k as make$11, ki as empty$1, kn as fnUntraced, kr as UnknownError, kt as BooleanLiterals, l as errorReported, la as BaseProto, ln as acquireRelease, lr as try_, lt as systemError, ma as isNotUndefined, mi as of, mr as effect, mt as make$13, n as QuitError, nr as serviceOption, nt as get, o as Stdio, oa as mapInput, oi as isReadonlyArrayNonEmpty, or as tap, ot as isSink, pa as isNotNull, pn as as, pr as round, pt as failCauseUnsafe, q as mkString, qi as map$4, qn as orElseSucceed, qr as findFirstIndex, r as Terminal, rn as make$6, rr as succeed$1, rt as make$14, s as make$12, sa as Prototype, sn as bytes, sr as tapError, st as BadArgument, ta as String$6, tn as toCodecStringTree, tr as scoped, tt as unwrap, u as makeRunMain, ua as format$1, ui as map$3, un as addFinalizer$1, ur as uninterruptible, ut as fromTransform, va as identity, vn as catchFilter, vr as succeed$4, vt as take, w as Crypto, wn as ensuring, wr as isDoneUnsafe, xn as catch_, xr as _await, y as value$1, ya as pipe, yi as sort, yn as catchTag, yr as addFinalizer, yt as make$8, z as fromChannel$1, zi as fromUndefinedOr, zt as String$5 } from "./dist-NXZtp5_0.js";
3
+ import { a as holds, c as storeDirs, l as PackageConfig, n as DocumentSource, o as loomsIn, r as LoomCompiler, s as projectIn, t as LoomFormatter, u as LoomConfig } from "./LoomFormatter-CcAXsbSL.js";
4
+ import { a as installedVersion, d as serviceVersion, f as standalone, g as workspaceRoot, h as workspaceOf, i as installTypeScript, m as storeTypeScript, n as embeddedFile, p as storeDir, r as installService, s as removeService, t as ServiceInstall, u as servicePackage } from "./LoomStore-Bcx6V9HH.js";
5
5
  import * as OS from "node:os";
6
- import { homedir } from "node:os";
6
+ import { homedir, tmpdir } from "node:os";
7
7
  import * as NodeChildProcess from "node:child_process";
8
8
  import { PassThrough } from "node:stream";
9
9
  import * as NodeCrypto from "node:crypto";
10
+ import { createHash } from "node:crypto";
10
11
  import * as NFS from "node:fs";
11
- import { cpSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
12
+ import { cpSync, existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
12
13
  import * as Path from "node:path";
13
- import { dirname, relative, resolve } from "node:path";
14
+ import { delimiter, dirname, relative, resolve } from "node:path";
15
+ import { gunzipSync } from "node:zlib";
14
16
  import * as NodeUrl from "node:url";
15
17
  import { fileURLToPath, pathToFileURL } from "node:url";
16
18
  import * as readline from "node:readline";
@@ -3038,7 +3040,7 @@ var withDefault$1 = /*#__PURE__*/ dual(2, (self, defaultValue) => {
3038
3040
  * @category combinators
3039
3041
  * @since 4.0.0
3040
3042
  */
3041
- var variadic = (self, options) => {
3043
+ var variadic$1 = (self, options) => {
3042
3044
  const single = getUnderlyingSingleOrThrow(self);
3043
3045
  const parse = (args) => {
3044
3046
  if (single.kind === "argument") return parsePositionalVariadic(self, single, args, options);
@@ -3180,7 +3182,7 @@ var transformSingle = (param, f) => {
3180
3182
  Map: (mapped) => map(transformSingle(mapped.param, f), mapped.f),
3181
3183
  Transform: (mapped) => transform(transformSingle(mapped.param, f), mapped.f, mapped.alternatives.map((alternative) => () => transformSingle(alternative(), f))),
3182
3184
  Optional: (p) => optional$2(transformSingle(p.param, f)),
3183
- Variadic: (p) => variadic(transformSingle(p.param, f), {
3185
+ Variadic: (p) => variadic$1(transformSingle(p.param, f), {
3184
3186
  min: getOrUndefined(p.min),
3185
3187
  max: getOrUndefined(p.max)
3186
3188
  })
@@ -3293,6 +3295,35 @@ var Directory = (name, options) => Directory$1(argumentKind, name, options);
3293
3295
  * @since 4.0.0
3294
3296
  */
3295
3297
  var optional$1 = (arg) => optional$2(arg);
3298
+ /**
3299
+ * Creates a variadic positional argument that accepts multiple values.
3300
+ *
3301
+ * **Example** (Accepting multiple values)
3302
+ *
3303
+ * ```ts import.meta.vitest
3304
+ * import { Argument } from "effect/cli"
3305
+ *
3306
+ * // Accept any number of files
3307
+ * const anyFiles = Argument.String("files").pipe(Argument.variadic)
3308
+ *
3309
+ * // Accept at least 1 file
3310
+ * const atLeastOneFile = Argument.String("files").pipe(
3311
+ * Argument.variadic({ min: 1 })
3312
+ * )
3313
+ *
3314
+ * // Accept between 1 and 5 files
3315
+ * const limitedFiles = Argument.String("files").pipe(
3316
+ * Argument.variadic({ min: 1, max: 5 })
3317
+ * )
3318
+ *
3319
+ * const kinds = [anyFiles.kind, atLeastOneFile.kind, limitedFiles.kind] // => ["argument", "argument", "argument"]
3320
+ * ```
3321
+ *
3322
+ * @stability unstable
3323
+ * @category combinators
3324
+ * @since 4.0.0
3325
+ */
3326
+ var variadic = /*#__PURE__*/ dual((args) => isParam(args[0]), (self, options) => variadic$1(self, options));
3296
3327
  //#endregion
3297
3328
  //#region ../../node_modules/effect/dist/cli/CliOutput.js
3298
3329
  /**
@@ -6165,7 +6196,7 @@ var promptSingle = (single) => {
6165
6196
  case "Date": return map$2(run$2(Date$1({ message })), (date) => commandLineArg(date.toISOString()));
6166
6197
  case "Finite": return map$2(run$2(Number$1({ message })), (value) => commandLineArg(String(value)));
6167
6198
  case "Int": return map$2(run$2(Int$2({ message })), (value) => commandLineArg(String(value)));
6168
- case "Redacted": return map$2(run$2(Password({ message })), (value$1) => commandLineArg(value(value$1), "<redacted>"));
6199
+ case "Redacted": return map$2(run$2(Password({ message })), (value$2) => commandLineArg(value(value$2), "<redacted>"));
6169
6200
  default: return map$2(run$2(String$3({ message })), commandLineArg);
6170
6201
  }
6171
6202
  };
@@ -8621,7 +8652,7 @@ var tangleWatch = (file) => gen(function* () {
8621
8652
  yield* log(`loom: watching ${file} — re-tangling on change`);
8622
8653
  yield* runForEach(tangler.watch(resolve(process.cwd(), file)), match$3({
8623
8654
  onSuccess: reportWritten,
8624
- onFailure: (error$1) => error(error$1.message)
8655
+ onFailure: (error$2) => error(error$2.message)
8625
8656
  }));
8626
8657
  });
8627
8658
  var tangle = (file, watch) => watch ? tangleWatch(file) : tangleOnce(file);
@@ -8653,10 +8684,12 @@ var format = (path, check) => gen(function* () {
8653
8684
  if (check && changed.length > 0) yield* sync(() => void (process.exitCode = 1));
8654
8685
  });
8655
8686
  var typeScriptFrom = (from) => liftThrowable(() => createRequire(from).resolve("typescript/lib/typescript.js"))();
8656
- var projectTypeScript = (root) => match$1(orElse(typeScriptFrom(resolve(root, "package.json")), () => typeScriptFrom(import.meta.url)), {
8657
- onNone: () => succeed$1(none()),
8658
- onSome: (file) => tryPromise(() => import(pathToFileURL(file).href)).pipe(map$2((module) => some(module.default ?? module)), orElseSucceed(() => none()))
8659
- });
8687
+ var foundTypeScript = (root) => pipe(typeScriptFrom(resolve(root, "package.json")), orElse(() => standalone ? none() : typeScriptFrom(import.meta.url)), orElse(() => storeTypeScript(root)));
8688
+ var storedTypeScript = (root) => error(`loom: installing TypeScript ^6 into ${storeDir(root)}`).pipe(andThen(installTypeScript(root)), tapError((error$1) => error(`loom: could not install TypeScript — ${String(error$1.cause)}`)));
8689
+ var projectTypeScript = (root) => match$1(foundTypeScript(root), {
8690
+ onNone: () => storedTypeScript(root),
8691
+ onSome: succeed$1
8692
+ }).pipe(flatMap$1((file) => tryPromise(() => import(pathToFileURL(file).href))), map$2((module) => some(module.default ?? module)), orElseSucceed(() => none()));
8660
8693
  var formatLanguages = (target) => gen(function* () {
8661
8694
  const config = yield* LoomConfig;
8662
8695
  const root = workspaceRoot(dirname(target));
@@ -8669,8 +8702,8 @@ var formatLanguages = (target) => gen(function* () {
8669
8702
  yield* sync(() => {
8670
8703
  globalThis.require ??= createRequire(import.meta.url);
8671
8704
  });
8672
- const { installHostRuntime } = yield* promise(() => import("./Runtime-XT-nb-2w.js"));
8673
- const { loadActive } = yield* promise(() => import("./LanguageLoader-DJZBFaqF.js"));
8705
+ const { installHostRuntime } = yield* promise(() => import("./Runtime-B-1DeuX_.js"));
8706
+ const { loadActive } = yield* promise(() => import("./LanguageLoader-BF5irHbe.js"));
8674
8707
  yield* sync(() => installHostRuntime(ts));
8675
8708
  return yield* loadActive(ids, root);
8676
8709
  })
@@ -8752,24 +8785,27 @@ var updateLanguages = (config, dir, change) => gen(function* () {
8752
8785
  const current = yield* config.manifest(workspace);
8753
8786
  const ids = change(Object.keys(current?.languages ?? {}));
8754
8787
  const languages = Object.fromEntries(ids.map((id) => [id, current?.languages?.[id] ?? {}]));
8755
- yield* config.materialize(workspace, {
8756
- ...current ?? {},
8757
- languages
8758
- });
8788
+ yield* config.edit(workspace, ["languages"], languages);
8759
8789
  });
8790
+ var activatedLanguages = (config, dir) => config.manifest(workspaceRoot(dir)).pipe(map$2((manifest) => Object.keys(manifest?.languages ?? {})));
8791
+ var installNote = (language, change) => ServiceInstall.$match(change, {
8792
+ Current: () => `${servicePackage(language)} ${serviceVersion} is already in the store`,
8793
+ Installed: () => `installed ${servicePackage(language)} ${serviceVersion}`,
8794
+ Updated: ({ from }) => `updated ${servicePackage(language)} from ${from} to ${serviceVersion}`
8795
+ });
8796
+ var failedInstall = (error) => refuse(`loom: could not install ${error.packageName} — ${String(error.cause)}`);
8797
+ var alreadyActive = (language, dir) => log(`\n ${teal("✓")} ${language} is already activated\n` + match$1(installedVersion(language, dir), {
8798
+ onNone: () => ` ${dim(`its service is not in the store; \`loom update ${language}\` installs it`)}\n`,
8799
+ onSome: (version) => version === "0.0.14" ? "" : ` ${dim(`the store holds its service at ${version}; \`loom update ${language}\` brings it to ${serviceVersion}`)}\n`
8800
+ }));
8760
8801
  var add = (language) => gen(function* () {
8761
8802
  const config = yield* LoomConfig;
8762
8803
  const dir = process.cwd();
8763
- const change = yield* addService(language, dir);
8764
- yield* updateLanguages(config, dir, (ids) => [.../* @__PURE__ */ new Set([...ids, language])]);
8765
- const service = `${servicePackage(language)} ${serviceVersion}`;
8766
- const done = ServiceInstall.$match(change, {
8767
- Current: () => `${service} is already in the store`,
8768
- Installed: () => `installed ${service}`,
8769
- Updated: ({ from }) => `updated ${servicePackage(language)} from ${from} to ${serviceVersion}`
8770
- });
8771
- yield* log(`\n ${teal("✓")} activated ${language}\n ${dim(done)}\n ${dim(`store: ${storeDir(dir)}`)}\n`);
8772
- }).pipe(catchTag("StoreError", (error$2) => error(`loom: could not install ${servicePackage(error$2.id)} — ${String(error$2.cause)}`).pipe(andThen(sync(() => void (process.exitCode = 1))))));
8804
+ if ((yield* activatedLanguages(config, dir)).includes(language)) return yield* alreadyActive(language, dir);
8805
+ const change = yield* installService(language, dir);
8806
+ yield* updateLanguages(config, dir, (ids) => [...ids, language]);
8807
+ yield* log(`\n ${teal("✓")} activated ${language}\n ${dim(installNote(language, change))}\n ${dim(`store: ${storeDir(dir)}`)}\n`);
8808
+ }).pipe(catchTag("StoreError", failedInstall));
8773
8809
  var remove = (language) => gen(function* () {
8774
8810
  const config = yield* LoomConfig;
8775
8811
  const dir = process.cwd();
@@ -8777,6 +8813,183 @@ var remove = (language) => gen(function* () {
8777
8813
  yield* updateLanguages(config, dir, (ids) => ids.filter((id) => id !== language));
8778
8814
  yield* log(`\n ${teal("✓")} removed ${language}\n`);
8779
8815
  });
8816
+ var updateUsage = "usage: loom update <language>… | loom update --all";
8817
+ var update = (languages, all) => gen(function* () {
8818
+ if (languages.length === 0 && !all) return yield* refuse(`loom: name the languages to update, or use --all — ${updateUsage}\n To upgrade Loom itself, run \`loom upgrade\`.`);
8819
+ if (languages.length > 0 && all) return yield* refuse(`loom: name languages or use --all, not both — ${updateUsage}`);
8820
+ const config = yield* LoomConfig;
8821
+ const dir = process.cwd();
8822
+ const activated = yield* activatedLanguages(config, dir);
8823
+ const inactive = languages.filter((id) => !activated.includes(id));
8824
+ if (inactive.length > 0) return yield* forEach(inactive, (id) => refuse(`loom: ${id} is not activated; \`loom add ${id}\` turns it on`), { discard: true });
8825
+ const ids = all ? activated : languages;
8826
+ if (ids.length === 0) return yield* log(`\n ${dim("no languages are activated")}\n`);
8827
+ yield* log("");
8828
+ yield* forEach(ids, (id) => installService(id, dir).pipe(flatMap$1((change) => log(` ${teal("✓")} ${dim(installNote(id, change))}`))));
8829
+ yield* log(` ${dim(`store: ${storeDir(dir)}`)}\n`);
8830
+ }).pipe(catchTag("StoreError", failedInstall));
8831
+ var Installation = taggedEnum();
8832
+ var lockfiles = [
8833
+ ["bun.lock", "bun"],
8834
+ ["bun.lockb", "bun"],
8835
+ ["pnpm-lock.yaml", "pnpm"],
8836
+ ["yarn.lock", "yarn"]
8837
+ ];
8838
+ var projectManager = (root) => pipe(findFirst(lockfiles, ([lockfile]) => existsSync(resolve(root, lockfile))), match$1({
8839
+ onNone: () => "npm",
8840
+ onSome: ([, manager]) => manager
8841
+ }));
8842
+ var projectAt = (path) => pipe(fromNullishOr(/^(.*?)[\\/]node_modules[\\/]/.exec(path)), flatMap$2((found) => fromNullishOr(found[1])), filter$3((root) => existsSync(resolve(root, "package.json"))));
8843
+ var marked = (mark) => (path) => mark.test(path);
8844
+ var installationAt = (path, otherwise) => value$1(path).pipe(when(marked(/[\\/]Cellar[\\/]/), () => Installation.Homebrew()), when(marked(/[\\/]\.bun[\\/]/), () => Installation.Bun()), when(marked(/[\\/]pnpm[\\/]/), () => Installation.Pnpm()), when(marked(/[\\/]node_modules[\\/]/), (p) => match$1(projectAt(p), {
8845
+ onNone: () => Installation.Npm(),
8846
+ onSome: (root) => Installation.Project({
8847
+ root,
8848
+ manager: projectManager(root)
8849
+ })
8850
+ })), when(marked(/[\\/]npm[\\/][^\\/]+$/), () => Installation.Npm()), orElse$1(() => otherwise));
8851
+ var realOf = (path) => getOrElse(liftThrowable(() => realpathSync(path))(), () => path);
8852
+ var thisFile = standalone ? process.execPath : fileURLToPath(import.meta.url);
8853
+ var thisInstallation = installationAt(realOf(thisFile), standalone ? Installation.Executable() : Installation.Npm());
8854
+ var describedInstallation = Installation.$match({
8855
+ Executable: () => "a standalone executable",
8856
+ Unowned: () => "a file no installer owns",
8857
+ Homebrew: () => "installed by Homebrew",
8858
+ Npm: () => "installed by npm",
8859
+ Bun: () => "installed by Bun",
8860
+ Pnpm: () => "installed by pnpm",
8861
+ Project: ({ root, manager }) => `installed by ${manager} in the project at ${root}`
8862
+ });
8863
+ var quoted = (path) => `"${path}"`;
8864
+ var projectCommands = {
8865
+ npm: {
8866
+ add: "npm install",
8867
+ remove: "npm uninstall"
8868
+ },
8869
+ bun: {
8870
+ add: "bun add",
8871
+ remove: "bun remove"
8872
+ },
8873
+ pnpm: {
8874
+ add: "pnpm add",
8875
+ remove: "pnpm remove"
8876
+ },
8877
+ yarn: {
8878
+ add: "yarn add",
8879
+ remove: "yarn remove"
8880
+ }
8881
+ };
8882
+ var installerUpgrade = Installation.$match({
8883
+ Executable: () => none(),
8884
+ Unowned: () => none(),
8885
+ Homebrew: () => some("brew upgrade loom"),
8886
+ Npm: () => some("npm install -g @athrio/loom@latest"),
8887
+ Bun: () => some("bun add -g @athrio/loom@latest"),
8888
+ Pnpm: () => some("pnpm add -g @athrio/loom@latest"),
8889
+ Project: ({ root, manager }) => some(`cd ${quoted(root)} && ${projectCommands[manager].add} @athrio/loom@latest`)
8890
+ });
8891
+ var loomVersion = "0.0.14";
8892
+ var releases = process.env.LOOM_RELEASES ?? "https://api.github.com/repos/athrio-com/loom/releases";
8893
+ var ReleaseSchema = Struct({
8894
+ tag_name: String$5,
8895
+ assets: ArraySchema(Struct({
8896
+ name: String$5,
8897
+ browser_download_url: String$5
8898
+ }))
8899
+ });
8900
+ var versionOrder = mapInput(Array_(Number$2), (version) => version.split(".").map(Number));
8901
+ var ReleaseUnreachable = class extends TaggedError$1("ReleaseUnreachable") {};
8902
+ var fetched = (url) => tryPromise({
8903
+ try: () => fetch(url, { headers: { "user-agent": "loom" } }),
8904
+ catch: (cause) => new ReleaseUnreachable({
8905
+ url,
8906
+ cause
8907
+ })
8908
+ }).pipe(filterOrFail((response) => response.ok, (response) => new ReleaseUnreachable({
8909
+ url,
8910
+ cause: `${response.status} ${response.statusText}`
8911
+ })));
8912
+ var latestRelease = gen(function* () {
8913
+ const url = `${releases}/latest`;
8914
+ const response = yield* fetched(url);
8915
+ const body = yield* tryPromise({
8916
+ try: () => response.json(),
8917
+ catch: (cause) => new ReleaseUnreachable({
8918
+ url,
8919
+ cause
8920
+ })
8921
+ });
8922
+ return yield* decodeUnknownEffect(ReleaseSchema)(body).pipe(mapError((cause) => new ReleaseUnreachable({
8923
+ url,
8924
+ cause
8925
+ })));
8926
+ });
8927
+ var bytesAt = (url) => fetched(url).pipe(flatMap$1((response) => tryPromise({
8928
+ try: async () => new Uint8Array(await response.arrayBuffer()),
8929
+ catch: (cause) => new ReleaseUnreachable({
8930
+ url,
8931
+ cause
8932
+ })
8933
+ })));
8934
+ var assetName = `${process.platform === "win32" ? `loom-windows-${process.arch}.exe` : `loom-${process.platform}-${process.arch}`}.gz`;
8935
+ var ReleaseLacksAsset = class extends TaggedError$1("ReleaseLacksAsset") {};
8936
+ var ChecksumMismatch = class extends TaggedError$1("ChecksumMismatch") {};
8937
+ var assetUrl = (release, asset) => match$1(findFirst(release.assets, (candidate) => candidate.name === asset), {
8938
+ onNone: () => fail(new ReleaseLacksAsset({
8939
+ version: release.tag_name,
8940
+ asset
8941
+ })),
8942
+ onSome: (found) => succeed$1(found.browser_download_url)
8943
+ });
8944
+ var listedChecksum = (sums, asset) => pipe(sums.split("\n"), map$3((line) => line.trim().split(/\s+/)), findFirst((fields) => fields[1] === asset || fields[1] === `*${asset}`), flatMap$2((fields) => fromNullishOr(fields[0])));
8945
+ var verified = (bytes, sums, asset) => contains(listedChecksum(sums, asset), createHash("sha256").update(bytes).digest("hex")) ? succeed$1(bytes) : fail(new ChecksumMismatch({ asset }));
8946
+ var UnpackFailed = class extends TaggedError$1("UnpackFailed") {};
8947
+ var unpacked = (archive) => try_({
8948
+ try: () => new Uint8Array(gunzipSync(archive)),
8949
+ catch: (cause) => new UnpackFailed({
8950
+ asset: assetName,
8951
+ cause
8952
+ })
8953
+ });
8954
+ var ReplaceFailed = class extends TaggedError$1("ReplaceFailed") {};
8955
+ var moveAside = (target) => {
8956
+ if (process.platform !== "win32") return;
8957
+ rmSync(`${target}.old`, { force: true });
8958
+ renameSync(target, `${target}.old`);
8959
+ };
8960
+ var replaceExecutable = (bytes) => {
8961
+ const target = process.execPath;
8962
+ const partial = `${target}.${process.pid}`;
8963
+ return try_({
8964
+ try: () => {
8965
+ writeFileSync(partial, bytes, { mode: 493 });
8966
+ moveAside(target);
8967
+ renameSync(partial, target);
8968
+ },
8969
+ catch: (cause) => new ReplaceFailed({
8970
+ path: target,
8971
+ cause
8972
+ })
8973
+ }).pipe(tapError(() => sync(() => rmSync(partial, { force: true }))));
8974
+ };
8975
+ var upgradeStandalone = gen(function* () {
8976
+ const release = yield* latestRelease;
8977
+ const latest = release.tag_name.replace(/^v/, "");
8978
+ if (!isGreaterThan(versionOrder)(latest, loomVersion)) return yield* log(`\n ${teal("✓")} Loom ${loomVersion} is up to date; the latest release is ${latest}\n`);
8979
+ yield* verified(yield* assetUrl(release, assetName).pipe(flatMap$1(bytesAt)), yield* assetUrl(release, "SHA256SUMS").pipe(flatMap$1(bytesAt), map$2((bytes) => new TextDecoder().decode(bytes))), assetName).pipe(flatMap$1(unpacked), flatMap$1(replaceExecutable));
8980
+ yield* log(`\n ${teal("✓")} upgraded Loom from ${loomVersion} to ${latest}\n ${dim("run `loom update --all` in each workspace to bring its services along")}\n`);
8981
+ });
8982
+ var upgrade = gen(function* () {
8983
+ const command = installerUpgrade(thisInstallation);
8984
+ if (isNone(command)) return yield* upgradeStandalone;
8985
+ yield* log(`\n Loom was ${describedInstallation(thisInstallation)}. Upgrade it with:\n\n ${command.value}\n\n ${dim("then run `loom update --all` in each workspace to bring its services along")}\n`);
8986
+ }).pipe(catchTags({
8987
+ ReleaseUnreachable: (error) => refuse(`loom: could not reach the latest release at ${error.url} — ${String(error.cause)}`),
8988
+ ReleaseLacksAsset: (error) => refuse(`loom: release ${error.version} carries no ${error.asset}`),
8989
+ ChecksumMismatch: (error) => refuse(`loom: the checksum of the downloaded ${error.asset} does not match the release's list, so Loom was left as it was`),
8990
+ UnpackFailed: (error) => refuse(`loom: could not unpack ${error.asset} — ${String(error.cause)}`),
8991
+ ReplaceFailed: (error) => refuse(`loom: could not replace ${error.path} — ${String(error.cause)}\n Run the install script again, or move Loom somewhere you can write to.`)
8992
+ }));
8780
8993
  var status = gen(function* () {
8781
8994
  const config = yield* LoomConfig;
8782
8995
  const dir = process.cwd();
@@ -8784,12 +8997,92 @@ var status = gen(function* () {
8784
8997
  const primary = manifest?.primary;
8785
8998
  const languages = Object.keys(manifest?.languages ?? {});
8786
8999
  const mark = (id) => match$1(installedVersion(id, dir), {
8787
- onNone: () => ` ${dim("○")} ${id}${dim(` — run \`loom add ${id}\``)}`,
8788
- onSome: (version) => version === "0.0.12" ? ` ${teal("●")} ${id}` : ` ${dim("◐")} ${id}${dim(` — ${version} is installed; run \`loom add ${id}\` for ${serviceVersion}`)}`
9000
+ onNone: () => ` ${dim("○")} ${id}${dim(` — run \`loom update ${id}\``)}`,
9001
+ onSome: (version) => version === "0.0.14" ? ` ${teal("●")} ${id}` : ` ${dim("◐")} ${id}${dim(` — ${version} is installed; run \`loom update ${id}\` for ${serviceVersion}`)}`
8789
9002
  });
8790
9003
  yield* log(`\n ${dim("store")} ${storeDir(dir)}\n ${dim("primary")} ${primary ?? dim("(none)")}\n ${dim("activated")} ${languages.length === 0 ? dim("(none)") : languages.join(", ")}\n`);
8791
9004
  if (languages.length > 0) yield* log(`${languages.map(mark).join("\n")}\n`);
8792
9005
  });
9006
+ var Finding = taggedEnum();
9007
+ var commandNames = (command) => process.platform === "win32" ? [`${command}.exe`, `${command}.cmd`] : [command];
9008
+ var isProgram = (file) => pipe(liftThrowable(() => statSync(file))(), exists((stats) => stats.isFile() && (process.platform === "win32" || (stats.mode & 73) !== 0)));
9009
+ var programsOnPath = (command) => pipe((process.env.PATH ?? "").split(delimiter), filter((folder) => folder !== ""), flatMap$3((folder) => map$3(commandNames(command), (name) => resolve(folder, name))), filter(isProgram), dedupeWith((one, other) => realOf(one) === realOf(other)));
9010
+ var loomsOnPath = () => programsOnPath("loom");
9011
+ var installationOf = (file) => installationAt(realOf(file), Installation.Unowned());
9012
+ var isThisLoom = (file) => realOf(file) === realOf(thisFile) || equals(installationOf(file), thisInstallation);
9013
+ var installLine = "curl -fsSL https://github.com/athrio-com/loom/releases/latest/download/install.sh | sh";
9014
+ var installerRemoval = (installation, file) => Installation.$match(installation, {
9015
+ Executable: () => `rm ${quoted(file)}`,
9016
+ Unowned: () => `rm ${quoted(file)}`,
9017
+ Homebrew: () => "brew uninstall loom",
9018
+ Npm: () => "npm uninstall -g @athrio/loom",
9019
+ Bun: () => "bun remove -g @athrio/loom",
9020
+ Pnpm: () => "pnpm remove -g @athrio/loom",
9021
+ Project: ({ root, manager }) => `cd ${quoted(root)} && ${projectCommands[manager].remove} @athrio/loom`
9022
+ });
9023
+ var otherLoom = (file, note) => Finding.Problem({
9024
+ note: `${note}, ${describedInstallation(installationOf(file))}`,
9025
+ fix: installerRemoval(installationOf(file), file)
9026
+ });
9027
+ var thisLoomFinding = Finding.Fine({ note: `loom v${loomVersion} runs from ${thisFile}, ${describedInstallation(thisInstallation)}` });
9028
+ var pathFindings = (looms) => match(looms, {
9029
+ onEmpty: () => [Finding.Problem({
9030
+ note: "no loom is on PATH, so a terminal finds none to run",
9031
+ fix: installLine
9032
+ })],
9033
+ onNonEmpty: ([first, ...rest]) => [isThisLoom(first) ? Finding.Fine({ note: `a terminal runs this loom, at ${first}` }) : otherLoom(first, `a terminal runs ${first} instead`), ...pipe(rest, filter((file) => !isThisLoom(file)), map$3((file) => otherLoom(file, `${file} is on PATH too`)))]
9034
+ });
9035
+ var serviceFinding = (id, root) => match$1(installedVersion(id, root), {
9036
+ onNone: () => Finding.Problem({
9037
+ note: `the store holds no service for ${id}`,
9038
+ fix: `loom update ${id}`
9039
+ }),
9040
+ onSome: (version) => version === "0.0.14" ? Finding.Fine({ note: `the store holds ${id}'s service at this Loom's ${serviceVersion}` }) : Finding.Problem({
9041
+ note: `the store holds ${id}'s service at ${version}, and this Loom needs ${serviceVersion}`,
9042
+ fix: `loom update ${id}`
9043
+ })
9044
+ });
9045
+ var serviceFindings = (languages, root) => match(languages, {
9046
+ onEmpty: () => [Finding.Fine({ note: "no language is activated, so the store needs no service" })],
9047
+ onNonEmpty: (ids) => map$3(ids, (id) => serviceFinding(id, root))
9048
+ });
9049
+ var missingTypeScript = (root) => value$1({
9050
+ standalone,
9051
+ npm: programsOnPath("npm").length > 0
9052
+ }).pipe(when({ standalone: true }, () => Finding.Fine({ note: `the language server unpacks the TypeScript Loom carries into ${storeDir(root)} when it first starts` })), when({ npm: true }, () => Finding.Fine({ note: `the language server installs TypeScript ^6 into ${storeDir(root)} with npm when it first starts` })), orElse$1(() => Finding.Problem({
9053
+ note: "the language server finds no TypeScript, and has no npm to install one with",
9054
+ fix: installLine
9055
+ })));
9056
+ var typeScriptFinding = (root) => match$1(foundTypeScript(root), {
9057
+ onNone: () => missingTypeScript(root),
9058
+ onSome: (file) => Finding.Fine({ note: `the language server finds TypeScript in ${dirname(dirname(file))}` })
9059
+ });
9060
+ var workspaceFindings = (root) => gen(function* () {
9061
+ const manifest = yield* (yield* LoomConfig).manifest(root);
9062
+ return [...serviceFindings(Object.keys(manifest?.languages ?? {}), root), typeScriptFinding(root)];
9063
+ });
9064
+ var amber = (s) => `\x1b[38;5;214m${s}${reset}`;
9065
+ var findingLines = (findings) => map$3(findings, Finding.$match({
9066
+ Fine: ({ note }) => ` ${teal("✓")} ${note}`,
9067
+ Problem: ({ note, fix }) => ` ${amber("✗")} ${note}\n ${fix}`
9068
+ })).join("\n");
9069
+ var doctor = gen(function* () {
9070
+ const dir = process.cwd();
9071
+ const machine = [thisLoomFinding, ...pathFindings(loomsOnPath())];
9072
+ const workspace = workspaceOf(dir);
9073
+ const inWorkspace = yield* match$1(workspace, {
9074
+ onNone: () => succeed$1([]),
9075
+ onSome: workspaceFindings
9076
+ });
9077
+ const problems = filter([...machine, ...inWorkspace], Finding.$is("Problem")).length;
9078
+ yield* log(`\n ${dim("this machine")}\n${findingLines(machine)}\n\n` + match$1(workspace, {
9079
+ onNone: () => ` ${dim(`no workspace holds ${dir}, so no services to check`)}\n`,
9080
+ onSome: (root) => ` ${dim(`the workspace at ${root}`)}\n${findingLines(inWorkspace)}\n`
9081
+ }));
9082
+ if (problems === 0) return yield* log(` ${teal("✓")} no problems found\n`);
9083
+ yield* log(` ${problems === 1 ? "1 problem" : `${problems} problems`} found\n`);
9084
+ yield* sync(() => void (process.exitCode = 1));
9085
+ });
8793
9086
  var set = (name, value) => gen(function* () {
8794
9087
  const config = yield* LoomConfig;
8795
9088
  const tangler = yield* LoomTangler;
@@ -8806,13 +9099,7 @@ var set = (name, value) => gen(function* () {
8806
9099
  return;
8807
9100
  }
8808
9101
  const current = yield* config.manifest(workspace);
8809
- yield* config.materialize(workspace, {
8810
- ...current ?? {},
8811
- variables: {
8812
- ...current?.variables ?? {},
8813
- [name]: value
8814
- }
8815
- });
9102
+ yield* config.edit(workspace, ["variables", name], value);
8816
9103
  const corpus = resolve(workspace, current?.corpus ?? "corpus");
8817
9104
  yield* log(`loom: set ${name} = ${value} (re-tangled ${(yield* tangler.tangle(corpus)).length} files)`);
8818
9105
  }).pipe(catchTag("TangleError", (e) => error(e.message).pipe(andThen(sync(() => void (process.exitCode = 1))))));
@@ -8835,12 +9122,24 @@ var design = (project, application, port) => gen(function* () {
8835
9122
  }), (running) => running.exitCode));
8836
9123
  yield* sync(() => void (process.exitCode = code));
8837
9124
  }).pipe(catchTag("DesignMissing", () => error("loom: Loom Design is not installed.\n Add it with `bun add -d @athrio/loom-design`, then run this again.").pipe(andThen(sync(() => void (process.exitCode = 1))))), catchCause((cause) => error(`loom: Loom Design could not start\n${pretty(cause)}`).pipe(andThen(sync(() => void (process.exitCode = 1))))));
9125
+ var embeddedGrammar = tryPromise(() => import("./_virtual_tree-sitter-loom-CFLf84Ng.js")).pipe(map$2((module) => some(module.default)), orElseSucceed(() => none()));
9126
+ var unpackedGrammar = (files) => acquireRelease(sync(() => mkdtempSync(resolve(tmpdir(), "loom-grammar-"))), (dir) => sync(() => rmSync(dir, {
9127
+ recursive: true,
9128
+ force: true
9129
+ }))).pipe(tap((dir) => forEach(Object.entries(files), ([path, text]) => sync(() => {
9130
+ mkdirSync(dirname(resolve(dir, path)), { recursive: true });
9131
+ writeFileSync(resolve(dir, path), text);
9132
+ }), { discard: true })));
8838
9133
  var GrammarMissing = class extends TaggedError$1("GrammarMissing") {};
8839
9134
  var grammarIn = (dir) => existsSync(resolve(dir, "src", "parser.c")) ? some(dir) : none();
8840
- var shippedGrammar = pipe(grammarIn(resolve(dirname(fileURLToPath(import.meta.url)), "tree-sitter-loom")), orElse(() => flatMap$2(liftThrowable(() => createRequire(import.meta.url).resolve("tree-sitter-loom/package.json"))(), (manifest) => grammarIn(dirname(manifest)))), match$1({
8841
- onNone: () => fail(new GrammarMissing()),
8842
- onSome: (dir) => succeed$1(dir)
8843
- }));
9135
+ var workspaceGrammar = () => flatMap$2(liftThrowable(() => createRequire(import.meta.url).resolve("tree-sitter-loom/package.json"))(), (manifest) => grammarIn(dirname(manifest)));
9136
+ var shippedGrammar = embeddedGrammar.pipe(flatMap$1(match$1({
9137
+ onSome: unpackedGrammar,
9138
+ onNone: () => match$1(workspaceGrammar(), {
9139
+ onNone: () => fail(new GrammarMissing()),
9140
+ onSome: (dir) => succeed$1(dir)
9141
+ })
9142
+ })));
8844
9143
  var GrammarCompileFailed = class extends TaggedError$1("GrammarCompileFailed") {};
8845
9144
  var compileGrammar = (grammar, library) => gen(function* () {
8846
9145
  const compiler = process.env.CC ?? "cc";
@@ -8863,10 +9162,19 @@ var compileGrammar = (grammar, library) => gen(function* () {
8863
9162
  }), (running) => running.exitCode)).pipe(catchCause(() => succeed$1(-1)))) !== 0) return yield* fail(new GrammarCompileFailed({ compiler }));
8864
9163
  yield* sync(() => renameSync(partial, library));
8865
9164
  });
9165
+ var grammarLibrary = process.platform === "win32" ? "loom.dll" : "loom.so";
9166
+ var writeLibrary = (prebuilt, library) => promise(() => prebuilt.arrayBuffer()).pipe(flatMap$1((bytes) => sync(() => {
9167
+ const partial = `${library}.${process.pid}`;
9168
+ writeFileSync(partial, new Uint8Array(bytes), { mode: 493 });
9169
+ renameSync(partial, library);
9170
+ })));
9171
+ var buildGrammar = (grammar, library) => match$1(embeddedFile(grammarLibrary), {
9172
+ onSome: (prebuilt) => writeLibrary(prebuilt, library),
9173
+ onNone: () => compileGrammar(grammar, library)
9174
+ });
8866
9175
  var refuse = (message) => error(message).pipe(andThen(sync(() => void (process.exitCode = 1))));
8867
9176
  var cannotCompile = (error) => refuse(`loom: could not compile the grammar with \`${error.compiler}\`.\n Install a C compiler, or name one in the CC variable, then run this again.`);
8868
9177
  var helixConfigDir = () => process.platform === "win32" ? resolve(process.env.APPDATA ?? homedir(), "helix") : resolve(process.env.XDG_CONFIG_HOME ?? resolve(homedir(), ".config"), "helix");
8869
- var grammarLibrary = process.platform === "win32" ? "loom.dll" : "loom.so";
8870
9178
  var helixBlock = {
8871
9179
  begin: "# Loom: written by `loom helix`, which replaces this block on every run",
8872
9180
  end: "# Loom: end",
@@ -8875,7 +9183,7 @@ var helixBlock = {
8875
9183
  "name = \"loom\"",
8876
9184
  "scope = \"source.loom\"",
8877
9185
  "file-types = [\"loom\"]",
8878
- "roots = [\".loom\"]",
9186
+ "roots = [\".loom/config.yaml\"]",
8879
9187
  "injection-regex = \"^loom$\"",
8880
9188
  "language-servers = [\"loom\"]",
8881
9189
  "soft-wrap = { enable = true, wrap-at-text-width = true }",
@@ -8899,14 +9207,14 @@ var helix = gen(function* () {
8899
9207
  const languages = yield* withLoomLanguages(languagesFile, yield* sync(() => existsSync(languagesFile) ? readFileSync(languagesFile, "utf8") : ""));
8900
9208
  const library = resolve(config, "runtime", "grammars", grammarLibrary);
8901
9209
  yield* sync(() => mkdirSync(dirname(library), { recursive: true }));
8902
- yield* compileGrammar(grammar, library);
9210
+ yield* buildGrammar(grammar, library);
8903
9211
  yield* log(`\n ${teal("✓")} built the grammar into ${library}`);
8904
9212
  const queries = resolve(config, "runtime", "queries", "loom");
8905
9213
  yield* sync(() => cpSync(resolve(grammar, "editors", "helix", "queries", "loom"), queries, { recursive: true }));
8906
9214
  yield* log(` ${teal("✓")} copied the queries into ${queries}`);
8907
9215
  yield* sync(() => writeFileSync(languagesFile, languages));
8908
9216
  yield* log(` ${teal("✓")} added Loom to ${languagesFile}\n ${dim("check it with `hx --health loom`")}\n`);
8909
- }).pipe(catchTags({
9217
+ }).pipe(scoped, catchTags({
8910
9218
  GrammarMissing: () => refuse("loom: this installation of Loom carries no grammar for Helix."),
8911
9219
  GrammarCompileFailed: cannotCompile,
8912
9220
  HelixConfigClash: (error) => refuse(`loom: ${error.file} already sets up Loom.\n Remove its Loom entries, then run this again to replace them with the managed block.`)
@@ -8923,7 +9231,13 @@ var nvimPlugin = [
8923
9231
  "vim.lsp.config('loom', {",
8924
9232
  " cmd = { 'loom', 'lsp', '--stdio' },",
8925
9233
  " filetypes = { 'loom' },",
8926
- " root_markers = { '.loom', '.git' },",
9234
+ " root_dir = function(bufnr, on_dir)",
9235
+ " local workspace = function(name, path)",
9236
+ " local config = vim.fs.joinpath(path, name, 'config.yaml')",
9237
+ " return name == '.loom' and vim.uv.fs_stat(config) ~= nil",
9238
+ " end",
9239
+ " on_dir(vim.fs.root(bufnr, workspace) or vim.fs.root(bufnr, '.git'))",
9240
+ " end,",
8927
9241
  "})",
8928
9242
  "vim.lsp.enable('loom')",
8929
9243
  "",
@@ -8944,7 +9258,7 @@ var nvim = gen(function* () {
8944
9258
  if (exists(yield* sync(() => existsSync(pluginFile) ? some(readFileSync(pluginFile, "utf8")) : none()), (text) => !text.startsWith(nvimHeader))) return yield* fail(new NvimConfigClash({ file: pluginFile }));
8945
9259
  const parser = resolve(site, "parser", "loom.so");
8946
9260
  yield* sync(() => mkdirSync(dirname(parser), { recursive: true }));
8947
- yield* compileGrammar(grammar, parser);
9261
+ yield* buildGrammar(grammar, parser);
8948
9262
  yield* log(`\n ${teal("✓")} built the grammar into ${parser}`);
8949
9263
  const queries = resolve(site, "queries", "loom");
8950
9264
  yield* sync(() => cpSync(resolve(grammar, "queries"), queries, { recursive: true }));
@@ -8954,7 +9268,7 @@ var nvim = gen(function* () {
8954
9268
  writeFileSync(pluginFile, nvimPlugin);
8955
9269
  });
8956
9270
  yield* log(` ${teal("✓")} added Loom to ${pluginFile}\n ${dim("check it with `:checkhealth vim.treesitter` in Neovim")}\n`);
8957
- }).pipe(catchTags({
9271
+ }).pipe(scoped, catchTags({
8958
9272
  GrammarMissing: () => refuse("loom: this installation of Loom carries no grammar for Neovim."),
8959
9273
  GrammarCompileFailed: cannotCompile,
8960
9274
  NvimConfigClash: (error) => refuse(`loom: ${error.file} was not written by \`loom nvim\`.\n Move it aside, then run this again.`)
@@ -8976,7 +9290,13 @@ var tocCommand = make$5("toc", { path: String$1("path") }, ({ path }) => toc(pat
8976
9290
  var initCommand = make$5("init", { dir: optional$1(Directory("dir")) }, ({ dir }) => init(dir));
8977
9291
  var addCommand = make$5("add", { language: String$1("language") }, ({ language }) => add(language));
8978
9292
  var removeCommand = make$5("remove", { language: String$1("language") }, ({ language }) => remove(language));
9293
+ var updateCommand = make$5("update", {
9294
+ languages: String$1("language").pipe(variadic()),
9295
+ all: Boolean("all").pipe(withDefault(false))
9296
+ }, ({ languages, all }) => update(languages, all));
9297
+ var upgradeCommand = make$5("upgrade", {}, () => upgrade);
8979
9298
  var statusCommand = make$5("status", {}, () => status);
9299
+ var doctorCommand = make$5("doctor", {}, () => doctor);
8980
9300
  var setCommand = make$5("set", {
8981
9301
  name: String$1("name"),
8982
9302
  value: String$1("value")
@@ -8997,15 +9317,18 @@ var program = run(make$5("loom").pipe(withSubcommands([
8997
9317
  initCommand,
8998
9318
  addCommand,
8999
9319
  removeCommand,
9320
+ updateCommand,
9321
+ upgradeCommand,
9000
9322
  statusCommand,
9323
+ doctorCommand,
9001
9324
  setCommand,
9002
9325
  designCommand,
9003
9326
  helixCommand,
9004
9327
  nvimCommand
9005
- ])), { version: "0.0.12" }).pipe(provide$1(LoomTangler.layer), provide$1(LoomWeaver.layer), provide$1(LoomContents.layer), provide$1(LoomFormatter.layer), provide$1(DocumentSource.layer), provide$1(PackageConfig.layer), provide$1(LoomConfig.layer), provide$1(layer));
9328
+ ])), { version: loomVersion }).pipe(provide$1(LoomTangler.layer), provide$1(LoomWeaver.layer), provide$1(LoomContents.layer), provide$1(LoomFormatter.layer), provide$1(DocumentSource.layer), provide$1(PackageConfig.layer), provide$1(LoomConfig.layer), provide$1(layer));
9006
9329
  if (process.argv[2] === "lsp") {
9007
9330
  globalThis.require = createRequire(import.meta.url);
9008
- const { startLanguageServer } = await import("./LoomServer-DXIree_1.js");
9331
+ const { startLanguageServer } = await import("./LoomServer-DpleSkxj.js");
9009
9332
  startLanguageServer();
9010
9333
  } else runMain(program);
9011
9334
  //#endregion