Compare commits

...

32 Commits

Author SHA1 Message Date
Patrik Svensson
380c6aca45 Add net5.0 target framework 2020-11-11 15:28:32 +01:00
Patrik Svensson
b1da5e7ba8 Add support for markup text in panel header 2020-11-07 20:43:53 +01:00
Patrik Svensson
be3350a411 Bump dotnet-example to 1.0.0 2020-11-03 18:14:41 +01:00
Patrik Svensson
a1d11e9d0c Add support for moving the cursor 2020-10-28 18:57:08 +01:00
Patrik Svensson
93d1971f48 Update rule example and docs 2020-10-27 17:30:50 +01:00
Martin Andersen
bca1c889d1 Add Padding extension
Add extension method for specifying horizontal and vertical padding.
Similar constructor for `Padding` already existed.

Update documentation for table column appearance (padding).

Update
`Should_Render_Padded_Object_Correctly_When_Nested_Within_Other_Object`
test to use new extension method.
2020-10-27 09:09:30 +01:00
Takahito Yamatoya
9915a0d6a8 Update Documentation for escape 2020-10-27 09:08:27 +01:00
Takahito Yamatoya
f34fc43d00 Update documentation for aligning tables 2020-10-27 09:08:27 +01:00
Patrik Svensson
e7f497050c Add row and column accessors for tables and grids 2020-10-26 18:15:27 +01:00
Martin Andersen
3e5e22d6c2 Update documentation
- ExceptionFormat -> ExceptionFormats.
- Fix link to documentation.
- Add cross reference to Styles.
- Render table in example code.
- Add code for setting background color.
2020-10-26 15:31:44 +01:00
Patrik Svensson
10daf727e9 Fix outdated documentation 2020-10-26 12:20:17 +01:00
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
172 changed files with 5752 additions and 993 deletions

View File

@@ -21,7 +21,7 @@ jobs:
- name: Setup dotnet - name: Setup dotnet
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '3.1.301' # SDK Version to use. dotnet-version: 5.0.100
- name: Build - name: Build
shell: bash shell: bash
@@ -55,10 +55,15 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup dotnet - name: Setup dotnet 3.1.402
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: 3.1.301 dotnet-version: 3.1.402
- name: Setup dotnet 5.0.100
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.100
- name: Integration Tests - name: Integration Tests
shell: bash shell: bash
@@ -71,6 +76,7 @@ jobs:
dotnet example colors dotnet example colors
dotnet example emojis dotnet example emojis
dotnet example exceptions dotnet example exceptions
dotnet example calendars
- name: Build - name: Build
shell: bash shell: bash

View File

@@ -24,7 +24,7 @@ jobs:
- name: Setup dotnet - name: Setup dotnet
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '3.1.301' # SDK Version to use. dotnet-version: 5.0.100
- name: Publish - name: Publish
shell: bash shell: bash

View File

@@ -29,7 +29,7 @@ jobs:
- name: Setup dotnet - name: Setup dotnet
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: '3.1.301' # SDK Version to use. dotnet-version: 5.0.100
- name: Build - name: Build
shell: bash shell: bash
@@ -64,10 +64,15 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup dotnet - name: Setup dotnet 3.1.402
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: 3.1.301 dotnet-version: 3.1.402
- name: Setup dotnet 5.0.100
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.100
- name: Build - name: Build
shell: bash shell: bash
@@ -90,10 +95,15 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Setup dotnet - name: Setup dotnet 3.1.402
uses: actions/setup-dotnet@v1 uses: actions/setup-dotnet@v1
with: with:
dotnet-version: 3.1.301 dotnet-version: 3.1.402
- name: Setup dotnet 5.0.100
uses: actions/setup-dotnet@v1
with:
dotnet-version: 5.0.100
- name: Publish - name: Publish
shell: bash shell: bash

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 restore
```
このリポジトリで提供している例が一覧表示されます
```
> dotnet example
╭────────────┬───────────────────────────────────────┬──────────────────────────────────────────────────────╮
│ Name │ Path │ Description │
├────────────┼───────────────────────────────────────┼──────────────────────────────────────────────────────┤
│ Borders │ examples/Borders/Borders.csproj │ Demonstrates the different kind of borders. │
│ Calendars │ examples/Calendars/Calendars.csproj │ Demonstrates how to render calendars. │
│ Colors │ examples/Colors/Colors.csproj │ Demonstrates how to use colors in the console. │
│ Columns │ examples/Columns/Columns.csproj │ Demonstrates how to render data into columns. │
│ Emojis │ examples/Emojis/Emojis.csproj │ Demonstrates how to render emojis. │
│ Exceptions │ examples/Exceptions/Exceptions.csproj │ Demonstrates how to render formatted exceptions. │
│ Grids │ examples/Grids/Grids.csproj │ Demonstrates how to render grids in a console. │
│ Info │ examples/Info/Info.csproj │ Displays the capabilities of the current console. │
│ Links │ examples/Links/Links.csproj │ Demonstrates how to render links in a console. │
│ Panels │ examples/Panels/Panels.csproj │ Demonstrates how to render items in panels. │
│ Rules │ examples/Rules/Rules.csproj │ Demonstrates how to render horizontal rules (lines). │
│ Tables │ examples/Tables/Tables.csproj │ Demonstrates how to render tables in a console. │
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
```
そして、例を実行します
```
> dotnet example tables
┌──────────┬──────────┬────────┐
│ Foo │ Bar │ Baz │
├──────────┼──────────┼────────┤
│ Hello │ World! │ │
│ Bonjour │ le │ monde! │
│ Hej │ Världen! │ │
└──────────┴──────────┴────────┘
```
## クイックスタート
pectre.Consoleの利用を開始する最初の方法は、Nugetパッケージをインストールすることです。
```shell
> dotnet add package Spectre.Console
```
その後、`Spectre.Console`名前空間を参照する必要があります。一度参照したら、提供されている全ての機能を使用できます。
```csharp
using Spectre.Console
public static class Program
{
public static void Main(string[] args)
{
AnsiConsole.Markup("[underline red]Hello[/] World!");
}
}
```
## マークアップ
`Markup`クラスは、コンソールにリッチなテキストを出力することができます。
### 文法
コンソールマークアップはbbcodeに影響を受けた文法を利用します。角括弧でスタイルを書いたらスタイルを参照、例えば、`[bold red]`
は、`[/]`で閉じるまでスタイルが適用されます。
```csharp
AnsiConsole.Render(new Markup("[bold yellow]Hello[/] [red]World![/]"));
```
`Markup` クラスは`IRenderable`を実装しており、table、grid、Panelを使用できることを意味します。
`IRenderable`のレンダリングに対応している多くのクラスは、リッチテキストの描画を上書きます。
```csharp
var table = new Table();
table.AddColumn(new TableColumn(new Markup("[yellow]Foo[/]")));
table.AddColumn(new TableColumn("[blue]Bar[/]"));
```
### 便利なメソッド
`AnsiConsole`には、新しい`Markup`インスタンスをインスタンス化することなく、コンソールにマークアップテキストを書き込める便利なメソッドがあります。
```csharp
AnsiConsole.Markup("[underline green]Hello[/] ");
AnsiConsole.MarkupLine("[bold]World[/]");
```
### エスケープ文字列
`[`を出力するために、 `[[`を利用し、`]`を出力するために`]]`を利用します。
```csharp
AnsiConsole.Markup("[[Hello]] "); // [Hello]
AnsiConsole.Markup("[red][[World]][/]"); // [World]
```
`SafeMarkup`拡張メソッドを使用することもできます。
```csharp
AnsiConsole.Markup("[red]{0}[/]", "Hello [World]".SafeMarkup());
```
### カラー
`new Style(foreground: Color.Maroon)`のようなコード、または、`AnsiConsole.Markup("[maroon on blue]Hello[/]")`のようなマークアップテキストで色を使用できます。
### 背景色の設定
カラー指定の際に、`on`を付けることで、マークアップで背景色を設定できます。
```
[bold yellow on blue]Hello[/]
[default on blue]World[/]
```
### 絵文字の描画
マークアップの一部として絵文字を出力するために、emojiショートコードが使用できます。
```csharp
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
```
emojiのスタイルについては、付録の[Emoji](./appendix/emojis) を参照してください。
### カラー
上の例では、全ての色は名前で参照されています。
しかし、16進数やRGB表現をマークダウンで色指定に使用できます。
```csharp
AnsiConsole.Markup("[red]Foo[/] ");
AnsiConsole.Markup("[#ff0000]Bar[/] ");
AnsiConsole.Markup("[rgb(255,0,0)]Baz[/] ");
```
## 絵文字
どのような絵文字が使用できるかは、使用しているOSやターミナルに依存し、どのように表示されるかは保証されません。絵文字の幅計算は正確ではないため、表、パネル、グリッドで使用する場合は表示がずれるかもしれません。
完全な互換性を確保するために、Unicode 13.0 より以前の`Emoji_Presentation`カテゴリにあるものだけを使用することを検討してください。
公式の絵文字一覧
https://www.unicode.org/Public/UCD/latest/ucd/emoji/emoji-data.txt
```csharp
// Markup
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
// Constant
var hello = "Hello " + Emoji.Known.GlobeShowingEuropeAfrica;
```
テキスト内の絵文字を置き換えることができます。
```csharp
var phrase = "Mmmm :birthday_cake:";
var rendered
```
既存の絵文字を別のものにしたり、完全に新しい物を追加したいことがあります。このために、`Emoji.Remap`メソッドを使用できます。
この方法は、マークアップ文字と`Emoji.Replace`の両方で動作します。
```csharp
// Remap the emoji
Emoji.Remap("globe_showing_europe_africa", "😄");
// Render markup
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!");
// Replace emojis in string
var phrase = "Hello :globe_showing_europe_africa:!";
var rendered = Emoji.Replace(phrase);
```
## テーブル
テーブルはターミナルで表データを表示するのに完璧な方法です。
`Spectre.Console` は、テーブルの描画にとても優れていて、全てのカラムは中に合わせて調整してくれます。
`IRenderable`を実装しているものは、列ヘッダやセル、別のテーブルとして使用できます。
### 使い方
テーブルを描画するために、`Table`インスタンスを作成し、必要な数の列を追加し、行を追加します。
テーブルをコンソールの`Render`メソッドに渡して終わりです。
```csharp
// テーブルの作成
var table = new Table();
// 列の追加
table.AddColumn("Foo");
table.AddColumn(new TableColumn("Bar").Centered());
// 行の追加
table.AddRow("Baz", "[green]Qux[/]");
table.AddRow(new Markup("[blue]Corgi[/]"), new Panel("Waldo"));
// コンソールにテーブルの描画
AnsiConsole.Render(table);
```
これは次のように出力を描画します。
![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,
ExceptionFormats.ShortenPaths | ExceptionFormats.ShortenTypes |
ExceptionFormats.ShortenMethods | ExceptionFormats.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)

View File

@@ -10,10 +10,11 @@ for Python.
1. [Features](#features) 1. [Features](#features)
2. [Example](#example) 2. [Example](#example)
3. [Usage](#usage) 3. [Installing](#installing)
3.1. [Using the static API](#using-the-static-api) 4. [Usage](#usage)
3.2. [Creating a console](#creating-a-console) 4.1. [Using the static API](#using-the-static-api)
4. [Running examples](#running-examples) 4.2. [Creating a console](#creating-a-console)
5. [Running examples](#running-examples)
## Features ## Features
@@ -30,6 +31,14 @@ for Python.
![Example](resources/gfx/screenshots/example.png) ![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 ## Usage
The `Spectre.Console` API is stateful and is not thread-safe. The `Spectre.Console` API is stateful and is not thread-safe.
@@ -40,7 +49,7 @@ regular `System.Console` API.
If the current terminal does not support ANSI escape sequences, If the current terminal does not support ANSI escape sequences,
`Spectre.Console` will fallback to using the `System.Console` API. `Spectre.Console` will fallback to using the `System.Console` API.
_NOTE: This library is currently under development and API's _NOTE: This library is currently under development and APIs
might change or get removed at any point up until a 1.0 release._ might change or get removed at any point up until a 1.0 release._
### Using the static API ### Using the static API
@@ -91,7 +100,7 @@ To see Spectre.Console in action, install the
global tool. global tool.
``` ```
> dotnet tool install -g dotnet-example > dotnet tool restore
``` ```
Now you can list available examples in this repository: Now you can list available examples in this repository:
@@ -99,20 +108,28 @@ Now you can list available examples in this repository:
``` ```
> dotnet example > dotnet example
╭───────────────────────────────────────┬─────────────────────────────────────────────────╮ ╭────────────┬───────────────────────────────────────┬──────────────────────────────────────────────────────
│ Name │ Path │ Description │ │ Name │ Path │ Description
├───────────────────────────────────────┼─────────────────────────────────────────────────┤ ├────────────┼───────────────────────────────────────┼──────────────────────────────────────────────────────
Colors │ examples/Colors/Colors.csproj │ Demonstrates how to use colors in the console. Borders │ examples/Borders/Borders.csproj │ Demonstrates the different kind of borders.
Grid │ examples/Grid/Grid.csproj │ Demonstrates how to render grids in a console. Calendars │ examples/Calendars/Calendars.csproj │ Demonstrates how to render calendars.
Panel │ examples/Panel/Panel.csproj │ Demonstrates how to render items in panels. Colors │ examples/Colors/Colors.csproj │ Demonstrates how to use colors in the console.
Table │ examples/Table/Table.csproj │ Demonstrates how to render tables in a console. Columns │ examples/Columns/Columns.csproj │ Demonstrates how to render data into columns.
╰────────┴───────────────────────────────┴─────────────────────────────────────────────────╯ │ Emojis │ examples/Emojis/Emojis.csproj │ Demonstrates how to render emojis. │
│ Exceptions │ examples/Exceptions/Exceptions.csproj │ Demonstrates how to render formatted exceptions. │
│ Grids │ examples/Grids/Grids.csproj │ Demonstrates how to render grids in a console. │
│ Info │ examples/Info/Info.csproj │ Displays the capabilities of the current console. │
│ Links │ examples/Links/Links.csproj │ Demonstrates how to render links in a console. │
│ Panels │ examples/Panels/Panels.csproj │ Demonstrates how to render items in panels. │
│ Rules │ examples/Rules/Rules.csproj │ Demonstrates how to render horizontal rules (lines). │
│ Tables │ examples/Tables/Tables.csproj │ Demonstrates how to render tables in a console. │
╰────────────┴───────────────────────────────────────┴──────────────────────────────────────────────────────╯
``` ```
And to run an example: And to run an example:
``` ```
> dotnet example table > dotnet example tables
┌──────────┬──────────┬────────┐ ┌──────────┬──────────┬────────┐
│ Foo │ Bar │ Baz │ │ Foo │ Bar │ Baz │
├──────────┼──────────┼────────┤ ├──────────┼──────────┼────────┤

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory> <RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
<DefaultItemExcludes>$(DefaultItemExcludes);output\**;.gitignore</DefaultItemExcludes> <DefaultItemExcludes>$(DefaultItemExcludes);output\**;.gitignore</DefaultItemExcludes>
<MinVerSkip Condition="'$(Configuration)' == 'Debug'">true</MinVerSkip> <MinVerSkip Condition="'$(Configuration)' == 'Debug'">true</MinVerSkip>
@@ -31,8 +31,8 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Statiq.Web" Version="1.0.0-beta.5" /> <PackageReference Include="Statiq.Web" Version="1.0.0-beta.11" />
<PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.0" /> <PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.1" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -10,7 +10,7 @@ The documentation site uses [Statiq](https://statiq.dev), a static site generato
> 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). After the build is complete, you can navigate to [http://localhost:5080/spectre.console](http://localhost:5080/spectre.console).
**Note that the site runs under a virtual directory.** **Note that the site runs under a virtual directory.**

View File

@@ -130,7 +130,7 @@
<div class="sidebar-nav-item @(Document.IdEquals(root) ? "active" : null)"> <div class="sidebar-nav-item @(Document.IdEquals(root) ? "active" : null)">
@if(root.ShowLink()) @if(root.ShowLink())
{ {
@Html.DocumentLink(root) @Html.DocumentLink(root)
} }
else else
{ {
@@ -140,6 +140,11 @@
@foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible()) @foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible())
{ {
if(string.IsNullOrWhiteSpace(document.GetTitle()))
{
continue;
}
DocumentList<IDocument> documentChildren = OutputPages.GetChildrenOf(document); DocumentList<IDocument> documentChildren = OutputPages.GetChildrenOf(document);
<div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(documentChildren.Any() ? "has-children" : null)"> <div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(documentChildren.Any() ? "has-children" : null)">
@if(document.ShowLink()) @if(document.ShowLink())

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 MiB

View File

@@ -19,8 +19,8 @@ the hyperlinks are clickable is up to the terminal.
```csharp ```csharp
AnsiConsole.WriteException(ex, AnsiConsole.WriteException(ex,
ExceptionFormat.ShortenPaths | ExceptionFormat.ShortenTypes | ExceptionFormats.ShortenPaths | ExceptionFormats.ShortenTypes |
ExceptionFormat.ShortenMethods | ExceptionFormat.ShowLinks); ExceptionFormats.ShortenMethods | ExceptionFormats.ShowLinks);
``` ```
<img src="assets/images/compact_exception.png" style="max-width: 100%;"> <img src="assets/images/compact_exception.png" style="max-width: 100%;">
@@ -36,15 +36,15 @@ AnsiConsole.WriteException(ex, new ExceptionSettings
Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks, Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
Style = new ExceptionStyle Style = new ExceptionStyle
{ {
Exception = Style.WithForeground(Color.Grey), Exception = new Style().Foreground(Color.Grey),
Message = Style.WithForeground(Color.White), Message = new Style().Foreground(Color.White),
NonEmphasized = Style.WithForeground(Color.Cornsilk1), NonEmphasized = new Style().Foreground(Color.Cornsilk1),
Parenthesis = Style.WithForeground(Color.Cornsilk1), Parenthesis = new Style().Foreground(Color.Cornsilk1),
Method = Style.WithForeground(Color.Red), Method = new Style().Foreground(Color.Red),
ParameterName = Style.WithForeground(Color.Cornsilk1), ParameterName = new Style().Foreground(Color.Cornsilk1),
ParameterType = Style.WithForeground(Color.Red), ParameterType = new Style().Foreground(Color.Red),
Path = Style.WithForeground(Color.Red), Path = new Style().Foreground(Color.Red),
LineNumber = Style.WithForeground(Color.Cornsilk1), LineNumber = new Style().Foreground(Color.Cornsilk1),
} }
}); });
``` ```

View File

@@ -1,4 +1,4 @@
Title: Welcome Title: Welcome
Order: 0 Order: 0
--- ---
@@ -20,7 +20,7 @@ for Python written by Will McGugan.
The library will detect the capabilities of the current terminal The library will detect the capabilities of the current terminal
and downgrade colors as needed. and downgrade colors as needed.
## Example ## Examples
<img width="100%" <img src="assets/images/table.gif" style="max-width: 100%; margin-top: 15px; margin-bottom: 25px;" />
src="https://github.com/spectresystems/spectre.console/raw/main/resources/gfx/screenshots/example.png" /> <img src="https://github.com/spectresystems/spectre.console/raw/main/resources/gfx/screenshots/example.png" style="max-width: 100%;" />

View File

@@ -6,7 +6,7 @@ The class `Markup` allows you to output rich text to the console.
# Syntax # Syntax
Console markup uses a syntax inspired by bbcode. If you write the style (see Styles) Console markup uses a syntax inspired by bbcode. If you write the style (see [Styles](xref:styles))
in square brackets, e.g. `[bold red]`, that style will apply until it is closed with a `[/]`. in square brackets, e.g. `[bold red]`, that style will apply until it is closed with a `[/]`.
```csharp ```csharp
@@ -21,6 +21,7 @@ rendering of `IRenderable` also have overloads for rendering rich text.
var table = new Table(); var table = new Table();
table.AddColumn(new TableColumn(new Markup("[yellow]Foo[/]"))); table.AddColumn(new TableColumn(new Markup("[yellow]Foo[/]")));
table.AddColumn(new TableColumn("[blue]Bar[/]")); table.AddColumn(new TableColumn("[blue]Bar[/]"));
AnsiConsole.Render(table);
``` ```
# Convenience methods # Convenience methods
@@ -43,20 +44,24 @@ AnsiConsole.Markup("[[Hello]] "); // [Hello]
AnsiConsole.Markup("[red][[World]][/]"); // [World] AnsiConsole.Markup("[red][[World]][/]"); // [World]
``` ```
You can also use the `SafeMarkup` extension method. You can also use the `EscapeMarkup` extension method.
```csharp ```csharp
AnsiConsole.Markup("[red]{0}[/]", "Hello [World]".SafeMarkup()); AnsiConsole.Markup("[red]{0}[/]", "Hello [World]".EscapeMarkup());
``` ```
You can also use the `Markup.Escape` method.
```csharp
AnsiConsole.Markup("[red]{0}[/]", Markup.Escape("Hello [World]"));
```
# Setting background color # Setting background color
You can set the background color in markup by prefixing the color with You can set the background color in markup by prefixing the color with
`on`. `on`.
``` ```csharp
[bold yellow on blue]Hello[/] AnsiConsole.Markup("[bold yellow on blue]Hello[/]");
[default on blue]World[/] AnsiConsole.Markup("[default on blue]World[/]");
``` ```
# Rendering emojis # Rendering emojis
@@ -64,10 +69,10 @@ You can set the background color in markup by prefixing the color with
To output an emoji as part of markup, you can use emoji shortcodes. To output an emoji as part of markup, you can use emoji shortcodes.
```csharp ```csharp
AnsiConsole.MarkupLine("Hello :globe_showing_europe_africa:!"); AnsiConsole.Markup("Hello :globe_showing_europe_africa:!");
``` ```
For a list of emoji, see the [Emojis](xref:styles) appendix section. For a list of emoji, see the [Emojis](xref:emojis) appendix section.
# Colors # Colors

View File

@@ -0,0 +1,121 @@
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);
```
```text
2020 October
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ │ │ 1 │ 2 │ 3 │
│ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │
│ 11 │ 12 │ 13 │ 14 │ 15 │ 16 │ 17 │
│ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │
│ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │
│ │ │ │ │ │ │ │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
```
## Culture
You can set the calendar's culture to show localized weekdays.
```csharp
var calendar = new Calendar(2020,10);
calendar.Culture("ja-JP");
AnsiConsole.Render(calendar);
```
```text
Oktober 2020
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ Mån │ Tis │ Ons │ Tor │ Fre │ Lör │ Sön │
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ │ 1 │ 2 │ 3 │ 4 │
│ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11* │
│ 12 │ 13 │ 14 │ 15 │ 16 │ 17 │ 18 │
│ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │ 25 │
│ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │ │
│ │ │ │ │ │ │ │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
```
## Header
You can hide the calendar header.
```csharp
var calendar = new Calendar(2020,10);
calendar.ShowHeader();
AnsiConsole.Render(calendar);
```
```text
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ │ │ 1 │ 2 │ 3 │
│ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │
│ 11 │ 12 │ 13 │ 14 │ 15 │ 16 │ 17 │
│ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │
│ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │
│ │ │ │ │ │ │ │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
```
You can set the header style of the calendar.
```csharp
var calendar = new Calendar(2020, 10);
calendar.HeaderStyle(Style.Parse("blue bold"));
AnsiConsole.Render(calendar);
```
## Calendar Events
You can add an event to the calendar.
If a date has an event associated with it, the date gets highlighted in the calendar.
```csharp
var calendar = new Calendar(2020,10);
calendar.AddCalendarEvent(2020, 10, 11);
AnsiConsole.Render(calendar);
```
```text
2020 October
┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐
│ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │
├─────┼─────┼─────┼─────┼─────┼─────┼─────┤
│ │ │ │ │ 1 │ 2 │ 3 │
│ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │
│ 11* │ 12 │ 13 │ 14 │ 15 │ 16 │ 17 │
│ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │
│ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │
│ │ │ │ │ │ │ │
└─────┴─────┴─────┴─────┴─────┴─────┴─────┘
```
### Highlight style
You can set the highlight style for a calendar event via `SetHighlightStyle`.
```csharp
var calendar = new Calendar(2020, 10);
calendar.AddCalendarEvent(2020, 10, 11);
calendar.HighlightStyle(Style.Parse("yellow bold"));
AnsiConsole.Render(calendar);
```

