rich-ruby 1.0.1 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +80 -0
- data/LICENSE +21 -21
- data/README.md +547 -547
- data/docs/architecture.md +43 -0
- data/docs/cheat-sheet.md +52 -0
- data/docs/customization.md +53 -0
- data/docs/how-to-use.md +96 -0
- data/docs/test-report.md +112 -0
- data/docs/troubleshooting.md +36 -0
- data/docs/windows-notes.md +30 -0
- data/examples/demo.rb +106 -106
- data/examples/showcase.rb +420 -420
- data/examples/smoke_test.rb +41 -41
- data/examples/stress_test.rb +604 -604
- data/examples/syntax_markdown_demo.rb +166 -166
- data/examples/verify.rb +216 -215
- data/examples/visual_demo.rb +145 -145
- data/lib/rich/_palettes.rb +148 -148
- data/lib/rich/box.rb +342 -342
- data/lib/rich/cells.rb +524 -512
- data/lib/rich/color.rb +631 -628
- data/lib/rich/color_triplet.rb +227 -220
- data/lib/rich/console.rb +604 -549
- data/lib/rich/control.rb +332 -332
- data/lib/rich/json.rb +260 -254
- data/lib/rich/layout.rb +314 -314
- data/lib/rich/markdown.rb +531 -509
- data/lib/rich/markup.rb +186 -175
- data/lib/rich/panel.rb +318 -311
- data/lib/rich/progress.rb +430 -430
- data/lib/rich/segment.rb +387 -387
- data/lib/rich/style.rb +464 -433
- data/lib/rich/syntax.rb +1220 -1145
- data/lib/rich/table.rb +547 -525
- data/lib/rich/terminal_theme.rb +126 -126
- data/lib/rich/text.rb +460 -433
- data/lib/rich/tree.rb +220 -220
- data/lib/rich/version.rb +5 -5
- data/lib/rich/win32_console.rb +620 -582
- data/lib/rich.rb +108 -108
- metadata +15 -5
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Architecture & Data Flow
|
|
2
|
+
|
|
3
|
+
This document explains how Rich Ruby processes text and components to generate terminal output.
|
|
4
|
+
|
|
5
|
+
## 1. High-Level Concept
|
|
6
|
+
|
|
7
|
+
Rich Ruby follows a pipeline:
|
|
8
|
+
**Input (Markup/Object) -> Text/Segments -> Console Options -> ANSI String -> Terminal**
|
|
9
|
+
|
|
10
|
+
## 2. Core Entities
|
|
11
|
+
|
|
12
|
+
### `Rich::Console`
|
|
13
|
+
The "brain" of the library. It holds state about the terminal's width, height, and color capabilities. It acts as the orchestrator for all rendering.
|
|
14
|
+
|
|
15
|
+
### `Rich::Text`
|
|
16
|
+
A representation of text that includes "Spans" (range of characters + a Style). This is an intermediate format before splitting into segments.
|
|
17
|
+
|
|
18
|
+
### `Rich::Segment`
|
|
19
|
+
The lowest-level rendering unit. A segment is a simple string paired with a `Rich::Style`.
|
|
20
|
+
- When you render any component (Table, Panel, etc.), it ultimately breaks down into a list of `Segments`.
|
|
21
|
+
- Segments are responsible for generating the final ANSI escape codes via `Segment.render`.
|
|
22
|
+
|
|
23
|
+
### `Rich::Style`
|
|
24
|
+
Encapsulates foreground color, background color, and attributes (bold, etc.). Styles are **immutable**. Combining styles (`style1 + style2`) creates a new style object.
|
|
25
|
+
|
|
26
|
+
## 3. The Rendering Pipeline
|
|
27
|
+
|
|
28
|
+
1. **Measurement**: Components (like `Table`) calculate the required width of each cell using `Rich::Cells.cell_len`.
|
|
29
|
+
2. **Layout**: Wrapping and alignment logic is applied to fit the `max_width`.
|
|
30
|
+
3. **Segmentation**: The component converts its visual structure into `Rich::Segment` objects.
|
|
31
|
+
4. **ANSI Generation**: The `Console` takes the segments and joins them into a single string containing escape sequences.
|
|
32
|
+
5. **Output**: The string is written to `$stdout` (or the configured output stream).
|
|
33
|
+
|
|
34
|
+
## 4. Windows Integration Logic
|
|
35
|
+
|
|
36
|
+
In `lib/rich/win32_console.rb`, we use `Fiddle` to interface with `kernel32.dll`:
|
|
37
|
+
|
|
38
|
+
- **VT Processing**: We call `GetConsoleMode` and `SetConsoleMode` to enable ANSI support.
|
|
39
|
+
- **Size Detection**: We call `GetConsoleScreenBufferInfo` to get accurate dimensions without relying on environment variables.
|
|
40
|
+
|
|
41
|
+
## 5. Extensibility
|
|
42
|
+
|
|
43
|
+
Developers can create new components by implementing a `render` (or `to_segments`) method that returns a collection of `Rich::Segment` objects. This ensures that any new component automatically inherits font-width calculation and color-downgrade support.
|
data/docs/cheat-sheet.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Rich Ruby Cheat Sheet
|
|
2
|
+
|
|
3
|
+
A quick visual reference for markup, styles, and colors.
|
|
4
|
+
|
|
5
|
+
## 1. Markup Tags
|
|
6
|
+
Commonly used tags in `[tag]content[/tag]` syntax.
|
|
7
|
+
|
|
8
|
+
| Tag | Result |
|
|
9
|
+
|-----|--------|
|
|
10
|
+
| `[bold]` | **Bold Text** |
|
|
11
|
+
| `[dim]` | Dimmed Text |
|
|
12
|
+
| `[italic]` | *Italic Text* |
|
|
13
|
+
| `[u]` or `[underline]` | <u>Underline</u> |
|
|
14
|
+
| `[strike]` | ~~Strikethrough~~ |
|
|
15
|
+
| `[reverse]` | Inverse Background/Foreground |
|
|
16
|
+
| `[red]` | Red Foreground |
|
|
17
|
+
| `[on blue]` | Blue Background |
|
|
18
|
+
| `[#ff5500]` | Hex Color |
|
|
19
|
+
|
|
20
|
+
## 2. Color Keywords
|
|
21
|
+
Standard 16-color names supported by almost all terminals.
|
|
22
|
+
|
|
23
|
+
- `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`
|
|
24
|
+
- `bright_black`, `bright_red`, `bright_green`, etc.
|
|
25
|
+
|
|
26
|
+
## 3. Component Comparison
|
|
27
|
+
|
|
28
|
+
| Component | best for... |
|
|
29
|
+
|-----------|-------------|
|
|
30
|
+
| **Panel** | Single focus messages, headers, or boxed content. |
|
|
31
|
+
| **Table** | Columns of data, spreadsheets, or grid layouts. |
|
|
32
|
+
| **Tree** | File systems, dependency graphs, or nested lists. |
|
|
33
|
+
| **Syntax** | Code snippets in logs or documentation. |
|
|
34
|
+
| **JSON** | Debugging API responses or config files. |
|
|
35
|
+
| **Markdown**| Rendering READMEs or rich terminal helps. |
|
|
36
|
+
|
|
37
|
+
## 4. Quick API Snippets
|
|
38
|
+
|
|
39
|
+
### Print with Style
|
|
40
|
+
```ruby
|
|
41
|
+
Rich.print("[yellow]Wait...[/] [bold green]Success![/]")
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### Create a Rule (Divider)
|
|
45
|
+
```ruby
|
|
46
|
+
Rich.rule("Chapter 1", style: "cyan")
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Inspect a Ruby Object
|
|
50
|
+
```ruby
|
|
51
|
+
puts Rich::Pretty.to_s(some_hash)
|
|
52
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Customization & Extensibility
|
|
2
|
+
|
|
3
|
+
Rich Ruby is designed to be modular. You can extend it by creating your own box styles, syntax lexers, and themes.
|
|
4
|
+
|
|
5
|
+
## 1. Custom Box Styles
|
|
6
|
+
You can create a custom `Box` by instantiating the class with a set of characters.
|
|
7
|
+
|
|
8
|
+
```ruby
|
|
9
|
+
MY_BOX = Rich::Box.new(
|
|
10
|
+
top_left: "┏", top_right: "┓",
|
|
11
|
+
bottom_left: "┗", bottom_right: "┛",
|
|
12
|
+
horizontal: "━", vertical: "┃",
|
|
13
|
+
cross: "╋"
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
panel = Rich::Panel.new("Custom Border", box: MY_BOX)
|
|
17
|
+
puts panel.render
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 2. Advanced Syntax Themes
|
|
21
|
+
Themes are simply Hashes mapping token types to `Rich::Style` objects.
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
MY_THEME = {
|
|
25
|
+
keyword: Rich::Style.new(color: "red", bold: true),
|
|
26
|
+
string: Rich::Style.new(color: "green"),
|
|
27
|
+
comment: Rich::Style.new(color: "yellow", dim: true),
|
|
28
|
+
text: Rich::Style.new(color: "default")
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
syntax = Rich::Syntax.new(code, language: "ruby", theme: MY_THEME)
|
|
32
|
+
puts syntax.render
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## 3. Adding a New Lexer
|
|
36
|
+
To add support for a new language, create a class inheriting from `Rich::BaseLexer` and register it in `Rich::Syntax::LEXERS`.
|
|
37
|
+
|
|
38
|
+
```ruby
|
|
39
|
+
class MyLanguageLexer < Rich::BaseLexer
|
|
40
|
+
def tokenize(line, theme)
|
|
41
|
+
# Return an array of Rich::Segment objects
|
|
42
|
+
[Rich::Segment.new(line, style: theme[:text])]
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Register it
|
|
47
|
+
Rich::Syntax::LEXERS["mylang"] = MyLanguageLexer.new
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## 4. Custom Markup Tags
|
|
51
|
+
The `Rich::Markup` parser utilizes the `Rich::Style` parsing engine. If you want to create a shorthand tag, you can add it to the `Style` registry if implemented, or simply use combined strings.
|
|
52
|
+
|
|
53
|
+
Note: Rich Ruby aims to keep the core small. For complex custom components, we recommend composing existing `Panel`, `Table`, and `Text` objects.
|
data/docs/how-to-use.md
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
# How-To Use Rich Ruby
|
|
2
|
+
|
|
3
|
+
This guide provides quick examples and tips for using Rich Ruby effectively, categorized by user level.
|
|
4
|
+
|
|
5
|
+
## 1. Beginner: Quick Start & Basic Styling
|
|
6
|
+
|
|
7
|
+
If you're new to Rich Ruby, the easiest way to start is using the `Rich.print` method and [Markup](README.md#text-and-markup).
|
|
8
|
+
|
|
9
|
+
### Styled Hello World
|
|
10
|
+
```ruby
|
|
11
|
+
require 'rich'
|
|
12
|
+
|
|
13
|
+
Rich.print("[bold red]ERROR:[/] Something went wrong!")
|
|
14
|
+
Rich.print("[green]SUCCESS:[/] Operation completed.")
|
|
15
|
+
Rich.print("[blue italic]INFO:[/] Processing data...")
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### Simple Rules (Dividers)
|
|
19
|
+
Use rules to organize your terminal output.
|
|
20
|
+
```ruby
|
|
21
|
+
Rich.rule("Section 1")
|
|
22
|
+
puts "Content goes here"
|
|
23
|
+
Rich.rule(style: "dim")
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## 2. Intermediate: Components & Layout
|
|
29
|
+
|
|
30
|
+
Once you're comfortable with basic printing, start using structured components like **Panels** and **Tables**.
|
|
31
|
+
|
|
32
|
+
### Grouping with Panels
|
|
33
|
+
Panels are great for highlights or error messages.
|
|
34
|
+
```ruby
|
|
35
|
+
panel = Rich::Panel.new(
|
|
36
|
+
"Data backup complete.\nVerified 1,024 files.",
|
|
37
|
+
title: "Backup Status",
|
|
38
|
+
border_style: "cyan"
|
|
39
|
+
)
|
|
40
|
+
puts panel.render(max_width: 40)
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### Organizing with Tables
|
|
44
|
+
Tables automatically calculate column widths.
|
|
45
|
+
```ruby
|
|
46
|
+
table = Rich::Table.new(title: "Inventory")
|
|
47
|
+
table.add_column("Item", header_style: "bold")
|
|
48
|
+
table.add_column("Stock", justify: :right)
|
|
49
|
+
|
|
50
|
+
table.add_row("Apples", "50")
|
|
51
|
+
table.add_row("Oranges", "12")
|
|
52
|
+
puts table.render(max_width: 30)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## 3. Advanced: Dynamic Content & Technical Control
|
|
58
|
+
|
|
59
|
+
For power users building complex CLI tools.
|
|
60
|
+
|
|
61
|
+
### Live Progress Bars
|
|
62
|
+
```ruby
|
|
63
|
+
bar = Rich::ProgressBar.new(total: 100)
|
|
64
|
+
100.times do |i|
|
|
65
|
+
bar.update(i + 1)
|
|
66
|
+
print "\r#{bar.render}"
|
|
67
|
+
sleep 0.01
|
|
68
|
+
end
|
|
69
|
+
puts "" # New line after completion
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Code Highlighting
|
|
73
|
+
Perfect for dev tools or logging code snippets.
|
|
74
|
+
```ruby
|
|
75
|
+
code = "def hello; puts 'world'; end"
|
|
76
|
+
syntax = Rich::Syntax.new(code, language: "ruby", theme: :monokai)
|
|
77
|
+
puts syntax.render
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Technical Transparency & Limitations
|
|
81
|
+
- **Pure Ruby**: The entire library is implemented in Pure Ruby (with `Fiddle` for Windows API). This ensures portability but means performance may degrade with exceptionally large datasets (e.g., tables with 10,000+ rows).
|
|
82
|
+
- **Windows Integration**: On Windows, we directly interface with `kernel32.dll` to enable Virtual Terminal processing. This is robust but depends on modern Windows 10/11 features for the best experience.
|
|
83
|
+
- **Color Systems**: While we support TrueColor, the actual appearance depends on your terminal emulator's capabilities.
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Guide for Quick Reference
|
|
88
|
+
|
|
89
|
+
| Task | Tool to Use |
|
|
90
|
+
|------|-------------|
|
|
91
|
+
| Quick logging | `Rich.print` |
|
|
92
|
+
| Boxing content | `Rich::Panel` |
|
|
93
|
+
| List data | `Rich::Table` |
|
|
94
|
+
| File trees | `Rich::Tree` |
|
|
95
|
+
| Source code | `Rich::Syntax` |
|
|
96
|
+
| Formatted docs | `Rich::Markdown` |
|
data/docs/test-report.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Rich Ruby: Test Report
|
|
2
|
+
|
|
3
|
+
This document showcases the results of the final test verification for the Rich Ruby library.
|
|
4
|
+
|
|
5
|
+
## Environment
|
|
6
|
+
- **Ruby**: 3.4.8 (MSVC)
|
|
7
|
+
- **Platform**: Windows 10 (64-bit)
|
|
8
|
+
- **Date**: December 23, 2025
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## 1. Functional Test Suite
|
|
13
|
+
The functional test suite covers core components: Color, Style, Text, Markup, Console, Box, Table, Trees, Progress, Syntax, Markdown, and JSON.
|
|
14
|
+
|
|
15
|
+
**Command:**
|
|
16
|
+
```bash
|
|
17
|
+
ruby -W0 -Ilib -Itest -e "require './test/test_helper'; Dir['test/test_*.rb'].each { |f| require File.expand_path(f) }"
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
**Results:**
|
|
21
|
+
```text
|
|
22
|
+
Run options: --seed 29775
|
|
23
|
+
|
|
24
|
+
# Running:
|
|
25
|
+
|
|
26
|
+
.......................................................................................
|
|
27
|
+
───────────────────────────────── Title ───────────────────────────────────────────────
|
|
28
|
+
...Hello
|
|
29
|
+
..................................................................................................
|
|
30
|
+
|
|
31
|
+
Finished in 0.041029s, 4582.0690 runs/s, 8432.9568 assertions/s.
|
|
32
|
+
|
|
33
|
+
188 runs, 346 assertions, 0 failures, 0 errors, 0 skips
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 2. Performance & Stress Test Suite
|
|
39
|
+
The stress test suite validates the library under heavy load and deep nesting conditions.
|
|
40
|
+
|
|
41
|
+
**Command:**
|
|
42
|
+
```bash
|
|
43
|
+
ruby -W0 -Ilib examples/stress_test.rb
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Results:**
|
|
47
|
+
```text
|
|
48
|
+
======================================================================
|
|
49
|
+
Rich Library Stress Test Suite
|
|
50
|
+
======================================================================
|
|
51
|
+
|
|
52
|
+
Parse all 256 ANSI color names ... ✓ PASS (0.000s)
|
|
53
|
+
Parse 10,000 random hex colors ... ✓ PASS (0.042s)
|
|
54
|
+
Color downgrade from truecolor to 256 ... ✓ PASS (0.004s)
|
|
55
|
+
Color downgrade from truecolor to 16 ... ✓ PASS (0.014s)
|
|
56
|
+
ColorTriplet HSL roundtrip ... ✓ PASS (0.000s)
|
|
57
|
+
Color parse caching performance ... ✓ PASS (0.125s)
|
|
58
|
+
Parse complex style definitions ... ✓ PASS (0.000s)
|
|
59
|
+
Style combination chain (1000 styles) ... ✓ PASS (0.008s)
|
|
60
|
+
Style attribute bitmask integrity ... ✓ PASS (0.000s)
|
|
61
|
+
Style render with all attributes ... ✓ PASS (0.000s)
|
|
62
|
+
CJK character width calculation ... ✓ PASS (0.001s)
|
|
63
|
+
Zero-width combining characters ... ✓ PASS (0.000s)
|
|
64
|
+
Mixed ASCII and Unicode ... ✓ PASS (0.001s)
|
|
65
|
+
Large Unicode string (10KB) ... ✓ PASS (0.315s)
|
|
66
|
+
Empty and whitespace strings ... ✓ PASS (0.000s)
|
|
67
|
+
Segment split at every position ... ✓ PASS (0.002s)
|
|
68
|
+
Segment line splitting with many newlines ... ✓ PASS (0.000s)
|
|
69
|
+
Segment simplification (1000 segments) ... ✓ PASS (0.001s)
|
|
70
|
+
Segment rendering with control codes ... ✓ PASS (0.000s)
|
|
71
|
+
Text with 1000 overlapping spans ... ✓ PASS (0.053s)
|
|
72
|
+
Deeply nested markup ... ✓ PASS (0.000s)
|
|
73
|
+
Markup validation with errors ... ✓ PASS (0.000s)
|
|
74
|
+
Text wrapping at various widths ... ✓ PASS (0.120s)
|
|
75
|
+
Text with special characters ... ✓ PASS (0.000s)
|
|
76
|
+
Panel with very long content ... ✓ PASS (0.061s)
|
|
77
|
+
Panel with Unicode borders and content ... ✓ PASS (0.001s)
|
|
78
|
+
Table with 100 rows ... ✓ PASS (0.088s)
|
|
79
|
+
Table with Unicode content ... ✓ PASS (0.003s)
|
|
80
|
+
Tree with deep nesting (10 levels) ... ✓ PASS (0.000s)
|
|
81
|
+
Tree with many siblings (100) ... ✓ PASS (0.000s)
|
|
82
|
+
All box styles render correctly ... ✓ PASS (0.002s)
|
|
83
|
+
Progress bar at every percentage ... ✓ PASS (0.000s)
|
|
84
|
+
Progress bar with very large total ... ✓ PASS (0.000s)
|
|
85
|
+
Spinner cycles through all frames ... ✓ PASS (0.004s)
|
|
86
|
+
Multiple spinner styles ... ✓ PASS (0.000s)
|
|
87
|
+
JSON with deeply nested structure ... ✓ PASS (0.002s)
|
|
88
|
+
JSON with large array ... ✓ PASS (0.017s)
|
|
89
|
+
JSON with special characters ... ✓ PASS (0.000s)
|
|
90
|
+
Pretty print complex Ruby object ... ✓ PASS (0.001s)
|
|
91
|
+
Console size detection ... ✓ PASS (0.000s)
|
|
92
|
+
Console options update ... ✓ PASS (0.000s)
|
|
93
|
+
Control codes generate valid ANSI ... ✓ PASS (0.000s)
|
|
94
|
+
ANSI stripping ... ✓ PASS (0.000s)
|
|
95
|
+
Windows Console API functions available ... ✓ PASS (0.000s)
|
|
96
|
+
Windows ANSI support detection ... ✓ PASS (0.000s)
|
|
97
|
+
Windows console size valid ... ✓ PASS (0.000s)
|
|
98
|
+
Empty inputs handled gracefully ... ✓ PASS (0.000s)
|
|
99
|
+
Nil inputs handled gracefully ... ✓ PASS (0.000s)
|
|
100
|
+
Very long single-line content ... ✓ PASS (0.000s)
|
|
101
|
+
Content at exact width boundary ... ✓ PASS (0.002s)
|
|
102
|
+
Zero and negative values ... ✓ PASS (0.000s)
|
|
103
|
+
|
|
104
|
+
======================================================================
|
|
105
|
+
Results: 51/51 tests passed in 0.87s
|
|
106
|
+
======================================================================
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
---
|
|
110
|
+
|
|
111
|
+
## 3. Transparency & Stability
|
|
112
|
+
The recent repairs to the `Syntax` lexers specifically addressed infinite loop scenarios, ensuring that even large or malformed code blocks are processed efficiently. The library remains a zero-dependency, pure Ruby implementation optimized for the modern terminal.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Troubleshooting & FAQ
|
|
2
|
+
|
|
3
|
+
Common issues and solutions when working with Rich Ruby.
|
|
4
|
+
|
|
5
|
+
## 1. Character Encoding & Unicode
|
|
6
|
+
**Problem**: CJK characters (Chinese, Japanese, Korean) or emojis appear as blocks or distorted.
|
|
7
|
+
**Solution**:
|
|
8
|
+
- Ensure your terminal emulator has a font that supports these characters (e.g., Cascadia Code, JetBrains Mono, or a Nerd Font).
|
|
9
|
+
- On Windows, ensure your shell environment is set to UTF-8. In PowerShell/CMD, run: `chcp 65001`.
|
|
10
|
+
- Rich Ruby uses `Rich::Cells` to calculate width, but if the terminal font doesn't match the expected Unicode width, the layout might look slightly off.
|
|
11
|
+
|
|
12
|
+
## 2. Colors Not Appearing
|
|
13
|
+
**Problem**: Output is plain text with no color.
|
|
14
|
+
**Solution**:
|
|
15
|
+
- Check if your terminal supports ANSI colors.
|
|
16
|
+
- If you are piping output (e.g., `ruby script.rb > log.txt`), Rich Ruby automatically disables color. Use `Rich::Console.new(force_terminal: true)` to override this.
|
|
17
|
+
- If on Windows, Rich Ruby attempts to enable VT Processing. If it fails (e.g., very old Win 10), it will downgrade to basic 16-color mode via Console API.
|
|
18
|
+
|
|
19
|
+
## 3. The `io-nonblock` Warning
|
|
20
|
+
**Problem**: `Ignoring io-nonblock-0.3.2 because its extensions are not built.`
|
|
21
|
+
**Solution**:
|
|
22
|
+
- This is a Ruby environment issue, not a Rich Ruby bug. Rich Ruby has **zero dependencies**.
|
|
23
|
+
- You can ignore it, or run your scripts with `ruby -W0` to silence it.
|
|
24
|
+
|
|
25
|
+
## 4. Performance in Large Loops
|
|
26
|
+
**Problem**: The script feels slow when printing thousands of lines.
|
|
27
|
+
**Solution**:
|
|
28
|
+
- Standard terminal I/O is slow. Try batching your output or using the `Rich::Live` display (if available in your version) to update only changed lines.
|
|
29
|
+
- Avoid re-creating `Rich::Console` instances inside tight loops; use the global `Rich.get_console` instead.
|
|
30
|
+
|
|
31
|
+
## 5. Dark Mode vs. Light Mode
|
|
32
|
+
**Problem**: Text is invisible because it's too bright/dark for the background.
|
|
33
|
+
**Solution**:
|
|
34
|
+
- Avoid using hardcoded colors like `white` or `black` for main content.
|
|
35
|
+
- Use `default` color or theme-aware colors.
|
|
36
|
+
- Rich Ruby doesn't currently detect the terminal's background color (as many terminals don't support the query), so providing high-contrast themes like `:monokai` or `:dracula` is the best practice for user accessibility.
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Windows Support & Environmental Notes
|
|
2
|
+
|
|
3
|
+
Rich Ruby is designed to be a first-class citizen on Windows.
|
|
4
|
+
|
|
5
|
+
## Windows Native Integration
|
|
6
|
+
|
|
7
|
+
We use Ruby's `Fiddle` to call Windows API functions directly. This avoids dependencies on external gems like `curses` or `win32-console`.
|
|
8
|
+
|
|
9
|
+
### Virtual Terminal Processing
|
|
10
|
+
When you initialize a `Rich::Console`, it attempts to enable `ENABLE_VIRTUAL_TERMINAL_PROCESSING` (0x0004) via `SetConsoleMode`. This allows the Windows Command Prompt and PowerShell to understand ANSI escape codes natively.
|
|
11
|
+
|
|
12
|
+
### Fallback Behavior
|
|
13
|
+
On older systems (legacy console), the library detects the lack of VT support and simplifies output to basic 16 colors using the Windows Console API where possible, or strips formatting to ensure readability.
|
|
14
|
+
|
|
15
|
+
## Known Environmental Artifacts
|
|
16
|
+
|
|
17
|
+
### `io-nonblock` Warning
|
|
18
|
+
You may see the following warning in your terminal:
|
|
19
|
+
`Ignoring io-nonblock-0.3.2 because its extensions are not built.`
|
|
20
|
+
|
|
21
|
+
**Transparency Note:**
|
|
22
|
+
This warning is related to the local Ruby environment's gem installation and is **not caused by Rich Ruby**. Rich Ruby has **zero external gem dependencies** and does not require `io-nonblock` for its core functionality.
|
|
23
|
+
|
|
24
|
+
To run tests without seeing this warning, use the `-W0` flag:
|
|
25
|
+
```bash
|
|
26
|
+
ruby -W0 -Ilib -Itest test/test_console.rb
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## MSVC Compatibility
|
|
30
|
+
Rich Ruby is developed and tested on **Ruby 3.4.8 (MSVC)** compiled with Visual Studio 2026. It is fully compatible with MSVC-built Ruby runtimes.
|
data/examples/demo.rb
CHANGED
|
@@ -1,106 +1,106 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
# Comprehensive demo of Rich library features
|
|
4
|
-
|
|
5
|
-
require_relative "../lib/rich"
|
|
6
|
-
|
|
7
|
-
console = Rich::Console.new
|
|
8
|
-
|
|
9
|
-
# Title
|
|
10
|
-
console.rule("Rich Library Demo", style: "bold magenta")
|
|
11
|
-
puts ""
|
|
12
|
-
|
|
13
|
-
# 1. Colors and Styles
|
|
14
|
-
puts "1. Colors and Styles"
|
|
15
|
-
puts "=" * 40
|
|
16
|
-
console.print("Normal text")
|
|
17
|
-
console.print("Bold text", style: "bold")
|
|
18
|
-
console.print("Italic text", style: "italic")
|
|
19
|
-
console.print("Underlined text", style: "underline")
|
|
20
|
-
console.print("Red text", style: "red")
|
|
21
|
-
console.print("Green on yellow", style: "green on yellow")
|
|
22
|
-
console.print("Bold blue italic", style: "bold blue italic")
|
|
23
|
-
puts ""
|
|
24
|
-
|
|
25
|
-
# 2. Text with Spans
|
|
26
|
-
puts "2. Text with Style Spans"
|
|
27
|
-
puts "=" * 40
|
|
28
|
-
text = Rich::Text.new("Hello ")
|
|
29
|
-
text.append("World", style: "bold red")
|
|
30
|
-
text.append("! This is ")
|
|
31
|
-
text.append("Rich", style: "italic magenta")
|
|
32
|
-
text.append(" for Ruby.")
|
|
33
|
-
puts text.render + "\n"
|
|
34
|
-
|
|
35
|
-
# 3. Markup
|
|
36
|
-
puts "3. Markup Parsing"
|
|
37
|
-
puts "=" * 40
|
|
38
|
-
markup = Rich::Markup.render("[bold]Bold[/bold] and [italic red]italic red[/italic red] text")
|
|
39
|
-
puts markup + "\n"
|
|
40
|
-
|
|
41
|
-
# 4. Panel
|
|
42
|
-
puts "4. Panel Component"
|
|
43
|
-
puts "=" * 40
|
|
44
|
-
panel = Rich::Panel.new(
|
|
45
|
-
"This is content inside a panel.\nIt can have multiple lines.",
|
|
46
|
-
title: "My Panel",
|
|
47
|
-
subtitle: "Subtitle here",
|
|
48
|
-
border_style: "cyan",
|
|
49
|
-
title_style: "bold white"
|
|
50
|
-
)
|
|
51
|
-
puts panel.render(max_width: 50)
|
|
52
|
-
puts ""
|
|
53
|
-
|
|
54
|
-
# 5. Table
|
|
55
|
-
puts "5. Table Component"
|
|
56
|
-
puts "=" * 40
|
|
57
|
-
table = Rich::Table.new(
|
|
58
|
-
title: "User Data",
|
|
59
|
-
show_header: true,
|
|
60
|
-
border_style: "blue"
|
|
61
|
-
)
|
|
62
|
-
table.add_column("Name", header_style: "bold")
|
|
63
|
-
table.add_column("Age", justify: :right)
|
|
64
|
-
table.add_column("City", header_style: "bold green")
|
|
65
|
-
|
|
66
|
-
table.add_row("Alice", "30", "New York")
|
|
67
|
-
table.add_row("Bob", "25", "San Francisco")
|
|
68
|
-
table.add_row("Charlie", "35", "London")
|
|
69
|
-
table.add_row("Diana", "28", "Tokyo")
|
|
70
|
-
|
|
71
|
-
puts table.render(max_width: 60)
|
|
72
|
-
puts ""
|
|
73
|
-
|
|
74
|
-
# 6. Box Styles
|
|
75
|
-
puts "6. Different Box Styles"
|
|
76
|
-
puts "=" * 40
|
|
77
|
-
|
|
78
|
-
[Rich::Box::ASCII, Rich::Box::SQUARE, Rich::Box::ROUNDED, Rich::Box::HEAVY, Rich::Box::DOUBLE].each do |box_style|
|
|
79
|
-
small_panel = Rich::Panel.new(
|
|
80
|
-
"Content",
|
|
81
|
-
title: box_style.class == Class ? box_style.name : "Box",
|
|
82
|
-
box: box_style,
|
|
83
|
-
expand: false,
|
|
84
|
-
padding: 0
|
|
85
|
-
)
|
|
86
|
-
puts small_panel.render(max_width: 30)
|
|
87
|
-
end
|
|
88
|
-
puts ""
|
|
89
|
-
|
|
90
|
-
# 7. Color System Info
|
|
91
|
-
puts "7. System Information"
|
|
92
|
-
puts "=" * 40
|
|
93
|
-
info_table = Rich::Table.new(show_header: false, box: Rich::Box::SIMPLE)
|
|
94
|
-
info_table.add_column("Property", style: "cyan")
|
|
95
|
-
info_table.add_column("Value", style: "yellow")
|
|
96
|
-
info_table.add_row("Color System", console.color_system.to_s)
|
|
97
|
-
info_table.add_row("Terminal", console.terminal? ? "Yes" : "No")
|
|
98
|
-
info_table.add_row("Width", console.width.to_s)
|
|
99
|
-
info_table.add_row("Height", console.height.to_s)
|
|
100
|
-
info_table.add_row("Ruby Version", RUBY_VERSION)
|
|
101
|
-
info_table.add_row("Platform", RUBY_PLATFORM)
|
|
102
|
-
|
|
103
|
-
puts info_table.render(max_width: 50)
|
|
104
|
-
puts ""
|
|
105
|
-
|
|
106
|
-
console.rule("Demo Complete!", style: "bold green")
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Comprehensive demo of Rich library features
|
|
4
|
+
|
|
5
|
+
require_relative "../lib/rich"
|
|
6
|
+
|
|
7
|
+
console = Rich::Console.new
|
|
8
|
+
|
|
9
|
+
# Title
|
|
10
|
+
console.rule("Rich Library Demo", style: "bold magenta")
|
|
11
|
+
puts ""
|
|
12
|
+
|
|
13
|
+
# 1. Colors and Styles
|
|
14
|
+
puts "1. Colors and Styles"
|
|
15
|
+
puts "=" * 40
|
|
16
|
+
console.print("Normal text")
|
|
17
|
+
console.print("Bold text", style: "bold")
|
|
18
|
+
console.print("Italic text", style: "italic")
|
|
19
|
+
console.print("Underlined text", style: "underline")
|
|
20
|
+
console.print("Red text", style: "red")
|
|
21
|
+
console.print("Green on yellow", style: "green on yellow")
|
|
22
|
+
console.print("Bold blue italic", style: "bold blue italic")
|
|
23
|
+
puts ""
|
|
24
|
+
|
|
25
|
+
# 2. Text with Spans
|
|
26
|
+
puts "2. Text with Style Spans"
|
|
27
|
+
puts "=" * 40
|
|
28
|
+
text = Rich::Text.new("Hello ")
|
|
29
|
+
text.append("World", style: "bold red")
|
|
30
|
+
text.append("! This is ")
|
|
31
|
+
text.append("Rich", style: "italic magenta")
|
|
32
|
+
text.append(" for Ruby.")
|
|
33
|
+
puts text.render + "\n"
|
|
34
|
+
|
|
35
|
+
# 3. Markup
|
|
36
|
+
puts "3. Markup Parsing"
|
|
37
|
+
puts "=" * 40
|
|
38
|
+
markup = Rich::Markup.render("[bold]Bold[/bold] and [italic red]italic red[/italic red] text")
|
|
39
|
+
puts markup + "\n"
|
|
40
|
+
|
|
41
|
+
# 4. Panel
|
|
42
|
+
puts "4. Panel Component"
|
|
43
|
+
puts "=" * 40
|
|
44
|
+
panel = Rich::Panel.new(
|
|
45
|
+
"This is content inside a panel.\nIt can have multiple lines.",
|
|
46
|
+
title: "My Panel",
|
|
47
|
+
subtitle: "Subtitle here",
|
|
48
|
+
border_style: "cyan",
|
|
49
|
+
title_style: "bold white"
|
|
50
|
+
)
|
|
51
|
+
puts panel.render(max_width: 50)
|
|
52
|
+
puts ""
|
|
53
|
+
|
|
54
|
+
# 5. Table
|
|
55
|
+
puts "5. Table Component"
|
|
56
|
+
puts "=" * 40
|
|
57
|
+
table = Rich::Table.new(
|
|
58
|
+
title: "User Data",
|
|
59
|
+
show_header: true,
|
|
60
|
+
border_style: "blue"
|
|
61
|
+
)
|
|
62
|
+
table.add_column("Name", header_style: "bold")
|
|
63
|
+
table.add_column("Age", justify: :right)
|
|
64
|
+
table.add_column("City", header_style: "bold green")
|
|
65
|
+
|
|
66
|
+
table.add_row("Alice", "30", "New York")
|
|
67
|
+
table.add_row("Bob", "25", "San Francisco")
|
|
68
|
+
table.add_row("Charlie", "35", "London")
|
|
69
|
+
table.add_row("Diana", "28", "Tokyo")
|
|
70
|
+
|
|
71
|
+
puts table.render(max_width: 60)
|
|
72
|
+
puts ""
|
|
73
|
+
|
|
74
|
+
# 6. Box Styles
|
|
75
|
+
puts "6. Different Box Styles"
|
|
76
|
+
puts "=" * 40
|
|
77
|
+
|
|
78
|
+
[Rich::Box::ASCII, Rich::Box::SQUARE, Rich::Box::ROUNDED, Rich::Box::HEAVY, Rich::Box::DOUBLE].each do |box_style|
|
|
79
|
+
small_panel = Rich::Panel.new(
|
|
80
|
+
"Content",
|
|
81
|
+
title: box_style.class == Class ? box_style.name : "Box",
|
|
82
|
+
box: box_style,
|
|
83
|
+
expand: false,
|
|
84
|
+
padding: 0
|
|
85
|
+
)
|
|
86
|
+
puts small_panel.render(max_width: 30)
|
|
87
|
+
end
|
|
88
|
+
puts ""
|
|
89
|
+
|
|
90
|
+
# 7. Color System Info
|
|
91
|
+
puts "7. System Information"
|
|
92
|
+
puts "=" * 40
|
|
93
|
+
info_table = Rich::Table.new(show_header: false, box: Rich::Box::SIMPLE)
|
|
94
|
+
info_table.add_column("Property", style: "cyan")
|
|
95
|
+
info_table.add_column("Value", style: "yellow")
|
|
96
|
+
info_table.add_row("Color System", console.color_system.to_s)
|
|
97
|
+
info_table.add_row("Terminal", console.terminal? ? "Yes" : "No")
|
|
98
|
+
info_table.add_row("Width", console.width.to_s)
|
|
99
|
+
info_table.add_row("Height", console.height.to_s)
|
|
100
|
+
info_table.add_row("Ruby Version", RUBY_VERSION)
|
|
101
|
+
info_table.add_row("Platform", RUBY_PLATFORM)
|
|
102
|
+
|
|
103
|
+
puts info_table.render(max_width: 50)
|
|
104
|
+
puts ""
|
|
105
|
+
|
|
106
|
+
console.rule("Demo Complete!", style: "bold green")
|