simple_ext 0.1.0 → 0.1.1

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: 5f972070633ea700b9c69fc42ed84258ed68bbfe3fb95df8284c62dc3342db42
4
- data.tar.gz: 7e19bc443f5f7ddc6658aaf20936ccfce95e108e4e6498e489d68ec1f7da9973
3
+ metadata.gz: cf6ae6ea43d968052f7497699c79073dbce1b9c1dff9646bd40b05176daf17ca
4
+ data.tar.gz: 779f743a29f86ed1d2ea8b0c779c7f9875efc3fc88ab1497074a65d13eb9c0d8
5
5
  SHA512:
6
- metadata.gz: 8778c40b09e43907f4da9cbfb7473a2d6add060632025925a77553daf61eb58249fe3f4afea0238d59ca0a29596207284d2388682c7fc70a7092d108247cfaa4
7
- data.tar.gz: 8723bbf6360f6637382acae47b95d82bb1b7f6dddfcf8e0605670c449960ac0c36edb60621ed8d480c3fdbc441106cecb77655126328d8b4e58e72d385ea9f65
6
+ metadata.gz: e7b212f5eb4cf9701be6aa5701bcf1c953e1c665fcae644f6f6bbf629a51ccc862fbc3ed9231be337e35feec5e2d4f208072465d917c890c41cf292c08d4250f
7
+ data.tar.gz: 4e3c0499391f114534b282f0db21b28858facd3821f16dde161e369231024d4096784bacf3b014d5c0a3baa1774523033116f26a82a1a54ecdd4b097a73cae07
@@ -23,4 +23,6 @@ class Hash
23
23
  def extract!(*keys)
24
24
  keys.each_with_object(self.class.new) { |key, result| result[key] = delete(key) if has_key?(key) }
25
25
  end
26
+
27
+ alias_method :extract, :slice
26
28
  end
