prissy 1.0.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.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in prissy.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Paul Sadauskas
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,110 @@
1
+ # Prissy
2
+
3
+ Pretty prints JSON output with even more prettiness, and focus on readability. Also understands things like terminal width, colors, and HTML.
4
+
5
+ ## Why another one?
6
+
7
+ There's plenty of JSON formatters out there, in tons of languages. While none of them are perfect, this one is special because:
8
+
9
+ * Left-align key names. Column-align the values.
10
+ * When nested objects or arrays are short and simple, keep them in the same line as the key. If they're longer, or contain further nestings, then make them multiline.
11
+ * Terminal width aware, so that things don't wrap if we can help it.
12
+ * Colorized terminal output optional.
13
+ * TODO: (colored) HTML output, so we don't have to roundtrip through yet another syntax library.
14
+
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ gem 'prissy'
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install prissy
29
+
30
+ ## Usage
31
+
32
+ ### From the command line
33
+
34
+ ```
35
+ $ cat example_input.json | prissy
36
+ {
37
+ "array": [
38
+ "one",
39
+ "two",
40
+ "three",
41
+ "four",
42
+ "five",
43
+ "six",
44
+ "seven",
45
+ "eight",
46
+ "nine",
47
+ "ten",
48
+ "eleven",
49
+ "twelve"
50
+ ],
51
+ "false": false,
52
+ "inline_array": ["one", "two", "three"],
53
+ "inline_object": {"foo": "bar"},
54
+ "null": null,
55
+ "number": 42.0,
56
+ "object": {
57
+ "baz": "bax",
58
+ "foo": "bar",
59
+ "more": [1, 2, 3]
60
+ },
61
+ "string": "a text string",
62
+ "true": true
63
+ }
64
+
65
+ $ curl -H "Accept: application/json" https://api.github.com/users/paul | prissy
66
+ {
67
+ "type": "User",
68
+ "avatar_url":
69
+ "https://secure.gravatar.com/avatar/d587890d0fcf8f45724baa8b1bfe1bf4?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png",
70
+ "bio": "",
71
+ "blog": "blog.theamazingrando.com",
72
+ "company": "GitHub",
73
+ "created_at": "2008-02-11T18:44:09Z",
74
+ "email": "psadauskas@gmail.com",
75
+ "followers": 35,
76
+ "following": 1,
77
+ "gravatar_id": "d587890d0fcf8f45724baa8b1bfe1bf4",
78
+ "hireable": false,
79
+ "html_url": "https://github.com/paul",
80
+ "id": 184,
81
+ "location": "Boulder, CO",
82
+ "login": "paul",
83
+ "name": "Paul Sadauskas",
84
+ "public_gists": 322,
85
+ "public_repos": 82,
86
+ "url": "https://api.github.com/users/paul"
87
+ }
88
+ ```
89
+
90
+ ### In Ruby
91
+
92
+ ```ruby
93
+ # The easy way
94
+ Prissy(json_or_hash)
95
+
96
+ # With options
97
+ Prissy.new(width: 120, color: false).prissy(json_or_hash)
98
+ ```
99
+
100
+ ## Output:
101
+
102
+ ![prissy output](https://github-images.s3.amazonaws.com/skitch/2._psadauskas%40Pauls-GitHub-MBP__%7E_Code_personal_prissy_%28zsh%29-20120717-163756.png)
103
+
104
+ ## Contributing
105
+
106
+ 1. Fork it
107
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
108
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
109
+ 4. Push to the branch (`git push origin my-new-feature`)
110
+ 5. Create new Pull Request
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'terminfo'
4
+ $:.unshift(File.expand_path("../../lib", __FILE__))
5
+ require 'prissy'
6
+
7
+
8
+ json = STDIN.read
9
+
10
+ width = TermInfo.screen_width
11
+ has_color = TermInfo.default_object.tigetnum("colors")
12
+
13
+ print Prissy.new(:max_width => width, :color => has_color).prissy(json)
14
+
@@ -0,0 +1,13 @@
1
+
2
+ {
3
+ "inline_array": ["one", "two", "three"],
4
+ "array": [ "one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten", "eleven", "twelve" ],
5
+ "string": "a text string",
6
+ "number": 42.0,
7
+ "true": true,
8
+ "false": false,
9
+ "null": null,
10
+ "inline_object": {"foo": "bar"},
11
+ "object": {"foo": "bar", "baz": "bax", "more": [1,2,3]}
12
+ }
13
+
@@ -0,0 +1,48 @@
1
+ require "prissy/version"
2
+ require 'prissy/printer'
3
+ require 'prissy/color_printer'
4
+
5
+ require 'multi_json'
6
+
7
+
8
+ class Prissy
9
+ attr_reader :options
10
+
11
+ def initialize(options = {})
12
+ defaults = {}
13
+
14
+ @options = defaults.merge(options)
15
+ end
16
+
17
+ def prissy(json_or_hash)
18
+ hash = (json_or_hash.is_a?(String) ? parse(json_or_hash) : json_or_hash)
19
+
20
+ printer.print(hash)
21
+ end
22
+
23
+ protected
24
+
25
+ def parse(json)
26
+ MultiJson.decode(json)
27
+ end
28
+
29
+ def printer
30
+ @printer ||= begin
31
+ if $0 =~ /prissy$/
32
+ if options[:color]
33
+ ColorPrinter.new(options)
34
+ else
35
+ Printer.new(options)
36
+ end
37
+ else
38
+ Printer.new(options)
39
+ end
40
+ end
41
+ end
42
+
43
+
44
+ end
45
+
46
+ def Prissy(json_or_hash)
47
+ Prissy.new.prissy(json_or_hash)
48
+ end
@@ -0,0 +1,34 @@
1
+ require 'term/ansicolor'
2
+
3
+ class Prissy
4
+ class ColorPrinter < Printer
5
+ include Term::ANSIColor
6
+
7
+ def print_string(string, starting_column)
8
+ super blue{string}
9
+ end
10
+
11
+ def print_number(number)
12
+ super yellow{number.to_s}
13
+ end
14
+
15
+ def print_literal(char)
16
+ super green{char}
17
+ end
18
+
19
+ def print_key(key)
20
+ super cyan{key}
21
+ end
22
+
23
+ def print_true
24
+ @txt << green{"true"}
25
+ end
26
+ def print_false
27
+ @txt << green{"false"}
28
+ end
29
+ def print_null
30
+ @txt << green{"null"}
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,149 @@
1
+ class Prissy
2
+ class Printer
3
+ attr_reader :options
4
+
5
+ def initialize(options = {})
6
+ @txt = ""
7
+ @indent = 0
8
+ @options = options
9
+ options[:max_width] ||= 80
10
+ end
11
+
12
+ def print(object)
13
+ print_object(object)
14
+ @txt << "\n"
15
+ end
16
+
17
+ protected
18
+
19
+ def print_object(object, starting_column = 0)
20
+ if object.empty?
21
+ print_literal '{}'
22
+ elsif object.size == 1
23
+ pair = object.first
24
+ print_literal '{'
25
+ print_pair(pair.first, pair.last)
26
+ print_literal '}'
27
+ else
28
+ max_key_width = object.keys.max_by { |k| k.length }.length
29
+ print_literal '{'
30
+ newline!
31
+ @indent += 1
32
+ object.keys.sort.each do |key|
33
+ value = object[key]
34
+ indent!
35
+ print_pair(key, value, max_key_width)
36
+ print_literal ',' unless key == object.keys.sort.last
37
+ newline!
38
+ end
39
+ @indent -= 1
40
+ indent!
41
+ print_literal '}'
42
+ end
43
+ end
44
+
45
+ def print_pair(key, value, max_key_width = 0)
46
+ print_key(key)
47
+ print_separator
48
+ spacing = max_key_width > 0 ? (max_key_width - key.length) : 0
49
+ @txt << " " * spacing
50
+ print_value(value, @indent * 2 + key.length + 4 + spacing )
51
+ end
52
+
53
+ def print_array(array, starting_column = 0)
54
+ # Length of all values, plus quotes, commas, spaces and brackets
55
+ array_length = calculate_array_length(array)
56
+
57
+ if !array.any?{|el| el.is_a?(Hash) || el.is_a?(Array)} &&
58
+ (starting_column + array_length < options[:max_width])
59
+
60
+ print_literal '['
61
+ array.each do |el|
62
+ print_value(el)
63
+ print_literal ', ' unless el == array.last
64
+ end
65
+ print_literal ']'
66
+ else
67
+ print_literal '['
68
+ newline!
69
+ @indent += 1
70
+ array.each do |el|
71
+ indent!
72
+ print_value(el)
73
+ print_literal ',' unless el == array.last
74
+ newline!
75
+ end
76
+ @indent -= 1
77
+ indent!
78
+ print_literal ']'
79
+ end
80
+
81
+ end
82
+
83
+ def print_key(key)
84
+ @txt << %{"#{key.to_s}"}
85
+ end
86
+
87
+ def print_value(value, starting_column = 0)
88
+ case value
89
+ when Array then print_array(value, starting_column)
90
+ when Hash then print_object(value, starting_column)
91
+ when Numeric then print_number(value)
92
+ when String then print_string(value, starting_column)
93
+ when TrueClass then print_true
94
+ when FalseClass then print_false
95
+ when NilClass then print_null
96
+ end
97
+ end
98
+
99
+ # Make all these explicit, so its easier to override them in subclasses
100
+ def print_string(string, starting_column = 0)
101
+ @txt << %{"#{string}"}
102
+ end
103
+
104
+ def print_number(number)
105
+ @txt << number.to_s
106
+ end
107
+
108
+ def print_true
109
+ @txt << "true"
110
+ end
111
+
112
+ def print_false
113
+ @txt << "false"
114
+ end
115
+
116
+ def print_null
117
+ @txt << "null"
118
+ end
119
+
120
+ def print_separator
121
+ @txt << ": "
122
+ end
123
+
124
+ def print_literal(literal)
125
+ @txt << literal
126
+ end
127
+
128
+ def indent!
129
+ @txt << " " * @indent
130
+ end
131
+
132
+ def newline!
133
+ @txt << "\n"
134
+ end
135
+
136
+ def calculate_array_length(array)
137
+ array.inject(0) do |sum, item|
138
+ case item
139
+ when Numeric, TrueClass, FalseClass, NilClass
140
+ sum += item.to_s.length
141
+ when String
142
+ sum += item.length + 2 # "quotes"
143
+ end
144
+ sum += 2 # ", "
145
+ end
146
+ end
147
+
148
+ end
149
+ end
@@ -0,0 +1,3 @@
1
+ class Prissy
2
+ VERSION = "1.0.0"
3
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/prissy/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Paul Sadauskas"]
6
+ gem.email = ["psadauskas@gmail.com"]
7
+ gem.description = %q{Even prettier JSON console output}
8
+ gem.summary = %q{Nicely format JSON}
9
+ gem.homepage = "https://github.com/paul/prissy"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "prissy"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Prissy::VERSION
17
+
18
+ gem.add_development_dependency "rspec", "~> 2.11"
19
+
20
+ gem.add_dependency "multi_json", "~> 1.3"
21
+
22
+ gem.add_dependency "options", "~> 2.3.0"
23
+ gem.add_dependency "term-ansicolor", "~> 1.0.7"
24
+ gem.add_dependency "ruby-terminfo", "~> 0.1.1"
25
+ end
@@ -0,0 +1,36 @@
1
+ require 'spec_helper'
2
+
3
+ describe Prissy, "the easy way" do
4
+ let(:json) { <<-JSON }
5
+ {
6
+ "Image": {
7
+ "Width": 800,
8
+ "Height": 600,
9
+ "Title": "View from 15th Floor",
10
+ "Thumbnail": {
11
+ "Url": "http://www.example.com/image/481989943",
12
+ "Height": 125,
13
+ "Width": "100"
14
+ },
15
+ "IDs": [116, 943, 234, 38793]
16
+ }
17
+ }
18
+ JSON
19
+
20
+ subject { Prissy(json) }
21
+
22
+ it { should look_like(<<-JSON.strip) }
23
+ {"Image": {
24
+ "Height": 600,
25
+ "IDs": [116, 943, 234, 38793],
26
+ "Thumbnail": {
27
+ "Height": 125,
28
+ "Url": "http://www.example.com/image/481989943",
29
+ "Width": "100"
30
+ },
31
+ "Title": "View from 15th Floor",
32
+ "Width": 800
33
+ }}
34
+ JSON
35
+ end
36
+
@@ -0,0 +1,21 @@
1
+ require 'prissy'
2
+
3
+ RSpec.configure do |config|
4
+ config.treat_symbols_as_metadata_keys_with_true_values = true
5
+ config.run_all_when_everything_filtered = true
6
+ config.filter_run :focus
7
+
8
+ # Run specs in random order to surface order dependencies. If you find an
9
+ # order dependency and want to debug it, you can fix the order by providing
10
+ # the seed, which is printed after each run.
11
+ # --seed 1234
12
+ #config.order = 'random'
13
+ end
14
+
15
+ RSpec::Matchers.define(:look_like) do |expected|
16
+ match do |actual|
17
+ actual.strip == expected.strip
18
+ end
19
+
20
+ diffable
21
+ end
@@ -0,0 +1,102 @@
1
+ require 'spec_helper'
2
+
3
+ describe Prissy::Printer do
4
+
5
+ subject { Prissy::Printer.new.print(object) }
6
+
7
+ describe "an empty object" do
8
+ let(:object) { {} }
9
+ it { should look_like '{}' }
10
+ end
11
+
12
+ describe "a simple object" do
13
+ let(:object) { {"foo" => "bar"} }
14
+ it { should look_like '{"foo": "bar"}' }
15
+ end
16
+
17
+ describe "an object with multiple keys" do
18
+ let(:object) { {"foo" => "bar", "x" => "y" } }
19
+ it { should look_like <<-STR.strip }
20
+ {
21
+ "foo": "bar",
22
+ "x": "y"
23
+ }
24
+ STR
25
+ end
26
+
27
+ describe "an object with simple nested objects" do
28
+ let(:object) { {"foo" => "bar", "other" => {"subkey" => "subvalue"}} }
29
+ it { should look_like <<-STR.strip }
30
+ {
31
+ "foo": "bar",
32
+ "other": {"subkey": "subvalue"}
33
+ }
34
+ STR
35
+ end
36
+
37
+ describe "an object with multiple nested objects" do
38
+ let(:object) { {"foo" => "bar", "other" => {"a" => "b", "c" => "d"}} }
39
+ it { should look_like <<-STR.strip }
40
+ {
41
+ "foo": "bar",
42
+ "other": {
43
+ "a": "b",
44
+ "c": "d"
45
+ }
46
+ }
47
+ STR
48
+ end
49
+
50
+ describe "an object with a short array" do
51
+ let(:object) { {"stooges" => %w[Moe Larry Curly] } }
52
+ it { should look_like <<-STR.strip }
53
+ {"stooges": ["Moe", "Larry", "Curly"]}
54
+ STR
55
+ end
56
+
57
+ describe "an object with a long array" do
58
+ let(:object) { {"dwarves" => %w[ Fili Kili Oin Gloin Thorin Dwalin Balin Bifur Bofur Bombur Dori Nori Ori ]} }
59
+ it { should look_like <<-STR.strip }
60
+ {"dwarves": [
61
+ "Fili",
62
+ "Kili",
63
+ "Oin",
64
+ "Gloin",
65
+ "Thorin",
66
+ "Dwalin",
67
+ "Balin",
68
+ "Bifur",
69
+ "Bofur",
70
+ "Bombur",
71
+ "Dori",
72
+ "Nori",
73
+ "Ori"
74
+ ]}
75
+ STR
76
+ end
77
+
78
+ describe "basic types" do
79
+ let(:object) { {
80
+ "string" => "string",
81
+ "number" => 42.0,
82
+ "object" => {"foo" => "bar"},
83
+ "array" => [1, 2, 3],
84
+ "true" => true,
85
+ "false" => false,
86
+ "null" => nil
87
+ } }
88
+ it { should look_like <<-STR.strip }
89
+ {
90
+ "array": [1, 2, 3],
91
+ "false": false,
92
+ "null": null,
93
+ "number": 42.0,
94
+ "object": {"foo": "bar"},
95
+ "string": "string",
96
+ "true": true
97
+ }
98
+ STR
99
+ end
100
+
101
+ end
102
+
metadata ADDED
@@ -0,0 +1,145 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: prissy
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Paul Sadauskas
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-07-17 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ~>
20
+ - !ruby/object:Gem::Version
21
+ version: '2.11'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ version: '2.11'
30
+ - !ruby/object:Gem::Dependency
31
+ name: multi_json
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '1.3'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '1.3'
46
+ - !ruby/object:Gem::Dependency
47
+ name: options
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 2.3.0
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 2.3.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: term-ansicolor
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 1.0.7
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 1.0.7
78
+ - !ruby/object:Gem::Dependency
79
+ name: ruby-terminfo
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 0.1.1
86
+ type: :runtime
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 0.1.1
94
+ description: Even prettier JSON console output
95
+ email:
96
+ - psadauskas@gmail.com
97
+ executables:
98
+ - prissy
99
+ extensions: []
100
+ extra_rdoc_files: []
101
+ files:
102
+ - .gitignore
103
+ - .rspec
104
+ - Gemfile
105
+ - LICENSE
106
+ - README.md
107
+ - Rakefile
108
+ - bin/prissy
109
+ - example_input.json
110
+ - lib/prissy.rb
111
+ - lib/prissy/color_printer.rb
112
+ - lib/prissy/printer.rb
113
+ - lib/prissy/version.rb
114
+ - prissy.gemspec
115
+ - spec/acceptance/the_easy_way_spec.rb
116
+ - spec/spec_helper.rb
117
+ - spec/unit/plain_printer_spec.rb
118
+ homepage: https://github.com/paul/prissy
119
+ licenses: []
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ none: false
126
+ requirements:
127
+ - - ! '>='
128
+ - !ruby/object:Gem::Version
129
+ version: '0'
130
+ required_rubygems_version: !ruby/object:Gem::Requirement
131
+ none: false
132
+ requirements:
133
+ - - ! '>='
134
+ - !ruby/object:Gem::Version
135
+ version: '0'
136
+ requirements: []
137
+ rubyforge_project:
138
+ rubygems_version: 1.8.23
139
+ signing_key:
140
+ specification_version: 3
141
+ summary: Nicely format JSON
142
+ test_files:
143
+ - spec/acceptance/the_easy_way_spec.rb
144
+ - spec/spec_helper.rb
145
+ - spec/unit/plain_printer_spec.rb