pastel 0.6.1 → 0.8.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.
Files changed (49) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +66 -12
  3. data/README.md +38 -29
  4. data/lib/pastel/alias_importer.rb +9 -7
  5. data/lib/pastel/ansi.rb +2 -2
  6. data/lib/pastel/color.rb +64 -24
  7. data/lib/pastel/color_parser.rb +24 -18
  8. data/lib/pastel/color_resolver.rb +3 -1
  9. data/lib/pastel/decorator_chain.rb +52 -8
  10. data/lib/pastel/delegator.rb +57 -26
  11. data/lib/pastel/detached.rb +41 -5
  12. data/lib/pastel/version.rb +2 -2
  13. data/lib/pastel.rb +17 -19
  14. metadata +35 -104
  15. data/.gitignore +0 -22
  16. data/.rspec +0 -3
  17. data/.travis.yml +0 -25
  18. data/Gemfile +0 -15
  19. data/Rakefile +0 -8
  20. data/assets/pastel_logo.png +0 -0
  21. data/assets/screenshot.png +0 -0
  22. data/benchmarks/nesting_speed.rb +0 -41
  23. data/benchmarks/speed.rb +0 -45
  24. data/examples/palette.rb +0 -14
  25. data/pastel.gemspec +0 -26
  26. data/spec/spec_helper.rb +0 -45
  27. data/spec/unit/alias_color_spec.rb +0 -24
  28. data/spec/unit/alias_importer_spec.rb +0 -29
  29. data/spec/unit/color/alias_color_spec.rb +0 -40
  30. data/spec/unit/color/code_spec.rb +0 -24
  31. data/spec/unit/color/colored_spec.rb +0 -15
  32. data/spec/unit/color/decorate_spec.rb +0 -79
  33. data/spec/unit/color/equal_spec.rb +0 -22
  34. data/spec/unit/color/lookup_spec.rb +0 -17
  35. data/spec/unit/color/new_spec.rb +0 -10
  36. data/spec/unit/color/strip_spec.rb +0 -56
  37. data/spec/unit/color/styles_spec.rb +0 -10
  38. data/spec/unit/color/valid_spec.rb +0 -19
  39. data/spec/unit/color_parser_spec.rb +0 -67
  40. data/spec/unit/decorate_dsl_spec.rb +0 -94
  41. data/spec/unit/decorator_chain_spec.rb +0 -47
  42. data/spec/unit/delegator_spec.rb +0 -38
  43. data/spec/unit/detach_spec.rb +0 -48
  44. data/spec/unit/new_spec.rb +0 -52
  45. data/spec/unit/respond_to_spec.rb +0 -17
  46. data/spec/unit/undecorate_spec.rb +0 -12
  47. data/tasks/console.rake +0 -10
  48. data/tasks/coverage.rake +0 -11
  49. data/tasks/spec.rake +0 -29
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 36792f1ad19da1d3055e30adc845e03e6ac1c3be
4
- data.tar.gz: 4ddf64dfbb76fb94f39117fc11f1d037ca192313
2
+ SHA256:
3
+ metadata.gz: '06693f6ff4f804468ff3802df48c725067fb8eb425e9ba4301627f7c496099bb'
4
+ data.tar.gz: 0752767e8bbe626d683e5eb8b576f5c1229c322f72475d41b1041f4f15eb2c11
5
5
  SHA512:
6
- metadata.gz: 4c3391540a8a5b9100cb4cadde405ac364b5dc9de035a4192a5002130c5076cf338870e20cacbb30a9704b3bd193587f8793a0440bf50ea3a8f37166ad156525
7
- data.tar.gz: 1876b306cb278ec5cbc0bd5cde41a9e5be19733b30d26091c52329bcdd4db3b5cfda1f4e870257e512c7972eaf6c30d0cd67acaa5e17b29719e8e93b0aec9574
6
+ metadata.gz: 2239724d8aa9165ec045a2f43b6b8ce336c35ad487bc9e5ca1a8005c0321c682a73fff711316710848fee9931790c47a72dc5469afda25e98975bf6c38a9dfc5
7
+ data.tar.gz: b8f59e4fa1c52973d91d41d4e3f8602da3b164a41125a7416c7f119f53f880e81f4d3a79ea52e25b4e9de4dcb338d37ff1045f9b7b4437056cb7dc1597ce87df
data/CHANGELOG.md CHANGED
@@ -1,5 +1,53 @@
1
1
  # Change log
