Compare commits
103 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
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.
|
||||||
26
.github/workflows/ci.yaml
vendored
@@ -21,7 +21,7 @@ jobs:
|
|||||||
- name: Setup dotnet
|
- name: Setup dotnet
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: '3.1.301' # SDK Version to use.
|
dotnet-version: 5.0.100
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -55,24 +55,32 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup dotnet
|
- name: Setup dotnet 3.1.402
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
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.100
|
||||||
|
|
||||||
- name: Integration Tests
|
- name: Integration Tests
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
dotnet tool restore
|
dotnet tool restore
|
||||||
dotnet example info
|
dotnet example --all
|
||||||
dotnet example table
|
|
||||||
dotnet example grid
|
|
||||||
dotnet example panel
|
|
||||||
dotnet example colors
|
|
||||||
dotnet example emojis
|
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
dotnet tool restore
|
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
|
- name: Setup dotnet
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: '3.1.301' # SDK Version to use.
|
dotnet-version: 5.0.100
|
||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
20
.github/workflows/publish.yaml
vendored
@@ -29,7 +29,7 @@ jobs:
|
|||||||
- name: Setup dotnet
|
- name: Setup dotnet
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: '3.1.301' # SDK Version to use.
|
dotnet-version: 5.0.100
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -64,10 +64,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup dotnet
|
- name: Setup dotnet 3.1.402
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
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.100
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -90,10 +95,15 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- name: Setup dotnet
|
- name: Setup dotnet 3.1.402
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
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.100
|
||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
4
.gitignore
vendored
@@ -5,6 +5,7 @@
|
|||||||
[Pp]ackages/
|
[Pp]ackages/
|
||||||
/.artifacts/
|
/.artifacts/
|
||||||
/[Tt]ools/
|
/[Tt]ools/
|
||||||
|
.idea
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
# Cakeup
|
# Cakeup
|
||||||
@@ -78,7 +79,6 @@ x64/
|
|||||||
_ReSharper*
|
_ReSharper*
|
||||||
|
|
||||||
# NCrunch
|
# NCrunch
|
||||||
*.ncrunch*
|
|
||||||
.*crunch*.local.xml
|
.*crunch*.local.xml
|
||||||
_NCrunch_*
|
_NCrunch_*
|
||||||
|
|
||||||
@@ -87,3 +87,5 @@ packages
|
|||||||
|
|
||||||
# Windows
|
# Windows
|
||||||
Thumbs.db
|
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/spectresystems/spectre.console/blob/main/LICENSE) the contribution under the terms applied to the rest of the Spectre.Console project.
|
||||||
|
* You agree to follow the [code of conduct](https://github.com/spectresystems/spectre.console/blob/main/CODE_OF_CONDUCT.md).
|
||||||
|
|
||||||
|
## Definition of trivial contributions
|
||||||
|
It's hard to define what is a trivial contribution. Sometimes even a 1 character change can be considered significant.
|
||||||
|
Unfortunately because it can be subjective, the decision on what is trivial comes from the maintainers of the project
|
||||||
|
and not from folks contributing to the project.
|
||||||
|
|
||||||
|
What is generally considered trivial:
|
||||||
|
|
||||||
|
* Fixing a typo.
|
||||||
|
* Documentation changes.
|
||||||
|
|
||||||
|
## Code
|
||||||
|
### Code style
|
||||||
|
|
||||||
|
Normal .NET coding guidelines apply.
|
||||||
|
See the [Framework Design Guidelines](https://msdn.microsoft.com/en-us/library/ms229042%28v=vs.110%29.aspx) for more information.
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
The assembly `Spectre.Console` should have no dependencies except the .NET BCL library.
|
||||||
|
|
||||||
|
### Unit tests
|
||||||
|
|
||||||
|
Make sure to run all unit tests before creating a pull request.
|
||||||
|
Any new code should also have reasonable unit test coverage.
|
||||||
|
|
||||||
|
## Contributing process
|
||||||
|
### Get buyoff or find open community issues or features
|
||||||
|
|
||||||
|
* Through GitHub, or through the [GitHub discussions](https://github.com/spectresystems/spectre.console/discussions) (preferred),
|
||||||
|
you talk about a feature you would like to see (or a bug), and why it should be in Spectre.Console.
|
||||||
|
* If approved through the GitHub discussions, ensure an accompanying GitHub issue is created with
|
||||||
|
information and a link back to the discussion.
|
||||||
|
* Once you get a nod from someone in the Spectre.Console Team, you can start on the feature.
|
||||||
|
* Alternatively, if a feature is on the issues list with the
|
||||||
|
[Up For Grabs](https://github.com/spectresystems/spectre.console/labels/up-for-grabs) label,
|
||||||
|
it is open for a community member (contributor) to patch. You should comment that you are signing up for it on
|
||||||
|
the issue so someone else doesn't also sign up for the work.
|
||||||
|
|
||||||
|
### Set up your environment
|
||||||
|
|
||||||
|
* You create, or update, a fork of `spectresystems/spectre.console` under your GitHub account.
|
||||||
|
* From there you create a branch named specific to the feature.
|
||||||
|
* In the branch you do work specific to the feature.
|
||||||
|
* Please also observe the following:
|
||||||
|
* No reformatting
|
||||||
|
* No changing files that are not specific to the feature.
|
||||||
|
* More covered below in the **Prepare commits** section.
|
||||||
|
* Test your changes and please help us out by updating and implementing some automated tests.
|
||||||
|
It is recommended that all contributors spend some time looking over the tests in the source code.
|
||||||
|
You can't go wrong emulating one of the existing tests and then changing it specific to the behavior you are testing.
|
||||||
|
* Please do not update your branch from the main branch unless we ask you to. See the responding to feedback section below.
|
||||||
|
|
||||||
|
### Prepare commits
|
||||||
|
This section serves to help you understand what makes a good commit.
|
||||||
|
|
||||||
|
A commit should observe the following:
|
||||||
|
|
||||||
|
* A commit is a small logical unit that represents a change.
|
||||||
|
* Should include new or changed tests relevant to the changes you are making.
|
||||||
|
* No unnecessary whitespace. Check for whitespace with `git diff --check` and `git diff --cached --check` before commit.
|
||||||
|
* You can stage parts of a file for commit.
|
||||||
|
|
||||||
|
### Submit pull request
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
* You are making commits in a feature branch.
|
||||||
|
* All code should compile without errors or warnings.
|
||||||
|
* All tests should be passing.
|
||||||
|
|
||||||
|
Submitting PR:
|
||||||
|
|
||||||
|
* Once you feel it is ready, submit the pull request to the `spectresystems/spectre.console` repository against the `main` branch
|
||||||
|
unless specifically requested to submit it against another branch.
|
||||||
|
* In the case of a larger change that is going to require more discussion,
|
||||||
|
please submit a PR sooner. Waiting until you are ready may mean more changes than you are
|
||||||
|
interested in if the changes are taking things in a direction the maintainers do not want to go.
|
||||||
|
* In the pull request, outline what you did and point to specific conversations (as in URLs)
|
||||||
|
and issues that you are resolving. This is a tremendous help for us in evaluation and acceptance.
|
||||||
|
* Once the pull request is in, please do not delete the branch or close the pull request
|
||||||
|
(unless something is wrong with it).
|
||||||
|
* One of the Spectre.Console team members, or one of the maintainers, will evaluate it within a
|
||||||
|
reasonable time period (which is to say usually within 1-3 weeks). Some things get evaluated
|
||||||
|
faster or fast tracked. We are human and we have active lives outside of open source so don't
|
||||||
|
fret if you haven't seen any activity on your pull request within a month or two.
|
||||||
|
We don't have a Service Level Agreement (SLA) for pull requests.
|
||||||
|
Just know that we will evaluate your pull request.
|
||||||
|
|
||||||
|
### Respond to feedback on pull request
|
||||||
|
|
||||||
|
We may have feedback for you to fix or change some things. We generally like to see that pushed against
|
||||||
|
the same topic branch (it will automatically update the Pull Request). You can also fix/squash/rebase
|
||||||
|
commits and push the same topic branch with `--force` (it's generally acceptable to do this on topic
|
||||||
|
branches not in the main repository, it is generally unacceptable and should be avoided at all costs
|
||||||
|
against the main repository).
|
||||||
|
|
||||||
|
If we have comments or questions when we do evaluate it and receive no response, it will probably
|
||||||
|
lessen the chance of getting accepted. Eventually, this means it will be closed if it is not accepted.
|
||||||
|
Please know this doesn't mean we don't value your contribution, just that things go stale. If in the
|
||||||
|
future you want to pick it back up, feel free to address our concerns/questions/feedback and reopen
|
||||||
|
the issue/open a new PR (referencing old one).
|
||||||
|
|
||||||
|
Sometimes we may need you to rebase your commit against the latest code before we can review it further.
|
||||||
|
If this happens, you can do the following:
|
||||||
|
|
||||||
|
* `git fetch upstream` (upstream remote would be `spectresystems/spectre.console`)
|
||||||
|
* `git checkout main`
|
||||||
|
* `git rebase upstream/main`
|
||||||
|
* `git checkout your-branch`
|
||||||
|
* `git rebase main`
|
||||||
|
* Fix any merge conflicts
|
||||||
|
* `git push origin your-branch` (origin would be your GitHub repo or `your-github-username/spectre.console` in this case).
|
||||||
|
You may need to `git push origin your-branch --force` to get the commits pushed.
|
||||||
|
This is generally acceptable with topic branches not in the mainstream repository.
|
||||||
|
|
||||||
|
The only reasons a pull request should be closed and resubmitted are as follows:
|
||||||
|
|
||||||
|
* When the pull request is targeting the wrong branch (this doesn't happen as often).
|
||||||
|
* When there are updates made to the original by someone other than the original contributor.
|
||||||
|
Then the old branch is closed with a note on the newer branch this supersedes #github_number.
|
||||||
|
|
||||||
|
## Other general information
|
||||||
|
If you reformat code or hit core functionality without an approval from a person on the Spectre.Console Team,
|
||||||
|
it's likely that no matter how awesome it looks afterwards, it will probably not get accepted.
|
||||||
|
Reformatting code makes it harder for us to evaluate exactly what was changed.
|
||||||
|
|
||||||
|
If you do these things, it will be make evaluation and acceptance easy.
|
||||||
|
Now if you stray outside of the guidelines we have above, it doesn't mean we are going to ignore
|
||||||
|
your pull request. It will just make things harder for us.
|
||||||
|
Harder for us roughly translates to a longer SLA for your pull request.
|
||||||
|
|
||||||
|
## Acknowledgement
|
||||||
|
|
||||||
|
This contribution guide was taken from the [Chocolatey project](https://chocolatey.org/)
|
||||||
|
with permission and was edited to follow Spectre.Console's conventions and processes.
|
||||||
413
README.jp.md
Normal file
@@ -0,0 +1,413 @@
|
|||||||
|
# `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. │
|
||||||
|
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
|
||||||
|
```
|
||||||
|
|
||||||
|
そして、例を実行します
|
||||||
|
|
||||||
|
```
|
||||||
|
> 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),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
97
README.md
@@ -2,18 +2,17 @@
|
|||||||
|
|
||||||
_[](https://www.nuget.org/packages/spectre.console)_
|
_[](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)
|
It is heavily inspired by the excellent [Rich library](https://github.com/willmcgugan/rich)
|
||||||
for Python.
|
for Python.
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
1. [Features](#features)
|
1. [Features](#features)
|
||||||
2. [Example](#example)
|
2. [Installing](#installing)
|
||||||
3. [Usage](#usage)
|
3. [Documentation](#documentation)
|
||||||
3.1. [Using the static API](#using-the-static-api)
|
4. [Examples](#examples)
|
||||||
3.2. [Creating a console](#creating-a-console)
|
5. [License](#license)
|
||||||
4. [Running examples](#running-examples)
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -26,98 +25,48 @@ for Python.
|
|||||||
The library will detect the capabilities of the current 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.
|
The fastest way of getting started using `Spectre.Console` is to install the NuGet package.
|
||||||
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.
|
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
AnsiConsole.Foreground = Color.CornflowerBlue;
|
dotnet add package Spectre.Console
|
||||||
AnsiConsole.Decoration = Decoration.Underline | Decoration.Bold;
|
|
||||||
AnsiConsole.WriteLine("Hello World!");
|
|
||||||
|
|
||||||
AnsiConsole.Reset();
|
|
||||||
AnsiConsole.MarkupLine("[bold yellow on red]{0}[/] [underline]world[/]!", "Goodbye");
|
|
||||||
```
|
```
|
||||||
|
|
||||||
If you want to get a reference to the default `IAnsiConsole`,
|
## Documentation
|
||||||
you can access it via `AnsiConsole.Console`.
|
|
||||||
|
|
||||||
### Creating a console
|
The documentation for `Spectre.Console` can be found at
|
||||||
|
https://spectresystems.github.io/spectre.console/
|
||||||
|
|
||||||
Sometimes it's useful to explicitly create a console with specific
|
## Examples
|
||||||
capabilities, such as during unit testing when you want control
|
|
||||||
over the environment your code runs in.
|
|
||||||
|
|
||||||
It's recommended to not use `AnsiConsole` in code that run as
|
To see `Spectre.Console` in action, install the
|
||||||
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
|
|
||||||
[dotnet-example](https://github.com/patriksvensson/dotnet-example)
|
[dotnet-example](https://github.com/patriksvensson/dotnet-example)
|
||||||
global tool.
|
global tool.
|
||||||
|
|
||||||
```
|
```
|
||||||
> dotnet tool install -g dotnet-example
|
> dotnet tool restore
|
||||||
```
|
```
|
||||||
|
|
||||||
Now you can list available examples in this repository:
|
Now you can list available examples in this repository:
|
||||||
|
|
||||||
```
|
```
|
||||||
> dotnet example
|
> 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:
|
And to run an example:
|
||||||
|
|
||||||
```
|
```
|
||||||
> dotnet example table
|
> dotnet example tables
|
||||||
┌──────────┬──────────┬────────┐
|
|
||||||
│ Foo │ Bar │ Baz │
|
|
||||||
├──────────┼──────────┼────────┤
|
|
||||||
│ Hello │ World! │ │
|
|
||||||
│ Bonjour │ le │ monde! │
|
|
||||||
│ Hej │ Världen! │ │
|
|
||||||
└──────────┴──────────┴────────┘
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright © Spectre Systems.
|
||||||
|
|
||||||
|
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://spectresystems.github.io/spectre.console/
|
||||||
|
|
||||||
|
## 例子
|
||||||
|
|
||||||
|
如果想直接运行`Spectre.Console`的例子,则需要安装[dotnet-example](https://github.com/patriksvensson/dotnet-example)工具。
|
||||||
|
|
||||||
|
```
|
||||||
|
> dotnet tool restore
|
||||||
|
```
|
||||||
|
|
||||||
|
然后你可以列出仓库里的所有例子:
|
||||||
|
|
||||||
|
```
|
||||||
|
> dotnet example
|
||||||
|
```
|
||||||
|
|
||||||
|
跑一个看看效果:
|
||||||
|
|
||||||
|
```
|
||||||
|
> dotnet example tables
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
版权所有 © Spectre Systems。
|
||||||
|
|
||||||
|
Spectre.Console 基于 MIT 协议提供。查看 LICENSE 文件了解更多信息。
|
||||||
|
|
||||||
|
* SixLabors.ImageSharp 的协议请查看 https://github.com/SixLabors/ImageSharp/blob/master/LICENSE
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
|
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
|
||||||
<DefaultItemExcludes>$(DefaultItemExcludes);output\**;.gitignore</DefaultItemExcludes>
|
<DefaultItemExcludes>$(DefaultItemExcludes);output\**;.gitignore</DefaultItemExcludes>
|
||||||
<MinVerSkip Condition="'$(Configuration)' == 'Debug'">true</MinVerSkip>
|
<MinVerSkip Condition="'$(Configuration)' == 'Debug'">true</MinVerSkip>
|
||||||
@@ -31,8 +31,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Statiq.Web" Version="1.0.0-beta.5" />
|
<PackageReference Include="Statiq.Web" Version="1.0.0-beta.13" />
|
||||||
<PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.0" />
|
<PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,8 +1,50 @@
|
|||||||
# Documentation
|
# Documentation
|
||||||
|
|
||||||
Preview the documentation locally by running the following
|
To start contributing to the [Spectre.Console](https://github.com/spectresystems/spectre.console) documentation, you will need the [.NET Core SDK](https://dot.net) 3.1 or higher.
|
||||||
from your favourite shell:
|
|
||||||
|
## 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"
|
> dotnet run preview --virtual-dir "spectre.console"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
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. Enhancements to the build process include:
|
||||||
|
|
||||||
|
- [Extension Methods](./src/Extensions)
|
||||||
|
- [Models](./src/Models)
|
||||||
|
- [Pipelines](./src/Pipelines)
|
||||||
|
- [Shortcodes](./src/Shortcodes)
|
||||||
|
- [Utilities](./src/Utilities)
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 Spectre Systems AB
|
||||||
|
|
||||||
|
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.
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
|
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
|
||||||
<link href="/spectre.console/assets/bootstrap/bootstrap.css" rel="stylesheet" />
|
<link href="@Context.GetLink("/assets/bootstrap/bootstrap.css")" rel="stylesheet" />
|
||||||
<link href="/spectre.console/assets/css/styles.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 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">
|
<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">
|
<nav id="topnav" class="navbar navbar-expand-lg navbar-light">
|
||||||
<div class="container py-3">
|
<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">
|
<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>
|
<span class="navbar-toggler-icon"></span>
|
||||||
</button>
|
</button>
|
||||||
@@ -140,6 +140,11 @@
|
|||||||
|
|
||||||
@foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible())
|
@foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible())
|
||||||
{
|
{
|
||||||
|
if(string.IsNullOrWhiteSpace(document.GetTitle()))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
DocumentList<IDocument> documentChildren = OutputPages.GetChildrenOf(document);
|
DocumentList<IDocument> documentChildren = OutputPages.GetChildrenOf(document);
|
||||||
<div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(documentChildren.Any() ? "has-children" : null)">
|
<div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(documentChildren.Any() ? "has-children" : null)">
|
||||||
@if(document.ShowLink())
|
@if(document.ShowLink())
|
||||||
|
|||||||
@@ -4,16 +4,30 @@ Order: 2
|
|||||||
|
|
||||||
There is different built-in borders you can use for tables and panels.
|
There is different built-in borders you can use for tables and panels.
|
||||||
|
|
||||||
# Built-in borders
|
# Table borders
|
||||||
|
|
||||||
<img src="../assets/images/borders.png" style="max-width: 100%;">
|
<img src="../assets/images/borders/table.png" style="max-width: 100%;">
|
||||||
|
|
||||||
# Usage
|
## Example
|
||||||
|
|
||||||
To create a table and set it's border to `SimpleHeavy` as seen in the
|
To set a table border to `SimpleHeavy`:
|
||||||
image above:
|
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
var table = new Table();
|
var table = new Table();
|
||||||
table.Border = Border.SimpleHeavy;
|
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;
|
||||||
```
|
```
|
||||||
@@ -13,4 +13,19 @@ in markup text such as `AnsiConsole.Markup("[maroon on blue]Hello[/]")`.
|
|||||||
|
|
||||||
# Standard colors
|
# 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 /?>
|
<?# ColorTable /?>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="../assets/js/table-search.js"></script>
|
||||||
@@ -30,9 +30,43 @@ var phrase = "Mmmm :birthday_cake:";
|
|||||||
var rendered = Emoji.Replace(phrase);
|
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
|
# Emojis
|
||||||
|
|
||||||
_The images in the table below might not render correctly in your
|
_The images in the table below might not render correctly in your
|
||||||
browser for the same reasons mentioned in the `Compatibility` section._
|
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 /?>
|
<?# 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>
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
Title: Appendix
|
|
||||||
Order: 10
|
|
||||||
---
|
|
||||||
|
|
||||||
# Sections
|
|
||||||
|
|
||||||
* [Styles](xref:styles)
|
|
||||||
* [Colors](xref:colors)
|
|
||||||
* [Borders](xref:borders)
|
|
||||||
* [Emojis](xref:emojis)
|
|
||||||
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",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
```
|
||||||
BIN
docs/input/assets/images/barchart.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
|
Before Width: | Height: | Size: 415 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/exception.png
Normal file
|
After Width: | Height: | Size: 421 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/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>
|
||||||
117
docs/input/cli/introduction.md
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
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(AddPackageSettings settings, ILookup<string, string> remaining)
|
||||||
|
{
|
||||||
|
// Omitted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddReferenceCommand : Command<AddReferenceSettings>
|
||||||
|
{
|
||||||
|
public override int Execute(AddReferenceSettings settings, ILookup<string, string> remaining)
|
||||||
|
{
|
||||||
|
// Omitted
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 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;
|
||||||
|
```
|
||||||
52
docs/input/exceptions.md
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
Title: Exceptions
|
||||||
|
Order: 3
|
||||||
|
---
|
||||||
|
|
||||||
|
Exceptions isn'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
|
Order: 0
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ for Python written by Will McGugan.
|
|||||||
The library will detect the capabilities of the current terminal
|
The library will detect the capabilities of the current terminal
|
||||||
and downgrade colors as needed.
|
and downgrade colors as needed.
|
||||||
|
|
||||||
## Example
|
## Examples
|
||||||
|
|
||||||
<img width="100%"
|
<img src="assets/images/table.gif" style="max-width: 100%; margin-top: 15px; margin-bottom: 25px;" />
|
||||||
src="https://github.com/spectresystems/spectre.console/raw/main/resources/gfx/screenshots/example.png" />
|
<img src="https://github.com/spectresystems/spectre.console/raw/main/resources/gfx/screenshots/example.png" style="max-width: 100%;" />
|
||||||
@@ -6,7 +6,7 @@ The class `Markup` allows you to output rich text to the console.
|
|||||||
|
|
||||||
# Syntax
|
# Syntax
|
||||||
|
|
||||||
Console markup uses a syntax inspired by bbcode. If you write the style (see Styles)
|
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 `[/]`.
|
in square brackets, e.g. `[bold red]`, that style will apply until it is closed with a `[/]`.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
@@ -21,6 +21,7 @@ rendering of `IRenderable` also have overloads for rendering rich text.
|
|||||||
var table = new Table();
|
var table = new Table();
|
||||||
table.AddColumn(new TableColumn(new Markup("[yellow]Foo[/]")));
|
table.AddColumn(new TableColumn(new Markup("[yellow]Foo[/]")));
|
||||||
table.AddColumn(new TableColumn("[blue]Bar[/]"));
|
table.AddColumn(new TableColumn("[blue]Bar[/]"));
|
||||||
|
AnsiConsole.Render(table);
|
||||||
```
|
```
|
||||||
|
|
||||||
# Convenience methods
|
# Convenience methods
|
||||||
@@ -43,14 +44,24 @@ AnsiConsole.Markup("[[Hello]] "); // [Hello]
|
|||||||
AnsiConsole.Markup("[red][[World]][/]"); // [World]
|
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
|
# Setting background color
|
||||||
|
|
||||||
You can set the background color in markup by prefixing the color with
|
You can set the background color in markup by prefixing the color with
|
||||||
`on`.
|
`on`.
|
||||||
|
|
||||||
```
|
```csharp
|
||||||
[bold yellow on blue]Hello[/]
|
AnsiConsole.Markup("[bold yellow on blue]Hello[/]");
|
||||||
[default on blue]World[/]
|
AnsiConsole.Markup("[default on blue]World[/]");
|
||||||
```
|
```
|
||||||
|
|
||||||
# Rendering emojis
|
# Rendering emojis
|
||||||
@@ -58,13 +69,22 @@ You can set the background color in markup by prefixing the color with
|
|||||||
To output an emoji as part of markup, you can use emoji shortcodes.
|
To output an emoji as part of markup, you can use emoji shortcodes.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
|
AnsiConsole.Markup("Hello :globe_showing_europe_africa:!");
|
||||||
```
|
```
|
||||||
|
|
||||||
For a list of emoji, see the [Emojis](xref:styles) appendix section.
|
For a list of emoji, see the [Emojis](xref:emojis) appendix section.
|
||||||
|
|
||||||
# Colors
|
# Colors
|
||||||
|
|
||||||
|
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.
|
For a list of colors, see the [Colors](xref:colors) appendix section.
|
||||||
|
|
||||||
# Styles
|
# Styles
|
||||||
|
|||||||
78
docs/input/progress.md
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
Title: Progress
|
||||||
|
Order: 5
|
||||||
|
---
|
||||||
|
|
||||||
|
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;">
|
||||||
|
|
||||||
|
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
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(), // Task description
|
||||||
|
new ProgressBarColumn(), // Progress bar
|
||||||
|
new PercentageColumn(), // Percentage
|
||||||
|
new RemainingTimeColumn(), // Remaining time
|
||||||
|
new SpinnerColumn(), // Spinner
|
||||||
|
})
|
||||||
|
.Start(ctx =>
|
||||||
|
{
|
||||||
|
// Omitted
|
||||||
|
});
|
||||||
|
```
|
||||||
12
docs/input/prompts/index.cshtml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Title: Prompts
|
||||||
|
Order: 5
|
||||||
|
---
|
||||||
|
|
||||||
|
<h1>Sections</h1>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
|
||||||
|
{
|
||||||
|
<li>@Html.DocumentLink(child)</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
31
docs/input/prompts/multiselection.md
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
Title: Multi Selection
|
||||||
|
Order: 3
|
||||||
|
---
|
||||||
|
|
||||||
|
The `MultiSelectionPrompt` can be used when you want the user to select
|
||||||
|
one or many items from a provided list.
|
||||||
|
|
||||||
|
<img src="../assets/images/multiselection.gif" style="width: 100%;" />
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Ask for the user's favorite fruits
|
||||||
|
var fruits = AnsiConsole.Prompt(
|
||||||
|
new MultiSelectionPrompt<string>()
|
||||||
|
.Title("What are your [green]favorite fruits[/]?")
|
||||||
|
.NotRequired() // Not required to have a favorite fruit
|
||||||
|
.PageSize(10)
|
||||||
|
.AddChoice("Apple")
|
||||||
|
.AddChoices(new[] {
|
||||||
|
"Apricot", "Avocado",
|
||||||
|
"Banana", "Blackcurrant", "Blueberry",
|
||||||
|
"Cherry", "Cloudberry", "Cocunut",
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Write the selected fruits to the terminal
|
||||||
|
foreach (string fruit in fruits)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine(fruit);
|
||||||
|
}
|
||||||
|
```
|
||||||
27
docs/input/prompts/selection.md
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
Title: Selection
|
||||||
|
Order: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
The `SelectionPrompt` can be used when you want the user to select
|
||||||
|
a single item from a provided list.
|
||||||
|
|
||||||
|
<img src="../assets/images/selection.gif" style="width: 100%;" />
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Ask for the user's favorite fruit
|
||||||
|
var fruit = AnsiConsole.Prompt(
|
||||||
|
new SelectionPrompt<string>()
|
||||||
|
.Title("What's your [green]favorite fruit[/]?")
|
||||||
|
.PageSize(10)
|
||||||
|
.AddChoice("Apple")
|
||||||
|
.AddChoices(new[] {
|
||||||
|
"Apricot", "Avocado",
|
||||||
|
"Banana", "Blackcurrant", "Blueberry",
|
||||||
|
"Cherry", "Cloudberry", "Cocunut",
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Echo the fruit back to the terminal
|
||||||
|
AnsiConsole.WriteLine($"I agree. {fruit} is tasty!");
|
||||||
|
```
|
||||||
100
docs/input/prompts/text.md
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
Title: Text
|
||||||
|
Order: 0
|
||||||
|
RedirectFrom: prompt
|
||||||
|
---
|
||||||
|
|
||||||
|
Sometimes you want to get some input from the user, and for this
|
||||||
|
you can use the `Prompt<TResult>`.
|
||||||
|
|
||||||
|
# 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
|
The fastest way of getting started using Spectre.Console is
|
||||||
to install the NuGet package.
|
to install the NuGet package.
|
||||||
|
|
||||||
```shell
|
```text
|
||||||
> dotnet add package Spectre.Console
|
> dotnet add package Spectre.Console
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
60
docs/input/status.md
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
Title: Status
|
||||||
|
Order: 6
|
||||||
|
---
|
||||||
|
|
||||||
|
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;">
|
||||||
|
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
```
|
||||||
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);
|
||||||
|
```
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
Title: Tables
|
Title: Table
|
||||||
Order: 3
|
Order: 0
|
||||||
|
RedirectFrom: tables
|
||||||
---
|
---
|
||||||
|
|
||||||
Tables are a perfect way of displaying tabular data in a terminal.
|
Tables are a perfect way of displaying tabular data in a terminal.
|
||||||
@@ -36,7 +37,7 @@ AnsiConsole.Render(table);
|
|||||||
|
|
||||||
This will render the following output:
|
This will render the following output:
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
# Table appearance
|
# Table appearance
|
||||||
|
|
||||||
@@ -50,10 +51,10 @@ For a list of borders, see the [Borders](xref:borders) appendix section.
|
|||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Sets the border
|
// Sets the border
|
||||||
table.SetBorder(Border.None);
|
table.Border(TableBorder.None);
|
||||||
table.SetBorder(Border.Ascii);
|
table.Border(TableBorder.Ascii);
|
||||||
table.SetBorder(Border.Square);
|
table.Border(TableBorder.Square);
|
||||||
table.SetBorder(Border.Rounded);
|
table.Border(TableBorder.Rounded);
|
||||||
```
|
```
|
||||||
|
|
||||||
## Expand / Collapse
|
## Expand / Collapse
|
||||||
@@ -78,7 +79,16 @@ table.HideHeaders();
|
|||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Sets the table width to 50 cells
|
// Sets the table width to 50 cells
|
||||||
table.SetWidth(50);
|
table.Width(50);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Alignment
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
table.Alignment(Justify.Right);
|
||||||
|
table.RightAligned();
|
||||||
|
table.Centered();
|
||||||
|
table.LeftAligned();
|
||||||
```
|
```
|
||||||
|
|
||||||
# Column appearance
|
# Column appearance
|
||||||
@@ -90,31 +100,37 @@ table.SetWidth(50);
|
|||||||
## Alignment
|
## Alignment
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Set the alignment explicitly
|
table.Columns[0].Alignment(Justify.Right);
|
||||||
column.SetAlignment(Justify.Right);
|
table.Columns[0].LeftAligned();
|
||||||
|
table.Columns[0].Centered();
|
||||||
|
table.Columns[0].RightAligned();
|
||||||
```
|
```
|
||||||
|
|
||||||
## Padding
|
## Padding
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Set left and right padding
|
// Set padding individually
|
||||||
column.SetPadding(left: 3, right: 5);
|
table.Columns[0].PadLeft(3);
|
||||||
|
table.Columns[0].PadRight(5);
|
||||||
|
|
||||||
// Set padding individually.
|
// Or chained together
|
||||||
column.PadLeft(3);
|
table.Columns[0].PadLeft(3).PadRight(5);
|
||||||
column.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
|
## Disable column wrapping
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Disable column wrapping
|
// Disable column wrapping
|
||||||
column.NoWrap();
|
table.Columns[0].NoWrap();
|
||||||
```
|
```
|
||||||
|
|
||||||
## Set column width
|
## Set column width
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
// Set the column width (no fluent extension method for this yet)
|
// Set the column width
|
||||||
column.Width = 15;
|
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 tree = new Tree("Root");
|
||||||
|
|
||||||
|
// Add some nodes
|
||||||
|
var foo = tree.AddNode("[yellow]Foo[/]");
|
||||||
|
var table = foo.AddNode(new Table()
|
||||||
|
.RoundedBorder()
|
||||||
|
.AddColumn("First")
|
||||||
|
.AddColumn("Second")
|
||||||
|
.AddRow("1", "2")
|
||||||
|
.AddRow("3", "4")
|
||||||
|
.AddRow("5", "6"));
|
||||||
|
|
||||||
|
table.AddNode("[blue]Baz[/]");
|
||||||
|
foo.AddNode("Qux");
|
||||||
|
|
||||||
|
var bar = tree.AddNode("[yellow]Bar[/]");
|
||||||
|
bar.AddNode(new Calendar(2020, 12)
|
||||||
|
.AddCalendarEvent(2020, 12, 12)
|
||||||
|
.HideHeader());
|
||||||
|
|
||||||
|
// Render the tree
|
||||||
|
AnsiConsole.Render(root);
|
||||||
|
```
|
||||||
|
|
||||||
|
# Collapsing nodes
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
root.AddNode("Label").Collapsed();
|
||||||
|
```
|
||||||
|
|
||||||
|
# Appearance
|
||||||
|
|
||||||
|
## Style
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var root = new Tree("Root")
|
||||||
|
.Style("white on red");
|
||||||
|
```
|
||||||
|
|
||||||
|
## Guide lines
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// ASCII guide lines
|
||||||
|
var root = new Tree("Root")
|
||||||
|
.Guide(TreeGuide.Ascii);
|
||||||
|
|
||||||
|
// Default guide lines
|
||||||
|
var root = new Tree("Root")
|
||||||
|
.Guide(TreeGuide.Line);
|
||||||
|
|
||||||
|
// Double guide lines
|
||||||
|
var root = new Tree("Root")
|
||||||
|
.Guide(TreeGuide.DoubleLine);
|
||||||
|
|
||||||
|
// Bold guide lines
|
||||||
|
var root = new Tree("Root")
|
||||||
|
.Guide(TreeGuide.BoldLine);
|
||||||
|
```
|
||||||
@@ -20,10 +20,7 @@ namespace Docs
|
|||||||
|
|
||||||
public static Bootstrapper ConfigureDeployment(this Bootstrapper bootstrapper, string deployBranch)
|
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;
|
return bootstrapper;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,13 @@ namespace Docs.Pipelines
|
|||||||
{
|
{
|
||||||
public class ColorsPipeline : Pipeline
|
public class ColorsPipeline : Pipeline
|
||||||
{
|
{
|
||||||
public const string Url = "https://raw.githubusercontent.com/spectresystems/spectre.console/main/resources/scripts/Generator/Data/colors.json";
|
|
||||||
|
|
||||||
public ColorsPipeline()
|
public ColorsPipeline()
|
||||||
{
|
{
|
||||||
InputModules = new ModuleList
|
InputModules = new ModuleList
|
||||||
{
|
{
|
||||||
new ExecuteConfig(
|
new ExecuteConfig(
|
||||||
Config.FromContext(ctx => {
|
Config.FromContext(ctx => {
|
||||||
return new ReadWeb(Url);
|
return new ReadWeb(Constants.Colors.Url);
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ namespace Docs.Shortcodes
|
|||||||
.First().Object;
|
.First().Object;
|
||||||
|
|
||||||
// Headers
|
// Headers
|
||||||
var table = new XElement("table", new XAttribute("class", "table"));
|
var table = new XElement("table", new XAttribute("class", "table"), new XAttribute("id", "color-results"));
|
||||||
var header = new XElement("tr", new XAttribute("class", "color-row"));
|
var header = new XElement("tr", new XAttribute("class", "color-row"));
|
||||||
header.Add(new XElement("th", ""));
|
header.Add(new XElement("th", ""));
|
||||||
header.Add(new XElement("th", "#"));
|
header.Add(new XElement("th", "#"));
|
||||||
@@ -44,7 +44,7 @@ namespace Docs.Shortcodes
|
|||||||
var clr = new XElement("td", new XElement("code", color.ClrName));
|
var clr = new XElement("td", new XElement("code", color.ClrName));
|
||||||
|
|
||||||
// Create row
|
// Create row
|
||||||
var row = new XElement("tr");
|
var row = new XElement("tr", new XAttribute("class", "search-row"));
|
||||||
row.Add(rep);
|
row.Add(rep);
|
||||||
row.Add(name);
|
row.Add(name);
|
||||||
row.Add(number);
|
row.Add(number);
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ namespace Docs.Shortcodes
|
|||||||
.First().Object;
|
.First().Object;
|
||||||
|
|
||||||
// Headers
|
// Headers
|
||||||
var table = new XElement("table", new XAttribute("class", "table"));
|
var table = new XElement("table", new XAttribute("class", "table"), new XAttribute("id", "emoji-results"));
|
||||||
var header = new XElement("tr", new XAttribute("class", "emoji-row"));
|
var header = new XElement("tr", new XAttribute("class", "emoji-row-header"));
|
||||||
header.Add(new XElement("th", ""));
|
header.Add(new XElement("th", ""));
|
||||||
header.Add(new XElement("th", "Markup"));
|
header.Add(new XElement("th", "Markup"));
|
||||||
header.Add(new XElement("th", "Constant"));
|
header.Add(new XElement("th", "Constant"));
|
||||||
@@ -28,9 +28,9 @@ namespace Docs.Shortcodes
|
|||||||
foreach (var emoji in emojis)
|
foreach (var emoji in emojis)
|
||||||
{
|
{
|
||||||
var code = emoji.Code.Replace("U+0000", "U+").Replace("U+000", "U+");
|
var code = emoji.Code.Replace("U+0000", "U+").Replace("U+000", "U+");
|
||||||
var icon = string.Format("&#x{0};", emoji.Code.Replace("U+", string.Empty));
|
var icon = $"&#x{emoji.Code.Replace("U+", string.Empty)};";
|
||||||
|
|
||||||
var row = new XElement("tr");
|
var row = new XElement("tr", new XAttribute("class", "search-row"));
|
||||||
row.Add(new XElement("td", icon));
|
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.Id}:")));
|
||||||
row.Add(new XElement("td", new XElement("code", emoji.Name)));
|
row.Add(new XElement("td", new XElement("code", emoji.Name)));
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"cake.tool": {
|
"cake.tool": {
|
||||||
"version": "0.38.4",
|
"version": "1.0.0-rc0002",
|
||||||
"commands": [
|
"commands": [
|
||||||
"dotnet-cake"
|
"dotnet-cake"
|
||||||
]
|
]
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dotnet-example": {
|
"dotnet-example": {
|
||||||
"version": "0.8.0",
|
"version": "1.2.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"dotnet-example"
|
"dotnet-example"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,14 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
<Description>Demonstrates the different kind of borders.</Description>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
using Spectre.Console.Rendering;
|
|
||||||
|
|
||||||
namespace Borders
|
|
||||||
{
|
|
||||||
public static class Program
|
|
||||||
{
|
|
||||||
public static void Main()
|
|
||||||
{
|
|
||||||
var items = new[]
|
|
||||||
{
|
|
||||||
Create("Ascii", Border.Ascii),
|
|
||||||
Create("Ascii2", Border.Ascii2),
|
|
||||||
Create("AsciiDoubleHead", Border.AsciiDoubleHead),
|
|
||||||
Create("Horizontal", Border.Horizontal),
|
|
||||||
Create("Simple", Border.Simple),
|
|
||||||
Create("SimpleHeavy", Border.SimpleHeavy),
|
|
||||||
Create("Minimal", Border.Minimal),
|
|
||||||
Create("MinimalHeavyHead", Border.MinimalHeavyHead),
|
|
||||||
Create("MinimalDoubleHead", Border.MinimalDoubleHead),
|
|
||||||
Create("Square", Border.Square),
|
|
||||||
Create("Rounded", Border.Rounded),
|
|
||||||
Create("Heavy", Border.Heavy),
|
|
||||||
Create("HeavyEdge", Border.HeavyEdge),
|
|
||||||
Create("HeavyHead", Border.HeavyHead),
|
|
||||||
Create("Double", Border.Double),
|
|
||||||
Create("DoubleEdge", Border.DoubleEdge),
|
|
||||||
};
|
|
||||||
|
|
||||||
AnsiConsole.WriteLine();
|
|
||||||
AnsiConsole.Render(new Columns(items).Collapse());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static IRenderable Create(string name, Border border)
|
|
||||||
{
|
|
||||||
var table = new Table().SetBorder(border);
|
|
||||||
table.AddColumns("[yellow]Header 1[/]", "[yellow]Header 2[/]");
|
|
||||||
table.AddRow("Cell", "Cell");
|
|
||||||
table.AddRow("Cell", "Cell");
|
|
||||||
|
|
||||||
return new Panel(table)
|
|
||||||
.SetHeader($" {name} ", Style.Parse("blue"), Justify.Center)
|
|
||||||
.SetBorderStyle(Style.Parse("grey"))
|
|
||||||
.NoBorder();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
16
examples/Cli/Delegates/BarSettings.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Delegates
|
||||||
|
{
|
||||||
|
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="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
39
examples/Cli/Delegates/Program.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Delegates
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
Console.WriteLine("Foo");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int Bar(CommandContext context, BarSettings settings)
|
||||||
|
{
|
||||||
|
for (var index = 0; index < settings.Count; index++)
|
||||||
|
{
|
||||||
|
Console.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="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
20
examples/Cli/Dynamic/MyCommand.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Dynamic
|
||||||
|
{
|
||||||
|
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.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.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 Dynamic
|
||||||
|
{
|
||||||
|
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 Injection.Commands
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
examples/Cli/Injection/IGreeter.cs
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Injection
|
||||||
|
{
|
||||||
|
public interface IGreeter
|
||||||
|
{
|
||||||
|
void Greet(string name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class HelloWorldGreeter : IGreeter
|
||||||
|
{
|
||||||
|
public void Greet(string name)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Hello {name}!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
31
examples/Cli/Injection/Infrastructure/TypeRegistrar.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Injection
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
examples/Cli/Injection/Infrastructure/TypeResolver.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Injection
|
||||||
|
{
|
||||||
|
public sealed class TypeResolver : ITypeResolver
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _provider;
|
||||||
|
|
||||||
|
public TypeResolver(IServiceProvider provider)
|
||||||
|
{
|
||||||
|
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Resolve(Type type)
|
||||||
|
{
|
||||||
|
return _provider.GetRequiredService(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
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="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
23
examples/Cli/Injection/Program.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Injection.Commands;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Injection
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
// Create a type registrar and register any dependencies.
|
||||||
|
// A type registrar is an adapter for a DI framework.
|
||||||
|
var registrations = new ServiceCollection();
|
||||||
|
registrations.AddSingleton<IGreeter, HelloWorldGreeter>();
|
||||||
|
var registrar = new TypeRegistrar(registrations);
|
||||||
|
|
||||||
|
// Create a new command app with the registrar
|
||||||
|
// and run it with the provided arguments.
|
||||||
|
var app = new CommandApp<DefaultCommand>(registrar);
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
<Description>Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console.</Description>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
<Description>Demonstrates how to render data into columns.</Description>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace ColumnsExample
|
|
||||||
{
|
|
||||||
public static class Program
|
|
||||||
{
|
|
||||||
public static async Task Main()
|
|
||||||
{
|
|
||||||
// Download some random users
|
|
||||||
using var client = new HttpClient();
|
|
||||||
dynamic users = JObject.Parse(
|
|
||||||
await client.GetStringAsync("https://randomuser.me/api/?results=15"));
|
|
||||||
|
|
||||||
// Create a card for each user
|
|
||||||
var cards = new List<Panel>();
|
|
||||||
foreach(var user in users.results)
|
|
||||||
{
|
|
||||||
cards.Add(new Panel(GetCard(user))
|
|
||||||
.SetHeader($"{user.location.country}")
|
|
||||||
.RoundedBorder().Expand());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render all cards in columns
|
|
||||||
AnsiConsole.Render(new Columns(cards));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetCard(dynamic user)
|
|
||||||
{
|
|
||||||
var name = $"{user.name.first} {user.name.last}";
|
|
||||||
var country = $"{user.location.city}";
|
|
||||||
|
|
||||||
return $"[b]{name}[/]\n[yellow]{country}[/]";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
15
examples/Console/Borders/Borders.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<ExampleTitle>Borders</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates the different kind of borders.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
91
examples/Console/Borders/Program.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace BordersExample
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
// Render panel borders
|
||||||
|
HorizontalRule("PANEL BORDERS");
|
||||||
|
PanelBorders();
|
||||||
|
|
||||||
|
// Render table borders
|
||||||
|
HorizontalRule("TABLE BORDERS");
|
||||||
|
TableBorders();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PanelBorders()
|
||||||
|
{
|
||||||
|
static IRenderable CreatePanel(string name, BoxBorder border)
|
||||||
|
{
|
||||||
|
return new Panel($"This is a panel with\nthe [yellow]{name}[/] border.")
|
||||||
|
.Header($" [blue]{name}[/] ", Justify.Center)
|
||||||
|
.Border(border)
|
||||||
|
.BorderStyle(Style.Parse("grey"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = new[]
|
||||||
|
{
|
||||||
|
CreatePanel("Ascii", BoxBorder.Ascii),
|
||||||
|
CreatePanel("Square", BoxBorder.Square),
|
||||||
|
CreatePanel("Rounded", BoxBorder.Rounded),
|
||||||
|
CreatePanel("Heavy", BoxBorder.Heavy),
|
||||||
|
CreatePanel("Double", BoxBorder.Double),
|
||||||
|
CreatePanel("None", BoxBorder.None),
|
||||||
|
};
|
||||||
|
|
||||||
|
AnsiConsole.Render(
|
||||||
|
new Padder(
|
||||||
|
new Columns(items).PadRight(2),
|
||||||
|
new Padding(2,0,0,0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TableBorders()
|
||||||
|
{
|
||||||
|
static IRenderable CreateTable(string name, TableBorder border)
|
||||||
|
{
|
||||||
|
var table = new Table().Border(border);
|
||||||
|
table.AddColumn("[yellow]Header 1[/]", c => c.Footer("[grey]Footer 1[/]"));
|
||||||
|
table.AddColumn("[yellow]Header 2[/]", col => col.Footer("[grey]Footer 2[/]").RightAligned());
|
||||||
|
table.AddRow("Cell", "Cell");
|
||||||
|
table.AddRow("Cell", "Cell");
|
||||||
|
|
||||||
|
return new Panel(table)
|
||||||
|
.Header($" [blue]{name}[/] ", Justify.Center)
|
||||||
|
.NoBorder();
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = new[]
|
||||||
|
{
|
||||||
|
CreateTable("Ascii", TableBorder.Ascii),
|
||||||
|
CreateTable("Ascii2", TableBorder.Ascii2),
|
||||||
|
CreateTable("AsciiDoubleHead", TableBorder.AsciiDoubleHead),
|
||||||
|
CreateTable("Horizontal", TableBorder.Horizontal),
|
||||||
|
CreateTable("Simple", TableBorder.Simple),
|
||||||
|
CreateTable("SimpleHeavy", TableBorder.SimpleHeavy),
|
||||||
|
CreateTable("Minimal", TableBorder.Minimal),
|
||||||
|
CreateTable("MinimalHeavyHead", TableBorder.MinimalHeavyHead),
|
||||||
|
CreateTable("MinimalDoubleHead", TableBorder.MinimalDoubleHead),
|
||||||
|
CreateTable("Square", TableBorder.Square),
|
||||||
|
CreateTable("Rounded", TableBorder.Rounded),
|
||||||
|
CreateTable("Heavy", TableBorder.Heavy),
|
||||||
|
CreateTable("HeavyEdge", TableBorder.HeavyEdge),
|
||||||
|
CreateTable("HeavyHead", TableBorder.HeavyHead),
|
||||||
|
CreateTable("Double", TableBorder.Double),
|
||||||
|
CreateTable("DoubleEdge", TableBorder.DoubleEdge),
|
||||||
|
CreateTable("Markdown", TableBorder.Markdown),
|
||||||
|
};
|
||||||
|
|
||||||
|
AnsiConsole.Render(new Columns(items).Collapse());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HorizontalRule(string title)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Render(new Rule($"[white bold]{title}[/]").RuleStyle("grey").LeftAligned());
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Calendars/Calendars.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<ExampleTitle>Calendars</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render calendars.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
19
examples/Console/Calendars/Program.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Calendars
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Render(new Calendar(2020, 10)
|
||||||
|
.RoundedBorder()
|
||||||
|
.HighlightStyle(Style.Parse("red"))
|
||||||
|
.HeaderStyle(Style.Parse("yellow"))
|
||||||
|
.AddCalendarEvent("An event", 2020, 9, 22)
|
||||||
|
.AddCalendarEvent("Another event", 2020, 10, 2)
|
||||||
|
.AddCalendarEvent("A third event", 2020, 10, 13));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
22
examples/Console/Canvas/Canvas.csproj
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||||
|
<ExampleTitle>Canvas</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render pixels and images.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\src\Spectre.Console.ImageSharp\Spectre.Console.ImageSharp.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="cake.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
87
examples/Console/Canvas/Mandelbrot.cs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
/*
|
||||||
|
Ported from: https://rosettacode.org/wiki/Mandelbrot_set#C.23
|
||||||
|
Licensed under GNU Free Documentation License 1.2
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace CanvasExample
|
||||||
|
{
|
||||||
|
public static class Mandelbrot
|
||||||
|
{
|
||||||
|
private const double MaxValueExtent = 2.0;
|
||||||
|
|
||||||
|
private struct ComplexNumber
|
||||||
|
{
|
||||||
|
public double Real { get; }
|
||||||
|
public double Imaginary { get; }
|
||||||
|
|
||||||
|
public ComplexNumber(double real, double imaginary)
|
||||||
|
{
|
||||||
|
Real = real;
|
||||||
|
Imaginary = imaginary;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ComplexNumber operator +(ComplexNumber x, ComplexNumber y)
|
||||||
|
{
|
||||||
|
return new ComplexNumber(x.Real + y.Real, x.Imaginary + y.Imaginary);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ComplexNumber operator *(ComplexNumber x, ComplexNumber y)
|
||||||
|
{
|
||||||
|
return new ComplexNumber(x.Real * y.Real - x.Imaginary * y.Imaginary,
|
||||||
|
x.Real * y.Imaginary + x.Imaginary * y.Real);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double Abs()
|
||||||
|
{
|
||||||
|
return Real * Real + Imaginary * Imaginary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Canvas Generate(int width, int height)
|
||||||
|
{
|
||||||
|
var canvas = new Canvas(width, height);
|
||||||
|
|
||||||
|
var scale = 2 * MaxValueExtent / Math.Min(canvas.Width, canvas.Height);
|
||||||
|
for (var i = 0; i < canvas.Height; i++)
|
||||||
|
{
|
||||||
|
var y = (canvas.Height / 2 - i) * scale;
|
||||||
|
for (var j = 0; j < canvas.Width; j++)
|
||||||
|
{
|
||||||
|
var x = (j - canvas.Width / 2) * scale;
|
||||||
|
var value = Calculate(new ComplexNumber(x, y));
|
||||||
|
canvas.SetPixel(j, i, GetColor(value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return canvas;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static double Calculate(ComplexNumber c)
|
||||||
|
{
|
||||||
|
const int MaxIterations = 1000;
|
||||||
|
const double MaxNorm = MaxValueExtent * MaxValueExtent;
|
||||||
|
|
||||||
|
var iteration = 0;
|
||||||
|
var z = new ComplexNumber();
|
||||||
|
do
|
||||||
|
{
|
||||||
|
z = z * z + c;
|
||||||
|
iteration++;
|
||||||
|
} while (z.Abs() < MaxNorm && iteration < MaxIterations);
|
||||||
|
|
||||||
|
return iteration < MaxIterations
|
||||||
|
? (double)iteration / MaxIterations
|
||||||
|
: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Color GetColor(double value)
|
||||||
|
{
|
||||||
|
const double MaxColor = 256;
|
||||||
|
const double ContrastValue = 0.2;
|
||||||
|
return new Color(0, 0, (byte)(MaxColor * Math.Pow(value, ContrastValue)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
36
examples/Console/Canvas/Program.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace CanvasExample
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
// Draw a mandelbrot set using a Canvas
|
||||||
|
var mandelbrot = Mandelbrot.Generate(32, 32);
|
||||||
|
Render(mandelbrot, "Mandelbrot");
|
||||||
|
|
||||||
|
// Draw an image using CanvasImage powered by ImageSharp.
|
||||||
|
// This requires the "Spectre.Console.ImageSharp" NuGet package.
|
||||||
|
var image = new CanvasImage("cake.png");
|
||||||
|
image.BilinearResampler();
|
||||||
|
image.MaxWidth(16);
|
||||||
|
Render(image, "Image from file (16 wide)");
|
||||||
|
|
||||||
|
// Draw image again, but without render width
|
||||||
|
image.NoMaxWidth();
|
||||||
|
image.Mutate(ctx => ctx.Grayscale().Rotate(-45).EntropyCrop());
|
||||||
|
Render(image, "Image from file (fit, greyscale, rotated)");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Render(IRenderable canvas, string title)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Render(new Rule($"[yellow]{title}[/]").LeftAligned().RuleStyle("grey"));
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Render(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
examples/Console/Canvas/cake.png
Normal file
|
After Width: | Height: | Size: 52 KiB |
15
examples/Console/Charts/Charts.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<ExampleTitle>Charts</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render charts in a console.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
21
examples/Console/Charts/Program.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace InfoExample
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
var chart = 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);
|
||||||
|
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Render(chart);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Colors/Colors.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<ExampleTitle>Colors</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console.</ExampleDescription>
|
||||||
|
<ExampleGroup>Misc</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||