spectreconsole / spectre.console Goto Github PK
View Code? Open in Web Editor NEWA .NET library that makes it easier to create beautiful console applications.
Home Page: https://spectreconsole.net
License: MIT License
A .NET library that makes it easier to create beautiful console applications.
Home Page: https://spectreconsole.net
License: MIT License
There should be an option to specify overflow strategies for tables when one or more columns can't be displayed.
requested max-width <= 0
), show an ellipsis.Do nothing to prevent bad rendering.
Do nothing to prevent bad rendering.
Do not truncate the table or show ellipsis.
Start dropping columns until content fit.
Display columns that won't fit with an ellipsis.
Split columns in half until all columns fit.
Split rows so all columns are grouped together even if not all fit.
Please upvote ๐ this issue if you are interested in it.
Support rendering arbitrary data into columns.
An Exception gets thrown when running the Grids or Table example on a very small console window:
Grid:
System.InvalidOperationException: Text folding failed since 'take' was zero.
Table:
System.ArgumentOutOfRangeException: Length cannot be less than zero. (Parameter 'length')
I don't expect pretty output but at least the program shouldn't crash.
Just as we do when we parse markup, it would be convenient if we could construct a style from a string.
var style = Style.Parse("bold magenta on green");
Perhaps we should add support for implicit conversion from String
to Style
as well?
Sometimes consecutive segments use the same style which causes the same ANSI escape codes to be repeated. Consecutive segments with the same style should be merged before rendering.
We know whether or not we're running in a legacy console (cmd.exe) which doesn't support true type fonts. If we are, we should automatically downgrade borders that use true type fonts to something that can be properly rendered.
var isLegacyConsole = console.Capabilities.LegacyConsole;
If not table column widths can be calculated, the measurement algorithm sometimes goes into an endless loop, which is not very good. This should be fixed.
If this happen, we could probably return a length of 1 for the column and not write anything at all into the cell.
Update:
This seem to have something to do with Segment.SplitLines
if it gets a max width of 0
The Panel
class should support using different borders just like Table
does.
Figlet fonts allow folks to more easily design outputs in specialized ascii patterns.
Font: alligator
::: ::: :::::::: ::::::::
:+:+: :+:+: :+: :+::+: :+:
+:+ +:+:+ +:++:+ +:++:+ +:+
+#+ +:+ +#++#+ +:++#+ +:+
+#+ +#++#+ +#++#+ +#+
#+# #+##+# #+##+# #+#
### ### ######## ########
Trying to do this markup fails because it thinks it might be an emoji - Hello [link=http://example.com]http://example.com[/]
Failing test - phil-scott-78@1f5e00e
Exception
System.Collections.Generic.KeyNotFoundException
The given key '//example.com]http' was not present in the dictionary.
at System.Collections.Generic.Dictionary`2.get_Item(TKey key)
at Spectre.Console.Emoji.<Replace>g__ReplaceEmoji|1_0(Match match) in R:\Projects\spectre.console\src\Spectre.Console\Emoji.cs:line 19
at System.Text.RegularExpressions.Regex.Replace(MatchEvaluator evaluator, Regex regex, String input, Int32 count, Int32 startat)
at System.Text.RegularExpressions.Regex.Replace(String input, MatchEvaluator evaluator)
at Spectre.Console.Emoji.Replace(String value) in R:\Projects\spectre.console\src\Spectre.Console\Emoji.cs:line 20
at Spectre.Console.Internal.MarkupParser.Parse(String text, Style style) in R:\Projects\spectre.console\src\Spectre.Console\Internal\Text\Markup\MarkupParser.cs:line 16
at Spectre.Console.Markup..ctor(String text, Style style) in R:\Projects\spectre.console\src\Spectre.Console\Widgets\Markup.cs:line 35
at Spectre.Console.Tests.Unit.MarkupTests.Should_render_links_as_expected(String input, String output) in R:\Projects\spectre.console\src\Spectre.Console.Tests\Unit\MarkupTests.cs:line 33
Would be nice to use markdown borders for tables.
Right now we can escape [
characters with [[
but @agc93 suggested that it might be a good idea to support \[
since this probably is the first thing a user tries when trying to escape something.
If the user provides a command to a leaf command and strict parsing is turned off, the trailing command should be treated as an extra remaining argument instead of showing an error.
Support rendering arbitrary data into rows.
Only examples specified on the root should show at the root. If examples are specified for commands it should not show up at the root since this is a bit confusing.
If text overflows, we should support different ways of mitigating this
โฆ
Right now we calculate the widths of all the columns and rows in the table in one pass. This means that unless columns take up their maximum width, not all the available width is used.
Would be nice to specify a default column overflow for tables and grids.
"Bounjour" should be replaced by "Bonjour"
It would be handy if there were support in spectre.console to output ANSI hyperlinks (clickable links) in the terminals that support this feature.
While there are currently only a handful of terminals that currently support this.
Current state of support (per 2020-05-31) can be seen here: https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda
From my own testing, I have found that GNOME Terminal supports these links, and partially Windows Terminal (mainly only that it won't choke when ANSI hyperlinks are used).
I am using Emojis for a project and everything worked perfectly fine on my machine.
After distributing the self executable to the customer he reported me that the emojis didn't get printed out and instead two question marks (??) are displayed.
This was quite surprising because in the documentation there exists no section of when emojis get printed and when not.
So this is an effort of collecting solutions on how to get emojis to work on Windows.
Set the OutputEncoding manually:
This is an easy fix to do, just add System.Console.OutputEncoding = System.Text.Encoding.UTF8
as the first line of the main function.
Altough this is a quick fix I don't think it is the best solution because basically you override the Encoding settings of the parent console.
Set the Encoding of the PowerShell (Core) console on a per session basis:
You can set the input and output encoding of the console by executing the following line
[console]::InputEncoding = [console]::OutputEncoding = [System.Text.Encoding]::UTF8
This commaand can be put in the profile file so the command gets executed automatically.
There exists also an issue to set UTF-8 as the default encoding on PowerShell Core: PowerShell/PowerShell#7233
Set the UTF-8 worldwide language support:
In fact this was the setting I had set on my development machine which caused to render the emojis correctly.
I hope this helps troubleshooting the issues I had with the output encoding (and emojis) and maybe some explanation could be added to the documentation.
The sample should show the features of the library in a way that's simple and easy to understand.
It should be no problem to render other stuff in tables since all columns and rows are of the type IRenderable
, but at some point, when the API is "done", we should add explicit support for adding arbitrary renderable objects to a table.
[underline]Foo[/]
== [u]Foo[/]
[bold]Foo[/]
== [b]Foo[/]
[italic]Foo[/]
== [i]Foo[/]
Right now, text rendered via the Text
class does not take word boundaries into account. We should support proper word wrapping.
Hello, first of all, thanks for this amazing project. It enable us to build cool dotnet tools :)
I'm trying to render a table that contains emojis, and depending on the emoji (I suppose because of their length), the table renders ok with some emojis and it has an extra spacing with others.
Here is some sample code:
var hcTable = new Table().SetBorder(Border.Rounded);
hcTable.AddColumn(new TableColumn("Name ") { Padding = new Padding(10, 10), Alignment = Justify.Center });
hcTable.AddColumn(new TableColumn(new Markup($"Status โ๏ธ")) { Padding = new Padding(10, 10), Alignment = Justify.Center });
hcTable.AddColumn(new TableColumn("Description โน") { Padding = new Padding(10, 10), Alignment = Justify.Center });
hcTable.AddColumn(new TableColumn("Duration ๐ ") { Padding = new Padding(10, 10), Alignment = Justify.Center });
hcTable.AddRow(new Text("name"), new Markup($"๐ some text"), new Text("some text"), new Text("Some text"));
hcTable.AddRow(new Text("name"), new Markup($"โ some text"), new Text("some text"), new Text("Some text"));
hcTable.AddRow(new Text("name"), new Markup($"๐ some text"), new Text("some text"), new Text("Some text"));
AnsiConsole.Render(hcTable);
As you can see it does not happen with the ๐ but happens with the โ and also in table headers. They report lengths of 2 and 1 (4 and 3 bytes).
I see you are considering this extra spacing in the unit tests, but is there any chance to correctly calculate cell length and width when having emojis?
Thanks
Especially for Unix/Linux platforms, the convention is usually to provide options before arguments:
Usage: grep [OPTION]... PATTERN [FILE]...
Usage: tar [OPTION...] [FILE]...
systemctl [OPTIONS...] {COMMAND} ...
Using boolean options before arguments currently gets incorrectly interpreted as assigning a value to the option flag. Would be good to support this ordering (preferably alongside existing behaviour).
Would be nice to use RGN colors in markup.
AnsiConsole.Markup("[bold rgb(92,92,92) on rgb(255,0,0)]Hello World[/]");
๐
When the background (also assuming the foreground, but can't be verified) gets changed multiple times (by setting AnsiConsole.Background
), then after the text has been printed, the previous background color is being used for the rest of the line.
Examples from different shells:
I tried to look into why this happens, but I was unable to find the reason.
Would be nice to use hex colors in markup.
AnsiConsole.Markup("[bold #121212 on #FF0000]Hello World[/]");
It would be a nice to have feature if it would be possible to either remap or add additional emojis to the already supported emoji list supported by Spectre.Console.
For instance, in my use case, I would like to have the ability to map the GitHub emoji icon names to something that would be equivalent to the ones already in the Spectre.Console emoji list.
ie:
Remapping :smile
(:smile:) to :grinning_face_with_smiling_eyes:
and so on.
I do not think it would worthwhile in the long run for Spectre.Console to know about them (mostly due to the number of icons), so having the option of adding/remapping them ourself would be great.
Here is an initial draft of the API. Feedback and thoughts are welcome.
new BarGraph<FruitCount>(title: "Favorite Fruit")
// Y-axis should be numeric
.Data(new[]
{
new FruitCount { Fruit = "Apple", NumberOfPeople = 35 },
new FruitCount { Fruit = "Orange", NumberOfPeople = 30 },
new FruitCount { Fruit = "Banana", NumberOfPeople = 10 }
})
.X(x => x.Fruit)
.Y(y => y.NumberOfPeople, "# of People");
// Other formatting extensions
In some cases, it would be useful to have the ability to have a single header or row span multiple columns in a table.
For instance, if the header of the table is used as a title instead of the value name of each column, or if a row has the same value for multiple columns next to each other or even if the row is more used as a separator.
Please upvote ๐ this issue if you are interested in it.
Allow folks to take a markdown file and render it to the console.
Support the ability to print out pretty looking calendar months, with the ability to highlight dates.
var calendar = new Calendar(
currentMonth: 1,
2020,
CultureInfo.InvariantCulture,
new List<CalendarEvent> {
new CalendarEvent("New Years Day", new DateTime(2020, 1, 1))
});
AnsiConsole.Render(calendar);
With a resulting output of the following:
Sun Mon Tue Wed Thu Fri Sat
1* 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
I have an initial implementation here, but the surface API and the configurable options can be changed and enhanced. I used Grid
, but maybe I should have used Table
?
** adapted from https://stackoverflow.com/questions/40912268/c-sharp-write-a-program-that-displays-the-calendar-asking-just-for-the-year-a
public class Calendar : IRenderable
{
private Grid grid;
public Calendar(
int currentMonth,
int currentYear,
CultureInfo cultureInfo = null,
List<CalendarEvent> events = null)
{
CurrentMonth = currentMonth;
CurrentYear = currentYear;
CultureInfo = cultureInfo ?? CultureInfo;
CalendarEvents = events ?? CalendarEvents;
grid = new Grid();
}
public CultureInfo CultureInfo { get; }
= CultureInfo.InvariantCulture;
public int CurrentMonth { get; }
= 1;
public int CurrentYear { get; }
= DateTime.UtcNow.Year;
public List<CalendarEvent> CalendarEvents { get; set; }
= new List<CalendarEvent>();
public Measurement Measure(RenderContext context, int maxWidth)
{
return ((IRenderable) grid).Measure(context, maxWidth);
}
public IEnumerable<Segment> Render(RenderContext context, int maxWidth)
{
var names = CultureInfo.DateTimeFormat.AbbreviatedDayNames;
var calendar = new int[6, 7];
var days = DateTime.DaysInMonth(CurrentYear, CurrentMonth);
var currentDay = 1;
var date = new DateTime(CurrentYear, CurrentMonth, currentDay);
var dayOfWeek = (int) date.DayOfWeek;
foreach (var day in names)
{
grid.AddColumn(new GridColumn());
}
// add day names
grid.AddRow(names);
// calendar rows
for (var i = 0; i < calendar.GetLength(0); i++)
{
var row = new List<string>();
// days
for (var j = 0; j < calendar.GetLength(1) && currentDay - dayOfWeek + 1 <= days; j++)
{
if (i == 0 && CurrentMonth > j)
{
row.Add(string.Empty);
}
else
{
var day = (currentDay - dayOfWeek + 1);
var display = string.Empty;
if (day > 0) {
var isEvent = CalendarEvents.Any(@event =>
@event.DateTime.Day == day &&
@event.DateTime.Month == CurrentMonth &&
@event.DateTime.Year == CurrentYear);
display = isEvent ? $"[blue]{day}*[/]" : day.ToString();
}
row.Add(display);
currentDay++;
}
}
grid.AddRow(row.ToArray());
}
return ((IRenderable) grid).Render(context, maxWidth);
}
}
public record CalendarEvent(string Name, DateTime DateTime);
Here is the table implementation.
public class Calendar : IRenderable
{
private Table table;
public Calendar(
int currentMonth,
int currentYear,
CultureInfo cultureInfo = null,
List<CalendarEvent> events = null)
{
CurrentMonth = currentMonth;
CurrentYear = currentYear;
CultureInfo = cultureInfo ?? CultureInfo;
CalendarEvents = events ?? CalendarEvents;
table = new Table
{
Border = TableBorder.Rounded,
ShowHeaders = true
};
}
public CultureInfo CultureInfo { get; }
= CultureInfo.InvariantCulture;
public int CurrentMonth { get; }
= 1;
public int CurrentYear { get; }
= DateTime.UtcNow.Year;
public List<CalendarEvent> CalendarEvents { get; set; }
= new List<CalendarEvent>();
public Measurement Measure(RenderContext context, int maxWidth)
{
return ((IRenderable) table).Measure(context, maxWidth);
}
public IEnumerable<Segment> Render(RenderContext context, int maxWidth)
{
var names = CultureInfo.DateTimeFormat.AbbreviatedDayNames;
var calendar = new int[6, 7];
var days = DateTime.DaysInMonth(CurrentYear, CurrentMonth);
var currentDay = 1;
var date = new DateTime(CurrentYear, CurrentMonth, currentDay);
var dayOfWeek = (int) date.DayOfWeek;
foreach (var day in names)
{
table.AddColumn(new TableColumn(day));
}
// calendar rows
for (var i = 0; i < calendar.GetLength(0); i++)
{
var row = new List<string>();
// days
for (var j = 0; j < calendar.GetLength(1) && currentDay - dayOfWeek + 1 <= days; j++)
{
if (i == 0 && CurrentMonth > j)
{
row.Add(string.Empty);
}
else
{
var day = (currentDay - dayOfWeek + 1);
var display = string.Empty;
if (day > 0) {
var isEvent = CalendarEvents.Any(@event =>
@event.DateTime.Day == day &&
@event.DateTime.Month == CurrentMonth &&
@event.DateTime.Year == CurrentYear);
display = isEvent ? $"[blue]{day}*[/]" : day.ToString();
}
row.Add(display);
currentDay++;
}
}
table.AddRow(row.ToArray());
}
return ((IRenderable) table).Render(context, maxWidth);
}
}
With the following output.
https://twitter.com/ThePracticalDev/status/1297551421903077377?s=20
Saw this npm package and thought it's concept would be a great addition to this library. Is it doable? Appropriate? In scope?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.