attentive 0.3.1 → 0.3.2

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
  SHA1:
3
- metadata.gz: 0ed20d6d06d7bd6ed7310ce2a21b1845147c85e0
4
- data.tar.gz: 5c9d38c8b0d02e2df99e05b0079b61da0d844a97
3
+ metadata.gz: ed9424d444fc7b37aa1ad0e003fa687a00fc5aa6
4
+ data.tar.gz: 031fc365d1be4944cd5c612caa218c7d64cc2e97
5
5
  SHA512:
6
- metadata.gz: e5332983ceaa6b98858a9fb25ad013bea52e446b677030980263fdd0d058d79fb8d6ad0a41c07a1c991787f3dc6f866790a8d854a3d4a9817862bfd4b1af9bf6
7
- data.tar.gz: edceb04320ea91fc4b416554d3cbbd03bbce2872f3f0e3387e78480e10fc06b1ef54e88a63a1e3f05469872a90235ed55ca82bdf99816c0774bce24ee3ffaa5a
6
+ metadata.gz: 015a425a258acc78e6d0d5b0d99c8af95c0af16ced679de556863219d99a6c59610af1353bf2f92b777b91f69a7fbb727304baa77b7301b5547b842e921d97c1
7
+ data.tar.gz: 4f4fc07e43650c108b8f01511485716a17f360d6c8a7d6d2e76ba4fbb81379b4bbcfaa79007f2d280aa45b0dc60c6f214c27c6062b8b28da070cf7bc175960da
data/Rakefile CHANGED
@@ -25,7 +25,7 @@ namespace :compile do
25
25
  # the first value is the contraction.
26
26
  # the remaining values are possible phrases that match it
27
27
  phrases = line.downcase.chomp.split("\t")
28
- raise "#{line.inspect} must have exactly two values" unless phrases.length >= 2
28
+ raise "#{line.inspect} must have at least two values" unless phrases.length >= 2
29
29
 
30
30
  substitutions[phrases.shift] = phrases
31
31
  end
@@ -0,0 +1,35 @@
1
+ module Attentive
2
+ class Duration < Struct.new(:years, :months, :days)
3
+
4
+ def initialize(attributes)
5
+ super(
6
+ attributes.fetch(:years, 0),
7
+ attributes.fetch(:months, 0),
8
+ attributes.fetch(:days, 0))
9
+ end
10
+
11
+ def +(other)
12
+ self.class.new(
13
+ years: years + other.years,
14
+ months: months + other.months,
15
+ days: days + other.days)
16
+ end
17
+
18
+ def inspect
19
+ phrases = []
20
+ phrases.push "#{years} years" if years > 0
21
+ phrases.push "#{months} months" if months > 0
22
+ phrases.push "#{days} days" if days > 0
23
+ "<#{phrases.join(" ")}>"
24
+ end
25
+
26
+ def after(date)
27
+ (date >> (years * 12 + months)) + days
28
+ end
29
+
30
+ def before(date)
31
+ (date >> -(years * 12 + months)) - days
32
+ end
33
+
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ require "attentive/entity"
2
+ require "date"
3
+
4
+ Attentive::Entity.define "core.date.duration.units",
5
+ "day",
6
+ "days",
7
+ "week",
8
+ "wk",
9
+ "weeks",
10
+ "wks",
11
+ "month",
12
+ "mo",
13
+ "months",
14
+ "mos",
15
+ "year",
16
+ "yr",
17
+ "years",
18
+ "yrs",
19
+ published: false do |match|
20
+
21
+ case match.phrase
22
+ when "day", "days" then :days
23
+ when "week", "wk", "weeks", "wks" then :weeks
24
+ when "month", "mo", "months", "mos" then :months
25
+ when "year", "yr", "years", "yrs" then :years
26
+ else
27
+ nomatch!
28
+ end
29
+ end
@@ -0,0 +1,25 @@
1
+ require "attentive/entity"
2
+ require "attentive/duration"
3
+ require "attentive/entities/core/date/duration/units"
4
+
5
+ Attentive::Entity.define "core.date.duration.single",
6
+ "{{n:core.number.integer.positive}} {{unit:core.date.duration.units}}",
7
+ published: false do |match|
8
+
9
+ unit = match["unit"]
10
+ n = match["n"]
11
+ unit, n = [:days, n * 7] if unit == :weeks
12
+ Attentive::Duration.new(unit => n)
13
+
14
+ end
15
+
16
+ Attentive::Entity.define "core.date.duration",
17
+ "{{a:core.date.duration.single}} {{b:core.date.duration}}",
18
+ "{{a:core.date.duration.single}} and {{b:core.date.duration}}",
19
+ "{{a:core.date.duration.single}}" do |match|
20
+
21
+ a = match["a"]
22
+ a += match["b"] if match.matched?("b")
23
+ a
24
+
25
+ end
@@ -22,7 +22,7 @@ Attentive::Entity.define "core.date.relative.future",
22
22
  case match.to_s
