lovely-rufus 0.0.4 → 0.0.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- metadata +54 -33
- data/.rubocop.yml +0 -23
- data/.ruby-version +0 -1
- data/Gemfile +0 -2
- data/Gemfile.lock +0 -39
- data/LICENCE +0 -661
- data/README.md +0 -70
- data/Rakefile +0 -18
- data/bin/lovely-rufus +0 -4
- data/config/reek.yml +0 -0
- data/lib/lovely-rufus.rb +0 -5
- data/lib/lovely-rufus/executable.rb +0 -25
- data/lib/lovely-rufus/wrapper.rb +0 -93
- data/lovely-rufus.gemspec +0 -14
- data/spec/fixtures/wrapper.yml +0 -188
- data/spec/lovely-rufus/executable_spec.rb +0 -25
- data/spec/lovely-rufus/wrapper_spec.rb +0 -26
- data/spec/spec_helper.rb +0 -5
data/README.md
DELETED
@@ -1,70 +0,0 @@
|
|
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
|
-
|
18
|
-
Lovely Rufus can also be used from Ruby code through the `Wrapper` class:
|
19
|
-
|
20
|
-
$ irb
|
21
|
-
>> require 'lovely-rufus'
|
22
|
-
>> text = 'The Ballyshannon foundered off the coast of Cariboo, And down in fathoms many went the captain and the crew;'
|
23
|
-
>> puts LovelyRufus::Wrapper.new(text).wrapped
|
24
|
-
The Ballyshannon foundered off the coast of Cariboo,
|
25
|
-
And down in fathoms many went the captain and the crew;
|
26
|
-
>>
|
27
|
-
|
28
|
-
Note that `Wrapper#wrapped` can take optional desired width:
|
29
|
-
|
30
|
-
$ irb
|
31
|
-
>> require 'lovely-rufus'
|
32
|
-
>> text = 'The Ballyshannon foundered off the coast of Cariboo, And down in fathoms many went the captain and the crew;'
|
33
|
-
>> puts LovelyRufus::Wrapper.new(text).wrapped(15)
|
34
|
-
The
|
35
|
-
Ballyshannon
|
36
|
-
foundered off
|
37
|
-
the coast of
|
38
|
-
Cariboo, And
|
39
|
-
down in fathoms
|
40
|
-
many went the
|
41
|
-
captain and the
|
42
|
-
crew;
|
43
|
-
>>
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
features
|
48
|
-
--------
|
49
|
-
|
50
|
-
Currently, Lovely Rufus sports the following features:
|
51
|
-
|
52
|
-
* paragraphs are wrapped to the specified width,
|
53
|
-
* one-letter words are not left at ends of lines,
|
54
|
-
* email quotes (`>`) are handled properly and normalised (`> > >` → `>>>`),
|
55
|
-
* email-quoted paragraph breaks are cleared,
|
56
|
-
* code comments (starting with `#` and `//`) are handled properly,
|
57
|
-
* multiple paragraphs are wrapped independently.
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
name and history
|
62
|
-
----------------
|
63
|
-
|
64
|
-
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).
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
---
|
69
|
-
|
70
|
-
© MMX-MMXIII Piotr Szotkowski <chastell@chastell.net>, licensed under AGPL 3 (see LICENCE)
|
data/Rakefile
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'rake/testtask'
|
2
|
-
require 'reek/rake/task'
|
3
|
-
require 'rubocop/rake_task'
|
4
|
-
|
5
|
-
task default: %i[spec rubocop]
|
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
DELETED
data/config/reek.yml
DELETED
File without changes
|
data/lib/lovely-rufus.rb
DELETED
@@ -1,25 +0,0 @@
|
|
1
|
-
module LovelyRufus class Executable
|
2
|
-
def initialize args = ARGV
|
3
|
-
@settings = settings_from args
|
4
|
-
end
|
5
|
-
|
6
|
-
def run input = $stdin
|
7
|
-
puts Wrapper.new(input.read).wrapped settings.width
|
8
|
-
end
|
9
|
-
|
10
|
-
attr_reader :settings
|
11
|
-
private :settings
|
12
|
-
|
13
|
-
private
|
14
|
-
|
15
|
-
def settings_from args
|
16
|
-
Struct.new(:width).new.tap do |settings|
|
17
|
-
settings.width = 72
|
18
|
-
OptionParser.new do |opts|
|
19
|
-
opts.on '-w', '--width WIDTH', Integer, 'Wrapping width' do |width|
|
20
|
-
settings.width = width
|
21
|
-
end
|
22
|
-
end.parse! args
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end end
|
data/lib/lovely-rufus/wrapper.rb
DELETED
@@ -1,93 +0,0 @@
|
|
1
|
-
module LovelyRufus class Wrapper
|
2
|
-
NBSP = ' '
|
3
|
-
|
4
|
-
def initialize text
|
5
|
-
@paras = text.split(%r{\n[/#> ]*\n}).map { |para| Para.new para.strip }
|
6
|
-
end
|
7
|
-
|
8
|
-
def wrapped max_width = 72
|
9
|
-
return '' if paras.all?(&:empty?)
|
10
|
-
|
11
|
-
paras.map do |para|
|
12
|
-
para.wrap_recursively max_width
|
13
|
-
end.join "\n\n"
|
14
|
-
end
|
15
|
-
|
16
|
-
attr_reader :paras
|
17
|
-
private :paras
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
class Para
|
22
|
-
def initialize text
|
23
|
-
@text = text
|
24
|
-
end
|
25
|
-
|
26
|
-
def empty?
|
27
|
-
text.empty?
|
28
|
-
end
|
29
|
-
|
30
|
-
def wrap_recursively max_width
|
31
|
-
best = wrap_to_width max_width
|
32
|
-
(max_width - 1).downto 1 do |width|
|
33
|
-
shorter = wrap_to_width width
|
34
|
-
break if shorter.lines.count > best.lines.count
|
35
|
-
break if shorter.lines.map(&:size).max > best.lines.map(&:size).max
|
36
|
-
best = shorter
|
37
|
-
end
|
38
|
-
best
|
39
|
-
end
|
40
|
-
|
41
|
-
def wrap_to_width width
|
42
|
-
quotes = text[/^([\/#> ]*)/]
|
43
|
-
leader = quotes.empty? ? '' : quotes.tr(' ', '') + ' '
|
44
|
-
width -= leader.size if width > leader.size
|
45
|
-
text.lines
|
46
|
-
.map { |line| line[quotes.size..-1] }.join # drop quotes
|
47
|
-
.tr("\n", ' ') # unwrap para
|
48
|
-
.gsub(/ ([^ ]) /, " \\1#{NBSP}") # glue 1-letter words
|
49
|
-
.gsub(/(.{1,#{width}})( |$\n?)/, "\\1\n") # wrap to width
|
50
|
-
.tap { |par| remove_hangouts par, width } # handle hangouts
|
51
|
-
.lines.map { |line| line.insert 0, leader }.join # re-insert leader
|
52
|
-
.tr(NBSP, ' ') # drop glue spaces
|
53
|
-
.chomp # final touch
|
54
|
-
end
|
55
|
-
|
56
|
-
attr_reader :text
|
57
|
-
private :text
|
58
|
-
|
59
|
-
private
|
60
|
-
|
61
|
-
def find_hangout_line lines
|
62
|
-
lines.find.with_index do |line, i|
|
63
|
-
i < lines.size - 1 and
|
64
|
-
space = hangout_last_space(line) and
|
65
|
-
(hangout_to_previous_line i, lines, space or
|
66
|
-
hangout_to_next_line i, lines, space)
|
67
|
-
end
|
68
|
-
end
|
69
|
-
|
70
|
-
def hangout_last_space line
|
71
|
-
line.rindex(/[ #{NBSP}]/)
|
72
|
-
end
|
73
|
-
|
74
|
-
def hangout_to_next_line i, lines, space
|
75
|
-
(i < lines.size - 2 or lines.size == 2) and
|
76
|
-
space + 1 >= lines[i + 1].size
|
77
|
-
end
|
78
|
-
|
79
|
-
def hangout_to_previous_line i, lines, space
|
80
|
-
i > 0 and space + 1 >= lines[i - 1].size
|
81
|
-
end
|
82
|
-
|
83
|
-
def remove_hangouts para, width
|
84
|
-
lines = para.split "\n"
|
85
|
-
hangout_line = find_hangout_line lines
|
86
|
-
if hangout_line
|
87
|
-
hangout_line << NBSP
|
88
|
-
fixed = self.class.new lines.join(' ').gsub "#{NBSP} ", NBSP
|
89
|
-
para.replace fixed.wrap_to_width width
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
end end
|
data/lovely-rufus.gemspec
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
Gem::Specification.new do |gem|
|
2
|
-
gem.name = 'lovely-rufus'
|
3
|
-
gem.version = '0.0.4'
|
4
|
-
gem.summary = 'lovely-rufus: text wrapper'
|
5
|
-
gem.homepage = 'http://github.com/chastell/lovely-rufus'
|
6
|
-
gem.author = 'Piotr Szotkowski'
|
7
|
-
gem.email = 'chastell@chastell.net'
|
8
|
-
|
9
|
-
gem.files = `git ls-files -z`.split "\0"
|
10
|
-
gem.executables = gem.files.grep(%r{^bin/}).map { |path| File.basename path }
|
11
|
-
gem.test_files = gem.files.grep %r{^spec/.*\.rb$}
|
12
|
-
|
13
|
-
gem.add_dependency 'lovely_rufus'
|
14
|
-
end
|
data/spec/fixtures/wrapper.yml
DELETED
@@ -1,188 +0,0 @@
|
|
1
|
-
# returns unwrapped input if it’s short enough
|
2
|
-
- input: ‘Etiquette’ by Sir William Schwenck Gilbert
|
3
|
-
output: ‘Etiquette’ by Sir William Schwenck Gilbert
|
4
|
-
|
5
|
-
# wraps short input if requested to wrap it shorter (and avoids hangouts)
|
6
|
-
- width: 16
|
7
|
-
input: ‘Etiquette’ by Sir William Schwenck Gilbert
|
8
|
-
output: |-
|
9
|
-
‘Etiquette’
|
10
|
-
by Sir William
|
11
|
-
Schwenck Gilbert
|
12
|
-
|
13
|
-
# certain tricky hangout situations are catered for
|
14
|
-
- input: |-
|
15
|
-
dropping spaces, it-would-look-like this written-by-Sir-William-Schwenck-Gilbert
|
16
|
-
output: |-
|
17
|
-
dropping spaces, it-would-look-like this
|
18
|
-
written-by-Sir-William-Schwenck-Gilbert
|
19
|
-
|
20
|
-
# next-to-last hangouts are taken care of in two-line paragraphs
|
21
|
-
- input: |-
|
22
|
-
Well, the old ones go mmmmmbbbbzzzzttteeeeeep as they start up and
|
23
|
-
the new ones go whupwhupwhupwhooopwhooooopwhooooooommmmmmmmmm.
|
24
|
-
output: |-
|
25
|
-
Well, the old ones go mmmmmbbbbzzzzttteeeeeep as they start up
|
26
|
-
and the new ones go whupwhupwhupwhooopwhooooopwhooooooommmmmmmmmm.
|
27
|
-
|
28
|
-
# unwrapping works with quoted text
|
29
|
-
- input: |-
|
30
|
-
> For some reason recently lovely-rufus
|
31
|
-
> versions can’t wrap.
|
32
|
-
output: |-
|
33
|
-
> For some reason recently lovely-rufus versions can’t wrap.
|
34
|
-
|
35
|
-
# wraps long input to 72 characters by default
|
36
|
-
- input: The Ballyshannon foundered off the coast of Cariboo, And down in fathoms many went the captain and the crew;
|
37
|
-
output: |-
|
38
|
-
The Ballyshannon foundered off the coast of Cariboo,
|
39
|
-
And down in fathoms many went the captain and the crew;
|
40
|
-
|
41
|
-
# rewraps multiline paragraphs
|
42
|
-
- input: |-
|
43
|
-
Down went the owners — greedy men
|
44
|
-
whom hope of gain allured:
|
45
|
-
Oh, dry the starting tear,
|
46
|
-
for they were heavily insured.
|
47
|
-
output: |-
|
48
|
-
Down went the owners — greedy men whom hope of gain allured:
|
49
|
-
Oh, dry the starting tear, for they were heavily insured.
|
50
|
-
|
51
|
-
# wrapped paragraphs are as short as possible
|
52
|
-
- input: |-
|
53
|
-
Besides the captain and the mate, the owners and the crew,
|
54
|
-
The passengers were also drowned, excepting only two:
|
55
|
-
Young PETER GRAY, who tasted teas for BAKER, CROOP, AND CO.,
|
56
|
-
And SOMERS, who from Eastern shores imported indigo.
|
57
|
-
output: |-
|
58
|
-
Besides the captain and the mate, the owners and the crew,
|
59
|
-
The passengers were also drowned, excepting only two: Young
|
60
|
-
PETER GRAY, who tasted teas for BAKER, CROOP, AND CO., And
|
61
|
-
SOMERS, who from Eastern shores imported indigo.
|
62
|
-
|
63
|
-
# one-letter words are not left at line ends
|
64
|
-
- width: 39
|
65
|
-
input: |-
|
66
|
-
These passengers, by reason of their clinging to a mast,
|
67
|
-
Upon a desert island were eventually cast.
|
68
|
-
They hunted for their meals, as ALEXANDER SELKIRK used,
|
69
|
-
But they couldn’t chat together — they had not been introduced.
|
70
|
-
output: |-
|
71
|
-
These passengers, by reason of
|
72
|
-
their clinging to a mast, Upon
|
73
|
-
a desert island were eventually
|
74
|
-
cast. They hunted for their meals,
|
75
|
-
as ALEXANDER SELKIRK used, But they
|
76
|
-
couldn’t chat together — they had
|
77
|
-
not been introduced.
|
78
|
-
|
79
|
-
# multiple paragraphs are wrapped independently
|
80
|
-
- input: |-
|
81
|
-
For PETER GRAY, and SOMERS too, though certainly in trade,
|
82
|
-
Were properly particular about the friends they made;
|
83
|
-
And somehow thus they settled it without a word of mouth —
|
84
|
-
That GRAY should take the northern half while SOMERS took the south.
|
85
|
-
|
86
|
-
On PETER’S portion oysters grew — a delicacy rare,
|
87
|
-
But oysters were a delicacy PETER couldn’t bear.
|
88
|
-
On SOMERS’ side was turtle, on the shingle lying thick,
|
89
|
-
Which SOMERS couldn’t eat, because it always made him sick.
|
90
|
-
output: |-
|
91
|
-
For PETER GRAY, and SOMERS too, though certainly in trade, Were
|
92
|
-
properly particular about the friends they made; And somehow
|
93
|
-
thus they settled it without a word of mouth — That GRAY should
|
94
|
-
take the northern half while SOMERS took the south.
|
95
|
-
|
96
|
-
On PETER’S portion oysters grew — a delicacy rare, But
|
97
|
-
oysters were a delicacy PETER couldn’t bear. On SOMERS’
|
98
|
-
side was turtle, on the shingle lying thick, Which
|
99
|
-
SOMERS couldn’t eat, because it always made him sick.
|
100
|
-
|
101
|
-
# email-quoted paragraphs are wrapped regardless of quotes
|
102
|
-
- input: |-
|
103
|
-
> On PETER’S portion oysters grew — a delicacy rare,
|
104
|
-
> But oysters were a delicacy PETER couldn’t bear.
|
105
|
-
> On SOMERS’ side was turtle, on the shingle lying thick,
|
106
|
-
> Which SOMERS couldn’t eat, because it always made him sick.
|
107
|
-
output: |-
|
108
|
-
> On PETER’S portion oysters grew — a delicacy rare, But
|
109
|
-
> oysters were a delicacy PETER couldn’t bear. On SOMERS’
|
110
|
-
> side was turtle, on the shingle lying thick, Which
|
111
|
-
> SOMERS couldn’t eat, because it always made him sick.
|
112
|
-
|
113
|
-
# email quotes can be of any depth
|
114
|
-
- input: |-
|
115
|
-
>> GRAY gnashed his teeth with envy as he saw a mighty store
|
116
|
-
>> Of turtle unmolested on his fellow-creature’s shore:
|
117
|
-
>> The oysters at his feet aside impatiently he shoved,
|
118
|
-
>> For turtle and his mother were the only things he loved.
|
119
|
-
output: |-
|
120
|
-
>> GRAY gnashed his teeth with envy as he saw a mighty store
|
121
|
-
>> Of turtle unmolested on his fellow-creature’s shore: The
|
122
|
-
>> oysters at his feet aside impatiently he shoved, For turtle
|
123
|
-
>> and his mother were the only things he loved.
|
124
|
-
|
125
|
-
# email quotes are normalised upon wrapping
|
126
|
-
- input: |-
|
127
|
-
> > >And SOMERS sighed in sorrow as he settled in the south,
|
128
|
-
> > >For the thought of PETER’S oysters brought the water to his mouth.
|
129
|
-
> > >He longed to lay him down upon the shelly bed, and stuff:
|
130
|
-
> > >He had often eaten oysters, but had never had enough.
|
131
|
-
output: |-
|
132
|
-
>>> And SOMERS sighed in sorrow as he settled in the south, For
|
133
|
-
>>> the thought of PETER’S oysters brought the water to his mouth.
|
134
|
-
>>> He longed to lay him down upon the shelly bed, and stuff: He
|
135
|
-
>>> had often eaten oysters, but had never had enough.
|
136
|
-
|
137
|
-
# quoted paragraph breaks are cleared
|
138
|
-
- input: |-
|
139
|
-
>> How they wished an introduction to each other they had had
|
140
|
-
>> When on board The Ballyshannon! And it drove them nearly mad
|
141
|
-
>> To think how very friendly with each other they might get,
|
142
|
-
>> If it wasn’t for the arbitrary rule of etiquette!
|
143
|
-
>
|
144
|
-
> One day, when out a-hunting for the mus ridiculus,
|
145
|
-
> GRAY overheard his fellow-man soliloquising thus:
|
146
|
-
> ‘I wonder how the playmates of my youth are getting on,
|
147
|
-
> MCCONNELL, S. B. WALTERS, PADDY BYLES, and ROBINSON?’
|
148
|
-
output: |-
|
149
|
-
>> How they wished an introduction to each other they had had
|
150
|
-
>> When on board The Ballyshannon! And it drove them nearly
|
151
|
-
>> mad To think how very friendly with each other they might
|
152
|
-
>> get, If it wasn’t for the arbitrary rule of etiquette!
|
153
|
-
|
154
|
-
> One day, when out a-hunting for the mus ridiculus, GRAY overheard his
|
155
|
-
> fellow-man soliloquising thus: ‘I wonder how the playmates of my youth
|
156
|
-
> are getting on, MCCONNELL, S. B. WALTERS, PADDY BYLES, and ROBINSON?’
|
157
|
-
|
158
|
-
# code comments are handled like email-quoted text
|
159
|
-
- input: |-
|
160
|
-
// These simple words made PETER as delighted as could be,
|
161
|
-
// Old chummies at the Charterhouse were ROBINSON and he!
|
162
|
-
// He walked straight up to SOMERS, then he turned extremely red,
|
163
|
-
// Hesitated, hummed and hawed a bit, then cleared his throat, and said:
|
164
|
-
//
|
165
|
-
# ‘I beg your pardon—pray forgive me if I seem too bold,
|
166
|
-
# But you have breathed a name I knew familiarly of old.
|
167
|
-
# You spoke aloud of ROBINSON – I happened to be by—
|
168
|
-
# You know him?’ ‘Yes, extremely well.’ ‘Allow me – so do I!’
|
169
|
-
#
|
170
|
-
It was enough: they felt they could more sociably get on,
|
171
|
-
For (ah, the magic of the fact!) they each knew ROBINSON!
|
172
|
-
And MR. SOMERS’ turtle was at PETER’S service quite,
|
173
|
-
And MR. SOMERS punished PETER’S oyster-beds all night.
|
174
|
-
output: |-
|
175
|
-
// These simple words made PETER as delighted as could be, Old
|
176
|
-
// chummies at the Charterhouse were ROBINSON and he! He walked
|
177
|
-
// straight up to SOMERS, then he turned extremely red, Hesitated,
|
178
|
-
// hummed and hawed a bit, then cleared his throat, and said:
|
179
|
-
|
180
|
-
# ‘I beg your pardon—pray forgive me if I seem too bold,
|
181
|
-
# But you have breathed a name I knew familiarly of old.
|
182
|
-
# You spoke aloud of ROBINSON – I happened to be by— You
|
183
|
-
# know him?’ ‘Yes, extremely well.’ ‘Allow me – so do I!’
|
184
|
-
|
185
|
-
It was enough: they felt they could more sociably get on,
|
186
|
-
For (ah, the magic of the fact!) they each knew ROBINSON!
|
187
|
-
And MR. SOMERS’ turtle was at PETER’S service quite, And
|
188
|
-
MR. SOMERS punished PETER’S oyster-beds all night.
|
@@ -1,25 +0,0 @@
|
|
1
|
-
require_relative '../spec_helper'
|
2
|
-
|
3
|
-
module LovelyRufus describe Executable do
|
4
|
-
describe '#run' do
|
5
|
-
it 'outputs passed text' do
|
6
|
-
text = StringIO.new 'some text'
|
7
|
-
-> { Executable.new.run text }.must_output "some text\n"
|
8
|
-
end
|
9
|
-
|
10
|
-
it 'wraps passed text to desired width' do
|
11
|
-
text = StringIO.new 'some text'
|
12
|
-
-> { Executable.new(%w[--width 4]).run text }.must_output "some\ntext\n"
|
13
|
-
end
|
14
|
-
|
15
|
-
it 'supports short arguments' do
|
16
|
-
text = StringIO.new 'some text'
|
17
|
-
-> { Executable.new(%w[-w4]).run text }.must_output "some\ntext\n"
|
18
|
-
end
|
19
|
-
|
20
|
-
it 'outputs properly wrapped input' do
|
21
|
-
text = StringIO.new 'some more text'
|
22
|
-
-> { Executable.new(%w[-w4]).run text }.must_output "some\nmore\ntext\n"
|
23
|
-
end
|
24
|
-
end
|
25
|
-
end end
|