mirror of
https://github.com/spectreconsole/examples.git
synced 2025-10-25 15:19:18 +00:00
Initial commits
This commit is contained in:
178
.editorconfig
Normal file
178
.editorconfig
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
end_of_line = LF
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = false
|
||||||
|
trim_trailing_whitespace = true
|
||||||
|
|
||||||
|
[*.sln]
|
||||||
|
indent_style = tab
|
||||||
|
|
||||||
|
[*.{csproj,vbproj,vcxproj,vcxproj.filters}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.{xml,config,props,targets,nuspec,ruleset}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.{yml,yaml}]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_size = 2
|
||||||
|
|
||||||
|
[*.md]
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
|
||||||
|
[*.cs]
|
||||||
|
# Prefer file scoped namespace declarations
|
||||||
|
csharp_style_namespace_declarations = file_scoped:warning
|
||||||
|
|
||||||
|
# Sort using and Import directives with System.* appearing first
|
||||||
|
dotnet_sort_system_directives_first = true
|
||||||
|
dotnet_separate_import_directive_groups = false
|
||||||
|
|
||||||
|
# Avoid "this." and "Me." if not necessary
|
||||||
|
dotnet_style_qualification_for_field = false:refactoring
|
||||||
|
dotnet_style_qualification_for_property = false:refactoring
|
||||||
|
dotnet_style_qualification_for_method = false:refactoring
|
||||||
|
dotnet_style_qualification_for_event = false:refactoring
|
||||||
|
|
||||||
|
# Use language keywords instead of framework type names for type references
|
||||||
|
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
|
||||||
|
dotnet_style_predefined_type_for_member_access = true:suggestion
|
||||||
|
|
||||||
|
# Suggest more modern language features when available
|
||||||
|
dotnet_style_object_initializer = true:suggestion
|
||||||
|
dotnet_style_collection_initializer = true:suggestion
|
||||||
|
dotnet_style_coalesce_expression = true:suggestion
|
||||||
|
dotnet_style_null_propagation = true:suggestion
|
||||||
|
dotnet_style_explicit_tuple_names = true:suggestion
|
||||||
|
|
||||||
|
# Non-private static fields are PascalCase
|
||||||
|
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = suggestion
|
||||||
|
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields
|
||||||
|
dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style
|
||||||
|
dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
|
||||||
|
dotnet_naming_symbols.non_private_static_fields.required_modifiers = static
|
||||||
|
dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
|
||||||
|
|
||||||
|
# Non-private readonly fields are PascalCase
|
||||||
|
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = suggestion
|
||||||
|
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields
|
||||||
|
dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_readonly_field_style
|
||||||
|
dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field
|
||||||
|
dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
|
||||||
|
dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly
|
||||||
|
dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case
|
||||||
|
|
||||||
|
# Constants are PascalCase
|
||||||
|
dotnet_naming_rule.constants_should_be_pascal_case.severity = suggestion
|
||||||
|
dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants
|
||||||
|
dotnet_naming_rule.constants_should_be_pascal_case.style = constant_style
|
||||||
|
dotnet_naming_symbols.constants.applicable_kinds = field, local
|
||||||
|
dotnet_naming_symbols.constants.required_modifiers = const
|
||||||
|
dotnet_naming_style.constant_style.capitalization = pascal_case
|
||||||
|
|
||||||
|
# Instance fields are camelCase and start with _
|
||||||
|
dotnet_naming_rule.instance_fields_should_be_camel_case.severity = suggestion
|
||||||
|
dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
|
||||||
|
dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
|
||||||
|
dotnet_naming_symbols.instance_fields.applicable_kinds = field
|
||||||
|
dotnet_naming_style.instance_field_style.capitalization = camel_case
|
||||||
|
dotnet_naming_style.instance_field_style.required_prefix = _
|
||||||
|
|
||||||
|
# Locals and parameters are camelCase
|
||||||
|
dotnet_naming_rule.locals_should_be_camel_case.severity = suggestion
|
||||||
|
dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
|
||||||
|
dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
|
||||||
|
dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
|
||||||
|
dotnet_naming_style.camel_case_style.capitalization = camel_case
|
||||||
|
|
||||||
|
# Local functions are PascalCase
|
||||||
|
dotnet_naming_rule.local_functions_should_be_pascal_case.severity = suggestion
|
||||||
|
dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
|
||||||
|
dotnet_naming_rule.local_functions_should_be_pascal_case.style = local_function_style
|
||||||
|
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
|
||||||
|
dotnet_naming_style.local_function_style.capitalization = pascal_case
|
||||||
|
|
||||||
|
# By default, name items with PascalCase
|
||||||
|
dotnet_naming_rule.members_should_be_pascal_case.severity = suggestion
|
||||||
|
dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
|
||||||
|
dotnet_naming_rule.members_should_be_pascal_case.style = pascal_case_style
|
||||||
|
dotnet_naming_symbols.all_members.applicable_kinds = *
|
||||||
|
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
|
||||||
|
|
||||||
|
# Newline settings
|
||||||
|
csharp_new_line_before_open_brace = all
|
||||||
|
csharp_new_line_before_else = true
|
||||||
|
csharp_new_line_before_catch = true
|
||||||
|
csharp_new_line_before_finally = true
|
||||||
|
csharp_new_line_before_members_in_object_initializers = true
|
||||||
|
csharp_new_line_before_members_in_anonymous_types = true
|
||||||
|
csharp_new_line_between_query_expression_clauses = true
|
||||||
|
|
||||||
|
# Indentation preferences
|
||||||
|
csharp_indent_block_contents = true
|
||||||
|
csharp_indent_braces = false
|
||||||
|
csharp_indent_case_contents = true
|
||||||
|
csharp_indent_case_contents_when_block = true
|
||||||
|
csharp_indent_switch_labels = true
|
||||||
|
csharp_indent_labels = flush_left
|
||||||
|
|
||||||
|
# Prefer "var" everywhere
|
||||||
|
csharp_style_var_for_built_in_types = true:suggestion
|
||||||
|
csharp_style_var_when_type_is_apparent = true:suggestion
|
||||||
|
csharp_style_var_elsewhere = true:suggestion
|
||||||
|
|
||||||
|
# Prefer method-like constructs to have a block body
|
||||||
|
csharp_style_expression_bodied_methods = false:none
|
||||||
|
csharp_style_expression_bodied_constructors = false:none
|
||||||
|
csharp_style_expression_bodied_operators = false:none
|
||||||
|
|
||||||
|
# Prefer property-like constructs to have an expression-body
|
||||||
|
csharp_style_expression_bodied_properties = true:none
|
||||||
|
csharp_style_expression_bodied_indexers = true:none
|
||||||
|
csharp_style_expression_bodied_accessors = true:none
|
||||||
|
|
||||||
|
# Suggest more modern language features when available
|
||||||
|
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
|
||||||
|
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
|
||||||
|
csharp_style_inlined_variable_declaration = true:suggestion
|
||||||
|
csharp_style_throw_expression = true:suggestion
|
||||||
|
csharp_style_conditional_delegate_call = true:suggestion
|
||||||
|
|
||||||
|
# Space preferences
|
||||||
|
csharp_space_after_cast = false
|
||||||
|
csharp_space_after_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_after_comma = true
|
||||||
|
csharp_space_after_dot = false
|
||||||
|
csharp_space_after_keywords_in_control_flow_statements = true
|
||||||
|
csharp_space_after_semicolon_in_for_statement = true
|
||||||
|
csharp_space_around_binary_operators = before_and_after
|
||||||
|
csharp_space_around_declaration_statements = do_not_ignore
|
||||||
|
csharp_space_before_colon_in_inheritance_clause = true
|
||||||
|
csharp_space_before_comma = false
|
||||||
|
csharp_space_before_dot = false
|
||||||
|
csharp_space_before_open_square_brackets = false
|
||||||
|
csharp_space_before_semicolon_in_for_statement = false
|
||||||
|
csharp_space_between_empty_square_brackets = false
|
||||||
|
csharp_space_between_method_call_empty_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_call_name_and_opening_parenthesis = false
|
||||||
|
csharp_space_between_method_call_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_method_declaration_name_and_open_parenthesis = false
|
||||||
|
csharp_space_between_method_declaration_parameter_list_parentheses = false
|
||||||
|
csharp_space_between_parentheses = false
|
||||||
|
csharp_space_between_square_brackets = false
|
||||||
|
|
||||||
|
# Blocks are allowed
|
||||||
|
csharp_prefer_braces = true:silent
|
||||||
|
csharp_preserve_single_line_blocks = true
|
||||||
|
csharp_preserve_single_line_statements = true
|
||||||
|
|
||||||
|
# warning RS0037: PublicAPI.txt is missing '#nullable enable'
|
||||||
|
dotnet_diagnostic.RS0037.severity = none
|
||||||
93
.gitignore
vendored
Normal file
93
.gitignore
vendored
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
# Misc folders
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Tt]emp/
|
||||||
|
[Pp]ackages/
|
||||||
|
/.artifacts/
|
||||||
|
/[Tt]ools/
|
||||||
|
.idea
|
||||||
|
.DS_Store
|
||||||
|
|
||||||
|
# Cakeup
|
||||||
|
cakeup-x86_64-latest.exe
|
||||||
|
|
||||||
|
# .NET Core CLI
|
||||||
|
/.dotnet/
|
||||||
|
/.packages/
|
||||||
|
dotnet-install.sh*
|
||||||
|
*.lock.json
|
||||||
|
|
||||||
|
# Visual Studio
|
||||||
|
.vs/
|
||||||
|
.vscode/
|
||||||
|
launchSettings.json
|
||||||
|
*.sln.ide/
|
||||||
|
|
||||||
|
# Rider
|
||||||
|
src/.idea/**/workspace.xml
|
||||||
|
src/.idea/**/tasks.xml
|
||||||
|
src/.idea/dictionaries
|
||||||
|
src/.idea/**/dataSources/
|
||||||
|
src/.idea/**/dataSources.ids
|
||||||
|
src/.idea/**/dataSources.xml
|
||||||
|
src/.idea/**/dataSources.local.xml
|
||||||
|
src/.idea/**/sqlDataSources.xml
|
||||||
|
src/.idea/**/dynamic.xml
|
||||||
|
src/.idea/**/uiDesigner.xml
|
||||||
|
|
||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.sln.docstates
|
||||||
|
*.userprefs
|
||||||
|
*.GhostDoc.xml
|
||||||
|
*StyleCop.Cache
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Rr]elease/
|
||||||
|
x64/
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
.*crunch*.local.xml
|
||||||
|
_NCrunch_*
|
||||||
|
|
||||||
|
# NuGet Packages Directory
|
||||||
|
packages
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
*.received.*
|
||||||
|
|
||||||
|
node_modules
|
||||||
132
CODE_OF_CONDUCT.md
Normal file
132
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
We as members, contributors, and leaders pledge to make participation in our
|
||||||
|
community a harassment-free experience for everyone, regardless of age, body
|
||||||
|
size, visible or invisible disability, ethnicity, sex characteristics, gender
|
||||||
|
identity and expression, level of experience, education, socio-economic status,
|
||||||
|
nationality, personal appearance, race, caste, color, religion, or sexual
|
||||||
|
identity and orientation.
|
||||||
|
|
||||||
|
We pledge to act and interact in ways that contribute to an open, welcoming,
|
||||||
|
diverse, inclusive, and healthy community.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to a positive environment for our
|
||||||
|
community include:
|
||||||
|
|
||||||
|
* Demonstrating empathy and kindness toward other people
|
||||||
|
* Being respectful of differing opinions, viewpoints, and experiences
|
||||||
|
* Giving and gracefully accepting constructive feedback
|
||||||
|
* Accepting responsibility and apologizing to those affected by our mistakes,
|
||||||
|
and learning from the experience
|
||||||
|
* Focusing on what is best not just for us as individuals, but for the overall
|
||||||
|
community
|
||||||
|
|
||||||
|
Examples of unacceptable behavior include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery, and sexual attention or advances of
|
||||||
|
any kind
|
||||||
|
* Trolling, insulting or derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or email address,
|
||||||
|
without their explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a
|
||||||
|
professional setting
|
||||||
|
|
||||||
|
## Enforcement Responsibilities
|
||||||
|
|
||||||
|
Community leaders are responsible for clarifying and enforcing our standards of
|
||||||
|
acceptable behavior and will take appropriate and fair corrective action in
|
||||||
|
response to any behavior that they deem inappropriate, threatening, offensive,
|
||||||
|
or harmful.
|
||||||
|
|
||||||
|
Community leaders have the right and responsibility to remove, edit, or reject
|
||||||
|
comments, commits, code, wiki edits, issues, and other contributions that are
|
||||||
|
not aligned to this Code of Conduct, and will communicate reasons for moderation
|
||||||
|
decisions when appropriate.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies within all community spaces, and also applies when
|
||||||
|
an individual is officially representing the community in public spaces.
|
||||||
|
Examples of representing our community include using an official e-mail address,
|
||||||
|
posting via an official social media account, or acting as an appointed
|
||||||
|
representative at an online or offline event.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||||
|
reported to the community leaders responsible for enforcement at
|
||||||
|
conduct@dotnetfoundation.org.
|
||||||
|
All complaints will be reviewed and investigated promptly and fairly.
|
||||||
|
|
||||||
|
All community leaders are obligated to respect the privacy and security of the
|
||||||
|
reporter of any incident.
|
||||||
|
|
||||||
|
## Enforcement Guidelines
|
||||||
|
|
||||||
|
Community leaders will follow these Community Impact Guidelines in determining
|
||||||
|
the consequences for any action they deem in violation of this Code of Conduct:
|
||||||
|
|
||||||
|
### 1. Correction
|
||||||
|
|
||||||
|
**Community Impact**: Use of inappropriate language or other behavior deemed
|
||||||
|
unprofessional or unwelcome in the community.
|
||||||
|
|
||||||
|
**Consequence**: A private, written warning from community leaders, providing
|
||||||
|
clarity around the nature of the violation and an explanation of why the
|
||||||
|
behavior was inappropriate. A public apology may be requested.
|
||||||
|
|
||||||
|
### 2. Warning
|
||||||
|
|
||||||
|
**Community Impact**: A violation through a single incident or series of
|
||||||
|
actions.
|
||||||
|
|
||||||
|
**Consequence**: A warning with consequences for continued behavior. No
|
||||||
|
interaction with the people involved, including unsolicited interaction with
|
||||||
|
those enforcing the Code of Conduct, for a specified period of time. This
|
||||||
|
includes avoiding interactions in community spaces as well as external channels
|
||||||
|
like social media. Violating these terms may lead to a temporary or permanent
|
||||||
|
ban.
|
||||||
|
|
||||||
|
### 3. Temporary Ban
|
||||||
|
|
||||||
|
**Community Impact**: A serious violation of community standards, including
|
||||||
|
sustained inappropriate behavior.
|
||||||
|
|
||||||
|
**Consequence**: A temporary ban from any sort of interaction or public
|
||||||
|
communication with the community for a specified period of time. No public or
|
||||||
|
private interaction with the people involved, including unsolicited interaction
|
||||||
|
with those enforcing the Code of Conduct, is allowed during this period.
|
||||||
|
Violating these terms may lead to a permanent ban.
|
||||||
|
|
||||||
|
### 4. Permanent Ban
|
||||||
|
|
||||||
|
**Community Impact**: Demonstrating a pattern of violation of community
|
||||||
|
standards, including sustained inappropriate behavior, harassment of an
|
||||||
|
individual, or aggression toward or disparagement of classes of individuals.
|
||||||
|
|
||||||
|
**Consequence**: A permanent ban from any sort of public interaction within the
|
||||||
|
community.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
|
||||||
|
version 2.1, available at
|
||||||
|
[https://www.contributor-covenant.org/version/2/1/code_of_conduct.html][v2.1].
|
||||||
|
|
||||||
|
Community Impact Guidelines were inspired by
|
||||||
|
[Mozilla's code of conduct enforcement ladder][Mozilla CoC].
|
||||||
|
|
||||||
|
For answers to common questions about this code of conduct, see the FAQ at
|
||||||
|
[https://www.contributor-covenant.org/faq][FAQ]. Translations are available at
|
||||||
|
[https://www.contributor-covenant.org/translations][translations].
|
||||||
|
|
||||||
|
[homepage]: https://www.contributor-covenant.org
|
||||||
|
[v2.1]: https://www.contributor-covenant.org/version/2/1/code_of_conduct.html
|
||||||
|
[Mozilla CoC]: https://github.com/mozilla/diversity
|
||||||
|
[FAQ]: https://www.contributor-covenant.org/faq
|
||||||
|
[translations]: https://www.contributor-covenant.org/translations
|
||||||
21
LICENSE.md
Normal file
21
LICENSE.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2020 Patrik Svensson, Phil Scott, Nils Andresen, Cédric Luthi, Frank Ray
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
6
NuGet.Config
Normal file
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>
|
||||||
21
README.md
Normal file
21
README.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
# `Spectre.Console` examples
|
||||||
|
|
||||||
|
To see `Spectre.Console` in action, install the
|
||||||
|
[dotnet-example](https://github.com/patriksvensson/dotnet-example)
|
||||||
|
global tool.
|
||||||
|
|
||||||
|
```
|
||||||
|
> dotnet tool restore
|
||||||
|
```
|
||||||
|
|
||||||
|
Now you can list available examples in this repository:
|
||||||
|
|
||||||
|
```
|
||||||
|
> dotnet example
|
||||||
|
```
|
||||||
|
|
||||||
|
And to run an example:
|
||||||
|
|
||||||
|
```
|
||||||
|
> dotnet example tables
|
||||||
|
```
|
||||||
36
build.cake
Normal file
36
build.cake
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
var target = Argument("target", "Default");
|
||||||
|
var configuration = Argument("configuration", "Release");
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Tasks
|
||||||
|
|
||||||
|
Task("Clean")
|
||||||
|
.Does(context =>
|
||||||
|
{
|
||||||
|
context.CleanDirectory("./.artifacts");
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("Build")
|
||||||
|
.IsDependentOn("Clean")
|
||||||
|
.Does(context =>
|
||||||
|
{
|
||||||
|
DotNetBuild("./examples/Examples.sln", new DotNetBuildSettings {
|
||||||
|
Configuration = configuration,
|
||||||
|
Verbosity = DotNetVerbosity.Minimal,
|
||||||
|
NoLogo = true,
|
||||||
|
NoIncremental = context.HasArgument("rebuild"),
|
||||||
|
MSBuildSettings = new DotNetMSBuildSettings()
|
||||||
|
.TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Targets
|
||||||
|
|
||||||
|
Task("Default")
|
||||||
|
.IsDependentOn("Package");
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Execution
|
||||||
|
|
||||||
|
RunTarget(target)
|
||||||
18
dotnet-tools.json
Normal file
18
dotnet-tools.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"isRoot": true,
|
||||||
|
"tools": {
|
||||||
|
"cake.tool": {
|
||||||
|
"version": "4.0.0",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-cake"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"dotnet-example": {
|
||||||
|
"version": "3.1.0",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-example"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Cli/Delegates/BarSettings.cs
Normal file
15
examples/Cli/Delegates/BarSettings.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Delegates;
|
||||||
|
|
||||||
|
public static partial class Program
|
||||||
|
{
|
||||||
|
public sealed class BarSettings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("--count")]
|
||||||
|
[Description("The number of bars to print")]
|
||||||
|
[DefaultValue(3)]
|
||||||
|
public int Count { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
17
examples/Cli/Delegates/Delegates.csproj
Normal file
17
examples/Cli/Delegates/Delegates.csproj
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.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>
|
||||||
61
examples/Cli/Delegates/Program.cs
Normal file
61
examples/Cli/Delegates/Program.cs
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
using System.Threading.Tasks;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Delegates;
|
||||||
|
|
||||||
|
public static partial class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new CommandApp();
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.AddDelegate("foo", Foo)
|
||||||
|
.WithDescription("Foos the bars");
|
||||||
|
|
||||||
|
config.AddDelegate<BarSettings>("bar", Bar)
|
||||||
|
.WithDescription("Bars the foos");
|
||||||
|
|
||||||
|
config.AddAsyncDelegate("fooAsync", FooAsync)
|
||||||
|
.WithDescription("Foos the bars asynchronously");
|
||||||
|
|
||||||
|
config.AddAsyncDelegate<BarSettings>("barAsync", BarAsync)
|
||||||
|
.WithDescription("Bars the foos asynchronously");
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task<int> FooAsync(CommandContext context)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine("Foo");
|
||||||
|
return Task.FromResult(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Task<int> BarAsync(CommandContext context, BarSettings settings)
|
||||||
|
{
|
||||||
|
for (var index = 0; index < settings.Count; index++)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine("Bar");
|
||||||
|
}
|
||||||
|
|
||||||
|
return Task.FromResult(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
46
examples/Cli/Demo/Commands/Add/AddPackageCommand.cs
Normal file
46
examples/Cli/Demo/Commands/Add/AddPackageCommand.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Demo.Utilities;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Commands.Add;
|
||||||
|
|
||||||
|
[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
examples/Cli/Demo/Commands/Add/AddReferenceCommand.cs
Normal file
29
examples/Cli/Demo/Commands/Add/AddReferenceCommand.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Demo.Utilities;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Commands.Add;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
11
examples/Cli/Demo/Commands/Add/AddSettings.cs
Normal file
11
examples/Cli/Demo/Commands/Add/AddSettings.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Commands.Add;
|
||||||
|
|
||||||
|
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; }
|
||||||
|
}
|
||||||
69
examples/Cli/Demo/Commands/Run/RunCommand.cs
Normal file
69
examples/Cli/Demo/Commands/Run/RunCommand.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System.ComponentModel;
|
||||||
|
using Demo.Utilities;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Commands.Run;
|
||||||
|
|
||||||
|
[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;
|
||||||
|
}
|
||||||
|
}
|
||||||
40
examples/Cli/Demo/Commands/Serve/ServeCommand.cs
Normal file
40
examples/Cli/Demo/Commands/Serve/ServeCommand.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using Demo.Utilities;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Demo.Commands.Serve;
|
||||||
|
|
||||||
|
[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
17
examples/Cli/Demo/Demo.csproj
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.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="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
39
examples/Cli/Demo/Program.cs
Normal file
39
examples/Cli/Demo/Program.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using Demo.Commands;
|
||||||
|
using Demo.Commands.Add;
|
||||||
|
using Demo.Commands.Run;
|
||||||
|
using Demo.Commands.Serve;
|
||||||
|
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("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("serve", "-o", "firefox")
|
||||||
|
.WithExample("serve", "--port", "80", "-o", "firefox");
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
examples/Cli/Demo/Utilities/SettingsDumper.cs
Normal file
28
examples/Cli/Demo/Utilities/SettingsDumper.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
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.Write(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
53
examples/Cli/Demo/Verbosity.cs
Normal file
53
examples/Cli/Demo/Verbosity.cs
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
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
17
examples/Cli/Dynamic/Dynamic.csproj
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.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
20
examples/Cli/Dynamic/MyCommand.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Dynamic;
|
||||||
|
|
||||||
|
public sealed class MyCommand : Command
|
||||||
|
{
|
||||||
|
public override int Execute(CommandContext context)
|
||||||
|
{
|
||||||
|
if (!(context.Data is int data))
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Command has no associated data.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
AnsiConsole.WriteLine("Value = {0}", data);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
examples/Cli/Dynamic/Program.cs
Normal file
23
examples/Cli/Dynamic/Program.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Dynamic;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new CommandApp();
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
foreach (var index in Enumerable.Range(1, 10))
|
||||||
|
{
|
||||||
|
config.AddCommand<MyCommand>($"c{index}")
|
||||||
|
.WithDescription($"Prints the number {index}")
|
||||||
|
.WithData(index);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
30
examples/Cli/Help/CustomHelpProvider.cs
Normal file
30
examples/Cli/Help/CustomHelpProvider.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System.Linq;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
using Spectre.Console.Cli.Help;
|
||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace Help;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example showing how to extend the built-in Spectre.Console help provider
|
||||||
|
/// by rendering a custom banner at the top of the help information
|
||||||
|
/// </summary>
|
||||||
|
internal class CustomHelpProvider : HelpProvider
|
||||||
|
{
|
||||||
|
public CustomHelpProvider(ICommandAppSettings settings)
|
||||||
|
: base(settings)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override IEnumerable<IRenderable> GetHeader(ICommandModel model, ICommandInfo? command)
|
||||||
|
{
|
||||||
|
return new[]
|
||||||
|
{
|
||||||
|
new Text("--------------------------------------"), Text.NewLine,
|
||||||
|
new Text("--- CUSTOM HELP PROVIDER ---"), Text.NewLine,
|
||||||
|
new Text("--------------------------------------"), Text.NewLine,
|
||||||
|
Text.NewLine,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
20
examples/Cli/Help/DefaultCommand.cs
Normal file
20
examples/Cli/Help/DefaultCommand.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Help;
|
||||||
|
|
||||||
|
public sealed class DefaultCommand : Command
|
||||||
|
{
|
||||||
|
private IAnsiConsole _console;
|
||||||
|
|
||||||
|
public DefaultCommand(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
_console = console;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Execute(CommandContext context)
|
||||||
|
{
|
||||||
|
_console.WriteLine("Hello world");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
18
examples/Cli/Help/Help.csproj
Normal file
18
examples/Cli/Help/Help.csproj
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
<ExampleName>Help</ExampleName>
|
||||||
|
<ExampleDescription>Demonstrates how to extend the built-in Spectre.Console help provider to render a custom banner at the top of the help information.</ExampleDescription>
|
||||||
|
<ExampleGroup>Cli</ExampleGroup>
|
||||||
|
<ExampleVisible>false</ExampleVisible>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
23
examples/Cli/Help/Program.cs
Normal file
23
examples/Cli/Help/Program.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Spectre.Console.Cli;
|
||||||
|
using Spectre.Console.Cli.Help;
|
||||||
|
|
||||||
|
namespace Help;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
var app = new CommandApp<DefaultCommand>();
|
||||||
|
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
// Register the custom help provider
|
||||||
|
config.SetHelpProvider(new CustomHelpProvider(config.Settings));
|
||||||
|
|
||||||
|
// Render an unstyled help text for maximum accessibility
|
||||||
|
config.Settings.HelpProviderStyles = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
29
examples/Cli/Injection/Commands/DefaultCommand.cs
Normal file
29
examples/Cli/Injection/Commands/DefaultCommand.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Injection.Commands;
|
||||||
|
|
||||||
|
public sealed class DefaultCommand : Command<DefaultCommand.Settings>
|
||||||
|
{
|
||||||
|
private readonly IGreeter _greeter;
|
||||||
|
|
||||||
|
public sealed class Settings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("-n|--name <NAME>")]
|
||||||
|
[Description("The person or thing to greet.")]
|
||||||
|
[DefaultValue("World")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public DefaultCommand(IGreeter greeter)
|
||||||
|
{
|
||||||
|
_greeter = greeter ?? throw new ArgumentNullException(nameof(greeter));
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int Execute(CommandContext context, Settings settings)
|
||||||
|
{
|
||||||
|
_greeter.Greet(settings.Name);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
16
examples/Cli/Injection/IGreeter.cs
Normal file
16
examples/Cli/Injection/IGreeter.cs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Injection;
|
||||||
|
|
||||||
|
public interface IGreeter
|
||||||
|
{
|
||||||
|
void Greet(string name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class HelloWorldGreeter : IGreeter
|
||||||
|
{
|
||||||
|
public void Greet(string name)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine($"Hello {name}!");
|
||||||
|
}
|
||||||
|
}
|
||||||
40
examples/Cli/Injection/Infrastructure/TypeRegistrar.cs
Normal file
40
examples/Cli/Injection/Infrastructure/TypeRegistrar.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Injection.Infrastructure;
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
32
examples/Cli/Injection/Infrastructure/TypeResolver.cs
Normal file
32
examples/Cli/Injection/Infrastructure/TypeResolver.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Injection.Infrastructure;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _provider.GetService(type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
if (_provider is IDisposable disposable)
|
||||||
|
{
|
||||||
|
disposable.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
examples/Cli/Injection/Injection.csproj
Normal file
21
examples/Cli/Injection/Injection.csproj
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.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="8.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
23
examples/Cli/Injection/Program.cs
Normal file
23
examples/Cli/Injection/Program.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Injection.Commands;
|
||||||
|
using Injection.Infrastructure;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Injection;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
public static int Main(string[] args)
|
||||||
|
{
|
||||||
|
// Create a type registrar and register any dependencies.
|
||||||
|
// A type registrar is an adapter for a DI framework.
|
||||||
|
var registrations = new ServiceCollection();
|
||||||
|
registrations.AddSingleton<IGreeter, HelloWorldGreeter>();
|
||||||
|
var registrar = new TypeRegistrar(registrations);
|
||||||
|
|
||||||
|
// Create a new command app with the registrar
|
||||||
|
// and run it with the provided arguments.
|
||||||
|
var app = new CommandApp<DefaultCommand>(registrar);
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
34
examples/Cli/Logging/Commands/HelloCommand.cs
Normal file
34
examples/Cli/Logging/Commands/HelloCommand.cs
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Logging.Commands;
|
||||||
|
|
||||||
|
public class HelloCommand : Command<HelloCommand.Settings>
|
||||||
|
{
|
||||||
|
private ILogger<HelloCommand> _logger;
|
||||||
|
private IAnsiConsole _console;
|
||||||
|
|
||||||
|
public HelloCommand(IAnsiConsole console, ILogger<HelloCommand> logger)
|
||||||
|
{
|
||||||
|
_console = console;
|
||||||
|
_logger = logger;
|
||||||
|
_logger.LogDebug("{0} initialized", nameof(HelloCommand));
|
||||||
|
}
|
||||||
|
|
||||||
|
public class Settings : LogCommandSettings
|
||||||
|
{
|
||||||
|
[CommandArgument(0, "[Name]")]
|
||||||
|
public string Name { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public override int Execute(CommandContext context, Settings settings)
|
||||||
|
{
|
||||||
|
_logger.LogInformation("Starting my command");
|
||||||
|
AnsiConsole.MarkupLine($"Hello, [blue]{settings.Name}[/]");
|
||||||
|
_logger.LogInformation("Completed my command");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
55
examples/Cli/Logging/Commands/LogCommandSettings.cs
Normal file
55
examples/Cli/Logging/Commands/LogCommandSettings.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Globalization;
|
||||||
|
using Serilog.Events;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Logging.Commands;
|
||||||
|
|
||||||
|
public class LogCommandSettings : CommandSettings
|
||||||
|
{
|
||||||
|
[CommandOption("--logFile")]
|
||||||
|
[Description("Path and file name for logging")]
|
||||||
|
public string LogFile { get; set; }
|
||||||
|
|
||||||
|
[CommandOption("--logLevel")]
|
||||||
|
[Description("Minimum level for logging")]
|
||||||
|
[TypeConverter(typeof(VerbosityConverter))]
|
||||||
|
[DefaultValue(LogEventLevel.Information)]
|
||||||
|
public LogEventLevel LogLevel { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public sealed class VerbosityConverter : TypeConverter
|
||||||
|
{
|
||||||
|
private readonly Dictionary<string, LogEventLevel> _lookup;
|
||||||
|
|
||||||
|
public VerbosityConverter()
|
||||||
|
{
|
||||||
|
_lookup = new Dictionary<string, LogEventLevel>(StringComparer.OrdinalIgnoreCase)
|
||||||
|
{
|
||||||
|
{"d", LogEventLevel.Debug},
|
||||||
|
{"v", LogEventLevel.Verbose},
|
||||||
|
{"i", LogEventLevel.Information},
|
||||||
|
{"w", LogEventLevel.Warning},
|
||||||
|
{"e", LogEventLevel.Error},
|
||||||
|
{"f", LogEventLevel.Fatal}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
|
||||||
|
{
|
||||||
|
if (value is string stringValue)
|
||||||
|
{
|
||||||
|
var result = _lookup.TryGetValue(stringValue, out var verbosity);
|
||||||
|
if (!result)
|
||||||
|
{
|
||||||
|
const string format = "The value '{0}' is not a valid verbosity.";
|
||||||
|
var message = string.Format(CultureInfo.InvariantCulture, format, value);
|
||||||
|
throw new InvalidOperationException(message);
|
||||||
|
}
|
||||||
|
return verbosity;
|
||||||
|
}
|
||||||
|
throw new NotSupportedException("Can't convert value to verbosity.");
|
||||||
|
}
|
||||||
|
}
|
||||||
19
examples/Cli/Logging/Infrastructure/LogInterceptor.cs
Normal file
19
examples/Cli/Logging/Infrastructure/LogInterceptor.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Logging.Commands;
|
||||||
|
using Serilog.Core;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Logging.Infrastructure;
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
37
examples/Cli/Logging/Infrastructure/LoggingEnricher.cs
Normal file
37
examples/Cli/Logging/Infrastructure/LoggingEnricher.cs
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
using Serilog.Core;
|
||||||
|
using Serilog.Events;
|
||||||
|
|
||||||
|
namespace Logging.Infrastructure;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
40
examples/Cli/Logging/Infrastructure/TypeRegistrar.cs
Normal file
40
examples/Cli/Logging/Infrastructure/TypeRegistrar.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using System;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Logging.Infrastructure;
|
||||||
|
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
24
examples/Cli/Logging/Infrastructure/TypeResolver.cs
Normal file
24
examples/Cli/Logging/Infrastructure/TypeResolver.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using System;
|
||||||
|
using Spectre.Console.Cli;
|
||||||
|
|
||||||
|
namespace Logging.Infrastructure;
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if (type == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _provider.GetService(type);
|
||||||
|
}
|
||||||
|
}
|
||||||
26
examples/Cli/Logging/Logging.csproj
Normal file
26
examples/Cli/Logging/Logging.csproj
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.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="8.0.0" />
|
||||||
|
<PackageReference Include="Serilog" Version="4.0.1" />
|
||||||
|
<PackageReference Include="Serilog.Extensions.Logging" Version="8.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.File" Version="6.0.0" />
|
||||||
|
<PackageReference Include="Serilog.Sinks.Map" Version="2.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
54
examples/Cli/Logging/Program.cs
Normal file
54
examples/Cli/Logging/Program.cs
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
using Logging.Commands;
|
||||||
|
using Logging.Infrastructure;
|
||||||
|
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 its state populated via a
|
||||||
|
* Spectre.Console CommandInterceptor
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Logging;
|
||||||
|
|
||||||
|
public class Program
|
||||||
|
{
|
||||||
|
static int Main(string[] args)
|
||||||
|
{
|
||||||
|
// to retrieve the log file name, we must first parse the command settings
|
||||||
|
// this will require us to delay setting the file path for the file writer.
|
||||||
|
// With serilog we can use an enricher and Serilog.Sinks.Map to dynamically
|
||||||
|
// pull this setting.
|
||||||
|
var serviceCollection = new ServiceCollection()
|
||||||
|
.AddLogging(configure =>
|
||||||
|
configure.AddSerilog(new LoggerConfiguration()
|
||||||
|
// log level will be dynamically be controlled by our log interceptor upon running
|
||||||
|
.MinimumLevel.ControlledBy(LogInterceptor.LogLevel)
|
||||||
|
// the log enricher will add a new property with the log file path from the settings
|
||||||
|
// that we can use to set the path dynamically
|
||||||
|
.Enrich.With<LoggingEnricher>()
|
||||||
|
// serilog.sinks.map will defer the configuration of the sink to be ondemand
|
||||||
|
// allowing us to look at the properties set by the enricher to set the path appropriately
|
||||||
|
.WriteTo.Map(LoggingEnricher.LogFilePathPropertyName,
|
||||||
|
(logFilePath, wt) => wt.File($"{logFilePath}"), 1)
|
||||||
|
.CreateLogger()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
var registrar = new TypeRegistrar(serviceCollection);
|
||||||
|
var app = new CommandApp(registrar);
|
||||||
|
|
||||||
|
app.Configure(config =>
|
||||||
|
{
|
||||||
|
config.SetInterceptor(new LogInterceptor()); // add the interceptor
|
||||||
|
config.AddCommand<HelloCommand>("hello");
|
||||||
|
});
|
||||||
|
|
||||||
|
return app.Run(args);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/AlternateScreen/AlternateScreen.csproj
Normal file
15
examples/Console/AlternateScreen/AlternateScreen.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Screens</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to use alternate screens.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
26
examples/Console/AlternateScreen/Program.cs
Normal file
26
examples/Console/AlternateScreen/Program.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
// Check if we can use alternate screen buffers
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
if (!AnsiConsole.Profile.Capabilities.AlternateBuffer)
|
||||||
|
{
|
||||||
|
AnsiConsole.MarkupLine(
|
||||||
|
"[red]Alternate screen buffers are not supported " +
|
||||||
|
"by your terminal[/] [yellow]:([/]");
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write to the terminal
|
||||||
|
AnsiConsole.Write(new Rule("[yellow]Normal universe[/]"));
|
||||||
|
AnsiConsole.Write(new Panel("Hello World!"));
|
||||||
|
AnsiConsole.MarkupLine("[grey]Press a key to continue[/]");
|
||||||
|
AnsiConsole.Console.Input.ReadKey(true);
|
||||||
|
|
||||||
|
AnsiConsole.AlternateScreen(() =>
|
||||||
|
{
|
||||||
|
// Now we're in another terminal screen buffer
|
||||||
|
AnsiConsole.Write(new Rule("[red]Mirror universe[/]"));
|
||||||
|
AnsiConsole.Write(new Panel("[red]Welcome to the upside down![/]"));
|
||||||
|
AnsiConsole.MarkupLine("[grey]Press a key to return[/]");
|
||||||
|
AnsiConsole.Console.Input.ReadKey(true);
|
||||||
|
});
|
||||||
15
examples/Console/Borders/Borders.csproj
Normal file
15
examples/Console/Borders/Borders.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.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>
|
||||||
86
examples/Console/Borders/Program.cs
Normal file
86
examples/Console/Borders/Program.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace Borders;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
// Render panel borders
|
||||||
|
HorizontalRule("PANEL BORDERS");
|
||||||
|
PanelBorders();
|
||||||
|
|
||||||
|
// Render table borders
|
||||||
|
HorizontalRule("TABLE BORDERS");
|
||||||
|
TableBorders();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void PanelBorders()
|
||||||
|
{
|
||||||
|
static IRenderable CreatePanel(string name, BoxBorder border)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
new Panel($"This is a panel with\nthe [yellow]{name}[/] border.")
|
||||||
|
.Header($" [blue]{name}[/] ", Justify.Center)
|
||||||
|
.Border(border)
|
||||||
|
.BorderStyle(Style.Parse("grey"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = new[]
|
||||||
|
{
|
||||||
|
CreatePanel("Ascii", BoxBorder.Ascii),
|
||||||
|
CreatePanel("Square", BoxBorder.Square),
|
||||||
|
CreatePanel("Rounded", BoxBorder.Rounded),
|
||||||
|
CreatePanel("Heavy", BoxBorder.Heavy),
|
||||||
|
CreatePanel("Double", BoxBorder.Double),
|
||||||
|
CreatePanel("None", BoxBorder.None),
|
||||||
|
};
|
||||||
|
|
||||||
|
AnsiConsole.Write(
|
||||||
|
new Padder(
|
||||||
|
new Columns(items).PadRight(2),
|
||||||
|
new Padding(2, 0, 0, 0)));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void TableBorders()
|
||||||
|
{
|
||||||
|
static IRenderable CreateTable(string name, TableBorder border)
|
||||||
|
{
|
||||||
|
var table = new Table().Border(border);
|
||||||
|
table.ShowRowSeparators();
|
||||||
|
table.AddColumn("[yellow]Header 1[/]", c => c.Footer("[grey]Footer 1[/]"));
|
||||||
|
table.AddColumn("[yellow]Header 2[/]", col => col.Footer("[grey]Footer 2[/]").RightAligned());
|
||||||
|
table.AddRow("Cell", "Cell");
|
||||||
|
table.AddRow("Cell", "Cell");
|
||||||
|
|
||||||
|
return new Panel(table)
|
||||||
|
.Header($" [blue]{name}[/] ", Justify.Center)
|
||||||
|
.PadBottom(1)
|
||||||
|
.NoBorder();
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = new[]
|
||||||
|
{
|
||||||
|
CreateTable("Ascii", TableBorder.Ascii), CreateTable("Ascii2", TableBorder.Ascii2),
|
||||||
|
CreateTable("AsciiDoubleHead", TableBorder.AsciiDoubleHead),
|
||||||
|
CreateTable("Horizontal", TableBorder.Horizontal), CreateTable("Simple", TableBorder.Simple),
|
||||||
|
CreateTable("SimpleHeavy", TableBorder.SimpleHeavy), CreateTable("Minimal", TableBorder.Minimal),
|
||||||
|
CreateTable("MinimalHeavyHead", TableBorder.MinimalHeavyHead),
|
||||||
|
CreateTable("MinimalDoubleHead", TableBorder.MinimalDoubleHead),
|
||||||
|
CreateTable("Square", TableBorder.Square), CreateTable("Rounded", TableBorder.Rounded),
|
||||||
|
CreateTable("Heavy", TableBorder.Heavy), CreateTable("HeavyEdge", TableBorder.HeavyEdge),
|
||||||
|
CreateTable("HeavyHead", TableBorder.HeavyHead), CreateTable("Double", TableBorder.Double),
|
||||||
|
CreateTable("DoubleEdge", TableBorder.DoubleEdge), CreateTable("Markdown", TableBorder.Markdown),
|
||||||
|
};
|
||||||
|
|
||||||
|
AnsiConsole.Write(new Columns(items).Collapse());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void HorizontalRule(string title)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule($"[white bold]{title}[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Calendars/Calendars.csproj
Normal file
15
examples/Console/Calendars/Calendars.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Calendars</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render calendars.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
18
examples/Console/Calendars/Program.cs
Normal file
18
examples/Console/Calendars/Program.cs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Calendars;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Calendar(2020, 10)
|
||||||
|
.RoundedBorder()
|
||||||
|
.HighlightStyle(Style.Parse("red"))
|
||||||
|
.HeaderStyle(Style.Parse("yellow"))
|
||||||
|
.AddCalendarEvent("An event", 2020, 9, 22)
|
||||||
|
.AddCalendarEvent("Another event", 2020, 10, 2)
|
||||||
|
.AddCalendarEvent("A third event", 2020, 10, 13));
|
||||||
|
}
|
||||||
|
}
|
||||||
21
examples/Console/Canvas/Canvas.csproj
Normal file
21
examples/Console/Canvas/Canvas.csproj
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Canvas</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render pixels and images.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="cake.png">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</EmbeddedResource>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
43
examples/Console/Canvas/Program.cs
Normal file
43
examples/Console/Canvas/Program.cs
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
using System.Diagnostics;
|
||||||
|
using System.Reflection;
|
||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace Canvas;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
// 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 max 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.Write(new Rule($"[yellow]{title}[/]").LeftJustified().RuleStyle("grey"));
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
examples/Console/Canvas/cake.png
Normal file
BIN
examples/Console/Canvas/cake.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 52 KiB |
15
examples/Console/Charts/Charts.csproj
Normal file
15
examples/Console/Charts/Charts.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.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>
|
||||||
42
examples/Console/Charts/Program.cs
Normal file
42
examples/Console/Charts/Program.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace Charts;
|
||||||
|
|
||||||
|
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()
|
||||||
|
.WithValueColor(Color.Orange1)
|
||||||
|
.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.Write(
|
||||||
|
new Panel(chart)
|
||||||
|
.Padding(1, 1)
|
||||||
|
.Header(title));
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Colors/Colors.csproj
Normal file
15
examples/Console/Colors/Colors.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Colors</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console.</ExampleDescription>
|
||||||
|
<ExampleGroup>Misc</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
105
examples/Console/Colors/Program.cs
Normal file
105
examples/Console/Colors/Program.cs
Normal file
@@ -0,0 +1,105 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Examples;
|
||||||
|
|
||||||
|
namespace Colors;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// No colors
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
if (AnsiConsole.Profile.Capabilities.ColorSystem == ColorSystem.NoColors)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine("No colors are supported.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// 3-BIT
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
if (AnsiConsole.Profile.Supports(ColorSystem.Legacy))
|
||||||
|
{
|
||||||
|
AnsiConsole.ResetColors();
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule("[yellow bold underline]3-bit Colors[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
|
||||||
|
for (var i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
AnsiConsole.Background = Color.FromInt32(i);
|
||||||
|
AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor();
|
||||||
|
AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString()));
|
||||||
|
AnsiConsole.ResetColors();
|
||||||
|
if ((i + 1) % 8 == 0)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// 4-BIT
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
if (AnsiConsole.Profile.Supports(ColorSystem.Standard))
|
||||||
|
{
|
||||||
|
AnsiConsole.ResetColors();
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule("[yellow bold underline]4-bit Colors[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
|
||||||
|
for (var i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
AnsiConsole.Background = Color.FromInt32(i);
|
||||||
|
AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor();
|
||||||
|
AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString()));
|
||||||
|
AnsiConsole.ResetColors();
|
||||||
|
if ((i + 1) % 8 == 0)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// 8-BIT
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
if (AnsiConsole.Profile.Supports(ColorSystem.EightBit))
|
||||||
|
{
|
||||||
|
AnsiConsole.ResetColors();
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule("[yellow bold underline]8-bit Colors[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
|
||||||
|
for (var i = 0; i < 16; i++)
|
||||||
|
{
|
||||||
|
for (var j = 0; j < 16; j++)
|
||||||
|
{
|
||||||
|
var number = i * 16 + j;
|
||||||
|
AnsiConsole.Background = Color.FromInt32(number);
|
||||||
|
AnsiConsole.Foreground = AnsiConsole.Background.GetInvertedColor();
|
||||||
|
AnsiConsole.Write(string.Format(" {0,-4}", number));
|
||||||
|
AnsiConsole.ResetColors();
|
||||||
|
if ((number + 1) % 16 == 0)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
// 24-BIT
|
||||||
|
/////////////////////////////////////////////////////////////////
|
||||||
|
if (AnsiConsole.Profile.Supports(ColorSystem.TrueColor))
|
||||||
|
{
|
||||||
|
AnsiConsole.ResetColors();
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule("[yellow bold underline]24-bit Colors[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
|
||||||
|
AnsiConsole.Write(new ColorBox(width: 80, height: 15));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
19
examples/Console/Columns/Columns.csproj
Normal file
19
examples/Console/Columns/Columns.csproj
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Columns</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render data into columns.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
30
examples/Console/Columns/Program.cs
Normal file
30
examples/Console/Columns/Program.cs
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Columns;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
var cards = new List<Panel>();
|
||||||
|
foreach (var user in User.LoadUsers())
|
||||||
|
{
|
||||||
|
cards.Add(
|
||||||
|
new Panel(GetCardContent(user))
|
||||||
|
.Header($"{user.Country}")
|
||||||
|
.RoundedBorder().Expand());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render all cards in columns
|
||||||
|
AnsiConsole.Write(new Spectre.Console.Columns(cards));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string GetCardContent(User user)
|
||||||
|
{
|
||||||
|
var name = $"{user.FirstName} {user.LastName}";
|
||||||
|
var city = $"{user.City}";
|
||||||
|
|
||||||
|
return $"[b]{name}[/]\n[yellow]{city}[/]";
|
||||||
|
}
|
||||||
|
}
|
||||||
88
examples/Console/Columns/User.cs
Normal file
88
examples/Console/Columns/User.cs
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Columns;
|
||||||
|
|
||||||
|
public sealed class User
|
||||||
|
{
|
||||||
|
public string FirstName { get; set; }
|
||||||
|
public string LastName { get; set; }
|
||||||
|
public string City { get; set; }
|
||||||
|
public string Country { get; set; }
|
||||||
|
|
||||||
|
public static List<User> LoadUsers()
|
||||||
|
{
|
||||||
|
return new List<User>
|
||||||
|
{
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
FirstName = "Andrea",
|
||||||
|
LastName = "Johansen",
|
||||||
|
City = "Hornbæk",
|
||||||
|
Country = "Denmark",
|
||||||
|
},
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
FirstName = "Phil",
|
||||||
|
LastName = "Scott",
|
||||||
|
City = "Dayton",
|
||||||
|
Country = "United States",
|
||||||
|
},
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
FirstName = "Patrik",
|
||||||
|
LastName = "Svensson",
|
||||||
|
City = "Stockholm",
|
||||||
|
Country = "Sweden",
|
||||||
|
},
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
FirstName = "Freya",
|
||||||
|
LastName = "Thompson",
|
||||||
|
City = "Rotorua",
|
||||||
|
Country = "New Zealand",
|
||||||
|
},
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
FirstName = "طاها",
|
||||||
|
LastName = "رضایی",
|
||||||
|
City = "اهواز",
|
||||||
|
Country = "Iran",
|
||||||
|
},
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
FirstName = "Yara",
|
||||||
|
LastName = "Simon",
|
||||||
|
City = "Develier",
|
||||||
|
Country = "Switzerland",
|
||||||
|
},
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
FirstName = "Giray",
|
||||||
|
LastName = "Erbay",
|
||||||
|
City = "Karabük",
|
||||||
|
Country = "Turkey",
|
||||||
|
},
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
FirstName = "Miodrag",
|
||||||
|
LastName = "Schaffer",
|
||||||
|
City = "Möckern",
|
||||||
|
Country = "Germany",
|
||||||
|
},
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
FirstName = "Carmela",
|
||||||
|
LastName = "Lo Castro",
|
||||||
|
City = "Firenze",
|
||||||
|
Country = "Italy",
|
||||||
|
},
|
||||||
|
new User
|
||||||
|
{
|
||||||
|
FirstName = "Roberto",
|
||||||
|
LastName = "Sims",
|
||||||
|
City = "Mallow",
|
||||||
|
Country = "Ireland",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Cursor/Cursor.csproj
Normal file
15
examples/Console/Cursor/Cursor.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Cursor</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to move the cursor.</ExampleDescription>
|
||||||
|
<ExampleGroup>Misc</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
19
examples/Console/Cursor/Program.cs
Normal file
19
examples/Console/Cursor/Program.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Cursor;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
AnsiConsole.Write("Hello");
|
||||||
|
|
||||||
|
// Move the cursor 3 cells to the right
|
||||||
|
AnsiConsole.Cursor.Move(CursorDirection.Right, 3);
|
||||||
|
AnsiConsole.Write("World");
|
||||||
|
|
||||||
|
// Move the cursor 5 cells to the left.
|
||||||
|
AnsiConsole.Cursor.Move(CursorDirection.Left, 5);
|
||||||
|
AnsiConsole.WriteLine("Universe");
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Decorations/Decorations.csproj
Normal file
15
examples/Console/Decorations/Decorations.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Decorations</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to [italic]use[/] [bold]decorations[/] [dim]in[/] the console.</ExampleDescription>
|
||||||
|
<ExampleGroup>Misc</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
29
examples/Console/Decorations/Program.cs
Normal file
29
examples/Console/Decorations/Program.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Colors;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
AnsiConsole.ResetDecoration();
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
|
||||||
|
if (AnsiConsole.Profile.Capabilities.Ansi)
|
||||||
|
{
|
||||||
|
AnsiConsole.Write(new Rule("[bold green]ANSI Decorations[/]"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AnsiConsole.Write(new Rule("[bold red]Legacy Decorations (unsupported)[/]"));
|
||||||
|
}
|
||||||
|
|
||||||
|
var decorations = System.Enum.GetValues(typeof(Decoration));
|
||||||
|
foreach (var decoration in decorations)
|
||||||
|
{
|
||||||
|
var name = System.Enum.GetName(typeof(Decoration),decoration);
|
||||||
|
AnsiConsole.Write(name + ": ");
|
||||||
|
AnsiConsole.Write(new Markup(name+"\n", new Style(decoration: (Decoration)decoration)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Emojis/Emojis.csproj
Normal file
15
examples/Console/Emojis/Emojis.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Emojis</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render emojis.</ExampleDescription>
|
||||||
|
<ExampleGroup>Misc</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
23
examples/Console/Emojis/Program.cs
Normal file
23
examples/Console/Emojis/Program.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Emojis;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// Show a known emoji
|
||||||
|
RenderEmoji();
|
||||||
|
|
||||||
|
// Show a remapped emoji
|
||||||
|
Emoji.Remap("globe_showing_europe_africa", Emoji.Known.GrinningFaceWithSmilingEyes);
|
||||||
|
RenderEmoji();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void RenderEmoji()
|
||||||
|
{
|
||||||
|
AnsiConsole.Write(
|
||||||
|
new Panel("[yellow]Hello :globe_showing_europe_africa:![/]")
|
||||||
|
.RoundedBorder());
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Exceptions/Exceptions.csproj
Normal file
15
examples/Console/Exceptions/Exceptions.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Exceptions</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render formatted exceptions.</ExampleDescription>
|
||||||
|
<ExampleGroup>Misc</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
101
examples/Console/Exceptions/Program.cs
Normal file
101
examples/Console/Exceptions/Program.cs
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Authentication;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Exceptions;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var foo = new List<string>();
|
||||||
|
DoMagic(42, null, ref foo);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule("Default").LeftJustified());
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.WriteException(ex);
|
||||||
|
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule("Compact").LeftJustified());
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks);
|
||||||
|
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule("Compact + Custom colors").LeftJustified());
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.WriteException(ex, new ExceptionSettings
|
||||||
|
{
|
||||||
|
Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
|
||||||
|
Style = new ExceptionStyle
|
||||||
|
{
|
||||||
|
Exception = new Style().Foreground(Color.Grey),
|
||||||
|
Message = new Style().Foreground(Color.White),
|
||||||
|
NonEmphasized = new Style().Foreground(Color.Cornsilk1),
|
||||||
|
Parenthesis = new Style().Foreground(Color.Cornsilk1),
|
||||||
|
Method = new Style().Foreground(Color.Red),
|
||||||
|
ParameterName = new Style().Foreground(Color.Cornsilk1),
|
||||||
|
ParameterType = new Style().Foreground(Color.Red),
|
||||||
|
Path = new Style().Foreground(Color.Red),
|
||||||
|
LineNumber = new Style().Foreground(Color.Cornsilk1),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await DoMagicAsync<int>(42, null);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule("Async").LeftJustified());
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenPaths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DoMagic(int foo, string[,] bar, ref List<string> result)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CheckCredentials(foo, bar);
|
||||||
|
result = new List<string>();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Whaaat?", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool CheckCredentials(int? qux, string[,] corgi)
|
||||||
|
{
|
||||||
|
throw new InvalidCredentialException("The credentials are invalid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task DoMagicAsync<T>(T foo, string[,] bar)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await CheckCredentialsAsync(new[] { foo }.ToList(), new []{ foo }, bar);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Whaaat?", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<bool> CheckCredentialsAsync<T>(List<T> qux, T[] otherArray, string[,] corgi)
|
||||||
|
{
|
||||||
|
await Task.Delay(0);
|
||||||
|
throw new InvalidCredentialException("The credentials are invalid.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
15
examples/Console/Figlet/Figlet.csproj
Normal file
15
examples/Console/Figlet/Figlet.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Figlet</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render FIGlet text.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
13
examples/Console/Figlet/Program.cs
Normal file
13
examples/Console/Figlet/Program.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Figlet;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
AnsiConsole.Write(new FigletText("Left aligned").LeftJustified().Color(Color.Red));
|
||||||
|
AnsiConsole.Write(new FigletText("Centered").Centered().Color(Color.Green));
|
||||||
|
AnsiConsole.Write(new FigletText("Right aligned").RightJustified().Color(Color.Blue));
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Grids/Grids.csproj
Normal file
15
examples/Console/Grids/Grids.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Grids</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render grids in a console.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
23
examples/Console/Grids/Program.cs
Normal file
23
examples/Console/Grids/Program.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Grids;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options]] [[[[--]] <additional arguments>...]]]][/]");
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
|
||||||
|
var grid = new Grid();
|
||||||
|
grid.AddColumn(new GridColumn().NoWrap());
|
||||||
|
grid.AddColumn(new GridColumn().PadLeft(2));
|
||||||
|
grid.AddRow("Options:");
|
||||||
|
grid.AddRow(" [blue]-h[/], [blue]--help[/]", "Show command line help.");
|
||||||
|
grid.AddRow(" [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "The configuration to run for.");
|
||||||
|
grid.AddRow(" [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "Set the [grey]MSBuild[/] verbosity level.");
|
||||||
|
|
||||||
|
AnsiConsole.Write(grid);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Info/Info.csproj
Normal file
15
examples/Console/Info/Info.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Info</ExampleTitle>
|
||||||
|
<ExampleDescription>Displays the capabilities of the current console.</ExampleDescription>
|
||||||
|
<ExampleGroup>Misc</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
33
examples/Console/Info/Program.cs
Normal file
33
examples/Console/Info/Program.cs
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Info;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
var grid = new Grid()
|
||||||
|
.AddColumn(new GridColumn().NoWrap().PadRight(4))
|
||||||
|
.AddColumn()
|
||||||
|
.AddRow("[b]Enrichers[/]", string.Join(", ", AnsiConsole.Profile.Enrichers))
|
||||||
|
.AddRow("[b]Color system[/]", $"{AnsiConsole.Profile.Capabilities.ColorSystem}")
|
||||||
|
.AddRow("[b]Unicode?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Unicode)}")
|
||||||
|
.AddRow("[b]Supports ansi?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Ansi)}")
|
||||||
|
.AddRow("[b]Supports links?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Links)}")
|
||||||
|
.AddRow("[b]Legacy console?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Legacy)}")
|
||||||
|
.AddRow("[b]Interactive?[/]", $"{YesNo(AnsiConsole.Profile.Capabilities.Interactive)}")
|
||||||
|
.AddRow("[b]Terminal?[/]", $"{YesNo(AnsiConsole.Profile.Out.IsTerminal)}")
|
||||||
|
.AddRow("[b]Buffer width[/]", $"{AnsiConsole.Console.Profile.Width}")
|
||||||
|
.AddRow("[b]Buffer height[/]", $"{AnsiConsole.Console.Profile.Height}")
|
||||||
|
.AddRow("[b]Encoding[/]", $"{AnsiConsole.Console.Profile.Encoding.EncodingName}");
|
||||||
|
|
||||||
|
AnsiConsole.Write(
|
||||||
|
new Panel(grid)
|
||||||
|
.Header("Information"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string YesNo(bool value)
|
||||||
|
{
|
||||||
|
return value ? "Yes" : "No";
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Json/Json.csproj
Normal file
15
examples/Console/Json/Json.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Json</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to print syntax highlighted JSON.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
36
examples/Console/Json/Program.cs
Normal file
36
examples/Console/Json/Program.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Json;
|
||||||
|
|
||||||
|
namespace Json;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
var json = new JsonText(
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"hello": 32,
|
||||||
|
"world": {
|
||||||
|
"foo": 21,
|
||||||
|
"bar": 255,
|
||||||
|
"baz": [
|
||||||
|
0.32, 0.33e-32,
|
||||||
|
0.42e32, 0.55e+32,
|
||||||
|
{
|
||||||
|
"hello": "world",
|
||||||
|
"lol": null
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""");
|
||||||
|
|
||||||
|
AnsiConsole.Write(
|
||||||
|
new Panel(json)
|
||||||
|
.Header("Some JSON in a panel")
|
||||||
|
.Collapse()
|
||||||
|
.RoundedBorder()
|
||||||
|
.BorderColor(Color.Yellow));
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Layout/Layout.csproj
Normal file
15
examples/Console/Layout/Layout.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Layout</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to use layouts.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
60
examples/Console/Layout/Program.cs
Normal file
60
examples/Console/Layout/Program.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Layouts;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
var layout = CreateLayout();
|
||||||
|
AnsiConsole.Write(layout);
|
||||||
|
|
||||||
|
Console.ReadKey(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Layout CreateLayout()
|
||||||
|
{
|
||||||
|
var layout = new Layout();
|
||||||
|
|
||||||
|
layout.SplitRows(
|
||||||
|
new Layout("Top")
|
||||||
|
.SplitColumns(
|
||||||
|
new Layout("Left")
|
||||||
|
.SplitRows(
|
||||||
|
new Layout("LeftTop"),
|
||||||
|
new Layout("LeftBottom")),
|
||||||
|
new Layout("Right").Ratio(2),
|
||||||
|
new Layout("RightRight").Size(3)),
|
||||||
|
new Layout("Bottom"));
|
||||||
|
|
||||||
|
layout["LeftBottom"].Update(
|
||||||
|
new Panel("[blink]PRESS ANY KEY TO QUIT[/]")
|
||||||
|
.Expand()
|
||||||
|
.BorderColor(Color.Yellow)
|
||||||
|
.Padding(0, 0));
|
||||||
|
|
||||||
|
layout["Right"].Update(
|
||||||
|
new Panel(
|
||||||
|
new Table()
|
||||||
|
.AddColumns("[blue]Qux[/]", "[green]Corgi[/]")
|
||||||
|
.AddRow("9", "8")
|
||||||
|
.AddRow("7", "6")
|
||||||
|
.Expand())
|
||||||
|
.Header("A [yellow]Table[/] in a [blue]Panel[/] (Ratio=2)")
|
||||||
|
.Expand());
|
||||||
|
|
||||||
|
layout["RightRight"].Update(
|
||||||
|
new Panel("Explicit-size-is-[yellow]3[/]")
|
||||||
|
.BorderColor(Color.Yellow)
|
||||||
|
.Padding(0, 0));
|
||||||
|
|
||||||
|
layout["Bottom"].Update(
|
||||||
|
new Panel(
|
||||||
|
new FigletText("Hello World"))
|
||||||
|
.Header("Some [green]Figlet[/] text")
|
||||||
|
.Expand());
|
||||||
|
|
||||||
|
return layout;
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Links/Links.csproj
Normal file
15
examples/Console/Links/Links.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Links</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render links in a console.</ExampleDescription>
|
||||||
|
<ExampleGroup>Misc</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
20
examples/Console/Links/Program.cs
Normal file
20
examples/Console/Links/Program.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Links;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
if (AnsiConsole.Profile.Capabilities.Links)
|
||||||
|
{
|
||||||
|
AnsiConsole.MarkupLine("[link=https://patriksvensson.se]Click to visit my blog[/]!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
AnsiConsole.MarkupLine("[red]It looks like your terminal doesn't support links[/]");
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.MarkupLine("[yellow](╯°□°)╯[/]︵ [blue]┻━┻[/]");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Live/Live.csproj
Normal file
15
examples/Console/Live/Live.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Live</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to do live updates.</ExampleDescription>
|
||||||
|
<ExampleGroup>Live</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
81
examples/Console/Live/Program.cs
Normal file
81
examples/Console/Live/Program.cs
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Live;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
var table = new Table().Centered();
|
||||||
|
|
||||||
|
// Animate
|
||||||
|
AnsiConsole.Live(table)
|
||||||
|
.AutoClear(false)
|
||||||
|
.Overflow(VerticalOverflow.Ellipsis)
|
||||||
|
.Cropping(VerticalOverflowCropping.Top)
|
||||||
|
.Start(ctx =>
|
||||||
|
{
|
||||||
|
void Update(int delay, Action action)
|
||||||
|
{
|
||||||
|
action();
|
||||||
|
ctx.Refresh();
|
||||||
|
Thread.Sleep(delay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Columns
|
||||||
|
Update(230, () => table.AddColumn("Release date"));
|
||||||
|
Update(230, () => table.AddColumn("Title"));
|
||||||
|
Update(230, () => table.AddColumn("Budget"));
|
||||||
|
Update(230, () => table.AddColumn("Opening Weekend"));
|
||||||
|
Update(230, () => table.AddColumn("Box office"));
|
||||||
|
|
||||||
|
// Rows
|
||||||
|
Update(70, () => table.AddRow("May 25, 1977", "[yellow]Star Wars[/] [grey]Ep.[/] [u]IV[/]", "$11,000,000", "$1,554,475", "$775,398,007"));
|
||||||
|
Update(70, () => table.AddRow("May 21, 1980", "[yellow]Star Wars[/] [grey]Ep.[/] [u]V[/]", "$18,000,000", "$4,910,483", "$547,969,004"));
|
||||||
|
Update(70, () => table.AddRow("May 25, 1983", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VI[/]", "$32,500,000", "$23,019,618", "$475,106,177"));
|
||||||
|
Update(70, () => table.AddRow("May 19, 1999", "[yellow]Star Wars[/] [grey]Ep.[/] [u]I[/]", "$115,000,000", "$64,810,870", "$1,027,044,677"));
|
||||||
|
Update(70, () => table.AddRow("May 16, 2002", "[yellow]Star Wars[/] [grey]Ep.[/] [u]II[/]", "$115,000,000", "$80,027,814", "$649,436,358"));
|
||||||
|
Update(70, () => table.AddRow("May 19, 2005", "[yellow]Star Wars[/] [grey]Ep.[/] [u]III[/]", "$113,000,000", "$108,435,841", "$850,035,635"));
|
||||||
|
Update(70, () => table.AddRow("Dec 18, 2015", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VII[/]", "$245,000,000", "$247,966,675", "$2,068,223,624"));
|
||||||
|
Update(70, () => table.AddRow("Dec 15, 2017", "[yellow]Star Wars[/] [grey]Ep.[/] [u]VIII[/]", "$317,000,000", "$220,009,584", "$1,333,539,889"));
|
||||||
|
Update(70, () => table.AddRow("Dec 20, 2019", "[yellow]Star Wars[/] [grey]Ep.[/] [u]IX[/]", "$245,000,000", "$177,383,864", "$1,074,114,248"));
|
||||||
|
|
||||||
|
// Column footer
|
||||||
|
Update(230, () => table.Columns[2].Footer("$1,633,000,000"));
|
||||||
|
Update(230, () => table.Columns[3].Footer("$928,119,224"));
|
||||||
|
Update(400, () => table.Columns[4].Footer("$10,318,030,576"));
|
||||||
|
|
||||||
|
// Column alignment
|
||||||
|
Update(230, () => table.Columns[2].RightAligned());
|
||||||
|
Update(230, () => table.Columns[3].RightAligned());
|
||||||
|
Update(400, () => table.Columns[4].RightAligned());
|
||||||
|
|
||||||
|
// Column titles
|
||||||
|
Update(70, () => table.Columns[0].Header("[bold]Release date[/]"));
|
||||||
|
Update(70, () => table.Columns[1].Header("[bold]Title[/]"));
|
||||||
|
Update(70, () => table.Columns[2].Header("[red bold]Budget[/]"));
|
||||||
|
Update(70, () => table.Columns[3].Header("[green bold]Opening Weekend[/]"));
|
||||||
|
Update(400, () => table.Columns[4].Header("[blue bold]Box office[/]"));
|
||||||
|
|
||||||
|
// Footers
|
||||||
|
Update(70, () => table.Columns[2].Footer("[red bold]$1,633,000,000[/]"));
|
||||||
|
Update(70, () => table.Columns[3].Footer("[green bold]$928,119,224[/]"));
|
||||||
|
Update(400, () => table.Columns[4].Footer("[blue bold]$10,318,030,576[/]"));
|
||||||
|
|
||||||
|
// Title
|
||||||
|
Update(500, () => table.Title("Star Wars Movies"));
|
||||||
|
Update(400, () => table.Title("[[ [yellow]Star Wars Movies[/] ]]"));
|
||||||
|
|
||||||
|
// Borders
|
||||||
|
Update(230, () => table.BorderColor(Color.Yellow));
|
||||||
|
Update(230, () => table.MinimalBorder());
|
||||||
|
Update(230, () => table.SimpleBorder());
|
||||||
|
Update(230, () => table.SimpleHeavyBorder());
|
||||||
|
|
||||||
|
// Caption
|
||||||
|
Update(400, () => table.Caption("[[ [blue]THE END[/] ]]"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/LiveTable/LiveTable.csproj
Normal file
15
examples/Console/LiveTable/LiveTable.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>LiveTable</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to do live updates in a table.</ExampleDescription>
|
||||||
|
<ExampleGroup>Live</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
86
examples/Console/LiveTable/Program.cs
Normal file
86
examples/Console/LiveTable/Program.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace LiveTable;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
private const int NumberOfRows = 10;
|
||||||
|
|
||||||
|
private static readonly Random _random = new();
|
||||||
|
private static readonly string[] _exchanges = new string[]
|
||||||
|
{
|
||||||
|
"SGD", "SEK", "PLN",
|
||||||
|
"MYR", "EUR", "USD",
|
||||||
|
"AUD", "JPY", "CNH",
|
||||||
|
"HKD", "CAD", "INR",
|
||||||
|
"DKK", "GBP", "RUB",
|
||||||
|
"NZD", "MXN", "IDR",
|
||||||
|
"TWD", "THB", "VND",
|
||||||
|
};
|
||||||
|
|
||||||
|
public static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
var table = new Table().Expand().BorderColor(Color.Grey);
|
||||||
|
table.AddColumn("[yellow]Source currency[/]");
|
||||||
|
table.AddColumn("[yellow]Destination currency[/]");
|
||||||
|
table.AddColumn("[yellow]Exchange rate[/]");
|
||||||
|
|
||||||
|
AnsiConsole.MarkupLine("Press [yellow]CTRL+C[/] to exit");
|
||||||
|
|
||||||
|
await AnsiConsole.Live(table)
|
||||||
|
.AutoClear(false)
|
||||||
|
.Overflow(VerticalOverflow.Ellipsis)
|
||||||
|
.Cropping(VerticalOverflowCropping.Bottom)
|
||||||
|
.StartAsync(async ctx =>
|
||||||
|
{
|
||||||
|
// Add some initial rows
|
||||||
|
foreach (var _ in Enumerable.Range(0, NumberOfRows))
|
||||||
|
{
|
||||||
|
AddExchangeRateRow(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continously update the table
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
// More rows than we want?
|
||||||
|
if (table.Rows.Count > NumberOfRows)
|
||||||
|
{
|
||||||
|
// Remove the first one
|
||||||
|
table.Rows.RemoveAt(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add a new row
|
||||||
|
AddExchangeRateRow(table);
|
||||||
|
|
||||||
|
// Refresh and wait for a while
|
||||||
|
ctx.Refresh();
|
||||||
|
await Task.Delay(400);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AddExchangeRateRow(Table table)
|
||||||
|
{
|
||||||
|
var (source, destination, rate) = GetExchangeRate();
|
||||||
|
table.AddRow(
|
||||||
|
source, destination,
|
||||||
|
_random.NextDouble() > 0.35D ? $"[green]{rate}[/]" : $"[red]{rate}[/]");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static (string Source, string Destination, double Rate) GetExchangeRate()
|
||||||
|
{
|
||||||
|
var source = _exchanges[_random.Next(0, _exchanges.Length)];
|
||||||
|
var dest = _exchanges[_random.Next(0, _exchanges.Length)];
|
||||||
|
var rate = 200 / ((_random.NextDouble() * 320) + 1);
|
||||||
|
|
||||||
|
while (source == dest)
|
||||||
|
{
|
||||||
|
dest = _exchanges[_random.Next(0, _exchanges.Length)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return (source, dest, rate);
|
||||||
|
}
|
||||||
|
}
|
||||||
2
examples/Console/Minimal/GlobalUsings.cs
Normal file
2
examples/Console/Minimal/GlobalUsings.cs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
global using Spectre.Console;
|
||||||
|
global using static Spectre.Console.AnsiConsole;
|
||||||
16
examples/Console/Minimal/Minimal.csproj
Normal file
16
examples/Console/Minimal/Minimal.csproj
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<ExampleTitle>Minimal</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates a minimal console application.</ExampleDescription>
|
||||||
|
<ExampleGroup>Live</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
12
examples/Console/Minimal/Program.cs
Normal file
12
examples/Console/Minimal/Program.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
// Write a markup line to the console
|
||||||
|
MarkupLine("[yellow]Hello[/], [blue]World[/]!");
|
||||||
|
|
||||||
|
// Write text to the console
|
||||||
|
WriteLine("Hello, World!");
|
||||||
|
|
||||||
|
// Write a table to the console
|
||||||
|
Write(new Table()
|
||||||
|
.RoundedBorder()
|
||||||
|
.AddColumns("[red]Greeting[/]", "[red]Subject[/]")
|
||||||
|
.AddRow("[yellow]Hello[/]", "World")
|
||||||
|
.AddRow("[green]Oh hi[/]", "[blue u]Mark[/]"));
|
||||||
15
examples/Console/Panels/Panels.csproj
Normal file
15
examples/Console/Panels/Panels.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Panels</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render items in panels.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
41
examples/Console/Panels/Program.cs
Normal file
41
examples/Console/Panels/Program.cs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Panels;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
var content = new Markup(
|
||||||
|
"[underline]I[/] heard [underline on blue]you[/] like panels\n\n\n\n" +
|
||||||
|
"So I put a panel in a panel").Centered();
|
||||||
|
|
||||||
|
AnsiConsole.Write(
|
||||||
|
new Panel(
|
||||||
|
new Panel(content)
|
||||||
|
.Border(BoxBorder.Rounded)));
|
||||||
|
|
||||||
|
// Left adjusted panel with text
|
||||||
|
AnsiConsole.Write(
|
||||||
|
new Panel(new Text("Left adjusted\nLeft").LeftJustified())
|
||||||
|
.Expand()
|
||||||
|
.SquareBorder()
|
||||||
|
.Header("[red]Left[/]"));
|
||||||
|
|
||||||
|
// Centered ASCII panel with text
|
||||||
|
AnsiConsole.Write(
|
||||||
|
new Panel(new Text("Centered\nCenter").Centered())
|
||||||
|
.Expand()
|
||||||
|
.AsciiBorder()
|
||||||
|
.Header("[green]Center[/]")
|
||||||
|
.HeaderAlignment(Justify.Center));
|
||||||
|
|
||||||
|
// Right adjusted, rounded panel with text
|
||||||
|
AnsiConsole.Write(
|
||||||
|
new Panel(new Text("Right adjusted\nRight").RightJustified())
|
||||||
|
.Expand()
|
||||||
|
.RoundedBorder()
|
||||||
|
.Header("[blue]Right[/]")
|
||||||
|
.HeaderAlignment(Justify.Right));
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Paths/Paths.csproj
Normal file
15
examples/Console/Paths/Paths.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Paths</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render paths.</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
67
examples/Console/Paths/Program.cs
Normal file
67
examples/Console/Paths/Program.cs
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Paths;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
var windowsPath = @"C:\This is\A\Super Long\Windows\Path\That\Goes\On And On\And\Never\Seems\To\Stop\But\At\Some\Point\It\Must\I\Guess.txt";
|
||||||
|
var unixPath = @"//This is/A/Super Long/Unix/Path/That/Goes/On And On/And/Never/Seems/To/Stop/But/At/Some/Point/It/Must/I/Guess.txt";
|
||||||
|
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
WritePlain(windowsPath, unixPath);
|
||||||
|
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
WriteColorized(windowsPath, unixPath);
|
||||||
|
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
WriteAligned(windowsPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WritePlain(string windowsPath, string unixPath)
|
||||||
|
{
|
||||||
|
var table = new Table().BorderColor(Color.Grey).Title("Plain").RoundedBorder();
|
||||||
|
table.AddColumns("[grey]OS[/]", "[grey]Path[/]");
|
||||||
|
table.AddRow(new Text("Windows"), new TextPath(windowsPath));
|
||||||
|
table.AddRow(new Text("Unix"), new TextPath(unixPath));
|
||||||
|
|
||||||
|
AnsiConsole.Write(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteColorized(string windowsPath, string unixPath)
|
||||||
|
{
|
||||||
|
var table = new Table().BorderColor(Color.Grey).Title("Colorized").RoundedBorder();
|
||||||
|
table.AddColumns("[grey]OS[/]", "[grey]Path[/]");
|
||||||
|
|
||||||
|
table.AddRow(new Text("Windows"),
|
||||||
|
new TextPath(windowsPath)
|
||||||
|
.RootColor(Color.Blue)
|
||||||
|
.SeparatorColor(Color.Yellow)
|
||||||
|
.StemColor(Color.Red)
|
||||||
|
.LeafColor(Color.Green));
|
||||||
|
|
||||||
|
table.AddRow(new Text("Unix"),
|
||||||
|
new TextPath(unixPath)
|
||||||
|
.RootColor(Color.Blue)
|
||||||
|
.SeparatorColor(Color.Yellow)
|
||||||
|
.StemColor(Color.Red)
|
||||||
|
.LeafColor(Color.Green));
|
||||||
|
|
||||||
|
AnsiConsole.Write(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteAligned(string path)
|
||||||
|
{
|
||||||
|
var table = new Table().BorderColor(Color.Grey).Title("Aligned").RoundedBorder();
|
||||||
|
table.AddColumns("[grey]Alignment[/]", "[grey]Path[/]");
|
||||||
|
|
||||||
|
table.AddRow(new Text("Left"), new TextPath(path).LeftJustified());
|
||||||
|
table.AddRow(new Text("Center"), new TextPath(path).Centered());
|
||||||
|
table.AddRow(new Text("Right"), new TextPath(path).RightJustified());
|
||||||
|
|
||||||
|
AnsiConsole.Write(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
44
examples/Console/Progress/DescriptionGenerator.cs
Normal file
44
examples/Console/Progress/DescriptionGenerator.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Progress;
|
||||||
|
|
||||||
|
public static class DescriptionGenerator
|
||||||
|
{
|
||||||
|
private static readonly string[] _verbs = new[] { "Downloading", "Rerouting", "Retriculating", "Collapsing", "Folding", "Solving", "Colliding", "Measuring" };
|
||||||
|
private static readonly string[] _nouns = new[] { "internet", "splines", "space", "capacitators", "quarks", "algorithms", "data structures", "spacetime" };
|
||||||
|
|
||||||
|
private static readonly Random _random;
|
||||||
|
private static readonly HashSet<string> _used;
|
||||||
|
|
||||||
|
static DescriptionGenerator()
|
||||||
|
{
|
||||||
|
_random = new Random(DateTime.Now.Millisecond);
|
||||||
|
_used = new HashSet<string>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool TryGenerate(out string name)
|
||||||
|
{
|
||||||
|
var iterations = 0;
|
||||||
|
while (iterations < 25)
|
||||||
|
{
|
||||||
|
name = Generate();
|
||||||
|
if (!_used.Contains(name))
|
||||||
|
{
|
||||||
|
_used.Add(name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
iterations++;
|
||||||
|
}
|
||||||
|
|
||||||
|
name = Generate();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string Generate()
|
||||||
|
{
|
||||||
|
return _verbs[_random.Next(0, _verbs.Length)]
|
||||||
|
+ " " + _nouns[_random.Next(0, _nouns.Length)];
|
||||||
|
}
|
||||||
|
}
|
||||||
121
examples/Console/Progress/Program.cs
Normal file
121
examples/Console/Progress/Program.cs
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace Progress;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
AnsiConsole.MarkupLine("[yellow]Initializing warp drive[/]...");
|
||||||
|
|
||||||
|
// Show progress
|
||||||
|
AnsiConsole.Progress()
|
||||||
|
.AutoClear(false)
|
||||||
|
.Columns(new ProgressColumn[]
|
||||||
|
{
|
||||||
|
new TaskDescriptionColumn(), // Task description
|
||||||
|
new ProgressBarColumn(), // Progress bar
|
||||||
|
new PercentageColumn(), // Percentage
|
||||||
|
new RemainingTimeColumn(), // Remaining time
|
||||||
|
new SpinnerColumn(), // Spinner
|
||||||
|
})
|
||||||
|
.UseRenderHook((renderable, tasks) => RenderHook(tasks, renderable))
|
||||||
|
.Start(ctx =>
|
||||||
|
{
|
||||||
|
var random = new Random(DateTime.Now.Millisecond);
|
||||||
|
|
||||||
|
// Create some tasks
|
||||||
|
var tasks = CreateTasks(ctx, random);
|
||||||
|
var warpTask = ctx.AddTask("Going to warp", autoStart: false).IsIndeterminate();
|
||||||
|
|
||||||
|
// Wait for all tasks (except the indeterminate one) to complete
|
||||||
|
while (!ctx.IsFinished)
|
||||||
|
{
|
||||||
|
// Increment progress
|
||||||
|
foreach (var (task, increment) in tasks)
|
||||||
|
{
|
||||||
|
task.Increment(random.NextDouble() * increment);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write some random things to the terminal
|
||||||
|
if (random.NextDouble() < 0.1)
|
||||||
|
{
|
||||||
|
WriteLogMessage();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulate some delay
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now start the "warp" task
|
||||||
|
warpTask.StartTask();
|
||||||
|
warpTask.IsIndeterminate(false);
|
||||||
|
while (!ctx.IsFinished)
|
||||||
|
{
|
||||||
|
warpTask.Increment(12 * random.NextDouble());
|
||||||
|
|
||||||
|
// Simulate some delay
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Done
|
||||||
|
AnsiConsole.MarkupLine("[green]Done![/]");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IRenderable RenderHook(IReadOnlyList<ProgressTask> tasks, IRenderable renderable)
|
||||||
|
{
|
||||||
|
var header = new Panel("Going on a :rocket:, we're going to the :crescent_moon:").Expand().RoundedBorder();
|
||||||
|
var footer = new Rows(
|
||||||
|
new Rule(),
|
||||||
|
new Markup(
|
||||||
|
$"[blue]{tasks.Count}[/] total tasks. [green]{tasks.Count(i => i.IsFinished)}[/] complete.")
|
||||||
|
);
|
||||||
|
|
||||||
|
const string ESC = "\u001b";
|
||||||
|
string escapeSequence;
|
||||||
|
if (tasks.All(i => i.IsFinished))
|
||||||
|
{
|
||||||
|
escapeSequence = $"{ESC}]]9;4;0;100{ESC}\\";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var total = tasks.Sum(i => i.MaxValue);
|
||||||
|
var done = tasks.Sum(i => i.Value);
|
||||||
|
var percent = (int)(done / total * 100);
|
||||||
|
escapeSequence = $"{ESC}]]9;4;1;{percent}{ESC}\\";
|
||||||
|
}
|
||||||
|
|
||||||
|
var middleContent = new Grid().AddColumns(new GridColumn(), new GridColumn().Width(20));
|
||||||
|
middleContent.AddRow(renderable, new FigletText(tasks.Count(i => i.IsFinished == false).ToString()));
|
||||||
|
|
||||||
|
return new Rows(header, middleContent, footer, new ControlCode(escapeSequence));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<(ProgressTask Task, int Delay)> CreateTasks(ProgressContext progress, Random random)
|
||||||
|
{
|
||||||
|
var tasks = new List<(ProgressTask, int)>();
|
||||||
|
while (tasks.Count < 5)
|
||||||
|
{
|
||||||
|
if (DescriptionGenerator.TryGenerate(out var name))
|
||||||
|
{
|
||||||
|
tasks.Add((progress.AddTask(name), random.Next(2, 10)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteLogMessage()
|
||||||
|
{
|
||||||
|
AnsiConsole.MarkupLine(
|
||||||
|
"[grey]LOG:[/] " +
|
||||||
|
DescriptionGenerator.Generate() +
|
||||||
|
"[grey]...[/]");
|
||||||
|
}
|
||||||
|
}
|
||||||
19
examples/Console/Progress/Progress.csproj
Normal file
19
examples/Console/Progress/Progress.csproj
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Progress</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to show progress bars.</ExampleDescription>
|
||||||
|
<ExampleGroup>Status</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
182
examples/Console/Prompt/Program.cs
Normal file
182
examples/Console/Prompt/Program.cs
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Prompt
|
||||||
|
{
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// Check if we can accept key strokes
|
||||||
|
if (!AnsiConsole.Profile.Capabilities.Interactive)
|
||||||
|
{
|
||||||
|
AnsiConsole.MarkupLine("[red]Environment does not support interaction.[/]");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirmation
|
||||||
|
if (!AskConfirmation())
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ask the user for some different things
|
||||||
|
WriteDivider("Strings");
|
||||||
|
var name = AskName();
|
||||||
|
|
||||||
|
WriteDivider("Lists");
|
||||||
|
var fruit = AskFruit();
|
||||||
|
|
||||||
|
WriteDivider("Choices");
|
||||||
|
var sport = AskSport();
|
||||||
|
|
||||||
|
WriteDivider("Integers");
|
||||||
|
var age = AskAge();
|
||||||
|
|
||||||
|
WriteDivider("Secrets");
|
||||||
|
var password = AskPassword();
|
||||||
|
|
||||||
|
WriteDivider("Mask");
|
||||||
|
var mask = AskPasswordWithCustomMask();
|
||||||
|
|
||||||
|
WriteDivider("Null Mask");
|
||||||
|
var nullMask = AskPasswordWithNullMask();
|
||||||
|
|
||||||
|
WriteDivider("Optional");
|
||||||
|
var color = AskColor();
|
||||||
|
|
||||||
|
// Summary
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule("[yellow]Results[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
AnsiConsole.Write(new Table().AddColumns("[grey]Question[/]", "[grey]Answer[/]")
|
||||||
|
.RoundedBorder()
|
||||||
|
.BorderColor(Color.Grey)
|
||||||
|
.AddRow("[grey]Name[/]", name)
|
||||||
|
.AddRow("[grey]Favorite fruit[/]", fruit)
|
||||||
|
.AddRow("[grey]Favorite sport[/]", sport)
|
||||||
|
.AddRow("[grey]Age[/]", age.ToString())
|
||||||
|
.AddRow("[grey]Password[/]", password)
|
||||||
|
.AddRow("[grey]Mask[/]", mask)
|
||||||
|
.AddRow("[grey]Null Mask[/]", nullMask)
|
||||||
|
.AddRow("[grey]Favorite color[/]", string.IsNullOrEmpty(color) ? "Unknown" : color));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteDivider(string text)
|
||||||
|
{
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(new Rule($"[yellow]{text}[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool AskConfirmation()
|
||||||
|
{
|
||||||
|
if (!AnsiConsole.Confirm("Run prompt example?"))
|
||||||
|
{
|
||||||
|
AnsiConsole.MarkupLine("Ok... :(");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AskName()
|
||||||
|
{
|
||||||
|
var name = AnsiConsole.Ask<string>("What's your [green]name[/]?");
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AskFruit()
|
||||||
|
{
|
||||||
|
var favorites = AnsiConsole.Prompt(
|
||||||
|
new MultiSelectionPrompt<string>()
|
||||||
|
.PageSize(10)
|
||||||
|
.Title("What are your [green]favorite fruits[/]?")
|
||||||
|
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
|
||||||
|
.InstructionsText("[grey](Press [blue]<space>[/] to toggle a fruit, [green]<enter>[/] to accept)[/]")
|
||||||
|
.AddChoiceGroup("Berries", new[]
|
||||||
|
{
|
||||||
|
"Blackcurrant", "Blueberry", "Cloudberry",
|
||||||
|
"Elderberry", "Honeyberry", "Mulberry"
|
||||||
|
})
|
||||||
|
.AddChoices(new[]
|
||||||
|
{
|
||||||
|
"Apple", "Apricot", "Avocado", "Banana",
|
||||||
|
"Cherry", "Cocunut", "Date", "Dragonfruit", "Durian",
|
||||||
|
"Egg plant", "Fig", "Grape", "Guava",
|
||||||
|
"Jackfruit", "Jambul", "Kiwano", "Kiwifruit", "Lime", "Lylo",
|
||||||
|
"Lychee", "Melon", "Nectarine", "Orange", "Olive"
|
||||||
|
}));
|
||||||
|
|
||||||
|
var fruit = favorites.Count == 1 ? favorites[0] : null;
|
||||||
|
if (string.IsNullOrWhiteSpace(fruit))
|
||||||
|
{
|
||||||
|
fruit = AnsiConsole.Prompt(
|
||||||
|
new SelectionPrompt<string>()
|
||||||
|
.EnableSearch()
|
||||||
|
.Title("Ok, but if you could only choose [green]one[/]?")
|
||||||
|
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
|
||||||
|
.AddChoices(favorites));
|
||||||
|
}
|
||||||
|
|
||||||
|
AnsiConsole.MarkupLine("You selected: [yellow]{0}[/]", fruit);
|
||||||
|
return fruit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AskSport()
|
||||||
|
{
|
||||||
|
return AnsiConsole.Prompt(
|
||||||
|
new TextPrompt<string>("What's your [green]favorite sport[/]?")
|
||||||
|
.InvalidChoiceMessage("[red]That's not a sport![/]")
|
||||||
|
.DefaultValue("Sport?")
|
||||||
|
.AddChoice("Soccer")
|
||||||
|
.AddChoice("Hockey")
|
||||||
|
.AddChoice("Basketball"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int AskAge()
|
||||||
|
{
|
||||||
|
return AnsiConsole.Prompt(
|
||||||
|
new TextPrompt<int>("How [green]old[/] are you?")
|
||||||
|
.PromptStyle("green")
|
||||||
|
.ValidationErrorMessage("[red]That's not a valid age[/]")
|
||||||
|
.Validate(age =>
|
||||||
|
{
|
||||||
|
return age switch
|
||||||
|
{
|
||||||
|
<= 0 => ValidationResult.Error("[red]You must at least be 1 years old[/]"),
|
||||||
|
>= 123 => ValidationResult.Error("[red]You must be younger than the oldest person alive[/]"),
|
||||||
|
_ => ValidationResult.Success(),
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AskPassword()
|
||||||
|
{
|
||||||
|
return AnsiConsole.Prompt(
|
||||||
|
new TextPrompt<string>("Enter [green]password[/]?")
|
||||||
|
.PromptStyle("red")
|
||||||
|
.Secret());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AskPasswordWithCustomMask()
|
||||||
|
{
|
||||||
|
return AnsiConsole.Prompt(
|
||||||
|
new TextPrompt<string>("Enter [green]password[/]?")
|
||||||
|
.PromptStyle("red")
|
||||||
|
.Secret('-'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AskPasswordWithNullMask()
|
||||||
|
{
|
||||||
|
return AnsiConsole.Prompt(
|
||||||
|
new TextPrompt<string>("Enter [green]password[/]?")
|
||||||
|
.PromptStyle("red")
|
||||||
|
.Secret(null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string AskColor()
|
||||||
|
{
|
||||||
|
return AnsiConsole.Prompt(
|
||||||
|
new TextPrompt<string>("[grey][[Optional]][/] What is your [green]favorite color[/]?")
|
||||||
|
.AllowEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
16
examples/Console/Prompt/Prompt.csproj
Normal file
16
examples/Console/Prompt/Prompt.csproj
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<LangVersion>9</LangVersion>
|
||||||
|
<ExampleTitle>Prompt</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to get input from a user.</ExampleDescription>
|
||||||
|
<ExampleGroup>Misc</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
42
examples/Console/Rules/Program.cs
Normal file
42
examples/Console/Rules/Program.cs
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Rules;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main(string[] args)
|
||||||
|
{
|
||||||
|
// No title
|
||||||
|
Render(
|
||||||
|
new Rule()
|
||||||
|
.RuleStyle(Style.Parse("yellow"))
|
||||||
|
.AsciiBorder()
|
||||||
|
.LeftJustified());
|
||||||
|
|
||||||
|
// Left aligned title
|
||||||
|
Render(
|
||||||
|
new Rule("[blue]Left aligned[/]")
|
||||||
|
.RuleStyle(Style.Parse("red"))
|
||||||
|
.DoubleBorder()
|
||||||
|
.LeftJustified());
|
||||||
|
|
||||||
|
// Centered title
|
||||||
|
Render(
|
||||||
|
new Rule("[green]Centered[/]")
|
||||||
|
.RuleStyle(Style.Parse("green"))
|
||||||
|
.HeavyBorder()
|
||||||
|
.Centered());
|
||||||
|
|
||||||
|
// Right aligned title
|
||||||
|
Render(
|
||||||
|
new Rule("[red]Right aligned[/]")
|
||||||
|
.RuleStyle(Style.Parse("blue"))
|
||||||
|
.RightJustified());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Render(Rule rule)
|
||||||
|
{
|
||||||
|
AnsiConsole.Write(rule);
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Rules/Rules.csproj
Normal file
15
examples/Console/Rules/Rules.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Rules</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to render horizontal rules (lines).</ExampleDescription>
|
||||||
|
<ExampleGroup>Widgets</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
29
examples/Console/Showcase/ExceptionGenerator.cs
Normal file
29
examples/Console/Showcase/ExceptionGenerator.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Showcase;
|
||||||
|
|
||||||
|
public static class ExceptionGenerator
|
||||||
|
{
|
||||||
|
public static Exception GenerateException()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
SomeOperation();
|
||||||
|
throw new InvalidOperationException();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SomeOperation()
|
||||||
|
{
|
||||||
|
SomeOperationGoingWrong();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SomeOperationGoingWrong()
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Something went very wrong!");
|
||||||
|
}
|
||||||
|
}
|
||||||
154
examples/Console/Showcase/Program.cs
Normal file
154
examples/Console/Showcase/Program.cs
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Examples;
|
||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace Showcase;
|
||||||
|
|
||||||
|
public static partial class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
var table = new Table().HideHeaders().NoBorder();
|
||||||
|
table.Title("[u][yellow]Spectre.Console[/] [b]Features[/][/]");
|
||||||
|
table.AddColumn("Feature", c => c.NoWrap().RightAligned().Width(10).PadRight(3));
|
||||||
|
table.AddColumn("Demonstration", c => c.PadRight(0));
|
||||||
|
table.AddEmptyRow();
|
||||||
|
|
||||||
|
// Colors
|
||||||
|
table.AddRow(
|
||||||
|
new Markup("[red]Colors[/]"),
|
||||||
|
GetColorTable());
|
||||||
|
|
||||||
|
// Styles
|
||||||
|
table.AddEmptyRow();
|
||||||
|
table.AddRow(
|
||||||
|
new Markup("[red]OS[/]"),
|
||||||
|
new Grid().Expand().AddColumns(3)
|
||||||
|
.AddRow(
|
||||||
|
"[bold green]Windows[/]",
|
||||||
|
"[bold blue]macOS[/]",
|
||||||
|
"[bold yellow]Linux[/]"));
|
||||||
|
|
||||||
|
// Styles
|
||||||
|
table.AddEmptyRow();
|
||||||
|
table.AddRow(
|
||||||
|
"[red]Styles[/]",
|
||||||
|
"All ansi styles: [bold]bold[/], [dim]dim[/], [italic]italic[/], [underline]underline[/], "
|
||||||
|
+ "[strikethrough]strikethrough[/], [reverse]reverse[/], and even [blink]blink[/].");
|
||||||
|
|
||||||
|
// Text
|
||||||
|
table.AddEmptyRow();
|
||||||
|
table.AddRow(
|
||||||
|
new Markup("[red]Text[/]"),
|
||||||
|
new Markup("Word wrap text. Justify [green]left[/], [yellow]center[/] or [blue]right[/]."));
|
||||||
|
|
||||||
|
table.AddEmptyRow();
|
||||||
|
table.AddRow(
|
||||||
|
Text.Empty,
|
||||||
|
GetTextGrid());
|
||||||
|
|
||||||
|
// Markup
|
||||||
|
table.AddEmptyRow();
|
||||||
|
table.AddRow(
|
||||||
|
"[red]Markup[/]",
|
||||||
|
"[bold purple]Spectre.Console[/] supports a simple [i]bbcode[/] like "
|
||||||
|
+ "[b]markup[/] for [yellow]color[/], [underline]style[/], and emoji! "
|
||||||
|
+ ":thumbs_up: :red_apple: :ant: :bear: :baguette_bread: :bus:");
|
||||||
|
|
||||||
|
// Trees and tables
|
||||||
|
table.AddEmptyRow();
|
||||||
|
table.AddRow(
|
||||||
|
new Markup("[red]Tables and Trees[/]"),
|
||||||
|
GetTreeTable());
|
||||||
|
|
||||||
|
// Charts
|
||||||
|
table.AddRow(
|
||||||
|
new Markup("[red]Charts[/]"),
|
||||||
|
new Grid().Collapse().AddColumns(2).AddRow(
|
||||||
|
new Panel(GetBreakdownChart()).BorderColor(Color.Grey),
|
||||||
|
new Panel(GetBarChart()).BorderColor(Color.Grey)));
|
||||||
|
|
||||||
|
|
||||||
|
// Exceptions
|
||||||
|
table.AddEmptyRow();
|
||||||
|
table.AddRow(
|
||||||
|
new Markup("[red]Exceptions[/]"),
|
||||||
|
ExceptionGenerator.GenerateException().GetRenderable());
|
||||||
|
|
||||||
|
// Much more
|
||||||
|
table.AddEmptyRow();
|
||||||
|
table.AddRow(
|
||||||
|
"[red]+ Much more![/]",
|
||||||
|
"Tables, Grids, Trees, Progress bars, Status, Bar charts, Calendars, Figlet, Images, Text prompts, "
|
||||||
|
+ "List boxes, Separators, Pretty exceptions, Canvas, CLI parsing");
|
||||||
|
table.AddEmptyRow();
|
||||||
|
|
||||||
|
// Render the table
|
||||||
|
AnsiConsole.WriteLine();
|
||||||
|
AnsiConsole.Write(table);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IRenderable GetColorTable()
|
||||||
|
{
|
||||||
|
var colorTable = new Table().Collapse().HideHeaders().NoBorder();
|
||||||
|
colorTable.AddColumn("Desc", c => c.PadRight(3)).AddColumn("Colors", c => c.PadRight(0));
|
||||||
|
colorTable.AddRow(
|
||||||
|
new Markup(
|
||||||
|
"✓ [bold grey]NO_COLOR support[/]\n" +
|
||||||
|
"✓ [bold green]3-bit color[/]\n" +
|
||||||
|
"✓ [bold blue]4-bit color[/]\n" +
|
||||||
|
"✓ [bold purple]8-bit color[/]\n" +
|
||||||
|
"✓ [bold yellow]Truecolor (16.7 million)[/]\n" +
|
||||||
|
"✓ [bold aqua]Automatic color conversion[/]"),
|
||||||
|
new ColorBox(height: 6));
|
||||||
|
|
||||||
|
return colorTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IRenderable GetTextGrid()
|
||||||
|
{
|
||||||
|
var loremTable = new Grid();
|
||||||
|
var lorem = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Quisque in metus sed sapien ultricies pretium a at justo. Maecenas luctus velit et auctor maximus.";
|
||||||
|
loremTable.AddColumn(new GridColumn().LeftAligned());
|
||||||
|
loremTable.AddColumn(new GridColumn().Centered());
|
||||||
|
loremTable.AddColumn(new GridColumn().RightAligned());
|
||||||
|
loremTable.AddRow($"[green]{lorem}[/]", $"[yellow]{lorem}[/]", $"[blue]{lorem}[/]");
|
||||||
|
return loremTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IRenderable GetTreeTable()
|
||||||
|
{
|
||||||
|
var tree = new Tree("📁 src");
|
||||||
|
tree.AddNode("📁 foo").AddNode("📄 bar.cs");
|
||||||
|
tree.AddNode("📁 baz").AddNode("📁 qux").AddNode("📄 corgi.txt");
|
||||||
|
tree.AddNode("📄 waldo.xml");
|
||||||
|
|
||||||
|
var table = new Table().SimpleBorder().BorderColor(Color.Grey);
|
||||||
|
table.AddColumn(new TableColumn("Overview"));
|
||||||
|
table.AddColumn(new TableColumn("").Footer("[grey]3 Files, 225 KiB[/]"));
|
||||||
|
table.AddRow(new Markup("[yellow]Files[/]"), tree);
|
||||||
|
|
||||||
|
return new Table().RoundedBorder().Collapse().BorderColor(Color.Yellow)
|
||||||
|
.AddColumn("Foo").AddColumn("Bar")
|
||||||
|
.AddRow(new Text("Baz"), table)
|
||||||
|
.AddRow("Qux", "Corgi");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IRenderable GetBarChart()
|
||||||
|
{
|
||||||
|
return new BarChart()
|
||||||
|
.AddItem("Apple", 32, Color.Green)
|
||||||
|
.AddItem("Oranges", 13, Color.Orange1)
|
||||||
|
.AddItem("Bananas", 22, Color.Yellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IRenderable GetBreakdownChart()
|
||||||
|
{
|
||||||
|
return new BreakdownChart()
|
||||||
|
.ShowPercentage()
|
||||||
|
.FullSize()
|
||||||
|
.AddItem("C#", 82, Color.Green)
|
||||||
|
.AddItem("PowerShell", 13, Color.Red)
|
||||||
|
.AddItem("Bash", 5, Color.Blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
examples/Console/Showcase/Showcase.csproj
Normal file
15
examples/Console/Showcase/Showcase.csproj
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Showcase</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstration of Spectre.Console.</ExampleDescription>
|
||||||
|
<ExampleGroup>Misc</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
69
examples/Console/Status/Program.cs
Normal file
69
examples/Console/Status/Program.cs
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
using System.Threading;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Status;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static void Main()
|
||||||
|
{
|
||||||
|
AnsiConsole.Status()
|
||||||
|
.AutoRefresh(true)
|
||||||
|
.Spinner(Spinner.Known.Default)
|
||||||
|
.Start("[yellow]Initializing warp drive[/]", ctx =>
|
||||||
|
{
|
||||||
|
// Initialize
|
||||||
|
Thread.Sleep(3000);
|
||||||
|
WriteLogMessage("Starting gravimetric field displacement manifold");
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
WriteLogMessage("Warming up deuterium chamber");
|
||||||
|
Thread.Sleep(2000);
|
||||||
|
WriteLogMessage("Generating antideuterium");
|
||||||
|
|
||||||
|
// Warp nacelles
|
||||||
|
Thread.Sleep(3000);
|
||||||
|
ctx.Spinner(Spinner.Known.BouncingBar);
|
||||||
|
ctx.Status("[bold blue]Unfolding warp nacelles[/]");
|
||||||
|
WriteLogMessage("Unfolding left warp nacelle");
|
||||||
|
Thread.Sleep(2000);
|
||||||
|
WriteLogMessage("Left warp nacelle [green]online[/]");
|
||||||
|
WriteLogMessage("Unfolding right warp nacelle");
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
WriteLogMessage("Right warp nacelle [green]online[/]");
|
||||||
|
|
||||||
|
// Warp bubble
|
||||||
|
Thread.Sleep(3000);
|
||||||
|
ctx.Spinner(Spinner.Known.Star2);
|
||||||
|
ctx.Status("[bold blue]Generating warp bubble[/]");
|
||||||
|
Thread.Sleep(3000);
|
||||||
|
ctx.Spinner(Spinner.Known.Star);
|
||||||
|
ctx.Status("[bold blue]Stabilizing warp bubble[/]");
|
||||||
|
|
||||||
|
// Safety
|
||||||
|
ctx.Spinner(Spinner.Known.Monkey);
|
||||||
|
ctx.Status("[bold blue]Performing safety checks[/]");
|
||||||
|
WriteLogMessage("Enabling interior dampening");
|
||||||
|
Thread.Sleep(2000);
|
||||||
|
WriteLogMessage("Interior dampening [green]enabled[/]");
|
||||||
|
|
||||||
|
// Warp!
|
||||||
|
Thread.Sleep(3000);
|
||||||
|
ctx.Spinner(Spinner.Known.Moon);
|
||||||
|
WriteLogMessage("Preparing for warp");
|
||||||
|
Thread.Sleep(1000);
|
||||||
|
for (var warp = 1; warp < 10; warp++)
|
||||||
|
{
|
||||||
|
ctx.Status($"[bold blue]Warp {warp}[/]");
|
||||||
|
Thread.Sleep(500);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Done
|
||||||
|
AnsiConsole.MarkupLine("[bold green]Crusing at Warp 9.8[/]");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void WriteLogMessage(string message)
|
||||||
|
{
|
||||||
|
AnsiConsole.MarkupLine($"[grey]LOG:[/] {message}[grey]...[/]");
|
||||||
|
}
|
||||||
|
}
|
||||||
19
examples/Console/Status/Status.csproj
Normal file
19
examples/Console/Status/Status.csproj
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<ExampleTitle>Status</ExampleTitle>
|
||||||
|
<ExampleDescription>Demonstrates how to show status updates.</ExampleDescription>
|
||||||
|
<ExampleGroup>Status</ExampleGroup>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\Shared\Shared.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user