View File

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

View File

@@ -0,0 +1,72 @@
Title: Rule
Order: 5
RedirectFrom: rule
---
The `Rule` class is used to render a horizontal rule (line) to the terminal.
<img src="../assets/images/rule.png" style="width: 100%;" />
# Usage
To render a rule without a title:
```csharp
var rule = new Rule();
AnsiConsole.Render(rule);
```
## Title
You can set the rule title markup text.
```csharp
var rule = new Rule("[red]Hello[/]");
AnsiConsole.Render(rule);
```
```text
───────────────────────────────── Hello ─────────────────────────────────
```
### Title alignment
You can set the rule's title alignment.
```csharp
var rule = new Rule("[red]Hello[/]");
rule.Alignment = Justify.Left;
AnsiConsole.Render(rule);
```
```text
── Hello ────────────────────────────────────────────────────────────────
```
You can also specify it via an extension method:
```csharp
var rule = new Rule("[red]Hello[/]");
rule.LeftAligned();
AnsiConsole.Render(rule);
```
```text
── Hello ────────────────────────────────────────────────────────────────
```
## Styling
```csharp
var rule = new Rule("[red]Hello[/]");
rule.Style = Style.Parse("red dim");
AnsiConsole.Render(rule);
```
You can also specify it via an extension method
```csharp
var rule = new Rule("[red]Hello[/]");
rule.RuleStyle("red dim");
AnsiConsole.Render(rule);
```

View File

@@ -1,5 +1,6 @@
Title: Tables Title: Table
Order: 3 Order: 3
RedirectFrom: tables
--- ---
Tables are a perfect way of displaying tabular data in a terminal. Tables are a perfect way of displaying tabular data in a terminal.
@@ -36,7 +37,7 @@ AnsiConsole.Render(table);
This will render the following output: This will render the following output:
![Table](assets/images/table.png) ![Table](../assets/images/table.png)
# Table appearance # Table appearance
@@ -50,10 +51,10 @@ For a list of borders, see the [Borders](xref:borders) appendix section.
```csharp ```csharp
// Sets the border // Sets the border
table.SetBorder(Border.None); table.Border(TableBorder.None);
table.SetBorder(Border.Ascii); table.Border(TableBorder.Ascii);
table.SetBorder(Border.Square); table.Border(TableBorder.Square);
table.SetBorder(Border.Rounded); table.Border(TableBorder.Rounded);
``` ```
## Expand / Collapse ## Expand / Collapse
@@ -78,7 +79,16 @@ table.HideHeaders();
```csharp ```csharp
// Sets the table width to 50 cells // Sets the table width to 50 cells
table.SetWidth(50); table.Width(50);
```
## Alignment
```csharp
table.Alignment(Justify.Right);
table.RightAligned();
table.Centered();
table.LeftAligned();
``` ```
# Column appearance # Column appearance
@@ -90,31 +100,37 @@ table.SetWidth(50);
## Alignment ## Alignment
```csharp ```csharp
// Set the alignment explicitly table.Columns[0].Alignment(Justify.Right);
column.SetAlignment(Justify.Right); table.Columns[0].LeftAligned();
table.Columns[0].Centered();
table.Columns[0].RightAligned();
``` ```
## Padding ## Padding
```csharp ```csharp
// Set left and right padding // Set padding individually
column.SetPadding(left: 3, right: 5); table.Columns[0].PadLeft(3);
table.Columns[0].PadRight(5);
// Set padding individually. // Or chained together
column.PadLeft(3); table.Columns[0].PadLeft(3).PadRight(5);
column.PadRight(5);
// Or with the shorthand method if the left and right
// padding are identical. Vertical padding is ignored.
table.Columns[0].Padding(4, 0);
``` ```
## Disable column wrapping ## Disable column wrapping
```csharp ```csharp
// Disable column wrapping // Disable column wrapping
column.NoWrap(); table.Columns[0].NoWrap();
``` ```
## Set column width ## Set column width
```csharp ```csharp
// Set the column width (no fluent extension method for this yet) // Set the column width
column.Width = 15; table.Columns[0].Width(15);
``` ```

View File

@@ -3,7 +3,7 @@
"isRoot": true, "isRoot": true,
"tools": { "tools": {
"cake.tool": { "cake.tool": {
"version": "0.38.4", "version": "1.0.0-rc0001",
"commands": [ "commands": [
"dotnet-cake" "dotnet-cake"
] ]
@@ -15,7 +15,7 @@
] ]
}, },
"dotnet-example": { "dotnet-example": {
"version": "0.8.0", "version": "1.1.0",
"commands": [ "commands": [
"dotnet-example" "dotnet-example"
] ]

View File

@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<Title>Borders</Title> <Title>Borders</Title>
<Description>Demonstrates the different kind of borders.</Description> <Description>Demonstrates the different kind of borders.</Description>

View File

@@ -8,26 +8,22 @@ namespace BordersExample
public static void Main() public static void Main()
{ {
// Render panel borders // Render panel borders
AnsiConsole.WriteLine(); HorizontalRule("PANEL BORDERS");
AnsiConsole.MarkupLine("[white bold underline]PANEL BORDERS[/]"); PanelBorders();
AnsiConsole.WriteLine();
RenderPanelBorders();
// Render table borders // Render table borders
AnsiConsole.WriteLine(); HorizontalRule("TABLE BORDERS");
AnsiConsole.MarkupLine("[white bold underline]TABLE BORDERS[/]"); TableBorders();
AnsiConsole.WriteLine();
RenderTableBorders();
} }
private static void RenderPanelBorders() private static void PanelBorders()
{ {
static IRenderable CreatePanel(string name, BoxBorder border) static IRenderable CreatePanel(string name, BoxBorder border)
{ {
return new Panel($"This is a panel with\nthe [yellow]{name}[/] border.") return new Panel($"This is a panel with\nthe [yellow]{name}[/] border.")
.SetHeader($" {name} ", Style.Parse("blue"), Justify.Center) .Header($" [blue]{name}[/] ", Justify.Center)
.SetBorderStyle(Style.Parse("grey")) .Border(border)
.SetBorder(border); .BorderStyle(Style.Parse("grey"));
} }
var items = new[] var items = new[]
@@ -46,19 +42,18 @@ namespace BordersExample
new Padding(2,0,0,0))); new Padding(2,0,0,0)));
} }
private static void RenderTableBorders() private static void TableBorders()
{ {
static IRenderable CreateTable(string name, TableBorder border) static IRenderable CreateTable(string name, TableBorder border)
{ {
var table = new Table().SetBorder(border); var table = new Table().Border(border);
table.AddColumn("[yellow]Header 1[/]"); table.AddColumn("[yellow]Header 1[/]", c => c.Footer("[grey]Footer 1[/]"));
table.AddColumn("[yellow]Header 2[/]", col => col.RightAligned()); table.AddColumn("[yellow]Header 2[/]", col => col.Footer("[grey]Footer 2[/]").RightAligned());
table.AddRow("Cell", "Cell"); table.AddRow("Cell", "Cell");
table.AddRow("Cell", "Cell"); table.AddRow("Cell", "Cell");
return new Panel(table) return new Panel(table)
.SetHeader($" {name} ", Style.Parse("blue"), Justify.Center) .Header($" [blue]{name}[/] ", Justify.Center)
.SetBorderStyle(Style.Parse("grey"))
.NoBorder(); .NoBorder();
} }
@@ -85,5 +80,12 @@ namespace BordersExample
AnsiConsole.Render(new Columns(items).Collapse()); 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>net5.0</TargetFramework>
<IsPackable>false</IsPackable>
<Title>Calendars</Title>
<Description>Demonstrates how to render calendars.</Description>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
</ItemGroup>
</Project>

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

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

View File

@@ -24,7 +24,7 @@ namespace ColorExample
AnsiConsole.ResetColors(); AnsiConsole.ResetColors();
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[bold underline]3-bit Colors[/]"); AnsiConsole.Render(new Rule("[yellow bold underline]3-bit Colors[/]").RuleStyle("grey").LeftAligned());
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
for (var i = 0; i < 8; i++) for (var i = 0; i < 8; i++)
@@ -47,7 +47,7 @@ namespace ColorExample
AnsiConsole.ResetColors(); AnsiConsole.ResetColors();
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[bold underline]4-bit Colors[/]"); AnsiConsole.Render(new Rule("[yellow bold underline]4-bit Colors[/]").RuleStyle("grey").LeftAligned());
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
for (var i = 0; i < 16; i++) for (var i = 0; i < 16; i++)
@@ -70,7 +70,7 @@ namespace ColorExample
AnsiConsole.ResetColors(); AnsiConsole.ResetColors();
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[bold underline]8-bit Colors[/]"); AnsiConsole.Render(new Rule("[yellow bold underline]8-bit Colors[/]").RuleStyle("grey").LeftAligned());
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
for (var i = 0; i < 16; i++) for (var i = 0; i < 16; i++)
@@ -97,7 +97,7 @@ namespace ColorExample
AnsiConsole.ResetColors(); AnsiConsole.ResetColors();
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
AnsiConsole.MarkupLine("[bold underline]24-bit Colors[/]"); AnsiConsole.Render(new Rule("[yellow bold underline]24-bit Colors[/]").RuleStyle("grey").LeftAligned());
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
var index = 0; var index = 0;

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<Title>Columns</Title> <Title>Columns</Title>
<Description>Demonstrates how to render data into columns.</Description> <Description>Demonstrates how to render data into columns.</Description>

View File

@@ -19,8 +19,8 @@ namespace ColumnsExample
var cards = new List<Panel>(); var cards = new List<Panel>();
foreach(var user in users.results) foreach(var user in users.results)
{ {
cards.Add(new Panel(GetCard(user)) cards.Add(new Panel(GetCardContent(user))
.SetHeader($"{user.location.country}") .Header($"{user.location.country}")
.RoundedBorder().Expand()); .RoundedBorder().Expand());
} }
@@ -28,7 +28,7 @@ namespace ColumnsExample
AnsiConsole.Render(new Columns(cards)); AnsiConsole.Render(new Columns(cards));
} }
private static string GetCard(dynamic user) private static string GetCardContent(dynamic user)
{ {
var name = $"{user.name.first} {user.name.last}"; var name = $"{user.name.first} {user.name.last}";
var country = $"{user.location.city}"; var country = $"{user.location.city}";

View File

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

View File

@@ -0,0 +1,20 @@
using Spectre.Console;
namespace Cursor
{
public static class Program
{
public static void Main(string[] args)
{
AnsiConsole.Write("Hello");
// Move the cursor 3 cells to the right
AnsiConsole.Cursor.Move(CursorDirection.Right, 3);
AnsiConsole.Write("World");
// Move the cursor 5 cells to the left.
AnsiConsole.Cursor.Move(CursorDirection.Left, 5);
AnsiConsole.WriteLine("Universe");
}
}
}

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<Title>Emojis</Title> <Title>Emojis</Title>
<Description>Demonstrates how to render emojis.</Description> <Description>Demonstrates how to render emojis.</Description>

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<Title>Exceptions</Title> <Title>Exceptions</Title>
<Description>Demonstrates how to render formatted exceptions.</Description> <Description>Demonstrates how to render formatted exceptions.</Description>

View File

@@ -15,32 +15,32 @@ namespace Exceptions
catch (Exception ex) catch (Exception ex)
{ {
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
AnsiConsole.Render(new Panel("[u]Default[/]").Expand()); AnsiConsole.Render(new Rule("Default").LeftAligned());
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex); AnsiConsole.WriteException(ex);
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
AnsiConsole.Render(new Panel("[u]Compact[/]").Expand()); AnsiConsole.Render(new Rule("Compact").LeftAligned());
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks); AnsiConsole.WriteException(ex, ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks);
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
AnsiConsole.Render(new Panel("[u]Custom colors[/]").Expand()); AnsiConsole.Render(new Rule("Compact + Custom colors").LeftAligned());
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
AnsiConsole.WriteException(ex, new ExceptionSettings AnsiConsole.WriteException(ex, new ExceptionSettings
{ {
Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks, Format = ExceptionFormats.ShortenEverything | ExceptionFormats.ShowLinks,
Style = new ExceptionStyle Style = new ExceptionStyle
{ {
Exception = Style.WithForeground(Color.Grey), Exception = new Style().Foreground(Color.Grey),
Message = Style.WithForeground(Color.White), Message = new Style().Foreground(Color.White),
NonEmphasized = Style.WithForeground(Color.Cornsilk1), NonEmphasized = new Style().Foreground(Color.Cornsilk1),
Parenthesis = Style.WithForeground(Color.Cornsilk1), Parenthesis = new Style().Foreground(Color.Cornsilk1),
Method = Style.WithForeground(Color.Red), Method = new Style().Foreground(Color.Red),
ParameterName = Style.WithForeground(Color.Cornsilk1), ParameterName = new Style().Foreground(Color.Cornsilk1),
ParameterType = Style.WithForeground(Color.Red), ParameterType = new Style().Foreground(Color.Red),
Path = Style.WithForeground(Color.Red), Path = new Style().Foreground(Color.Red),
LineNumber = Style.WithForeground(Color.Cornsilk1), LineNumber = new Style().Foreground(Color.Cornsilk1),
} }
}); });
} }

View File

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

View File

@@ -11,13 +11,12 @@ namespace GridExample
AnsiConsole.WriteLine(); AnsiConsole.WriteLine();
var grid = new Grid(); var grid = new Grid();
grid.AddColumn(new GridColumn { NoWrap = true }); grid.AddColumn(new GridColumn().NoWrap());
grid.AddColumn(new GridColumn { NoWrap = true, Width = 2 }); grid.AddColumn(new GridColumn().PadLeft(2));
grid.AddColumn(); grid.AddRow("Options:");
grid.AddRow("Options:", "", ""); grid.AddRow(" [blue]-h[/], [blue]--help[/]", "Show command line help.");
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]-c[/], [blue]--configuration[/] <CONFIGURATION>", "", "The configuration to run for."); grid.AddRow(" [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "Set the [grey]MSBuild[/] verbosity level.");
grid.AddRow(" [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "", "Set the [grey]MSBuild[/] verbosity level.");
AnsiConsole.Render(grid); AnsiConsole.Render(grid);
} }

View File

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

View File

@@ -17,7 +17,7 @@ namespace InfoExample
AnsiConsole.Render( AnsiConsole.Render(
new Panel(grid) new Panel(grid)
.SetHeader("Information")); .Header("Information"));
} }
private static string YesNo(bool value) private static string YesNo(bool value)

View File