@@ -0,0 +1,105 @@
1
+ # frozen_string_literal: true
2
+
3
+ class String
4
+ # If you pass a single integer, returns a substring of one character at that
5
+ # position. The first character of the string is at position 0, the next at
6
+ # position 1, and so on. If a range is supplied, a substring containing
7
+ # characters at offsets given by the range is returned. In both cases, if an
8
+ # offset is negative, it is counted from the end of the string. Returns +nil+
9
+ # if the initial offset falls outside the string. Returns an empty string if
10
+ # the beginning of the range is greater than the end of the string.
11
+ #
12
+ # str = "hello"
13
+ # str.at(0) # => "h"
14
+ # str.at(1..3) # => "ell"
15
+ # str.at(-2) # => "l"
16
+ # str.at(-2..-1) # => "lo"
17
+ # str.at(5) # => nil
18
+ # str.at(5..-1) # => ""
19
+ #
20
+ # If a Regexp is given, the matching portion of the string is returned.
21
+ # If a String is given, that given string is returned if it occurs in
22
+ # the string. In both cases, +nil+ is returned if there is no match.
23
+ #
24
+ # str = "hello"
25
+ # str.at(/lo/) # => "lo"
26
+ # str.at(/ol/) # => nil
27
+ # str.at("lo") # => "lo"
28
+ # str.at("ol") # => nil
29
+ def at(position)
30
+ self[position]
31
+ end
32
+
33
+ # Returns a substring from the given position to the end of the string.
34
+ # If the position is negative, it is counted from the end of the string.
35
+ #
36
+ # str = "hello"
37
+ # str.from(0) # => "hello"
38
+ # str.from(3) # => "lo"
39
+ # str.from(-2) # => "lo"
40
+ #
41
+ # You can mix it with +to+ method and do fun things like:
42
+ #
43
+ # str = "hello"
44
+ # str.from(0).to(-1) # => "hello"
45
+ # str.from(1).to(-2) # => "ell"
46
+ def from(position)
47
+ self[position, length]
48
+ end
49
+
50
+ # Returns a substring from the beginning of the string to the given position.
51
+ # If the position is negative, it is counted from the end of the string.
52
+ #
53
+ # str = "hello"
54
+ # str.to(0) # => "h"
55
+ # str.to(3) # => "hell"
56
+ # str.to(-2) # => "hell"
57
+ #
58
+ # You can mix it with +from+ method and do fun things like:
59
+ #
60
+ # str = "hello"
61
+ # str.from(0).to(-1) # => "hello"
62
+ # str.from(1).to(-2) # => "ell"
63
+ def to(position)
64
+ position += size if position < 0
65
+ self[0, position + 1] || +""
66
+ end
67
+
68
+ # Returns the first character. If a limit is supplied, returns a substring
69
+ # from the beginning of the string until it reaches the limit value. If the
70
+ # given limit is greater than or equal to the string length, returns a copy of self.
71
+ #
72
+ # str = "hello"
73
+ # str.first # => "h"
74
+ # str.first(1) # => "h"
75
+ # str.first(2) # => "he"
76
+ # str.first(0) # => ""
77
+ # str.first(6) # => "hello"
78
+ def first(limit = 1)
79
+ self[0, limit] || raise(ArgumentError, "negative limit")
80
+ end
81
+
82
+ # Returns the last character of the string. If a limit is supplied, returns a substring
83
+ # from the end of the string until it reaches the limit value (counting backwards). If
84
+ # the given limit is greater than or equal to the string length, returns a copy of self.
85
+ #
86
+ # str = "hello"
87
+ # str.last # => "o"
88
+ # str.last(1) # => "o"
89
+ # str.last(2) # => "lo"
90
+ # str.last(0) # => ""
91
+ # str.last(6) # => "hello"
92
+ def last(limit = 1)
93
+ self[[length - limit, 0].max, limit] || raise(ArgumentError, "negative limit")
94
+ end
95
+
96
+ # The inverse of <tt>String#include?</tt>. Returns true if the string
97
+ # does not include the other string.
98
+ #
99
+ # "hello".exclude? "lo" # => false
100
+ # "hello".exclude? "ol" # => true
101
+ # "hello".exclude? ?h # => false
102
+ def exclude?(string)
103
+ !include?(string)
104
+ end
105
+ end
@@ -0,0 +1,145 @@
1
+ # frozen_string_literal: true
2
+
3
+ class String
4
+ # Returns the string, first removing all whitespace on both ends of
5
+ # the string, and then changing remaining consecutive whitespace
6
+ # groups into one space each.
7
+ #
8
+ # Note that it handles both ASCII and Unicode whitespace.
9
+ #
10
+ # %{ Multi-line
11
+ # string }.squish # => "Multi-line string"
12
+ # " foo bar \n \t boo".squish # => "foo bar boo"
13
+ def squish
14
+ dup.squish!
15
+ end
16
+
17
+ # Performs a destructive squish. See String#squish.
18
+ # str = " foo bar \n \t boo"
19
+ # str.squish! # => "foo bar boo"
20
+ # str # => "foo bar boo"
21
+ def squish!
22
+ gsub!(/[[:space:]]+/, " ")
23
+ strip!
24
+ self
25
+ end
26
+
27
+ # Returns a new string with all occurrences of the patterns removed.
28
+ # str = "foo bar test"
29
+ # str.remove(" test") # => "foo bar"
30
+ # str.remove(" test", /bar/) # => "foo "
31
+ # str # => "foo bar test"
32
+ def remove(*patterns)
33
+ dup.remove!(*patterns)
34
+ end
35
+
36
+ # Alters the string by removing all occurrences of the patterns.
37
+ # str = "foo bar test"
38
+ # str.remove!(" test", /bar/) # => "foo "
39
+ # str # => "foo "
40
+ def remove!(*patterns)
41
+ patterns.each do |pattern|
42
+ gsub! pattern, ""
43
+ end
44
+
45
+ self
46
+ end
47
+
48
+ # Truncates a given +text+ after a given <tt>length</tt> if +text+ is longer than <tt>length</tt>:
49
+ #
50
+ # 'Once upon a time in a world far far away'.truncate(27)
51
+ # # => "Once upon a time in a wo..."
52
+ #
53
+ # Pass a string or regexp <tt>:separator</tt> to truncate +text+ at a natural break:
54
+ #
55
+ # 'Once upon a time in a world far far away'.truncate(27, separator: ' ')
56
+ # # => "Once upon a time in a..."
57
+ #
58
+ # 'Once upon a time in a world far far away'.truncate(27, separator: /\s/)
59
+ # # => "Once upon a time in a..."
60
+ #
61
+ # The last characters will be replaced with the <tt>:omission</tt> string (defaults to "...")
62
+ # for a total length not exceeding <tt>length</tt>:
63
+ #
64
+ # 'And they found that many people were sleeping better.'.truncate(25, omission: '... (continued)')
65
+ # # => "And they f... (continued)"
66
+ def truncate(truncate_at, options = {})
67
+ return dup unless length > truncate_at
68
+
69
+ omission = options[:omission] || "..."
70
+ length_with_room_for_omission = truncate_at - omission.length
71
+ stop = \
72
+ if options[:separator]
73
+ rindex(options[:separator], length_with_room_for_omission) || length_with_room_for_omission
74
+ else
75
+ length_with_room_for_omission
76
+ end
77
+
78
+ +"#{self[0, stop]}#{omission}"
79
+ end
80
+
81
+ # Truncates +text+ to at most <tt>bytesize</tt> bytes in length without
82
+ # breaking string encoding by splitting multibyte characters or breaking
83
+ # grapheme clusters ("perceptual characters") by truncating at combining
84
+ # characters.
85
+ #
86
+ # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".size
87
+ # => 20
88
+ # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".bytesize
89
+ # => 80
90
+ # >> "🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪🔪".truncate_bytes(20)
91
+ # => "🔪🔪🔪🔪…"
92
+ #
93
+ # The truncated text ends with the <tt>:omission</tt> string, defaulting
94
+ # to "…", for a total length not exceeding <tt>bytesize</tt>.
95
+ def truncate_bytes(truncate_at, omission: "…")
96
+ omission ||= ""
97
+
98
+ case
99
+ when bytesize <= truncate_at
100
+ dup
101
+ when omission.bytesize > truncate_at
102
+ raise ArgumentError, "Omission #{omission.inspect} is #{omission.bytesize}, larger than the truncation length of #{truncate_at} bytes"
103
+ when omission.bytesize == truncate_at
104
+ omission.dup
105
+ else
106
+ self.class.new.tap do |cut|
107
+ cut_at = truncate_at - omission.bytesize
108
+
109
+ scan(/\X/) do |grapheme|
110
+ if cut.bytesize + grapheme.bytesize <= cut_at
111
+ cut << grapheme
112
+ else
113
+ break
114
+ end
115
+ end
116
+
117
+ cut << omission
118
+ end
119
+ end
120
+ end
121
+
122
+ # Truncates a given +text+ after a given number of words (<tt>words_count</tt>):
123
+ #
124
+ # 'Once upon a time in a world far far away'.truncate_words(4)
125
+ # # => "Once upon a time..."
126
+ #
127
+ # Pass a string or regexp <tt>:separator</tt> to specify a different separator of words:
128
+ #
129
+ # 'Once<br>upon<br>a<br>time<br>in<br>a<br>world'.truncate_words(5, separator: '<br>')
130
+ # # => "Once<br>upon<br>a<br>time<br>in..."
131
+ #
132
+ # The last characters will be replaced with the <tt>:omission</tt> string (defaults to "..."):
133
+ #
134
+ # 'And they found that many people were sleeping better.'.truncate_words(5, omission: '... (continued)')
135
+ # # => "And they found that many... (continued)"
136
+ def truncate_words(words_count, options = {})
137
+ sep = options[:separator] || /\s+/
138
+ sep = Regexp.escape(sep.to_s) unless Regexp === sep
139
+ if self =~ /\A((?>.+?#{sep}){#{words_count - 1}}.+?)#{sep}.*/m
140
+ $1 + (options[:omission] || "...")
141
+ else
142
+ dup
143
+ end
144
+ end
145
+ end
@@ -0,0 +1,4 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'string/access.rb'
4
+ require_relative 'string/filters.rb'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_ext
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tushar Hawaldar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-05 00:00:00.000000000 Z
11
+ date: 2020-02-06 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Core ruby extentions extracted from Rails ActiveSupport
14
14
  email:
@@ -38,6 +38,9 @@ files:
38
38
  - lib/simple_ext/object/instance_variables.rb
39
39
  - lib/simple_ext/object/to_query.rb
40
40
  - lib/simple_ext/object/try.rb
41
+ - lib/simple_ext/string.rb
42
+ - lib/simple_ext/string/access.rb
43
+ - lib/simple_ext/string/filters.rb
41
44
  homepage: https://github.com/kumartushar/simple_ext.git
42
45
  licenses:
43
46
  - MIT