tickle 1.0.2 → 2.0.0rc3
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 +5 -5
- data/.gitignore +3 -1
- data/.travis.yml +12 -0
- data/CHANGES.md +25 -3
- data/Gemfile +14 -1
- data/LICENCE +1 -1
- data/README.md +1 -1
- data/Rakefile +3 -8
- data/benchmarks/main.rb +71 -0
- data/lib/ext/array.rb +6 -0
- data/lib/ext/date_and_time.rb +64 -0
- data/lib/ext/string.rb +39 -0
- data/lib/tickle.rb +23 -113
- data/lib/tickle/filters.rb +58 -0
- data/lib/tickle/handler.rb +223 -80
- data/lib/tickle/helpers.rb +51 -0
- data/lib/tickle/patterns.rb +115 -0
- data/lib/tickle/repeater.rb +232 -116
- data/lib/tickle/tickle.rb +97 -201
- data/lib/tickle/tickled.rb +173 -0
- data/lib/tickle/token.rb +94 -0
- data/lib/tickle/version.rb +2 -2
- data/spec/helpers_spec.rb +36 -0
- data/spec/patterns_spec.rb +240 -0
- data/spec/spec_helper.rb +43 -0
- data/spec/tickle_spec.rb +551 -0
- data/spec/token_spec.rb +82 -0
- data/tickle.gemspec +4 -9
- metadata +34 -74
- data/lib/numerizer/numerizer.rb +0 -103
data/spec/token_spec.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative "../lib/tickle/token.rb"
|
3
|
+
require 'rspec/its'
|
4
|
+
|
5
|
+
module Tickle # for convenience
|
6
|
+
|
7
|
+
describe "Token" do
|
8
|
+
|
9
|
+
describe "The basics" do
|
10
|
+
subject { Token.new( "" ) }
|
11
|
+
it { should be_a_kind_of ::String }
|
12
|
+
it { should respond_to :original }
|
13
|
+
it { should respond_to :word }
|
14
|
+
it { should respond_to :type }
|
15
|
+
it { should respond_to :interval }
|
16
|
+
it { should respond_to :start }
|
17
|
+
it { should respond_to :update! }
|
18
|
+
it { should respond_to :normalize! }
|
19
|
+
end
|
20
|
+
|
21
|
+
|
22
|
+
describe "Instantation" do
|
23
|
+
context "Given a token" do
|
24
|
+
context "and no options" do
|
25
|
+
subject { Token.new( "Today" ) }
|
26
|
+
its(:original) { should == "Today" }
|
27
|
+
its(:word) { should be_nil }
|
28
|
+
its(:type) { should be_nil }
|
29
|
+
its(:interval) { should be_nil }
|
30
|
+
its(:start) { should be_nil }
|
31
|
+
it { should == "Today" }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
describe "After normalization" do
|
37
|
+
context "Given a token" do
|
38
|
+
context "That is not a number" do
|
39
|
+
context "and no options" do
|
40
|
+
subject { Token.new( "Today" ).normalize! }
|
41
|
+
it { should == "Today" }
|
42
|
+
its(:word) { should == "today" }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
context "That is a number" do
|
46
|
+
context "and no options" do
|
47
|
+
subject { Token.new( "Twenty" ).normalize! }
|
48
|
+
it { should == "Twenty" }
|
49
|
+
its(:word) { should == "20" }
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
|
56
|
+
describe "update!" do
|
57
|
+
pending
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
describe "tokenize" do
|
62
|
+
subject { Token.tokenize "Next Monday" }
|
63
|
+
it { should == ["Next", "Monday"] }
|
64
|
+
its(:first) { should be_a_kind_of Token }
|
65
|
+
end
|
66
|
+
|
67
|
+
|
68
|
+
describe "scan" do
|
69
|
+
context "Given an invalid argument" do
|
70
|
+
it {
|
71
|
+
expect {Token.scan Token.tokenize 9999}.to raise_error ArgumentError
|
72
|
+
}
|
73
|
+
end
|
74
|
+
context "Given a valid argument (tokens)" do
|
75
|
+
subject { Token.scan! Token.tokenize "Next Monday" }
|
76
|
+
it { should == ["Next", "Monday"] }
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
data/tickle.gemspec
CHANGED
@@ -17,16 +17,11 @@ Gem::Specification.new do |s|
|
|
17
17
|
s.files = `git ls-files`.split($/)
|
18
18
|
s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
19
|
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
20
|
-
|
21
|
-
s.require_paths = ["lib"]
|
22
20
|
|
23
|
-
s.
|
24
|
-
s.add_development_dependency "shoulda", "~> 2.10.3"
|
25
|
-
s.add_development_dependency "simplecov"
|
21
|
+
s.require_paths = ["lib"]
|
26
22
|
|
27
|
-
s.
|
28
|
-
s.
|
29
|
-
s.
|
30
|
-
s.add_development_dependency "maruku"
|
23
|
+
s.add_dependency "numerizer", "~> 0.2.0"
|
24
|
+
s.add_dependency "gitlab-chronic", "~> 0.10.6"
|
25
|
+
s.add_dependency "texttube", "~> 6.0.0"
|
31
26
|
end
|
32
27
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tickle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0rc3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joshua Lippiner
|
@@ -9,106 +9,50 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2020-09-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: numerizer
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
18
|
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 0.2.
|
20
|
+
version: 0.2.0
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
25
|
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 0.2.
|
27
|
+
version: 0.2.0
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
|
-
name:
|
29
|
+
name: gitlab-chronic
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
32
|
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
|
-
version:
|
35
|
-
type: :
|
34
|
+
version: 0.10.6
|
35
|
+
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
39
|
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
|
-
version:
|
42
|
-
- !ruby/object:Gem::Dependency
|
43
|
-
name: simplecov
|
44
|
-
requirement: !ruby/object:Gem::Requirement
|
45
|
-
requirements:
|
46
|
-
- - ">="
|
47
|
-
- !ruby/object:Gem::Version
|
48
|
-
version: '0'
|
49
|
-
type: :development
|
50
|
-
prerelease: false
|
51
|
-
version_requirements: !ruby/object:Gem::Requirement
|
52
|
-
requirements:
|
53
|
-
- - ">="
|
54
|
-
- !ruby/object:Gem::Version
|
55
|
-
version: '0'
|
41
|
+
version: 0.10.6
|
56
42
|
- !ruby/object:Gem::Dependency
|
57
|
-
name:
|
43
|
+
name: texttube
|
58
44
|
requirement: !ruby/object:Gem::Requirement
|
59
45
|
requirements:
|
60
46
|
- - "~>"
|
61
47
|
- !ruby/object:Gem::Version
|
62
|
-
version:
|
63
|
-
type: :
|
48
|
+
version: 6.0.0
|
49
|
+
type: :runtime
|
64
50
|
prerelease: false
|
65
51
|
version_requirements: !ruby/object:Gem::Requirement
|
66
52
|
requirements:
|
67
53
|
- - "~>"
|
68
54
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
70
|
-
- !ruby/object:Gem::Dependency
|
71
|
-
name: rake
|
72
|
-
requirement: !ruby/object:Gem::Requirement
|
73
|
-
requirements:
|
74
|
-
- - ">="
|
75
|
-
- !ruby/object:Gem::Version
|
76
|
-
version: '0'
|
77
|
-
type: :development
|
78
|
-
prerelease: false
|
79
|
-
version_requirements: !ruby/object:Gem::Requirement
|
80
|
-
requirements:
|
81
|
-
- - ">="
|
82
|
-
- !ruby/object:Gem::Version
|
83
|
-
version: '0'
|
84
|
-
- !ruby/object:Gem::Dependency
|
85
|
-
name: yard
|
86
|
-
requirement: !ruby/object:Gem::Requirement
|
87
|
-
requirements:
|
88
|
-
- - ">="
|
89
|
-
- !ruby/object:Gem::Version
|
90
|
-
version: '0'
|
91
|
-
type: :development
|
92
|
-
prerelease: false
|
93
|
-
version_requirements: !ruby/object:Gem::Requirement
|
94
|
-
requirements:
|
95
|
-
- - ">="
|
96
|
-
- !ruby/object:Gem::Version
|
97
|
-
version: '0'
|
98
|
-
- !ruby/object:Gem::Dependency
|
99
|
-
name: maruku
|
100
|
-
requirement: !ruby/object:Gem::Requirement
|
101
|
-
requirements:
|
102
|
-
- - ">="
|
103
|
-
- !ruby/object:Gem::Version
|
104
|
-
version: '0'
|
105
|
-
type: :development
|
106
|
-
prerelease: false
|
107
|
-
version_requirements: !ruby/object:Gem::Requirement
|
108
|
-
requirements:
|
109
|
-
- - ">="
|
110
|
-
- !ruby/object:Gem::Version
|
111
|
-
version: '0'
|
55
|
+
version: 6.0.0
|
112
56
|
description: Tickle is a date/time helper gem to help parse natural language into
|
113
57
|
a recurring pattern. Tickle is designed to be a compliment of Chronic and can interpret
|
114
58
|
things such as "every 2 days, every Sunday, Sundays, Weekly, etc.
|
@@ -119,21 +63,34 @@ extra_rdoc_files: []
|
|
119
63
|
files:
|
120
64
|
- ".document"
|
121
65
|
- ".gitignore"
|
66
|
+
- ".travis.yml"
|
122
67
|
- CHANGES.md
|
123
68
|
- Gemfile
|
124
69
|
- LICENCE
|
125
70
|
- README.md
|
126
71
|
- Rakefile
|
127
72
|
- SCENARIOS.rdoc
|
73
|
+
- benchmarks/main.rb
|
128
74
|
- examples.rb
|
129
75
|
- git-flow-version
|
130
|
-
- lib/
|
76
|
+
- lib/ext/array.rb
|
77
|
+
- lib/ext/date_and_time.rb
|
78
|
+
- lib/ext/string.rb
|
131
79
|
- lib/tickle.rb
|
80
|
+
- lib/tickle/filters.rb
|
132
81
|
- lib/tickle/handler.rb
|
82
|
+
- lib/tickle/helpers.rb
|
83
|
+
- lib/tickle/patterns.rb
|
133
84
|
- lib/tickle/repeater.rb
|
134
85
|
- lib/tickle/tickle.rb
|
86
|
+
- lib/tickle/tickled.rb
|
87
|
+
- lib/tickle/token.rb
|
135
88
|
- lib/tickle/version.rb
|
89
|
+
- spec/helpers_spec.rb
|
90
|
+
- spec/patterns_spec.rb
|
136
91
|
- spec/spec_helper.rb
|
92
|
+
- spec/tickle_spec.rb
|
93
|
+
- spec/token_spec.rb
|
137
94
|
- test/git-flow-version
|
138
95
|
- test/helper.rb
|
139
96
|
- test/test_parsing.rb
|
@@ -153,17 +110,20 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
153
110
|
version: '0'
|
154
111
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
155
112
|
requirements:
|
156
|
-
- - "
|
113
|
+
- - ">"
|
157
114
|
- !ruby/object:Gem::Version
|
158
|
-
version:
|
115
|
+
version: 1.3.1
|
159
116
|
requirements: []
|
160
|
-
|
161
|
-
rubygems_version: 2.4.5
|
117
|
+
rubygems_version: 3.1.2
|
162
118
|
signing_key:
|
163
119
|
specification_version: 4
|
164
120
|
summary: natural language parser for recurring events
|
165
121
|
test_files:
|
122
|
+
- spec/helpers_spec.rb
|
123
|
+
- spec/patterns_spec.rb
|
166
124
|
- spec/spec_helper.rb
|
125
|
+
- spec/tickle_spec.rb
|
126
|
+
- spec/token_spec.rb
|
167
127
|
- test/git-flow-version
|
168
128
|
- test/helper.rb
|
169
129
|
- test/test_parsing.rb
|
data/lib/numerizer/numerizer.rb
DELETED
@@ -1,103 +0,0 @@
|
|
1
|
-
require 'strscan'
|
2
|
-
|
3
|
-
class Numerizer
|
4
|
-
|
5
|
-
DIRECT_NUMS = [
|
6
|
-
['eleven', '11'],
|
7
|
-
['twelve', '12'],
|
8
|
-
['thirteen', '13'],
|
9
|
-
['fourteen', '14'],
|
10
|
-
['fifteen', '15'],
|
11
|
-
['sixteen', '16'],
|
12
|
-
['seventeen', '17'],
|
13
|
-
['eighteen', '18'],
|
14
|
-
['nineteen', '19'],
|
15
|
-
['ninteen', '19'], # Common mis-spelling
|
16
|
-
['zero', '0'],
|
17
|
-
['one', '1'],
|
18
|
-
['two', '2'],
|
19
|
-
['three', '3'],
|
20
|
-
['four(\W|$)', '4\1'], # The weird regex is so that it matches four but not fourty
|
21
|
-
['five', '5'],
|
22
|
-
['six(\W|$)', '6\1'],
|
23
|
-
['seven(\W|$)', '7\1'],
|
24
|
-
['eight(\W|$)', '8\1'],
|
25
|
-
['nine(\W|$)', '9\1'],
|
26
|
-
['ten', '10'],
|
27
|
-
['\ba[\b^$]', '1'] # doesn't make sense for an 'a' at the end to be a 1
|
28
|
-
]
|
29
|
-
|
30
|
-
TEN_PREFIXES = [ ['twenty', 20],
|
31
|
-
['thirty', 30],
|
32
|
-
['fourty', 40],
|
33
|
-
['fifty', 50],
|
34
|
-
['sixty', 60],
|
35
|
-
['seventy', 70],
|
36
|
-
['eighty', 80],
|
37
|
-
['ninety', 90]
|
38
|
-
]
|
39
|
-
|
40
|
-
BIG_PREFIXES = [ ['hundred', 100],
|
41
|
-
['thousand', 1000],
|
42
|
-
['million', 1_000_000],
|
43
|
-
['billion', 1_000_000_000],
|
44
|
-
['trillion', 1_000_000_000_000],
|
45
|
-
]
|
46
|
-
|
47
|
-
class << self
|
48
|
-
def numerize(string)
|
49
|
-
string = string.dup
|
50
|
-
|
51
|
-
# preprocess
|
52
|
-
string.gsub!(/ +|([^\d])-([^d])/, '\1 \2') # will mutilate hyphenated-words but shouldn't matter for date extraction
|
53
|
-
string.gsub!(/a half/, 'haAlf') # take the 'a' out so it doesn't turn into a 1, save the half for the end
|
54
|
-
|
55
|
-
# easy/direct replacements
|
56
|
-
|
57
|
-
DIRECT_NUMS.each do |dn|
|
58
|
-
string.gsub!(/#{dn[0]}/i, dn[1])
|
59
|
-
end
|
60
|
-
|
61
|
-
# ten, twenty, etc.
|
62
|
-
|
63
|
-
TEN_PREFIXES.each do |tp|
|
64
|
-
string.gsub!(/(?:#{tp[0]})( *\d(?=[^\d]|$))*/i) { (tp[1] + $1.to_i).to_s }
|
65
|
-
end
|
66
|
-
|
67
|
-
# hundreds, thousands, millions, etc.
|
68
|
-
|
69
|
-
BIG_PREFIXES.each do |bp|
|
70
|
-
string.gsub!(/(\d*) *#{bp[0]}/i) { (bp[1] * $1.to_i).to_s}
|
71
|
-
andition(string)
|
72
|
-
#combine_numbers(string) # Should to be more efficient way to do this
|
73
|
-
end
|
74
|
-
|
75
|
-
# fractional addition
|
76
|
-
# I'm not combining this with the previous block as using float addition complicates the strings
|
77
|
-
# (with extraneous .0's and such )
|
78
|
-
string.gsub!(/(\d+)(?: | and |-)*haAlf/i) { ($1.to_f + 0.5).to_s }
|
79
|
-
|
80
|
-
string
|
81
|
-
end
|
82
|
-
|
83
|
-
private
|
84
|
-
def andition(string)
|
85
|
-
sc = StringScanner.new(string)
|
86
|
-
while(sc.scan_until(/(\d+)( | and )(\d+)(?=[^\w]|$)/i))
|
87
|
-
if sc[2] =~ /and/ || sc[1].size > sc[3].size
|
88
|
-
string[(sc.pos - sc.matched_size)..(sc.pos-1)] = (sc[1].to_i + sc[3].to_i).to_s
|
89
|
-
sc.reset
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|
93
|
-
|
94
|
-
# def combine_numbers(string)
|
95
|
-
# sc = StringScanner.new(string)
|
96
|
-
# while(sc.scan_until(/(\d+)(?: | and |-)(\d+)(?=[^\w]|$)/i))
|
97
|
-
# string[(sc.pos - sc.matched_size)..(sc.pos-1)] = (sc[1].to_i + sc[2].to_i).to_s
|
98
|
-
# sc.reset
|
99
|
-
# end
|
100
|
-
# end
|
101
|
-
|
102
|
-
end
|
103
|
-
end
|