pastel 0.3.0 → 0.4.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a3a74798586ce6f5429d3c76faad4e3445319463
4
- data.tar.gz: c2b581122d3029f273f29d5c6fcb9cbca064cc64
3
+ metadata.gz: 20dcaf43ced285d36ad7074808b52e6963e2da79
4
+ data.tar.gz: 592af5b9be60dbd781e909a3dc29222cfc68eef0
5
5
  SHA512:
6
- metadata.gz: c47eac8d882f22e8dc9c1217497ce9f4a2aea4371d523801e8c37261aad1fc9f03d8f2e7f45c7ab168f22c68621331e9201d7363d5ae357a129596110a7fa27c
7
- data.tar.gz: e7fdf3e1428864ad525fb50dfb3fe6f9f760ce7923d91af73b7f9df054f22e51dbc0db969cbd2def2bcce3b4d6b8337addbc0ac1b406395fb88bf106f5ae8434
6
+ metadata.gz: bf6a4be639512821cf4e990dbb0a6a15a4e0f009912161be8b9f429bf9287985baa02202378d80ae2b2d8b3de218319150b713f929ed6ec5fb17006e96a530e7
7
+ data.tar.gz: 204a5342e5b5e2e29d1cd50896db08c8d543467a18d0efac9cfe39a77536aca277f630a7716981aff33239b1a05cac2701d6644c0f224e232704b90eb6a62ba2
@@ -1,6 +1,12 @@
1
+ 0.4.0 (November 22, 2014)
2
+
3
+ * Fix Delegator#respond_to method to correctly report existence of methods
4
+ * Add ability to #detach color combination for later reuse
5
+ * Add ability to nest styles with blocks
6
+
1
7
  0.3.0 (November 8, 2014)
2
8
 
3
- * Add ability to alias colors through alias_color method
9
+ * Add ability to alias colors through #alias_color method
4
10
  * Add ability to alias colors through the environment variable
5
11
  * Improve performance of Pastel::Color styles and lookup methods
6
12
  * Fix bug concerned with lack of escaping for nested styles
