Compare commits

...

85 Commits

Author SHA1 Message Date
Patrik Svensson
03334f693d Add support for table footers 2020-10-26 00:01:13 +01:00
Patrik Svensson
c9c0ad733f Fix rendering bug when splitting lines
The bug might occur if there are wide characters such as emojis
at the end of a line. The SplitLines method mixed cell width
and text length, which might give incorrect results. This commit
makes sure that comparison and calculation is done using cell width
where it's appropriate.
2020-10-24 01:45:41 +02:00
Patrik Svensson
041bd016a2 Remove verbs from extension methods
Removed the verbs from all extension methods that manipulate
properties which makes the API more succinct and easier to read.

Also added implicit conversion from string to Style.

As a good OSS citizen, I've obsoleted the old methods with
a warning for now, so this shouldn't break anyone using
the old methods.
2020-10-23 15:08:18 +02:00
Takahito Yamatoya
037a215a78 Add documentation for rule 2020-10-22 08:53:20 +02:00
Patrik Svensson
9afc1ea721 Add support for aligning tables 2020-10-21 18:15:51 +02:00
Takahito Yamatoya
b52056ee49 Update documentation for calendar 2020-10-20 21:55:29 +02:00
Patrik Svensson
3941fd81ab Move table and calendar docs 2020-10-20 02:32:04 +02:00
Patrik Svensson
5a1b8a1710 Add rule widget
Adds a new rule widget.
Also fixes some bugs I encountered while testing
some unrelated things in an extremely small console.
2020-10-20 01:45:53 +02:00
Patrik Svensson
1410cba6c5 Add Markdown.Escape method 2020-10-20 01:09:26 +02:00
Patrik Svensson
70fc14e9cd Add new ctors for Rows and Columns widgets 2020-10-19 21:25:28 +02:00
Takahito Yamatoya
0b4359a52a Add installation instructions
* to add how to install

* fix

* remove empty line
2020-10-19 16:50:54 +02:00
Patrik Svensson
cb2924a609 Add table heading and footnote support
Closes #116
2020-10-19 15:46:57 +02:00
Takahito Yamatoya
5c119ee0c3 Add documentation for calendar 2020-10-19 15:44:16 +02:00
Takahito Yamatoya
b9d182b6e3 Add README.jp.md 2020-10-19 15:42:33 +02:00
Patrik Svensson
bfffef630f Do not draw tables that can't be drawn
This is a temporary fix for undrawable tables until we've
implemented a proper strategy. What this does is that it replaces
an undrawable table with an ellipsis (...). This should only
occur in either super big tables or deeply nested tables in a
console with a small buffer width.
2020-10-18 08:03:40 +02:00
Takahito Yamatoya
a2f507e58f update sample output 2020-10-18 06:56:47 +02:00
Takahito Yamatoya
d1d06d6a6b fix incorrect command 2020-10-18 06:56:47 +02:00
Patrik Svensson
52718c499c Fix minor typo in example 2020-10-17 13:22:01 +02:00
Patrik Svensson
7ef1ac483a Fix overflow splitting bug
Closes #93
2020-10-17 12:37:20 +02:00
Takahito Yamatoya
c0875c912a fix incorrect link 2020-10-17 12:16:18 +02:00
Patrik Svensson
3f2ca49071 Add calendar control
Closes #101
2020-10-16 23:02:53 +02:00
Khalid Abuhakmeh
0a0380ae0a Don't throw when console is small
this just returns an empty collection when
take is 0. It leads to some strange output, but
it doesn't blow up.

 #93
2020-10-08 22:17:12 +02:00
Patrik Svensson
ae92c606bb Add support for remapping emojis
Closes #94
2020-10-07 17:33:05 +02:00
Patrik Svensson
68e92f3365 Add various exception improvements 2020-10-07 11:57:28 +02:00
Patrik Svensson
39a8588dc3 Rename ExceptionFormats.None 2020-10-07 11:57:28 +02:00
Patrik Svensson
3c3afe7439 Add support for rendering exceptions 2020-10-05 07:03:02 +02:00
Gary Ewan Park
971f9032ba (doc) Dynamically generate sections
Rather than hard-coding them.  Then, as the number of sections increase,
no additional changes will be required here.
2020-10-03 16:30:21 +02:00
Gary Ewan Park
5149557560 (doc) Remove hard-coded link
Rather than specifying spectre.console directly in the layout, figure out
the URL using GetLink method.
2020-10-03 16:30:21 +02:00
Khalid Abuhakmeh
e0947708c9 Generalized Search
Generalized the search to work with any table
with some basic classes and some updated
JavaScript, we can now search colors and emojis.
2020-10-02 19:39:02 +02:00
Patrik Svensson
b1db8a9403 Clean up border code
Removed caching that really didn't do anything anymore.
2020-10-01 23:05:02 +02:00
Khalid Abuhakmeh
a2f8652575 Add Search To Emoji Page
This adds a typeahead search feature
for the very large emoji table. It filters as you type to find if an emoji exists or not.

The JavaScript could be adapted to work on all tables in the future.
2020-10-01 22:00:39 +02:00
Khalid Abuhakmeh
672faa131f Update Docs Readme
Added some more context to the docs readme for
folks looking to contribute. Also added the license
so its clear what the license of the docs site is. As
a small tweak I removed a duplicate string value and
use the Constant.
2020-10-01 20:51:32 +02:00
Patrik Svensson
e429f6434b Update examples 2020-10-01 14:43:08 +02:00
Patrik Svensson
93ec7401c8 Add support for markdown tables
Closes #85

* Split Border into BoxBorder and TableBorder
* Change how different table parts are composed
* Add markdown table border
2020-10-01 14:43:08 +02:00
Patrik Svensson
697273917e Move console encoder to rendering namespace 2020-09-21 17:07:05 +02:00
Patrik Svensson
2943535973 Make segments immutable 2020-09-21 17:03:17 +02:00
Patrik Svensson
cd0d182f12 Add support for recording console output
This commit adds support for recording console output
as well as exporting it to either text or HTML. A user can
also provide their own encoder if they wish.
2020-09-21 13:33:28 +02:00
Patrik Svensson
b197f278ed Add support for rows
Closes #69
2020-09-20 19:17:33 +02:00
Patrik Svensson
3847a8949f Fix bug with uris being interpreted as emojis
Closes #82
2020-09-20 13:00:44 +02:00
Patrik Svensson
eeb3f967b6 Update emoji support
* Add constants for emojis
* Move emoji shortcode rendering to Markup
* Add documentation
* Add example
* Add tests
2020-09-18 16:11:51 +02:00
Patrik Svensson
090b30f731 Use Wcwidth library 2020-09-18 15:31:12 +02:00
Patrik Svensson
df291ef84e Fix Info example emoji problem
The emojis that previously were used, used Unicode combinators
which are not fully supported. Changing to :thumbs_up: and :thumbs_down:
instead.
2020-09-17 10:58:50 +02:00
Patrik Svensson
7d6104ace4 Add padder widget
This commit adds a padder can be use to pad other IRenderable
objects such as tables, panels, grids, text, etc.
2020-09-17 10:58:50 +02:00
Kristian Hellang
314456ca17 Add emoji codes to example 2020-09-17 10:35:15 +02:00
Kristian Hellang
b7f654cd7f Replace emoji in segment text 2020-09-17 10:35:15 +02:00
Kristian Hellang
fea8a36e8a Add generated Emoji class with corresponding non-generated file 2020-09-17 10:35:15 +02:00
Kristian Hellang
0632b38477 Fix relative path in existing color script 2020-09-17 10:35:15 +02:00
Kristian Hellang
a7b7d4e556 Add Generator command to generate emoji lookup table 2020-09-17 10:35:15 +02:00
Kristian Hellang
11d331e31d Add .DS_Store to .gitignore 2020-09-17 10:35:15 +02:00
Patrik Svensson
ce670a7ca9 Add link identity generator 2020-09-12 14:47:32 +02:00
Patrik Svensson
101e244059 Minor clean up 2020-09-12 10:46:57 +02:00
Patrik Svensson
504746c5dc Add link support for supported terminals
Also refactors the code quite a bit, to make it a bit more
easier to add features like this in the future.

Closes #75
2020-09-11 17:44:56 +02:00
Patrik Svensson
1601ef24b3 Update border documentation 2020-09-09 14:27:40 +02:00
Patrik Svensson
b46d0fa4f6 Group IAnsiConsole extensions in csproj 2020-09-09 08:47:55 +02:00
Patrik Svensson
4f06687104 Restructure solution a bit 2020-09-09 08:43:48 +02:00
Patrik Svensson
003e15686f Add documentation for tables
Also moves "Colors" and "Styles" sections to appendix.
2020-09-08 18:21:52 +02:00
Patrik Svensson
3e9796849b Add more borders for grids, tables, and panels
* Ascii2
* AsciiDoubleHead
* Double
* DoubleEdge
* Heavy
* HeavyEdge
* HeavyHead
* Horizontal
* Minimal
* MinimalDoubleHead
* MinimalHeavyHead
* Simple
* SimpleHeavy
2020-09-08 00:16:20 +02:00
Patrik Svensson
3cc19520b0 Add implicit conversion op from string to Style
Closes #71
2020-09-06 23:03:51 +02:00
Patrik Svensson
87bde3e5a2 Remove BorderKind in favour of Border 2020-09-06 12:29:48 +02:00
Patrik Svensson
e6e9a4d950 Add description for 'Info' example 2020-09-05 08:52:06 +02:00
Patrik Svensson
29ce14e1e8 Rename 'Diagnostic' example to 'Info' 2020-09-05 08:50:00 +02:00
Patrik Svensson
ceb3572d6a Make table and grid extension methods fluent 2020-09-05 08:49:36 +02:00
Patrik Svensson
13c56eca01 Allow mutation of segments 2020-09-05 08:39:48 +02:00
Patrik Svensson
a477884d36 Move Panel extensions to Spectre.Console namespace 2020-09-05 08:20:13 +02:00
Patrik Svensson
ae6d2c63a3 Add column support
Adds support for rendering arbitrary data into columns.

Closes #67
2020-09-05 07:45:38 +02:00
Patrik Svensson
e946289bd9 Make styles composable
Also adds some new extension methods and make some APIs a bit more consistent.

Closes #64
2020-09-03 21:26:20 +02:00
Patrik Svensson
bcaaa6b2d3 Update table of contents (skip-ci) 2020-09-03 20:04:06 +02:00
Patrik Svensson
d3588a4b06 Remove styles and colors (skip-ci) 2020-09-03 20:03:26 +02:00
Patrik Svensson
7471e9d38c Add panel header support
Closes #63
2020-09-03 19:02:29 +02:00
Patrik Svensson
9f8ca6d648 Add text overflow support
Closes #61
2020-09-03 14:57:57 +02:00
Patrik Svensson
88edfe68ec Add border for color representations 2020-09-02 09:55:44 +02:00
Patrik Svensson
5d32764a64 Fix typo: SRG -> SGR 2020-09-02 09:02:59 +02:00
Patrik Svensson
4f6c9c62c7 Set fetch depth to 0 2020-09-01 22:05:46 +02:00
Patrik Svensson
f2677213a4 Separate build and run when publishing docs 2020-09-01 22:00:44 +02:00
Patrik Svensson
bdaf00a556 Remove empty documentation pages 2020-09-01 21:51:25 +02:00
Patrik Svensson
7de4b6c7b9 Build docs as part of CI 2020-09-01 21:50:36 +02:00
Patrik Svensson
0bc801e3eb Build docs when source change 2020-09-01 21:40:49 +02:00
Patrik Svensson
88a82cdad0 Build docs in release mode 2020-09-01 21:39:40 +02:00
Patrik Svensson
0cecb555d5 Show documentation version in footer 2020-09-01 21:33:15 +02:00
Patrik Svensson
52e3ee17b0 Fix logo link 2020-09-01 21:28:52 +02:00
Dave Glick
caf7661e66 Moves all the pages up a level and hardcodes the section name 2020-09-01 21:23:01 +02:00
Dave Glick
65f0a085cc Updated to the latest Statiq Web with breakage fixes 2020-09-01 21:03:47 +02:00
Patrik Svensson
a123806cd8 Add docs for escaping [ and ] in markup 2020-09-01 16:52:40 +02:00
Patrik Svensson
173645cdd2 Added documentation for markup text 2020-08-31 14:05:28 +02:00
Patrik Svensson
7fd2efaeb5 Merge segments before rendering
This will reduce the number of segments to render
and produce cleaner ANSI escape code sequences.

Closes #46
2020-08-30 12:40:34 +02:00
293 changed files with 30753 additions and 3897 deletions

View File

@@ -6,6 +6,35 @@ env:
DOTNET_CLI_TELEMETRY_OPTOUT: true
jobs:
###################################################
# DOCS
###################################################
docs:
name: Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- name: Setup dotnet
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.301' # SDK Version to use.
- name: Build
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cd docs
dotnet run --configuration Release
###################################################
# BUILD
###################################################
build:
name: Build
if: "!contains(github.event.head_commit.message, 'skip-ci')"
@@ -35,11 +64,14 @@ jobs:
shell: bash
run: |
dotnet tool restore
dotnet example diagnostic
dotnet example table
dotnet example grid
dotnet example panel
dotnet example info
dotnet example tables
dotnet example grids
dotnet example panels
dotnet example colors
dotnet example emojis
dotnet example exceptions
dotnet example calendars
- name: Build
shell: bash

View File

@@ -4,14 +4,22 @@ on:
push:
paths:
- 'docs/**'
- 'src/**'
jobs:
###################################################
# DOCS
###################################################
build:
name: Deploy
runs-on: windows-latest
steps:
- name: Checkout
uses: actions/checkout@master
uses: actions/checkout@v2
with:
fetch-depth: 0
- name: Setup dotnet
uses: actions/setup-dotnet@v1
@@ -24,4 +32,4 @@ jobs:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cd docs
dotnet run -- deploy
dotnet run --configuration Release -- deploy

View File

@@ -6,6 +6,8 @@ on:
- '*'
branches:
- main
paths:
- 'src/**'
env:
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
@@ -13,12 +15,37 @@ env:
jobs:
###################################################
# DOCS
###################################################
docs:
name: Documentation
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@master
- name: Setup dotnet
uses: actions/setup-dotnet@v1
with:
dotnet-version: '3.1.301' # SDK Version to use.
- name: Build
shell: bash
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
cd docs
dotnet run --configuration Release
###################################################
# BUILD
###################################################
build:
name: Build
needs: [docs]
if: "!contains(github.event.head_commit.message, 'skip-ci') || startsWith(github.ref, 'refs/tags/')"
strategy:
matrix:

2
.gitignore vendored
View File

@@ -5,6 +5,8 @@
[Pp]ackages/
/.artifacts/
/[Tt]ools/
.idea
.DS_Store
# Cakeup
cakeup-x86_64-latest.exe

413
README.jp.md Normal file
View File

@@ -0,0 +1,413 @@
# `Spectre.Console`
_[![Spectre.Console NuGet Version](https://img.shields.io/nuget/v/spectre.console.svg?style=flat&label=NuGet%3A%20Spectre.Console)](https://www.nuget.org/packages/spectre.console)_
綺麗なコンソールアプリケーションを簡単に作成するための.NET Standard 2.0ライブラリです。
Python用の素晴らしい[Rich ライブラリ](https://github.com/willmcgugan/rich)に強く影響を受けています。
## 目次
1. [特徴](#特徴)
2. [](#例)
3. [使用方法](#使用方法)
3.1. [Static APIの利用](#static-apiの利用)
3.2. [コンソールの作成](#コンソールの作成)
4. [例の実行](#例の実行)
5. [クイックスタート](#クイックスタート)
6. [マークアップ](#マークアップ)
7. [絵文字](#絵文字)
8. [テーブル](#テーブル)
9. [例外](#例外)
## 特徴
* ユニットテストを意識して書いています。
* table、grid、panel、マークアップ言語に影響を受けた [rich](https://github.com/willmcgugan/rich) に対応しています。
* 太字、薄字、斜字、下線、斜線、点滅などの一般的なSGR parameters に対応しています。
* ターミナルで 3/4/8/24ビットカラーに対応しています。
ライブラリは現在のターミナルの性能を検知し、必要なカラーにダウングレードします
## 例
![Example](resources/gfx/screenshots/example.png)
## 使用方法
`Spectre.Console` APIはステートフルで、スレッドセーフではありません。
異なるスレッドからコンソールに書く必要がある場合、通常の`System.Console` APIを使用するときと同様、適切な注意を払ってください。
現在の端末がANSIエスケープシーケンスに対応していない場合、
`Spectre.Console`は、`System.Console` APIの利用に切り替わります。
_メモ: このライブラリは現在開発中で、APIは1.0のリリースまでの間に変更されたり、
削除されたりする可能性があります。_
### Static APIの利用
`System.Console` APIでするように、テキストを出力したいだけの時にはstatic APIが最適ですが、綺麗です。
```csharp
AnsiConsole.Foreground = Color.CornflowerBlue;
AnsiConsole.Decoration = Decoration.Underline | Decoration.Bold;
AnsiConsole.WriteLine("Hello World!");
AnsiConsole.Reset();
AnsiConsole.MarkupLine("[bold yellow on red]{0}[/] [underline]world[/]!", "Goodbye");
```
もし、デフォルトの`IAnsiConsole`への参照を取得したい場合、
`AnsiConsole.Console`経由でアクセスできます。
### コンソールの作成
単体テスト中にコードの実行環境を制御したい場合など、
特定の機能をもつコンソールを明示的に作成すると便利なことがあります。
単体テストの一部としてコードで `AnsiConsole`を使わないことを推奨します。
```csharp
IAnsiConsole console = AnsiConsole.Create(
new AnsiConsoleSettings()
{
Ansi = AnsiSupport.Yes,
ColorSystem = ColorSystemSupport.TrueColor,
Out = new StringWriter(),
});
```
_メモ: 主導でコンソールを作成しているときに特定のカラーシステムを指定できたとしても、
ユーザーのターミナルでは使えないかもしれないことを覚えておいてください。
テスト用にIAnsiConsoleを作成していない限り、
常に`ColorSystemSupport.Detect``AnsiSupport.Detect`を使用してください。_
## 例の実行
Spectre.Consoleでできることを見るために、
[dotnet-example](https://github.com/patriksvensson/dotnet-example)グローバルツールをインストールします。
```
> dotnet tool install -g dotnet-example
```
このリポジトリで提供している例が一覧表示されます
```
> dotnet example
╭────────────┬───────────────────────────────────────┬──────────────────────────────────────────────────────╮
│ Name │ Path │ Description │
├────────────┼───────────────────────────────────────┼──────────────────────────────────────────────────────┤
│ Borders │ examples/Borders/Borders.csproj │ Demonstrates the different kind of borders. │
│ Calendars │ examples/Calendars/Calendars.csproj │ Demonstrates how to render calendars. │
│ Colors │ examples/Colors/Colors.csproj │ Demonstrates how to use colors in the console. │
│ Columns │ examples/Columns/Columns.csproj │ Demonstrates how to render data into columns. │
│ Emojis │ examples/Emojis/Emojis.csproj │ Demonstrates how to render emojis. │
│ Exceptions │ examples/Exceptions/Exceptions.csproj │ Demonstrates how to render formatted exceptions. │
│ Grids │ examples/Grids/Grids.csproj │ Demonstrates how to render grids in a console. │
│ Info │ examples/Info/Info.csproj │ Displays the capabilities of the current console. │
│ Links │ examples/Links/Links.csproj │ Demonstrates how to render links in a console. │
│ Panels │ examples/Panels/Panels.csproj │ Demonstrates how to render items in panels. │
│ Rules │ examples/Rules/Rules.csproj │ Demonstrates how to render horizontal rules (lines). │
│ Tables │ examples/Tables/Tables.csproj │ Demonstrates how to render tables in a console. │
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
```
そして、例を実行します
```
> dotnet example tables
┌──────────┬──────────┬────────┐
│ Foo │ Bar │ Baz │
├──────────┼──────────┼────────┤
│ Hello │ World! │ │
│ Bonjour │ le │ monde! │
│ Hej │ Världen! │ │
└──────────┴──────────┴────────┘
```
## クイックスタート
pectre.Consoleの利用を開始する最初の方法は、Nugetパッケージをインストールすることです。
```shell
> dotnet add package Spectre.Console
```
その後、`Spectre.Console`名前空間を参照する必要があります。一度参照したら、提供されている全ての機能を使用できます。
```csharp
using Spectre.Console
public static class Program
{
public static void Main(string[] args)
{
AnsiConsole.Markup("[underline red]Hello[/] World!");
}
}
```
## マークアップ
`Markup`クラスは、コンソールにリッチなテキストを出力することができます。
### 文法
コンソールマークアップはbbcodeに影響を受けた文法を利用します。角括弧でスタイルを書いたらスタイルを参照、例えば、`[bold red]`
は、`[/]`で閉じるまでスタイルが適用されます。
```csharp
AnsiConsole.Render(new Markup("[bold yellow]Hello[/] [red]World![/]"));
```
`Markup` クラスは`IRenderable`を実装しており、table、grid、Panelを使用できることを意味します。
`IRenderable`のレンダリングに対応している多くのクラスは、リッチテキストの描画を上書きます。
```csharp
var table = new Table();
table.AddColumn(new TableColumn(new Markup("[yellow]Foo[/]")));
table.AddColumn(new TableColumn("[blue]Bar[/]"));
```
### 便利なメソッド
`AnsiConsole`には、新しい`Markup`インスタンスをインスタンス化することなく、コンソールにマークアップテキストを書き込める便利なメソッドがあります。
```csharp
AnsiConsole.Markup("[underline green]Hello[/] ");
AnsiConsole.MarkupLine("[bold]World[/]");
```
### エスケープ文字列
`[`を出力するために、 `[[`を利用し、`]`を出力するために`]]`を利用します。
```csharp
AnsiConsole.Markup("[[Hello]] "); // [Hello]
AnsiConsole.Markup("[red][[World]][/]"); // [World]
```
`SafeMarkup`拡張メソッドを使用することもできます。
```csharp
AnsiConsole.Markup("[red]{0}[/]", "Hello [World]".SafeMarkup());
```
### カラー
`new Style(foreground: Color.Maroon)`のようなコード、または、`AnsiConsole.Markup("[maroon on blue]Hello[/]")`のようなマークアップテキストで色を使用できます。
### 背景色の設定
カラー指定の際に、`on`を付けることで、マークアップで背景色を設定できます。
```
[bold yellow on blue]Hello[/]
[default on blue]World[/]
```
### 絵文字の描画
マークアップの一部として絵文字を出力するために、emojiショートコードが使用できます。
```csharp
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
```
emojiのスタイルについては、付録の[Emoji](./appendix/emojis) を参照してください。
### カラー
上の例では、全ての色は名前で参照されています。
しかし、16進数やRGB表現をマークダウンで色指定に使用できます。
```csharp
AnsiConsole.Markup("[red]Foo[/] ");
AnsiConsole.Markup("[#ff0000]Bar[/] ");
AnsiConsole.Markup("[rgb(255,0,0)]Baz[/] ");
```
## 絵文字
どのような絵文字が使用できるかは、使用しているOSやターミナルに依存し、どのように表示されるかは保証されません。絵文字の幅計算は正確ではないため、表、パネル、グリッドで使用する場合は表示がずれるかもしれません。
完全な互換性を確保するために、Unicode 13.0 より以前の`Emoji_Presentation`カテゴリにあるものだけを使用することを検討してください。
公式の絵文字一覧
https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt
```csharp
// Markup
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
// Constant
var hello = "Hello " + Emoji.Known.GlobeShowingEuropeAfrica;
```
テキスト内の絵文字を置き換えることができます。
```csharp
var phrase = "Mmmm :birthday_cake:";
var rendered
```
既存の絵文字を別のものにしたり、完全に新しい物を追加したいことがあります。このために、`Emoji.Remap`メソッドを使用できます。
この方法は、マークアップ文字と`Emoji.Replace`の両方で動作します。
```csharp
// Remap the emoji
Emoji.Remap("globe_showing_europe_africa", "😄");
// Render markup
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
// Replace emojis in string
var phrase = "Hello :globe_showing_europe_africa:!";
var rendered = Emoji.Replace(phrase);
```
## テーブル
テーブルはターミナルで表データを表示するのに完璧な方法です。
`Spectre.Console` は、テーブルの描画にとても優れていて、全てのカラムは中に合わせて調整してくれます。
`IRenderable`を実装しているものは、列ヘッダやセル、別のテーブルとして使用できます。
### 使い方
テーブルを描画するために、`Table`インスタンスを作成し、必要な数の列を追加し、行を追加します。
テーブルをコンソールの`Render`メソッドに渡して終わりです。
```csharp
// テーブルの作成
var table = new Table();
// 列の追加
table.AddColumn("Foo");
table.AddColumn(new TableColumn("Bar").Centered());
// 行の追加
table.AddRow("Baz", "[green]Qux[/]");
table.AddRow(new Markup("[blue]Corgi[/]"), new Panel("Waldo"));
// コンソールにテーブルの描画
AnsiConsole.Render(table);
```
これは次のように出力を描画します。
![Table](docs/input/assets/images/table.png)
### 罫線
```csharp
// 罫線を設定します
table.SetBorder(Border.None);
table.SetBorder(Border.Ascii);
table.SetBorder(Border.Square);
table.SetBorder(Border.Rounded);
```
### 拡大 / 縮小
```csharp
// テーブル幅を最大に設定します
table.Expand();
// テーブル幅を最小に設定します
table.Collapse();
```
### ヘッダーを隠す
```csharp
// 全ての列のヘッダーを隠します
table.HideHeaders();
```
### テーブル幅の設定
```csharp
// テーブル幅50セルに設定します
table.SetWidth(50);
```
### 整列(アライメント)
```csharp
// 整列を明示的に設定する
column.SetAlignment(Justify.Right);
```
### パディング
```csharp
// 左と右のパディングを設定する
column.SetPadding(left: 3, right: 5);
// 個別にパディングを設定する
column.PadLeft(3);
column.PadRight(5);
```
### 列改行の無効化
```csharp
// 列改行の無効化
column.NoWrap();
```
### 列幅の設定
```csharp
// 列幅の設定(これはまだ柔軟な拡張メソッドがありません)
column.Width = 15;
```
## 例外
例外はターミナルで見たときに読みやすいとは限りません。
`WriteException`メソッドを使用することで、例外をもう少し読みやすくすることができます。
```csharp
AnsiConsole.WriteException(ex);
```
![exception](docs/input/assets/images/exception.png)
### 例外の省略表示
例外の特定部分を短くして、さらに読みやすくしたり、パスをクリック可能なハイパーリンクにすることもできます。
ハイパーリンクがクリックできるかはターミナル次第です。
```csharp
AnsiConsole.WriteException(ex,
ExceptionFormat.ShortenPaths | ExceptionFormat.ShortenTypes |
ExceptionFormat.ShortenMethods | ExceptionFormat.ShowLinks);
```
![exception](docs/input/assets/images/compact_exception.png)
### 例外出力のカスタマイズ
例外の特定部分を短縮するだけでなく、デフォルトのスタイルを上書きすることもできます。
```csharp
AnsiConsole.WriteException(ex, new ExceptionSettings
{
Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
Style = new ExceptionStyle
{
Exception = Style.WithForeground(Color.Grey),
Message = Style.WithForeground(Color.White),
NonEmphasized = Style.WithForeground(Color.Cornsilk1),
Parenthesis = Style.WithForeground(Color.Cornsilk1),
Method = Style.WithForeground(Color.Red),
ParameterName = Style.WithForeground(Color.Cornsilk1),
ParameterType = Style.WithForeground(Color.Red),
Path = Style.WithForeground(Color.Red),
LineNumber = Style.WithForeground(Color.Cornsilk1),
}
});
```
![exception](docs/input/assets/images/custom_exception.png)

324
README.md
View File

@@ -10,12 +10,11 @@ for Python.
1. [Features](#features)
2. [Example](#example)
3. [Usage](#usage)
3.1. [Using the static API](#using-the-static-api)
3.2. [Creating a console](#creating-a-console)
4. [Running examples](#running-examples)
5. [Available styles](#available-styles)
6. [Predefined colors](#predefined-colors)
3. [Installing](#installing)
4. [Usage](#usage)
4.1. [Using the static API](#using-the-static-api)
4.2. [Creating a console](#creating-a-console)
5. [Running examples](#running-examples)
## Features
@@ -32,6 +31,14 @@ for Python.
![Example](resources/gfx/screenshots/example.png)
## Installing
The fastest way of getting started using Spectre.Console is to install the NuGet package.
```csharp
dotnet add package Spectre.Console
```
## Usage
The `Spectre.Console` API is stateful and is not thread-safe.
@@ -101,20 +108,28 @@ Now you can list available examples in this repository:
```
> dotnet example
╭───────────────────────────────────────┬─────────────────────────────────────────────────╮
│ Name │ Path │ Description │
├───────────────────────────────────────┼─────────────────────────────────────────────────┤
Colors │ examples/Colors/Colors.csproj │ Demonstrates how to use colors in the console.
Grid │ examples/Grid/Grid.csproj │ Demonstrates how to render grids in a console.
Panel │ examples/Panel/Panel.csproj │ Demonstrates how to render items in panels.
Table │ examples/Table/Table.csproj │ Demonstrates how to render tables in a console.
╰────────┴───────────────────────────────┴─────────────────────────────────────────────────╯
╭────────────┬───────────────────────────────────────┬──────────────────────────────────────────────────────
│ Name │ Path │ Description
├────────────┼───────────────────────────────────────┼──────────────────────────────────────────────────────
Borders │ examples/Borders/Borders.csproj │ Demonstrates the different kind of borders.
Calendars │ examples/Calendars/Calendars.csproj │ Demonstrates how to render calendars.
Colors │ examples/Colors/Colors.csproj │ Demonstrates how to use colors in the console.
Columns │ examples/Columns/Columns.csproj │ Demonstrates how to render data into columns.
│ Emojis │ examples/Emojis/Emojis.csproj │ Demonstrates how to render emojis. │
│ Exceptions │ examples/Exceptions/Exceptions.csproj │ Demonstrates how to render formatted exceptions. │
│ Grids │ examples/Grids/Grids.csproj │ Demonstrates how to render grids in a console. │
│ Info │ examples/Info/Info.csproj │ Displays the capabilities of the current console. │
│ Links │ examples/Links/Links.csproj │ Demonstrates how to render links in a console. │
│ Panels │ examples/Panels/Panels.csproj │ Demonstrates how to render items in panels. │
│ Rules │ examples/Rules/Rules.csproj │ Demonstrates how to render horizontal rules (lines). │
│ Tables │ examples/Tables/Tables.csproj │ Demonstrates how to render tables in a console. │
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
```
And to run an example:
```
> dotnet example table
> dotnet example tables
┌──────────┬──────────┬────────┐
│ Foo │ Bar │ Baz │
├──────────┼──────────┼────────┤
@@ -122,281 +137,4 @@ And to run an example:
│ Bonjour │ le │ monde! │
│ Hej │ Världen! │ │
└──────────┴──────────┴────────┘
```
## Available styles
_NOTE: Not all styles are supported in every terminal._
Name | Description
--- | ---
`bold` | Bold text
`dim` | Dim or faint text
`italic` | Italic text
`underline` | Underlined text
`invert` | Swaps the foreground and background colors
`conceal` | Hides the text
`slowblink` | Makes text blink slowly
`rapidblink` | Makes text blink
`strikethrough` | Shows text with a horizontal line through the center
## Predefined colors
Number | Name | RGB | Hex | System.ConsoleColor
--- | --- | --- | --- | ---
`0` | `black` | `0,0,0` | `#000000` | `Black`
`1` | `maroon` | `128,0,0` | `#800000` | `DarkRed`
`2` | `green` | `0,128,0` | `#008000` | `DarkGreen`
`3` | `olive` | `128,128,0` | `#808000` | `DarkYellow`
`4` | `navy` | `0,0,128` | `#000080` | `DarkBlue`
`5` | `purple` | `128,0,128` | `#800080` | `DarkMagenta`
`6` | `teal` | `0,128,128` | `#008080` | `DarkCyan`
`7` | `silver` | `192,192,192` | `#c0c0c0` | `Gray`
`8` | `grey` | `128,128,128` | `#808080` | `DarkGray`
`9` | `red` | `255,0,0` | `#ff0000` | `Red`
`10` | `lime` | `0,255,0` | `#00ff00` | `Green`
`11` | `yellow` | `255,255,0` | `#ffff00` | `Yellow`
`12` | `blue` | `0,0,255` | `#0000ff` | `Blue`
`13` | `fuchsia` | `255,0,255` | `#ff00ff` | `Magenta`
`14` | `aqua` | `0,255,255` | `#00ffff` | `Cyan`
`15` | `white` | `255,255,255` | `#ffffff` | `White`
`16` | `grey0` | `0,0,0` | `#000000`
`17` | `navyblue` | `0,0,95` | `#00005f`
`18` | `darkblue` | `0,0,135` | `#000087`
`19` | `blue3` | `0,0,175` | `#0000af`
`20` | `blue3_1` | `0,0,215` | `#0000d7`
`21` | `blue1` | `0,0,255` | `#0000ff`
`22` | `darkgreen` | `0,95,0` | `#005f00`
`23` | `deepskyblue4` | `0,95,95` | `#005f5f`
`24` | `deepskyblue4_1` | `0,95,135` | `#005f87`
`25` | `deepskyblue4_2` | `0,95,175` | `#005faf`
`26` | `dodgerblue3` | `0,95,215` | `#005fd7`
`27` | `dodgerblue2` | `0,95,255` | `#005fff`
`28` | `green4` | `0,135,0` | `#008700`
`29` | `springgreen4` | `0,135,95` | `#00875f`
`30` | `turquoise4` | `0,135,135` | `#008787`
`31` | `deepskyblue3` | `0,135,175` | `#0087af`
`32` | `deepskyblue3_1` | `0,135,215` | `#0087d7`
`33` | `dodgerblue1` | `0,135,255` | `#0087ff`
`34` | `green3` | `0,175,0` | `#00af00`
`35` | `springgreen3` | `0,175,95` | `#00af5f`
`36` | `darkcyan` | `0,175,135` | `#00af87`
`37` | `lightseagreen` | `0,175,175` | `#00afaf`
`38` | `deepskyblue2` | `0,175,215` | `#00afd7`
`39` | `deepskyblue1` | `0,175,255` | `#00afff`
`40` | `green3_1` | `0,215,0` | `#00d700`
`41` | `springgreen3_1` | `0,215,95` | `#00d75f`
`42` | `springgreen2` | `0,215,135` | `#00d787`
`43` | `cyan3` | `0,215,175` | `#00d7af`
`44` | `darkturquoise` | `0,215,215` | `#00d7d7`
`45` | `turquoise2` | `0,215,255` | `#00d7ff`
`46` | `green1` | `0,255,0` | `#00ff00`
`47` | `springgreen2_1` | `0,255,95` | `#00ff5f`
`48` | `springgreen1` | `0,255,135` | `#00ff87`
`49` | `mediumspringgreen` | `0,255,175` | `#00ffaf`
`50` | `cyan2` | `0,255,215` | `#00ffd7`
`51` | `cyan1` | `0,255,255` | `#00ffff`
`52` | `darkred` | `95,0,0` | `#5f0000`
`53` | `deeppink4` | `95,0,95` | `#5f005f`
`54` | `purple4` | `95,0,135` | `#5f0087`
`55` | `purple4_1` | `95,0,175` | `#5f00af`
`56` | `purple3` | `95,0,215` | `#5f00d7`
`57` | `blueviolet` | `95,0,255` | `#5f00ff`
`58` | `orange4` | `95,95,0` | `#5f5f00`
`59` | `grey37` | `95,95,95` | `#5f5f5f`
`60` | `mediumpurple4` | `95,95,135` | `#5f5f87`
`61` | `slateblue3` | `95,95,175` | `#5f5faf`
`62` | `slateblue3_1` | `95,95,215` | `#5f5fd7`
`63` | `royalblue1` | `95,95,255` | `#5f5fff`
`64` | `chartreuse4` | `95,135,0` | `#5f8700`
`65` | `darkseagreen4` | `95,135,95` | `#5f875f`
`66` | `paleturquoise4` | `95,135,135` | `#5f8787`
`67` | `steelblue` | `95,135,175` | `#5f87af`
`68` | `steelblue3` | `95,135,215` | `#5f87d7`
`69` | `cornflowerblue` | `95,135,255` | `#5f87ff`
`70` | `chartreuse3` | `95,175,0` | `#5faf00`
`71` | `darkseagreen4_1` | `95,175,95` | `#5faf5f`
`72` | `cadetblue` | `95,175,135` | `#5faf87`
`73` | `cadetblue_1` | `95,175,175` | `#5fafaf`
`74` | `skyblue3` | `95,175,215` | `#5fafd7`
`75` | `steelblue1` | `95,175,255` | `#5fafff`
`76` | `chartreuse3_1` | `95,215,0` | `#5fd700`
`77` | `palegreen3` | `95,215,95` | `#5fd75f`
`78` | `seagreen3` | `95,215,135` | `#5fd787`
`79` | `aquamarine3` | `95,215,175` | `#5fd7af`
`80` | `mediumturquoise` | `95,215,215` | `#5fd7d7`
`81` | `steelblue1_1` | `95,215,255` | `#5fd7ff`
`82` | `chartreuse2` | `95,255,0` | `#5fff00`
`83` | `seagreen2` | `95,255,95` | `#5fff5f`
`84` | `seagreen1` | `95,255,135` | `#5fff87`
`85` | `seagreen1_1` | `95,255,175` | `#5fffaf`
`86` | `aquamarine1` | `95,255,215` | `#5fffd7`
`87` | `darkslategray2` | `95,255,255` | `#5fffff`
`88` | `darkred_1` | `135,0,0` | `#870000`
`89` | `deeppink4_1` | `135,0,95` | `#87005f`
`90` | `darkmagenta` | `135,0,135` | `#870087`
`91` | `darkmagenta_1` | `135,0,175` | `#8700af`
`92` | `darkviolet` | `135,0,215` | `#8700d7`
`93` | `purple_1` | `135,0,255` | `#8700ff`
`94` | `orange4_1` | `135,95,0` | `#875f00`
`95` | `lightpink4` | `135,95,95` | `#875f5f`
`96` | `plum4` | `135,95,135` | `#875f87`
`97` | `mediumpurple3` | `135,95,175` | `#875faf`
`98` | `mediumpurple3_1` | `135,95,215` | `#875fd7`
`99` | `slateblue1` | `135,95,255` | `#875fff`
`100` | `yellow4` | `135,135,0` | `#878700`
`101` | `wheat4` | `135,135,95` | `#87875f`
`102` | `grey53` | `135,135,135` | `#878787`
`103` | `lightslategrey` | `135,135,175` | `#8787af`
`104` | `mediumpurple` | `135,135,215` | `#8787d7`
`105` | `lightslateblue` | `135,135,255` | `#8787ff`
`106` | `yellow4_1` | `135,175,0` | `#87af00`
`107` | `darkolivegreen3` | `135,175,95` | `#87af5f`
`108` | `darkseagreen` | `135,175,135` | `#87af87`
`109` | `lightskyblue3` | `135,175,175` | `#87afaf`
`110` | `lightskyblue3_1` | `135,175,215` | `#87afd7`
`111` | `skyblue2` | `135,175,255` | `#87afff`
`112` | `chartreuse2_1` | `135,215,0` | `#87d700`
`113` | `darkolivegreen3_1` | `135,215,95` | `#87d75f`
`114` | `palegreen3_1` | `135,215,135` | `#87d787`
`115` | `darkseagreen3` | `135,215,175` | `#87d7af`
`116` | `darkslategray3` | `135,215,215` | `#87d7d7`
`117` | `skyblue1` | `135,215,255` | `#87d7ff`
`118` | `chartreuse1` | `135,255,0` | `#87ff00`
`119` | `lightgreen` | `135,255,95` | `#87ff5f`
`120` | `lightgreen_1` | `135,255,135` | `#87ff87`
`121` | `palegreen1` | `135,255,175` | `#87ffaf`
`122` | `aquamarine1_1` | `135,255,215` | `#87ffd7`
`123` | `darkslategray1` | `135,255,255` | `#87ffff`
`124` | `red3` | `175,0,0` | `#af0000`
`125` | `deeppink4_2` | `175,0,95` | `#af005f`
`126` | `mediumvioletred` | `175,0,135` | `#af0087`
`127` | `magenta3` | `175,0,175` | `#af00af`
`128` | `darkviolet_1` | `175,0,215` | `#af00d7`
`129` | `purple_2` | `175,0,255` | `#af00ff`
`130` | `darkorange3` | `175,95,0` | `#af5f00`
`131` | `indianred` | `175,95,95` | `#af5f5f`
`132` | `hotpink3` | `175,95,135` | `#af5f87`
`133` | `mediumorchid3` | `175,95,175` | `#af5faf`
`134` | `mediumorchid` | `175,95,215` | `#af5fd7`
`135` | `mediumpurple2` | `175,95,255` | `#af5fff`
`136` | `darkgoldenrod` | `175,135,0` | `#af8700`
`137` | `lightsalmon3` | `175,135,95` | `#af875f`
`138` | `rosybrown` | `175,135,135` | `#af8787`
`139` | `grey63` | `175,135,175` | `#af87af`
`140` | `mediumpurple2_1` | `175,135,215` | `#af87d7`
`141` | `mediumpurple1` | `175,135,255` | `#af87ff`
`142` | `gold3` | `175,175,0` | `#afaf00`
`143` | `darkkhaki` | `175,175,95` | `#afaf5f`
`144` | `navajowhite3` | `175,175,135` | `#afaf87`
`145` | `grey69` | `175,175,175` | `#afafaf`
`146` | `lightsteelblue3` | `175,175,215` | `#afafd7`
`147` | `lightsteelblue` | `175,175,255` | `#afafff`
`148` | `yellow3` | `175,215,0` | `#afd700`
`149` | `darkolivegreen3_2` | `175,215,95` | `#afd75f`
`150` | `darkseagreen3_1` | `175,215,135` | `#afd787`
`151` | `darkseagreen2` | `175,215,175` | `#afd7af`
`152` | `lightcyan3` | `175,215,215` | `#afd7d7`
`153` | `lightskyblue1` | `175,215,255` | `#afd7ff`
`154` | `greenyellow` | `175,255,0` | `#afff00`
`155` | `darkolivegreen2` | `175,255,95` | `#afff5f`
`156` | `palegreen1_1` | `175,255,135` | `#afff87`
`157` | `darkseagreen2_1` | `175,255,175` | `#afffaf`
`158` | `darkseagreen1` | `175,255,215` | `#afffd7`
`159` | `paleturquoise1` | `175,255,255` | `#afffff`
`160` | `red3_1` | `215,0,0` | `#d70000`
`161` | `deeppink3` | `215,0,95` | `#d7005f`
`162` | `deeppink3_1` | `215,0,135` | `#d70087`
`163` | `magenta3_1` | `215,0,175` | `#d700af`
`164` | `magenta3_2` | `215,0,215` | `#d700d7`
`165` | `magenta2` | `215,0,255` | `#d700ff`
`166` | `darkorange3_1` | `215,95,0` | `#d75f00`
`167` | `indianred_1` | `215,95,95` | `#d75f5f`
`168` | `hotpink3_1` | `215,95,135` | `#d75f87`
`169` | `hotpink2` | `215,95,175` | `#d75faf`
`170` | `orchid` | `215,95,215` | `#d75fd7`
`171` | `mediumorchid1` | `215,95,255` | `#d75fff`
`172` | `orange3` | `215,135,0` | `#d78700`
`173` | `lightsalmon3_1` | `215,135,95` | `#d7875f`
`174` | `lightpink3` | `215,135,135` | `#d78787`
`175` | `pink3` | `215,135,175` | `#d787af`
`176` | `plum3` | `215,135,215` | `#d787d7`
`177` | `violet` | `215,135,255` | `#d787ff`
`178` | `gold3_1` | `215,175,0` | `#d7af00`
`179` | `lightgoldenrod3` | `215,175,95` | `#d7af5f`
`180` | `tan` | `215,175,135` | `#d7af87`
`181` | `mistyrose3` | `215,175,175` | `#d7afaf`
`182` | `thistle3` | `215,175,215` | `#d7afd7`
`183` | `plum2` | `215,175,255` | `#d7afff`
`184` | `yellow3_1` | `215,215,0` | `#d7d700`
`185` | `khaki3` | `215,215,95` | `#d7d75f`
`186` | `lightgoldenrod2` | `215,215,135` | `#d7d787`
`187` | `lightyellow3` | `215,215,175` | `#d7d7af`
`188` | `grey84` | `215,215,215` | `#d7d7d7`
`189` | `lightsteelblue1` | `215,215,255` | `#d7d7ff`
`190` | `yellow2` | `215,255,0` | `#d7ff00`
`191` | `darkolivegreen1` | `215,255,95` | `#d7ff5f`
`192` | `darkolivegreen1_1` | `215,255,135` | `#d7ff87`
`193` | `darkseagreen1_1` | `215,255,175` | `#d7ffaf`
`194` | `honeydew2` | `215,255,215` | `#d7ffd7`
`195` | `lightcyan1` | `215,255,255` | `#d7ffff`
`196` | `red1` | `255,0,0` | `#ff0000`
`197` | `deeppink2` | `255,0,95` | `#ff005f`
`198` | `deeppink1` | `255,0,135` | `#ff0087`
`199` | `deeppink1_1` | `255,0,175` | `#ff00af`
`200` | `magenta2_1` | `255,0,215` | `#ff00d7`
`201` | `magenta1` | `255,0,255` | `#ff00ff`
`202` | `orangered1` | `255,95,0` | `#ff5f00`
`203` | `indianred1` | `255,95,95` | `#ff5f5f`
`204` | `indianred1_1` | `255,95,135` | `#ff5f87`
`205` | `hotpink` | `255,95,175` | `#ff5faf`
`206` | `hotpink_1` | `255,95,215` | `#ff5fd7`
`207` | `mediumorchid1_1` | `255,95,255` | `#ff5fff`
`208` | `darkorange` | `255,135,0` | `#ff8700`
`209` | `salmon1` | `255,135,95` | `#ff875f`
`210` | `lightcoral` | `255,135,135` | `#ff8787`
`211` | `palevioletred1` | `255,135,175` | `#ff87af`
`212` | `orchid2` | `255,135,215` | `#ff87d7`
`213` | `orchid1` | `255,135,255` | `#ff87ff`
`214` | `orange1` | `255,175,0` | `#ffaf00`
`215` | `sandybrown` | `255,175,95` | `#ffaf5f`
`216` | `lightsalmon1` | `255,175,135` | `#ffaf87`
`217` | `lightpink1` | `255,175,175` | `#ffafaf`
`218` | `pink1` | `255,175,215` | `#ffafd7`
`219` | `plum1` | `255,175,255` | `#ffafff`
`220` | `gold1` | `255,215,0` | `#ffd700`
`221` | `lightgoldenrod2_1` | `255,215,95` | `#ffd75f`
`222` | `lightgoldenrod2_2` | `255,215,135` | `#ffd787`
`223` | `navajowhite1` | `255,215,175` | `#ffd7af`
`224` | `mistyrose1` | `255,215,215` | `#ffd7d7`
`225` | `thistle1` | `255,215,255` | `#ffd7ff`
`226` | `yellow1` | `255,255,0` | `#ffff00`
`227` | `lightgoldenrod1` | `255,255,95` | `#ffff5f`
`228` | `khaki1` | `255,255,135` | `#ffff87`
`229` | `wheat1` | `255,255,175` | `#ffffaf`
`230` | `cornsilk1` | `255,255,215` | `#ffffd7`
`231` | `grey100` | `255,255,255` | `#ffffff`
`232` | `grey3` | `8,8,8` | `#080808`
`233` | `grey7` | `18,18,18` | `#121212`
`234` | `grey11` | `28,28,28` | `#1c1c1c`
`235` | `grey15` | `38,38,38` | `#262626`
`236` | `grey19` | `48,48,48` | `#303030`
`237` | `grey23` | `58,58,58` | `#3a3a3a`
`238` | `grey27` | `68,68,68` | `#444444`
`239` | `grey30` | `78,78,78` | `#4e4e4e`
`240` | `grey35` | `88,88,88` | `#585858`
`241` | `grey39` | `98,98,98` | `#626262`
`242` | `grey42` | `108,108,108` | `#6c6c6c`
`243` | `grey46` | `118,118,118` | `#767676`
`244` | `grey50` | `128,128,128` | `#808080`
`245` | `grey54` | `138,138,138` | `#8a8a8a`
`246` | `grey58` | `148,148,148` | `#949494`
`247` | `grey62` | `158,158,158` | `#9e9e9e`
`248` | `grey66` | `168,168,168` | `#a8a8a8`
`249` | `grey70` | `178,178,178` | `#b2b2b2`
`250` | `grey74` | `188,188,188` | `#bcbcbc`
`251` | `grey78` | `198,198,198` | `#c6c6c6`
`252` | `grey82` | `208,208,208` | `#d0d0d0`
`253` | `grey85` | `218,218,218` | `#dadada`
`254` | `grey89` | `228,228,228` | `#e4e4e4`
`255` | `grey93` | `238,238,238` | `#eeeeee`
```

View File

@@ -1,10 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
<DefaultItemExcludes>$(DefaultItemExcludes);output\**;.gitignore</DefaultItemExcludes>
<MinVerSkip Condition="'$(Configuration)' == 'Debug'">true</MinVerSkip>
</PropertyGroup>
<ItemGroup>
@@ -22,8 +23,27 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Statiq.Web" Version="1.0.0-alpha.9" />
<PackageReference Include="NJsonSchema" Version="10.1.12" />
<None Remove="src\Data\emojis.json" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="src\Data\emojis.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Statiq.Web" Version="1.0.0-beta.5" />
<PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.0" />
</ItemGroup>
<ItemGroup>
<Folder Include="input\assets\images\emojis\" />
</ItemGroup>
<Target Name="Versioning" BeforeTargets="MinVer">
<PropertyGroup Label="Build">
<MinVerDefaultPreReleasePhase>preview</MinVerDefaultPreReleasePhase>
<MinVerVerbosity>normal</MinVerVerbosity>
</PropertyGroup>
</Target>
</Project>

1
docs/Preview.ps1 Normal file
View File

@@ -0,0 +1 @@
dotnet run -- preview --virtual-dir "spectre.console"

View File

@@ -19,6 +19,7 @@ namespace Docs
.ConfigureDeployment(deployBranch: "docs")
.AddShortcode("Children", typeof(ChildrenShortcode))
.AddShortcode("ColorTable", typeof(ColorTableShortcode))
.AddShortcode("EmojiTable", typeof(EmojiTableShortcode))
.AddPipelines()
.RunAsync();

View File

@@ -1,8 +1,50 @@
# Documentation
Preview the documentation locally by running the following
from your favourite shell:
To start contributing to the [Spectre.Console](https://github.com/spectresystems/spectre.console) documentation, you will need the [.NET Core SDK](https://dot.net) 3.1 or higher.
## Running Preview Site
The documentation site uses [Statiq](https://statiq.dev), a static site generator. To build the documentation site run the following in a command-line terminal.
```
> dotnet run -- preview --virtual-dir "spectre.console"
```
> dotnet run preview --virtual-dir "spectre.console"
```
After the build is complete, you can navigate to [http://localhost:5080/spectre.consle](http://localhost:5080/spectre.console).
**Note that the site runs under a virtual directory.**
## Editing Content
The documentation is written using [Markdown](https://www.markdownguide.org/basic-syntax/).
Markdown files can be found under the following directories:
- [/input](./input)
- [/appendix](./input/appendix)
## Editing Layout
Layout and styling can also be found in the [input](./input) directory. Look for Sass, Css, and Images under the [assets](./input/assets) directory.
## Custom Build Features
The documentation site has custom enhancements to Statiq located under the [./src](./src) directory. Enhancements to the build process include:
- [Extension Methods](./src/Extensions)
- [Models](./src/Models)
- [Pipelines](./src/Pipelines)
- [Shortcodes](./src/Shortcodes)
- [Utilities](./src/Utilities)
## License
MIT License
Copyright (c) 2020 Spectre Systems AB
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@@ -1,12 +1,12 @@
<!DOCTYPE html>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link href="/spectre.console/assets/bootstrap/bootstrap.css" rel="stylesheet" />
<link href="/spectre.console/assets/css/styles.css" rel="stylesheet" />
<link href="@Context.GetLink("/assets/bootstrap/bootstrap.css")" rel="stylesheet" />
<link href="@Context.GetLink("/assets/css/styles.css")" rel="stylesheet" />
<link href="https://fonts.googleapis.com/css2?family=Roboto+Mono:wght@400;700&family=Roboto+Slab:wght@400;700&family=Roboto:ital,wght@0,300;0,400;0,700;1,300;1,400;1,700&display=swap" rel="stylesheet" data-no-mirror>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/prismjs@1.19.0/themes/prism.css">
@@ -29,7 +29,7 @@
<nav id="topnav" class="navbar navbar-expand-lg navbar-light">
<div class="container py-3">
<a class="navbar-brand" href="/spectre.console/docs"><img id="logo" src="/spectre.console/assets/logo.svg" alt="Spectre.Console"> Spectre.Console</a>
<a class="navbar-brand" href="@Context.GetLink("/")"><img id="logo" src="@Context.GetLink("/assets/logo.svg")" alt="Spectre.Console"> Spectre.Console</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
@@ -52,8 +52,8 @@
{
@RenderSection(Constants.Sections.Splash, false)
}
@{
string section = Document.Destination.Segments.Length > 1 ? Document.Destination.Segments[0].ToString() : null;
@{
string section = "docs";
}
<div class="flex-grow-1 d-flex bg-body flex-column @(section != null ? "section-" + section : null)">
@@ -62,7 +62,7 @@
<div id="titlebar" class="py-4">
<div class="container">
<div class="row">
@{
@{
string titleBarClasses = Document.GetBool(Constants.NoSidebar) ? string.Empty : "offset-md-3 offset-lg-2";
}
<div class="@titleBarClasses px-3 px-md-0">
@@ -97,7 +97,7 @@
</div>
</div>
}
<div class="flex-grow-1 d-flex flex-column bg-body">
@if (Document.GetBool(Constants.NoContainer))
{
@@ -126,21 +126,36 @@
}
else
{
IDocument root = Outputs[nameof(Content)].First(x => x.Destination == section + "/index.html");
IDocument root = OutputPages["index.html"].First();
<div class="sidebar-nav-item @(Document.IdEquals(root) ? "active" : null)">
@Html.DocumentLink(root)
@if(root.ShowLink())
{
@Html.DocumentLink(root)
}
else
{
@root.GetTitle()
}
</div>
@foreach (IDocument document in root.GetChildren().OnlyVisible())
@foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible())
{
<div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(document.HasChildren() ? "has-children" : null)">
@Html.DocumentLink(document)
DocumentList<IDocument> documentChildren = OutputPages.GetChildrenOf(document);
<div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(documentChildren.Any() ? "has-children" : null)">
@if(document.ShowLink())
{
@Html.DocumentLink(document)
}
else
{
@document.GetTitle()
}
</div>
@if (document.HasVisibleChildren())
@if (documentChildren.OnlyVisible().Any())
{
<div class="sidebar-nav-children @(Document.IdEquals(document) || document.GetChildren().Any(x => Document.IdEquals(x)) ? "active" : null)">
@foreach (IDocument child in document.GetChildren().OnlyVisible())
<div class="sidebar-nav-children @(Document.IdEquals(document) || documentChildren.Any(x => Document.IdEquals(x)) ? "active" : null)">
@foreach (IDocument child in documentChildren.OnlyVisible())
{
<div class="sidebar-nav-child @(Document.IdEquals(child) ? "active" : null)">
@Html.DocumentLink(child)
@@ -182,7 +197,10 @@
</div>
<div id="footer" class="p-3 text-white font-size-sm">
<div class="container">
<div>© @DateTime.Today.Year Spectre Systems AB</div>
<div>
<span>© @DateTime.Today.Year Spectre Systems AB</span>
<span class="float-right" style="color: #888888;">@VersionUtilities.GetVersion()</span>
</div>
</div>
</div>
<script>
@@ -195,7 +213,7 @@
},
startOnLoad: false,
cloneCssStyles: false
});
});
mermaid.init(undefined, ".mermaid");
// Remove the max-width setting that Mermaid sets
@@ -214,13 +232,13 @@
center: true,
maxZoom: 20,
zoomScaleSensitivity: 0.6
});
});
// Do the reset once right away to fit the diagram
panZoom.resize();
panZoom.fit();
panZoom.center();
$(window).resize(function(){
panZoom.resize();
panZoom.fit();

View File

@@ -3,5 +3,6 @@
@using Statiq.Web
@using Statiq.Web.Pipelines
@using Docs
@using Docs.Utilities;
@inherits StatiqRazorPage<IDocument>

View File

@@ -0,0 +1,33 @@
Title: Borders
Order: 2
---
There is different built-in borders you can use for tables and panels.
# Table borders
<img src="../assets/images/borders/table.png" style="max-width: 100%;">
## Example
To set a table border to `SimpleHeavy`:
```csharp
var table = new Table();
table.Border = TableBorder.SimpleHeavy;
```
---
# Panel borders
<img src="../assets/images/borders/panel.png" style="max-width: 100%;">
## Example
To set a panel border to `Rounded`:
```csharp
var panel = new Panel("Hello World");
panel.Border = BoxBorder.Rounded;
```

View File

@@ -0,0 +1,31 @@
Title: Colors
Order: 0
---
The following is a list of the standard 8-bit colors supported in terminals.
Note that the first 16 colors are generally defined by the system or your terminal software, and may not display exactly as rendered here.
# Usage
You can either use the colors in code, such as `new Style(foreground: Color.Maroon)` or
in markup text such as `AnsiConsole.Markup("[maroon on blue]Hello[/]")`.
# Standard colors
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">
<i class="fas fa-search" aria-hidden="true"></i>
</span>
</div>
<input
class="form-control w-100 filter"
data-table="color-results"
type="text" placeholder="Search Colors..." autocomplete="off"
aria-label="Search Colors">
</div>
<?# ColorTable /?>
<script type="text/javascript" src="../assets/js/table-search.js"></script>

View File

@@ -0,0 +1,72 @@
Title: Emojis
Order: 3
---
Please note that what emojis that can be used is completely up to
the operating system and/or terminal you're using, and no guarantees
can be made of how it will look. Calculating the width of emojis
is also not an exact science in many ways, so milage might vary when
used in tables, panels or grids.
To ensure best compatibility, consider only using emojis introduced
before Unicode 13.0 that belongs in the `Emoji_Presentation` category
in the official emoji list at
https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt
# Usage
```csharp
// Markup
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
// Constant
var hello = "Hello " + Emoji.Known.GlobeShowingEuropeAfrica;
```
# Replacing emojis in text
```csharp
var phrase = "Mmmm :birthday_cake:";
var rendered = Emoji.Replace(phrase);
```
# Remapping or adding an emoji
Sometimes you want to remap an existing emoji, or
add a completely new one. For this you can use the
`Emoji.Remap` method. This approach works both with
markup strings and `Emoji.Replace`.
```csharp
// Remap the emoji
Emoji.Remap("globe_showing_europe_africa", "😄");
// Render markup
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
// Replace emojis in string
var phrase = "Hello :globe_showing_europe_africa:!";
var rendered = Emoji.Replace(phrase);
```
# Emojis
_The images in the table below might not render correctly in your
browser for the same reasons mentioned in the `Compatibility` section._
<div class="input-group mb-3">
<div class="input-group-prepend">
<span class="input-group-text" id="basic-addon1">
<i class="fas fa-search" aria-hidden="true"></i>
</span>
</div>
<input
class="form-control w-100 filter"
data-table="emoji-results"
type="text" placeholder="Search Emojis..." autocomplete="off"
aria-label="Search Emojis">
</div>
<?# EmojiTable /?>
<script type="text/javascript" src="../assets/js/table-search.js"></script>

View File

@@ -0,0 +1,12 @@
Title: Appendix
Order: 10
---
<h1>Sections</h1>
<ul>
@foreach (IDocument child in OutputPages.GetChildrenOf(Document))
{
<li>@Html.DocumentLink(child)</li>
}
</ul>

View File

@@ -0,0 +1,44 @@
Title: Styles
Order: 1
---
Note that what styles that can be used is defined by the system or your terminal software, and may not appear as they should.
<table class="table">
<tr>
<td><code>bold</code></td>
<td>Bold text</td>
</tr>
<tr>
<td><code>dim</code></td>
<td>Dim or faint text</td>
</tr>
<tr>
<td><code>italic</code></td>
<td>Italic text</td>
</tr>
<tr>
<td><code>underline</code></td>
<td>Underlined text</td>
</tr>
<tr>
<td><code>invert</code></td>
<td>Swaps the foreground and background colors</td>
</tr>
<tr>
<td><code>conceal</code></td>
<td>Hides the text</td>
</tr>
<tr>
<td><code>slowblink</code></td>
<td>Makes text blink slowly</td>
</tr>
<tr>
<td><code>rapidblink</code></td>
<td>Makes text blink</td>
</tr>
<tr>
<td><code>strikethrough</code></td>
<td>Shows text with a horizontal line through the center</td>
</tr>
</table>

View File

@@ -18,6 +18,7 @@ $thebackground: $gray-200;
display: inline-block;
width: 60px;
height: 15px;
border: 2px solid #000000;
}
#topnav {

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 503 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 163 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 159 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 421 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 55 KiB

View File

@@ -0,0 +1,35 @@
$(document).ready(function () {
$('.filter').each(function () {
let input = this;
let table = document.getElementById(input.dataset.table);
input.onkeyup = function (event) {
if (event.key === "Enter") {
event.preventDefault();
event.stopPropagation();
return false;
}
let value = input.value.toUpperCase();
let rows = table.getElementsByClassName('search-row');
for (let i = 0; i < rows.length; i++) {
let row = rows[i];
let match =
new RegExp(value, "i").test(row.textContent) ||
value === '';
if (match) {
row.style.display = 'table-row';
} else {
row.style.display = 'none';
}
}
}; // keyup
})
}); // ready

View File

@@ -1,16 +0,0 @@
Title: Colors
Order: 2
---
The following is a list of the standard 8-bit colors supported in terminals.
Note that the first 16 colors are generally defined by the system or your terminal software, and may not display exactly as rendered here.
# Usage
You can either use the colors in code, such as `new Style(foreground: Color.Maroon)` or
in markup text such as `AnsiConsole.Markup("[maroon on blue]Hello[/]")`.
# Standard colors
<?# ColorTable /?>

View File

@@ -1,6 +0,0 @@
Title: Console API
Order: 2
Hidden: True
---
__To be written__

View File

@@ -1,6 +0,0 @@
Title: Grids
Order: 4
Hidden: True
---
__To be written__

View File

@@ -1,6 +0,0 @@
Title: Panels
Order: 5
Hidden: True
---
__To be written__

View File

@@ -1,6 +0,0 @@
Title: Tables
Order: 3
Hidden: True
---
__To be written__

52
docs/input/exceptions.md Normal file
View File

@@ -0,0 +1,52 @@
Title: Exceptions
Order: 3
---
Exceptions isn't always readable when viewed in the terminal.
You can make exception a bit more readable by using the `WriteException` method.
```csharp
AnsiConsole.WriteException(ex);
```
<img src="assets/images/exception.png" style="max-width: 100%;">
## Shortening parts
You can also shorten specific parts of the exception to make it even
more readable, and make paths clickable hyperlinks. Whether or not
the hyperlinks are clickable is up to the terminal.
```csharp
AnsiConsole.WriteException(ex,
ExceptionFormat.ShortenPaths | ExceptionFormat.ShortenTypes |
ExceptionFormat.ShortenMethods | ExceptionFormat.ShowLinks);
```
<img src="assets/images/compact_exception.png" style="max-width: 100%;">
## Customizing exception output
In addition to shorten specific part of the exception, you can
also override the default styling.
```csharp
AnsiConsole.WriteException(ex, new ExceptionSettings
{
Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
Style = new ExceptionStyle
{
Exception = Style.WithForeground(Color.Grey),
Message = Style.WithForeground(Color.White),
NonEmphasized = Style.WithForeground(Color.Cornsilk1),
Parenthesis = Style.WithForeground(Color.Cornsilk1),
Method = Style.WithForeground(Color.Red),
ParameterName = Style.WithForeground(Color.Cornsilk1),
ParameterType = Style.WithForeground(Color.Red),
Path = Style.WithForeground(Color.Red),
LineNumber = Style.WithForeground(Color.Cornsilk1),
}
});
```
<img src="assets/images/custom_exception.png" style="max-width: 100%;">

View File

@@ -1,15 +0,0 @@
Title: Start
NoContainer: true
---
@section Splash {
<div id="hero" class="jumbotron jumbotron-fluid mb-0">
<div class="container">
<div class="display-4 text-white">Spectre.Console</div>
<p class="lead text-white">
A .NET Standard library that makes it easier to create beautiful console applications.
<br /><br />
<a class="btn btn-primary" href="/spectre.console/docs" role="button">Take me to the documentation</a>
</p>
</div>
</div>
}

View File

@@ -13,14 +13,14 @@ for Python written by Will McGugan.
* Supports tables, grids, panels, and a [Rich](https://github.com/willmcgugan/rich)
inspired markup language.
* Supports the most common
[SRG parameters](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters)
[SGR parameters](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters)
when it comes to text styling such as bold, dim, italic, underline, strikethrough,
and blinking text.
* Supports `3`/`4`/`8`/`24`-bit colors in the terminal.
The library will detect the capabilities of the current terminal
and downgrade colors as needed.
## Example
## Examples
<img width="100%"
src="https://github.com/spectresystems/spectre.console/raw/main/resources/gfx/screenshots/example.png" />
<img src="assets/images/table.gif" style="max-width: 100%; margin-top: 15px; margin-bottom: 25px;" />
<img src="https://github.com/spectresystems/spectre.console/raw/main/resources/gfx/screenshots/example.png" style="max-width: 100%;" />

87
docs/input/markup.md Normal file
View File

@@ -0,0 +1,87 @@
Title: Markup
Order: 2
---
The class `Markup` allows you to output rich text to the console.
# Syntax
Console markup uses a syntax inspired by bbcode. If you write the style (see Styles)
in square brackets, e.g. `[bold red]`, that style will apply until it is closed with a `[/]`.
```csharp
AnsiConsole.Render(new Markup("[bold yellow]Hello[/] [red]World![/]"));
```
The `Markup` class implements `IRenderable` which means that you
can use this in tables, grids, and panels. Most classes that support
rendering of `IRenderable` also have overloads for rendering rich text.
```csharp
var table = new Table();
table.AddColumn(new TableColumn(new Markup("[yellow]Foo[/]")));
table.AddColumn(new TableColumn("[blue]Bar[/]"));
```
# Convenience methods
There is also convenience methods on `AnsiConsole` that can be used
to write markup text to the console without instantiating a new `Markup`
instance.
```csharp
AnsiConsole.Markup("[underline green]Hello[/] ");
AnsiConsole.MarkupLine("[bold]World[/]");
```
# Escaping format characters
To output a `[` you use `[[`, and to output a `]` you use `]]`.
```csharp
AnsiConsole.Markup("[[Hello]] "); // [Hello]
AnsiConsole.Markup("[red][[World]][/]"); // [World]
```
You can also use the `SafeMarkup` extension method.
```csharp
AnsiConsole.Markup("[red]{0}[/]", "Hello [World]".SafeMarkup());
```
# Setting background color
You can set the background color in markup by prefixing the color with
`on`.
```
[bold yellow on blue]Hello[/]
[default on blue]World[/]
```
# Rendering emojis
To output an emoji as part of markup, you can use emoji shortcodes.
```csharp
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
```
For a list of emoji, see the [Emojis](xref:emojis) appendix section.
# Colors
In the examples above, all colors was referenced by their name,
but you can also use the hex or rgb representation for colors in markdown.
```csharp
AnsiConsole.Markup("[red]Foo[/] ");
AnsiConsole.Markup("[#ff0000]Bar[/] ");
AnsiConsole.Markup("[rgb(255,0,0)]Baz[/] ");
```
For a list of colors, see the [Colors](xref:colors) appendix section.
# Styles
For a list of styles, see the [Styles](xref:styles) appendix section.

View File

@@ -0,0 +1,114 @@
Title: Calendar
Order: 4
RedirectFrom: calendar
---
The `Calendar` is used to render a calendar to the terminal.
# Usage
To render a calendar, create a `Calendar` instance with a target date.
```csharp
var calendar = new Calendar(2020,10);
AnsiConsole.Render(calendar);
2020 October
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
Sun Mon Tue Wed Thu Fri Sat
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
```
## Culture
You can set the calendar's culture to show localized weekdays.
```csharp
var calendar = new Calendar(2020,10);
calendar.SetCulture("ja-JP");
AnsiConsole.Render(calendar);
202010
┌────┬────┬────┬────┬────┬────┬────┐
├────┼────┼────┼────┼────┼────┼────┤
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
└────┴────┴────┴────┴────┴────┴────┘
```
## Header
You can hide the calendar header.
```csharp
var calendar = new Calendar(2020,10);
calendar.ShowHeader = false;
AnsiConsole.Render(calendar);
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
Sun Mon Tue Wed Thu Fri Sat
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
```
You can set the header style of the calendar.
```csharp
var calendar = new Calendar(2020,10);
calendar.SetHeaderStyle(Style.Parse("blue bold"));
AnsiConsole.Render(calendar);
```
## Calendar Event
You can add an event to the calendar.
If a date has an event associated with it, the date gets highlighted in the calendar.
```csharp
var calendar = new Calendar(2020,10);
calendar.AddCalendarEvent(2020, 10, 11);
AnsiConsole.Render(calendar);
2020 October
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
Sun Mon Tue Wed Thu Fri Sat
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
1 2 3
4 5 6 7 8 9 10
11* 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
```
### Highlight style
You can set the highlight style for a calendar event via `SetHighlightStyle`.
```csharp
var calendar = new Calendar(2020,10);
calendar.AddCalendarEvent(2020, 10, 11);
calendar.SetHighlightStyle(Style.Parse("yellow bold"));
AnsiConsole.Render(calendar);
```

View File

@@ -0,0 +1,3 @@
Title: Widgets
Order: 9
---

View File

@@ -0,0 +1,71 @@
Title: Rule
Order: 5
RedirectFrom: rule
---
The `Rule` class is used to render a horizontal rule (line) to the terminal.
![Rule](../assets/images/rule.png)
# Usage
To render a rule without a title:
```csharp
var rule = new Rule();
AnsiConsole.Render(rule);
```
## Title
You can set the rule title markup text.
```csharp
var rule = new Rule("[red]Hello[/]");
AnsiConsole.Render(rule);
// output
───────────────────────────────── Hello ─────────────────────────────────
```
### Title alignment
You can set the rule's title alignment.
```csharp
var rule = new Rule("[red]Hello[/]");
rule.Alignment = Justify.Left;
AnsiConsole.Render(rule);
//output
── Hello ────────────────────────────────────────────────────────────────
```
You can also specify it with a method
```csharp
var rule = new Rule("[red]Hello[/]");
rule.LeftAligned();
AnsiConsole.Render(rule);
//output
── Hello ────────────────────────────────────────────────────────────────
```
## Style
You can set the rule style.
```csharp
var rule = new Rule("[red]Hello[/]");
rule.Style = Style.Parse("red dim");
AnsiConsole.Render(rule);
```
You can also specify it with a method
```csharp
var rule = new Rule("[red]Hello[/]");
rule.SetStyle("red dim");
AnsiConsole.Render(rule);
```

121
docs/input/widgets/table.md Normal file
View File

@@ -0,0 +1,121 @@
Title: Table
Order: 3
RedirectFrom: tables
---
Tables are a perfect way of displaying tabular data in a terminal.
`Spectre.Console` is super smart about rendering tables and will adjust
all columns to fit whatever is inside them. Anything that implements
`IRenderable` can be used as a column header or column cell, even another table!
# Usage
<!------------------------->
<!--- USAGE --->
<!------------------------->
To render a table, create a `Table` instance, add the number of
columns that you need, and then add the rows. Finish by passing the
table to a console's `Render` method.
```csharp
// Create a table
var table = new Table();
// Add some columns
table.AddColumn("Foo");
table.AddColumn(new TableColumn("Bar").Centered());
// Add some rows
table.AddRow("Baz", "[green]Qux[/]");
table.AddRow(new Markup("[blue]Corgi[/]"), new Panel("Waldo"));
// Render the table to the console
AnsiConsole.Render(table);
```
This will render the following output:
![Table](../assets/images/table.png)
# Table appearance
<!------------------------->
<!--- TABLE APPEARANCE --->
<!------------------------->
## Borders
For a list of borders, see the [Borders](xref:borders) appendix section.
```csharp
// Sets the border
table.SetBorder(Border.None);
table.SetBorder(Border.Ascii);
table.SetBorder(Border.Square);
table.SetBorder(Border.Rounded);
```
## Expand / Collapse
```csharp
// Table will take up as much space as it can
// with respect to other things.
table.Expand();
// Table will take up minimal width
table.Collapse();
```
## Hide headers
```csharp
// Hides all column headers
table.HideHeaders();
```
## Set table width
```csharp
// Sets the table width to 50 cells
table.SetWidth(50);
```
# Column appearance
<!------------------------->
<!--- COLUMN APPEARANCE --->
<!------------------------->
## Alignment
```csharp
// Set the alignment explicitly
column.SetAlignment(Justify.Right);
```
## Padding
```csharp
// Set left and right padding
column.SetPadding(left: 3, right: 5);
// Set padding individually.
column.PadLeft(3);
column.PadRight(5);
```
## Disable column wrapping
```csharp
// Disable column wrapping
column.NoWrap();
```
## Set column width
```csharp
// Set the column width (no fluent extension method for this yet)
column.Width = 15;
```

View File

@@ -1,14 +1,20 @@
namespace Docs
namespace Docs
{
public static class Constants
{
public const string NoContainer = nameof(NoContainer);
public const string NoSidebar = nameof(NoSidebar);
public const string NoLink = nameof(NoLink);
public const string Topic = nameof(Topic);
public const string EditLink = nameof(EditLink);
public const string Description = nameof(Description);
public const string Hidden = nameof(Hidden);
public static class Emojis
{
public const string Root = "EMOJIS_ROOT";
}
public static class Colors
{
public const string Url = "https://raw.githubusercontent.com/spectresystems/spectre.console/main/resources/scripts/Generator/Data/colors.json";

7946
docs/src/Data/emojis.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -20,10 +20,7 @@ namespace Docs
public static Bootstrapper ConfigureDeployment(this Bootstrapper bootstrapper, string deployBranch)
{
if (bootstrapper != null)
{
bootstrapper.AddSetting(Constants.Deployment.TargetBranch, deployBranch);
}
bootstrapper?.AddSetting(Constants.Deployment.TargetBranch, deployBranch);
return bootstrapper;
}
}

View File

@@ -1,4 +1,4 @@
using Statiq.Common;
using Statiq.Common;
using System.Collections.Generic;
using System.Linq;
@@ -11,20 +11,16 @@ namespace Docs
return document?.GetString(Constants.Description, string.Empty) ?? string.Empty;
}
public static bool HasVisibleChildren(this IDocument document)
{
if (document != null)
{
return document.HasChildren() && document.GetChildren().Any(x => x.IsVisible());
}
return false;
}
public static bool IsVisible(this IDocument document)
{
return !document.GetBool(Constants.Hidden, false);
}
public static bool ShowLink(this IDocument document)
{
return !document.GetBool(Constants.NoLink, false);
}
public static IEnumerable<IDocument> OnlyVisible(this IEnumerable<IDocument> source)
{
return source.Where(x => x.IsVisible());

20
docs/src/Models/Emoji.cs Normal file
View File

@@ -0,0 +1,20 @@
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
namespace Docs.Models
{
public sealed class Emoji
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Code { get; set; }
public static List<Emoji> Parse(string json)
{
return JsonConvert.DeserializeObject<List<Emoji>>(json);
}
}
}

View File

@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using Statiq.Common;
namespace Docs.Modules
{
public sealed class ReadEmbedded : Module
{
private readonly System.Reflection.Assembly _assembly;
private readonly string _resource;
public ReadEmbedded(System.Reflection.Assembly assembly, string resource)
{
_assembly = assembly ?? throw new ArgumentNullException(nameof(assembly));
_resource = resource ?? throw new ArgumentNullException(nameof(resource));
}
protected override Task<IEnumerable<IDocument>> ExecuteContextAsync(IExecutionContext context)
{
return Task.FromResult((IEnumerable<IDocument>)new[]
{
context.CreateDocument(ReadResource()),
});
}
private Stream ReadResource()
{
var resourceName = _resource.Replace("/", ".");
var stream = _assembly.GetManifestResourceStream(resourceName);
if (stream == null)
{
throw new InvalidOperationException("Could not load manifest resource stream.");
}
return stream;
}
}
}

View File

@@ -1,8 +1,7 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using Docs.Models;
using NJsonSchema;
using Statiq.Common;
using Statiq.Core;
@@ -10,15 +9,13 @@ namespace Docs.Pipelines
{
public class ColorsPipeline : Pipeline
{
public const string Url = "https://raw.githubusercontent.com/spectresystems/spectre.console/main/resources/scripts/Generator/Data/colors.json";
public ColorsPipeline()
{
InputModules = new ModuleList
{
new ExecuteConfig(
Config.FromContext(ctx => {
return new ReadWeb(Url);
return new ReadWeb(Constants.Colors.Url);
}))
};
@@ -27,15 +24,10 @@ namespace Docs.Pipelines
new ExecuteConfig(
Config.FromDocument(async (doc, ctx) =>
{
var colors = Color.Parse(await doc.GetContentStringAsync()).ToList();
var definitions = new List<IDocument> { colors.ToDocument(Constants.Colors.Root) };
return doc.Clone(new MetadataDictionary
{
[Constants.Colors.Root] = definitions
});
var data = Color.Parse(await doc.GetContentStringAsync()).ToList();
return data.ToDocument(Constants.Colors.Root);
}))
};
}
}
}
}

View File

@@ -0,0 +1,34 @@
using System.Collections.Generic;
using Docs.Models;
using Docs.Modules;
using Statiq.Common;
using Statiq.Core;
namespace Docs.Pipelines
{
public class EmojiPipeline : Pipeline
{
public EmojiPipeline()
{
InputModules = new ModuleList
{
new ExecuteConfig(
Config.FromContext(ctx => {
return new ReadEmbedded(
typeof(EmojiPipeline).Assembly,
"Docs/src/Data/emojis.json");
}))
};
ProcessModules = new ModuleList
{
new ExecuteConfig(
Config.FromDocument(async (doc, ctx) =>
{
var data = Emoji.Parse(await doc.GetContentStringAsync());
return data.ToDocument(Constants.Emojis.Root);
}))
};
}
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using NJsonSchema;
using Statiq.Common;
using System.Xml.Linq;
using Docs.Pipelines;
@@ -18,12 +17,11 @@ namespace Docs.Shortcodes
// Get the definition.
var colors = context.Outputs
.FromPipeline(nameof(ColorsPipeline))
.First()
.GetChildren(Constants.Colors.Root)
.OfType<ObjectDocument<List<Color>>>()
.First().Object;
var table = new XElement("table", new XAttribute("class", "table"));
// Headers
var table = new XElement("table", new XAttribute("class", "table"), new XAttribute("id", "color-results"));
var header = new XElement("tr", new XAttribute("class", "color-row"));
header.Add(new XElement("th", ""));
header.Add(new XElement("th", "#"));
@@ -35,8 +33,8 @@ namespace Docs.Shortcodes
foreach (var color in colors)
{
var rep = new XElement("td",
new XElement("span",
var rep = new XElement("td",
new XElement("span",
new XAttribute("class", "color-representation"),
new XAttribute("style", $"background-color:{color.Hex};")));
var name = new XElement("td", new XElement("code", color.Number.ToString()));
@@ -46,7 +44,7 @@ namespace Docs.Shortcodes
var clr = new XElement("td", new XElement("code", color.ClrName));
// Create row
var row = new XElement("tr");
var row = new XElement("tr", new XAttribute("class", "search-row"));
row.Add(rep);
row.Add(name);
row.Add(number);

View File

@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Statiq.Common;
using System.Xml.Linq;
using Docs.Pipelines;
using Docs.Models;
namespace Docs.Shortcodes
{
public class EmojiTableShortcode : SyncShortcode
{
public override ShortcodeResult Execute(KeyValuePair<string, string>[] args, string content, IDocument document, IExecutionContext context)
{
var emojis = context.Outputs
.FromPipeline(nameof(EmojiPipeline))
.OfType<ObjectDocument<List<Emoji>>>()
.First().Object;
// Headers
var table = new XElement("table", new XAttribute("class", "table"), new XAttribute("id", "emoji-results"));
var header = new XElement("tr", new XAttribute("class", "emoji-row-header"));
header.Add(new XElement("th", ""));
header.Add(new XElement("th", "Markup"));
header.Add(new XElement("th", "Constant"));
table.Add(header);
foreach (var emoji in emojis)
{
var code = emoji.Code.Replace("U+0000", "U+").Replace("U+000", "U+");
var icon = $"&#x{emoji.Code.Replace("U+", string.Empty)};";
var row = new XElement("tr", new XAttribute("class", "search-row"));
row.Add(new XElement("td", icon));
row.Add(new XElement("td", new XElement("code", $":{emoji.Id}:")));
row.Add(new XElement("td", new XElement("code", emoji.Name)));
table.Add(row);
}
return table.ToString()
.Replace("&amp;#x", "&#x");
}
}
}

View File

@@ -0,0 +1,34 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Text;
namespace Docs.Utilities
{
public static class VersionUtilities
{
public static string GetVersion()
{
return GetVersion(typeof(VersionUtilities).Assembly);
}
private static string GetVersion(Assembly assembly)
{
if (assembly == null)
{
return "?";
}
try
{
var info = FileVersionInfo.GetVersionInfo(assembly.Location);
return info.ProductVersion ?? "?";
}
catch
{
return "?";
}
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Borders</Title>
<Description>Demonstrates the different kind of borders.</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,92 @@
using System.Diagnostics;
using Spectre.Console;
using Spectre.Console.Rendering;
namespace BordersExample
{
public static class Program
{
public static void Main()
{
// Render panel borders
HorizontalRule("PANEL BORDERS");
PanelBorders();
// Render table borders
HorizontalRule("TABLE BORDERS");
TableBorders();
}
private static void PanelBorders()
{
static IRenderable CreatePanel(string name, BoxBorder border)
{
return new Panel($"This is a panel with\nthe [yellow]{name}[/] border.")
.Header($" {name} ", Style.Parse("blue"), Justify.Center)
.Border(border)
.BorderStyle(Style.Parse("grey"));
}
var items = new[]
{
CreatePanel("Ascii", BoxBorder.Ascii),
CreatePanel("Square", BoxBorder.Square),
CreatePanel("Rounded", BoxBorder.Rounded),
CreatePanel("Heavy", BoxBorder.Heavy),
CreatePanel("Double", BoxBorder.Double),
CreatePanel("None", BoxBorder.None),
};
AnsiConsole.Render(
new Padder(
new Columns(items).PadRight(2),
new Padding(2,0,0,0)));
}
private static void TableBorders()
{
static IRenderable CreateTable(string name, TableBorder border)
{
var table = new Table().Border(border);
table.AddColumn("[yellow]Header 1[/]", c => c.Footer("[grey]Footer 1[/]"));
table.AddColumn("[yellow]Header 2[/]", col => col.Footer("[grey]Footer 2[/]").RightAligned());
table.AddRow("Cell", "Cell");
table.AddRow("Cell", "Cell");
return new Panel(table)
.Header($" {name} ", Style.Parse("blue"), Justify.Center)
.NoBorder();
}
var items = new[]
{
CreateTable("Ascii", TableBorder.Ascii),
CreateTable("Ascii2", TableBorder.Ascii2),
CreateTable("AsciiDoubleHead", TableBorder.AsciiDoubleHead),
CreateTable("Horizontal", TableBorder.Horizontal),
CreateTable("Simple", TableBorder.Simple),
CreateTable("SimpleHeavy", TableBorder.SimpleHeavy),
CreateTable("Minimal", TableBorder.Minimal),
CreateTable("MinimalHeavyHead", TableBorder.MinimalHeavyHead),
CreateTable("MinimalDoubleHead", TableBorder.MinimalDoubleHead),
CreateTable("Square", TableBorder.Square),
CreateTable("Rounded", TableBorder.Rounded),
CreateTable("Heavy", TableBorder.Heavy),
CreateTable("HeavyEdge", TableBorder.HeavyEdge),
CreateTable("HeavyHead", TableBorder.HeavyHead),
CreateTable("Double", TableBorder.Double),
CreateTable("DoubleEdge", TableBorder.DoubleEdge),
CreateTable("Markdown", TableBorder.Markdown),
};
AnsiConsole.Render(new Columns(items).Collapse());
}
private static void HorizontalRule(string title)
{
AnsiConsole.WriteLine();
AnsiConsole.Render(new Rule($"[white bold]{title}[/]").RuleStyle("grey").LeftAligned());
AnsiConsole.WriteLine();
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Calendars</Title>
<Description>Demonstrates how to render calendars.</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,19 @@
using Spectre.Console;
namespace Calendars
{
public static class Program
{
public static void Main(string[] args)
{
AnsiConsole.WriteLine();
AnsiConsole.Render(new Calendar(2020, 10)
.RoundedBorder()
.HighlightStyle(Style.Parse("red"))
.HeaderStyle(Style.Parse("yellow"))
.AddCalendarEvent("An event", 2020, 9, 22)
.AddCalendarEvent("Another event", 2020, 10, 2)
.AddCalendarEvent("A third event", 2020, 10, 13));
}
}
}

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Colors</Title>
<Description>Demonstrates how to use [yellow]c[/][red]o[/][green]l[/][blue]o[/][aqua]r[/][lime]s[/] in the console.</Description>
</PropertyGroup>

View File

@@ -4,7 +4,7 @@ namespace ColorExample
{
public static class Program
{
public static void Main(string[] args)
public static void Main()
{
if (AnsiConsole.Capabilities.ColorSystem == ColorSystem.NoColors)
{
@@ -24,7 +24,7 @@ namespace ColorExample
AnsiConsole.ResetColors();
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[bold underline]3-bit Colors[/]");
AnsiConsole.Render(new Rule("[yellow bold underline]3-bit Colors[/]").RuleStyle("grey").LeftAligned());
AnsiConsole.WriteLine();
for (var i = 0; i < 8; i++)
@@ -47,7 +47,7 @@ namespace ColorExample
AnsiConsole.ResetColors();
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[bold underline]4-bit Colors[/]");
AnsiConsole.Render(new Rule("[yellow bold underline]4-bit Colors[/]").RuleStyle("grey").LeftAligned());
AnsiConsole.WriteLine();
for (var i = 0; i < 16; i++)
@@ -70,7 +70,7 @@ namespace ColorExample
AnsiConsole.ResetColors();
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[bold underline]8-bit Colors[/]");
AnsiConsole.Render(new Rule("[yellow bold underline]8-bit Colors[/]").RuleStyle("grey").LeftAligned());
AnsiConsole.WriteLine();
for (var i = 0; i < 16; i++)
@@ -97,7 +97,7 @@ namespace ColorExample
AnsiConsole.ResetColors();
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[bold underline]24-bit Colors[/]");
AnsiConsole.Render(new Rule("[yellow bold underline]24-bit Colors[/]").RuleStyle("grey").LeftAligned());
AnsiConsole.WriteLine();
var index = 0;

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Columns</Title>
<Description>Demonstrates how to render data into columns.</Description>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,39 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using Spectre.Console;
namespace ColumnsExample
{
public static class Program
{
public static async Task Main()
{
// Download some random users
using var client = new HttpClient();
dynamic users = JObject.Parse(
await client.GetStringAsync("https://randomuser.me/api/?results=15"));
// Create a card for each user
var cards = new List<Panel>();
foreach(var user in users.results)
{
cards.Add(new Panel(GetCardContent(user))
.Header($"{user.location.country}")
.RoundedBorder().Expand());
}
// Render all cards in columns
AnsiConsole.Render(new Columns(cards));
}
private static string GetCardContent(dynamic user)
{
var name = $"{user.name.first} {user.name.last}";
var country = $"{user.location.city}";
return $"[b]{name}[/]\n[yellow]{country}[/]";
}
}
}

View File

@@ -1,18 +0,0 @@
using System;
using Spectre.Console;
namespace Diagnostic
{
public class Program
{
public static void Main(string[] args)
{
AnsiConsole.MarkupLine("Color system: [bold]{0}[/]", AnsiConsole.Capabilities.ColorSystem);
AnsiConsole.MarkupLine("Supports ansi? [bold]{0}[/]", AnsiConsole.Capabilities.SupportsAnsi);
AnsiConsole.MarkupLine("Legacy console? [bold]{0}[/]", AnsiConsole.Capabilities.LegacyConsole);
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("Buffer width: [bold]{0}[/]", AnsiConsole.Console.Width);
AnsiConsole.MarkupLine("Buffer height: [bold]{0}[/]", AnsiConsole.Console.Height);
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Emojis</Title>
<Description>Demonstrates how to render emojis.</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,24 @@
using Spectre.Console;
namespace EmojiExample
{
public static class Program
{
public static void Main(string[] args)
{
// Show a known emoji
RenderEmoji();
// Show a remapped emoji
Emoji.Remap("globe_showing_europe_africa", Emoji.Known.GrinningFaceWithSmilingEyes);
RenderEmoji();
}
private static void RenderEmoji()
{
AnsiConsole.Render(
new Panel("[yellow]Hello :globe_showing_europe_africa:![/]")
.RoundedBorder());
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Exceptions</Title>
<Description>Demonstrates how to render formatted exceptions.</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,66 @@
using System;
using System.Security.Authentication;
using Spectre.Console;
namespace Exceptions
{
public static class Program
{
public static void Main(string[] args)
{
try
{
DoMagic(42, null);
}
catch (Exception ex)
{
AnsiConsole.WriteLine();
AnsiConsole.Render(new Rule("Default").LeftAligned());
AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex);
AnsiConsole.WriteLine();
AnsiConsole.Render(new Rule("Compact").LeftAligned());
AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks);
AnsiConsole.WriteLine();
AnsiConsole.Render(new Rule("Compact + Custom colors").LeftAligned());
AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex, new ExceptionSettings
{
Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
Style = new ExceptionStyle
{
Exception = new Style().Foreground(Color.Grey),
Message = new Style().Foreground(Color.White),
NonEmphasized = new Style().Foreground(Color.Cornsilk1),
Parenthesis = new Style().Foreground(Color.Cornsilk1),
Method = new Style().Foreground(Color.Red),
ParameterName = new Style().Foreground(Color.Cornsilk1),
ParameterType = new Style().Foreground(Color.Red),
Path = new Style().Foreground(Color.Red),
LineNumber = new Style().Foreground(Color.Cornsilk1),
}
});
}
}
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.");
}
}
}

View File

@@ -1,25 +0,0 @@
using Spectre.Console;
namespace GridExample
{
public sealed class Program
{
static void Main(string[] args)
{
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options]] [[[[--]] <additional arguments>...]]]][/]");
AnsiConsole.WriteLine();
var grid = new Grid();
grid.AddColumn(new GridColumn { NoWrap = true });
grid.AddColumn(new GridColumn { NoWrap = true, Width = 2 });
grid.AddColumn();
grid.AddRow("Options:", "", "");
grid.AddRow(" [blue]-h[/], [blue]--help[/]", "", "Show command line help.");
grid.AddRow(" [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "", "The configuration to run for.");
grid.AddRow(" [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "", "Set the [grey]MSBuild[/] verbosity level.");
AnsiConsole.Render(grid);
}
}
}

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Grids</Title>
<Description>Demonstrates how to render grids in a console.</Description>
</PropertyGroup>

24
examples/Grids/Program.cs Normal file
View File

@@ -0,0 +1,24 @@
using Spectre.Console;
namespace GridExample
{
public static class Program
{
public static void Main()
{
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options]] [[[[--]] <additional arguments>...]]]][/]");
AnsiConsole.WriteLine();
var grid = new Grid();
grid.AddColumn(new GridColumn().NoWrap());
grid.AddColumn(new GridColumn().PadLeft(2));
grid.AddRow("Options:");
grid.AddRow(" [blue]-h[/], [blue]--help[/]", "Show command line help.");
grid.AddRow(" [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "The configuration to run for.");
grid.AddRow(" [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "Set the [grey]MSBuild[/] verbosity level.");
AnsiConsole.Render(grid);
}
}
}

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Info</Title>
<Description>Displays the capabilities of the current console.</Description>
</PropertyGroup>

28
examples/Info/Program.cs Normal file
View File

@@ -0,0 +1,28 @@
using Spectre.Console;
namespace InfoExample
{
public static class Program
{
public static void Main()
{
var grid = new Grid()
.AddColumn(new GridColumn().NoWrap().PadRight(4))
.AddColumn()
.AddRow("[b]Color system[/]", $"{AnsiConsole.Capabilities.ColorSystem}")
.AddRow("[b]Supports ansi?[/]", $"{YesNo(AnsiConsole.Capabilities.SupportsAnsi)}")
.AddRow("[b]Legacy console?[/]", $"{YesNo(AnsiConsole.Capabilities.LegacyConsole)}")
.AddRow("[b]Buffer width[/]", $"{AnsiConsole.Console.Width}")
.AddRow("[b]Buffer height[/]", $"{AnsiConsole.Console.Height}");
AnsiConsole.Render(
new Panel(grid)
.Header("Information"));
}
private static string YesNo(bool value)
{
return value ? "Yes" : "No";
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Links</Title>
<Description>Demonstrates how to render links in a console.</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
</Project>

21
examples/Links/Program.cs Normal file
View File

@@ -0,0 +1,21 @@
using Spectre.Console;
namespace LinkExample
{
public static class Program
{
public static void Main()
{
if (AnsiConsole.Capabilities.SupportLinks)
{
AnsiConsole.MarkupLine("[link=https://patriksvensson.se]Click to visit my blog[/]!");
}
else
{
AnsiConsole.MarkupLine("[red]It looks like your terminal doesn't support links[/]");
AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[yellow](╯°□°)╯[/]︵ [blue]┻━┻[/]");
}
}
}
}

View File

@@ -1,44 +0,0 @@
using Spectre.Console;
namespace PanelExample
{
class Program
{
static void Main(string[] args)
{
var content = new Markup(
"[underline]I[/] heard [underline on blue]you[/] like panels\n\n\n\n" +
"So I put a panel in a panel").Centered();
AnsiConsole.Render(
new Panel(
new Panel(content)
{
Border = BorderKind.Rounded
}));
// Left adjusted panel with text
AnsiConsole.Render(new Panel(
new Text("Left adjusted\nLeft").LeftAligned())
{
Expand = true,
});
// Centered ASCII panel with text
AnsiConsole.Render(new Panel(
new Text("Centered\nCenter").Centered())
{
Expand = true,
Border = BorderKind.Ascii,
});
// Right adjusted, rounded panel with text
AnsiConsole.Render(new Panel(
new Text("Right adjusted\nRight").RightAligned())
{
Expand = true,
Border = BorderKind.Rounded,
});
}
}
}

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Panels</Title>
<Description>Demonstrates how to render items in panels.</Description>
</PropertyGroup>

View File

@@ -0,0 +1,45 @@
using Spectre.Console;
namespace PanelExample
{
public static class Program
{
public static void Main()
{
var content = new Markup(
"[underline]I[/] heard [underline on blue]you[/] like panels\n\n\n\n" +
"So I put a panel in a panel").Centered();
AnsiConsole.Render(
new Panel(
new Panel(content)
.Border(BoxBorder.Rounded)));
// Left adjusted panel with text
AnsiConsole.Render(
new Panel(new Text("Left adjusted\nLeft").LeftAligned())
.Expand()
.SquareBorder()
.Header("Left")
.HeaderStyle("red"));
// Centered ASCII panel with text
AnsiConsole.Render(
new Panel(new Text("Centered\nCenter").Centered())
.Expand()
.AsciiBorder()
.Header("Center")
.HeaderStyle("green")
.HeaderAlignment(Justify.Center));
// Right adjusted, rounded panel with text
AnsiConsole.Render(
new Panel(new Text("Right adjusted\nRight").RightAligned())
.Expand()
.RoundedBorder()
.Header("Right")
.HeaderStyle("blue")
.HeaderAlignment(Justify.Right));
}
}
}

40
examples/Rules/Program.cs Normal file
View File

@@ -0,0 +1,40 @@
using Spectre.Console;
namespace EmojiExample
{
public static class Program
{
public static void Main(string[] args)
{
// No title
WrapInPanel(
new Rule()
.RuleStyle(Style.Parse("yellow"))
.LeftAligned());
// Left aligned title
WrapInPanel(
new Rule("[white]Left aligned[/]")
.RuleStyle(Style.Parse("red"))
.LeftAligned());
// Centered title
WrapInPanel(
new Rule("[silver]Centered[/]")
.RuleStyle(Style.Parse("green"))
.Centered());
// Right aligned title
WrapInPanel(
new Rule("[grey]Right aligned[/]")
.RuleStyle(Style.Parse("blue"))
.RightAligned());
}
private static void WrapInPanel(Rule rule)
{
AnsiConsole.Render(new Panel(rule).Expand().BorderStyle(Style.Parse("grey")));
AnsiConsole.WriteLine();
}
}
}

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Rules</Title>
<Description>Demonstrates how to render horizontal rules (lines).</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,91 +0,0 @@
using Spectre.Console;
using Spectre.Console.Rendering;
namespace TableExample
{
public static class Program
{
public static void Main(string[] args)
{
// A simple table
RenderSimpleTable();
// A big table
RenderBigTable();
// A nested table
RenderNestedTable();
}
private static void RenderSimpleTable()
{
// Create the table.
var table = new Table();
table.AddColumn(new TableColumn("[u]Foo[/]"));
table.AddColumn(new TableColumn("[u]Bar[/]"));
table.AddColumn(new TableColumn("[u]Baz[/]"));
// Add some rows
table.AddRow("Hello", "[red]World![/]", "");
table.AddRow("[blue]Bonjour[/]", "[white]le[/]", "[red]monde![/]");
table.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
AnsiConsole.Render(table);
}
private static void RenderBigTable()
{
// Create the table.
var table = new Table().SetBorder(BorderKind.Rounded);
table.AddColumn("[red underline]Foo[/]");
table.AddColumn(new TableColumn("[blue]Bar[/]") { Alignment = Justify.Right, NoWrap = true });
// Add some rows
table.AddRow("[blue][underline]Hell[/]o[/]", "World");
table.AddRow("[yellow]Patrik [green]\"Hello World\"[/] Svensson[/]", "Was [underline]here[/]!");
table.AddEmptyRow();
table.AddRow(
"Lorem ipsum dolor sit amet, consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " +
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " +
"dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat " +
"non proident, sunt in culpa qui officia deserunt mollit anim id est laborum", "<- Strange language");
table.AddEmptyRow();
table.AddRow("Hej", "[green]Världen[/]");
AnsiConsole.Render(table);
}
private static void RenderNestedTable()
{
// Create simple table.
var simple = new Table().SetBorder(BorderKind.Rounded).SetBorderColor(Color.Red);
simple.AddColumn(new TableColumn("[u]Foo[/]").Centered());
simple.AddColumn(new TableColumn("[u]Bar[/]"));
simple.AddColumn(new TableColumn("[u]Baz[/]"));
simple.AddRow("Hello", "[red]World![/]", "");
simple.AddRow("[blue]Bonjour[/]", "[white]le[/]", "[red]monde![/]");
simple.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
// Create other table.
var second = new Table().SetBorder(BorderKind.Square).SetBorderColor(Color.Green);
second.AddColumn(new TableColumn("[u]Foo[/]"));
second.AddColumn(new TableColumn("[u]Bar[/]"));
second.AddColumn(new TableColumn("[u]Baz[/]"));
second.AddRow("Hello", "[red]World![/]", "");
second.AddRow(simple, new Text("Whaaat"), new Text("Lolz"));
second.AddRow("[blue]Hej[/]", "[yellow]Världen![/]", "");
var table = new Table().SetBorder(BorderKind.Rounded);
table.AddColumn(new TableColumn(new Panel("[u]Foo[/]").SetBorderColor(Color.Red)));
table.AddColumn(new TableColumn(new Panel("[u]Bar[/]").SetBorderColor(Color.Green)));
table.AddColumn(new TableColumn(new Panel("[u]Baz[/]").SetBorderColor(Color.Blue)));
// Add some rows
table.AddRow(new Text("Hello").Centered(), new Markup("[red]World![/]"), Text.Empty);
table.AddRow(second, new Text("Whaaat"), new Text("Lol"));
table.AddRow(new Markup("[blue]Hej[/]").Centered(), new Markup("[yellow]Världen![/]"), Text.Empty);
AnsiConsole.Render(table);
}
}
}

View File

@@ -0,0 +1,51 @@
using Spectre.Console;
namespace TableExample
{
public static class Program
{
public static void Main()
{
// Create the table.
var table = CreateTable();
// Render the table.
AnsiConsole.Render(table);
}
private static Table CreateTable()
{
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![/]", "");
return 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);
}
}
}

View File

@@ -4,6 +4,7 @@
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Tables</Title>
<Description>Demonstrates how to render tables in a console.</Description>
</PropertyGroup>

View File

@@ -2,6 +2,6 @@
"projects": [ "src" ],
"sdk": {
"version": "3.1.301",
"rollForward": "latestMajor"
"rollForward": "latestPatch"
}
}

View File

@@ -3,7 +3,7 @@
##########################################################
$Output = Join-Path $PSScriptRoot "Temp"
$Source = Join-Path $PSScriptRoot "/../src/Spectre.Console"
$Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console"
if(!(Test-Path $Output -PathType Container)) {
New-Item -ItemType Directory -Path $Output | Out-Null

View File

@@ -0,0 +1,24 @@
##########################################################
# Script that generates the emoji lookup table.
##########################################################
$Output = Join-Path $PSScriptRoot "Temp"
$Source = Join-Path $PSScriptRoot "/../../src/Spectre.Console"
$Docs = Join-Path $PSScriptRoot "/../../docs/src/Data"
if(!(Test-Path $Output -PathType Container)) {
New-Item -ItemType Directory -Path $Output | Out-Null
}
# Generate the files
Push-Location Generator
&dotnet run -- emoji "$Output" --input $Output
if(!$?) {
Pop-Location
Throw "An error occured when generating code."
}
Pop-Location
# Copy the files to the correct location
Copy-Item (Join-Path "$Output" "Emoji.Generated.cs") -Destination "$Source/Emoji.Generated.cs"
Copy-Item (Join-Path "$Output" "emojis.json") -Destination "$Docs/emojis.json"

View File

@@ -55,5 +55,8 @@ namespace Generator.Commands
{
[CommandArgument(0, "<OUTPUT>")]
public string Output { get; set; }
[CommandOption("-i|--input <PATH>")]
public string Input { get; set; }
}
}

View File

@@ -0,0 +1,101 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using AngleSharp.Html.Parser;
using Generator.Models;
using Scriban;
using Scriban.Runtime;
using Spectre.Cli;
using Spectre.IO;
using Path = Spectre.IO.Path;
using SpectreEnvironment = Spectre.IO.Environment;
namespace Generator.Commands
{
public sealed class EmojiGeneratorCommand : AsyncCommand<GeneratorCommandSettings>
{
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" },
};
public EmojiGeneratorCommand()
{
_fileSystem = new FileSystem();
_environment = new SpectreEnvironment();
_parser = new HtmlParser();
}
public override async Task<int> ExecuteAsync(CommandContext context, GeneratorCommandSettings settings)
{
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(GeneratorCommandSettings 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);
}
}
}

View File

@@ -24,9 +24,17 @@
<None Update="Templates\ColorPalette.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="0.14.0" />
<PackageReference Include="Humanizer.Core" Version="2.8.26" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="Scriban" Version="2.1.3" />
<PackageReference Include="Spectre.Cli" Version="0.36.1-preview.0.6" />

View File

@@ -0,0 +1,95 @@
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");
}
}
}

View File

@@ -11,6 +11,7 @@ namespace Generator
app.Configure(config =>
{
config.AddCommand<ColorGeneratorCommand>("colors");
config.AddCommand<EmojiGeneratorCommand>("emoji");
});
return app.Run(args);

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Generated {{ date.now | date.to_string `%Y-%m-%d %k:%M` }}
// Generated {{ date.now | date.to_string `%F %R` }}
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Generated {{ date.now | date.to_string `%Y-%m-%d %k:%M` }}
// Generated {{ date.now | date.to_string `%F %R` }}
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.

View File

@@ -1,7 +1,7 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Generated {{ date.now | date.to_string `%Y-%m-%d %k:%M` }}
// Generated {{ date.now | date.to_string `%F %R` }}
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.

View File

@@ -0,0 +1,43 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Generated {{ date.now | date.to_string `%F %R` }}
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
namespace Spectre.Console
{
/// <summary>
/// Utility for working with emojis.
/// </summary>
public static partial class Emoji
{
private static readonly Dictionary<string, string> _emojis
= new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase)
{
{{~ for emoji in emojis ~}}
{ "{{ emoji.identifier }}", Emoji.Known.{{ emoji.name }} },
{{~ end ~}}
};
/// <summary>
/// Contains all predefined emojis.
/// </summary>
public static class Known
{
{{- for emoji in emojis }}
/// <summary>
/// Gets the "{{ emoji.identifier }}" emoji.
/// Description: {{ emoji.description }}.
/// </summary>
public const string {{ emoji.name }} = "{{ emoji.code }}";
{{~ end ~}}
}
}
}

View File

@@ -0,0 +1,10 @@
[
{{~ for x in 0..(emojis.size-1) ~}}
{
"id": "{{ emojis[x].identifier }}",
"name": "{{ emojis[x].name }}",
"description": "{{ emojis[x].description }}",
"code": "{{ emojis[x].normalized_code }}"
}{{ if x != (emojis.size-1) }},{{ end }}
{{~ end ~}}
]

View File

@@ -82,5 +82,11 @@ dotnet_diagnostic.RCS1079.severity = warning
# RCS1057: Add empty line between declarations.
dotnet_diagnostic.RCS1057.severity = none
# RCS1057: Validate arguments correctly
dotnet_diagnostic.RCS1227.severity = none
# IDE0004: Remove Unnecessary Cast
dotnet_diagnostic.IDE0004.severity = warning
dotnet_diagnostic.IDE0004.severity = warning
# CA1810: Initialize reference type static fields inline
dotnet_diagnostic.CA1810.severity = none

View File

@@ -42,7 +42,7 @@
<PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.113">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="Roslynator.Analyzers" Version="2.3.0">
<PackageReference Include="Roslynator.Analyzers" Version="3.0.0">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
</ItemGroup>

View File

@@ -24,3 +24,6 @@ dotnet_diagnostic.CA2000.severity = none
# SA1118: Parameter should not span multiple lines
dotnet_diagnostic.SA1118.severity = none
# CA1031: Do not catch general exception types
dotnet_diagnostic.CA1031.severity = none

View File

@@ -0,0 +1,23 @@
using System;
using System.Diagnostics.CodeAnalysis;
namespace Spectre.Console.Tests.Data
{
public static class TestExceptions
{
[SuppressMessage("Usage", "CA1801:Review unused parameters", Justification = "<Pending>")]
public static bool MethodThatThrows(int? number) => throw new InvalidOperationException("Throwing!");
public static void ThrowWithInnerException()
{
try
{
MethodThatThrows(null);
}
catch (Exception ex)
{
throw new InvalidOperationException("Something threw!", ex);
}
}
}
}

View File

@@ -1,24 +0,0 @@
using System;
namespace Spectre.Console.Tests
{
public static class ConsoleExtensions
{
public static void SetColor(this IAnsiConsole console, Color color, bool foreground)
{
if (console is null)
{
throw new ArgumentNullException(nameof(console));
}
if (foreground)
{
console.Foreground = color;
}
else
{
console.Background = color;
}
}
}
}

View File

@@ -1,13 +1,34 @@
using System;
using System.Text.RegularExpressions;
namespace Spectre.Console.Tests
{
public static class StringExtensions
{
private static readonly Regex _lineNumberRegex = new Regex(":\\d+", RegexOptions.Singleline);
private static readonly Regex _filenameRegex = new Regex("\\sin\\s.*cs:nn", RegexOptions.Multiline);
public static string NormalizeLineEndings(this string text)
{
return text?.Replace("\r\n", "\n", StringComparison.OrdinalIgnoreCase)
?.Replace("\r", string.Empty, StringComparison.OrdinalIgnoreCase);
}
public static string NormalizeStackTrace(this string text)
{
text = _lineNumberRegex.Replace(text, match =>
{
return ":nn";
});
return _filenameRegex.Replace(text, match =>
{
var value = match.Value;
var index = value.LastIndexOfAny(new[] { '\\', '/' });
var filename = value.Substring(index + 1, value.Length - index - 1);
return $" in /xyz/{filename}";
});
}
}
}

View File

@@ -0,0 +1,15 @@
namespace Spectre.Console.Tests
{
internal static class StyleExtensions
{
public static Style SetColor(this Style style, Color color, bool foreground)
{
if (foreground)
{
return style.Foreground(color);
}
return style.Background(color);
}
}
}

Some files were not shown because too many files have changed in this diff Show More