attentive 0.3.1 → 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
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