data/README.md CHANGED
@@ -2,12 +2,14 @@
2
2
  [![Gem Version](https://badge.fury.io/rb/pastel.png)][gem]
3
3
  [![Build Status](https://secure.travis-ci.org/peter-murach/pastel.png?branch=master)][travis]
4
4
  [![Code Climate](https://codeclimate.com/github/peter-murach/pastel.png)][codeclimate]
5
+ [![Coverage Status](https://coveralls.io/repos/peter-murach/pastel/badge.png)][coverage]
5
6
 
6
7
  [gem]: http://badge.fury.io/rb/pastel
7
8
  [travis]: http://travis-ci.org/peter-murach/pastel
8
9
  [codeclimate]: https://codeclimate.com/github/peter-murach/pastel
10
+ [coverage]: https://coveralls.io/r/peter-murach/pastel
9
11
 
10
- Terminal output styling with intuitive and clean API that doesn't monkey patch String class.
12
+ > Terminal output styling with intuitive and clean API that doesn't monkey patch String class.
11
13
 
12
14
  **Pastel** is minimal and focused to work in all terminal emulators.
13
15
 
@@ -43,11 +45,12 @@ Or install it yourself as:
43
45
  * [2. Interface](#2-interface)
44
46
  * [2.1 Color](#21-color)
45
47
  * [2.2 Decorate](#22-decorate)
46
- * [2.3 Strip](#23-strip)
47
- * [2.4 Styles](#24-styles)
48
- * [2.5 Valid?](#25-valid)
49
- * [2.6 Enabled?](#26-enabled)
50
- * [2.7 Alias Color](#27-alias-color)
48
+ * [2.3 Detach](#23-detach)
49
+ * [2.4 Strip](#24-strip)
50
+ * [2.5 Styles](#25-styles)
51
+ * [2.6 Valid?](#26-valid)
52
+ * [2.7 Enabled?](#27-enabled)
53
+ * [2.8 Alias Color](#28-alias-color)
51
54
  * [3. Supported Colors](#3-supported-colors)
52
55
  * [4. Environment](#4-environment)
53
56
 
@@ -58,19 +61,19 @@ Or install it yourself as:
58
61
  ```ruby
59
62
  pastel = Pastel.new
60
63
 
61
- pastel.red('Unicorns!')
64
+ puts pastel.red('Unicorns!')
62
65
  ```
63
66
 
64
- It allows you to combine styled strings with regular ones:
67
+ You can compose multiple styles through chainable API:
65
68
 
66
69
  ```ruby
67
- pastel.red('Unicorns') + ' will rule ' + pastel.green('the World!')
70
+ pastel.red.on_green.bold('Unicorns!')
68
71
  ```
69
72
 
70
- You can compose multiple styles through chainable API:
73
+ It allows you to combine styled strings with unstyled ones:
71
74
 
72
75
  ```ruby
73
- pastel.red.on_green.bold('Unicorns!')
76
+ pastel.red('Unicorns') + ' will rule ' + pastel.green('the World!')
74
77
  ```
75
78
 
76
79
  It supports variable number of arguments:
@@ -85,6 +88,32 @@ You can also nest styles as follows:
85
88
  pastel.red('Unicorns ', pastel.on_green('everywhere!'))
86
89
  ```
87
90
 
91
+ Nesting is smart enough to know where one color ends and another one starts:
92
+
93
+ ```ruby
94
+ pastel.red('Unicorns ' + pastel.green('everywhere') + pastel.on_yellow('!'))
95
+ ```
96
+
97
+ You can also nest styles inside blocks:
98
+
99
+ ```ruby
100
+ pastel.red.on_green('Unicorns') {
101
+ green.on_red('will ', 'dominate') {
102
+ yellow('the world!')
103
+ }
104
+ }
105
+ ```
106
+
107
+ You can also predefine needed styles and reuse them:
108
+
109
+ ```ruby
110
+ error = pastel.red.on_bold.detach
111
+ warning = pastel.yellow.detach
112
+
113
+ puts error('Error!')
114
+ puts warning('Warning')
115
+ ```
116
+
88
117
  ## 2 Interface
89
118
 
90
119
  ### 2.1 Color
@@ -107,15 +136,25 @@ pastel.decorate('Unicorn', :green, :on_blue, :bold)
107
136
 
108
137
  This method will be useful in situations where colors are provided as a list of parameters.
109
138
 
110
- ### 2.3 Strip
139
+ ### 2.3 Detach
140
+
141
+ The `detach` method allows to keep all the coloring for later reference. This method is useful when detached colors are being resued frequently and thus shorthand version is preferred.
142
+
143
+ ```ruby
144
+ notice = pastel.blue.bold.detach
145
+ puts notice.call('Unicorns running')
146
+ puts notice.call('They are super wild')
147
+ ```
148
+
149
+ ### 2.4 Strip
111
150
 
112
151
  Strip all color sequence characters from the provided strings. The return value will be eithre array of modified strings or a single string. The arguments are not modified.
113
152
 
114
153
  ```ruby
115
- pastel.strip("\e[1m\e[34mbold blue text\e[0m"") # => "bold blue text"
154
+ pastel.strip("\e[1m\e[34mbold blue text\e[0m") # => "bold blue text"
116
155
  ```
117
156
 
118
- ### 2.4 Styles
157
+ ### 2.5 Styles
119
158
 
120
159
  To get a full list of supported styles with the corresponding color codes do:
121
160
 
@@ -123,7 +162,7 @@ To get a full list of supported styles with the corresponding color codes do:
123
162
  pastel.styles
124
163
  ```
125
164
 
126
- ### 2.5 Valid?
165
+ ### 2.6 Valid?
127
166
 
128
167
  Determine whether a color or a list of colors are valid. `valid?` takes one or more attribute strings or symbols and returns true if all attributes are known and false otherwise.
129
168
 
@@ -132,7 +171,7 @@ pastel.valid?(:red, :blue) # => true
132
171
  pastel.valid?(:unicorn) # => false
133
172
  ```
134
173
 
135
- ### 2.6 Enabled?
174
+ ### 2.7 Enabled?
136
175
 
137
176
  In order to detect if your terminal supports coloring do:
138
177
 
@@ -147,7 +186,7 @@ pastel = Pastel.new(enabled: true)
147
186
  pastel.enabled? # => false
148
187
  ```
149
188
 
150
- ### 2.7 Alias Color
189
+ ### 2.8 Alias Color
151
190
 
152
191
  In order to setup an alias for the standard color do:
153
192
 
@@ -231,7 +270,7 @@ This environment variable allows you to specify custom color aliases at runtime
231
270
  Only alphanumeric and `_` are allowed in the alias names with the following format:
232
271
 
233
272
  ```ruby
234
- PASTEL_COLORS_ALIASES='newcolor_1=red,newcolor_2=on_gree'
273
+ PASTEL_COLORS_ALIASES='newcolor_1=red,newcolor_2=on_green'
235
274
  ```
236
275
 
237
276
  ## Contributing
@@ -0,0 +1,26 @@
1
+ require 'pastel'
2
+ require 'benchmark/ips'
3
+
4
+ pastel = Pastel.new
5
+
6
+ Benchmark.ips do |bench|
7
+ bench.config(time: 5, warmup: 2)
8
+
9
+ bench.report('regular nesting') do
10
+ pastel.red.on_green('Unicorns' +
11
+ pastel.green.on_red('will ', 'dominate' + pastel.yellow('the world!')))
12
+ end
13
+
14
+ bench.report('block nesting') do
15
+ pastel.red.on_green('Unicorns') do
16
+ green.on_red('will ', 'dominate') do
17
+ yellow('the world!')
18
+ end
19
+ end
20
+ end
21
+
22
+ bench.compare!
23
+ end
24
+
25
+ # regular nesting: 2800/s
26
+ # block nesting: 2600/s
@@ -6,11 +6,16 @@ pastel = Pastel.new
6
6
  Benchmark.ips do |bench|
7
7
  bench.config(time: 5, warmup: 2)
8
8
 
9
- bench.report('styles') do
10
- pastel.styles
9
+ bench.report('color decorate') do
10
+ pastel.decorate('string', :red, :on_green, :bold)
11
11
  end
12
12
 
13
- bench.report('decorate') do
14
- pastel.decorate('string', :red, :on_green, :bold)
13
+ bench.report('dsl styling') do
14
+ pastel.red.on_green.bold('string')
15
15
  end
16
+
17
+ bench.compare!
16
18
  end
19
+
20
+ # color decorate: 14K/s
21
+ # dsl styling: 10K/s
@@ -8,6 +8,7 @@ require 'pastel/alias_importer'
8
8
  require 'pastel/color'
9
9
  require 'pastel/color_resolver'
10
10
  require 'pastel/delegator'
11
+ require 'pastel/detached'
11
12
  require 'pastel/decorator_chain'
12
13
  require 'pastel/version'
13
14
 
@@ -21,9 +21,12 @@ module Pastel
21
21
  # Resolve uncolored string
22
22
  #
23
23
  # @api private
24
- def resolve(base, *args)
25
- unprocessed_string = args.join
26
- color.decorate(unprocessed_string, *base)
24
+ def resolve(base, unprocessed_string)
25
+ if base.to_a.last == :detach
26
+ Detached.new(color, *base.to_a[0...-1])
27
+ else
28
+ color.decorate(unprocessed_string, *base)
29
+ end
27
30
  end
28
31
  end # ColorResolver
29
32
  end # Pastel
@@ -8,8 +8,6 @@ module Pastel
8
8
  include Enumerable
9
9
  include Equatable
10
10
 
11
- attr_reader :decorators
12
-
13
11
  def initialize(decorators = [])
14
12
  @decorators = decorators
15
13
  end
@@ -36,5 +34,9 @@ module Pastel
36
34
  def self.empty
37
35
  new([])
38
36
  end
37
+
38
+ protected
39
+
40
+ attr_reader :decorators
39
41
  end # DecoratorChain
40
42
  end # Patel
@@ -44,6 +44,9 @@ module Pastel
44
44
 
45
45
  attr_reader :resolver
46
46
 
47
+ # Wrap colors
48
+ #
49
+ # @api private
47
50
  def wrap(base)
48
51
  self.class.new(resolver, base)
49
52
  end
@@ -51,15 +54,25 @@ module Pastel
51
54
  def method_missing(method_name, *args, &block)
52
55
  new_base = base.add(method_name)
53
56
  delegator = wrap(new_base)
54
- if args.empty?
57
+ if args.empty? && !(method_name.to_sym == :detach)
55
58
  delegator
56
59
  else
57
- resolver.resolve(new_base, *args)
60
+ string = args.join
61
+ string << evaluate_block(&block) if block_given?
62
+ resolver.resolve(new_base, string)
58
63
  end
59
64
  end
60
65
 
61
66
  def respond_to_missing?(name, include_all = false)
62
- super || @resolver.color.respond_to?(name, include_all)
67
+ resolver.color.respond_to?(name, include_all) || valid?(name) || super
68
+ end
69
+
70
+ # Evaluate color block
71
+ #
72
+ # @api private
73
+ def evaluate_block(&block)
74
+ delegator = self.class.new(resolver, DecoratorChain.empty)
75
+ delegator.instance_eval(&block)
63
76
  end
64
77
  end # Delegator
65
78
  end # Pastel
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+
3
+ module Pastel
4
+ # A class representing detached color
5
+ class Detached
6
+ include Equatable
7
+
8
+ def initialize(color, *styles)
9
+ @color = color
10
+ @styles = styles.dup
11
+ freeze
12
+ end
13
+
14
+ # Decorate the values corresponding to styles
15
+ #
16
+ # @example
17
+ #
18
+ # @param [String] value
19
+ # the stirng to decorate with styles
20
+ #
21
+ # @return [String]
22
+ #
23
+ # @api public
24
+ def call(*args)
25
+ value = args.join
26
+ @color.decorate(value, *styles)
27
+ end
28
+
29
+ private
30
+
31
+ # @api private
32
+ attr_reader :styles
33
+ end # Detached
34
+ end # Pastel
@@ -1,5 +1,5 @@
1
1
  # coding: utf-8
2
2
 
3
3
  module Pastel
4
- VERSION = "0.3.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -1,5 +1,20 @@
1
1
  # encoding: utf-8
2
2
 
3
+ if RUBY_VERSION > '1.9' and (ENV['COVERAGE'] || ENV['TRAVIS'])
4
+ require 'simplecov'
5
+ require 'coveralls'
6
+
7
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
8
+ SimpleCov::Formatter::HTMLFormatter,
9
+ Coveralls::SimpleCov::Formatter
10
+ ]
11
+
12
+ SimpleCov.start do
13
+ command_name 'spec'
14
+ add_filter 'spec'
15
+ end
16
+ end
17
+
3
18
  require 'pastel'
4
19
 
5
20
  RSpec.configure do |config|
@@ -7,6 +7,11 @@ RSpec.describe Pastel::Color, '.decorate' do
7
7
 
8
8
  subject(:color) { described_class.new(enabled: true) }
9
9
 
10
+ it "doesn't output styling when disabled" do
11
+ color = described_class.new(enabled: false)
12
+ expect(color.decorate('foo', :red)).to eq('foo')
13
+ end
14
+
10
15
  it "doesn't apply styling to empty string" do
11
16
  expect(color.decorate('')).to eq('')
12
17
  end
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Pastel, '.detach' do
6
+
7
+ subject(:pastel) { described_class.new(enabled: true) }
8
+
9
+ it "detaches colors combination" do
10
+ error = pastel.red.bold.detach
11
+ expect(error.call('unicorn')).to eq("\e[31;1municorn\e[0m")
12
+ expect(error.call('error')).to eq("\e[31;1merror\e[0m")
13
+ end
14
+
15
+ it "calls detached colors with no arguments" do
16
+ warning = pastel.yellow.detach
17
+ expect(warning.call('')).to eq('')
18
+ end
19
+
20
+ it "inspects detached colors" do
21
+ warning = pastel.yellow.bold.detach
22
+ expect(warning.inspect).to eq('#<Pastel::Detached styles=[:yellow, :bold]>')
23
+ end
24
+
25
+ it "accepts multiple strings" do
26
+ error = pastel.red.bold.detach
27
+ expect(error.call('Unicorns', ' run ', 'wild')).
28
+ to eq("\e[31;1mUnicorns run wild\e[0m")
29
+ end
30
+ end
@@ -59,6 +59,17 @@ RSpec.describe Pastel do
59
59
  to eq("\e[31mr\e[32mg\e[31mr\e[0m")
60
60
  end
61
61
 
62
+ it "allows to nest styles within block" do
63
+ string = pastel.red.on_green('Unicorns' +
64
+ pastel.green.on_red('will ', 'dominate' + pastel.yellow('the world!')))
65
+
66
+ expect(pastel.red.on_green('Unicorns') do
67
+ green.on_red('will ', 'dominate') do
68
+ yellow('the world!')
69
+ end
70
+ end).to eq(string)
71
+ end
72
+
62
73
  it "raises error when chained with unrecognized color" do
63
74
  expect {
64
75
  pastel.unknown.on_red('unicorn')
@@ -0,0 +1,19 @@
1
+ # coding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ RSpec.describe Pastel, '.respond_to?' do
6
+ subject(:pastel) { described_class.new(enabled: true) }
7
+
8
+ it "responds correctly to color method" do
9
+ expect(pastel.respond_to?(:decorate)).to eq(true)
10
+ end
11
+
12
+ it "responds correctly to color property" do
13
+ expect(pastel.respond_to?(:red)).to eq(true)
14
+ end
15
+
16
+ it "responds correctly to unkown method" do
17
+ expect(pastel.respond_to?(:unknown)).to eq(false)
18
+ end
19
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pastel
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Murach
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-11-08 00:00:00.000000000 Z
11
+ date: 2014-11-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: equatable
@@ -56,6 +56,7 @@ files:
56
56
  - README.md
57
57
  - Rakefile
58
58
  - assets/screenshot.png
59
+ - benchmarks/nesting_speed.rb
59
60
  - benchmarks/speed.rb
60
61
  - lib/pastel.rb
61
62
  - lib/pastel/alias_importer.rb
@@ -64,6 +65,7 @@ files:
64
65
  - lib/pastel/color_resolver.rb
65
66
  - lib/pastel/decorator_chain.rb
66
67
  - lib/pastel/delegator.rb
68
+ - lib/pastel/detached.rb
67
69
  - lib/pastel/version.rb
68
70
  - pastel.gemspec
69
71
  - spec/spec_helper.rb
@@ -77,7 +79,9 @@ files:
77
79
  - spec/unit/color/supports_spec.rb
78
80
  - spec/unit/decorator_chain_spec.rb
79
81
  - spec/unit/delegator_spec.rb
82
+ - spec/unit/detach_spec.rb
80
83
  - spec/unit/new_spec.rb
84
+ - spec/unit/respond_to_spec.rb
81
85
  - tasks/console.rake
82
86
  - tasks/coverage.rake
83
87
  - tasks/spec.rake
@@ -117,5 +121,7 @@ test_files:
117
121
  - spec/unit/color/supports_spec.rb
118
122
  - spec/unit/decorator_chain_spec.rb
119
123
  - spec/unit/delegator_spec.rb
124
+ - spec/unit/detach_spec.rb
120
125
  - spec/unit/new_spec.rb
126
+ - spec/unit/respond_to_spec.rb
121
127
  has_rdoc: