visual_width 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 05cf7a6f8d1cb732fa2f35fabbe3a495c727e4d3
4
- data.tar.gz: 47a372ba9ede858b3cf1c1f697c6476027ecfa4f
3
+ metadata.gz: 4de483063c67cddbaca1f3ac3a1ac27536311218
4
+ data.tar.gz: 3d9ab9b361e41e1edc9d2f095c28a3591e72cfbb
5
5
  SHA512:
6
- metadata.gz: 3077e27f95bf06842b167e819396557fe3337c48bed7f520e1225da0f08918004120676ec78e7fa1188f1c610628c3dc557d67af14ddb86616bded777ce90cb6
7
- data.tar.gz: 7150d1b9c1f9fe84109098848d98f1b0da45cf56a2125b011b974a4ff8270a8f251077b508633245d73a78e85dc1faeaba85d3307f906bb91078660698f428df
6
+ metadata.gz: fd041e918922cf48e5686b8d9d7c4417b8bbde49c11fa65f6f2d3c6783f0afccd6f41397d2aae6b75f94ed3cdba3e3fbdd04901433df06ee1ee935ed724b68e0
7
+ data.tar.gz: 40a336d2d2e0e2b919109744910a17cb2860dfe13e59c69c7766c3707f65a614e8226402c1bbf5711953f81a154f1022c3c7e8df7bc93b76755d54fcd429f815
data/.travis.yml ADDED
@@ -0,0 +1,3 @@
1
+ languages: ruby
2
+ rvm:
3
+ - 2.0.0
data/README.md CHANGED
@@ -21,12 +21,28 @@ Or install it yourself as:
21
21
  ## Usage
22
22
 
23
23
  ```ruby
24
+ # VisualWidth
24
25
  require 'visual_width'
25
26
 
26
- p VisualWidth.count("こんにちは") # => 10
27
- p VisualWidth.count("abcdefghij") # => 10
27
+ p VisualWidth.measure("こんにちは") # => 10
28
+ p VisualWidth.measure("abcdefghij") # => 10
28
29
 
29
30
  p VisualWidth.truncate("恋すてふ 我が名はまだき 立ちにけり 人知れずこそ 思ひそめしか", 20) # => "恋すてふ 我が名は..."
31
+
32
+ # VisualWidth::Table
33
+ require 'visual_width/table'
34
+
35
+ t = VisualWidth::Table.new(
36
+ format: [VisualWidth::Table::LEFT, VisualWidth::Table::RIGHT, VisualWidth::Table::RIGHT]
37
+ )
38
+
39
+ header = ['Student', 'Mid-Terms', 'Finals']
40
+ rows = [
41
+ ['Sam', 94, 93],
42
+ ['Jane', 92, 99],
43
+ ['Average', 93, 96],
44
+ ]
45
+ t.draw(rows, header: header)
30
46
  ```
31
47
 
32
48
  Each method can take `east_asian: false` to tell it is not in an East Asian context, regarding ambiguous characters as half-width.