2
2
 
3
+ ## [v0.8.0] - 2020-07-04
4
+
5
+ ### Changed
6
+ * Change gemspec to require Ruby 2.0 or higher
7
+ * Change Pastel#new to use keyword arguments in place of hash options
8
+ * Change to freeze all strings
9
+ * Remove equatable dependency
10
+
11
+ ### Fixed
12
+ * Fix Pastel#strip to recognise no-number reset by DanielVartanov(@DanielVartanov)
13
+ * Fix Pastel#undecorate to correctly assign styles for nested colors
14
+
15
+ ## [v0.7.4] - 2020-05-08
16
+
17
+ ### Fixed
18
+ * Fix ColorParser#undecorate to require direct dependency by Nick Pezza(@npezza93)
19
+
20
+ ## [v0.7.3] - 2019-06-16
21
+
22
+ ### Changed
23
+ * Change gemspec to load required files directly without git
24
+ * Change to update tty-color & equatable dependency versions
25
+
26
+ ### Fixed
27
+ * Fix Delegator warning
28
+
29
+ ## [v0.7.2] - 2017-11-09
30
+
31
+ ### Changed
32
+ * Change to load relative file paths
33
+ * Change to allow `#alias_color` to accept multiple colors by Jared Ning (@ordinaryzelig)
34
+
35
+ ## [v0.7.1] - 2017-01-09
36
+
37
+ ### Changed
38
+ * Change to load specific files when needed
39
+ * Change to freeze ANSI attributes
40
+ * Change to directly assign enabled attribute
41
+
42
+ ## [v0.7.0] - 2016-12-27
43
+
44
+ ### Changed
45
+ * Enabled colors on Windows by default
46
+ * Update tty-color dependency
47
+
48
+ ### Fixed
49
+ * Fix Color#decorate to prevent redecoration with the same color
50
+
3
51
  ## [v0.6.1] - 2016-04-09
4
52
 
5
53
  ### Fixed
@@ -8,7 +56,7 @@
8
56
  ## [v0.6.0] - 2016-01-15
9
57
 
10
58
  ### Added
11
- * Add helper functions #foreground?, #backgroud?, #style to ANSI module
59
+ * Add helper functions #foreground?, #background?, #style to ANSI module
12
60
  * Add ColorParser for parsing color symbols out of text
13
61
  * Add Pastel#undecorate for parsing color names out of strings
14
62
 
@@ -86,14 +134,20 @@
86
134
  * Change gemspec to include equatable as dependency
87
135
  * Change Delegator to stop creating instances and improve performance
88
136
 
