simple_ext 0.1.0 → 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/simple_ext/hash/slice.rb +2 -0
- data/lib/simple_ext/string/access.rb +105 -0
- data/lib/simple_ext/string/filters.rb +145 -0
- data/lib/simple_ext/string.rb +4 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cf6ae6ea43d968052f7497699c79073dbce1b9c1dff9646bd40b05176daf17ca
|
4
|
+
data.tar.gz: 779f743a29f86ed1d2ea8b0c779c7f9875efc3fc88ab1497074a65d13eb9c0d8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e7b212f5eb4cf9701be6aa5701bcf1c953e1c665fcae644f6f6bbf629a51ccc862fbc3ed9231be337e35feec5e2d4f208072465d917c890c41cf292c08d4250f
|
7
|
+
data.tar.gz: 4e3c0499391f114534b282f0db21b28858facd3821f16dde161e369231024d4096784bacf3b014d5c0a3baa1774523033116f26a82a1a54ecdd4b097a73cae07
|
@@ -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
|
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.
|
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-
|
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
|