tint_me 1.0.0 → 1.1.0
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 +17 -0
- data/README.md +104 -25
- data/lib/tint_me/sgr_builder.rb +1 -1
- data/lib/tint_me/style/types.rb +21 -0
- data/lib/tint_me/style.rb +69 -0
- data/lib/tint_me/version.rb +1 -1
- data/sig/dry-schema.rbs +8 -0
- data/sig/dry-types.rbs +11 -0
- data/sig/tint_me/error.rbs +4 -0
- data/sig/tint_me/sgr_builder.rbs +60 -0
- data/sig/tint_me/style/schema.rbs +5 -0
- data/sig/tint_me/style/types.rbs +14 -0
- data/sig/tint_me/style.rbs +73 -0
- data/sig/tint_me.rbs +1 -45
- metadata +13 -31
- data/.rubocop_todo.yml +0 -7
- data/.serena/project.yml +0 -68
- data/.simplecov +0 -24
- data/.yardopts +0 -6
- data/AGENTS.md +0 -60
- data/CLAUDE.md +0 -1
- data/RELEASING.md +0 -202
- data/Rakefile +0 -18
- data/benchmark/2025-09-08-style-caching-optimization/01_baseline_results.txt +0 -39
- data/benchmark/2025-09-08-style-caching-optimization/02_with_full_caching_results.txt +0 -54
- data/benchmark/2025-09-08-style-caching-optimization/03_prefix_only_caching_results.txt +0 -107
- data/benchmark/2025-09-08-style-caching-optimization/04_baseline_vs_optimized_analysis.txt +0 -65
- data/benchmark/2025-09-08-style-caching-optimization/05_caching_approaches_comparison.txt +0 -59
- data/benchmark/2025-09-08-style-caching-optimization/06_append_operator_results.txt +0 -107
- data/benchmark/2025-09-08-style-caching-optimization/07_string_concatenation_comparison.txt +0 -66
- data/benchmark/2025-09-08-style-caching-optimization/08_with_freeze_optimization_results.txt +0 -107
- data/benchmark/2025-09-08-style-caching-optimization/09_freeze_optimization_analysis.txt +0 -49
- data/benchmark/2025-09-08-style-caching-optimization/10_constant_access_results.txt +0 -107
- data/benchmark/2025-09-08-style-caching-optimization/11_constant_vs_cache_analysis.txt +0 -74
- data/benchmark/2025-09-08-style-caching-optimization/12_empty_prefix_analysis.txt +0 -81
- data/benchmark/2025-09-08-style-caching-optimization/13_nil_check_optimization_results.txt +0 -107
- data/benchmark/2025-09-08-style-caching-optimization/14_nil_vs_empty_check_analysis.txt +0 -81
- data/benchmark/2025-09-08-style-caching-optimization/README.md +0 -45
- data/benchmark/2025-09-08-style-caching-optimization/benchmark_script.rb +0 -180
- data/docs/agents/git-pr.md +0 -298
- data/docs/agents/languages.md +0 -388
- data/docs/agents/rubocop.md +0 -55
- data/mise.toml +0 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 194d04d6b9fdf4c668e84163bce1e59301ba84512f56ff856c1b7e0bc9674ee4
|
|
4
|
+
data.tar.gz: 47b341342f5074b594ca4d2c171bd20303f3ea52638cbb352cbab3bff34d31a2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 67ece923c3216024f8a9d7a9c22d37c212a9253bc0e1d8328f7281b8c43e2470defb07b815eccb63562f6ea3b663a1ced75889234d44e01f9250fc43de935b06
|
|
7
|
+
data.tar.gz: 54fa3e283c219cecccd9ed00fc4a20defd15b59dd4a114a04638f000f0d6e1a8b5fe2be0f72f5e5e890c571c42c02d08c90647da601b53a959c5b8e049331c81
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
## [Unreleased]
|
|
2
2
|
|
|
3
|
+
## [1.1.0] - 2025-11-02
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
- **Positional Arguments Support**: New concise syntax for style creation
|
|
7
|
+
- Single color as positional argument: `TIntMe[:red]` sets foreground
|
|
8
|
+
- Two colors as positional arguments: `TIntMe[:red, :yellow]` sets foreground and background
|
|
9
|
+
- Boolean flags as positional arguments: `TIntMe[:bold, :italic]`
|
|
10
|
+
- Mixed usage: `TIntMe[:red, :yellow, :bold, background: :blue]`
|
|
11
|
+
- Support for all color formats: symbols, hex strings (with/without #, 3/6 digits)
|
|
12
|
+
- Maximum 2 color arguments allowed (3+ raises ArgumentError)
|
|
13
|
+
- Keyword arguments take precedence over positional arguments
|
|
14
|
+
- Type safety with dry-types `PositionalArgumentsArray` validation
|
|
15
|
+
- Comprehensive test coverage for all positional argument scenarios
|
|
16
|
+
|
|
17
|
+
### Development
|
|
18
|
+
- Improved release workflow branch cleanup with existence check
|
|
19
|
+
|
|
3
20
|
## [1.0.0] - 2025-09-09
|
|
4
21
|
|
|
5
22
|
### Added
|
data/README.md
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
# :lipstick: TIntMe! :nail_care:
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/rb/tint_me)
|
|
4
|
+
[](https://github.com/sakuro/tint_me/actions/workflows/ci.yml)
|
|
5
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
|
+
[](https://rubygems.org/gems/tint_me)
|
|
7
|
+
[](https://depfu.com/github/sakuro/tint_me)
|
|
8
|
+
|
|
3
9
|
A Ruby library for terminal text styling with ANSI colors and effects. TIntMe! provides an elegant and composable API for applying colors, text decorations, and formatting to terminal output.
|
|
4
10
|
|
|
5
11
|
## Features
|
|
@@ -10,7 +16,7 @@ A Ruby library for terminal text styling with ANSI colors and effects. TIntMe! p
|
|
|
10
16
|
- **Type Safety**: Comprehensive argument validation using dry-schema and dry-types
|
|
11
17
|
- **Immutable Design**: All style operations return new instances, making them safe for concurrent use
|
|
12
18
|
- **Zeitwerk Integration**: Automatic loading with proper module organization
|
|
13
|
-
- **
|
|
19
|
+
- **Positional Arguments**: Concise syntax with `TIntMe[:red, :bold]` for streamlined styling
|
|
14
20
|
|
|
15
21
|
## Installation
|
|
16
22
|
|
|
@@ -36,11 +42,13 @@ gem install tint_me
|
|
|
36
42
|
|
|
37
43
|
### Basic Styling
|
|
38
44
|
|
|
45
|
+
TIntMe supports both keyword arguments and positional arguments for creating styles. Here are examples using keyword arguments:
|
|
46
|
+
|
|
39
47
|
```ruby
|
|
40
48
|
require 'tint_me'
|
|
41
49
|
|
|
42
|
-
# Create a style
|
|
43
|
-
red_style = TIntMe
|
|
50
|
+
# Create a style with keyword arguments
|
|
51
|
+
red_style = TIntMe[foreground: :red]
|
|
44
52
|
puts red_style.call("Hello World")
|
|
45
53
|
|
|
46
54
|
# Using the shortcut syntax
|
|
@@ -48,37 +56,104 @@ blue_style = TIntMe[foreground: :blue, bold: true]
|
|
|
48
56
|
puts blue_style["Hello World"]
|
|
49
57
|
```
|
|
50
58
|
|
|
59
|
+
### Positional Arguments
|
|
60
|
+
|
|
61
|
+
TIntMe supports a concise positional argument syntax for common styling scenarios:
|
|
62
|
+
|
|
63
|
+
#### Supported Positional Arguments
|
|
64
|
+
|
|
65
|
+
**Colors** (applied as foreground):
|
|
66
|
+
- Color symbols: `:red`, `:green`, `:blue`, `:yellow`, `:magenta`, `:cyan`, `:white`, `:black`, `:gray`
|
|
67
|
+
- Bright colors: `:bright_red`, `:bright_green`, `:bright_blue`, etc.
|
|
68
|
+
- Special values: `:default`, `:reset`
|
|
69
|
+
- Hex strings: `"#FF0000"`, `"FF0000"`, `"#F00"`, `"F00"`
|
|
70
|
+
|
|
71
|
+
**Boolean flags** (set to `true`):
|
|
72
|
+
- `:bold`, `:faint`, `:italic`, `:underline`, `:overline`, `:blink`, `:inverse`, `:conceal`
|
|
73
|
+
|
|
74
|
+
#### Behavior Rules
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
# Two colors: first is foreground, second is background
|
|
78
|
+
TIntMe[:red, :yellow] # => foreground: :red, background: :yellow
|
|
79
|
+
|
|
80
|
+
# Too many colors: error
|
|
81
|
+
TIntMe[:red, :blue, :green] # => ArgumentError: Too many color arguments
|
|
82
|
+
|
|
83
|
+
# Duplicate flags: idempotent (no error)
|
|
84
|
+
TIntMe[:bold, :italic, :bold] # => bold: true, italic: true
|
|
85
|
+
|
|
86
|
+
# Keyword arguments override positional
|
|
87
|
+
TIntMe[:red, foreground: :blue] # => foreground: :blue
|
|
88
|
+
TIntMe[:red, :yellow, background: :green] # => foreground: :red, background: :green
|
|
89
|
+
TIntMe[:bold, bold: false] # => bold: false
|
|
90
|
+
|
|
91
|
+
# Mix freely for complex styling
|
|
92
|
+
TIntMe[:red, :yellow, :bold, underline: :double] # => foreground: :red, background: :yellow, bold: true, underline: :double
|
|
93
|
+
```
|
|
94
|
+
|
|
51
95
|
### Color Options
|
|
52
96
|
|
|
53
97
|
```ruby
|
|
54
|
-
# Standard colors
|
|
98
|
+
# Standard colors (keyword arguments)
|
|
55
99
|
TIntMe[foreground: :red]
|
|
56
100
|
TIntMe[background: :yellow]
|
|
57
101
|
|
|
58
|
-
#
|
|
102
|
+
# Standard colors (positional arguments)
|
|
103
|
+
TIntMe[:red] # Foreground color
|
|
104
|
+
TIntMe[:bright_blue] # Bright colors supported
|
|
105
|
+
|
|
106
|
+
# Hex colors (keyword arguments)
|
|
59
107
|
TIntMe[foreground: "#FF0000"]
|
|
60
108
|
TIntMe[background: "#00FF00"]
|
|
61
109
|
TIntMe[foreground: "FF0000"]
|
|
110
|
+
|
|
111
|
+
# Hex colors (positional arguments)
|
|
112
|
+
TIntMe["#FF0000"] # 6-digit with hash
|
|
113
|
+
TIntMe["FF0000"] # 6-digit without hash
|
|
114
|
+
TIntMe["#F00"] # 3-digit with hash
|
|
115
|
+
TIntMe["F00"] # 3-digit without hash
|
|
116
|
+
|
|
117
|
+
# Mix positional and keyword arguments
|
|
118
|
+
TIntMe[:red, background: :yellow] # Red foreground, yellow background
|
|
119
|
+
TIntMe["#00FF00", :bold, background: :black] # Green foreground, bold, black background
|
|
62
120
|
```
|
|
63
121
|
|
|
64
122
|
### Text Effects
|
|
65
123
|
|
|
66
124
|
```ruby
|
|
67
|
-
# Individual effects
|
|
125
|
+
# Individual effects (keyword arguments)
|
|
68
126
|
TIntMe[bold: true]
|
|
69
|
-
TIntMe[faint: true]
|
|
127
|
+
TIntMe[faint: true] # Faint/dim text
|
|
70
128
|
TIntMe[italic: true]
|
|
71
129
|
TIntMe[underline: true]
|
|
72
|
-
TIntMe[underline: :double]
|
|
73
|
-
TIntMe[overline: true]
|
|
74
|
-
TIntMe[blink: true]
|
|
75
|
-
TIntMe[inverse: true]
|
|
76
|
-
TIntMe[conceal: true]
|
|
77
|
-
|
|
78
|
-
#
|
|
130
|
+
TIntMe[underline: :double] # Double underline
|
|
131
|
+
TIntMe[overline: true] # Overline decoration
|
|
132
|
+
TIntMe[blink: true] # Blinking text
|
|
133
|
+
TIntMe[inverse: true] # Reverse colors
|
|
134
|
+
TIntMe[conceal: true] # Hidden/concealed text
|
|
135
|
+
|
|
136
|
+
# Individual effects (positional arguments)
|
|
137
|
+
TIntMe[:bold] # Bold text
|
|
138
|
+
TIntMe[:italic] # Italic text
|
|
139
|
+
TIntMe[:underline] # Underlined text
|
|
140
|
+
|
|
141
|
+
# Multiple effects (keyword arguments)
|
|
79
142
|
TIntMe[foreground: :green, bold: true, underline: true]
|
|
143
|
+
|
|
144
|
+
# Multiple effects (positional arguments)
|
|
145
|
+
TIntMe[:bold, :italic, :underline] # Multiple boolean flags
|
|
146
|
+
TIntMe[:red, :bold, :italic] # Color + effects
|
|
147
|
+
TIntMe[:red, :yellow, :bold, :italic] # Foreground + background + effects
|
|
148
|
+
TIntMe["#FF5733", :bold, :underline, :blink] # Hex color + effects
|
|
149
|
+
|
|
150
|
+
# Mixed approaches
|
|
151
|
+
TIntMe[:bold, :italic, background: :yellow] # Positional flags + keyword background
|
|
152
|
+
TIntMe[:red, :yellow, underline: :double] # Positional colors + keyword underline
|
|
153
|
+
TIntMe[:red, :bold, background: :blue] # Positional color/flag + keyword background
|
|
80
154
|
```
|
|
81
155
|
|
|
156
|
+
|
|
82
157
|
### Style Composition
|
|
83
158
|
|
|
84
159
|
```ruby
|
|
@@ -101,10 +176,13 @@ final = base >> emphasis >> TIntMe[background: :white]
|
|
|
101
176
|
```ruby
|
|
102
177
|
# ✅ RECOMMENDED: Pre-compose and reuse
|
|
103
178
|
ERROR_STYLE = TIntMe[foreground: :red] >> TIntMe[bold: true]
|
|
104
|
-
|
|
179
|
+
# OR using positional arguments (equivalent)
|
|
180
|
+
ERROR_STYLE = TIntMe[:red] >> TIntMe[:bold]
|
|
181
|
+
ERROR_STYLE.call("Error message") # Fast: ~4.8M operations/sec
|
|
105
182
|
|
|
106
|
-
# ❌ AVOID: Runtime composition
|
|
183
|
+
# ❌ AVOID: Runtime composition
|
|
107
184
|
(TIntMe[foreground: :red] >> TIntMe[bold: true]).call("Error") # Slow: ~0.01M ops/sec
|
|
185
|
+
(TIntMe[:red] >> TIntMe[:bold]).call("Error") # Also slow: ~0.01M ops/sec
|
|
108
186
|
```
|
|
109
187
|
|
|
110
188
|
**Key Guidelines:**
|
|
@@ -124,26 +202,27 @@ ERROR_STYLE.call("Error message") # Fast: ~4.8M operations/sec
|
|
|
124
202
|
```ruby
|
|
125
203
|
# Terminal UI frameworks with predefined styles
|
|
126
204
|
UI_STYLES = {
|
|
127
|
-
error: TIntMe[
|
|
128
|
-
success: TIntMe[foreground: :green
|
|
129
|
-
|
|
205
|
+
error: TIntMe[:red, :bold], # Concise positional syntax
|
|
206
|
+
success: TIntMe[foreground: :green, bold: true], # Or keyword arguments
|
|
207
|
+
warning: TIntMe[:yellow] >> TIntMe[:bold], # Or use composition (combining styles)
|
|
208
|
+
info: TIntMe[:blue, :italic]
|
|
130
209
|
}
|
|
131
210
|
|
|
132
211
|
def show_error(msg)
|
|
133
|
-
puts UI_STYLES[:error].call(msg)
|
|
212
|
+
puts UI_STYLES[:error].call(msg) # Extremely fast: ~4.8M ops/sec
|
|
134
213
|
end
|
|
135
214
|
```
|
|
136
215
|
|
|
137
216
|
**Consider alternatives for:**
|
|
138
217
|
```ruby
|
|
139
218
|
# Dynamic styling (use Paint gem instead)
|
|
140
|
-
texts.each { |text| Paint[text, :red, :bold] }
|
|
219
|
+
texts.each { |text| Paint[text, :red, :bold] } # ~2M ops/sec
|
|
141
220
|
|
|
142
221
|
# One-time styling with readable syntax (use Rainbow gem)
|
|
143
|
-
puts Rainbow("Success").green.bold
|
|
222
|
+
puts Rainbow("Success").green.bold # ~0.5M ops/sec
|
|
144
223
|
|
|
145
224
|
# Avoid with TIntMe - creates unnecessary overhead
|
|
146
|
-
texts.each { |text| (red >> bold).call(text) }
|
|
225
|
+
texts.each { |text| (red >> bold).call(text) } # Only ~0.01M ops/sec
|
|
147
226
|
```
|
|
148
227
|
|
|
149
228
|
**Design Philosophy:**
|
|
@@ -157,14 +236,14 @@ style = TIntMe[foreground: :red, bold: true]
|
|
|
157
236
|
# All of these are equivalent
|
|
158
237
|
puts style.call("Hello")
|
|
159
238
|
puts style["Hello"]
|
|
160
|
-
puts style.("Hello")
|
|
239
|
+
puts style.("Hello") # Callable syntax
|
|
161
240
|
```
|
|
162
241
|
|
|
163
242
|
## Development
|
|
164
243
|
|
|
165
244
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
166
245
|
|
|
167
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb
|
|
246
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb` and update the CHANGELOG.md, then create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org). However, there are GitHub Actions workflows set up to automate these processes, so please use those instead. See `RELEASING.md` for details.
|
|
168
247
|
|
|
169
248
|
## Contributing
|
|
170
249
|
|
data/lib/tint_me/sgr_builder.rb
CHANGED
|
@@ -97,7 +97,7 @@ module TIntMe
|
|
|
97
97
|
# prefix_codes(foreground: :red, bold: true)
|
|
98
98
|
# # => "\e[31;1m"
|
|
99
99
|
#
|
|
100
|
-
# @example
|
|
100
|
+
# @example RGB true color (24-bit)
|
|
101
101
|
# prefix_codes(foreground: "#FF6B35", background: "#F7931E")
|
|
102
102
|
# # => "\e[38;2;255;107;53;48;2;247;147;30m"
|
|
103
103
|
#
|
data/lib/tint_me/style/types.rb
CHANGED
|
@@ -45,6 +45,27 @@ module TIntMe
|
|
|
45
45
|
|
|
46
46
|
UnderlineOption = (Bool | Symbol.enum(:double, :reset)).optional
|
|
47
47
|
public_constant :UnderlineOption
|
|
48
|
+
|
|
49
|
+
# Boolean flags that can be used as positional arguments
|
|
50
|
+
BooleanFlagSymbol = Symbol.enum(
|
|
51
|
+
:bold,
|
|
52
|
+
:faint,
|
|
53
|
+
:italic,
|
|
54
|
+
:underline,
|
|
55
|
+
:overline,
|
|
56
|
+
:blink,
|
|
57
|
+
:inverse,
|
|
58
|
+
:conceal
|
|
59
|
+
)
|
|
60
|
+
public_constant :BooleanFlagSymbol
|
|
61
|
+
|
|
62
|
+
# Valid positional arguments (color symbols + hex strings + boolean flags)
|
|
63
|
+
PositionalArgument = ColorSymbol | ColorString | BooleanFlagSymbol
|
|
64
|
+
public_constant :PositionalArgument
|
|
65
|
+
|
|
66
|
+
# Array of positional arguments for validation
|
|
67
|
+
PositionalArgumentsArray = Array.of(PositionalArgument)
|
|
68
|
+
public_constant :PositionalArgumentsArray
|
|
48
69
|
end
|
|
49
70
|
end
|
|
50
71
|
end
|
data/lib/tint_me/style.rb
CHANGED
|
@@ -42,6 +42,70 @@ module TIntMe
|
|
|
42
42
|
# # ... other boolean effects: overline, blink, conceal
|
|
43
43
|
# )
|
|
44
44
|
class Style
|
|
45
|
+
# Module to extend constructor with positional argument support
|
|
46
|
+
# @api private
|
|
47
|
+
module ConstructorExtensions
|
|
48
|
+
# Normalize positional and keyword arguments for Style construction
|
|
49
|
+
# @param args [Array] Positional arguments (colors and boolean flags)
|
|
50
|
+
# @param kwargs [Hash] Keyword arguments
|
|
51
|
+
# @return [Hash] Normalized keyword arguments
|
|
52
|
+
# @api private
|
|
53
|
+
def normalize_constructor_args(*args, **kwargs)
|
|
54
|
+
# Validate all positional arguments at once using array validation
|
|
55
|
+
Types::PositionalArgumentsArray[args] unless args.empty?
|
|
56
|
+
|
|
57
|
+
# Now normalize the positional arguments
|
|
58
|
+
normalized = kwargs.dup
|
|
59
|
+
colors = []
|
|
60
|
+
|
|
61
|
+
args.each do |arg|
|
|
62
|
+
# Determine if it's a color or a boolean flag
|
|
63
|
+
if Types::ColorSymbol.valid?(arg) || Types::ColorString.valid?(arg)
|
|
64
|
+
# Color argument - collect up to 2 colors
|
|
65
|
+
colors << arg
|
|
66
|
+
elsif Types::BooleanFlagSymbol.valid?(arg)
|
|
67
|
+
# Boolean flag - set to true (idempotent)
|
|
68
|
+
normalized[arg] = true unless normalized.key?(arg)
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Validate maximum 2 colors
|
|
73
|
+
if colors.length > 2
|
|
74
|
+
raise ArgumentError, "Too many color arguments (maximum 2 allowed, got #{colors.length})"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# Apply colors if specified (keyword arguments take precedence)
|
|
78
|
+
if colors.length >= 1 && !normalized.key?(:foreground)
|
|
79
|
+
normalized[:foreground] = colors[0]
|
|
80
|
+
end
|
|
81
|
+
if colors.length == 2 && !normalized.key?(:background)
|
|
82
|
+
normalized[:background] = colors[1]
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
normalized
|
|
86
|
+
rescue Dry::Types::CoercionError => e
|
|
87
|
+
# Extract the invalid argument from the error for a cleaner message
|
|
88
|
+
raise ArgumentError, "Invalid positional argument(s): #{e.message}"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Override new to support positional arguments
|
|
92
|
+
def new(*args, **)
|
|
93
|
+
return super(**) if args.empty?
|
|
94
|
+
|
|
95
|
+
super(**normalize_constructor_args(*args, **))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Override [] to support positional arguments
|
|
99
|
+
def [](*args, **)
|
|
100
|
+
return super(**) if args.empty?
|
|
101
|
+
|
|
102
|
+
super(**normalize_constructor_args(*args, **))
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
# Apply the constructor extensions to the singleton class
|
|
107
|
+
singleton_class.prepend ConstructorExtensions
|
|
108
|
+
|
|
45
109
|
# Returns the singleton instance of SGRBuilder
|
|
46
110
|
# @return [SGRBuilder] The SGR builder instance
|
|
47
111
|
# @api private
|
|
@@ -96,6 +160,11 @@ module TIntMe
|
|
|
96
160
|
# @example Valid usage
|
|
97
161
|
# Style.new(foreground: :red, bold: true)
|
|
98
162
|
# Style.new(underline: :double, background: "#FF0000")
|
|
163
|
+
# @example Positional arguments
|
|
164
|
+
# Style.new(:red, :bold, :italic) # foreground: :red, bold: true, italic: true
|
|
165
|
+
# Style.new(:red, :yellow, :bold) # foreground: :red, background: :yellow, bold: true
|
|
166
|
+
# Style.new("#FF0000", "#00FF00") # foreground: "#FF0000", background: "#00FF00"
|
|
167
|
+
# Style[:blue, :bold] # foreground: :blue, bold: true
|
|
99
168
|
# @example Invalid usage (raises ArgumentError)
|
|
100
169
|
# Style.new(foreground: 123) # Invalid color type
|
|
101
170
|
# Style.new(bold: "true") # Invalid boolean type
|
data/lib/tint_me/version.rb
CHANGED
data/sig/dry-schema.rbs
ADDED
data/sig/dry-types.rbs
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
module TIntMe
|
|
2
|
+
class SGRBuilder
|
|
3
|
+
ESC: String
|
|
4
|
+
CSI: String
|
|
5
|
+
SGR_END: String
|
|
6
|
+
RESET_CODE: String
|
|
7
|
+
COLORS: Hash[Symbol, Integer]
|
|
8
|
+
EFFECTS: Hash[Symbol, Integer]
|
|
9
|
+
|
|
10
|
+
def self.instance: () -> SGRBuilder
|
|
11
|
+
|
|
12
|
+
private
|
|
13
|
+
|
|
14
|
+
def self.new: () -> void
|
|
15
|
+
|
|
16
|
+
public
|
|
17
|
+
|
|
18
|
+
def prefix_codes: (
|
|
19
|
+
?foreground: (Symbol | String)?,
|
|
20
|
+
?background: (Symbol | String)?,
|
|
21
|
+
?bold: bool?,
|
|
22
|
+
?faint: bool?,
|
|
23
|
+
?italic: bool?,
|
|
24
|
+
?underline: (bool | :double)?,
|
|
25
|
+
?blink: bool?,
|
|
26
|
+
?inverse: bool?,
|
|
27
|
+
?conceal: bool?,
|
|
28
|
+
?overline: bool?
|
|
29
|
+
) -> String
|
|
30
|
+
|
|
31
|
+
def reset_code: () -> String
|
|
32
|
+
|
|
33
|
+
private
|
|
34
|
+
|
|
35
|
+
def rgb_to_sgr: (Integer red, Integer green, Integer blue, ?background: bool) -> String
|
|
36
|
+
|
|
37
|
+
def build_parameters: (
|
|
38
|
+
foreground: (Symbol | String)?,
|
|
39
|
+
background: (Symbol | String)?,
|
|
40
|
+
bold: bool?,
|
|
41
|
+
faint: bool?,
|
|
42
|
+
italic: bool?,
|
|
43
|
+
underline: (bool | :double)?,
|
|
44
|
+
blink: bool?,
|
|
45
|
+
inverse: bool?,
|
|
46
|
+
conceal: bool?,
|
|
47
|
+
overline: bool?
|
|
48
|
+
) -> Array[Integer | String]
|
|
49
|
+
|
|
50
|
+
def process_foreground_color: (Symbol | String foreground) -> (Integer | String)
|
|
51
|
+
|
|
52
|
+
def process_background_color: (Symbol | String background) -> (Integer | String)
|
|
53
|
+
|
|
54
|
+
def build_sgr_sequence: (Array[Integer | String] parameters) -> String
|
|
55
|
+
|
|
56
|
+
def hex_color?: (String value) -> bool
|
|
57
|
+
|
|
58
|
+
def hex_to_rgb: (String hex) -> [Integer, Integer, Integer]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
module TIntMe
|
|
2
|
+
class Style
|
|
3
|
+
module Types
|
|
4
|
+
ColorSymbol: Dry::Types::Type
|
|
5
|
+
ColorString: Dry::Types::Type
|
|
6
|
+
Color: Dry::Types::Type
|
|
7
|
+
BooleanOption: Dry::Types::Type
|
|
8
|
+
UnderlineOption: Dry::Types::Type
|
|
9
|
+
BooleanFlagSymbol: Dry::Types::Type
|
|
10
|
+
PositionalArgument: Dry::Types::Type
|
|
11
|
+
PositionalArgumentsArray: Dry::Types::Type
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
module TIntMe
|
|
2
|
+
class Style
|
|
3
|
+
type color_value = :default | :reset | :black | :red | :green | :yellow | :blue | :magenta | :cyan | :white | :gray | :bright_black | :bright_red | :bright_green | :bright_yellow | :bright_blue | :bright_magenta | :bright_cyan | :bright_white | String
|
|
4
|
+
type boolean_value = bool | :reset
|
|
5
|
+
type underline_value = bool | :double | :reset
|
|
6
|
+
type positional_arg = color_value | :bold | :faint | :italic | :underline | :overline | :blink | :inverse | :conceal
|
|
7
|
+
type attribute_value = color_value? | boolean_value? | underline_value?
|
|
8
|
+
|
|
9
|
+
attr_reader foreground: color_value?
|
|
10
|
+
attr_reader background: color_value?
|
|
11
|
+
attr_reader inverse: boolean_value?
|
|
12
|
+
attr_reader bold: boolean_value?
|
|
13
|
+
attr_reader faint: boolean_value?
|
|
14
|
+
attr_reader underline: underline_value?
|
|
15
|
+
attr_reader overline: boolean_value?
|
|
16
|
+
attr_reader blink: boolean_value?
|
|
17
|
+
attr_reader italic: boolean_value?
|
|
18
|
+
attr_reader conceal: boolean_value?
|
|
19
|
+
|
|
20
|
+
def self.sgr_builder: () -> SGRBuilder
|
|
21
|
+
|
|
22
|
+
def self.new: (
|
|
23
|
+
*positional_arg args,
|
|
24
|
+
?foreground: color_value?,
|
|
25
|
+
?background: color_value?,
|
|
26
|
+
?inverse: boolean_value?,
|
|
27
|
+
?bold: boolean_value?,
|
|
28
|
+
?faint: boolean_value?,
|
|
29
|
+
?underline: underline_value?,
|
|
30
|
+
?overline: boolean_value?,
|
|
31
|
+
?blink: boolean_value?,
|
|
32
|
+
?italic: boolean_value?,
|
|
33
|
+
?conceal: boolean_value?
|
|
34
|
+
) -> Style
|
|
35
|
+
|
|
36
|
+
def self.[]: (
|
|
37
|
+
*positional_arg args,
|
|
38
|
+
?foreground: color_value?,
|
|
39
|
+
?background: color_value?,
|
|
40
|
+
?inverse: boolean_value?,
|
|
41
|
+
?bold: boolean_value?,
|
|
42
|
+
?faint: boolean_value?,
|
|
43
|
+
?underline: underline_value?,
|
|
44
|
+
?overline: boolean_value?,
|
|
45
|
+
?blink: boolean_value?,
|
|
46
|
+
?italic: boolean_value?,
|
|
47
|
+
?conceal: boolean_value?
|
|
48
|
+
) -> Style
|
|
49
|
+
|
|
50
|
+
def initialize: (
|
|
51
|
+
?foreground: color_value?,
|
|
52
|
+
?background: color_value?,
|
|
53
|
+
?inverse: boolean_value?,
|
|
54
|
+
?bold: boolean_value?,
|
|
55
|
+
?faint: boolean_value?,
|
|
56
|
+
?underline: underline_value?,
|
|
57
|
+
?overline: boolean_value?,
|
|
58
|
+
?blink: boolean_value?,
|
|
59
|
+
?italic: boolean_value?,
|
|
60
|
+
?conceal: boolean_value?
|
|
61
|
+
) -> void
|
|
62
|
+
|
|
63
|
+
def call: (String text) -> String
|
|
64
|
+
|
|
65
|
+
alias [] call
|
|
66
|
+
|
|
67
|
+
def >>: (Style other) -> Style
|
|
68
|
+
|
|
69
|
+
private
|
|
70
|
+
|
|
71
|
+
def compose_attribute: (attribute_value current, attribute_value other) -> attribute_value
|
|
72
|
+
end
|
|
73
|
+
end
|
data/sig/tint_me.rbs
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
module TIntMe
|
|
2
2
|
VERSION: String
|
|
3
3
|
|
|
4
|
-
# Creates a new Style instance with the given options
|
|
5
4
|
def self.[]: (
|
|
5
|
+
*Style::positional_arg args,
|
|
6
6
|
?foreground: Style::color_value?,
|
|
7
7
|
?background: Style::color_value?,
|
|
8
8
|
?bold: Style::boolean_value?,
|
|
@@ -14,48 +14,4 @@ module TIntMe
|
|
|
14
14
|
?inverse: Style::boolean_value?,
|
|
15
15
|
?conceal: Style::boolean_value?
|
|
16
16
|
) -> Style
|
|
17
|
-
|
|
18
|
-
class Style
|
|
19
|
-
type color_value = :red | :green | :blue | :cyan | :yellow | :magenta | :gray | :white | :black | :default | :reset | String
|
|
20
|
-
type underline_value = bool | :double | :reset
|
|
21
|
-
type boolean_value = bool | :reset
|
|
22
|
-
type style_attribute = :red | :green | :blue | :cyan | :yellow | :magenta | :gray | :white | :black |
|
|
23
|
-
:underline | :double_underline | :overline | :bold | :faint | :blink | :italic | :inverse | :conceal |
|
|
24
|
-
String | nil
|
|
25
|
-
|
|
26
|
-
attr_reader foreground: color_value?
|
|
27
|
-
attr_reader background: color_value?
|
|
28
|
-
attr_reader bold: boolean_value?
|
|
29
|
-
attr_reader faint: boolean_value?
|
|
30
|
-
attr_reader italic: boolean_value?
|
|
31
|
-
attr_reader underline: underline_value?
|
|
32
|
-
attr_reader overline: boolean_value?
|
|
33
|
-
attr_reader blink: boolean_value?
|
|
34
|
-
attr_reader inverse: boolean_value?
|
|
35
|
-
attr_reader conceal: boolean_value?
|
|
36
|
-
|
|
37
|
-
def initialize: (
|
|
38
|
-
?foreground: color_value?,
|
|
39
|
-
?background: color_value?,
|
|
40
|
-
?bold: boolean_value?,
|
|
41
|
-
?faint: boolean_value?,
|
|
42
|
-
?italic: boolean_value?,
|
|
43
|
-
?underline: underline_value?,
|
|
44
|
-
?overline: boolean_value?,
|
|
45
|
-
?blink: boolean_value?,
|
|
46
|
-
?inverse: boolean_value?,
|
|
47
|
-
?conceal: boolean_value?
|
|
48
|
-
) -> void
|
|
49
|
-
|
|
50
|
-
def call: (String text) -> String
|
|
51
|
-
|
|
52
|
-
alias [] call
|
|
53
|
-
|
|
54
|
-
def >>: (Style other) -> Style
|
|
55
|
-
|
|
56
|
-
private
|
|
57
|
-
|
|
58
|
-
def compose_attribute: ((color_value | underline_value | boolean_value)?, (color_value | underline_value | boolean_value)?) -> (color_value | underline_value | boolean_value)?
|
|
59
|
-
|
|
60
|
-
end
|
|
61
17
|
end
|