89
- [v0.6.1]: https://github.com/peter-murach/pastel/compare/v0.6.0...v0.6.1
90
- [v0.6.0]: https://github.com/peter-murach/pastel/compare/v0.5.3...v0.6.0
91
- [v0.5.3]: https://github.com/peter-murach/pastel/compare/v0.5.2...v0.5.3
92
- [v0.5.2]: https://github.com/peter-murach/pastel/compare/v0.5.1...v0.5.2
93
- [v0.5.1]: https://github.com/peter-murach/pastel/compare/v0.5.0...v0.5.1
94
- [v0.5.0]: https://github.com/peter-murach/pastel/compare/v0.4.0...v0.5.0
95
- [v0.4.0]: https://github.com/peter-murach/pastel/compare/v0.3.0...v0.4.0
96
- [v0.3.0]: https://github.com/peter-murach/pastel/compare/v0.2.1...v0.3.0
97
- [v0.2.1]: https://github.com/peter-murach/pastel/compare/v0.2.0...v0.2.1
98
- [v0.2.0]: https://github.com/peter-murach/pastel/compare/v0.1.0...v0.2.0
99
- [v0.1.0]: https://github.com/peter-murach/pastel/compare/v0.1.0
137
+ [v0.8.0]: https://github.com/piotrmurach/pastel/compare/v0.7.4...v0.8.0
138
+ [v0.7.4]: https://github.com/piotrmurach/pastel/compare/v0.7.3...v0.7.4
139
+ [v0.7.3]: https://github.com/piotrmurach/pastel/compare/v0.7.2...v0.7.3
140
+ [v0.7.2]: https://github.com/piotrmurach/pastel/compare/v0.7.1...v0.7.2
141
+ [v0.7.1]: https://github.com/piotrmurach/pastel/compare/v0.7.0...v0.7.1
142
+ [v0.7.0]: https://github.com/piotrmurach/pastel/compare/v0.6.1...v0.7.0
143
+ [v0.6.1]: https://github.com/piotrmurach/pastel/compare/v0.6.0...v0.6.1
144
+ [v0.6.0]: https://github.com/piotrmurach/pastel/compare/v0.5.3...v0.6.0
145
+ [v0.5.3]: https://github.com/piotrmurach/pastel/compare/v0.5.2...v0.5.3
146
+ [v0.5.2]: https://github.com/piotrmurach/pastel/compare/v0.5.1...v0.5.2
147
+ [v0.5.1]: https://github.com/piotrmurach/pastel/compare/v0.5.0...v0.5.1
148
+ [v0.5.0]: https://github.com/piotrmurach/pastel/compare/v0.4.0...v0.5.0
149
+ [v0.4.0]: https://github.com/piotrmurach/pastel/compare/v0.3.0...v0.4.0
150
+ [v0.3.0]: https://github.com/piotrmurach/pastel/compare/v0.2.1...v0.3.0
151
+ [v0.2.1]: https://github.com/piotrmurach/pastel/compare/v0.2.0...v0.2.1
152
+ [v0.2.0]: https://github.com/piotrmurach/pastel/compare/v0.1.0...v0.2.0
153
+ [v0.1.0]: https://github.com/piotrmurach/pastel/compare/v0.1.0
data/README.md CHANGED
@@ -1,15 +1,19 @@
1
1
  <div align="center">
2
2
  <img width="215" src="https://cdn.rawgit.com/piotrmurach/pastel/master/assets/pastel_logo.png" alt="pastel logo" />
3
3
  </div>
4
+
4
5
  # Pastel