@@ -2,7 +2,7 @@
<PropertyGroup> <PropertyGroup>
<OutputType>Exe</OutputType> <OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFramework>net5.0</TargetFramework>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
<Title>Links</Title> <Title>Links</Title>
<Description>Demonstrates how to render links in a console.</Description> <Description>Demonstrates how to render links in a console.</Description>

View File

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

View File

@@ -13,28 +13,30 @@ namespace PanelExample
AnsiConsole.Render( AnsiConsole.Render(
new Panel( new Panel(
new Panel(content) new Panel(content)
.SetBorder(BoxBorder.Rounded))); .Border(BoxBorder.Rounded)));
// Left adjusted panel with text // Left adjusted panel with text
AnsiConsole.Render( AnsiConsole.Render(
new Panel(new Text("Left adjusted\nLeft").LeftAligned()) new Panel(new Text("Left adjusted\nLeft").LeftAligned())
.Expand() .Expand()
.SquareBorder() .SquareBorder()
.SetHeader("Left", Style.WithForeground(Color.Red))); .Header("[red]Left[/]"));
// Centered ASCII panel with text // Centered ASCII panel with text
AnsiConsole.Render( AnsiConsole.Render(
new Panel(new Text("Centered\nCenter").Centered()) new Panel(new Text("Centered\nCenter").Centered())
.Expand() .Expand()
.AsciiBorder() .AsciiBorder()
.SetHeader("Center", Style.WithForeground(Color.Green), Justify.Center)); .Header("[green]Center[/]")
.HeaderAlignment(Justify.Center));
// Right adjusted, rounded panel with text // Right adjusted, rounded panel with text
AnsiConsole.Render( AnsiConsole.Render(
new Panel(new Text("Right adjusted\nRight").RightAligned()) new Panel(new Text("Right adjusted\nRight").RightAligned())
.Expand() .Expand()
.RoundedBorder() .RoundedBorder()
.SetHeader("Right", Style.WithForeground(Color.Blue), Justify.Right)); .Header("[blue]Right[/]")
.HeaderAlignment(Justify.Right));
} }
} }
} }

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

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

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</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

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

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

View File

@@ -1,7 +1,7 @@
{ {
"projects": [ "src" ], "projects": [ "src" ],
"sdk": { "sdk": {
"version": "3.1.301", "version": "5.0.100",
"rollForward": "latestPatch" "rollForward": "latestPatch"
} }
} }

View File

@@ -6,10 +6,10 @@ namespace Spectre.Console.Tests
{ {
if (foreground) if (foreground)
{ {
return style.WithForeground(color); return style.Foreground(color);
} }
return style.WithBackground(color); return style.Background(color);
} }
} }
} }

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk"> <Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup> <PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework> <TargetFrameworks>net5.0;netcoreapp3.1</TargetFrameworks>
<IsPackable>false</IsPackable> <IsPackable>false</IsPackable>
</PropertyGroup> </PropertyGroup>

View File

