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 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 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 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)!; } }