lovely_rufus 0.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 +7 -0
- data/.rubocop.yml +20 -0
- data/.ruby-version +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +48 -0
- data/LICENCE +661 -0
- data/README.md +67 -0
- data/Rakefile +18 -0
- data/bin/lovely-rufus +4 -0
- data/config/reek.yml +14 -0
- data/lib/lovely_rufus/basic_wrapper.rb +17 -0
- data/lib/lovely_rufus/cli_wrapper.rb +30 -0
- data/lib/lovely_rufus/hangout_wrapper.rb +32 -0
- data/lib/lovely_rufus/layer.rb +12 -0
- data/lib/lovely_rufus/one_letter_gluer.rb +7 -0
- data/lib/lovely_rufus/quote_stripper.rb +27 -0
- data/lib/lovely_rufus/text_wrapper.rb +29 -0
- data/lib/lovely_rufus/wrap.rb +10 -0
- data/lib/lovely_rufus.rb +13 -0
- data/lovely_rufus.gemspec +20 -0
- data/spec/lovely_rufus/basic_wrapper_spec.rb +43 -0
- data/spec/lovely_rufus/cli_wrapper_spec.rb +27 -0
- data/spec/lovely_rufus/hangout_wrapper_spec.rb +25 -0
- data/spec/lovely_rufus/one_letter_gluer_spec.rb +26 -0
- data/spec/lovely_rufus/quote_stripper_spec.rb +113 -0
- data/spec/lovely_rufus/text_wrapper_spec.rb +40 -0
- data/spec/lovely_rufus/text_wrapper_spec.yml +166 -0
- data/spec/lovely_rufus/wrap_spec.rb +27 -0
- data/spec/spec_helper.rb +15 -0
- metadata +150 -0
data/README.md
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
Lovely Rufus
|
2
|
+
============
|
3
|
+
|
4
|
+
Lovely Rufus is an executable and a Ruby library for wrapping paragraphs of text in the spirit of [Par](http://www.nicemice.net/par/).
|
5
|
+
|
6
|
+
|
7
|
+
|
8
|
+
Usage
|
9
|
+
-----
|
10
|
+
|
11
|
+
Lovely Rufus can be used from the command-line by piping text through the `lovely-rufus` executable:
|
12
|
+
|
13
|
+
$ echo 'The Ballyshannon foundered off the coast of Cariboo, And down in fathoms many went the captain and the crew;' | lovely-rufus
|
14
|
+
The Ballyshannon foundered off the coast of Cariboo,
|
15
|
+
And down in fathoms many went the captain and the crew;
|
16
|
+
|
17
|
+
Lovely Rufus can also be used from Ruby code through the `TextWrapper` class:
|
18
|
+
|
19
|
+
$ irb
|
20
|
+
>> require 'lovely_rufus'
|
21
|
+
>> text = 'The Ballyshannon foundered off the coast of Cariboo, And down in fathoms many went the captain and the crew;'
|
22
|
+
>> puts LovelyRufus::TextWrapper.wrap text
|
23
|
+
The Ballyshannon foundered off the coast of Cariboo,
|
24
|
+
And down in fathoms many went the captain and the crew;
|
25
|
+
|
26
|
+
Note that `TextWrapper.wrap` can take optional desired width:
|
27
|
+
|
28
|
+
$ irb
|
29
|
+
>> require 'lovely_rufus'
|
30
|
+
>> text = 'The Ballyshannon foundered off the coast of Cariboo, And down in fathoms many went the captain and the crew;'
|
31
|
+
>> puts LovelyRufus::TextWrapper.wrap text, width: 15
|
32
|
+
The
|
33
|
+
Ballyshannon
|
34
|
+
foundered off
|
35
|
+
the coast of
|
36
|
+
Cariboo, And
|
37
|
+
down in fathoms
|
38
|
+
many went the
|
39
|
+
captain and
|
40
|
+
the crew;
|
41
|
+
|
42
|
+
|
43
|
+
|
44
|
+
Features
|
45
|
+
--------
|
46
|
+
|
47
|
+
Currently, Lovely Rufus sports the following features:
|
48
|
+
|
49
|
+
* paragraphs are wrapped to the specified width,
|
50
|
+
* one-letter words are not left at ends of lines,
|
51
|
+
* email quotes (`>`) are handled properly and normalised (`> > >` → `>>>`),
|
52
|
+
* email-quoted paragraph breaks are cleared,
|
53
|
+
* code comments (starting with `#` and `//`) are handled properly,
|
54
|
+
* multiple paragraphs are wrapped independently.
|
55
|
+
|
56
|
+
|
57
|
+
|
58
|
+
Name and history
|
59
|
+
----------------
|
60
|
+
|
61
|
+
Lovely Rufus was created as a [Ruby Mendicant University](http://blog.majesticseacreature.com/tag/rubymendicant) project and is named after [a certain _Love Actually_ character](http://en.wikipedia.org/wiki/Love_Actually#Rufus) who’s [exceptionally good at wrapping](http://www.youtube.com/watch?v=W6E1wPwOaE4).
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
---
|
66
|
+
|
67
|
+
© MMX-MMXIV Piotr Szotkowski <chastell@chastell.net>, licensed under AGPL-3.0 (see LICENCE)
|
data/Rakefile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rake/testtask'
|
2
|
+
require 'reek/rake/task'
|
3
|
+
require 'rubocop/rake_task'
|
4
|
+
|
5
|
+
task default: %i[spec rubocop reek]
|
6
|
+
|
7
|
+
Rake::TestTask.new :spec do |task|
|
8
|
+
task.test_files = FileList['spec/**/*_spec.rb']
|
9
|
+
task.warning = true
|
10
|
+
end
|
11
|
+
|
12
|
+
Reek::Rake::Task.new do |task|
|
13
|
+
task.config_files = 'config/reek.yml'
|
14
|
+
task.fail_on_error = false
|
15
|
+
task.reek_opts = '--quiet'
|
16
|
+
end
|
17
|
+
|
18
|
+
Rubocop::RakeTask.new
|
data/bin/lovely-rufus
ADDED
data/config/reek.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
IrresponsibleModule:
|
2
|
+
enabled: false
|
3
|
+
|
4
|
+
NestedIterators:
|
5
|
+
max_allowed_nesting: 2
|
6
|
+
|
7
|
+
UncommunicativeVariableName:
|
8
|
+
exclude:
|
9
|
+
- LovelyRufus::HangoutWrapper#hangout_line
|
10
|
+
|
11
|
+
UnusedParameters:
|
12
|
+
exclude:
|
13
|
+
- LovelyRufus::Layer#call
|
14
|
+
- LovelyRufus::OneLetterGluer#call
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module LovelyRufus class BasicWrapper < Layer
|
2
|
+
def call wrap
|
3
|
+
@wrap = wrap
|
4
|
+
wrapped = chopped.gsub(/(.{1,#{wrap.width}})( |$\n?)/, "\\1\n")
|
5
|
+
next_layer.call Wrap[wrapped, width: wrap.width]
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :wrap
|
9
|
+
private :wrap
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def chopped
|
14
|
+
words = wrap.text.split
|
15
|
+
words.map { |word| word.gsub(/(.{1,#{wrap.width}})/, '\\1 ') }.join.chop
|
16
|
+
end
|
17
|
+
end end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
module LovelyRufus class CLIWrapper
|
4
|
+
def initialize args = ARGV, text_wrapper: TextWrapper
|
5
|
+
@settings = Settings.new args
|
6
|
+
@text_wrapper = text_wrapper
|
7
|
+
end
|
8
|
+
|
9
|
+
def run stream = $stdin
|
10
|
+
puts text_wrapper.wrap stream.read, width: settings.width
|
11
|
+
end
|
12
|
+
|
13
|
+
attr_reader :settings, :text_wrapper
|
14
|
+
private :settings, :text_wrapper
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
class Settings
|
19
|
+
attr_reader :width
|
20
|
+
|
21
|
+
def initialize args
|
22
|
+
@width = 72
|
23
|
+
OptionParser.new do |opts|
|
24
|
+
opts.on '-w', '--width WIDTH', Integer, 'Wrapping width' do |width|
|
25
|
+
@width = width
|
26
|
+
end
|
27
|
+
end.parse! args
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module LovelyRufus class HangoutWrapper < Layer
|
2
|
+
def call wrap
|
3
|
+
@wrap = wrap
|
4
|
+
final = hangout_line ? rewrapped : wrap.text
|
5
|
+
next_layer.call Wrap[final, width: wrap.width]
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :wrap
|
9
|
+
private :wrap
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def hangout_line
|
14
|
+
lines.each_cons 2 do |a, b|
|
15
|
+
return a if a[/\p{space}/] and a.rindex(/\p{space}/) >= b.size
|
16
|
+
unless b == lines.last
|
17
|
+
return b if b[/\p{space}/] and b.rindex(/\p{space}/) >= a.size
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def lines
|
23
|
+
@lines ||= wrap.text.lines.map(&:chomp)
|
24
|
+
end
|
25
|
+
|
26
|
+
def rewrapped
|
27
|
+
hangout_line << NBSP
|
28
|
+
unfolded = lines.join(' ').gsub("#{NBSP} ", NBSP)
|
29
|
+
wrapped = BasicWrapper.new.call(Wrap[unfolded, width: wrap.width]).text
|
30
|
+
HangoutWrapper.new.call(Wrap[wrapped, width: wrap.width]).text
|
31
|
+
end
|
32
|
+
end end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module LovelyRufus class QuoteStripper < Layer
|
2
|
+
def call wrap
|
3
|
+
@wrap = wrap
|
4
|
+
wrapped = next_layer.call stripped_wrap
|
5
|
+
quoted = wrapped.text.lines.map { |line| fixed_quote + line }.join
|
6
|
+
Wrap[quoted, width: wrapped.width + fixed_quote.size]
|
7
|
+
end
|
8
|
+
|
9
|
+
attr_reader :wrap
|
10
|
+
private :wrap
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def fixed_quote
|
15
|
+
quote.size > 0 ? quote.delete(' ') + ' ' : ''
|
16
|
+
end
|
17
|
+
|
18
|
+
def quote
|
19
|
+
starts = wrap.text.lines.map { |line| line[/^#{QUOTES}/] }.uniq
|
20
|
+
starts.size == 1 ? starts.first || '' : ''
|
21
|
+
end
|
22
|
+
|
23
|
+
def stripped_wrap
|
24
|
+
stripped_text = wrap.text.lines.map { |line| line[quote.size..-1] }.join
|
25
|
+
Wrap[stripped_text, width: wrap.width - fixed_quote.size]
|
26
|
+
end
|
27
|
+
end end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module LovelyRufus class TextWrapper
|
2
|
+
def self.wrap text, width: 72
|
3
|
+
new(Wrap[text, width: width]).call
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize wrap
|
7
|
+
@wrap = wrap
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
paras.map do |para|
|
12
|
+
chain.call(Wrap[para, width: wrap.width]).text.tr NBSP, ' '
|
13
|
+
end.join "\n"
|
14
|
+
end
|
15
|
+
|
16
|
+
attr_reader :wrap
|
17
|
+
private :wrap
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def chain
|
22
|
+
layers = [QuoteStripper, OneLetterGluer, BasicWrapper, HangoutWrapper]
|
23
|
+
layers.reverse.reduce(-> wrap { wrap }) { |inner, outer| outer.new inner }
|
24
|
+
end
|
25
|
+
|
26
|
+
def paras
|
27
|
+
wrap.text.split(/\n#{QUOTES}?\n/).reject { |para| para[/^#{QUOTES}?$/] }
|
28
|
+
end
|
29
|
+
end end
|
data/lib/lovely_rufus.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require_relative 'lovely_rufus/layer'
|
2
|
+
require_relative 'lovely_rufus/basic_wrapper'
|
3
|
+
require_relative 'lovely_rufus/cli_wrapper'
|
4
|
+
require_relative 'lovely_rufus/hangout_wrapper'
|
5
|
+
require_relative 'lovely_rufus/one_letter_gluer'
|
6
|
+
require_relative 'lovely_rufus/quote_stripper'
|
7
|
+
require_relative 'lovely_rufus/text_wrapper'
|
8
|
+
require_relative 'lovely_rufus/wrap'
|
9
|
+
|
10
|
+
module LovelyRufus
|
11
|
+
NBSP = "\u00A0"
|
12
|
+
QUOTES = %r{[>/#][>/# ]*}
|
13
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
Gem::Specification.new do |gem|
|
2
|
+
gem.author = 'Piotr Szotkowski'
|
3
|
+
gem.description = 'An executable and a Ruby library for wrapping paragraphs of text.'
|
4
|
+
gem.email = 'chastell@chastell.net'
|
5
|
+
gem.homepage = 'http://github.com/chastell/lovely_rufus'
|
6
|
+
gem.license = 'AGPL-3.0'
|
7
|
+
gem.name = 'lovely_rufus'
|
8
|
+
gem.summary = 'lovely_rufus: text wrapper'
|
9
|
+
gem.version = '0.1.0'
|
10
|
+
|
11
|
+
gem.files = `git ls-files -z`.split "\0"
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map { |path| File.basename path }
|
13
|
+
gem.test_files = gem.files.grep %r{^spec/.*\.rb$}
|
14
|
+
|
15
|
+
gem.add_development_dependency 'bogus', '~> 0.1.4'
|
16
|
+
gem.add_development_dependency 'minitest', '~> 5.0'
|
17
|
+
gem.add_development_dependency 'minitest-focus', '~> 1.1'
|
18
|
+
gem.add_development_dependency 'reek', '~> 1.3'
|
19
|
+
gem.add_development_dependency 'rubocop', '~> 0.18.0'
|
20
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
module LovelyRufus describe BasicWrapper do
|
4
|
+
describe '#call' do
|
5
|
+
it 'wraps text to the given width' do
|
6
|
+
text = 'I go crazy when I hear a cymbal and a hi-hat ' \
|
7
|
+
'with a souped-up tempo'
|
8
|
+
wrap = <<-end.dedent
|
9
|
+
I go crazy when I hear
|
10
|
+
a cymbal and a hi-hat
|
11
|
+
with a souped-up tempo
|
12
|
+
end
|
13
|
+
bw = BasicWrapper.new
|
14
|
+
bw.call(Wrap[text, width: 22]).must_equal Wrap[wrap, width: 22]
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'never extends past the given width, chopping words if necessary' do
|
18
|
+
text = 'I’m killing your brain like a poisonous mushroom'
|
19
|
+
wrap = <<-end.dedent
|
20
|
+
I’m
|
21
|
+
killi
|
22
|
+
ng
|
23
|
+
your
|
24
|
+
brain
|
25
|
+
like
|
26
|
+
a
|
27
|
+
poiso
|
28
|
+
nous
|
29
|
+
mushr
|
30
|
+
oom
|
31
|
+
end
|
32
|
+
bw = BasicWrapper.new
|
33
|
+
bw.call(Wrap[text, width: 5]).must_equal Wrap[wrap, width: 5]
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'passes the fixed text to the next layer and returns its outcome' do
|
37
|
+
final = fake :wrap
|
38
|
+
layer = fake :layer
|
39
|
+
mock(layer).call(Wrap["I\nO\nU\n", width: 2]) { final }
|
40
|
+
BasicWrapper.new(layer).call(Wrap['I O U', width: 2]).must_equal final
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
module LovelyRufus describe CLIWrapper do
|
4
|
+
describe '#run' do
|
5
|
+
let(:text) { "all right: stop, collaborate and listen\n" }
|
6
|
+
let(:text_wrapper) { fake :text_wrapper, as: :class }
|
7
|
+
|
8
|
+
it 'reads the passed stream to TextWrapper and prints the results' do
|
9
|
+
stub(text_wrapper).wrap(text, width: 72) { text }
|
10
|
+
lambda do
|
11
|
+
CLIWrapper.new(text_wrapper: text_wrapper).run StringIO.new text
|
12
|
+
end.must_output text
|
13
|
+
end
|
14
|
+
|
15
|
+
it 'accepts the desired width and passes it to TextWrapper' do
|
16
|
+
wrap = <<-end.dedent
|
17
|
+
all right: stop,
|
18
|
+
collaborate and listen
|
19
|
+
end
|
20
|
+
stub(text_wrapper).wrap(text, width: 22) { wrap }
|
21
|
+
lambda do
|
22
|
+
stream = StringIO.new text
|
23
|
+
CLIWrapper.new(%w[--width 22], text_wrapper: text_wrapper).run stream
|
24
|
+
end.must_output wrap
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
module LovelyRufus describe HangoutWrapper do
|
4
|
+
describe '#call' do
|
5
|
+
it 'removes hangouts from the text' do
|
6
|
+
text = <<-end.dedent
|
7
|
+
I go crazy when I hear a cymbal and
|
8
|
+
a hi-hat with a souped-up tempo
|
9
|
+
end
|
10
|
+
wrap = <<-end.dedent
|
11
|
+
I go crazy when I hear a cymbal
|
12
|
+
and a hi-hat with a souped-up tempo
|
13
|
+
end
|
14
|
+
hw = HangoutWrapper.new
|
15
|
+
hw.call(Wrap[text, width: 35]).must_equal Wrap[wrap, width: 35]
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'passes the fixed text to the next layer and returns its outcome' do
|
19
|
+
final = fake :wrap
|
20
|
+
layer = fake :layer
|
21
|
+
mock(layer).call(any Wrap) { final }
|
22
|
+
HangoutWrapper.new(layer).call(Wrap["I O\nU", width: 4]).must_equal final
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
module LovelyRufus describe OneLetterGluer do
|
4
|
+
describe '#call' do
|
5
|
+
it 'replaces spaces after one-letter words with non-break spaces' do
|
6
|
+
text = 'I go crazy when I hear a cymbal and a hi-hat'
|
7
|
+
glue = 'I go crazy when I hear a cymbal and a hi-hat'
|
8
|
+
olg = OneLetterGluer.new
|
9
|
+
olg.call(Wrap[text, width: 42]).must_equal Wrap[glue, width: 42]
|
10
|
+
end
|
11
|
+
|
12
|
+
it 'glues subsequent one-letter words' do
|
13
|
+
text = 'one-letter words in English: a, I & o'
|
14
|
+
glue = 'one-letter words in English: a, I & o'
|
15
|
+
olg = OneLetterGluer.new
|
16
|
+
olg.call(Wrap[text, width: 42]).must_equal Wrap[glue, width: 42]
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'passes the fixed text to the next layer and returns its outcome' do
|
20
|
+
final = fake :wrap
|
21
|
+
layer = fake :layer
|
22
|
+
mock(layer).call(Wrap['I O U', width: 69]) { final }
|
23
|
+
OneLetterGluer.new(layer).call(Wrap['I O U', width: 69]).must_equal final
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
module LovelyRufus describe QuoteStripper do
|
4
|
+
describe '#call' do
|
5
|
+
it 'strips quotes and adjusts width before calling the next layer' do
|
6
|
+
quoted = <<-end.dedent
|
7
|
+
> to the extreme I rock a mic like a vandal
|
8
|
+
> light up a stage and wax a chump like a candle
|
9
|
+
end
|
10
|
+
unquoted = <<-end.dedent
|
11
|
+
to the extreme I rock a mic like a vandal
|
12
|
+
light up a stage and wax a chump like a candle
|
13
|
+
end
|
14
|
+
layer = fake :layer, call: Wrap[unquoted, width: 70]
|
15
|
+
QuoteStripper.new(layer).call Wrap[quoted, width: 72]
|
16
|
+
layer.must_have_received :call, [Wrap[unquoted, width: 70]]
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'adds quotes back in (and adjusts width) before returning' do
|
20
|
+
quoted = <<-end.dedent
|
21
|
+
> take heed, ’cause I’m a lyrical poet
|
22
|
+
> Miami’s on the scene just in case you didn’t know it
|
23
|
+
end
|
24
|
+
wrap = Wrap[quoted, width: 72]
|
25
|
+
QuoteStripper.new.call(wrap).must_equal wrap
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'does not touch non-quoted texts' do
|
29
|
+
plain = <<-end.dedent
|
30
|
+
my town, that created all the bass sound
|
31
|
+
enough to shake and kick holes in the ground
|
32
|
+
end
|
33
|
+
wrap = Wrap[plain, width: 72]
|
34
|
+
QuoteStripper.new.call(wrap).must_equal wrap
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'does not alter text contents' do
|
38
|
+
wrap = Wrap['> foo > bar']
|
39
|
+
QuoteStripper.new.call(wrap).must_equal wrap
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'strips multilevel quotes' do
|
43
|
+
quoted = <<-end.dedent
|
44
|
+
>> ’cause my style’s like a chemical spill
|
45
|
+
>> feasible rhymes that you can vision and feel
|
46
|
+
end
|
47
|
+
unquoted = <<-end.dedent
|
48
|
+
’cause my style’s like a chemical spill
|
49
|
+
feasible rhymes that you can vision and feel
|
50
|
+
end
|
51
|
+
layer = fake :layer, call: Wrap[unquoted, width: 69]
|
52
|
+
QuoteStripper.new(layer).call Wrap[quoted, width: 72]
|
53
|
+
layer.must_have_received :call, [Wrap[unquoted, width: 69]]
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'strips broken quotes properly' do
|
57
|
+
quoted = <<-end.dedent
|
58
|
+
> > >conducted and formed this is a hell of a concept
|
59
|
+
> > >we make it hype and you want to step with this
|
60
|
+
end
|
61
|
+
unquoted = <<-end.dedent
|
62
|
+
conducted and formed this is a hell of a concept
|
63
|
+
we make it hype and you want to step with this
|
64
|
+
end
|
65
|
+
layer = fake :layer, call: Wrap[unquoted, width: 68]
|
66
|
+
QuoteStripper.new(layer).call Wrap[quoted, width: 72]
|
67
|
+
layer.must_have_received :call, [Wrap[unquoted, width: 68]]
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'fixes broken quotes when adding them back in' do
|
71
|
+
quoted = <<-end.dedent
|
72
|
+
> > >Shay plays on the fade,
|
73
|
+
> > >slice like a ninja
|
74
|
+
> > >cut like a razor blade
|
75
|
+
end
|
76
|
+
fixed = <<-end.dedent
|
77
|
+
>>> Shay plays on the fade,
|
78
|
+
>>> slice like a ninja
|
79
|
+
>>> cut like a razor blade
|
80
|
+
end
|
81
|
+
wrap = Wrap[quoted, width: 72]
|
82
|
+
QuoteStripper.new.call(wrap).must_equal Wrap[fixed, width: 72]
|
83
|
+
end
|
84
|
+
|
85
|
+
it 'strips // code comments' do
|
86
|
+
quoted = <<-end.dedent
|
87
|
+
// so fast other DJs say ‘damn!’
|
88
|
+
// if my rhyme was a drug I’d sell it by the gram
|
89
|
+
end
|
90
|
+
unquoted = <<-end.dedent
|
91
|
+
so fast other DJs say ‘damn!’
|
92
|
+
if my rhyme was a drug I’d sell it by the gram
|
93
|
+
end
|
94
|
+
layer = fake :layer, call: Wrap[unquoted, width: 69]
|
95
|
+
QuoteStripper.new(layer).call Wrap[quoted, width: 72]
|
96
|
+
layer.must_have_received :call, [Wrap[unquoted, width: 69]]
|
97
|
+
end
|
98
|
+
|
99
|
+
it 'strips # code comments' do
|
100
|
+
quoted = <<-end.dedent
|
101
|
+
# keep my composure when it’s time to get loose
|
102
|
+
# magnetized by the mic while I kick my juice
|
103
|
+
end
|
104
|
+
unquoted = <<-end.dedent
|
105
|
+
keep my composure when it’s time to get loose
|
106
|
+
magnetized by the mic while I kick my juice
|
107
|
+
end
|
108
|
+
layer = fake :layer, call: Wrap[unquoted, width: 70]
|
109
|
+
QuoteStripper.new(layer).call Wrap[quoted, width: 72]
|
110
|
+
layer.must_have_received :call, [Wrap[unquoted, width: 70]]
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require_relative '../spec_helper'
|
2
|
+
|
3
|
+
module LovelyRufus describe TextWrapper do
|
4
|
+
describe '.wrap' do
|
5
|
+
it 'wraps the passed String to 72 characters by default' do
|
6
|
+
short = 'all right: stop, collaborate and listen'
|
7
|
+
long = short + ' – Ice is back with a brand new invention'
|
8
|
+
wrap = <<-end.dedent
|
9
|
+
all right: stop, collaborate and listen
|
10
|
+
– Ice is back with a brand new invention
|
11
|
+
end
|
12
|
+
TextWrapper.wrap(short).must_equal "#{short}\n"
|
13
|
+
TextWrapper.wrap(long).must_equal wrap
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'wraps the passed String to the given number of characters' do
|
17
|
+
input = 'something grabs a hold of me tightly; ' \
|
18
|
+
'flow like a harpoon – daily and nightly'
|
19
|
+
TextWrapper.wrap(input, width: 40).must_equal <<-end.dedent
|
20
|
+
something grabs a hold of me tightly;
|
21
|
+
flow like a harpoon – daily and nightly
|
22
|
+
end
|
23
|
+
TextWrapper.wrap(input, width: 21).must_equal <<-end.dedent
|
24
|
+
something grabs
|
25
|
+
a hold of me tightly;
|
26
|
+
flow like a harpoon
|
27
|
+
– daily and nightly
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'supports all the example use-cases' do
|
32
|
+
path = File.expand_path 'text_wrapper_spec.yml', __dir__
|
33
|
+
YAML.load_file(path).each do |spec|
|
34
|
+
width = spec.fetch('width') { 72 }
|
35
|
+
wrap = "#{spec['output']}\n"
|
36
|
+
TextWrapper.wrap(spec['input'], width: width).must_equal wrap
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end end
|