NoteLinkHelper inserts wikilinks into an existing 'Siehe auch' section
or appends one. ApplyPlaceholders fills {{title}}/{{date}}/{{topic}} in
template bodies. new --template <name> fetches a server-side template
before opening the editor. SlugGuard moved to NozCli.Core in a previous
session — remove stale copy from NozCli.
67 lines
2.3 KiB
C#
67 lines
2.3 KiB
C#
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 <source> <target> [--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 <source> <target> [--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;
|
|
}
|
|
}
|