Skip to content

Commit e549b2f

Browse files
committed
Add tree command
1 parent 95d76cf commit e549b2f

File tree

3 files changed

+68
-2
lines changed

3 files changed

+68
-2
lines changed

packages/cli/bin.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
AddCommand,
33
type CommandDescriptor,
44
FetchCommand,
5+
TreeCommand,
56
ViewCommand,
67
} from "./src/commands.ts";
78
import { Command } from "@cliffy/command";
@@ -15,7 +16,7 @@ const bin = new Command()
1516
console.log(bin.getHelp());
1617
});
1718

18-
const commands = [FetchCommand, AddCommand, ViewCommand];
19+
const commands = [FetchCommand, AddCommand, ViewCommand, TreeCommand];
1920
const container = new Container();
2021

2122
for (const cmd of commands) {

packages/cli/deno.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "@lpm/cli",
33
"exports": "./bin.ts",
4-
"version": "0.1.15",
4+
"version": "0.1.16",
55
"license": "MIT",
66

77
"imports": {

packages/cli/src/commands.ts

+65
Original file line numberDiff line numberDiff line change
@@ -196,3 +196,68 @@ export class ViewCommand implements CommandDescriptor {
196196
);
197197
}
198198
}
199+
200+
@injectable()
201+
export class TreeCommand implements CommandDescriptor {
202+
constructor(private registry = inject(NodeRegistry)) {}
203+
204+
name = "tree";
205+
206+
command = new Command()
207+
.name("tree")
208+
.description("View a lexicon tree.")
209+
.type("nsid", inputTypes.nsid)
210+
.option("-d --depth <depth:number>", "The depth of the tree.", {
211+
default: Infinity,
212+
})
213+
.arguments("<nsid:nsid>")
214+
.action(({ depth }, nsid) => this.#action(nsid, depth));
215+
216+
async #action(nsid: NSID, maxDepth: number) {
217+
const root = await this.registry.get(nsid).resolve();
218+
if (!root.success) {
219+
console.error("failed to resolve ", root.errorCode);
220+
return;
221+
}
222+
223+
const getIndent = (ancestors: string[], isLast: boolean): string => {
224+
let indent = "";
225+
for (let i = 0; i < ancestors.length; i++) {
226+
indent += i === ancestors.length - 1
227+
? `${isLast ? "└" : "├"}─── `
228+
: "│ ";
229+
}
230+
return indent;
231+
};
232+
233+
const printNode = async (
234+
node: Resolution,
235+
ancestors: string[],
236+
isLast = false,
237+
) => {
238+
if (!node.success) {
239+
throw new Error("failed to resolve");
240+
}
241+
const nodeId = node.nsid.toString();
242+
const indent = getIndent(ancestors, isLast);
243+
if (ancestors.includes(nodeId)) {
244+
console.log(`${indent}${nodeId} ${fmt.yellow("●")}`);
245+
return;
246+
}
247+
console.log(
248+
`${indent}${node.children.length === 0 ? nodeId : fmt.bold(nodeId)}`,
249+
);
250+
if (ancestors.length + 1 > maxDepth) {
251+
return;
252+
}
253+
254+
for (const [i, child] of node.children.entries()) {
255+
const childResolution = await this.registry.get(child).resolve();
256+
const isLast = i === node.children.length - 1;
257+
await printNode(childResolution, [...ancestors, nodeId], isLast);
258+
}
259+
};
260+
261+
await printNode(root, []);
262+
}
263+
}

0 commit comments

Comments
 (0)