6
+
5
7
  [![Gem Version](https://badge.fury.io/rb/pastel.svg)][gem]
6
8
  [![Build Status](https://secure.travis-ci.org/piotrmurach/pastel.svg?branch=master)][travis]
9
+ [![Build status](https://ci.appveyor.com/api/projects/status/9blbjfq42o4v1rk4?svg=true)][appveyor]
7
10
  [![Code Climate](https://codeclimate.com/github/piotrmurach/pastel/badges/gpa.svg)][codeclimate]
8
11
  [![Coverage Status](https://coveralls.io/repos/github/piotrmurach/pastel/badge.svg)][coverage]
9
12
  [![Inline docs](http://inch-ci.org/github/piotrmurach/pastel.svg?branch=master)][inchpages]
10
13
 
11
14
  [gem]: http://badge.fury.io/rb/pastel
12
15
  [travis]: http://travis-ci.org/piotrmurach/pastel
16
+ [appveyor]: https://ci.appveyor.com/project/piotrmurach/pastel
13
17
  [codeclimate]: https://codeclimate.com/github/piotrmurach/pastel
14
18
  [coverage]: https://coveralls.io/github/piotrmurach/pastel
15
19
  [inchpages]: http://inch-ci.org/github/piotrmurach/pastel
@@ -35,7 +39,7 @@
35
39
 
36
40
  Add this line to your application's Gemfile:
37
41
 
38
- gem 'pastel'
42
+ gem "pastel"
39
43
 
40
44
  And then execute:
41
45
 
@@ -72,7 +76,7 @@ Or install it yourself as:
72
76
  ```ruby
73
77
  pastel = Pastel.new
74
78
 
75
- puts pastel.red('Unicorns!')
79
+ puts pastel.red("Unicorns!")
76
80
  ```
77
81
 
78
82
  **Pastel** doesn't print the colored string out, just returns it, you'll have to print it yourself.
@@ -80,46 +84,46 @@ puts pastel.red('Unicorns!')
80
84
  You can compose multiple styles through chainable API:
81
85
 
82
86
  ```ruby
83
- pastel.red.on_green.bold('Unicorns!')
87
+ pastel.red.on_green.bold("Unicorns!")
84
88
  ```
85
89
 
86
90
  It allows you to combine styled strings with unstyled ones:
87
91
 
88
92
  ```ruby
89
- pastel.red('Unicorns') + ' will rule ' + pastel.green('the World!')
93
+ pastel.red("Unicorns") + " will rule " + pastel.green("the World!")
90
94
  ```
91
95
 
92
96
  It supports variable number of arguments:
93
97
 
94
98
  ```ruby
95
- pastel.red('Unicorns', 'are', 'running', 'everywhere!')
99
+ pastel.red("Unicorns", "are", "running", "everywhere!")
96
100
  ```
97
101
 
98
102
  You can also nest styles as follows:
99
103
 
100
104
  ```ruby
101
- pastel.red('Unicorns ', pastel.on_green('everywhere!'))
105
+ pastel.red("Unicorns ", pastel.on_green("everywhere!"))
102
106
  ```
103
107
 
104
108
  Nesting is smart enough to know where one color ends and another one starts:
105
109
 
106
110
  ```ruby
107
- pastel.red('Unicorns ' + pastel.green('everywhere') + pastel.on_yellow('!'))
111
+ pastel.red("Unicorns " + pastel.green("everywhere") + pastel.on_yellow("!"))
108
112
  ```
109
113
 
110
114
  You can also nest styles inside blocks:
111
115
 
112
116
  ```ruby
113
- pastel.red.on_green('Unicorns') {
114
- green.on_red('will ', 'dominate') {
115
- yellow('the world!')
117
+ pastel.red.on_green("Unicorns") {
118
+ green.on_red("will ", "dominate") {
119
+ yellow("the world!")
116
120
  }
117
121
  }
118
122
  ```
119
123
 
120
- When dealing with multiline strings you can set `eachline` option(more info see [eachline](#29-eachline)):
124
+ When dealing with multiline strings you can set `eachline` option(more info see [eachline](#211-eachline)):
121
125
 
122
- ```
126
+ ```ruby
123
127
  pastel = Pastel.new(eachline: "\n")
124
128
  ```
125
129
 
@@ -129,8 +133,8 @@ You can also predefine needed styles and reuse them:
129
133
  error = pastel.red.bold.detach
130
134
  warning = pastel.yellow.detach
131
135
 
132
- puts error.('Error!')
133
- puts warning.('Warning')
136
+ puts error.("Error!")
137
+ puts warning.("Warning")
134
138
  ```
135
139
 
136
140
  If your output is redirected to a file, you probably don't want Pastel to add color to your text.
@@ -139,7 +143,7 @@ See https://github.com/piotrmurach/pastel#210-enabled for a way to easily accomp
139
143
  **Pastel** has companion library called `pastel-cli` that allows you to style text in terminal via `pastel` executable:
140
144
 
141
145
  ```bash
142
- $ pastel green 'Unicorns & rainbows!'
146
+ $ pastel green "Unicorns & rainbows!"
143
147
  ```
144
148
 
145
149
  ## 2 Interface
@@ -151,7 +155,7 @@ pastel.`<color>[.<color>...](string, [string...])`
151
155
  Color styles are invoked as method calls with a string argument. A given color can take any number of strings as arguments. Then it returns a colored string which isn't printed out to terminal. You need to print it yourself if you need to. This is done so that you can save it as a string, pass to something else, send it to a file handle and so on.
152
156
 
153
157
  ```ruby
154
- pastel.red('Unicorns ', pastel.bold.underline('everywhere'), '!')
158
+ pastel.red("Unicorns ", pastel.bold.underline("everywhere"), "!")
155
159
  ```
156
160
 
157
161
  Please refer to [3. Supported Colors](#3-supported-colors) section for full list of supported styles.
@@ -161,7 +165,7 @@ Please refer to [3. Supported Colors](#3-supported-colors) section for full list
161
165
  This method is a lower level string styling call that takes as the first argument the string to style followed by any number of color attributes, and returns string wrapped in styles.
162
166
 
163
167
  ```ruby
164
- pastel.decorate('Unicorn', :green, :on_blue, :bold)
168
+ pastel.decorate("Unicorn", :green, :on_blue, :bold)
165
169
  ```
166
170
 
167
171
  This method will be useful in situations where colors are provided as a list of parameters that have been generated dynamically.
@@ -172,7 +176,7 @@ It performs the opposite to `decorate` method by turning color escape sequences
172
176
 
173
177
  ```ruby
174
178
  pastel.undecorate("\e[32mfoo\e[0m \e[31mbar\e[0m")
175
- # => [{foreground: :green, text: 'foo'}, {text: ' '}, {foreground: :red, text: 'bar'}]
179
+ # => [{foreground: :green, text: "foo"}, {text: " "}, {foreground: :red, text: "bar"}]
176
180
  ```
177
181
 
178
182
  To translate the color name into sequence use [lookup](#27-lookup)
@@ -184,9 +188,9 @@ The `detach` method allows to keep all the associated colors with the detached i
184
188
  ```ruby
185
189
  notice = pastel.blue.bold.detach
186
190
 
187
- notice.call('Unicorns running')
188
- notice.('Unicorns running')
189
- notice['Unicorns running']
191
+ notice.call("Unicorns running")
192
+ notice.("Unicorns running")
193
+ notice["Unicorns running"]
190
194
  ```
191
195
 
192
196
  ### 2.5 Strip
@@ -210,7 +214,8 @@ pastel.styles
210
214
  To perform translation of color name into ansi escape code use `lookup`:
211
215
 
212
216
  ```ruby
213
- color.lookup(:red) # => "\e[31m"
217
+ pastel.lookup(:red) # => "\e[31m"
218
+ pastel.lookup(:reset) # => "\e[0m"
214
219
  ```
215
220
 
216
221
  ### 2.8 Valid?
@@ -264,16 +269,16 @@ pastel.red("foo\nbar") # => "\e[31mfoo\e[0m\n\e[31mbar\e[0m"
264
269
 
265
270
  ### 2.12 Alias Color
266
271
 
267
- In order to setup an alias for the standard color do:
272
+ In order to setup an alias for standard colors do:
268
273
 
269
274
  ```ruby
270
- pastel.alias_color(:funky, :red)
275
+ pastel.alias_color(:funky, :red, :bold)
271
276
  ```
272
277
 
273
- From that point forward, `:funky` alias can be passed to `decorate`, `valid?` with the same meaning as standard color:
278
+ From that point forward, `:funky` alias can be passed to `decorate`, `valid?` with the same meaning as standard colors:
274
279
 
275
280
  ```ruby
276
- pastel.funky.on_green('unicorn') # => will use :red color
281
+ pastel.funky.on_green("unicorn") # => will use :red, :bold color
277
282
  ```
278
283
 
279
284
  This method allows you to give more meaningful names to existing colors.
@@ -343,10 +348,10 @@ Generic styles:
343
348
 
344
349
  This environment variable allows you to specify custom color aliases at runtime that will be understood by **Pastel**. The environment variable is read and used when the instance of **Pastel** is created. You can also use `alias_color` to create aliases.
345
350
 
346
- Only alphanumeric and `_` are allowed in the alias names with the following format:
351
+ Only alphanumeric and `_` and `.` are allowed in the alias names with the following format:
347
352
 
348
353
  ```ruby
349
- PASTEL_COLORS_ALIASES='newcolor_1=red,newcolor_2=on_green'
354
+ PASTEL_COLORS_ALIASES="newcolor_1=red,newcolor_2=on_green,funky=red.bold"
350
355
  ```
351
356
 
352
357
  ## 5. Command line
@@ -365,6 +370,10 @@ $ pastel green 'Unicorns & rainbows!'
365
370
  4. Push to the branch (`git push origin my-new-feature`)
366
371
  5. Create a new Pull Request
367
372
 
373
+ ## Code of Conduct
374
+
375
+ Everyone interacting in the Pastel project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/piotrmurach/pastel/blob/master/CODE_OF_CONDUCT.md).
376
+
368
377
  ## Copyright
369
378
 
370
- Copyright (c) 2014-2016 Piotr Murach. See LICENSE for further details.
379
+ Copyright (c) 2014 Piotr Murach. See LICENSE for further details.
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Pastel
4
4
  # A class responsible for importing color aliases
@@ -18,21 +18,23 @@ module Pastel
18
18
  # Import aliases from the environment
19
19
  #
20
20
  # @example
21
- # importer = Pastel::AliasImporter.new(Pastel::Color.new)
21
+ # importer = Pastel::AliasImporter.new(Pastel::Color.new, {})
22
22
  # importer.import
23
23
  #
24
24
  # @return [nil]
25
25
  #
26
26
  # @api public
27
27
  def import
28
- color_aliases = env['PASTEL_COLORS_ALIASES']
28
+ color_aliases = env["PASTEL_COLORS_ALIASES"]
29
29
  return unless color_aliases
30
- color_aliases.split(',').each do |color_alias|
31
- new_color, old_color = color_alias.split('=').map(&:to_sym)
32
- if !new_color || !old_color
30
+
31
+ color_aliases.split(",").each do |color_alias|
32
+ new_color, old_colors = color_alias.split("=")
33
+ if !new_color || !old_colors
33
34
  output.puts "Bad color mapping `#{color_alias}`"
34
35
  else
35
- color.alias_color(new_color, old_color)
36
+ color.alias_color(new_color.to_sym,
37
+ *old_colors.split(".").map(&:to_sym))
36
38
  end
37
39
  end
38
40
  end
data/lib/pastel/ansi.rb CHANGED
@@ -1,4 +1,4 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
3
  module Pastel
4
4
  # Mixin that provides ANSI codes
@@ -51,7 +51,7 @@ module Pastel
51
51
  on_bright_magenta: 105,
52
52
  on_bright_cyan: 106,
53
53
  on_bright_white: 107
54
- }
54
+ }.freeze
55
55
 
56
56
  module_function
57
57
 
data/lib/pastel/color.rb CHANGED
@@ -1,28 +1,29 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "ansi"
2
4
 
3
5
  module Pastel
4
6
  # A class responsible for coloring strings.
5
7
  class Color
6
- include Equatable
7
8
  include ANSI
8
9
 
9
10
  # All color aliases
10
11
  ALIASES = {}
11
12
 
12
13
  # Match all color escape sequences
13
- ANSI_COLOR_REGEXP = /\x1b+(\[|\[\[)[0-9;:?]+m/mo.freeze
14
+ ANSI_COLOR_REGEXP = /\x1b\[{1,2}[0-9;:?]*m/mo.freeze
14
15
 
15
16
  attr_reader :enabled
16
- alias_method :enabled?, :enabled
17
+ alias enabled? enabled
17
18
 
18
19
  attr_reader :eachline
19
20
 
20
21
  # Initialize a Terminal Color
21
22
  #
22
23
  # @api public
23
- def initialize(options = {})
24
- @enabled = options[:enabled]
25
- @eachline = options.fetch(:eachline) { false }
24
+ def initialize(enabled: nil, eachline: false)
25
+ @enabled = enabled
26
+ @eachline = eachline
26
27
  @cache = {}
27
28
  end
28
29
 
@@ -53,7 +54,7 @@ module Pastel
53
54
  def decorate(string, *colors)
54
55
  return string if blank?(string) || !enabled || colors.empty?
55
56
 
56
- ansi_colors = lookup(*colors)
57
+ ansi_colors = lookup(*colors.dup.uniq)
57
58
  if eachline
58
59
  string.dup.split(eachline).map! do |line|
59
60
  apply_codes(line, ansi_colors)
@@ -100,7 +101,7 @@ module Pastel
100
101
  #
101
102
  # @api public
102
103
  def strip(*strings)
103
- modified = strings.map { |string| string.dup.gsub(ANSI_COLOR_REGEXP, '') }
104
+ modified = strings.map { |string| string.dup.gsub(ANSI_COLOR_REGEXP, "") }
104
105
  modified.size == 1 ? modified[0] : modified
105
106
  end
106
107
 
@@ -191,29 +192,67 @@ module Pastel
191
192
  colors.all? { |color| style_names.include?(color.to_sym) }
192
193
  end
193
194
 
194
- # Define a new color alias
195
+ # Define a new colors alias
195
196
  #
196
197
  # @param [String] alias_name
197
- # the color alias to define
198
- # @param [String] color
199
- # the color the alias will correspond to
198
+ # the colors alias to define
199
+ # @param [Array[Symbol,String]] color
200
+ # the colors the alias will correspond to
200
201
  #
201
- # @return [String]
202
- # the standard color value of the alias
202
+ # @return [Array[String]]
203
+ # the standard color values of the alias
203
204
  #
204
205
  # @api public
205
- def alias_color(alias_name, color)
206
- validate(color)
206
+ def alias_color(alias_name, *colors)
207
+ validate(*colors)
207
208
 
208
209
  if !(alias_name.to_s =~ /^[\w]+$/)
209
- fail InvalidAliasNameError, "Invalid alias name `#{alias_name}`"
210
+ raise InvalidAliasNameError, "Invalid alias name `#{alias_name}`"
210
211
  elsif ANSI::ATTRIBUTES[alias_name]
211
- fail InvalidAliasNameError,
212
- "Cannot alias standard color `#{alias_name}`"
212
+ raise InvalidAliasNameError,
213
+ "Cannot alias standard color `#{alias_name}`"
213
214
  end
214
215
 
215
- ALIASES[alias_name.to_sym] = ANSI::ATTRIBUTES[color]
216
- color
216
+ ALIASES[alias_name.to_sym] = colors.map(&ANSI::ATTRIBUTES.method(:[]))
217
+ colors
218
+ end
219
+
220
+ # Compare colors for equality of attributes
221
+ #
222
+ # @return [Boolean]
223
+ #
224
+ # @api public
225
+ def eql?(other)
226
+ instance_of?(other.class) &&
227
+ enabled.eql?(other.enabled) && eachline.eql?(other.eachline)
228
+ end
229
+
230
+ # Compare colors for equivalence of attributes
231
+ #
232
+ # @return [Boolean]
233
+ #
234
+ # @api public
235
+ def ==(other)
236
+ other.is_a?(self.class) &&
237
+ enabled == other.enabled && eachline == other.eachline
238
+ end
239
+
240
+ # Inspect this instance attributes
241
+ #
242
+ # @return [String]
243
+ #
244
+ # @api public
245
+ def inspect
246
+ "#<#{self.class.name} enabled=#{enabled.inspect} eachline=#{eachline.inspect}>"
247
+ end
248
+
249
+ # Hash for this instance and its attributes
250
+ #
251
+ # @return [Numeric]
252
+ #
253
+ # @api public
254
+ def hash
255
+ [self.class, enabled, eachline].hash
217
256
  end
218
257
 
219
258
  private
@@ -224,13 +263,14 @@ module Pastel
224
263
  #
225
264
  # @api private
226
265
  def blank?(value)
227
- value.nil? || !value.respond_to?(:to_str) || value.to_s == ''
266
+ value.nil? || !value.respond_to?(:to_str) || value.to_s == ""
228
267
  end
229
268
 
230
269
  # @api private
231
270
  def validate(*colors)
232
271
  return if valid?(*colors)
233
- fail InvalidAttributeNameError, 'Bad style or unintialized constant, ' \
272
+
273
+ raise InvalidAttributeNameError, "Bad style or unintialized constant, " \
234
274
  " valid styles are: #{style_names.join(', ')}."
235
275
  end
236
276
  end # Color
@@ -1,4 +1,8 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
+
3
+ require "strscan"
4
+
5
+ require_relative "ansi"
2
6
 
3
7
  module Pastel
4
8
  # Responsible for parsing color symbols out of text with color escapes
@@ -9,15 +13,16 @@ module Pastel
9
13
  class ColorParser
10
14
  include ANSI
11
15
 
12
- ESC = "\x1b".freeze
13
- CSI = "\[".freeze
16
+ ESC = "\x1b"
17
+ CSI = "\["
14
18
 
15
19
  # Parse color escape sequences into a list of hashes
16
20
  # corresponding to the color attributes being set by these
17
21
  # sequences
18
22
  #
19
23
  # @example
20
- # parse("\e[32mfoo\e[0m") # => [{colors: [:green], text: 'foo'}
24
+ # parse("\e[32mfoo\e[0m")
25
+ # # => [{foreground: :green, text: "foo"}
21
26
  #
22
27
  # @param [String] text
23
28
  # the text to parse for presence of color ansi codes
@@ -30,20 +35,19 @@ module Pastel
30
35
  state = {}
31
36
  result = []
32
37
  ansi_stack = []
33
- text_chunk = ''
38
+ text_chunk = []
34
39
 
35
40
  until scanner.eos?
36
41
  char = scanner.getch
37
42
  # match control
38
43
  if char == ESC && (delim = scanner.getch) == CSI
39
- if scanner.scan(/^0m/)
44
+ if scanner.scan(/^0?m/) # reset
40
45
  unpack_ansi(ansi_stack) { |attr, name| state[attr] = name }
41
46
  ansi_stack = []
42
47
  elsif scanner.scan(/^([1-9;:]+)m/)
43
48
  # ansi codes separated by text
44
49
  if !text_chunk.empty? && !ansi_stack.empty?
45
50
  unpack_ansi(ansi_stack) { |attr, name| state[attr] = name }
46
- ansi_stack = []
47
51
  end
48
52
  scanner[1].split(/:|;/).each do |code|
49
53
  ansi_stack << code
@@ -51,10 +55,10 @@ module Pastel
51
55
  end
52
56
 
53
57
  if !text_chunk.empty?
54
- state[:text] = text_chunk
58
+ state[:text] = text_chunk.join
55
59
  result.push(state)
56
60
  state = {}
57
- text_chunk = ''
61
+ text_chunk.clear
58
62
  end
59
63
  elsif char == ESC # broken escape
60
64
  text_chunk << char + delim.to_s
@@ -64,12 +68,12 @@ module Pastel
64
68
  end
65
69
 
66
70
  if !text_chunk.empty?
67
- state[:text] = text_chunk
71
+ state[:text] = text_chunk.join
68
72
  end
69
73
  if !ansi_stack.empty?
70
74
  unpack_ansi(ansi_stack) { |attr, name| state[attr] = name}
71
75
  end
72
- if state.values.any? { |val| !val.empty? }
76
+ if !state[:text].to_s.empty?
73
77
  result.push(state)
74
78
  end
75
79
  result
@@ -84,10 +88,8 @@ module Pastel
84
88
  #
85
89
  # @api private
86
90
  def self.unpack_ansi(ansi_stack)
87
- ansi_stack.each do |ansi|
88
- name = ansi_for(ansi)
89
- attr = attribute_for(ansi)
90
- yield attr, name
91
+ ansi_stack.each do |code|
92
+ yield(attribute_name(code), color_name(code))
91
93
  end
92
94
  end
93
95
 
@@ -99,7 +101,7 @@ module Pastel
99
101
  # @return [Symbol]
100
102
  #
101
103
  # @api private
102
- def self.attribute_for(ansi)
104
+ def self.attribute_name(ansi)
103
105
  if ANSI.foreground?(ansi)
104
106
  :foreground
105
107
  elsif ANSI.background?(ansi)
@@ -109,9 +111,13 @@ module Pastel
109
111
  end
110
112
  end
111
113
 
114
+ # Convert ANSI code to color name
115
+ #
116
+ # @return [String]
117
+ #
112
118
  # @api private
113
- def self.ansi_for(ansi)
114
- ATTRIBUTES.key(ansi.to_i)
119
+ def self.color_name(ansi_code)
120
+ ATTRIBUTES.key(ansi_code.to_i)
115
121
  end
116
122
  end # Parser
117
123
  end # Pastel
@@ -1,4 +1,6 @@
1
- # coding: utf-8
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "detached"
2
4
 
3
5
  module Pastel
4
6
  # Contains logic for resolving styles applied to component