mirror of
https://github.com/spectreconsole/spectre.console.git
synced 2025-10-25 15:19:23 +00:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f8ca6d648 | ||
|
|
88edfe68ec | ||
|
|
5d32764a64 | ||
|
|
4f6c9c62c7 | ||
|
|
f2677213a4 | ||
|
|
bdaf00a556 | ||
|
|
7de4b6c7b9 | ||
|
|
0bc801e3eb | ||
|
|
88a82cdad0 | ||
|
|
0cecb555d5 | ||
|
|
52e3ee17b0 | ||
|
|
caf7661e66 | ||
|
|
65f0a085cc | ||
|
|
a123806cd8 | ||
|
|
173645cdd2 | ||
|
|
7fd2efaeb5 | ||
|
|
47fd646d21 | ||
|
|
a06859dcb5 | ||
|
|
7d3a67e6ae | ||
|
|
f4497b1278 | ||
|
|
a16daade6c | ||
|
|
ab73d16583 | ||
|
|
f2566f2ca4 | ||
|
|
358b0225b4 |
39
.github/workflows/ci.yaml
vendored
39
.github/workflows/ci.yaml
vendored
@@ -6,6 +6,35 @@ env:
|
||||
DOTNET_CLI_TELEMETRY_OPTOUT: true
|
||||
|
||||
jobs:
|
||||
|
||||
###################################################
|
||||
# DOCS
|
||||
###################################################
|
||||
|
||||
docs:
|
||||
name: Documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '3.1.301' # SDK Version to use.
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
cd docs
|
||||
dotnet run --configuration Release
|
||||
|
||||
###################################################
|
||||
# BUILD
|
||||
###################################################
|
||||
|
||||
build:
|
||||
name: Build
|
||||
if: "!contains(github.event.head_commit.message, 'skip-ci')"
|
||||
@@ -31,6 +60,16 @@ jobs:
|
||||
with:
|
||||
dotnet-version: 3.1.301
|
||||
|
||||
- name: Integration Tests
|
||||
shell: bash
|
||||
run: |
|
||||
dotnet tool restore
|
||||
dotnet example diagnostic
|
||||
dotnet example table
|
||||
dotnet example grid
|
||||
dotnet example panel
|
||||
dotnet example colors
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
run: |
|
||||
|
||||
12
.github/workflows/docs.yaml
vendored
12
.github/workflows/docs.yaml
vendored
@@ -4,14 +4,22 @@ on:
|
||||
push:
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- 'src/**'
|
||||
|
||||
jobs:
|
||||
|
||||
###################################################
|
||||
# DOCS
|
||||
###################################################
|
||||
|
||||
build:
|
||||
name: Deploy
|
||||
runs-on: windows-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v1
|
||||
@@ -24,4 +32,4 @@ jobs:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
cd docs
|
||||
dotnet run -- deploy
|
||||
dotnet run --configuration Release -- deploy
|
||||
|
||||
31
.github/workflows/publish.yaml
vendored
31
.github/workflows/publish.yaml
vendored
@@ -6,6 +6,8 @@ on:
|
||||
- '*'
|
||||
branches:
|
||||
- main
|
||||
paths:
|
||||
- 'src/**'
|
||||
|
||||
env:
|
||||
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
|
||||
@@ -13,13 +15,38 @@ env:
|
||||
|
||||
jobs:
|
||||
|
||||
###################################################
|
||||
# DOCS
|
||||
###################################################
|
||||
|
||||
docs:
|
||||
name: Documentation
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: Setup dotnet
|
||||
uses: actions/setup-dotnet@v1
|
||||
with:
|
||||
dotnet-version: '3.1.301' # SDK Version to use.
|
||||
|
||||
- name: Build
|
||||
shell: bash
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
cd docs
|
||||
dotnet run --configuration Release
|
||||
|
||||
###################################################
|
||||
# BUILD
|
||||
###################################################
|
||||
|
||||
build:
|
||||
name: Build
|
||||
if: "!contains(github.event.head_commit.message, 'skip-ci')"
|
||||
needs: [docs]
|
||||
if: "!contains(github.event.head_commit.message, 'skip-ci') || startsWith(github.ref, 'refs/tags/')"
|
||||
strategy:
|
||||
matrix:
|
||||
kind: ['linux', 'windows', 'macOS']
|
||||
@@ -55,7 +82,7 @@ jobs:
|
||||
publish:
|
||||
name: Publish
|
||||
needs: [build]
|
||||
if: "!contains(github.event.head_commit.message, 'skip-ci')"
|
||||
if: "!contains(github.event.head_commit.message, 'skip-ci') || startsWith(github.ref, 'refs/tags/')"
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RunWorkingDirectory>$(MSBuildProjectDirectory)</RunWorkingDirectory>
|
||||
<DefaultItemExcludes>$(DefaultItemExcludes);output\**;.gitignore</DefaultItemExcludes>
|
||||
<MinVerSkip Condition="'$(Configuration)' == 'Debug'">true</MinVerSkip>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -22,8 +23,15 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Statiq.Web" Version="1.0.0-alpha.9" />
|
||||
<PackageReference Include="NJsonSchema" Version="10.1.12" />
|
||||
<PackageReference Include="Statiq.Web" Version="1.0.0-beta.5" />
|
||||
<PackageReference Include="MinVer" PrivateAssets="All" Version="2.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="Versioning" BeforeTargets="MinVer">
|
||||
<PropertyGroup Label="Build">
|
||||
<MinVerDefaultPreReleasePhase>preview</MinVerDefaultPreReleasePhase>
|
||||
<MinVerVerbosity>normal</MinVerVerbosity>
|
||||
</PropertyGroup>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
1
docs/Preview.ps1
Normal file
1
docs/Preview.ps1
Normal file
@@ -0,0 +1 @@
|
||||
dotnet run -- preview --virtual-dir "spectre.console"
|
||||
8
docs/README.md
Normal file
8
docs/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# Documentation
|
||||
|
||||
Preview the documentation locally by running the following
|
||||
from your favourite shell:
|
||||
|
||||
```
|
||||
> dotnet run -- preview --virtual-dir "spectre.console"
|
||||
```
|
||||
@@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
@@ -26,13 +26,34 @@
|
||||
</head>
|
||||
<body class="d-flex flex-column">
|
||||
<div class="flex-grow-1 d-flex flex-column">
|
||||
|
||||
|
||||
<nav id="topnav" class="navbar navbar-expand-lg navbar-light">
|
||||
<div class="container py-3">
|
||||
<a class="navbar-brand" href="/spectre.console"><img id="logo" src="/spectre.console/assets/logo.svg" alt="Spectre.Console"> Spectre.Console</a>
|
||||
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
|
||||
<span class="navbar-toggler-icon"></span>
|
||||
</button>
|
||||
<div class="collapse navbar-collapse" id="navbarText">
|
||||
<ul class="navbar-nav mr-auto">
|
||||
</ul>
|
||||
<ul class="navbar-nav">
|
||||
<li class="nav-item">
|
||||
<a class="nav-link font-weight-light font-size-lg text-red" href="https://github.com/sponsors/patriksvensson"><i class="far fa-heart"></i> Sponsor</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link font-weight-light font-size-lg" href="https://github.com/spectresystems/spectre.console"><i class="fab fa-github"></i> GitHub</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
@if (IsSectionDefined(Constants.Sections.Splash))
|
||||
{
|
||||
@RenderSection(Constants.Sections.Splash, false)
|
||||
}
|
||||
@{
|
||||
string section = Document.Destination.Segments.Length > 1 ? Document.Destination.Segments[0].ToString() : null;
|
||||
@{
|
||||
string section = "docs";
|
||||
}
|
||||
|
||||
<div class="flex-grow-1 d-flex bg-body flex-column @(section != null ? "section-" + section : null)">
|
||||
@@ -41,7 +62,7 @@
|
||||
<div id="titlebar" class="py-4">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
@{
|
||||
@{
|
||||
string titleBarClasses = Document.GetBool(Constants.NoSidebar) ? string.Empty : "offset-md-3 offset-lg-2";
|
||||
}
|
||||
<div class="@titleBarClasses px-3 px-md-0">
|
||||
@@ -76,7 +97,7 @@
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
|
||||
<div class="flex-grow-1 d-flex flex-column bg-body">
|
||||
@if (Document.GetBool(Constants.NoContainer))
|
||||
{
|
||||
@@ -105,21 +126,22 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
IDocument root = Outputs[nameof(Content)].First(x => x.Destination == section + "/index.html");
|
||||
IDocument root = OutputPages["index.html"].First();
|
||||
<div class="sidebar-nav-item @(Document.IdEquals(root) ? "active" : null)">
|
||||
@Html.DocumentLink(root)
|
||||
</div>
|
||||
|
||||
@foreach (IDocument document in root.GetChildren().OnlyVisible())
|
||||
@foreach (IDocument document in OutputPages.GetChildrenOf(root).OnlyVisible())
|
||||
{
|
||||
<div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(document.HasChildren() ? "has-children" : null)">
|
||||
DocumentList<IDocument> documentChildren = OutputPages.GetChildrenOf(document);
|
||||
<div class="sidebar-nav-item @(Document.IdEquals(document) ? "active" : null) @(documentChildren.Any() ? "has-children" : null)">
|
||||
@Html.DocumentLink(document)
|
||||
</div>
|
||||
|
||||
@if (document.HasVisibleChildren())
|
||||
@if (documentChildren.OnlyVisible().Any())
|
||||
{
|
||||
<div class="sidebar-nav-children @(Document.IdEquals(document) || document.GetChildren().Any(x => Document.IdEquals(x)) ? "active" : null)">
|
||||
@foreach (IDocument child in document.GetChildren().OnlyVisible())
|
||||
<div class="sidebar-nav-children @(Document.IdEquals(document) || documentChildren.Any(x => Document.IdEquals(x)) ? "active" : null)">
|
||||
@foreach (IDocument child in documentChildren.OnlyVisible())
|
||||
{
|
||||
<div class="sidebar-nav-child @(Document.IdEquals(child) ? "active" : null)">
|
||||
@Html.DocumentLink(child)
|
||||
@@ -161,7 +183,10 @@
|
||||
</div>
|
||||
<div id="footer" class="p-3 text-white font-size-sm">
|
||||
<div class="container">
|
||||
<div>© @DateTime.Today.Year Spectre Systems AB</div>
|
||||
<div>
|
||||
<span>© @DateTime.Today.Year Spectre Systems AB</span>
|
||||
<span class="float-right" style="color: #888888;">@VersionUtilities.GetVersion()</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script>
|
||||
@@ -174,7 +199,7 @@
|
||||
},
|
||||
startOnLoad: false,
|
||||
cloneCssStyles: false
|
||||
});
|
||||
});
|
||||
mermaid.init(undefined, ".mermaid");
|
||||
|
||||
// Remove the max-width setting that Mermaid sets
|
||||
@@ -193,13 +218,13 @@
|
||||
center: true,
|
||||
maxZoom: 20,
|
||||
zoomScaleSensitivity: 0.6
|
||||
});
|
||||
});
|
||||
|
||||
// Do the reset once right away to fit the diagram
|
||||
panZoom.resize();
|
||||
panZoom.fit();
|
||||
panZoom.center();
|
||||
|
||||
|
||||
$(window).resize(function(){
|
||||
panZoom.resize();
|
||||
panZoom.fit();
|
||||
|
||||
@@ -3,5 +3,6 @@
|
||||
@using Statiq.Web
|
||||
@using Statiq.Web.Pipelines
|
||||
@using Docs
|
||||
@using Docs.Utilities;
|
||||
|
||||
@inherits StatiqRazorPage<IDocument>
|
||||
@@ -18,6 +18,18 @@ $thebackground: $gray-200;
|
||||
display: inline-block;
|
||||
width: 60px;
|
||||
height: 15px;
|
||||
border: 2px solid #000000;
|
||||
}
|
||||
|
||||
#topnav {
|
||||
padding: 0px;
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
#topnav .container {
|
||||
padding-top: 0px !important;
|
||||
padding-bottom: 0px !important;
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
@media screen {
|
||||
|
||||
BIN
docs/input/assets/images/helloworld.png
Normal file
BIN
docs/input/assets/images/helloworld.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.3 KiB |
@@ -1,5 +1,5 @@
|
||||
Title: Colors
|
||||
Order: 2
|
||||
Order: 4
|
||||
---
|
||||
|
||||
The following is a list of the standard 8-bit colors supported in terminals.
|
||||
@@ -1,6 +0,0 @@
|
||||
Title: Console API
|
||||
Order: 2
|
||||
Hidden: True
|
||||
---
|
||||
|
||||
__To be written__
|
||||
@@ -1,6 +0,0 @@
|
||||
Title: Grids
|
||||
Order: 4
|
||||
Hidden: True
|
||||
---
|
||||
|
||||
__To be written__
|
||||
@@ -1,6 +0,0 @@
|
||||
Title: Panels
|
||||
Order: 5
|
||||
Hidden: True
|
||||
---
|
||||
|
||||
__To be written__
|
||||
@@ -1,6 +0,0 @@
|
||||
Title: Tables
|
||||
Order: 3
|
||||
Hidden: True
|
||||
---
|
||||
|
||||
__To be written__
|
||||
@@ -1,84 +0,0 @@
|
||||
Title: Start
|
||||
NoContainer: true
|
||||
---
|
||||
@section Splash {
|
||||
<div id="hero" class="jumbotron jumbotron-fluid mb-0">
|
||||
<div class="container">
|
||||
<div class="display-4 text-white">Spectre.Console</div>
|
||||
<p class="lead text-white">
|
||||
A .NET Standard library that makes it easier to create beautiful console applications.
|
||||
<br /><br />
|
||||
<a class="btn btn-primary" href="/spectre.console/docs" role="button">Take me to the documentation</a>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
@* <div class="container py-3">
|
||||
<div class="row">
|
||||
<div class="col-sm py-3">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<i class="fad fa-heartbeat fa-2x icon-md-100 icon-theme"></i>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<h3 class="font-weight-bold font-size-base text-dark mb-2">A beautiful console</h3>
|
||||
<p>
|
||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
|
||||
Aenean elementum est lorem, at auctor nibh rhoncus eget.
|
||||
Ut lorem leo, aliquet sit amet tortor vitae, aliquet eleifend dui.
|
||||
Etiam lectus diam, maximus a pretium a, lacinia in augue.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm py-3">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<i class="fad fa-code fa-2x icon-md-100 icon-theme"></i>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<h3 class="font-weight-bold font-size-base text-dark mb-2">Rich formatting language</h3>
|
||||
<p>
|
||||
Donec at rutrum turpis. Etiam tempor sed ex quis pharetra.
|
||||
Suspendisse ullamcorper at magna ac efficitur. Nulla ornare,
|
||||
lectus feugiat ornare ultricies, nunc lorem maximus ipsum,
|
||||
nec accumsan eros tellus quis ante
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm py-3">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<i class="fad fa-cogs fa-2x icon-md-100 icon-theme"></i>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<h3 class="font-weight-bold font-size-base text-dark mb-2">Configurable</h3>
|
||||
<p>
|
||||
Suspendisse vel condimentum tortor. Fusce tempus ligula ut eros finibus,
|
||||
nec fermentum ipsum hendrerit. Proin eu diam in tortor vestibulum bibendum.
|
||||
Integer tincidunt felis eu urna pulvinar vehicula.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm py-3">
|
||||
<div class="row">
|
||||
<div class="col-md-2">
|
||||
<i class="fad fa-search fa-2x icon-md-100 icon-theme"></i>
|
||||
</div>
|
||||
<div class="col-md-10">
|
||||
<h3 class="font-weight-bold font-size-base text-dark mb-2">Find problems quickly</h3>
|
||||
<p>
|
||||
Aliquam nec nisl ullamcorper, aliquam mauris sit amet, sagittis orci.
|
||||
Aenean sapien dui, eleifend eget sapien nec, tristique accumsan tortor.
|
||||
Quisque ex quam, rhoncus sagittis consequat id, euismod sit amet dolor.
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> *@
|
||||
@@ -13,7 +13,7 @@ for Python written by Will McGugan.
|
||||
* Supports tables, grids, panels, and a [Rich](https://github.com/willmcgugan/rich)
|
||||
inspired markup language.
|
||||
* Supports the most common
|
||||
[SRG parameters](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters)
|
||||
[SGR parameters](https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters)
|
||||
when it comes to text styling such as bold, dim, italic, underline, strikethrough,
|
||||
and blinking text.
|
||||
* Supports `3`/`4`/`8`/`24`-bit colors in the terminal.
|
||||
104
docs/input/markup.md
Normal file
104
docs/input/markup.md
Normal file
@@ -0,0 +1,104 @@
|
||||
Title: Markup
|
||||
Order: 3
|
||||
Hidden: False
|
||||
---
|
||||
|
||||
In `Spectre.Console` there's a class called `Markup` that
|
||||
allows you to output rich text to the console.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Render(new Markup("[bold yellow]Hello[/] [red]World![/]"));
|
||||
```
|
||||
|
||||
Which should output something similar to the image below. Note that the
|
||||
actual appearance might vary depending on your terminal.
|
||||
|
||||

|
||||
|
||||
|
||||
The `Markup` class implements `IRenderable` which means that you
|
||||
can use this in tables, grids, and panels. Most classes that support
|
||||
rendering of `IRenderable` also have overloads for rendering rich text.
|
||||
|
||||
```csharp
|
||||
var table = new Table();
|
||||
table.AddColumn(new TableColumn(new Markup("[yellow]Foo[/]")));
|
||||
table.AddColumn(new TableColumn("[blue]Bar[/]"));
|
||||
```
|
||||
|
||||
# Convenience methods
|
||||
|
||||
There is also convenience methods on `AnsiConsole` that can be used
|
||||
to write markup text to the console without instantiating a new `Markup`
|
||||
instance.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("[underline green]Hello[/] ");
|
||||
AnsiConsole.MarkupLine("[bold]World[/]");
|
||||
```
|
||||
|
||||
# Escaping format characters
|
||||
|
||||
To output a `[` you use `[[`, and to output a `]` you use `]]`.
|
||||
|
||||
```csharp
|
||||
AnsiConsole.Markup("[[Hello]] "); // [Hello]
|
||||
AnsiConsole.Markup("[red][[World]][/]"); // [World]
|
||||
```
|
||||
|
||||
# Setting background color
|
||||
|
||||
You can set the background color in markup by prefixing the color with
|
||||
`on`.
|
||||
|
||||
```
|
||||
[bold yellow on blue]Hello[/]
|
||||
[default on blue]World[/]
|
||||
```
|
||||
|
||||
# Colors
|
||||
|
||||
For a list of colors, see the [Colors](xref:colors) section.
|
||||
|
||||
# Styles
|
||||
|
||||
Note that what styles that can be used is defined by the system or your terminal software, and may not appear as they should.
|
||||
|
||||
<table class="table">
|
||||
<tr>
|
||||
<td><code>bold</code></td>
|
||||
<td>Bold text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>dim</code></td>
|
||||
<td>Dim or faint text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>italic</code></td>
|
||||
<td>Italic text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>underline</code></td>
|
||||
<td>Underlined text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>invert</code></td>
|
||||
<td>Swaps the foreground and background colors</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>conceal</code></td>
|
||||
<td>Hides the text</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>slowblink</code></td>
|
||||
<td>Makes text blink slowly</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>rapidblink</code></td>
|
||||
<td>Makes text blink</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>strikethrough</code></td>
|
||||
<td>Shows text with a horizontal line through the center</td>
|
||||
</tr>
|
||||
</table>
|
||||
@@ -11,15 +11,6 @@ namespace Docs
|
||||
return document?.GetString(Constants.Description, string.Empty) ?? string.Empty;
|
||||
}
|
||||
|
||||
public static bool HasVisibleChildren(this IDocument document)
|
||||
{
|
||||
if (document != null)
|
||||
{
|
||||
return document.HasChildren() && document.GetChildren().Any(x => x.IsVisible());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static bool IsVisible(this IDocument document)
|
||||
{
|
||||
return !document.GetBool(Constants.Hidden, false);
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Docs.Models;
|
||||
using NJsonSchema;
|
||||
using Statiq.Common;
|
||||
using Statiq.Core;
|
||||
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NJsonSchema;
|
||||
using Statiq.Common;
|
||||
using System.Xml.Linq;
|
||||
using Docs.Pipelines;
|
||||
@@ -26,6 +25,7 @@ namespace Docs.Shortcodes
|
||||
var table = new XElement("table", new XAttribute("class", "table"));
|
||||
var header = new XElement("tr", new XAttribute("class", "color-row"));
|
||||
header.Add(new XElement("th", ""));
|
||||
header.Add(new XElement("th", "#"));
|
||||
header.Add(new XElement("th", "Name"));
|
||||
header.Add(new XElement("th", "RGB"));
|
||||
header.Add(new XElement("th", "Hex"));
|
||||
@@ -38,7 +38,8 @@ namespace Docs.Shortcodes
|
||||
new XElement("span",
|
||||
new XAttribute("class", "color-representation"),
|
||||
new XAttribute("style", $"background-color:{color.Hex};")));
|
||||
var name = new XElement("td", new XElement("code", color.Name.ToLower()));
|
||||
var name = new XElement("td", new XElement("code", color.Number.ToString()));
|
||||
var number = new XElement("td", new XElement("code", color.Name.ToLower()));
|
||||
var rgb = new XElement("td", new XElement("code", $"{color.R},{color.G},{color.B}"));
|
||||
var hex = new XElement("td", new XElement("code", color.Hex));
|
||||
var clr = new XElement("td", new XElement("code", color.ClrName));
|
||||
@@ -47,6 +48,7 @@ namespace Docs.Shortcodes
|
||||
var row = new XElement("tr");
|
||||
row.Add(rep);
|
||||
row.Add(name);
|
||||
row.Add(number);
|
||||
row.Add(rgb);
|
||||
row.Add(hex);
|
||||
row.Add(clr);
|
||||
|
||||
34
docs/src/Utilities/VersionUtilities.cs
Normal file
34
docs/src/Utilities/VersionUtilities.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace Docs.Utilities
|
||||
{
|
||||
public static class VersionUtilities
|
||||
{
|
||||
public static string GetVersion()
|
||||
{
|
||||
return GetVersion(typeof(VersionUtilities).Assembly);
|
||||
}
|
||||
|
||||
private static string GetVersion(Assembly assembly)
|
||||
{
|
||||
if (assembly == null)
|
||||
{
|
||||
return "?";
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var info = FileVersionInfo.GetVersionInfo(assembly.Location);
|
||||
return info.ProductVersion ?? "?";
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "?";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,12 @@
|
||||
"commands": [
|
||||
"gpr"
|
||||
]
|
||||
},
|
||||
"dotnet-example": {
|
||||
"version": "0.8.0",
|
||||
"commands": [
|
||||
"dotnet-example"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,75 +2,117 @@ using Spectre.Console;
|
||||
|
||||
namespace ColorExample
|
||||
{
|
||||
class Program
|
||||
public static class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 4-BIT
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
AnsiConsole.ResetColors();
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("[bold underline]4-bit Colors[/]");
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
for (var i = 0; i < 16; i++)
|
||||
if (AnsiConsole.Capabilities.ColorSystem == ColorSystem.NoColors)
|
||||
{
|
||||
AnsiConsole.Background = Color.FromInt32(i);
|
||||
AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString()));
|
||||
AnsiConsole.ResetColors();
|
||||
if ((i + 1) % 8 == 0)
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// No colors
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
AnsiConsole.WriteLine("No colors are supported.");
|
||||
return;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 8-BIT
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
AnsiConsole.ResetColors();
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("[bold underline]8-bit Colors[/]");
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
for (var i = 0; i < 16; i++)
|
||||
if (AnsiConsole.Capabilities.Supports(ColorSystem.Legacy))
|
||||
{
|
||||
for (var j = 0; j < 16; j++)
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 3-BIT
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
AnsiConsole.ResetColors();
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("[bold underline]3-bit Colors[/]");
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
for (var i = 0; i < 8; i++)
|
||||
{
|
||||
var number = i * 16 + j;
|
||||
AnsiConsole.Background = Color.FromInt32(number);
|
||||
AnsiConsole.Write(string.Format(" {0,-4}", number));
|
||||
AnsiConsole.Background = Color.FromInt32(i);
|
||||
AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString()));
|
||||
AnsiConsole.ResetColors();
|
||||
if ((number + 1) % 16 == 0)
|
||||
if ((i + 1) % 8 == 0)
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 24-BIT
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
AnsiConsole.ResetColors();
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("[bold underline]24-bit Colors[/]");
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
var index = 0;
|
||||
for (var i = 0.0005; i < 1; i += 0.0025)
|
||||
if (AnsiConsole.Capabilities.Supports(ColorSystem.Standard))
|
||||
{
|
||||
index++;
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 4-BIT
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
var color = Utilities.HSL2RGB(i, 0.5, 0.5);
|
||||
AnsiConsole.Background = new Color(color.R, color.G, color.B);
|
||||
AnsiConsole.Write(" ");
|
||||
AnsiConsole.ResetColors();
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("[bold underline]4-bit Colors[/]");
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
if (index % 50 == 0)
|
||||
for (var i = 0; i < 16; i++)
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.Background = Color.FromInt32(i);
|
||||
AnsiConsole.Write(string.Format(" {0,-9}", AnsiConsole.Background.ToString()));
|
||||
AnsiConsole.ResetColors();
|
||||
if ((i + 1) % 8 == 0)
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AnsiConsole.Capabilities.Supports(ColorSystem.EightBit))
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 8-BIT
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
AnsiConsole.ResetColors();
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("[bold underline]8-bit Colors[/]");
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
for (var i = 0; i < 16; i++)
|
||||
{
|
||||
for (var j = 0; j < 16; j++)
|
||||
{
|
||||
var number = i * 16 + j;
|
||||
AnsiConsole.Background = Color.FromInt32(number);
|
||||
AnsiConsole.Write(string.Format(" {0,-4}", number));
|
||||
AnsiConsole.ResetColors();
|
||||
if ((number + 1) % 16 == 0)
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (AnsiConsole.Capabilities.Supports(ColorSystem.TrueColor))
|
||||
{
|
||||
/////////////////////////////////////////////////////////////////
|
||||
// 24-BIT
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
AnsiConsole.ResetColors();
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("[bold underline]24-bit Colors[/]");
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
var index = 0;
|
||||
for (var i = 0.0005; i < 1; i += 0.0025)
|
||||
{
|
||||
index++;
|
||||
|
||||
var color = Utilities.HSL2RGB(i, 0.5, 0.5);
|
||||
AnsiConsole.Background = new Color(color.R, color.G, color.B);
|
||||
AnsiConsole.Write(" ");
|
||||
|
||||
if (index % 50 == 0)
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
14
examples/Diagnostic/Diagnostic.csproj
Normal file
14
examples/Diagnostic/Diagnostic.csproj
Normal file
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Description>Displays the capabilities of the current console.</Description>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\Spectre.Console\Spectre.Console.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
18
examples/Diagnostic/Program.cs
Normal file
18
examples/Diagnostic/Program.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
using System;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace Diagnostic
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
AnsiConsole.MarkupLine("Color system: [bold]{0}[/]", AnsiConsole.Capabilities.ColorSystem);
|
||||
AnsiConsole.MarkupLine("Supports ansi? [bold]{0}[/]", AnsiConsole.Capabilities.SupportsAnsi);
|
||||
AnsiConsole.MarkupLine("Legacy console? [bold]{0}[/]", AnsiConsole.Capabilities.LegacyConsole);
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("Buffer width: [bold]{0}[/]", AnsiConsole.Console.Width);
|
||||
AnsiConsole.MarkupLine("Buffer height: [bold]{0}[/]", AnsiConsole.Console.Height);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,25 @@
|
||||
using Spectre.Console;
|
||||
|
||||
namespace GridExample
|
||||
{
|
||||
public sealed class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options] [[[[--] <additional arguments>...]][/]");
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn { NoWrap = true });
|
||||
grid.AddColumn(new GridColumn { NoWrap = true, Width = 2 });
|
||||
grid.AddColumn();
|
||||
grid.AddRow("Options:", "", "");
|
||||
grid.AddRow(" [blue]-h[/], [blue]--help[/]", "", "Show command line help.");
|
||||
grid.AddRow(" [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "", "The configuration to run for.");
|
||||
grid.AddRow(" [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "", "Set the [grey]MSBuild[/] verbosity level.");
|
||||
|
||||
AnsiConsole.Render(grid);
|
||||
}
|
||||
}
|
||||
}
|
||||
using Spectre.Console;
|
||||
|
||||
namespace GridExample
|
||||
{
|
||||
public sealed class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine("Usage: [grey]dotnet [blue]run[/] [[options]] [[[[--]] <additional arguments>...]]]][/]");
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
var grid = new Grid();
|
||||
grid.AddColumn(new GridColumn { NoWrap = true });
|
||||
grid.AddColumn(new GridColumn { NoWrap = true, Width = 2 });
|
||||
grid.AddColumn();
|
||||
grid.AddRow("Options:", "", "");
|
||||
grid.AddRow(" [blue]-h[/], [blue]--help[/]", "", "Show command line help.");
|
||||
grid.AddRow(" [blue]-c[/], [blue]--configuration[/] <CONFIGURATION>", "", "The configuration to run for.");
|
||||
grid.AddRow(" [blue]-v[/], [blue]--verbosity[/] <LEVEL>", "", "Set the [grey]MSBuild[/] verbosity level.");
|
||||
|
||||
AnsiConsole.Render(grid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,9 +7,8 @@ namespace PanelExample
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var content = new Markup(
|
||||
"[underline]I[/] heard [underline on blue]you[/] like 📦\n\n\n\n" +
|
||||
"So I put a 📦 in a 📦\n\n" +
|
||||
"😅").Centered();
|
||||
"[underline]I[/] heard [underline on blue]you[/] like panels\n\n\n\n" +
|
||||
"So I put a panel in a panel").Centered();
|
||||
|
||||
AnsiConsole.Render(
|
||||
new Panel(
|
||||
|
||||
@@ -41,16 +41,16 @@ namespace TableExample
|
||||
table.AddColumn(new TableColumn("[blue]Bar[/]") { Alignment = Justify.Right, NoWrap = true });
|
||||
|
||||
// Add some rows
|
||||
table.AddRow("[blue][underline]Hell[/]o[/]", "World 🌍");
|
||||
table.AddRow("[blue][underline]Hell[/]o[/]", "World");
|
||||
table.AddRow("[yellow]Patrik [green]\"Hello World\"[/] Svensson[/]", "Was [underline]here[/]!");
|
||||
table.AddEmptyRow();
|
||||
table.AddRow(
|
||||
"Lorem ipsum dolor sit amet, consectetur adipiscing elit,sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. " +
|
||||
"Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure " +
|
||||
"dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat " +
|
||||
"non proident, sunt in culpa qui officia deserunt mollit anim id est laborum", "◀ Strange language");
|
||||
"non proident, sunt in culpa qui officia deserunt mollit anim id est laborum", "<- Strange language");
|
||||
table.AddEmptyRow();
|
||||
table.AddRow("Hej 👋", "[green]Världen[/]");
|
||||
table.AddRow("Hej", "[green]Världen[/]");
|
||||
|
||||
AnsiConsole.Render(table);
|
||||
}
|
||||
@@ -81,7 +81,7 @@ namespace TableExample
|
||||
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(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);
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("[yellow]Hello[/]", "[93mHello[0m")]
|
||||
[InlineData("[yellow]Hello [italic]World[/]![/]", "[93mHello[0m[93m [0m[3;93mWorld[0m[93m![0m")]
|
||||
[InlineData("[yellow]Hello [italic]World[/]![/]", "[93mHello [0m[3;93mWorld[0m[93m![0m")]
|
||||
public void Should_Output_Expected_Ansi_For_Markup(string markup, string expected)
|
||||
{
|
||||
// Given
|
||||
@@ -26,7 +26,7 @@ namespace Spectre.Console.Tests.Unit
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("[yellow]Hello [[ World[/]", "[93mHello[0m[93m [0m[93m[[0m[93m [0m[93mWorld[0m")]
|
||||
[InlineData("[yellow]Hello [[ World[/]", "[93mHello [ World[0m")]
|
||||
public void Should_Be_Able_To_Escape_Tags(string markup, string expected)
|
||||
{
|
||||
// Given
|
||||
|
||||
@@ -83,5 +83,25 @@ namespace Spectre.Console.Tests.Unit
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(expected);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(Overflow.Fold, "foo \npneumonoultram\nicroscopicsili\ncovolcanoconio\nsis bar qux")]
|
||||
[InlineData(Overflow.Crop, "foo \npneumonoultram\nbar qux")]
|
||||
[InlineData(Overflow.Ellipsis, "foo \npneumonoultra…\nbar qux")]
|
||||
public void Should_Overflow_Text_Correctly(Overflow overflow, string expected)
|
||||
{
|
||||
// Given
|
||||
var fixture = new PlainConsole(14);
|
||||
var text = new Text("foo pneumonoultramicroscopicsilicovolcanoconiosis bar qux")
|
||||
.SetOverflow(overflow);
|
||||
|
||||
// When
|
||||
fixture.Render(text);
|
||||
|
||||
// Then
|
||||
fixture.Output
|
||||
.NormalizeLineEndings()
|
||||
.ShouldBe(expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Grid", "..\examples\Grid\Gr
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Colors", "..\examples\Colors\Colors.csproj", "{1F51C55C-BA4C-4856-9001-0F7924FFB179}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Diagnostic", "..\examples\Diagnostic\Diagnostic.csproj", "{4337F255-88E9-4408-81A3-DF1AF58AC753}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -107,6 +109,18 @@ Global
|
||||
{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Release|x64.Build.0 = Release|Any CPU
|
||||
{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{1F51C55C-BA4C-4856-9001-0F7924FFB179}.Release|x86.Build.0 = Release|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Release|x64.Build.0 = Release|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -116,6 +130,7 @@ Global
|
||||
{BFF37228-B376-4ADD-9657-4E501F929713} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||
{C7FF6FDB-FB59-4517-8669-521C96AB7323} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||
{1F51C55C-BA4C-4856-9001-0F7924FFB179} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||
{4337F255-88E9-4408-81A3-DF1AF58AC753} = {F0575243-121F-4DEE-9F6B-246E26DC0844}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {5729B071-67A0-48FB-8B1B-275E6822086C}
|
||||
|
||||
@@ -38,6 +38,17 @@ namespace Spectre.Console
|
||||
LegacyConsole = legacyConsole;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether the current capabilities supports
|
||||
/// the specified color system.
|
||||
/// </summary>
|
||||
/// <param name="colorSystem">The color system to check.</param>
|
||||
/// <returns><c>true</c> if the color system is supported, otherwise <c>false</c>.</returns>
|
||||
public bool Supports(ColorSystem colorSystem)
|
||||
{
|
||||
return (int)colorSystem <= (int)ColorSystem;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override string ToString()
|
||||
{
|
||||
|
||||
@@ -30,8 +30,11 @@ namespace Spectre.Console
|
||||
|
||||
using (console.PushStyle(Style.Plain))
|
||||
{
|
||||
var segments = renderable.Render(options, console.Width);
|
||||
segments = Segment.Merge(segments);
|
||||
|
||||
var current = Style.Plain;
|
||||
foreach (var segment in renderable.Render(options, console.Width))
|
||||
foreach (var segment in segments)
|
||||
{
|
||||
if (string.IsNullOrEmpty(segment.Text))
|
||||
{
|
||||
|
||||
@@ -21,7 +21,7 @@ namespace Spectre.Console.Internal
|
||||
{
|
||||
if (_out.IsStandardOut())
|
||||
{
|
||||
return System.Console.BufferWidth;
|
||||
return ConsoleHelper.GetSafeBufferWidth(Constants.DefaultBufferWidth);
|
||||
}
|
||||
|
||||
return Constants.DefaultBufferWidth;
|
||||
@@ -34,7 +34,7 @@ namespace Spectre.Console.Internal
|
||||
{
|
||||
if (_out.IsStandardOut())
|
||||
{
|
||||
return System.Console.BufferHeight;
|
||||
return ConsoleHelper.GetSafeBufferHeight(Constants.DefaultBufferHeight);
|
||||
}
|
||||
|
||||
return Constants.DefaultBufferHeight;
|
||||
|
||||
@@ -3,7 +3,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
internal static class ConsoleExtensions
|
||||
internal static class AnsiConsoleExtensions
|
||||
{
|
||||
public static IDisposable PushStyle(this IAnsiConsole console, Style style)
|
||||
{
|
||||
@@ -24,7 +24,7 @@ namespace Spectre.Console.Internal
|
||||
{
|
||||
if (_out.IsStandardOut())
|
||||
{
|
||||
return System.Console.BufferWidth;
|
||||
return ConsoleHelper.GetSafeBufferWidth(Constants.DefaultBufferWidth);
|
||||
}
|
||||
|
||||
return Constants.DefaultBufferWidth;
|
||||
@@ -37,7 +37,7 @@ namespace Spectre.Console.Internal
|
||||
{
|
||||
if (_out.IsStandardOut())
|
||||
{
|
||||
return System.Console.BufferHeight;
|
||||
return ConsoleHelper.GetSafeBufferHeight(Constants.DefaultBufferHeight);
|
||||
}
|
||||
|
||||
return Constants.DefaultBufferHeight;
|
||||
|
||||
43
src/Spectre.Console/Internal/Utilities/ConsoleHelper.cs
Normal file
43
src/Spectre.Console/Internal/Utilities/ConsoleHelper.cs
Normal file
@@ -0,0 +1,43 @@
|
||||
using System.IO;
|
||||
|
||||
namespace Spectre.Console.Internal
|
||||
{
|
||||
internal static class ConsoleHelper
|
||||
{
|
||||
public static int GetSafeBufferWidth(int defaultValue = Constants.DefaultBufferWidth)
|
||||
{
|
||||
try
|
||||
{
|
||||
var width = System.Console.BufferWidth;
|
||||
if (width == 0)
|
||||
{
|
||||
width = defaultValue;
|
||||
}
|
||||
|
||||
return width;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
public static int GetSafeBufferHeight(int defaultValue = Constants.DefaultBufferWidth)
|
||||
{
|
||||
try
|
||||
{
|
||||
var height = System.Console.BufferHeight;
|
||||
if (height == 0)
|
||||
{
|
||||
height = defaultValue;
|
||||
}
|
||||
|
||||
return height;
|
||||
}
|
||||
catch (IOException)
|
||||
{
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ namespace Spectre.Console
|
||||
/// <summary>
|
||||
/// A renderable piece of markup text.
|
||||
/// </summary>
|
||||
public sealed class Markup : Renderable, IAlignable
|
||||
public sealed class Markup : Renderable, IAlignable, IOverflowable
|
||||
{
|
||||
private readonly Paragraph _paragraph;
|
||||
|
||||
@@ -18,6 +18,13 @@ namespace Spectre.Console
|
||||
set => _paragraph.Alignment = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Overflow? Overflow
|
||||
{
|
||||
get => _paragraph.Overflow;
|
||||
set => _paragraph.Overflow = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Markup"/> class.
|
||||
/// </summary>
|
||||
|
||||
24
src/Spectre.Console/Rendering/Overflow.cs
Normal file
24
src/Spectre.Console/Rendering/Overflow.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents text overflow.
|
||||
/// </summary>
|
||||
public enum Overflow
|
||||
{
|
||||
/// <summary>
|
||||
/// Put any excess characters on the next line.
|
||||
/// </summary>
|
||||
Fold = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Truncates the text at the end of the line.
|
||||
/// </summary>
|
||||
Crop = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Truncates the text at the end of the line and
|
||||
/// also inserts an ellipsis character.
|
||||
/// </summary>
|
||||
Ellipsis = 2,
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
@@ -12,7 +12,7 @@ namespace Spectre.Console
|
||||
/// of the paragraph can have individual styling.
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{_text,nq}")]
|
||||
public sealed class Paragraph : Renderable, IAlignable
|
||||
public sealed class Paragraph : Renderable, IAlignable, IOverflowable
|
||||
{
|
||||
private readonly List<SegmentLine> _lines;
|
||||
|
||||
@@ -21,6 +21,11 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
public Justify? Alignment { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text overflow strategy.
|
||||
/// </summary>
|
||||
public Overflow? Overflow { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Paragraph"/> class.
|
||||
/// </summary>
|
||||
@@ -197,34 +202,76 @@ namespace Spectre.Console
|
||||
var line = new SegmentLine();
|
||||
|
||||
var newLine = true;
|
||||
using (var iterator = new SegmentLineIterator(_lines))
|
||||
|
||||
using var iterator = new SegmentLineIterator(_lines);
|
||||
var queue = new Queue<Segment>();
|
||||
while (true)
|
||||
{
|
||||
while (iterator.MoveNext())
|
||||
var current = (Segment?)null;
|
||||
if (queue.Count == 0)
|
||||
{
|
||||
var current = iterator.Current;
|
||||
if (current == null)
|
||||
if (!iterator.MoveNext())
|
||||
{
|
||||
throw new InvalidOperationException("Iterator returned empty segment.");
|
||||
break;
|
||||
}
|
||||
|
||||
if (newLine && current.IsWhiteSpace && !current.IsLineBreak)
|
||||
{
|
||||
newLine = false;
|
||||
continue;
|
||||
}
|
||||
current = iterator.Current;
|
||||
}
|
||||
else
|
||||
{
|
||||
current = queue.Dequeue();
|
||||
}
|
||||
|
||||
if (current == null)
|
||||
{
|
||||
throw new InvalidOperationException("Iterator returned empty segment.");
|
||||
}
|
||||
|
||||
if (newLine && current.IsWhiteSpace && !current.IsLineBreak)
|
||||
{
|
||||
newLine = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (current.IsLineBreak)
|
||||
newLine = false;
|
||||
|
||||
if (current.IsLineBreak)
|
||||
{
|
||||
line.Add(current);
|
||||
lines.Add(line);
|
||||
line = new SegmentLine();
|
||||
newLine = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
var length = current.CellLength(context.Encoding);
|
||||
if (length > maxWidth)
|
||||
{
|
||||
// The current segment is longer than the width of the console,
|
||||
// so we will need to crop it up, into new segments.
|
||||
var segments = Segment.SplitOverflow(current, Overflow, context.Encoding, maxWidth);
|
||||
if (segments.Count > 0)
|
||||
{
|
||||
line.Add(current);
|
||||
lines.Add(line);
|
||||
line = new SegmentLine();
|
||||
newLine = true;
|
||||
continue;
|
||||
}
|
||||
if (line.CellWidth(context.Encoding) + segments[0].CellLength(context.Encoding) > maxWidth)
|
||||
{
|
||||
lines.Add(line);
|
||||
line = new SegmentLine();
|
||||
newLine = true;
|
||||
|
||||
var length = current.CellLength(context.Encoding);
|
||||
segments.ForEach(s => queue.Enqueue(s));
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add the segment and push the rest of them to the queue.
|
||||
line.Add(segments[0]);
|
||||
segments.Skip(1).ForEach(s => queue.Enqueue(s));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (line.CellWidth(context.Encoding) + length > maxWidth)
|
||||
{
|
||||
line.Add(Segment.Empty);
|
||||
@@ -232,16 +279,16 @@ namespace Spectre.Console
|
||||
line = new SegmentLine();
|
||||
newLine = true;
|
||||
}
|
||||
|
||||
if (newLine && current.IsWhiteSpace)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
newLine = false;
|
||||
|
||||
line.Add(current);
|
||||
}
|
||||
|
||||
if (newLine && current.IsWhiteSpace)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
newLine = false;
|
||||
|
||||
line.Add(current);
|
||||
}
|
||||
|
||||
// Flush remaining.
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Spectre.Console.Rendering
|
||||
/// <summary>
|
||||
/// Gets the segment text.
|
||||
/// </summary>
|
||||
public string Text { get; }
|
||||
public string Text { get; internal set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether or not this is an expicit line break
|
||||
@@ -226,6 +226,92 @@ namespace Spectre.Console.Rendering
|
||||
return lines;
|
||||
}
|
||||
|
||||
internal static IEnumerable<Segment> Merge(IEnumerable<Segment> segments)
|
||||
{
|
||||
var result = new List<Segment>();
|
||||
|
||||
var previous = (Segment?)null;
|
||||
foreach (var segment in segments)
|
||||
{
|
||||
if (previous == null)
|
||||
{
|
||||
previous = segment;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Same style?
|
||||
if (previous.Style.Equals(segment.Style))
|
||||
{
|
||||
// Modify the content of the previous segment
|
||||
previous.Text += segment.Text;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Push the current one to the results.
|
||||
result.Add(previous);
|
||||
previous = segment;
|
||||
}
|
||||
}
|
||||
|
||||
if (previous != null)
|
||||
{
|
||||
result.Add(previous);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Splits an overflowing segment into several new segments.
|
||||
/// </summary>
|
||||
/// <param name="segment">The segment to split.</param>
|
||||
/// <param name="overflow">The overflow strategy to use.</param>
|
||||
/// <param name="encoding">The encodign to use.</param>
|
||||
/// <param name="width">The maxiumum width.</param>
|
||||
/// <returns>A list of segments that has been split.</returns>
|
||||
public static List<Segment> SplitOverflow(Segment segment, Overflow? overflow, Encoding encoding, int width)
|
||||
{
|
||||
if (segment is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(segment));
|
||||
}
|
||||
|
||||
if (segment.CellLength(encoding) <= width)
|
||||
{
|
||||
return new List<Segment>(1) { segment };
|
||||
}
|
||||
|
||||
// Default to folding
|
||||
overflow ??= Overflow.Fold;
|
||||
|
||||
var result = new List<Segment>();
|
||||
|
||||
if (overflow == Overflow.Fold)
|
||||
{
|
||||
var totalLength = segment.Text.CellLength(encoding);
|
||||
var lengthLeft = totalLength;
|
||||
while (lengthLeft > 0)
|
||||
{
|
||||
var index = totalLength - lengthLeft;
|
||||
var take = Math.Min(width, totalLength - index);
|
||||
|
||||
result.Add(new Segment(segment.Text.Substring(index, take), segment.Style));
|
||||
lengthLeft -= take;
|
||||
}
|
||||
}
|
||||
else if (overflow == Overflow.Crop)
|
||||
{
|
||||
result.Add(new Segment(segment.Text.Substring(0, width), segment.Style));
|
||||
}
|
||||
else if (overflow == Overflow.Ellipsis)
|
||||
{
|
||||
result.Add(new Segment(segment.Text.Substring(0, width - 1), segment.Style));
|
||||
result.Add(new Segment("…", segment.Style));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
internal static List<List<SegmentLine>> MakeSameHeight(int cellHeight, List<List<SegmentLine>> cells)
|
||||
{
|
||||
foreach (var cell in cells)
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Spectre.Console
|
||||
/// </summary>
|
||||
[DebuggerDisplay("{_text,nq}")]
|
||||
[SuppressMessage("Naming", "CA1724:Type names should not match namespaces")]
|
||||
public sealed class Text : Renderable, IAlignable
|
||||
public sealed class Text : Renderable, IAlignable, IOverflowable
|
||||
{
|
||||
private readonly Paragraph _paragraph;
|
||||
|
||||
@@ -38,6 +38,15 @@ namespace Spectre.Console
|
||||
set => _paragraph.Alignment = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the text overflow strategy.
|
||||
/// </summary>
|
||||
public Overflow? Overflow
|
||||
{
|
||||
get => _paragraph.Overflow;
|
||||
set => _paragraph.Overflow = value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Measurement Measure(RenderContext context, int maxWidth)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Contains extension methods for <see cref="IOverflowable"/>.
|
||||
/// </summary>
|
||||
public static class OverflowableExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Folds any overflowing text.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object implementing <see cref="IOverflowable"/>.</typeparam>
|
||||
/// <param name="obj">The overflowable object instance.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T Fold<T>(this T obj)
|
||||
where T : class, IOverflowable
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
return SetOverflow(obj, Overflow.Fold);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Crops any overflowing text.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object implementing <see cref="IOverflowable"/>.</typeparam>
|
||||
/// <param name="obj">The overflowable object instance.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T Crop<T>(this T obj)
|
||||
where T : class, IOverflowable
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
return SetOverflow(obj, Overflow.Crop);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Crops any overflowing text and adds an ellipsis to the end.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">An object implementing <see cref="IOverflowable"/>.</typeparam>
|
||||
/// <param name="obj">The overflowable object instance.</param>
|
||||
/// <returns>The same instance so that multiple calls can be chained.</returns>
|
||||
public static T Ellipsis<T>(this T obj)
|
||||
where T : class, IOverflowable
|
||||
{
|
||||
if (obj is null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
return SetOverflow(obj, Overflow.Ellipsis);
|
||||
}
|
||||
|
||||
/// <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>
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
13
src/Spectre.Console/Rendering/Traits/IOverflowable.cs
Normal file
13
src/Spectre.Console/Rendering/Traits/IOverflowable.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
namespace Spectre.Console
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents something that can overflow.
|
||||
/// </summary>
|
||||
public interface IOverflowable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the text overflow strategy.
|
||||
/// </summary>
|
||||
Overflow? Overflow { get; set; }
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user