visual_width 0.0.1 → 0.0.2

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