@nijaru/tk 0.0.3 → 0.0.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/package.json +1 -1
- package/src/cli.test.ts +236 -40
- package/src/cli.ts +52 -308
- package/src/db/storage.ts +87 -51
- package/src/lib/completions.ts +23 -8
- package/src/lib/format.test.ts +81 -5
- package/src/lib/format.ts +48 -35
- package/src/lib/help.ts +266 -0
- package/src/lib/time.test.ts +222 -0
- package/src/lib/time.ts +24 -1
- package/src/types.ts +4 -4
package/src/cli.ts
CHANGED
|
@@ -13,11 +13,13 @@ import {
|
|
|
13
13
|
green,
|
|
14
14
|
red,
|
|
15
15
|
yellow,
|
|
16
|
+
dim,
|
|
16
17
|
} from "./lib/format";
|
|
17
18
|
import { findRoot, setWorkingDir } from "./lib/root";
|
|
18
19
|
import { parseId } from "./types";
|
|
19
20
|
import type { Status, TaskWithMeta } from "./types";
|
|
20
21
|
import { BASH_COMPLETION, ZSH_COMPLETION, FISH_COMPLETION } from "./lib/completions";
|
|
22
|
+
import { MAIN_HELP, COMMAND_HELP } from "./lib/help";
|
|
21
23
|
|
|
22
24
|
const VALID_STATUSES: Status[] = ["open", "active", "done"];
|
|
23
25
|
const PROJECT_PATTERN = /^[a-z][a-z0-9]*$/;
|
|
@@ -40,7 +42,7 @@ const TASK_MUTATION_OPTIONS = {
|
|
|
40
42
|
function validateProject(name: string): void {
|
|
41
43
|
if (!PROJECT_PATTERN.test(name)) {
|
|
42
44
|
throw new Error(
|
|
43
|
-
`Invalid project name: ${name}. Use lowercase letters and numbers, starting with a letter.`,
|
|
45
|
+
`Invalid project name: ${name}. Use lowercase letters and numbers, starting with a letter (e.g., 'api', 'web2').`,
|
|
44
46
|
);
|
|
45
47
|
}
|
|
46
48
|
}
|
|
@@ -108,7 +110,7 @@ function resolveId(input: string | undefined, context: string): string {
|
|
|
108
110
|
const matches = storage.findMatchingIds(input);
|
|
109
111
|
if (matches.length > 1) {
|
|
110
112
|
throw new Error(
|
|
111
|
-
`Ambiguous ID '${input}' matches ${matches.length} tasks: ${matches.join(", ")}
|
|
113
|
+
`Ambiguous ID '${input}' matches ${matches.length} tasks: ${matches.join(", ")}. Use more characters to narrow it down.`,
|
|
112
114
|
);
|
|
113
115
|
}
|
|
114
116
|
|
|
@@ -116,7 +118,7 @@ function resolveId(input: string | undefined, context: string): string {
|
|
|
116
118
|
// and let getTask handle the "not found" error consistently.
|
|
117
119
|
if (parseId(input)) return input;
|
|
118
120
|
|
|
119
|
-
throw new Error(`Task not found: ${input}
|
|
121
|
+
throw new Error(`Task not found: ${input}. Run 'tk ls' to see available tasks.`);
|
|
120
122
|
}
|
|
121
123
|
|
|
122
124
|
/**
|
|
@@ -126,7 +128,7 @@ function resolveId(input: string | undefined, context: string): string {
|
|
|
126
128
|
function resolveTask(input: string | undefined, context: string): TaskWithMeta {
|
|
127
129
|
const id = resolveId(input, context);
|
|
128
130
|
const result = storage.getTask(id);
|
|
129
|
-
if (!result) error(`Task not found: ${id}
|
|
131
|
+
if (!result) error(`Task not found: ${id}. Run 'tk ls' to see available tasks.`);
|
|
130
132
|
|
|
131
133
|
outputCleanup(id, result.cleanup);
|
|
132
134
|
return result.task;
|
|
@@ -195,258 +197,12 @@ function error(message: string): never {
|
|
|
195
197
|
process.exit(1);
|
|
196
198
|
}
|
|
197
199
|
|
|
198
|
-
function showHelp() {
|
|
199
|
-
console.log(
|
|
200
|
-
|
|
201
|
-
USAGE:
|
|
202
|
-
tk <command> [options]
|
|
203
|
-
|
|
204
|
-
COMMANDS:
|
|
205
|
-
init Initialize .tasks/ directory
|
|
206
|
-
add Create task
|
|
207
|
-
ls, list List tasks
|
|
208
|
-
ready List ready tasks (active/open + unblocked)
|
|
209
|
-
show Show task details
|
|
210
|
-
start Start working (open -> active)
|
|
211
|
-
done Complete task
|
|
212
|
-
reopen Reopen task
|
|
213
|
-
edit Edit task
|
|
214
|
-
log Add log entry
|
|
215
|
-
block Add blocker
|
|
216
|
-
unblock Remove blocker
|
|
217
|
-
rm, remove Delete task
|
|
218
|
-
clean Remove old done tasks
|
|
219
|
-
check Check for data issues
|
|
220
|
-
config Show/set configuration
|
|
221
|
-
completions Output shell completions
|
|
222
|
-
|
|
223
|
-
GLOBAL OPTIONS:
|
|
224
|
-
-C <dir> Run in different directory
|
|
225
|
-
--json Output as JSON
|
|
226
|
-
-h, --help Show help
|
|
227
|
-
-V Show version
|
|
228
|
-
|
|
229
|
-
Run 'tk <command> --help' for command-specific options.
|
|
230
|
-
`);
|
|
200
|
+
function showHelp(): void {
|
|
201
|
+
console.log(MAIN_HELP);
|
|
231
202
|
}
|
|
232
203
|
|
|
233
|
-
function showCommandHelp(cmd: string) {
|
|
234
|
-
const
|
|
235
|
-
init: `tk init - Initialize .tasks/ directory
|
|
236
|
-
|
|
237
|
-
USAGE:
|
|
238
|
-
tk init [options]
|
|
239
|
-
|
|
240
|
-
OPTIONS:
|
|
241
|
-
-P, --project <name> Set default project name
|
|
242
|
-
`,
|
|
243
|
-
add: `tk add - Create a new task
|
|
244
|
-
|
|
245
|
-
USAGE:
|
|
246
|
-
tk add <title> [options]
|
|
247
|
-
|
|
248
|
-
OPTIONS:
|
|
249
|
-
-p, --priority <0-4> Priority (0=none, 1=urgent, 2=high, 3=medium, 4=low)
|
|
250
|
-
-P, --project <name> Project prefix for ID
|
|
251
|
-
-d, --description <text> Description
|
|
252
|
-
-l, --labels <csv> Labels (comma-separated)
|
|
253
|
-
-A, --assignees <csv> Assignees (comma-separated, @me for git user)
|
|
254
|
-
--parent <id> Parent task ID
|
|
255
|
-
--estimate <n> Estimate (user-defined units)
|
|
256
|
-
--due <date> Due date (YYYY-MM-DD or +Nh/+Nd/+Nw/+Nm)
|
|
257
|
-
|
|
258
|
-
EXAMPLES:
|
|
259
|
-
tk add "Fix login bug" -p 1
|
|
260
|
-
tk add "New feature" -P api -l bug,urgent
|
|
261
|
-
tk add "Sprint task" --due +7d
|
|
262
|
-
`,
|
|
263
|
-
ls: `tk ls - List tasks
|
|
264
|
-
|
|
265
|
-
USAGE:
|
|
266
|
-
tk ls [options]
|
|
267
|
-
|
|
268
|
-
OPTIONS:
|
|
269
|
-
-s, --status <status> Filter by status (open, active, done)
|
|
270
|
-
-p, --priority <0-4> Filter by priority
|
|
271
|
-
-P, --project <name> Filter by project
|
|
272
|
-
-l, --label <label> Filter by label
|
|
273
|
-
--assignee <name> Filter by assignee
|
|
274
|
-
--parent <id> Filter by parent
|
|
275
|
-
--roots Show only root tasks (no parent)
|
|
276
|
-
--overdue Show only overdue tasks
|
|
277
|
-
-n, --limit <n> Limit results (default: 20)
|
|
278
|
-
-a, --all Show all (no limit)
|
|
279
|
-
|
|
280
|
-
EXAMPLES:
|
|
281
|
-
tk ls -s open -p 1 # Urgent open tasks
|
|
282
|
-
tk ls --overdue # Overdue tasks
|
|
283
|
-
tk ls -P api --roots # Root tasks in api project
|
|
284
|
-
`,
|
|
285
|
-
list: `tk list - List tasks (alias for 'ls')
|
|
286
|
-
|
|
287
|
-
Run 'tk ls --help' for options.
|
|
288
|
-
`,
|
|
289
|
-
ready: `tk ready - List ready tasks (active/open + unblocked)
|
|
290
|
-
|
|
291
|
-
USAGE:
|
|
292
|
-
tk ready
|
|
293
|
-
|
|
294
|
-
Shows active or open tasks that are not blocked by any incomplete task.
|
|
295
|
-
`,
|
|
296
|
-
show: `tk show - Show task details
|
|
297
|
-
|
|
298
|
-
USAGE:
|
|
299
|
-
tk show <id>
|
|
300
|
-
|
|
301
|
-
EXAMPLES:
|
|
302
|
-
tk show tk-1
|
|
303
|
-
tk show 1 # If unambiguous
|
|
304
|
-
`,
|
|
305
|
-
start: `tk start - Start working on a task
|
|
306
|
-
|
|
307
|
-
USAGE:
|
|
308
|
-
tk start <id>
|
|
309
|
-
|
|
310
|
-
Changes status from open to active.
|
|
311
|
-
`,
|
|
312
|
-
done: `tk done - Complete a task
|
|
313
|
-
|
|
314
|
-
USAGE:
|
|
315
|
-
tk done <id>
|
|
316
|
-
|
|
317
|
-
Changes status to done.
|
|
318
|
-
`,
|
|
319
|
-
reopen: `tk reopen - Reopen a task
|
|
320
|
-
|
|
321
|
-
USAGE:
|
|
322
|
-
tk reopen <id>
|
|
323
|
-
|
|
324
|
-
Changes status back to open.
|
|
325
|
-
`,
|
|
326
|
-
edit: `tk edit - Edit a task
|
|
327
|
-
|
|
328
|
-
USAGE:
|
|
329
|
-
tk edit <id> [options]
|
|
330
|
-
|
|
331
|
-
OPTIONS:
|
|
332
|
-
-t, --title <text> New title
|
|
333
|
-
-d, --description <text> New description
|
|
334
|
-
-p, --priority <0-4> New priority
|
|
335
|
-
-l, --labels <csv> Replace labels (use +tag/-tag to add/remove)
|
|
336
|
-
-A, --assignees <csv> Replace assignees
|
|
337
|
-
--parent <id> Set parent (use - to clear)
|
|
338
|
-
--estimate <n> Set estimate (use - to clear)
|
|
339
|
-
--due <date> Set due date (use - to clear)
|
|
340
|
-
|
|
341
|
-
EXAMPLES:
|
|
342
|
-
tk edit tk-1 -t "New title"
|
|
343
|
-
tk edit tk-1 -l +urgent # Add label
|
|
344
|
-
tk edit tk-1 --due - # Clear due date
|
|
345
|
-
`,
|
|
346
|
-
log: `tk log - Add a log entry to a task
|
|
347
|
-
|
|
348
|
-
USAGE:
|
|
349
|
-
tk log <id> "<message>"
|
|
350
|
-
|
|
351
|
-
Message must be quoted.
|
|
352
|
-
|
|
353
|
-
EXAMPLES:
|
|
354
|
-
tk log tk-1 "Started implementation"
|
|
355
|
-
tk log tk-1 "Blocked on API changes"
|
|
356
|
-
`,
|
|
357
|
-
block: `tk block - Add a blocker dependency
|
|
358
|
-
|
|
359
|
-
USAGE:
|
|
360
|
-
tk block <task> <blocker>
|
|
361
|
-
|
|
362
|
-
The first task becomes blocked by the second.
|
|
363
|
-
|
|
364
|
-
EXAMPLES:
|
|
365
|
-
tk block tk-2 tk-1 # tk-2 is blocked by tk-1
|
|
366
|
-
`,
|
|
367
|
-
unblock: `tk unblock - Remove a blocker dependency
|
|
368
|
-
|
|
369
|
-
USAGE:
|
|
370
|
-
tk unblock <task> <blocker>
|
|
371
|
-
|
|
372
|
-
EXAMPLES:
|
|
373
|
-
tk unblock tk-2 tk-1
|
|
374
|
-
`,
|
|
375
|
-
rm: `tk rm - Delete a task
|
|
376
|
-
|
|
377
|
-
USAGE:
|
|
378
|
-
tk rm <id>
|
|
379
|
-
|
|
380
|
-
EXAMPLES:
|
|
381
|
-
tk rm tk-1
|
|
382
|
-
`,
|
|
383
|
-
remove: `tk remove - Delete a task (alias for 'rm')
|
|
384
|
-
|
|
385
|
-
USAGE:
|
|
386
|
-
tk remove <id>
|
|
387
|
-
`,
|
|
388
|
-
clean: `tk clean - Remove old completed tasks
|
|
389
|
-
|
|
390
|
-
USAGE:
|
|
391
|
-
tk clean [options]
|
|
392
|
-
|
|
393
|
-
OPTIONS:
|
|
394
|
-
--older-than <days> Age threshold in days (default: from config, 14)
|
|
395
|
-
-f, --force Remove all done tasks (ignores age and disabled state)
|
|
396
|
-
|
|
397
|
-
EXAMPLES:
|
|
398
|
-
tk clean # Remove done tasks older than config.clean_after days
|
|
399
|
-
tk clean --older-than 30 # Remove done tasks older than 30 days
|
|
400
|
-
tk clean --force # Remove all done tasks regardless of age
|
|
401
|
-
`,
|
|
402
|
-
check: `tk check - Check for data issues
|
|
403
|
-
|
|
404
|
-
USAGE:
|
|
405
|
-
tk check
|
|
406
|
-
|
|
407
|
-
Scans all tasks for issues. Auto-fixable issues (orphaned references, ID
|
|
408
|
-
mismatches) are fixed automatically. Unfixable issues (corrupted JSON) are
|
|
409
|
-
reported for manual intervention.
|
|
410
|
-
|
|
411
|
-
Note: Auto-fixing also happens during normal task operations (show, done,
|
|
412
|
-
edit, etc.) - this command is for bulk cleanup or diagnostics.
|
|
413
|
-
|
|
414
|
-
EXAMPLES:
|
|
415
|
-
tk check # Scan and fix all tasks
|
|
416
|
-
`,
|
|
417
|
-
config: `tk config - Show or set configuration
|
|
418
|
-
|
|
419
|
-
USAGE:
|
|
420
|
-
tk config Show all config
|
|
421
|
-
tk config project Show default project
|
|
422
|
-
tk config project <name> Set default project
|
|
423
|
-
tk config project <new> --rename <old> Rename project (old-* → new-*)
|
|
424
|
-
tk config alias List aliases
|
|
425
|
-
tk config alias <name> <path> Add alias
|
|
426
|
-
tk config alias --rm <name> Remove alias
|
|
427
|
-
|
|
428
|
-
EXAMPLES:
|
|
429
|
-
tk config project api
|
|
430
|
-
tk config project lsmvec --rename cloudlsmvec
|
|
431
|
-
tk config alias web src/web
|
|
432
|
-
`,
|
|
433
|
-
completions: `tk completions - Output shell completions
|
|
434
|
-
|
|
435
|
-
USAGE:
|
|
436
|
-
tk completions <shell>
|
|
437
|
-
|
|
438
|
-
SHELLS:
|
|
439
|
-
bash Bash completion script
|
|
440
|
-
zsh Zsh completion script
|
|
441
|
-
fish Fish completion script
|
|
442
|
-
|
|
443
|
-
EXAMPLES:
|
|
444
|
-
eval "$(tk completions bash)" # Add to ~/.bashrc
|
|
445
|
-
eval "$(tk completions zsh)" # Add to ~/.zshrc
|
|
446
|
-
`,
|
|
447
|
-
};
|
|
448
|
-
|
|
449
|
-
const help = helps[cmd];
|
|
204
|
+
function showCommandHelp(cmd: string): void {
|
|
205
|
+
const help = COMMAND_HELP[cmd];
|
|
450
206
|
if (help) {
|
|
451
207
|
console.log(help);
|
|
452
208
|
} else {
|
|
@@ -498,7 +254,7 @@ function main() {
|
|
|
498
254
|
if (info.exists) {
|
|
499
255
|
output(
|
|
500
256
|
{ path: info.tasksDir, created: false },
|
|
501
|
-
|
|
257
|
+
dim(`Already initialized: ${info.tasksDir}`),
|
|
502
258
|
);
|
|
503
259
|
} else {
|
|
504
260
|
const path = storage.initTasks(values.project);
|
|
@@ -525,7 +281,8 @@ function main() {
|
|
|
525
281
|
let parentId: string | undefined;
|
|
526
282
|
if (values.parent) {
|
|
527
283
|
const resolved = storage.resolveId(values.parent);
|
|
528
|
-
if (!resolved)
|
|
284
|
+
if (!resolved)
|
|
285
|
+
error(`Parent task not found: ${values.parent}. Run 'tk ls' to see available tasks.`);
|
|
529
286
|
parentId = resolved;
|
|
530
287
|
const parentResult = storage.validateParent(parentId);
|
|
531
288
|
if (!parentResult.ok) error(parentResult.error!);
|
|
@@ -551,8 +308,9 @@ function main() {
|
|
|
551
308
|
const { values } = parseArgs({
|
|
552
309
|
args,
|
|
553
310
|
options: {
|
|
554
|
-
|
|
555
|
-
|
|
311
|
+
project: { type: "string", short: "P" },
|
|
312
|
+
priority: { type: "string", short: "p" },
|
|
313
|
+
label: { type: "string", short: "l" },
|
|
556
314
|
status: { type: "string", short: "s" },
|
|
557
315
|
assignee: { type: "string" },
|
|
558
316
|
parent: { type: "string" },
|
|
@@ -571,7 +329,8 @@ function main() {
|
|
|
571
329
|
let parentFilter: string | undefined;
|
|
572
330
|
if (values.parent) {
|
|
573
331
|
const resolved = storage.resolveId(values.parent);
|
|
574
|
-
if (!resolved)
|
|
332
|
+
if (!resolved)
|
|
333
|
+
error(`Parent task not found: ${values.parent}. Run 'tk ls' to see available tasks.`);
|
|
575
334
|
parentFilter = resolved;
|
|
576
335
|
}
|
|
577
336
|
|
|
@@ -579,7 +338,7 @@ function main() {
|
|
|
579
338
|
status,
|
|
580
339
|
priority,
|
|
581
340
|
project: values.project,
|
|
582
|
-
label: values.label
|
|
341
|
+
label: values.label,
|
|
583
342
|
assignee: values.assignee,
|
|
584
343
|
parent: parentFilter,
|
|
585
344
|
roots: values.roots,
|
|
@@ -592,7 +351,10 @@ function main() {
|
|
|
592
351
|
|
|
593
352
|
case "ready": {
|
|
594
353
|
const list = storage.listReadyTasks();
|
|
595
|
-
output(
|
|
354
|
+
output(
|
|
355
|
+
list,
|
|
356
|
+
formatTaskList(list, undefined, "No ready tasks. All tasks are either done or blocked."),
|
|
357
|
+
);
|
|
596
358
|
break;
|
|
597
359
|
}
|
|
598
360
|
|
|
@@ -641,12 +403,12 @@ function main() {
|
|
|
641
403
|
let labels: string[] | undefined;
|
|
642
404
|
if (values.labels) {
|
|
643
405
|
if (values.labels.startsWith("+")) {
|
|
644
|
-
|
|
645
|
-
|
|
406
|
+
const newLabel = values.labels.slice(1).trim();
|
|
407
|
+
if (!newLabel) throw new Error("Label name required after '+'");
|
|
646
408
|
labels = task.labels.includes(newLabel) ? task.labels : [...task.labels, newLabel];
|
|
647
409
|
} else if (values.labels.startsWith("-")) {
|
|
648
|
-
|
|
649
|
-
|
|
410
|
+
const removeLabel = values.labels.slice(1).trim();
|
|
411
|
+
if (!removeLabel) throw new Error("Label name required after '-'");
|
|
650
412
|
labels = task.labels.filter((l: string) => l !== removeLabel);
|
|
651
413
|
} else {
|
|
652
414
|
// Replace labels
|
|
@@ -660,7 +422,8 @@ function main() {
|
|
|
660
422
|
resolvedParent = null;
|
|
661
423
|
} else if (values.parent) {
|
|
662
424
|
const resolved = storage.resolveId(values.parent);
|
|
663
|
-
if (!resolved)
|
|
425
|
+
if (!resolved)
|
|
426
|
+
error(`Parent task not found: ${values.parent}. Run 'tk ls' to see available tasks.`);
|
|
664
427
|
resolvedParent = resolved;
|
|
665
428
|
const parentResult = storage.validateParent(resolvedParent, task.id);
|
|
666
429
|
if (!parentResult.ok) error(parentResult.error!);
|
|
@@ -668,7 +431,7 @@ function main() {
|
|
|
668
431
|
|
|
669
432
|
const updated = storage.updateTask(task.id, {
|
|
670
433
|
title: values.title?.trim() || undefined,
|
|
671
|
-
description: values.description,
|
|
434
|
+
description: values.description === "-" ? null : values.description,
|
|
672
435
|
priority: values.priority ? parsePriority(values.priority) : undefined,
|
|
673
436
|
labels,
|
|
674
437
|
assignees: parseAssignees(values.assignees),
|
|
@@ -696,10 +459,13 @@ function main() {
|
|
|
696
459
|
}
|
|
697
460
|
|
|
698
461
|
case "block": {
|
|
699
|
-
if (!args[0] || !args[1])
|
|
462
|
+
if (!args[0] || !args[1])
|
|
463
|
+
error(
|
|
464
|
+
"Two IDs required: tk block <task> <blocker>. The first task becomes blocked by the second.",
|
|
465
|
+
);
|
|
700
466
|
const taskId = resolveId(args[0], "block");
|
|
701
467
|
const blockerId = resolveId(args[1], "block");
|
|
702
|
-
if (taskId === blockerId) error("Task cannot block itself");
|
|
468
|
+
if (taskId === blockerId) error("Task cannot block itself.");
|
|
703
469
|
const result = storage.addBlock(taskId, blockerId);
|
|
704
470
|
if (!result.ok) error(result.error!);
|
|
705
471
|
output(
|
|
@@ -710,7 +476,7 @@ function main() {
|
|
|
710
476
|
}
|
|
711
477
|
|
|
712
478
|
case "unblock": {
|
|
713
|
-
if (!args[0] || !args[1]) error("
|
|
479
|
+
if (!args[0] || !args[1]) error("Two IDs required: tk unblock <task> <blocker>.");
|
|
714
480
|
const taskId = resolveId(args[0], "unblock");
|
|
715
481
|
const blockerId = resolveId(args[1], "unblock");
|
|
716
482
|
const removed = storage.removeBlock(taskId, blockerId);
|
|
@@ -726,11 +492,24 @@ function main() {
|
|
|
726
492
|
case "remove": {
|
|
727
493
|
const id = resolveId(args[0], "rm");
|
|
728
494
|
const deleted = storage.deleteTask(id);
|
|
729
|
-
if (!deleted) error(`Task not found: ${id}
|
|
495
|
+
if (!deleted) error(`Task not found: ${id}. Run 'tk ls' to see available tasks.`);
|
|
730
496
|
output({ id, deleted: true }, green(`Deleted: ${id}`));
|
|
731
497
|
break;
|
|
732
498
|
}
|
|
733
499
|
|
|
500
|
+
case "mv":
|
|
501
|
+
case "move": {
|
|
502
|
+
const id = resolveId(args[0], "mv");
|
|
503
|
+
const newProject = args[1];
|
|
504
|
+
if (!newProject) error("Project required: tk mv <id> <project>");
|
|
505
|
+
validateProject(newProject);
|
|
506
|
+
const result = storage.moveTask(id, newProject);
|
|
507
|
+
const refMsg =
|
|
508
|
+
result.referencesUpdated > 0 ? `\nUpdated ${result.referencesUpdated} references` : "";
|
|
509
|
+
output(result, green(`Moved: ${result.old_id} → ${result.new_id}${refMsg}`));
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
|
|
734
513
|
case "clean": {
|
|
735
514
|
const config = storage.getConfig();
|
|
736
515
|
const { values } = parseArgs({
|
|
@@ -851,43 +630,8 @@ function main() {
|
|
|
851
630
|
}
|
|
852
631
|
break;
|
|
853
632
|
}
|
|
854
|
-
case "alias": {
|
|
855
|
-
const { values, positionals } = parseArgs({
|
|
856
|
-
args: args.slice(1),
|
|
857
|
-
options: {
|
|
858
|
-
rm: { type: "string" },
|
|
859
|
-
list: { type: "boolean" },
|
|
860
|
-
},
|
|
861
|
-
allowPositionals: true,
|
|
862
|
-
});
|
|
863
|
-
|
|
864
|
-
if (values.rm) {
|
|
865
|
-
const updated = storage.removeAlias(values.rm);
|
|
866
|
-
output(updated, green(`Removed alias: ${values.rm}`));
|
|
867
|
-
} else if (positionals.length >= 2) {
|
|
868
|
-
const alias = positionals[0];
|
|
869
|
-
const path = positionals[1];
|
|
870
|
-
if (!alias || !path || !alias.trim()) {
|
|
871
|
-
error("Alias name and path are required");
|
|
872
|
-
}
|
|
873
|
-
const updated = storage.setAlias(alias, path);
|
|
874
|
-
output(updated, green(`Added alias: ${alias} → ${path}`));
|
|
875
|
-
} else {
|
|
876
|
-
// List aliases
|
|
877
|
-
const aliases = config.aliases;
|
|
878
|
-
if (Object.keys(aliases).length === 0) {
|
|
879
|
-
output({ aliases: {} }, "No aliases defined.");
|
|
880
|
-
} else {
|
|
881
|
-
const lines = Object.entries(aliases)
|
|
882
|
-
.map(([a, p]) => `${a} → ${p}`)
|
|
883
|
-
.join("\n");
|
|
884
|
-
output({ aliases }, lines);
|
|
885
|
-
}
|
|
886
|
-
}
|
|
887
|
-
break;
|
|
888
|
-
}
|
|
889
633
|
default:
|
|
890
|
-
error(`Unknown config command: ${subcommand}
|
|
634
|
+
error(`Unknown config command: ${subcommand}. Valid: project.`);
|
|
891
635
|
}
|
|
892
636
|
break;
|
|
893
637
|
}
|
|
@@ -905,7 +649,7 @@ function main() {
|
|
|
905
649
|
console.log(FISH_COMPLETION);
|
|
906
650
|
break;
|
|
907
651
|
default:
|
|
908
|
-
error("Shell required: tk completions <bash|zsh|fish
|
|
652
|
+
error("Shell required: tk completions <bash|zsh|fish>. Add to your shell's rc file.");
|
|
909
653
|
}
|
|
910
654
|
break;
|
|
911
655
|
}
|