Compare commits
222 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5a9c0ca26 | ||
|
|
23564612c1 | ||
|
|
f2b8afffb3 | ||
|
|
3e2eea730b | ||
|
|
bc9f610258 | ||
|
|
ae96606ab7 | ||
|
|
41ccc0b464 | ||
|
|
3545e0f6b5 | ||
|
|
2fe2bb3c32 | ||
|
|
1fc6f22ea9 | ||
|
|
6a5c507936 | ||
|
|
efa3d3b130 | ||
|
|
6007fcaafc | ||
|
|
13ac38ed04 | ||
|
|
ca036f6543 | ||
|
|
36ec3d1fd3 | ||
|
|
fe5096dceb | ||
|
|
39b59c8d4a | ||
|
|
8cf7794852 | ||
|
|
4edc647fdd | ||
|
|
be45a0ff4e | ||
|
|
256fcdd27f | ||
|
|
dafbfe63ba | ||
|
|
a2ab522516 | ||
|
|
8778ab1739 | ||
|
|
693e1fa170 | ||
|
|
4b37a4708f | ||
|
|
a690ce4955 | ||
|
|
759b16aed9 | ||
|
|
254880e93a | ||
|
|
6f16081f42 | ||
|
|
6121203fee | ||
|
|
9204671b27 | ||
|
|
c765bbd0dd | ||
|
|
6bceac8a5e | ||
|
|
1ed7e65fcb | ||
|
|
20650f1e7e | ||
|
|
2ba6da3514 | ||
|
|
8830779875 | ||
|
|
9c46c21e27 | ||
|
|
c643ec735d | ||
|
|
b17eabaa1f | ||
|
|
7f6f2437b1 | ||
|
|
c2bab0ebf8 | ||
|
|
9502aaf2b9 | ||
|
|
57a8e6ccc1 | ||
|
|
8c099a0038 | ||
|
|
08b65cfa47 | ||
|
|
2540f48622 | ||
|
|
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 | ||
|
|
4e2251fd62 | ||
|
|
0ae419326d | ||
|
|
0bbf9b81a9 | ||
|
|
041aea2ae5 | ||
|
|
f417e297cd | ||
|
|
5045b8b959 | ||
|
|
7dccb310f3 | ||
|
|
1cf30f62fc | ||
|
|
e280b82679 | ||
|
|
6932c95731 | ||
|
|
ee305702e8 | ||
|
|
63abcc92ba | ||
|
|
acf01e056f | ||
|
|
501db5d287 | ||
|
|
cbed41e637 | ||
|
|
3c504155bc | ||
|
|
ae32785f21 | ||
|
|
c61e386440 | ||
|
|
b7cd7dd53e | ||
|
|
3e1251b86a | ||
|
|
01fdbac51e | ||
|
|
b0b988a1e7 | ||
|
|
2a9fa223de | ||
|
|
4f6eca4fcb | ||
|
|
a5125d640c | ||
|
|
a59e0dcb21 | ||
|
|
bde61cc6ff | ||
|
|
5c33b87a9c | ||
|
|
aaf77c3b25 | ||
|
|
d70ad661fc | ||
|
|
0d209d8f18 | ||
|
|
380c6aca45 | ||
|
|
b1da5e7ba8 | ||
|
|
be3350a411 | ||
|
|
a1d11e9d0c | ||
|
|
93d1971f48 | ||
|
|
bca1c889d1 | ||
|
|
9915a0d6a8 | ||
|
|
f34fc43d00 | ||
|
|
e7f497050c | ||
|
|
3e5e22d6c2 | ||
|
|
10daf727e9 | ||
|
|
03334f693d | ||
|
|
c9c0ad733f | ||
|
|
041bd016a2 | ||
|
|
037a215a78 | ||
|
|
9afc1ea721 | ||
|
|
b52056ee49 | ||
|
|
3941fd81ab | ||
|
|
5a1b8a1710 | ||
|
|
1410cba6c5 | ||
|
|
70fc14e9cd | ||
|
|
0b4359a52a | ||
|
|
cb2924a609 | ||
|
|
5c119ee0c3 | ||
|
|
b9d182b6e3 | ||
|
|
bfffef630f | ||
|
|
a2f507e58f | ||
|
|
d1d06d6a6b | ||
|
|
52718c499c | ||
|
|
7ef1ac483a | ||
|
|
c0875c912a | ||
|
|
3f2ca49071 | ||
|
|
0a0380ae0a | ||
|
|
ae92c606bb | ||
|
|
68e92f3365 | ||
|
|
39a8588dc3 | ||
|
|
3c3afe7439 | ||
|
|
971f9032ba | ||
|
|
5149557560 | ||
|
|
e0947708c9 | ||
|
|
b1db8a9403 | ||
|
|
a2f8652575 | ||
|
|
672faa131f | ||
|
|
e429f6434b | ||
|
|
93ec7401c8 | ||
|
|
697273917e | ||
|
|
2943535973 | ||
|
|
cd0d182f12 | ||
|
|
b197f278ed | ||
|
|
3847a8949f | ||
|
|
eeb3f967b6 | ||
|
|
090b30f731 | ||
|
|
df291ef84e | ||
|
|
7d6104ace4 | ||
|
|
314456ca17 | ||
|
|
b7f654cd7f | ||
|
|
fea8a36e8a | ||
|
|
0632b38477 | ||
|
|
a7b7d4e556 | ||
|
|
11d331e31d | ||
|
|
ce670a7ca9 | ||
|
|
101e244059 | ||
|
|
504746c5dc | ||
|
|
1601ef24b3 | ||
|
|
b46d0fa4f6 | ||
|
|
4f06687104 | ||
|
|
003e15686f | ||
|
|
3e9796849b | ||
|
|
3cc19520b0 | ||
|
|
87bde3e5a2 | ||
|
|
e6e9a4d950 | ||
|
|
29ce14e1e8 | ||
|
|
ceb3572d6a | ||
|
|
13c56eca01 | ||
|
|
a477884d36 | ||
|
|
ae6d2c63a3 | ||
|
|
e946289bd9 | ||
|
|
bcaaa6b2d3 | ||
|
|
d3588a4b06 | ||
|
|
7471e9d38c |
28
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
title: ''
|
||||
labels: bug
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Information**
|
||||
- OS: [eg Windows/Linux/MacOS]
|
||||
- Version: [e.g. 0.33.0]
|
||||
- Terminal: [e.g Windows Terminal]
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Steps to reproduce the behavior.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Screenshots**
|
||||
If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
title: ''
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
||||
27
.github/workflows/ci.yaml
vendored
@@ -21,7 +21,7 @@ jobs:
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '3.1.301' # SDK Version to use.
|
||||
dotnet-version: 5.0.202
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -55,23 +55,32 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup dotnet
|
||||
- name: Setup dotnet 3.1.402
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 3.1.301
|
||||
dotnet-version: 3.1.402
|
||||
|
||||
- name: Setup dotnet 5.0.100
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.202
|
||||
|
||||
- name: Integration Tests
|
||||
shell: bash
|
||||
run: |
|
||||
dotnet tool restore
|
||||
dotnet example diagnostic
|
||||
dotnet example table
|
||||
dotnet example grid
|
||||
dotnet example panel
|
||||
dotnet example colors
|
||||
dotnet example --all
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
dotnet tool restore
|
||||
dotnet cake
|
||||
dotnet cake
|
||||
|
||||
- name: Upload Verify Test Results
|
||||
if: failure()
|
||||
uses: actions/upload-artifact@v2
|
||||
with:
|
||||
name: verify-test-results
|
||||
path: |
|
||||
**/*.received.*
|
||||
2
.github/workflows/docs.yaml
vendored
@@ -24,7 +24,7 @@ jobs:
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '3.1.301' # SDK Version to use.
|
||||
dotnet-version: 5.0.202
|
||||
|
||||
- name: Publish
|
||||
shell: bash
|
||||
|
||||
20
.github/workflows/publish.yaml
vendored
@@ -29,7 +29,7 @@ jobs:
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '3.1.301' # SDK Version to use.
|
||||
dotnet-version: 5.0.202
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -64,10 +64,15 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup dotnet
|
||||
- name: Setup dotnet 3.1.402
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 3.1.301
|
||||
dotnet-version: 3.1.402
|
||||
|
||||
- name: Setup dotnet 5.0.100
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.202
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
@@ -90,10 +95,15 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup dotnet
|
||||
- name: Setup dotnet 3.1.402
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 3.1.301
|
||||
dotnet-version: 3.1.402
|
||||
|
||||
- name: Setup dotnet 5.0.100
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: 5.0.202
|
||||
|
||||
- name: Publish
|
||||
shell: bash
|
||||
|
||||
5
.gitignore
vendored
@@ -5,6 +5,8 @@
|
||||
[Pp]ackages/
|
||||
/.artifacts/
|
||||
/[Tt]ools/
|
||||
.idea
|
||||
.DS_Store
|
||||
|
||||
# Cakeup
|
||||
cakeup-x86_64-latest.exe
|
||||
@@ -77,7 +79,6 @@ x64/
|
||||
_ReSharper*
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
.*crunch*.local.xml
|
||||
_NCrunch_*
|
||||
|
||||
@@ -86,3 +87,5 @@ packages
|
||||
|
||||
# Windows
|
||||
Thumbs.db
|
||||
|
||||
*.received.*
|
||||
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/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.
|
||||
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/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/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 `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:
|
||||
* 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 `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
|
||||
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 `spectreconsole/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.
|
||||
@@ -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
@@ -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
@@ -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://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>
|
||||
414
README.jp.md
Normal file
@@ -0,0 +1,414 @@
|
||||
# `Spectre.Console`
|
||||
|
||||
_[](https://www.nuget.org/packages/spectre.console)_
|
||||
|
||||
綺麗なコンソールアプリケーションを簡単に作成するための.NET Standard 2.0ライブラリです。
|
||||
Python用の素晴らしい[Rich ライブラリ](https://github.com/willmcgugan/rich)に強く影響を受けています。
|
||||
|
||||
## 目次
|
||||
|
||||
1. [特徴](#特徴)
|
||||
2. [例](#例)
|
||||
3. [使用方法](#使用方法)
|
||||
3.1. [Static APIの利用](#static-apiの利用)
|
||||
3.2. [コンソールの作成](#コンソールの作成)
|
||||
4. [例の実行](#例の実行)
|
||||
5. [クイックスタート](#クイックスタート)
|
||||
6. [マークアップ](#マークアップ)
|
||||
7. [絵文字](#絵文字)
|
||||
8. [テーブル](#テーブル)
|
||||
9. [例外](#例外)
|
||||
|
||||
## 特徴
|
||||
|
||||
* ユニットテストを意識して書いています。
|
||||
* table、grid、panel、マークアップ言語に影響を受けた [rich](https://github.com/willmcgugan/rich) に対応しています。
|
||||
* 太字、薄字、斜字、下線、斜線、点滅などの一般的なSGR parameters に対応しています。
|
||||
* ターミナルで 3/4/8/24ビットカラーに対応しています。
|
||||
ライブラリは現在のターミナルの性能を検知し、必要なカラーにダウングレードします
|
||||
|
||||
## 例
|
||||
|
||||

|
||||
|
||||
## 使用方法
|
||||
|
||||
`Spectre.Console` APIはステートフルで、スレッドセーフではありません。
|
||||
異なるスレッドからコンソールに書く必要がある場合、通常の`System.Console` APIを使用するときと同様、適切な注意を払ってください。
|
||||
|
||||
現在の端末がANSIエスケープシーケンスに対応していない場合、
|
||||
`Spectre.Console`は、`System.Console` APIの利用に切り替わります。
|
||||
|
||||
_メモ: このライブラリは現在開発中で、APIは1.0のリリースまでの間に変更されたり、
|
||||
削除されたりする可能性があります。_
|
||||
|
||||
### Static APIの利用
|
||||
|
||||
|
||||
`System.Console` APIでするように、テキストを出力したいだけの時にはstatic APIが最適ですが、綺麗です。
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Foreground = Color.CornflowerBlue;
|
||||
AnsiConsole.Decoration = Decoration.Underline | Decoration.Bold;
|
||||
AnsiConsole.WriteLine("Hello World!");
|
||||
|
||||
AnsiConsole.Reset();
|
||||
AnsiConsole.MarkupLine("[bold yellow on red]{0}[/] [underline]world[/]!", "Goodbye");
|
||||
```
|
||||
|
||||
もし、デフォルトの`IAnsiConsole`への参照を取得したい場合、
|
||||
`AnsiConsole.Console`経由でアクセスできます。
|
||||
|
||||
### コンソールの作成
|
||||
|
||||
単体テスト中にコードの実行環境を制御したい場合など、
|
||||
特定の機能をもつコンソールを明示的に作成すると便利なことがあります。
|
||||
|
||||
単体テストの一部としてコードで `AnsiConsole`を使わないことを推奨します。
|
||||
|
||||
```csharp
|
||||
IAnsiConsole console = AnsiConsole.Create(
|
||||
new AnsiConsoleSettings()
|
||||
{
|
||||
Ansi = AnsiSupport.Yes,
|
||||
ColorSystem = ColorSystemSupport.TrueColor,
|
||||
Out = new StringWriter(),
|
||||
});
|
||||
```
|
||||
|
||||
_メモ: 主導でコンソールを作成しているときに特定のカラーシステムを指定できたとしても、
|
||||
ユーザーのターミナルでは使えないかもしれないことを覚えておいてください。
|
||||
テスト用にIAnsiConsoleを作成していない限り、
|
||||
常に`ColorSystemSupport.Detect` と `AnsiSupport.Detect`を使用してください。_
|
||||
|
||||
## 例の実行
|
||||
|
||||
Spectre.Consoleでできることを見るために、
|
||||
[dotnet-example](https://github.com/patriksvensson/dotnet-example)グローバルツールをインストールします。
|
||||
|
||||
|
||||
```
|
||||
> dotnet tool restore
|
||||
```
|
||||
|
||||
このリポジトリで提供している例が一覧表示されます
|
||||
|
||||
```
|
||||
> dotnet example
|
||||
|
||||
╭────────────┬───────────────────────────────────────┬──────────────────────────────────────────────────────╮
|
||||
│ Name │ Path │ Description │
|
||||
├────────────┼───────────────────────────────────────┼──────────────────────────────────────────────────────┤
|
||||
│ Borders │ examples/Borders/Borders.csproj │ Demonstrates the different kind of borders. │
|
||||
│ Calendars │ examples/Calendars/Calendars.csproj │ Demonstrates how to render calendars. │
|
||||
│ Colors │ examples/Colors/Colors.csproj │ Demonstrates how to use colors in the console. │
|
||||
│ Columns │ examples/Columns/Columns.csproj │ Demonstrates how to render data into columns. │
|
||||
│ Emojis │ examples/Emojis/Emojis.csproj │ Demonstrates how to render emojis. │
|
||||
│ Exceptions │ examples/Exceptions/Exceptions.csproj │ Demonstrates how to render formatted exceptions. │
|
||||
│ Grids │ examples/Grids/Grids.csproj │ Demonstrates how to render grids in a console. │
|
||||
│ Info │ examples/Info/Info.csproj │ Displays the capabilities of the current console. │
|
||||
│ Links │ examples/Links/Links.csproj │ Demonstrates how to render links in a 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. │
|
||||
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
そして、例を実行します
|
||||
|
||||
```
|
||||
> dotnet example tables
|
||||
┌──────────┬──────────┬────────┐
|
||||
│ Foo │ Bar │ Baz │
|
||||
├──────────┼──────────┼────────┤
|
||||
│ Hello │ World! │ │
|
||||
│ Bonjour │ le │ monde! │
|
||||
│ Hej │ Världen! │ │
|
||||
└──────────┴──────────┴────────┘
|
||||
```
|
||||
|
||||
## クイックスタート
|
||||
pectre.Consoleの利用を開始する最初の方法は、Nugetパッケージをインストールすることです。
|
||||
|
||||
```shell
|
||||
> dotnet add package Spectre.Console
|
||||
```
|
||||
|
||||
その後、`Spectre.Console`名前空間を参照する必要があります。一度参照したら、提供されている全ての機能を使用できます。
|
||||
|
||||
```csharp
|
||||
using Spectre.Console
|
||||
|
||||
public static class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
AnsiConsole.Markup("[underline red]Hello[/] World!");
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## マークアップ
|
||||
`Markup`クラスは、コンソールにリッチなテキストを出力することができます。
|
||||
|
||||
### 文法
|
||||
|
||||
コンソールマークアップはbbcodeに影響を受けた文法を利用します。角括弧でスタイルを書いたら(スタイルを参照)、例えば、`[bold red]`
|
||||
は、`[/]`で閉じるまでスタイルが適用されます。
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Render(new Markup("[bold yellow]Hello[/] [red]World![/]"));
|
||||
```
|
||||
|
||||
`Markup` クラスは`IRenderable`を実装しており、table、grid、Panelを使用できることを意味します。
|
||||
`IRenderable`のレンダリングに対応している多くのクラスは、リッチテキストの描画を上書きます。
|
||||
|
||||
```csharp
|
||||
var table = new Table();
|
||||
table.AddColumn(new TableColumn(new Markup("[yellow]Foo[/]")));
|
||||
table.AddColumn(new TableColumn("[blue]Bar[/]"));
|
||||
```
|
||||
|
||||
### 便利なメソッド
|
||||
|
||||
`AnsiConsole`には、新しい`Markup`インスタンスをインスタンス化することなく、コンソールにマークアップテキストを書き込める便利なメソッドがあります。
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("[underline green]Hello[/] ");
|
||||
AnsiConsole.MarkupLine("[bold]World[/]");
|
||||
```
|
||||
|
||||
### エスケープ文字列
|
||||
|
||||
`[`を出力するために、 `[[`を利用し、`]`を出力するために`]]`を利用します。
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("[[Hello]] "); // [Hello]
|
||||
AnsiConsole.Markup("[red][[World]][/]"); // [World]
|
||||
```
|
||||
|
||||
`SafeMarkup`拡張メソッドを使用することもできます。
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("[red]{0}[/]", "Hello [World]".SafeMarkup());
|
||||
```
|
||||
|
||||
### カラー
|
||||
|
||||
`new Style(foreground: Color.Maroon)`のようなコード、または、`AnsiConsole.Markup("[maroon on blue]Hello[/]")`のようなマークアップテキストで色を使用できます。
|
||||
|
||||
### 背景色の設定
|
||||
|
||||
カラー指定の際に、`on`を付けることで、マークアップで背景色を設定できます。
|
||||
|
||||
```
|
||||
[bold yellow on blue]Hello[/]
|
||||
[default on blue]World[/]
|
||||
```
|
||||
|
||||
### 絵文字の描画
|
||||
|
||||
マークアップの一部として絵文字を出力するために、emojiショートコードが使用できます。
|
||||
|
||||
```csharp
|
||||
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
|
||||
```
|
||||
|
||||
emojiのスタイルについては、付録の[Emoji](./appendix/emojis) を参照してください。
|
||||
|
||||
### カラー
|
||||
|
||||
上の例では、全ての色は名前で参照されています。
|
||||
しかし、16進数やRGB表現をマークダウンで色指定に使用できます。
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("[red]Foo[/] ");
|
||||
AnsiConsole.Markup("[#ff0000]Bar[/] ");
|
||||
AnsiConsole.Markup("[rgb(255,0,0)]Baz[/] ");
|
||||
```
|
||||
|
||||
## 絵文字
|
||||
|
||||
どのような絵文字が使用できるかは、使用しているOSやターミナルに依存し、どのように表示されるかは保証されません。絵文字の幅計算は正確ではないため、表、パネル、グリッドで使用する場合は表示がずれるかもしれません。
|
||||
|
||||
完全な互換性を確保するために、Unicode 13.0 より以前の`Emoji_Presentation`カテゴリにあるものだけを使用することを検討してください。
|
||||
公式の絵文字一覧
|
||||
https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt
|
||||
|
||||
|
||||
```csharp
|
||||
// Markup
|
||||
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
|
||||
|
||||
// Constant
|
||||
var hello = "Hello " + Emoji.Known.GlobeShowingEuropeAfrica;
|
||||
```
|
||||
|
||||
テキスト内の絵文字を置き換えることができます。
|
||||
|
||||
```csharp
|
||||
var phrase = "Mmmm :birthday_cake:";
|
||||
var rendered
|
||||
```
|
||||
|
||||
既存の絵文字を別のものにしたり、完全に新しい物を追加したいことがあります。このために、`Emoji.Remap`メソッドを使用できます。
|
||||
この方法は、マークアップ文字と`Emoji.Replace`の両方で動作します。
|
||||
|
||||
```csharp
|
||||
// Remap the emoji
|
||||
Emoji.Remap("globe_showing_europe_africa", "😄");
|
||||
|
||||
// Render markup
|
||||
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
|
||||
|
||||
// Replace emojis in string
|
||||
var phrase = "Hello :globe_showing_europe_africa:!";
|
||||
var rendered = Emoji.Replace(phrase);
|
||||
```
|
||||
|
||||
## テーブル
|
||||
|
||||
テーブルはターミナルで表データを表示するのに完璧な方法です。
|
||||
`Spectre.Console` は、テーブルの描画にとても優れていて、全てのカラムは中に合わせて調整してくれます。
|
||||
`IRenderable`を実装しているものは、列ヘッダやセル、別のテーブルとして使用できます。
|
||||
|
||||
### 使い方
|
||||
|
||||
テーブルを描画するために、`Table`インスタンスを作成し、必要な数の列を追加し、行を追加します。
|
||||
テーブルをコンソールの`Render`メソッドに渡して終わりです。
|
||||
|
||||
```csharp
|
||||
// テーブルの作成
|
||||
var table = new Table();
|
||||
|
||||
// 列の追加
|
||||
table.AddColumn("Foo");
|
||||
table.AddColumn(new TableColumn("Bar").Centered());
|
||||
|
||||
// 行の追加
|
||||
table.AddRow("Baz", "[green]Qux[/]");
|
||||
table.AddRow(new Markup("[blue]Corgi[/]"), new Panel("Waldo"));
|
||||
|
||||
// コンソールにテーブルの描画
|
||||
AnsiConsole.Render(table);
|
||||
```
|
||||
|
||||
これは次のように出力を描画します。
|
||||
|
||||

|
||||
|
||||
### 罫線
|
||||
|
||||
|
||||
```csharp
|
||||
// 罫線を設定します
|
||||
table.SetBorder(Border.None);
|
||||
table.SetBorder(Border.Ascii);
|
||||
table.SetBorder(Border.Square);
|
||||
table.SetBorder(Border.Rounded);
|
||||
```
|
||||
|
||||
### 拡大 / 縮小
|
||||
|
||||
```csharp
|
||||
// テーブル幅を最大に設定します
|
||||
table.Expand();
|
||||
|
||||
// テーブル幅を最小に設定します
|
||||
table.Collapse();
|
||||
```
|
||||
|
||||
### ヘッダーを隠す
|
||||
|
||||
```csharp
|
||||
// 全ての列のヘッダーを隠します
|
||||
table.HideHeaders();
|
||||
```
|
||||
|
||||
### テーブル幅の設定
|
||||
|
||||
```csharp
|
||||
// テーブル幅50セルに設定します
|
||||
table.SetWidth(50);
|
||||
```
|
||||
|
||||
### 整列(アライメント)
|
||||
|
||||
```csharp
|
||||
// 整列を明示的に設定する
|
||||
column.SetAlignment(Justify.Right);
|
||||
```
|
||||
|
||||
### パディング
|
||||
|
||||
```csharp
|
||||
// 左と右のパディングを設定する
|
||||
column.SetPadding(left: 3, right: 5);
|
||||
|
||||
// 個別にパディングを設定する
|
||||
column.PadLeft(3);
|
||||
column.PadRight(5);
|
||||
```
|
||||
|
||||
### 列改行の無効化
|
||||
|
||||
```csharp
|
||||
// 列改行の無効化
|
||||
column.NoWrap();
|
||||
```
|
||||
|
||||
### 列幅の設定
|
||||
|
||||
```csharp
|
||||
// 列幅の設定(これはまだ柔軟な拡張メソッドがありません)
|
||||
column.Width = 15;
|
||||
```
|
||||
|
||||
## 例外
|
||||
例外はターミナルで見たときに読みやすいとは限りません。
|
||||
`WriteException`メソッドを使用することで、例外をもう少し読みやすくすることができます。
|
||||
|
||||
```csharp
|
||||
AnsiConsole.WriteException(ex);
|
||||
```
|
||||
|
||||

|
||||
### 例外の省略表示
|
||||
|
||||
例外の特定部分を短くして、さらに読みやすくしたり、パスをクリック可能なハイパーリンクにすることもできます。
|
||||
ハイパーリンクがクリックできるかはターミナル次第です。
|
||||
|
||||
|
||||
```csharp
|
||||
AnsiConsole.WriteException(ex,
|
||||
ExceptionFormats.ShortenPaths | ExceptionFormats.ShortenTypes |
|
||||
ExceptionFormats.ShortenMethods | ExceptionFormats.ShowLinks);
|
||||
```
|
||||
|
||||

|
||||
|
||||
### 例外出力のカスタマイズ
|
||||
|
||||
例外の特定部分を短縮するだけでなく、デフォルトのスタイルを上書きすることもできます。
|
||||
|
||||
```csharp
|
||||
AnsiConsole.WriteException(ex, new ExceptionSettings
|
||||
{
|
||||
Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
|
||||
Style = new ExceptionStyle
|
||||
{
|
||||
Exception = Style.WithForeground(Color.Grey),
|
||||
Message = Style.WithForeground(Color.White),
|
||||
NonEmphasized = Style.WithForeground(Color.Cornsilk1),
|
||||
Parenthesis = Style.WithForeground(Color.Cornsilk1),
|
||||
Method = Style.WithForeground(Color.Red),
|
||||
ParameterName = Style.WithForeground(Color.Cornsilk1),
|
||||
ParameterType = Style.WithForeground(Color.Red),
|
||||
Path = Style.WithForeground(Color.Red),
|
||||
LineNumber = Style.WithForeground(Color.Cornsilk1),
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||

|
||||
390
README.md
@@ -2,20 +2,18 @@
|
||||
|
||||
_[](https://www.nuget.org/packages/spectre.console)_
|
||||
|
||||
A .NET Standard 2.0 library that makes it easier to create beautiful console applications.
|
||||
A .NET 5/.NET Standard 2.0 library that makes it easier to create beautiful, cross platform, console applications.
|
||||
It is heavily inspired by the excellent [Rich library](https://github.com/willmcgugan/rich)
|
||||
for Python.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Features](#features)
|
||||
2. [Example](#example)
|
||||
3. [Usage](#usage)
|
||||
3.1. [Using the static API](#using-the-static-api)
|
||||
3.2. [Creating a console](#creating-a-console)
|
||||
4. [Running examples](#running-examples)
|
||||
5. [Available styles](#available-styles)
|
||||
6. [Predefined colors](#predefined-colors)
|
||||
2. [Installing](#installing)
|
||||
3. [Documentation](#documentation)
|
||||
4. [Examples](#examples)
|
||||
5. [Sponsors](#sponsors)
|
||||
5. [License](#license)
|
||||
|
||||
## Features
|
||||
|
||||
@@ -26,377 +24,69 @@ for Python.
|
||||
and blinking text.
|
||||
* Supports 3/4/8/24-bit colors in the terminal.
|
||||
The library will detect the capabilities of the current terminal
|
||||
and downgrade colors as needed.
|
||||
and downgrade colors as needed.
|
||||
|
||||
## Example
|
||||
|
||||

|
||||

|
||||
|
||||
## Usage
|
||||
## Installing
|
||||
|
||||
The `Spectre.Console` API is stateful and is not thread-safe.
|
||||
If you need to write to the console from different threads, make sure that
|
||||
you take appropriate precautions, just like when you use the
|
||||
regular `System.Console` API.
|
||||
|
||||
If the current terminal does not support ANSI escape sequences,
|
||||
`Spectre.Console` will fallback to using the `System.Console` API.
|
||||
|
||||
_NOTE: This library is currently under development and API's
|
||||
might change or get removed at any point up until a 1.0 release._
|
||||
|
||||
### Using the static API
|
||||
|
||||
The static API is perfect when you just want to output text
|
||||
like you usually do with the `System.Console` API, but prettier.
|
||||
The fastest way of getting started using `Spectre.Console` is to install the NuGet package.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Foreground = Color.CornflowerBlue;
|
||||
AnsiConsole.Decoration = Decoration.Underline | Decoration.Bold;
|
||||
AnsiConsole.WriteLine("Hello World!");
|
||||
|
||||
AnsiConsole.Reset();
|
||||
AnsiConsole.MarkupLine("[bold yellow on red]{0}[/] [underline]world[/]!", "Goodbye");
|
||||
dotnet add package Spectre.Console
|
||||
```
|
||||
|
||||
If you want to get a reference to the default `IAnsiConsole`,
|
||||
you can access it via `AnsiConsole.Console`.
|
||||
## Documentation
|
||||
|
||||
### Creating a console
|
||||
The documentation for `Spectre.Console` can be found at
|
||||
https://spectreconsole.net/
|
||||
|
||||
Sometimes it's useful to explicitly create a console with specific
|
||||
capabilities, such as during unit testing when you want control
|
||||
over the environment your code runs in.
|
||||
## Examples
|
||||
|
||||
It's recommended to not use `AnsiConsole` in code that run as
|
||||
part of a unit test.
|
||||
|
||||
```csharp
|
||||
IAnsiConsole console = AnsiConsole.Create(
|
||||
new AnsiConsoleSettings()
|
||||
{
|
||||
Ansi = AnsiSupport.Yes,
|
||||
ColorSystem = ColorSystemSupport.TrueColor,
|
||||
Out = new StringWriter(),
|
||||
});
|
||||
```
|
||||
|
||||
_NOTE: Even if you can specify a specific color system to use
|
||||
when manually creating a console, remember that the user's terminal
|
||||
might not be able to use it, so unless you're creating an IAnsiConsole
|
||||
for testing, always use `ColorSystemSupport.Detect` and `AnsiSupport.Detect`._
|
||||
|
||||
## Running examples
|
||||
|
||||
To see Spectre.Console in action, install the
|
||||
To see `Spectre.Console` in action, install the
|
||||
[dotnet-example](https://github.com/patriksvensson/dotnet-example)
|
||||
global tool.
|
||||
|
||||
```
|
||||
> dotnet tool install -g dotnet-example
|
||||
> dotnet tool restore
|
||||
```
|
||||
|
||||
Now you can list available examples in this repository:
|
||||
|
||||
```
|
||||
> dotnet example
|
||||
|
||||
╭────────┬───────────────────────────────┬─────────────────────────────────────────────────╮
|
||||
│ Name │ Path │ Description │
|
||||
├────────┼───────────────────────────────┼─────────────────────────────────────────────────┤
|
||||
│ Colors │ examples/Colors/Colors.csproj │ Demonstrates how to use colors in the console. │
|
||||
│ Grid │ examples/Grid/Grid.csproj │ Demonstrates how to render grids in a console. │
|
||||
│ Panel │ examples/Panel/Panel.csproj │ Demonstrates how to render items in panels. │
|
||||
│ Table │ examples/Table/Table.csproj │ Demonstrates how to render tables in a console. │
|
||||
╰────────┴───────────────────────────────┴─────────────────────────────────────────────────╯
|
||||
```
|
||||
|
||||
And to run an example:
|
||||
|
||||
```
|
||||
> dotnet example table
|
||||
┌──────────┬──────────┬────────┐
|
||||
│ Foo │ Bar │ Baz │
|
||||
├──────────┼──────────┼────────┤
|
||||
│ Hello │ World! │ │
|
||||
│ Bonjour │ le │ monde! │
|
||||
│ Hej │ Världen! │ │
|
||||
└──────────┴──────────┴────────┘
|
||||
> dotnet example tables
|
||||
```
|
||||
|
||||
## Available styles
|
||||
## Sponsors
|
||||
|
||||
_NOTE: Not all styles are supported in every terminal._
|
||||
The following people are [sponsoring](https://github.com/sponsors/patriksvensson)
|
||||
Spectre.Console to show their support and to ensure the longevity of the project.
|
||||
|
||||
Name | Description
|
||||
--- | ---
|
||||
`bold` | Bold text
|
||||
`dim` | Dim or faint text
|
||||
`italic` | Italic text
|
||||
`underline` | Underlined text
|
||||
`invert` | Swaps the foreground and background colors
|
||||
`conceal` | Hides the text
|
||||
`slowblink` | Makes text blink slowly
|
||||
`rapidblink` | Makes text blink
|
||||
`strikethrough` | Shows text with a horizontal line through the center
|
||||
* [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)
|
||||
|
||||
## Predefined colors
|
||||
I really appreciate it.
|
||||
**Thank you very much!**
|
||||
|
||||
Number | Name | RGB | Hex | System.ConsoleColor
|
||||
--- | --- | --- | --- | ---
|
||||
`0` | `black` | `0,0,0` | `#000000` | `Black`
|
||||
`1` | `maroon` | `128,0,0` | `#800000` | `DarkRed`
|
||||
`2` | `green` | `0,128,0` | `#008000` | `DarkGreen`
|
||||
`3` | `olive` | `128,128,0` | `#808000` | `DarkYellow`
|
||||
`4` | `navy` | `0,0,128` | `#000080` | `DarkBlue`
|
||||
`5` | `purple` | `128,0,128` | `#800080` | `DarkMagenta`
|
||||
`6` | `teal` | `0,128,128` | `#008080` | `DarkCyan`
|
||||
`7` | `silver` | `192,192,192` | `#c0c0c0` | `Gray`
|
||||
`8` | `grey` | `128,128,128` | `#808080` | `DarkGray`
|
||||
`9` | `red` | `255,0,0` | `#ff0000` | `Red`
|
||||
`10` | `lime` | `0,255,0` | `#00ff00` | `Green`
|
||||
`11` | `yellow` | `255,255,0` | `#ffff00` | `Yellow`
|
||||
`12` | `blue` | `0,0,255` | `#0000ff` | `Blue`
|
||||
`13` | `fuchsia` | `255,0,255` | `#ff00ff` | `Magenta`
|
||||
`14` | `aqua` | `0,255,255` | `#00ffff` | `Cyan`
|
||||
`15` | `white` | `255,255,255` | `#ffffff` | `White`
|
||||
`16` | `grey0` | `0,0,0` | `#000000`
|
||||
`17` | `navyblue` | `0,0,95` | `#00005f`
|
||||
`18` | `darkblue` | `0,0,135` | `#000087`
|
||||
`19` | `blue3` | `0,0,175` | `#0000af`
|
||||
`20` | `blue3_1` | `0,0,215` | `#0000d7`
|
||||
`21` | `blue1` | `0,0,255` | `#0000ff`
|
||||
`22` | `darkgreen` | `0,95,0` | `#005f00`
|
||||
`23` | `deepskyblue4` | `0,95,95` | `#005f5f`
|
||||
`24` | `deepskyblue4_1` | `0,95,135` | `#005f87`
|
||||
`25` | `deepskyblue4_2` | `0,95,175` | `#005faf`
|
||||
`26` | `dodgerblue3` | `0,95,215` | `#005fd7`
|
||||
`27` | `dodgerblue2` | `0,95,255` | `#005fff`
|
||||
`28` | `green4` | `0,135,0` | `#008700`
|
||||
`29` | `springgreen4` | `0,135,95` | `#00875f`
|
||||
`30` | `turquoise4` | `0,135,135` | `#008787`
|
||||
`31` | `deepskyblue3` | `0,135,175` | `#0087af`
|
||||
`32` | `deepskyblue3_1` | `0,135,215` | `#0087d7`
|
||||
`33` | `dodgerblue1` | `0,135,255` | `#0087ff`
|
||||
`34` | `green3` | `0,175,0` | `#00af00`
|
||||
`35` | `springgreen3` | `0,175,95` | `#00af5f`
|
||||
`36` | `darkcyan` | `0,175,135` | `#00af87`
|
||||
`37` | `lightseagreen` | `0,175,175` | `#00afaf`
|
||||
`38` | `deepskyblue2` | `0,175,215` | `#00afd7`
|
||||
`39` | `deepskyblue1` | `0,175,255` | `#00afff`
|
||||
`40` | `green3_1` | `0,215,0` | `#00d700`
|
||||
`41` | `springgreen3_1` | `0,215,95` | `#00d75f`
|
||||
`42` | `springgreen2` | `0,215,135` | `#00d787`
|
||||
`43` | `cyan3` | `0,215,175` | `#00d7af`
|
||||
`44` | `darkturquoise` | `0,215,215` | `#00d7d7`
|
||||
`45` | `turquoise2` | `0,215,255` | `#00d7ff`
|
||||
`46` | `green1` | `0,255,0` | `#00ff00`
|
||||
`47` | `springgreen2_1` | `0,255,95` | `#00ff5f`
|
||||
`48` | `springgreen1` | `0,255,135` | `#00ff87`
|
||||
`49` | `mediumspringgreen` | `0,255,175` | `#00ffaf`
|
||||
`50` | `cyan2` | `0,255,215` | `#00ffd7`
|
||||
`51` | `cyan1` | `0,255,255` | `#00ffff`
|
||||
`52` | `darkred` | `95,0,0` | `#5f0000`
|
||||
`53` | `deeppink4` | `95,0,95` | `#5f005f`
|
||||
`54` | `purple4` | `95,0,135` | `#5f0087`
|
||||
`55` | `purple4_1` | `95,0,175` | `#5f00af`
|
||||
`56` | `purple3` | `95,0,215` | `#5f00d7`
|
||||
`57` | `blueviolet` | `95,0,255` | `#5f00ff`
|
||||
`58` | `orange4` | `95,95,0` | `#5f5f00`
|
||||
`59` | `grey37` | `95,95,95` | `#5f5f5f`
|
||||
`60` | `mediumpurple4` | `95,95,135` | `#5f5f87`
|
||||
`61` | `slateblue3` | `95,95,175` | `#5f5faf`
|
||||
`62` | `slateblue3_1` | `95,95,215` | `#5f5fd7`
|
||||
`63` | `royalblue1` | `95,95,255` | `#5f5fff`
|
||||
`64` | `chartreuse4` | `95,135,0` | `#5f8700`
|
||||
`65` | `darkseagreen4` | `95,135,95` | `#5f875f`
|
||||
`66` | `paleturquoise4` | `95,135,135` | `#5f8787`
|
||||
`67` | `steelblue` | `95,135,175` | `#5f87af`
|
||||
`68` | `steelblue3` | `95,135,215` | `#5f87d7`
|
||||
`69` | `cornflowerblue` | `95,135,255` | `#5f87ff`
|
||||
`70` | `chartreuse3` | `95,175,0` | `#5faf00`
|
||||
`71` | `darkseagreen4_1` | `95,175,95` | `#5faf5f`
|
||||
`72` | `cadetblue` | `95,175,135` | `#5faf87`
|
||||
`73` | `cadetblue_1` | `95,175,175` | `#5fafaf`
|
||||
`74` | `skyblue3` | `95,175,215` | `#5fafd7`
|
||||
`75` | `steelblue1` | `95,175,255` | `#5fafff`
|
||||
`76` | `chartreuse3_1` | `95,215,0` | `#5fd700`
|
||||
`77` | `palegreen3` | `95,215,95` | `#5fd75f`
|
||||
`78` | `seagreen3` | `95,215,135` | `#5fd787`
|
||||
`79` | `aquamarine3` | `95,215,175` | `#5fd7af`
|
||||
`80` | `mediumturquoise` | `95,215,215` | `#5fd7d7`
|
||||
`81` | `steelblue1_1` | `95,215,255` | `#5fd7ff`
|
||||
`82` | `chartreuse2` | `95,255,0` | `#5fff00`
|
||||
`83` | `seagreen2` | `95,255,95` | `#5fff5f`
|
||||
`84` | `seagreen1` | `95,255,135` | `#5fff87`
|
||||
`85` | `seagreen1_1` | `95,255,175` | `#5fffaf`
|
||||
`86` | `aquamarine1` | `95,255,215` | `#5fffd7`
|
||||
`87` | `darkslategray2` | `95,255,255` | `#5fffff`
|
||||
`88` | `darkred_1` | `135,0,0` | `#870000`
|
||||
`89` | `deeppink4_1` | `135,0,95` | `#87005f`
|
||||
`90` | `darkmagenta` | `135,0,135` | `#870087`
|
||||
`91` | `darkmagenta_1` | `135,0,175` | `#8700af`
|
||||
`92` | `darkviolet` | `135,0,215` | `#8700d7`
|
||||
`93` | `purple_1` | `135,0,255` | `#8700ff`
|
||||
`94` | `orange4_1` | `135,95,0` | `#875f00`
|
||||
`95` | `lightpink4` | `135,95,95` | `#875f5f`
|
||||
`96` | `plum4` | `135,95,135` | `#875f87`
|
||||
`97` | `mediumpurple3` | `135,95,175` | `#875faf`
|
||||
`98` | `mediumpurple3_1` | `135,95,215` | `#875fd7`
|
||||
`99` | `slateblue1` | `135,95,255` | `#875fff`
|
||||
`100` | `yellow4` | `135,135,0` | `#878700`
|
||||
`101` | `wheat4` | `135,135,95` | `#87875f`
|
||||
`102` | `grey53` | `135,135,135` | `#878787`
|
||||
`103` | `lightslategrey` | `135,135,175` | `#8787af`
|
||||
`104` | `mediumpurple` | `135,135,215` | `#8787d7`
|
||||
`105` | `lightslateblue` | `135,135,255` | `#8787ff`
|
||||
`106` | `yellow4_1` | `135,175,0` | `#87af00`
|
||||
`107` | `darkolivegreen3` | `135,175,95` | `#87af5f`
|
||||
`108` | `darkseagreen` | `135,175,135` | `#87af87`
|
||||
`109` | `lightskyblue3` | `135,175,175` | `#87afaf`
|
||||
`110` | `lightskyblue3_1` | `135,175,215` | `#87afd7`
|
||||
`111` | `skyblue2` | `135,175,255` | `#87afff`
|
||||
`112` | `chartreuse2_1` | `135,215,0` | `#87d700`
|
||||
`113` | `darkolivegreen3_1` | `135,215,95` | `#87d75f`
|
||||
`114` | `palegreen3_1` | `135,215,135` | `#87d787`
|
||||
`115` | `darkseagreen3` | `135,215,175` | `#87d7af`
|
||||
`116` | `darkslategray3` | `135,215,215` | `#87d7d7`
|
||||
`117` | `skyblue1` | `135,215,255` | `#87d7ff`
|
||||
`118` | `chartreuse1` | `135,255,0` | `#87ff00`
|
||||
`119` | `lightgreen` | `135,255,95` | `#87ff5f`
|
||||
`120` | `lightgreen_1` | `135,255,135` | `#87ff87`
|
||||
`121` | `palegreen1` | `135,255,175` | `#87ffaf`
|
||||
`122` | `aquamarine1_1` | `135,255,215` | `#87ffd7`
|
||||
`123` | `darkslategray1` | `135,255,255` | `#87ffff`
|
||||
`124` | `red3` | `175,0,0` | `#af0000`
|
||||
`125` | `deeppink4_2` | `175,0,95` | `#af005f`
|
||||
`126` | `mediumvioletred` | `175,0,135` | `#af0087`
|
||||
`127` | `magenta3` | `175,0,175` | `#af00af`
|
||||
`128` | `darkviolet_1` | `175,0,215` | `#af00d7`
|
||||
`129` | `purple_2` | `175,0,255` | `#af00ff`
|
||||
`130` | `darkorange3` | `175,95,0` | `#af5f00`
|
||||
`131` | `indianred` | `175,95,95` | `#af5f5f`
|
||||
`132` | `hotpink3` | `175,95,135` | `#af5f87`
|
||||
`133` | `mediumorchid3` | `175,95,175` | `#af5faf`
|
||||
`134` | `mediumorchid` | `175,95,215` | `#af5fd7`
|
||||
`135` | `mediumpurple2` | `175,95,255` | `#af5fff`
|
||||
`136` | `darkgoldenrod` | `175,135,0` | `#af8700`
|
||||
`137` | `lightsalmon3` | `175,135,95` | `#af875f`
|
||||
`138` | `rosybrown` | `175,135,135` | `#af8787`
|
||||
`139` | `grey63` | `175,135,175` | `#af87af`
|
||||
`140` | `mediumpurple2_1` | `175,135,215` | `#af87d7`
|
||||
`141` | `mediumpurple1` | `175,135,255` | `#af87ff`
|
||||
`142` | `gold3` | `175,175,0` | `#afaf00`
|
||||
`143` | `darkkhaki` | `175,175,95` | `#afaf5f`
|
||||
`144` | `navajowhite3` | `175,175,135` | `#afaf87`
|
||||
`145` | `grey69` | `175,175,175` | `#afafaf`
|
||||
`146` | `lightsteelblue3` | `175,175,215` | `#afafd7`
|
||||
`147` | `lightsteelblue` | `175,175,255` | `#afafff`
|
||||
`148` | `yellow3` | `175,215,0` | `#afd700`
|
||||
`149` | `darkolivegreen3_2` | `175,215,95` | `#afd75f`
|
||||
`150` | `darkseagreen3_1` | `175,215,135` | `#afd787`
|
||||
`151` | `darkseagreen2` | `175,215,175` | `#afd7af`
|
||||
`152` | `lightcyan3` | `175,215,215` | `#afd7d7`
|
||||
`153` | `lightskyblue1` | `175,215,255` | `#afd7ff`
|
||||
`154` | `greenyellow` | `175,255,0` | `#afff00`
|
||||
`155` | `darkolivegreen2` | `175,255,95` | `#afff5f`
|
||||
`156` | `palegreen1_1` | `175,255,135` | `#afff87`
|
||||
`157` | `darkseagreen2_1` | `175,255,175` | `#afffaf`
|
||||
`158` | `darkseagreen1` | `175,255,215` | `#afffd7`
|
||||
`159` | `paleturquoise1` | `175,255,255` | `#afffff`
|
||||
`160` | `red3_1` | `215,0,0` | `#d70000`
|
||||
`161` | `deeppink3` | `215,0,95` | `#d7005f`
|
||||
`162` | `deeppink3_1` | `215,0,135` | `#d70087`
|
||||
`163` | `magenta3_1` | `215,0,175` | `#d700af`
|
||||
`164` | `magenta3_2` | `215,0,215` | `#d700d7`
|
||||
`165` | `magenta2` | `215,0,255` | `#d700ff`
|
||||
`166` | `darkorange3_1` | `215,95,0` | `#d75f00`
|
||||
`167` | `indianred_1` | `215,95,95` | `#d75f5f`
|
||||
`168` | `hotpink3_1` | `215,95,135` | `#d75f87`
|
||||
`169` | `hotpink2` | `215,95,175` | `#d75faf`
|
||||
`170` | `orchid` | `215,95,215` | `#d75fd7`
|
||||
`171` | `mediumorchid1` | `215,95,255` | `#d75fff`
|
||||
`172` | `orange3` | `215,135,0` | `#d78700`
|
||||
`173` | `lightsalmon3_1` | `215,135,95` | `#d7875f`
|
||||
`174` | `lightpink3` | `215,135,135` | `#d78787`
|
||||
`175` | `pink3` | `215,135,175` | `#d787af`
|
||||
`176` | `plum3` | `215,135,215` | `#d787d7`
|
||||
`177` | `violet` | `215,135,255` | `#d787ff`
|
||||
`178` | `gold3_1` | `215,175,0` | `#d7af00`
|
||||
`179` | `lightgoldenrod3` | `215,175,95` | `#d7af5f`
|
||||
`180` | `tan` | `215,175,135` | `#d7af87`
|
||||
`181` | `mistyrose3` | `215,175,175` | `#d7afaf`
|
||||
`182` | `thistle3` | `215,175,215` | `#d7afd7`
|
||||
`183` | `plum2` | `215,175,255` | `#d7afff`
|
||||
`184` | `yellow3_1` | `215,215,0` | `#d7d700`
|
||||
`185` | `khaki3` | `215,215,95` | `#d7d75f`
|
||||
`186` | `lightgoldenrod2` | `215,215,135` | `#d7d787`
|
||||
`187` | `lightyellow3` | `215,215,175` | `#d7d7af`
|
||||
`188` | `grey84` | `215,215,215` | `#d7d7d7`
|
||||
`189` | `lightsteelblue1` | `215,215,255` | `#d7d7ff`
|
||||
`190` | `yellow2` | `215,255,0` | `#d7ff00`
|
||||
`191` | `darkolivegreen1` | `215,255,95` | `#d7ff5f`
|
||||
`192` | `darkolivegreen1_1` | `215,255,135` | `#d7ff87`
|
||||
`193` | `darkseagreen1_1` | `215,255,175` | `#d7ffaf`
|
||||
`194` | `honeydew2` | `215,255,215` | `#d7ffd7`
|
||||
`195` | `lightcyan1` | `215,255,255` | `#d7ffff`
|
||||
`196` | `red1` | `255,0,0` | `#ff0000`
|
||||
`197` | `deeppink2` | `255,0,95` | `#ff005f`
|
||||
`198` | `deeppink1` | `255,0,135` | `#ff0087`
|
||||
`199` | `deeppink1_1` | `255,0,175` | `#ff00af`
|
||||
`200` | `magenta2_1` | `255,0,215` | `#ff00d7`
|
||||
`201` | `magenta1` | `255,0,255` | `#ff00ff`
|
||||
`202` | `orangered1` | `255,95,0` | `#ff5f00`
|
||||
`203` | `indianred1` | `255,95,95` | `#ff5f5f`
|
||||
`204` | `indianred1_1` | `255,95,135` | `#ff5f87`
|
||||
`205` | `hotpink` | `255,95,175` | `#ff5faf`
|
||||
`206` | `hotpink_1` | `255,95,215` | `#ff5fd7`
|
||||
`207` | `mediumorchid1_1` | `255,95,255` | `#ff5fff`
|
||||
`208` | `darkorange` | `255,135,0` | `#ff8700`
|
||||
`209` | `salmon1` | `255,135,95` | `#ff875f`
|
||||
`210` | `lightcoral` | `255,135,135` | `#ff8787`
|
||||
`211` | `palevioletred1` | `255,135,175` | `#ff87af`
|
||||
`212` | `orchid2` | `255,135,215` | `#ff87d7`
|
||||
`213` | `orchid1` | `255,135,255` | `#ff87ff`
|
||||
`214` | `orange1` | `255,175,0` | `#ffaf00`
|
||||
`215` | `sandybrown` | `255,175,95` | `#ffaf5f`
|
||||
`216` | `lightsalmon1` | `255,175,135` | `#ffaf87`
|
||||
`217` | `lightpink1` | `255,175,175` | `#ffafaf`
|
||||
`218` | `pink1` | `255,175,215` | `#ffafd7`
|
||||
`219` | `plum1` | `255,175,255` | `#ffafff`
|
||||
`220` | `gold1` | `255,215,0` | `#ffd700`
|
||||
`221` | `lightgoldenrod2_1` | `255,215,95` | `#ffd75f`
|
||||
`222` | `lightgoldenrod2_2` | `255,215,135` | `#ffd787`
|
||||
`223` | `navajowhite1` | `255,215,175` | `#ffd7af`
|
||||
`224` | `mistyrose1` | `255,215,215` | `#ffd7d7`
|
||||
`225` | `thistle1` | `255,215,255` | `#ffd7ff`
|
||||
`226` | `yellow1` | `255,255,0` | `#ffff00`
|
||||
`227` | `lightgoldenrod1` | `255,255,95` | `#ffff5f`
|
||||
`228` | `khaki1` | `255,255,135` | `#ffff87`
|
||||
`229` | `wheat1` | `255,255,175` | `#ffffaf`
|
||||
`230` | `cornsilk1` | `255,255,215` | `#ffffd7`
|
||||
`231` | `grey100` | `255,255,255` | `#ffffff`
|
||||
`232` | `grey3` | `8,8,8` | `#080808`
|
||||
`233` | `grey7` | `18,18,18` | `#121212`
|
||||
`234` | `grey11` | `28,28,28` | `#1c1c1c`
|
||||
`235` | `grey15` | `38,38,38` | `#262626`
|
||||
`236` | `grey19` | `48,48,48` | `#303030`
|
||||
`237` | `grey23` | `58,58,58` | `#3a3a3a`
|
||||
`238` | `grey27` | `68,68,68` | `#444444`
|
||||
`239` | `grey30` | `78,78,78` | `#4e4e4e`
|
||||
`240` | `grey35` | `88,88,88` | `#585858`
|
||||
`241` | `grey39` | `98,98,98` | `#626262`
|
||||
`242` | `grey42` | `108,108,108` | `#6c6c6c`
|
||||
`243` | `grey46` | `118,118,118` | `#767676`
|
||||
`244` | `grey50` | `128,128,128` | `#808080`
|
||||
`245` | `grey54` | `138,138,138` | `#8a8a8a`
|
||||
`246` | `grey58` | `148,148,148` | `#949494`
|
||||
`247` | `grey62` | `158,158,158` | `#9e9e9e`
|
||||
`248` | `grey66` | `168,168,168` | `#a8a8a8`
|
||||
`249` | `grey70` | `178,178,178` | `#b2b2b2`
|
||||
`250` | `grey74` | `188,188,188` | `#bcbcbc`
|
||||
`251` | `grey78` | `198,198,198` | `#c6c6c6`
|
||||
`252` | `grey82` | `208,208,208` | `#d0d0d0`
|
||||
`253` | `grey85` | `218,218,218` | `#dadada`
|
||||
`254` | `grey89` | `228,228,228` | `#e4e4e4`
|
||||
`255` | `grey93` | `238,238,238` | `#eeeeee`
|
||||
## License
|
||||
|
||||
Copyright © Patrik Svensson, Phil Scott
|
||||
|
||||
Spectre.Console is provided as-is under the MIT license. For more information see LICENSE.
|
||||
|
||||
* For SixLabors.ImageSharp, see https://github.com/SixLabors/ImageSharp/blob/master/LICENSE
|
||||
65
README.zh.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# `Spectre.Console`
|
||||
|
||||
_[](https://www.nuget.org/packages/spectre.console)_
|
||||
|
||||
`Spectre.Console`是一个 .NET 5/.NET Standard 2.0 的库,能让您在终端里更方便地生成精美的界面。
|
||||
|
||||
深受 [Rich](https://github.com/willmcgugan/rich) 这个优秀库的启发。
|
||||
|
||||
## 目录
|
||||
|
||||
1. [功能](#features)
|
||||
2. [安装](#installing)
|
||||
3. [文档](#documentation)
|
||||
4. [例子](#examples)
|
||||
5. [License](#license)
|
||||
|
||||
## 功能
|
||||
|
||||
* 编写时考虑到了单元测试。
|
||||
* 支持 tables、grid、panel 和 [rich](https://github.com/willmcgugan/rich) 所支持的标记语言。
|
||||
* 支持大部分的 SRG 参数,包括粗体、暗淡字、斜体、下划线、删除线和闪烁文本。
|
||||
* 支持终端显示 3/4/8/24 位色。自动检测终端类型,自适应颜色范围。
|
||||
|
||||

|
||||
|
||||
## 安装
|
||||
|
||||
最快的安装方式,就是用NuGet包管理直接安装Spectre.Console。
|
||||
|
||||
```csharp
|
||||
dotnet add package Spectre.Console
|
||||
```
|
||||
|
||||
## 文档
|
||||
|
||||
`Spectre.Console`的文档可以在这里查看
|
||||
https://spectreconsole.net/
|
||||
|
||||
## 例子
|
||||
|
||||
如果想直接运行`Spectre.Console`的例子,则需要安装[dotnet-example](https://github.com/patriksvensson/dotnet-example)工具。
|
||||
|
||||
```
|
||||
> dotnet tool restore
|
||||
```
|
||||
|
||||
然后你可以列出仓库里的所有例子:
|
||||
|
||||
```
|
||||
> dotnet example
|
||||
```
|
||||
|
||||
跑一个看看效果:
|
||||
|
||||
```
|
||||
> dotnet example tables
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
版权所有 © Patrik Svensson, Phil Scott
|
||||
|
||||
Spectre.Console 基于 MIT 协议提供。查看 LICENSE 文件了解更多信息。
|
||||
|
||||
* SixLabors.ImageSharp 的协议请查看 https://github.com/SixLabors/ImageSharp/blob/master/LICENSE
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);output\**;.gitignore</DefaultItemExcludes>
|
||||
<MinVerSkip Condition="'$(Configuration)' == 'Debug'">true</MinVerSkip>
|
||||
@@ -23,8 +23,20 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Statiq.Web" Version="1.0.0-beta.5" />
|
||||
<PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.0" />
|
||||
<None Remove="src\Data\emojis.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="src\Data\emojis.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Statiq.Web" Version="1.0.0-beta.13" />
|
||||
<PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Folder Include="input\assets\images\emojis\" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="Versioning" BeforeTargets="MinVer">
|
||||
|
||||
@@ -1 +1 @@
|
||||
dotnet run -- preview --virtual-dir "spectre.console"
|
||||
dotnet run -- preview
|
||||
@@ -11,14 +11,14 @@ 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))
|
||||
.AddShortcode("EmojiTable", typeof(EmojiTableShortcode))
|
||||
.AddPipelines()
|
||||
.RunAsync();
|
||||
|
||||
|
||||
@@ -1,8 +1,44 @@
|
||||
# Documentation
|
||||
|
||||
Preview the documentation locally by running the following
|
||||
from your favourite shell:
|
||||
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).
|
||||
|
||||
**Note that the site runs under a virtual directory.**
|
||||
|
||||
## Editing Content
|
||||
|
||||
The documentation is written using [Markdown](https://www.markdownguide.org/basic-syntax/).
|
||||
|
||||
Markdown files can be found under the following directories:
|
||||
|
||||
- [/input](./input)
|
||||
- [/appendix](./input/appendix)
|
||||
|
||||
## Editing Layout
|
||||
|
||||
Layout and styling can also be found in the [input](./input) directory. Look for Sass, Css, and Images under the [assets](./input/assets) directory.
|
||||
|
||||
## Custom Build Features
|
||||
|
||||
The documentation site has custom enhancements to Statiq located under the [./src](./src) directory.
|
||||
|
||||
## License
|
||||
|
||||
MIT License
|
||||
|
||||
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:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
1
docs/input/CNAME
Normal file
@@ -0,0 +1 @@
|
||||
spectreconsole.net
|
||||
@@ -5,8 +5,8 @@
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<link href="/spectre.console/assets/bootstrap/bootstrap.css" rel="stylesheet" />
|
||||
<link href="/spectre.console/assets/css/styles.css" rel="stylesheet" />
|
||||
<link href="@Context.GetLink("/assets/bootstrap/bootstrap.css")" rel="stylesheet" />
|
||||
<link href="@Context.GetLink("/assets/css/styles.css")" rel="stylesheet" />
|
||||
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&family=Roboto+Slab:wght@400;700&family=Roboto:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap" rel="stylesheet" data-no-mirror>
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.19.0/themes/prism.css">
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
<nav id="topnav" class="navbar navbar-expand-lg navbar-light">
|
||||
<div class="container py-3">
|
||||
<a class="navbar-brand" href="/spectre.console"><img id="logo" src="/spectre.console/assets/logo.svg" alt="Spectre.Console"> Spectre.Console</a>
|
||||
<a class="navbar-brand" href="@Context.GetLink("/")"><img id="logo" src="@Context.GetLink("/assets/logo.svg")" alt="Spectre.Console"> Spectre.Console</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
@@ -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>
|
||||
@@ -128,14 +128,33 @@
|
||||
{
|
||||
IDocument root = OutputPages["index.html"].First();
|
||||
<div class="sidebar-nav-item @(Document.IdEquals(root) ? "active" : null)">
|
||||
@Html.DocumentLink(root)
|
||||
@if(root.ShowLink())
|
||||
{
|
||||
@Html.DocumentLink(root)
|
||||
}
|
||||
else
|
||||
{
|
||||
@root.GetTitle()
|
||||
}
|
||||
</div>
|
||||
|
||||
@foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible())
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(document.GetTitle()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
DocumentList<IDocument> documentChildren = OutputPages.GetChildrenOf(document);
|
||||
<div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(documentChildren.Any() ? "has-children" : null)">
|
||||
@Html.DocumentLink(document)
|
||||
@if(document.ShowLink())
|
||||
{
|
||||
@Html.DocumentLink(document)
|
||||
}
|
||||
else
|
||||
{
|
||||
@document.GetTitle()
|
||||
}
|
||||
</div>
|
||||
|
||||
@if (documentChildren.OnlyVisible().Any())
|
||||
@@ -184,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>
|
||||
|
||||
33
docs/input/appendix/borders.md
Normal file
@@ -0,0 +1,33 @@
|
||||
Title: Borders
|
||||
Order: 2
|
||||
---
|
||||
|
||||
There is different built-in borders you can use for tables and panels.
|
||||
|
||||
# Table borders
|
||||
|
||||
<img src="../assets/images/borders/table.png" style="max-width: 100%;">
|
||||
|
||||
## Example
|
||||
|
||||
To set a table border to `SimpleHeavy`:
|
||||
|
||||
```csharp
|
||||
var table = new Table();
|
||||
table.Border = TableBorder.SimpleHeavy;
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
# Panel borders
|
||||
|
||||
<img src="../assets/images/borders/panel.png" style="max-width: 100%;">
|
||||
|
||||
## Example
|
||||
|
||||
To set a panel border to `Rounded`:
|
||||
|
||||
```csharp
|
||||
var panel = new Panel("Hello World");
|
||||
panel.Border = BoxBorder.Rounded;
|
||||
```
|
||||
31
docs/input/appendix/colors.md
Normal file
@@ -0,0 +1,31 @@
|
||||
Title: Colors
|
||||
Order: 0
|
||||
---
|
||||
|
||||
The following is a list of the standard 8-bit colors supported in terminals.
|
||||
|
||||
Note that the first 16 colors are generally defined by the system or your terminal software, and may not display exactly as rendered here.
|
||||
|
||||
# Usage
|
||||
|
||||
You can either use the colors in code, such as `new Style(foreground: Color.Maroon)` or
|
||||
in markup text such as `AnsiConsole.Markup("[maroon on blue]Hello[/]")`.
|
||||
|
||||
# Standard colors
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" id="basic-addon1">
|
||||
<i class="fas fa-search" aria-hidden="true"></i>
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
class="form-control w-100 filter"
|
||||
data-table="color-results"
|
||||
type="text" placeholder="Search Colors..." autocomplete="off"
|
||||
aria-label="Search Colors">
|
||||
</div>
|
||||
|
||||
<?# ColorTable /?>
|
||||
|
||||
<script type="text/javascript" src="../assets/js/table-search.js"></script>
|
||||
72
docs/input/appendix/emojis.md
Normal file
@@ -0,0 +1,72 @@
|
||||
Title: Emojis
|
||||
Order: 3
|
||||
---
|
||||
|
||||
Please note that what emojis that can be used is completely up to
|
||||
the operating system and/or terminal you're using, and no guarantees
|
||||
can be made of how it will look. Calculating the width of emojis
|
||||
is also not an exact science in many ways, so milage might vary when
|
||||
used in tables, panels or grids.
|
||||
|
||||
To ensure best compatibility, consider only using emojis introduced
|
||||
before Unicode 13.0 that belongs in the `Emoji_Presentation` category
|
||||
in the official emoji list at
|
||||
https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt
|
||||
|
||||
# Usage
|
||||
|
||||
```csharp
|
||||
// Markup
|
||||
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
|
||||
|
||||
// Constant
|
||||
var hello = "Hello " + Emoji.Known.GlobeShowingEuropeAfrica;
|
||||
```
|
||||
|
||||
# Replacing emojis in text
|
||||
|
||||
```csharp
|
||||
var phrase = "Mmmm :birthday_cake:";
|
||||
var rendered = Emoji.Replace(phrase);
|
||||
```
|
||||
|
||||
# Remapping or adding an emoji
|
||||
|
||||
Sometimes you want to remap an existing emoji, or
|
||||
add a completely new one. For this you can use the
|
||||
`Emoji.Remap` method. This approach works both with
|
||||
markup strings and `Emoji.Replace`.
|
||||
|
||||
```csharp
|
||||
// Remap the emoji
|
||||
Emoji.Remap("globe_showing_europe_africa", "😄");
|
||||
|
||||
// Render markup
|
||||
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
|
||||
|
||||
// Replace emojis in string
|
||||
var phrase = "Hello :globe_showing_europe_africa:!";
|
||||
var rendered = Emoji.Replace(phrase);
|
||||
```
|
||||
|
||||
# Emojis
|
||||
|
||||
_The images in the table below might not render correctly in your
|
||||
browser for the same reasons mentioned in the `Compatibility` section._
|
||||
|
||||
<div class="input-group mb-3">
|
||||
<div class="input-group-prepend">
|
||||
<span class="input-group-text" id="basic-addon1">
|
||||
<i class="fas fa-search" aria-hidden="true"></i>
|
||||
</span>
|
||||
</div>
|
||||
<input
|
||||
class="form-control w-100 filter"
|
||||
data-table="emoji-results"
|
||||
type="text" placeholder="Search Emojis..." autocomplete="off"
|
||||
aria-label="Search Emojis">
|
||||
</div>
|
||||
|
||||
<?# EmojiTable /?>
|
||||
|
||||
<script type="text/javascript" src="../assets/js/table-search.js"></script>
|
||||
12
docs/input/appendix/index.cshtml
Normal file
@@ -0,0 +1,12 @@
|
||||
Title: Appendix
|
||||
Order: 100
|
||||
---
|
||||
|
||||
<h1>Sections</h1>
|
||||
|
||||
<ul>
|
||||
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
|
||||
{
|
||||
<li>@Html.DocumentLink(child)</li>
|
||||
}
|
||||
</ul>
|
||||
43
docs/input/appendix/spinners.md
Normal file
@@ -0,0 +1,43 @@
|
||||
Title: Spinners
|
||||
Order: 4
|
||||
---
|
||||
|
||||
For all available spinners, see https://jsfiddle.net/sindresorhus/2eLtsbey/embedded/result/
|
||||
|
||||
# Usage
|
||||
|
||||
Spinners can be used with [Progress](xref:progress) and [Status](xref:status).
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Status()
|
||||
.Spinner(Spinner.Known.Star)
|
||||
.Start("Thinking...", ctx => {
|
||||
// Omitted
|
||||
});
|
||||
```
|
||||
|
||||
# Implementing a spinner
|
||||
|
||||
To implement your own spinner, all you have to do is
|
||||
inherit from the `Spinner` base class.
|
||||
|
||||
In the example below, the spinner will alterate between
|
||||
the characters `A`, `B` and `C` every 100 ms.
|
||||
|
||||
```csharp
|
||||
public sealed class MySpinner : Spinner
|
||||
{
|
||||
// The interval for each frame
|
||||
public override TimeSpan Interval => TimeSpan.FromMilliseconds(100);
|
||||
|
||||
// Whether or not the spinner contains unicode characters
|
||||
public override bool IsUnicode => false;
|
||||
|
||||
// The individual frames of the spinner
|
||||
public override IReadOnlyList<string> Frames =>
|
||||
new List<string>
|
||||
{
|
||||
"A", "B", "C",
|
||||
};
|
||||
}
|
||||
```
|
||||
44
docs/input/appendix/styles.md
Normal file
@@ -0,0 +1,44 @@
|
||||
Title: Styles
|
||||
Order: 1
|
||||
---
|
||||
|
||||
Note that what styles that can be used is defined by the system or your terminal software, and may not appear as they should.
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<td><code>bold</code></td>
|
||||
<td>Bold text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dim</code></td>
|
||||
<td>Dim or faint text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>italic</code></td>
|
||||
<td>Italic text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>underline</code></td>
|
||||
<td>Underlined text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>invert</code></td>
|
||||
<td>Swaps the foreground and background colors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>conceal</code></td>
|
||||
<td>Hides the text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>slowblink</code></td>
|
||||
<td>Makes text blink slowly</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>rapidblink</code></td>
|
||||
<td>Makes text blink</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>strikethrough</code></td>
|
||||
<td>Shows text with a horizontal line through the center</td>
|
||||
</tr>
|
||||
</table>
|
||||
BIN
docs/input/assets/images/barchart.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
BIN
docs/input/assets/images/borders/panel.png
Normal file
|
After Width: | Height: | Size: 112 KiB |
BIN
docs/input/assets/images/borders/table.png
Normal file
|
After Width: | Height: | Size: 503 KiB |
BIN
docs/input/assets/images/compact_exception.png
Normal file
|
After Width: | Height: | Size: 163 KiB |
BIN
docs/input/assets/images/custom_exception.png
Normal file
|
After Width: | Height: | Size: 159 KiB |
BIN
docs/input/assets/images/example.png
Normal file
|
After Width: | Height: | Size: 219 KiB |
BIN
docs/input/assets/images/exception.png
Normal file
|
After Width: | Height: | Size: 421 KiB |
|
Before Width: | Height: | Size: 1.3 KiB |
BIN
docs/input/assets/images/multiselection.gif
Normal file
|
After Width: | Height: | Size: 229 KiB |
BIN
docs/input/assets/images/progress.gif
Normal file
|
After Width: | Height: | Size: 164 KiB |
BIN
docs/input/assets/images/progress.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
docs/input/assets/images/progress_fallback.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
docs/input/assets/images/rule.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
docs/input/assets/images/selection.gif
Normal file
|
After Width: | Height: | Size: 208 KiB |
BIN
docs/input/assets/images/status.gif
Normal file
|
After Width: | Height: | Size: 257 KiB |
BIN
docs/input/assets/images/table.gif
Normal file
|
After Width: | Height: | Size: 1.4 MiB |
BIN
docs/input/assets/images/table.png
Normal file
|
After Width: | Height: | Size: 55 KiB |
BIN
docs/input/assets/images/tree.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
34
docs/input/assets/js/table-search.js
Normal file
@@ -0,0 +1,34 @@
|
||||
$(document).ready(function () {
|
||||
|
||||
$('.filter').each(function () {
|
||||
let input = this;
|
||||
let table = document.getElementById(input.dataset.table);
|
||||
|
||||
input.onkeyup = function (event) {
|
||||
|
||||
if (event.key === "Enter") {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
}
|
||||
|
||||
let value = input.value.toUpperCase();
|
||||
let rows = table.getElementsByClassName('search-row');
|
||||
|
||||
for (let i = 0; i < rows.length; i++) {
|
||||
let row = rows[i];
|
||||
|
||||
let match =
|
||||
new RegExp(value, "i").test(row.textContent) ||
|
||||
value === '';
|
||||
|
||||
if (match) {
|
||||
row.style.display = 'table-row';
|
||||
} else {
|
||||
row.style.display = 'none';
|
||||
}
|
||||
}
|
||||
}; // keyup
|
||||
})
|
||||
|
||||
}); // ready
|
||||
12
docs/input/cli/index.cshtml
Normal file
@@ -0,0 +1,12 @@
|
||||
Title: CLI
|
||||
Order: 10
|
||||
---
|
||||
|
||||
<h1>Sections</h1>
|
||||
|
||||
<ul>
|
||||
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
|
||||
{
|
||||
<li>@Html.DocumentLink(child)</li>
|
||||
}
|
||||
</ul>
|
||||
121
docs/input/cli/introduction.md
Normal file
@@ -0,0 +1,121 @@
|
||||
Title: Introduction
|
||||
Order: 1
|
||||
---
|
||||
|
||||
`Spectre.Console.Cli` is a modern library for parsing command line arguments. While it's extremely
|
||||
opinionated in what it does, it tries to follow established industry conventions, and draws
|
||||
its inspiration from applications you use everyday.
|
||||
|
||||
# How does it work?
|
||||
|
||||
The underlying philosophy behind `Spectre.Console.Cli` is to rely on the .NET type system to
|
||||
declare the commands, but tie everything together via composition.
|
||||
|
||||
Imagine the following command structure:
|
||||
|
||||
* dotnet *(executable)*
|
||||
* add `[PROJECT]`
|
||||
* package `<PACKAGE_NAME>` --version `<VERSION>`
|
||||
* reference `<PROJECT_REFERENCE>`
|
||||
|
||||
For this I would like to implement the commands (the different levels in the tree that
|
||||
executes something) separately from the settings (the options, flags and arguments),
|
||||
which I want to be able to inherit from each other.
|
||||
|
||||
## Specify the settings
|
||||
|
||||
We start by creating some settings that represents the options, flags and arguments
|
||||
that we want to act upon.
|
||||
|
||||
```csharp
|
||||
public class AddSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "[PROJECT]")]
|
||||
public string Project { get; set; }
|
||||
}
|
||||
|
||||
public class AddPackageSettings : AddSettings
|
||||
{
|
||||
[CommandArgument(0, "<PACKAGE_NAME>")]
|
||||
public string PackageName { get; set; }
|
||||
|
||||
[CommandOption("-v|--version <VERSION>")]
|
||||
public string Version { get; set; }
|
||||
}
|
||||
|
||||
public class AddReferenceSettings : AddSettings
|
||||
{
|
||||
[CommandArgument(0, "<PROJECT_REFERENCE>")]
|
||||
public string ProjectReference { get; set; }
|
||||
}
|
||||
```
|
||||
|
||||
## Specify the commands
|
||||
|
||||
Now it's time to specify the commands that act on the settings we created
|
||||
in the previous step.
|
||||
|
||||
```csharp
|
||||
public class AddPackageCommand : Command<AddPackageSettings>
|
||||
{
|
||||
public override int Execute(CommandContext context, AddPackageSettings settings)
|
||||
{
|
||||
// Omitted
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public class AddReferenceCommand : Command<AddReferenceSettings>
|
||||
{
|
||||
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
|
||||
that tells the parser how to interpret user input.
|
||||
|
||||
```csharp
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace MyApp
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
var app = new CommandApp();
|
||||
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.AddBranch<AddSettings>("add", add =>
|
||||
{
|
||||
add.AddCommand<AddPackageCommand>("package");
|
||||
add.AddCommand<AddReferenceCommand>("reference");
|
||||
});
|
||||
});
|
||||
|
||||
return app.Run(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
# So why this way?
|
||||
|
||||
Now you might wonder, why do things like this? Well, for starters the different parts
|
||||
of the application are separated, while still having the option to share things like options,
|
||||
flags and arguments between them.
|
||||
|
||||
This make the resulting code very clean and easy to navigate, not to mention to unit test.
|
||||
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.
|
||||
47
docs/input/cli/migration.md
Normal file
@@ -0,0 +1,47 @@
|
||||
Title: Migrate from Spectre.Cli
|
||||
Order: 2
|
||||
---
|
||||
|
||||
The functionality in `Spectre.Cli` has been moved into the `Spectre.Console`
|
||||
library. If you're using `Spectre.Cli`, you will need to migrate to ensure
|
||||
that you get updates or fixes.
|
||||
|
||||
## 1. Remove Spectre.Cli NuGet package
|
||||
|
||||
Start with removing the `Spectre.Cli` package reference from your project(s).
|
||||
|
||||
```text
|
||||
> dotnet remove package Spectre.Cli
|
||||
```
|
||||
|
||||
## 2. Add Spectre.Console NuGet package
|
||||
|
||||
Add the [Spectre.Console](https://www.nuget.org/packages/spectre.console) NuGet package to your project(s).
|
||||
|
||||
```text
|
||||
> dotnet add package Spectre.Console
|
||||
```
|
||||
|
||||
## 3. Change using statements
|
||||
|
||||
Change all using statements from `Spectre.Cli`
|
||||
to `Spectre.Console.CLi`.
|
||||
|
||||
```diff
|
||||
- using Spectre.Cli;
|
||||
+ using Spectre.Console.Cli;
|
||||
```
|
||||
|
||||
# Breaking Changes
|
||||
|
||||
In the process of moving `Spectre.Cli`, there have been some minor breaking changes.
|
||||
|
||||
## Spectre.Cli.Exceptions namespace moved
|
||||
|
||||
All exceptions have been moved from the `Spectre.Cli.Exceptions` namespace to
|
||||
the `Spectre.Console.Cli` namespace.
|
||||
|
||||
```diff
|
||||
- using Spectre.Cli.Exceptions;
|
||||
+ using Spectre.Console.Cli;
|
||||
```
|
||||
@@ -1,16 +0,0 @@
|
||||
Title: Colors
|
||||
Order: 4
|
||||
---
|
||||
|
||||
The following is a list of the standard 8-bit colors supported in terminals.
|
||||
|
||||
Note that the first 16 colors are generally defined by the system or your terminal software, and may not display exactly as rendered here.
|
||||
|
||||
# Usage
|
||||
|
||||
You can either use the colors in code, such as `new Style(foreground: Color.Maroon)` or
|
||||
in markup text such as `AnsiConsole.Markup("[maroon on blue]Hello[/]")`.
|
||||
|
||||
# Standard colors
|
||||
|
||||
<?# ColorTable /?>
|
||||
52
docs/input/exceptions.md
Normal file
@@ -0,0 +1,52 @@
|
||||
Title: Exceptions
|
||||
Order: 3
|
||||
---
|
||||
|
||||
Exceptions aren't always readable when viewed in the terminal.
|
||||
You can make exception a bit more readable by using the `WriteException` method.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.WriteException(ex);
|
||||
```
|
||||
|
||||
<img src="assets/images/exception.png" style="max-width: 100%;">
|
||||
|
||||
## Shortening parts
|
||||
|
||||
You can also shorten specific parts of the exception to make it even
|
||||
more readable, and make paths clickable hyperlinks. Whether or not
|
||||
the hyperlinks are clickable is up to the terminal.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.WriteException(ex,
|
||||
ExceptionFormats.ShortenPaths | ExceptionFormats.ShortenTypes |
|
||||
ExceptionFormats.ShortenMethods | ExceptionFormats.ShowLinks);
|
||||
```
|
||||
|
||||
<img src="assets/images/compact_exception.png" style="max-width: 100%;">
|
||||
|
||||
## Customizing exception output
|
||||
|
||||
In addition to shorten specific part of the exception, you can
|
||||
also override the default styling.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.WriteException(ex, new ExceptionSettings
|
||||
{
|
||||
Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
|
||||
Style = new ExceptionStyle
|
||||
{
|
||||
Exception = new Style().Foreground(Color.Grey),
|
||||
Message = new Style().Foreground(Color.White),
|
||||
NonEmphasized = new Style().Foreground(Color.Cornsilk1),
|
||||
Parenthesis = new Style().Foreground(Color.Cornsilk1),
|
||||
Method = new Style().Foreground(Color.Red),
|
||||
ParameterName = new Style().Foreground(Color.Cornsilk1),
|
||||
ParameterType = new Style().Foreground(Color.Red),
|
||||
Path = new Style().Foreground(Color.Red),
|
||||
LineNumber = new Style().Foreground(Color.Cornsilk1),
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
<img src="assets/images/custom_exception.png" style="max-width: 100%;">
|
||||
@@ -1,4 +1,4 @@
|
||||
Title: Welcome
|
||||
Title: Welcome
|
||||
Order: 0
|
||||
---
|
||||
|
||||
@@ -20,7 +20,7 @@ for Python written by Will McGugan.
|
||||
The library will detect the capabilities of the current terminal
|
||||
and downgrade colors as needed.
|
||||
|
||||
## Example
|
||||
## Examples
|
||||
|
||||
<img width="100%"
|
||||
src="https://github.com/spectresystems/spectre.console/raw/main/resources/gfx/screenshots/example.png" />
|
||||
<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%;" />
|
||||
|
||||
12
docs/input/live/index.cshtml
Normal 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>
|
||||
86
docs/input/live/progress.md
Normal file
@@ -0,0 +1,86 @@
|
||||
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;">
|
||||
|
||||
<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%;">
|
||||
|
||||
# Usage
|
||||
|
||||
```csharp
|
||||
// Synchronous
|
||||
AnsiConsole.Progress()
|
||||
.Start(ctx =>
|
||||
{
|
||||
// Define tasks
|
||||
var task1 = ctx.AddTask("[green]Reticulating splines[/]");
|
||||
var task2 = ctx.AddTask("[green]Folding space[/]");
|
||||
|
||||
while(!ctx.IsFinished)
|
||||
{
|
||||
task1.Increment(1.5);
|
||||
task2.Increment(0.5);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Asynchronous progress
|
||||
|
||||
If you prefer to use async/await, you can use `StartAsync` instead of `Start`.
|
||||
|
||||
```csharp
|
||||
// Asynchronous
|
||||
await AnsiConsole.Progress()
|
||||
.StartAsync(async ctx =>
|
||||
{
|
||||
// Define tasks
|
||||
var task1 = ctx.AddTask("[green]Reticulating splines[/]");
|
||||
var task2 = ctx.AddTask("[green]Folding space[/]");
|
||||
|
||||
while (!ctx.IsFinished)
|
||||
{
|
||||
// Simulate some work
|
||||
await Task.Delay(250);
|
||||
|
||||
// Increment
|
||||
task1.Increment(1.5);
|
||||
task2.Increment(0.5);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
# Configure
|
||||
|
||||
```csharp
|
||||
// Asynchronous
|
||||
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
|
||||
new ProgressBarColumn(), // Progress bar
|
||||
new PercentageColumn(), // Percentage
|
||||
new RemainingTimeColumn(), // Remaining time
|
||||
new SpinnerColumn(), // Spinner
|
||||
})
|
||||
.Start(ctx =>
|
||||
{
|
||||
// Omitted
|
||||
});
|
||||
```
|
||||
67
docs/input/live/status.md
Normal file
@@ -0,0 +1,67 @@
|
||||
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;">
|
||||
|
||||
<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
|
||||
ANSI control sequence, any progress will be displayed in a simpler way.
|
||||
|
||||
# Usage
|
||||
|
||||
```csharp
|
||||
// Synchronous
|
||||
AnsiConsole.Status()
|
||||
.Start("Thinking...", ctx =>
|
||||
{
|
||||
// Simulate some work
|
||||
AnsiConsole.MarkupLine("Doing some work...");
|
||||
Thread.Sleep(1000);
|
||||
|
||||
// Update the status and spinner
|
||||
ctx.Status("Thinking some more");
|
||||
ctx.Spinner(Spinner.Known.Star);
|
||||
ctx.SpinnerStyle(Style.Parse("green"));
|
||||
|
||||
// Simulate some work
|
||||
AnsiConsole.MarkupLine("Doing some more work...");
|
||||
Thread.Sleep(2000);
|
||||
});
|
||||
```
|
||||
|
||||
## Asynchronous progress
|
||||
|
||||
If you prefer to use async/await, you can use `StartAsync` instead of `Start`.
|
||||
|
||||
```csharp
|
||||
// Asynchronous
|
||||
await AnsiConsole.Status()
|
||||
.StartAsync("Thinking...", async ctx =>
|
||||
{
|
||||
// Omitted
|
||||
});
|
||||
```
|
||||
|
||||
# Configure
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Status()
|
||||
.AutoRefresh(false)
|
||||
.Spinner(Spinner.Known.Star)
|
||||
.SpinnerStyle(Style.Parse("green bold"))
|
||||
.Start("Thinking...", ctx =>
|
||||
{
|
||||
// Omitted
|
||||
ctx.Refresh();
|
||||
});
|
||||
```
|
||||
@@ -1,21 +1,18 @@
|
||||
Title: Markup
|
||||
Order: 3
|
||||
Hidden: False
|
||||
Order: 2
|
||||
---
|
||||
|
||||
In `Spectre.Console` there's a class called `Markup` that
|
||||
allows you to output rich text to the console.
|
||||
The class `Markup` allows you to output rich text to the console.
|
||||
|
||||
# Syntax
|
||||
|
||||
Console markup uses a syntax inspired by bbcode. If you write the style (see [Styles](xref:styles))
|
||||
in square brackets, e.g. `[bold red]`, that style will apply until it is closed with a `[/]`.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Render(new Markup("[bold yellow]Hello[/] [red]World![/]"));
|
||||
```
|
||||
|
||||
Which should output something similar to the image below. Note that the
|
||||
actual appearance might vary depending on your terminal.
|
||||
|
||||

|
||||
|
||||
|
||||
The `Markup` class implements `IRenderable` which means that you
|
||||
can use this in tables, grids, and panels. Most classes that support
|
||||
rendering of `IRenderable` also have overloads for rendering rich text.
|
||||
@@ -24,6 +21,7 @@ rendering of `IRenderable` also have overloads for rendering rich text.
|
||||
var table = new Table();
|
||||
table.AddColumn(new TableColumn(new Markup("[yellow]Foo[/]")));
|
||||
table.AddColumn(new TableColumn("[blue]Bar[/]"));
|
||||
AnsiConsole.Render(table);
|
||||
```
|
||||
|
||||
# Convenience methods
|
||||
@@ -46,59 +44,49 @@ AnsiConsole.Markup("[[Hello]] "); // [Hello]
|
||||
AnsiConsole.Markup("[red][[World]][/]"); // [World]
|
||||
```
|
||||
|
||||
You can also use the `EscapeMarkup` extension method.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("[red]{0}[/]", "Hello [World]".EscapeMarkup());
|
||||
```
|
||||
You can also use the `Markup.Escape` method.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("[red]{0}[/]", Markup.Escape("Hello [World]"));
|
||||
```
|
||||
# Setting background color
|
||||
|
||||
You can set the background color in markup by prefixing the color with
|
||||
`on`.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("[bold yellow on blue]Hello[/]");
|
||||
AnsiConsole.Markup("[default on blue]World[/]");
|
||||
```
|
||||
[bold yellow on blue]Hello[/]
|
||||
[default on blue]World[/]
|
||||
|
||||
# Rendering emojis
|
||||
|
||||
To output an emoji as part of markup, you can use emoji shortcodes.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("Hello :globe_showing_europe_africa:!");
|
||||
```
|
||||
|
||||
For a list of emoji, see the [Emojis](xref:emojis) appendix section.
|
||||
|
||||
# Colors
|
||||
|
||||
For a list of colors, see the [Colors](xref:colors) section.
|
||||
In the examples above, all colors was referenced by their name,
|
||||
but you can also use the hex or rgb representation for colors in markdown.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("[red]Foo[/] ");
|
||||
AnsiConsole.Markup("[#ff0000]Bar[/] ");
|
||||
AnsiConsole.Markup("[rgb(255,0,0)]Baz[/] ");
|
||||
```
|
||||
|
||||
For a list of colors, see the [Colors](xref:colors) appendix section.
|
||||
|
||||
# Styles
|
||||
|
||||
Note that what styles that can be used is defined by the system or your terminal software, and may not appear as they should.
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<td><code>bold</code></td>
|
||||
<td>Bold text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dim</code></td>
|
||||
<td>Dim or faint text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>italic</code></td>
|
||||
<td>Italic text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>underline</code></td>
|
||||
<td>Underlined text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>invert</code></td>
|
||||
<td>Swaps the foreground and background colors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>conceal</code></td>
|
||||
<td>Hides the text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>slowblink</code></td>
|
||||
<td>Makes text blink slowly</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>rapidblink</code></td>
|
||||
<td>Makes text blink</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>strikethrough</code></td>
|
||||
<td>Shows text with a horizontal line through the center</td>
|
||||
</tr>
|
||||
</table>
|
||||
For a list of styles, see the [Styles](xref:styles) appendix section.
|
||||
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>
|
||||
40
docs/input/prompts/multiselection.md
Normal file
@@ -0,0 +1,40 @@
|
||||
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%;" />
|
||||
|
||||
<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
|
||||
// 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)
|
||||
.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",
|
||||
"Banana", "Blackcurrant", "Blueberry",
|
||||
"Cherry", "Cloudberry", "Cocunut",
|
||||
}));
|
||||
|
||||
// Write the selected fruits to the terminal
|
||||
foreach (string fruit in fruits)
|
||||
{
|
||||
AnsiConsole.WriteLine(fruit);
|
||||
}
|
||||
```
|
||||
33
docs/input/prompts/selection.md
Normal file
@@ -0,0 +1,33 @@
|
||||
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%;" />
|
||||
|
||||
<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
|
||||
// Ask for the user's favorite fruit
|
||||
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",
|
||||
"Banana", "Blackcurrant", "Blueberry",
|
||||
"Cherry", "Cloudberry", "Cocunut",
|
||||
}));
|
||||
|
||||
// Echo the fruit back to the terminal
|
||||
AnsiConsole.WriteLine($"I agree. {fruit} is tasty!");
|
||||
```
|
||||
105
docs/input/prompts/text.md
Normal file
@@ -0,0 +1,105 @@
|
||||
Title: Text prompt
|
||||
Order: 0
|
||||
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
|
||||
if (!AnsiConsole.Confirm("Run example?"))
|
||||
{
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
```text
|
||||
Run example? [y/n] (y): _
|
||||
```
|
||||
|
||||
# Simple
|
||||
|
||||
```csharp
|
||||
// Ask for the user's name
|
||||
string name = AnsiConsole.Ask<string>("What's your [green]name[/]?");
|
||||
|
||||
// Ask for the user's age
|
||||
int age = AnsiConsole.Ask<int>("What's your [green]age[/]?");
|
||||
```
|
||||
|
||||
```text
|
||||
What's your name? Patrik
|
||||
What's your age? 37
|
||||
```
|
||||
|
||||
# Choices
|
||||
|
||||
```csharp
|
||||
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"));
|
||||
```
|
||||
|
||||
```text
|
||||
What's your favorite fruit? [Apple/Banana/Orange] (Orange): _
|
||||
```
|
||||
|
||||
# Validation
|
||||
|
||||
```csharp
|
||||
var age = AnsiConsole.Prompt(
|
||||
new TextPrompt<int>("What's the secret number?")
|
||||
.Validate(age =>
|
||||
{
|
||||
return age switch
|
||||
{
|
||||
< 99 => ValidationResult.Error("[red]Too low[/]"),
|
||||
> 99 => ValidationResult.Error("[red]Too high[/]"),
|
||||
_ => ValidationResult.Success(),
|
||||
};
|
||||
}));
|
||||
```
|
||||
|
||||
```text
|
||||
What's the secret number? 32
|
||||
Too low
|
||||
What's the secret number? 102
|
||||
Too high
|
||||
What's the secret number? _
|
||||
```
|
||||
|
||||
# Secrets
|
||||
|
||||
```csharp
|
||||
var password = AnsiConsole.Prompt(
|
||||
new TextPrompt<string>("Enter [green]password[/]")
|
||||
.PromptStyle("red")
|
||||
.Secret());
|
||||
```
|
||||
|
||||
```text
|
||||
Enter password: ************_
|
||||
```
|
||||
|
||||
# Optional
|
||||
|
||||
```csharp
|
||||
var color = AnsiConsole.Prompt(
|
||||
new TextPrompt<string>("[grey][[Optional]][/] [green]Favorite color[/]?")
|
||||
.AllowEmpty());
|
||||
```
|
||||
|
||||
```text
|
||||
[Optional] Favorite color? _
|
||||
```
|
||||
@@ -5,7 +5,7 @@ Order: 1
|
||||
The fastest way of getting started using Spectre.Console is
|
||||
to install the NuGet package.
|
||||
|
||||
```shell
|
||||
```text
|
||||
> dotnet add package Spectre.Console
|
||||
```
|
||||
|
||||
|
||||
20
docs/input/sponsors.md
Normal 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!**
|
||||
75
docs/input/widgets/barchart.md
Normal file
@@ -0,0 +1,75 @@
|
||||
Title: Bar Chart
|
||||
Order: 20
|
||||
---
|
||||
|
||||
Use `BarChart` to render bar charts to the console.
|
||||
|
||||
<img src="../assets/images/barchart.png" style="width: 100%;" />
|
||||
|
||||
# Usage
|
||||
|
||||
## Basic usage
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Render(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));
|
||||
```
|
||||
|
||||
## Add items with converter
|
||||
|
||||
```csharp
|
||||
// Create a list of fruits
|
||||
var items = new List<(string Label, double Value)>
|
||||
{
|
||||
("Apple", 12),
|
||||
("Orange", 54),
|
||||
("Banana", 33),
|
||||
};
|
||||
|
||||
// Render bar chart
|
||||
AnsiConsole.Render(new BarChart()
|
||||
.Width(60)
|
||||
.Label("[green bold underline]Number of fruits[/]")
|
||||
.CenterLabel()
|
||||
.AddItems(items, (item) => new BarChartItem(
|
||||
item.Label, item.Value, Color.Yellow)));
|
||||
```
|
||||
|
||||
## Add items implementing IBarChartItem
|
||||
|
||||
```csharp
|
||||
public sealed class Fruit : IBarChartItem
|
||||
{
|
||||
public string Label { get; set; }
|
||||
public double Value { get; set; }
|
||||
public Color? Color { get; set; }
|
||||
|
||||
public Fruit(string label, double value, Color? color = null)
|
||||
{
|
||||
Label = label;
|
||||
Value = value;
|
||||
Color = color;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a list of fruits
|
||||
var items = new List<Fruit>
|
||||
{
|
||||
new Fruit("Apple", 12, Color.Yellow),
|
||||
new Fruit("Orange", 54, Color.Red),
|
||||
new Fruit("Banana", 33, Color.Green),
|
||||
};
|
||||
|
||||
// Render bar chart
|
||||
AnsiConsole.Render(new BarChart()
|
||||
.Width(60)
|
||||
.Label("[green bold underline]Number of fruits[/]")
|
||||
.CenterLabel()
|
||||
.AddItem(new Fruit("Mango", 3))
|
||||
.AddItems(items));
|
||||
```
|
||||
121
docs/input/widgets/calendar.md
Normal file
@@ -0,0 +1,121 @@
|
||||
Title: Calendar
|
||||
Order: 40
|
||||
RedirectFrom: calendar
|
||||
---
|
||||
|
||||
The `Calendar` is used to render a calendar to the terminal.
|
||||
|
||||
# Usage
|
||||
|
||||
To render a calendar, create a `Calendar` instance with a target date.
|
||||
|
||||
```csharp
|
||||
var calendar = new Calendar(2020,10);
|
||||
AnsiConsole.Render(calendar);
|
||||
```
|
||||
|
||||
```text
|
||||
2020 October
|
||||
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
|
||||
│ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │
|
||||
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
|
||||
│ │ │ │ │ 1 │ 2 │ 3 │
|
||||
│ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │
|
||||
│ 11 │ 12 │ 13 │ 14 │ 15 │ 16 │ 17 │
|
||||
│ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │
|
||||
│ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │
|
||||
│ │ │ │ │ │ │ │
|
||||
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
|
||||
```
|
||||
|
||||
## Culture
|
||||
|
||||
You can set the calendar's culture to show localized weekdays.
|
||||
|
||||
```csharp
|
||||
var calendar = new Calendar(2020,10);
|
||||
calendar.Culture("ja-JP");
|
||||
AnsiConsole.Render(calendar);
|
||||
```
|
||||
|
||||
```text
|
||||
Oktober 2020
|
||||
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
|
||||
│ Mån │ Tis │ Ons │ Tor │ Fre │ Lör │ Sön │
|
||||
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
|
||||
│ │ │ │ 1 │ 2 │ 3 │ 4 │
|
||||
│ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11* │
|
||||
│ 12 │ 13 │ 14 │ 15 │ 16 │ 17 │ 18 │
|
||||
│ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │ 25 │
|
||||
│ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │ │
|
||||
│ │ │ │ │ │ │ │
|
||||
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
|
||||
```
|
||||
|
||||
## Header
|
||||
|
||||
You can hide the calendar header.
|
||||
|
||||
```csharp
|
||||
var calendar = new Calendar(2020,10);
|
||||
calendar.ShowHeader();
|
||||
AnsiConsole.Render(calendar);
|
||||
```
|
||||
|
||||
```text
|
||||
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
|
||||
│ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │
|
||||
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
|
||||
│ │ │ │ │ 1 │ 2 │ 3 │
|
||||
│ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │
|
||||
│ 11 │ 12 │ 13 │ 14 │ 15 │ 16 │ 17 │
|
||||
│ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │
|
||||
│ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │
|
||||
│ │ │ │ │ │ │ │
|
||||
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
|
||||
```
|
||||
|
||||
You can set the header style of the calendar.
|
||||
|
||||
```csharp
|
||||
var calendar = new Calendar(2020, 10);
|
||||
calendar.HeaderStyle(Style.Parse("blue bold"));
|
||||
AnsiConsole.Render(calendar);
|
||||
```
|
||||
|
||||
|
||||
## Calendar Events
|
||||
|
||||
You can add an event to the calendar.
|
||||
If a date has an event associated with it, the date gets highlighted in the calendar.
|
||||
|
||||
```csharp
|
||||
var calendar = new Calendar(2020,10);
|
||||
calendar.AddCalendarEvent(2020, 10, 11);
|
||||
AnsiConsole.Render(calendar);
|
||||
```
|
||||
|
||||
```text
|
||||
2020 October
|
||||
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
|
||||
│ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │
|
||||
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
|
||||
│ │ │ │ │ 1 │ 2 │ 3 │
|
||||
│ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │
|
||||
│ 11* │ 12 │ 13 │ 14 │ 15 │ 16 │ 17 │
|
||||
│ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │
|
||||
│ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │
|
||||
│ │ │ │ │ │ │ │
|
||||
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
|
||||
```
|
||||
|
||||
### Highlight style
|
||||
|
||||
You can set the highlight style for a calendar event via `SetHighlightStyle`.
|
||||
|
||||
```csharp
|
||||
var calendar = new Calendar(2020, 10);
|
||||
calendar.AddCalendarEvent(2020, 10, 11);
|
||||
calendar.HighlightStyle(Style.Parse("yellow bold"));
|
||||
AnsiConsole.Render(calendar);
|
||||
```
|
||||
106
docs/input/widgets/canvas-image.md
Normal file
@@ -0,0 +1,106 @@
|
||||
Title: Canvas Image
|
||||
Order: 70
|
||||
---
|
||||
|
||||
To add [ImageSharp](https://github.com/SixLabors/ImageSharp) superpowers to
|
||||
your console application to draw images, you will need to install
|
||||
the [Spectre.Console.ImageSharp](https://www.nuget.org/packages/Spectre.Console.ImageSharp) NuGet package.
|
||||
|
||||
```text
|
||||
> dotnet add package Spectre.Console.ImageSharp
|
||||
```
|
||||
|
||||
# Loading images
|
||||
|
||||
Once you've added the `Spectre.Console.ImageSharp` NuGet package,
|
||||
you can create a new instance of `CanvasImage` to draw images to the console.
|
||||
|
||||
```csharp
|
||||
// Load an image
|
||||
var image = new CanvasImage("cake.png");
|
||||
|
||||
// Set the max width of the image.
|
||||
// If no max width is set, the image will take
|
||||
// up as much space as there is available.
|
||||
image.MaxWidth(16);
|
||||
|
||||
// Render the image to the console
|
||||
AnsiConsole.Render(image);
|
||||
```
|
||||
|
||||
## Result
|
||||
|
||||
<pre style="font-size:90%;font-family:consolas,'Courier New',monospace;line-height: normal; padding: 0px;background-color: #222222; padding: 20px;">
|
||||
<span> </span><span style="background-color: #542813"> </span><span style="background-color: #572F1B"> </span><span style="background-color: #4E1F09"> </span><span style="background-color: #5B3826"> </span><span style="background-color: #5E3A29"> </span><span style="background-color: #532611"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #562E1B"> </span><span style="background-color: #634737"> </span><span style="background-color: #562E1A"> </span><span style="background-color: #5D4132"> </span><span style="background-color: #6D584B"> </span><span style="background-color: #624332"> </span><span style="background-color: #562B17"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #512714"> </span><span style="background-color: #654E40"> </span><span style="background-color: #705243"> </span><span style="background-color: #745749"> </span><span style="background-color: #6D5B4F"> </span><span style="background-color: #715E52"> </span><span style="background-color: #644636"> </span><span style="background-color: #6A4433"> </span><span style="background-color: #542916"> </span><span style="background-color: #431C0B"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #491E0A"> </span><span style="background-color: #5C3523"> </span><span style="background-color: #695346"> </span><span style="background-color: #705C4F"> </span><span style="background-color: #654838"> </span><span style="background-color: #654A3A"> </span><span style="background-color: #726154"> </span><span style="background-color: #715D50"> </span><span style="background-color: #B8A79F"> </span><span style="background-color: #AE988F"> </span><span style="background-color: #6F4A39"> </span><span style="background-color: #441906"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #532916"> </span><span style="background-color: #8A6C5E"> </span><span style="background-color: #C2B3AB"> </span><span style="background-color: #8B786E"> </span><span style="background-color: #6B584C"> </span><span style="background-color: #695143"> </span><span style="background-color: #6C5648"> </span><span style="background-color: #6F5D51"> </span><span style="background-color: #816A55"> </span><span style="background-color: #E7E1DA"> </span><span style="background-color: #F9F5EE"> </span><span style="background-color: #BAA593"> </span><span style="background-color: #61381F"> </span><span> </span>
|
||||
<span style="background-color: #421C0A"> </span><span style="background-color: #603826"> </span><span style="background-color: #9E8479"> </span><span style="background-color: #E2DAD6"> </span><span style="background-color: #FBF9F6"> </span><span style="background-color: #F0EADF"> </span><span style="background-color: #C4B59D"> </span><span style="background-color: #9D8663"> </span><span style="background-color: #786451"> </span><span style="background-color: #705D4E"> </span><span style="background-color: #BFA052"> </span><span style="background-color: #FEE88B"> </span><span style="background-color: #FDE580"> </span><span style="background-color: #E2C362"> </span><span style="background-color: #794E1D"> </span><span> </span>
|
||||
<span style="background-color: #4B1D05"> </span><span style="background-color: #A6844C"> </span><span style="background-color: #E9D595"> </span><span style="background-color: #F1DC92"> </span><span style="background-color: #F5DD83"> </span><span style="background-color: #FBE278"> </span><span style="background-color: #FFE36E"> </span><span style="background-color: #F1D25E"> </span><span style="background-color: #866F4B"> </span><span style="background-color: #726256"> </span><span style="background-color: #967945"> </span><span style="background-color: #F5D456"> </span><span style="background-color: #F8D756"> </span><span style="background-color: #E1BE4A"> </span><span style="background-color: #7D511B"> </span><span> </span>
|
||||
<span style="background-color: #4F2005"> </span><span style="background-color: #C9A441"> </span><span style="background-color: #FFE05C"> </span><span style="background-color: #FEDF5B"> </span><span style="background-color: #FCDC59"> </span><span style="background-color: #F7D555"> </span><span style="background-color: #E5C04A"> </span><span style="background-color: #795E3B"> </span><span style="background-color: #726256"> </span><span style="background-color: #755F4C"> </span><span style="background-color: #A17124"> </span><span style="background-color: #AE7414"> </span><span style="background-color: #AE791D"> </span><span style="background-color: #794D18"> </span><span> </span>
|
||||
<span style="background-color: #4E1F04"> </span><span style="background-color: #B78D31"> </span><span style="background-color: #DDB33E"> </span><span style="background-color: #D0A132"> </span><span style="background-color: #C28F25"> </span><span style="background-color: #B67E1A"> </span><span style="background-color: #AC7111"> </span><span style="background-color: #9E610A"> </span><span style="background-color: #5F3212"> </span><span style="background-color: #6A574B"> </span><span style="background-color: #726256"> </span><span style="background-color: #744D2A"> </span><span style="background-color: #955401"> </span><span style="background-color: #8C5106"> </span><span style="background-color: #5F310C"> </span><span> </span>
|
||||
<span style="background-color: #4B1A00"> </span><span style="background-color: #854903"> </span><span style="background-color: #9B5A02"> </span><span style="background-color: #995700"> </span><span style="background-color: #935200"> </span><span style="background-color: #592402"> </span><span style="background-color: #5B3F30"> </span><span style="background-color: #726256"> </span><span style="background-color: #705A4A"> </span><span style="background-color: #844C0C"> </span><span style="background-color: #824400"> </span><span style="background-color: #4C1B00"> </span><span> </span>
|
||||
<span style="background-color: #4B1A00"> </span><span style="background-color: #824500"> </span><span style="background-color: #995700"> </span><span style="background-color: #935200"> </span><span style="background-color: #592300"> </span><span style="background-color: #4F2411"> </span><span style="background-color: #6B584C"> </span><span style="background-color: #736256"> </span><span style="background-color: #734E2C"> </span><span style="background-color: #7C4101"> </span><span style="background-color: #4C1B00"> </span><span> </span>
|
||||
<span style="background-color: #4B1A00"> </span><span style="background-color: #824500"> </span><span style="background-color: #995700"> </span><span style="background-color: #935200"> </span><span style="background-color: #592300"> </span><span style="background-color: #4A1902"> </span><span style="background-color: #5C4031"> </span><span style="background-color: #726256"> </span><span style="background-color: #705B4B"> </span><span style="background-color: #6A390F"> </span><span style="background-color: #4C1A00"> </span><span> </span>
|
||||
<span style="background-color: #4B1A00"> </span><span style="background-color: #824500"> </span><span style="background-color: #995700"> </span><span style="background-color: #935200"> </span><span style="background-color: #592300"> </span><span style="background-color: #4A1700"> </span><span style="background-color: #4F2512"> </span><span style="background-color: #6B594D"> </span><span style="background-color: #736256"> </span><span style="background-color: #634432"> </span><span style="background-color: #4C1D08"> </span><span> </span>
|
||||
<span style="background-color: #4B1A00"> </span><span style="background-color: #814400"> </span><span style="background-color: #955400"> </span><span style="background-color: #915100"> </span><span style="background-color: #8C4D00"> </span><span style="background-color: #864800"> </span><span style="background-color: #7F4301"> </span><span style="background-color: #743A01"> </span><span style="background-color: #521E01"> </span><span style="background-color: #4A1700"> </span><span style="background-color: #4A1902"> </span><span style="background-color: #5D4132"> </span><span style="background-color: #726256"> </span><span style="background-color: #6F5B4E"> </span><span style="background-color: #5D3A28"> </span><span style="background-color: #53220C"> </span>
|
||||
<span style="background-color: #471801"> </span><span style="background-color: #642D01"> </span><span style="background-color: #6B3301"> </span><span style="background-color: #642E02"> </span><span style="background-color: #5D2902"> </span><span style="background-color: #542203"> </span><span style="background-color: #4C1C04"> </span><span style="background-color: #461905"> </span><span style="background-color: #4A1C07"> </span><span style="background-color: #4C1A03"> </span><span style="background-color: #4B1801"> </span><span style="background-color: #502613"> </span><span style="background-color: #69564A"> </span><span style="background-color: #705F54"> </span><span style="background-color: #604232"> </span><span style="background-color: #51200A"> </span>
|
||||
<span style="background-color: #411806"> </span><span style="background-color: #431A07"> </span><span style="background-color: #411D0D"> </span><span> </span><span style="background-color: #4D1B05"> </span><span style="background-color: #4D1D07"> </span><span style="background-color: #533324"> </span><span style="background-color: #583E30"> </span><span style="background-color: #53301F"> </span><span style="background-color: #53230D"> </span>
|
||||
</pre>
|
||||
|
||||
# Manipulating images
|
||||
|
||||
You can take full advantage of [ImageSharp](https://github.com/SixLabors/ImageSharp)
|
||||
and manipulate images directly via it's [Processing API](https://docs.sixlabors.com/api/ImageSharp/SixLabors.ImageSharp.Processing.html).
|
||||
|
||||
```csharp
|
||||
// Load an image
|
||||
var image = new CanvasImage("cake.png");
|
||||
image.MaxWidth(32);
|
||||
|
||||
// Set a sampler that will be used when scaling the image.
|
||||
image.BilinearResampler();
|
||||
|
||||
// Mutate the image using ImageSharp
|
||||
image.Mutate(ctx => ctx.Grayscale().Rotate(-45).EntropyCrop());
|
||||
|
||||
// Render the image to the console
|
||||
AnsiConsole.Render(image);
|
||||
```
|
||||
|
||||
## Result
|
||||
|
||||
<pre style="font-size:90%;font-family:consolas,'Courier New',monospace;line-height: normal; padding: 0px;background-color: #222222; padding: 20px;">
|
||||
<span> </span><span style="background-color: #282828"> </span><span style="background-color: #222222"> </span><span style="background-color: #232323"> </span><span style="background-color: #353535"> </span><span style="background-color: #4B4B4B"> </span><span style="background-color: #595959"> </span><span style="background-color: #3B3B3B"> </span><span style="background-color: #202020"> </span><span style="background-color: #191919"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #343434"> </span><span style="background-color: #2B2B2B"> </span><span style="background-color: #292929"> </span><span style="background-color: #272727"> </span><span style="background-color: #252525"> </span><span style="background-color: #292929"> </span><span style="background-color: #555555"> </span><span style="background-color: #929292"> </span><span style="background-color: #C7C7C7"> </span><span style="background-color: #E5E5E5"> </span><span style="background-color: #F0F0F0"> </span><span style="background-color: #E4E4E4"> </span><span style="background-color: #A8A8A8"> </span><span style="background-color: #515151"> </span><span style="background-color: #202020"> </span><span style="background-color: #191919"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #2E2E2E"> </span><span style="background-color: #2B2B2B"> </span><span style="background-color: #333333"> </span><span style="background-color: #373737"> </span><span style="background-color: #3C3C3C"> </span><span style="background-color: #414141"> </span><span style="background-color: #474747"> </span><span style="background-color: #4B4B4B"> </span><span style="background-color: #454545"> </span><span style="background-color: #828282"> </span><span style="background-color: #E0E0E0"> </span><span style="background-color: #FFFFFF"> </span><span style="background-color: #FCFCFC"> </span><span style="background-color: #DEDEDE"> </span><span style="background-color: #DADADA"> </span><span style="background-color: #BCBCBC"> </span><span style="background-color: #515151"> </span><span style="background-color: #202020"> </span><span style="background-color: #191919"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #272727"> </span><span style="background-color: #414141"> </span><span style="background-color: #5C5C5C"> </span><span style="background-color: #616161"> </span><span style="background-color: #636363"> </span><span style="background-color: #656565"> </span><span style="background-color: #666666"> </span><span style="background-color: #656565"> </span><span style="background-color: #5A5A5A"> </span><span style="background-color: #707070"> </span><span style="background-color: #F3F3F3"> </span><span style="background-color: #FFFFFF"> </span><span style="background-color: #F0F0F0"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #BABABA"> </span><span style="background-color: #505050"> </span><span style="background-color: #202020"> </span><span style="background-color: #1B1B1B"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #242424"> </span><span style="background-color: #3B3B3B"> </span><span style="background-color: #545454"> </span><span style="background-color: #606060"> </span><span style="background-color: #656565"> </span><span style="background-color: #666666"> </span><span style="background-color: #606060"> </span><span style="background-color: #575757"> </span><span style="background-color: #E8E8E8"> </span><span style="background-color: #F6F6F6"> </span><span style="background-color: #E1E1E1"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #D9D9D9"> </span><span style="background-color: #A0A0A0"> </span><span style="background-color: #989898"> </span><span style="background-color: #4E4E4E"> </span><span style="background-color: #222222"> </span><span> </span>
|
||||
<span style="background-color: #2F2F2F"> </span><span style="background-color: #2C2C2C"> </span><span style="background-color: #222222"> </span><span style="background-color: #282828"> </span><span style="background-color: #2D2D2D"> </span><span style="background-color: #3E3E3E"> </span><span style="background-color: #4D4D4D"> </span><span style="background-color: #616161"> </span><span style="background-color: #636363"> </span><span style="background-color: #666666"> </span><span style="background-color: #606060"> </span><span style="background-color: #535353"> </span><span style="background-color: #D4D4D4"> </span><span style="background-color: #E2E2E2"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #DCDCDC"> </span><span style="background-color: #AFAFAF"> </span><span style="background-color: #666666"> </span><span style="background-color: #6F6F6F"> </span><span style="background-color: #717171"> </span><span style="background-color: #242424"> </span><span style="background-color: #191919"> </span><span> </span>
|
||||
<span style="background-color: #2C2C2C"> </span><span style="background-color: #343434"> </span><span style="background-color: #2E2E2E"> </span><span style="background-color: #262626"> </span><span style="background-color: #404040"> </span><span style="background-color: #868686"> </span><span style="background-color: #4D4D4D"> </span><span style="background-color: #5A5A5A"> </span><span style="background-color: #3D3D3D"> </span><span style="background-color: #474747"> </span><span style="background-color: #646464"> </span><span style="background-color: #616161"> </span><span style="background-color: #4D4D4D"> </span><span style="background-color: #9D9D9D"> </span><span style="background-color: #C8C8C8"> </span><span style="background-color: #DADADA"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #C4C4C4"> </span><span style="background-color: #717171"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #595959"> </span><span style="background-color: #343434"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #191919"> </span><span> </span>
|
||||
<span style="background-color: #343434"> </span><span style="background-color: #575757"> </span><span style="background-color: #555555"> </span><span style="background-color: #454545"> </span><span style="background-color: #4C4C4C"> </span><span style="background-color: #656565"> </span><span style="background-color: #5B5B5B"> </span><span style="background-color: #434343"> </span><span style="background-color: #3E3E3E"> </span><span style="background-color: #595959"> </span><span style="background-color: #666666"> </span><span style="background-color: #606060"> </span><span style="background-color: #595959"> </span><span style="background-color: #5E5E5E"> </span><span style="background-color: #787878"> </span><span style="background-color: #9E9E9E"> </span><span style="background-color: #797979"> </span><span style="background-color: #5E5E5E"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #575757"> </span><span style="background-color: #343434"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #191919"> </span><span> </span>
|
||||
<span style="background-color: #2B2B2B"> </span><span style="background-color: #3B3B3B"> </span><span style="background-color: #575757"> </span><span style="background-color: #646464"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5E5E5E"> </span><span style="background-color: #575757"> </span><span style="background-color: #3D3D3D"> </span><span style="background-color: #525252"> </span><span style="background-color: #656565"> </span><span style="background-color: #666666"> </span><span style="background-color: #656565"> </span><span style="background-color: #616161"> </span><span style="background-color: #595959"> </span><span style="background-color: #4B4B4B"> </span><span style="background-color: #454545"> </span><span style="background-color: #4B4B4B"> </span><span style="background-color: #555555"> </span><span style="background-color: #5D5D5D"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #575757"> </span><span style="background-color: #343434"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #191919"> </span><span> </span>
|
||||
<span style="background-color: #3A3A3A"> </span><span style="background-color: #292929"> </span><span style="background-color: #323232"> </span><span style="background-color: #4A4A4A"> </span><span style="background-color: #626262"> </span><span style="background-color: #666666"> </span><span style="background-color: #656565"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #616161"> </span><span style="background-color: #5E5E5E"> </span><span style="background-color: #616161"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #666666"> </span><span style="background-color: #626262"> </span><span style="background-color: #575757"> </span><span style="background-color: #4B4B4B"> </span><span style="background-color: #454545"> </span><span style="background-color: #4A4A4A"> </span><span style="background-color: #545454"> </span><span style="background-color: #343434"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #191919"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #252525"> </span><span style="background-color: #383838"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #616161"> </span><span style="background-color: #5B5B5B"> </span><span style="background-color: #505050"> </span><span style="background-color: #545454"> </span><span style="background-color: #8A8A8A"> </span><span style="background-color: #C5C5C5"> </span><span style="background-color: #959595"> </span><span style="background-color: #5E5E5E"> </span><span style="background-color: #636363"> </span><span style="background-color: #666666"> </span><span style="background-color: #626262"> </span><span style="background-color: #595959"> </span><span style="background-color: #4D4D4D"> </span><span style="background-color: #454545"> </span><span style="background-color: #414141"> </span><span style="background-color: #282828"> </span><span style="background-color: #1E1E1E"> </span><span style="background-color: #1D1D1D"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #212121"> </span><span style="background-color: #2C2C2C"> </span><span style="background-color: #4F4F4F"> </span><span style="background-color: #515151"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #898989"> </span><span style="background-color: #CDCDCD"> </span><span style="background-color: #E8E8E8"> </span><span style="background-color: #DEDEDE"> </span><span style="background-color: #D8D8D8"> </span><span style="background-color: #939393"> </span><span style="background-color: #4D4D4D"> </span><span style="background-color: #525252"> </span><span style="background-color: #5E5E5E"> </span><span style="background-color: #646464"> </span><span style="background-color: #666666"> </span><span style="background-color: #636363"> </span><span style="background-color: #5A5A5A"> </span><span style="background-color: #4A4A4A"> </span><span style="background-color: #383838"> </span><span style="background-color: #323232"> </span><span style="background-color: #2A2A2A"> </span><span style="background-color: #282828"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #272727"> </span><span style="background-color: #404040"> </span><span style="background-color: #C8C8C8"> </span><span style="background-color: #DFDFDF"> </span><span style="background-color: #F0F0F0"> </span><span style="background-color: #FDFDFD"> </span><span style="background-color: #F3F3F3"> </span><span style="background-color: #DFDFDF"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #D7D7D7"> </span><span style="background-color: #757575"> </span><span style="background-color: #2B2B2B"> </span><span style="background-color: #333333"> </span><span style="background-color: #444444"> </span><span style="background-color: #535353"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #646464"> </span><span style="background-color: #666666"> </span><span style="background-color: #646464"> </span><span style="background-color: #5B5B5B"> </span><span style="background-color: #4F4F4F"> </span><span style="background-color: #3A3A3A"> </span><span style="background-color: #292929"> </span>
|
||||
<span> </span><span style="background-color: #242424"> </span><span style="background-color: #4F4F4F"> </span><span style="background-color: #E7E7E7"> </span><span style="background-color: #FFFFFF"> </span><span style="background-color: #F2F2F2"> </span><span style="background-color: #DFDFDF"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #C2C2C2"> </span><span style="background-color: #6E6E6E"> </span><span style="background-color: #434343"> </span><span style="background-color: #242424"> </span><span style="background-color: #222222"> </span><span style="background-color: #282828"> </span><span style="background-color: #343434"> </span><span style="background-color: #454545"> </span><span style="background-color: #555555"> </span><span style="background-color: #606060"> </span><span style="background-color: #656565"> </span><span style="background-color: #666666"> </span><span style="background-color: #595959"> </span><span style="background-color: #313131"> </span>
|
||||
<span> </span><span style="background-color: #222222"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #F2F2F2"> </span><span style="background-color: #FFFFFF"> </span><span style="background-color: #F4F4F4"> </span><span style="background-color: #D7D7D7"> </span><span style="background-color: #DCDCDC"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #D1D1D1"> </span><span style="background-color: #818181"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5D5D5D"> </span><span style="background-color: #434343"> </span><span style="background-color: #242424"> </span><span style="background-color: #202020"> </span><span style="background-color: #222222"> </span><span style="background-color: #282828"> </span><span style="background-color: #353535"> </span><span style="background-color: #464646"> </span><span style="background-color: #565656"> </span><span style="background-color: #606060"> </span><span style="background-color: #656565"> </span><span style="background-color: #666666"> </span><span style="background-color: #585858"> </span><span style="background-color: #333333"> </span>
|
||||
<span> </span><span style="background-color: #222222"> </span><span style="background-color: #707070"> </span><span style="background-color: #FAFAFA"> </span><span style="background-color: #D2D2D2"> </span><span style="background-color: #D9D9D9"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #D9D9D9"> </span><span style="background-color: #979797"> </span><span style="background-color: #616161"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5D5D5D"> </span><span style="background-color: #434343"> </span><span style="background-color: #242424"> </span><span style="background-color: #202020"> </span><span style="background-color: #222222"> </span><span style="background-color: #292929"> </span><span style="background-color: #363636"> </span><span style="background-color: #474747"> </span><span style="background-color: #575757"> </span><span style="background-color: #606060"> </span><span style="background-color: #616161"> </span><span style="background-color: #575757"> </span><span style="background-color: #404040"> </span><span style="background-color: #2B2B2B"> </span>
|
||||
<span> </span><span style="background-color: #212121"> </span><span style="background-color: #858585"> </span><span style="background-color: #FCFCFC"> </span><span style="background-color: #D9D9D9"> </span><span style="background-color: #D2D2D2"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #DCDCDC"> </span><span style="background-color: #AEAEAE"> </span><span style="background-color: #666666"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5D5D5D"> </span><span style="background-color: #434343"> </span><span style="background-color: #242424"> </span><span style="background-color: #202020"> </span><span style="background-color: #222222"> </span><span style="background-color: #292929"> </span><span style="background-color: #363636"> </span><span style="background-color: #3E3E3E"> </span><span style="background-color: #363636"> </span><span style="background-color: #2B2B2B"> </span><span style="background-color: #282828"> </span>
|
||||
<span> </span><span style="background-color: #222222"> </span><span style="background-color: #9B9B9B"> </span><span style="background-color: #EAEAEA"> </span><span style="background-color: #D0D0D0"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #C3C3C3"> </span><span style="background-color: #707070"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5D5D5D"> </span><span style="background-color: #434343"> </span><span style="background-color: #242424"> </span><span style="background-color: #202020"> </span><span style="background-color: #212121"> </span><span style="background-color: #242424"> </span><span style="background-color: #272727"> </span><span style="background-color: #2C2C2C"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #292929"> </span><span style="background-color: #ACACAC"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #DCDCDC"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #D1D1D1"> </span><span style="background-color: #818181"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5D5D5D"> </span><span style="background-color: #434343"> </span><span style="background-color: #242424"> </span><span style="background-color: #202020"> </span><span style="background-color: #212121"> </span><span style="background-color: #222222"> </span><span style="background-color: #232323"> </span><span style="background-color: #242424"> </span><span style="background-color: #262626"> </span><span style="background-color: #2E2E2E"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #2D2D2D"> </span><span style="background-color: #A6A6A6"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #D9D9D9"> </span><span style="background-color: #989898"> </span><span style="background-color: #616161"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5D5D5D"> </span><span style="background-color: #3E3E3E"> </span><span style="background-color: #222222"> </span><span style="background-color: #242424"> </span><span style="background-color: #262626"> </span><span style="background-color: #2B2B2B"> </span><span style="background-color: #363636"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #212121"> </span><span style="background-color: #575757"> </span><span style="background-color: #BEBEBE"> </span><span style="background-color: #DDDDDD"> </span><span style="background-color: #DCDCDC"> </span><span style="background-color: #AFAFAF"> </span><span style="background-color: #666666"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5B5B5B"> </span><span style="background-color: #373737"> </span><span style="background-color: #222222"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #171717"> </span><span style="background-color: #212121"> </span><span style="background-color: #585858"> </span><span style="background-color: #BEBEBE"> </span><span style="background-color: #C3C3C3"> </span><span style="background-color: #717171"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5E5E5E"> </span><span style="background-color: #424242"> </span><span style="background-color: #252525"> </span><span style="background-color: #242424"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #171717"> </span><span style="background-color: #212121"> </span><span style="background-color: #545454"> </span><span style="background-color: #717171"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #4D4D4D"> </span><span style="background-color: #292929"> </span><span style="background-color: #232323"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #171717"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #343434"> </span><span style="background-color: #565656"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #565656"> </span><span style="background-color: #303030"> </span><span style="background-color: #222222"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #171717"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #343434"> </span><span style="background-color: #565656"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5C5C5C"> </span><span style="background-color: #393939"> </span><span style="background-color: #232323"> </span><span style="background-color: #252525"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #171717"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #343434"> </span><span style="background-color: #565656"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #5E5E5E"> </span><span style="background-color: #444444"> </span><span style="background-color: #252525"> </span><span style="background-color: #222222"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #171717"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #343434"> </span><span style="background-color: #565656"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #4F4F4F"> </span><span style="background-color: #2A2A2A"> </span><span style="background-color: #222222"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #171717"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #343434"> </span><span style="background-color: #565656"> </span><span style="background-color: #5F5F5F"> </span><span style="background-color: #575757"> </span><span style="background-color: #323232"> </span><span style="background-color: #222222"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #171717"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #343434"> </span><span style="background-color: #565656"> </span><span style="background-color: #5C5C5C"> </span><span style="background-color: #3C3C3C"> </span><span style="background-color: #232323"> </span><span style="background-color: #252525"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #171717"> </span><span style="background-color: #1F1F1F"> </span><span style="background-color: #343434"> </span><span style="background-color: #404040"> </span><span style="background-color: #262626"> </span><span style="background-color: #232323"> </span><span> </span>
|
||||
<span> </span><span style="background-color: #171717"> </span><span style="background-color: #1E1E1E"> </span><span style="background-color: #222222"> </span><span> </span>
|
||||
</pre>
|
||||
52
docs/input/widgets/canvas.md
Normal file
@@ -0,0 +1,52 @@
|
||||
Title: Canvas
|
||||
Order: 60
|
||||
---
|
||||
|
||||
`Canvas` is a widget that allows you to render arbitrary "pixels"
|
||||
(or _coxels_, as [Simon Cropp](https://twitter.com/SimonCropp/status/1331554791726534657?s=20)
|
||||
suggested we should call them).
|
||||
|
||||
# Drawing primitives
|
||||
|
||||
```csharp
|
||||
// Create a canvas
|
||||
var canvas = new Canvas(16, 16);
|
||||
|
||||
// Draw some shapes
|
||||
for(var i = 0; i < canvas.Width; i++)
|
||||
{
|
||||
// Cross
|
||||
canvas.SetPixel(i, i, Color.White);
|
||||
canvas.SetPixel(canvas.Width - i - 1, i, Color.White);
|
||||
|
||||
// Border
|
||||
canvas.SetPixel(i, 0, Color.Red);
|
||||
canvas.SetPixel(0, i, Color.Green);
|
||||
canvas.SetPixel(i, canvas.Height - 1, Color.Blue);
|
||||
canvas.SetPixel(canvas.Width - 1, i, Color.Yellow);
|
||||
}
|
||||
|
||||
// Render the canvas
|
||||
AnsiConsole.Render(canvas);
|
||||
```
|
||||
|
||||
## Result
|
||||
|
||||
<pre style="font-size:100%;font-family:consolas,'Courier New',monospace;line-height: normal; padding: 0px;background-color: #222222; padding: 20px;">
|
||||
<span style="background-color: #008000"> </span><span style="background-color: #FF0000"> </span>
|
||||
<span style="background-color: #008000"> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span style="background-color: #800080"> </span><span> </span><span style="background-color: #800080"> </span><span style="background-color: #FFFF00"> </span>
|
||||
<span style="background-color: #008000"> </span><span style="background-color: #0000FF"> </span><span style="background-color: #FFFF00"> </span>
|
||||
</pre>
|
||||
34
docs/input/widgets/figlet.md
Normal file
@@ -0,0 +1,34 @@
|
||||
Title: Figlet
|
||||
Order: 50
|
||||
RedirectFrom: figlet
|
||||
---
|
||||
|
||||
Spectre.Console can render [FIGlet](http://www.figlet.org/) text by using the `FigletText` class.
|
||||
|
||||
# Default font
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Render(
|
||||
new FigletText("Hello")
|
||||
.LeftAligned()
|
||||
.Color(Color.Red));
|
||||
```
|
||||
|
||||
```text
|
||||
_ _ _ _
|
||||
| | | | ___ | | | | ___
|
||||
| |_| | / _ \ | | | | / _ \
|
||||
| _ | | __/ | | | | | (_) |
|
||||
|_| |_| \___| |_| |_| \___/
|
||||
```
|
||||
|
||||
# Custom font
|
||||
|
||||
```csharp
|
||||
var font = FigletFont.Load("starwars.flf");
|
||||
|
||||
AnsiConsole.Render(
|
||||
new FigletText(font, "Hello")
|
||||
.LeftAligned()
|
||||
.Color(Color.Red));
|
||||
```
|
||||
12
docs/input/widgets/index.cshtml
Normal file
@@ -0,0 +1,12 @@
|
||||
Title: Widgets
|
||||
Order: 9
|
||||
---
|
||||
|
||||
<h1>Sections</h1>
|
||||
|
||||
<ul>
|
||||
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
|
||||
{
|
||||
<li>@Html.DocumentLink(child)</li>
|
||||
}
|
||||
</ul>
|
||||
72
docs/input/widgets/rule.md
Normal file
@@ -0,0 +1,72 @@
|
||||
Title: Rule
|
||||
Order: 30
|
||||
RedirectFrom: rule
|
||||
---
|
||||
|
||||
The `Rule` class is used to render a horizontal rule (line) to the terminal.
|
||||
|
||||
<img src="../assets/images/rule.png" style="width: 100%;" />
|
||||
|
||||
# Usage
|
||||
|
||||
To render a rule without a title:
|
||||
|
||||
```csharp
|
||||
var rule = new Rule();
|
||||
AnsiConsole.Render(rule);
|
||||
```
|
||||
|
||||
## Title
|
||||
|
||||
You can set the rule title markup text.
|
||||
|
||||
```csharp
|
||||
var rule = new Rule("[red]Hello[/]");
|
||||
AnsiConsole.Render(rule);
|
||||
```
|
||||
|
||||
```text
|
||||
───────────────────────────────── Hello ─────────────────────────────────
|
||||
```
|
||||
|
||||
### Title alignment
|
||||
|
||||
You can set the rule's title alignment.
|
||||
|
||||
```csharp
|
||||
var rule = new Rule("[red]Hello[/]");
|
||||
rule.Alignment = Justify.Left;
|
||||
AnsiConsole.Render(rule);
|
||||
```
|
||||
|
||||
```text
|
||||
── Hello ────────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
You can also specify it via an extension method:
|
||||
|
||||
```csharp
|
||||
var rule = new Rule("[red]Hello[/]");
|
||||
rule.LeftAligned();
|
||||
AnsiConsole.Render(rule);
|
||||
```
|
||||
|
||||
```text
|
||||
── Hello ────────────────────────────────────────────────────────────────
|
||||
```
|
||||
|
||||
|
||||
## Styling
|
||||
|
||||
```csharp
|
||||
var rule = new Rule("[red]Hello[/]");
|
||||
rule.Style = Style.Parse("red dim");
|
||||
AnsiConsole.Render(rule);
|
||||
```
|
||||
You can also specify it via an extension method
|
||||
|
||||
```csharp
|
||||
var rule = new Rule("[red]Hello[/]");
|
||||
rule.RuleStyle("red dim");
|
||||
AnsiConsole.Render(rule);
|
||||
```
|
||||
136
docs/input/widgets/table.md
Normal file
@@ -0,0 +1,136 @@
|
||||
Title: Table
|
||||
Order: 0
|
||||
RedirectFrom: tables
|
||||
---
|
||||
|
||||
Tables are a perfect way of displaying tabular data in a terminal.
|
||||
|
||||
`Spectre.Console` is super smart about rendering tables and will adjust
|
||||
all columns to fit whatever is inside them. Anything that implements
|
||||
`IRenderable` can be used as a column header or column cell, even another table!
|
||||
|
||||
# Usage
|
||||
|
||||
<!------------------------->
|
||||
<!--- USAGE --->
|
||||
<!------------------------->
|
||||
|
||||
To render a table, create a `Table` instance, add the number of
|
||||
columns that you need, and then add the rows. Finish by passing the
|
||||
table to a console's `Render` method.
|
||||
|
||||
```csharp
|
||||
// Create a table
|
||||
var table = new Table();
|
||||
|
||||
// Add some columns
|
||||
table.AddColumn("Foo");
|
||||
table.AddColumn(new TableColumn("Bar").Centered());
|
||||
|
||||
// Add some rows
|
||||
table.AddRow("Baz", "[green]Qux[/]");
|
||||
table.AddRow(new Markup("[blue]Corgi[/]"), new Panel("Waldo"));
|
||||
|
||||
// Render the table to the console
|
||||
AnsiConsole.Render(table);
|
||||
```
|
||||
|
||||
This will render the following output:
|
||||
|
||||

|
||||
|
||||
# Table appearance
|
||||
|
||||
<!------------------------->
|
||||
<!--- TABLE APPEARANCE --->
|
||||
<!------------------------->
|
||||
|
||||
## Borders
|
||||
|
||||
For a list of borders, see the [Borders](xref:borders) appendix section.
|
||||
|
||||
```csharp
|
||||
// Sets the border
|
||||
table.Border(TableBorder.None);
|
||||
table.Border(TableBorder.Ascii);
|
||||
table.Border(TableBorder.Square);
|
||||
table.Border(TableBorder.Rounded);
|
||||
```
|
||||
|
||||
## Expand / Collapse
|
||||
|
||||
```csharp
|
||||
// Table will take up as much space as it can
|
||||
// with respect to other things.
|
||||
table.Expand();
|
||||
|
||||
// Table will take up minimal width
|
||||
table.Collapse();
|
||||
```
|
||||
|
||||
## Hide headers
|
||||
|
||||
```csharp
|
||||
// Hides all column headers
|
||||
table.HideHeaders();
|
||||
```
|
||||
|
||||
## Set table width
|
||||
|
||||
```csharp
|
||||
// Sets the table width to 50 cells
|
||||
table.Width(50);
|
||||
```
|
||||
|
||||
## Alignment
|
||||
|
||||
```csharp
|
||||
table.Alignment(Justify.Right);
|
||||
table.RightAligned();
|
||||
table.Centered();
|
||||
table.LeftAligned();
|
||||
```
|
||||
|
||||
# Column appearance
|
||||
|
||||
<!------------------------->
|
||||
<!--- COLUMN APPEARANCE --->
|
||||
<!------------------------->
|
||||
|
||||
## Alignment
|
||||
|
||||
```csharp
|
||||
table.Columns[0].Alignment(Justify.Right);
|
||||
table.Columns[0].LeftAligned();
|
||||
table.Columns[0].Centered();
|
||||
table.Columns[0].RightAligned();
|
||||
```
|
||||
|
||||
## Padding
|
||||
|
||||
```csharp
|
||||
// Set padding individually
|
||||
table.Columns[0].PadLeft(3);
|
||||
table.Columns[0].PadRight(5);
|
||||
|
||||
// Or chained together
|
||||
table.Columns[0].PadLeft(3).PadRight(5);
|
||||
|
||||
// Or with the shorthand method if the left and right
|
||||
// padding are identical. Vertical padding is ignored.
|
||||
table.Columns[0].Padding(4, 0);
|
||||
```
|
||||
|
||||
## Disable column wrapping
|
||||
|
||||
```csharp
|
||||
// Disable column wrapping
|
||||
table.Columns[0].NoWrap();
|
||||
```
|
||||
|
||||
## Set column width
|
||||
|
||||
```csharp
|
||||
// Set the column width
|
||||
table.Columns[0].Width(15);
|
||||
```
|
||||
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 root = new Tree("Root");
|
||||
|
||||
// Add some nodes
|
||||
var foo = root.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 = root.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);
|
||||
```
|
||||
@@ -1,17 +1,23 @@
|
||||
namespace Docs
|
||||
namespace Docs
|
||||
{
|
||||
public static class Constants
|
||||
{
|
||||
public const string NoContainer = nameof(NoContainer);
|
||||
public const string NoSidebar = nameof(NoSidebar);
|
||||
public const string NoLink = nameof(NoLink);
|
||||
public const string Topic = nameof(Topic);
|
||||
public const string EditLink = nameof(EditLink);
|
||||
public const string Description = nameof(Description);
|
||||
public const string Hidden = nameof(Hidden);
|
||||
|
||||
public static class Emojis
|
||||
{
|
||||
public const string Root = "EMOJIS_ROOT";
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
|
||||
7946
docs/src/Data/emojis.json
Normal file
@@ -20,10 +20,7 @@ namespace Docs
|
||||
|
||||
public static Bootstrapper ConfigureDeployment(this Bootstrapper bootstrapper, string deployBranch)
|
||||
{
|
||||
if (bootstrapper != null)
|
||||
{
|
||||
bootstrapper.AddSetting(Constants.Deployment.TargetBranch, deployBranch);
|
||||
}
|
||||
bootstrapper?.AddSetting(Constants.Deployment.TargetBranch, deployBranch);
|
||||
return bootstrapper;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Statiq.Common;
|
||||
using Statiq.Common;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
@@ -16,6 +16,11 @@ namespace Docs
|
||||
return !document.GetBool(Constants.Hidden, false);
|
||||
}
|
||||
|
||||
public static bool ShowLink(this IDocument document)
|
||||
{
|
||||
return !document.GetBool(Constants.NoLink, false);
|
||||
}
|
||||
|
||||
public static IEnumerable<IDocument> OnlyVisible(this IEnumerable<IDocument> source)
|
||||
{
|
||||
return source.Where(x => x.IsVisible());
|
||||
|
||||
20
docs/src/Models/Emoji.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Docs.Models
|
||||
{
|
||||
public sealed class Emoji
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string Code { get; set; }
|
||||
|
||||
public static List<Emoji> Parse(string json)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<List<Emoji>>(json);
|
||||
}
|
||||
}
|
||||
}
|
||||
41
docs/src/Modules/ReadEmbedded.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Statiq.Common;
|
||||
|
||||
namespace Docs.Modules
|
||||
{
|
||||
public sealed class ReadEmbedded : Module
|
||||
{
|
||||
private readonly System.Reflection.Assembly _assembly;
|
||||
private readonly string _resource;
|
||||
|
||||
public ReadEmbedded(System.Reflection.Assembly assembly, string resource)
|
||||
{
|
||||
_assembly = assembly ?? throw new ArgumentNullException(nameof(assembly));
|
||||
_resource = resource ?? throw new ArgumentNullException(nameof(resource));
|
||||
}
|
||||
|
||||
protected override Task<IEnumerable<IDocument>> ExecuteContextAsync(IExecutionContext context)
|
||||
{
|
||||
return Task.FromResult((IEnumerable<IDocument>)new[]
|
||||
{
|
||||
context.CreateDocument(ReadResource()),
|
||||
});
|
||||
}
|
||||
|
||||
private Stream ReadResource()
|
||||
{
|
||||
var resourceName = _resource.Replace("/", ".");
|
||||
|
||||
var stream = _assembly.GetManifestResourceStream(resourceName);
|
||||
if (stream == null)
|
||||
{
|
||||
throw new InvalidOperationException("Could not load manifest resource stream.");
|
||||
}
|
||||
|
||||
return stream;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,13 @@ namespace Docs.Pipelines
|
||||
{
|
||||
public class ColorsPipeline : Pipeline
|
||||
{
|
||||
public const string Url = "https://raw.githubusercontent.com/spectresystems/spectre.console/main/resources/scripts/Generator/Data/colors.json";
|
||||
|
||||
public ColorsPipeline()
|
||||
{
|
||||
InputModules = new ModuleList
|
||||
{
|
||||
new ExecuteConfig(
|
||||
Config.FromContext(ctx => {
|
||||
return new ReadWeb(Url);
|
||||
return new ReadWeb(Constants.Colors.Url);
|
||||
}))
|
||||
};
|
||||
|
||||
@@ -26,15 +24,10 @@ namespace Docs.Pipelines
|
||||
new ExecuteConfig(
|
||||
Config.FromDocument(async (doc, ctx) =>
|
||||
{
|
||||
var colors = Color.Parse(await doc.GetContentStringAsync()).ToList();
|
||||
var definitions = new List<IDocument> { colors.ToDocument(Constants.Colors.Root) };
|
||||
|
||||
return doc.Clone(new MetadataDictionary
|
||||
{
|
||||
[Constants.Colors.Root] = definitions
|
||||
});
|
||||
var data = Color.Parse(await doc.GetContentStringAsync()).ToList();
|
||||
return data.ToDocument(Constants.Colors.Root);
|
||||
}))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
34
docs/src/Pipelines/EmojiPipeline.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using Docs.Models;
|
||||
using Docs.Modules;
|
||||
using Statiq.Common;
|
||||
using Statiq.Core;
|
||||
|
||||
namespace Docs.Pipelines
|
||||
{
|
||||
public class EmojiPipeline : Pipeline
|
||||
{
|
||||
public EmojiPipeline()
|
||||
{
|
||||
InputModules = new ModuleList
|
||||
{
|
||||
new ExecuteConfig(
|
||||
Config.FromContext(ctx => {
|
||||
return new ReadEmbedded(
|
||||
typeof(EmojiPipeline).Assembly,
|
||||
"Docs/src/Data/emojis.json");
|
||||
}))
|
||||
};
|
||||
|
||||
ProcessModules = new ModuleList
|
||||
{
|
||||
new ExecuteConfig(
|
||||
Config.FromDocument(async (doc, ctx) =>
|
||||
{
|
||||
var data = Emoji.Parse(await doc.GetContentStringAsync());
|
||||
return data.ToDocument(Constants.Emojis.Root);
|
||||
}))
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,11 @@ namespace Docs.Shortcodes
|
||||
// Get the definition.
|
||||
var colors = context.Outputs
|
||||
.FromPipeline(nameof(ColorsPipeline))
|
||||
.First()
|
||||
.GetChildren(Constants.Colors.Root)
|
||||
.OfType<ObjectDocument<List<Color>>>()
|
||||
.First().Object;
|
||||
|
||||
var table = new XElement("table", new XAttribute("class", "table"));
|
||||
// Headers
|
||||
var table = new XElement("table", new XAttribute("class", "table"), new XAttribute("id", "color-results"));
|
||||
var header = new XElement("tr", new XAttribute("class", "color-row"));
|
||||
header.Add(new XElement("th", ""));
|
||||
header.Add(new XElement("th", "#"));
|
||||
@@ -34,8 +33,8 @@ namespace Docs.Shortcodes
|
||||
|
||||
foreach (var color in colors)
|
||||
{
|
||||
var rep = new XElement("td",
|
||||
new XElement("span",
|
||||
var rep = new XElement("td",
|
||||
new XElement("span",
|
||||
new XAttribute("class", "color-representation"),
|
||||
new XAttribute("style", $"background-color:{color.Hex};")));
|
||||
var name = new XElement("td", new XElement("code", color.Number.ToString()));
|
||||
@@ -45,7 +44,7 @@ namespace Docs.Shortcodes
|
||||
var clr = new XElement("td", new XElement("code", color.ClrName));
|
||||
|
||||
// Create row
|
||||
var row = new XElement("tr");
|
||||
var row = new XElement("tr", new XAttribute("class", "search-row"));
|
||||
row.Add(rep);
|
||||
row.Add(name);
|
||||
row.Add(number);
|
||||
|
||||
45
docs/src/Shortcodes/EmojiTableShortcode.cs
Normal file
@@ -0,0 +1,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Statiq.Common;
|
||||
using System.Xml.Linq;
|
||||
using Docs.Pipelines;
|
||||
using Docs.Models;
|
||||
|
||||
namespace Docs.Shortcodes
|
||||
{
|
||||
public class EmojiTableShortcode : SyncShortcode
|
||||
{
|
||||
public override ShortcodeResult Execute(KeyValuePair<string, string>[] args, string content, IDocument document, IExecutionContext context)
|
||||
{
|
||||
var emojis = context.Outputs
|
||||
.FromPipeline(nameof(EmojiPipeline))
|
||||
.OfType<ObjectDocument<List<Emoji>>>()
|
||||
.First().Object;
|
||||
|
||||
// Headers
|
||||
var table = new XElement("table", new XAttribute("class", "table"), new XAttribute("id", "emoji-results"));
|
||||
var header = new XElement("tr", new XAttribute("class", "emoji-row-header"));
|
||||
header.Add(new XElement("th", ""));
|
||||
header.Add(new XElement("th", "Markup"));
|
||||
header.Add(new XElement("th", "Constant"));
|
||||
table.Add(header);
|
||||
|
||||
foreach (var emoji in emojis)
|
||||
{
|
||||
var code = emoji.Code.Replace("U+0000", "U+").Replace("U+000", "U+");
|
||||
var icon = $"&#x{emoji.Code.Replace("U+", string.Empty)};";
|
||||
|
||||
var row = new XElement("tr", new XAttribute("class", "search-row"));
|
||||
row.Add(new XElement("td", icon));
|
||||
row.Add(new XElement("td", new XElement("code", $":{emoji.Id}:")));
|
||||
row.Add(new XElement("td", new XElement("code", emoji.Name)));
|
||||
|
||||
table.Add(row);
|
||||
}
|
||||
|
||||
return table.ToString()
|
||||
.Replace("&#x", "&#x");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"cake.tool": {
|
||||
"version": "0.38.4",
|
||||
"version": "1.1.0",
|
||||
"commands": [
|
||||
"dotnet-cake"
|
||||
]
|
||||
@@ -15,7 +15,7 @@
|
||||
]
|
||||
},
|
||||
"dotnet-example": {
|
||||
"version": "0.8.0",
|
||||
"version": "1.2.0",
|
||||
"commands": [
|
||||
"dotnet-example"
|
||||
]
|
||||
|
||||
16
examples/Cli/Delegates/BarSettings.cs
Normal file
@@ -0,0 +1,16 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Examples
|
||||
{
|
||||
public static partial class Program
|
||||
{
|
||||
public sealed class BarSettings : CommandSettings
|
||||
{
|
||||
[CommandOption("--count")]
|
||||
[Description("The number of bars to print")]
|
||||
[DefaultValue(1)]
|
||||
public int Count { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
||||
17
examples/Cli/Delegates/Delegates.csproj
Normal file
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<ExampleName>Delegates</ExampleName>
|
||||
<ExampleDescription>Demonstrates how to specify commands as delegates.</ExampleDescription>
|
||||
<ExampleGroup>Cli</ExampleGroup>
|
||||
<ExampleVisible>false</ExampleVisible>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
38
examples/Cli/Delegates/Program.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Examples
|
||||
{
|
||||
public static partial class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.AddDelegate("foo", Foo)
|
||||
.WithDescription("Foos the bars");
|
||||
|
||||
config.AddDelegate<BarSettings>("bar", Bar)
|
||||
.WithDescription("Bars the foos"); ;
|
||||
});
|
||||
|
||||
return app.Run(args);
|
||||
}
|
||||
|
||||
private static int Foo(CommandContext context)
|
||||
{
|
||||
AnsiConsole.WriteLine("Foo");
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static int Bar(CommandContext context, BarSettings settings)
|
||||
{
|
||||
for (var index = 0; index < settings.Count; index++)
|
||||
{
|
||||
AnsiConsole.WriteLine("Bar");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
47
examples/Cli/Demo/Commands/Add/AddPackageCommand.cs
Normal file
@@ -0,0 +1,47 @@
|
||||
using System.ComponentModel;
|
||||
using Demo.Utilities;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Demo.Commands
|
||||
{
|
||||
[Description("Add a NuGet package reference to the project.")]
|
||||
public sealed class AddPackageCommand : Command<AddPackageCommand.Settings>
|
||||
{
|
||||
public sealed class Settings : AddSettings
|
||||
{
|
||||
[CommandArgument(0, "<PACKAGENAME>")]
|
||||
[Description("The package reference to add.")]
|
||||
public string PackageName { get; set; }
|
||||
|
||||
[CommandOption("-v|--version <VERSION>")]
|
||||
[Description("The version of the package to add.")]
|
||||
public string Version { get; set; }
|
||||
|
||||
[CommandOption("-f|--framework <FRAMEWORK>")]
|
||||
[Description("Add the reference only when targeting a specific framework.")]
|
||||
public string Framework { get; set; }
|
||||
|
||||
[CommandOption("--no-restore")]
|
||||
[Description("Add the reference without performing restore preview and compatibility check.")]
|
||||
public bool NoRestore { get; set; }
|
||||
|
||||
[CommandOption("--source <SOURCE>")]
|
||||
[Description("The NuGet package source to use during the restore.")]
|
||||
public string Source { get; set; }
|
||||
|
||||
[CommandOption("--package-directory <PACKAGEDIR>")]
|
||||
[Description("The directory to restore packages to.")]
|
||||
public string PackageDirectory { get; set; }
|
||||
|
||||
[CommandOption("--interactive")]
|
||||
[Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")]
|
||||
public bool Interactive { get; set; }
|
||||
}
|
||||
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
SettingsDumper.Dump(settings);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
30
examples/Cli/Demo/Commands/Add/AddReferenceCommand.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System.ComponentModel;
|
||||
using Demo.Utilities;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Demo.Commands
|
||||
{
|
||||
public sealed class AddReferenceCommand : Command<AddReferenceCommand.Settings>
|
||||
{
|
||||
public sealed class Settings : AddSettings
|
||||
{
|
||||
[CommandArgument(0, "<PROJECTPATH>")]
|
||||
[Description("The package reference to add.")]
|
||||
public string ProjectPath { get; set; }
|
||||
|
||||
[CommandOption("-f|--framework <FRAMEWORK>")]
|
||||
[Description("Add the reference only when targeting a specific framework.")]
|
||||
public string Framework { get; set; }
|
||||
|
||||
[CommandOption("--interactive")]
|
||||
[Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")]
|
||||
public bool Interactive { get; set; }
|
||||
}
|
||||
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
SettingsDumper.Dump(settings);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
examples/Cli/Demo/Commands/Add/AddSettings.cs
Normal file
@@ -0,0 +1,12 @@
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Demo.Commands
|
||||
{
|
||||
public abstract class AddSettings : CommandSettings
|
||||
{
|
||||
[CommandArgument(0, "<PROJECT>")]
|
||||
[Description("The project file to operate on. If a file is not specified, the command will search the current directory for one.")]
|
||||
public string Project { get; set; }
|
||||
}
|
||||
}
|
||||
70
examples/Cli/Demo/Commands/Run/RunCommand.cs
Normal file
@@ -0,0 +1,70 @@
|
||||
using System.ComponentModel;
|
||||
using Demo.Utilities;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Demo.Commands
|
||||
{
|
||||
[Description("Build and run a .NET project output.")]
|
||||
public sealed class RunCommand : Command<RunCommand.Settings>
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("-c|--configuration <CONFIGURATION>")]
|
||||
[Description("The configuration to run for. The default for most projects is '[grey]Debug[/]'.")]
|
||||
[DefaultValue("Debug")]
|
||||
public string Configuration { get; set; }
|
||||
|
||||
[CommandOption("-f|--framework <FRAMEWORK>")]
|
||||
[Description("The target framework to run for. The target framework must also be specified in the project file.")]
|
||||
public string Framework { get; set; }
|
||||
|
||||
[CommandOption("-r|--runtime <RUNTIMEIDENTIFIER>")]
|
||||
[Description("The target runtime to run for.")]
|
||||
public string RuntimeIdentifier { get; set; }
|
||||
|
||||
[CommandOption("-p|--project <PROJECTPATH>")]
|
||||
[Description("The path to the project file to run (defaults to the current directory if there is only one project).")]
|
||||
public string ProjectPath { get; set; }
|
||||
|
||||
[CommandOption("--launch-profile <LAUNCHPROFILE>")]
|
||||
[Description("The name of the launch profile (if any) to use when launching the application.")]
|
||||
public string LaunchProfile { get; set; }
|
||||
|
||||
[CommandOption("--no-launch-profile")]
|
||||
[Description("Do not attempt to use [grey]launchSettings.json[/] to configure the application.")]
|
||||
public bool NoLaunchProfile { get; set; }
|
||||
|
||||
[CommandOption("--no-build")]
|
||||
[Description("Do not build the project before running. Implies [grey]--no-restore[/].")]
|
||||
public bool NoBuild { get; set; }
|
||||
|
||||
[CommandOption("--interactive")]
|
||||
[Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")]
|
||||
public string Interactive { get; set; }
|
||||
|
||||
[CommandOption("--no-restore")]
|
||||
[Description("Do not restore the project before building.")]
|
||||
public bool NoRestore { get; set; }
|
||||
|
||||
[CommandOption("--verbosity <VERBOSITY>")]
|
||||
[Description("Set the MSBuild verbosity level. Allowed values are q[grey]uiet[/], m[grey]inimal[/], n[grey]ormal[/], d[grey]etailed[/], and diag[grey]nostic[/].")]
|
||||
[TypeConverter(typeof(VerbosityConverter))]
|
||||
[DefaultValue(Verbosity.Normal)]
|
||||
public Verbosity Verbosity { get; set; }
|
||||
|
||||
[CommandOption("--no-dependencies")]
|
||||
[Description("Do not restore project-to-project references and only restore the specified project.")]
|
||||
public bool NoDependencies { get; set; }
|
||||
|
||||
[CommandOption("--force")]
|
||||
[Description("Force all dependencies to be resolved even if the last restore was successful. This is equivalent to deleting [grey]project.assets.json[/].")]
|
||||
public bool Force { get; set; }
|
||||
}
|
||||
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
SettingsDumper.Dump(settings);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
41
examples/Cli/Demo/Commands/Serve/ServeCommand.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Demo.Utilities;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Demo.Commands
|
||||
{
|
||||
[Description("Launches a web server in the current working directory and serves all files in it.")]
|
||||
public sealed class ServeCommand : Command<ServeCommand.Settings>
|
||||
{
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("-p|--port <PORT>")]
|
||||
[Description("Port to use. Defaults to [grey]8080[/]. Use [grey]0[/] for a dynamic port.")]
|
||||
public int Port { get; set; }
|
||||
|
||||
[CommandOption("-o|--open-browser [BROWSER]")]
|
||||
[Description("Open a web browser when the server starts. You can also specify which browser to use. If none is specified, the default one will be used.")]
|
||||
public FlagValue<string> OpenBrowser { get; set; }
|
||||
}
|
||||
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
if (settings.OpenBrowser.IsSet)
|
||||
{
|
||||
var browser = settings.OpenBrowser.Value;
|
||||
if (browser != null)
|
||||
{
|
||||
Console.WriteLine($"Open in {browser}");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"Open in default browser.");
|
||||
}
|
||||
}
|
||||
|
||||
SettingsDumper.Dump(settings);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
17
examples/Cli/Demo/Demo.csproj
Normal file
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<ExampleName>Demo</ExampleName>
|
||||
<ExampleDescription>Demonstrates the most common use cases of Spectre.Cli.</ExampleDescription>
|
||||
<ExampleGroup>Cli</ExampleGroup>
|
||||
<ExampleVisible>false</ExampleVisible>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
37
examples/Cli/Demo/Program.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using Demo.Commands;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Demo
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
config.SetApplicationName("fake-dotnet");
|
||||
config.ValidateExamples();
|
||||
config.AddExample(new[] { "run", "--no-build" });
|
||||
|
||||
// Run
|
||||
config.AddCommand<RunCommand>("run");
|
||||
|
||||
// Add
|
||||
config.AddBranch<AddSettings>("add", add =>
|
||||
{
|
||||
add.SetDescription("Add a package or reference to a .NET project");
|
||||
add.AddCommand<AddPackageCommand>("package");
|
||||
add.AddCommand<AddReferenceCommand>("reference");
|
||||
});
|
||||
|
||||
// Serve
|
||||
config.AddCommand<ServeCommand>("serve")
|
||||
.WithExample(new[] { "serve", "-o", "firefox" })
|
||||
.WithExample(new[] { "serve", "--port", "80", "-o", "firefox" });
|
||||
});
|
||||
|
||||
return app.Run(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
29
examples/Cli/Demo/Utilities/SettingsDumper.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using Spectre.Console;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Demo.Utilities
|
||||
{
|
||||
public static class SettingsDumper
|
||||
{
|
||||
public static void Dump(CommandSettings settings)
|
||||
{
|
||||
var table = new Table().RoundedBorder();
|
||||
table.AddColumn("[grey]Name[/]");
|
||||
table.AddColumn("[grey]Value[/]");
|
||||
|
||||
var properties = settings.GetType().GetProperties();
|
||||
foreach (var property in properties)
|
||||
{
|
||||
var value = property.GetValue(settings)
|
||||
?.ToString()
|
||||
?.Replace("[", "[[");
|
||||
|
||||
table.AddRow(
|
||||
property.Name,
|
||||
value ?? "[grey]null[/]");
|
||||
}
|
||||
|
||||
AnsiConsole.Render(table);
|
||||
}
|
||||
}
|
||||
}
|
||||
54
examples/Cli/Demo/Verbosity.cs
Normal file
@@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
|
||||
namespace Demo
|
||||
{
|
||||
public enum Verbosity
|
||||
{
|
||||
Quiet,
|
||||
Minimal,
|
||||
Normal,
|
||||
Detailed,
|
||||
Diagnostic
|
||||
}
|
||||
|
||||
public sealed class VerbosityConverter : TypeConverter
|
||||
{
|
||||
private readonly Dictionary<string, Verbosity> _lookup;
|
||||
|
||||
public VerbosityConverter()
|
||||
{
|
||||
_lookup = new Dictionary<string, Verbosity>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ "q", Verbosity.Quiet },
|
||||
{ "quiet", Verbosity.Quiet },
|
||||
{ "m", Verbosity.Minimal },
|
||||
{ "minimal", Verbosity.Minimal },
|
||||
{ "n", Verbosity.Normal },
|
||||
{ "normal", Verbosity.Normal },
|
||||
{ "d", Verbosity.Detailed },
|
||||
{ "detailed", Verbosity.Detailed },
|
||||
{ "diag", Verbosity.Diagnostic },
|
||||
{ "diagnostic", Verbosity.Diagnostic }
|
||||
};
|
||||
}
|
||||
|
||||
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.");
|
||||
}
|
||||
}
|
||||
}
|
||||
17
examples/Cli/Dynamic/Dynamic.csproj
Normal file
@@ -0,0 +1,17 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<ExampleName>Dynamic</ExampleName>
|
||||
<ExampleDescription>Demonstrates how to define dynamic commands.</ExampleDescription>
|
||||
<ExampleGroup>Cli</ExampleGroup>
|
||||
<ExampleVisible>false</ExampleVisible>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
20
examples/Cli/Dynamic/MyCommand.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Examples
|
||||
{
|
||||
public sealed class MyCommand : Command
|
||||
{
|
||||
public override int Execute(CommandContext context)
|
||||
{
|
||||
if (!(context.Data is int data))
|
||||
{
|
||||
throw new InvalidOperationException("Command has no associated data.");
|
||||
|
||||
}
|
||||
|
||||
AnsiConsole.WriteLine("Value = {0}", data);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
24
examples/Cli/Dynamic/Program.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using System.Linq;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Examples
|
||||
{
|
||||
public static class Program
|
||||
{
|
||||
public static int Main(string[] args)
|
||||
{
|
||||
var app = new CommandApp();
|
||||
app.Configure(config =>
|
||||
{
|
||||
foreach(var index in Enumerable.Range(1, 10))
|
||||
{
|
||||
config.AddCommand<MyCommand>($"c{index}")
|
||||
.WithDescription($"Prints the number {index}")
|
||||
.WithData(index);
|
||||
}
|
||||
});
|
||||
|
||||
return app.Run(args);
|
||||
}
|
||||
}
|
||||
}
|
||||
30
examples/Cli/Injection/Commands/DefaultCommand.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Examples
|
||||
{
|
||||
public sealed class DefaultCommand : Command<DefaultCommand.Settings>
|
||||
{
|
||||
private readonly IGreeter _greeter;
|
||||
|
||||
public sealed class Settings : CommandSettings
|
||||
{
|
||||
[CommandOption("-n|--name <NAME>")]
|
||||
[Description("The person or thing to greet.")]
|
||||
[DefaultValue("World")]
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
public DefaultCommand(IGreeter greeter)
|
||||
{
|
||||
_greeter = greeter ?? throw new ArgumentNullException(nameof(greeter));
|
||||
}
|
||||
|
||||
public override int Execute(CommandContext context, Settings settings)
|
||||
{
|
||||
_greeter.Greet(settings.Name);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
15
examples/Cli/Injection/IGreeter.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace Spectre.Console.Examples
|
||||
{
|
||||
public interface IGreeter
|
||||
{
|
||||
void Greet(string name);
|
||||
}
|
||||
|
||||
public sealed class HelloWorldGreeter : IGreeter
|
||||
{
|
||||
public void Greet(string name)
|
||||
{
|
||||
AnsiConsole.WriteLine($"Hello {name}!");
|
||||
}
|
||||
}
|
||||
}
|
||||
41
examples/Cli/Injection/Infrastructure/TypeRegistrar.cs
Normal 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, (provider) => func());
|
||||
}
|
||||
}
|
||||
}
|
||||
29
examples/Cli/Injection/Infrastructure/TypeResolver.cs
Normal file
@@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Spectre.Console.Cli;
|
||||
|
||||
namespace Spectre.Console.Examples
|
||||
{
|
||||
public sealed class TypeResolver : ITypeResolver, IDisposable
|
||||
{
|
||||
private readonly IServiceProvider _provider;
|
||||
|
||||
public TypeResolver(IServiceProvider provider)
|
||||
{
|
||||
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
|
||||
}
|
||||
|
||||
public object Resolve(Type type)
|
||||
{
|
||||
return _provider.GetRequiredService(type);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_provider is IDisposable disposable)
|
||||
{
|
||||
disposable.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
21
examples/Cli/Injection/Injection.csproj
Normal file
@@ -0,0 +1,21 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<ExampleName>Injection</ExampleName>
|
||||
<ExampleDescription>Demonstrates how to use dependency injection with Spectre.Cli.</ExampleDescription>
|
||||
<ExampleGroup>Cli</ExampleGroup>
|
||||
<ExampleVisible>false</ExampleVisible>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||