@@ -40,3 +56,7 @@ See [Ambiguous Characters](http://www.unicode.org/reports/tr11/#Ambiguous) in th
40
56
  3. Commit your changes (`git commit -am 'Add some feature'`)
41
57
  4. Push to the branch (`git push origin my-new-feature`)
42
58
  5. Create new Pull Request
59
+
60
+ ## See Also
61
+
62
+ * [unicode-display_width](https://rubygems.org/gems/unicode-display_width) has the same feature as `VisualWidth.measure()` but it extends String class directly and is much slower than `VisualWidth.measure()`
data/example/table.rb ADDED
@@ -0,0 +1,13 @@
1
+ # VisualWidth::Table
2
+ require 'visual_width/table'
3
+ t = VisualWidth::Table.new(
4
+ format: [VisualWidth::Table::LEFT, VisualWidth::Table::RIGHT, VisualWidth::Table::RIGHT]
5
+ )
6
+
7
+ header = ['Student', 'Mid-Terms', 'Finals']
8
+ rows = [
9
+ ['Sam', 94, 93],
10
+ ['Jane', 92, 99],
11
+ ['Average', 93, 96],
12
+ ]
13
+ puts t.draw(rows, header: header)
@@ -2,7 +2,7 @@ require 'visual_width'
2
2
 
3
3
  class String
4
4
  def width(opts = {})
5
- VisualWidth.count(self, opts)
5
+ VisualWidth.measure(self, opts)
6
6
  end
7
7
 
8
8
  def truncate(max_length, opts = {})
@@ -3,7 +3,7 @@ require 'visual_width'
3
3
  module VisualWidth
4
4
  refine String do
5
5
  def width(opts = {})
6
- VisualWidth.count(self, opts)
6
+ VisualWidth.measure(self, opts)
7
7
  end
8
8
 
9
9
  def truncate(max_length, opts = {})
@@ -0,0 +1,83 @@
1
+ require 'visual_width'
2
+
3
+ class VisualWidth::Table
4
+ attr_accessor :header, :footer, :format
5
+
6
+ # align (left, right, center)
7
+ LEFT = -> (cell, fill) {
8
+ cell + (' ' * fill)
9
+ }
10
+
11
+ RIGHT = -> (cell, fill) {
12
+ (' ' * fill) + cell
13
+ }
14
+
15
+ CENTER = -> (cell, fill) {
16
+ half = fill / 2.0
17
+ (' ' * half.floor) + cell + (' ' * half.ceil)
18
+ }
19
+
20
+ def initialize(header: nil, format: [])
21
+ @header = header
22
+ @format = format
23
+ end
24
+
25
+ def draw(rows, header: nil, output: "")
26
+ max_widths = calc_max_widths(rows)
27
+ h = header || @header
28
+ if h
29
+ max_widths = h.map { |cell| VisualWidth.measure(cell) }
30
+ .zip(max_widths)
31
+ .map { |values| values.max }
32
+ format_header = [CENTER] * h.length
33
+ else
34
+ format_header = nil
35
+ end
36
+ draw_row(output, max_widths, format_header, h, separated: true)
37
+ rows.each do |row|
38
+ draw_row(output, max_widths, @format, row)
39
+ end
40
+ line(output, max_widths)
41
+ output
42
+ end
43
+ private
44
+
45
+ def draw_row(output, max_widths, format, row, separated: false)
46
+ if separated
47
+ line(output, max_widths)
48
+ end
49
+
50
+ if row
51
+ output << '|'
52
+ row.each_with_index do |cell, i|
53
+ fill(output, max_widths[i], cell.to_s, format[i])
54
+ output << '|'
55
+ end
56
+ output << "\n"
57
+
58
+ if separated
59
+ line(output, max_widths)
60
+ end
61
+ end
62
+ end
63
+
64
+ def line (output, max_widths)
65
+ output << '+' << max_widths.map { |width| '-' * width }.join('+') << "+\n"
66
+ end
67
+
68
+ def fill(output, max_width, cell, f)
69
+ f ||= LEFT
70
+ w = VisualWidth.measure(cell)
71
+ output << f.call(cell, (max_width - w))
72
+ end
73
+
74
+ def calc_max_widths(rows) # -> [max_col0_width, max_col1_width, ...]
75
+ result = []
76
+ rows.each_with_index do |row|
77
+ row.each_with_index do |cell, i|
78
+ result[i] = [result[i] || 0, VisualWidth.measure(cell.to_s)].max
79
+ end
80
+ end
81
+ result
82
+ end
83
+ end
@@ -1,3 +1,3 @@
1
1
  module VisualWidth
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/visual_width.rb CHANGED
@@ -4,44 +4,44 @@ require "visual_width/data"
4
4
  module VisualWidth
5
5
  EAST_ASIAN = true
6
6
 
7
- @@c1 = /( (?:#{Fullwide} | #{Wide} | #{Ambiguous})+ )/x
8
- @@c0 = /( (?:#{Fullwide} | #{Wide} )+ )/x
7
+ r1 = /#{Fullwide} | #{Wide} | #{Ambiguous}/x;
8
+ r0 = /#{Fullwide} | #{Wide} /x;
9
9
 
10
- @@t1 = /( (?:#{Fullwide} | #{Wide} | #{Ambiguous}) ) | ./x
11
- @@t0 = /( (?:#{Fullwide} | #{Wide} ) ) | ./x
10
+ @@c1 = /( #{r1}+ )/x
11
+ @@c0 = /( #{r0}+ )/x
12
+
13
+ @@t1 = /( #{r1} ) | . /x
14
+ @@t0 = /( #{r0} ) | . /x
12
15
 
13
16
  module_function
14
17
 
15
- def count(str, east_asian: EAST_ASIAN)
18
+ def count(*args)
19
+ warn "count() is deprecated. use measure() instead"
20
+ measure(*args)
21
+ end
22
+
23
+ def measure(str, east_asian: EAST_ASIAN)
16
24
  rx = east_asian ? @@c1 : @@c0
17
25
  full_width = 0
18
- str.scan(rx) do |w,|
19
- full_width += w.length
26
+ str.scan(rx) do |wide,|
27
+ full_width += wide.length
20
28
  end
21
29
  (full_width * 2) + (str.length - full_width)
22
30
  end
23
31
 
24
32
  def truncate(str, max_length, omission: '...', east_asian: EAST_ASIAN)
25
- max = max_length - omission.length
26
33
  rx = east_asian ? @@t1 : @@t0
34
+ max = max_length - omission.length
27
35
  pos = 0
28
36
  width = 0
29
37
  str.scan(rx) do |wide,|
30
- if wide
31
- width += 2
32
- else
33
- width += 1
34
- end
38
+ width += wide ? 2 : 1
35
39
 
36
- if width > max
37
- break
38
- end
40
+ break if width > max
39
41
 
40
42
  pos += 1
41
43
 
42
- if width == max
43
- break
44
- end
44
+ break if width == max
45
45
  end
46
46
 
47
47
  if width < str.length
@@ -1,10 +1,13 @@
1
+ # coding: utf-8
2
+
1
3
  require 'rspec'
2
4
 
5
+ require 'visual_width/string_ext' # workaround Ruby 2.0.0 bug
3
6
  require 'visual_width/string_refine'
4
7
 
5
8
  using VisualWidth
6
9
 
7
- describe VisualWidth do
10
+ describe VisualWidth, skip: RUBY_VERSION < "2.0.0" do
8
11
  context "String#width" do
9
12
  it do
10
13
  expect("こんにちは".width).to eql(10)
@@ -0,0 +1,77 @@
1
+ # coding: utf-8
2
+
3
+ require 'rspec'
4
+
5
+ require 'visual_width/table'
6
+
7
+ describe VisualWidth::Table do
8
+ let (:rows) do
9
+ rows = []
10
+ rows << %w(りんご なし)
11
+ rows << %w(べにしぐれ せいぎょく)
12
+ rows << %w(となみ いなぎ)
13
+ rows
14
+ end
15
+
16
+ context "#draw" do
17
+ it 'draws text table' do
18
+ t = VisualWidth::Table.new
19
+
20
+ expect(t.draw(rows)).to eql(<<-'TEXT')
21
+ +----------+----------+
22
+ |りんご |なし |
23
+ |べにしぐれ|せいぎょく|
24
+ |となみ |いなぎ |
25
+ +----------+----------+
26
+ TEXT
27
+ end
28
+
29
+ it 'draws text table with formatter/CENTER, RIGHT' do
30
+ t = VisualWidth::Table.new(
31
+ format: [VisualWidth::Table::CENTER, VisualWidth::Table::RIGHT],
32
+ )
33
+
34
+ expect(t.draw(rows)).to eql(<<-'TEXT')
35
+ +----------+----------+
36
+ | りんご | なし|
37
+ |べにしぐれ|せいぎょく|
38
+ | となみ | いなぎ|
39
+ +----------+----------+
40
+ TEXT
41
+ end
42
+
43
+ it 'draws text table with header/footer' do
44
+ t = VisualWidth::Table.new(
45
+ header: %w(A B),
46
+ )
47
+ expect(t.draw(rows)).to eql(<<-'TEXT')
48
+ +----------+----------+
49
+ | A | B |
50
+ +----------+----------+
51
+ |りんご |なし |
52
+ |べにしぐれ|せいぎょく|
53
+ |となみ |いなぎ |
54
+ +----------+----------+
55
+ TEXT
56
+ end
57
+
58
+ it "does jobs with non-string elements" do
59
+ header = ['Student', 'Mid-Terms', 'Finals']
60
+ rows = [
61
+ ['Sam', 94, 93],
62
+ ['Jane', 92, 99],
63
+ ['Average', 93, 96],
64
+ ]
65
+
66
+ expect(VisualWidth::Table.new.draw(rows, header: header)).to eql(<<-'TEXT')
67
+ +-------+---------+------+
68
+ |Student|Mid-Terms|Finals|
69
+ +-------+---------+------+
70
+ |Sam |94 |93 |
71
+ |Jane |92 |99 |
72
+ |Average|93 |96 |
73
+ +-------+---------+------+
74
+ TEXT
75
+ end
76
+ end
77
+ end
@@ -1,40 +1,42 @@
1
+ # coding: utf-8
2
+
1
3
  require 'rspec'
2
4
 
3
5
  require 'visual_width'
4
6
  require 'visual_width/string_ext'
5
7
 
6
8
  describe VisualWidth do
7
- context ".count" do
8
- it "counts Half characters" do
9
- expect(VisualWidth.count("foo")).to eql(3)
9
+ context ".measure" do
10
+ it "measures Half characters" do
11
+ expect(VisualWidth.measure("foo")).to eql(3)
10
12
  end
11
- it "counts Wide characters" do
12
- expect(VisualWidth.count("こんにちは")).to eql(10)
13
+ it "measures Wide characters" do
14
+ expect(VisualWidth.measure("こんにちは")).to eql(10)
13
15
  end
14
16
 
15
- it "counts Half characters" do
16
- expect(VisualWidth.count("コンニチハ")).to eql(5)
17
+ it "measures Half characters" do
18
+ expect(VisualWidth.measure("コンニチハ")).to eql(5)
17
19
  end
18
20
 
19
- it "counts Ambiguous characters" do
20
- expect(VisualWidth.count("αβ")).to eql(4)
21
+ it "measures Ambiguous characters" do
22
+ expect(VisualWidth.measure("αβ")).to eql(4)
21
23
  end
22
24
  end
23
25
 
24
26
  context ".counnt with east_asian: false" do
25
- it "counts Halfwide characters" do
26
- expect(VisualWidth.count("foo", east_asian: false)).to eql(3)
27
+ it "measures Halfwide characters" do
28
+ expect(VisualWidth.measure("foo", east_asian: false)).to eql(3)
27
29
  end
28
- it "counts Wide characters" do
29
- expect(VisualWidth.count("こんにちは", east_asian: false)).to eql(10)
30
+ it "measures Wide characters" do
31
+ expect(VisualWidth.measure("こんにちは", east_asian: false)).to eql(10)
30
32
  end
31
33
 
32
- it "counts Half characters" do
33
- expect(VisualWidth.count("コンニチハ", east_asian: false)).to eql(5)
34
+ it "measures Half characters" do
35
+ expect(VisualWidth.measure("コンニチハ", east_asian: false)).to eql(5)
34
36
  end
35
37
 
36
- it "counts Ambiguous characters" do
37
- expect(VisualWidth.count("αβ", east_asian: false)).to eql(2)
38
+ it "measures Ambiguous characters" do
39
+ expect(VisualWidth.measure("αβ", east_asian: false)).to eql(2)
38
40
  end
39
41
  end
40
42
 
@@ -46,35 +48,35 @@ describe VisualWidth do
46
48
  it "truncates str, adding '...'" do
47
49
  str = "The quick brown fox jumps over the lazy dog."
48
50
  s = VisualWidth.truncate(str, 15)
49
- expect(s.visual_width).to be <= 15
51
+ expect(s.width).to be <= 15
50
52
  expect(s).to eql('The quick br...')
51
53
  end
52
54
 
53
55
  it "truncates str, adding '(snip)'" do
54
56
  str = "The quick brown fox jumps over the lazy dog."
55
57
  s = VisualWidth.truncate(str, 15, omission: '(snip)')
56
- expect(s.visual_width).to be <= 15
58
+ expect(s.width).to be <= 15
57
59
  expect(s).to eql('The quick(snip)')
58
60
  end
59
61
 
60
62
  it "truncates Wide characters" do
61
63
  str = "くにざかいのながいトンネルを抜けるとゆきぐにであった"
62
64
  s = VisualWidth.truncate(str, 20)
63
- expect(s.visual_width).to be <= 20
65
+ expect(s.width).to be <= 20
64
66
  expect(s).to eql('くにざかいのなが...')
65
67
  end
66
68
 
67
69
  it "truncates mixed character types" do
68
70
  str = "くにざかいの ながい トンネルを 抜けると ゆきぐにであった"
69
71
  s = VisualWidth.truncate(str, 20)
70
- expect(s.visual_width).to be <= 20
72
+ expect(s.width).to be <= 20
71
73
  expect(s).to eql('くにざかいの なが...')
72
74
  end
73
75
 
74
76
  it "truncates Ambiguous characters" do
75
77
  str = "αβγδεζηθικλμνξοπρστυφχψω"
76
78
  s = VisualWidth.truncate(str, 10)
77
- expect(s.visual_width).to be <= 10
79
+ expect(s.width).to be <= 10
78
80
  expect(s).to eql('αβγ...')
79
81
  end
80
82
  end
@@ -83,7 +85,7 @@ describe VisualWidth do
83
85
  it "truncates str with Ambiguous characters" do
84
86
  str = "αβγδεζηθικλμνξοπρστυφχψω"
85
87
  s = VisualWidth.truncate(str, 10, east_asian: false)
86
- expect(s.visual_width(east_asian: false)).to be <= 10
88
+ expect(s.width(east_asian: false)).to be <= 10
87
89
  expect(s).to eql('αβγδεζη...')
88
90
  end
89
91
  end
data/tool/benchmark.rb CHANGED
@@ -6,13 +6,13 @@ require 'unicode/display_width'
6
6
 
7
7
  str = "foo あいうえお bar αβγδε baz"
8
8
 
9
- VisualWidth.count(str) == str.display_width(2)
9
+ VisualWidth.measure(str) == str.display_width(2)
10
10
 
11
11
  [str, str * 5, str * 10].each do |str|
12
- puts "\n", "for length #{str.length}:"
12
+ puts "\n", "measures string with length #{str.length}:"
13
13
  Benchmark.bmbm do |x|
14
14
  x.report("visual_width") do
15
- 1000.times { VisualWidth.count(str) }
15
+ 1000.times { VisualWidth.measure(str) }
16
16
  end
17
17
  x.report("display_width") do
18
18
  1000.times { str.display_width(2) }
data/tool/tables.rb ADDED
@@ -0,0 +1,21 @@
1
+ #!ruby
2
+ require 'terminal-table'
3
+ require 'text-table'
4
+ require 'visual_width/table'
5
+
6
+ table = Text::Table.new
7
+ table.head = ['じゃがいも', 'さといも']
8
+ table.rows = [['コロッケ', '雑煮']]
9
+ table.rows << ['肉じゃが', '塩ゆで']
10
+ puts table
11
+
12
+ rows = []
13
+ rows << ['じゃがいも', 'さといも']
14
+ rows << ['コロッケ', '雑煮']
15
+ rows << ['肉じゃが', '塩ゆで']
16
+ table = Terminal::Table.new :rows => rows
17
+ puts table
18
+
19
+ t = VisualWidth::Table.new
20
+
21
+ puts t.draw(rows)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: visual_width
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fuji, Goro (gfx)
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-10-23 00:00:00.000000000 Z
11
+ date: 2013-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -47,20 +47,25 @@ extra_rdoc_files: []
47
47
  files:
48
48
  - .gitignore
49
49
  - .rspec
50
+ - .travis.yml
50
51
  - Changes
51
52
  - Gemfile
52
53
  - LICENSE.txt
53
54
  - README.md
54
55
  - Rakefile
56
+ - example/table.rb
55
57
  - lib/visual_width.rb
56
58
  - lib/visual_width/data.rb
57
59
  - lib/visual_width/string_ext.rb
58
60
  - lib/visual_width/string_refine.rb
61
+ - lib/visual_width/table.rb
59
62
  - lib/visual_width/version.rb
60
63
  - spec/visual_width/string_refine_spec.rb
64
+ - spec/visual_width/table_spec.rb
61
65
  - spec/visual_width_spec.rb
62
66
  - tool/benchmark.rb
63
67
  - tool/east-asian-width.pl
68
+ - tool/tables.rb
64
69
  - visual_width.gemspec
65
70
  homepage: https://github.com/gfx/visual_width.rb
66
71
  licenses:
@@ -88,5 +93,6 @@ specification_version: 4
88
93
  summary: Ruby Implementation of East Asian Width
89
94
  test_files:
90
95
  - spec/visual_width/string_refine_spec.rb
96
+ - spec/visual_width/table_spec.rb
91
97
  - spec/visual_width_spec.rb
92
98
  has_rdoc: