mirror of
https://github.com/spectreconsole/spectre.console.git
synced 2025-10-25 15:19:23 +00:00
Compare commits
62 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4dda283bb | ||
|
|
da9c6ee4c2 | ||
|
|
855127f32a | ||
|
|
fa731070d8 | ||
|
|
ef08c5bf2b | ||
|
|
1c769c6610 | ||
|
|
1cd335e785 | ||
|
|
29e6e34f83 | ||
|
|
bff3438a5a | ||
|
|
c64884854f | ||
|
|
3a42c0a119 | ||
|
|
525b414ff8 | ||
|
|
ed0fb29be4 | ||
|
|
04d0e663d5 | ||
|
|
17ee8990f4 | ||
|
|
a1050fc676 | ||
|
|
9312663bde | ||
|
|
102e2dc38d | ||
|
|
28e9c14de4 | ||
|
|
fd217ffc83 | ||
|
|
95ec04df40 | ||
|
|
705cf745ea | ||
|
|
b64e016e8c | ||
|
|
58400fe74e | ||
|
|
e20f6284f9 | ||
|
|
953008b5e3 | ||
|
|
ad49b6aa67 | ||
|
|
31a5e17a45 | ||
|
|
f06dc7e7d8 | ||
|
|
a23bec4082 | ||
|
|
913a7b1e37 | ||
|
|
63bae278a9 | ||
|
|
1a747696a8 | ||
|
|
994540d97f | ||
|
|
dee3c01629 | ||
|
|
a3e11b24e5 | ||
|
|
35568ab823 | ||
|
|
07db28bb6f | ||
|
|
d87d8e4422 | ||
|
|
a977fdadff | ||
|
|
8261b25e5c | ||
|
|
0e0f4b4220 | ||
|
|
3a593857c8 | ||
|
|
11e192e750 | ||
|
|
8901450283 | ||
|
|
0796bad598 | ||
|
|
5b553a4106 | ||
|
|
1bb0b9ccc6 | ||
|
|
9ad5f2daeb | ||
|
|
1f211d3e1f | ||
|
|
87e6b42409 | ||
|
|
1aa958ced3 | ||
|
|
4bfb24bfcb | ||
|
|
b136d0299b | ||
|
|
179e243214 | ||
|
|
c6210f75ca | ||
|
|
b81739567b | ||
|
|
5cf41725a5 | ||
|
|
f561d71e4e | ||
|
|
e71db7f78c | ||
|
|
79742ce9e3 | ||
|
|
241423dd16 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -79,7 +79,6 @@ x64/
|
||||
_ReSharper*
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
_NCrunch_*
|
||||
|
||||
|
||||
161
CONTRIBUTING.md
Normal file
161
CONTRIBUTING.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# Contribution Guidelines
|
||||
|
||||
* [Prerequisites](#prerequisites)
|
||||
* [Definition of trivial contributions](#definition-of-trivial-contributions)
|
||||
* [Code](#code)
|
||||
* [Code style](#code-style)
|
||||
* [Dependencies](#dependencies)
|
||||
* [Unit tests](#unit-tests)
|
||||
* [Contributing process](#contributing-process)
|
||||
* [Get buyoff or find open community issues or features](#get-buyoff-or-find-open-community-issues-or-features)
|
||||
* [Set up your environment](#Set-up-your-environment)
|
||||
* [Prepare commits](#prepare-commits)
|
||||
* [Submit pull request](#Submit-pull-request)
|
||||
* [Respond to feedback on pull request](#respond-to-feedback-on-pull-request)
|
||||
* [Other general information](#other-general-information)
|
||||
* [Acknowledgement](#acknowledgement)
|
||||
|
||||
## Prerequisites
|
||||
|
||||
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).
|
||||
|
||||
## Definition of trivial contributions
|
||||
It's hard to define what is a trivial contribution. Sometimes even a 1 character change can be considered significant.
|
||||
Unfortunately because it can be subjective, the decision on what is trivial comes from the maintainers of the project
|
||||
and not from folks contributing to the project.
|
||||
|
||||
What is generally considered trivial:
|
||||
|
||||
* Fixing a typo.
|
||||
* Documentation changes.
|
||||
|
||||
## Code
|
||||
### Code style
|
||||
|
||||
Normal .NET coding guidelines apply.
|
||||
See the [Framework Design Guidelines](https://msdn.microsoft.com/en-us/library/ms229042%28v=vs.110%29.aspx) for more information.
|
||||
|
||||
### Dependencies
|
||||
|
||||
The assembly `Spectre.Console` should have no dependencies except the .NET BCL library.
|
||||
|
||||
### Unit tests
|
||||
|
||||
Make sure to run all unit tests before creating a pull request.
|
||||
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),
|
||||
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,
|
||||
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.
|
||||
* 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:
|
||||
* No reformatting
|
||||
* No changing files that are not specific to the feature.
|
||||
* More covered below in the **Prepare commits** section.
|
||||
* Test your changes and please help us out by updating and implementing some automated tests.
|
||||
It is recommended that all contributors spend some time looking over the tests in the source code.
|
||||
You can't go wrong emulating one of the existing tests and then changing it specific to the behavior you are testing.
|
||||
* Please do not update your branch from the main branch unless we ask you to. See the responding to feedback section below.
|
||||
|
||||
### Prepare commits
|
||||
This section serves to help you understand what makes a good commit.
|
||||
|
||||
A commit should observe the following:
|
||||
|
||||
* A commit is a small logical unit that represents a change.
|
||||
* Should include new or changed tests relevant to the changes you are making.
|
||||
* No unnecessary whitespace. Check for whitespace with `git diff --check` and `git diff --cached --check` before commit.
|
||||
* You can stage parts of a file for commit.
|
||||
|
||||
### Submit pull request
|
||||
Prerequisites:
|
||||
|
||||
* You are making commits in a feature branch.
|
||||
* All code should compile without errors or warnings.
|
||||
* All tests should be passing.
|
||||
|
||||
Submitting PR:
|
||||
|
||||
* Once you feel it is ready, submit the pull request to the `spectresystems/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
|
||||
interested in if the changes are taking things in a direction the maintainers do not want to go.
|
||||
* In the pull request, outline what you did and point to specific conversations (as in URLs)
|
||||
and issues that you are resolving. This is a tremendous help for us in evaluation and acceptance.
|
||||
* Once the pull request is in, please do not delete the branch or close the pull request
|
||||
(unless something is wrong with it).
|
||||
* One of the Spectre.Console team members, or one of the maintainers, will evaluate it within a
|
||||
reasonable time period (which is to say usually within 1-3 weeks). Some things get evaluated
|
||||
faster or fast tracked. We are human and we have active lives outside of open source so don't
|
||||
fret if you haven't seen any activity on your pull request within a month or two.
|
||||
We don't have a Service Level Agreement (SLA) for pull requests.
|
||||
Just know that we will evaluate your pull request.
|
||||
|
||||
### Respond to feedback on pull request
|
||||
|
||||
We may have feedback for you to fix or change some things. We generally like to see that pushed against
|
||||
the same topic branch (it will automatically update the Pull Request). You can also fix/squash/rebase
|
||||
commits and push the same topic branch with `--force` (it's generally acceptable to do this on topic
|
||||
branches not in the main repository, it is generally unacceptable and should be avoided at all costs
|
||||
against the main repository).
|
||||
|
||||
If we have comments or questions when we do evaluate it and receive no response, it will probably
|
||||
lessen the chance of getting accepted. Eventually, this means it will be closed if it is not accepted.
|
||||
Please know this doesn't mean we don't value your contribution, just that things go stale. If in the
|
||||
future you want to pick it back up, feel free to address our concerns/questions/feedback and reopen
|
||||
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 checkout main`
|
||||
* `git rebase upstream/main`
|
||||
* `git checkout your-branch`
|
||||
* `git rebase main`
|
||||
* Fix any merge conflicts
|
||||
* `git push origin your-branch` (origin would be your GitHub repo or `your-github-username/spectre.console` in this case).
|
||||
You may need to `git push origin your-branch --force` to get the commits pushed.
|
||||
This is generally acceptable with topic branches not in the mainstream repository.
|
||||
|
||||
The only reasons a pull request should be closed and resubmitted are as follows:
|
||||
|
||||
* When the pull request is targeting the wrong branch (this doesn't happen as often).
|
||||
* When there are updates made to the original by someone other than the original contributor.
|
||||
Then the old branch is closed with a note on the newer branch this supersedes #github_number.
|
||||
|
||||
## Other general information
|
||||
If you reformat code or hit core functionality without an approval from a person on the Spectre.Console Team,
|
||||
it's likely that no matter how awesome it looks afterwards, it will probably not get accepted.
|
||||
Reformatting code makes it harder for us to evaluate exactly what was changed.
|
||||
|
||||
If you do these things, it will be make evaluation and acceptance easy.
|
||||
Now if you stray outside of the guidelines we have above, it doesn't mean we are going to ignore
|
||||
your pull request. It will just make things harder for us.
|
||||
Harder for us roughly translates to a longer SLA for your pull request.
|
||||
|
||||
## Acknowledgement
|
||||
|
||||
This contribution guide was taken from the [Chocolatey project](https://chocolatey.org/)
|
||||
with permission and was edited to follow Spectre.Console's conventions and processes.
|
||||
77
README.fa.md
Normal file
77
README.fa.md
Normal file
@@ -0,0 +1,77 @@
|
||||
# `Spectre.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-بیت در ترمینال.
|
||||
این کتابخانه توانایی ترمینال فعلی را تشخیص داده و در صورت لزوم رنگها را کاهش میدهد.
|
||||
|
||||
|
||||

|
||||
|
||||
<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://spectresystems.github.io/spectre.console/
|
||||
</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 © Spectre Systems.
|
||||
</div>
|
||||
|
||||
همانطور که Spectre.Console تحت مجوز MIT ارائه شده است؛ برای کسب اطلاعات بیشتر به مجوز مراجعه کنید.
|
||||
|
||||
* برای SixLabors.ImageSharp، مشاهده کنید: https://github.com/SixLabors/ImageSharp/blob/master/LICENSE
|
||||
|
||||
</div>
|
||||
@@ -29,7 +29,7 @@ Python用の素晴らしい[Rich ライブラリ](https://github.com/willmcgugan
|
||||
|
||||
## 例
|
||||
|
||||

|
||||

|
||||
|
||||
## 使用方法
|
||||
|
||||
@@ -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. │
|
||||
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
|
||||
21
README.md
21
README.md
@@ -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.
|
||||
|
||||
|
||||

|
||||

|
||||
|
||||
## Installing
|
||||
|
||||
@@ -63,6 +64,24 @@ 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)
|
||||
|
||||
I really appreciate it.
|
||||
**Thank you very much!**
|
||||
|
||||
## License
|
||||
|
||||
Copyright © Spectre Systems.
|
||||
|
||||
@@ -7,7 +7,7 @@ To start contributing to the [Spectre.Console](https://github.com/spectresystems
|
||||
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,13 +29,7 @@ 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
|
||||
|
||||
|
||||
BIN
docs/input/assets/images/example.png
Normal file
BIN
docs/input/assets/images/example.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 219 KiB |
BIN
docs/input/assets/images/multiselection.gif
Normal file
BIN
docs/input/assets/images/multiselection.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 229 KiB |
BIN
docs/input/assets/images/selection.gif
Normal file
BIN
docs/input/assets/images/selection.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 208 KiB |
BIN
docs/input/assets/images/tree.png
Normal file
BIN
docs/input/assets/images/tree.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
@@ -58,17 +58,19 @@ 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;
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -114,4 +116,4 @@ This make the resulting code very clean and easy to navigate, not to mention to
|
||||
And most importantly at all, the type system guides me to do the right thing. I can't configure
|
||||
commands in non-compatible ways, and if I want to add a new top-level `add-package` command
|
||||
(or move the command completely), it's just a single line to change. This makes it easy to
|
||||
experiment and makes the CLI experience a first class citizen of your application.
|
||||
experiment and makes the CLI experience a first class citizen of your application.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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%;" />
|
||||
|
||||
@@ -63,6 +63,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
|
||||
|
||||
12
docs/input/prompts/index.cshtml
Normal file
12
docs/input/prompts/index.cshtml
Normal file
@@ -0,0 +1,12 @@
|
||||
Title: Prompts
|
||||
Order: 5
|
||||
---
|
||||
|
||||
<h1>Sections</h1>
|
||||
|
||||
<ul>
|
||||
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
|
||||
{
|
||||
<li>@Html.DocumentLink(child)</li>
|
||||
}
|
||||
</ul>
|
||||
31
docs/input/prompts/multiselection.md
Normal file
31
docs/input/prompts/multiselection.md
Normal file
@@ -0,0 +1,31 @@
|
||||
Title: Multi Selection
|
||||
Order: 3
|
||||
---
|
||||
|
||||
The `MultiSelectionPrompt` can be used when you want the user to select
|
||||
one or many items from a provided list.
|
||||
|
||||
<img src="../assets/images/multiselection.gif" style="width: 100%;" />
|
||||
|
||||
# Usage
|
||||
|
||||
```csharp
|
||||
// Ask for the user's favorite fruits
|
||||
var fruits = AnsiConsole.Prompt(
|
||||
new MultiSelectionPrompt<string>()
|
||||
.Title("What are your [green]favorite fruits[/]?")
|
||||
.NotRequired() // Not required to have a favorite fruit
|
||||
.PageSize(10)
|
||||
.AddChoice("Apple")
|
||||
.AddChoices(new[] {
|
||||
"Apricot", "Avocado",
|
||||
"Banana", "Blackcurrant", "Blueberry",
|
||||
"Cherry", "Cloudberry", "Cocunut",
|
||||
}));
|
||||
|
||||
// Write the selected fruits to the terminal
|
||||
foreach (string fruit in fruits)
|
||||
{
|
||||
AnsiConsole.WriteLine(fruit);
|
||||
}
|
||||
```
|
||||
27
docs/input/prompts/selection.md
Normal file
27
docs/input/prompts/selection.md
Normal file
@@ -0,0 +1,27 @@
|
||||
Title: Selection
|
||||
Order: 1
|
||||
---
|
||||
|
||||
The `SelectionPrompt` can be used when you want the user to select
|
||||
a single item from a provided list.
|
||||
|
||||
<img src="../assets/images/selection.gif" style="width: 100%;" />
|
||||
|
||||
# Usage
|
||||
|
||||
```csharp
|
||||
// Ask for the user's favorite fruit
|
||||
var fruit = AnsiConsole.Prompt(
|
||||
new SelectionPrompt<string>()
|
||||
.Title("What's your [green]favorite fruit[/]?")
|
||||
.PageSize(10)
|
||||
.AddChoice("Apple")
|
||||
.AddChoices(new[] {
|
||||
"Apricot", "Avocado",
|
||||
"Banana", "Blackcurrant", "Blueberry",
|
||||
"Cherry", "Cloudberry", "Cocunut",
|
||||
}));
|
||||
|
||||
// Echo the fruit back to the terminal
|
||||
AnsiConsole.WriteLine($"I agree. {fruit} is tasty!");
|
||||
```
|
||||
@@ -1,5 +1,6 @@
|
||||
Title: Prompt
|
||||
Order: 4
|
||||
Title: Text
|
||||
Order: 0
|
||||
RedirectFrom: prompt
|
||||
---
|
||||
|
||||
Sometimes you want to get some input from the user, and for this
|
||||
19
docs/input/sponsors.md
Normal file
19
docs/input/sponsors.md
Normal file
@@ -0,0 +1,19 @@
|
||||
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)
|
||||
|
||||
I really appreciate it.
|
||||
**Thank you very much!**
|
||||
@@ -1,5 +1,5 @@
|
||||
Title: Bar Chart
|
||||
Order: 1
|
||||
Order: 20
|
||||
---
|
||||
|
||||
Use `BarChart` to render bar charts to the console.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Title: Calendar
|
||||
Order: 3
|
||||
Order: 40
|
||||
RedirectFrom: calendar
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Title: Canvas Image
|
||||
Order: 6
|
||||
Order: 70
|
||||
---
|
||||
|
||||
To add [ImageSharp](https://github.com/SixLabors/ImageSharp) superpowers to
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Title: Canvas
|
||||
Order: 5
|
||||
Order: 60
|
||||
---
|
||||
|
||||
`Canvas` is a widget that allows you to render arbitrary "pixels"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Title: Figlet
|
||||
Order: 4
|
||||
Order: 50
|
||||
RedirectFrom: figlet
|
||||
---
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Title: Rule
|
||||
Order: 2
|
||||
Order: 30
|
||||
RedirectFrom: rule
|
||||
---
|
||||
|
||||
|
||||
70
docs/input/widgets/tree.md
Normal file
70
docs/input/widgets/tree.md
Normal file
@@ -0,0 +1,70 @@
|
||||
Title: Tree
|
||||
Order: 10
|
||||
---
|
||||
|
||||
The `Tree` widget can be used to render hierarchical data.
|
||||
|
||||
<img src="../assets/images/tree.png" style="width: 100%;" />
|
||||
|
||||
# Usage
|
||||
|
||||
```csharp
|
||||
// Create the tree
|
||||
var tree = new Tree("Root");
|
||||
|
||||
// Add some nodes
|
||||
var foo = tree.AddNode("[yellow]Foo[/]");
|
||||
var table = foo.AddNode(new Table()
|
||||
.RoundedBorder()
|
||||
.AddColumn("First")
|
||||
.AddColumn("Second")
|
||||
.AddRow("1", "2")
|
||||
.AddRow("3", "4")
|
||||
.AddRow("5", "6"));
|
||||
|
||||
table.AddNode("[blue]Baz[/]");
|
||||
foo.AddNode("Qux");
|
||||
|
||||
var bar = tree.AddNode("[yellow]Bar[/]");
|
||||
bar.AddNode(new Calendar(2020, 12)
|
||||
.AddCalendarEvent(2020, 12, 12)
|
||||
.HideHeader());
|
||||
|
||||
// Render the tree
|
||||
AnsiConsole.Render(root);
|
||||
```
|
||||
|
||||
# Collapsing nodes
|
||||
|
||||
```csharp
|
||||
root.AddNode("Label").Collapsed();
|
||||
```
|
||||
|
||||
# Appearance
|
||||
|
||||
## Style
|
||||
|
||||
```csharp
|
||||
var root = new Tree("Root")
|
||||
.Style("white on red");
|
||||
```
|
||||
|
||||
## Guide lines
|
||||
|
||||
```csharp
|
||||
// ASCII guide lines
|
||||
var root = new Tree("Root")
|
||||
.Guide(TreeGuide.Ascii);
|
||||
|
||||
// Default guide lines
|
||||
var root = new Tree("Root")
|
||||
.Guide(TreeGuide.Line);
|
||||
|
||||
// Double guide lines
|
||||
var root = new Tree("Root")
|
||||
.Guide(TreeGuide.DoubleLine);
|
||||
|
||||
// Bold guide lines
|
||||
var root = new Tree("Root")
|
||||
.Guide(TreeGuide.BoldLine);
|
||||
```
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
35
examples/Cli/Logging/Commands/HelloCommand.cs
Normal file
35
examples/Cli/Logging/Commands/HelloCommand.cs
Normal file
@@ -0,0 +1,35 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Logging.Commands
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
56
examples/Cli/Logging/Commands/LogCommandSettings.cs
Normal file
56
examples/Cli/Logging/Commands/LogCommandSettings.cs
Normal 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 Logging.Commands
|
||||
{
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
20
examples/Cli/Logging/Infrastructure/LogInterceptor.cs
Normal file
20
examples/Cli/Logging/Infrastructure/LogInterceptor.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using Logging.Commands;
|
||||
using Serilog.Core;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Logging
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
38
examples/Cli/Logging/Infrastructure/LoggingEnricher.cs
Normal file
38
examples/Cli/Logging/Infrastructure/LoggingEnricher.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Serilog.Core;
|
||||
using Serilog.Events;
|
||||
|
||||
namespace Logging
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
41
examples/Cli/Logging/Infrastructure/TypeRegistrar.cs
Normal file
41
examples/Cli/Logging/Infrastructure/TypeRegistrar.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Logging
|
||||
{
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
21
examples/Cli/Logging/Infrastructure/TypeResolver.cs
Normal file
21
examples/Cli/Logging/Infrastructure/TypeResolver.cs
Normal file
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Logging
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
26
examples/Cli/Logging/Logging.csproj
Normal file
26
examples/Cli/Logging/Logging.csproj
Normal 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="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
54
examples/Cli/Logging/Program.cs
Normal file
54
examples/Cli/Logging/Program.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using Logging.Commands;
|
||||
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 Logging
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<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>
|
||||
@@ -14,9 +14,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="cake.png">
|
||||
<EmbeddedResource Include="cake.png">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</EmbeddedResource>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Rendering;
|
||||
@@ -23,6 +25,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)
|
||||
|
||||
@@ -1,21 +1,42 @@
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace InfoExample
|
||||
namespace Charts
|
||||
{
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace ColorExample
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
if (AnsiConsole.Capabilities.ColorSystem == ColorSystem.NoColors)
|
||||
if (AnsiConsole.Profile.ColorSystem == ColorSystem.NoColors)
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// No colors
|
||||
@@ -16,7 +16,7 @@ namespace ColorExample
|
||||
return;
|
||||
}
|
||||
|
||||
if (AnsiConsole.Capabilities.Supports(ColorSystem.Legacy))
|
||||
if (AnsiConsole.Profile.Supports(ColorSystem.Legacy))
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 3-BIT
|
||||
@@ -39,7 +39,7 @@ namespace ColorExample
|
||||
}
|
||||
}
|
||||
|
||||
if (AnsiConsole.Capabilities.Supports(ColorSystem.Standard))
|
||||
if (AnsiConsole.Profile.Supports(ColorSystem.Standard))
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 4-BIT
|
||||
@@ -62,7 +62,7 @@ namespace ColorExample
|
||||
}
|
||||
}
|
||||
|
||||
if (AnsiConsole.Capabilities.Supports(ColorSystem.EightBit))
|
||||
if (AnsiConsole.Profile.Supports(ColorSystem.EightBit))
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 8-BIT
|
||||
@@ -89,7 +89,7 @@ namespace ColorExample
|
||||
}
|
||||
}
|
||||
|
||||
if (AnsiConsole.Capabilities.Supports(ColorSystem.TrueColor))
|
||||
if (AnsiConsole.Profile.Supports(ColorSystem.TrueColor))
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 24-BIT
|
||||
|
||||
@@ -9,12 +9,16 @@ 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.ColorSystem}")
|
||||
.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]TTY?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Tty)}")
|
||||
.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)
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace LinkExample
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
if (AnsiConsole.Capabilities.SupportLinks)
|
||||
if (AnsiConsole.Profile.Capabilities.Links)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[link=https://patriksvensson.se]Click to visit my blog[/]!");
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Cursor
|
||||
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;
|
||||
@@ -20,26 +20,87 @@ namespace Cursor
|
||||
return;
|
||||
}
|
||||
|
||||
// String
|
||||
// Ask the user for some different things
|
||||
var name = AskName();
|
||||
var fruit = AskFruit();
|
||||
var sport = AskSport();
|
||||
var age = AskAge();
|
||||
var password = AskPassword();
|
||||
var color = AskColor();
|
||||
|
||||
// Summary
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Render(new Rule("[yellow]Results[/]").RuleStyle("grey").LeftAligned());
|
||||
AnsiConsole.Render(new Table().AddColumns("[grey]Question[/]", "[grey]Answer[/]")
|
||||
.RoundedBorder()
|
||||
.BorderColor(Color.Grey)
|
||||
.AddRow("[grey]Name[/]", name)
|
||||
.AddRow("[grey]Favorite fruit[/]", fruit)
|
||||
.AddRow("[grey]Favorite sport[/]", sport)
|
||||
.AddRow("[grey]Age[/]", age.ToString())
|
||||
.AddRow("[grey]Password[/]", password)
|
||||
.AddRow("[grey]Favorite color[/]", string.IsNullOrEmpty(color) ? "Unknown" : color));
|
||||
}
|
||||
|
||||
private static string AskName()
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Render(new Rule("[yellow]Strings[/]").RuleStyle("grey").LeftAligned());
|
||||
var name = AnsiConsole.Ask<string>("What's your [green]name[/]?");
|
||||
return name;
|
||||
}
|
||||
|
||||
// String with choices
|
||||
private static string AskFruit()
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Render(new Rule("[yellow]Lists[/]").RuleStyle("grey").LeftAligned());
|
||||
|
||||
var favorites = AnsiConsole.Prompt(
|
||||
new MultiSelectionPrompt<string>()
|
||||
.PageSize(10)
|
||||
.Title("What are your [green]favorite fruits[/]?")
|
||||
.AddChoices(new[]
|
||||
{
|
||||
"Apple", "Apricot", "Avocado", "Banana", "Blackcurrant", "Blueberry",
|
||||
"Cherry", "Cloudberry", "Cocunut", "Date", "Dragonfruit", "Durian",
|
||||
"Egg plant", "Elderberry", "Fig", "Grape", "Guava", "Honeyberry",
|
||||
"Jackfruit", "Jambul", "Kiwano", "Kiwifruit", "Lime", "Lylo",
|
||||
"Lychee", "Melon", "Mulberry", "Nectarine", "Orange", "Olive"
|
||||
}));
|
||||
|
||||
var fruit = favorites.Count == 1 ? favorites[0] : null;
|
||||
if (string.IsNullOrWhiteSpace(fruit))
|
||||
{
|
||||
fruit = AnsiConsole.Prompt(
|
||||
new SelectionPrompt<string>()
|
||||
.Title("Ok, but if you could only choose [green]one[/]?")
|
||||
.AddChoices(favorites));
|
||||
}
|
||||
|
||||
AnsiConsole.MarkupLine("Your selected: [yellow]{0}[/]", fruit);
|
||||
return fruit;
|
||||
}
|
||||
|
||||
private static string AskSport()
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Render(new Rule("[yellow]Choices[/]").RuleStyle("grey").LeftAligned());
|
||||
var fruit = AnsiConsole.Prompt(
|
||||
new TextPrompt<string>("What's your [green]favorite fruit[/]?")
|
||||
.InvalidChoiceMessage("[red]That's not a valid fruit[/]")
|
||||
.DefaultValue("Orange")
|
||||
.AddChoice("Apple")
|
||||
.AddChoice("Banana")
|
||||
.AddChoice("Orange"));
|
||||
|
||||
// Integer
|
||||
return AnsiConsole.Prompt(
|
||||
new TextPrompt<string>("What's your [green]favorite sport[/]?")
|
||||
.InvalidChoiceMessage("[red]That's not a valid fruit[/]")
|
||||
.DefaultValue("Lol")
|
||||
.AddChoice("Soccer")
|
||||
.AddChoice("Hockey")
|
||||
.AddChoice("Basketball"));
|
||||
}
|
||||
|
||||
private static int AskAge()
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Render(new Rule("[yellow]Integers[/]").RuleStyle("grey").LeftAligned());
|
||||
var age = AnsiConsole.Prompt(
|
||||
|
||||
return AnsiConsole.Prompt(
|
||||
new TextPrompt<int>("How [green]old[/] are you?")
|
||||
.PromptStyle("green")
|
||||
.ValidationErrorMessage("[red]That's not a valid age[/]")
|
||||
@@ -52,33 +113,27 @@ namespace Cursor
|
||||
_ => ValidationResult.Success(),
|
||||
};
|
||||
}));
|
||||
}
|
||||
|
||||
// Secret
|
||||
private static string AskPassword()
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Render(new Rule("[yellow]Secrets[/]").RuleStyle("grey").LeftAligned());
|
||||
var password = AnsiConsole.Prompt(
|
||||
|
||||
return AnsiConsole.Prompt(
|
||||
new TextPrompt<string>("Enter [green]password[/]?")
|
||||
.PromptStyle("red")
|
||||
.Secret());
|
||||
}
|
||||
|
||||
// Optional
|
||||
private static string AskColor()
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Render(new Rule("[yellow]Optional[/]").RuleStyle("grey").LeftAligned());
|
||||
var color = AnsiConsole.Prompt(
|
||||
|
||||
return AnsiConsole.Prompt(
|
||||
new TextPrompt<string>("[grey][[Optional]][/] What is your [green]favorite color[/]?")
|
||||
.AllowEmpty());
|
||||
|
||||
// Summary
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Render(new Rule("[yellow]Results[/]").RuleStyle("grey").LeftAligned());
|
||||
AnsiConsole.Render(new Table().AddColumns("[grey]Question[/]", "[grey]Answer[/]")
|
||||
.RoundedBorder()
|
||||
.BorderColor(Color.Grey)
|
||||
.AddRow("[grey]Name[/]", name)
|
||||
.AddRow("[grey]Favorite fruit[/]", fruit)
|
||||
.AddRow("[grey]Age[/]", age.ToString())
|
||||
.AddRow("[grey]Password[/]", password)
|
||||
.AddRow("[grey]Favorite color[/]", string.IsNullOrEmpty(color) ? "Unknown" : color));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
45
examples/Console/Trees/Program.cs
Normal file
45
examples/Console/Trees/Program.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using Spectre.Console;
|
||||
|
||||
namespace TableExample
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
// Render the tree
|
||||
var tree = BuildTree();
|
||||
AnsiConsole.Render(tree);
|
||||
}
|
||||
|
||||
private static Tree BuildTree()
|
||||
{
|
||||
// Create the tree
|
||||
var tree = new Tree("Root")
|
||||
.Style(Style.Parse("red"))
|
||||
.Guide(TreeGuide.BoldLine);
|
||||
|
||||
// Add some nodes
|
||||
var foo = tree.AddNode("[yellow]Foo[/]");
|
||||
var table = foo.AddNode(new Table()
|
||||
.RoundedBorder()
|
||||
.AddColumn("First")
|
||||
.AddColumn("Second")
|
||||
.AddRow("1", "2")
|
||||
.AddRow("3", "4")
|
||||
.AddRow("5", "6"));
|
||||
|
||||
table.AddNode("[blue]Baz[/]");
|
||||
foo.AddNode("Qux");
|
||||
|
||||
var bar = tree.AddNode("[yellow]Bar[/]");
|
||||
bar.AddNode(new Calendar(2020, 12)
|
||||
.AddCalendarEvent(2020, 12, 12)
|
||||
.HideHeader());
|
||||
|
||||
// Return the tree
|
||||
return tree;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
examples/Console/Trees/Trees.csproj
Normal file
15
examples/Console/Trees/Trees.csproj
Normal file
@@ -0,0 +1,15 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<ExampleTitle>Trees</ExampleTitle>
|
||||
<ExampleDescription>Demonstrates how to render trees in a console.</ExampleDescription>
|
||||
<ExampleGroup>Widgets</ExampleGroup>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 247 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
@@ -19,4 +19,4 @@ if(!$?) {
|
||||
Pop-Location
|
||||
|
||||
# Copy the files to the correct location
|
||||
Copy-Item (Join-Path "$Output" "Spinner.Generated.cs") -Destination "$Source/Progress/Spinner.Generated.cs"
|
||||
Copy-Item (Join-Path "$Output" "Spinner.Generated.cs") -Destination "$Source/Widgets/Progress/Spinner.Generated.cs"
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Generated {{ date.now | date.to_string `%F %R` }}
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Generated {{ date.now | date.to_string `%F %R` }}
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@@ -10,7 +9,7 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
namespace Spectre.Console
|
||||
{
|
||||
internal static partial class ColorPalette
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Generated {{ date.now | date.to_string `%F %R` }}
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
@@ -11,7 +10,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
namespace Spectre.Console
|
||||
{
|
||||
internal static partial class ColorTable
|
||||
{
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Generated {{ date.now | date.to_string `%F %R` }}
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Generated {{ date.now | date.to_string `%F %R` }}
|
||||
//
|
||||
// Partly generated from
|
||||
// https://github.com/sindresorhus/cli-spinners/blob/master/spinners.json
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using SixLabors.ImageSharp.PixelFormats;
|
||||
using SixLabors.ImageSharp.Processing;
|
||||
using SixLabors.ImageSharp.Processing.Processors.Transforms;
|
||||
@@ -51,6 +52,24 @@ namespace Spectre.Console
|
||||
Image = SixLabors.ImageSharp.Image.Load<Rgba32>(filename);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CanvasImage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Buffer containing an image.</param>
|
||||
public CanvasImage(ReadOnlySpan<byte> data)
|
||||
{
|
||||
Image = SixLabors.ImageSharp.Image.Load<Rgba32>(data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CanvasImage"/> class.
|
||||
/// </summary>
|
||||
/// <param name="data">Stream containing an image.</param>
|
||||
public CanvasImage(Stream data)
|
||||
{
|
||||
Image = SixLabors.ImageSharp.Image.Load<Rgba32>(data);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Measurement Measure(RenderContext context, int maxWidth)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netstandard2.0</TargetFrameworks>
|
||||
<TargetFrameworks>net5.0;netstandard2.0</TargetFrameworks>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>true</IsPackable>
|
||||
<Description>A library that extends Spectre.Console with ImageSharp superpowers.</Description>
|
||||
|
||||
@@ -7,6 +7,9 @@ dotnet_diagnostic.CS1591.severity = none
|
||||
# SA1600: Elements should be documented
|
||||
dotnet_diagnostic.SA1600.severity = none
|
||||
|
||||
# SA1200: Using directives should be placed correctly
|
||||
dotnet_diagnostic.SA1200.severity = none
|
||||
|
||||
# Default severity for analyzer diagnostics with category 'StyleCop.CSharp.OrderingRules'
|
||||
dotnet_analyzer_diagnostic.category-StyleCop.CSharp.OrderingRules.severity = none
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using Spectre.Console.Rendering;
|
||||
|
||||
namespace Spectre.Console.Testing
|
||||
@@ -13,10 +12,7 @@ namespace Spectre.Console.Testing
|
||||
|
||||
public string Output => _writer.ToString();
|
||||
|
||||
public Capabilities Capabilities => _console.Capabilities;
|
||||
public Encoding Encoding => _console.Encoding;
|
||||
public int Width { get; }
|
||||
public int Height => _console.Height;
|
||||
public Profile Profile => _console.Profile;
|
||||
public IAnsiConsoleCursor Cursor => _console.Cursor;
|
||||
public FakeConsoleInput Input { get; }
|
||||
public RenderPipeline Pipeline => _console.Pipeline;
|
||||
@@ -24,21 +20,26 @@ namespace Spectre.Console.Testing
|
||||
IAnsiConsoleInput IAnsiConsole.Input => Input;
|
||||
|
||||
public FakeAnsiConsole(
|
||||
ColorSystem system, AnsiSupport ansi = AnsiSupport.Yes,
|
||||
InteractionSupport interaction = InteractionSupport.Yes,
|
||||
ColorSystem system,
|
||||
AnsiSupport ansi = AnsiSupport.Yes,
|
||||
int width = 80)
|
||||
{
|
||||
_writer = new StringWriter();
|
||||
_console = AnsiConsole.Create(new AnsiConsoleSettings
|
||||
|
||||
var factory = new AnsiConsoleFactory();
|
||||
_console = factory.Create(new AnsiConsoleSettings
|
||||
{
|
||||
Ansi = ansi,
|
||||
ColorSystem = (ColorSystemSupport)system,
|
||||
Interactive = interaction,
|
||||
Out = _writer,
|
||||
LinkIdentityGenerator = new FakeLinkIdentityGenerator(1024),
|
||||
Enrichment = new ProfileEnrichment
|
||||
{
|
||||
UseDefaultEnrichers = false,
|
||||
},
|
||||
});
|
||||
|
||||
Width = width;
|
||||
_console.Profile.Width = width;
|
||||
|
||||
Input = new FakeConsoleInput();
|
||||
}
|
||||
|
||||
|
||||
@@ -9,24 +9,13 @@ namespace Spectre.Console.Testing
|
||||
{
|
||||
public sealed class FakeConsole : IAnsiConsole, IDisposable
|
||||
{
|
||||
public Capabilities Capabilities { get; }
|
||||
public Encoding Encoding { get; }
|
||||
public Profile Profile { get; }
|
||||
public IAnsiConsoleCursor Cursor => new FakeAnsiConsoleCursor();
|
||||
public FakeConsoleInput Input { get; }
|
||||
|
||||
public int Width { get; }
|
||||
public int Height { get; }
|
||||
|
||||
IAnsiConsoleInput IAnsiConsole.Input => Input;
|
||||
public RenderPipeline Pipeline { get; }
|
||||
|
||||
public Decoration Decoration { get; set; }
|
||||
public Color Foreground { get; set; }
|
||||
public Color Background { get; set; }
|
||||
public string Link { get; set; }
|
||||
|
||||
public StringWriter Writer { get; }
|
||||
public string Output => Writer.ToString();
|
||||
public FakeConsoleInput Input { get; }
|
||||
public string Output => Profile.Out.ToString();
|
||||
public IReadOnlyList<string> Lines => Output.TrimEnd('\n').Split(new char[] { '\n' });
|
||||
|
||||
public FakeConsole(
|
||||
@@ -34,18 +23,22 @@ namespace Spectre.Console.Testing
|
||||
bool supportsAnsi = true, ColorSystem colorSystem = ColorSystem.Standard,
|
||||
bool legacyConsole = false, bool interactive = true)
|
||||
{
|
||||
Capabilities = new Capabilities(supportsAnsi, colorSystem, legacyConsole, interactive);
|
||||
Encoding = encoding ?? Encoding.UTF8;
|
||||
Width = width;
|
||||
Height = height;
|
||||
Writer = new StringWriter();
|
||||
Input = new FakeConsoleInput();
|
||||
Pipeline = new RenderPipeline();
|
||||
|
||||
Profile = new Profile(new StringWriter(), encoding ?? Encoding.UTF8);
|
||||
Profile.Width = width;
|
||||
Profile.Height = height;
|
||||
Profile.ColorSystem = colorSystem;
|
||||
Profile.Capabilities.Ansi = supportsAnsi;
|
||||
Profile.Capabilities.Legacy = legacyConsole;
|
||||
Profile.Capabilities.Interactive = interactive;
|
||||
Profile.Capabilities.Links = true;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Writer.Dispose();
|
||||
Profile.Out.Dispose();
|
||||
}
|
||||
|
||||
public void Clear(bool home)
|
||||
@@ -61,7 +54,7 @@ namespace Spectre.Console.Testing
|
||||
|
||||
foreach (var segment in segments)
|
||||
{
|
||||
Writer.Write(segment.Text);
|
||||
Profile.Out.Write(segment.Text);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
namespace Spectre.Console.Testing
|
||||
{
|
||||
public sealed class FakeLinkIdentityGenerator : ILinkIdentityGenerator
|
||||
{
|
||||
private readonly int _linkId;
|
||||
|
||||
public FakeLinkIdentityGenerator(int linkId)
|
||||
{
|
||||
_linkId = linkId;
|
||||
}
|
||||
|
||||
public int GenerateId(string link, string text)
|
||||
{
|
||||
return _linkId;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,19 @@ namespace Spectre.Console.Testing
|
||||
}
|
||||
}
|
||||
|
||||
public void RegisterLazy(Type service, Func<object> factory)
|
||||
{
|
||||
if (factory is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(factory));
|
||||
}
|
||||
|
||||
if (!Instances.ContainsKey(service))
|
||||
{
|
||||
Instances.Add(service, new List<object> { factory() });
|
||||
}
|
||||
}
|
||||
|
||||
public ITypeResolver Build()
|
||||
{
|
||||
return _resolver;
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<ProjectConfiguration>
|
||||
<Settings>
|
||||
<XUnit2Enabled>False</XUnit2Enabled>
|
||||
</Settings>
|
||||
</ProjectConfiguration>
|
||||
@@ -7,6 +7,12 @@ dotnet_analyzer_diagnostic.category-StyleCop.CSharp.DocumentationRules.severity
|
||||
# CA1707: Identifiers should not contain underscores
|
||||
dotnet_diagnostic.CA1707.severity = none
|
||||
|
||||
# SA1600: Elements should be documented
|
||||
dotnet_diagnostic.SA1600.severity = none
|
||||
|
||||
# SA1601: Partial elements should be documented
|
||||
dotnet_diagnostic.SA1601.severity = none
|
||||
|
||||
# SA1200: Using directives should be placed correctly
|
||||
dotnet_diagnostic.SA1200.severity = none
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests
|
||||
{
|
||||
public static class Constants
|
||||
@@ -5,15 +7,15 @@ namespace Spectre.Console.Tests
|
||||
public static string[] VersionCommand { get; } =
|
||||
new[]
|
||||
{
|
||||
Spectre.Console.Cli.Internal.Constants.Commands.Branch,
|
||||
Spectre.Console.Cli.Internal.Constants.Commands.Version,
|
||||
CliConstants.Commands.Branch,
|
||||
CliConstants.Commands.Version,
|
||||
};
|
||||
|
||||
public static string[] XmlDocCommand { get; } =
|
||||
new[]
|
||||
{
|
||||
Spectre.Console.Cli.Internal.Constants.Commands.Branch,
|
||||
Spectre.Console.Cli.Internal.Constants.Commands.XmlDoc,
|
||||
CliConstants.Commands.Branch,
|
||||
CliConstants.Commands.XmlDoc,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class DumpRemainingCommand : Command<EmptyCommandSettings>
|
||||
{
|
||||
private readonly IAnsiConsole _console;
|
||||
|
||||
public DumpRemainingCommand(IAnsiConsole console)
|
||||
{
|
||||
_console = console;
|
||||
}
|
||||
|
||||
public override int Execute([NotNull] CommandContext context, [NotNull] EmptyCommandSettings settings)
|
||||
{
|
||||
if (context.Remaining.Raw.Count > 0)
|
||||
{
|
||||
_console.WriteLine("# Raw");
|
||||
foreach (var item in context.Remaining.Raw)
|
||||
{
|
||||
_console.WriteLine(item);
|
||||
}
|
||||
}
|
||||
|
||||
if (context.Remaining.Parsed.Count > 0)
|
||||
{
|
||||
_console.WriteLine("# Parsed");
|
||||
foreach (var item in context.Remaining.Parsed)
|
||||
{
|
||||
_console.WriteLine(string.Format("{0}={1}", item.Key, string.Join(",", item.Select(x => x))));
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
using System;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class InterceptingCommand<TSettings> : Command<TSettings>
|
||||
where TSettings : CommandSettings
|
||||
{
|
||||
private readonly Action<CommandContext, TSettings> _action;
|
||||
|
||||
public InterceptingCommand(Action<CommandContext, TSettings> action)
|
||||
{
|
||||
_action = action ?? throw new ArgumentNullException(nameof(action));
|
||||
}
|
||||
|
||||
public override int Execute(CommandContext context, TSettings settings)
|
||||
{
|
||||
_action(context, settings);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class NoDescriptionCommand : Command<EmptyCommandSettings>
|
||||
{
|
||||
[CommandOption("-f|--foo <VALUE>")]
|
||||
public int Foo { get; set; }
|
||||
|
||||
public override int Execute([NotNull] CommandContext context, [NotNull] EmptyCommandSettings settings)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,11 @@
|
||||
using System;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public static class TestExceptions
|
||||
{
|
||||
[SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "<Pending>")]
|
||||
public static bool MethodThatThrows(int? number) => throw new InvalidOperationException("Throwing!");
|
||||
|
||||
[SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "<Pending>")]
|
||||
public static bool GenericMethodThatThrows<T0, T1, TRet>(int? number) => throw new InvalidOperationException("Throwing!");
|
||||
|
||||
public static void ThrowWithInnerException()
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
{
|
||||
public sealed class ArgumentOrderSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "[QUX]")]
|
||||
public int Qux { get; set; }
|
||||
|
||||
[CommandArgument(3, "<CORGI>")]
|
||||
public int Corgi { get; set; }
|
||||
|
||||
[CommandArgument(1, "<BAR>")]
|
||||
public int Bar { get; set; }
|
||||
|
||||
[CommandArgument(2, "<BAZ>")]
|
||||
public int Baz { get; set; }
|
||||
|
||||
[CommandArgument(0, "<FOO>")]
|
||||
public int Foo { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
@@ -6,7 +5,6 @@ namespace Spectre.Console.Tests.Data
|
||||
public class ArgumentVectorSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<Foos>")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public string[] Foo { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
@@ -6,18 +5,15 @@ namespace Spectre.Console.Tests.Data
|
||||
public class MultipleArgumentVectorSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<Foos>")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public string[] Foo { get; set; }
|
||||
|
||||
[CommandArgument(0, "<Bars>")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public string[] Bar { get; set; }
|
||||
}
|
||||
|
||||
public class MultipleArgumentVectorSpecifiedFirstSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<Foos>")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public string[] Foo { get; set; }
|
||||
|
||||
[CommandArgument(1, "<Bar>")]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Tests.Data
|
||||
@@ -6,11 +5,9 @@ namespace Spectre.Console.Tests.Data
|
||||
public class OptionVectorSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--foo")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public string[] Foo { get; set; }
|
||||
|
||||
[CommandOption("--bar")]
|
||||
[SuppressMessage("Performance", "CA1819:Properties should not return arrays")]
|
||||
public int[] Bar { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Hello World
|
||||
@@ -1,3 +0,0 @@
|
||||
Greeting
|
||||
Hello World
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user