noz-cli/NozCli/Repl/ReplContext.cs
2026-05-16 19:25:39 +02:00

54 lines
2 KiB
C#

using NozCli.Core.Client;
using NozCli.Core.Models;
namespace NozCli.Repl;
/// Shared mutable state across the REPL session.
public class ReplContext
{
public NozApiClient Api { get; }
public string CurrentPath { get; set; } = "~";
public List<NoteInfo> NoteCache { get; set; } = [];
public bool Running { get; set; } = true;
public ReplContext(NozApiClient api) => Api = api;
/// Returns the topic/folder prefix implied by CurrentPath, or null if at root.
public string? PathPrefix()
{
if (CurrentPath is "~" or "~/noosphere") return null;
var stripped = CurrentPath.Replace("~/noosphere/", "").Replace("~/noosphere", "");
return string.IsNullOrEmpty(stripped) ? null : stripped;
}
/// Notes visible at the current path level.
public IEnumerable<NoteInfo> NotesInView()
{
var prefix = PathPrefix();
return prefix is null
? NoteCache
: NoteCache.Where(n => n.Slug.StartsWith(prefix + "/"));
}
/// Resolves a short name (e.g. "hydroponik") to a full slug using the current path as prefix.
public string ResolveSlug(string nameOrSlug)
{
// Already a full slug
if (NoteCache.Any(n => n.Slug == nameOrSlug)) return nameOrSlug;
var prefix = PathPrefix();
var candidate = prefix is null ? nameOrSlug : $"{prefix}/{nameOrSlug}";
return NoteCache.Any(n => n.Slug == candidate) ? candidate : nameOrSlug;
}
/// Immediate sub-segments (topics or subfolders) at current path.
public IEnumerable<string> FoldersInView()
{
var prefix = PathPrefix();
var depth = prefix is null ? 0 : prefix.Split('/').Length;
return NoteCache
.Where(n => prefix is null || n.Slug.StartsWith(prefix + "/"))
.Select(n => n.Slug.Split('/').ElementAtOrDefault(depth))
.Where(s => s is not null)
.Distinct(StringComparer.OrdinalIgnoreCase)!;
}
}