@@ -17,6 +17,7 @@ namespace Spectre.Console.Tests
public Encoding Encoding => _console.Encoding; public Encoding Encoding => _console.Encoding;
public int Width { get; } public int Width { get; }
public int Height => _console.Height; public int Height => _console.Height;
public IAnsiConsoleCursor Cursor => _console.Cursor;
public TestableAnsiConsole(ColorSystem system, AnsiSupport ansi = AnsiSupport.Yes, int width = 80) public TestableAnsiConsole(ColorSystem system, AnsiSupport ansi = AnsiSupport.Yes, int width = 80)
{ {
@@ -37,6 +38,11 @@ namespace Spectre.Console.Tests
_writer?.Dispose(); _writer?.Dispose();
} }
public void Clear(bool home)
{
_console.Clear(home);
}
public void Write(Segment segment) public void Write(Segment segment)
{ {
_console.Write(segment); _console.Write(segment);

View File

@@ -14,6 +14,7 @@ namespace Spectre.Console.Tests.Tools
public Capabilities Capabilities => _console.Capabilities; public Capabilities Capabilities => _console.Capabilities;
public Encoding Encoding => _console.Encoding; public Encoding Encoding => _console.Encoding;
public IAnsiConsoleCursor Cursor => _console.Cursor;
public int Width { get; } public int Width { get; }
public int Height => _console.Height; public int Height => _console.Height;
@@ -36,6 +37,11 @@ namespace Spectre.Console.Tests.Tools
_writer?.Dispose(); _writer?.Dispose();
} }
public void Clear(bool home)
{
_console.Clear(home);
}
public void Write(Segment segment) public void Write(Segment segment)
{ {
_console.Write(segment); _console.Write(segment);

View File

@@ -11,6 +11,7 @@ namespace Spectre.Console.Tests
{ {
public Capabilities Capabilities { get; } public Capabilities Capabilities { get; }
public Encoding Encoding { get; } public Encoding Encoding { get; }
public IAnsiConsoleCursor Cursor => throw new NotSupportedException();
public int Width { get; } public int Width { get; }
public int Height { get; } public int Height { get; }
@@ -42,6 +43,10 @@ namespace Spectre.Console.Tests
Writer.Dispose(); Writer.Dispose();
} }
public void Clear(bool home)
{
}
public void Write(Segment segment) public void Write(Segment segment)
{ {
if (segment is null) if (segment is null)

View File

@@ -21,7 +21,7 @@ namespace Spectre.Console.Tests.Unit
var console = new TestableAnsiConsole(ColorSystem.TrueColor); var console = new TestableAnsiConsole(ColorSystem.TrueColor);
// When // When
console.Write("Hello World", Style.WithDecoration(decoration)); console.Write("Hello World", new Style().Decoration(decoration));
// Then // Then
console.Output.ShouldBe(expected); console.Output.ShouldBe(expected);
@@ -36,7 +36,7 @@ namespace Spectre.Console.Tests.Unit
var console = new TestableAnsiConsole(ColorSystem.TrueColor); var console = new TestableAnsiConsole(ColorSystem.TrueColor);
// When // When
console.Write("Hello World", Style.WithDecoration(decoration)); console.Write("Hello World", new Style().Decoration(decoration));
// Then // Then
console.Output.ShouldBe(expected); console.Output.ShouldBe(expected);

View File

@@ -15,9 +15,10 @@ namespace Spectre.Console.Tests.Unit
// When // When
console.Write( console.Write(
"Hello", "Hello",
Style.WithForeground(Color.RoyalBlue1) new Style()
.WithBackground(Color.NavajoWhite1) .Foreground(Color.RoyalBlue1)
.WithDecoration(Decoration.Italic)); .Background(Color.NavajoWhite1)
.Decoration(Decoration.Italic));
// Then // Then
console.Output.ShouldBe("\u001b[3;90;47mHello\u001b[0m"); console.Output.ShouldBe("\u001b[3;90;47mHello\u001b[0m");
@@ -32,9 +33,10 @@ namespace Spectre.Console.Tests.Unit
// When // When
console.Write( console.Write(
"Hello", "Hello",
Style.WithForeground(Color.Default) new Style()
.WithBackground(Color.NavajoWhite1) .Foreground(Color.Default)
.WithDecoration(Decoration.Italic)); .Background(Color.NavajoWhite1)
.Decoration(Decoration.Italic));
// Then // Then
console.Output.ShouldBe("\u001b[3;47mHello\u001b[0m"); console.Output.ShouldBe("\u001b[3;47mHello\u001b[0m");
@@ -49,9 +51,10 @@ namespace Spectre.Console.Tests.Unit
// When // When
console.Write( console.Write(
"Hello", "Hello",
Style.WithForeground(Color.RoyalBlue1) new Style()
.WithBackground(Color.Default) .Foreground(Color.RoyalBlue1)
.WithDecoration(Decoration.Italic)); .Background(Color.Default)
.Decoration(Decoration.Italic));
// Then // Then
console.Output.ShouldBe("\u001b[3;90mHello\u001b[0m"); console.Output.ShouldBe("\u001b[3;90mHello\u001b[0m");
@@ -66,9 +69,10 @@ namespace Spectre.Console.Tests.Unit
// When // When
console.Write( console.Write(
"Hello", "Hello",
Style.WithForeground(Color.RoyalBlue1) new Style()
.WithBackground(Color.NavajoWhite1) .Foreground(Color.RoyalBlue1)
.WithDecoration(Decoration.None)); .Background(Color.NavajoWhite1)
.Decoration(Decoration.None));
// Then // Then
console.Output.ShouldBe("\u001b[90;47mHello\u001b[0m"); console.Output.ShouldBe("\u001b[90;47mHello\u001b[0m");
@@ -83,8 +87,8 @@ namespace Spectre.Console.Tests.Unit
var console = new TestableAnsiConsole(ColorSystem.Standard, AnsiSupport.Yes); var console = new TestableAnsiConsole(ColorSystem.Standard, AnsiSupport.Yes);
// When // When
console.WriteLine("Hello", Style.WithBackground(ConsoleColor.Red)); console.WriteLine("Hello", new Style().Background(ConsoleColor.Red));
console.WriteLine("World", Style.WithBackground(ConsoleColor.Green)); console.WriteLine("World", new Style().Background(ConsoleColor.Green));
// Then // Then
console.Output.NormalizeLineEndings() console.Output.NormalizeLineEndings()
@@ -98,7 +102,7 @@ namespace Spectre.Console.Tests.Unit
var console = new TestableAnsiConsole(ColorSystem.Standard, AnsiSupport.Yes); var console = new TestableAnsiConsole(ColorSystem.Standard, AnsiSupport.Yes);
// When // When
console.WriteLine("Hello\nWorld", Style.WithBackground(ConsoleColor.Red)); console.WriteLine("Hello\nWorld", new Style().Background(ConsoleColor.Red));
// Then // Then
console.Output.NormalizeLineEndings() console.Output.NormalizeLineEndings()

View File

@@ -14,7 +14,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border() public void Should_Return_Safe_Border()
{ {
// Given, When // Given, When
var border = BoxBorder.None.GetSafeBorder(safe: true); var border = BoxExtensions.GetSafeBorder(BoxBorder.None, safe: true);
// Then // Then
border.ShouldBeSameAs(BoxBorder.None); border.ShouldBeSameAs(BoxBorder.None);
@@ -47,7 +47,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border() public void Should_Return_Safe_Border()
{ {
// Given, When // Given, When
var border = BoxBorder.Ascii.GetSafeBorder(safe: true); var border = BoxExtensions.GetSafeBorder(BoxBorder.Ascii, safe: true);
// Then // Then
border.ShouldBeSameAs(BoxBorder.Ascii); border.ShouldBeSameAs(BoxBorder.Ascii);
@@ -80,7 +80,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border() public void Should_Return_Safe_Border()
{ {
// Given, When // Given, When
var border = BoxBorder.Double.GetSafeBorder(safe: true); var border = BoxExtensions.GetSafeBorder(BoxBorder.Double, safe: true);
// Then // Then
border.ShouldBeSameAs(BoxBorder.Double); border.ShouldBeSameAs(BoxBorder.Double);
@@ -113,7 +113,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border() public void Should_Return_Safe_Border()
{ {
// Given, When // Given, When
var border = BoxBorder.Heavy.GetSafeBorder(safe: true); var border = BoxExtensions.GetSafeBorder(BoxBorder.Heavy, safe: true);
// Then // Then
border.ShouldBeSameAs(BoxBorder.Square); border.ShouldBeSameAs(BoxBorder.Square);
@@ -144,7 +144,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border() public void Should_Return_Safe_Border()
{ {
// Given, When // Given, When
var border = BoxBorder.Rounded.GetSafeBorder(safe: true); var border = BoxExtensions.GetSafeBorder(BoxBorder.Rounded, safe: true);
// Then // Then
border.ShouldBeSameAs(BoxBorder.Square); border.ShouldBeSameAs(BoxBorder.Square);
@@ -174,7 +174,7 @@ namespace Spectre.Console.Tests.Unit
public void Should_Return_Safe_Border() public void Should_Return_Safe_Border()
{ {
// Given, When // Given, When
var border = BoxBorder.Square.GetSafeBorder(safe: true); var border = BoxExtensions.GetSafeBorder(BoxBorder.Square, safe: true);
// Then // Then
border.ShouldBeSameAs(BoxBorder.Square); border.ShouldBeSameAs(BoxBorder.Square);
@@ -203,7 +203,7 @@ namespace Spectre.Console.Tests.Unit
public static Panel GetPanel() public static Panel GetPanel()
{ {
return new Panel("Hello World") return new Panel("Hello World")
.SetHeader("Greeting"); .Header("Greeting");
} }
} }
} }

View File

@@ -0,0 +1,153 @@
using System;
using Shouldly;
using Xunit;
namespace Spectre.Console.Tests.Unit
{
public sealed class CalendarTests
{
[Fact]
public void Should_Render_Calendar_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var calendar = new Calendar(2020, 10)
.AddCalendarEvent(new DateTime(2020, 9, 1))
.AddCalendarEvent(new DateTime(2020, 10, 3))
.AddCalendarEvent(new DateTime(2020, 10, 12));
// When
console.Render(calendar);
// Then
console.Lines.Count.ShouldBe(11);
console.Lines[00].ShouldBe(" 2020 October ");
console.Lines[01].ShouldBe("┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐");
console.Lines[02].ShouldBe("│ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │");
console.Lines[03].ShouldBe("├─────┼─────┼─────┼─────┼─────┼─────┼─────┤");
console.Lines[04].ShouldBe("│ │ │ │ │ 1 │ 2 │ 3* │");
console.Lines[05].ShouldBe("│ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │");
console.Lines[06].ShouldBe("│ 11 │ 12* │ 13 │ 14 │ 15 │ 16 │ 17 │");
console.Lines[07].ShouldBe("│ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │");
console.Lines[08].ShouldBe("│ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │");
console.Lines[09].ShouldBe("│ │ │ │ │ │ │ │");
console.Lines[10].ShouldBe("└─────┴─────┴─────┴─────┴─────┴─────┴─────┘");
}
[Fact]
public void Should_Center_Calendar_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var calendar = new Calendar(2020, 10)
.Centered()
.AddCalendarEvent(new DateTime(2020, 9, 1))
.AddCalendarEvent(new DateTime(2020, 10, 3))
.AddCalendarEvent(new DateTime(2020, 10, 12));
// When
console.Render(calendar);
// Then
console.Lines.Count.ShouldBe(11);
console.Lines[00].ShouldBe(" 2020 October ");
console.Lines[01].ShouldBe(" ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐ ");
console.Lines[02].ShouldBe(" │ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │ ");
console.Lines[03].ShouldBe(" ├─────┼─────┼─────┼─────┼─────┼─────┼─────┤ ");
console.Lines[04].ShouldBe(" │ │ │ │ │ 1 │ 2 │ 3* │ ");
console.Lines[05].ShouldBe(" │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ ");
console.Lines[06].ShouldBe(" │ 11 │ 12* │ 13 │ 14 │ 15 │ 16 │ 17 │ ");
console.Lines[07].ShouldBe(" │ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │ ");
console.Lines[08].ShouldBe(" │ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │ ");
console.Lines[09].ShouldBe(" │ │ │ │ │ │ │ │ ");
console.Lines[10].ShouldBe(" └─────┴─────┴─────┴─────┴─────┴─────┴─────┘ ");
}
[Fact]
public void Should_Left_Align_Calendar_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var calendar = new Calendar(2020, 10)
.LeftAligned()
.AddCalendarEvent(new DateTime(2020, 9, 1))
.AddCalendarEvent(new DateTime(2020, 10, 3))
.AddCalendarEvent(new DateTime(2020, 10, 12));
// When
console.Render(calendar);
// Then
console.Lines.Count.ShouldBe(11);
console.Lines[00].ShouldBe(" 2020 October ");
console.Lines[01].ShouldBe("┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐");
console.Lines[02].ShouldBe("│ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │");
console.Lines[03].ShouldBe("├─────┼─────┼─────┼─────┼─────┼─────┼─────┤");
console.Lines[04].ShouldBe("│ │ │ │ │ 1 │ 2 │ 3* │");
console.Lines[05].ShouldBe("│ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │");
console.Lines[06].ShouldBe("│ 11 │ 12* │ 13 │ 14 │ 15 │ 16 │ 17 │");
console.Lines[07].ShouldBe("│ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │");
console.Lines[08].ShouldBe("│ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │");
console.Lines[09].ShouldBe("│ │ │ │ │ │ │ │");
console.Lines[10].ShouldBe("└─────┴─────┴─────┴─────┴─────┴─────┴─────┘");
}
[Fact]
public void Should_Right_Align_Calendar_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var calendar = new Calendar(2020, 10)
.RightAligned()
.AddCalendarEvent(new DateTime(2020, 9, 1))
.AddCalendarEvent(new DateTime(2020, 10, 3))
.AddCalendarEvent(new DateTime(2020, 10, 12));
// When
console.Render(calendar);
// Then
console.Lines.Count.ShouldBe(11);
console.Lines[00].ShouldBe(" 2020 October ");
console.Lines[01].ShouldBe(" ┌─────┬─────┬─────┬─────┬─────┬─────┬─────┐");
console.Lines[02].ShouldBe(" │ Sun │ Mon │ Tue │ Wed │ Thu │ Fri │ Sat │");
console.Lines[03].ShouldBe(" ├─────┼─────┼─────┼─────┼─────┼─────┼─────┤");
console.Lines[04].ShouldBe(" │ │ │ │ │ 1 │ 2 │ 3* │");
console.Lines[05].ShouldBe(" │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │");
console.Lines[06].ShouldBe(" │ 11 │ 12* │ 13 │ 14 │ 15 │ 16 │ 17 │");
console.Lines[07].ShouldBe(" │ 18 │ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │");
console.Lines[08].ShouldBe(" │ 25 │ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │");
console.Lines[09].ShouldBe(" │ │ │ │ │ │ │ │");
console.Lines[10].ShouldBe(" └─────┴─────┴─────┴─────┴─────┴─────┴─────┘");
}
[Fact]
public void Should_Render_Calendar_Correctly_For_Specific_Culture()
{
// Given
var console = new PlainConsole(width: 80);
var calendar = new Calendar(2020, 10, 15)
.Culture("de-DE")
.AddCalendarEvent(new DateTime(2020, 9, 1))
.AddCalendarEvent(new DateTime(2020, 10, 3))
.AddCalendarEvent(new DateTime(2020, 10, 12));
// When
console.Render(calendar);
// Then
console.Lines.Count.ShouldBe(11);
console.Lines[00].ShouldBe(" Oktober 2020 ");
console.Lines[01].ShouldBe("┌─────┬────┬────┬────┬────┬────┬────┐");
console.Lines[02].ShouldBe("│ Mo │ Di │ Mi │ Do │ Fr │ Sa │ So │");
console.Lines[03].ShouldBe("├─────┼────┼────┼────┼────┼────┼────┤");
console.Lines[04].ShouldBe("│ │ │ │ 1 │ 2 │ 3* │ 4 │");
console.Lines[05].ShouldBe("│ 5 │ 6 │ 7 │ 8 │ 9 │ 10 │ 11 │");
console.Lines[06].ShouldBe("│ 12* │ 13 │ 14 │ 15 │ 16 │ 17 │ 18 │");
console.Lines[07].ShouldBe("│ 19 │ 20 │ 21 │ 22 │ 23 │ 24 │ 25 │");
console.Lines[08].ShouldBe("│ 26 │ 27 │ 28 │ 29 │ 30 │ 31 │ │");
console.Lines[09].ShouldBe("│ │ │ │ │ │ │ │");
console.Lines[10].ShouldBe("└─────┴────┴────┴────┴────┴────┴────┘");
}
}
}

View File

@@ -53,7 +53,7 @@ namespace Spectre.Console.Tests.Unit
grid.AddRow("Foo"); grid.AddRow("Foo");
// Then // Then
grid.RowCount.ShouldBe(1); grid.Rows.Count.ShouldBe(1);
} }
[Fact] [Fact]

View File

@@ -6,6 +6,24 @@ namespace Spectre.Console.Tests.Unit
{ {
public sealed class MarkupTests public sealed class MarkupTests
{ {
public sealed class TheEscapeMethod
{
[Theory]
[InlineData("Hello World", "Hello World")]
[InlineData("Hello World [", "Hello World [[")]
[InlineData("Hello World ]", "Hello World ]]")]
[InlineData("Hello [World]", "Hello [[World]]")]
[InlineData("Hello [[World]]", "Hello [[[[World]]]]")]
public void Should_Escape_Markup_As_Expected(string input, string expected)
{
// Given, When
var result = Markup.Escape(input);
// Then
result.ShouldBe(expected);
}
}
[Theory] [Theory]
[InlineData("Hello [[ World ]")] [InlineData("Hello [[ World ]")]
[InlineData("Hello [[ World ] !")] [InlineData("Hello [[ World ] !")]

View File

@@ -17,7 +17,7 @@ namespace Spectre.Console.Tests.Unit
table.AddRow("Corgi", "Waldo"); table.AddRow("Corgi", "Waldo");
// When // When
console.Render(new Padder(table).SetPadding(1, 2, 3, 4)); console.Render(new Padder(table).Padding(1, 2, 3, 4));
// Then // Then
console.Lines.Count.ShouldBe(12); console.Lines.Count.ShouldBe(12);
@@ -48,7 +48,7 @@ namespace Spectre.Console.Tests.Unit
// When // When
console.Render(new Padder(table) console.Render(new Padder(table)
.SetPadding(1, 2, 3, 4) .Padding(1, 2, 3, 4)
.Expand()); .Expand());
// Then // Then
@@ -77,11 +77,11 @@ namespace Spectre.Console.Tests.Unit
table.AddColumn("Bar", c => c.PadLeft(0).PadRight(0)); table.AddColumn("Bar", c => c.PadLeft(0).PadRight(0));
table.AddRow("Baz", "Qux"); table.AddRow("Baz", "Qux");
table.AddRow(new Text("Corgi"), new Padder(new Panel("Waldo")) table.AddRow(new Text("Corgi"), new Padder(new Panel("Waldo"))
.SetPadding(2, 1, 2, 1)); .Padding(2, 1));
// When // When
console.Render(new Padder(table) console.Render(new Padder(table)
.SetPadding(1, 2, 3, 4) .Padding(1, 2, 3, 4)
.Expand()); .Expand());
// Then // Then

View File

@@ -244,7 +244,7 @@ namespace Spectre.Console.Tests.Unit
} }
[Fact] [Fact]
public void Should_Justify_Child_To_Right() public void Should_Justify_Child_To_Right_Correctly()
{ {
// Given // Given
var console = new PlainConsole(width: 25); var console = new PlainConsole(width: 25);
@@ -264,7 +264,7 @@ namespace Spectre.Console.Tests.Unit
} }
[Fact] [Fact]
public void Should_Justify_Child_To_Center() public void Should_Center_Child_Correctly()
{ {
// Given // Given
var console = new PlainConsole(width: 25); var console = new PlainConsole(width: 25);
@@ -315,15 +315,15 @@ namespace Spectre.Console.Tests.Unit
var panel = new Panel(grid) var panel = new Panel(grid)
.Expand().RoundedBorder() .Expand().RoundedBorder()
.SetBorderStyle(Style.WithForeground(Color.Grey)) .BorderStyle(new Style().Foreground(Color.Grey))
.SetHeader("Short paths ", Style.WithForeground(Color.Grey)); .Header("[grey]Short paths[/]");
// When // When
console.Render(panel); console.Render(panel);
// Then // Then
console.Lines.Count.ShouldBe(4); console.Lines.Count.ShouldBe(4);
console.Lines[0].ShouldBe("╭─Short paths ─────────────────────────────────────────────────────────────────────╮"); console.Lines[0].ShouldBe("╭─Short paths─────────────────────────────────────────────────────────────────────╮");
console.Lines[1].ShouldBe("│ at System.Runtime.CompilerServices.TaskAwaiter. │"); console.Lines[1].ShouldBe("│ at System.Runtime.CompilerServices.TaskAwaiter. │");
console.Lines[2].ShouldBe("│ HandleNonSuccessAndDebuggerNotification(Task task) │"); console.Lines[2].ShouldBe("│ HandleNonSuccessAndDebuggerNotification(Task task) │");
console.Lines[3].ShouldBe("╰──────────────────────────────────────────────────────────────────────────────────╯"); console.Lines[3].ShouldBe("╰──────────────────────────────────────────────────────────────────────────────────╯");

View File

@@ -43,7 +43,7 @@ namespace Spectre.Console.Tests.Unit
.AddColumns("[red on black]Foo[/]", "[green bold]Bar[/]", "[blue italic]Qux[/]") .AddColumns("[red on black]Foo[/]", "[green bold]Bar[/]", "[blue italic]Qux[/]")
.AddRow("[invert underline]Corgi[/]", "[bold strikethrough]Waldo[/]", "[dim]Zap[/]") .AddRow("[invert underline]Corgi[/]", "[bold strikethrough]Waldo[/]", "[dim]Zap[/]")
.AddRow(new Panel("[blue]Hello World[/]") .AddRow(new Panel("[blue]Hello World[/]")
.SetBorderColor(Color.Red).RoundedBorder())); .BorderColor(Color.Red).RoundedBorder()));
// When // When
var html = recorder.ExportHtml(); var html = recorder.ExportHtml();

View File

@@ -0,0 +1,153 @@
using Shouldly;
using Xunit;
namespace Spectre.Console.Tests.Unit
{
public sealed class RuleTests
{
[Fact]
public void Should_Render_Default_Rule_Without_Title()
{
// Given
var console = new PlainConsole(width: 40);
// When
console.Render(new Rule());
// Then
console.Lines.Count.ShouldBe(1);
console.Lines[0].ShouldBe("────────────────────────────────────────");
}
[Fact]
public void Should_Render_Default_Rule_With_Specified_Box()
{
// Given
var console = new PlainConsole(width: 40);
// When
console.Render(new Rule().DoubleBorder());
// Then
console.Lines.Count.ShouldBe(1);
console.Lines[0].ShouldBe("════════════════════════════════════════");
}
[Fact]
public void Should_Render_With_Specified_Box()
{
// Given
var console = new PlainConsole(width: 40);
// When
console.Render(new Rule("Hello World").DoubleBorder());
// Then
console.Lines.Count.ShouldBe(1);
console.Lines[0].ShouldBe("═════════════ Hello World ══════════════");
}
[Fact]
public void Should_Render_Default_Rule_With_Title_Centered_By_Default()
{
// Given
var console = new PlainConsole(width: 40);
// When
console.Render(new Rule("Hello World"));
// Then
console.Lines.Count.ShouldBe(1);
console.Lines[0].ShouldBe("───────────── Hello World ──────────────");
}
[Fact]
public void Should_Render_Default_Rule_With_Title_Left_Aligned()
{
// Given
var console = new PlainConsole(width: 40);
// When
console.Render(new Rule("Hello World")
{
Alignment = Justify.Left,
});
// Then
console.Lines.Count.ShouldBe(1);
console.Lines[0].ShouldBe("── Hello World ─────────────────────────");
}
[Fact]
public void Should_Render_Default_Rule_With_Title_Right_Aligned()
{
// Given
var console = new PlainConsole(width: 40);
// When
console.Render(new Rule("Hello World")
{
Alignment = Justify.Right,
});
// Then
console.Lines.Count.ShouldBe(1);
console.Lines[0].ShouldBe("───────────────────────── Hello World ──");
}
[Fact]
public void Should_Convert_Line_Breaks_In_Title_To_Spaces()
{
// Given
var console = new PlainConsole(width: 40);
// When
console.Render(new Rule("Hello\nWorld\r\n!"));
// Then
console.Lines.Count.ShouldBe(1);
console.Lines[0].ShouldBe("──────────── Hello World ! ─────────────");
}
[Fact]
public void Should_Truncate_Title()
{
// Given
var console = new PlainConsole(width: 40);
// When
console.Render(new Rule(" Hello World "));
// Then
console.Lines.Count.ShouldBe(1);
console.Lines[0].ShouldBe("───────────── Hello World ──────────────");
}
[Theory]
[InlineData(0, "Hello World Hello World Hello World Hello World Hello World", "")]
[InlineData(1, "Hello World Hello World Hello World Hello World Hello World", "─")]
[InlineData(2, "Hello World Hello World Hello World Hello World Hello World", "──")]
[InlineData(3, "Hello World Hello World Hello World Hello World Hello World", "───")]
[InlineData(4, "Hello World Hello World Hello World Hello World Hello World", "────")]
[InlineData(5, "Hello World Hello World Hello World Hello World Hello World", "─────")]
[InlineData(6, "Hello World Hello World Hello World Hello World Hello World", "──────")]
[InlineData(7, "Hello World Hello World Hello World Hello World Hello World", "───────")]
[InlineData(8, "Hello World Hello World Hello World Hello World Hello World", "── H… ──")]
[InlineData(8, "A", "── A ───")]
[InlineData(8, "AB", "── AB ──")]
[InlineData(8, "ABC", "── A… ──")]
[InlineData(40, "Hello World Hello World Hello World Hello World Hello World", "──── Hello World Hello World Hello… ────")]
public void Should_Truncate_Too_Long_Title(int width, string input, string expected)
{
// Given
var console = new PlainConsole(width);
// When
console.Render(new Rule(input));
// Then
console.Lines.Count.ShouldBe(1);
console.Lines[0].ShouldBe(expected);
}
}
}

View File

@@ -1,3 +1,4 @@
using System.Text;
using Shouldly; using Shouldly;
using Spectre.Console.Rendering; using Spectre.Console.Rendering;
using Xunit; using Xunit;
@@ -6,6 +7,16 @@ namespace Spectre.Console.Tests.Unit
{ {
public sealed class SegmentTests public sealed class SegmentTests
{ {
[Fact]
public void Lol()
{
var context = new RenderContext(Encoding.UTF8, false);
var result = new Segment(" ").CellCount(context);
result.ShouldBe(4);
}
public sealed class TheSplitMethod public sealed class TheSplitMethod
{ {
[Fact] [Fact]
@@ -31,7 +42,10 @@ namespace Spectre.Console.Tests.Unit
[Fact] [Fact]
public void Should_Split_Segment() public void Should_Split_Segment()
{ {
var context = new RenderContext(Encoding.UTF8, false);
var lines = Segment.SplitLines( var lines = Segment.SplitLines(
context,
new[] new[]
{ {
new Segment("Foo"), new Segment("Foo"),
@@ -61,7 +75,9 @@ namespace Spectre.Console.Tests.Unit
[Fact] [Fact]
public void Should_Split_Segments_With_Linebreak_In_Text() public void Should_Split_Segments_With_Linebreak_In_Text()
{ {
var context = new RenderContext(Encoding.UTF8, false);
var lines = Segment.SplitLines( var lines = Segment.SplitLines(
context,
new[] new[]
{ {
new Segment("Foo\n"), new Segment("Foo\n"),

View File

@@ -42,10 +42,11 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(3); console.Lines.Count.ShouldBe(4);
console.Lines[0].ShouldBe("Header 1 Header 2"); console.Lines[0].ShouldBe("Header 1 Header 2");
console.Lines[1].ShouldBe("Cell Cell "); console.Lines[1].ShouldBe("Cell Cell ");
console.Lines[2].ShouldBe("Cell Cell "); console.Lines[2].ShouldBe("Cell Cell ");
console.Lines[3].ShouldBe("Footer 1 Footer 2");
} }
} }
@@ -85,13 +86,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("+---------------------+"); console.Lines[0].ShouldBe("+---------------------+");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("|----------+----------|"); console.Lines[2].ShouldBe("|----------+----------|");
console.Lines[3].ShouldBe("| Cell | Cell |"); console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |"); console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe("+---------------------+"); console.Lines[5].ShouldBe("|----------+----------|");
console.Lines[6].ShouldBe("| Footer 1 | Footer 2 |");
console.Lines[7].ShouldBe("+---------------------+");
} }
} }
@@ -131,13 +134,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("+----------+----------+"); console.Lines[0].ShouldBe("+----------+----------+");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("|----------+----------|"); console.Lines[2].ShouldBe("|----------+----------|");
console.Lines[3].ShouldBe("| Cell | Cell |"); console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |"); console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe("+----------+----------+"); console.Lines[5].ShouldBe("|----------+----------|");
console.Lines[6].ShouldBe("| Footer 1 | Footer 2 |");
console.Lines[7].ShouldBe("+----------+----------+");
} }
} }
@@ -177,13 +182,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("+----------+----------+"); console.Lines[0].ShouldBe("+----------+----------+");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("|==========+==========|"); console.Lines[2].ShouldBe("|==========+==========|");
console.Lines[3].ShouldBe("| Cell | Cell |"); console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |"); console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe("+----------+----------+"); console.Lines[5].ShouldBe("+----------+----------+");
console.Lines[6].ShouldBe("| Footer 1 | Footer 2 |");
console.Lines[7].ShouldBe("+----------+----------+");
} }
} }
@@ -223,13 +230,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("┌──────────┬──────────┐"); console.Lines[0].ShouldBe("┌──────────┬──────────┐");
console.Lines[1].ShouldBe("│ Header 1 │ Header 2 │"); console.Lines[1].ShouldBe("│ Header 1 │ Header 2 │");
console.Lines[2].ShouldBe("├──────────┼──────────┤"); console.Lines[2].ShouldBe("├──────────┼──────────┤");
console.Lines[3].ShouldBe("│ Cell │ Cell │"); console.Lines[3].ShouldBe("│ Cell │ Cell │");
console.Lines[4].ShouldBe("│ Cell │ Cell │"); console.Lines[4].ShouldBe("│ Cell │ Cell │");
console.Lines[5].ShouldBe("────────────────────"); console.Lines[5].ShouldBe("────────────────────");
console.Lines[6].ShouldBe("│ Footer 1 │ Footer 2 │");
console.Lines[7].ShouldBe("└──────────┴──────────┘");
} }
} }
@@ -269,13 +278,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("╭──────────┬──────────╮"); console.Lines[0].ShouldBe("╭──────────┬──────────╮");
console.Lines[1].ShouldBe("│ Header 1 │ Header 2 │"); console.Lines[1].ShouldBe("│ Header 1 │ Header 2 │");
console.Lines[2].ShouldBe("├──────────┼──────────┤"); console.Lines[2].ShouldBe("├──────────┼──────────┤");
console.Lines[3].ShouldBe("│ Cell │ Cell │"); console.Lines[3].ShouldBe("│ Cell │ Cell │");
console.Lines[4].ShouldBe("│ Cell │ Cell │"); console.Lines[4].ShouldBe("│ Cell │ Cell │");
console.Lines[5].ShouldBe("────────────────────"); console.Lines[5].ShouldBe("────────────────────");
console.Lines[6].ShouldBe("│ Footer 1 │ Footer 2 │");
console.Lines[7].ShouldBe("╰──────────┴──────────╯");
} }
} }
@@ -315,13 +326,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe(" "); console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe(" Header 1 │ Header 2 "); console.Lines[1].ShouldBe(" Header 1 │ Header 2 ");
console.Lines[2].ShouldBe(" ──────────┼────────── "); console.Lines[2].ShouldBe(" ──────────┼────────── ");
console.Lines[3].ShouldBe(" Cell │ Cell "); console.Lines[3].ShouldBe(" Cell │ Cell ");
console.Lines[4].ShouldBe(" Cell │ Cell "); console.Lines[4].ShouldBe(" Cell │ Cell ");
console.Lines[5].ShouldBe(" "); console.Lines[5].ShouldBe(" ──────────┼────────── ");
console.Lines[6].ShouldBe(" Footer 1 │ Footer 2 ");
console.Lines[7].ShouldBe(" ");
} }
} }
@@ -361,13 +374,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe(" "); console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe(" Header 1 │ Header 2 "); console.Lines[1].ShouldBe(" Header 1 │ Header 2 ");
console.Lines[2].ShouldBe(" ━━━━━━━━━━┿━━━━━━━━━━ "); console.Lines[2].ShouldBe(" ━━━━━━━━━━┿━━━━━━━━━━ ");
console.Lines[3].ShouldBe(" Cell │ Cell "); console.Lines[3].ShouldBe(" Cell │ Cell ");
console.Lines[4].ShouldBe(" Cell │ Cell "); console.Lines[4].ShouldBe(" Cell │ Cell ");
console.Lines[5].ShouldBe(" "); console.Lines[5].ShouldBe(" ━━━━━━━━━━┿━━━━━━━━━━ ");
console.Lines[6].ShouldBe(" Footer 1 │ Footer 2 ");
console.Lines[7].ShouldBe(" ");
} }
} }
@@ -407,13 +422,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe(" "); console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe(" Header 1 │ Header 2 "); console.Lines[1].ShouldBe(" Header 1 │ Header 2 ");
console.Lines[2].ShouldBe(" ══════════╪══════════ "); console.Lines[2].ShouldBe(" ══════════╪══════════ ");
console.Lines[3].ShouldBe(" Cell │ Cell "); console.Lines[3].ShouldBe(" Cell │ Cell ");
console.Lines[4].ShouldBe(" Cell │ Cell "); console.Lines[4].ShouldBe(" Cell │ Cell ");
console.Lines[5].ShouldBe(" "); console.Lines[5].ShouldBe(" ══════════╪══════════ ");
console.Lines[6].ShouldBe(" Footer 1 │ Footer 2 ");
console.Lines[7].ShouldBe(" ");
} }
} }
@@ -453,13 +470,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe(" "); console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe(" Header 1 Header 2 "); console.Lines[1].ShouldBe(" Header 1 Header 2 ");
console.Lines[2].ShouldBe("───────────────────────"); console.Lines[2].ShouldBe("───────────────────────");
console.Lines[3].ShouldBe(" Cell Cell "); console.Lines[3].ShouldBe(" Cell Cell ");
console.Lines[4].ShouldBe(" Cell Cell "); console.Lines[4].ShouldBe(" Cell Cell ");
console.Lines[5].ShouldBe(" "); console.Lines[5].ShouldBe("───────────────────────");
console.Lines[6].ShouldBe(" Footer 1 Footer 2 ");
console.Lines[7].ShouldBe(" ");
} }
} }
@@ -499,13 +518,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("───────────────────────"); console.Lines[0].ShouldBe("───────────────────────");
console.Lines[1].ShouldBe(" Header 1 Header 2 "); console.Lines[1].ShouldBe(" Header 1 Header 2 ");
console.Lines[2].ShouldBe("───────────────────────"); console.Lines[2].ShouldBe("───────────────────────");
console.Lines[3].ShouldBe(" Cell Cell "); console.Lines[3].ShouldBe(" Cell Cell ");
console.Lines[4].ShouldBe(" Cell Cell "); console.Lines[4].ShouldBe(" Cell Cell ");
console.Lines[5].ShouldBe("───────────────────────"); console.Lines[5].ShouldBe("───────────────────────");
console.Lines[6].ShouldBe(" Footer 1 Footer 2 ");
console.Lines[7].ShouldBe("───────────────────────");
} }
} }
@@ -545,13 +566,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe(" "); console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe(" Header 1 Header 2 "); console.Lines[1].ShouldBe(" Header 1 Header 2 ");
console.Lines[2].ShouldBe("━━━━━━━━━━━━━━━━━━━━━━━"); console.Lines[2].ShouldBe("━━━━━━━━━━━━━━━━━━━━━━━");
console.Lines[3].ShouldBe(" Cell Cell "); console.Lines[3].ShouldBe(" Cell Cell ");
console.Lines[4].ShouldBe(" Cell Cell "); console.Lines[4].ShouldBe(" Cell Cell ");
console.Lines[5].ShouldBe(" "); console.Lines[5].ShouldBe("━━━━━━━━━━━━━━━━━━━━━━━");
console.Lines[6].ShouldBe(" Footer 1 Footer 2 ");
console.Lines[7].ShouldBe(" ");
} }
} }
@@ -591,13 +614,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("┏━━━━━━━━━━┳━━━━━━━━━━┓"); console.Lines[0].ShouldBe("┏━━━━━━━━━━┳━━━━━━━━━━┓");
console.Lines[1].ShouldBe("┃ Header 1 ┃ Header 2 ┃"); console.Lines[1].ShouldBe("┃ Header 1 ┃ Header 2 ┃");
console.Lines[2].ShouldBe("┣━━━━━━━━━━╋━━━━━━━━━━┫"); console.Lines[2].ShouldBe("┣━━━━━━━━━━╋━━━━━━━━━━┫");
console.Lines[3].ShouldBe("┃ Cell ┃ Cell ┃"); console.Lines[3].ShouldBe("┃ Cell ┃ Cell ┃");
console.Lines[4].ShouldBe("┃ Cell ┃ Cell ┃"); console.Lines[4].ShouldBe("┃ Cell ┃ Cell ┃");
console.Lines[5].ShouldBe("━━━━━━━━━━━━━━━━━━━━"); console.Lines[5].ShouldBe("━━━━━━━━━━━━━━━━━━━━");
console.Lines[6].ShouldBe("┃ Footer 1 ┃ Footer 2 ┃");
console.Lines[7].ShouldBe("┗━━━━━━━━━━┻━━━━━━━━━━┛");
} }
} }
@@ -637,13 +662,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("┏━━━━━━━━━━┯━━━━━━━━━━┓"); console.Lines[0].ShouldBe("┏━━━━━━━━━━┯━━━━━━━━━━┓");
console.Lines[1].ShouldBe("┃ Header 1 │ Header 2 ┃"); console.Lines[1].ShouldBe("┃ Header 1 │ Header 2 ┃");
console.Lines[2].ShouldBe("┠──────────┼──────────┨"); console.Lines[2].ShouldBe("┠──────────┼──────────┨");
console.Lines[3].ShouldBe("┃ Cell │ Cell ┃"); console.Lines[3].ShouldBe("┃ Cell │ Cell ┃");
console.Lines[4].ShouldBe("┃ Cell │ Cell ┃"); console.Lines[4].ShouldBe("┃ Cell │ Cell ┃");
console.Lines[5].ShouldBe("┗━━━━━━━━━━┷━━━━━━━━━━┛"); console.Lines[5].ShouldBe("┠──────────┼──────────┨");
console.Lines[6].ShouldBe("┃ Footer 1 │ Footer 2 ┃");
console.Lines[7].ShouldBe("┗━━━━━━━━━━┷━━━━━━━━━━┛");
} }
} }
@@ -683,13 +710,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("┏━━━━━━━━━━┳━━━━━━━━━━┓"); console.Lines[0].ShouldBe("┏━━━━━━━━━━┳━━━━━━━━━━┓");
console.Lines[1].ShouldBe("┃ Header 1 ┃ Header 2 ┃"); console.Lines[1].ShouldBe("┃ Header 1 ┃ Header 2 ┃");
console.Lines[2].ShouldBe("┡━━━━━━━━━━╇━━━━━━━━━━┩"); console.Lines[2].ShouldBe("┡━━━━━━━━━━╇━━━━━━━━━━┩");
console.Lines[3].ShouldBe("│ Cell │ Cell │"); console.Lines[3].ShouldBe("│ Cell │ Cell │");
console.Lines[4].ShouldBe("│ Cell │ Cell │"); console.Lines[4].ShouldBe("│ Cell │ Cell │");
console.Lines[5].ShouldBe("────────────────────"); console.Lines[5].ShouldBe("────────────────────");
console.Lines[6].ShouldBe("│ Footer 1 │ Footer 2 │");
console.Lines[7].ShouldBe("└──────────┴──────────┘");
} }
} }
@@ -729,13 +758,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("╔══════════╦══════════╗"); console.Lines[0].ShouldBe("╔══════════╦══════════╗");
console.Lines[1].ShouldBe("║ Header 1 ║ Header 2 ║"); console.Lines[1].ShouldBe("║ Header 1 ║ Header 2 ║");
console.Lines[2].ShouldBe("╠══════════╬══════════╣"); console.Lines[2].ShouldBe("╠══════════╬══════════╣");
console.Lines[3].ShouldBe("║ Cell ║ Cell ║"); console.Lines[3].ShouldBe("║ Cell ║ Cell ║");
console.Lines[4].ShouldBe("║ Cell ║ Cell ║"); console.Lines[4].ShouldBe("║ Cell ║ Cell ║");
console.Lines[5].ShouldBe("════════════════════"); console.Lines[5].ShouldBe("════════════════════");
console.Lines[6].ShouldBe("║ Footer 1 ║ Footer 2 ║");
console.Lines[7].ShouldBe("╚══════════╩══════════╝");
} }
} }
@@ -775,13 +806,15 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("╔══════════╤══════════╗"); console.Lines[0].ShouldBe("╔══════════╤══════════╗");
console.Lines[1].ShouldBe("║ Header 1 │ Header 2 ║"); console.Lines[1].ShouldBe("║ Header 1 │ Header 2 ║");
console.Lines[2].ShouldBe("╟──────────┼──────────╢"); console.Lines[2].ShouldBe("╟──────────┼──────────╢");
console.Lines[3].ShouldBe("║ Cell │ Cell ║"); console.Lines[3].ShouldBe("║ Cell │ Cell ║");
console.Lines[4].ShouldBe("║ Cell │ Cell ║"); console.Lines[4].ShouldBe("║ Cell │ Cell ║");
console.Lines[5].ShouldBe("╚══════════╧══════════╝"); console.Lines[5].ShouldBe("╟──────────┼──────────╢");
console.Lines[6].ShouldBe("║ Footer 1 │ Footer 2 ║");
console.Lines[7].ShouldBe("╚══════════╧══════════╝");
} }
} }
@@ -821,13 +854,14 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(7);
console.Lines[0].ShouldBe(" "); console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("| -------- | -------- |"); console.Lines[2].ShouldBe("| -------- | -------- |");
console.Lines[3].ShouldBe("| Cell | Cell |"); console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |"); console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe(" "); console.Lines[5].ShouldBe("| Footer 1 | Footer 2 |");
console.Lines[6].ShouldBe(" ");
} }
[Fact] [Fact]
@@ -841,13 +875,14 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(7);
console.Lines[0].ShouldBe(" "); console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("| -------- | :------- |"); console.Lines[2].ShouldBe("| -------- | :------- |");
console.Lines[3].ShouldBe("| Cell | Cell |"); console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |"); console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe(" "); console.Lines[5].ShouldBe("| Footer 1 | Footer 2 |");
console.Lines[6].ShouldBe(" ");
} }
[Fact] [Fact]
@@ -861,13 +896,14 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(7);
console.Lines[0].ShouldBe(" "); console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("| -------- | :------: |"); console.Lines[2].ShouldBe("| -------- | :------: |");
console.Lines[3].ShouldBe("| Cell | Cell |"); console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |"); console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe(" "); console.Lines[5].ShouldBe("| Footer 1 | Footer 2 |");
console.Lines[6].ShouldBe(" ");
} }
[Fact] [Fact]
@@ -881,13 +917,14 @@ namespace Spectre.Console.Tests.Unit
console.Render(table); console.Render(table);
// Then // Then
console.Lines.Count.ShouldBe(6); console.Lines.Count.ShouldBe(7);
console.Lines[0].ShouldBe(" "); console.Lines[0].ShouldBe(" ");
console.Lines[1].ShouldBe("| Header 1 | Header 2 |"); console.Lines[1].ShouldBe("| Header 1 | Header 2 |");
console.Lines[2].ShouldBe("| -------- | -------: |"); console.Lines[2].ShouldBe("| -------- | -------: |");
console.Lines[3].ShouldBe("| Cell | Cell |"); console.Lines[3].ShouldBe("| Cell | Cell |");
console.Lines[4].ShouldBe("| Cell | Cell |"); console.Lines[4].ShouldBe("| Cell | Cell |");
console.Lines[5].ShouldBe(" "); console.Lines[5].ShouldBe("| Footer 1 | Footer 2 |");
console.Lines[6].ShouldBe(" ");
} }
} }
@@ -896,8 +933,8 @@ namespace Spectre.Console.Tests.Unit
public static Table GetTable(Justify? header1 = null, Justify? header2 = null) public static Table GetTable(Justify? header1 = null, Justify? header2 = null)
{ {
var table = new Table(); var table = new Table();
table.AddColumn("Header 1", c => c.Alignment = header1); table.AddColumn("Header 1", c => c.Alignment(header1).Footer("Footer 1"));
table.AddColumn("Header 2", c => c.Alignment = header2); table.AddColumn("Header 2", c => c.Alignment(header2).Footer("Footer 2"));
table.AddRow("Cell", "Cell"); table.AddRow("Cell", "Cell");
table.AddRow("Cell", "Cell"); table.AddRow("Cell", "Cell");
return table; return table;

View File

@@ -98,7 +98,7 @@ namespace Spectre.Console.Tests.Unit
table.AddRow("Foo"); table.AddRow("Foo");
// Then // Then
table.RowCount.ShouldBe(1); table.Rows.Count.ShouldBe(1);
} }
[Fact] [Fact]
@@ -168,6 +168,105 @@ namespace Spectre.Console.Tests.Unit
console.Lines[5].ShouldBe("└────────┴────────┴───────┘"); console.Lines[5].ShouldBe("└────────┴────────┴───────┘");
} }
[Fact]
public void Should_Render_Table_With_Footers_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table();
table.AddColumn(new TableColumn("Foo").Footer("Oof").RightAligned());
table.AddColumn("Bar");
table.AddColumns(new TableColumn("Baz").Footer("Zab"));
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe("┌────────┬────────┬───────┐");
console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │");
console.Lines[2].ShouldBe("├────────┼────────┼───────┤");
console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │");
console.Lines[4].ShouldBe("│ Grault │ Garply │ Fred │");
console.Lines[5].ShouldBe("├────────┼────────┼───────┤");
console.Lines[6].ShouldBe("│ Oof │ │ Zab │");
console.Lines[7].ShouldBe("└────────┴────────┴───────┘");
}
[Fact]
public void Should_Left_Align_Table_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table();
table.Alignment = Justify.Left;
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(6);
console.Lines[0].ShouldBe("┌────────┬────────┬───────┐");
console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │");
console.Lines[2].ShouldBe("├────────┼────────┼───────┤");
console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │");
console.Lines[4].ShouldBe("│ Grault │ Garply │ Fred │");
console.Lines[5].ShouldBe("└────────┴────────┴───────┘");
}
[Fact]
public void Should_Center_Table_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table();
table.Alignment = Justify.Center;
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(6);
console.Lines[0].ShouldBe(" ┌────────┬────────┬───────┐ ");
console.Lines[1].ShouldBe(" │ Foo │ Bar │ Baz │ ");
console.Lines[2].ShouldBe(" ├────────┼────────┼───────┤ ");
console.Lines[3].ShouldBe(" │ Qux │ Corgi │ Waldo │ ");
console.Lines[4].ShouldBe(" │ Grault │ Garply │ Fred │ ");
console.Lines[5].ShouldBe(" └────────┴────────┴───────┘ ");
}
[Fact]
public void Should_Right_Align_Table_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table();
table.Alignment = Justify.Right;
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(6);
console.Lines[0].ShouldBe(" ┌────────┬────────┬───────┐");
console.Lines[1].ShouldBe(" │ Foo │ Bar │ Baz │");
console.Lines[2].ShouldBe(" ├────────┼────────┼───────┤");
console.Lines[3].ShouldBe(" │ Qux │ Corgi │ Waldo │");
console.Lines[4].ShouldBe(" │ Grault │ Garply │ Fred │");
console.Lines[5].ShouldBe(" └────────┴────────┴───────┘");
}
[Fact] [Fact]
public void Should_Render_Table_Nested_In_Panels_Correctly() public void Should_Render_Table_Nested_In_Panels_Correctly()
{ {
@@ -250,52 +349,6 @@ namespace Spectre.Console.Tests.Unit
console.Lines[5].ShouldBe("└───────────────────────────┴───────────────────────────┴──────────────────────┘"); console.Lines[5].ShouldBe("└───────────────────────────┴───────────────────────────┴──────────────────────┘");
} }
[Fact]
public void Should_Render_Table_With_Ascii_Border_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = TableBorder.Ascii };
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(6);
console.Lines[0].ShouldBe("+-------------------------+");
console.Lines[1].ShouldBe("| Foo | Bar | Baz |");
console.Lines[2].ShouldBe("|--------+--------+-------|");
console.Lines[3].ShouldBe("| Qux | Corgi | Waldo |");
console.Lines[4].ShouldBe("| Grault | Garply | Fred |");
console.Lines[5].ShouldBe("+-------------------------+");
}
[Fact]
public void Should_Render_Table_With_Rounded_Border_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = TableBorder.Rounded };
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(6);
console.Lines[0].ShouldBe("╭────────┬────────┬───────╮");
console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │");
console.Lines[2].ShouldBe("├────────┼────────┼───────┤");
console.Lines[3].ShouldBe("│ Qux │ Corgi │ Waldo │");
console.Lines[4].ShouldBe("│ Grault │ Garply │ Fred │");
console.Lines[5].ShouldBe("╰────────┴────────┴───────╯");
}
[Fact] [Fact]
public void Should_Render_Table_With_No_Border_Correctly() public void Should_Render_Table_With_No_Border_Correctly()
{ {
@@ -383,5 +436,165 @@ namespace Spectre.Console.Tests.Unit
console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │"); console.Lines[1].ShouldBe("│ Foo │ Bar │ Baz │");
console.Lines[2].ShouldBe("└─────┴─────┴────────┘"); console.Lines[2].ShouldBe("└─────┴─────┴────────┘");
} }
[Fact]
public void Should_Not_Draw_Tables_That_Are_Impossible_To_Draw()
{
// Given
var console = new PlainConsole(width: 25);
var first = new Table().Border(TableBorder.Rounded).BorderColor(Color.Red);
first.AddColumn(new TableColumn("[u]PS1[/]").Centered());
first.AddColumn(new TableColumn("[u]PS2[/]"));
first.AddColumn(new TableColumn("[u]PS3[/]"));
first.AddRow("Hello", "[red]World[/]", string.Empty);
first.AddRow("[blue]Bonjour[/]", "[white]le[/]", "[red]monde![/]");
first.AddRow("[blue]Hej[/]", "[yellow]Världen[/]", string.Empty);
var second = new Table().Border(TableBorder.Square).BorderColor(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[/]", string.Empty);
second.AddRow(first, new Text("Whaaat"), new Text("Lolz"));
second.AddRow("[blue]Hej[/]", "[yellow]Världen[/]", string.Empty);
var table = new Table().Border(TableBorder.Rounded);
table.AddColumn(new TableColumn(new Panel("[u]ABC[/]").BorderColor(Color.Red)));
table.AddColumn(new TableColumn(new Panel("[u]DEF[/]").BorderColor(Color.Green)));
table.AddColumn(new TableColumn(new Panel("[u]GHI[/]").BorderColor(Color.Blue)));
table.AddRow(new Text("Hello").Centered(), new Markup("[red]World[/]"), Text.Empty);
table.AddRow(second, new Text("Whaat"), new Text("Lol").RightAligned());
table.AddRow(new Markup("[blue]Hej[/]"), new Markup("[yellow]Världen[/]"), Text.Empty);
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(12);
console.Lines[00].ShouldBe("╭───────┬───────┬───────╮");
console.Lines[01].ShouldBe("│ ┌───┐ │ ┌───┐ │ ┌───┐ │");
console.Lines[02].ShouldBe("│ │ A │ │ │ D │ │ │ G │ │");
console.Lines[03].ShouldBe("│ │ B │ │ │ E │ │ │ H │ │");
console.Lines[04].ShouldBe("│ │ C │ │ │ F │ │ │ I │ │");
console.Lines[05].ShouldBe("│ └───┘ │ └───┘ │ └───┘ │");
console.Lines[06].ShouldBe("├───────┼───────┼───────┤");
console.Lines[07].ShouldBe("│ Hello │ World │ │");
console.Lines[08].ShouldBe("│ … │ Whaat │ Lol │");
console.Lines[09].ShouldBe("│ Hej │ Värld │ │");
console.Lines[10].ShouldBe("│ │ en │ │");
console.Lines[11].ShouldBe("╰───────┴───────┴───────╯");
}
[Fact]
public void Should_Render_Table_With_Title_And_Caption_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = TableBorder.Rounded };
table.Title = new TableTitle("Hello World");
table.Caption = new TableTitle("Goodbye World");
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe(" Hello World ");
console.Lines[1].ShouldBe("╭────────┬────────┬───────╮");
console.Lines[2].ShouldBe("│ Foo │ Bar │ Baz │");
console.Lines[3].ShouldBe("├────────┼────────┼───────┤");
console.Lines[4].ShouldBe("│ Qux │ Corgi │ Waldo │");
console.Lines[5].ShouldBe("│ Grault │ Garply │ Fred │");
console.Lines[6].ShouldBe("╰────────┴────────┴───────╯");
console.Lines[7].ShouldBe(" Goodbye World ");
}
[Fact]
public void Should_Left_Align_Table_With_Title_And_Caption_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = TableBorder.Rounded };
table.LeftAligned();
table.Title = new TableTitle("Hello World");
table.Caption = new TableTitle("Goodbye World");
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe(" Hello World ");
console.Lines[1].ShouldBe("╭────────┬────────┬───────╮");
console.Lines[2].ShouldBe("│ Foo │ Bar │ Baz │");
console.Lines[3].ShouldBe("├────────┼────────┼───────┤");
console.Lines[4].ShouldBe("│ Qux │ Corgi │ Waldo │");
console.Lines[5].ShouldBe("│ Grault │ Garply │ Fred │");
console.Lines[6].ShouldBe("╰────────┴────────┴───────╯");
console.Lines[7].ShouldBe(" Goodbye World ");
}
[Fact]
public void Should_Center_Table_With_Title_And_Caption_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = TableBorder.Rounded };
table.Centered();
table.Title = new TableTitle("Hello World");
table.Caption = new TableTitle("Goodbye World");
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe(" Hello World ");
console.Lines[1].ShouldBe(" ╭────────┬────────┬───────╮ ");
console.Lines[2].ShouldBe(" │ Foo │ Bar │ Baz │ ");
console.Lines[3].ShouldBe(" ├────────┼────────┼───────┤ ");
console.Lines[4].ShouldBe(" │ Qux │ Corgi │ Waldo │ ");
console.Lines[5].ShouldBe(" │ Grault │ Garply │ Fred │ ");
console.Lines[6].ShouldBe(" ╰────────┴────────┴───────╯ ");
console.Lines[7].ShouldBe(" Goodbye World ");
}
[Fact]
public void Should_Right_Align_Table_With_Title_And_Caption_Correctly()
{
// Given
var console = new PlainConsole(width: 80);
var table = new Table { Border = TableBorder.Rounded };
table.RightAligned();
table.Title = new TableTitle("Hello World");
table.Caption = new TableTitle("Goodbye World");
table.AddColumns("Foo", "Bar", "Baz");
table.AddRow("Qux", "Corgi", "Waldo");
table.AddRow("Grault", "Garply", "Fred");
// When
console.Render(table);
// Then
console.Lines.Count.ShouldBe(8);
console.Lines[0].ShouldBe(" Hello World ");
console.Lines[1].ShouldBe(" ╭────────┬────────┬───────╮");
console.Lines[2].ShouldBe(" │ Foo │ Bar │ Baz │");
console.Lines[3].ShouldBe(" ├────────┼────────┼───────┤");
console.Lines[4].ShouldBe(" │ Qux │ Corgi │ Waldo │");
console.Lines[5].ShouldBe(" │ Grault │ Garply │ Fred │");
console.Lines[6].ShouldBe(" ╰────────┴────────┴───────╯");
console.Lines[7].ShouldBe(" Goodbye World ");
}
} }
} }

