Compare commits

...

88 Commits

Author SHA1 Message Date
Phil Scott
f5a9c0ca26 Removes automatic registration of settings
Original intention was to register Settings automatically for DI. This ran into problem when the container verifies the configuration is valid for a settings using the constructor for initialization. It tries to resolve the parameters and fails.

This removes the automatic registration and falls back ActivatorCreateInstance when no Setting is registered.
2021-04-18 22:41:05 +02:00
Loïc Sharma
23564612c1 Make AsyncCommand a little more discoverable (#375) 2021-04-18 09:35:37 +02:00
Phil Scott
f2b8afffb3 Marks Spectre.Console.Testing as not a test project
Probably something that only bothers me, but I'm in a habit of running dotnet test at the solution level. It was discovering this project as a test project even though it isn't. This produces an error complaining about not having a testhost.dll. I'm pretty sure this comes in via a props when xunit is referenced. 

This attribute in the csproj marks the project explicitly as not a test project
2021-04-17 09:30:33 +02:00
Patrik Svensson
3e2eea730b Add output abstraction and reorganize profile
* Moves ColorSystem from Profile to Capabilities
* Renames Tty to IsTerminal
* Adds IAnsiConsoleOutput to make output more flexible

Closes #343
Closes #359
Closes #369
2021-04-13 21:39:54 -04:00
Phil Scott
bc9f610258 Added "--hidden" param to explain feature
Probably shouldn't include the hidden commands by default. This lets the user show them if needed.
2021-04-13 17:40:55 +02:00
Phil Scott
ae96606ab7 Adds default command to explain feature 2021-04-13 17:40:55 +02:00
Phil Scott
41ccc0b464 Adds CLI explain command
Wanted a command to break down how Spectre views the command model. This outputs all the relevant settings in a tree. You can get a short explanation for all the commands, or a detailed explanation for all commands (there is a flag to go vice versa on the detailed view if you want)

app cli explain
app cli explain myappcommand
app cli explain -d
2021-04-12 17:40:31 +02:00
Patrik Svensson
3545e0f6b5 Add example infrastructure
* Add "Shared" projects for all examples
* Update "Colors" example with better TrueColor demo
* Use same namespace for all examples
2021-04-11 22:03:13 -04:00
Patrik Svensson
2fe2bb3c32 Add parameterless Clear method for IAnsiConsole
Closes #338
2021-04-11 22:01:14 -04:00
Patrik Svensson
1fc6f22ea9 Remove Style.Clone method
Closes #362
2021-04-11 21:58:58 -04:00
Patrik Svensson
6a5c507936 Rename 'Demo' example to 'Showcase' 2021-04-09 22:01:05 +02:00
Patrik Svensson
efa3d3b130 Add NuGet.Config 2021-04-09 08:45:30 -04:00
Patrik Svensson
6007fcaafc Update to .NET SDK 5.0.202 2021-04-09 07:48:10 -04:00
Patrik Svensson
13ac38ed04 Fix color system mapping bug
Closes #342
2021-04-08 12:18:54 -04:00
Patrik Svensson
ca036f6543 Add demo example 2021-04-07 20:32:07 -04:00
Phil Scott
36ec3d1fd3 Adds rune width caching for cell length calculations 2021-04-07 23:59:23 +02:00
Patrik Svensson
fe5096dceb Fixes color system detection bug
If an application runs on Windows 10.0.15063 or above, on a
runtime prior to net5.0, the color system detection will fail
and fall back to 8-bit color support.

The reason for this is because the behavior of
Environment.OSVersion.Version differs between runtimes. Unless you're
running on net5.0, both the major and build version components will
not reflect those in the actual Windows version.
2021-04-07 11:15:45 -04:00
Christian Wischenbart
39b59c8d4a Cleanup AnsiSequences.cs
1. Update CSI constant to include the [ character.
See ECMA-48 Section 8.3.16
https://www.ecma-international.org/wp-content/uploads/ECMA-48_5th_edition_june_1991.pdf

2. Use string interpolation, because it's easier to read
(and internally uses a StringBuilder)

3. Add ESC constant, because the AnsiBuilder needs it to create links.

4. Remove unused SGR overload.
2021-04-06 22:51:42 +02:00
Phil Scott
8cf7794852 Adding unit tests for settings constructor 2021-04-06 22:48:51 +02:00
Phil Scott
4edc647fdd Falls back to null for settings constructor 2021-04-06 22:48:51 +02:00
Christian Wischenbart
be45a0ff4e Fix AnsiConsoleBackend.Clear
1. Add an ED3 command to clear the scroll buffer.

This command is not in the original ANSI terminal control sequences but
was added later to XTerm to account for the fact that most modern
terminals have a scroll-buffer.

https://invisible-island.net/xterm/ctlseqs/ctlseqs.html#h4-Functions-using-CSI-_-ordered-by-the-final-character-lparen-s-rparen:CSI-Ps-J.1C8A

This command is now awailable in basically
all terminals with scroll-buffers

2. Change CUP coordinates to 1, 1

The coordinates 0, 0 also worked, but strictly speaking they are outside
the available screen area and are capped to 1, 1 anyways.

This commit fixes #337
2021-04-06 22:42:03 +02:00
Christian Wischenbart
256fcdd27f Remove redundant Style constructor. 2021-04-06 07:30:31 -04:00
Patrik Svensson
dafbfe63ba Update link to docs site 2021-04-05 17:54:32 +02:00
Patrik Svensson
a2ab522516 Add CNAME 2021-04-05 17:45:29 +02:00
Patrik Svensson
8778ab1739 Set new host for docs 2021-04-05 17:41:18 +02:00
Patrik Svensson
693e1fa170 Update links, references and copyright 2021-04-05 16:59:09 +02:00
Patrik Svensson
4b37a4708f Update documentation 2021-04-05 16:48:02 +02:00
Phil Scott
a690ce4955 Marks nullable bools as flags too 2021-04-05 16:14:13 +02:00
Andreia Gaita
759b16aed9 Fix OS version detection 2021-04-04 09:28:20 -04:00
Phil Scott
254880e93a Replaces emoji regex with ReadOnlySpan implementation
The RegEx runtime perf was never anything noticeable - it was the startup time that was eating over a third of time during initialization.

This shaves 200ms off the startup time.
2021-04-04 04:10:25 +02:00
Patrik Svensson
6f16081f42 Add support for indeterminate progress
This commit also changes the behavior of ProgressContext.IsFinished.
Only tasks that have been started will be taken into consideration,
and not indeterminate tasks.

Closes #329
Closes #331
2021-04-03 09:42:49 -04:00
MB
6121203fee Rename tree to root so the example compiles.
The 'root' variable does not exist in current context. Either should call Render(tree) or have it renamed to root. I've chosen root as it's more consistent with the examples later on.
2021-04-02 23:32:15 +02:00
Phil Scott
9204671b27 Uses Environment.TickCount for seed instead of DateTime.Now 2021-04-02 18:52:18 +02:00
Phil Scott
c765bbd0dd Uses OSVersion instead of RegEx to detect Windows Build info
Perf improvement.
2021-04-02 18:51:30 +02:00
Thomas Freudenberg
6bceac8a5e enable disposing ITypeResolver 2021-03-30 00:53:38 +02:00
Patrik Svensson
1ed7e65fcb Make VT-100 sequences easier to understand 2021-03-28 12:51:19 -04:00
Patrik Svensson
20650f1e7e Change IAnsiConsole to render IRenderable
This makes it possible for encoders to output better representation
of the actual objects instead of working with chopped up segments.

* IAnsiConsole.Write now takes an IRenderable instead of segments
* Calculating cell width does no longer require a render context
* Removed RenderContext.LegacyConsole
* Removed RenderContext.Encoding
* Added Capabilities.Unicode
2021-03-28 09:06:06 -04:00
Alexey Golub
2ba6da3514 Respect encoding of TextWriter provided to AnsiConsole.Create(...) 2021-03-25 21:19:49 +01:00
Alexey Golub
8830779875 Add params to ProgressExtensions.Columns(...)
This way you can omit `new ProgressColumn[] { ... }` and just list the columns separated by comma.
2021-03-25 21:11:51 +01:00
Patrik Svensson
9c46c21e27 Fix argument order
Closes #319
2021-03-24 18:58:17 -04:00
Reilly Wood
c643ec735d Fix documentation for ProgressContext.AddTask 2021-03-24 07:34:56 -04:00
Phil Scott
b17eabaa1f Adds helper overloads for Markup calls without args
Without specific overloads without the args string.format will get called even if it's not needed. 

This closes #309
2021-03-22 19:14:59 +01:00
Patrik Svensson
7f6f2437b1 Add support for exclusive mode 2021-03-15 13:14:40 -04:00
Patrik Svensson
c2bab0ebf8 Allow custom instructions for prompts
Closes #229
2021-03-14 21:27:44 -04:00
Patrik Svensson
9502aaf2b9 Allow markup in selection prompts
Closes #221
2021-03-14 21:27:44 -04:00
Patrik Svensson
57a8e6ccc1 Support Home, End, PgUp, and PgDown in prompts
Closes #296
2021-03-14 21:27:44 -04:00
Patrik Svensson
8c099a0038 Add Elmah.io as sponsor 2021-03-14 21:17:56 -04:00
Bastian Eicher
08b65cfa47 Fix Windows ANSI support detection with redirected stderr 2021-03-14 23:41:07 +01:00
Christopher-Marcel Esser
2540f48622 Hide examples of hidden commands 2021-03-13 23:21:48 +01:00
Phil Scott
e4dda283bb Adds overloads for MarkUp methods without args
These methods don't require a string.format call so we'll directly call the Render method without a call to string.format.

Added bonus of a a couple fewer allocations too.
2021-03-08 15:04:55 +01:00
Phil Scott
da9c6ee4c2 Add IProgress<double> to ProgressTask.cs
Makes the Report method an explicit implementation to allow for better interoperability with standard .NET progress functionality while keeping backwards compatibility with existing ProgressTask functionality.

Closes #285
2021-03-07 09:24:44 +01:00
Phil Scott
855127f32a Changes progress task IsFinished to account for stopped tasks
Previous behavior was that the only way to get a task to a finished state was to artificially set the Value to MaxValue.

With this change StopTask() will also complete the task with the change that a task cannot be restarted.
2021-03-07 09:24:21 +01:00
stf
fa731070d8 update the docs
To improve discoveratbility of the new option
2021-03-04 07:47:00 -05:00
stf
ef08c5bf2b Improve the unit test around HideCompleted 2021-03-04 07:47:00 -05:00
stf
1c769c6610 Add Progress.HideCompleted 2021-03-04 07:47:00 -05:00
Phil Scott
1cd335e785 Serilog example for logging 2021-03-04 08:39:53 +01:00
Patrik Svensson
29e6e34f83 Support setting the static console 2021-03-01 15:22:35 -05:00
Phil Scott
bff3438a5a using loop instead of linq
In both of these loops context is captured preventing caching of the lambda. this results in a pretty significant amount of allocations especially with progress bars that constantly are remeasuring
2021-03-01 08:22:45 +01:00
Oskar Klintrot
c64884854f Make it possible to set Value directly 2021-02-25 11:56:32 +01:00
Phil Scott
3a42c0a119 Adds DotSettings and tweaks editoconfigs for tests
R# and Rider have quite a bit of noise related to documentation in the testing projects so this disables those warnings.

In the main projects, R# and Rider complain loudly about the namespaces not matching the file structure. The DotSettings file disables that warning.

Once you get rid of that noise there are quite a few opportunities for trimming out redundant code that R# points out especially with the nullable support enabled, plus there are some bugs related to multiple enumerations worth looking into I think.
2021-02-23 22:34:33 +01:00
Thomas Freudenberg
525b414ff8 Make alignment of TaskDescriptionColumn configurable 2021-02-16 23:33:47 +01:00
Thomas Freudenberg
ed0fb29be4 Make default answer for confirmation prompt configurable 2021-02-16 23:32:49 +01:00
Phil Scott
04d0e663d5 Extends maximum size of remaining and elapsed time displayed, plus a failsafe
Elapsed and remaining now support > 9 hours, and if a timespan can't be rendered in that size **:**:** will be displayed
2021-02-16 23:31:55 +01:00
Patrik Svensson
17ee8990f4 Update example image 2021-02-15 13:01:30 +01:00
Bastian Eicher
a1050fc676 Handle output to stderr 2021-02-14 18:08:42 +01:00
Phil Scott
9312663bde Adds text and Progress bar spinner column for tasks yet to be started 2021-02-14 18:03:57 +01:00
Patrik Svensson
102e2dc38d Allow formatting breakdown charts with lambda expr
Relates to #252
2021-02-13 17:09:51 +01:00
Patrik Svensson
28e9c14de4 Register the console lazily in CLI type registrar
This should fix a strange bug we're seeing in Cake on macOS.
2021-02-12 02:04:59 +01:00
Patrik Svensson
fd217ffc83 Update sponsor text 2021-02-11 23:22:43 +01:00
Patrik Svensson
95ec04df40 Add sponsor information 2021-02-11 23:20:11 +01:00
Patrik Svensson
705cf745ea Add formatting support for breakdown chart values
Closes #252
2021-02-05 11:53:55 +01:00
Patrik Svensson
b64e016e8c Add breakdown chart support
This also cleans up the bar chart code slightly and fixes
some minor bugs that were detected in related code.

Closes #244
2021-02-01 01:03:39 +01:00
Patrik Svensson
58400fe74e Fix code generation
Previous changes introduced some bugs to the
code generation scripts and templates, which
now have been fixed.
2021-01-29 21:46:08 +01:00
Patrik Svensson
e20f6284f9 Clean up profile enrichment 2021-01-29 20:16:52 +01:00
David Butler
953008b5e3 Implemented buffer/stream constructors for CanvasImage (#246)
* Implemented buffer/stream constructors for CanvasImage and added section to Canvas example

Signed-off-by: David Butler <mail@davidbutlerdesign.co.uk>
2021-01-27 18:12:22 +01:00
Milosz Krajewski
ad49b6aa67 GH-242: Fix version retrieval for single file applications (#245) 2021-01-26 00:45:38 +01:00
Patrik Svensson
31a5e17a45 Remove InteractivityDetector 2021-01-19 18:12:15 +01:00
Patrik Svensson
f06dc7e7d8 GitHub actions should use default width (for now) 2021-01-19 18:12:15 +01:00
Patrik Svensson
a23bec4082 Add profile support
Closes #231
2021-01-19 17:53:03 +01:00
Patrik Svensson
913a7b1e37 Add support for default choice in selection prompt
Closes #234
2021-01-15 17:05:11 +01:00
Nick
63bae278a9 Add support for selection prompt highlighting 2021-01-15 15:23:09 +01:00
Eslami Sepehr
1a747696a8 Add Persian README 2021-01-15 09:08:37 +01:00
Matt Constable
994540d97f Add cycle detection to tree rendering 2021-01-14 18:37:22 +01:00
Thomas Freudenberg
dee3c01629 mask default value when prompt is a secret 2021-01-14 17:44:18 +01:00
Mattias Karlsson
a3e11b24e5 (GH-226) Switch ParameterValidationAttribute check to IsNullOrWhiteSpace
* fixes #226
2021-01-13 20:31:33 +01:00
Jay Turpin
35568ab823 Updated Commands with with new Execute() method signature 2021-01-13 19:48:15 +01:00
Patrik Svensson
07db28bb6f Add enhancements to progress widget
* Adds TransferSpeedColumn
* Adds DownloadedColumn
* Adds ElapsedTimeColumn
* Minor enhancements to existing columns
2021-01-12 14:10:07 +01:00
ριтєя мαяχ
d87d8e4422 Update exceptions.md 2021-01-10 20:45:44 +01:00
456 changed files with 6420 additions and 2849 deletions

View File

@@ -21,7 +21,7 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.100
dotnet-version: 5.0.202
- name: Build
shell: bash
@@ -63,7 +63,7 @@ jobs:
- name: Setup dotnet 5.0.100
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.100
dotnet-version: 5.0.202
- name: Integration Tests
shell: bash

View File

@@ -24,7 +24,7 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.100
dotnet-version: 5.0.202
- name: Publish
shell: bash

View File

@@ -29,7 +29,7 @@ jobs:
- name: Setup dotnet
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.100
dotnet-version: 5.0.202
- name: Build
shell: bash
@@ -72,7 +72,7 @@ jobs:
- name: Setup dotnet 5.0.100
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.100
dotnet-version: 5.0.202
- name: Build
shell: bash
@@ -103,7 +103,7 @@ jobs:
- name: Setup dotnet 5.0.100
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.100
dotnet-version: 5.0.202
- name: Publish
shell: bash

View File

@@ -22,8 +22,8 @@ By contributing to Spectre.Console, you assert that:
* The contribution is your own original work.
* You have the right to assign the copyright for the work (it is not owned by your employer, or
you have been given copyright assignment in writing).
* You [license](https://github.com/spectresystems/spectre.console/blob/main/LICENSE) the contribution under the terms applied to the rest of the Spectre.Console project.
* You agree to follow the [code of conduct](https://github.com/spectresystems/spectre.console/blob/main/CODE_OF_CONDUCT.md).
* You [license](https://github.com/spectreconsole/spectre.console/blob/main/LICENSE) the contribution under the terms applied to the rest of the Spectre.Console project.
* You agree to follow the [code of conduct](https://github.com/spectreconsole/spectre.console/blob/main/CODE_OF_CONDUCT.md).
## Definition of trivial contributions
It's hard to define what is a trivial contribution. Sometimes even a 1 character change can be considered significant.
@@ -53,19 +53,19 @@ Any new code should also have reasonable unit test coverage.
## Contributing process
### Get buyoff or find open community issues or features
* Through GitHub, or through the [GitHub discussions](https://github.com/spectresystems/spectre.console/discussions) (preferred),
* Through GitHub, or through the [GitHub discussions](https://github.com/spectreconsole/spectre.console/discussions) (preferred),
you talk about a feature you would like to see (or a bug), and why it should be in Spectre.Console.
* If approved through the GitHub discussions, ensure an accompanying GitHub issue is created with
information and a link back to the discussion.
* Once you get a nod from someone in the Spectre.Console Team, you can start on the feature.
* Alternatively, if a feature is on the issues list with the
[Up For Grabs](https://github.com/spectresystems/spectre.console/labels/up-for-grabs) label,
[Up For Grabs](https://github.com/spectreconsole/spectre.console/labels/up-for-grabs) label,
it is open for a community member (contributor) to patch. You should comment that you are signing up for it on
the issue so someone else doesn't also sign up for the work.
### Set up your environment
* You create, or update, a fork of `spectresystems/spectre.console` under your GitHub account.
* You create, or update, a fork of `spectreconsole/spectre.console` under your GitHub account.
* From there you create a branch named specific to the feature.
* In the branch you do work specific to the feature.
* Please also observe the following:
@@ -96,7 +96,7 @@ Prerequisites:
Submitting PR:
* Once you feel it is ready, submit the pull request to the `spectresystems/spectre.console` repository against the `main` branch
* Once you feel it is ready, submit the pull request to the `spectreconsole/spectre.console` repository against the `main` branch
unless specifically requested to submit it against another branch.
* In the case of a larger change that is going to require more discussion,
please submit a PR sooner. Waiting until you are ready may mean more changes than you are
@@ -129,7 +129,7 @@ the issue/open a new PR (referencing old one).
Sometimes we may need you to rebase your commit against the latest code before we can review it further.
If this happens, you can do the following:
* `git fetch upstream` (upstream remote would be `spectresystems/spectre.console`)
* `git fetch upstream` (upstream remote would be `spectreconsole/spectre.console`)
* `git checkout main`
* `git rebase upstream/main`
* `git checkout your-branch`

View File

@@ -1,6 +1,6 @@
MIT License
Copyright (c) 2020 Spectre Systems AB
Copyright (c) 2020 Patrik Svensson, Phil Scott
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal

6
NuGet.Config Normal file
View File

@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>

77
README.fa.md Normal file
View File

@@ -0,0 +1,77 @@
# `Spectre.Console`
_[![Spectre.Console NuGet Version](https://img.shields.io/nuget/v/spectre.console.svg?style=flat&label=NuGet%3A%20Spectre.Console)](https://www.nuget.org/packages/spectre.console)_
<div dir="rtl">
یک کتابخانه NET Standard 2.0/.NET 5. که ایجاد Console Applicationهای زیبا و cross platform را آسان‌تر می‌کند.
از کتابخانه عالی [Rich](https://github.com/willmcgugan/rich) برای پایتون، بسیار الهام گرفته شده است.
## فهرست
1. [امکانات](#features)
2. [نصب](#installing)
3. [مستندات](#documentation)
4. [مثال‌ها](#examples)
5. [مجوز](#license)
<h2 id="features">امکانات</h2>
* با در نظر گرفتن تست واحد نوشته شده است.
* جداول، چارچوب‌ها، پنل‌ها و یک زبان نشانه گذاری که از [rich](https://github.com/willmcgugan/rich) الهام گرفته شده است را پشتیبانی می‌کند.
* از رایج ترین پارامترهای SRG در هنگام فرم دهی متن مانند پررنگ، کم نور، اریب، زیرخط، خط زدن و چشمک زدن پشتیبانی می‌کند.
* پشتیبانی از رنگ‌های 28/8/4/3-بیت در ترمینال.
این کتابخانه توانایی ترمینال فعلی را تشخیص داده و در صورت لزوم رنگ‌ها را کاهش می‌دهد.
![Example](docs/input/assets/images/example.png)
<h2 id="installing">نصب</h2>
سریع ترین راه برای شروع `Spectre.Console` نصب از طریق NuGet Package می‌باشد.
<pre dir="ltr">
dotnet add package Spectre.Console
</pre>
<h2 id="documentation">مستندات</h2>
مستندات `Spectre.Console` را در اینجا می‌توایند پیدا کنید:
<div dir="ltr">
https://spectreconsole.net/
</div>
<h2 id="examples">مثال‌ها</h2>
برای بررسی `Spectre.Console` در عمل، ابزار سراسری
[dotnet-example](https://github.com/patriksvensson/dotnet-example)
را نصب کنید.
<pre dir="ltr">
> dotnet tool restore
</pre>
حالا شما می‌توانید مثال‌های موجود در این مخزن را لیست کنید:
<pre dir="ltr">
> dotnet example
</pre>
و برای اجرای مثال:
<pre dir="ltr">
> dotnet example tables
</pre>
<h2 id="license">مجوز</h2>
<div dir="ltr">
Copyright © Patrik Svensson, Phil Scott
</div>
همانطور که Spectre.Console تحت مجوز MIT ارائه شده است؛ برای کسب اطلاعات بیشتر به مجوز مراجعه کنید.
* برای SixLabors.ImageSharp، مشاهده کنید: https://github.com/SixLabors/ImageSharp/blob/master/LICENSE
</div>

View File

@@ -29,7 +29,7 @@ Python用の素晴らしい[Rich ライブラリ](https://github.com/willmcgugan
## 例
![Example](resources/gfx/screenshots/example.png)
![Example](docs/input/assets/images/example.png)
## 使用方法
@@ -111,6 +111,7 @@ Spectre.Consoleでできることを見るために、
│ Panels │ examples/Panels/Panels.csproj │ Demonstrates how to render items in panels. │
│ Rules │ examples/Rules/Rules.csproj │ Demonstrates how to render horizontal rules (lines). │
│ Tables │ examples/Tables/Tables.csproj │ Demonstrates how to render tables in a console. │
│ Trees │ examples/Trees/Trees.csproj │ Demonstrates how to render trees in a console. │
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
```

View File

@@ -12,6 +12,7 @@ for Python.
2. [Installing](#installing)
3. [Documentation](#documentation)
4. [Examples](#examples)
5. [Sponsors](#sponsors)
5. [License](#license)
## Features
@@ -26,7 +27,7 @@ for Python.
and downgrade colors as needed.
![Example](resources/gfx/screenshots/example.png)
![Example](docs/input/assets/images/example.png)
## Installing
@@ -39,7 +40,7 @@ dotnet add package Spectre.Console
## Documentation
The documentation for `Spectre.Console` can be found at
https://spectresystems.github.io/spectre.console/
https://spectreconsole.net/
## Examples
@@ -63,9 +64,28 @@ And to run an example:
> dotnet example tables
```
## Sponsors
The following people are [sponsoring](https://github.com/sponsors/patriksvensson)
Spectre.Console to show their support and to ensure the longevity of the project.
* [Rodney Littles II](https://github.com/RLittlesII)
* [Martin Björkström](https://github.com/bjorkstromm)
* [Dave Glick](https://github.com/daveaglick)
* [Kim Gunanrsson](https://github.com/kimgunnarsson)
* [Andrew McClenaghan](https://github.com/andymac4182)
* [C. Augusto Proiete](https://github.com/augustoproiete)
* [Viktor Elofsson](https://github.com/vktr)
* [Steven Knox](https://github.com/stevenknox)
* [David Pendray](https://github.com/dpen2000)
* [Elmah.io](https://github.com/elmahio)
I really appreciate it.
**Thank you very much!**
## License
Copyright © Spectre Systems.
Copyright © Patrik Svensson, Phil Scott
Spectre.Console is provided as-is under the MIT license. For more information see LICENSE.

View File

@@ -34,7 +34,7 @@ dotnet add package Spectre.Console
## 文档
`Spectre.Console`的文档可以在这里查看
https://spectresystems.github.io/spectre.console/
https://spectreconsole.net/
## 例子
@@ -58,7 +58,7 @@ https://spectresystems.github.io/spectre.console/
## License
版权所有 © Spectre Systems。
版权所有 © Patrik Svensson, Phil Scott
Spectre.Console 基于 MIT 协议提供。查看 LICENSE 文件了解更多信息。

View File

@@ -1 +1 @@
dotnet run -- preview --virtual-dir "spectre.console"
dotnet run -- preview

View File

@@ -11,11 +11,10 @@ namespace Docs
public static async Task<int> Main(string[] args) =>
await Bootstrapper.Factory
.CreateWeb(args)
.AddSetting(Keys.Host, "spectresystems.github.io")
.AddSetting(Keys.LinkRoot, "/spectre.console")
.AddSetting(Keys.Host, "spectreconsole.net")
.AddSetting(Keys.LinksUseHttps, true)
.AddSetting(Constants.EditLink, ConfigureEditLink())
.ConfigureSite("spectresystems", "spectre.console", "main")
.ConfigureSite("spectreconsole", "spectre.console", "main")
.ConfigureDeployment(deployBranch: "docs")
.AddShortcode("Children", typeof(ChildrenShortcode))
.AddShortcode("ColorTable", typeof(ColorTableShortcode))

View File

@@ -1,13 +1,13 @@
# Documentation
To start contributing to the [Spectre.Console](https://github.com/spectresystems/spectre.console) documentation, you will need the [.NET Core SDK](https://dot.net) 3.1 or higher.
To start contributing to the [Spectre.Console](https://github.com/spectreconsole/spectre.console) documentation, you will need the [.NET Core SDK](https://dot.net) 3.1 or higher.
## Running Preview Site
The documentation site uses [Statiq](https://statiq.dev), a static site generator. To build the documentation site run the following in a command-line terminal.
```
> dotnet run preview --virtual-dir "spectre.console"
> Preview.ps1
```
After the build is complete, you can navigate to [http://localhost:5080/spectre.console](http://localhost:5080/spectre.console).
@@ -29,19 +29,13 @@ Layout and styling can also be found in the [input](./input) directory. Look for
## Custom Build Features
The documentation site has custom enhancements to Statiq located under the [./src](./src) directory. Enhancements to the build process include:
- [Extension Methods](./src/Extensions)
- [Models](./src/Models)
- [Pipelines](./src/Pipelines)
- [Shortcodes](./src/Shortcodes)
- [Utilities](./src/Utilities)
The documentation site has custom enhancements to Statiq located under the [./src](./src) directory.
## License
MIT License
Copyright (c) 2020 Spectre Systems AB
Copyright (c) 2020 Patrik Svensson, Phil Scott
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

1
docs/input/CNAME Normal file
View File

@@ -0,0 +1 @@
spectreconsole.net

View File

@@ -41,7 +41,7 @@
<a class="nav-link font-weight-light font-size-lg text-red" href="https://github.com/sponsors/patriksvensson"><i class="far fa-heart"></i> Sponsor</a>
</li>
<li class="nav-item">
<a class="nav-link font-weight-light font-size-lg" href="https://github.com/spectresystems/spectre.console"><i class="fab fa-github"></i> GitHub</a>
<a class="nav-link font-weight-light font-size-lg" href="https://github.com/spectreconsole/spectre.console"><i class="fab fa-github"></i> GitHub</a>
</li>
</ul>
</div>
@@ -203,7 +203,7 @@
<div id="footer" class="p-3 text-white font-size-sm">
<div class="container">
<div>
<span>© @DateTime.Today.Year Spectre Systems AB</span>
<span>© @DateTime.Today.Year Patrik Svensson, Phil Scott</span>
<span class="float-right" style="color: #888888;">@VersionUtilities.GetVersion()</span>
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 219 KiB

View File

@@ -58,21 +58,25 @@ in the previous step.
```csharp
public class AddPackageCommand : Command<AddPackageSettings>
{
public override int Execute(AddPackageSettings settings, ILookup<string, string> remaining)
public override int Execute(CommandContext context, AddPackageSettings settings)
{
// Omitted
return 0;
}
}
public class AddReferenceCommand : Command<AddReferenceSettings>
{
public override int Execute(AddReferenceSettings settings, ILookup<string, string> remaining)
public override int Execute(CommandContext context, AddReferenceSettings settings)
{
// Omitted
return 0;
}
}
```
You can use `AsyncCommand` if you need async support.
## Let's tie it together
Now when we have our commands and settings implemented, we can compose a command tree

View File

@@ -2,7 +2,7 @@ Title: Exceptions
Order: 3
---
Exceptions isn't always readable when viewed in the terminal.
Exceptions aren't always readable when viewed in the terminal.
You can make exception a bit more readable by using the `WriteException` method.
```csharp

View File

@@ -22,5 +22,5 @@ for Python written by Will McGugan.
## Examples
<img src="assets/images/table.gif" style="max-width: 100%; margin-top: 15px; margin-bottom: 25px;" />
<img src="https://github.com/spectresystems/spectre.console/raw/main/resources/gfx/screenshots/example.png" style="max-width: 100%;" />
<img src="./assets/images/example.png" style="max-width: 100%; margin-top: 15px; margin-bottom: 25px;" />
<img src="./assets/images/table.gif" style="max-width: 100%;" />

View File

@@ -0,0 +1,12 @@
Title: Live Displays
Order: 4
---
<h1>Sections</h1>
<ul>
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
{
<li>@Html.DocumentLink(child)</li>
}
</ul>

View File

@@ -1,16 +1,23 @@
Title: Progress
Order: 5
RedirectFrom: progress
---
Spectre.Console can display information about long running tasks in the console.
<img src="assets/images/progress.png" style="max-width: 100%;margin-bottom:20px;">
<img src="../assets/images/progress.png" style="max-width: 100%;margin-bottom:20px;">
<div class="alert alert-warning" role="alert">
<i class="fas fa-exclamation-triangle icon-web"></i> The progress display is not
thread safe, and using it together with other interactive components such as
prompts, status displays or other progress displays are not supported.
</div>
If the current terminal isn't considered "interactive", such as when running
in a continuous integration system, or the terminal can't display
ANSI control sequence, any progress will be displayed in a simpler way.
<img src="assets/images/progress_fallback.png" style="max-width: 100%;">
<img src="../assets/images/progress_fallback.png" style="max-width: 100%;">
# Usage
@@ -63,6 +70,7 @@ await AnsiConsole.Progress()
AnsiConsole.Progress()
.AutoRefresh(false) // Turn off auto refresh
.AutoClear(false) // Do not remove the task list when done
.HideCompleted(false) // Hide tasks as they are completed
.Columns(new ProgressColumn[]
{
new TaskDescriptionColumn(), // Task description

View File

@@ -1,10 +1,17 @@
Title: Status
Order: 6
RedirectFrom: status
---
Spectre.Console can display information about long running tasks in the console.
<img src="assets/images/status.gif" style="max-width: 100%;margin-bottom:20px;">
<img src="../assets/images/status.gif" style="max-width: 100%;margin-bottom:20px;">
<div class="alert alert-warning" role="alert">
<i class="fas fa-exclamation-triangle icon-web"></i> The status display is not
thread safe, and using it together with other interactive components such as
prompts, progress displays or other status displays are not supported.
</div>
If the current terminal isn't considered "interactive", such as when running
in a continuous integration system, or the terminal can't display

View File

@@ -7,6 +7,11 @@ one or many items from a provided list.
<img src="../assets/images/multiselection.gif" style="width: 100%;" />
<div class="alert alert-warning" role="alert" style="margin-top:20px;">
<i class="fas fa-exclamation-triangle icon-web"></i> The use of prompts
insides status or progress displays is not supported.
</div>
# Usage
```csharp
@@ -16,6 +21,10 @@ var fruits = AnsiConsole.Prompt(
.Title("What are your [green]favorite fruits[/]?")
.NotRequired() // Not required to have a favorite fruit
.PageSize(10)
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
.InstructionsText(
"[grey](Press [blue]<space>[/] to toggle a fruit, " +
"[green]<enter>[/] to accept)[/]")
.AddChoice("Apple")
.AddChoices(new[] {
"Apricot", "Avocado",

View File

@@ -7,6 +7,11 @@ a single item from a provided list.
<img src="../assets/images/selection.gif" style="width: 100%;" />
<div class="alert alert-warning" role="alert" style="margin-top:20px;">
<i class="fas fa-exclamation-triangle icon-web"></i> Using prompts inside
status or progress displays, are not supported.
</div>
# Usage
```csharp
@@ -15,6 +20,7 @@ var fruit = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.Title("What's your [green]favorite fruit[/]?")
.PageSize(10)
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
.AddChoice("Apple")
.AddChoices(new[] {
"Apricot", "Avocado",

View File

@@ -1,4 +1,4 @@
Title: Text
Title: Text prompt
Order: 0
RedirectFrom: prompt
---
@@ -6,6 +6,11 @@ RedirectFrom: prompt
Sometimes you want to get some input from the user, and for this
you can use the `Prompt<TResult>`.
<div class="alert alert-warning" role="alert">
<i class="fas fa-exclamation-triangle icon-web"></i> The use of prompts
insides status or progress displays is not supported.
</div>
# Confirmation
```csharp

20
docs/input/sponsors.md Normal file
View File

@@ -0,0 +1,20 @@
Title: Sponsors
Order: 0
---
The following people are [sponsoring](https://github.com/sponsors/patriksvensson)
Spectre.Console to show their support and to ensure the longevity of the project.
* [Rodney Littles II](https://github.com/RLittlesII)
* [Martin Björkström](https://github.com/bjorkstromm)
* [Dave Glick](https://github.com/daveaglick)
* [Kim Gunanrsson](https://github.com/kimgunnarsson)
* [Andrew McClenaghan](https://github.com/andymac4182)
* [C. Augusto Proiete](https://github.com/augustoproiete)
* [Viktor Elofsson](https://github.com/vktr)
* [Steven Knox](https://github.com/stevenknox)
* [David Pendray](https://github.com/dpen2000)
* [Elmah.io](https://github.com/elmahio)
I really appreciate it.
**Thank you very much!**

View File

@@ -10,10 +10,10 @@ The `Tree` widget can be used to render hierarchical data.
```csharp
// Create the tree
var tree = new Tree("Root");
var root = new Tree("Root");
// Add some nodes
var foo = tree.AddNode("[yellow]Foo[/]");
var foo = root.AddNode("[yellow]Foo[/]");
var table = foo.AddNode(new Table()
.RoundedBorder()
.AddColumn("First")
@@ -25,7 +25,7 @@ var table = foo.AddNode(new Table()
table.AddNode("[blue]Baz[/]");
foo.AddNode("Qux");
var bar = tree.AddNode("[yellow]Bar[/]");
var bar = root.AddNode("[yellow]Bar[/]");
bar.AddNode(new Calendar(2020, 12)
.AddCalendarEvent(2020, 12, 12)
.HideHeader());

View File

@@ -17,7 +17,7 @@ namespace Docs
public static class Colors
{
public const string Url = "https://raw.githubusercontent.com/spectresystems/spectre.console/main/resources/scripts/Generator/Data/colors.json";
public const string Url = "https://raw.githubusercontent.com/spectreconsole/spectre.console/main/resources/scripts/Generator/Data/colors.json";
public const string Root = "COLORS_ROOT";
}

View File

@@ -3,7 +3,7 @@
"isRoot": true,
"tools": {
"cake.tool": {
"version": "1.0.0-rc0002",
"version": "1.1.0",
"commands": [
"dotnet-cake"
]

View File

@@ -1,7 +1,7 @@
using System.ComponentModel;
using Spectre.Console.Cli;
namespace Delegates
namespace Spectre.Console.Examples
{
public static partial class Program
{

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
@@ -11,7 +11,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,6 @@
using System;
using Spectre.Console.Cli;
namespace Delegates
namespace Spectre.Console.Examples
{
public static partial class Program
{
@@ -22,7 +21,7 @@ namespace Delegates
private static int Foo(CommandContext context)
{
Console.WriteLine("Foo");
AnsiConsole.WriteLine("Foo");
return 0;
}
@@ -30,7 +29,7 @@ namespace Delegates
{
for (var index = 0; index < settings.Count; index++)
{
Console.WriteLine("Bar");
AnsiConsole.WriteLine("Bar");
}
return 0;

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
@@ -11,7 +11,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,7 @@
using System;
using Spectre.Console.Cli;
namespace Dynamic
namespace Spectre.Console.Examples
{
public sealed class MyCommand : Command
{
@@ -13,7 +13,7 @@ namespace Dynamic
}
Console.WriteLine("Value = {0}", data);
AnsiConsole.WriteLine("Value = {0}", data);
return 0;
}
}

View File

@@ -1,7 +1,7 @@
using System.Linq;
using Spectre.Console.Cli;
namespace Dynamic
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -2,7 +2,7 @@ using System;
using System.ComponentModel;
using Spectre.Console.Cli;
namespace Injection.Commands
namespace Spectre.Console.Examples
{
public sealed class DefaultCommand : Command<DefaultCommand.Settings>
{

View File

@@ -1,6 +1,4 @@
using System;
namespace Injection
namespace Spectre.Console.Examples
{
public interface IGreeter
{
@@ -11,7 +9,7 @@ namespace Injection
{
public void Greet(string name)
{
Console.WriteLine($"Hello {name}!");
AnsiConsole.WriteLine($"Hello {name}!");
}
}
}

View File

@@ -2,7 +2,7 @@ using System;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console.Cli;
namespace Injection
namespace Spectre.Console.Examples
{
public sealed class TypeRegistrar : ITypeRegistrar
{
@@ -27,5 +27,15 @@ namespace Injection
{
_builder.AddSingleton(service, implementation);
}
public void RegisterLazy(Type service, Func<object> func)
{
if (func is null)
{
throw new ArgumentNullException(nameof(func));
}
_builder.AddSingleton(service, (provider) => func());
}
}
}

View File

@@ -2,9 +2,9 @@ using System;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console.Cli;
namespace Injection
namespace Spectre.Console.Examples
{
public sealed class TypeResolver : ITypeResolver
public sealed class TypeResolver : ITypeResolver, IDisposable
{
private readonly IServiceProvider _provider;
@@ -17,5 +17,13 @@ namespace Injection
{
return _provider.GetRequiredService(type);
}
public void Dispose()
{
if (_provider is IDisposable disposable)
{
disposable.Dispose();
}
}
}
}

View File

@@ -15,7 +15,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,8 +1,7 @@
using Injection.Commands;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console.Cli;
namespace Injection
namespace Spectre.Console.Examples
{
public class Program
{

View File

@@ -0,0 +1,34 @@
using Microsoft.Extensions.Logging;
using Spectre.Console.Cli;
namespace Spectre.Console.Examples
{
public class HelloCommand : Command<HelloCommand.Settings>
{
private ILogger<HelloCommand> _logger;
private IAnsiConsole _console;
public HelloCommand(IAnsiConsole console, ILogger<HelloCommand> logger)
{
_console = console;
_logger = logger;
_logger.LogDebug("{0} initialized", nameof(HelloCommand));
}
public class Settings : LogCommandSettings
{
[CommandArgument(0, "[Name]")]
public string Name { get; set; }
}
public override int Execute(CommandContext context, Settings settings)
{
_logger.LogInformation("Starting my command");
AnsiConsole.MarkupLine($"Hello, [blue]{settings.Name}[/]");
_logger.LogInformation("Completed my command");
return 0;
}
}
}

View File

@@ -0,0 +1,56 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Globalization;
using Serilog.Events;
using Spectre.Console.Cli;
namespace Spectre.Console.Examples
{
public class LogCommandSettings : CommandSettings
{
[CommandOption("--logFile")]
[Description("Path and file name for logging")]
public string LogFile { get; set; }
[CommandOption("--logLevel")]
[Description("Minimum level for logging")]
[TypeConverter(typeof(VerbosityConverter))]
[DefaultValue(LogEventLevel.Information)]
public LogEventLevel LogLevel { get; set; }
}
public sealed class VerbosityConverter : TypeConverter
{
private readonly Dictionary<string, LogEventLevel> _lookup;
public VerbosityConverter()
{
_lookup = new Dictionary<string, LogEventLevel>(StringComparer.OrdinalIgnoreCase)
{
{"d", LogEventLevel.Debug},
{"v", LogEventLevel.Verbose},
{"i", LogEventLevel.Information},
{"w", LogEventLevel.Warning},
{"e", LogEventLevel.Error},
{"f", LogEventLevel.Fatal}
};
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value is string stringValue)
{
var result = _lookup.TryGetValue(stringValue, out var verbosity);
if (!result)
{
const string format = "The value '{0}' is not a valid verbosity.";
var message = string.Format(CultureInfo.InvariantCulture, format, value);
throw new InvalidOperationException(message);
}
return verbosity;
}
throw new NotSupportedException("Can't convert value to verbosity.");
}
}
}

View File

@@ -0,0 +1,19 @@
using Serilog.Core;
using Spectre.Console.Cli;
namespace Spectre.Console.Examples
{
public class LogInterceptor : ICommandInterceptor
{
public static readonly LoggingLevelSwitch LogLevel = new();
public void Intercept(CommandContext context, CommandSettings settings)
{
if (settings is LogCommandSettings logSettings)
{
LoggingEnricher.Path = logSettings.LogFile ?? "application.log";
LogLevel.MinimumLevel = logSettings.LogLevel;
}
}
}
}

View File

@@ -0,0 +1,38 @@
using Serilog.Core;
using Serilog.Events;
namespace Spectre.Console.Examples
{
internal class LoggingEnricher : ILogEventEnricher
{
private string _cachedLogFilePath;
private LogEventProperty _cachedLogFilePathProperty;
// this path and level will be set by the LogInterceptor.cs after parsing the settings
public static string Path = string.Empty;
public const string LogFilePathPropertyName = "LogFilePath";
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
{
// the settings might not have a path or we might not be within a command in which case
// we won't have the setting so a default value for the log file will be required
LogEventProperty logFilePathProperty;
if (_cachedLogFilePathProperty != null && Path.Equals(_cachedLogFilePath))
{
// Path hasn't changed, so let's use the cached property
logFilePathProperty = _cachedLogFilePathProperty;
}
else
{
// We've got a new path for the log. Let's create a new property
// and cache it for future log events to use
_cachedLogFilePath = Path;
_cachedLogFilePathProperty = logFilePathProperty = propertyFactory.CreateProperty(LogFilePathPropertyName, Path);
}
logEvent.AddPropertyIfAbsent(logFilePathProperty);
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console.Cli;
namespace Spectre.Console.Examples
{
public sealed class TypeRegistrar : ITypeRegistrar
{
private readonly IServiceCollection _builder;
public TypeRegistrar(IServiceCollection builder)
{
_builder = builder;
}
public ITypeResolver Build()
{
return new TypeResolver(_builder.BuildServiceProvider());
}
public void Register(Type service, Type implementation)
{
_builder.AddSingleton(service, implementation);
}
public void RegisterInstance(Type service, object implementation)
{
_builder.AddSingleton(service, implementation);
}
public void RegisterLazy(Type service, Func<object> func)
{
if (func is null)
{
throw new ArgumentNullException(nameof(func));
}
_builder.AddSingleton(service, _ => func());
}
}
}

View File

@@ -0,0 +1,21 @@
using System;
using Microsoft.Extensions.DependencyInjection;
using Spectre.Console.Cli;
namespace Spectre.Console.Examples
{
public sealed class TypeResolver : ITypeResolver
{
private readonly IServiceProvider _provider;
public TypeResolver(IServiceProvider provider)
{
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
}
public object Resolve(Type type)
{
return _provider.GetRequiredService(type);
}
}
}

View File

@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
<ExampleName>Logging</ExampleName>
<ExampleDescription>Demonstrates how to dynamically configure Serilog for logging using parameters from a command.</ExampleDescription>
<ExampleGroup>Cli</ExampleGroup>
<ExampleVisible>false</ExampleVisible>
<Nullable>disable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
<PackageReference Include="Serilog" Version="2.10.0" />
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
<PackageReference Include="Serilog.Sinks.Map" Version="1.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,53 @@
using Microsoft.Extensions.DependencyInjection;
using Serilog;
using Spectre.Console.Cli;
/*
* Dynamically control serilog configuration via command line parameters
*
* This works around the chicken and egg situation with configuring serilog via the command line.
* The logger needs to be configured prior to executing the parser, but the logger needs the parsed values
* to be configured. By using serilog.sinks.map we can defer configuration. We use a LogLevelSwitch to control the
* logging levels dynamically, and then we use a serilog enricher that has it's state populated via a
* Spectre.Console CommandInterceptor
*/
namespace Spectre.Console.Examples
{
public class Program
{
static int Main(string[] args)
{
// to retrieve the log file name, we must first parse the command settings
// this will require us to delay setting the file path for the file writer.
// With serilog we can use an enricher and Serilog.Sinks.Map to dynamically
// pull this setting.
var serviceCollection = new ServiceCollection()
.AddLogging(configure =>
configure.AddSerilog(new LoggerConfiguration()
// log level will be dynamically be controlled by our log interceptor upon running
.MinimumLevel.ControlledBy(LogInterceptor.LogLevel)
// the log enricher will add a new property with the log file path from the settings
// that we can use to set the path dynamically
.Enrich.With<LoggingEnricher>()
// serilog.sinks.map will defer the configuration of the sink to be ondemand
// allowing us to look at the properties set by the enricher to set the path appropriately
.WriteTo.Map(LoggingEnricher.LogFilePathPropertyName,
(logFilePath, wt) => wt.File($"{logFilePath}"), 1)
.CreateLogger()
)
);
var registrar = new TypeRegistrar(serviceCollection);
var app = new CommandApp(registrar);
app.Configure(config =>
{
config.SetInterceptor(new LogInterceptor()); // add the interceptor
config.AddCommand<HelloCommand>("hello");
});
return app.Run(args);
}
}
}

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,6 @@
using Spectre.Console;
using Spectre.Console.Rendering;
namespace BordersExample
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using Spectre.Console;
namespace Calendars
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -2,21 +2,21 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<ExampleTitle>Canvas</ExampleTitle>
<ExampleDescription>Demonstrates how to render pixels and images.</ExampleDescription>
<ExampleGroup>Widgets</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
<ProjectReference Include="..\..\..\src\Spectre.Console.ImageSharp\Spectre.Console.ImageSharp.csproj" />
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="cake.png">
<EmbeddedResource Include="cake.png">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -4,9 +4,8 @@ Licensed under GNU Free Documentation License 1.2
*/
using System;
using Spectre.Console;
namespace CanvasExample
namespace Spectre.Console.Examples
{
public static class Mandelbrot
{

View File

@@ -1,8 +1,9 @@
using System.Diagnostics;
using System.Reflection;
using SixLabors.ImageSharp.Processing;
using Spectre.Console;
using Spectre.Console.Rendering;
namespace CanvasExample
namespace Spectre.Console.Examples
{
public static class Program
{
@@ -23,6 +24,16 @@ namespace CanvasExample
image.NoMaxWidth();
image.Mutate(ctx => ctx.Grayscale().Rotate(-45).EntropyCrop());
Render(image, "Image from file (fit, greyscale, rotated)");
// Draw image again, but load from embedded resource rather than file
using (var fileStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Canvas.cake.png"))
{
Debug.Assert(fileStream != null);
var embeddedImage = new CanvasImage(fileStream);
embeddedImage.BilinearResampler();
embeddedImage.MaxWidth(16);
Render(embeddedImage, "Image from embedded resource (16 wide)");
}
}
private static void Render(IRenderable canvas, string title)

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,21 +1,41 @@
using Spectre.Console;
using Spectre.Console.Rendering;
namespace InfoExample
namespace Spectre.Console.Examples
{
public static class Program
{
public static void Main()
{
var chart = new BarChart()
// Render a bar chart
AnsiConsole.WriteLine();
Render("Fruits per month", new BarChart()
.Width(60)
.Label("[green bold underline]Number of fruits[/]")
.CenterLabel()
.AddItem("Apple", 12, Color.Yellow)
.AddItem("Orange", 54, Color.Green)
.AddItem("Banana", 33, Color.Red);
.AddItem("Banana", 33, Color.Red));
// Render a breakdown chart
AnsiConsole.WriteLine();
AnsiConsole.Render(chart);
Render("Languages used", new BreakdownChart()
.FullSize()
.Width(60)
.ShowPercentage()
.AddItem("SCSS", 37, Color.Red)
.AddItem("HTML", 28.3, Color.Blue)
.AddItem("C#", 22.6, Color.Green)
.AddItem("JavaScript", 6, Color.Yellow)
.AddItem("Ruby", 6, Color.LightGreen)
.AddItem("Shell", 0.1, Color.Aqua));
}
private static void Render(string title, IRenderable chart)
{
AnsiConsole.Render(
new Panel(chart)
.Padding(1, 1)
.Header(title));
}
}
}

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,27 +1,23 @@
using Spectre.Console;
namespace ColorExample
namespace Spectre.Console.Examples
{
public static class Program
{
public static void Main()
{
if (AnsiConsole.Capabilities.ColorSystem == ColorSystem.NoColors)
/////////////////////////////////////////////////////////////////
// No colors
/////////////////////////////////////////////////////////////////
if (AnsiConsole.Profile.Capabilities.ColorSystem == ColorSystem.NoColors)
{
/////////////////////////////////////////////////////////////////
// No colors
/////////////////////////////////////////////////////////////////
AnsiConsole.WriteLine("No colors are supported.");
return;
}
if (AnsiConsole.Capabilities.Supports(ColorSystem.Legacy))
/////////////////////////////////////////////////////////////////
// 3-BIT
/////////////////////////////////////////////////////////////////
if (AnsiConsole.Profile.Supports(ColorSystem.Legacy))
{
/////////////////////////////////////////////////////////////////
// 3-BIT
/////////////////////////////////////////////////////////////////
AnsiConsole.ResetColors();
AnsiConsole.WriteLine();
AnsiConsole.Render(new Rule("[yellow bold underline]3-bit Colors[/]").RuleStyle("grey").LeftAligned());
@@ -30,6 +26,7 @@ namespace ColorExample
for (var i = 0; i < 8; i++)
{
AnsiConsole.Background = Color.FromInt32(i);
AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor();
AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString()));
AnsiConsole.ResetColors();
if ((i + 1) % 8 == 0)
@@ -39,12 +36,11 @@ namespace ColorExample
}
}
if (AnsiConsole.Capabilities.Supports(ColorSystem.Standard))
/////////////////////////////////////////////////////////////////
// 4-BIT
/////////////////////////////////////////////////////////////////
if (AnsiConsole.Profile.Supports(ColorSystem.Standard))
{
/////////////////////////////////////////////////////////////////
// 4-BIT
/////////////////////////////////////////////////////////////////
AnsiConsole.ResetColors();
AnsiConsole.WriteLine();
AnsiConsole.Render(new Rule("[yellow bold underline]4-bit Colors[/]").RuleStyle("grey").LeftAligned());
@@ -53,6 +49,7 @@ namespace ColorExample
for (var i = 0; i < 16; i++)
{
AnsiConsole.Background = Color.FromInt32(i);
AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor();
AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString()));
AnsiConsole.ResetColors();
if ((i + 1) % 8 == 0)
@@ -62,12 +59,11 @@ namespace ColorExample
}
}
if (AnsiConsole.Capabilities.Supports(ColorSystem.EightBit))
/////////////////////////////////////////////////////////////////
// 8-BIT
/////////////////////////////////////////////////////////////////
if (AnsiConsole.Profile.Supports(ColorSystem.EightBit))
{
/////////////////////////////////////////////////////////////////
// 8-BIT
/////////////////////////////////////////////////////////////////
AnsiConsole.ResetColors();
AnsiConsole.WriteLine();
AnsiConsole.Render(new Rule("[yellow bold underline]8-bit Colors[/]").RuleStyle("grey").LeftAligned());
@@ -79,6 +75,7 @@ namespace ColorExample
{
var number = i * 16 + j;
AnsiConsole.Background = Color.FromInt32(number);
AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor();
AnsiConsole.Write(string.Format(" {0,-4}", number));
AnsiConsole.ResetColors();
if ((number + 1) % 16 == 0)
@@ -89,31 +86,17 @@ namespace ColorExample
}
}
if (AnsiConsole.Capabilities.Supports(ColorSystem.TrueColor))
/////////////////////////////////////////////////////////////////
// 24-BIT
/////////////////////////////////////////////////////////////////
if (AnsiConsole.Profile.Supports(ColorSystem.TrueColor))
{
/////////////////////////////////////////////////////////////////
// 24-BIT
/////////////////////////////////////////////////////////////////
AnsiConsole.ResetColors();
AnsiConsole.WriteLine();
AnsiConsole.Render(new Rule("[yellow bold underline]24-bit Colors[/]").RuleStyle("grey").LeftAligned());
AnsiConsole.WriteLine();
var index = 0;
for (var i = 0.0005; i < 1; i += 0.0025)
{
index++;
var color = Utilities.HSL2RGB(i, 0.5, 0.5);
AnsiConsole.Background = new Color(color.R, color.G, color.B);
AnsiConsole.Write(" ");
if (index % 50 == 0)
{
AnsiConsole.WriteLine();
}
}
AnsiConsole.Render(new ColorBox(width: 80, height: 15));
}
}
}

View File

@@ -1,77 +0,0 @@
using System;
using Spectre.Console;
namespace ColorExample
{
public static class Utilities
{
// Borrowed from https://geekymonkey.com/Programming/CSharp/RGB2HSL_HSL2RGB.htm
public static Color HSL2RGB(double h, double sl, double l)
{
double v;
double r, g, b;
r = l; // default to gray
g = l;
b = l;
v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
if (v > 0)
{
double m;
double sv;
int sextant;
double fract, vsf, mid1, mid2;
m = l + l - v;
sv = (v - m) / v;
h *= 6.0;
sextant = (int)h;
fract = h - sextant;
vsf = v * sv * fract;
mid1 = m + vsf;
mid2 = v - vsf;
switch (sextant)
{
case 0:
r = v;
g = mid1;
b = m;
break;
case 1:
r = mid2;
g = v;
b = m;
break;
case 2:
r = m;
g = v;
b = mid1;
break;
case 3:
r = m;
g = mid2;
b = v;
break;
case 4:
r = mid1;
g = m;
b = v;
break;
case 5:
r = v;
g = m;
b = mid2;
break;
}
}
return new Color(
Convert.ToByte(r * 255.0f),
Convert.ToByte(g * 255.0f),
Convert.ToByte(b * 255.0f));
}
}
}

View File

@@ -13,7 +13,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,6 @@
using System.Collections.Generic;
using Spectre.Console;
namespace ColumnsExample
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -1,6 +1,6 @@
using System.Collections.Generic;
namespace ColumnsExample
namespace Spectre.Console.Examples
{
public sealed class User
{
@@ -22,9 +22,9 @@ namespace ColumnsExample
},
new User
{
FirstName = "Brandon",
LastName = "Cole",
City = "Washington",
FirstName = "Phil",
LastName = "Scott",
City = "Dayton",
Country = "United States",
},
new User

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using Spectre.Console;
namespace Cursor
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using Spectre.Console;
namespace EmojiExample
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,8 +1,7 @@
using System;
using System.Security.Authentication;
using Spectre.Console;
namespace Exceptions
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using Spectre.Console;
namespace EmojiExample
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using Spectre.Console;
namespace GridExample
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using Spectre.Console;
namespace InfoExample
namespace Spectre.Console.Examples
{
public static class Program
{
@@ -9,12 +7,17 @@ namespace InfoExample
var grid = new Grid()
.AddColumn(new GridColumn().NoWrap().PadRight(4))
.AddColumn()
.AddRow("[b]Color system[/]", $"{AnsiConsole.Capabilities.ColorSystem}")
.AddRow("[b]Supports ansi?[/]", $"{YesNo(AnsiConsole.Capabilities.SupportsAnsi)}")
.AddRow("[b]Legacy console?[/]", $"{YesNo(AnsiConsole.Capabilities.LegacyConsole)}")
.AddRow("[b]Interactive?[/]", $"{YesNo(AnsiConsole.Capabilities.SupportsInteraction)}")
.AddRow("[b]Buffer width[/]", $"{AnsiConsole.Console.Width}")
.AddRow("[b]Buffer height[/]", $"{AnsiConsole.Console.Height}");
.AddRow("[b]Enrichers[/]", string.Join(", ", AnsiConsole.Profile.Enrichers))
.AddRow("[b]Color system[/]", $"{AnsiConsole.Profile.Capabilities.ColorSystem}")
.AddRow("[b]Unicode?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Unicode)}")
.AddRow("[b]Supports ansi?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Ansi)}")
.AddRow("[b]Supports links?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Links)}")
.AddRow("[b]Legacy console?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Legacy)}")
.AddRow("[b]Interactive?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Interactive)}")
.AddRow("[b]Terminal?[/]", $"{YesNo(AnsiConsole.Profile.Out.IsTerminal)}")
.AddRow("[b]Buffer width[/]", $"{AnsiConsole.Console.Profile.Width}")
.AddRow("[b]Buffer height[/]", $"{AnsiConsole.Console.Profile.Height}")
.AddRow("[b]Encoding[/]", $"{AnsiConsole.Console.Profile.Encoding.EncodingName}");
AnsiConsole.Render(
new Panel(grid)

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,12 +1,10 @@
using Spectre.Console;
namespace LinkExample
namespace Spectre.Console.Examples
{
public static class Program
{
public static void Main()
{
if (AnsiConsole.Capabilities.SupportLinks)
if (AnsiConsole.Profile.Capabilities.Links)
{
AnsiConsole.MarkupLine("[link=https://patriksvensson.se]Click to visit my blog[/]!");
}

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using Spectre.Console;
namespace PanelExample
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -1,7 +1,7 @@
using System;
using System.Collections.Generic;
namespace ProgressExample
namespace Spectre.Console.Examples
{
public static class DescriptionGenerator
{

View File

@@ -1,9 +1,8 @@
using System;
using System.Collections.Generic;
using System.Threading;
using Spectre.Console;
namespace ProgressExample
namespace Spectre.Console.Examples
{
public static class Program
{
@@ -25,8 +24,12 @@ namespace ProgressExample
.Start(ctx =>
{
var random = new Random(DateTime.Now.Millisecond);
var tasks = CreateTasks(ctx, random);
// Create some tasks
var tasks = CreateTasks(ctx, random);
var warpTask = ctx.AddTask("Going to warp", autoStart: false).IsIndeterminate();
// Wait for all tasks (except the indeterminate one) to complete
while (!ctx.IsFinished)
{
// Increment progress
@@ -44,13 +47,24 @@ namespace ProgressExample
// Simulate some delay
Thread.Sleep(100);
}
// Now start the "warp" task
warpTask.StartTask();
warpTask.IsIndeterminate(false);
while (!ctx.IsFinished)
{
warpTask.Increment(12 * random.NextDouble());
// Simulate some delay
Thread.Sleep(100);
}
});
// Done
AnsiConsole.MarkupLine("[green]Done![/]");
}
private static List<(ProgressTask, int)> CreateTasks(ProgressContext progress, Random random)
private static List<(ProgressTask Task, int Delay)> CreateTasks(ProgressContext progress, Random random)
{
var tasks = new List<(ProgressTask, int)>();
while (tasks.Count < 5)

View File

@@ -13,7 +13,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,13 +1,11 @@
using Spectre.Console;
namespace Cursor
namespace Spectre.Console.Examples
{
public static class Program
{
public static void Main(string[] args)
{
// Check if we can accept key strokes
if (!AnsiConsole.Capabilities.SupportsInteraction)
if (!AnsiConsole.Profile.Capabilities.Interactive)
{
AnsiConsole.MarkupLine("[red]Environment does not support interaction.[/]");
return;
@@ -59,6 +57,8 @@ namespace Cursor
new MultiSelectionPrompt<string>()
.PageSize(10)
.Title("What are your [green]favorite fruits[/]?")
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
.InstructionsText("[grey](Press [blue]<space>[/] to toggle a fruit, [green]<enter>[/] to accept)[/]")
.AddChoices(new[]
{
"Apple", "Apricot", "Avocado", "Banana", "Blackcurrant", "Blueberry",
@@ -74,6 +74,7 @@ namespace Cursor
fruit = AnsiConsole.Prompt(
new SelectionPrompt<string>()
.Title("Ok, but if you could only choose [green]one[/]?")
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
.AddChoices(favorites));
}
@@ -88,8 +89,8 @@ namespace Cursor
return AnsiConsole.Prompt(
new TextPrompt<string>("What's your [green]favorite sport[/]?")
.InvalidChoiceMessage("[red]That's not a valid fruit[/]")
.DefaultValue("Lol")
.InvalidChoiceMessage("[red]That's not a sport![/]")
.DefaultValue("Sport?")
.AddChoice("Soccer")
.AddChoice("Hockey")
.AddChoice("Basketball"));

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<TargetFramework>net5.0</TargetFramework>
<LangVersion>9</LangVersion>
<ExampleTitle>Prompt</ExampleTitle>
<ExampleDescription>Demonstrates how to get input from a user.</ExampleDescription>
@@ -10,7 +10,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using Spectre.Console;
namespace EmojiExample
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,30 @@
using System;
namespace Spectre.Console.Examples
{
public static class ExceptionGenerator
{
public static Exception GenerateException()
{
try
{
SomeOperation();
throw new InvalidOperationException();
}
catch (Exception ex)
{
return ex;
}
}
private static void SomeOperation()
{
SomeOperationGoingWrong();
}
private static void SomeOperationGoingWrong()
{
throw new InvalidOperationException("Something went very wrong!");
}
}
}

View File

@@ -0,0 +1,153 @@
using Spectre.Console.Rendering;
namespace Spectre.Console.Examples
{
public static partial class Program
{
public static void Main()
{
var table = new Table().HideHeaders().NoBorder();
table.Title("[u][yellow]Spectre.Console[/] [b]Features[/][/]");
table.AddColumn("Feature", c => c.NoWrap().RightAligned().Width(10).PadRight(3));
table.AddColumn("Demonstration", c => c.PadRight(0));
table.AddEmptyRow();
// Colors
table.AddRow(
new Markup("[red]Colors[/]"),
GetColorTable());
// Styles
table.AddEmptyRow();
table.AddRow(
new Markup("[red]OS[/]"),
new Grid().Expand().AddColumns(3)
.AddRow(
"[bold green]Windows[/]",
"[bold blue]macOS[/]",
"[bold yellow]Linux[/]"));
// Styles
table.AddEmptyRow();
table.AddRow(
"[red]Styles[/]",
"All ansi styles: [bold]bold[/], [dim]dim[/], [italic]italic[/], [underline]underline[/], "
+ "[strikethrough]strikethrough[/], [reverse]reverse[/], and even [blink]blink[/].");
// Text
table.AddEmptyRow();
table.AddRow(
new Markup("[red]Text[/]"),
new Markup("Word wrap text. Justify [green]left[/], [yellow]center[/] or [blue]right[/]."));
table.AddEmptyRow();
table.AddRow(
Text.Empty,
GetTextGrid());
// Markup
table.AddEmptyRow();
table.AddRow(
"[red]Markup[/]",
"[bold purple]Spectre.Console[/] supports a simple [i]bbcode[/] like "
+ "[b]markup[/] for [yellow]color[/], [underline]style[/], and emoji! "
+ ":thumbs_up: :red_apple: :ant: :bear: :baguette_bread: :bus:");
// Trees and tables
table.AddEmptyRow();
table.AddRow(
new Markup("[red]Tables and Trees[/]"),
GetTreeTable());
// Charts
table.AddRow(
new Markup("[red]Charts[/]"),
new Grid().Collapse().AddColumns(2).AddRow(
new Panel(GetBreakdownChart()).BorderColor(Color.Grey),
new Panel(GetBarChart()).BorderColor(Color.Grey)));
// Exceptions
table.AddEmptyRow();
table.AddRow(
new Markup("[red]Exceptions[/]"),
ExceptionGenerator.GenerateException().GetRenderable());
// Much more
table.AddEmptyRow();
table.AddRow(
"[red]+ Much more![/]",
"Tables, Grids, Trees, Progress bars, Status, Bar charts, Calendars, Figlet, Images, Text prompts, "
+ "List boxes, Separators, Pretty exceptions, Canvas, CLI parsing");
table.AddEmptyRow();
// Render the table
AnsiConsole.WriteLine();
AnsiConsole.Render(table);
}
private static IRenderable GetColorTable()
{
var colorTable = new Table().Collapse().HideHeaders().NoBorder();
colorTable.AddColumn("Desc", c => c.PadRight(3)).AddColumn("Colors", c => c.PadRight(0));
colorTable.AddRow(
new Markup(
"✓ [bold grey]NO_COLOR support[/]\n" +
"✓ [bold green]3-bit color[/]\n" +
"✓ [bold blue]4-bit color[/]\n" +
"✓ [bold purple]8-bit color[/]\n" +
"✓ [bold yellow]Truecolor (16.7 million)[/]\n" +
"✓ [bold aqua]Automatic color conversion[/]"),
new ColorBox(height: 6));
return colorTable;
}
private static IRenderable GetTextGrid()
{
var loremTable = new Grid();
var lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque in metus sed sapien ultricies pretium a at justo. Maecenas luctus velit et auctor maximus.";
loremTable.AddColumn(new GridColumn().LeftAligned());
loremTable.AddColumn(new GridColumn().Centered());
loremTable.AddColumn(new GridColumn().RightAligned());
loremTable.AddRow($"[green]{lorem}[/]", $"[yellow]{lorem}[/]", $"[blue]{lorem}[/]");
return loremTable;
}
private static IRenderable GetTreeTable()
{
var tree = new Tree("📁 src");
tree.AddNode("📁 foo").AddNode("📄 bar.cs");
tree.AddNode("📁 baz").AddNode("📁 qux").AddNode("📄 corgi.txt");
tree.AddNode("📄 waldo.xml");
var table = new Table().SimpleBorder().BorderColor(Color.Grey);
table.AddColumn(new TableColumn("Overview"));
table.AddColumn(new TableColumn("").Footer("[grey]3 Files, 225 KiB[/]"));
table.AddRow(new Markup("[yellow]Files[/]"), tree);
return new Table().RoundedBorder().Collapse().BorderColor(Color.Yellow)
.AddColumn("Foo").AddColumn("Bar")
.AddRow(new Text("Baz"), table)
.AddRow("Qux", "Corgi");
}
private static IRenderable GetBarChart()
{
return new BarChart()
.AddItem("Apple", 32, Color.Green)
.AddItem("Oranges", 13, Color.Orange1)
.AddItem("Bananas", 22, Color.Yellow);
}
private static IRenderable GetBreakdownChart()
{
return new BreakdownChart()
.ShowPercentage()
.FullSize()
.AddItem("C#", 82, Color.Green)
.AddItem("PowerShell", 13, Color.Red)
.AddItem("Bash", 5, Color.Blue);
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<ExampleTitle>Showcase</ExampleTitle>
<ExampleDescription>Demonstation of Spectre.Console.</ExampleDescription>
<ExampleGroup>Misc</ExampleGroup>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,6 @@
using System.Threading;
using Spectre.Console;
namespace ProgressExample
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -13,7 +13,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using Spectre.Console;
namespace TableExample
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,6 +1,4 @@
using Spectre.Console;
namespace TableExample
namespace Spectre.Console.Examples
{
public static class Program
{

View File

@@ -9,7 +9,7 @@
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
<ProjectReference Include="..\..\Shared\Shared.csproj" />
</ItemGroup>
</Project>

124
examples/Shared/ColorBox.cs Normal file
View File

@@ -0,0 +1,124 @@
using System;
using System.Collections.Generic;
using Spectre.Console.Rendering;
namespace Spectre.Console.Examples
{
public sealed class ColorBox : Renderable
{
private readonly int _height;
private int? _width;
public ColorBox(int height)
{
_height = height;
}
public ColorBox(int width, int height)
: this(height)
{
_width = width;
}
protected override Measurement Measure(RenderContext context, int maxWidth)
{
return new Measurement(1, GetWidth(maxWidth));
}
protected override IEnumerable<Segment> Render(RenderContext context, int maxWidth)
{
maxWidth = GetWidth(maxWidth);
for (var y = 0; y < _height; y++)
{
for (var x = 0; x < maxWidth; x++)
{
var h = x / (float)maxWidth;
var l = 0.1f + ((y / (float)_height) * 0.7f);
var (r1, g1, b1) = ColorFromHSL(h, l, 1.0f);
var (r2, g2, b2) = ColorFromHSL(h, l + (0.7f / 10), 1.0f);
var background = new Color((byte)(r1 * 255), (byte)(g1 * 255), (byte)(b1 * 255));
var foreground = new Color((byte)(r2 * 255), (byte)(g2 * 255), (byte)(b2 * 255));
yield return new Segment("▄", new Style(foreground, background));
}
yield return Segment.LineBreak;
}
}
private int GetWidth(int maxWidth)
{
var width = maxWidth;
if (_width != null)
{
width = Math.Min(_width.Value, width);
}
return width;
}
private static (float, float, float) ColorFromHSL(double h, double l, double s)
{
double r = 0, g = 0, b = 0;
if (l != 0)
{
if (s == 0)
{
r = g = b = l;
}
else
{
double temp2;
if (l < 0.5)
{
temp2 = l * (1.0 + s);
}
else
{
temp2 = l + s - (l * s);
}
var temp1 = 2.0 * l - temp2;
r = GetColorComponent(temp1, temp2, h + 1.0 / 3.0);
g = GetColorComponent(temp1, temp2, h);
b = GetColorComponent(temp1, temp2, h - 1.0 / 3.0);
}
}
return ((float)r, (float)g, (float)b);
}
private static double GetColorComponent(double temp1, double temp2, double temp3)
{
if (temp3 < 0.0)
{
temp3 += 1.0;
}
else if (temp3 > 1.0)
{
temp3 -= 1.0;
}
if (temp3 < 1.0 / 6.0)
{
return temp1 + (temp2 - temp1) * 6.0 * temp3;
}
else if (temp3 < 0.5)
{
return temp2;
}
else if (temp3 < 2.0 / 3.0)
{
return temp1 + ((temp2 - temp1) * ((2.0 / 3.0) - temp3) * 6.0);
}
else
{
return temp1;
}
}
}
}

View File

@@ -0,0 +1,15 @@
namespace Spectre.Console.Examples
{
public static class ColorExtensions
{
public static Color GetInvertedColor(this Color color)
{
return GetLuminance(color) < 140 ? Color.White : Color.Black;
}
private static float GetLuminance(this Color color)
{
return (float)((0.2126 * color.R) + (0.7152 * color.G) + (0.0722 * color.B));
}
}
}

View File

@@ -0,0 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net5.0</TargetFramework>
<ExampleVisible>false</ExampleVisible>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,7 +1,7 @@
{
"projects": [ "src" ],
"sdk": {
"version": "5.0.100",
"version": "5.0.202",
"rollForward": "latestPatch"
}
}

Some files were not shown because too many files have changed in this diff Show More