lovely_rufus 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|