23
23
  when "today" then today
24
24
  when "tomorrow" then today + 1
25
- else raise NotImplementedError, "Unrecognized match: #{match.to_s}"
25
+ else nomatch!
26
26
  end
27
27
  end
28
28
  end
@@ -19,7 +19,7 @@ Attentive::Entity.define "core.date.relative.past",
19
19
  case match.to_s
20
20
  when "today" then today
21
21
  when "yesterday" then today - 1
22
- else raise NotImplementedError, "Unrecognized match: #{match.to_s}"
22
+ else nomatch!
23
23
  end
24
24
  end
25
25
  end
@@ -1,5 +1,6 @@
1
1
  require "attentive/entities/core/date/month"
2
2
  require "attentive/entities/core/date/wday"
3
+ require "attentive/entities/core/date/duration"
3
4
  require "attentive/entities/core/date/relative"
4
5
  require "attentive/entities/core/date/partial"
5
6
  require "attentive/entities/core/date/explicit"
@@ -32,7 +32,7 @@ module Attentive
32
32
 
33
33
  create! entity_name do |entity_klass|
34
34
  entity_klass.phrases = phrases.map do |phrase|
35
- Attentive::Tokenizer.tokenize(phrase, entities: true, regexps: true, ambiguous: false)
35
+ Attentive::Tokenizer.tokenize(phrase, entities: true, regexps: true)
36
36
  end
37
37
  entity_klass.published = options.fetch(:published, true)
38
38
  entity_klass.send :define_method, :_value_from_match, &block if block_given?
@@ -50,8 +50,8 @@ module Attentive
50
50
  entity_symbol = entity_name.to_sym
51
51
  entity_klass = Class.new(self)
52
52
  entity_klass.token_name = entity_symbol
53
- yield entity_klass
54
53
  Entity.register! entity_symbol, entity_klass
54
+ yield entity_klass
55
55
  end
56
56
 
57
57
  def register!(entity_name, entity_klass)
@@ -1,7 +1,4 @@
1
1
  module Attentive
2
- class AmbiguousPhraseError < RuntimeError
3
- end
4
-
5
2
  class UndefinedEntityError < RuntimeError
6
3
  end
7
4
  end
@@ -43,7 +43,7 @@ module Attentive
43
43
  end
44
44
 
45
45
  def tokenize_phrase!(phrase)
46
- Attentive::Tokenizer.tokenize(phrase, entities: true, regexps: true, ambiguous: false)
46
+ Attentive::Tokenizer.tokenize(phrase, entities: true, regexps: true)
47
47
  end
48
48
 
49
49
  end
@@ -6,6 +6,7 @@ module Attentive
6
6
  attr_reader :contexts, :text
7
7
 
8
8
  def initialize(text, params={})
9
+ raise ArgumentError, "Message cannot be initialized without 'text'" unless text
9
10
  @text = text
10
11
  @contexts = Set.new(params.fetch(:contexts, []))
11
12
  contexts << :conversation if tokens.grep(Attentive::Tokens::Invocation).any?
@@ -33,10 +33,6 @@ module Attentive
33
33
  options.fetch(:substitutions, true)
34
34
  end
35
35
 