View File

@@ -108,7 +108,7 @@ namespace Spectre.Console.Tests.Unit
// Given // Given
var console = new PlainConsole(14); var console = new PlainConsole(14);
var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux") var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux")
.SetOverflow(overflow); .Overflow(overflow);
// When // When
console.Render(text); console.Render(text);

View File

@@ -44,6 +44,12 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "GitHub", "GitHub", "{C3E2CB
..\.github\workflows\publish.yaml = ..\.github\workflows\publish.yaml ..\.github\workflows\publish.yaml = ..\.github\workflows\publish.yaml
EndProjectSection EndProjectSection
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Calendars", "..\examples\Calendars\Calendars.csproj", "{57691C7D-683D-46E6-AA4F-57A8C5F65D25}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Rules", "..\examples\Rules\Rules.csproj", "{8622A261-02C6-40CA-9797-E3F01ED87D6B}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Cursor", "..\examples\Cursor\Cursor.csproj", "{75C608C3-ABB4-4168-A229-7F8250B946D1}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -198,6 +204,42 @@ Global
{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|x64.Build.0 = Release|Any CPU {90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|x64.Build.0 = Release|Any CPU
{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|x86.ActiveCfg = Release|Any CPU {90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|x86.ActiveCfg = Release|Any CPU
{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|x86.Build.0 = Release|Any CPU {90C081A7-7C1D-4A4A-82B6-8FF473C3EA32}.Release|x86.Build.0 = Release|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Debug|Any CPU.Build.0 = Debug|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Debug|x64.ActiveCfg = Debug|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Debug|x64.Build.0 = Debug|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Debug|x86.ActiveCfg = Debug|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Debug|x86.Build.0 = Debug|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Release|Any CPU.ActiveCfg = Release|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Release|Any CPU.Build.0 = Release|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Release|x64.ActiveCfg = Release|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Release|x64.Build.0 = Release|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Release|x86.ActiveCfg = Release|Any CPU
{57691C7D-683D-46E6-AA4F-57A8C5F65D25}.Release|x86.Build.0 = Release|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Debug|x64.ActiveCfg = Debug|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Debug|x64.Build.0 = Debug|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Debug|x86.ActiveCfg = Debug|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Debug|x86.Build.0 = Debug|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Release|Any CPU.Build.0 = Release|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Release|x64.ActiveCfg = Release|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Release|x64.Build.0 = Release|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Release|x86.ActiveCfg = Release|Any CPU
{8622A261-02C6-40CA-9797-E3F01ED87D6B}.Release|x86.Build.0 = Release|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Debug|x64.ActiveCfg = Debug|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Debug|x64.Build.0 = Debug|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Debug|x86.ActiveCfg = Debug|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Debug|x86.Build.0 = Debug|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Release|Any CPU.Build.0 = Release|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Release|x64.ActiveCfg = Release|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Release|x64.Build.0 = Release|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Release|x86.ActiveCfg = Release|Any CPU
{75C608C3-ABB4-4168-A229-7F8250B946D1}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -214,6 +256,9 @@ Global
{1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2} = {F0575243-121F-4DEE-9F6B-246E26DC0844} {1EABB956-957F-4C1A-8AC0-FD19C8F3C2F2} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
{90C081A7-7C1D-4A4A-82B6-8FF473C3EA32} = {F0575243-121F-4DEE-9F6B-246E26DC0844} {90C081A7-7C1D-4A4A-82B6-8FF473C3EA32} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
{C3E2CB5C-1517-4C75-B59A-93D4E22BEC8D} = {20595AD4-8D75-4AF8-B6BC-9C38C160423F} {C3E2CB5C-1517-4C75-B59A-93D4E22BEC8D} = {20595AD4-8D75-4AF8-B6BC-9C38C160423F}
{57691C7D-683D-46E6-AA4F-57A8C5F65D25} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
{8622A261-02C6-40CA-9797-E3F01ED87D6B} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
{75C608C3-ABB4-4168-A229-7F8250B946D1} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C} SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C}

View File

@@ -14,7 +14,7 @@ namespace Spectre.Console
public static Color Foreground public static Color Foreground
{ {
get => CurrentStyle.Foreground; get => CurrentStyle.Foreground;
set => CurrentStyle = CurrentStyle.WithForeground(value); set => CurrentStyle = CurrentStyle.Foreground(value);
} }
/// <summary> /// <summary>
@@ -23,7 +23,7 @@ namespace Spectre.Console
public static Color Background public static Color Background
{ {
get => CurrentStyle.Background; get => CurrentStyle.Background;
set => CurrentStyle = CurrentStyle.WithBackground(value); set => CurrentStyle = CurrentStyle.Background(value);
} }
/// <summary> /// <summary>
@@ -32,7 +32,7 @@ namespace Spectre.Console
public static Decoration Decoration public static Decoration Decoration
{ {
get => CurrentStyle.Decoration; get => CurrentStyle.Decoration;
set => CurrentStyle = CurrentStyle.WithDecoration(value); set => CurrentStyle = CurrentStyle.Decoration(value);
} }
/// <summary> /// <summary>

View File

@@ -27,6 +27,11 @@ namespace Spectre.Console
/// </summary> /// </summary>
public static IAnsiConsole Console => _recorder ?? _console.Value; public static IAnsiConsole Console => _recorder ?? _console.Value;
/// <summary>
/// Gets the <see cref="IAnsiConsoleCursor"/>.
/// </summary>
public static IAnsiConsoleCursor Cursor => _recorder?.Cursor ?? _console.Value.Cursor;
/// <summary> /// <summary>
/// Gets the console's capabilities. /// Gets the console's capabilities.
/// </summary> /// </summary>
@@ -56,7 +61,7 @@ namespace Spectre.Console
/// <returns>An <see cref="IAnsiConsole"/> instance.</returns> /// <returns>An <see cref="IAnsiConsole"/> instance.</returns>
public static IAnsiConsole Create(AnsiConsoleSettings settings) public static IAnsiConsole Create(AnsiConsoleSettings settings)
{ {
return AnsiConsoleBuilder.Build(settings); return BackendBuilder.Build(settings);
} }
} }
} }

