ellipsized 0.1.0 → 0.2.0

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
  SHA256:
3
- metadata.gz: 1c05fb67e627a48333959a2e5939faf1ef73fec35c8bc3cb81f106452089797c
4
- data.tar.gz: 4196eaefe1dbf1ba369d2c35248ae762653e842b8f371529241d9a730caa9773
3
+ metadata.gz: abc2bd33ae6083981ccec4e019ae59fb4b8f572201137b2cc2b0e34dbea907b7
4
+ data.tar.gz: 447f61c07ba3e232ee181c8ed4bd1ecfba632085e409230d816b5e524ceec940
5
5
  SHA512:
6
- metadata.gz: 5b870d389d1f990a94af3a5f381c486eb144c7984704c97f75fd0ebd8fc66788583de8b58067e509ca9a3a4bc202d56b699125f336aaa04f5cb0254507536d9a
7
- data.tar.gz: 39e19c22d146df6356ded9ebf56297fb9dadaf681eab7e4a15081c3ff04a1ab8d30a8035ca811a090e6c98faa9a129b72c2a8abb9f1058b4783e671033dc7b08
6
+ metadata.gz: 13a5933003e880a53970c9931d29be03d3ac985cc994261683e0876ad28a14900b8eb2423d000d68b7b601a6fa5a351c351903562b1b9430cb36b2ba005c21c3
7
+ data.tar.gz: 7d870cd017c7b628a23546bb62e724eaa357ec145ce5e4dd701158bf4984a76174448afc586868c045732edcc94df98e00e276ce70824ea757b2116cc5e31b83
@@ -16,4 +16,4 @@ jobs:
16
16
  runs-on: ubuntu-24.04
17
17
  steps:
18
18
  - uses: actions/checkout@v4
19
- - uses: yegor256/copyrights-action@0.0.8
19
+ - uses: yegor256/copyrights-action@0.0.12
data/.rubocop.yml CHANGED
@@ -19,4 +19,10 @@ Layout/EndOfLine:
19
19
  Style/EvalWithLocation:
20
20
  Enabled: false
21
21
  Metrics/AbcSize:
22
- Max: 25
22
+ Max: 30
23
+ Metrics/CyclomaticComplexity:
24
+ Max: 10
25
+ Metrics/PerceivedComplexity:
26
+ Max: 10
27
+ Metrics/MethodLength:
28
+ Max: 30
data/Gemfile.lock CHANGED
@@ -10,7 +10,7 @@ GEM
10
10
  ast (2.4.3)
11
11
  builder (3.3.0)
12
12
  docile (1.4.1)
13
- json (2.12.0)
13
+ json (2.12.2)
14
14
  language_server-protocol (3.17.0.5)
15
15
  lint_roller (1.1.0)
16
16
  minitest (5.25.5)
@@ -26,10 +26,10 @@ GEM
26
26
  prism (1.4.0)
27
27
  racc (1.8.1)
28
28
  rainbow (3.1.1)
29
- rake (13.2.1)
29
+ rake (13.3.0)
30
30
  regexp_parser (2.10.0)
31
31
  rexml (3.4.1)
32
- rubocop (1.75.6)
32
+ rubocop (1.75.8)
33
33
  json (~> 2.3)
34
34
  language_server-protocol (~> 3.17.0.2)
35
35
  lint_roller (~> 1.1.0)
@@ -43,7 +43,7 @@ GEM
43
43
  rubocop-ast (1.44.1)
44
44
  parser (>= 3.3.7.2)
45
45
  prism (~> 1.4)
46
- rubocop-minitest (0.38.0)
46
+ rubocop-minitest (0.38.1)
47
47
  lint_roller (~> 1.1)
48
48
  rubocop (>= 1.75.0, < 2.0)
49
49
  rubocop-ast (>= 1.38.0, < 2.0)