36
- def fail_if_ambiguous?
37
- !options.fetch(:ambiguous, true)
38
- end
39
-
40
36
 
41
37
 
42
38
  def tokenize
@@ -80,8 +76,6 @@ module Attentive
80
76
  end
81
77
  end
82
78
 
83
- fail_if_ambiguous!(message, tokens) if fail_if_ambiguous?
84
-
85
79
  Attentive::Phrase.new(tokens)
86
80
  end
87
81
 
@@ -132,7 +126,7 @@ module Attentive
132
126
  end
133
127
 
134
128
  def match_whitespace_at(i)
135
- whitespace = chars[i]
129
+ whitespace = chars[i].dup
136
130
  while (i += 1) < chars.length
137
131
  break unless WHITESPACE === chars[i]
138
132
  whitespace << chars[i]
@@ -142,7 +136,7 @@ module Attentive
142
136
 
143
137
  def match_number_at(i)
144
138
  return false if CONDITIONAL_NUMBER_START === chars[i] && !(NUMBER === chars[i + 1])
145
- number = chars[i]
139
+ number = chars[i].dup
146
140
  while (i += 1) < chars.length
147
141
  break unless NUMBER === chars[i] || (CONDITIONAL_NUMBER === chars[i] && NUMBER === chars[i + 1])
148
142
  number << chars[i]
@@ -151,7 +145,7 @@ module Attentive
151
145
  end
152
146
 
153
147
  def match_word_at(i)
154
- word = chars[i]
148
+ word = chars[i].dup
155
149
  while (i += 1) < chars.length
156
150
  break unless WORD === chars[i]
157
151
  word << chars[i]
@@ -207,15 +201,6 @@ module Attentive
207
201
  "‘" => "'",
208
202
  "’" => "'" }.freeze
209
203
 
210
- def fail_if_ambiguous!(phrase, tokens)
211
- ambiguous_token = tokens.find(&:ambiguous?)
212
- return unless ambiguous_token
213
-
214
- raise Attentive::AmbiguousPhraseError.new(
215
- "The phrase #{phrase.inspect} is ambiguous. " <<
216
- "Please use #{ambiguous_token.possibilities.map(&:inspect).join(" or ")}")
217
- end
218
-
219
204
  end
220
205
  end
221
206
 
@@ -18,6 +18,18 @@ module Attentive
18
18
  true
19
19
  end
20
20
 
21
+ def matches?(cursor)
22
+ possibilities.each do |phrase|
23
+ cursor_copy = cursor.new_from_here
24
+ match = Attentive::Matcher.new(phrase, cursor_copy).match!
25
+ if match
26
+ cursor.advance cursor_copy.pos
27
+ return match.to_h
28
+ end
29
+ end
30
+ false
31
+ end
32
+
21
33
  end
22
34
  end
23
35
  end
@@ -1,3 +1,3 @@
1
1
  module Attentive
2
- VERSION = "0.3.1"
2
+ VERSION = "0.3.2"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: attentive
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bob Lail
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-05-28 00:00:00.000000000 Z
11
+ date: 2016-06-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thread_safe
@@ -156,8 +156,11 @@ files:
156
156
  - lib/attentive/composite_entity.rb
157
157
  - lib/attentive/config.rb
158
158
  - lib/attentive/cursor.rb
159
+ - lib/attentive/duration.rb
159
160
  - lib/attentive/entities/core.rb
160
161
  - lib/attentive/entities/core/date.rb
162
+ - lib/attentive/entities/core/date/duration.rb
163
+ - lib/attentive/entities/core/date/duration/units.rb
161
164
  - lib/attentive/entities/core/date/explicit.rb
162
165
  - lib/attentive/entities/core/date/future.rb
163
166
  - lib/attentive/entities/core/date/month.rb
@@ -220,7 +223,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
220
223
  version: '0'
221
224
  requirements: []
222
225
  rubyforge_project:
223
- rubygems_version: 2.2.2
226
+ rubygems_version: 2.5.1
224
227
  signing_key:
225
228
  specification_version: 4
226
229
  summary: A library for matching messages to natural-language listeners