diff --git a/src/Terminal.Gui.Cli/CliHost.cs b/src/Terminal.Gui.Cli/CliHost.cs index 2ed053d..4620145 100644 --- a/src/Terminal.Gui.Cli/CliHost.cs +++ b/src/Terminal.Gui.Cli/CliHost.cs @@ -1,5 +1,6 @@ using System.Reflection; using Terminal.Gui.App; +using Terminal.Gui.Drivers; namespace Terminal.Gui.Cli; @@ -181,6 +182,30 @@ private static CommandResult CreateCancelledResult () null); } + /// + /// Creates, initializes, and disposes a headless ANSI-driver Terminal.Gui application around + /// . Centralizes the Terminal.Gui lifecycle here (constitution C1) so + /// helpers such as never call lifecycle entrypoints directly. + /// + internal static void RunHeadlessRender (int width, int height, Action render) + { + var previousDriverIO = Environment.GetEnvironmentVariable ("DisableRealDriverIO"); + Environment.SetEnvironmentVariable ("DisableRealDriverIO", "1"); + IApplication app = Application.Create (); + + try + { + app.Init (DriverRegistry.Names.ANSI); + app.Driver?.SetScreenSize (width, height); + render (app); + } + finally + { + app.Dispose (); + Environment.SetEnvironmentVariable ("DisableRealDriverIO", previousDriverIO); + } + } + private async Task RunWithTerminalGuiAsync (ICliCommand command, CommandRunOptions runOptions, CancellationToken cancellationToken) { diff --git a/src/Terminal.Gui.Cli/MarkdownRenderer.cs b/src/Terminal.Gui.Cli/MarkdownRenderer.cs index a7e4ab3..1e0c5b5 100644 --- a/src/Terminal.Gui.Cli/MarkdownRenderer.cs +++ b/src/Terminal.Gui.Cli/MarkdownRenderer.cs @@ -1,6 +1,4 @@ using System.Text; -using Terminal.Gui.App; -using Terminal.Gui.Drivers; using Terminal.Gui.ViewBase; using Terminal.Gui.Views; @@ -62,46 +60,41 @@ public static void RenderToAnsi (string markdown, TextWriter output) height = 24; } - var previousDriverIO = Environment.GetEnvironmentVariable ("DisableRealDriverIO"); - Environment.SetEnvironmentVariable ("DisableRealDriverIO", "1"); - IApplication app = Application.Create (); - try { - app.Init (DriverRegistry.Names.ANSI); - app.Driver?.SetScreenSize (width, height); - - Markdown markdownView = new () + // CliHost owns the Terminal.Gui lifecycle (constitution C1); this helper only + // performs view layout and drawing inside the callback. + CliHost.RunHeadlessRender (width, height, app => { - App = app, - UseThemeBackground = false, - ShowCopyButtons = false, - Width = Dim.Fill (), - Height = Dim.Fill (), - Text = markdown - }; - - markdownView.SetRelativeLayout (app.Screen.Size); - markdownView.Layout (); - - var contentHeight = markdownView.GetContentHeight (); - app.Driver?.SetScreenSize (width, contentHeight); - markdownView.SetRelativeLayout (app.Screen.Size); - markdownView.Frame = app.Screen with { X = 0, Y = 0 }; - markdownView.Layout (); - - app.Driver?.ClearContents (); - markdownView.Draw (); - - var rendered = app.Driver?.ToAnsi () ?? string.Empty; - rendered = TerminalEscapeSanitizer.SanitizeRenderedOutput (rendered); - target.WriteLine (rendered); + Markdown markdownView = new () + { + App = app, + UseThemeBackground = false, + ShowCopyButtons = false, + Width = Dim.Fill (), + Height = Dim.Fill (), + Text = markdown + }; + + markdownView.SetRelativeLayout (app.Screen.Size); + markdownView.Layout (); + + var contentHeight = markdownView.GetContentHeight (); + app.Driver?.SetScreenSize (width, contentHeight); + markdownView.SetRelativeLayout (app.Screen.Size); + markdownView.Frame = app.Screen with { X = 0, Y = 0 }; + markdownView.Layout (); + + app.Driver?.ClearContents (); + markdownView.Draw (); + + var rendered = app.Driver?.ToAnsi () ?? string.Empty; + rendered = TerminalEscapeSanitizer.SanitizeRenderedOutput (rendered); + target.WriteLine (rendered); + }); } finally { - app.Dispose (); - Environment.SetEnvironmentVariable ("DisableRealDriverIO", previousDriverIO); - if (previousEncoding is not null) { Console.OutputEncoding = previousEncoding;