verse 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/.gitignore +14 -0
- data/.rspec +3 -0
- data/.ruby-version +1 -0
- data/.travis.yml +22 -0
- data/Gemfile +15 -0
- data/LICENSE.txt +22 -0
- data/README.md +106 -0
- data/Rakefile +8 -0
- data/lib/verse.rb +31 -0
- data/lib/verse/alignment.rb +94 -0
- data/lib/verse/sanitizer.rb +18 -0
- data/lib/verse/truncation.rb +78 -0
- data/lib/verse/version.rb +5 -0
- data/lib/verse/wrapping.rb +123 -0
- data/spec/spec_helper.rb +49 -0
- data/spec/unit/alignment/align_spec.rb +33 -0
- data/spec/unit/alignment/left_spec.rb +33 -0
- data/spec/unit/alignment/right_spec.rb +33 -0
- data/spec/unit/sanitizer/sanitize_spec.rb +23 -0
- data/spec/unit/truncate_spec.rb +10 -0
- data/spec/unit/truncation/new_spec.rb +28 -0
- data/spec/unit/truncation/truncate_spec.rb +63 -0
- data/spec/unit/wrap_spec.rb +10 -0
- data/spec/unit/wrapping/new_spec.rb +27 -0
- data/spec/unit/wrapping/wrap_spec.rb +88 -0
- data/tasks/console.rake +10 -0
- data/tasks/coverage.rake +11 -0
- data/tasks/spec.rake +29 -0
- data/verse.gemspec +22 -0
- metadata +99 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: c1d878680201432d1d1d982be8af68dd04f63a8e
|
4
|
+
data.tar.gz: 4b2a2ff0056cf352051636ab8d974afafcf7a097
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 75e7dafdb2d0264ffa9457d1fae6a42159cb8a5650fa5ba87b75371fb1686ebae80c006541df13d83f7f1a753503c9749c2d64ab9f6df1760128e3ece77a8523
|
7
|
+
data.tar.gz: 86da8ab2fc5690ffb84795b8bf892e51b9d36289cfd054546885926946b8c819c739813dac99e9d86559e2eafbb640c22440b7ab31fa0742728a1dae47bd623f
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.0.0
|
data/.travis.yml
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
language: ruby
|
2
|
+
bundler_args: --without yard benchmarks
|
3
|
+
script: "bundle exec rake ci"
|
4
|
+
rvm:
|
5
|
+
- 1.9.3
|
6
|
+
- 2.0.0
|
7
|
+
- 2.1.0
|
8
|
+
- 2.2.0
|
9
|
+
- ruby-head
|
10
|
+
matrix:
|
11
|
+
include:
|
12
|
+
- rvm: jruby-19mode
|
13
|
+
- rvm: jruby-20mode
|
14
|
+
- rvm: jruby-21mode
|
15
|
+
- rvm: jruby-head
|
16
|
+
- rvm: rbx-2
|
17
|
+
allow_failures:
|
18
|
+
- rvm: ruby-head
|
19
|
+
- rvm: jruby-head
|
20
|
+
fast_finish: true
|
21
|
+
branches:
|
22
|
+
only: master
|
data/Gemfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development do
|
6
|
+
gem 'rake', '~> 10.3.2'
|
7
|
+
gem 'rspec', '~> 3.1.0'
|
8
|
+
gem 'yard', '~> 0.8.7'
|
9
|
+
end
|
10
|
+
|
11
|
+
group :metrics do
|
12
|
+
gem 'coveralls', '~> 0.7.0'
|
13
|
+
gem 'simplecov', '~> 0.8.2'
|
14
|
+
gem 'yardstick', '~> 0.9.9'
|
15
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 Piotr Murach
|
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.
|
data/README.md
ADDED
@@ -0,0 +1,106 @@
|
|
1
|
+
# Verse
|
2
|
+
[![Gem Version](https://badge.fury.io/rb/verse.png)][gem]
|
3
|
+
[![Build Status](https://secure.travis-ci.org/peter-murach/verse.png?branch=master)][travis]
|
4
|
+
[![Code Climate](https://codeclimate.com/github/peter-murach/verse.png)][codeclimate]
|
5
|
+
[![Coverage Status](https://coveralls.io/repos/peter-murach/verse/badge.png)][coverage]
|
6
|
+
[![Inline docs](http://inch-ci.org/github/peter-murach/verse.png)][inchpages]
|
7
|
+
|
8
|
+
[gem]: http://badge.fury.io/rb/verse
|
9
|
+
[travis]: http://travis-ci.org/peter-murach/verse
|
10
|
+
[codeclimate]: https://codeclimate.com/github/peter-murach/verse
|
11
|
+
[coverage]: https://coveralls.io/r/peter-murach/verse
|
12
|
+
[inchpages]: http://inch-ci.org/github/peter-murach/verse
|
13
|
+
|
14
|
+
> Text transformations such as truncation, wrapping, aligning, indentation and grouping of words.
|
15
|
+
|
16
|
+
## Features
|
17
|
+
|
18
|
+
* No monkey-patching String class
|
19
|
+
|
20
|
+
## Installation
|
21
|
+
|
22
|
+
Add this line to your application's Gemfile:
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
gem 'verse'
|
26
|
+
```
|
27
|
+
|
28
|
+
And then execute:
|
29
|
+
|
30
|
+
```bash
|
31
|
+
$ bundle
|
32
|
+
```
|
33
|
+
|
34
|
+
Or install it yourself as:
|
35
|
+
|
36
|
+
```bash
|
37
|
+
$ gem install verse
|
38
|
+
```
|
39
|
+
|
40
|
+
## 1 Usage
|
41
|
+
|
42
|
+
### 1.1 align
|
43
|
+
|
44
|
+
**Verse** allows you to align text:
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
alignment = Verse::Alignment.new "for there is no folly of the beast\n" +
|
48
|
+
" of the earth which\n" +
|
49
|
+
" is not infinitely\n" +
|
50
|
+
" outdone by the madness of men"
|
51
|
+
```
|
52
|
+
|
53
|
+
Then using `right`, `left` or `center` methods and passing width you can align the text:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
alignemnt.right(40) # =>
|
57
|
+
" for there is no folly of the beast\n" +
|
58
|
+
" of the earth which\n" +
|
59
|
+
" is not infinitely\n" +
|
60
|
+
" outdone by the madness of men"
|
61
|
+
```
|
62
|
+
|
63
|
+
### 1.2 truncate
|
64
|
+
|
65
|
+
Using **Verse** you can truncate a given text:
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
truncation = Verse::Truncation.new "for there is no folly of the beast of the earth " +
|
69
|
+
"which is not infinitely outdone by the madness of men"
|
70
|
+
|
71
|
+
```
|
72
|
+
|
73
|
+
Then to shorten the text to given length call `truncate`:
|
74
|
+
|
75
|
+
```ruby
|
76
|
+
truncation.truncate(20) # => "for there is no fol…"
|
77
|
+
```
|
78
|
+
|
79
|
+
### 1.3 wrap
|
80
|
+
|
81
|
+
```ruby
|
82
|
+
wrapping = Verse::Wrapping.new "Think not, is my eleventh commandment; " +
|
83
|
+
"and sleep when you can, is my twelfth."
|
84
|
+
|
85
|
+
```
|
86
|
+
|
87
|
+
Then to wrap the text to given length call `wrap`:
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
wrapping.wrap(30)
|
91
|
+
# => "Think not, is my eleventh"
|
92
|
+
"commandment; and sleep when"
|
93
|
+
"you can, is my twelfth."
|
94
|
+
```
|
95
|
+
|
96
|
+
## Contributing
|
97
|
+
|
98
|
+
1. Fork it ( https://github.com/peter-murach/verse/fork )
|
99
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
100
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
101
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
102
|
+
5. Create a new Pull Request
|
103
|
+
|
104
|
+
## Copyright
|
105
|
+
|
106
|
+
Copyright (c) 2015 Piotr Murach. See LICENSE for further details.
|
data/Rakefile
ADDED
data/lib/verse.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'verse/alignment'
|
4
|
+
require 'verse/sanitizer'
|
5
|
+
require 'verse/truncation'
|
6
|
+
require 'verse/wrapping'
|
7
|
+
require 'verse/version'
|
8
|
+
|
9
|
+
module Verse
|
10
|
+
SPACE = ' '.freeze
|
11
|
+
NEWLINE = "\n".freeze
|
12
|
+
TAB = "\n".freeze
|
13
|
+
|
14
|
+
# Truncate a text at a given length
|
15
|
+
#
|
16
|
+
# @see Verse::Truncation#truncate
|
17
|
+
#
|
18
|
+
# @api public
|
19
|
+
def self.truncate(text, truncate_at, options = {})
|
20
|
+
Truncation.truncate(text, truncate_at, options)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Wrap a text into lines at wrap length
|
24
|
+
#
|
25
|
+
# @see Verse::Wrapping#wrap
|
26
|
+
#
|
27
|
+
# @api public
|
28
|
+
def self.wrap(text, wrap_at, options = {})
|
29
|
+
Wrapping.wrap(text, wrap_at, options = {})
|
30
|
+
end
|
31
|
+
end # Verse
|
@@ -0,0 +1,94 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Verse
|
4
|
+
# A class responsible for text alignment
|
5
|
+
class Alignment
|
6
|
+
|
7
|
+
attr_reader :fill
|
8
|
+
|
9
|
+
attr_reader :direction
|
10
|
+
|
11
|
+
# Initialize an Alignment
|
12
|
+
#
|
13
|
+
# @api public
|
14
|
+
def initialize(text, options = {})
|
15
|
+
@text = text
|
16
|
+
@fill = options.fetch(:fill) { SPACE }
|
17
|
+
@direction = options.fetch(:direction) { :left }
|
18
|
+
end
|
19
|
+
|
20
|
+
# Aligns text to the left
|
21
|
+
#
|
22
|
+
# @return [String]
|
23
|
+
#
|
24
|
+
# @api public
|
25
|
+
def left(width, options = {})
|
26
|
+
align(width, :left, options)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Centers text within the width
|
30
|
+
#
|
31
|
+
# @return [String]
|
32
|
+
#
|
33
|
+
# @api public
|
34
|
+
def center(width, options = {})
|
35
|
+
align(width, :center, options)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Aligns text to the right
|
39
|
+
#
|
40
|
+
# @return [String]
|
41
|
+
#
|
42
|
+
# @api public
|
43
|
+
def right(width, options = {})
|
44
|
+
align(width, :right, options)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Aligns text within the width.
|
48
|
+
#
|
49
|
+
# If the text is greater than the width then unmodified
|
50
|
+
# string is returned.
|
51
|
+
#
|
52
|
+
# @example
|
53
|
+
# alignment = Verse::Alignment.new "the madness of men"
|
54
|
+
#
|
55
|
+
# alignment.align(22, :left)
|
56
|
+
# # => "the madness of men "
|
57
|
+
#
|
58
|
+
# alignment.align(22, :center)
|
59
|
+
# # => " the madness of men "
|
60
|
+
#
|
61
|
+
# alignment.align(22, :right)
|
62
|
+
# # => " the madness of men"
|
63
|
+
#
|
64
|
+
# @api public
|
65
|
+
def align(width, direction = :left, options = {})
|
66
|
+
filler = options.fetch(:fill) { fill }
|
67
|
+
method = convert_to_method(direction)
|
68
|
+
process_lines { |line| line.send(method, width, filler) }
|
69
|
+
end
|
70
|
+
|
71
|
+
private
|
72
|
+
|
73
|
+
# @api private
|
74
|
+
def convert_to_method(direction)
|
75
|
+
case direction
|
76
|
+
when :left then :ljust
|
77
|
+
when :right then :rjust
|
78
|
+
when :center then :center
|
79
|
+
else
|
80
|
+
fail ArgumentError, "Unknown alignment `#{direction}`."
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
# @api private
|
85
|
+
def process_lines
|
86
|
+
lines = text.split(NEWLINE)
|
87
|
+
lines.reduce([]) do |aligned, line|
|
88
|
+
aligned << yield(line.strip)
|
89
|
+
end.join("\n")
|
90
|
+
end
|
91
|
+
|
92
|
+
attr_reader :text
|
93
|
+
end # Alignment
|
94
|
+
end # Verse
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Verse
|
4
|
+
class Sanitizer
|
5
|
+
ANSI_MATCHER = /(\[)?\033(\[)?[;?\d]*[\dA-Za-z](\])?/.freeze
|
6
|
+
|
7
|
+
# Strip ANSI characters from the text
|
8
|
+
#
|
9
|
+
# @param [String] text
|
10
|
+
#
|
11
|
+
# @return [String]
|
12
|
+
#
|
13
|
+
# @api private
|
14
|
+
def sanitize(text)
|
15
|
+
text.gsub(ANSI_MATCHER, '')
|
16
|
+
end
|
17
|
+
end # Sanitizer
|
18
|
+
end # Verse
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Verse
|
4
|
+
# A class responsible for text truncation operations
|
5
|
+
class Truncation
|
6
|
+
DEFAULT_TRAILING = '…'.freeze
|
7
|
+
|
8
|
+
DEFAULT_LENGTH = 30.freeze
|
9
|
+
|
10
|
+
attr_reader :separator
|
11
|
+
|
12
|
+
attr_reader :trailing
|
13
|
+
|
14
|
+
# Initialize a Truncation
|
15
|
+
#
|
16
|
+
# @param [String] text
|
17
|
+
# the text to be truncated
|
18
|
+
#
|
19
|
+
# @param [Hash] options
|
20
|
+
# @option options [Symbol] :separator the character for splitting words
|
21
|
+
# @option options [Symbol] :trailing the character for ending sentence
|
22
|
+
#
|
23
|
+
# @api public
|
24
|
+
def initialize(text, options = {})
|
25
|
+
@text = text
|
26
|
+
@sanitizer = Sanitizer.new
|
27
|
+
@separator = options.fetch(:separator) { nil }
|
28
|
+
@trailing = options.fetch(:trailing) { DEFAULT_TRAILING }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Truncate a text at a given length
|
32
|
+
#
|
33
|
+
# @see Verse::Truncation#truncate
|
34
|
+
#
|
35
|
+
# @api public
|
36
|
+
def self.truncate(text, truncate_at, options = {})
|
37
|
+
new(text).truncate(truncate_at, options)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Truncate a text at a given length (defualts to 30)
|
41
|
+
#
|
42
|
+
# @example
|
43
|
+
# truncation = Verse::Truncation.new
|
44
|
+
# "The sovereignest thing on earth is parmacetti for an inward bruise."
|
45
|
+
#
|
46
|
+
# truncation.truncate
|
47
|
+
# # => "The sovereignest thing on ear…"
|
48
|
+
#
|
49
|
+
# truncate(20)
|
50
|
+
# # => "The sovereignest th…"
|
51
|
+
#
|
52
|
+
# truncate(20, separator: ' ' )
|
53
|
+
# # => "The sovereignest…"
|
54
|
+
#
|
55
|
+
# truncate(40, trailing: '... (see more)' )
|
56
|
+
# # => "The sovereignest thing on... (see more)"
|
57
|
+
#
|
58
|
+
# @api public
|
59
|
+
def truncate(truncate_at = DEFAULT_LENGTH, options = {})
|
60
|
+
if text.length <= truncate_at.to_i || truncate_at.to_i.zero?
|
61
|
+
return text.dup
|
62
|
+
end
|
63
|
+
trail = options.fetch(:trailing) { trailing }
|
64
|
+
separation = options.fetch(:separator) { separator }
|
65
|
+
|
66
|
+
chars = @sanitizer.sanitize(text).chars.to_a
|
67
|
+
return chars.join if chars.length <= truncate_at
|
68
|
+
length_without_trailing = truncate_at - trail.chars.to_a.size
|
69
|
+
stop = chars[0, length_without_trailing].rindex(separation)
|
70
|
+
|
71
|
+
chars[0, stop || length_without_trailing].join + trail
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
attr_reader :text
|
77
|
+
end # Truncation
|
78
|
+
end # Verse
|
@@ -0,0 +1,123 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module Verse
|
4
|
+
# A class responsible for text wrapping
|
5
|
+
class Wrapping
|
6
|
+
DEFAULT_WIDTH = 80.freeze
|
7
|
+
|
8
|
+
attr_reader :indent
|
9
|
+
|
10
|
+
attr_reader :padding
|
11
|
+
|
12
|
+
# Initialize a Wrapping
|
13
|
+
#
|
14
|
+
# @param [String] text
|
15
|
+
# the text to be wrapped
|
16
|
+
#
|
17
|
+
# @param [Hash] options
|
18
|
+
# @option options [Symbol] :indent the indentation
|
19
|
+
# @option options [Symbol] :padding the desired spacing
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
def initialize(text, options = {})
|
23
|
+
@text = text
|
24
|
+
@indent = options.fetch(:indent) { 0 }
|
25
|
+
@padding = options.fetch(:padding) { [] }
|
26
|
+
@line_width = options.fetch(:line_width) { DEFAULT_WIDTH }
|
27
|
+
@sanitizer = Sanitizer.new
|
28
|
+
end
|
29
|
+
|
30
|
+
# Wrap a text into lines no longer than wrap_at
|
31
|
+
#
|
32
|
+
# @api public
|
33
|
+
def self.wrap(text, wrap_at, options = {})
|
34
|
+
new(text).wrap(wrap_at, options)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Wrap a text into lines no longer than wrap_at length.
|
38
|
+
# Preserves existing lines and existing word boundaries.
|
39
|
+
#
|
40
|
+
# @example
|
41
|
+
# wrapping = Verse::Wrapping.new "Some longish text"
|
42
|
+
#
|
43
|
+
# wrapping.wrap(8)
|
44
|
+
# # => "Some\nlongish\ntext"
|
45
|
+
#
|
46
|
+
# wrapping.wrap(8, indent: 4)
|
47
|
+
# # => > Some
|
48
|
+
# > longish
|
49
|
+
# > text
|
50
|
+
#
|
51
|
+
# @api public
|
52
|
+
def wrap(wrap_at = DEFAULT_WIDTH, options = {})
|
53
|
+
if text.length < wrap_at.to_i || wrap_at.to_i.zero?
|
54
|
+
return text.dup
|
55
|
+
end
|
56
|
+
|
57
|
+
indentation = options.fetch(:indent) { indent }
|
58
|
+
spacing = options.fetch(:padding) { padding }
|
59
|
+
|
60
|
+
text.split(NEWLINE, -1).map do |line|
|
61
|
+
pad_line(indent_line(wrap_line(line, wrap_at), indentation), spacing)
|
62
|
+
end * NEWLINE
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
# Calculate string length without color escapes
|
68
|
+
#
|
69
|
+
# @param [String] string
|
70
|
+
#
|
71
|
+
# @api private
|
72
|
+
def actual_length(string, at)
|
73
|
+
at + (string.length - @sanitizer.sanitize(string).length)
|
74
|
+
end
|
75
|
+
|
76
|
+
# Wrap line at given length
|
77
|
+
#
|
78
|
+
# @param [String] line
|
79
|
+
#
|
80
|
+
# @return [String]
|
81
|
+
#
|
82
|
+
# @api private
|
83
|
+
def wrap_line(line, at)
|
84
|
+
wrap_at = actual_length(line, at)
|
85
|
+
line.strip.gsub(/\n/, ' ').squeeze(' ')
|
86
|
+
.gsub(/(.{1,#{wrap_at}})(?:\s+|$\n?)|(.{1,#{wrap_at}})/, "\\1\\2\n")
|
87
|
+
.strip
|
88
|
+
end
|
89
|
+
|
90
|
+
# Indent string by given value
|
91
|
+
#
|
92
|
+
# @param [String] text
|
93
|
+
#
|
94
|
+
# @return [String]
|
95
|
+
#
|
96
|
+
# @api private
|
97
|
+
def indent_line(text, indent)
|
98
|
+
text.split(NEWLINE).each do |line|
|
99
|
+
line.insert(0, SPACE * indent)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
# Add padding to each line in wrapped text
|
104
|
+
#
|
105
|
+
# @param [String] text
|
106
|
+
# the wrapped text
|
107
|
+
#
|
108
|
+
# @return [String]
|
109
|
+
#
|
110
|
+
# @api private
|
111
|
+
def pad_line(text, padding)
|
112
|
+
return text if text.empty? || padding.empty?
|
113
|
+
|
114
|
+
padding_left = SPACE * padding[3].to_i
|
115
|
+
padding_right = SPACE * padding[1].to_i
|
116
|
+
text.map! do |part|
|
117
|
+
part.insert(0, padding_left).insert(-1, padding_right)
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
attr_reader :text
|
122
|
+
end # Wrapping
|
123
|
+
end # Verse
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
# encoding: utf-8
|
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
|
+
|
18
|
+
require 'verse'
|
19
|
+
|
20
|
+
RSpec.configure do |config|
|
21
|
+
config.expect_with :rspec do |expectations|
|
22
|
+
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
|
23
|
+
end
|
24
|
+
|
25
|
+
config.mock_with :rspec do |mocks|
|
26
|
+
mocks.verify_partial_doubles = true
|
27
|
+
end
|
28
|
+
|
29
|
+
# Limits the available syntax to the non-monkey patched syntax that is recommended.
|
30
|
+
config.disable_monkey_patching!
|
31
|
+
|
32
|
+
# This setting enables warnings. It's recommended, but in some cases may
|
33
|
+
# be too noisy due to issues in dependencies.
|
34
|
+
config.warnings = true
|
35
|
+
|
36
|
+
if config.files_to_run.one?
|
37
|
+
config.default_formatter = 'doc'
|
38
|
+
end
|
39
|
+
|
40
|
+
config.profile_examples = 2
|
41
|
+
|
42
|
+
config.order = :random
|
43
|
+
|
44
|
+
Kernel.srand config.seed
|
45
|
+
end
|
46
|
+
|
47
|
+
def unindent(text)
|
48
|
+
text.gsub(/^[ \t]*/, '').chomp
|
49
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Verse::Alignment, '.align' do
|
6
|
+
it "centers line" do
|
7
|
+
text = "the madness of men"
|
8
|
+
alignment = Verse::Alignment.new(text)
|
9
|
+
expect(alignment.center(22)).to eq(" the madness of men ")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "centers multiline text" do
|
13
|
+
text = "for there is no folly of the beast\n of the earth which\n is not infinitely\n outdone by the madness of men"
|
14
|
+
alignment = Verse::Alignment.new(text)
|
15
|
+
expect(alignment.center(40)).to eq([
|
16
|
+
" for there is no folly of the beast \n",
|
17
|
+
" of the earth which \n",
|
18
|
+
" is not infinitely \n",
|
19
|
+
" outdone by the madness of men "
|
20
|
+
].join)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "centers multiline text with fill of '*'" do
|
24
|
+
text = "for there is no folly of the beast\n of the earth which\n is not infinitely\n outdone by the madness of men"
|
25
|
+
alignment = Verse::Alignment.new(text, fill: '*')
|
26
|
+
expect(alignment.center(40)).to eq([
|
27
|
+
"***for there is no folly of the beast***\n",
|
28
|
+
"***********of the earth which***********\n",
|
29
|
+
"***********is not infinitely************\n",
|
30
|
+
"*****outdone by the madness of men******"
|
31
|
+
].join)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Verse::Alignment, '.left' do
|
6
|
+
it "aligns line to left" do
|
7
|
+
text = "the madness of men"
|
8
|
+
alignment = Verse::Alignment.new(text)
|
9
|
+
expect(alignment.left(22)).to eq("the madness of men ")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "aligns multiline text to left" do
|
13
|
+
text = "for there is no folly of the beast\n of the earth which\n is not infinitely\n outdone by the madness of men"
|
14
|
+
alignment = Verse::Alignment.new(text)
|
15
|
+
expect(alignment.left(40)).to eq([
|
16
|
+
"for there is no folly of the beast \n",
|
17
|
+
"of the earth which \n",
|
18
|
+
"is not infinitely \n",
|
19
|
+
"outdone by the madness of men "
|
20
|
+
].join)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "centers multiline text with fill of '*'" do
|
24
|
+
text = "for there is no folly of the beast\n of the earth which\n is not infinitely\n outdone by the madness of men"
|
25
|
+
alignment = Verse::Alignment.new(text, fill: '*')
|
26
|
+
expect(alignment.left(40)).to eq([
|
27
|
+
"for there is no folly of the beast******\n",
|
28
|
+
"of the earth which**********************\n",
|
29
|
+
"is not infinitely***********************\n",
|
30
|
+
"outdone by the madness of men***********"
|
31
|
+
].join)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Verse::Alignment, '.right' do
|
6
|
+
it "aligns line to left" do
|
7
|
+
text = "the madness of men"
|
8
|
+
alignment = Verse::Alignment.new(text)
|
9
|
+
expect(alignment.right(22)).to eq(" the madness of men")
|
10
|
+
end
|
11
|
+
|
12
|
+
it "aligns multiline text to left" do
|
13
|
+
text = "for there is no folly of the beast\n of the earth which\n is not infinitely\n outdone by the madness of men"
|
14
|
+
alignment = Verse::Alignment.new(text)
|
15
|
+
expect(alignment.right(40)).to eq([
|
16
|
+
" for there is no folly of the beast\n",
|
17
|
+
" of the earth which\n",
|
18
|
+
" is not infinitely\n",
|
19
|
+
" outdone by the madness of men"
|
20
|
+
].join)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "centers multiline text with fill of '*'" do
|
24
|
+
text = "for there is no folly of the beast\n of the earth which\n is not infinitely\n outdone by the madness of men"
|
25
|
+
alignment = Verse::Alignment.new(text, fill: '*')
|
26
|
+
expect(alignment.right(40)).to eq([
|
27
|
+
"******for there is no folly of the beast\n",
|
28
|
+
"**********************of the earth which\n",
|
29
|
+
"***********************is not infinitely\n",
|
30
|
+
"***********outdone by the madness of men"
|
31
|
+
].join)
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Verse::Sanitizer, '.sanitize' do
|
6
|
+
subject(:sanitizer) { described_class.new }
|
7
|
+
|
8
|
+
{
|
9
|
+
"\e[20h" => '',
|
10
|
+
"\e[?1h" => '',
|
11
|
+
"\e[20l" => '',
|
12
|
+
"\e[?9l" => '',
|
13
|
+
"\eO" => '',
|
14
|
+
"\e[m" => '',
|
15
|
+
"\e[0m" => '',
|
16
|
+
"\eA" => '',
|
17
|
+
"\e[0;33;49;3;9;4m\e[0m" => ''
|
18
|
+
}.each do |code, expected|
|
19
|
+
it "strips #{code} from string" do
|
20
|
+
expect(sanitizer.sanitize(code)).to eq(expected)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Verse::Truncation, '#new' do
|
6
|
+
let(:text) { 'There go the ships; there is that Leviathan whom thou hast made to play therein.'}
|
7
|
+
|
8
|
+
it "defaults to no separator and unicode trailing" do
|
9
|
+
truncation = Verse::Truncation.new text
|
10
|
+
expect(truncation.separator).to eq(nil)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "defaults to unicode trailing" do
|
14
|
+
truncation = Verse::Truncation.new text
|
15
|
+
expect(truncation.trailing).to eq('…')
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
it "allows to setup global separator value" do
|
20
|
+
truncation = Verse::Truncation.new text, separator: ' '
|
21
|
+
expect(truncation.separator).to eq(' ')
|
22
|
+
end
|
23
|
+
|
24
|
+
it "allows to setup global trailing value" do
|
25
|
+
truncation = Verse::Truncation.new text, trailing: '...'
|
26
|
+
expect(truncation.trailing).to eq('...')
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Verse::Truncation, '.truncate' do
|
6
|
+
let(:text) { 'ラドクリフ、マラソン五輪代表に1万m出場にも含み' }
|
7
|
+
|
8
|
+
it "doesn't change text for 0 length" do
|
9
|
+
truncation = Verse::Truncation.new(text)
|
10
|
+
expect(truncation.truncate(0)).to eq(text)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "doensn't change text for nil length" do
|
14
|
+
truncation = Verse::Truncation.new(text)
|
15
|
+
expect(truncation.truncate(nil)).to eq(text)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "doesn't change text for equal length" do
|
19
|
+
truncation = Verse::Truncation.new(text)
|
20
|
+
expect(truncation.truncate(text.length)).to eq(text)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'truncates text' do
|
24
|
+
truncation = Verse::Truncation.new(text)
|
25
|
+
trailing = '…'
|
26
|
+
expect(truncation.truncate(12)).to eq("ラドクリフ、マラソン五#{trailing}")
|
27
|
+
end
|
28
|
+
|
29
|
+
it "doesn't truncate text when length exceeds content" do
|
30
|
+
truncation = Verse::Truncation.new(text)
|
31
|
+
expect(truncation.truncate(100)).to eq(text)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'truncates text with string separator' do
|
35
|
+
truncation = Verse::Truncation.new(text)
|
36
|
+
trailing = '…'
|
37
|
+
expect(truncation.truncate(12, separator: ' ')).to eq("ラドクリフ、マラソン五#{trailing}")
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'truncates text with regex separator' do
|
41
|
+
truncation = Verse::Truncation.new(text)
|
42
|
+
trailing = '…'
|
43
|
+
expect(truncation.truncate(12, separator: /\s/)).to eq("ラドクリフ、マラソン五#{trailing}")
|
44
|
+
end
|
45
|
+
|
46
|
+
it 'truncates text with custom trailing' do
|
47
|
+
truncation = Verse::Truncation.new(text)
|
48
|
+
trailing = '... (see more)'
|
49
|
+
expect(truncation.truncate(20, trailing: trailing)).to eq("ラドクリフ、#{trailing}")
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'correctly truncates with ANSI characters' do
|
53
|
+
text = "This is a \e[1m\e[34mbold blue text\e[0m"
|
54
|
+
truncation = Verse::Truncation.new(text)
|
55
|
+
expect(truncation.truncate).to eq 'This is a bold blue text'
|
56
|
+
end
|
57
|
+
|
58
|
+
it "finishes on word boundary" do
|
59
|
+
text = "for there is no folly of the beast of the earth"
|
60
|
+
truncation = Verse::Truncation.new(text)
|
61
|
+
expect(truncation.truncate(20, separator: ' ')).to eq('for there is no…')
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Verse::Wrapping, '#new' do
|
6
|
+
let(:text) { "There go the ships; there is that Leviathan whom thou hast made to play therein."}
|
7
|
+
|
8
|
+
it "defaults indentation to 0" do
|
9
|
+
wrapping = Verse::Wrapping.new(text)
|
10
|
+
expect(wrapping.indent).to eq(0)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "defaults paddnig to empty array" do
|
14
|
+
wrapping = Verse::Wrapping.new(text)
|
15
|
+
expect(wrapping.padding).to eq([])
|
16
|
+
end
|
17
|
+
|
18
|
+
it "allows to set global indenation" do
|
19
|
+
wrapping = Verse::Wrapping.new(text, indent: 5)
|
20
|
+
expect(wrapping.indent).to eq(5)
|
21
|
+
end
|
22
|
+
|
23
|
+
it "allows to set global padding" do
|
24
|
+
wrapping = Verse::Wrapping.new(text, padding: [1,2,3,4])
|
25
|
+
expect(wrapping.padding).to eq([1,2,3,4])
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
RSpec.describe Verse::Wrapping, '.wrap' do
|
6
|
+
context 'when unicode' do
|
7
|
+
let(:text) { 'ラドクリフ、マラソン五輪代表に1万m出場にも含み' }
|
8
|
+
|
9
|
+
it "doesn't wrap at zero length" do
|
10
|
+
wrapping = Verse::Wrapping.new(text)
|
11
|
+
expect(wrapping.wrap(0)).to eq(text)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "doesn't wrap at nil length" do
|
15
|
+
wrapping = Verse::Wrapping.new(text)
|
16
|
+
expect(wrapping.wrap(nil)).to eq(text)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'wraps at 8 characters' do
|
20
|
+
wrapping = Verse::Wrapping.new(text)
|
21
|
+
expect(wrapping.wrap(8)).to eq("ラドクリフ、マラ\nソン五輪代表に1\n万m出場にも含み")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "doesn't wrap at length exceeding content length" do
|
25
|
+
wrapping = Verse::Wrapping.new(text)
|
26
|
+
expect(wrapping.wrap(100)).to eq(text)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when long text' do
|
31
|
+
it "wraps long text at 45 characters" do
|
32
|
+
text =
|
33
|
+
"What of it, if some old hunks of a sea-captain orders me to get a broom
|
34
|
+
and sweep down the decks? What does that indignity amount to, weighed,
|
35
|
+
I mean, in the scales of the New Testament? Do you think the archangel
|
36
|
+
Gabriel thinks anything the less of me, because I promptly and
|
37
|
+
respectfully obey that old hunks in that particular instance? Who ain't
|
38
|
+
a slave? Tell me that. Well, then, however the old sea-captains may
|
39
|
+
order me about--however they may thump and punch me about, I have the
|
40
|
+
satisfaction of knowing that it is all right;
|
41
|
+
"
|
42
|
+
wrapping = Verse::Wrapping.new(text)
|
43
|
+
expect(wrapping.wrap(45)).to eq unindent <<-EOS
|
44
|
+
What of it, if some old hunks of a\n sea-captain orders me to get a broom
|
45
|
+
and sweep down the decks? What does that\n indignity amount to, weighed,
|
46
|
+
I mean, in the scales of the New Testament?\n Do you think the archangel
|
47
|
+
Gabriel thinks anything the less of me,\n because I promptly and
|
48
|
+
respectfully obey that old hunks in that\nparticular instance? Who ain't
|
49
|
+
a slave? Tell me that. Well, then, however\n the old sea-captains may
|
50
|
+
order me about--however they may thump and\n punch me about, I have the
|
51
|
+
satisfaction of knowing that it is all right;\n
|
52
|
+
EOS
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when indented' do
|
57
|
+
let(:length) { 8 }
|
58
|
+
let(:indent) { 4 }
|
59
|
+
|
60
|
+
it "wraps with indentation" do
|
61
|
+
text = 'ラドクリフ、マラソン五輪代表に1万m出場にも含み'
|
62
|
+
wrapping = Verse::Wrapping.new(text)
|
63
|
+
expect(wrapping.wrap(8, indent: 4)).to eq(" ラドクリフ、マラ\n ソン五輪代表に1\n 万m出場にも含み")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context 'with ansi colors' do
|
68
|
+
it "wraps text with ANSII codes" do
|
69
|
+
text = "\[\033[01;32m\]Hey have\[\033[01;34m\]some cake\[\033[00m\]"
|
70
|
+
wrapping = Verse::Wrapping.new(text)
|
71
|
+
expect(wrapping.wrap(8)).to eq("\[\033[01;32m\]Hey have\[\033[01;34m\]some\ncake\[\033[00m\]")
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'with newlines' do
|
76
|
+
it "preserves newlines for both prefix and postfix" do
|
77
|
+
text = "\n\nラドクリフ、マラソン五輪代表に1万m出場にも含み\n\n\n"
|
78
|
+
wrapping = Verse::Wrapping.new(text)
|
79
|
+
expect(wrapping.wrap(10)).to eq("\n\nラドクリフ、マラソン\n五輪代表に1万m出場\nにも含み\n\n\n")
|
80
|
+
end
|
81
|
+
|
82
|
+
it "preserves newlines with padding" do
|
83
|
+
text = "\n\nラドクリフ、マラソン五輪代表に1万m出場にも含み\n\n"
|
84
|
+
wrapping = Verse::Wrapping.new(text)
|
85
|
+
expect(wrapping.wrap(10, padding: [1,2,3,4])).to eq("\n\n ラドクリフ、マラソン \n 五輪代表に1万m出場 \n にも含み \n\n")
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
data/tasks/console.rake
ADDED
data/tasks/coverage.rake
ADDED
data/tasks/spec.rake
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
begin
|
4
|
+
require 'rspec/core/rake_task'
|
5
|
+
|
6
|
+
desc 'Run all specs'
|
7
|
+
RSpec::Core::RakeTask.new(:spec) do |task|
|
8
|
+
task.pattern = 'spec/{unit,integration}{,/*/**}/*_spec.rb'
|
9
|
+
end
|
10
|
+
|
11
|
+
namespace :spec do
|
12
|
+
desc 'Run unit specs'
|
13
|
+
RSpec::Core::RakeTask.new(:unit) do |task|
|
14
|
+
task.pattern = 'spec/unit{,/*/**}/*_spec.rb'
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Run integration specs'
|
18
|
+
RSpec::Core::RakeTask.new(:integration) do |task|
|
19
|
+
task.pattern = 'spec/integration{,/*/**}/*_spec.rb'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
rescue LoadError
|
24
|
+
%w[spec spec:unit spec:integration].each do |name|
|
25
|
+
task name do
|
26
|
+
$stderr.puts "In order to run #{name}, do `gem install rspec`"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/verse.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'verse/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "verse"
|
8
|
+
spec.version = Verse::VERSION
|
9
|
+
spec.authors = ["Piotr Murach"]
|
10
|
+
spec.email = [""]
|
11
|
+
spec.summary = %q{}
|
12
|
+
spec.description = %q{}
|
13
|
+
spec.homepage = ""
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(spec)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: verse
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Piotr Murach
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-02-07 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.5'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.5'
|
27
|
+
description: ''
|
28
|
+
email:
|
29
|
+
- ''
|
30
|
+
executables: []
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- .rspec
|
36
|
+
- .ruby-version
|
37
|
+
- .travis.yml
|
38
|
+
- Gemfile
|
39
|
+
- LICENSE.txt
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- lib/verse.rb
|
43
|
+
- lib/verse/alignment.rb
|
44
|
+
- lib/verse/sanitizer.rb
|
45
|
+
- lib/verse/truncation.rb
|
46
|
+
- lib/verse/version.rb
|
47
|
+
- lib/verse/wrapping.rb
|
48
|
+
- spec/spec_helper.rb
|
49
|
+
- spec/unit/alignment/align_spec.rb
|
50
|
+
- spec/unit/alignment/left_spec.rb
|
51
|
+
- spec/unit/alignment/right_spec.rb
|
52
|
+
- spec/unit/sanitizer/sanitize_spec.rb
|
53
|
+
- spec/unit/truncate_spec.rb
|
54
|
+
- spec/unit/truncation/new_spec.rb
|
55
|
+
- spec/unit/truncation/truncate_spec.rb
|
56
|
+
- spec/unit/wrap_spec.rb
|
57
|
+
- spec/unit/wrapping/new_spec.rb
|
58
|
+
- spec/unit/wrapping/wrap_spec.rb
|
59
|
+
- tasks/console.rake
|
60
|
+
- tasks/coverage.rake
|
61
|
+
- tasks/spec.rake
|
62
|
+
- verse.gemspec
|
63
|
+
homepage: ''
|
64
|
+
licenses:
|
65
|
+
- MIT
|
66
|
+
metadata: {}
|
67
|
+
post_install_message:
|
68
|
+
rdoc_options: []
|
69
|
+
require_paths:
|
70
|
+
- lib
|
71
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
requirements: []
|
82
|
+
rubyforge_project:
|
83
|
+
rubygems_version: 2.0.3
|
84
|
+
signing_key:
|
85
|
+
specification_version: 4
|
86
|
+
summary: ''
|
87
|
+
test_files:
|
88
|
+
- spec/spec_helper.rb
|
89
|
+
- spec/unit/alignment/align_spec.rb
|
90
|
+
- spec/unit/alignment/left_spec.rb
|
91
|
+
- spec/unit/alignment/right_spec.rb
|
92
|
+
- spec/unit/sanitizer/sanitize_spec.rb
|
93
|
+
- spec/unit/truncate_spec.rb
|
94
|
+
- spec/unit/truncation/new_spec.rb
|
95
|
+
- spec/unit/truncation/truncate_spec.rb
|
96
|
+
- spec/unit/wrap_spec.rb
|
97
|
+
- spec/unit/wrapping/new_spec.rb
|
98
|
+
- spec/unit/wrapping/wrap_spec.rb
|
99
|
+
has_rdoc:
|