Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement fixed-size log-text area for ProgressTask #1520

Closed
flobernd opened this issue Apr 18, 2024 · 5 comments
Closed

Implement fixed-size log-text area for ProgressTask #1520

flobernd opened this issue Apr 18, 2024 · 5 comments

Comments

@flobernd
Copy link

Is your feature request related to a problem? Please describe.

I would like to display live log output individually for each progress task - similar to what Docker does when building an image.

Describe the solution you'd like

ProgressTask should provide a WriteLine method that allows to output log strings to the console. These log strings should be displayed below the progress bar. The log area for each progress task should have a (configurable) fixed height of e.g. 10 lines. After exceeding the maximum, text should start to scroll out of the screen.

As an alternative, ProgressTask could contain a Rows component which would allow the user to dynamically add- or remove lines while the task is running.


Please upvote 👍 this issue if you are interested in it.

@patriksvensson
Copy link
Contributor

patriksvensson commented Apr 18, 2024

Everything written to the console using an IAnsiConsole will already automatically be put above the progress.

@flobernd
Copy link
Author

flobernd commented Apr 19, 2024

Hi @patriksvensson, thanks for the reply. That's not exactly what I'm trying to achieve 🙂 I need something like this:

|= Reticulating splines ----------------------------------------  63% 00:06:181 -
52438428
1870133191
1511040860
494825954
1900287500
1576363183
934959048
1910108725
1465638547
1366240317

|=        Folding space ----------------------------------------  21% 00:06:179 -
52438428
1870133191
1511040860
494825954
1900287500
1576363183
934959048
1910108725
1465638547
1366240317

This is useful to have output of a task near (in this case below) the corresponding progress bar to allow the user to quickly determine which output belongs to which concurrently running task.

Utilizing the new RenderHook property, I managed to create a sample application that demonstrates the desired behavior. It's just hacked together, so please don't take too close of a look at the code style. The rows output is shared for both tasks in this example which of course should not be the case in production.

internal static class Program
{
    private static async Task Main()
    {
        var ri = 0;
        var rows = Enumerable.Repeat<IRenderable>(new Text(""), 11).ToArray();

        var progress = AnsiConsole.Progress()
            .AutoRefresh(true)
            .AutoClear(false)
            .HideCompleted(false)
            .Columns(
                new TaskDescriptionColumn(),
                new ProgressBarColumn(),
                new PercentageColumn(),
                new ElapsedTimeMilliColumn(),
                new SpinnerColumn()
            );
        progress.RefreshRate = TimeSpan.FromMilliseconds(50);
        progress.RenderHook = RenderHook;

        IRenderable RenderHook(IRenderable renderable, IReadOnlyList<ProgressTask> tasks)
        {
            if (renderable is not Grid layout)
            {
                return renderable;
            }

            if (layout.Rows[0][0] is not Grid grid)
            {
                return renderable;
            }

            var result = new List<IRenderable>();

            var i = 0;
            foreach (var row in grid.Rows)
            {
                var g = new Grid();
                foreach (var column in grid.Columns)
                {
                    g.AddColumn(column);
                }

                g.AddRow([.. row]);

                result.Add(g);

                if (ri != 0 && !tasks[i].IsFinished)
                {
                    result.Add(new Rows(rows[..(ri + 1)]));
                }

                ++i;
            }

            var l = new Grid { Expand = true };
            l.AddColumn();
            l.AddRow(new Rows(result));

            return l;
        }

        AnsiConsole.Clear();
        AnsiConsole.MarkupLine("[blue]Elasticsearch.NET[/] Client Generator");
        AnsiConsole.WriteLine();

        progress
            .Start(ctx =>
            {
                // Define tasks
                var task1 = ctx.AddTask("[green]|= Reticulating splines[/]");
                var task2 = ctx.AddTask("[green]|=        Folding space[/]");

                while (!ctx.IsFinished)
                {
                    // Simulate some work
                    Task.Delay(50).Wait();

                    // Increment
                    task1.Increment(1.5);
                    task2.Increment(0.5);

                    if (ri == 10)
                    {
                        for (var i = 1; i < 10; ++i)
                        {
                            rows[i - 1] = rows[i];
                        }

                        ri = 9;
                    }

                    rows[ri++] = new Text($"{new Random((int)DateTime.Now.Ticks).Next()}");
                }

                ctx.Refresh();
            });

        // Fixme: Empty lines between the last progress bar and "test"
        AnsiConsole.WriteLine("test");
    }
}

@flobernd
Copy link
Author

I would as well offer to create a PR, if this functionality is something you would consider adding 🙂

@patriksvensson
Copy link
Contributor

Since this is a very niche thing, and nothing that we're really planning the progress bars to support, I think this would make an excellent addition as a external Spectre.Console extension.

@flobernd
Copy link
Author

Hi @patriksvensson, no problem. This will however result in a lot of duplicate code I'm afraid.

Closing this feature request as not planned.

@flobernd flobernd closed this as not planned Won't fix, can't repro, duplicate, stale Apr 22, 2024
@github-project-automation github-project-automation bot moved this from Todo 🕑 to Done 🚀 in Spectre Console Apr 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done 🚀
Development

No branches or pull requests

2 participants