data/README.md CHANGED
@@ -12,7 +12,7 @@
12
12
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](https://github.com/yegor256/ellipsized/blob/master/LICENSE.txt)
13
13
 
14
14
  It makes a string fit into a required length by replacing
15
- part of it in the middle with an ellipsis:
15
+ part of it in the middle with an [ellipsis]:
16
16
 
17
17
  ```ruby
18
18
  require 'ellipsized'
@@ -25,10 +25,10 @@ Prints:
25
25
  Hello, ...world!
26
26
  ```
27
27
 
28
- You can also specify what to fill the gap with:
28
+ You can also specify what to use to fill the gap:
29
29
 
30
30
  ```ruby
31
- puts 'How are you doing?'.ellipsized(14, gap: '.. skip ..')
31
+ puts 'How are you doing?'.ellipsized(14, '.. skip ..')
32
32
  ```
33
33
 
34
34
  Prints:
@@ -37,6 +37,18 @@ Prints:
37
37
  Ho.. skip ..g?
38
38
  ```
39
39
 
40
+ You can also specify alignment:
41
+
42
+ ```ruby
43
+ puts 'How are you doing?'.ellipsized(14, '.. skip ..', :left)
44
+ ```
45
+
46
+ Prints:
47
+
48
+ ```text
49
+ .. skip ..ing?
50
+ ```
51
+
40
52
  That's it.
41
53
 
42
54
  ## How to contribute
@@ -54,3 +66,5 @@ bundle exec rake
54
66
  ```
55
67
 
56
68
  If it's clean and you don't see any error messages, submit your pull request.
69
+
70
+ [ellipsis]: https://en.wikipedia.org/wiki/Ellipsis
data/_typos.toml ADDED
@@ -0,0 +1,7 @@
1
+ # SPDX-FileCopyrightText: Copyright (c) 2025 Yegor Bugayenko
2
+ # SPDX-License-Identifier: MIT
3
+
4
+ [default.extend-words]
5
+ tring = "tring"
6
+ ther = "ther"
7
+ ather = "ather"
data/ellipsized.gemspec CHANGED
@@ -9,7 +9,7 @@ Gem::Specification.new do |s|
9
9
  s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
10
10
  s.required_ruby_version = '>=3.2'
11
11
  s.name = 'ellipsized'
12
- s.version = '0.1.0'
12
+ s.version = '0.2.0'
13
13
  s.license = 'MIT'
14
14
  s.summary = 'A simple Ruby gem that adds a .ellipsized() method to String'
15
15
  s.description =
data/lib/ellipsized.rb CHANGED
@@ -15,7 +15,9 @@ class String
15
15
  # or equal to the maximum length.
16
16
  #
17
17
  # @param [Integer] max The maximum length of the resulting string
18
- # @param [String] gap The string to use as gap (default: '...')
18
+ # @param [String] gap The string to use as a gap (default: '...')
19
+ # @param [Symbol] align The alignment can be :left, :center, or :right
20
+ # (default: :center)
19
21
  # @return [String] The truncated string with gap in the middle if necessary
20
22
  #
21
23
  # @example Basic usage with default parameters
@@ -27,23 +29,46 @@ class String
27
29
  # # => "This is...truncated"
28
30
  #
29
31
  # @example Custom gap
30
- # "Another very long string example".ellipsized(15, gap: "***")
32
+ # "Another very long string example".ellipsized(15, '***')
31
33
  # # => "Anoth***example"
32
34
  #
35
+ # @example Custom align
36
+ # "Another very long string example".ellipsized(15, '...', :left)
37
+ # # => "...tring example"
38
+ #
33
39
  # @example Edge cases
34
40
  # "".ellipsized # => ""
35
41
  # "Short".ellipsized # => "Short"
36
42
  # "xyz".ellipsized(0) # => ""
37
- # "xyz".ellipsized(2, gap: "...") # => "xy"
38
- def ellipsized(max = 64, gap: '...')
43
+ # "xyz".ellipsized(2, '...') # => "xy"
44
+ def ellipsized(max = 64, gap = '...', align = :center)
45
+ validate_arguments(max, gap, align)
39
46
  return '' if empty?
40
47
  return self if length <= max
41
48
  return '' if max.zero?
49
+
50
+ gap = gap.to_s
42
51
  return self[0..max - 1] if gap.length >= max
43
52
 
44
- head = tail = (max - gap.length) / 2
45
- head += 1 if head + tail + gap.length < max
46
- head = max if head > max
47
- "#{self[0, head]}#{gap}#{self[length - tail..]}"
53
+ case align
54
+ when :left
55
+ "#{gap}#{self[length - max + gap.length..]}"
56
+ when :center
57
+ head = tail = (max - gap.length) / 2
58
+ head += 1 if head + tail + gap.length < max
59
+ head = max if head > max
60
+ "#{self[0, head]}#{gap}#{self[length - tail..]}"
61
+ when :right
62
+ "#{self[0, max - gap.length]}#{gap}"
63
+ end
64
+ end
65
+
66
+ private
67
+
68
+ def validate_arguments(max, gap, align)
69
+ raise "Max length must be an Integer, while #{max.class.name} provided" unless max.is_a?(Integer)
70
+ raise "Max length (#{max}) is negative" if max.negative?
71
+ raise "The gap doesn't implement to_s()" unless gap.respond_to?(:to_s)
72
+ raise "Unsupported align: #{align}" unless %i[left center right].include?(align)
48
73
  end
49
74
  end
data/test/test__helper.rb CHANGED
@@ -15,8 +15,8 @@ unless SimpleCov.running || ENV['PICKS']
15
15
  SimpleCov::Formatter::CoberturaFormatter
16
16
  ]