View File

@@ -0,0 +1,28 @@
namespace Spectre.Console
{
/// <summary>
/// Represents cursor direction.
/// </summary>
public enum CursorDirection
{
/// <summary>
/// Up
/// </summary>
Up,
/// <summary>
/// Down
/// </summary>
Down,
/// <summary>
/// Left
/// </summary>
Left,
/// <summary>
/// Right
/// </summary>
Right,
}
}

View File

@@ -12,7 +12,7 @@ namespace Spectre.Console
/// <param name="obj">The alignable object.</param> /// <param name="obj">The alignable object.</param>
/// <param name="alignment">The alignment.</param> /// <param name="alignment">The alignment.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetAlignment<T>(this T obj, Justify alignment) public static T Alignment<T>(this T obj, Justify? alignment)
where T : class, IAlignable where T : class, IAlignable
{ {
if (obj is null) if (obj is null)

View File

@@ -0,0 +1,132 @@
using System;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="Calendar"/>.
/// </summary>
public static class CalendarExtensions
{
/// <summary>
/// Adds a calendar event.
/// </summary>
/// <param name="calendar">The calendar to add the calendar event to.</param>
/// <param name="date">The calendar event date.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Calendar AddCalendarEvent(this Calendar calendar, DateTime date)
{
return AddCalendarEvent(calendar, string.Empty, date.Year, date.Month, date.Day);
}
/// <summary>
/// Adds a calendar event.
/// </summary>
/// <param name="calendar">The calendar to add the calendar event to.</param>
/// <param name="description">The calendar event description.</param>
/// <param name="date">The calendar event date.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Calendar AddCalendarEvent(this Calendar calendar, string description, DateTime date)
{
return AddCalendarEvent(calendar, description, date.Year, date.Month, date.Day);
}
/// <summary>
/// Adds a calendar event.
/// </summary>
/// <param name="calendar">The calendar to add the calendar event to.</param>
/// <param name="year">The year of the calendar event.</param>
/// <param name="month">The month of the calendar event.</param>
/// <param name="day">The day of the calendar event.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Calendar AddCalendarEvent(this Calendar calendar, int year, int month, int day)
{
return AddCalendarEvent(calendar, string.Empty, year, month, day);
}
/// <summary>
/// Adds a calendar event.
/// </summary>
/// <param name="calendar">The calendar.</param>
/// <param name="description">The calendar event description.</param>
/// <param name="year">The year of the calendar event.</param>
/// <param name="month">The month of the calendar event.</param>
/// <param name="day">The day of the calendar event.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Calendar AddCalendarEvent(this Calendar calendar, string description, int year, int month, int day)
{
if (calendar is null)
{
throw new ArgumentNullException(nameof(calendar));
}
calendar.CalendarEvents.Add(new CalendarEvent(description, year, month, day));
return calendar;
}
/// <summary>
/// Sets the calendar's highlight <see cref="Style"/>.
/// </summary>
/// <param name="calendar">The calendar.</param>
/// <param name="style">The highlight style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Calendar HighlightStyle(this Calendar calendar, Style? style)
{
if (calendar is null)
{
throw new ArgumentNullException(nameof(calendar));
}
calendar.HightlightStyle = style ?? Style.Plain;
return calendar;
}
/// <summary>
/// Sets the calendar's header <see cref="Style"/>.
/// </summary>
/// <param name="calendar">The calendar.</param>
/// <param name="style">The header style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Calendar HeaderStyle(this Calendar calendar, Style? style)
{
if (calendar is null)
{
throw new ArgumentNullException(nameof(calendar));
}
calendar.HeaderStyle = style ?? Style.Plain;
return calendar;
}
/// <summary>
/// Shows the calendar header.
/// </summary>
/// <param name="calendar">The calendar.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Calendar ShowHeader(this Calendar calendar)
{
if (calendar is null)
{
throw new ArgumentNullException(nameof(calendar));
}
calendar.ShowHeader = true;
return calendar;
}
/// <summary>
/// Hides the calendar header.
/// </summary>
/// <param name="calendar">The calendar.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Calendar HideHeader(this Calendar calendar)
{
if (calendar is null)
{
throw new ArgumentNullException(nameof(calendar));
}
calendar.ShowHeader = false;
return calendar;
}
}
}

View File

@@ -24,5 +24,24 @@ namespace Spectre.Console
obj.NoWrap = true; obj.NoWrap = true;
return obj; return obj;
} }
/// <summary>
/// Sets the width of the column.
/// </summary>
/// <typeparam name="T">An object implementing <see cref="IColumn"/>.</typeparam>
/// <param name="obj">The column.</param>
/// <param name="width">The column width.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T Width<T>(this T obj, int? width)
where T : class, IColumn
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Width = width;
return obj;
}
} }
} }

View File

@@ -0,0 +1,152 @@
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IAnsiConsoleCursor"/>.
/// </summary>
public static class CursorExtensions
{
/// <summary>
/// Shows the cursor.
/// </summary>
/// <param name="cursor">The cursor.</param>
public static void Show(this IAnsiConsoleCursor cursor)
{
if (cursor is null)
{
throw new System.ArgumentNullException(nameof(cursor));
}
cursor.Show(true);
}
/// <summary>
/// Hides the cursor.
/// </summary>
/// <param name="cursor">The cursor.</param>
public static void Hide(this IAnsiConsoleCursor cursor)
{
if (cursor is null)
{
throw new System.ArgumentNullException(nameof(cursor));
}
cursor.Show(false);
}
/// <summary>
/// Moves the cursor up.
/// </summary>
/// <param name="cursor">The cursor.</param>
public static void MoveUp(this IAnsiConsoleCursor cursor)
{
if (cursor is null)
{
throw new System.ArgumentNullException(nameof(cursor));
}
cursor.Move(CursorDirection.Up, 1);
}
/// <summary>
/// Moves the cursor up.
/// </summary>
/// <param name="cursor">The cursor.</param>
/// <param name="steps">The number of steps to move the cursor.</param>
public static void MoveUp(this IAnsiConsoleCursor cursor, int steps)
{
if (cursor is null)
{
throw new System.ArgumentNullException(nameof(cursor));
}
cursor.Move(CursorDirection.Up, steps);
}
/// <summary>
/// Moves the cursor down.
/// </summary>
/// <param name="cursor">The cursor.</param>
public static void MoveDown(this IAnsiConsoleCursor cursor)
{
if (cursor is null)
{
throw new System.ArgumentNullException(nameof(cursor));
}
cursor.Move(CursorDirection.Down, 1);
}
/// <summary>
/// Moves the cursor down.
/// </summary>
/// <param name="cursor">The cursor.</param>
/// <param name="steps">The number of steps to move the cursor.</param>
public static void MoveDown(this IAnsiConsoleCursor cursor, int steps)
{
if (cursor is null)
{
throw new System.ArgumentNullException(nameof(cursor));
}
cursor.Move(CursorDirection.Down, steps);
}
/// <summary>
/// Moves the cursor to the left.
/// </summary>
/// <param name="cursor">The cursor.</param>
public static void MoveLeft(this IAnsiConsoleCursor cursor)
{
if (cursor is null)
{
throw new System.ArgumentNullException(nameof(cursor));
}
cursor.Move(CursorDirection.Left, 1);
}
/// <summary>
/// Moves the cursor to the left.
/// </summary>
/// <param name="cursor">The cursor.</param>
/// <param name="steps">The number of steps to move the cursor.</param>
public static void MoveLeft(this IAnsiConsoleCursor cursor, int steps)
{
if (cursor is null)
{
throw new System.ArgumentNullException(nameof(cursor));
}
cursor.Move(CursorDirection.Left, steps);
}
/// <summary>
/// Moves the cursor to the right.
/// </summary>
/// <param name="cursor">The cursor.</param>
public static void MoveRight(this IAnsiConsoleCursor cursor)
{
if (cursor is null)
{
throw new System.ArgumentNullException(nameof(cursor));
}
cursor.Move(CursorDirection.Right, 1);
}
/// <summary>
/// Moves the cursor to the right.
/// </summary>
/// <param name="cursor">The cursor.</param>
/// <param name="steps">The number of steps to move the cursor.</param>
public static void MoveRight(this IAnsiConsoleCursor cursor, int steps)
{
if (cursor is null)
{
throw new System.ArgumentNullException(nameof(cursor));
}
cursor.Move(CursorDirection.Right, steps);
}
}
}

View File

@@ -0,0 +1,27 @@
using System;
using System.Globalization;
namespace Spectre.Console.Internal
{
internal static class DayOfWeekExtensions
{
public static string GetAbbreviatedDayName(this DayOfWeek day, CultureInfo culture)
{
culture ??= CultureInfo.InvariantCulture;
return culture.DateTimeFormat
.GetAbbreviatedDayName(day)
.Capitalize(culture);
}
public static DayOfWeek GetNextWeekDay(this DayOfWeek day)
{
var next = (int)day + 1;
if (next > (int)DayOfWeek.Saturday)
{
return DayOfWeek.Sunday;
}
return (DayOfWeek)next;
}
}
}

View File

@@ -6,6 +6,21 @@ namespace Spectre.Console.Internal
{ {
internal static class EnumerableExtensions internal static class EnumerableExtensions
{ {
public static int GetCount<T>(this IEnumerable<T> source)
{
if (source is IList<T> list)
{
return list.Count;
}
if (source is T[] array)
{
return array.Length;
}
return source.Count();
}
public static void ForEach<T>(this IEnumerable<T> source, Action<T> action) public static void ForEach<T>(this IEnumerable<T> source, Action<T> action)
{ {
foreach (var item in source) foreach (var item in source)
@@ -54,11 +69,13 @@ namespace Spectre.Console.Internal
return source.Select((value, index) => func(value, index)); return source.Select((value, index) => func(value, index));
} }
#if !NET5_0
public static IEnumerable<(TFirst First, TSecond Second)> Zip<TFirst, TSecond>( public static IEnumerable<(TFirst First, TSecond Second)> Zip<TFirst, TSecond>(
this IEnumerable<TFirst> source, IEnumerable<TSecond> first) this IEnumerable<TFirst> source, IEnumerable<TSecond> first)
{ {
return source.Zip(first, (first, second) => (first, second)); return source.Zip(first, (first, second) => (first, second));
} }
#endif
public static IEnumerable<(TFirst First, TSecond Second, TThird Third)> Zip<TFirst, TSecond, TThird>( public static IEnumerable<(TFirst First, TSecond Second, TThird Third)> Zip<TFirst, TSecond, TThird>(
this IEnumerable<TFirst> first, IEnumerable<TSecond> second, IEnumerable<TThird> third) this IEnumerable<TFirst> first, IEnumerable<TSecond> second, IEnumerable<TThird> third)

View File

@@ -1,4 +1,5 @@
using System; using System;
using Spectre.Console.Internal;
using Spectre.Console.Rendering; using Spectre.Console.Rendering;
namespace Spectre.Console namespace Spectre.Console

View File

@@ -17,7 +17,12 @@ namespace Spectre.Console
public static T Collapse<T>(this T obj) public static T Collapse<T>(this T obj)
where T : class, IExpandable where T : class, IExpandable
{ {
SetExpand<T>(obj, false); if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Expand = false;
return obj; return obj;
} }
@@ -29,20 +34,14 @@ namespace Spectre.Console
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static T Expand<T>(this T obj) public static T Expand<T>(this T obj)
where T : class, IExpandable where T : class, IExpandable
{
SetExpand<T>(obj, true);
return obj;
}
private static void SetExpand<T>(T obj, bool value)
where T : class, IExpandable
{ {
if (obj is null) if (obj is null)
{ {
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
} }
obj.Expand = value; obj.Expand = true;
return obj;
} }
} }
} }

View File

@@ -69,8 +69,8 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(grid)); throw new ArgumentNullException(nameof(grid));
} }
var columns = new IRenderable[grid.ColumnCount]; var columns = new IRenderable[grid.Columns.Count];
Enumerable.Range(0, grid.ColumnCount).ForEach(index => columns[index] = Text.Empty); Enumerable.Range(0, grid.Columns.Count).ForEach(index => columns[index] = Text.Empty);
grid.AddRow(columns); grid.AddRow(columns);
return grid; return grid;

View File

@@ -7,11 +7,29 @@ namespace Spectre.Console
/// </summary> /// </summary>
public static class HasBorderExtensions public static class HasBorderExtensions
{ {
/// <summary>
/// Enables the safe border.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to enable the safe border for.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SafeBorder<T>(this T obj)
where T : class, IHasBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.UseSafeBorder = true;
return obj;
}
/// <summary> /// <summary>
/// Disables the safe border. /// Disables the safe border.
/// </summary> /// </summary>
/// <typeparam name="T">An object type with a border.</typeparam> /// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param> /// <param name="obj">The object to disable the safe border for.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static T NoSafeBorder<T>(this T obj) public static T NoSafeBorder<T>(this T obj)
where T : class, IHasBorder where T : class, IHasBorder
@@ -29,10 +47,10 @@ namespace Spectre.Console
/// Sets the border style. /// Sets the border style.
/// </summary> /// </summary>
/// <typeparam name="T">An object type with a border.</typeparam> /// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border color for.</param> /// <param name="obj">The object to set the border style for.</param>
/// <param name="style">The border style to set.</param> /// <param name="style">The border style to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorderStyle<T>(this T obj, Style style) public static T BorderStyle<T>(this T obj, Style style)
where T : class, IHasBorder where T : class, IHasBorder
{ {
if (obj is null) if (obj is null)
@@ -51,7 +69,7 @@ namespace Spectre.Console
/// <param name="obj">The object to set the border color for.</param> /// <param name="obj">The object to set the border color for.</param>
/// <param name="color">The border color to set.</param> /// <param name="color">The border color to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorderColor<T>(this T obj, Color color) public static T BorderColor<T>(this T obj, Color color)
where T : class, IHasBorder where T : class, IHasBorder
{ {
if (obj is null) if (obj is null)
@@ -59,7 +77,7 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
} }
obj.BorderStyle = (obj.BorderStyle ?? Style.Plain).WithForeground(color); obj.BorderStyle = (obj.BorderStyle ?? Style.Plain).Foreground(color);
return obj; return obj;
} }
} }

View File

@@ -7,6 +7,25 @@ namespace Spectre.Console
/// </summary> /// </summary>
public static class HasBoxBorderExtensions public static class HasBoxBorderExtensions
{ {
/// <summary>
/// Sets the border.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param>
/// <param name="border">The border to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T Border<T>(this T obj, BoxBorder border)
where T : class, IHasBoxBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Border = border;
return obj;
}
/// <summary> /// <summary>
/// Do not display a border. /// Do not display a border.
/// </summary> /// </summary>
@@ -16,7 +35,7 @@ namespace Spectre.Console
public static T NoBorder<T>(this T obj) public static T NoBorder<T>(this T obj)
where T : class, IHasBoxBorder where T : class, IHasBoxBorder
{ {
return SetBorder(obj, BoxBorder.None); return Border(obj, BoxBorder.None);
} }
/// <summary> /// <summary>
@@ -28,7 +47,7 @@ namespace Spectre.Console
public static T SquareBorder<T>(this T obj) public static T SquareBorder<T>(this T obj)
where T : class, IHasBoxBorder where T : class, IHasBoxBorder
{ {
return SetBorder(obj, BoxBorder.Square); return Border(obj, BoxBorder.Square);
} }
/// <summary> /// <summary>
@@ -40,7 +59,7 @@ namespace Spectre.Console
public static T AsciiBorder<T>(this T obj) public static T AsciiBorder<T>(this T obj)
where T : class, IHasBoxBorder where T : class, IHasBoxBorder
{ {
return SetBorder(obj, BoxBorder.Ascii); return Border(obj, BoxBorder.Ascii);
} }
/// <summary> /// <summary>
@@ -52,7 +71,7 @@ namespace Spectre.Console
public static T RoundedBorder<T>(this T obj) public static T RoundedBorder<T>(this T obj)
where T : class, IHasBoxBorder where T : class, IHasBoxBorder
{ {
return SetBorder(obj, BoxBorder.Rounded); return Border(obj, BoxBorder.Rounded);
} }
/// <summary> /// <summary>
@@ -64,7 +83,7 @@ namespace Spectre.Console
public static T HeavyBorder<T>(this T obj) public static T HeavyBorder<T>(this T obj)
where T : class, IHasBoxBorder where T : class, IHasBoxBorder
{ {
return SetBorder(obj, BoxBorder.Heavy); return Border(obj, BoxBorder.Heavy);
} }
/// <summary> /// <summary>
@@ -76,26 +95,7 @@ namespace Spectre.Console
public static T DoubleBorder<T>(this T obj) public static T DoubleBorder<T>(this T obj)
where T : class, IHasBoxBorder where T : class, IHasBoxBorder
{ {
return SetBorder(obj, BoxBorder.Double); return Border(obj, BoxBorder.Double);
}
/// <summary>
/// Sets the border.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param>
/// <param name="border">The border to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorder<T>(this T obj, BoxBorder border)
where T : class, IHasBoxBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Border = border;
return obj;
} }
} }
} }

View File

@@ -0,0 +1,66 @@
using System;
using System.Globalization;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IHasCulture"/>.
/// </summary>
public static class HasCultureExtensions
{
/// <summary>
/// Sets the culture.
/// </summary>
/// <typeparam name="T">An object type with a culture.</typeparam>
/// <param name="obj">The object to set the culture for.</param>
/// <param name="culture">The culture to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T Culture<T>(this T obj, CultureInfo culture)
where T : class, IHasCulture
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
if (culture is null)
{
throw new ArgumentNullException(nameof(culture));
}
obj.Culture = culture;
return obj;
}
/// <summary>
/// Sets the culture.
/// </summary>
/// <typeparam name="T">An object type with a culture.</typeparam>
/// <param name="obj">The object to set the culture for.</param>
/// <param name="name">The culture to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T Culture<T>(this T obj, string name)
where T : class, IHasCulture
{
if (name is null)
{
throw new ArgumentNullException(nameof(name));
}
return Culture(obj, CultureInfo.GetCultureInfo(name));
}
/// <summary>
/// Sets the culture.
/// </summary>
/// <typeparam name="T">An object type with a culture.</typeparam>
/// <param name="obj">The object to set the culture for.</param>
/// <param name="culture">The culture to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T Culture<T>(this T obj, int culture)
where T : class, IHasCulture
{
return Culture(obj, CultureInfo.GetCultureInfo(culture));
}
}
}

View File

@@ -16,7 +16,7 @@ namespace Spectre.Console
public static T NoBorder<T>(this T obj) public static T NoBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.None); return Border(obj, TableBorder.None);
} }
/// <summary> /// <summary>
@@ -28,7 +28,7 @@ namespace Spectre.Console
public static T SquareBorder<T>(this T obj) public static T SquareBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.Square); return Border(obj, TableBorder.Square);
} }
/// <summary> /// <summary>
@@ -40,7 +40,7 @@ namespace Spectre.Console
public static T AsciiBorder<T>(this T obj) public static T AsciiBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.Ascii); return Border(obj, TableBorder.Ascii);
} }
/// <summary> /// <summary>
@@ -52,7 +52,7 @@ namespace Spectre.Console
public static T Ascii2Border<T>(this T obj) public static T Ascii2Border<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.Ascii2); return Border(obj, TableBorder.Ascii2);
} }
/// <summary> /// <summary>
@@ -64,7 +64,7 @@ namespace Spectre.Console
public static T AsciiDoubleHeadBorder<T>(this T obj) public static T AsciiDoubleHeadBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.AsciiDoubleHead); return Border(obj, TableBorder.AsciiDoubleHead);
} }
/// <summary> /// <summary>
@@ -76,7 +76,7 @@ namespace Spectre.Console
public static T RoundedBorder<T>(this T obj) public static T RoundedBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.Rounded); return Border(obj, TableBorder.Rounded);
} }
/// <summary> /// <summary>
@@ -88,7 +88,7 @@ namespace Spectre.Console
public static T MinimalBorder<T>(this T obj) public static T MinimalBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.Minimal); return Border(obj, TableBorder.Minimal);
} }
/// <summary> /// <summary>
@@ -100,7 +100,7 @@ namespace Spectre.Console
public static T MinimalHeavyHeadBorder<T>(this T obj) public static T MinimalHeavyHeadBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.MinimalHeavyHead); return Border(obj, TableBorder.MinimalHeavyHead);
} }
/// <summary> /// <summary>
@@ -112,7 +112,7 @@ namespace Spectre.Console
public static T MinimalDoubleHeadBorder<T>(this T obj) public static T MinimalDoubleHeadBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.MinimalDoubleHead); return Border(obj, TableBorder.MinimalDoubleHead);
} }
/// <summary> /// <summary>
@@ -124,7 +124,7 @@ namespace Spectre.Console
public static T SimpleBorder<T>(this T obj) public static T SimpleBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.Simple); return Border(obj, TableBorder.Simple);
} }
/// <summary> /// <summary>
@@ -136,7 +136,7 @@ namespace Spectre.Console
public static T SimpleHeavyBorder<T>(this T obj) public static T SimpleHeavyBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.SimpleHeavy); return Border(obj, TableBorder.SimpleHeavy);
} }
/// <summary> /// <summary>
@@ -148,7 +148,7 @@ namespace Spectre.Console
public static T HorizontalBorder<T>(this T obj) public static T HorizontalBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.Horizontal); return Border(obj, TableBorder.Horizontal);
} }
/// <summary> /// <summary>
@@ -160,7 +160,7 @@ namespace Spectre.Console
public static T HeavyBorder<T>(this T obj) public static T HeavyBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.Heavy); return Border(obj, TableBorder.Heavy);
} }
/// <summary> /// <summary>
@@ -172,7 +172,7 @@ namespace Spectre.Console
public static T HeavyEdgeBorder<T>(this T obj) public static T HeavyEdgeBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.HeavyEdge); return Border(obj, TableBorder.HeavyEdge);
} }
/// <summary> /// <summary>
@@ -184,7 +184,7 @@ namespace Spectre.Console
public static T HeavyHeadBorder<T>(this T obj) public static T HeavyHeadBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.HeavyHead); return Border(obj, TableBorder.HeavyHead);
} }
/// <summary> /// <summary>
@@ -196,7 +196,7 @@ namespace Spectre.Console
public static T DoubleBorder<T>(this T obj) public static T DoubleBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.Double); return Border(obj, TableBorder.Double);
} }
/// <summary> /// <summary>
@@ -208,7 +208,7 @@ namespace Spectre.Console
public static T DoubleEdgeBorder<T>(this T obj) public static T DoubleEdgeBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.DoubleEdge); return Border(obj, TableBorder.DoubleEdge);
} }
/// <summary> /// <summary>
@@ -220,7 +220,7 @@ namespace Spectre.Console
public static T MarkdownBorder<T>(this T obj) public static T MarkdownBorder<T>(this T obj)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
return SetBorder(obj, TableBorder.Markdown); return Border(obj, TableBorder.Markdown);
} }
/// <summary> /// <summary>
@@ -230,7 +230,7 @@ namespace Spectre.Console
/// <param name="obj">The object to set the border for.</param> /// <param name="obj">The object to set the border for.</param>
/// <param name="border">The border to use.</param> /// <param name="border">The border to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetBorder<T>(this T obj, TableBorder border) public static T Border<T>(this T obj, TableBorder border)
where T : class, IHasTableBorder where T : class, IHasTableBorder
{ {
if (obj is null) if (obj is null)

View File

@@ -0,0 +1,32 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IAlignable"/>.
/// </summary>
public static class ObsoleteAlignableExtensions
{
/// <summary>
/// Sets the alignment for an <see cref="IAlignable"/> object.
/// </summary>
/// <typeparam name="T">The alignable object type.</typeparam>
/// <param name="obj">The alignable object.</param>
/// <param name="alignment">The alignment.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Alignment(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetAlignment<T>(this T obj, Justify alignment)
where T : class, IAlignable
{
if (obj is null)
{
throw new System.ArgumentNullException(nameof(obj));
}
obj.Alignment = alignment;
return obj;
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="Calendar"/>.
/// </summary>
public static class ObsoleteCalendarExtensions
{
/// <summary>
/// Sets the calendar's highlight <see cref="Style"/>.
/// </summary>
/// <param name="calendar">The calendar.</param>
/// <param name="style">The highlight style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use HighlightStyle(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Calendar SetHighlightStyle(this Calendar calendar, Style? style)
{
if (calendar is null)
{
throw new ArgumentNullException(nameof(calendar));
}
calendar.HightlightStyle = style ?? Style.Plain;
return calendar;
}
/// <summary>
/// Sets the calendar's header <see cref="Style"/>.
/// </summary>
/// <param name="calendar">The calendar.</param>
/// <param name="style">The header style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use HeaderStyle(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Calendar SetHeaderStyle(this Calendar calendar, Style? style)
{
if (calendar is null)
{
throw new ArgumentNullException(nameof(calendar));
}
calendar.HeaderStyle = style ?? Style.Plain;
return calendar;
}
}
}

View File

@@ -0,0 +1,53 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IHasBorder"/>.
/// </summary>
public static class ObsoleteHasBorderExtensions
{
/// <summary>
/// Sets the border style.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border color for.</param>
/// <param name="style">The border style to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use BorderStyle(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetBorderStyle<T>(this T obj, Style style)
where T : class, IHasBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.BorderStyle = style;
return obj;
}
/// <summary>
/// Sets the border color.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border color for.</param>
/// <param name="color">The border color to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use BorderColor(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetBorderColor<T>(this T obj, Color color)
where T : class, IHasBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.BorderStyle = (obj.BorderStyle ?? Style.Plain).Foreground(color);
return obj;
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IHasBoxBorder"/>.
/// </summary>
public static class ObsoleteHasBoxBorderExtensions
{
/// <summary>
/// Sets the border.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param>
/// <param name="border">The border to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Border(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetBorder<T>(this T obj, BoxBorder border)
where T : class, IHasBoxBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Border = border;
return obj;
}
}
}

View File

@@ -0,0 +1,80 @@
using System;
using System.ComponentModel;
using System.Globalization;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IHasCulture"/>.
/// </summary>
public static class ObsoleteHasCultureExtensions
{
/// <summary>
/// Sets the culture.
/// </summary>
/// <typeparam name="T">An object type with a culture.</typeparam>
/// <param name="obj">The object to set the culture for.</param>
/// <param name="culture">The culture to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Culture(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetCulture<T>(this T obj, CultureInfo culture)
where T : class, IHasCulture
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
if (culture is null)
{
throw new ArgumentNullException(nameof(culture));
}
obj.Culture = culture;
return obj;
}
/// <summary>
/// Sets the culture.
/// </summary>
/// <typeparam name="T">An object type with a culture.</typeparam>
/// <param name="obj">The object to set the culture for.</param>
/// <param name="name">The culture to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Culture(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetCulture<T>(this T obj, string name)
where T : class, IHasCulture
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Culture = CultureInfo.GetCultureInfo(name);
return obj;
}
/// <summary>
/// Sets the culture.
/// </summary>
/// <typeparam name="T">An object type with a culture.</typeparam>
/// <param name="obj">The object to set the culture for.</param>
/// <param name="name">The culture to set.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Culture(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetCulture<T>(this T obj, int name)
where T : class, IHasCulture
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Culture = CultureInfo.GetCultureInfo(name);
return obj;
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IHasTableBorder"/>.
/// </summary>
public static class ObsoleteHasTableBorderExtensions
{
/// <summary>
/// Sets the border.
/// </summary>
/// <typeparam name="T">An object type with a border.</typeparam>
/// <param name="obj">The object to set the border for.</param>
/// <param name="border">The border to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Border(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetBorder<T>(this T obj, TableBorder border)
where T : class, IHasTableBorder
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Border = border;
return obj;
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IOverflowable"/>.
/// </summary>
public static class ObsoleteOverflowableExtensions
{
/// <summary>
/// Sets the overflow strategy.
/// </summary>
/// <typeparam name="T">An object implementing <see cref="IOverflowable"/>.</typeparam>
/// <param name="obj">The overflowable object instance.</param>
/// <param name="overflow">The overflow strategy to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Overflow(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetOverflow<T>(this T obj, Overflow overflow)
where T : class, IOverflowable
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Overflow = overflow;
return obj;
}
}
}

View File

@@ -0,0 +1,50 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="IPaddable"/>.
/// </summary>
public static class ObsoletePaddableExtensions
{
/// <summary>
/// Sets the left and right padding.
/// </summary>
/// <typeparam name="T">An object implementing <see cref="IPaddable"/>.</typeparam>
/// <param name="obj">The paddable object instance.</param>
/// <param name="left">The left padding to apply.</param>
/// <param name="top">The top padding to apply.</param>
/// <param name="right">The right padding to apply.</param>
/// <param name="bottom">The bottom padding to apply.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Padding(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetPadding<T>(this T obj, int left, int top, int right, int bottom)
where T : class, IPaddable
{
return SetPadding(obj, new Padding(left, top, right, bottom));
}
/// <summary>
/// Sets the padding.
/// </summary>
/// <typeparam name="T">An object implementing <see cref="IPaddable"/>.</typeparam>
/// <param name="obj">The paddable object instance.</param>
/// <param name="padding">The padding to apply.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Padding(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static T SetPadding<T>(this T obj, Padding padding)
where T : class, IPaddable
{
if (obj is null)
{
throw new ArgumentNullException(nameof(obj));
}
obj.Padding = padding;
return obj;
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="Panel"/>.
/// </summary>
public static class ObsoletePanelExtensions
{
/// <summary>
/// Sets the panel header.
/// </summary>
/// <param name="panel">The panel.</param>
/// <param name="text">The header text.</param>
/// <param name="style">The header style.</param>
/// <param name="alignment">The header alignment.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Header(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Panel SetHeader(this Panel panel, string text, Style? style = null, Justify? alignment = null)
{
if (panel is null)
{
throw new ArgumentNullException(nameof(panel));
}
if (text is null)
{
throw new ArgumentNullException(nameof(text));
}
alignment ??= panel.Header?.Alignment;
return SetHeader(panel, new PanelHeader(text, alignment));
}
/// <summary>
/// Sets the panel header.
/// </summary>
/// <param name="panel">The panel.</param>
/// <param name="header">The header to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Header(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Panel SetHeader(this Panel panel, PanelHeader header)
{
if (panel is null)
{
throw new ArgumentNullException(nameof(panel));
}
panel.Header = header;
return panel;
}
/// <summary>
/// Sets the panel header style.
/// </summary>
/// <param name="panel">The panel.</param>
/// <param name="style">The header style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use markup in header instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Panel HeaderStyle(this Panel panel, Style style)
{
return panel;
}
}
}

View File

@@ -0,0 +1,59 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="RuleExtensions"/>.
/// </summary>
public static class ObsoleteRuleExtensions
{
/// <summary>
/// Sets the rule title.
/// </summary>
/// <param name="rule">The rule.</param>
/// <param name="title">The title.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Title(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Rule SetTitle(this Rule rule, string title)
{
if (rule is null)
{
throw new ArgumentNullException(nameof(rule));
}
if (title is null)
{
throw new ArgumentNullException(nameof(title));
}
rule.Title = title;
return rule;
}
/// <summary>
/// Sets the rule style.
/// </summary>
/// <param name="rule">The rule.</param>
/// <param name="style">The rule style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Style(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Rule SetStyle(this Rule rule, Style style)
{
if (rule is null)
{
throw new ArgumentNullException(nameof(rule));
}
if (style is null)
{
throw new ArgumentNullException(nameof(style));
}
rule.Style = style;
return rule;
}
}
}

