strings 0.1.2 → 0.1.3
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 +4 -4
- data/CHANGELOG.md +9 -3
- data/README.md +9 -0
- data/lib/strings.rb +4 -3
- data/lib/strings/align.rb +1 -2
- data/lib/strings/pad.rb +1 -1
- data/lib/strings/truncate.rb +1 -2
- data/lib/strings/version.rb +4 -2
- data/lib/strings/wrap.rb +1 -1
- data/spec/spec_helper.rb +37 -0
- data/spec/unit/align/align_left_spec.rb +62 -0
- data/spec/unit/align/align_right_spec.rb +62 -0
- data/spec/unit/align/align_spec.rb +69 -0
- data/spec/unit/align_spec.rb +18 -0
- data/spec/unit/ansi_spec.rb +7 -0
- data/spec/unit/extensions_spec.rb +51 -0
- data/spec/unit/fold/fold_spec.rb +28 -0
- data/spec/unit/fold_spec.rb +7 -0
- data/spec/unit/pad/pad_spec.rb +63 -0
- data/spec/unit/pad_spec.rb +12 -0
- data/spec/unit/padder/parse_spec.rb +35 -0
- data/spec/unit/sanitize_spec.rb +7 -0
- data/spec/unit/truncate/truncate_spec.rb +70 -0
- data/spec/unit/truncate_spec.rb +8 -0
- data/spec/unit/wrap/wrap_spec.rb +155 -0
- data/spec/unit/wrap_spec.rb +15 -0
- data/strings.gemspec +3 -3
- metadata +33 -11
- data/.gitignore +0 -12
- data/.rspec +0 -4
- data/.travis.yml +0 -23
- data/CODE_OF_CONDUCT.md +0 -74
- data/Gemfile +0 -15
- data/appveyor.yml +0 -23
- data/assets/strings_logo.png +0 -0
- data/benchmarks/speed_profile.rb +0 -30
- data/lib/strings/ansi.rb +0 -68
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2c169560954048d363eb109d4c2098c122d2882d3a4f52ba41065cf9ec14411e
|
4
|
+
data.tar.gz: 051f5e21eb97227609ccc87f4e46b13c9ab48d9bf181435599872f335756b74e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27f4263a2874d1b3cee622a31254cf63dcd92d88c19208339f984ddbb3193088ff7fab4a5d0768114c262a57c70320c11534ef4e5eb1eb75521e677c58505776
|
7
|
+
data.tar.gz: ec8ee3980d43c8a7e7481c5e6b1c3d60d4423e7fa3eaaebffc49b2dfd558a019e073a4267283e1ef6008bf5fa2699ef9e1f86f45e538445f99e337dbccd8ee54
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,10 @@
|
|
1
1
|
# Change log
|
2
2
|
|
3
|
+
## [v0.1.3] - 2018-08-28
|
4
|
+
|
5
|
+
### Changed
|
6
|
+
* Change to extract Strings::ANSI to strings-ansi gem
|
7
|
+
|
3
8
|
## [v0.1.2] - 2018-08-10
|
4
9
|
|
5
10
|
### Changed
|
@@ -14,6 +19,7 @@
|
|
14
19
|
|
15
20
|
* Inital implementation and release
|
16
21
|
|
17
|
-
[v0.1.
|
18
|
-
[v0.1.
|
19
|
-
[v0.1.
|
22
|
+
[v0.1.3]: https://github.com/piotrmurach/strings/compare/v0.1.1...v0.1.3
|
23
|
+
[v0.1.2]: https://github.com/piotrmurach/strings/compare/v0.1.1...v0.1.2
|
24
|
+
[v0.1.1]: https://github.com/piotrmurach/strings/compare/v0.1.0...v0.1.1
|
25
|
+
[v0.1.0]: https://github.com/piotrmurach/strings/compare/v0.1.0
|
data/README.md
CHANGED
@@ -56,6 +56,7 @@ Or install it yourself as:
|
|
56
56
|
* [2.6 truncate](#26-truncate)
|
57
57
|
* [2.7 wrap](#27-wrap)
|
58
58
|
* [3. Extending String class](#3-extending-string-class)
|
59
|
+
* [4. Utilities](#4-utilities)
|
59
60
|
|
60
61
|
## 1. Usage
|
61
62
|
|
@@ -367,6 +368,14 @@ require 'strings/extensions'
|
|
367
368
|
using Strings::Extensions
|
368
369
|
```
|
369
370
|
|
371
|
+
## 4. Utilities
|
372
|
+
|
373
|
+
**Strings** aims to be fleaxible and allow you to choose only the utilities that you need. Currently you can choose from:
|
374
|
+
|
375
|
+
| Utility | Description | API docs |
|
376
|
+
| ------------ | ----------- | -------- |
|
377
|
+
| [strings-ansi](https://github.com/piotrmurach/strings-ansi) | Handle ANSI escape codes in strings. | [docs](http://www.rubydoc.info/gems/strings-ansi) |
|
378
|
+
|
370
379
|
## Development
|
371
380
|
|
372
381
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/lib/strings.rb
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'strings-ansi'
|
4
|
+
|
3
5
|
require_relative 'strings/align'
|
4
|
-
require_relative 'strings/ansi'
|
5
6
|
require_relative 'strings/fold'
|
6
7
|
require_relative 'strings/pad'
|
7
8
|
require_relative 'strings/truncate'
|
@@ -84,8 +85,8 @@ module Strings
|
|
84
85
|
# @see Strings::ANSI#sanitize
|
85
86
|
#
|
86
87
|
# @api public
|
87
|
-
def sanitize(
|
88
|
-
ANSI.sanitize(
|
88
|
+
def sanitize(string)
|
89
|
+
ANSI.sanitize(string)
|
89
90
|
end
|
90
91
|
module_function :sanitize
|
91
92
|
|
data/lib/strings/align.rb
CHANGED
data/lib/strings/pad.rb
CHANGED
data/lib/strings/truncate.rb
CHANGED
data/lib/strings/version.rb
CHANGED
data/lib/strings/wrap.rb
CHANGED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
if ENV['COVERAGE'] || ENV['TRAVIS']
|
2
|
+
require 'simplecov'
|
3
|
+
require 'coveralls'
|
4
|
+
|
5
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
6
|
+
SimpleCov::Formatter::HTMLFormatter,
|
7
|
+
Coveralls::SimpleCov::Formatter
|
8
|
+
]
|
9
|
+
|
10
|
+
SimpleCov.start do
|
11
|
+
command_name 'spec'
|
12
|
+
add_filter 'spec'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
require "bundler/setup"
|
17
|
+
require "strings"
|
18
|
+
|
19
|
+
module Helpers
|
20
|
+
def unindent(text)
|
21
|
+
text.gsub(/^[ \t]*/, '').chomp
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
RSpec.configure do |config|
|
26
|
+
config.include(Helpers)
|
27
|
+
|
28
|
+
# Enable flags like --only-failures and --next-failure
|
29
|
+
config.example_status_persistence_file_path = ".rspec_status"
|
30
|
+
|
31
|
+
# Disable RSpec exposing methods globally on `Module` and `main`
|
32
|
+
config.disable_monkey_patching!
|
33
|
+
|
34
|
+
config.expect_with :rspec do |c|
|
35
|
+
c.syntax = :expect
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Strings::Align, '#align_left' do
|
4
|
+
it "aligns line to left" do
|
5
|
+
text = "the madness of men"
|
6
|
+
expect(Strings::Align.align_left(text, 22)).to eq("the madness of men ")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "fills empty" do
|
10
|
+
expect(Strings::Align.align_left('', 22)).to eq(" ")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "left justifies string with unicode characters" do
|
14
|
+
text = "こんにちは"
|
15
|
+
expect(Strings::Align.align(text, 20, direction: :left)).to eq("こんにちは ")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "left justifies string with ansi codes" do
|
19
|
+
text = "\e[32mthe madness of men\e[0m"
|
20
|
+
expect(Strings::Align.align(text, 22, direction: :left)).to eq("\e[32mthe madness of men\e[0m ")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "aligns multiline text to left" do
|
24
|
+
text = "for there is no folly of the beast\nof the earth which\nis not infinitely\noutdone by the madness of men"
|
25
|
+
expect(Strings::Align.align_left(text, 40)).to eq([
|
26
|
+
"for there is no folly of the beast \n",
|
27
|
+
"of the earth which \n",
|
28
|
+
"is not infinitely \n",
|
29
|
+
"outdone by the madness of men "
|
30
|
+
].join)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "left justifies multiline utf text" do
|
34
|
+
text = "ラドクリフ\n、マラソン五輪\n代表に1万m出\n場にも含み"
|
35
|
+
expect(Strings::Align.align_left(text, 20)).to eq([
|
36
|
+
"ラドクリフ \n",
|
37
|
+
"、マラソン五輪 \n",
|
38
|
+
"代表に1万m出 \n",
|
39
|
+
"場にも含み "
|
40
|
+
].join)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "left justifies ansi text" do
|
44
|
+
text = "for \e[35mthere\e[0m is no folly of the beast\nof the \e[33mearth\e0m which\nis \e[34mnot infinitely\e[0m\n\e[33moutdone\e[0m by the madness of men"
|
45
|
+
expect(Strings::Align.align_left(text, 40)).to eq([
|
46
|
+
"for \e[35mthere\e[0m is no folly of the beast \n",
|
47
|
+
"of the \e[33mearth\e0m which \n",
|
48
|
+
"is \e[34mnot infinitely\e[0m \n",
|
49
|
+
"\e[33moutdone\e[0m by the madness of men "
|
50
|
+
].join)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "left justifies multiline text with fill of '*'" do
|
54
|
+
text = "for there is no folly of the beast\nof the earth which\nis not infinitely\noutdone by the madness of men"
|
55
|
+
expect(Strings::Align.align_left(text, 40, fill: '*')).to eq([
|
56
|
+
"for there is no folly of the beast******\n",
|
57
|
+
"of the earth which**********************\n",
|
58
|
+
"is not infinitely***********************\n",
|
59
|
+
"outdone by the madness of men***********"
|
60
|
+
].join)
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Strings::Align, '#align_right' do
|
4
|
+
it "aligns line to right" do
|
5
|
+
text = "the madness of men"
|
6
|
+
expect(Strings::Align.align_right(text, 22)).to eq(" the madness of men")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "fills empty" do
|
10
|
+
expect(Strings::Align.align_right('', 22)).to eq(" ")
|
11
|
+
end
|
12
|
+
|
13
|
+
it "aligns string to the right with unicode characters" do
|
14
|
+
text = "こんにちは"
|
15
|
+
expect(Strings::Align.align(text, 20, direction: :right)).to eq(" こんにちは")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "aligns string to the right with ansi codees" do
|
19
|
+
text = "\e[32mthe madness of men\e[0m"
|
20
|
+
expect(Strings::Align.align(text, 22, direction: :right)).to eq(" \e[32mthe madness of men\e[0m")
|
21
|
+
end
|
22
|
+
|
23
|
+
it "aligns multiline text to the right" 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
|
+
expect(Strings::Align.align_right(text, 40)).to eq([
|
26
|
+
" for there is no folly of the beast\n",
|
27
|
+
" of the earth which\n",
|
28
|
+
" is not infinitely\n",
|
29
|
+
" outdone by the madness of men"
|
30
|
+
].join)
|
31
|
+
end
|
32
|
+
|
33
|
+
it "aligns multiline text to right with unicode characters" do
|
34
|
+
text = "ラドクリフ\n、マラソン五輪\n代表に1万m出\n場にも含み"
|
35
|
+
expect(Strings::Align.align_right(text, 20)).to eq([
|
36
|
+
" ラドクリフ\n",
|
37
|
+
" 、マラソン五輪\n",
|
38
|
+
" 代表に1万m出\n",
|
39
|
+
" 場にも含み"
|
40
|
+
].join)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "right justfies ansi text" do
|
44
|
+
text = "for \e[35mthere\e[0m is no folly of the beast\nof the \e[33mearth\e0m which\nis \e[34mnot infinitely\e[0m\n\e[33moutdone\e[0m by the madness of men"
|
45
|
+
expect(Strings::Align.align_right(text, 40)).to eq([
|
46
|
+
" for \e[35mthere\e[0m is no folly of the beast\n",
|
47
|
+
" of the \e[33mearth\e0m which\n",
|
48
|
+
" is \e[34mnot infinitely\e[0m\n",
|
49
|
+
" \e[33moutdone\e[0m by the madness of men"
|
50
|
+
].join)
|
51
|
+
end
|
52
|
+
|
53
|
+
it "right justifies multiline text with fill of '*'" do
|
54
|
+
text = "for there is no folly of the beast\nof the earth which\nis not infinitely\noutdone by the madness of men"
|
55
|
+
expect(Strings::Align.align_right(text, 40, fill: '*')).to eq([
|
56
|
+
"******for there is no folly of the beast\n",
|
57
|
+
"**********************of the earth which\n",
|
58
|
+
"***********************is not infinitely\n",
|
59
|
+
"***********outdone by the madness of men"
|
60
|
+
].join)
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Strings::Align, '#align' do
|
4
|
+
it "doesn't align unrecognized direction" do
|
5
|
+
text = "the madness of men"
|
6
|
+
expect {
|
7
|
+
Strings::Align.align(text, 22, direction: :unknown)
|
8
|
+
}.to raise_error(ArgumentError, /Unknown alignment/)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "fills empty" do
|
12
|
+
expect(Strings::Align.align('', 22, direction: :center)).to eq(" ")
|
13
|
+
end
|
14
|
+
|
15
|
+
it "centers line" do
|
16
|
+
text = "the madness of men"
|
17
|
+
expect(Strings::Align.align_center(text, 22)).to eq(" the madness of men ")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "centers unicode characters" do
|
21
|
+
text = "こんにちは"
|
22
|
+
expect(Strings::Align.align_center(text, 20)).to eq(" こんにちは ")
|
23
|
+
end
|
24
|
+
|
25
|
+
it "centers string with ansi codes" do
|
26
|
+
text = "\e[32mthe madness of men\e[0m"
|
27
|
+
expect(Strings::Align.align_center(text, 22)).to eq(" \e[32mthe madness of men\e[0m ")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "centers multiline text" do
|
31
|
+
text = "for there is no folly of the beast\nof the earth which\nis not infinitely\noutdone by the madness of men"
|
32
|
+
expect(Strings::Align.align_center(text, 40)).to eq([
|
33
|
+
" for there is no folly of the beast \n",
|
34
|
+
" of the earth which \n",
|
35
|
+
" is not infinitely \n",
|
36
|
+
" outdone by the madness of men "
|
37
|
+
].join)
|
38
|
+
end
|
39
|
+
|
40
|
+
it "centers multiline unicode text" do
|
41
|
+
text = "ラドクリフ\n、マラソン五輪\n代表に1万m出\n場にも含み"
|
42
|
+
expect(Strings::Align.align_center(text, 20)).to eq([
|
43
|
+
" ラドクリフ \n",
|
44
|
+
" 、マラソン五輪 \n",
|
45
|
+
" 代表に1万m出 \n",
|
46
|
+
" 場にも含み "
|
47
|
+
].join)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "centers text with ansi codes" do
|
51
|
+
text = "for \e[35mthere\e[0m is no folly of the beast\nof the \e[33mearth\e0m which\nis \e[34mnot infinitely\e[0m\n\e[33moutdone\e[0m by the madness of men"
|
52
|
+
expect(Strings::Align.align_center(text, 40)).to eq([
|
53
|
+
" for \e[35mthere\e[0m is no folly of the beast \n",
|
54
|
+
" of the \e[33mearth\e0m which \n",
|
55
|
+
" is \e[34mnot infinitely\e[0m \n",
|
56
|
+
" \e[33moutdone\e[0m by the madness of men "
|
57
|
+
].join)
|
58
|
+
end
|
59
|
+
|
60
|
+
it "centers multiline text with fill character '*'" do
|
61
|
+
text = "for there is no folly of the beast\nof the earth which\nis not infinitely\noutdone by the madness of men"
|
62
|
+
expect(Strings::Align.align(text, 40, direction: :center, fill: '*')).to eq([
|
63
|
+
"***for there is no folly of the beast***\n",
|
64
|
+
"***********of the earth which***********\n",
|
65
|
+
"***********is not infinitely************\n",
|
66
|
+
"*****outdone by the madness of men******"
|
67
|
+
].join)
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Strings, '#align' do
|
4
|
+
it "aligns text" do
|
5
|
+
text = "the madness of men"
|
6
|
+
expect(Strings.align(text, 22, direction: :center)).to eq(" the madness of men ")
|
7
|
+
end
|
8
|
+
|
9
|
+
it "aligns text to left" do
|
10
|
+
text = "the madness of men"
|
11
|
+
expect(Strings.align_left(text, 22)).to eq("the madness of men ")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "aligns text to right" do
|
15
|
+
text = "the madness of men"
|
16
|
+
expect(Strings.align_right(text, 22)).to eq(" the madness of men")
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'strings/extensions'
|
4
|
+
|
5
|
+
using Strings::Extensions
|
6
|
+
|
7
|
+
RSpec.describe Strings::Extensions do
|
8
|
+
let(:text) { "the madness of men" }
|
9
|
+
|
10
|
+
it "aligns a line in the center" do
|
11
|
+
expect(text.align(22, direction: :center)).to eq(" the madness of men ")
|
12
|
+
end
|
13
|
+
|
14
|
+
it "aligns a line to the left" do
|
15
|
+
expect(text.align_left(22)).to eq("the madness of men ")
|
16
|
+
end
|
17
|
+
|
18
|
+
it "aligns a line to the right" do
|
19
|
+
expect(text.align_right(22)).to eq(" the madness of men")
|
20
|
+
end
|
21
|
+
|
22
|
+
it "checks for ansi" do
|
23
|
+
expect("\e[33mfoo\e[0m".ansi?).to eq(true)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "removes ansi codes" do
|
27
|
+
expect("\e[33mfoo\e[0m".sanitize).to eq('foo')
|
28
|
+
end
|
29
|
+
|
30
|
+
it "folds a line" do
|
31
|
+
expect("foo\n\nbar\n".fold).to eq('foo bar ')
|
32
|
+
end
|
33
|
+
|
34
|
+
it "pads a line" do
|
35
|
+
expect(text.pad(1)).to eq([
|
36
|
+
" " * (text.size + 2),
|
37
|
+
" #{text} ",
|
38
|
+
" " * (text.size + 2),
|
39
|
+
].join("\n"))
|
40
|
+
end
|
41
|
+
|
42
|
+
it "truncates a line" do
|
43
|
+
text = "the madness of men"
|
44
|
+
expect(text.truncate(10)).to eq('the madn…')
|
45
|
+
end
|
46
|
+
|
47
|
+
it "wraps a line" do
|
48
|
+
expect('foobar1'.wrap(3)).to eq("foo\nbar\n1")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# unicode: utf-8
|
2
|
+
# frozen_string_literals: true
|
3
|
+
|
4
|
+
RSpec.describe Strings, '#fold' do
|
5
|
+
{
|
6
|
+
" \n" => ' ',
|
7
|
+
"\n " => ' ',
|
8
|
+
"\n" => ' ',
|
9
|
+
"\n\n\n" => ' ',
|
10
|
+
" \n " => ' ',
|
11
|
+
" \n \n \n" => ' '
|
12
|
+
}.each do |actual, expected|
|
13
|
+
it "removes newline '#{actual.gsub(/\n/, '\\n')}' to '#{expected}'" do
|
14
|
+
expect(Strings::Fold.fold(actual)).to eq(expected)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
{
|
19
|
+
" \r\n" => ' ',
|
20
|
+
"\r\n " => ' ',
|
21
|
+
"\r\n" => ' ',
|
22
|
+
" \r\n " => ' ',
|
23
|
+
}.each do |actual, expected|
|
24
|
+
it "squashes '#{actual.gsub(/\r\n/, '\\r\\n')}' to '#{expected}'" do
|
25
|
+
expect(Strings::Fold.fold(actual, "\r\n")).to eq(expected)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Strings::Pad, '#pad' do
|
4
|
+
it "pads content with padding as a single value" do
|
5
|
+
text = "Ignorance is the parent of fear."
|
6
|
+
expect(Strings::Pad.pad(text, 1)).to eq([
|
7
|
+
" ",
|
8
|
+
" Ignorance is the parent of fear. ",
|
9
|
+
" ",
|
10
|
+
].join("\n"))
|
11
|
+
end
|
12
|
+
|
13
|
+
it "pads content with specific padding as an array" do
|
14
|
+
text = "Ignorance is the parent of fear."
|
15
|
+
expect(Strings::Pad.pad(text, [1,1,1,1])).to eq([
|
16
|
+
" ",
|
17
|
+
" Ignorance is the parent of fear. ",
|
18
|
+
" ",
|
19
|
+
].join("\n"))
|
20
|
+
end
|
21
|
+
|
22
|
+
it "pads with custom character" do
|
23
|
+
text = "Ignorance is the parent of fear."
|
24
|
+
expect(Strings::Pad.pad(text, [1, 2], fill: "*")).to eq([
|
25
|
+
"************************************",
|
26
|
+
"**Ignorance is the parent of fear.**",
|
27
|
+
"************************************",
|
28
|
+
].join("\n"))
|
29
|
+
end
|
30
|
+
|
31
|
+
it "pads unicode content" do
|
32
|
+
text = "ラドクリフ、マラソン"
|
33
|
+
expect(Strings::Pad.pad(text, [1,1,1,1])).to eq([
|
34
|
+
" ",
|
35
|
+
" ラドクリフ、マラソン ",
|
36
|
+
" "
|
37
|
+
].join("\n"))
|
38
|
+
end
|
39
|
+
|
40
|
+
it "pads multiline content" do
|
41
|
+
text = "It is the easiest thing\nin the world for a man\nto look as if he had \na great secret in him."
|
42
|
+
expect(Strings::Pad.pad(text, [1,2])).to eq([
|
43
|
+
" ",
|
44
|
+
" It is the easiest thing ",
|
45
|
+
" in the world for a man ",
|
46
|
+
" to look as if he had ",
|
47
|
+
" a great secret in him. ",
|
48
|
+
" ",
|
49
|
+
].join("\n"))
|
50
|
+
end
|
51
|
+
|
52
|
+
it "pads ANSI codes inside content" do
|
53
|
+
text = "It is \e[35mthe easiest\e[0m thing\nin the \e[34mworld\e[0m for a man\nto look as if he had \na great \e[33msecret\e[0m in him."
|
54
|
+
expect(Strings::Pad.pad(text, [1,1,1,1])).to eq([
|
55
|
+
" ",
|
56
|
+
" It is \e[35mthe easiest\e[0m thing ",
|
57
|
+
" in the \e[34mworld\e[0m for a man ",
|
58
|
+
" to look as if he had ",
|
59
|
+
" a great \e[33msecret\e[0m in him. ",
|
60
|
+
" ",
|
61
|
+
].join("\n"))
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal:true
|
2
|
+
|
3
|
+
RSpec.describe Strings::Padder, '#parse' do
|
4
|
+
it "parses nil" do
|
5
|
+
instance = Strings::Padder.parse(nil)
|
6
|
+
expect(instance.padding).to eq([])
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'parses self' do
|
10
|
+
value = Strings::Padder.new([])
|
11
|
+
instance = Strings::Padder.parse(value)
|
12
|
+
expect(instance.padding).to eq([])
|
13
|
+
end
|
14
|
+
|
15
|
+
it "parses digit" do
|
16
|
+
instance = Strings::Padder.parse(5)
|
17
|
+
expect(instance.padding).to eq([5,5,5,5])
|
18
|
+
end
|
19
|
+
|
20
|
+
it "parses 2-element array" do
|
21
|
+
instance = Strings::Padder.parse([2,3])
|
22
|
+
expect(instance.padding).to eq([2,3,2,3])
|
23
|
+
end
|
24
|
+
|
25
|
+
it "parses 4-element array" do
|
26
|
+
instance = Strings::Padder.parse([1,2,3,4])
|
27
|
+
expect(instance.padding).to eq([1,2,3,4])
|
28
|
+
end
|
29
|
+
|
30
|
+
it "fails to parse unknown value" do
|
31
|
+
expect {
|
32
|
+
Strings::Padder.parse(:unknown)
|
33
|
+
}.to raise_error(Strings::Padder::ParseError)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
RSpec.describe Strings::Truncate, '#truncate' do
|
4
|
+
let(:text) { 'ラドクリフ、マラソン五輪代表に1万m出場にも含み' }
|
5
|
+
|
6
|
+
it "doesn't change text for 0 length" do
|
7
|
+
expect(Strings::Truncate.truncate(text, 0)).to eq(text)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "doensn't change text for nil length" do
|
11
|
+
expect(Strings::Truncate.truncate(text, nil)).to eq(text)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "doesn't change text for equal length" do
|
15
|
+
truncation = Strings::Truncate.truncate(text, text.length * 2)
|
16
|
+
expect(truncation).to eq(text)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'truncates text and displays omission' do
|
20
|
+
trailing = '…'
|
21
|
+
expect(Strings::Truncate.truncate(text, 12)).to eq("ラドクリフ#{trailing}")
|
22
|
+
end
|
23
|
+
|
24
|
+
it "estimates total width correctly " do
|
25
|
+
text = '太丸ゴシック体'
|
26
|
+
trailing = '…'
|
27
|
+
expect(Strings::Truncate.truncate(text, 8)).to eq("太丸ゴ#{trailing}")
|
28
|
+
end
|
29
|
+
|
30
|
+
it "doesn't truncate text when length exceeds content" do
|
31
|
+
expect(Strings::Truncate.truncate(text, 100)).to eq(text)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "doesn't truncate whole words" do
|
35
|
+
text = "I know not all that may be coming, but be it what it will, I'll go to it laughing."
|
36
|
+
trailing = '…'
|
37
|
+
truncation = Strings::Truncate.truncate(text, separator: ' ')
|
38
|
+
expect(truncation).to eq("I know not all that may be#{trailing}")
|
39
|
+
end
|
40
|
+
|
41
|
+
it 'truncates text with string separator' do
|
42
|
+
trailing = '…'
|
43
|
+
truncation = Strings::Truncate.truncate(text, 12, separator: '')
|
44
|
+
expect(truncation).to eq("ラドクリフ#{trailing}")
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'truncates text with regex separator' do
|
48
|
+
trailing = '…'
|
49
|
+
truncation = Strings::Truncate.truncate(text, 12, separator: /\s/)
|
50
|
+
expect(truncation).to eq("ラドクリフ#{trailing}")
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'truncates text with custom trailing' do
|
54
|
+
trailing = '... (see more)'
|
55
|
+
truncation = Strings::Truncate.truncate(text, 20, trailing: trailing)
|
56
|
+
expect(truncation).to eq("ラド#{trailing}")
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'correctly truncates with ANSI characters' do
|
60
|
+
text = "I try \e[34mall things\e[0m, I achieve what I can"
|
61
|
+
truncation = Strings::Truncate.truncate(text, 18)
|
62
|
+
expect(truncation).to eq("I try \e[34mall things\e[0m…")
|
63
|
+
end
|
64
|
+
|
65
|
+
it "finishes on word boundary" do
|
66
|
+
text = "for there is no folly of the beast of the earth"
|
67
|
+
truncation = Strings::Truncate.truncate(text, 20, separator: ' ')
|
68
|
+
expect(truncation).to eq('for there is no…')
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,155 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
RSpec.describe Strings::Wrap, '.wrap' do
|
4
|
+
context 'when unicode' do
|
5
|
+
let(:text) { 'ラドクリフ、マラソン五輪代表に1万m出場にも含み' }
|
6
|
+
|
7
|
+
it "doesn't wrap at zero length" do
|
8
|
+
expect(Strings::Wrap.wrap(text, 0)).to eq(text)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "doesn't wrap at nil length" do
|
12
|
+
expect(Strings::Wrap.wrap(text, nil)).to eq(text)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "doesn't wrap at length exceeding content length" do
|
16
|
+
expect(Strings::Wrap.wrap(text, 100)).to eq(text)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "wraps correctly unbreakable words" do
|
20
|
+
expect(Strings::Wrap.wrap('foobar1', 3)).to eq([
|
21
|
+
"foo",
|
22
|
+
"bar",
|
23
|
+
"1"
|
24
|
+
].join("\n"))
|
25
|
+
end
|
26
|
+
|
27
|
+
it "collapses multiple line breaks " do
|
28
|
+
text = "some \r\n\n\n\nunbreakable\n\n\n\n \r\r\rcontent \t"
|
29
|
+
expect(Strings::Wrap.wrap(text, 5)).to eq([
|
30
|
+
"some ",
|
31
|
+
"unbre",
|
32
|
+
"akabl",
|
33
|
+
"e",
|
34
|
+
" ",
|
35
|
+
"conte",
|
36
|
+
"nt "
|
37
|
+
].join("\n"))
|
38
|
+
end
|
39
|
+
|
40
|
+
it "preserves newlines" do
|
41
|
+
text = "It is not down\n on any map;\n true places never are."
|
42
|
+
expect(Strings::Wrap.wrap(text, 10)).to eq([
|
43
|
+
"It is not ",
|
44
|
+
"down",
|
45
|
+
" on any ",
|
46
|
+
"map;",
|
47
|
+
" true ",
|
48
|
+
"places ",
|
49
|
+
"never are."
|
50
|
+
].join("\n"))
|
51
|
+
end
|
52
|
+
|
53
|
+
it "wraps ascii text" do
|
54
|
+
text = "for there is no folly of the beast of the earth which is not infinitely outdone by the madness of men "
|
55
|
+
expect(Strings::Wrap.wrap(text, 16)).to eq([
|
56
|
+
"for there is no ",
|
57
|
+
"folly of the ",
|
58
|
+
"beast of the ",
|
59
|
+
"earth which is ",
|
60
|
+
"not infinitely ",
|
61
|
+
"outdone by the ",
|
62
|
+
"madness of men "
|
63
|
+
].join("\n"))
|
64
|
+
end
|
65
|
+
|
66
|
+
it 'wraps at 8 characters' do
|
67
|
+
expect(Strings::Wrap.wrap(text, 8)).to eq([
|
68
|
+
"ラドクリ",
|
69
|
+
"フ、マラ",
|
70
|
+
"ソン五輪",
|
71
|
+
"代表に1",
|
72
|
+
"万m出場",
|
73
|
+
"にも含み"
|
74
|
+
].join("\n"))
|
75
|
+
end
|
76
|
+
|
77
|
+
it 'preserves whitespace' do
|
78
|
+
text = " As for me, I am tormented with an everlasting itch for things remote. "
|
79
|
+
expect(Strings::Wrap.wrap(text, 10)).to eq([
|
80
|
+
" As for ",
|
81
|
+
"me, I ",
|
82
|
+
"am ",
|
83
|
+
"tormented ",
|
84
|
+
"with an ",
|
85
|
+
"e",
|
86
|
+
"verlasting",
|
87
|
+
" itch ",
|
88
|
+
"for ",
|
89
|
+
"things ",
|
90
|
+
"remote. "
|
91
|
+
].join("\n"))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'when long text' do
|
96
|
+
it "wraps long text at 45 characters" do
|
97
|
+
text =
|
98
|
+
"What of it, if some old hunks of a sea-captain orders me to get a broom and sweep down the decks? What does that indignity amount to, weighed, I mean, in the scales of the New Testament? Do you think the archangel Gabriel thinks anything the less of me, because I promptly and respectfully obey that old hunks in that particular instance? Who ain't a slave? Tell me that. Well, then, however the old sea-captains may order me about--however they may thump and punch me about, I have the satisfaction of knowing that it is all right;"
|
99
|
+
expect(Strings::Wrap.wrap(text, 45)).to eq unindent <<-EOS
|
100
|
+
What of it, if some old hunks of a \nsea-captain orders me to get a broom and \n sweep down the decks? What does that \nindignity amount to, weighed, I mean, in the \n scales of the New Testament? Do you think \nthe archangel Gabriel thinks anything the \nless of me, because I promptly and \nrespectfully obey that old hunks in that \nparticular instance? Who ain't a slave? Tell \nme that. Well, then, however the old \nsea-captains may order me about--however \nthey may thump and punch me about, I have \nthe satisfaction of knowing that it is all \nright;
|
101
|
+
EOS
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
context 'with newlines' do
|
106
|
+
it "preserves newlines for both prefix and postfix" do
|
107
|
+
text = "\n\nラドクリフ、マラソン五輪代表に1万m出場にも含み\n\n\n"
|
108
|
+
expect(Strings::Wrap.wrap(text, 10)).to eq([
|
109
|
+
"\nラドクリフ",
|
110
|
+
"、マラソン",
|
111
|
+
"五輪代表に",
|
112
|
+
"1万m出場に",
|
113
|
+
"も含み\n"
|
114
|
+
].join("\n"))
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context 'with ANSI codes' do
|
119
|
+
it "wraps ANSI chars" do
|
120
|
+
text = "\e[32;44mIgnorance is the parent of fear.\e[0m"
|
121
|
+
expect(Strings::Wrap.wrap(text, 14)).to eq([
|
122
|
+
"\e[32;44mIgnorance is \e[0m",
|
123
|
+
"\e[32;44mthe parent of \e[0m",
|
124
|
+
"\e[32;44mfear.\e[0m",
|
125
|
+
].join("\n"))
|
126
|
+
end
|
127
|
+
|
128
|
+
it "wraps ANSI in the middle of text" do
|
129
|
+
text = "Ignorance is the \e[32mparent\e[0m of fear."
|
130
|
+
expect(Strings::Wrap.wrap(text, 14)).to eq([
|
131
|
+
"Ignorance is ",
|
132
|
+
"the \e[32mparent\e[0m of ",
|
133
|
+
"fear.",
|
134
|
+
].join("\n"))
|
135
|
+
end
|
136
|
+
|
137
|
+
it "wraps multline ANSI codes" do
|
138
|
+
text = "\e32;44mMulti\nLine\nContent.\e[0m"
|
139
|
+
expect(Strings::Wrap.wrap(text, 14)).to eq([
|
140
|
+
"\e32;44mMulti\e[0m",
|
141
|
+
"\e32;44mLine\e[0m",
|
142
|
+
"\e32;44mContent.\e[0m",
|
143
|
+
].join("\n"))
|
144
|
+
end
|
145
|
+
|
146
|
+
it "wraps multiple ANSI codes in a single line" do
|
147
|
+
text = "Talk \e[32mnot\e[0m to me of \e[33mblasphemy\e[0m, man; I'd \e[35mstrike the sun\e[0m if it insulted me."
|
148
|
+
expect(Strings::Wrap.wrap(text, 30)).to eq([
|
149
|
+
"Talk \e[32mnot\e[0m to me of \e[33mblasphemy\e[0m, ",
|
150
|
+
"man; I'd \e[35mstrike the sun\e[0m if it ",
|
151
|
+
"insulted me."
|
152
|
+
].join("\n"))
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
data/strings.gemspec
CHANGED
@@ -14,13 +14,13 @@ Gem::Specification.new do |spec|
|
|
14
14
|
spec.homepage = ""
|
15
15
|
spec.license = "MIT"
|
16
16
|
|
17
|
-
spec.files =
|
18
|
-
|
19
|
-
end
|
17
|
+
spec.files = Dir['{lib,spec}/**/*.rb', '{bin,tasks}/*', 'strings.gemspec']
|
18
|
+
spec.files += Dir['README.md', 'CHANGELOG.md', 'LICENSE.txt', 'Rakefile']
|
20
19
|
spec.bindir = "exe"
|
21
20
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
22
21
|
spec.require_paths = ["lib"]
|
23
22
|
|
23
|
+
spec.add_dependency 'strings-ansi', '~> 0.1.0'
|
24
24
|
spec.add_dependency 'unicode_utils', '~> 1.4.0'
|
25
25
|
spec.add_dependency 'unicode-display_width','~> 1.4.0'
|
26
26
|
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: strings
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Piotr Murach
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-08-
|
11
|
+
date: 2018-08-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: strings-ansi
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.1.0
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 0.1.0
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: unicode_utils
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -88,23 +102,14 @@ executables: []
|
|
88
102
|
extensions: []
|
89
103
|
extra_rdoc_files: []
|
90
104
|
files:
|
91
|
-
- ".gitignore"
|
92
|
-
- ".rspec"
|
93
|
-
- ".travis.yml"
|
94
105
|
- CHANGELOG.md
|
95
|
-
- CODE_OF_CONDUCT.md
|
96
|
-
- Gemfile
|
97
106
|
- LICENSE.txt
|
98
107
|
- README.md
|
99
108
|
- Rakefile
|
100
|
-
- appveyor.yml
|
101
|
-
- assets/strings_logo.png
|
102
|
-
- benchmarks/speed_profile.rb
|
103
109
|
- bin/console
|
104
110
|
- bin/setup
|
105
111
|
- lib/strings.rb
|
106
112
|
- lib/strings/align.rb
|
107
|
-
- lib/strings/ansi.rb
|
108
113
|
- lib/strings/extensions.rb
|
109
114
|
- lib/strings/fold.rb
|
110
115
|
- lib/strings/pad.rb
|
@@ -112,6 +117,23 @@ files:
|
|
112
117
|
- lib/strings/truncate.rb
|
113
118
|
- lib/strings/version.rb
|
114
119
|
- lib/strings/wrap.rb
|
120
|
+
- spec/spec_helper.rb
|
121
|
+
- spec/unit/align/align_left_spec.rb
|
122
|
+
- spec/unit/align/align_right_spec.rb
|
123
|
+
- spec/unit/align/align_spec.rb
|
124
|
+
- spec/unit/align_spec.rb
|
125
|
+
- spec/unit/ansi_spec.rb
|
126
|
+
- spec/unit/extensions_spec.rb
|
127
|
+
- spec/unit/fold/fold_spec.rb
|
128
|
+
- spec/unit/fold_spec.rb
|
129
|
+
- spec/unit/pad/pad_spec.rb
|
130
|
+
- spec/unit/pad_spec.rb
|
131
|
+
- spec/unit/padder/parse_spec.rb
|
132
|
+
- spec/unit/sanitize_spec.rb
|
133
|
+
- spec/unit/truncate/truncate_spec.rb
|
134
|
+
- spec/unit/truncate_spec.rb
|
135
|
+
- spec/unit/wrap/wrap_spec.rb
|
136
|
+
- spec/unit/wrap_spec.rb
|
115
137
|
- strings.gemspec
|
116
138
|
- tasks/console.rake
|
117
139
|
- tasks/coverage.rake
|
data/.gitignore
DELETED
data/.rspec
DELETED
data/.travis.yml
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
---
|
2
|
-
language: ruby
|
3
|
-
sudo: false
|
4
|
-
cache: bundler
|
5
|
-
before_install: "gem update bundler"
|
6
|
-
script: "bundle exec rake ci"
|
7
|
-
rvm:
|
8
|
-
- 2.0.0
|
9
|
-
- 2.1.10
|
10
|
-
- 2.2.9
|
11
|
-
- 2.3.6
|
12
|
-
- 2.4.4
|
13
|
-
- 2.5.1
|
14
|
-
- ruby-head
|
15
|
-
- jruby-9.1.5.0
|
16
|
-
- jruby-head
|
17
|
-
matrix:
|
18
|
-
allow_failures:
|
19
|
-
- rvm: ruby-head
|
20
|
-
- rvm: jruby-head
|
21
|
-
fast_finish: true
|
22
|
-
branches:
|
23
|
-
only: master
|
data/CODE_OF_CONDUCT.md
DELETED
@@ -1,74 +0,0 @@
|
|
1
|
-
# Contributor Covenant Code of Conduct
|
2
|
-
|
3
|
-
## Our Pledge
|
4
|
-
|
5
|
-
In the interest of fostering an open and welcoming environment, we as
|
6
|
-
contributors and maintainers pledge to making participation in our project and
|
7
|
-
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
-
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
-
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
-
orientation.
|
11
|
-
|
12
|
-
## Our Standards
|
13
|
-
|
14
|
-
Examples of behavior that contributes to creating a positive environment
|
15
|
-
include:
|
16
|
-
|
17
|
-
* Using welcoming and inclusive language
|
18
|
-
* Being respectful of differing viewpoints and experiences
|
19
|
-
* Gracefully accepting constructive criticism
|
20
|
-
* Focusing on what is best for the community
|
21
|
-
* Showing empathy towards other community members
|
22
|
-
|
23
|
-
Examples of unacceptable behavior by participants include:
|
24
|
-
|
25
|
-
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
-
advances
|
27
|
-
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
-
* Public or private harassment
|
29
|
-
* Publishing others' private information, such as a physical or electronic
|
30
|
-
address, without explicit permission
|
31
|
-
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
-
professional setting
|
33
|
-
|
34
|
-
## Our Responsibilities
|
35
|
-
|
36
|
-
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
-
behavior and are expected to take appropriate and fair corrective action in
|
38
|
-
response to any instances of unacceptable behavior.
|
39
|
-
|
40
|
-
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
-
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
-
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
-
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
-
threatening, offensive, or harmful.
|
45
|
-
|
46
|
-
## Scope
|
47
|
-
|
48
|
-
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
-
when an individual is representing the project or its community. Examples of
|
50
|
-
representing a project or community include using an official project e-mail
|
51
|
-
address, posting via an official social media account, or acting as an appointed
|
52
|
-
representative at an online or offline event. Representation of a project may be
|
53
|
-
further defined and clarified by project maintainers.
|
54
|
-
|
55
|
-
## Enforcement
|
56
|
-
|
57
|
-
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
-
reported by contacting the project team at [email]. All
|
59
|
-
complaints will be reviewed and investigated and will result in a response that
|
60
|
-
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
-
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
-
Further details of specific enforcement policies may be posted separately.
|
63
|
-
|
64
|
-
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
-
faith may face temporary or permanent repercussions as determined by other
|
66
|
-
members of the project's leadership.
|
67
|
-
|
68
|
-
## Attribution
|
69
|
-
|
70
|
-
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
-
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
-
|
73
|
-
[homepage]: http://contributor-covenant.org
|
74
|
-
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
DELETED
@@ -1,15 +0,0 @@
|
|
1
|
-
source "https://rubygems.org"
|
2
|
-
|
3
|
-
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
|
4
|
-
|
5
|
-
gemspec
|
6
|
-
|
7
|
-
group :metrics do
|
8
|
-
gem 'coveralls', '~> 0.8.22'
|
9
|
-
gem 'simplecov', '~> 0.16.1'
|
10
|
-
gem 'yardstick', '~> 0.9.9'
|
11
|
-
end
|
12
|
-
|
13
|
-
group :benchmarks do
|
14
|
-
gem 'benchmark-ips', '~> 2.7.2'
|
15
|
-
end
|
data/appveyor.yml
DELETED
@@ -1,23 +0,0 @@
|
|
1
|
-
---
|
2
|
-
install:
|
3
|
-
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
4
|
-
- ruby --version
|
5
|
-
- gem --version
|
6
|
-
- bundle install
|
7
|
-
build: off
|
8
|
-
test_script:
|
9
|
-
- bundle exec rake ci
|
10
|
-
environment:
|
11
|
-
matrix:
|
12
|
-
- ruby_version: "200"
|
13
|
-
- ruby_version: "200-x64"
|
14
|
-
- ruby_version: "21"
|
15
|
-
- ruby_version: "21-x64"
|
16
|
-
- ruby_version: "22"
|
17
|
-
- ruby_version: "22-x64"
|
18
|
-
- ruby_version: "23"
|
19
|
-
- ruby_version: "23-x64"
|
20
|
-
- ruby_version: "24"
|
21
|
-
- ruby_version: "24-x64"
|
22
|
-
- ruby_version: "25"
|
23
|
-
- ruby_version: "25-x64"
|
data/assets/strings_logo.png
DELETED
Binary file
|
data/benchmarks/speed_profile.rb
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
require 'benchmark/ips'
|
2
|
-
require 'strings'
|
3
|
-
|
4
|
-
text = "Ignorance is the parent of fear."
|
5
|
-
|
6
|
-
Benchmark.ips do |x|
|
7
|
-
x.report('wrap') do
|
8
|
-
Strings::Wrap.wrap(text, 10)
|
9
|
-
end
|
10
|
-
|
11
|
-
x.report('truncate') do
|
12
|
-
Strings::Truncate.truncate(text, 10)
|
13
|
-
end
|
14
|
-
|
15
|
-
x.compare!
|
16
|
-
end
|
17
|
-
|
18
|
-
# (2017-12-09)
|
19
|
-
#
|
20
|
-
# Calculating -------------------------------------
|
21
|
-
# wrap 186 i/100ms
|
22
|
-
# truncate 295 i/100ms
|
23
|
-
# -------------------------------------------------
|
24
|
-
# wrap 1917.2 (±2.2%) i/s - 9672 in 5.047297s
|
25
|
-
# truncate 3020.6 (±3.0%) i/s - 15340 in 5.083516s
|
26
|
-
#
|
27
|
-
# Comparison:
|
28
|
-
# truncate: 3020.6 i/s
|
29
|
-
# wrap: 1917.2 i/s - 1.58x slower
|
30
|
-
#
|
data/lib/strings/ansi.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
module Strings
|
4
|
-
# Helper functions for handling ANSI escape sequences
|
5
|
-
module ANSI
|
6
|
-
# The control sequence indicator
|
7
|
-
CSI = "\033".freeze
|
8
|
-
|
9
|
-
# The code for reseting styling
|
10
|
-
RESET = "\e[0m".freeze
|
11
|
-
|
12
|
-
# The regex to match ANSI codes
|
13
|
-
ANSI_MATCHER = '(\[)?\033(\[)?[;?\d]*[\dA-Za-z]([\];])?'.freeze
|
14
|
-
|
15
|
-
# Remove ANSI characters from the text
|
16
|
-
#
|
17
|
-
# @param [String] text
|
18
|
-
#
|
19
|
-
# @example
|
20
|
-
# Strings::ANSI.sanitize("\e[33mfoo\[e0m")
|
21
|
-
# # => "foo"
|
22
|
-
#
|
23
|
-
# @return [String]
|
24
|
-
#
|
25
|
-
# @api public
|
26
|
-
def sanitize(text)
|
27
|
-
text.gsub(/#{ANSI_MATCHER}/, '')
|
28
|
-
end
|
29
|
-
module_function :sanitize
|
30
|
-
|
31
|
-
# Check if string contains ANSI codes
|
32
|
-
#
|
33
|
-
# @param [String] string
|
34
|
-
# the string to check
|
35
|
-
#
|
36
|
-
# @example
|
37
|
-
# Strings::ANSI.ansi?("\e[33mfoo\[e0m")
|
38
|
-
# # => true
|
39
|
-
#
|
40
|
-
# @return [Boolean]
|
41
|
-
#
|
42
|
-
# @api public
|
43
|
-
def ansi?(string)
|
44
|
-
!!(string =~ /#{ANSI_MATCHER}/)
|
45
|
-
end
|
46
|
-
module_function :ansi?
|
47
|
-
|
48
|
-
# Check if string contains only ANSI codes
|
49
|
-
#
|
50
|
-
# @param [String] string
|
51
|
-
# the string to check
|
52
|
-
#
|
53
|
-
# @example
|
54
|
-
# Strings::ANSI.only_ansi?("\e[33mfoo\[e0m")
|
55
|
-
# # => false
|
56
|
-
#
|
57
|
-
# Strings::ANSI.only_ansi?("\e[33m")
|
58
|
-
# # => false
|
59
|
-
#
|
60
|
-
# @return [Boolean]
|
61
|
-
#
|
62
|
-
# @api public
|
63
|
-
def only_ansi?(string)
|
64
|
-
!!(string =~ /^#{ANSI_MATCHER}$/)
|
65
|
-
end
|
66
|
-
module_function :only_ansi?
|
67
|
-
end # Sanitizer
|
68
|
-
end # Strings
|