17
17
  )
18
- SimpleCov.minimum_coverage 95
19
- SimpleCov.minimum_coverage_by_file 90
18
+ SimpleCov.minimum_coverage 100
19
+ SimpleCov.minimum_coverage_by_file 100
20
20
  SimpleCov.start do
21
21
  add_filter 'test/'
22
22
  add_filter 'vendor/'
@@ -13,11 +13,27 @@ class TestEllipsized < Minitest::Test
13
13
  def test_simple
14
14
  assert_equal('', ''.ellipsized)
15
15
  assert_equal('apple', 'apple'.ellipsized)
16
- assert_equal('Мо...а', 'Москва спаленная пожаром французу отдана'.ellipsized(6))
16
+ assert_equal('Мо...?', 'Москва, спалённая пожаром, французу отдана?'.ellipsized(6))
17
17
  assert_equal('app...na', 'apple and banana'.ellipsized(8))
18
18
  assert_equal('пр...г!', 'привет, друг!'.ellipsized(7))
19
19
  end
20
20
 
21
+ def test_simple_left
22
+ assert_equal('', ''.ellipsized(64, '...', :left))
23
+ assert_equal('apple', 'apple'.ellipsized(64, '...', :left))
24
+ assert_equal('...на?', 'Москва, спалённая пожаром, французу отдана?'.ellipsized(6, '...', :left))
25
+ assert_equal('...anana', 'apple and banana'.ellipsized(8, '...', :left))
26
+ assert_equal('...руг!', 'привет, друг!'.ellipsized(7, '...', :left))
27
+ end
28
+
29
+ def test_simple_right
30
+ assert_equal('', ''.ellipsized(64, '...', :right))
31
+ assert_equal('apple', 'apple'.ellipsized(64, '...', :right))
32
+ assert_equal('Мос...', 'Москва, спалённая пожаром, французу отдана?'.ellipsized(6, '...', :right))
33
+ assert_equal('apple...', 'apple and banana'.ellipsized(8, '...', :right))
34
+ assert_equal('прив...', 'привет, друг!'.ellipsized(7, '...', :right))
35
+ end
36
+
21
37
  def test_with_very_small_window
22
38
  assert_equal('', 'The Godfather'.ellipsized(0))
23
39
  assert_equal('T', 'The Godfather'.ellipsized(1))
@@ -30,10 +46,78 @@ class TestEllipsized < Minitest::Test
30
46
  assert_equal('The...er', 'The Godfather'.ellipsized(8))
31
47
  end
32
48
 