View File

@@ -0,0 +1,23 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="string"/>.
/// </summary>
public static class ObsoleteStringExtensions
{
/// <summary>
/// Escapes text so that it wont be interpreted as markup.
/// </summary>
/// <param name="text">The text to escape.</param>
/// <returns>A string that is safe to use in markup.</returns>
[Obsolete("Use EscapeMarkup(..) instead.", false)]
[EditorBrowsable(EditorBrowsableState.Never)]
public static string SafeMarkup(this string text)
{
return text.EscapeMarkup();
}
}
}

View File

@@ -0,0 +1,100 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="Style"/>.
/// </summary>
public static class ObsoleteStyleExtensions
{
/// <summary>
/// Creates a new style from the specified one with
/// the specified foreground color.
/// </summary>
/// <param name="style">The style.</param>
/// <param name="color">The foreground color.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Foreground(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Style WithForeground(this Style style, Color color)
{
if (style is null)
{
throw new ArgumentNullException(nameof(style));
}
return new Style(
foreground: color,
background: style.Background,
decoration: style.Decoration);
}
/// <summary>
/// Creates a new style from the specified one with
/// the specified background color.
/// </summary>
/// <param name="style">The style.</param>
/// <param name="color">The background color.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Background(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Style WithBackground(this Style style, Color color)
{
if (style is null)
{
throw new ArgumentNullException(nameof(style));
}
return new Style(
foreground: style.Foreground,
background: color,
decoration: style.Decoration);
}
/// <summary>
/// Creates a new style from the specified one with
/// the specified text decoration.
/// </summary>
/// <param name="style">The style.</param>
/// <param name="decoration">The text decoration.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Decoration(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Style WithDecoration(this Style style, Decoration decoration)
{
if (style is null)
{
throw new ArgumentNullException(nameof(style));
}
return new Style(
foreground: style.Foreground,
background: style.Background,
decoration: decoration);
}
/// <summary>
/// Creates a new style from the specified one with
/// the specified link.
/// </summary>
/// <param name="style">The style.</param>
/// <param name="link">The link.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Link(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Style WithLink(this Style style, string link)
{
if (style is null)
{
throw new ArgumentNullException(nameof(style));
}
return new Style(
foreground: style.Foreground,
background: style.Background,
decoration: style.Decoration,
link: link);
}
}
}

View File

@@ -0,0 +1,202 @@
using System;
using System.ComponentModel;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="Table"/>.
/// </summary>
public static class ObsoleteTableExtensions
{
/// <summary>
/// Sets the table width.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="width">The width.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Width(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Table SetWidth(this Table table, int width)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
table.Width = width;
return table;
}
/// <summary>
/// Sets the table heading.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="text">The heading.</param>
/// <param name="style">The style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Heading(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Table SetHeading(this Table table, string text, Style? style = null)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
if (text is null)
{
throw new ArgumentNullException(nameof(text));
}
return SetHeading(table, new TableTitle(text, style));
}
/// <summary>
/// Sets the table heading.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="heading">The heading.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Heading(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Table SetHeading(this Table table, TableTitle heading)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
table.Title = heading;
return table;
}
/// <summary>
/// Sets the table footnote.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="text">The footnote.</param>
/// <param name="style">The style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Caption(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Table SetFootnote(this Table table, string text, Style? style = null)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
if (text is null)
{
throw new ArgumentNullException(nameof(text));
}
return SetFootnote(table, new TableTitle(text, style));
}
/// <summary>
/// Sets the table footnote.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="footnote">The footnote.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Caption(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Table SetFootnote(this Table table, TableTitle footnote)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
table.Caption = footnote;
return table;
}
/// <summary>
/// Sets the table footnote.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="text">The footnote.</param>
/// <param name="style">The style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Caption(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Table Footnote(this Table table, string text, Style? style = null)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
if (text is null)
{
throw new ArgumentNullException(nameof(text));
}
return Footnote(table, new TableTitle(text, style));
}
/// <summary>
/// Sets the table footnote.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="footnote">The footnote.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Caption(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Table Footnote(this Table table, TableTitle footnote)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
table.Caption = footnote;
return table;
}
/// <summary>
/// Sets the table heading.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="text">The heading.</param>
/// <param name="style">The style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Title(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Table Heading(this Table table, string text, Style? style = null)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
if (text is null)
{
throw new ArgumentNullException(nameof(text));
}
return Heading(table, new TableTitle(text, style));
}
/// <summary>
/// Sets the table heading.
/// </summary>
/// <param name="table">The table.</param>
/// <param name="heading">The heading.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
[Obsolete("Use Title(..) instead.")]
[EditorBrowsable(EditorBrowsableState.Never)]
public static Table Heading(this Table table, TableTitle heading)
{
if (table is null)
{
throw new ArgumentNullException(nameof(table));
}
table.Title = heading;
return table;
}
}
}

View File

@@ -21,7 +21,7 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
} }
return SetOverflow(obj, Overflow.Fold); return Overflow(obj, Console.Overflow.Fold);
} }
/// <summary> /// <summary>
@@ -38,7 +38,7 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
} }
return SetOverflow(obj, Overflow.Crop); return Overflow(obj, Console.Overflow.Crop);
} }
/// <summary> /// <summary>
@@ -55,7 +55,7 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
} }
return SetOverflow(obj, Overflow.Ellipsis); return Overflow(obj, Console.Overflow.Ellipsis);
} }
/// <summary> /// <summary>
@@ -65,7 +65,7 @@ namespace Spectre.Console
/// <param name="obj">The overflowable object instance.</param> /// <param name="obj">The overflowable object instance.</param>
/// <param name="overflow">The overflow strategy to use.</param> /// <param name="overflow">The overflow strategy to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetOverflow<T>(this T obj, Overflow overflow) public static T Overflow<T>(this T obj, Overflow overflow)
where T : class, IOverflowable where T : class, IOverflowable
{ {
if (obj is null) if (obj is null)

View File

@@ -22,7 +22,7 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
} }
return SetPadding(obj, new Padding(left, obj.Padding.Top, obj.Padding.Right, obj.Padding.Bottom)); return Padding(obj, new Padding(left, obj.Padding.GetTopSafe(), obj.Padding.GetRightSafe(), obj.Padding.GetBottomSafe()));
} }
/// <summary> /// <summary>
@@ -40,7 +40,7 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
} }
return SetPadding(obj, new Padding(obj.Padding.Left, top, obj.Padding.Right, obj.Padding.Bottom)); return Padding(obj, new Padding(obj.Padding.GetLeftSafe(), top, obj.Padding.GetRightSafe(), obj.Padding.GetBottomSafe()));
} }
/// <summary> /// <summary>
@@ -58,7 +58,7 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
} }
return SetPadding(obj, new Padding(obj.Padding.Left, obj.Padding.Top, right, obj.Padding.Bottom)); return Padding(obj, new Padding(obj.Padding.GetLeftSafe(), obj.Padding.GetTopSafe(), right, obj.Padding.GetBottomSafe()));
} }
/// <summary> /// <summary>
@@ -76,11 +76,11 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(obj)); throw new ArgumentNullException(nameof(obj));
} }
return SetPadding(obj, new Padding(obj.Padding.Left, obj.Padding.Top, obj.Padding.Right, bottom)); return Padding(obj, new Padding(obj.Padding.GetLeftSafe(), obj.Padding.GetTopSafe(), obj.Padding.GetRightSafe(), bottom));
} }
/// <summary> /// <summary>
/// Sets the left and right padding. /// Sets the left, top, right and bottom padding.
/// </summary> /// </summary>
/// <typeparam name="T">An object implementing <see cref="IPaddable"/>.</typeparam> /// <typeparam name="T">An object implementing <see cref="IPaddable"/>.</typeparam>
/// <param name="obj">The paddable object instance.</param> /// <param name="obj">The paddable object instance.</param>
@@ -89,10 +89,24 @@ namespace Spectre.Console
/// <param name="right">The right padding to apply.</param> /// <param name="right">The right padding to apply.</param>
/// <param name="bottom">The bottom padding to apply.</param> /// <param name="bottom">The bottom padding to apply.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetPadding<T>(this T obj, int left, int top, int right, int bottom) public static T Padding<T>(this T obj, int left, int top, int right, int bottom)
where T : class, IPaddable where T : class, IPaddable
{ {
return SetPadding(obj, new Padding(left, top, right, bottom)); return Padding(obj, new Padding(left, top, right, bottom));
}
/// <summary>
/// Sets the horizontal and vertical padding.
/// </summary>
/// <typeparam name="T">An object implementing <see cref="IPaddable"/>.</typeparam>
/// <param name="obj">The paddable object instance.</param>
/// <param name="horizontal">The left and right padding.</param>
/// <param name="vertical">The top and bottom padding.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static T Padding<T>(this T obj, int horizontal, int vertical)
where T : class, IPaddable
{
return Padding(obj, new Padding(horizontal, vertical));
} }
/// <summary> /// <summary>
@@ -102,7 +116,7 @@ namespace Spectre.Console
/// <param name="obj">The paddable object instance.</param> /// <param name="obj">The paddable object instance.</param>
/// <param name="padding">The padding to apply.</param> /// <param name="padding">The padding to apply.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static T SetPadding<T>(this T obj, Padding padding) public static T Padding<T>(this T obj, Padding padding)
where T : class, IPaddable where T : class, IPaddable
{ {
if (obj is null) if (obj is null)

View File

@@ -0,0 +1,48 @@
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="Padding"/>.
/// </summary>
public static class PaddingExtensions
{
/// <summary>
/// Gets the left padding.
/// </summary>
/// <param name="padding">The padding.</param>
/// <returns>The left padding or zero if <c>padding</c> is null.</returns>
public static int GetLeftSafe(this Padding? padding)
{
return padding?.Left ?? 0;
}
/// <summary>
/// Gets the right padding.
/// </summary>
/// <param name="padding">The padding.</param>
/// <returns>The right padding or zero if <c>padding</c> is null.</returns>
public static int GetRightSafe(this Padding? padding)
{
return padding?.Right ?? 0;
}
/// <summary>
/// Gets the top padding.
/// </summary>
/// <param name="padding">The padding.</param>
/// <returns>The top padding or zero if <c>padding</c> is null.</returns>
public static int GetTopSafe(this Padding? padding)
{
return padding?.Top ?? 0;
}
/// <summary>
/// Gets the bottom padding.
/// </summary>
/// <param name="padding">The padding.</param>
/// <returns>The bottom padding or zero if <c>padding</c> is null.</returns>
public static int GetBottomSafe(this Padding? padding)
{
return padding?.Bottom ?? 0;
}
}
}

View File

@@ -12,10 +12,9 @@ namespace Spectre.Console
/// </summary> /// </summary>
/// <param name="panel">The panel.</param> /// <param name="panel">The panel.</param>
/// <param name="text">The header text.</param> /// <param name="text">The header text.</param>
/// <param name="style">The header style.</param>
/// <param name="alignment">The header alignment.</param> /// <param name="alignment">The header alignment.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static Panel SetHeader(this Panel panel, string text, Style? style = null, Justify? alignment = null) public static Panel Header(this Panel panel, string text, Justify? alignment = null)
{ {
if (panel is null) if (panel is null)
{ {
@@ -27,7 +26,35 @@ namespace Spectre.Console
throw new ArgumentNullException(nameof(text)); throw new ArgumentNullException(nameof(text));
} }
return SetHeader(panel, new PanelHeader(text, style, alignment)); alignment ??= panel.Header?.Alignment;
return Header(panel, new PanelHeader(text, alignment));
}
/// <summary>
/// Sets the panel header alignment.
/// </summary>
/// <param name="panel">The panel.</param>
/// <param name="alignment">The header alignment.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Panel HeaderAlignment(this Panel panel, Justify alignment)
{
if (panel is null)
{
throw new ArgumentNullException(nameof(panel));
}
if (panel.Header != null)
{
// Update existing style
panel.Header.Alignment = alignment;
}
else
{
// Create header
Header(panel, string.Empty, alignment);
}
return panel;
} }
/// <summary> /// <summary>
@@ -36,7 +63,7 @@ namespace Spectre.Console
/// <param name="panel">The panel.</param> /// <param name="panel">The panel.</param>
/// <param name="header">The header to use.</param> /// <param name="header">The header to use.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static Panel SetHeader(this Panel panel, PanelHeader header) public static Panel Header(this Panel panel, PanelHeader header)
{ {
if (panel is null) if (panel is null)
{ {

View File

@@ -0,0 +1,54 @@
using System;
namespace Spectre.Console
{
/// <summary>
/// Contains extension methods for <see cref="RuleExtensions"/>.
/// </summary>
public static class RuleExtensions
{
/// <summary>
/// Sets the rule title.
/// </summary>
/// <param name="rule">The rule.</param>
/// <param name="title">The title.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Rule RuleTitle(this Rule rule, string title)
{
if (rule is null)
{
throw new ArgumentNullException(nameof(rule));
}
if (title is null)
{
throw new ArgumentNullException(nameof(title));
}
rule.Title = title;
return rule;
}
/// <summary>
/// Sets the rule style.
/// </summary>
/// <param name="rule">The rule.</param>
/// <param name="style">The rule style.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns>
public static Rule RuleStyle(this Rule rule, Style style)
{
if (rule is null)
{
throw new ArgumentNullException(nameof(rule));
}
if (style is null)
{
throw new ArgumentNullException(nameof(style));
}
rule.Style = style;
return rule;
}
}
}

View File

@@ -1,3 +1,11 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using Spectre.Console.Internal;
using Spectre.Console.Rendering;
namespace Spectre.Console namespace Spectre.Console
{ {
/// <summary> /// <summary>
@@ -5,13 +13,17 @@ namespace Spectre.Console
/// </summary> /// </summary>
public static class StringExtensions public static class StringExtensions
{ {
// Cache whether or not internally normalized line endings
// already are normalized. No reason to do yet another replace if it is.
private static readonly bool _alreadyNormalized
= Environment.NewLine.Equals("\n", StringComparison.OrdinalIgnoreCase);
/// <summary> /// <summary>
/// Converts the string to something that is safe to /// Escapes text so that it wont be interpreted as markup.
/// use in a markup string.
/// </summary> /// </summary>
/// <param name="text">The text to convert.</param> /// <param name="text">The text to escape.</param>
/// <returns>A string that is safe to use in a markup string.</returns> /// <returns>A string that is safe to use in markup.</returns>
public static string SafeMarkup(this string text) public static string EscapeMarkup(this string text)
{ {
if (text == null) if (text == null)
{ {
@@ -19,8 +31,137 @@ namespace Spectre.Console
} }
return text return text
.Replace("[", "[[") .ReplaceExact("[", "[[")
.Replace("]", "]]"); .ReplaceExact("]", "]]");
}
internal static int CellLength(this string text, RenderContext context)
{
if (context is null)
{
throw new ArgumentNullException(nameof(context));
}
return Cell.GetCellLength(context, text);
}
internal static string Capitalize(this string text, CultureInfo? culture = null)
{
if (text == null)
{
return string.Empty;
}
culture ??= CultureInfo.InvariantCulture;
if (text.Length > 0 && char.IsLower(text[0]))
{
text = string.Format(culture, "{0}{1}", char.ToUpper(text[0], culture), text.Substring(1));
}
return text;
}
internal static string NormalizeLineEndings(this string? text, bool native = false)
{
text = text?.ReplaceExact("\r\n", "\n");
text = text?.ReplaceExact("\r", string.Empty);
text ??= string.Empty;
if (native && !_alreadyNormalized)
{
text = text.ReplaceExact("\n", Environment.NewLine);
}
return text;
}
internal static string[] SplitLines(this string text)
{
var result = text?.NormalizeLineEndings()?.Split(new[] { '\n' }, StringSplitOptions.None);
return result ?? Array.Empty<string>();
}
internal static string[] SplitWords(this string word, StringSplitOptions options = StringSplitOptions.None)
{
var result = new List<string>();
static string Read(StringBuffer reader, Func<char, bool> criteria)
{
var buffer = new StringBuilder();
while (!reader.Eof)
{
var current = reader.Peek();
if (!criteria(current))
{
break;
}
buffer.Append(reader.Read());
}
return buffer.ToString();
}
using (var reader = new StringBuffer(word))
{
while (!reader.Eof)
{
var current = reader.Peek();
if (char.IsWhiteSpace(current))
{
var x = Read(reader, c => char.IsWhiteSpace(c));
if (options != StringSplitOptions.RemoveEmptyEntries)
{
result.Add(x);
}
}
else
{
result.Add(Read(reader, c => !char.IsWhiteSpace(c)));
}
}
}
return result.ToArray();
}
internal static string Repeat(this string text, int count)
{
if (text is null)
{
throw new ArgumentNullException(nameof(text));
}
if (count <= 0)
{
return string.Empty;
}
if (count == 1)
{
return text;
}
return string.Concat(Enumerable.Repeat(text, count));
}
internal static string ReplaceExact(this string text, string oldValue, string? newValue)
{
#if NET5_0
return text.Replace(oldValue, newValue, StringComparison.Ordinal);
#else
return text.Replace(oldValue, newValue);
#endif
}
internal static bool ContainsExact(this string text, string value)
{
#if NET5_0
return text.Contains(value, StringComparison.Ordinal);
#else
return text.Contains(value);
#endif
} }
} }
} }

View File

@@ -1,4 +1,5 @@
using System; using System;
using System.Collections.Generic;
namespace Spectre.Console namespace Spectre.Console
{ {
@@ -14,7 +15,7 @@ namespace Spectre.Console
/// <param name="style">The style.</param> /// <param name="style">The style.</param>
/// <param name="color">The foreground color.</param> /// <param name="color">The foreground color.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static Style WithForeground(this Style style, Color color) public static Style Foreground(this Style style, Color color)
{ {
if (style is null) if (style is null)
{ {
@@ -34,7 +35,7 @@ namespace Spectre.Console
/// <param name="style">The style.</param> /// <param name="style">The style.</param>
/// <param name="color">The background color.</param> /// <param name="color">The background color.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static Style WithBackground(this Style style, Color color) public static Style Background(this Style style, Color color)
{ {
if (style is null) if (style is null)
{ {
@@ -54,7 +55,7 @@ namespace Spectre.Console
/// <param name="style">The style.</param> /// <param name="style">The style.</param>
/// <param name="decoration">The text decoration.</param> /// <param name="decoration">The text decoration.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static Style WithDecoration(this Style style, Decoration decoration) public static Style Decoration(this Style style, Decoration decoration)
{ {
if (style is null) if (style is null)
{ {
@@ -74,7 +75,7 @@ namespace Spectre.Console
/// <param name="style">The style.</param> /// <param name="style">The style.</param>
/// <param name="link">The link.</param> /// <param name="link">The link.</param>
/// <returns>The same instance so that multiple calls can be chained.</returns> /// <returns>The same instance so that multiple calls can be chained.</returns>
public static Style WithLink(this Style style, string link) public static Style Link(this Style style, string link)
{ {
if (style is null) if (style is null)
{ {
@@ -87,5 +88,26 @@ namespace Spectre.Console
decoration: style.Decoration, decoration: style.Decoration,
link: link); link: link);
} }
internal static Style Combine(this Style style, IEnumerable<Style> source)
{
if (style is null)
{
throw new ArgumentNullException(nameof(style));
}
if (source is null)
{
return style;
}
var current = style;
foreach (var item in source)
{
current = current.Combine(item);
}
return current;
}
} }
} }

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