using NozCli.Core.Client; using NozCli.Repl; using Spectre.Console; namespace NozCli.Commands; public class LinkCommand : ICommand { public string Name => "link"; public string Description => "Add a wikilink from one note to another (builds the graph)"; public string Usage => "link [--both] [--section \"Siehe auch\"]"; public async Task ExecuteAsync(string[] args, ReplContext ctx, CancellationToken ct = default) { var both = args.Contains("--both"); var section = ParseFlag(args, "--section") ?? "Siehe auch"; var positional = args.Where(a => !a.StartsWith('-')).ToArray(); if (positional.Length < 2) { AnsiConsole.MarkupLine("[red]Usage:[/] link [--both] [--section \"Heading\"]"); return; } var source = ctx.ResolveSlug(positional[0]); var target = ctx.ResolveSlug(positional[1]); if (source == target) { AnsiConsole.MarkupLine("[yellow]Quelle und Ziel sind identisch.[/]"); return; } await LinkOneWay(ctx.Api, source, target, section, ct); if (both) await LinkOneWay(ctx.Api, target, source, section, ct); } private static async Task LinkOneWay( NozCli.Core.Client.NozApiClient api, string source, string target, string section, CancellationToken ct) { NozCli.Core.Models.NoteContent note = default!; await AnsiConsole.Status().StartAsync($"Lese {source}…", async _ => note = await api.GetNoteAsync(source, ct)); var updated = NoteLinkHelper.AddLink(note.Markdown, target, section); if (updated == note.Markdown) { AnsiConsole.MarkupLine($"[dim]{source}[/] → [dim]{target}[/] [yellow]bereits verlinkt[/]"); return; } await AnsiConsole.Status().StartAsync($"Aktualisiere {source}…", async _ => await api.PutNoteAsync(source, updated, ct)); AnsiConsole.MarkupLine($"[green]✓[/] [cyan]{source}[/] → [cyan]{target}[/] verlinkt"); } private static string? ParseFlag(string[] args, string flag) { var idx = Array.IndexOf(args, flag); return idx >= 0 && idx + 1 < args.Length ? args[idx + 1] : null; } }