49
+ def test_with_very_small_window_left
50
+ assert_equal('', 'The Godfather'.ellipsized(0, '...', :left))
51
+ assert_equal('T', 'The Godfather'.ellipsized(1, '...', :left))
52
+ assert_equal('Th', 'The Godfather'.ellipsized(2, '...', :left))
53
+ assert_equal('The', 'The Godfather'.ellipsized(3, '...', :left))
54
+ assert_equal('...r', 'The Godfather'.ellipsized(4, '...', :left))
55
+ assert_equal('...er', 'The Godfather'.ellipsized(5, '...', :left))
56
+ assert_equal('...her', 'The Godfather'.ellipsized(6, '...', :left))
57
+ assert_equal('...ther', 'The Godfather'.ellipsized(7, '...', :left))
58
+ assert_equal('...ather', 'The Godfather'.ellipsized(8, '...', :left))
59
+ end
60
+
61
+ def test_with_very_small_window_right
62
+ assert_equal('', 'The Godfather'.ellipsized(0, '...', :right))
63
+ assert_equal('T', 'The Godfather'.ellipsized(1, '...', :right))
64
+ assert_equal('Th', 'The Godfather'.ellipsized(2, '...', :right))
65
+ assert_equal('The', 'The Godfather'.ellipsized(3, '...', :right))
66
+ assert_equal('T...', 'The Godfather'.ellipsized(4, '...', :right))
67
+ assert_equal('Th...', 'The Godfather'.ellipsized(5, '...', :right))
68
+ assert_equal('The...', 'The Godfather'.ellipsized(6, '...', :right))
69
+ assert_equal('The ...', 'The Godfather'.ellipsized(7, '...', :right))
70
+ assert_equal('The G...', 'The Godfather'.ellipsized(8, '...', :right))
71
+ end
72
+
73
+ def test_with_empty_gap
74
+ assert_equal('', 'Encapsulation'.ellipsized(0, ''))
75
+ assert_equal('E', 'Encapsulation'.ellipsized(1, ''))
76
+ assert_equal('En', 'Encapsulation'.ellipsized(2, ''))
77
+ assert_equal('Enn', 'Encapsulation'.ellipsized(3, ''))
78
+ assert_equal('Enon', 'Encapsulation'.ellipsized(4, ''))
79
+ assert_equal('Encon', 'Encapsulation'.ellipsized(5, ''))
80
+ assert_equal('Encion', 'Encapsulation'.ellipsized(6, ''))
81
+ end
82
+
83
+ def test_with_empty_gap_left
84
+ assert_equal('', 'Encapsulation'.ellipsized(0, '', :left))
85
+ assert_equal('n', 'Encapsulation'.ellipsized(1, '', :left))
86
+ assert_equal('on', 'Encapsulation'.ellipsized(2, '', :left))
87
+ assert_equal('ion', 'Encapsulation'.ellipsized(3, '', :left))
88
+ assert_equal('tion', 'Encapsulation'.ellipsized(4, '', :left))
89
+ assert_equal('ation', 'Encapsulation'.ellipsized(5, '', :left))
90
+ assert_equal('lation', 'Encapsulation'.ellipsized(6, '', :left))
91
+ end
92
+
93
+ def test_with_empty_gap_right
94
+ assert_equal('', 'Encapsulation'.ellipsized(0, '', :right))
95
+ assert_equal('E', 'Encapsulation'.ellipsized(1, '', :right))
96
+ assert_equal('En', 'Encapsulation'.ellipsized(2, '', :right))
97
+ assert_equal('Enc', 'Encapsulation'.ellipsized(3, '', :right))
98
+ assert_equal('Enca', 'Encapsulation'.ellipsized(4, '', :right))
99
+ assert_equal('Encap', 'Encapsulation'.ellipsized(5, '', :right))
100
+ assert_equal('Encaps', 'Encapsulation'.ellipsized(6, '', :right))
101
+ end
102
+
33
103
  def test_with_replacement
34
104
  assert_equal(
35
105
  'This .. skip ..indow',
36
- 'This story is very long to fit into a small window'.ellipsized(20, gap: '.. skip ..')
106
+ 'This story is very long to fit into a small window'.ellipsized(20, '.. skip ..')
107
+ )
108
+ end
109
+
110
+ def test_with_replacement_left
111
+ assert_equal(
112
+ '.. skip ..all window',
113
+ 'This story is very long to fit into a small window'.ellipsized(20, '.. skip ..', :left)
114
+ )
115
+ end
116
+
117
+ def test_with_replacement_right
118
+ assert_equal(
119
+ 'This story.. skip ..',
120
+ 'This story is very long to fit into a small window'.ellipsized(20, '.. skip ..', :right)
37
121
  )
38
122
  end
39
123
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ellipsized
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Yegor Bugayenko
@@ -42,6 +42,7 @@ files:
42
42
  - README.md
43
43
  - REUSE.toml
44
44
  - Rakefile
45
+ - _typos.toml
45
46
  - ellipsized.gemspec
46
47
  - lib/ellipsized.rb
47
48
  - renovate.json