mirror of
https://github.com/spectreconsole/spectre.console.git
synced 2025-12-26 07:47:56 +01:00
Remove Spectre.Console.Cli from repository
* Move Spectre.Console.Cli to its own repository * Update build script to use Cake.Sdk and .NET Make * Remove StyleCop (unmaintained) * Add linting using dotnet format * Fix generator which was broken * Update dependencies
This commit is contained in:
committed by
Patrik Svensson
parent
1ec7b8ae8f
commit
45799107a3
153
.editorconfig
153
.editorconfig
@@ -24,155 +24,4 @@ indent_size = 2
|
|||||||
indent_size = 2
|
indent_size = 2
|
||||||
|
|
||||||
[*.md]
|
[*.md]
|
||||||
trim_trailing_whitespace = false
|
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
|
|
||||||
3
.github/workflows/ci.yaml
vendored
3
.github/workflows/ci.yaml
vendored
@@ -28,12 +28,13 @@ jobs:
|
|||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
8.0.x
|
8.0.x
|
||||||
9.0.x
|
9.0.x
|
||||||
|
10.0.x
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
dotnet tool restore
|
dotnet tool restore
|
||||||
dotnet cake
|
dotnet make
|
||||||
|
|
||||||
- name: Upload Verify Test Results
|
- name: Upload Verify Test Results
|
||||||
if: failure()
|
if: failure()
|
||||||
|
|||||||
3
.github/workflows/publish.yaml
vendored
3
.github/workflows/publish.yaml
vendored
@@ -34,12 +34,13 @@ jobs:
|
|||||||
dotnet-version: |
|
dotnet-version: |
|
||||||
8.0.x
|
8.0.x
|
||||||
9.0.x
|
9.0.x
|
||||||
|
10.0.x
|
||||||
|
|
||||||
- name: Publish
|
- name: Publish
|
||||||
shell: bash
|
shell: bash
|
||||||
run: |
|
run: |
|
||||||
dotnet tool restore
|
dotnet tool restore
|
||||||
dotnet cake --target="publish" \
|
dotnet make publish \
|
||||||
--nuget-key="${{secrets.NUGET_API_KEY}}" \
|
--nuget-key="${{secrets.NUGET_API_KEY}}" \
|
||||||
--github-key="${{secrets.GITHUB_TOKEN}}"
|
--github-key="${{secrets.GITHUB_TOKEN}}"
|
||||||
|
|
||||||
|
|||||||
21
README.md
21
README.md
@@ -11,7 +11,6 @@ It is heavily inspired by the excellent Python library, [Rich](https://github.co
|
|||||||
1. [Installing](#installing)
|
1. [Installing](#installing)
|
||||||
1. [Documentation](#documentation)
|
1. [Documentation](#documentation)
|
||||||
1. [Examples](#examples)
|
1. [Examples](#examples)
|
||||||
1. [Sponsors](#sponsors)
|
|
||||||
1. [Code of Conduct](#code-of-conduct)
|
1. [Code of Conduct](#code-of-conduct)
|
||||||
1. [.NET Foundation](#net-foundation)
|
1. [.NET Foundation](#net-foundation)
|
||||||
1. [License](#license)
|
1. [License](#license)
|
||||||
@@ -52,26 +51,6 @@ https://spectreconsole.net
|
|||||||
To see `Spectre.Console` in action, please see the
|
To see `Spectre.Console` in action, please see the
|
||||||
[examples repository](https://github.com/spectreconsole/examples).
|
[examples repository](https://github.com/spectreconsole/examples).
|
||||||
|
|
||||||
## Sponsors
|
|
||||||
|
|
||||||
The following people are [sponsoring](https://github.com/sponsors/patriksvensson)
|
|
||||||
`Spectre.Console` to show their support and to ensure the longevity of the project.
|
|
||||||
|
|
||||||
* [Rodney Littles II](https://github.com/RLittlesII)
|
|
||||||
* [Martin Björkström](https://github.com/bjorkstromm)
|
|
||||||
* [Dave Glick](https://github.com/daveaglick)
|
|
||||||
* [Kim Gunnarsson](https://github.com/kimgunnarsson)
|
|
||||||
* [Andrew McClenaghan](https://github.com/andymac4182)
|
|
||||||
* [C. Augusto Proiete](https://github.com/augustoproiete)
|
|
||||||
* [Viktor Elofsson](https://github.com/vktr)
|
|
||||||
* [Steven Knox](https://github.com/stevenknox)
|
|
||||||
* [David Pendray](https://github.com/dpen2000)
|
|
||||||
* [Elmah.io](https://github.com/elmahio)
|
|
||||||
* [Tom Kerkhove](https://github.com/tomkerkhove)
|
|
||||||
|
|
||||||
We really appreciate it.
|
|
||||||
**Thank you very much!**
|
|
||||||
|
|
||||||
## Code of Conduct
|
## Code of Conduct
|
||||||
|
|
||||||
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
|
This project has adopted the code of conduct defined by the Contributor Covenant to clarify expected behavior in our community.
|
||||||
|
|||||||
@@ -9,11 +9,10 @@ para Python.
|
|||||||
## Índice de Conteúdo
|
## Índice de Conteúdo
|
||||||
|
|
||||||
1. [Funcionalidades](#funcionalidades)
|
1. [Funcionalidades](#funcionalidades)
|
||||||
2. [Instalação](#instalação)
|
1. [Instalação](#instalação)
|
||||||
3. [Documentação](#documentação)
|
1. [Documentação](#documentação)
|
||||||
4. [Exemplos](#exemplos)
|
1. [Exemplos](#exemplos)
|
||||||
5. [Patrocinadores](#patrocinadores)
|
1. [Licença](#licença)
|
||||||
5. [Licença](#licença)
|
|
||||||
|
|
||||||
## Funcionalidades
|
## Funcionalidades
|
||||||
|
|
||||||
@@ -46,25 +45,6 @@ https://spectreconsole.net/
|
|||||||
To see `Spectre.Console` in action, please see the
|
To see `Spectre.Console` in action, please see the
|
||||||
[examples repository](https://github.com/spectreconsole/examples).
|
[examples repository](https://github.com/spectreconsole/examples).
|
||||||
|
|
||||||
## Patrocinadores
|
|
||||||
|
|
||||||
As seguintes pessoas estão [patrocinando](https://github.com/sponsors/patriksvensson)
|
|
||||||
o Spectre.Console para mostrar o seu apoio e garantir a longevidade do projeto.
|
|
||||||
|
|
||||||
* [Rodney Littles II](https://github.com/RLittlesII)
|
|
||||||
* [Martin Björkström](https://github.com/bjorkstromm)
|
|
||||||
* [Dave Glick](https://github.com/daveaglick)
|
|
||||||
* [Kim Gunanrsson](https://github.com/kimgunnarsson)
|
|
||||||
* [Andrew McClenaghan](https://github.com/andymac4182)
|
|
||||||
* [C. Augusto Proiete](https://github.com/augustoproiete)
|
|
||||||
* [Viktor Elofsson](https://github.com/vktr)
|
|
||||||
* [Steven Knox](https://github.com/stevenknox)
|
|
||||||
* [David Pendray](https://github.com/dpen2000)
|
|
||||||
* [Elmah.io](https://github.com/elmahio)
|
|
||||||
|
|
||||||
Eu estou muito agradecido.
|
|
||||||
**Muito obrigado!**
|
|
||||||
|
|
||||||
## Licença
|
## Licença
|
||||||
|
|
||||||
Copyright © Patrik Svensson, Phil Scott, Nils Andresen, Cédric Luthi, Frank Ray
|
Copyright © Patrik Svensson, Phil Scott, Nils Andresen, Cédric Luthi, Frank Ray
|
||||||
|
|||||||
27
README.zh.md
27
README.zh.md
@@ -9,11 +9,10 @@ _[
|
1. [功能](#功能)
|
||||||
2. [安装](#安装)
|
1. [安装](#安装)
|
||||||
3. [文档](#文档)
|
1. [文档](#文档)
|
||||||
4. [例子](#例子)
|
1. [例子](#例子)
|
||||||
5. [Sponsors](#Sponsors)
|
1. [开源许可](#开源许可)
|
||||||
6. [开源许可](#开源许可)
|
|
||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
|
|
||||||
@@ -42,24 +41,6 @@ https://spectreconsole.net/
|
|||||||
To see `Spectre.Console` in action, please see the
|
To see `Spectre.Console` in action, please see the
|
||||||
[examples repository](https://github.com/spectreconsole/examples).
|
[examples repository](https://github.com/spectreconsole/examples).
|
||||||
|
|
||||||
## Sponsors
|
|
||||||
|
|
||||||
下面这些用户正在[sponsor](https://github.com/sponsors/patriksvensson)上支持着Spectre.Console,确保这个项目的持续维护。
|
|
||||||
|
|
||||||
* [Rodney Littles II](https://github.com/RLittlesII)
|
|
||||||
* [Martin Björkström](https://github.com/bjorkstromm)
|
|
||||||
* [Dave Glick](https://github.com/daveaglick)
|
|
||||||
* [Kim Gunanrsson](https://github.com/kimgunnarsson)
|
|
||||||
* [Andrew McClenaghan](https://github.com/andymac4182)
|
|
||||||
* [C. Augusto Proiete](https://github.com/augustoproiete)
|
|
||||||
* [Viktor Elofsson](https://github.com/vktr)
|
|
||||||
* [Steven Knox](https://github.com/stevenknox)
|
|
||||||
* [David Pendray](https://github.com/dpen2000)
|
|
||||||
* [Elmah.io](https://github.com/elmahio)
|
|
||||||
|
|
||||||
我对此表示十分感激
|
|
||||||
**非常感谢各位!**
|
|
||||||
|
|
||||||
## 开源许可
|
## 开源许可
|
||||||
|
|
||||||
版权所有 © Patrik Svensson, Phil Scott, Nils Andresen, Cédric Luthi, Frank Ray
|
版权所有 © Patrik Svensson, Phil Scott, Nils Andresen, Cédric Luthi, Frank Ray
|
||||||
|
|||||||
@@ -1,3 +1,12 @@
|
|||||||
|
#:sdk Cake.Sdk@5.1.25296.94-beta
|
||||||
|
|
||||||
|
var solution = "./src/Spectre.Console.slnx";
|
||||||
|
var generatorSolution = "./resources/scripts/Generator/Generator.slnx";
|
||||||
|
var testProject = "./src/Spectre.Console.Tests/Spectre.Console.Tests.csproj";
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////
|
||||||
|
// Arguments
|
||||||
|
|
||||||
var target = Argument("target", "Default");
|
var target = Argument("target", "Default");
|
||||||
var configuration = Argument("configuration", "Release");
|
var configuration = Argument("configuration", "Release");
|
||||||
|
|
||||||
@@ -5,33 +14,31 @@ var configuration = Argument("configuration", "Release");
|
|||||||
// Tasks
|
// Tasks
|
||||||
|
|
||||||
Task("Clean")
|
Task("Clean")
|
||||||
.Does(context =>
|
.Does(ctx =>
|
||||||
{
|
{
|
||||||
context.CleanDirectory("./.artifacts");
|
ctx.CleanDirectory("./.artifacts");
|
||||||
|
});
|
||||||
|
|
||||||
|
Task("Lint")
|
||||||
|
.Does(ctx =>
|
||||||
|
{
|
||||||
|
ctx.DotNetFormat(solution, new DotNetFormatSettings
|
||||||
|
{
|
||||||
|
VerifyNoChanges = true,
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Task("Build")
|
Task("Build")
|
||||||
.IsDependentOn("Clean")
|
.IsDependentOn("Clean")
|
||||||
.Does(context =>
|
.IsDependentOn("Lint")
|
||||||
|
.Does(ctx =>
|
||||||
{
|
{
|
||||||
Information("Compiling generator...");
|
ctx.DotNetBuild(solution, new DotNetBuildSettings
|
||||||
DotNetBuild("./resources/scripts/Generator/Generator.slnx", new DotNetBuildSettings
|
|
||||||
{
|
{
|
||||||
Configuration = configuration,
|
Configuration = configuration,
|
||||||
Verbosity = DotNetVerbosity.Minimal,
|
Verbosity = DotNetVerbosity.Minimal,
|
||||||
NoLogo = true,
|
NoLogo = true,
|
||||||
NoIncremental = context.HasArgument("rebuild"),
|
NoIncremental = ctx.HasArgument("rebuild"),
|
||||||
MSBuildSettings = new DotNetMSBuildSettings()
|
|
||||||
.TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error)
|
|
||||||
});
|
|
||||||
|
|
||||||
Information("\nCompiling Spectre.Console...");
|
|
||||||
DotNetBuild("./src/Spectre.Console.slnx", new DotNetBuildSettings
|
|
||||||
{
|
|
||||||
Configuration = configuration,
|
|
||||||
Verbosity = DotNetVerbosity.Minimal,
|
|
||||||
NoLogo = true,
|
|
||||||
NoIncremental = context.HasArgument("rebuild"),
|
|
||||||
MSBuildSettings = new DotNetMSBuildSettings()
|
MSBuildSettings = new DotNetMSBuildSettings()
|
||||||
.TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error)
|
.TreatAllWarningsAs(MSBuildTreatAllWarningsAs.Error)
|
||||||
});
|
});
|
||||||
@@ -39,17 +46,9 @@ Task("Build")
|
|||||||
|
|
||||||
Task("Test")
|
Task("Test")
|
||||||
.IsDependentOn("Build")
|
.IsDependentOn("Build")
|
||||||
.Does(context =>
|
.Does(ctx =>
|
||||||
{
|
{
|
||||||
DotNetTest("./src/Tests/Spectre.Console.Tests/Spectre.Console.Tests.csproj", new DotNetTestSettings {
|
ctx.DotNetTest(testProject, new DotNetTestSettings {
|
||||||
Configuration = configuration,
|
|
||||||
Verbosity = DotNetVerbosity.Minimal,
|
|
||||||
NoLogo = true,
|
|
||||||
NoRestore = true,
|
|
||||||
NoBuild = true,
|
|
||||||
});
|
|
||||||
|
|
||||||
DotNetTest("./src/Tests/Spectre.Console.Cli.Tests/Spectre.Console.Cli.Tests.csproj", new DotNetTestSettings {
|
|
||||||
Configuration = configuration,
|
Configuration = configuration,
|
||||||
Verbosity = DotNetVerbosity.Minimal,
|
Verbosity = DotNetVerbosity.Minimal,
|
||||||
NoLogo = true,
|
NoLogo = true,
|
||||||
@@ -60,9 +59,9 @@ Task("Test")
|
|||||||
|
|
||||||
Task("Package")
|
Task("Package")
|
||||||
.IsDependentOn("Test")
|
.IsDependentOn("Test")
|
||||||
.Does(context =>
|
.Does(ctx =>
|
||||||
{
|
{
|
||||||
context.DotNetPack($"./src/Spectre.Console.slnx", new DotNetPackSettings
|
ctx.DotNetPack(solution, new DotNetPackSettings
|
||||||
{
|
{
|
||||||
Configuration = configuration,
|
Configuration = configuration,
|
||||||
Verbosity = DotNetVerbosity.Minimal,
|
Verbosity = DotNetVerbosity.Minimal,
|
||||||
@@ -78,17 +77,17 @@ Task("Package")
|
|||||||
Task("Publish-NuGet")
|
Task("Publish-NuGet")
|
||||||
.WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions")
|
.WithCriteria(ctx => BuildSystem.IsRunningOnGitHubActions, "Not running on GitHub Actions")
|
||||||
.IsDependentOn("Package")
|
.IsDependentOn("Package")
|
||||||
.Does(context =>
|
.Does(ctx =>
|
||||||
{
|
{
|
||||||
var apiKey = Argument<string>("nuget-key", null);
|
var apiKey = Argument<string?>("nuget-key", null);
|
||||||
if(string.IsNullOrWhiteSpace(apiKey)) {
|
if(string.IsNullOrWhiteSpace(apiKey)) {
|
||||||
throw new CakeException("No NuGet API key was provided.");
|
throw new CakeException("No NuGet API key was provided.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish to GitHub Packages
|
// Publish to GitHub Packages
|
||||||
foreach(var file in context.GetFiles("./.artifacts/*.nupkg"))
|
foreach(var file in ctx.GetFiles("./.artifacts/*.nupkg"))
|
||||||
{
|
{
|
||||||
context.Information("Publishing {0}...", file.GetFilename().FullPath);
|
ctx.Information("Publishing {0}...", file.GetFilename().FullPath);
|
||||||
DotNetNuGetPush(file.FullPath, new DotNetNuGetPushSettings
|
DotNetNuGetPush(file.FullPath, new DotNetNuGetPushSettings
|
||||||
{
|
{
|
||||||
Source = "https://api.nuget.org/v3/index.json",
|
Source = "https://api.nuget.org/v3/index.json",
|
||||||
@@ -22,7 +22,6 @@ namespace Docs
|
|||||||
.AddSetting(Constants.SourceFiles, new List<string>
|
.AddSetting(Constants.SourceFiles, new List<string>
|
||||||
{
|
{
|
||||||
"../../src/Spectre.Console/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs",
|
"../../src/Spectre.Console/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs",
|
||||||
"../../src/Spectre.Console.Cli/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs",
|
|
||||||
"../../src/Spectre.Console.Testing/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs",
|
"../../src/Spectre.Console.Testing/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs",
|
||||||
"../../src/Extensions/Spectre.Console.ImageSharp/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs",
|
"../../src/Extensions/Spectre.Console.ImageSharp/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs",
|
||||||
"../../src/Extensions/Spectre.Console.Json/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs"
|
"../../src/Extensions/Spectre.Console.Json/**/{!bin,!obj,!packages,!*.Tests,}/**/*.cs"
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
Title: CommandApp
|
Title: CommandApp
|
||||||
Order: 2
|
Order: 2
|
||||||
Description: "**CommandApp** is the entry point for a *Spectre.Console.Cli* command line application. It is used to configure the settings and commands used for execution of the application."
|
Description: "**CommandApp** is the entry point for a *Spectre.Console.Cli* command line application. It is used to configure the settings and commands used for execution of the application."
|
||||||
Reference:
|
|
||||||
- T:Spectre.Console.Cli.CommandApp
|
|
||||||
- T:Spectre.Console.Cli.CommandApp`1
|
|
||||||
---
|
---
|
||||||
|
|
||||||
`CommandApp` is the entry point for a `Spectre.Console.Cli` command line application. It is used to configure the settings and commands used for execution of the application. Most `Spectre.Console.Cli` applications will need to specify a custom configuration using the `Configure` method.
|
`CommandApp` is the entry point for a `Spectre.Console.Cli` command line application. It is used to configure the settings and commands used for execution of the application. Most `Spectre.Console.Cli` applications will need to specify a custom configuration using the `Configure` method.
|
||||||
@@ -76,7 +73,7 @@ return app.Run(args);
|
|||||||
```
|
```
|
||||||
|
|
||||||
<?# Alert ?>
|
<?# Alert ?>
|
||||||
`MyTypeRegistrar` is a custom class that implements [ITypeRegistrar](xref:T:Spectre.Console.Cli.ITypeRegistrar) and must be provided by the user.
|
`MyTypeRegistrar` is a custom class that implements `ITypeRegistrar` and must be provided by the user.
|
||||||
<?#/ Alert ?>
|
<?#/ Alert ?>
|
||||||
|
|
||||||
There is a working [example of dependency injection](https://github.com/spectreconsole/examples/tree/main/examples/Cli/Injection) that uses `Microsoft.Extensions.DependencyInjection` as the container. Example implementations of `ITypeRegistrar` and `ITypeResolver` are provided, which you can copy and paste to your application for dependency injection.
|
There is a working [example of dependency injection](https://github.com/spectreconsole/examples/tree/main/examples/Cli/Injection) that uses `Microsoft.Extensions.DependencyInjection` as the container. Example implementations of `ITypeRegistrar` and `ITypeResolver` are provided, which you can copy and paste to your application for dependency injection.
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
Title: Creating Commands
|
Title: Creating Commands
|
||||||
Order: 6
|
Order: 6
|
||||||
Description: "How to create commands for *Spectre.Console.Cli*"
|
Description: "How to create commands for *Spectre.Console.Cli*"
|
||||||
Reference:
|
|
||||||
- T:Spectre.Console.Cli.AsyncCommand`1
|
|
||||||
- T:Spectre.Console.Cli.Command`1
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Commands in `Spectre.Console.Cli` are defined by creating a class that inherits from either `Command<TSettings>` or `AsyncCommand<TSettings>`. `Command<TSettings>` must implement an `Execute` method that returns an int where as `AsyncCommand<TSettings>` must implement `ExecuteAsync` returning `Task<int>`.
|
Commands in `Spectre.Console.Cli` are defined by creating a class that inherits from either `Command<TSettings>` or `AsyncCommand<TSettings>`. `Command<TSettings>` must implement an `Execute` method that returns an int where as `AsyncCommand<TSettings>` must implement `ExecuteAsync` returning `Task<int>`.
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
Title: Specifying Settings
|
Title: Specifying Settings
|
||||||
Order: 5
|
Order: 5
|
||||||
Description: "How to define command line argument settings for your *Spectre.Console.Cli* Commands"
|
Description: "How to define command line argument settings for your *Spectre.Console.Cli* Commands"
|
||||||
Reference:
|
|
||||||
- T:Spectre.Console.Cli.CommandSettings
|
|
||||||
- T:Spectre.Console.Cli.CommandArgumentAttribute
|
|
||||||
- T:Spectre.Console.Cli.CommandOptionAttribute
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Settings for `Spectre.Console.Cli` commands are defined via classes that inherit from `CommandSettings`. Attributes are used to indicate how the parser interprets the command line arguments and create a runtime instance of the settings to be used.
|
Settings for `Spectre.Console.Cli` commands are defined via classes that inherit from `CommandSettings`. Attributes are used to indicate how the parser interprets the command line arguments and create a runtime instance of the settings to be used.
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
Title: Unit Testing
|
Title: Unit Testing
|
||||||
Order: 14
|
Order: 14
|
||||||
Description: Instructions for unit testing a Spectre.Console application.
|
Description: Instructions for unit testing a Spectre.Console application.
|
||||||
Reference:
|
|
||||||
- T:Spectre.Console.Testing.CommandAppTester
|
|
||||||
- T:Spectre.Console.Testing.TestConsole
|
|
||||||
- T:Spectre.Console.Testing.TestConsoleInput
|
|
||||||
---
|
---
|
||||||
|
|
||||||
`Spectre.Console` has a separate project that contains test harnesses for unit testing your own console applications.
|
`Spectre.Console` has a separate project that contains test harnesses for unit testing your own console applications.
|
||||||
|
|||||||
@@ -2,17 +2,19 @@
|
|||||||
"version": 1,
|
"version": 1,
|
||||||
"isRoot": true,
|
"isRoot": true,
|
||||||
"tools": {
|
"tools": {
|
||||||
"cake.tool": {
|
|
||||||
"version": "5.1.0",
|
|
||||||
"commands": [
|
|
||||||
"dotnet-cake"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
"verify.tool": {
|
"verify.tool": {
|
||||||
"version": "0.6.0",
|
"version": "0.6.0",
|
||||||
"commands": [
|
"commands": [
|
||||||
"dotnet-verify"
|
"dotnet-verify"
|
||||||
]
|
],
|
||||||
|
"rollForward": false
|
||||||
|
},
|
||||||
|
"make": {
|
||||||
|
"version": "0.8.0",
|
||||||
|
"commands": [
|
||||||
|
"dotnet-make"
|
||||||
|
],
|
||||||
|
"rollForward": false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "http://json.schemastore.org/global",
|
"$schema": "http://json.schemastore.org/global",
|
||||||
"sdk": {
|
"sdk": {
|
||||||
"version": "9.0.306",
|
"version": "10.0.100-rc.2.25502.107",
|
||||||
"rollForward": "latestFeature"
|
"rollForward": "latestFeature"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
# `Spectre.Console.Cli`
|
|
||||||
|
|
||||||
`Spectre.Console.Cli` is a modern library for parsing command line arguments. While it's extremely opinionated in what it does, it tries to follow established industry conventions, and draws its inspiration from applications you use everyday.
|
|
||||||
|
|
||||||
Detailed instructions for using this library is located on the project website, https://spectreconsole.net
|
|
||||||
5
resources/scripts/Generate-Colors.ps1
Normal file → Executable file
5
resources/scripts/Generate-Colors.ps1
Normal file → Executable file
@@ -1,8 +1,11 @@
|
|||||||
|
#!/usr/local/bin/pwsh
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
# Script that generates known colors and lookup tables.
|
# Script that generates known colors and lookup tables.
|
||||||
##########################################################
|
##########################################################
|
||||||
|
|
||||||
$Output = Join-Path $PSScriptRoot "Temp"
|
$Output = Join-Path $PSScriptRoot "Temp"
|
||||||
|
$Generator = Join-Path $PSScriptRoot "/../../src/Generator"
|
||||||
$Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console"
|
$Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console"
|
||||||
|
|
||||||
if(!(Test-Path $Output -PathType Container)) {
|
if(!(Test-Path $Output -PathType Container)) {
|
||||||
@@ -10,7 +13,7 @@ if(!(Test-Path $Output -PathType Container)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Generate the files
|
# Generate the files
|
||||||
Push-Location Generator
|
Push-Location $Generator
|
||||||
&dotnet run -- colors "$Output"
|
&dotnet run -- colors "$Output"
|
||||||
if(!$?) {
|
if(!$?) {
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
|||||||
5
resources/scripts/Generate-Emoji.ps1
Normal file → Executable file
5
resources/scripts/Generate-Emoji.ps1
Normal file → Executable file
@@ -1,8 +1,11 @@
|
|||||||
|
#!/usr/local/bin/pwsh
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
# Script that generates the emoji lookup table.
|
# Script that generates the emoji lookup table.
|
||||||
##########################################################
|
##########################################################
|
||||||
|
|
||||||
$Output = Join-Path $PSScriptRoot "Temp"
|
$Output = Join-Path $PSScriptRoot "Temp"
|
||||||
|
$Generator = Join-Path $PSScriptRoot "/../../src/Generator"
|
||||||
$Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console"
|
$Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console"
|
||||||
$Docs = Join-Path $PSScriptRoot "/../../docs/src/Data"
|
$Docs = Join-Path $PSScriptRoot "/../../docs/src/Data"
|
||||||
|
|
||||||
@@ -11,7 +14,7 @@ if(!(Test-Path $Output -PathType Container)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Generate the files
|
# Generate the files
|
||||||
Push-Location Generator
|
Push-Location $Generator
|
||||||
&dotnet run -- emoji "$Output" --input $Output
|
&dotnet run -- emoji "$Output" --input $Output
|
||||||
if(!$?) {
|
if(!$?) {
|
||||||
Pop-Location
|
Pop-Location
|
||||||
|
|||||||
15
resources/scripts/Generate-Samples.ps1
Normal file → Executable file
15
resources/scripts/Generate-Samples.ps1
Normal file → Executable file
@@ -1,11 +1,22 @@
|
|||||||
|
#!/usr/local/bin/pwsh
|
||||||
|
|
||||||
|
[CmdletBinding(PositionalBinding=$false)]
|
||||||
|
Param(
|
||||||
|
[Parameter(ValueFromRemainingArguments)]
|
||||||
|
[string[]]$Remaining
|
||||||
|
)
|
||||||
|
|
||||||
# first arg is either the name of a single sample you want to run or leave
|
# first arg is either the name of a single sample you want to run or leave
|
||||||
# blank if you want to run them all. the samples aren't going to run at the same
|
# blank if you want to run them all. the samples aren't going to run at the same
|
||||||
# speed each time so if you run all of them you'll have everything as a change
|
# speed each time so if you run all of them you'll have everything as a change
|
||||||
# for your commit so use this sparingly.
|
# for your commit so use this sparingly.
|
||||||
|
|
||||||
|
$Generator = Join-Path $PSScriptRoot "/../../src/Generator"
|
||||||
|
$Output = Join-Path $PSScriptRoot "../../docs/input/assets/casts"
|
||||||
|
|
||||||
# Generate the files
|
# Generate the files
|
||||||
Push-Location Generator
|
Push-Location $Generator
|
||||||
dotnet run -- samples -o "../../../docs/input/assets/casts" $args[0]
|
&dotnet run -- samples -o "$Output" $Remaining
|
||||||
if(!$?) {
|
if(!$?) {
|
||||||
Pop-Location
|
Pop-Location
|
||||||
Throw "An error occured when generating code."
|
Throw "An error occured when generating code."
|
||||||
|
|||||||
7
resources/scripts/Generate-Spinners.ps1
Normal file → Executable file
7
resources/scripts/Generate-Spinners.ps1
Normal file → Executable file
@@ -1,8 +1,11 @@
|
|||||||
|
#!/usr/local/bin/pwsh
|
||||||
|
|
||||||
##########################################################
|
##########################################################
|
||||||
# Script that generates progress spinners.
|
# Script that generates progress spinners.
|
||||||
##########################################################
|
##########################################################
|
||||||
|
|
||||||
$Output = Join-Path $PSScriptRoot "Temp"
|
$Output = Join-Path $PSScriptRoot "Temp"
|
||||||
|
$Generator = Join-Path $PSScriptRoot "/../../src/Generator"
|
||||||
$Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console"
|
$Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console"
|
||||||
|
|
||||||
if(!(Test-Path $Output -PathType Container)) {
|
if(!(Test-Path $Output -PathType Container)) {
|
||||||
@@ -10,8 +13,8 @@ if(!(Test-Path $Output -PathType Container)) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Generate the files
|
# Generate the files
|
||||||
Push-Location Generator
|
Push-Location $Generator
|
||||||
&dotnet run -- spinners "$Output" --input $Output
|
&dotnet run -- spinners "$Output"
|
||||||
if(!$?) {
|
if(!$?) {
|
||||||
Pop-Location
|
Pop-Location
|
||||||
Throw "An error occured when generating code."
|
Throw "An error occured when generating code."
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Spectre.Console;
|
|
||||||
using Generator.Commands;
|
|
||||||
using System.Threading;
|
|
||||||
|
|
||||||
namespace DocExampleGenerator
|
|
||||||
{
|
|
||||||
internal static class AnsiConsoleExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Displays something via AnsiConsole, waits a bit and then simulates typing based on the input. If the console
|
|
||||||
/// doesn't have the focus this will just type into whatever window does so watch the alt-tab.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="console"></param>
|
|
||||||
/// <param name="action">The display action.</param>
|
|
||||||
/// <param name="input">The characters to type. ↑ for an up arrow, ↓ for down arrow, ↲ for a return and ¦ for a pause.</param>
|
|
||||||
/// <param name="initialDelayMs">How long to delay before typing. This should be at least 100ms because we won't check if the prompt has displayed before simulating typing.</param>
|
|
||||||
/// <param name="keypressDelayMs">Delay between keypresses. There will be a bit of randomness between each keypress +/- 20% of this value.</param>
|
|
||||||
public static void DisplayThenType(this IAnsiConsole console, Action<IAnsiConsole> action, string input, int initialDelayMs = 500, int keypressDelayMs = 200)
|
|
||||||
{
|
|
||||||
if (console is not AsciiCastConsole asciiConsole)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Not an ASCII cast console");
|
|
||||||
}
|
|
||||||
|
|
||||||
asciiConsole.Input.PushText(input, keypressDelayMs);
|
|
||||||
|
|
||||||
Thread.Sleep(initialDelayMs);
|
|
||||||
|
|
||||||
action(console);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
using System;
|
|
||||||
using Spectre.Console;
|
|
||||||
using Spectre.Console.Rendering;
|
|
||||||
|
|
||||||
namespace Generator.Commands
|
|
||||||
{
|
|
||||||
public sealed class AsciiCastConsole : IAnsiConsole
|
|
||||||
{
|
|
||||||
private readonly IAnsiConsole _console;
|
|
||||||
private readonly AsciiCastInput _input;
|
|
||||||
|
|
||||||
public Profile Profile => _console.Profile;
|
|
||||||
|
|
||||||
public IAnsiConsoleCursor Cursor => _console.Cursor;
|
|
||||||
|
|
||||||
IAnsiConsoleInput IAnsiConsole.Input => _input;
|
|
||||||
|
|
||||||
public AsciiCastInput Input => _input;
|
|
||||||
|
|
||||||
public IExclusivityMode ExclusivityMode => _console.ExclusivityMode;
|
|
||||||
|
|
||||||
public RenderPipeline Pipeline => _console.Pipeline;
|
|
||||||
|
|
||||||
public AsciiCastConsole(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
_console = console ?? throw new ArgumentNullException(nameof(console));
|
|
||||||
_input = new AsciiCastInput();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Clear(bool home)
|
|
||||||
{
|
|
||||||
_console.Clear(home);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Write(IRenderable renderable)
|
|
||||||
{
|
|
||||||
_console.Write(renderable);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands
|
|
||||||
{
|
|
||||||
public static class AsciiCastExtensions
|
|
||||||
{
|
|
||||||
public static AsciiCastOut WrapWithAsciiCastRecorder(this IAnsiConsole ansiConsole)
|
|
||||||
{
|
|
||||||
AsciiCastOut castRecorder = new(ansiConsole.Profile.Out);
|
|
||||||
ansiConsole.Profile.Out = castRecorder;
|
|
||||||
|
|
||||||
return castRecorder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands
|
|
||||||
{
|
|
||||||
public sealed class AsciiCastInput : IAnsiConsoleInput
|
|
||||||
{
|
|
||||||
private readonly Queue<(ConsoleKeyInfo?, int)> _input;
|
|
||||||
private readonly Random _random = new Random();
|
|
||||||
|
|
||||||
public AsciiCastInput()
|
|
||||||
{
|
|
||||||
_input = new Queue<(ConsoleKeyInfo?, int)>();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PushText(string input, int keypressDelayMs)
|
|
||||||
{
|
|
||||||
if (input is null)
|
|
||||||
{
|
|
||||||
throw new ArgumentNullException(nameof(input));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var character in input)
|
|
||||||
{
|
|
||||||
PushCharacter(character, keypressDelayMs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PushTextWithEnter(string input, int keypressDelayMs)
|
|
||||||
{
|
|
||||||
PushText(input, keypressDelayMs);
|
|
||||||
PushKey(ConsoleKey.Enter, keypressDelayMs);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PushCharacter(char input, int keypressDelayMs)
|
|
||||||
{
|
|
||||||
var delay = keypressDelayMs + _random.Next((int)(keypressDelayMs * -.2), (int)(keypressDelayMs * .2));
|
|
||||||
|
|
||||||
switch (input)
|
|
||||||
{
|
|
||||||
case '↑':
|
|
||||||
PushKey(ConsoleKey.UpArrow, keypressDelayMs);
|
|
||||||
break;
|
|
||||||
case '↓':
|
|
||||||
PushKey(ConsoleKey.DownArrow, keypressDelayMs);
|
|
||||||
break;
|
|
||||||
case '↲':
|
|
||||||
PushKey(ConsoleKey.Enter, keypressDelayMs);
|
|
||||||
break;
|
|
||||||
case '¦':
|
|
||||||
_input.Enqueue((null, delay));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
var control = char.IsUpper(input);
|
|
||||||
_input.Enqueue((new ConsoleKeyInfo(input, (ConsoleKey)input, false, false, control), delay));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void PushKey(ConsoleKey input, int keypressDelayMs)
|
|
||||||
{
|
|
||||||
var delay = keypressDelayMs + _random.Next((int)(keypressDelayMs * -.2), (int)(keypressDelayMs * .2));
|
|
||||||
_input.Enqueue((new ConsoleKeyInfo((char)input, input, false, false, false), delay));
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsKeyAvailable()
|
|
||||||
{
|
|
||||||
return _input.Count > 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConsoleKeyInfo? ReadKey(bool intercept)
|
|
||||||
{
|
|
||||||
if (_input.Count == 0)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("No input available.");
|
|
||||||
}
|
|
||||||
|
|
||||||
var result = _input.Dequeue();
|
|
||||||
|
|
||||||
Thread.Sleep(result.Item2);
|
|
||||||
return result.Item1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Task<ConsoleKeyInfo?> ReadKeyAsync(bool intercept, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
return Task.FromResult(ReadKey(intercept));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Globalization;
|
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
using System.Text.Json;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands
|
|
||||||
{
|
|
||||||
public class AsciiCastOut : IAnsiConsoleOutput
|
|
||||||
{
|
|
||||||
private sealed class AsciiCastWriter : TextWriter
|
|
||||||
{
|
|
||||||
private readonly TextWriter _wrappedTextWriter;
|
|
||||||
private readonly StringBuilder _builder = new StringBuilder();
|
|
||||||
private int? _firstTick;
|
|
||||||
|
|
||||||
public AsciiCastWriter(TextWriter wrappedTextWriter)
|
|
||||||
{
|
|
||||||
_wrappedTextWriter = wrappedTextWriter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Write(string value)
|
|
||||||
{
|
|
||||||
if (value == null)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Append(value);
|
|
||||||
_wrappedTextWriter.Write(value);
|
|
||||||
base.Write(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override Encoding Encoding => _wrappedTextWriter.Encoding;
|
|
||||||
|
|
||||||
private void Append(string value)
|
|
||||||
{
|
|
||||||
var tick = 0m;
|
|
||||||
if (_firstTick.HasValue)
|
|
||||||
{
|
|
||||||
tick = Environment.TickCount - _firstTick.Value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_firstTick = Environment.TickCount;
|
|
||||||
}
|
|
||||||
|
|
||||||
tick /= 1000m;
|
|
||||||
|
|
||||||
_builder.Append('[')
|
|
||||||
.AppendFormat(CultureInfo.InvariantCulture, "{0}", tick)
|
|
||||||
.Append(", \"o\", \"").Append(JsonEncodedText.Encode(value)).AppendLine("\"]");
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetJsonAndClearBuffer()
|
|
||||||
{
|
|
||||||
var json = _builder.ToString();
|
|
||||||
|
|
||||||
// reset the buffer and also reset the first tick count
|
|
||||||
_builder.Clear();
|
|
||||||
_firstTick = null;
|
|
||||||
return json;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly IAnsiConsoleOutput _wrappedAnsiConsole;
|
|
||||||
private readonly AsciiCastWriter _asciiCastWriter;
|
|
||||||
|
|
||||||
public AsciiCastOut(IAnsiConsoleOutput wrappedAnsiConsole)
|
|
||||||
{
|
|
||||||
_wrappedAnsiConsole = wrappedAnsiConsole ?? throw new ArgumentNullException(nameof(wrappedAnsiConsole));
|
|
||||||
_asciiCastWriter = new AsciiCastWriter(_wrappedAnsiConsole.Writer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public TextWriter Writer => _asciiCastWriter;
|
|
||||||
|
|
||||||
public bool IsTerminal => _wrappedAnsiConsole.IsTerminal;
|
|
||||||
|
|
||||||
public int Width => _wrappedAnsiConsole.Width;
|
|
||||||
|
|
||||||
public int Height => _wrappedAnsiConsole.Height;
|
|
||||||
|
|
||||||
public void SetEncoding(Encoding encoding)
|
|
||||||
{
|
|
||||||
_wrappedAnsiConsole.SetEncoding(encoding);
|
|
||||||
}
|
|
||||||
|
|
||||||
public string GetCastJson(string title, int? width = null, int? height = null)
|
|
||||||
{
|
|
||||||
var header = $"{{\"version\": 2, \"width\": {width ?? _wrappedAnsiConsole.Width}, \"height\": {height ?? _wrappedAnsiConsole.Height}, \"title\": \"{JsonEncodedText.Encode(title)}\", \"env\": {{\"TERM\": \"Spectre.Console\"}}}}";
|
|
||||||
return $"{header}{Environment.NewLine}{_asciiCastWriter.GetJsonAndClearBuffer()}{Environment.NewLine}";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class BarChartSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 5);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.Write(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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,61 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
public abstract class BaseSample
|
|
||||||
{
|
|
||||||
public abstract void Run(IAnsiConsole console);
|
|
||||||
public virtual string Name() => PascalToKebab(GetType().Name.Replace("Sample",""));
|
|
||||||
public virtual (int Cols, int Rows) ConsoleSize => (82, 24);
|
|
||||||
public virtual IEnumerable<(string Name, Action<Capabilities> CapabilitiesAction)> GetCapabilities()
|
|
||||||
{
|
|
||||||
return new (string Name, Action<Capabilities> CapabilitiesAction)[]
|
|
||||||
{
|
|
||||||
("plain", capabilities =>
|
|
||||||
{
|
|
||||||
capabilities.Unicode = false;
|
|
||||||
capabilities.Ansi = true;
|
|
||||||
capabilities.Interactive = true;
|
|
||||||
capabilities.Legacy = false;
|
|
||||||
capabilities.Links = false;
|
|
||||||
capabilities.ColorSystem = ColorSystem.Legacy;
|
|
||||||
}),
|
|
||||||
("rich", capabilities =>
|
|
||||||
{
|
|
||||||
capabilities.Unicode = true;
|
|
||||||
capabilities.Ansi = true;
|
|
||||||
capabilities.Interactive = true;
|
|
||||||
capabilities.Legacy = false;
|
|
||||||
capabilities.Links = false;
|
|
||||||
capabilities.ColorSystem = ColorSystem.TrueColor;
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private string PascalToKebab(ReadOnlySpan<char> input)
|
|
||||||
{
|
|
||||||
var sb = new StringBuilder();
|
|
||||||
var previousUpper = true;
|
|
||||||
foreach (var chr in input)
|
|
||||||
{
|
|
||||||
if (char.IsUpper(chr) && previousUpper == false)
|
|
||||||
{
|
|
||||||
sb.Append('-');
|
|
||||||
previousUpper = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
previousUpper = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
sb.Append(char.ToLower(chr));
|
|
||||||
}
|
|
||||||
|
|
||||||
return sb.ToString();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class BreakdownChartSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 5);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.Write(new BreakdownChart()
|
|
||||||
.Width(60)
|
|
||||||
.AddItem("SCSS", 80, 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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal abstract class BaseCalendarSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 12);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class CalendarSample : BaseCalendarSample
|
|
||||||
{
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console) => console.Write(new Calendar(2020,10));
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class CalendarCultureSample : BaseCalendarSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console) => console.Write(new Calendar(2020,10).Culture("sv-SE"));
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class CalendarHeader : BaseCalendarSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var calendar = new Calendar(2020,10);
|
|
||||||
calendar.HeaderStyle(Style.Parse("blue bold"));
|
|
||||||
console.Write(calendar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class CalendarHighlightSample : BaseCalendarSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var calendar = new Calendar(2020, 10).HighlightStyle(Style.Parse("yellow bold"));
|
|
||||||
calendar.AddCalendarEvent(2020, 10, 11);
|
|
||||||
console.Write(calendar);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
using SixLabors.ImageSharp.Processing;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class CanvasImageSample : BaseSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var image = new CanvasImage("../../../examples/Console/Canvas/cake.png");
|
|
||||||
image.MaxWidth(16);
|
|
||||||
console.Write(image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class CanvasImageManipulationSample : BaseSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var image = new CanvasImage("../../../examples/Console/Canvas/cake.png");
|
|
||||||
image.MaxWidth(24);
|
|
||||||
image.BilinearResampler();
|
|
||||||
image.Mutate(ctx => ctx.Grayscale().Rotate(-45).EntropyCrop());
|
|
||||||
console.Write(image);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class CanvasSample : BaseSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var canvas = new Canvas(16, 16);
|
|
||||||
|
|
||||||
// Draw some shapes
|
|
||||||
for(var i = 0; i < canvas.Width; i++)
|
|
||||||
{
|
|
||||||
// Cross
|
|
||||||
canvas.SetPixel(i, i, Color.White);
|
|
||||||
canvas.SetPixel(canvas.Width - i - 1, i, Color.White);
|
|
||||||
|
|
||||||
// Border
|
|
||||||
canvas.SetPixel(i, 0, Color.Red);
|
|
||||||
canvas.SetPixel(0, i, Color.Green);
|
|
||||||
canvas.SetPixel(i, canvas.Height - 1, Color.Blue);
|
|
||||||
canvas.SetPixel(canvas.Width - 1, i, Color.Yellow);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Render the canvas
|
|
||||||
console.Write(canvas);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,81 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Security.Authentication;
|
|
||||||
using Generator.Commands.Samples;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
// keep the namespace here short because it'll be used in the display of the exceptions
|
|
||||||
// and we want to keep that below 100 characters wide.
|
|
||||||
namespace Samples
|
|
||||||
{
|
|
||||||
public class Exceptions
|
|
||||||
{
|
|
||||||
internal abstract class BaseExceptionSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (100, 12);
|
|
||||||
|
|
||||||
protected readonly Exception Exception = null!;
|
|
||||||
|
|
||||||
protected BaseExceptionSample()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
DoMagic(42, null);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
Exception = ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class DefaultExceptionSample : BaseExceptionSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console) => console.WriteException(Exception, ExceptionFormats.ShortenPaths);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class ShortenedExceptionSample : BaseExceptionSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console) => console.WriteException(Exception, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks);
|
|
||||||
}
|
|
||||||
|
|
||||||
internal class CustomColorsExceptionSample : BaseExceptionSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.WriteException(Exception, 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),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void DoMagic(int foo, string[,] bar)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
CheckCredentials(foo, bar);
|
|
||||||
}
|
|
||||||
catch(Exception ex)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Whaaat?", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void CheckCredentials(int qux, string[,] corgi)
|
|
||||||
{
|
|
||||||
throw new InvalidCredentialException("The credentials are invalid.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
public class FigletSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (100, 24);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.Write(new FigletText("Left aligned").LeftJustified().Color(Color.Red));
|
|
||||||
console.Write(new FigletText("Centered").Centered().Color(Color.Green));
|
|
||||||
console.Write(new FigletText("Right aligned").RightJustified().Color(Color.Blue));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,97 +0,0 @@
|
|||||||
using DocExampleGenerator;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class InputSample : BaseSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var age = 0;
|
|
||||||
var name = string.Empty;
|
|
||||||
var sport = string.Empty;
|
|
||||||
var password = string.Empty;
|
|
||||||
var color = string.Empty;
|
|
||||||
|
|
||||||
console.DisplayThenType(c => name = AskName(c), "Peter F↲");
|
|
||||||
console.DisplayThenType(c => sport = AskSport(c), "football↲¦¦¦¦Hockey↲");
|
|
||||||
console.DisplayThenType(c => age = AskAge(c), "Forty↲¦¦¦¦40↲");
|
|
||||||
console.DisplayThenType(c => password = AskPassword(c), "hunter2↲");
|
|
||||||
console.DisplayThenType(c => color = AskColor(c), "↲");
|
|
||||||
|
|
||||||
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 sport[/]", sport)
|
|
||||||
.AddRow("[grey]Age[/]", age.ToString())
|
|
||||||
.AddRow("[grey]Password[/]", password)
|
|
||||||
.AddRow("[grey]Favorite color[/]", string.IsNullOrEmpty(color) ? "Unknown" : color));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string AskName(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.WriteLine();
|
|
||||||
console.Write(new Rule("[yellow]Strings[/]").RuleStyle("grey").LeftJustified());
|
|
||||||
var name = console.Ask<string>("What's your [green]name[/]?");
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static string AskSport(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.WriteLine();
|
|
||||||
console.Write(new Rule("[yellow]Choices[/]").RuleStyle("grey").LeftJustified());
|
|
||||||
|
|
||||||
return console.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"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int AskAge(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.WriteLine();
|
|
||||||
console.Write(new Rule("[yellow]Integers[/]").RuleStyle("grey").LeftJustified());
|
|
||||||
|
|
||||||
return console.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(),
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string AskPassword(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.WriteLine();
|
|
||||||
console.Write(new Rule("[yellow]Secrets[/]").RuleStyle("grey").LeftJustified());
|
|
||||||
|
|
||||||
return console.Prompt(
|
|
||||||
new TextPrompt<string>("Enter [green]password[/]?")
|
|
||||||
.PromptStyle("red")
|
|
||||||
.Secret());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string AskColor(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.WriteLine();
|
|
||||||
console.Write(new Rule("[yellow]Optional[/]").RuleStyle("grey").LeftJustified());
|
|
||||||
|
|
||||||
return console.Prompt(
|
|
||||||
new TextPrompt<string>("[grey][[Optional]][/] What is your [green]favorite color[/]?")
|
|
||||||
.AllowEmpty());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
using Spectre.Console.Json;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
public class JsonSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (60, 20);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
using Spectre.Console.Json;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
public class LayoutSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (80, 24);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var layout = new Layout("Root")
|
|
||||||
.SplitColumns(
|
|
||||||
new Layout("Left"),
|
|
||||||
new Layout("Right")
|
|
||||||
.SplitRows(
|
|
||||||
new Layout("Top"),
|
|
||||||
new Layout("Bottom")));
|
|
||||||
|
|
||||||
layout["Left"].Update(
|
|
||||||
new Panel(
|
|
||||||
Align.Center(
|
|
||||||
new Markup("Hello [blue]World![/]"),
|
|
||||||
VerticalAlignment.Middle))
|
|
||||||
.Expand());
|
|
||||||
|
|
||||||
AnsiConsole.Write(layout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class LiveSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (100, 20);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var table = new Table();
|
|
||||||
|
|
||||||
// Animate
|
|
||||||
console.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[/] ]]"));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
using DocExampleGenerator;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class MultiSelectionSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 14);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.DisplayThenType(AskFruit, "↓↓ ¦¦↑↑ ¦¦ ¦¦↓ ↓↓↓↓↓ ↓↓↓↓ ¦¦↲");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AskFruit(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var favorites = console.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"
|
|
||||||
}));
|
|
||||||
|
|
||||||
console.MarkupLine("Your selected: [yellow]{0}[/]", string.Join(',', favorites));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class PanelSample : BaseSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var panel = new Panel("[red]Spaghetti\nLinguini\nFettucine\nTortellini\nCapellini\nLasagna[/]");
|
|
||||||
panel.Header = new PanelHeader("[underline]Pasta Menu[/]", Justify.Center);
|
|
||||||
panel.Border = BoxBorder.Double;
|
|
||||||
panel.Padding = new Padding(2, 2, 2, 2);
|
|
||||||
console.Write(panel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class ProgressSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 10);
|
|
||||||
|
|
||||||
public override IEnumerable<(string Name, Action<Capabilities> CapabilitiesAction)> GetCapabilities()
|
|
||||||
{
|
|
||||||
yield return ("non-interactive", capabilities =>
|
|
||||||
{
|
|
||||||
capabilities.Ansi = false;
|
|
||||||
capabilities.Interactive = false;
|
|
||||||
capabilities.Legacy = false;
|
|
||||||
capabilities.Unicode = true;
|
|
||||||
capabilities.ColorSystem = ColorSystem.TrueColor;
|
|
||||||
});
|
|
||||||
|
|
||||||
foreach (var capability in base.GetCapabilities())
|
|
||||||
{
|
|
||||||
yield return capability;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
// Show progress
|
|
||||||
console.Progress()
|
|
||||||
.AutoClear(false)
|
|
||||||
.Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new RemainingTimeColumn(), new SpinnerColumn())
|
|
||||||
.Start(ctx =>
|
|
||||||
{
|
|
||||||
var random = new Random(122978);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static List<(ProgressTask Task, int Delay)> CreateTasks(ProgressContext progress, Random random)
|
|
||||||
{
|
|
||||||
var tasks = new List<(ProgressTask, int)>();
|
|
||||||
|
|
||||||
var names = new[]
|
|
||||||
{
|
|
||||||
"Retriculating algorithms", "Colliding splines", "Solving quarks", "Folding data structures",
|
|
||||||
"Rerouting capacitators "
|
|
||||||
};
|
|
||||||
|
|
||||||
for (var i = 0; i < 5; i++)
|
|
||||||
{
|
|
||||||
tasks.Add((progress.AddTask(names[i]), random.Next(2, 10)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return tasks;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class RuleSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (82, 10);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.Write(new Rule());
|
|
||||||
console.WriteLine();
|
|
||||||
console.Write(new Rule("[blue]Left aligned[/]").LeftJustified().RuleStyle("red"));
|
|
||||||
console.WriteLine();
|
|
||||||
console.Write(new Rule("[green]Centered[/]").Centered().RuleStyle("green"));
|
|
||||||
console.WriteLine();
|
|
||||||
console.Write(new Rule("[red]Right aligned[/]").RightJustified().RuleStyle("blue"));
|
|
||||||
console.WriteLine();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
using DocExampleGenerator;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class SelectionSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 14);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.DisplayThenType(AskFruit, "↓↓↓¦¦¦¦ ");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void AskFruit(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
// Ask for the user's favorite fruit
|
|
||||||
var fruit = console.Prompt(
|
|
||||||
new SelectionPrompt<string>()
|
|
||||||
.Title("What's your [green]favorite fruit[/]?")
|
|
||||||
.PageSize(10)
|
|
||||||
.MoreChoicesText("[grey](Move up and down to reveal more fruits)[/]")
|
|
||||||
.AddChoices(new [] {"Apple", "Apricot", "Avocado", "Banana", "Blackcurrant", "Blueberry", "Cherry", "Cloudberry", "Cocunut"}));
|
|
||||||
|
|
||||||
// Echo the fruit back to the terminal
|
|
||||||
console.WriteLine($"I agree. {fruit} is tasty!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
using System.Threading;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class StatusSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 10);
|
|
||||||
|
|
||||||
private static void WriteLogMessage(string message)
|
|
||||||
{
|
|
||||||
AnsiConsole.MarkupLine($"[grey]LOG:[/] {message}[grey]...[/]");
|
|
||||||
}
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.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[/]"); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,46 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class TableSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (100, 30);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
var simple = new Table()
|
|
||||||
.Border(TableBorder.Square)
|
|
||||||
.BorderColor(Color.Red)
|
|
||||||
.AddColumn(new TableColumn("[u]CDE[/]").Footer("EDC").Centered())
|
|
||||||
.AddColumn(new TableColumn("[u]FED[/]").Footer("DEF"))
|
|
||||||
.AddColumn(new TableColumn("[u]IHG[/]").Footer("GHI"))
|
|
||||||
.AddRow("Hello", "[red]World![/]", "")
|
|
||||||
.AddRow("[blue]Bonjour[/]", "[white]le[/]", "[red]monde![/]")
|
|
||||||
.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
|
|
||||||
|
|
||||||
var second = new Table()
|
|
||||||
.Border(TableBorder.Rounded)
|
|
||||||
.BorderColor(Color.Green)
|
|
||||||
.AddColumn(new TableColumn("[u]Foo[/]"))
|
|
||||||
.AddColumn(new TableColumn("[u]Bar[/]"))
|
|
||||||
.AddColumn(new TableColumn("[u]Baz[/]"))
|
|
||||||
.AddRow("Hello", "[red]World![/]", "")
|
|
||||||
.AddRow(simple, new Text("Whaaat"), new Text("Lolz"))
|
|
||||||
.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
|
|
||||||
|
|
||||||
var table = new Table()
|
|
||||||
.Centered()
|
|
||||||
.Border(TableBorder.DoubleEdge)
|
|
||||||
.Title("TABLE [yellow]TITLE[/]")
|
|
||||||
.Caption("TABLE [yellow]CAPTION[/]")
|
|
||||||
.AddColumn(new TableColumn(new Panel("[u]ABC[/]").BorderColor(Color.Red)).Footer("[u]FOOTER 1[/]"))
|
|
||||||
.AddColumn(new TableColumn(new Panel("[u]DEF[/]").BorderColor(Color.Green)).Footer("[u]FOOTER 2[/]"))
|
|
||||||
.AddColumn(new TableColumn(new Panel("[u]GHI[/]").BorderColor(Color.Blue)).Footer("[u]FOOTER 3[/]"))
|
|
||||||
.AddRow(new Text("Hello").Centered(), new Markup("[red]World![/]"), Text.Empty)
|
|
||||||
.AddRow(second, new Text("Whaaat"), new Text("Lol"))
|
|
||||||
.AddRow(new Markup("[blue]Hej[/]").Centered(), new Markup("[yellow]Världen![/]"), Text.Empty);
|
|
||||||
|
|
||||||
console.Write(table);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
using DocExampleGenerator;
|
|
||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class TextPathSample : BaseSample
|
|
||||||
{
|
|
||||||
public override (int Cols, int Rows) ConsoleSize => (40, 23);
|
|
||||||
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
console.Write(
|
|
||||||
new Panel(
|
|
||||||
new Padder(new TextPath("C:/This/Is/A/Super/Long/Path/That/Will/Be/Truncated.txt"), new Padding(0,1)))
|
|
||||||
.BorderStyle(new Style(foreground: Color.Grey))
|
|
||||||
.Header("Windows path"));
|
|
||||||
|
|
||||||
console.Write(
|
|
||||||
new Panel(
|
|
||||||
new Padder(new TextPath("/This/Is/A/Super/Long/Path/That/Will/Be/Truncated.txt"), new Padding(0,1)))
|
|
||||||
.BorderStyle(new Style(foreground: Color.Grey))
|
|
||||||
.Header("Unix path"));
|
|
||||||
|
|
||||||
console.Write(
|
|
||||||
new Panel(
|
|
||||||
new Padder(new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt")
|
|
||||||
.RootColor(Color.Green)
|
|
||||||
.SeparatorColor(Color.Red)
|
|
||||||
.StemColor(Color.Yellow)
|
|
||||||
.LeafColor(Color.Blue), new Padding(0,1)))
|
|
||||||
.BorderStyle(new Style(foreground: Color.Grey))
|
|
||||||
.Header("Styling"));
|
|
||||||
|
|
||||||
console.Write(
|
|
||||||
new Panel(
|
|
||||||
new Padder(new Rows(
|
|
||||||
new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt").LeftJustified(),
|
|
||||||
new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt").Centered(),
|
|
||||||
new TextPath("/This/Is/A/Long/Path/That/Will/Be/Truncated.txt").RightJustified()), new Padding(0,1)))
|
|
||||||
.BorderStyle(new Style(foreground: Color.Grey))
|
|
||||||
.Header("Alignment"));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
using Spectre.Console;
|
|
||||||
|
|
||||||
namespace Generator.Commands.Samples
|
|
||||||
{
|
|
||||||
internal class TreeSample : BaseSample
|
|
||||||
{
|
|
||||||
public override void Run(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
// Create the tree
|
|
||||||
var tree = new Tree("Root")
|
|
||||||
.Style(Style.Parse("red"))
|
|
||||||
.Guide(TreeGuide.Line);
|
|
||||||
|
|
||||||
// Add some nodes
|
|
||||||
var foo = tree.AddNode("[yellow]Nest objects like tables[/]");
|
|
||||||
var table = foo.AddNode(new Table()
|
|
||||||
.RoundedBorder()
|
|
||||||
.AddColumn("First")
|
|
||||||
.AddColumn("Second")
|
|
||||||
.AddRow("1", "2")
|
|
||||||
.AddRow("3", "4")
|
|
||||||
.AddRow("5", "6"));
|
|
||||||
|
|
||||||
table.AddNode("[blue]with[/]");
|
|
||||||
table.AddNode("[blue]multiple[/]");
|
|
||||||
table.AddNode("[blue]children too[/]");
|
|
||||||
|
|
||||||
var bar = tree.AddNode("Any IRenderable can be nested, such as [yellow]calendars[/]");
|
|
||||||
bar.AddNode(new Calendar(2020, 12)
|
|
||||||
.Border(TableBorder.Rounded)
|
|
||||||
.BorderStyle(new Style(Color.Green3_1))
|
|
||||||
.AddCalendarEvent(2020, 12, 12)
|
|
||||||
.HideHeader());
|
|
||||||
|
|
||||||
console.Write(tree);
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using Generator.Models;
|
|
||||||
using Scriban;
|
|
||||||
using Spectre.Console.Cli;
|
|
||||||
using Spectre.IO;
|
|
||||||
|
|
||||||
namespace Generator.Commands
|
|
||||||
{
|
|
||||||
public sealed class ColorGeneratorCommand : Command<ColorGeneratorCommand.Settings>
|
|
||||||
{
|
|
||||||
private readonly IFileSystem _fileSystem;
|
|
||||||
|
|
||||||
public ColorGeneratorCommand()
|
|
||||||
{
|
|
||||||
_fileSystem = new FileSystem();
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class Settings : GeneratorSettings
|
|
||||||
{
|
|
||||||
[CommandOption("-i|--input <PATH>")]
|
|
||||||
public string Input { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Execute(CommandContext context, Settings settings, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var templates = new FilePath[]
|
|
||||||
{
|
|
||||||
"Templates/ColorPalette.Generated.template",
|
|
||||||
"Templates/Color.Generated.template",
|
|
||||||
"Templates/ColorTable.Generated.template"
|
|
||||||
};
|
|
||||||
|
|
||||||
// Read the color model.
|
|
||||||
var model = Color.Parse(File.ReadAllText("Data/colors.json"));
|
|
||||||
|
|
||||||
var output = new DirectoryPath(settings.Output);
|
|
||||||
if (!_fileSystem.Directory.Exists(settings.Output))
|
|
||||||
{
|
|
||||||
_fileSystem.Directory.Create(settings.Output);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var templatePath in templates)
|
|
||||||
{
|
|
||||||
// Parse the Scriban template.
|
|
||||||
var template = Template.Parse(File.ReadAllText(templatePath.FullPath));
|
|
||||||
|
|
||||||
// Render the template with the model.
|
|
||||||
var result = template.Render(new { Colors = model });
|
|
||||||
|
|
||||||
// Write output to file
|
|
||||||
var file = output.CombineWithFilePath(templatePath.GetFilename().ChangeExtension(".cs"));
|
|
||||||
File.WriteAllText(file.FullPath, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using AngleSharp.Html.Parser;
|
|
||||||
using Generator.Models;
|
|
||||||
using Scriban;
|
|
||||||
using Scriban.Runtime;
|
|
||||||
using Spectre.Console.Cli;
|
|
||||||
using Spectre.IO;
|
|
||||||
using Path = Spectre.IO.Path;
|
|
||||||
using SpectreEnvironment = Spectre.IO.Environment;
|
|
||||||
|
|
||||||
namespace Generator.Commands
|
|
||||||
{
|
|
||||||
public sealed class EmojiGeneratorCommand : AsyncCommand<EmojiGeneratorCommand.Settings>
|
|
||||||
{
|
|
||||||
private readonly IFileSystem _fileSystem;
|
|
||||||
private readonly IEnvironment _environment;
|
|
||||||
private readonly IHtmlParser _parser;
|
|
||||||
|
|
||||||
private readonly Dictionary<string, string> _templates = new Dictionary<string, string>
|
|
||||||
{
|
|
||||||
{ "Templates/Emoji.Generated.template", "Emoji.Generated.cs" },
|
|
||||||
{ "Templates/Emoji.Json.template", "emojis.json" }, // For documentation
|
|
||||||
};
|
|
||||||
|
|
||||||
public sealed class Settings : GeneratorSettings
|
|
||||||
{
|
|
||||||
[CommandOption("-i|--input <PATH>")]
|
|
||||||
public string Input { get; set; }
|
|
||||||
}
|
|
||||||
|
|
||||||
public EmojiGeneratorCommand()
|
|
||||||
{
|
|
||||||
_fileSystem = new FileSystem();
|
|
||||||
_environment = new SpectreEnvironment();
|
|
||||||
_parser = new HtmlParser();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override async Task<int> ExecuteAsync(CommandContext context, Settings settings, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var output = new DirectoryPath(settings.Output);
|
|
||||||
if (!_fileSystem.Directory.Exists(settings.Output))
|
|
||||||
{
|
|
||||||
_fileSystem.Directory.Create(settings.Output);
|
|
||||||
}
|
|
||||||
|
|
||||||
var stream = await FetchEmojis(settings);
|
|
||||||
var document = await _parser.ParseDocumentAsync(stream);
|
|
||||||
var emojis = Emoji.Parse(document).OrderBy(x => x.Name)
|
|
||||||
.Where(emoji => !emoji.HasCombinators)
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
// Render all templates
|
|
||||||
foreach (var (templateFilename, outputFilename) in _templates)
|
|
||||||
{
|
|
||||||
var result = await RenderTemplate(new FilePath(templateFilename), emojis);
|
|
||||||
|
|
||||||
var outputPath = output.CombineWithFilePath(outputFilename);
|
|
||||||
await File.WriteAllTextAsync(outputPath.FullPath, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<Stream> FetchEmojis(Settings settings)
|
|
||||||
{
|
|
||||||
var input = string.IsNullOrEmpty(settings.Input)
|
|
||||||
? _environment.WorkingDirectory
|
|
||||||
: new DirectoryPath(settings.Input);
|
|
||||||
|
|
||||||
var file = _fileSystem.File.Retrieve(input.CombineWithFilePath("emoji-list.html"));
|
|
||||||
if (!file.Exists)
|
|
||||||
{
|
|
||||||
using var http = new HttpClient();
|
|
||||||
using var httpStream = await http.GetStreamAsync("http://www.unicode.org/emoji/charts/emoji-list.html");
|
|
||||||
using var outStream = file.OpenWrite();
|
|
||||||
|
|
||||||
await httpStream.CopyToAsync(outStream);
|
|
||||||
}
|
|
||||||
|
|
||||||
return file.OpenRead();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static async Task<string> RenderTemplate(Path path, IReadOnlyCollection<Emoji> emojis)
|
|
||||||
{
|
|
||||||
var text = await File.ReadAllTextAsync(path.FullPath);
|
|
||||||
|
|
||||||
var template = Template.Parse(text);
|
|
||||||
var templateContext = new TemplateContext
|
|
||||||
{
|
|
||||||
// Because of the insane amount of Emojis,
|
|
||||||
// we need to get rid of some secure defaults :P
|
|
||||||
LoopLimit = int.MaxValue,
|
|
||||||
};
|
|
||||||
|
|
||||||
var scriptObject = new ScriptObject();
|
|
||||||
scriptObject.Import(new { Emojis = emojis });
|
|
||||||
templateContext.PushGlobal(scriptObject);
|
|
||||||
|
|
||||||
return await template.RenderAsync(templateContext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
using Spectre.Console.Cli;
|
|
||||||
|
|
||||||
namespace Generator.Commands
|
|
||||||
{
|
|
||||||
public class GeneratorSettings : CommandSettings
|
|
||||||
{
|
|
||||||
[CommandArgument(0, "<OUTPUT>")]
|
|
||||||
public string Output { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,101 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using System.Threading;
|
|
||||||
using Generator.Commands.Samples;
|
|
||||||
using Spectre.Console;
|
|
||||||
using Spectre.Console.Cli;
|
|
||||||
|
|
||||||
namespace Generator.Commands
|
|
||||||
{
|
|
||||||
internal class SampleCommand : Command<SampleCommand.Settings>
|
|
||||||
{
|
|
||||||
public class Settings : CommandSettings
|
|
||||||
{
|
|
||||||
public Settings(string outputPath, string sample, bool list)
|
|
||||||
{
|
|
||||||
Sample = sample;
|
|
||||||
OutputPath = outputPath ?? Environment.CurrentDirectory;
|
|
||||||
List = list;
|
|
||||||
}
|
|
||||||
|
|
||||||
[CommandArgument(0, "[sample]")]
|
|
||||||
public string Sample { get; }
|
|
||||||
|
|
||||||
[CommandOption("-o|--output")]
|
|
||||||
public string OutputPath { get; }
|
|
||||||
|
|
||||||
[CommandOption("-l|--list")]
|
|
||||||
public bool List { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
private readonly IAnsiConsole _console;
|
|
||||||
|
|
||||||
public SampleCommand(IAnsiConsole console)
|
|
||||||
{
|
|
||||||
_console = new AsciiCastConsole(console);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Execute([NotNull] CommandContext context, [NotNull] Settings settings, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
var samples = typeof(BaseSample).Assembly
|
|
||||||
.GetTypes()
|
|
||||||
.Where(i => i.IsClass && i.IsAbstract == false && i.IsSubclassOf(typeof(BaseSample)))
|
|
||||||
.Select(Activator.CreateInstance)
|
|
||||||
.Cast<BaseSample>();
|
|
||||||
|
|
||||||
var selectedSample = settings.Sample;
|
|
||||||
if (settings.List)
|
|
||||||
{
|
|
||||||
selectedSample = AnsiConsole.Prompt(
|
|
||||||
new SelectionPrompt<string>()
|
|
||||||
.Title("Select an example to record")
|
|
||||||
.PageSize(25)
|
|
||||||
.AddChoices(samples.Select(x => x.Name())));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!string.IsNullOrWhiteSpace(selectedSample))
|
|
||||||
{
|
|
||||||
var desiredSample = samples.FirstOrDefault(i => i.Name().Equals(selectedSample, StringComparison.OrdinalIgnoreCase));
|
|
||||||
if (desiredSample == null)
|
|
||||||
{
|
|
||||||
_console.MarkupLine($"[red]Error:[/] could not find sample [blue]{selectedSample}[/]");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
samples = new List<BaseSample> { desiredSample };
|
|
||||||
}
|
|
||||||
|
|
||||||
// from here on out everything we write will be recorded.
|
|
||||||
var recorder = _console.WrapWithAsciiCastRecorder();
|
|
||||||
|
|
||||||
foreach (var sample in samples)
|
|
||||||
{
|
|
||||||
var sampleName = sample.Name();
|
|
||||||
|
|
||||||
var originalWidth = _console.Profile.Width;
|
|
||||||
var originalHeight = _console.Profile.Height;
|
|
||||||
|
|
||||||
_console.Profile.Encoding = Encoding.UTF8;
|
|
||||||
_console.Profile.Width = sample.ConsoleSize.Cols;
|
|
||||||
_console.Profile.Height = sample.ConsoleSize.Rows;
|
|
||||||
|
|
||||||
foreach (var (capabilityName, action) in sample.GetCapabilities())
|
|
||||||
{
|
|
||||||
action(_console.Profile.Capabilities);
|
|
||||||
sample.Run(_console);
|
|
||||||
var json = recorder.GetCastJson($"{sampleName} ({capabilityName})", sample.ConsoleSize.Cols + 2, sample.ConsoleSize.Rows);
|
|
||||||
File.WriteAllText(Path.Combine(settings.OutputPath, $"{sampleName}-{capabilityName}.cast"), json);
|
|
||||||
}
|
|
||||||
|
|
||||||
_console.Profile.Width = originalWidth;
|
|
||||||
_console.Profile.Height = originalHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using Generator.Models;
|
|
||||||
using Scriban;
|
|
||||||
using Spectre.Console.Cli;
|
|
||||||
using Spectre.IO;
|
|
||||||
|
|
||||||
namespace Generator.Commands
|
|
||||||
{
|
|
||||||
public sealed class SpinnerGeneratorCommand : Command<GeneratorSettings>
|
|
||||||
{
|
|
||||||
private readonly IFileSystem _fileSystem;
|
|
||||||
|
|
||||||
public SpinnerGeneratorCommand()
|
|
||||||
{
|
|
||||||
_fileSystem = new FileSystem();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override int Execute(CommandContext context, GeneratorSettings settings, CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
// Read the spinner model.
|
|
||||||
var spinners = new List<Spinner>();
|
|
||||||
spinners.AddRange(Spinner.Parse(File.ReadAllText("Data/spinners_default.json")));
|
|
||||||
spinners.AddRange(Spinner.Parse(File.ReadAllText("Data/spinners_sindresorhus.json")));
|
|
||||||
|
|
||||||
var output = new DirectoryPath(settings.Output);
|
|
||||||
if (!_fileSystem.Directory.Exists(settings.Output))
|
|
||||||
{
|
|
||||||
_fileSystem.Directory.Create(settings.Output);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Parse the Scriban template.
|
|
||||||
var templatePath = new FilePath("Templates/Spinner.Generated.template");
|
|
||||||
var template = Template.Parse(File.ReadAllText(templatePath.FullPath));
|
|
||||||
|
|
||||||
// Render the template with the model.
|
|
||||||
var result = template.Render(new { Spinners = spinners });
|
|
||||||
|
|
||||||
// Write output to file
|
|
||||||
var file = output.CombineWithFilePath(templatePath.GetFilename().ChangeExtension(".cs"));
|
|
||||||
File.WriteAllText(file.FullPath, result);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,59 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<OutputType>Exe</OutputType>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<LangVersion>default</LangVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Compile Remove="out\**" />
|
|
||||||
<EmbeddedResource Remove="out\**" />
|
|
||||||
<None Remove="out\**" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<None Update="Data\colors.json">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Data\spinners_default.json">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Data\spinners_sindresorhus.json">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Templates\ColorTable.Generated.template">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Templates\Color.Generated.template">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Templates\ColorPalette.Generated.template">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Templates\Spinner.Generated.template">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Templates\Emoji.Json.template">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
<None Update="Templates\Emoji.Generated.template">
|
|
||||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
|
||||||
</None>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="AngleSharp" Version="1.3.0" />
|
|
||||||
<PackageReference Include="Humanizer.Core" Version="2.14.1" />
|
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
|
||||||
<PackageReference Include="Scriban" Version="6.4.0" />
|
|
||||||
<PackageReference Include="Spectre.IO" Version="0.21.0" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\src\Spectre.Console.Cli\Spectre.Console.Cli.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\src\Extensions\Spectre.Console.ImageSharp\Spectre.Console.ImageSharp.csproj" />
|
|
||||||
<ProjectReference Include="..\..\..\src\Extensions\Spectre.Console.Json\Spectre.Console.Json.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
@@ -1,79 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Generator.Models
|
|
||||||
{
|
|
||||||
public sealed class Color
|
|
||||||
{
|
|
||||||
public int Number { get; set; }
|
|
||||||
public string Hex { get; set; }
|
|
||||||
public string Name { get; set; }
|
|
||||||
public List<string> Aliases { get; set; } = new List<string>();
|
|
||||||
public Rgb Rgb { get; set; }
|
|
||||||
|
|
||||||
public int R => Rgb.R;
|
|
||||||
public int G => Rgb.G;
|
|
||||||
public int B => Rgb.B;
|
|
||||||
|
|
||||||
public static IEnumerable<Color> Parse(string json)
|
|
||||||
{
|
|
||||||
var source = JsonConvert.DeserializeObject<List<Color>>(json);
|
|
||||||
|
|
||||||
var check = new Dictionary<string, Color>(StringComparer.OrdinalIgnoreCase);
|
|
||||||
|
|
||||||
var colorAliases = source
|
|
||||||
.SelectMany(c => c.Aliases.Select(a => new { Alias = a, Color = c }))
|
|
||||||
.Select(a => new Color()
|
|
||||||
{
|
|
||||||
Hex = a.Color.Hex,
|
|
||||||
Name = a.Alias,
|
|
||||||
Number = a.Color.Number,
|
|
||||||
Rgb = a.Color.Rgb
|
|
||||||
})
|
|
||||||
.ToList();
|
|
||||||
|
|
||||||
var colors = source
|
|
||||||
.Union(colorAliases)
|
|
||||||
.OrderBy(c => c.Number);
|
|
||||||
|
|
||||||
foreach (var color in colors)
|
|
||||||
{
|
|
||||||
if (!check.ContainsKey(color.Name))
|
|
||||||
{
|
|
||||||
check.Add(color.Name, color);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var newName = (string)null;
|
|
||||||
for (int i = 1; i < 100; i++)
|
|
||||||
{
|
|
||||||
if (!check.ContainsKey($"{color.Name}_{i}"))
|
|
||||||
{
|
|
||||||
newName = $"{color.Name}_{i}";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (newName == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException("Impossible!");
|
|
||||||
}
|
|
||||||
|
|
||||||
check.Add(newName, color);
|
|
||||||
color.Name = newName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return colors;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public sealed class Rgb
|
|
||||||
{
|
|
||||||
public int R { get; set; }
|
|
||||||
public int G { get; set; }
|
|
||||||
public int B { get; set; }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Generator.Models
|
|
||||||
{
|
|
||||||
public sealed class ColorModel
|
|
||||||
{
|
|
||||||
public List<Color> Colors { get; set; }
|
|
||||||
|
|
||||||
public ColorModel(IEnumerable<Color> colors)
|
|
||||||
{
|
|
||||||
Colors = new List<Color>(colors);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,95 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
|
||||||
using AngleSharp.Dom;
|
|
||||||
using AngleSharp.Html.Dom;
|
|
||||||
using Humanizer;
|
|
||||||
|
|
||||||
namespace Generator.Models
|
|
||||||
{
|
|
||||||
public class Emoji
|
|
||||||
{
|
|
||||||
private static readonly string[] _headers = { "count", "code", "sample", "name" };
|
|
||||||
|
|
||||||
private Emoji(string identifier, string name, string code, string description)
|
|
||||||
{
|
|
||||||
Identifier = identifier;
|
|
||||||
Name = name;
|
|
||||||
Code = code;
|
|
||||||
Description = description;
|
|
||||||
NormalizedCode = Code.Replace("\\U", "U+");
|
|
||||||
HasCombinators = Code.Split(new[] { "\\U" }, System.StringSplitOptions.RemoveEmptyEntries).Length > 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
public string Identifier { get; set; }
|
|
||||||
public string Code { get; }
|
|
||||||
public string NormalizedCode { get; }
|
|
||||||
public string Name { get; }
|
|
||||||
public string Description { get; set; }
|
|
||||||
public bool HasCombinators { get; set; }
|
|
||||||
|
|
||||||
public static IEnumerable<Emoji> Parse(IHtmlDocument document)
|
|
||||||
{
|
|
||||||
var rows = document
|
|
||||||
.GetNodes<IHtmlTableRowElement>(predicate: row =>
|
|
||||||
row.Cells.Length >= _headers.Length && // Filter out rows that don't have enough cells.
|
|
||||||
row.Cells.All(x => x.LocalName == TagNames.Td)); // We're only interested in td cells, not th.
|
|
||||||
|
|
||||||
foreach (var row in rows)
|
|
||||||
{
|
|
||||||
var dictionary = _headers
|
|
||||||
.Zip(row.Cells, (header, cell) => (Header: header, cell.TextContent.Trim()))
|
|
||||||
.ToDictionary(x => x.Item1, x => x.Item2);
|
|
||||||
|
|
||||||
var code = TransformCode(dictionary["code"]);
|
|
||||||
var identifier = TransformName(dictionary["name"])
|
|
||||||
.Replace("-", "_")
|
|
||||||
.Replace("(", string.Empty)
|
|
||||||
.Replace(")", string.Empty);
|
|
||||||
|
|
||||||
var description = dictionary["name"].Humanize();
|
|
||||||
|
|
||||||
var name = identifier
|
|
||||||
.Replace("1st", "first")
|
|
||||||
.Replace("2nd", "second")
|
|
||||||
.Replace("3rd", "third")
|
|
||||||
.Pascalize();
|
|
||||||
|
|
||||||
yield return new Emoji(identifier, name, code, description);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string TransformName(string name)
|
|
||||||
{
|
|
||||||
return name.Replace(":", string.Empty)
|
|
||||||
.Replace(",", string.Empty)
|
|
||||||
.Replace(".", string.Empty)
|
|
||||||
.Replace("\u201c", string.Empty)
|
|
||||||
.Replace("\u201d", string.Empty)
|
|
||||||
.Replace("\u229b", string.Empty)
|
|
||||||
.Replace(' ', '_')
|
|
||||||
.Replace("’s", "s")
|
|
||||||
.Replace("’", "_")
|
|
||||||
.Replace("&", "and")
|
|
||||||
.Replace("#", "hash")
|
|
||||||
.Replace("*", "star")
|
|
||||||
.Replace("!", string.Empty)
|
|
||||||
.Trim()
|
|
||||||
.ToLowerInvariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static string TransformCode(string code)
|
|
||||||
{
|
|
||||||
var builder = new StringBuilder();
|
|
||||||
|
|
||||||
foreach (var part in code.Split(' '))
|
|
||||||
{
|
|
||||||
builder.Append(part.Length == 6
|
|
||||||
? part.Replace("+", "0000")
|
|
||||||
: part.Replace("+", "000"));
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder.ToString().Replace("U", "\\U");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace Generator.Models
|
|
||||||
{
|
|
||||||
public sealed class Palette
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using Humanizer;
|
|
||||||
using Newtonsoft.Json;
|
|
||||||
|
|
||||||
namespace Generator.Models
|
|
||||||
{
|
|
||||||
public sealed class Spinner
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
|
||||||
public string NormalizedName { get; set; }
|
|
||||||
public int Interval { get; set; }
|
|
||||||
public bool Unicode { get; set; }
|
|
||||||
public List<string> Frames { get; set; }
|
|
||||||
|
|
||||||
public static IEnumerable<Spinner> Parse(string json)
|
|
||||||
{
|
|
||||||
var data = JsonConvert.DeserializeObject<Dictionary<string, Spinner>>(json);
|
|
||||||
foreach (var item in data)
|
|
||||||
{
|
|
||||||
item.Value.Name = item.Key;
|
|
||||||
item.Value.NormalizedName = item.Value.Name.Pascalize();
|
|
||||||
|
|
||||||
var frames = item.Value.Frames;
|
|
||||||
item.Value.Frames = frames.Select(f => f.Replace("\\", "\\\\")).ToList();
|
|
||||||
}
|
|
||||||
|
|
||||||
return data.Values;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
using Generator.Commands;
|
|
||||||
using Spectre.Console.Cli;
|
|
||||||
|
|
||||||
namespace Generator
|
|
||||||
{
|
|
||||||
public static class Program
|
|
||||||
{
|
|
||||||
public static int Main(string[] args)
|
|
||||||
{
|
|
||||||
var app = new CommandApp();
|
|
||||||
app.Configure(config =>
|
|
||||||
{
|
|
||||||
config.AddCommand<ColorGeneratorCommand>("colors");
|
|
||||||
config.AddCommand<EmojiGeneratorCommand>("emoji");
|
|
||||||
config.AddCommand<SpinnerGeneratorCommand>("spinners");
|
|
||||||
config.AddCommand<SampleCommand>("samples");
|
|
||||||
});
|
|
||||||
|
|
||||||
return app.Run(args);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,156 @@
|
|||||||
root = false
|
root = false
|
||||||
|
|
||||||
[*.cs]
|
[*.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
|
||||||
|
|
||||||
|
# RS0037: PublicAPI.txt is missing '#nullable enable'
|
||||||
|
dotnet_diagnostic.RS0037.severity = none
|
||||||
|
|
||||||
# IDE0055: Fix formatting
|
# IDE0055: Fix formatting
|
||||||
dotnet_diagnostic.IDE0055.severity = warning
|
dotnet_diagnostic.IDE0055.severity = warning
|
||||||
|
|
||||||
|
|||||||
@@ -50,17 +50,10 @@
|
|||||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)/stylecop.json" Link="Properties/stylecop.json"/>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<!-- Allow folks to build with minimal dependencies (though they will need to provide their own Version data) -->
|
<!-- Allow folks to build with minimal dependencies (though they will need to provide their own Version data) -->
|
||||||
<ItemGroup Label="Build Tools Package References" Condition="'$(UseBuildTimeTools)' != 'false'">
|
<ItemGroup Label="Build Tools Package References" Condition="'$(UseBuildTimeTools)' != 'false'">
|
||||||
<PackageReference Include="MinVer" PrivateAssets="All" />
|
<PackageReference Include="MinVer" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" />
|
||||||
<PackageReference Include="StyleCop.Analyzers">
|
|
||||||
<PrivateAssets>All</PrivateAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="Roslynator.Analyzers">
|
<PackageReference Include="Roslynator.Analyzers">
|
||||||
<PrivateAssets>All</PrivateAssets>
|
<PrivateAssets>All</PrivateAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
<Project>
|
|
||||||
<Target Name="Versioning" BeforeTargets="MinVer">
|
|
||||||
<PropertyGroup Label="Build">
|
|
||||||
<MinVerDefaultPreReleaseIdentifiers>preview.0</MinVerDefaultPreReleaseIdentifiers>
|
|
||||||
<MinVerVerbosity>normal</MinVerVerbosity>
|
|
||||||
</PropertyGroup>
|
|
||||||
</Target>
|
|
||||||
</Project>
|
|
||||||
@@ -3,18 +3,22 @@
|
|||||||
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageVersion Include="AngleSharp" Version="1.3.0" />
|
||||||
|
<PackageVersion Include="Humanizer.Core" Version="2.14.1" />
|
||||||
<PackageVersion Include="IsExternalInit" Version="1.0.3" />
|
<PackageVersion Include="IsExternalInit" Version="1.0.3" />
|
||||||
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.10" />
|
<PackageVersion Include="Microsoft.Extensions.DependencyInjection" Version="9.0.10" />
|
||||||
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
|
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="18.0.0" />
|
||||||
<PackageVersion Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="8.0.0" />
|
<PackageVersion Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="8.0.0" />
|
||||||
<PackageVersion Include="MinVer" PrivateAssets="All" Version="6.0.0" />
|
<PackageVersion Include="MinVer" PrivateAssets="All" Version="6.0.0" />
|
||||||
<PackageVersion Include="OpenCli.Sources" Version="0.5.0" />
|
<PackageVersion Include="Newtonsoft.Json" Version="13.0.4" />
|
||||||
<PackageVersion Include="PolySharp" Version="1.15.0" />
|
<PackageVersion Include="PolySharp" Version="1.15.0" />
|
||||||
<PackageVersion Include="Roslynator.Analyzers" PrivateAssets="All" Version="4.14.1" />
|
<PackageVersion Include="Roslynator.Analyzers" PrivateAssets="All" Version="4.14.1" />
|
||||||
|
<PackageVersion Include="Scriban" Version="6.4.0" />
|
||||||
<PackageVersion Include="Shouldly" Version="4.3.0" />
|
<PackageVersion Include="Shouldly" Version="4.3.0" />
|
||||||
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.11" />
|
<PackageVersion Include="SixLabors.ImageSharp" Version="3.1.11" />
|
||||||
|
<PackageVersion Include="Spectre.Console.Cli" Version="0.53.0" />
|
||||||
|
<PackageVersion Include="Spectre.IO" Version="0.21.0" />
|
||||||
<PackageVersion Include="Spectre.Verify.Extensions" Version="28.16.0" />
|
<PackageVersion Include="Spectre.Verify.Extensions" Version="28.16.0" />
|
||||||
<PackageVersion Include="StyleCop.Analyzers" PrivateAssets="All" Version="1.2.0-beta.556" />
|
|
||||||
<PackageVersion Include="System.Memory" Version="4.6.3" />
|
<PackageVersion Include="System.Memory" Version="4.6.3" />
|
||||||
<PackageVersion Include="TunnelVisionLabs.ReferenceAssemblyAnnotator" Version="1.0.0-alpha.160" />
|
<PackageVersion Include="TunnelVisionLabs.ReferenceAssemblyAnnotator" Version="1.0.0-alpha.160" />
|
||||||
<PackageVersion Include="Verify.Xunit" Version="31.0.5" />
|
<PackageVersion Include="Verify.Xunit" Version="31.0.5" />
|
||||||
|
|||||||
@@ -11,4 +11,4 @@ public interface IJsonParser
|
|||||||
/// <param name="json">The JSON to parse.</param>
|
/// <param name="json">The JSON to parse.</param>
|
||||||
/// <returns>An <see cref="JsonSyntax"/> instance.</returns>
|
/// <returns>An <see cref="JsonSyntax"/> instance.</returns>
|
||||||
JsonSyntax Parse(string json);
|
JsonSyntax Parse(string json);
|
||||||
}
|
}
|
||||||
@@ -143,4 +143,4 @@ internal sealed class JsonParser : IJsonParser
|
|||||||
var value = ParseElement(reader);
|
var value = ParseElement(reader);
|
||||||
return new JsonMember(name.Lexeme, value);
|
return new JsonMember(name.Lexeme, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -103,4 +103,4 @@ public sealed class JsonText : JustInTimeRenderable
|
|||||||
_syntax.Accept(JsonBuilder.Shared, context);
|
_syntax.Accept(JsonBuilder.Shared, context);
|
||||||
return context.Paragraph;
|
return context.Paragraph;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -310,4 +310,4 @@ public static class JsonTextExtensions
|
|||||||
text.NullStyle = new Style(color);
|
text.NullStyle = new Style(color);
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,4 +11,4 @@ internal sealed class JsonTextStyles
|
|||||||
public Style NumberStyle { get; set; } = null!;
|
public Style NumberStyle { get; set; } = null!;
|
||||||
public Style BooleanStyle { get; set; } = null!;
|
public Style BooleanStyle { get; set; } = null!;
|
||||||
public Style NullStyle { get; set; } = null!;
|
public Style NullStyle { get; set; } = null!;
|
||||||
}
|
}
|
||||||
@@ -10,4 +10,4 @@ internal sealed class JsonToken
|
|||||||
Type = type;
|
Type = type;
|
||||||
Lexeme = lexeme ?? throw new ArgumentNullException(nameof(lexeme));
|
Lexeme = lexeme ?? throw new ArgumentNullException(nameof(lexeme));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -52,4 +52,4 @@ internal sealed class JsonTokenReader
|
|||||||
Position++;
|
Position++;
|
||||||
return _reader[Position - 1];
|
return _reader[Position - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -12,4 +12,4 @@ internal enum JsonTokenType
|
|||||||
Number,
|
Number,
|
||||||
Boolean,
|
Boolean,
|
||||||
Null,
|
Null,
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Spectre.Console.Json;
|
namespace Spectre.Console.Json;
|
||||||
|
|
||||||
internal static class JsonTokenizer
|
internal static class JsonTokenizer
|
||||||
@@ -202,4 +200,4 @@ internal static class JsonTokenizer
|
|||||||
accumulator.Append(current);
|
accumulator.Append(current);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,4 +23,4 @@ public sealed class JsonBoolean : JsonSyntax
|
|||||||
{
|
{
|
||||||
visitor.VisitBoolean(this, context);
|
visitor.VisitBoolean(this, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,4 +30,4 @@ public sealed class JsonMember : JsonSyntax
|
|||||||
{
|
{
|
||||||
visitor.VisitMember(this, context);
|
visitor.VisitMember(this, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,4 +23,4 @@ public sealed class JsonNull : JsonSyntax
|
|||||||
{
|
{
|
||||||
visitor.VisitNull(this, context);
|
visitor.VisitNull(this, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -13,4 +13,4 @@ internal sealed class JsonNumber : JsonSyntax
|
|||||||
{
|
{
|
||||||
visitor.VisitNumber(this, context);
|
visitor.VisitNumber(this, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -22,4 +22,4 @@ public sealed class JsonObject : JsonSyntax
|
|||||||
{
|
{
|
||||||
visitor.VisitObject(this, context);
|
visitor.VisitObject(this, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -23,4 +23,4 @@ public sealed class JsonString : JsonSyntax
|
|||||||
{
|
{
|
||||||
visitor.VisitString(this, context);
|
visitor.VisitString(this, context);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,4 +6,4 @@ namespace Spectre.Console.Json.Syntax;
|
|||||||
public abstract class JsonSyntax
|
public abstract class JsonSyntax
|
||||||
{
|
{
|
||||||
internal abstract void Accept<T>(JsonSyntaxVisitor<T> visitor, T context);
|
internal abstract void Accept<T>(JsonSyntaxVisitor<T> visitor, T context);
|
||||||
}
|
}
|
||||||
@@ -9,4 +9,4 @@ internal abstract class JsonSyntaxVisitor<T>
|
|||||||
public abstract void VisitString(JsonString syntax, T context);
|
public abstract void VisitString(JsonString syntax, T context);
|
||||||
public abstract void VisitBoolean(JsonBoolean syntax, T context);
|
public abstract void VisitBoolean(JsonBoolean syntax, T context);
|
||||||
public abstract void VisitNull(JsonNull syntax, T context);
|
public abstract void VisitNull(JsonNull syntax, T context);
|
||||||
}
|
}
|
||||||
32
src/Generator/Commands/AsciiCast/AnsiConsoleExtensions.cs
Normal file
32
src/Generator/Commands/AsciiCast/AnsiConsoleExtensions.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using Generator.Commands;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace DocExampleGenerator;
|
||||||
|
|
||||||
|
internal static class AnsiConsoleExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Displays something via AnsiConsole, waits a bit and then simulates typing based on the input. If the console
|
||||||
|
/// doesn't have the focus this will just type into whatever window does so watch the alt-tab.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="console"></param>
|
||||||
|
/// <param name="action">The display action.</param>
|
||||||
|
/// <param name="input">The characters to type. ↑ for an up arrow, ↓ for down arrow, ↲ for a return and ¦ for a pause.</param>
|
||||||
|
/// <param name="initialDelayMs">How long to delay before typing. This should be at least 100ms because we won't check if the prompt has displayed before simulating typing.</param>
|
||||||
|
/// <param name="keypressDelayMs">Delay between keypresses. There will be a bit of randomness between each keypress +/- 20% of this value.</param>
|
||||||
|
public static void DisplayThenType(this IAnsiConsole console, Action<IAnsiConsole> action, string input, int initialDelayMs = 500, int keypressDelayMs = 200)
|
||||||
|
{
|
||||||
|
if (console is not AsciiCastConsole asciiConsole)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Not an ASCII cast console");
|
||||||
|
}
|
||||||
|
|
||||||
|
asciiConsole.Input.PushText(input, keypressDelayMs);
|
||||||
|
|
||||||
|
Thread.Sleep(initialDelayMs);
|
||||||
|
|
||||||
|
action(console);
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/Generator/Commands/AsciiCast/AsciiCastConsole.cs
Normal file
39
src/Generator/Commands/AsciiCast/AsciiCastConsole.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using System;
|
||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Rendering;
|
||||||
|
|
||||||
|
namespace Generator.Commands;
|
||||||
|
|
||||||
|
public sealed class AsciiCastConsole : IAnsiConsole
|
||||||
|
{
|
||||||
|
private readonly IAnsiConsole _console;
|
||||||
|
private readonly AsciiCastInput _input;
|
||||||
|
|
||||||
|
public Profile Profile => _console.Profile;
|
||||||
|
|
||||||
|
public IAnsiConsoleCursor Cursor => _console.Cursor;
|
||||||
|
|
||||||
|
IAnsiConsoleInput IAnsiConsole.Input => _input;
|
||||||
|
|
||||||
|
public AsciiCastInput Input => _input;
|
||||||
|
|
||||||
|
public IExclusivityMode ExclusivityMode => _console.ExclusivityMode;
|
||||||
|
|
||||||
|
public RenderPipeline Pipeline => _console.Pipeline;
|
||||||
|
|
||||||
|
public AsciiCastConsole(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
_console = console ?? throw new ArgumentNullException(nameof(console));
|
||||||
|
_input = new AsciiCastInput();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Clear(bool home)
|
||||||
|
{
|
||||||
|
_console.Clear(home);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Write(IRenderable renderable)
|
||||||
|
{
|
||||||
|
_console.Write(renderable);
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/Generator/Commands/AsciiCast/AsciiCastExtensions.cs
Normal file
14
src/Generator/Commands/AsciiCast/AsciiCastExtensions.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands;
|
||||||
|
|
||||||
|
public static class AsciiCastExtensions
|
||||||
|
{
|
||||||
|
public static AsciiCastOut WrapWithAsciiCastRecorder(this IAnsiConsole ansiConsole)
|
||||||
|
{
|
||||||
|
AsciiCastOut castRecorder = new(ansiConsole.Profile.Out);
|
||||||
|
ansiConsole.Profile.Out = castRecorder;
|
||||||
|
|
||||||
|
return castRecorder;
|
||||||
|
}
|
||||||
|
}
|
||||||
91
src/Generator/Commands/AsciiCast/AsciiCastInput.cs
Normal file
91
src/Generator/Commands/AsciiCast/AsciiCastInput.cs
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands;
|
||||||
|
|
||||||
|
public sealed class AsciiCastInput : IAnsiConsoleInput
|
||||||
|
{
|
||||||
|
private readonly Queue<(ConsoleKeyInfo?, int)> _input;
|
||||||
|
private readonly Random _random = new Random();
|
||||||
|
|
||||||
|
public AsciiCastInput()
|
||||||
|
{
|
||||||
|
_input = new Queue<(ConsoleKeyInfo?, int)>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PushText(string input, int keypressDelayMs)
|
||||||
|
{
|
||||||
|
if (input is null)
|
||||||
|
{
|
||||||
|
throw new ArgumentNullException(nameof(input));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var character in input)
|
||||||
|
{
|
||||||
|
PushCharacter(character, keypressDelayMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PushTextWithEnter(string input, int keypressDelayMs)
|
||||||
|
{
|
||||||
|
PushText(input, keypressDelayMs);
|
||||||
|
PushKey(ConsoleKey.Enter, keypressDelayMs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PushCharacter(char input, int keypressDelayMs)
|
||||||
|
{
|
||||||
|
var delay = keypressDelayMs + _random.Next((int)(keypressDelayMs * -.2), (int)(keypressDelayMs * .2));
|
||||||
|
|
||||||
|
switch (input)
|
||||||
|
{
|
||||||
|
case '↑':
|
||||||
|
PushKey(ConsoleKey.UpArrow, keypressDelayMs);
|
||||||
|
break;
|
||||||
|
case '↓':
|
||||||
|
PushKey(ConsoleKey.DownArrow, keypressDelayMs);
|
||||||
|
break;
|
||||||
|
case '↲':
|
||||||
|
PushKey(ConsoleKey.Enter, keypressDelayMs);
|
||||||
|
break;
|
||||||
|
case '¦':
|
||||||
|
_input.Enqueue((null, delay));
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
var control = char.IsUpper(input);
|
||||||
|
_input.Enqueue((new ConsoleKeyInfo(input, (ConsoleKey)input, false, false, control), delay));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void PushKey(ConsoleKey input, int keypressDelayMs)
|
||||||
|
{
|
||||||
|
var delay = keypressDelayMs + _random.Next((int)(keypressDelayMs * -.2), (int)(keypressDelayMs * .2));
|
||||||
|
_input.Enqueue((new ConsoleKeyInfo((char)input, input, false, false, false), delay));
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool IsKeyAvailable()
|
||||||
|
{
|
||||||
|
return _input.Count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConsoleKeyInfo? ReadKey(bool intercept)
|
||||||
|
{
|
||||||
|
if (_input.Count == 0)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("No input available.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = _input.Dequeue();
|
||||||
|
|
||||||
|
Thread.Sleep(result.Item2);
|
||||||
|
return result.Item1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task<ConsoleKeyInfo?> ReadKeyAsync(bool intercept, CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
return Task.FromResult(ReadKey(intercept));
|
||||||
|
}
|
||||||
|
}
|
||||||
94
src/Generator/Commands/AsciiCast/AsciiCastOut.cs
Normal file
94
src/Generator/Commands/AsciiCast/AsciiCastOut.cs
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
using System;
|
||||||
|
using System.Globalization;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
using System.Text.Json;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands;
|
||||||
|
|
||||||
|
public class AsciiCastOut : IAnsiConsoleOutput
|
||||||
|
{
|
||||||
|
private sealed class AsciiCastWriter : TextWriter
|
||||||
|
{
|
||||||
|
private readonly TextWriter _wrappedTextWriter;
|
||||||
|
private readonly StringBuilder _builder = new StringBuilder();
|
||||||
|
private int? _firstTick;
|
||||||
|
|
||||||
|
public AsciiCastWriter(TextWriter wrappedTextWriter)
|
||||||
|
{
|
||||||
|
_wrappedTextWriter = wrappedTextWriter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Write(string? value)
|
||||||
|
{
|
||||||
|
if (value == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Append(value);
|
||||||
|
_wrappedTextWriter.Write(value);
|
||||||
|
base.Write(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Encoding Encoding => _wrappedTextWriter.Encoding;
|
||||||
|
|
||||||
|
private void Append(string value)
|
||||||
|
{
|
||||||
|
var tick = 0m;
|
||||||
|
if (_firstTick.HasValue)
|
||||||
|
{
|
||||||
|
tick = Environment.TickCount - _firstTick.Value;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_firstTick = Environment.TickCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
tick /= 1000m;
|
||||||
|
|
||||||
|
_builder.Append('[')
|
||||||
|
.AppendFormat(CultureInfo.InvariantCulture, "{0}", tick)
|
||||||
|
.Append(", \"o\", \"").Append(JsonEncodedText.Encode(value)).AppendLine("\"]");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetJsonAndClearBuffer()
|
||||||
|
{
|
||||||
|
var json = _builder.ToString();
|
||||||
|
|
||||||
|
// reset the buffer and also reset the first tick count
|
||||||
|
_builder.Clear();
|
||||||
|
_firstTick = null;
|
||||||
|
return json;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly IAnsiConsoleOutput _wrappedAnsiConsole;
|
||||||
|
private readonly AsciiCastWriter _asciiCastWriter;
|
||||||
|
|
||||||
|
public AsciiCastOut(IAnsiConsoleOutput wrappedAnsiConsole)
|
||||||
|
{
|
||||||
|
_wrappedAnsiConsole = wrappedAnsiConsole ?? throw new ArgumentNullException(nameof(wrappedAnsiConsole));
|
||||||
|
_asciiCastWriter = new AsciiCastWriter(_wrappedAnsiConsole.Writer);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextWriter Writer => _asciiCastWriter;
|
||||||
|
|
||||||
|
public bool IsTerminal => _wrappedAnsiConsole.IsTerminal;
|
||||||
|
|
||||||
|
public int Width => _wrappedAnsiConsole.Width;
|
||||||
|
|
||||||
|
public int Height => _wrappedAnsiConsole.Height;
|
||||||
|
|
||||||
|
public void SetEncoding(Encoding encoding)
|
||||||
|
{
|
||||||
|
_wrappedAnsiConsole.SetEncoding(encoding);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetCastJson(string title, int? width = null, int? height = null)
|
||||||
|
{
|
||||||
|
var header = $"{{\"version\": 2, \"width\": {width ?? _wrappedAnsiConsole.Width}, \"height\": {height ?? _wrappedAnsiConsole.Height}, \"title\": \"{JsonEncodedText.Encode(title)}\", \"env\": {{\"TERM\": \"Spectre.Console\"}}}}";
|
||||||
|
return $"{header}{Environment.NewLine}{_asciiCastWriter.GetJsonAndClearBuffer()}{Environment.NewLine}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Generator.Commands.Samples;
|
using Generator.Commands.Samples;
|
||||||
using Spectre.Console;
|
using Spectre.Console;
|
||||||
using Spectre.Console.Extensions;
|
using Spectre.Console.Extensions;
|
||||||
19
src/Generator/Commands/AsciiCast/Samples/BarChartSample.cs
Normal file
19
src/Generator/Commands/AsciiCast/Samples/BarChartSample.cs
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
internal class BarChartSample : BaseSample
|
||||||
|
{
|
||||||
|
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 5);
|
||||||
|
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
console.Write(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));
|
||||||
|
}
|
||||||
|
}
|
||||||
60
src/Generator/Commands/AsciiCast/Samples/BaseSample.cs
Normal file
60
src/Generator/Commands/AsciiCast/Samples/BaseSample.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
public abstract class BaseSample
|
||||||
|
{
|
||||||
|
public abstract void Run(IAnsiConsole console);
|
||||||
|
public virtual string Name() => PascalToKebab(GetType().Name.Replace("Sample", ""));
|
||||||
|
public virtual (int Cols, int Rows) ConsoleSize => (82, 24);
|
||||||
|
public virtual IEnumerable<(string Name, Action<Capabilities> CapabilitiesAction)> GetCapabilities()
|
||||||
|
{
|
||||||
|
return new (string Name, Action<Capabilities> CapabilitiesAction)[]
|
||||||
|
{
|
||||||
|
("plain", capabilities =>
|
||||||
|
{
|
||||||
|
capabilities.Unicode = false;
|
||||||
|
capabilities.Ansi = true;
|
||||||
|
capabilities.Interactive = true;
|
||||||
|
capabilities.Legacy = false;
|
||||||
|
capabilities.Links = false;
|
||||||
|
capabilities.ColorSystem = ColorSystem.Legacy;
|
||||||
|
}),
|
||||||
|
("rich", capabilities =>
|
||||||
|
{
|
||||||
|
capabilities.Unicode = true;
|
||||||
|
capabilities.Ansi = true;
|
||||||
|
capabilities.Interactive = true;
|
||||||
|
capabilities.Legacy = false;
|
||||||
|
capabilities.Links = false;
|
||||||
|
capabilities.ColorSystem = ColorSystem.TrueColor;
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private string PascalToKebab(ReadOnlySpan<char> input)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
var previousUpper = true;
|
||||||
|
foreach (var chr in input)
|
||||||
|
{
|
||||||
|
if (char.IsUpper(chr) && previousUpper == false)
|
||||||
|
{
|
||||||
|
sb.Append('-');
|
||||||
|
previousUpper = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
previousUpper = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb.Append(char.ToLower(chr));
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
internal class BreakdownChartSample : BaseSample
|
||||||
|
{
|
||||||
|
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 5);
|
||||||
|
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
console.Write(new BreakdownChart()
|
||||||
|
.Width(60)
|
||||||
|
.AddItem("SCSS", 80, 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
39
src/Generator/Commands/AsciiCast/Samples/CalendarSamples.cs
Normal file
39
src/Generator/Commands/AsciiCast/Samples/CalendarSamples.cs
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
internal abstract class BaseCalendarSample : BaseSample
|
||||||
|
{
|
||||||
|
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CalendarSample : BaseCalendarSample
|
||||||
|
{
|
||||||
|
|
||||||
|
public override void Run(IAnsiConsole console) => console.Write(new Calendar(2020, 10));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CalendarCultureSample : BaseCalendarSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console) => console.Write(new Calendar(2020, 10).Culture("sv-SE"));
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CalendarHeader : BaseCalendarSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
var calendar = new Calendar(2020, 10);
|
||||||
|
calendar.HeaderStyle(Style.Parse("blue bold"));
|
||||||
|
console.Write(calendar);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CalendarHighlightSample : BaseCalendarSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
var calendar = new Calendar(2020, 10).HighlightStyle(Style.Parse("yellow bold"));
|
||||||
|
calendar.AddCalendarEvent(2020, 10, 11);
|
||||||
|
console.Write(calendar);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
using SixLabors.ImageSharp.Processing;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
internal class CanvasImageSample : BaseSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
var image = new CanvasImage("./Data/cake.png");
|
||||||
|
image.MaxWidth(16);
|
||||||
|
console.Write(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CanvasImageManipulationSample : BaseSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
var image = new CanvasImage("./Data/cake.png");
|
||||||
|
image.MaxWidth(24);
|
||||||
|
image.BilinearResampler();
|
||||||
|
image.Mutate(ctx => ctx.Grayscale().Rotate(-45).EntropyCrop());
|
||||||
|
console.Write(image);
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/Generator/Commands/AsciiCast/Samples/CanvasSample.cs
Normal file
28
src/Generator/Commands/AsciiCast/Samples/CanvasSample.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
internal class CanvasSample : BaseSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
var canvas = new Canvas(16, 16);
|
||||||
|
|
||||||
|
// Draw some shapes
|
||||||
|
for (var i = 0; i < canvas.Width; i++)
|
||||||
|
{
|
||||||
|
// Cross
|
||||||
|
canvas.SetPixel(i, i, Color.White);
|
||||||
|
canvas.SetPixel(canvas.Width - i - 1, i, Color.White);
|
||||||
|
|
||||||
|
// Border
|
||||||
|
canvas.SetPixel(i, 0, Color.Red);
|
||||||
|
canvas.SetPixel(0, i, Color.Green);
|
||||||
|
canvas.SetPixel(i, canvas.Height - 1, Color.Blue);
|
||||||
|
canvas.SetPixel(canvas.Width - 1, i, Color.Yellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render the canvas
|
||||||
|
console.Write(canvas);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -43,11 +43,11 @@ public class ColumnsSample : BaseSample
|
|||||||
|
|
||||||
private sealed class Fruit
|
private sealed class Fruit
|
||||||
{
|
{
|
||||||
public string Name { get; init; }
|
public required string Name { get; init; }
|
||||||
|
|
||||||
public static List<Fruit> LoadFriuts()
|
public static List<Fruit> LoadFriuts()
|
||||||
{
|
{
|
||||||
return new []
|
return new[]
|
||||||
{
|
{
|
||||||
"Apple",
|
"Apple",
|
||||||
"Apricot",
|
"Apricot",
|
||||||
@@ -87,7 +87,7 @@ public class ColumnsSample : BaseSample
|
|||||||
"Ximenia",
|
"Ximenia",
|
||||||
"Yuzu",
|
"Yuzu",
|
||||||
}
|
}
|
||||||
.Select(x => new Fruit{Name = x})
|
.Select(x => new Fruit { Name = x })
|
||||||
.ToList();
|
.ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
80
src/Generator/Commands/AsciiCast/Samples/Exceptions.cs
Normal file
80
src/Generator/Commands/AsciiCast/Samples/Exceptions.cs
Normal file
@@ -0,0 +1,80 @@
|
|||||||
|
using System;
|
||||||
|
using System.Security.Authentication;
|
||||||
|
using Generator.Commands.Samples;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
// Keep the namespace here short because it'll be used in the display of the exceptions,
|
||||||
|
// and we want to keep that below 100 characters wide.
|
||||||
|
namespace Samples;
|
||||||
|
|
||||||
|
public static class Exceptions
|
||||||
|
{
|
||||||
|
internal abstract class BaseExceptionSample : BaseSample
|
||||||
|
{
|
||||||
|
public override (int Cols, int Rows) ConsoleSize => (100, 12);
|
||||||
|
|
||||||
|
protected readonly Exception Exception = null!;
|
||||||
|
|
||||||
|
protected BaseExceptionSample()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
DoMagic(42, null!);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Exception = ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class DefaultExceptionSample : BaseExceptionSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console) => console.WriteException(Exception, ExceptionFormats.ShortenPaths);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class ShortenedExceptionSample : BaseExceptionSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console) => console.WriteException(Exception, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class CustomColorsExceptionSample : BaseExceptionSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
console.WriteException(Exception, 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),
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void DoMagic(int foo, string[,] bar)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
CheckCredentials(foo, bar);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("Whaaat?", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void CheckCredentials(int qux, string[,] corgi)
|
||||||
|
{
|
||||||
|
throw new InvalidCredentialException("The credentials are invalid.");
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/Generator/Commands/AsciiCast/Samples/FigletSample.cs
Normal file
15
src/Generator/Commands/AsciiCast/Samples/FigletSample.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
public class FigletSample : BaseSample
|
||||||
|
{
|
||||||
|
public override (int Cols, int Rows) ConsoleSize => (100, 24);
|
||||||
|
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
console.Write(new FigletText("Left aligned").LeftJustified().Color(Color.Red));
|
||||||
|
console.Write(new FigletText("Centered").Centered().Color(Color.Green));
|
||||||
|
console.Write(new FigletText("Right aligned").RightJustified().Color(Color.Blue));
|
||||||
|
}
|
||||||
|
}
|
||||||
96
src/Generator/Commands/AsciiCast/Samples/InputSample.cs
Normal file
96
src/Generator/Commands/AsciiCast/Samples/InputSample.cs
Normal file
@@ -0,0 +1,96 @@
|
|||||||
|
using DocExampleGenerator;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
internal class InputSample : BaseSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
var age = 0;
|
||||||
|
var name = string.Empty;
|
||||||
|
var sport = string.Empty;
|
||||||
|
var password = string.Empty;
|
||||||
|
var color = string.Empty;
|
||||||
|
|
||||||
|
console.DisplayThenType(c => name = AskName(c), "Peter F↲");
|
||||||
|
console.DisplayThenType(c => sport = AskSport(c), "football↲¦¦¦¦Hockey↲");
|
||||||
|
console.DisplayThenType(c => age = AskAge(c), "Forty↲¦¦¦¦40↲");
|
||||||
|
console.DisplayThenType(c => password = AskPassword(c), "hunter2↲");
|
||||||
|
console.DisplayThenType(c => color = AskColor(c), "↲");
|
||||||
|
|
||||||
|
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 sport[/]", sport)
|
||||||
|
.AddRow("[grey]Age[/]", age.ToString())
|
||||||
|
.AddRow("[grey]Password[/]", password)
|
||||||
|
.AddRow("[grey]Favorite color[/]", string.IsNullOrEmpty(color) ? "Unknown" : color));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string AskName(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
console.WriteLine();
|
||||||
|
console.Write(new Rule("[yellow]Strings[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
var name = console.Ask<string>("What's your [green]name[/]?");
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static string AskSport(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
console.WriteLine();
|
||||||
|
console.Write(new Rule("[yellow]Choices[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
|
||||||
|
return console.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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static int AskAge(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
console.WriteLine();
|
||||||
|
console.Write(new Rule("[yellow]Integers[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
|
||||||
|
return console.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(),
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string AskPassword(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
console.WriteLine();
|
||||||
|
console.Write(new Rule("[yellow]Secrets[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
|
||||||
|
return console.Prompt(
|
||||||
|
new TextPrompt<string>("Enter [green]password[/]?")
|
||||||
|
.PromptStyle("red")
|
||||||
|
.Secret());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string AskColor(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
console.WriteLine();
|
||||||
|
console.Write(new Rule("[yellow]Optional[/]").RuleStyle("grey").LeftJustified());
|
||||||
|
|
||||||
|
return console.Prompt(
|
||||||
|
new TextPrompt<string>("[grey][[Optional]][/] What is your [green]favorite color[/]?")
|
||||||
|
.AllowEmpty());
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/Generator/Commands/AsciiCast/Samples/JsonSample.cs
Normal file
38
src/Generator/Commands/AsciiCast/Samples/JsonSample.cs
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
using Spectre.Console.Json;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
public class JsonSample : BaseSample
|
||||||
|
{
|
||||||
|
public override (int Cols, int Rows) ConsoleSize => (60, 20);
|
||||||
|
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
28
src/Generator/Commands/AsciiCast/Samples/LayoutSample.cs
Normal file
28
src/Generator/Commands/AsciiCast/Samples/LayoutSample.cs
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
public class LayoutSample : BaseSample
|
||||||
|
{
|
||||||
|
public override (int Cols, int Rows) ConsoleSize => (80, 24);
|
||||||
|
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
var layout = new Layout("Root")
|
||||||
|
.SplitColumns(
|
||||||
|
new Layout("Left"),
|
||||||
|
new Layout("Right")
|
||||||
|
.SplitRows(
|
||||||
|
new Layout("Top"),
|
||||||
|
new Layout("Bottom")));
|
||||||
|
|
||||||
|
layout["Left"].Update(
|
||||||
|
new Panel(
|
||||||
|
Align.Center(
|
||||||
|
new Markup("Hello [blue]World![/]"),
|
||||||
|
VerticalAlignment.Middle))
|
||||||
|
.Expand());
|
||||||
|
|
||||||
|
AnsiConsole.Write(layout);
|
||||||
|
}
|
||||||
|
}
|
||||||
83
src/Generator/Commands/AsciiCast/Samples/LiveSample.cs
Normal file
83
src/Generator/Commands/AsciiCast/Samples/LiveSample.cs
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
internal class LiveSample : BaseSample
|
||||||
|
{
|
||||||
|
public override (int Cols, int Rows) ConsoleSize => (100, 20);
|
||||||
|
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
var table = new Table();
|
||||||
|
|
||||||
|
// Animate
|
||||||
|
console.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[/] ]]"));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using DocExampleGenerator;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
internal class MultiSelectionSample : BaseSample
|
||||||
|
{
|
||||||
|
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 14);
|
||||||
|
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
console.DisplayThenType(AskFruit, "↓↓ ¦¦↑↑ ¦¦ ¦¦↓ ↓↓↓↓↓ ↓↓↓↓ ¦¦↲");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void AskFruit(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
var favorites = console.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"
|
||||||
|
}));
|
||||||
|
|
||||||
|
console.MarkupLine("Your selected: [yellow]{0}[/]", string.Join(',', favorites));
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/Generator/Commands/AsciiCast/Samples/PanelSample.cs
Normal file
15
src/Generator/Commands/AsciiCast/Samples/PanelSample.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
internal class PanelSample : BaseSample
|
||||||
|
{
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
var panel = new Panel("[red]Spaghetti\nLinguini\nFettucine\nTortellini\nCapellini\nLasagna[/]");
|
||||||
|
panel.Header = new PanelHeader("[underline]Pasta Menu[/]", Justify.Center);
|
||||||
|
panel.Border = BoxBorder.Double;
|
||||||
|
panel.Padding = new Padding(2, 2, 2, 2);
|
||||||
|
console.Write(panel);
|
||||||
|
}
|
||||||
|
}
|
||||||
87
src/Generator/Commands/AsciiCast/Samples/ProgressSample.cs
Normal file
87
src/Generator/Commands/AsciiCast/Samples/ProgressSample.cs
Normal file
@@ -0,0 +1,87 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using Spectre.Console;
|
||||||
|
|
||||||
|
namespace Generator.Commands.Samples;
|
||||||
|
|
||||||
|
internal class ProgressSample : BaseSample
|
||||||
|
{
|
||||||
|
public override (int Cols, int Rows) ConsoleSize => (base.ConsoleSize.Cols, 10);
|
||||||
|
|
||||||
|
public override IEnumerable<(string Name, Action<Capabilities> CapabilitiesAction)> GetCapabilities()
|
||||||
|
{
|
||||||
|
yield return ("non-interactive", capabilities =>
|
||||||
|
{
|
||||||
|
capabilities.Ansi = false;
|
||||||
|
capabilities.Interactive = false;
|
||||||
|
capabilities.Legacy = false;
|
||||||
|
capabilities.Unicode = true;
|
||||||
|
capabilities.ColorSystem = ColorSystem.TrueColor;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
foreach (var capability in base.GetCapabilities())
|
||||||
|
{
|
||||||
|
yield return capability;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void Run(IAnsiConsole console)
|
||||||
|
{
|
||||||
|
// Show progress
|
||||||
|
console.Progress()
|
||||||
|
.AutoClear(false)
|
||||||
|
.Columns(new TaskDescriptionColumn(), new ProgressBarColumn(), new PercentageColumn(), new RemainingTimeColumn(), new SpinnerColumn())
|
||||||
|
.Start(ctx =>
|
||||||
|
{
|
||||||
|
var random = new Random(122978);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private static List<(ProgressTask Task, int Delay)> CreateTasks(ProgressContext progress, Random random)
|
||||||
|
{
|
||||||
|
var tasks = new List<(ProgressTask, int)>();
|
||||||
|
|
||||||
|
var names = new[]
|
||||||
|
{
|
||||||
|
"Retriculating algorithms", "Colliding splines", "Solving quarks", "Folding data structures",
|
||||||
|
"Rerouting capacitators "
|
||||||
|
};
|
||||||
|
|
||||||
|
for (var i = 0; i < 5; i++)
|
||||||
|
{
|
||||||
|
tasks.Add((progress.AddTask(names[i]), random.Next(2, 10)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user