Compare commits
135 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f5a9c0ca26 | ||
|
|
23564612c1 | ||
|
|
f2b8afffb3 | ||
|
|
3e2eea730b | ||
|
|
bc9f610258 | ||
|
|
ae96606ab7 | ||
|
|
41ccc0b464 | ||
|
|
3545e0f6b5 | ||
|
|
2fe2bb3c32 | ||
|
|
1fc6f22ea9 | ||
|
|
6a5c507936 | ||
|
|
efa3d3b130 | ||
|
|
6007fcaafc | ||
|
|
13ac38ed04 | ||
|
|
ca036f6543 | ||
|
|
36ec3d1fd3 | ||
|
|
fe5096dceb | ||
|
|
39b59c8d4a | ||
|
|
8cf7794852 | ||
|
|
4edc647fdd | ||
|
|
be45a0ff4e | ||
|
|
256fcdd27f | ||
|
|
dafbfe63ba | ||
|
|
a2ab522516 | ||
|
|
8778ab1739 | ||
|
|
693e1fa170 | ||
|
|
4b37a4708f | ||
|
|
a690ce4955 | ||
|
|
759b16aed9 | ||
|
|
254880e93a | ||
|
|
6f16081f42 | ||
|
|
6121203fee | ||
|
|
9204671b27 | ||
|
|
c765bbd0dd | ||
|
|
6bceac8a5e | ||
|
|
1ed7e65fcb | ||
|
|
20650f1e7e | ||
|
|
2ba6da3514 | ||
|
|
8830779875 | ||
|
|
9c46c21e27 | ||
|
|
c643ec735d | ||
|
|
b17eabaa1f | ||
|
|
7f6f2437b1 | ||
|
|
c2bab0ebf8 | ||
|
|
9502aaf2b9 | ||
|
|
57a8e6ccc1 | ||
|
|
8c099a0038 | ||
|
|
08b65cfa47 | ||
|
|
2540f48622 | ||
|
|
e4dda283bb | ||
|
|
da9c6ee4c2 | ||
|
|
855127f32a | ||
|
|
fa731070d8 | ||
|
|
ef08c5bf2b | ||
|
|
1c769c6610 | ||
|
|
1cd335e785 | ||
|
|
29e6e34f83 | ||
|
|
bff3438a5a | ||
|
|
c64884854f | ||
|
|
3a42c0a119 | ||
|
|
525b414ff8 | ||
|
|
ed0fb29be4 | ||
|
|
04d0e663d5 | ||
|
|
17ee8990f4 | ||
|
|
a1050fc676 | ||
|
|
9312663bde | ||
|
|
102e2dc38d | ||
|
|
28e9c14de4 | ||
|
|
fd217ffc83 | ||
|
|
95ec04df40 | ||
|
|
705cf745ea | ||
|
|
b64e016e8c | ||
|
|
58400fe74e | ||
|
|
e20f6284f9 | ||
|
|
953008b5e3 | ||
|
|
ad49b6aa67 | ||
|
|
31a5e17a45 | ||
|
|
f06dc7e7d8 | ||
|
|
a23bec4082 | ||
|
|
913a7b1e37 | ||
|
|
63bae278a9 | ||
|
|
1a747696a8 | ||
|
|
994540d97f | ||
|
|
dee3c01629 | ||
|
|
a3e11b24e5 | ||
|
|
35568ab823 | ||
|
|
07db28bb6f | ||
|
|
d87d8e4422 | ||
|
|
a977fdadff | ||
|
|
8261b25e5c | ||
|
|
0e0f4b4220 | ||
|
|
3a593857c8 | ||
|
|
11e192e750 | ||
|
|
8901450283 | ||
|
|
0796bad598 | ||
|
|
5b553a4106 | ||
|
|
1bb0b9ccc6 | ||
|
|
9ad5f2daeb | ||
|
|
1f211d3e1f | ||
|
|
87e6b42409 | ||
|
|
1aa958ced3 | ||
|
|
4bfb24bfcb | ||
|
|
b136d0299b | ||
|
|
179e243214 | ||
|
|
c6210f75ca | ||
|
|
b81739567b | ||
|
|
5cf41725a5 | ||
|
|
f561d71e4e | ||
|
|
e71db7f78c | ||
|
|
79742ce9e3 | ||
|
|
241423dd16 | ||
|
|
4e2251fd62 | ||
|
|
0ae419326d | ||
|
|
0bbf9b81a9 | ||
|
|
041aea2ae5 | ||
|
|
f417e297cd | ||
|
|
5045b8b959 | ||
|
|
7dccb310f3 | ||
|
|
1cf30f62fc | ||
|
|
e280b82679 | ||
|
|
6932c95731 | ||
|
|
ee305702e8 | ||
|
|
63abcc92ba | ||
|
|
acf01e056f | ||
|
|
501db5d287 | ||
|
|
cbed41e637 | ||
|
|
3c504155bc | ||
|
|
ae32785f21 | ||
|
|
c61e386440 | ||
|
|
b7cd7dd53e | ||
|
|
3e1251b86a | ||
|
|
01fdbac51e | ||
|
|
b0b988a1e7 | ||
|
|
2a9fa223de | ||
|
|
4f6eca4fcb |
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.
|
||||||
13
.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: 5.0.100
|
dotnet-version: 5.0.202
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -63,20 +63,13 @@ jobs:
|
|||||||
- name: Setup dotnet 5.0.100
|
- name: Setup dotnet 5.0.100
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: 5.0.100
|
dotnet-version: 5.0.202
|
||||||
|
|
||||||
- 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 tables
|
|
||||||
dotnet example grids
|
|
||||||
dotnet example panels
|
|
||||||
dotnet example colors
|
|
||||||
dotnet example emojis
|
|
||||||
dotnet example exceptions
|
|
||||||
dotnet example calendars
|
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
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: 5.0.100
|
dotnet-version: 5.0.202
|
||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
6
.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: 5.0.100
|
dotnet-version: 5.0.202
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -72,7 +72,7 @@ jobs:
|
|||||||
- name: Setup dotnet 5.0.100
|
- name: Setup dotnet 5.0.100
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: 5.0.100
|
dotnet-version: 5.0.202
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
@@ -103,7 +103,7 @@ jobs:
|
|||||||
- name: Setup dotnet 5.0.100
|
- name: Setup dotnet 5.0.100
|
||||||
uses: actions/setup-dotnet@v1
|
uses: actions/setup-dotnet@v1
|
||||||
with:
|
with:
|
||||||
dotnet-version: 5.0.100
|
dotnet-version: 5.0.202
|
||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
shell: bash
|
shell: bash
|
||||||
|
|||||||
1
.gitignore
vendored
@@ -79,7 +79,6 @@ x64/
|
|||||||
_ReSharper*
|
_ReSharper*
|
||||||
|
|
||||||
# NCrunch
|
# NCrunch
|
||||||
*.ncrunch*
|
|
||||||
.*crunch*.local.xml
|
.*crunch*.local.xml
|
||||||
_NCrunch_*
|
_NCrunch_*
|
||||||
|
|
||||||
|
|||||||
161
CONTRIBUTING.md
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
# Contribution Guidelines
|
||||||
|
|
||||||
|
* [Prerequisites](#prerequisites)
|
||||||
|
* [Definition of trivial contributions](#definition-of-trivial-contributions)
|
||||||
|
* [Code](#code)
|
||||||
|
* [Code style](#code-style)
|
||||||
|
* [Dependencies](#dependencies)
|
||||||
|
* [Unit tests](#unit-tests)
|
||||||
|
* [Contributing process](#contributing-process)
|
||||||
|
* [Get buyoff or find open community issues or features](#get-buyoff-or-find-open-community-issues-or-features)
|
||||||
|
* [Set up your environment](#Set-up-your-environment)
|
||||||
|
* [Prepare commits](#prepare-commits)
|
||||||
|
* [Submit pull request](#Submit-pull-request)
|
||||||
|
* [Respond to feedback on pull request](#respond-to-feedback-on-pull-request)
|
||||||
|
* [Other general information](#other-general-information)
|
||||||
|
* [Acknowledgement](#acknowledgement)
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
By contributing to Spectre.Console, you assert that:
|
||||||
|
|
||||||
|
* The contribution is your own original work.
|
||||||
|
* You have the right to assign the copyright for the work (it is not owned by your employer, or
|
||||||
|
you have been given copyright assignment in writing).
|
||||||
|
* You [license](https://github.com/spectreconsole/spectre.console/blob/main/LICENSE) the contribution under the terms applied to the rest of the Spectre.Console project.
|
||||||
|
* You agree to follow the [code of conduct](https://github.com/spectreconsole/spectre.console/blob/main/CODE_OF_CONDUCT.md).
|
||||||
|
|
||||||
|
## Definition of trivial contributions
|
||||||
|
It's hard to define what is a trivial contribution. Sometimes even a 1 character change can be considered significant.
|
||||||
|
Unfortunately because it can be subjective, the decision on what is trivial comes from the maintainers of the project
|
||||||
|
and not from folks contributing to the project.
|
||||||
|
|
||||||
|
What is generally considered trivial:
|
||||||
|
|
||||||
|
* Fixing a typo.
|
||||||
|
* Documentation changes.
|
||||||
|
|
||||||
|
## Code
|
||||||
|
### Code style
|
||||||
|
|
||||||
|
Normal .NET coding guidelines apply.
|
||||||
|
See the [Framework Design Guidelines](https://msdn.microsoft.com/en-us/library/ms229042%28v=vs.110%29.aspx) for more information.
|
||||||
|
|
||||||
|
### Dependencies
|
||||||
|
|
||||||
|
The assembly `Spectre.Console` should have no dependencies except the .NET BCL library.
|
||||||
|
|
||||||
|
### Unit tests
|
||||||
|
|
||||||
|
Make sure to run all unit tests before creating a pull request.
|
||||||
|
Any new code should also have reasonable unit test coverage.
|
||||||
|
|
||||||
|
## Contributing process
|
||||||
|
### Get buyoff or find open community issues or features
|
||||||
|
|
||||||
|
* Through GitHub, or through the [GitHub discussions](https://github.com/spectreconsole/spectre.console/discussions) (preferred),
|
||||||
|
you talk about a feature you would like to see (or a bug), and why it should be in Spectre.Console.
|
||||||
|
* If approved through the GitHub discussions, ensure an accompanying GitHub issue is created with
|
||||||
|
information and a link back to the discussion.
|
||||||
|
* Once you get a nod from someone in the Spectre.Console Team, you can start on the feature.
|
||||||
|
* Alternatively, if a feature is on the issues list with the
|
||||||
|
[Up For Grabs](https://github.com/spectreconsole/spectre.console/labels/up-for-grabs) label,
|
||||||
|
it is open for a community member (contributor) to patch. You should comment that you are signing up for it on
|
||||||
|
the issue so someone else doesn't also sign up for the work.
|
||||||
|
|
||||||
|
### Set up your environment
|
||||||
|
|
||||||
|
* You create, or update, a fork of `spectreconsole/spectre.console` under your GitHub account.
|
||||||
|
* From there you create a branch named specific to the feature.
|
||||||
|
* In the branch you do work specific to the feature.
|
||||||
|
* Please also observe the following:
|
||||||
|
* No reformatting
|
||||||
|
* No changing files that are not specific to the feature.
|
||||||
|
* More covered below in the **Prepare commits** section.
|
||||||
|
* Test your changes and please help us out by updating and implementing some automated tests.
|
||||||
|
It is recommended that all contributors spend some time looking over the tests in the source code.
|
||||||
|
You can't go wrong emulating one of the existing tests and then changing it specific to the behavior you are testing.
|
||||||
|
* Please do not update your branch from the main branch unless we ask you to. See the responding to feedback section below.
|
||||||
|
|
||||||
|
### Prepare commits
|
||||||
|
This section serves to help you understand what makes a good commit.
|
||||||
|
|
||||||
|
A commit should observe the following:
|
||||||
|
|
||||||
|
* A commit is a small logical unit that represents a change.
|
||||||
|
* Should include new or changed tests relevant to the changes you are making.
|
||||||
|
* No unnecessary whitespace. Check for whitespace with `git diff --check` and `git diff --cached --check` before commit.
|
||||||
|
* You can stage parts of a file for commit.
|
||||||
|
|
||||||
|
### Submit pull request
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
* You are making commits in a feature branch.
|
||||||
|
* All code should compile without errors or warnings.
|
||||||
|
* All tests should be passing.
|
||||||
|
|
||||||
|
Submitting PR:
|
||||||
|
|
||||||
|
* Once you feel it is ready, submit the pull request to the `spectreconsole/spectre.console` repository against the `main` branch
|
||||||
|
unless specifically requested to submit it against another branch.
|
||||||
|
* In the case of a larger change that is going to require more discussion,
|
||||||
|
please submit a PR sooner. Waiting until you are ready may mean more changes than you are
|
||||||
|
interested in if the changes are taking things in a direction the maintainers do not want to go.
|
||||||
|
* In the pull request, outline what you did and point to specific conversations (as in URLs)
|
||||||
|
and issues that you are resolving. This is a tremendous help for us in evaluation and acceptance.
|
||||||
|
* Once the pull request is in, please do not delete the branch or close the pull request
|
||||||
|
(unless something is wrong with it).
|
||||||
|
* One of the Spectre.Console team members, or one of the maintainers, will evaluate it within a
|
||||||
|
reasonable time period (which is to say usually within 1-3 weeks). Some things get evaluated
|
||||||
|
faster or fast tracked. We are human and we have active lives outside of open source so don't
|
||||||
|
fret if you haven't seen any activity on your pull request within a month or two.
|
||||||
|
We don't have a Service Level Agreement (SLA) for pull requests.
|
||||||
|
Just know that we will evaluate your pull request.
|
||||||
|
|
||||||
|
### Respond to feedback on pull request
|
||||||
|
|
||||||
|
We may have feedback for you to fix or change some things. We generally like to see that pushed against
|
||||||
|
the same topic branch (it will automatically update the Pull Request). You can also fix/squash/rebase
|
||||||
|
commits and push the same topic branch with `--force` (it's generally acceptable to do this on topic
|
||||||
|
branches not in the main repository, it is generally unacceptable and should be avoided at all costs
|
||||||
|
against the main repository).
|
||||||
|
|
||||||
|
If we have comments or questions when we do evaluate it and receive no response, it will probably
|
||||||
|
lessen the chance of getting accepted. Eventually, this means it will be closed if it is not accepted.
|
||||||
|
Please know this doesn't mean we don't value your contribution, just that things go stale. If in the
|
||||||
|
future you want to pick it back up, feel free to address our concerns/questions/feedback and reopen
|
||||||
|
the issue/open a new PR (referencing old one).
|
||||||
|
|
||||||
|
Sometimes we may need you to rebase your commit against the latest code before we can review it further.
|
||||||
|
If this happens, you can do the following:
|
||||||
|
|
||||||
|
* `git fetch upstream` (upstream remote would be `spectreconsole/spectre.console`)
|
||||||
|
* `git checkout main`
|
||||||
|
* `git rebase upstream/main`
|
||||||
|
* `git checkout your-branch`
|
||||||
|
* `git rebase main`
|
||||||
|
* Fix any merge conflicts
|
||||||
|
* `git push origin your-branch` (origin would be your GitHub repo or `your-github-username/spectre.console` in this case).
|
||||||
|
You may need to `git push origin your-branch --force` to get the commits pushed.
|
||||||
|
This is generally acceptable with topic branches not in the mainstream repository.
|
||||||
|
|
||||||
|
The only reasons a pull request should be closed and resubmitted are as follows:
|
||||||
|
|
||||||
|
* When the pull request is targeting the wrong branch (this doesn't happen as often).
|
||||||
|
* When there are updates made to the original by someone other than the original contributor.
|
||||||
|
Then the old branch is closed with a note on the newer branch this supersedes #github_number.
|
||||||
|
|
||||||
|
## Other general information
|
||||||
|
If you reformat code or hit core functionality without an approval from a person on the Spectre.Console Team,
|
||||||
|
it's likely that no matter how awesome it looks afterwards, it will probably not get accepted.
|
||||||
|
Reformatting code makes it harder for us to evaluate exactly what was changed.
|
||||||
|
|
||||||
|
If you do these things, it will be make evaluation and acceptance easy.
|
||||||
|
Now if you stray outside of the guidelines we have above, it doesn't mean we are going to ignore
|
||||||
|
your pull request. It will just make things harder for us.
|
||||||
|
Harder for us roughly translates to a longer SLA for your pull request.
|
||||||
|
|
||||||
|
## Acknowledgement
|
||||||
|
|
||||||
|
This contribution guide was taken from the [Chocolatey project](https://chocolatey.org/)
|
||||||
|
with permission and was edited to follow Spectre.Console's conventions and processes.
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Spectre Systems AB
|
Copyright (c) 2020 Patrik Svensson, Phil Scott
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
|||||||
6
NuGet.Config
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<configuration>
|
||||||
|
<packageSources>
|
||||||
|
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
|
||||||
|
</packageSources>
|
||||||
|
</configuration>
|
||||||
77
README.fa.md
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
# `Spectre.Console`
|
||||||
|
|
||||||
|
_[](https://www.nuget.org/packages/spectre.console)_
|
||||||
|
|
||||||
|
<div dir="rtl">
|
||||||
|
|
||||||
|
یک کتابخانه NET Standard 2.0/.NET 5. که ایجاد Console Applicationهای زیبا و cross platform را آسانتر میکند.
|
||||||
|
از کتابخانه عالی [Rich](https://github.com/willmcgugan/rich) برای پایتون، بسیار الهام گرفته شده است.
|
||||||
|
|
||||||
|
## فهرست
|
||||||
|
|
||||||
|
1. [امکانات](#features)
|
||||||
|
2. [نصب](#installing)
|
||||||
|
3. [مستندات](#documentation)
|
||||||
|
4. [مثالها](#examples)
|
||||||
|
5. [مجوز](#license)
|
||||||
|
|
||||||
|
<h2 id="features">امکانات</h2>
|
||||||
|
|
||||||
|
* با در نظر گرفتن تست واحد نوشته شده است.
|
||||||
|
* جداول، چارچوبها، پنلها و یک زبان نشانه گذاری که از [rich](https://github.com/willmcgugan/rich) الهام گرفته شده است را پشتیبانی میکند.
|
||||||
|
* از رایج ترین پارامترهای SRG در هنگام فرم دهی متن مانند پررنگ، کم نور، اریب، زیرخط، خط زدن و چشمک زدن پشتیبانی میکند.
|
||||||
|
* پشتیبانی از رنگهای 28/8/4/3-بیت در ترمینال.
|
||||||
|
این کتابخانه توانایی ترمینال فعلی را تشخیص داده و در صورت لزوم رنگها را کاهش میدهد.
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
<h2 id="installing">نصب</h2>
|
||||||
|
|
||||||
|
سریع ترین راه برای شروع `Spectre.Console` نصب از طریق NuGet Package میباشد.
|
||||||
|
|
||||||
|
<pre dir="ltr">
|
||||||
|
dotnet add package Spectre.Console
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="documentation">مستندات</h2>
|
||||||
|
|
||||||
|
مستندات `Spectre.Console` را در اینجا میتوایند پیدا کنید:
|
||||||
|
|
||||||
|
<div dir="ltr">
|
||||||
|
https://spectreconsole.net/
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2 id="examples">مثالها</h2>
|
||||||
|
|
||||||
|
برای بررسی `Spectre.Console` در عمل، ابزار سراسری
|
||||||
|
[dotnet-example](https://github.com/patriksvensson/dotnet-example)
|
||||||
|
را نصب کنید.
|
||||||
|
|
||||||
|
<pre dir="ltr">
|
||||||
|
> dotnet tool restore
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
حالا شما میتوانید مثالهای موجود در این مخزن را لیست کنید:
|
||||||
|
|
||||||
|
<pre dir="ltr">
|
||||||
|
> dotnet example
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
و برای اجرای مثال:
|
||||||
|
|
||||||
|
<pre dir="ltr">
|
||||||
|
> dotnet example tables
|
||||||
|
</pre>
|
||||||
|
|
||||||
|
<h2 id="license">مجوز</h2>
|
||||||
|
|
||||||
|
<div dir="ltr">
|
||||||
|
Copyright © Patrik Svensson, Phil Scott
|
||||||
|
</div>
|
||||||
|
|
||||||
|
همانطور که Spectre.Console تحت مجوز MIT ارائه شده است؛ برای کسب اطلاعات بیشتر به مجوز مراجعه کنید.
|
||||||
|
|
||||||
|
* برای SixLabors.ImageSharp، مشاهده کنید: https://github.com/SixLabors/ImageSharp/blob/master/LICENSE
|
||||||
|
|
||||||
|
</div>
|
||||||
@@ -29,7 +29,7 @@ Python用の素晴らしい[Rich ライブラリ](https://github.com/willmcgugan
|
|||||||
|
|
||||||
## 例
|
## 例
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## 使用方法
|
## 使用方法
|
||||||
|
|
||||||
@@ -111,6 +111,7 @@ Spectre.Consoleでできることを見るために、
|
|||||||
│ Panels │ examples/Panels/Panels.csproj │ Demonstrates how to render items in panels. │
|
│ Panels │ examples/Panels/Panels.csproj │ Demonstrates how to render items in panels. │
|
||||||
│ Rules │ examples/Rules/Rules.csproj │ Demonstrates how to render horizontal rules (lines). │
|
│ 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. │
|
│ Tables │ examples/Tables/Tables.csproj │ Demonstrates how to render tables in a console. │
|
||||||
|
│ Trees │ examples/Trees/Trees.csproj │ Demonstrates how to render trees in a console. │
|
||||||
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
|
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
132
README.md
@@ -2,19 +2,18 @@
|
|||||||
|
|
||||||
_[](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. [Installing](#installing)
|
3. [Documentation](#documentation)
|
||||||
4. [Usage](#usage)
|
4. [Examples](#examples)
|
||||||
4.1. [Using the static API](#using-the-static-api)
|
5. [Sponsors](#sponsors)
|
||||||
4.2. [Creating a console](#creating-a-console)
|
5. [License](#license)
|
||||||
5. [Running examples](#running-examples)
|
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -25,77 +24,27 @@ for Python.
|
|||||||
and blinking text.
|
and blinking text.
|
||||||
* Supports 3/4/8/24-bit colors in the terminal.
|
* Supports 3/4/8/24-bit colors in the terminal.
|
||||||
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
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
## Installing
|
## Installing
|
||||||
|
|
||||||
The fastest way of getting started using Spectre.Console is to install the NuGet package.
|
The fastest way of getting started using `Spectre.Console` is to install the NuGet package.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
dotnet add package Spectre.Console
|
dotnet add package Spectre.Console
|
||||||
```
|
```
|
||||||
|
|
||||||
## Usage
|
## Documentation
|
||||||
|
|
||||||
The `Spectre.Console` API is stateful and is not thread-safe.
|
The documentation for `Spectre.Console` can be found at
|
||||||
If you need to write to the console from different threads, make sure that
|
https://spectreconsole.net/
|
||||||
you take appropriate precautions, just like when you use the
|
|
||||||
regular `System.Console` API.
|
|
||||||
|
|
||||||
If the current terminal does not support ANSI escape sequences,
|
## Examples
|
||||||
`Spectre.Console` will fallback to using the `System.Console` API.
|
|
||||||
|
|
||||||
_NOTE: This library is currently under development and APIs
|
To see `Spectre.Console` in action, install the
|
||||||
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
|
|
||||||
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");
|
|
||||||
```
|
|
||||||
|
|
||||||
If you want to get a reference to the default `IAnsiConsole`,
|
|
||||||
you can access it via `AnsiConsole.Console`.
|
|
||||||
|
|
||||||
### Creating a console
|
|
||||||
|
|
||||||
Sometimes it's useful to explicitly create a console with specific
|
|
||||||
capabilities, such as during unit testing when you want control
|
|
||||||
over the environment your code runs in.
|
|
||||||
|
|
||||||
It's recommended to not use `AnsiConsole` in code that run as
|
|
||||||
part of a unit test.
|
|
||||||
|
|
||||||
```csharp
|
|
||||||
IAnsiConsole console = AnsiConsole.Create(
|
|
||||||
new AnsiConsoleSettings()
|
|
||||||
{
|
|
||||||
Ansi = AnsiSupport.Yes,
|
|
||||||
ColorSystem = ColorSystemSupport.TrueColor,
|
|
||||||
Out = new StringWriter(),
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
_NOTE: Even if you can specify a specific color system to use
|
|
||||||
when manually creating a console, remember that the user's terminal
|
|
||||||
might not be able to use it, so unless you're creating an IAnsiConsole
|
|
||||||
for testing, always use `ColorSystemSupport.Detect` and `AnsiSupport.Detect`._
|
|
||||||
|
|
||||||
## Running examples
|
|
||||||
|
|
||||||
To see Spectre.Console in action, install the
|
|
||||||
[dotnet-example](https://github.com/patriksvensson/dotnet-example)
|
[dotnet-example](https://github.com/patriksvensson/dotnet-example)
|
||||||
global tool.
|
global tool.
|
||||||
|
|
||||||
@@ -107,34 +56,37 @@ Now you can list available examples in this repository:
|
|||||||
|
|
||||||
```
|
```
|
||||||
> dotnet example
|
> 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. │
|
|
||||||
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
|
|
||||||
```
|
```
|
||||||
|
|
||||||
And to run an example:
|
And to run an example:
|
||||||
|
|
||||||
```
|
```
|
||||||
> dotnet example tables
|
> dotnet example tables
|
||||||
┌──────────┬──────────┬────────┐
|
```
|
||||||
│ Foo │ Bar │ Baz │
|
|
||||||
├──────────┼──────────┼────────┤
|
## Sponsors
|
||||||
│ Hello │ World! │ │
|
|
||||||
│ Bonjour │ le │ monde! │
|
The following people are [sponsoring](https://github.com/sponsors/patriksvensson)
|
||||||
│ Hej │ Världen! │ │
|
Spectre.Console to show their support and to ensure the longevity of the project.
|
||||||
└──────────┴──────────┴────────┘
|
|
||||||
```
|
* [Rodney Littles II](https://github.com/RLittlesII)
|
||||||
|
* [Martin Björkström](https://github.com/bjorkstromm)
|
||||||
|
* [Dave Glick](https://github.com/daveaglick)
|
||||||
|
* [Kim Gunanrsson](https://github.com/kimgunnarsson)
|
||||||
|
* [Andrew McClenaghan](https://github.com/andymac4182)
|
||||||
|
* [C. Augusto Proiete](https://github.com/augustoproiete)
|
||||||
|
* [Viktor Elofsson](https://github.com/vktr)
|
||||||
|
* [Steven Knox](https://github.com/stevenknox)
|
||||||
|
* [David Pendray](https://github.com/dpen2000)
|
||||||
|
* [Elmah.io](https://github.com/elmahio)
|
||||||
|
|
||||||
|
I really appreciate it.
|
||||||
|
**Thank you very much!**
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
Copyright © Patrik Svensson, Phil Scott
|
||||||
|
|
||||||
|
Spectre.Console is provided as-is under the MIT license. For more information see LICENSE.
|
||||||
|
|
||||||
|
* For SixLabors.ImageSharp, see https://github.com/SixLabors/ImageSharp/blob/master/LICENSE
|
||||||
65
README.zh.md
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
# `Spectre.Console`
|
||||||
|
|
||||||
|
_[](https://www.nuget.org/packages/spectre.console)_
|
||||||
|
|
||||||
|
`Spectre.Console`是一个 .NET 5/.NET Standard 2.0 的库,能让您在终端里更方便地生成精美的界面。
|
||||||
|
|
||||||
|
深受 [Rich](https://github.com/willmcgugan/rich) 这个优秀库的启发。
|
||||||
|
|
||||||
|
## 目录
|
||||||
|
|
||||||
|
1. [功能](#features)
|
||||||
|
2. [安装](#installing)
|
||||||
|
3. [文档](#documentation)
|
||||||
|
4. [例子](#examples)
|
||||||
|
5. [License](#license)
|
||||||
|
|
||||||
|
## 功能
|
||||||
|
|
||||||
|
* 编写时考虑到了单元测试。
|
||||||
|
* 支持 tables、grid、panel 和 [rich](https://github.com/willmcgugan/rich) 所支持的标记语言。
|
||||||
|
* 支持大部分的 SRG 参数,包括粗体、暗淡字、斜体、下划线、删除线和闪烁文本。
|
||||||
|
* 支持终端显示 3/4/8/24 位色。自动检测终端类型,自适应颜色范围。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 安装
|
||||||
|
|
||||||
|
最快的安装方式,就是用NuGet包管理直接安装Spectre.Console。
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
dotnet add package Spectre.Console
|
||||||
|
```
|
||||||
|
|
||||||
|
## 文档
|
||||||
|
|
||||||
|
`Spectre.Console`的文档可以在这里查看
|
||||||
|
https://spectreconsole.net/
|
||||||
|
|
||||||
|
## 例子
|
||||||
|
|
||||||
|
如果想直接运行`Spectre.Console`的例子,则需要安装[dotnet-example](https://github.com/patriksvensson/dotnet-example)工具。
|
||||||
|
|
||||||
|
```
|
||||||
|
> dotnet tool restore
|
||||||
|
```
|
||||||
|
|
||||||
|
然后你可以列出仓库里的所有例子:
|
||||||
|
|
||||||
|
```
|
||||||
|
> dotnet example
|
||||||
|
```
|
||||||
|
|
||||||
|
跑一个看看效果:
|
||||||
|
|
||||||
|
```
|
||||||
|
> dotnet example tables
|
||||||
|
```
|
||||||
|
|
||||||
|
## License
|
||||||
|
|
||||||
|
版权所有 © Patrik Svensson, Phil Scott
|
||||||
|
|
||||||
|
Spectre.Console 基于 MIT 协议提供。查看 LICENSE 文件了解更多信息。
|
||||||
|
|
||||||
|
* SixLabors.ImageSharp 的协议请查看 https://github.com/SixLabors/ImageSharp/blob/master/LICENSE
|
||||||
@@ -1 +1 @@
|
|||||||
dotnet run -- preview --virtual-dir "spectre.console"
|
dotnet run -- preview
|
||||||
@@ -11,11 +11,10 @@ namespace Docs
|
|||||||
public static async Task<int> Main(string[] args) =>
|
public static async Task<int> Main(string[] args) =>
|
||||||
await Bootstrapper.Factory
|
await Bootstrapper.Factory
|
||||||
.CreateWeb(args)
|
.CreateWeb(args)
|
||||||
.AddSetting(Keys.Host, "spectresystems.github.io")
|
.AddSetting(Keys.Host, "spectreconsole.net")
|
||||||
.AddSetting(Keys.LinkRoot, "/spectre.console")
|
|
||||||
.AddSetting(Keys.LinksUseHttps, true)
|
.AddSetting(Keys.LinksUseHttps, true)
|
||||||
.AddSetting(Constants.EditLink, ConfigureEditLink())
|
.AddSetting(Constants.EditLink, ConfigureEditLink())
|
||||||
.ConfigureSite("spectresystems", "spectre.console", "main")
|
.ConfigureSite("spectreconsole", "spectre.console", "main")
|
||||||
.ConfigureDeployment(deployBranch: "docs")
|
.ConfigureDeployment(deployBranch: "docs")
|
||||||
.AddShortcode("Children", typeof(ChildrenShortcode))
|
.AddShortcode("Children", typeof(ChildrenShortcode))
|
||||||
.AddShortcode("ColorTable", typeof(ColorTableShortcode))
|
.AddShortcode("ColorTable", typeof(ColorTableShortcode))
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
# Documentation
|
# Documentation
|
||||||
|
|
||||||
To start contributing to the [Spectre.Console](https://github.com/spectresystems/spectre.console) documentation, you will need the [.NET Core SDK](https://dot.net) 3.1 or higher.
|
To start contributing to the [Spectre.Console](https://github.com/spectreconsole/spectre.console) documentation, you will need the [.NET Core SDK](https://dot.net) 3.1 or higher.
|
||||||
|
|
||||||
## Running Preview Site
|
## 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.
|
The documentation site uses [Statiq](https://statiq.dev), a static site generator. To build the documentation site run the following in a command-line terminal.
|
||||||
|
|
||||||
```
|
```
|
||||||
> dotnet run preview --virtual-dir "spectre.console"
|
> Preview.ps1
|
||||||
```
|
```
|
||||||
|
|
||||||
After the build is complete, you can navigate to [http://localhost:5080/spectre.console](http://localhost:5080/spectre.console).
|
After the build is complete, you can navigate to [http://localhost:5080/spectre.console](http://localhost:5080/spectre.console).
|
||||||
@@ -29,19 +29,13 @@ Layout and styling can also be found in the [input](./input) directory. Look for
|
|||||||
|
|
||||||
## Custom Build Features
|
## Custom Build Features
|
||||||
|
|
||||||
The documentation site has custom enhancements to Statiq located under the [./src](./src) directory. Enhancements to the build process include:
|
The documentation site has custom enhancements to Statiq located under the [./src](./src) directory.
|
||||||
|
|
||||||
- [Extension Methods](./src/Extensions)
|
|
||||||
- [Models](./src/Models)
|
|
||||||
- [Pipelines](./src/Pipelines)
|
|
||||||
- [Shortcodes](./src/Shortcodes)
|
|
||||||
- [Utilities](./src/Utilities)
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
MIT License
|
MIT License
|
||||||
|
|
||||||
Copyright (c) 2020 Spectre Systems AB
|
Copyright (c) 2020 Patrik Svensson, Phil Scott
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
|||||||
1
docs/input/CNAME
Normal file
@@ -0,0 +1 @@
|
|||||||
|
spectreconsole.net
|
||||||
@@ -41,7 +41,7 @@
|
|||||||
<a class="nav-link font-weight-light font-size-lg text-red" href="https://github.com/sponsors/patriksvensson"><i class="far fa-heart"></i> Sponsor</a>
|
<a class="nav-link font-weight-light font-size-lg text-red" href="https://github.com/sponsors/patriksvensson"><i class="far fa-heart"></i> Sponsor</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link font-weight-light font-size-lg" href="https://github.com/spectresystems/spectre.console"><i class="fab fa-github"></i> GitHub</a>
|
<a class="nav-link font-weight-light font-size-lg" href="https://github.com/spectreconsole/spectre.console"><i class="fab fa-github"></i> GitHub</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -203,7 +203,7 @@
|
|||||||
<div id="footer" class="p-3 text-white font-size-sm">
|
<div id="footer" class="p-3 text-white font-size-sm">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div>
|
<div>
|
||||||
<span>© @DateTime.Today.Year Spectre Systems AB</span>
|
<span>© @DateTime.Today.Year Patrik Svensson, Phil Scott</span>
|
||||||
<span class="float-right" style="color: #888888;">@VersionUtilities.GetVersion()</span>
|
<span class="float-right" style="color: #888888;">@VersionUtilities.GetVersion()</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Title: Appendix
|
Title: Appendix
|
||||||
Order: 10
|
Order: 100
|
||||||
---
|
---
|
||||||
|
|
||||||
<h1>Sections</h1>
|
<h1>Sections</h1>
|
||||||
|
|||||||
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 |
BIN
docs/input/assets/images/example.png
Normal file
|
After Width: | Height: | Size: 219 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/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/tree.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
@@ -31,5 +31,4 @@ $(document).ready(function () {
|
|||||||
}; // keyup
|
}; // keyup
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
}); // ready
|
}); // ready
|
||||||
12
docs/input/cli/index.cshtml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Title: CLI
|
||||||
|
Order: 10
|
||||||
|
---
|
||||||
|
|
||||||
|
<h1>Sections</h1>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
|
||||||
|
{
|
||||||
|
<li>@Html.DocumentLink(child)</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
121
docs/input/cli/introduction.md
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
Title: Introduction
|
||||||
|
Order: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
`Spectre.Console.Cli` is a modern library for parsing command line arguments. While it's extremely
|
||||||
|
opinionated in what it does, it tries to follow established industry conventions, and draws
|
||||||
|
its inspiration from applications you use everyday.
|
||||||
|
|
||||||
|
# How does it work?
|
||||||
|
|
||||||
|
The underlying philosophy behind `Spectre.Console.Cli` is to rely on the .NET type system to
|
||||||
|
declare the commands, but tie everything together via composition.
|
||||||
|
|
||||||
|
Imagine the following command structure:
|
||||||
|
|
||||||
|
* dotnet *(executable)*
|
||||||
|
* add `[PROJECT]`
|
||||||
|
* package `<PACKAGE_NAME>` --version `<VERSION>`
|
||||||
|
* reference `<PROJECT_REFERENCE>`
|
||||||
|
|
||||||
|
For this I would like to implement the commands (the different levels in the tree that
|
||||||
|
executes something) separately from the settings (the options, flags and arguments),
|
||||||
|
which I want to be able to inherit from each other.
|
||||||
|
|
||||||
|
## Specify the settings
|
||||||
|
|
||||||
|
We start by creating some settings that represents the options, flags and arguments
|
||||||
|
that we want to act upon.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class AddSettings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandArgument(0, "[PROJECT]")]
|
||||||
|
public string Project { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddPackageSettings : AddSettings
|
||||||
|
{
|
||||||
|
[CommandArgument(0, "<PACKAGE_NAME>")]
|
||||||
|
public string PackageName { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-v|--version <VERSION>")]
|
||||||
|
public string Version { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddReferenceSettings : AddSettings
|
||||||
|
{
|
||||||
|
[CommandArgument(0, "<PROJECT_REFERENCE>")]
|
||||||
|
public string ProjectReference { get; set; }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Specify the commands
|
||||||
|
|
||||||
|
Now it's time to specify the commands that act on the settings we created
|
||||||
|
in the previous step.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public class AddPackageCommand : Command<AddPackageSettings>
|
||||||
|
{
|
||||||
|
public override int Execute(CommandContext context, AddPackageSettings settings)
|
||||||
|
{
|
||||||
|
// Omitted
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class AddReferenceCommand : Command<AddReferenceSettings>
|
||||||
|
{
|
||||||
|
public override int Execute(CommandContext context, AddReferenceSettings settings)
|
||||||
|
{
|
||||||
|
// Omitted
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use `AsyncCommand` if you need async support.
|
||||||
|
|
||||||
|
## Let's tie it together
|
||||||
|
|
||||||
|
Now when we have our commands and settings implemented, we can compose a command tree
|
||||||
|
that tells the parser how to interpret user input.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace MyApp
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new CommandApp();
|
||||||
|
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.AddBranch<AddSettings>("add", add =>
|
||||||
|
{
|
||||||
|
add.AddCommand<AddPackageCommand>("package");
|
||||||
|
add.AddCommand<AddReferenceCommand>("reference");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# So why this way?
|
||||||
|
|
||||||
|
Now you might wonder, why do things like this? Well, for starters the different parts
|
||||||
|
of the application are separated, while still having the option to share things like options,
|
||||||
|
flags and arguments between them.
|
||||||
|
|
||||||
|
This make the resulting code very clean and easy to navigate, not to mention to unit test.
|
||||||
|
And most importantly at all, the type system guides me to do the right thing. I can't configure
|
||||||
|
commands in non-compatible ways, and if I want to add a new top-level `add-package` command
|
||||||
|
(or move the command completely), it's just a single line to change. This makes it easy to
|
||||||
|
experiment and makes the CLI experience a first class citizen of your application.
|
||||||
47
docs/input/cli/migration.md
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
Title: Migrate from Spectre.Cli
|
||||||
|
Order: 2
|
||||||
|
---
|
||||||
|
|
||||||
|
The functionality in `Spectre.Cli` has been moved into the `Spectre.Console`
|
||||||
|
library. If you're using `Spectre.Cli`, you will need to migrate to ensure
|
||||||
|
that you get updates or fixes.
|
||||||
|
|
||||||
|
## 1. Remove Spectre.Cli NuGet package
|
||||||
|
|
||||||
|
Start with removing the `Spectre.Cli` package reference from your project(s).
|
||||||
|
|
||||||
|
```text
|
||||||
|
> dotnet remove package Spectre.Cli
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Add Spectre.Console NuGet package
|
||||||
|
|
||||||
|
Add the [Spectre.Console](https://www.nuget.org/packages/spectre.console) NuGet package to your project(s).
|
||||||
|
|
||||||
|
```text
|
||||||
|
> dotnet add package Spectre.Console
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Change using statements
|
||||||
|
|
||||||
|
Change all using statements from `Spectre.Cli`
|
||||||
|
to `Spectre.Console.CLi`.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- using Spectre.Cli;
|
||||||
|
+ using Spectre.Console.Cli;
|
||||||
|
```
|
||||||
|
|
||||||
|
# Breaking Changes
|
||||||
|
|
||||||
|
In the process of moving `Spectre.Cli`, there have been some minor breaking changes.
|
||||||
|
|
||||||
|
## Spectre.Cli.Exceptions namespace moved
|
||||||
|
|
||||||
|
All exceptions have been moved from the `Spectre.Cli.Exceptions` namespace to
|
||||||
|
the `Spectre.Console.Cli` namespace.
|
||||||
|
|
||||||
|
```diff
|
||||||
|
- using Spectre.Cli.Exceptions;
|
||||||
|
+ using Spectre.Console.Cli;
|
||||||
|
```
|
||||||
@@ -2,7 +2,7 @@ Title: Exceptions
|
|||||||
Order: 3
|
Order: 3
|
||||||
---
|
---
|
||||||
|
|
||||||
Exceptions isn't always readable when viewed in the terminal.
|
Exceptions aren't always readable when viewed in the terminal.
|
||||||
You can make exception a bit more readable by using the `WriteException` method.
|
You can make exception a bit more readable by using the `WriteException` method.
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
|
|||||||
@@ -22,5 +22,5 @@ for Python written by Will McGugan.
|
|||||||
|
|
||||||
## Examples
|
## Examples
|
||||||
|
|
||||||
<img src="assets/images/table.gif" style="max-width: 100%; margin-top: 15px; margin-bottom: 25px;" />
|
<img src="./assets/images/example.png" style="max-width: 100%; margin-top: 15px; margin-bottom: 25px;" />
|
||||||
<img src="https://github.com/spectresystems/spectre.console/raw/main/resources/gfx/screenshots/example.png" style="max-width: 100%;" />
|
<img src="./assets/images/table.gif" style="max-width: 100%;" />
|
||||||
|
|||||||
12
docs/input/live/index.cshtml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Title: Live Displays
|
||||||
|
Order: 4
|
||||||
|
---
|
||||||
|
|
||||||
|
<h1>Sections</h1>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
|
||||||
|
{
|
||||||
|
<li>@Html.DocumentLink(child)</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
86
docs/input/live/progress.md
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
Title: Progress
|
||||||
|
Order: 5
|
||||||
|
RedirectFrom: progress
|
||||||
|
---
|
||||||
|
|
||||||
|
Spectre.Console can display information about long running tasks in the console.
|
||||||
|
|
||||||
|
<img src="../assets/images/progress.png" style="max-width: 100%;margin-bottom:20px;">
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
<i class="fas fa-exclamation-triangle icon-web"></i> The progress display is not
|
||||||
|
thread safe, and using it together with other interactive components such as
|
||||||
|
prompts, status displays or other progress displays are not supported.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
If the current terminal isn't considered "interactive", such as when running
|
||||||
|
in a continuous integration system, or the terminal can't display
|
||||||
|
ANSI control sequence, any progress will be displayed in a simpler way.
|
||||||
|
|
||||||
|
<img src="../assets/images/progress_fallback.png" style="max-width: 100%;">
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Synchronous
|
||||||
|
AnsiConsole.Progress()
|
||||||
|
.Start(ctx =>
|
||||||
|
{
|
||||||
|
// Define tasks
|
||||||
|
var task1 = ctx.AddTask("[green]Reticulating splines[/]");
|
||||||
|
var task2 = ctx.AddTask("[green]Folding space[/]");
|
||||||
|
|
||||||
|
while(!ctx.IsFinished)
|
||||||
|
{
|
||||||
|
task1.Increment(1.5);
|
||||||
|
task2.Increment(0.5);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Asynchronous progress
|
||||||
|
|
||||||
|
If you prefer to use async/await, you can use `StartAsync` instead of `Start`.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Asynchronous
|
||||||
|
await AnsiConsole.Progress()
|
||||||
|
.StartAsync(async ctx =>
|
||||||
|
{
|
||||||
|
// Define tasks
|
||||||
|
var task1 = ctx.AddTask("[green]Reticulating splines[/]");
|
||||||
|
var task2 = ctx.AddTask("[green]Folding space[/]");
|
||||||
|
|
||||||
|
while (!ctx.IsFinished)
|
||||||
|
{
|
||||||
|
// Simulate some work
|
||||||
|
await Task.Delay(250);
|
||||||
|
|
||||||
|
// Increment
|
||||||
|
task1.Increment(1.5);
|
||||||
|
task2.Increment(0.5);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
# Configure
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Asynchronous
|
||||||
|
AnsiConsole.Progress()
|
||||||
|
.AutoRefresh(false) // Turn off auto refresh
|
||||||
|
.AutoClear(false) // Do not remove the task list when done
|
||||||
|
.HideCompleted(false) // Hide tasks as they are completed
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(), // Task description
|
||||||
|
new ProgressBarColumn(), // Progress bar
|
||||||
|
new PercentageColumn(), // Percentage
|
||||||
|
new RemainingTimeColumn(), // Remaining time
|
||||||
|
new SpinnerColumn(), // Spinner
|
||||||
|
})
|
||||||
|
.Start(ctx =>
|
||||||
|
{
|
||||||
|
// Omitted
|
||||||
|
});
|
||||||
|
```
|
||||||
67
docs/input/live/status.md
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
Title: Status
|
||||||
|
Order: 6
|
||||||
|
RedirectFrom: status
|
||||||
|
---
|
||||||
|
|
||||||
|
Spectre.Console can display information about long running tasks in the console.
|
||||||
|
|
||||||
|
<img src="../assets/images/status.gif" style="max-width: 100%;margin-bottom:20px;">
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
<i class="fas fa-exclamation-triangle icon-web"></i> The status display is not
|
||||||
|
thread safe, and using it together with other interactive components such as
|
||||||
|
prompts, progress displays or other status displays are not supported.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
If the current terminal isn't considered "interactive", such as when running
|
||||||
|
in a continuous integration system, or the terminal can't display
|
||||||
|
ANSI control sequence, any progress will be displayed in a simpler way.
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Synchronous
|
||||||
|
AnsiConsole.Status()
|
||||||
|
.Start("Thinking...", ctx =>
|
||||||
|
{
|
||||||
|
// Simulate some work
|
||||||
|
AnsiConsole.MarkupLine("Doing some work...");
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
|
||||||
|
// Update the status and spinner
|
||||||
|
ctx.Status("Thinking some more");
|
||||||
|
ctx.Spinner(Spinner.Known.Star);
|
||||||
|
ctx.SpinnerStyle(Style.Parse("green"));
|
||||||
|
|
||||||
|
// Simulate some work
|
||||||
|
AnsiConsole.MarkupLine("Doing some more work...");
|
||||||
|
Thread.Sleep(2000);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Asynchronous progress
|
||||||
|
|
||||||
|
If you prefer to use async/await, you can use `StartAsync` instead of `Start`.
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Asynchronous
|
||||||
|
await AnsiConsole.Status()
|
||||||
|
.StartAsync("Thinking...", async ctx =>
|
||||||
|
{
|
||||||
|
// Omitted
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
# Configure
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
AnsiConsole.Status()
|
||||||
|
.AutoRefresh(false)
|
||||||
|
.Spinner(Spinner.Known.Star)
|
||||||
|
.SpinnerStyle(Style.Parse("green bold"))
|
||||||
|
.Start("Thinking...", ctx =>
|
||||||
|
{
|
||||||
|
// Omitted
|
||||||
|
ctx.Refresh();
|
||||||
|
});
|
||||||
|
```
|
||||||
12
docs/input/prompts/index.cshtml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Title: Prompts
|
||||||
|
Order: 5
|
||||||
|
---
|
||||||
|
|
||||||
|
<h1>Sections</h1>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
|
||||||
|
{
|
||||||
|
<li>@Html.DocumentLink(child)</li>
|
||||||
|
}
|
||||||
|
</ul>
|
||||||
40
docs/input/prompts/multiselection.md
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
Title: Multi Selection
|
||||||
|
Order: 3
|
||||||
|
---
|
||||||
|
|
||||||
|
The `MultiSelectionPrompt` can be used when you want the user to select
|
||||||
|
one or many items from a provided list.
|
||||||
|
|
||||||
|
<img src="../assets/images/multiselection.gif" style="width: 100%;" />
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert" style="margin-top:20px;">
|
||||||
|
<i class="fas fa-exclamation-triangle icon-web"></i> The use of prompts
|
||||||
|
insides status or progress displays is not supported.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Ask for the user's favorite fruits
|
||||||
|
var fruits = AnsiConsole.Prompt(
|
||||||
|
new MultiSelectionPrompt<string>()
|
||||||
|
.Title("What are your [green]favorite fruits[/]?")
|
||||||
|
.NotRequired() // Not required to have a favorite fruit
|
||||||
|
.PageSize(10)
|
||||||
|
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
|
||||||
|
.InstructionsText(
|
||||||
|
"[grey](Press [blue]<space>[/] to toggle a fruit, " +
|
||||||
|
"[green]<enter>[/] to accept)[/]")
|
||||||
|
.AddChoice("Apple")
|
||||||
|
.AddChoices(new[] {
|
||||||
|
"Apricot", "Avocado",
|
||||||
|
"Banana", "Blackcurrant", "Blueberry",
|
||||||
|
"Cherry", "Cloudberry", "Cocunut",
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Write the selected fruits to the terminal
|
||||||
|
foreach (string fruit in fruits)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine(fruit);
|
||||||
|
}
|
||||||
|
```
|
||||||
33
docs/input/prompts/selection.md
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
Title: Selection
|
||||||
|
Order: 1
|
||||||
|
---
|
||||||
|
|
||||||
|
The `SelectionPrompt` can be used when you want the user to select
|
||||||
|
a single item from a provided list.
|
||||||
|
|
||||||
|
<img src="../assets/images/selection.gif" style="width: 100%;" />
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert" style="margin-top:20px;">
|
||||||
|
<i class="fas fa-exclamation-triangle icon-web"></i> Using prompts inside
|
||||||
|
status or progress displays, are not supported.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Ask for the user's favorite fruit
|
||||||
|
var fruit = AnsiConsole.Prompt(
|
||||||
|
new SelectionPrompt<string>()
|
||||||
|
.Title("What's your [green]favorite fruit[/]?")
|
||||||
|
.PageSize(10)
|
||||||
|
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
|
||||||
|
.AddChoice("Apple")
|
||||||
|
.AddChoices(new[] {
|
||||||
|
"Apricot", "Avocado",
|
||||||
|
"Banana", "Blackcurrant", "Blueberry",
|
||||||
|
"Cherry", "Cloudberry", "Cocunut",
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Echo the fruit back to the terminal
|
||||||
|
AnsiConsole.WriteLine($"I agree. {fruit} is tasty!");
|
||||||
|
```
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
Title: Prompt
|
Title: Text prompt
|
||||||
Order: 4
|
Order: 0
|
||||||
|
RedirectFrom: prompt
|
||||||
---
|
---
|
||||||
|
|
||||||
Sometimes you want to get some input from the user, and for this
|
Sometimes you want to get some input from the user, and for this
|
||||||
you can use the `Prompt<TResult>`.
|
you can use the `Prompt<TResult>`.
|
||||||
|
|
||||||
|
<div class="alert alert-warning" role="alert">
|
||||||
|
<i class="fas fa-exclamation-triangle icon-web"></i> The use of prompts
|
||||||
|
insides status or progress displays is not supported.
|
||||||
|
</div>
|
||||||
|
|
||||||
# Confirmation
|
# Confirmation
|
||||||
|
|
||||||
```csharp
|
```csharp
|
||||||
@@ -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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
20
docs/input/sponsors.md
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
Title: Sponsors
|
||||||
|
Order: 0
|
||||||
|
---
|
||||||
|
|
||||||
|
The following people are [sponsoring](https://github.com/sponsors/patriksvensson)
|
||||||
|
Spectre.Console to show their support and to ensure the longevity of the project.
|
||||||
|
|
||||||
|
* [Rodney Littles II](https://github.com/RLittlesII)
|
||||||
|
* [Martin Björkström](https://github.com/bjorkstromm)
|
||||||
|
* [Dave Glick](https://github.com/daveaglick)
|
||||||
|
* [Kim Gunanrsson](https://github.com/kimgunnarsson)
|
||||||
|
* [Andrew McClenaghan](https://github.com/andymac4182)
|
||||||
|
* [C. Augusto Proiete](https://github.com/augustoproiete)
|
||||||
|
* [Viktor Elofsson](https://github.com/vktr)
|
||||||
|
* [Steven Knox](https://github.com/stevenknox)
|
||||||
|
* [David Pendray](https://github.com/dpen2000)
|
||||||
|
* [Elmah.io](https://github.com/elmahio)
|
||||||
|
|
||||||
|
I really appreciate it.
|
||||||
|
**Thank you very much!**
|
||||||
75
docs/input/widgets/barchart.md
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
Title: Bar Chart
|
||||||
|
Order: 20
|
||||||
|
---
|
||||||
|
|
||||||
|
Use `BarChart` to render bar charts to the console.
|
||||||
|
|
||||||
|
<img src="../assets/images/barchart.png" style="width: 100%;" />
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
## Basic usage
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
AnsiConsole.Render(new BarChart()
|
||||||
|
.Width(60)
|
||||||
|
.Label("[green bold underline]Number of fruits[/]")
|
||||||
|
.CenterLabel()
|
||||||
|
.AddItem("Apple", 12, Color.Yellow)
|
||||||
|
.AddItem("Orange", 54, Color.Green)
|
||||||
|
.AddItem("Banana", 33, Color.Red));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Add items with converter
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Create a list of fruits
|
||||||
|
var items = new List<(string Label, double Value)>
|
||||||
|
{
|
||||||
|
("Apple", 12),
|
||||||
|
("Orange", 54),
|
||||||
|
("Banana", 33),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render bar chart
|
||||||
|
AnsiConsole.Render(new BarChart()
|
||||||
|
.Width(60)
|
||||||
|
.Label("[green bold underline]Number of fruits[/]")
|
||||||
|
.CenterLabel()
|
||||||
|
.AddItems(items, (item) => new BarChartItem(
|
||||||
|
item.Label, item.Value, Color.Yellow)));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Add items implementing IBarChartItem
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
public sealed class Fruit : IBarChartItem
|
||||||
|
{
|
||||||
|
public string Label { get; set; }
|
||||||
|
public double Value { get; set; }
|
||||||
|
public Color? Color { get; set; }
|
||||||
|
|
||||||
|
public Fruit(string label, double value, Color? color = null)
|
||||||
|
{
|
||||||
|
Label = label;
|
||||||
|
Value = value;
|
||||||
|
Color = color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a list of fruits
|
||||||
|
var items = new List<Fruit>
|
||||||
|
{
|
||||||
|
new Fruit("Apple", 12, Color.Yellow),
|
||||||
|
new Fruit("Orange", 54, Color.Red),
|
||||||
|
new Fruit("Banana", 33, Color.Green),
|
||||||
|
};
|
||||||
|
|
||||||
|
// Render bar chart
|
||||||
|
AnsiConsole.Render(new BarChart()
|
||||||
|
.Width(60)
|
||||||
|
.Label("[green bold underline]Number of fruits[/]")
|
||||||
|
.CenterLabel()
|
||||||
|
.AddItem(new Fruit("Mango", 3))
|
||||||
|
.AddItems(items));
|
||||||
|
```
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Title: Calendar
|
Title: Calendar
|
||||||
Order: 4
|
Order: 40
|
||||||
RedirectFrom: calendar
|
RedirectFrom: 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>
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
Title: Figlet
|
Title: Figlet
|
||||||
Order: 5
|
Order: 50
|
||||||
|
RedirectFrom: figlet
|
||||||
---
|
---
|
||||||
|
|
||||||
Spectre.Console can render [FIGlet](http://www.figlet.org/) text by using the `FigletText` class.
|
Spectre.Console can render [FIGlet](http://www.figlet.org/) text by using the `FigletText` class.
|
||||||
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>
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
Title: Widgets
|
|
||||||
Order: 9
|
|
||||||
---
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
Title: Rule
|
Title: Rule
|
||||||
Order: 5
|
Order: 30
|
||||||
RedirectFrom: rule
|
RedirectFrom: rule
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
Title: Table
|
Title: Table
|
||||||
Order: 3
|
Order: 0
|
||||||
RedirectFrom: tables
|
RedirectFrom: tables
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|||||||
70
docs/input/widgets/tree.md
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
Title: Tree
|
||||||
|
Order: 10
|
||||||
|
---
|
||||||
|
|
||||||
|
The `Tree` widget can be used to render hierarchical data.
|
||||||
|
|
||||||
|
<img src="../assets/images/tree.png" style="width: 100%;" />
|
||||||
|
|
||||||
|
# Usage
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// Create the tree
|
||||||
|
var root = new Tree("Root");
|
||||||
|
|
||||||
|
// Add some nodes
|
||||||
|
var foo = root.AddNode("[yellow]Foo[/]");
|
||||||
|
var table = foo.AddNode(new Table()
|
||||||
|
.RoundedBorder()
|
||||||
|
.AddColumn("First")
|
||||||
|
.AddColumn("Second")
|
||||||
|
.AddRow("1", "2")
|
||||||
|
.AddRow("3", "4")
|
||||||
|
.AddRow("5", "6"));
|
||||||
|
|
||||||
|
table.AddNode("[blue]Baz[/]");
|
||||||
|
foo.AddNode("Qux");
|
||||||
|
|
||||||
|
var bar = root.AddNode("[yellow]Bar[/]");
|
||||||
|
bar.AddNode(new Calendar(2020, 12)
|
||||||
|
.AddCalendarEvent(2020, 12, 12)
|
||||||
|
.HideHeader());
|
||||||
|
|
||||||
|
// Render the tree
|
||||||
|
AnsiConsole.Render(root);
|
||||||
|
```
|
||||||
|
|
||||||
|
# Collapsing nodes
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
root.AddNode("Label").Collapsed();
|
||||||
|
```
|
||||||
|
|
||||||
|
# Appearance
|
||||||
|
|
||||||
|
## Style
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var root = new Tree("Root")
|
||||||
|
.Style("white on red");
|
||||||
|
```
|
||||||
|
|
||||||
|
## Guide lines
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
// ASCII guide lines
|
||||||
|
var root = new Tree("Root")
|
||||||
|
.Guide(TreeGuide.Ascii);
|
||||||
|
|
||||||
|
// Default guide lines
|
||||||
|
var root = new Tree("Root")
|
||||||
|
.Guide(TreeGuide.Line);
|
||||||
|
|
||||||
|
// Double guide lines
|
||||||
|
var root = new Tree("Root")
|
||||||
|
.Guide(TreeGuide.DoubleLine);
|
||||||
|
|
||||||
|
// Bold guide lines
|
||||||
|
var root = new Tree("Root")
|
||||||
|
.Guide(TreeGuide.BoldLine);
|
||||||
|
```
|
||||||
@@ -17,7 +17,7 @@ namespace Docs
|
|||||||
|
|
||||||
public static class Colors
|
public static class Colors
|
||||||
{
|
{
|
||||||
public const string Url = "https://raw.githubusercontent.com/spectresystems/spectre.console/main/resources/scripts/Generator/Data/colors.json";
|
public const string Url = "https://raw.githubusercontent.com/spectreconsole/spectre.console/main/resources/scripts/Generator/Data/colors.json";
|
||||||
public const string Root = "COLORS_ROOT";
|
public const string Root = "COLORS_ROOT";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"cake.tool": {
|
"cake.tool": {
|
||||||
"version": "1.0.0-rc0001",
|
"version": "1.1.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"dotnet-cake"
|
"dotnet-cake"
|
||||||
]
|
]
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"dotnet-example": {
|
"dotnet-example": {
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"dotnet-example"
|
"dotnet-example"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
<Title>Borders</Title>
|
|
||||||
<Description>Demonstrates the different kind of borders.</Description>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
<Title>Calendars</Title>
|
|
||||||
<Description>Demonstrates how to render calendars.</Description>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
|
||||||
16
examples/Cli/Delegates/BarSettings.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public static partial class Program
|
||||||
|
{
|
||||||
|
public sealed class BarSettings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("--count")]
|
||||||
|
[Description("The number of bars to print")]
|
||||||
|
[DefaultValue(1)]
|
||||||
|
public int Count { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
examples/Cli/Delegates/Delegates.csproj
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<ExampleName>Delegates</ExampleName>
|
||||||
|
<ExampleDescription>Demonstrates how to specify commands as delegates.</ExampleDescription>
|
||||||
|
<ExampleGroup>Cli</ExampleGroup>
|
||||||
|
<ExampleVisible>false</ExampleVisible>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
38
examples/Cli/Delegates/Program.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public static partial class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new CommandApp();
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.AddDelegate("foo", Foo)
|
||||||
|
.WithDescription("Foos the bars");
|
||||||
|
|
||||||
|
config.AddDelegate<BarSettings>("bar", Bar)
|
||||||
|
.WithDescription("Bars the foos"); ;
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int Foo(CommandContext context)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine("Foo");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int Bar(CommandContext context, BarSettings settings)
|
||||||
|
{
|
||||||
|
for (var index = 0; index < settings.Count; index++)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine("Bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
examples/Cli/Demo/Commands/Add/AddPackageCommand.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Demo.Utilities;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Commands
|
||||||
|
{
|
||||||
|
[Description("Add a NuGet package reference to the project.")]
|
||||||
|
public sealed class AddPackageCommand : Command<AddPackageCommand.Settings>
|
||||||
|
{
|
||||||
|
public sealed class Settings : AddSettings
|
||||||
|
{
|
||||||
|
[CommandArgument(0, "<PACKAGENAME>")]
|
||||||
|
[Description("The package reference to add.")]
|
||||||
|
public string PackageName { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-v|--version <VERSION>")]
|
||||||
|
[Description("The version of the package to add.")]
|
||||||
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-f|--framework <FRAMEWORK>")]
|
||||||
|
[Description("Add the reference only when targeting a specific framework.")]
|
||||||
|
public string Framework { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--no-restore")]
|
||||||
|
[Description("Add the reference without performing restore preview and compatibility check.")]
|
||||||
|
public bool NoRestore { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--source <SOURCE>")]
|
||||||
|
[Description("The NuGet package source to use during the restore.")]
|
||||||
|
public string Source { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--package-directory <PACKAGEDIR>")]
|
||||||
|
[Description("The directory to restore packages to.")]
|
||||||
|
public string PackageDirectory { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--interactive")]
|
||||||
|
[Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")]
|
||||||
|
public bool Interactive { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Execute(CommandContext context, Settings settings)
|
||||||
|
{
|
||||||
|
SettingsDumper.Dump(settings);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
examples/Cli/Demo/Commands/Add/AddReferenceCommand.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Demo.Utilities;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Commands
|
||||||
|
{
|
||||||
|
public sealed class AddReferenceCommand : Command<AddReferenceCommand.Settings>
|
||||||
|
{
|
||||||
|
public sealed class Settings : AddSettings
|
||||||
|
{
|
||||||
|
[CommandArgument(0, "<PROJECTPATH>")]
|
||||||
|
[Description("The package reference to add.")]
|
||||||
|
public string ProjectPath { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-f|--framework <FRAMEWORK>")]
|
||||||
|
[Description("Add the reference only when targeting a specific framework.")]
|
||||||
|
public string Framework { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--interactive")]
|
||||||
|
[Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")]
|
||||||
|
public bool Interactive { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Execute(CommandContext context, Settings settings)
|
||||||
|
{
|
||||||
|
SettingsDumper.Dump(settings);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
12
examples/Cli/Demo/Commands/Add/AddSettings.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Commands
|
||||||
|
{
|
||||||
|
public abstract class AddSettings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandArgument(0, "<PROJECT>")]
|
||||||
|
[Description("The project file to operate on. If a file is not specified, the command will search the current directory for one.")]
|
||||||
|
public string Project { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
70
examples/Cli/Demo/Commands/Run/RunCommand.cs
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Demo.Utilities;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Commands
|
||||||
|
{
|
||||||
|
[Description("Build and run a .NET project output.")]
|
||||||
|
public sealed class RunCommand : Command<RunCommand.Settings>
|
||||||
|
{
|
||||||
|
public sealed class Settings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("-c|--configuration <CONFIGURATION>")]
|
||||||
|
[Description("The configuration to run for. The default for most projects is '[grey]Debug[/]'.")]
|
||||||
|
[DefaultValue("Debug")]
|
||||||
|
public string Configuration { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-f|--framework <FRAMEWORK>")]
|
||||||
|
[Description("The target framework to run for. The target framework must also be specified in the project file.")]
|
||||||
|
public string Framework { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-r|--runtime <RUNTIMEIDENTIFIER>")]
|
||||||
|
[Description("The target runtime to run for.")]
|
||||||
|
public string RuntimeIdentifier { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-p|--project <PROJECTPATH>")]
|
||||||
|
[Description("The path to the project file to run (defaults to the current directory if there is only one project).")]
|
||||||
|
public string ProjectPath { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--launch-profile <LAUNCHPROFILE>")]
|
||||||
|
[Description("The name of the launch profile (if any) to use when launching the application.")]
|
||||||
|
public string LaunchProfile { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--no-launch-profile")]
|
||||||
|
[Description("Do not attempt to use [grey]launchSettings.json[/] to configure the application.")]
|
||||||
|
public bool NoLaunchProfile { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--no-build")]
|
||||||
|
[Description("Do not build the project before running. Implies [grey]--no-restore[/].")]
|
||||||
|
public bool NoBuild { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--interactive")]
|
||||||
|
[Description("Allows the command to stop and wait for user input or action (for example to complete authentication).")]
|
||||||
|
public string Interactive { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--no-restore")]
|
||||||
|
[Description("Do not restore the project before building.")]
|
||||||
|
public bool NoRestore { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--verbosity <VERBOSITY>")]
|
||||||
|
[Description("Set the MSBuild verbosity level. Allowed values are q[grey]uiet[/], m[grey]inimal[/], n[grey]ormal[/], d[grey]etailed[/], and diag[grey]nostic[/].")]
|
||||||
|
[TypeConverter(typeof(VerbosityConverter))]
|
||||||
|
[DefaultValue(Verbosity.Normal)]
|
||||||
|
public Verbosity Verbosity { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--no-dependencies")]
|
||||||
|
[Description("Do not restore project-to-project references and only restore the specified project.")]
|
||||||
|
public bool NoDependencies { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--force")]
|
||||||
|
[Description("Force all dependencies to be resolved even if the last restore was successful. This is equivalent to deleting [grey]project.assets.json[/].")]
|
||||||
|
public bool Force { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Execute(CommandContext context, Settings settings)
|
||||||
|
{
|
||||||
|
SettingsDumper.Dump(settings);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
examples/Cli/Demo/Commands/Serve/ServeCommand.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using Demo.Utilities;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Commands
|
||||||
|
{
|
||||||
|
[Description("Launches a web server in the current working directory and serves all files in it.")]
|
||||||
|
public sealed class ServeCommand : Command<ServeCommand.Settings>
|
||||||
|
{
|
||||||
|
public sealed class Settings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("-p|--port <PORT>")]
|
||||||
|
[Description("Port to use. Defaults to [grey]8080[/]. Use [grey]0[/] for a dynamic port.")]
|
||||||
|
public int Port { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("-o|--open-browser [BROWSER]")]
|
||||||
|
[Description("Open a web browser when the server starts. You can also specify which browser to use. If none is specified, the default one will be used.")]
|
||||||
|
public FlagValue<string> OpenBrowser { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Execute(CommandContext context, Settings settings)
|
||||||
|
{
|
||||||
|
if (settings.OpenBrowser.IsSet)
|
||||||
|
{
|
||||||
|
var browser = settings.OpenBrowser.Value;
|
||||||
|
if (browser != null)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Open in {browser}");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Console.WriteLine($"Open in default browser.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SettingsDumper.Dump(settings);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
examples/Cli/Demo/Demo.csproj
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<ExampleName>Demo</ExampleName>
|
||||||
|
<ExampleDescription>Demonstrates the most common use cases of Spectre.Cli.</ExampleDescription>
|
||||||
|
<ExampleGroup>Cli</ExampleGroup>
|
||||||
|
<ExampleVisible>false</ExampleVisible>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
37
examples/Cli/Demo/Program.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using Demo.Commands;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new CommandApp();
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.SetApplicationName("fake-dotnet");
|
||||||
|
config.ValidateExamples();
|
||||||
|
config.AddExample(new[] { "run", "--no-build" });
|
||||||
|
|
||||||
|
// Run
|
||||||
|
config.AddCommand<RunCommand>("run");
|
||||||
|
|
||||||
|
// Add
|
||||||
|
config.AddBranch<AddSettings>("add", add =>
|
||||||
|
{
|
||||||
|
add.SetDescription("Add a package or reference to a .NET project");
|
||||||
|
add.AddCommand<AddPackageCommand>("package");
|
||||||
|
add.AddCommand<AddReferenceCommand>("reference");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Serve
|
||||||
|
config.AddCommand<ServeCommand>("serve")
|
||||||
|
.WithExample(new[] { "serve", "-o", "firefox" })
|
||||||
|
.WithExample(new[] { "serve", "--port", "80", "-o", "firefox" });
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
examples/Cli/Demo/Utilities/SettingsDumper.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Utilities
|
||||||
|
{
|
||||||
|
public static class SettingsDumper
|
||||||
|
{
|
||||||
|
public static void Dump(CommandSettings settings)
|
||||||
|
{
|
||||||
|
var table = new Table().RoundedBorder();
|
||||||
|
table.AddColumn("[grey]Name[/]");
|
||||||
|
table.AddColumn("[grey]Value[/]");
|
||||||
|
|
||||||
|
var properties = settings.GetType().GetProperties();
|
||||||
|
foreach (var property in properties)
|
||||||
|
{
|
||||||
|
var value = property.GetValue(settings)
|
||||||
|
?.ToString()
|
||||||
|
?.Replace("[", "[[");
|
||||||
|
|
||||||
|
table.AddRow(
|
||||||
|
property.Name,
|
||||||
|
value ?? "[grey]null[/]");
|
||||||
|
}
|
||||||
|
|
||||||
|
AnsiConsole.Render(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
54
examples/Cli/Demo/Verbosity.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Globalization;
|
||||||
|
|
||||||
|
namespace Demo
|
||||||
|
{
|
||||||
|
public enum Verbosity
|
||||||
|
{
|
||||||
|
Quiet,
|
||||||
|
Minimal,
|
||||||
|
Normal,
|
||||||
|
Detailed,
|
||||||
|
Diagnostic
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class VerbosityConverter : TypeConverter
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, Verbosity> _lookup;
|
||||||
|
|
||||||
|
public VerbosityConverter()
|
||||||
|
{
|
||||||
|
_lookup = new Dictionary<string, Verbosity>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
{ "q", Verbosity.Quiet },
|
||||||
|
{ "quiet", Verbosity.Quiet },
|
||||||
|
{ "m", Verbosity.Minimal },
|
||||||
|
{ "minimal", Verbosity.Minimal },
|
||||||
|
{ "n", Verbosity.Normal },
|
||||||
|
{ "normal", Verbosity.Normal },
|
||||||
|
{ "d", Verbosity.Detailed },
|
||||||
|
{ "detailed", Verbosity.Detailed },
|
||||||
|
{ "diag", Verbosity.Diagnostic },
|
||||||
|
{ "diagnostic", Verbosity.Diagnostic }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
|
{
|
||||||
|
if (value is string stringValue)
|
||||||
|
{
|
||||||
|
var result = _lookup.TryGetValue(stringValue, out var verbosity);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
const string format = "The value '{0}' is not a valid verbosity.";
|
||||||
|
var message = string.Format(CultureInfo.InvariantCulture, format, value);
|
||||||
|
throw new InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
return verbosity;
|
||||||
|
}
|
||||||
|
throw new NotSupportedException("Can't convert value to verbosity.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
17
examples/Cli/Dynamic/Dynamic.csproj
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<ExampleName>Dynamic</ExampleName>
|
||||||
|
<ExampleDescription>Demonstrates how to define dynamic commands.</ExampleDescription>
|
||||||
|
<ExampleGroup>Cli</ExampleGroup>
|
||||||
|
<ExampleVisible>false</ExampleVisible>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
20
examples/Cli/Dynamic/MyCommand.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public sealed class MyCommand : Command
|
||||||
|
{
|
||||||
|
public override int Execute(CommandContext context)
|
||||||
|
{
|
||||||
|
if (!(context.Data is int data))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Command has no associated data.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AnsiConsole.WriteLine("Value = {0}", data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
24
examples/Cli/Dynamic/Program.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new CommandApp();
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
foreach(var index in Enumerable.Range(1, 10))
|
||||||
|
{
|
||||||
|
config.AddCommand<MyCommand>($"c{index}")
|
||||||
|
.WithDescription($"Prints the number {index}")
|
||||||
|
.WithData(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
30
examples/Cli/Injection/Commands/DefaultCommand.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public sealed class DefaultCommand : Command<DefaultCommand.Settings>
|
||||||
|
{
|
||||||
|
private readonly IGreeter _greeter;
|
||||||
|
|
||||||
|
public sealed class Settings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("-n|--name <NAME>")]
|
||||||
|
[Description("The person or thing to greet.")]
|
||||||
|
[DefaultValue("World")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultCommand(IGreeter greeter)
|
||||||
|
{
|
||||||
|
_greeter = greeter ?? throw new ArgumentNullException(nameof(greeter));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Execute(CommandContext context, Settings settings)
|
||||||
|
{
|
||||||
|
_greeter.Greet(settings.Name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Cli/Injection/IGreeter.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public interface IGreeter
|
||||||
|
{
|
||||||
|
void Greet(string name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class HelloWorldGreeter : IGreeter
|
||||||
|
{
|
||||||
|
public void Greet(string name)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine($"Hello {name}!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
examples/Cli/Injection/Infrastructure/TypeRegistrar.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public sealed class TypeRegistrar : ITypeRegistrar
|
||||||
|
{
|
||||||
|
private readonly IServiceCollection _builder;
|
||||||
|
|
||||||
|
public TypeRegistrar(IServiceCollection builder)
|
||||||
|
{
|
||||||
|
_builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeResolver Build()
|
||||||
|
{
|
||||||
|
return new TypeResolver(_builder.BuildServiceProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Register(Type service, Type implementation)
|
||||||
|
{
|
||||||
|
_builder.AddSingleton(service, implementation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterInstance(Type service, object implementation)
|
||||||
|
{
|
||||||
|
_builder.AddSingleton(service, implementation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterLazy(Type service, Func<object> func)
|
||||||
|
{
|
||||||
|
if (func is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(func));
|
||||||
|
}
|
||||||
|
|
||||||
|
_builder.AddSingleton(service, (provider) => func());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
29
examples/Cli/Injection/Infrastructure/TypeResolver.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public sealed class TypeResolver : ITypeResolver, IDisposable
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _provider;
|
||||||
|
|
||||||
|
public TypeResolver(IServiceProvider provider)
|
||||||
|
{
|
||||||
|
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Resolve(Type type)
|
||||||
|
{
|
||||||
|
return _provider.GetRequiredService(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_provider is IDisposable disposable)
|
||||||
|
{
|
||||||
|
disposable.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
examples/Cli/Injection/Injection.csproj
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<ExampleName>Injection</ExampleName>
|
||||||
|
<ExampleDescription>Demonstrates how to use dependency injection with Spectre.Cli.</ExampleDescription>
|
||||||
|
<ExampleGroup>Cli</ExampleGroup>
|
||||||
|
<ExampleVisible>false</ExampleVisible>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="3.1.8" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
22
examples/Cli/Injection/Program.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
examples/Cli/Logging/Commands/HelloCommand.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public class HelloCommand : Command<HelloCommand.Settings>
|
||||||
|
{
|
||||||
|
private ILogger<HelloCommand> _logger;
|
||||||
|
private IAnsiConsole _console;
|
||||||
|
|
||||||
|
public HelloCommand(IAnsiConsole console, ILogger<HelloCommand> logger)
|
||||||
|
{
|
||||||
|
_console = console;
|
||||||
|
_logger = logger;
|
||||||
|
_logger.LogDebug("{0} initialized", nameof(HelloCommand));
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Settings : LogCommandSettings
|
||||||
|
{
|
||||||
|
[CommandArgument(0, "[Name]")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override int Execute(CommandContext context, Settings settings)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Starting my command");
|
||||||
|
AnsiConsole.MarkupLine($"Hello, [blue]{settings.Name}[/]");
|
||||||
|
_logger.LogInformation("Completed my command");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
56
examples/Cli/Logging/Commands/LogCommandSettings.cs
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Globalization;
|
||||||
|
using Serilog.Events;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public class LogCommandSettings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("--logFile")]
|
||||||
|
[Description("Path and file name for logging")]
|
||||||
|
public string LogFile { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--logLevel")]
|
||||||
|
[Description("Minimum level for logging")]
|
||||||
|
[TypeConverter(typeof(VerbosityConverter))]
|
||||||
|
[DefaultValue(LogEventLevel.Information)]
|
||||||
|
public LogEventLevel LogLevel { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class VerbosityConverter : TypeConverter
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, LogEventLevel> _lookup;
|
||||||
|
|
||||||
|
public VerbosityConverter()
|
||||||
|
{
|
||||||
|
_lookup = new Dictionary<string, LogEventLevel>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
{"d", LogEventLevel.Debug},
|
||||||
|
{"v", LogEventLevel.Verbose},
|
||||||
|
{"i", LogEventLevel.Information},
|
||||||
|
{"w", LogEventLevel.Warning},
|
||||||
|
{"e", LogEventLevel.Error},
|
||||||
|
{"f", LogEventLevel.Fatal}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
|
{
|
||||||
|
if (value is string stringValue)
|
||||||
|
{
|
||||||
|
var result = _lookup.TryGetValue(stringValue, out var verbosity);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
const string format = "The value '{0}' is not a valid verbosity.";
|
||||||
|
var message = string.Format(CultureInfo.InvariantCulture, format, value);
|
||||||
|
throw new InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
return verbosity;
|
||||||
|
}
|
||||||
|
throw new NotSupportedException("Can't convert value to verbosity.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
examples/Cli/Logging/Infrastructure/LogInterceptor.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Serilog.Core;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public class LogInterceptor : ICommandInterceptor
|
||||||
|
{
|
||||||
|
public static readonly LoggingLevelSwitch LogLevel = new();
|
||||||
|
|
||||||
|
public void Intercept(CommandContext context, CommandSettings settings)
|
||||||
|
{
|
||||||
|
if (settings is LogCommandSettings logSettings)
|
||||||
|
{
|
||||||
|
LoggingEnricher.Path = logSettings.LogFile ?? "application.log";
|
||||||
|
LogLevel.MinimumLevel = logSettings.LogLevel;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
examples/Cli/Logging/Infrastructure/LoggingEnricher.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using Serilog.Core;
|
||||||
|
using Serilog.Events;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
internal class LoggingEnricher : ILogEventEnricher
|
||||||
|
{
|
||||||
|
private string _cachedLogFilePath;
|
||||||
|
private LogEventProperty _cachedLogFilePathProperty;
|
||||||
|
|
||||||
|
// this path and level will be set by the LogInterceptor.cs after parsing the settings
|
||||||
|
public static string Path = string.Empty;
|
||||||
|
|
||||||
|
public const string LogFilePathPropertyName = "LogFilePath";
|
||||||
|
|
||||||
|
public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
|
||||||
|
{
|
||||||
|
// the settings might not have a path or we might not be within a command in which case
|
||||||
|
// we won't have the setting so a default value for the log file will be required
|
||||||
|
LogEventProperty logFilePathProperty;
|
||||||
|
|
||||||
|
if (_cachedLogFilePathProperty != null && Path.Equals(_cachedLogFilePath))
|
||||||
|
{
|
||||||
|
// Path hasn't changed, so let's use the cached property
|
||||||
|
logFilePathProperty = _cachedLogFilePathProperty;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We've got a new path for the log. Let's create a new property
|
||||||
|
// and cache it for future log events to use
|
||||||
|
_cachedLogFilePath = Path;
|
||||||
|
_cachedLogFilePathProperty = logFilePathProperty = propertyFactory.CreateProperty(LogFilePathPropertyName, Path);
|
||||||
|
}
|
||||||
|
|
||||||
|
logEvent.AddPropertyIfAbsent(logFilePathProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
41
examples/Cli/Logging/Infrastructure/TypeRegistrar.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public sealed class TypeRegistrar : ITypeRegistrar
|
||||||
|
{
|
||||||
|
private readonly IServiceCollection _builder;
|
||||||
|
|
||||||
|
public TypeRegistrar(IServiceCollection builder)
|
||||||
|
{
|
||||||
|
_builder = builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITypeResolver Build()
|
||||||
|
{
|
||||||
|
return new TypeResolver(_builder.BuildServiceProvider());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Register(Type service, Type implementation)
|
||||||
|
{
|
||||||
|
_builder.AddSingleton(service, implementation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterInstance(Type service, object implementation)
|
||||||
|
{
|
||||||
|
_builder.AddSingleton(service, implementation);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RegisterLazy(Type service, Func<object> func)
|
||||||
|
{
|
||||||
|
if (func is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(func));
|
||||||
|
}
|
||||||
|
|
||||||
|
_builder.AddSingleton(service, _ => func());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
examples/Cli/Logging/Infrastructure/TypeResolver.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public sealed class TypeResolver : ITypeResolver
|
||||||
|
{
|
||||||
|
private readonly IServiceProvider _provider;
|
||||||
|
|
||||||
|
public TypeResolver(IServiceProvider provider)
|
||||||
|
{
|
||||||
|
_provider = provider ?? throw new ArgumentNullException(nameof(provider));
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Resolve(Type type)
|
||||||
|
{
|
||||||
|
return _provider.GetRequiredService(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
examples/Cli/Logging/Logging.csproj
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<IsPackable>false</IsPackable>
|
||||||
|
<ExampleName>Logging</ExampleName>
|
||||||
|
<ExampleDescription>Demonstrates how to dynamically configure Serilog for logging using parameters from a command.</ExampleDescription>
|
||||||
|
<ExampleGroup>Cli</ExampleGroup>
|
||||||
|
<ExampleVisible>false</ExampleVisible>
|
||||||
|
<Nullable>disable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="5.0.1" />
|
||||||
|
<PackageReference Include="Serilog" Version="2.10.0" />
|
||||||
|
<PackageReference Include="Serilog.Extensions.Logging" Version="3.0.1" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.File" Version="4.1.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Map" Version="1.0.2" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
53
examples/Cli/Logging/Program.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Serilog;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Dynamically control serilog configuration via command line parameters
|
||||||
|
*
|
||||||
|
* This works around the chicken and egg situation with configuring serilog via the command line.
|
||||||
|
* The logger needs to be configured prior to executing the parser, but the logger needs the parsed values
|
||||||
|
* to be configured. By using serilog.sinks.map we can defer configuration. We use a LogLevelSwitch to control the
|
||||||
|
* logging levels dynamically, and then we use a serilog enricher that has it's state populated via a
|
||||||
|
* Spectre.Console CommandInterceptor
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
static int Main(string[] args)
|
||||||
|
{
|
||||||
|
// to retrieve the log file name, we must first parse the command settings
|
||||||
|
// this will require us to delay setting the file path for the file writer.
|
||||||
|
// With serilog we can use an enricher and Serilog.Sinks.Map to dynamically
|
||||||
|
// pull this setting.
|
||||||
|
var serviceCollection = new ServiceCollection()
|
||||||
|
.AddLogging(configure =>
|
||||||
|
configure.AddSerilog(new LoggerConfiguration()
|
||||||
|
// log level will be dynamically be controlled by our log interceptor upon running
|
||||||
|
.MinimumLevel.ControlledBy(LogInterceptor.LogLevel)
|
||||||
|
// the log enricher will add a new property with the log file path from the settings
|
||||||
|
// that we can use to set the path dynamically
|
||||||
|
.Enrich.With<LoggingEnricher>()
|
||||||
|
// serilog.sinks.map will defer the configuration of the sink to be ondemand
|
||||||
|
// allowing us to look at the properties set by the enricher to set the path appropriately
|
||||||
|
.WriteTo.Map(LoggingEnricher.LogFilePathPropertyName,
|
||||||
|
(logFilePath, wt) => wt.File($"{logFilePath}"), 1)
|
||||||
|
.CreateLogger()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
var registrar = new TypeRegistrar(serviceCollection);
|
||||||
|
var app = new CommandApp(registrar);
|
||||||
|
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.SetInterceptor(new LogInterceptor()); // add the interceptor
|
||||||
|
config.AddCommand<HelloCommand>("hello");
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net5.0</TargetFramework>
|
|
||||||
<IsPackable>false</IsPackable>
|
|
||||||
<Title>Colors</Title>
|
|
||||||
<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,77 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace ColorExample
|
|
||||||
{
|
|
||||||
public static class Utilities
|
|
||||||
{
|
|
||||||
// Borrowed from https://geekymonkey.com/Programming/CSharp/RGB2HSL_HSL2RGB.htm
|
|
||||||
public static Color HSL2RGB(double h, double sl, double l)
|
|
||||||
{
|
|
||||||
double v;
|
|
||||||
double r, g, b;
|
|
||||||
|
|
||||||
r = l; // default to gray
|
|
||||||
g = l;
|
|
||||||
b = l;
|
|
||||||
v = (l <= 0.5) ? (l * (1.0 + sl)) : (l + sl - l * sl);
|
|
||||||
|
|
||||||
if (v > 0)
|
|
||||||
{
|
|
||||||
double m;
|
|
||||||
double sv;
|
|
||||||
int sextant;
|
|
||||||
double fract, vsf, mid1, mid2;
|
|
||||||
|
|
||||||
m = l + l - v;
|
|
||||||
sv = (v - m) / v;
|
|
||||||
h *= 6.0;
|
|
||||||
|
|
||||||
sextant = (int)h;
|
|
||||||
fract = h - sextant;
|
|
||||||
vsf = v * sv * fract;
|
|
||||||
mid1 = m + vsf;
|
|
||||||
mid2 = v - vsf;
|
|
||||||
|
|
||||||
switch (sextant)
|
|
||||||
{
|
|
||||||
case 0:
|
|
||||||
r = v;
|
|
||||||
g = mid1;
|
|
||||||
b = m;
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
r = mid2;
|
|
||||||
g = v;
|
|
||||||
b = m;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
r = m;
|
|
||||||
g = v;
|
|
||||||
b = mid1;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
r = m;
|
|
||||||
g = mid2;
|
|
||||||
b = v;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
r = mid1;
|
|
||||||
g = m;
|
|
||||||
b = v;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
r = v;
|
|
||||||
g = m;
|
|
||||||
b = mid2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return new Color(
|
|
||||||
Convert.ToByte(r * 255.0f),
|
|
||||||
Convert.ToByte(g * 255.0f),
|
|
||||||
Convert.ToByte(b * 255.0f));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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(GetCardContent(user))
|
|
||||||
.Header($"{user.location.country}")
|
|
||||||
.RoundedBorder().Expand());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render all cards in columns
|
|
||||||
AnsiConsole.Render(new Columns(cards));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string GetCardContent(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="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using Spectre.Console;
|
|
||||||
using Spectre.Console.Rendering;
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
namespace BordersExample
|
namespace Spectre.Console.Examples
|
||||||
{
|
{
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
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="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,6 +1,4 @@
|
|||||||
using Spectre.Console;
|
namespace Spectre.Console.Examples
|
||||||
|
|
||||||
namespace Calendars
|
|
||||||
{
|
{
|
||||||
public static class Program
|
public static class Program
|
||||||
{
|
{
|
||||||
22
examples/Console/Canvas/Canvas.csproj
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
<ExampleTitle>Canvas</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render pixels and images.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
<ProjectReference Include="..\..\..\src\Spectre.Console.ImageSharp\Spectre.Console.ImageSharp.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="cake.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
86
examples/Console/Canvas/Mandelbrot.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
Ported from: https://rosettacode.org/wiki/Mandelbrot_set#C.23
|
||||||
|
Licensed under GNU Free Documentation License 1.2
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
examples/Console/Canvas/Program.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
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)");
|
||||||
|
|
||||||
|
// Draw image again, but load from embedded resource rather than file
|
||||||
|
using (var fileStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Canvas.cake.png"))
|
||||||
|
{
|
||||||
|
Debug.Assert(fileStream != null);
|
||||||
|
var embeddedImage = new CanvasImage(fileStream);
|
||||||
|
embeddedImage.BilinearResampler();
|
||||||
|
embeddedImage.MaxWidth(16);
|
||||||
|
Render(embeddedImage, "Image from embedded resource (16 wide)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Render(IRenderable canvas, string title)
|
||||||
|
{
|
||||||
|
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="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
41
examples/Console/Charts/Program.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace Spectre.Console.Examples
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
// Render a bar chart
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
Render("Fruits per month", new BarChart()
|
||||||
|
.Width(60)
|
||||||
|
.Label("[green bold underline]Number of fruits[/]")
|
||||||
|
.CenterLabel()
|
||||||
|
.AddItem("Apple", 12, Color.Yellow)
|
||||||
|
.AddItem("Orange", 54, Color.Green)
|
||||||
|
.AddItem("Banana", 33, Color.Red));
|
||||||
|
|
||||||
|
// Render a breakdown chart
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
Render("Languages used", new BreakdownChart()
|
||||||
|
.FullSize()
|
||||||
|
.Width(60)
|
||||||
|
.ShowPercentage()
|
||||||
|
.AddItem("SCSS", 37, Color.Red)
|
||||||
|
.AddItem("HTML", 28.3, Color.Blue)
|
||||||
|
.AddItem("C#", 22.6, Color.Green)
|
||||||
|
.AddItem("JavaScript", 6, Color.Yellow)
|
||||||
|
.AddItem("Ruby", 6, Color.LightGreen)
|
||||||
|
.AddItem("Shell", 0.1, Color.Aqua));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Render(string title, IRenderable chart)
|
||||||
|
{
|
||||||
|
AnsiConsole.Render(
|
||||||
|
new Panel(chart)
|
||||||
|
.Padding(1, 1)
|
||||||
|
.Header(title));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||