charyf 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (111) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +6 -0
  3. data/Gemfile.lock +154 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +18 -0
  6. data/Rakefile +6 -0
  7. data/bin/charyf-debug +7 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/charyf.gemspec +48 -0
  11. data/exe/charyf +4 -0
  12. data/lib/charyf/deps.rb +9 -0
  13. data/lib/charyf/engine/all.rb +22 -0
  14. data/lib/charyf/engine/charyf.rb +5 -0
  15. data/lib/charyf/engine/context.rb +61 -0
  16. data/lib/charyf/engine/controller/actions.rb +29 -0
  17. data/lib/charyf/engine/controller/controller.rb +62 -0
  18. data/lib/charyf/engine/controller/conversation.rb +58 -0
  19. data/lib/charyf/engine/controller/helpers.rb +38 -0
  20. data/lib/charyf/engine/controller/renderers.rb +103 -0
  21. data/lib/charyf/engine/dispatcher/base.rb +121 -0
  22. data/lib/charyf/engine/dispatcher/default.rb +60 -0
  23. data/lib/charyf/engine/intent/intent.rb +54 -0
  24. data/lib/charyf/engine/intent/processors/dummy.rb +30 -0
  25. data/lib/charyf/engine/intent/processors/helpers.rb +32 -0
  26. data/lib/charyf/engine/intent/processors/processor.rb +56 -0
  27. data/lib/charyf/engine/interface/interface.rb +35 -0
  28. data/lib/charyf/engine/interface/program.rb +59 -0
  29. data/lib/charyf/engine/request.rb +32 -0
  30. data/lib/charyf/engine/response.rb +41 -0
  31. data/lib/charyf/engine/session/processors/default.rb +42 -0
  32. data/lib/charyf/engine/session/processors/processor.rb +39 -0
  33. data/lib/charyf/engine/session/session.rb +68 -0
  34. data/lib/charyf/engine/skill/info.rb +24 -0
  35. data/lib/charyf/engine/skill/routing.rb +57 -0
  36. data/lib/charyf/engine/skill/skill.rb +40 -0
  37. data/lib/charyf/engine.rb +3 -0
  38. data/lib/charyf/support/all.rb +4 -0
  39. data/lib/charyf/support/hash.rb +43 -0
  40. data/lib/charyf/support/object.rb +7 -0
  41. data/lib/charyf/support/string.rb +94 -0
  42. data/lib/charyf/support/string_inquirer.rb +17 -0
  43. data/lib/charyf/support.rb +1 -0
  44. data/lib/charyf/utils/all.rb +13 -0
  45. data/lib/charyf/utils/app_engine/extensions.rb +21 -0
  46. data/lib/charyf/utils/app_engine.rb +24 -0
  47. data/lib/charyf/utils/app_loader.rb +38 -0
  48. data/lib/charyf/utils/application/bootstrap.rb +176 -0
  49. data/lib/charyf/utils/application/configuration.rb +51 -0
  50. data/lib/charyf/utils/application.rb +131 -0
  51. data/lib/charyf/utils/charyf.rb +44 -0
  52. data/lib/charyf/utils/cli.rb +14 -0
  53. data/lib/charyf/utils/command/actions.rb +24 -0
  54. data/lib/charyf/utils/command/base.rb +138 -0
  55. data/lib/charyf/utils/command/behavior.rb +81 -0
  56. data/lib/charyf/utils/command/environment_argument.rb +40 -0
  57. data/lib/charyf/utils/command.rb +106 -0
  58. data/lib/charyf/utils/commands/all.rb +6 -0
  59. data/lib/charyf/utils/commands/application/application_command.rb +21 -0
  60. data/lib/charyf/utils/commands/cli/cli_command.rb +115 -0
  61. data/lib/charyf/utils/commands/console/console_command.rb +77 -0
  62. data/lib/charyf/utils/commands/destroy/destroy_command.rb +26 -0
  63. data/lib/charyf/utils/commands/generate/generate_command.rb +31 -0
  64. data/lib/charyf/utils/commands/help/USAGE +9 -0
  65. data/lib/charyf/utils/commands/help/help.rb +20 -0
  66. data/lib/charyf/utils/commands.rb +15 -0
  67. data/lib/charyf/utils/configuration.rb +36 -0
  68. data/lib/charyf/utils/error_handler.rb +26 -0
  69. data/lib/charyf/utils/extension/configurable.rb +41 -0
  70. data/lib/charyf/utils/extension/configuration.rb +63 -0
  71. data/lib/charyf/utils/extension.rb +129 -0
  72. data/lib/charyf/utils/generator/actions.rb +281 -0
  73. data/lib/charyf/utils/generator/base.rb +288 -0
  74. data/lib/charyf/utils/generators/app/USAGE +8 -0
  75. data/lib/charyf/utils/generators/app/app_generator.rb +274 -0
  76. data/lib/charyf/utils/generators/app/templates/Gemfile.erb +20 -0
  77. data/lib/charyf/utils/generators/app/templates/README.md +24 -0
  78. data/lib/charyf/utils/generators/app/templates/app/skill_controller.rb.tt +8 -0
  79. data/lib/charyf/utils/generators/app/templates/bin/charyf +5 -0
  80. data/lib/charyf/utils/generators/app/templates/config/application.rb.tt +32 -0
  81. data/lib/charyf/utils/generators/app/templates/config/boot.rb.tt +4 -0
  82. data/lib/charyf/utils/generators/app/templates/config/chapp.rb.tt +5 -0
  83. data/lib/charyf/utils/generators/app/templates/config/environments/development.rb.tt +2 -0
  84. data/lib/charyf/utils/generators/app/templates/config/environments/production.rb.tt +2 -0
  85. data/lib/charyf/utils/generators/app/templates/config/environments/test.rb.tt +2 -0
  86. data/lib/charyf/utils/generators/app/templates/config/load.rb.tt +17 -0
  87. data/lib/charyf/utils/generators/app/templates/gitignore +18 -0
  88. data/lib/charyf/utils/generators/app_base.rb +277 -0
  89. data/lib/charyf/utils/generators/defaults.rb +75 -0
  90. data/lib/charyf/utils/generators/intents/intents_generator.rb +41 -0
  91. data/lib/charyf/utils/generators/named_base.rb +73 -0
  92. data/lib/charyf/utils/generators/skill/skill_generator.rb +47 -0
  93. data/lib/charyf/utils/generators/skill/templates/controllers/skill_controller.rb.tt +10 -0
  94. data/lib/charyf/utils/generators/skill/templates/module.rb.tt +6 -0
  95. data/lib/charyf/utils/generators/skill/templates/skill.rb.tt +3 -0
  96. data/lib/charyf/utils/generators.rb +187 -0
  97. data/lib/charyf/utils/initializable.rb +95 -0
  98. data/lib/charyf/utils/logger.rb +26 -0
  99. data/lib/charyf/utils/machine.rb +129 -0
  100. data/lib/charyf/utils/parser/en_parser.rb +97 -0
  101. data/lib/charyf/utils/parser/parser.rb +37 -0
  102. data/lib/charyf/utils/ruby_version_check.rb +15 -0
  103. data/lib/charyf/utils/storage/provider.rb +44 -0
  104. data/lib/charyf/utils/strategy.rb +44 -0
  105. data/lib/charyf/utils/utils.rb +64 -0
  106. data/lib/charyf/utils.rb +2 -0
  107. data/lib/charyf/version.rb +19 -0
  108. data/lib/charyf.rb +18 -0
  109. data/lib/locale/en.yml +206 -0
  110. data/todo.md +3 -0
  111. metadata +272 -0
@@ -0,0 +1,187 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'thor/group'
4
+
5
+ require_relative 'command/behavior'
6
+
7
+
8
+ module Charyf
9
+ module Generators
10
+ include Charyf::Command::Behavior
11
+
12
+ REMOVED_GENERATORS = %w(app cli_app intents)
13
+
14
+
15
+ DEFAULT_ALIASES = {}
16
+
17
+ DEFAULT_OPTIONS = {
18
+ charyf: {
19
+ intents: true
20
+ }
21
+ }
22
+
23
+ class << self
24
+
25
+ def aliases #:nodoc:
26
+ @aliases ||= DEFAULT_ALIASES.dup
27
+ end
28
+
29
+ def options #:nodoc:
30
+ @options ||= DEFAULT_OPTIONS.dup
31
+ end
32
+
33
+ # Returns an array of generator namespaces that are hidden.
34
+ # Generator namespaces may be hidden for a variety of reasons.
35
+ def hidden_namespaces
36
+ @hidden_namespaces ||= []
37
+ end
38
+
39
+ def hide_namespaces(*namespaces)
40
+ hidden_namespaces.concat(namespaces)
41
+ end
42
+
43
+ alias hide_namespace hide_namespaces
44
+
45
+ # Show help message with available generators.
46
+ def help(command = "generate")
47
+ puts "Usage: charyf #{command} GENERATOR [args] [options]"
48
+ puts
49
+ puts "General options:"
50
+ puts " -h, [--help] # Print generator's options and usage"
51
+ puts " -p, [--pretend] # Run but do not make any changes"
52
+ puts " -f, [--force] # Overwrite files that already exist"
53
+ puts " -s, [--skip] # Skip files that already exist"
54
+ puts " -q, [--quiet] # Suppress status output"
55
+ puts
56
+ puts "Please choose a generator below."
57
+ puts
58
+
59
+ print_generators
60
+ end
61
+
62
+ # Receives a namespace, arguments and the behavior to invoke the generator.
63
+ # It's used as the default entry point for generate, destroy and update
64
+ # commands.
65
+ def invoke(namespace, args = ARGV, config = {})
66
+ names = namespace.to_s.split(":")
67
+ if klass = find_by_namespace(names.pop, names.any? && names.join(":"))
68
+ args << "--help" if args.empty? && klass.arguments.any?(&:required?)
69
+ klass.start(args, config)
70
+ else
71
+ options = sorted_groups.flat_map(&:last)
72
+ suggestions = options.sort_by { |suggested| levenshtein_distance(namespace.to_s, suggested) }.first(3)
73
+ suggestions.map! { |s| "'#{s}'" }
74
+ msg = "Could not find generator '#{namespace}'. ".dup
75
+
76
+ if suggestions.any?
77
+ msg << "Maybe you meant #{ suggestions[0...-1].join(', ')} or #{suggestions[-1]}\n"
78
+ msg << "Run `charyf generate --help` for more options."
79
+ end
80
+
81
+ puts msg
82
+ end
83
+ end
84
+
85
+ def configure!(config) #:nodoc:
86
+ options.deep_merge! config.options, union_arrays: true
87
+ hide_namespaces(*config.hidden_namespaces)
88
+ end
89
+
90
+ def print_generators
91
+ sorted_groups.each { |b, n| print_list(b, n) }
92
+ end
93
+
94
+ def sorted_groups
95
+ namespaces = public_namespaces
96
+ namespaces.sort!
97
+
98
+ groups = Hash.new { |h, k| h[k] = [] }
99
+ namespaces.each do |namespace|
100
+ base = namespace.split(":").first
101
+ groups[base] << namespace
102
+ end
103
+
104
+ charyf = groups.delete("charyf") || []
105
+ charyf.map! { |n| n.sub(/^charyf:/, "") }
106
+ REMOVED_GENERATORS.map { |name| charyf.delete(name) }
107
+
108
+ hidden_namespaces.each { |n| groups.delete(n.to_s) }
109
+
110
+ [[ "charyf", charyf ]] + groups.sort.to_a
111
+ end
112
+
113
+ def public_namespaces
114
+ subclasses.map(&:namespace)
115
+ end
116
+
117
+ # Charyf finds namespaces similar to Thor, it only adds one rule:
118
+ #
119
+ # find_by_namespace :foo, :charyf, :bar
120
+ #
121
+ # Will search for the following generators:
122
+ #
123
+ # "charyf:foo", "foo:bar", "foo"
124
+ #
125
+ # Notice that "charyf:generators:bar" could be loaded as well, what
126
+ # Charyf looks for is the first and last parts of the namespace.
127
+ def find_by_namespace(name, base = nil, context = nil) #:nodoc:
128
+ lookups = []
129
+ lookups << "#{base}:#{name}" if base
130
+ lookups << "#{name}:#{context}" if context
131
+
132
+ unless base || context
133
+ unless name.to_s.include?(?:)
134
+ lookups << "#{name}:#{name}"
135
+ lookups << "charyf:#{name}"
136
+ end
137
+ lookups << "#{name}"
138
+ end
139
+
140
+ namespaces = Hash[subclasses.map { |klass| [klass.namespace, klass] }]
141
+ lookups.each do |namespace|
142
+
143
+ klass = namespaces[namespace]
144
+ return klass if klass
145
+ end
146
+
147
+ invoke_fallbacks_for(name, base) || invoke_fallbacks_for(context, name)
148
+ end
149
+
150
+ # Hold configured generators fallbacks. If a plugin developer wants a
151
+ # generator group to fallback to another group in case of missing generators,
152
+ # they can add a fallback.
153
+ #
154
+ # For example, shoulda is considered a test_framework and is an extension
155
+ # of test_unit. However, most part of shoulda generators are similar to
156
+ # test_unit ones.
157
+ #
158
+ # Shoulda then can tell generators to search for test_unit generators when
159
+ # some of them are not available by adding a fallback:
160
+ #
161
+ # Charyf::Generators.fallbacks[:shoulda] = :test_unit
162
+ def fallbacks
163
+ @fallbacks ||= {}
164
+ end
165
+
166
+ private
167
+
168
+ # Try fallbacks for the given base.
169
+ def invoke_fallbacks_for(name, base)
170
+ return nil unless base && fallbacks[base.to_sym]
171
+ invoked_fallbacks = []
172
+
173
+ Array(fallbacks[base.to_sym]).each do |fallback|
174
+ next if invoked_fallbacks.include?(fallback)
175
+ invoked_fallbacks << fallback
176
+
177
+ klass = find_by_namespace(name, fallback)
178
+ return klass if klass
179
+ end
180
+
181
+ nil
182
+ end
183
+
184
+ end # End of self
185
+
186
+ end
187
+ end
@@ -0,0 +1,95 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'tsort'
4
+
5
+ module Charyf
6
+ module Initializable
7
+ def self.included(base) #:nodoc:
8
+ base.extend ClassMethods
9
+ end
10
+
11
+ class Initializer
12
+ attr_reader :name, :block
13
+
14
+ def initialize(name, context, options, &block)
15
+ options[:group] ||= :default
16
+ @name, @context, @options, @block = name, context, options, block
17
+ end
18
+
19
+ def before
20
+ @options[:before]
21
+ end
22
+
23
+ def after
24
+ @options[:after]
25
+ end
26
+
27
+ def belongs_to?(group)
28
+ @options[:group] == group || @options[:group] == :all
29
+ end
30
+
31
+ def run(*args)
32
+ @context.instance_exec(*args, &block)
33
+ end
34
+
35
+ def bind(context)
36
+ return self if @context
37
+ Initializer.new(@name, context, @options, &block)
38
+ end
39
+
40
+ def context_class
41
+ @context.class
42
+ end
43
+ end
44
+
45
+ class Collection < Array
46
+ include TSort
47
+
48
+ alias :tsort_each_node :each
49
+ def tsort_each_child(initializer, &block)
50
+ select { |i| i.before == initializer.name || i.name == initializer.after }.each(&block)
51
+ end
52
+
53
+ def +(other)
54
+ Collection.new(to_a + other.to_a)
55
+ end
56
+ end
57
+
58
+ def run_initializers(group = :default, *args)
59
+ return if instance_variable_defined?(:@ran)
60
+ initializers.tsort_each do |initializer|
61
+ initializer.run(*args) if initializer.belongs_to?(group)
62
+ end
63
+ @ran = true
64
+ end
65
+
66
+ def initializers
67
+ @initializers ||= self.class.initializers_for(self)
68
+ end
69
+
70
+ module ClassMethods
71
+ def initializers
72
+ @initializers ||= Collection.new
73
+ end
74
+
75
+ def initializers_chain
76
+ initializers = Collection.new
77
+ ancestors.reverse_each do |klass|
78
+ next unless klass.respond_to?(:initializers)
79
+ initializers = initializers + klass.initializers
80
+ end
81
+ initializers
82
+ end
83
+
84
+ def initializers_for(binding)
85
+ Collection.new(initializers_chain.map { |i| i.bind(binding) })
86
+ end
87
+
88
+ def initializer(name, opts = {}, &blk)
89
+ raise ArgumentError, 'A block must be passed when defining an initializer' unless blk
90
+ opts[:after] ||= initializers.last.name unless initializers.empty? || initializers.find { |i| i.name == opts[:before] }
91
+ initializers << Initializer.new(name, nil, opts, &blk)
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,26 @@
1
+ require 'logger'
2
+ require 'colorize'
3
+
4
+ module Charyf
5
+ class Logger < ::Logger
6
+
7
+ def initialize(logdev, shift_age = 0, shift_size = 1048576)
8
+ super
9
+
10
+ self.datetime_format = '%Y-%m-%d %H:%M:%S'
11
+
12
+ self.formatter = proc do |severity, datetime, progname, msg|
13
+ "#{datetime} [#{severity}]: #{msg}\n"
14
+ end
15
+ end
16
+
17
+ def flow_request(msg)
18
+ info(msg.green)
19
+ end
20
+
21
+ def flow_response(msg)
22
+ info(msg.blue)
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,129 @@
1
+ module Charyf
2
+ module Utils
3
+ class Machine
4
+
5
+ DefaultExists = Class.new(ArgumentError)
6
+ NotInState = Class.new(ArgumentError)
7
+ InvalidDefinition = Class.new(LoadError)
8
+ InvalidEvent = Class.new(ArgumentError)
9
+
10
+ class << self
11
+
12
+ # Sig does not handle blocks
13
+ def state(name, default: false, final: false, action: nil, &block)
14
+ if default
15
+ raise DefaultExists.new if @_default_state
16
+ @_default_state = name
17
+ end
18
+
19
+
20
+ _states[name] = {
21
+ action: action || name,
22
+ final: final
23
+ }
24
+
25
+ if block
26
+ @_state = name
27
+ block.call
28
+ @_state = nil
29
+ end
30
+ end
31
+
32
+ def on(event, go: nil, &block)
33
+ raise NotInState.new unless @_state
34
+
35
+ _events(@_state)[event] =
36
+ {
37
+ go: go,
38
+ callback: block
39
+ }
40
+ end
41
+
42
+ def _default_state
43
+ @_default_state
44
+ end
45
+
46
+ # def _final_states
47
+ # @_final_states ||= [:_terminated]
48
+ # end
49
+
50
+ def _states
51
+ @_states ||= {
52
+ _terminated: {
53
+ action: :_terminated,
54
+ final: true
55
+ }
56
+ }
57
+ end
58
+
59
+ def _events(state)
60
+ @_events ||= Hash.new
61
+ @_events[state] ||= Hash.new
62
+ end
63
+
64
+ def build
65
+ _states.each do |state_name, state|
66
+ events = _events(state_name)
67
+ raise InvalidDefinition.new("No transitions from state #{state_name}") if events.empty? && !state[:final]
68
+
69
+ _events(state_name).each do |event, details|
70
+ raise InvalidDefinition.new("Transition '#{event}' to undefined state '#{details[:go]}'") unless _states.include?(details[:go])
71
+ end
72
+ end
73
+
74
+ raise InvalidDefinition.new('No final states defined.') unless _states.values.any? { |state| state[:final] }
75
+ end
76
+
77
+ end # End of class
78
+
79
+ attr_reader :state
80
+
81
+ def initialize(state = nil)
82
+ @state ||= self.class._default_state
83
+ end
84
+
85
+ def trigger!(event, payload = nil)
86
+ raise InvalidEvent.new("No transition defined for event '#{event}' from state '#{@state}'") unless trigger?(event)
87
+ change(event, payload)
88
+ end
89
+
90
+ def trigger(event, payload = nil)
91
+ trigger?(event) && change(event, payload)
92
+ end
93
+
94
+ def trigger?(event)
95
+ self.class._events(@state).include?(event)
96
+ end
97
+
98
+ def terminate
99
+ @state = :_terminated
100
+ end
101
+
102
+ def final?
103
+ self.class._states[@state][:final]
104
+ end
105
+
106
+ def state?(state)
107
+ @state == state
108
+ end
109
+
110
+ def events
111
+ self.class._events(@state).keys
112
+ end
113
+
114
+ private
115
+
116
+ def change(event, payload)
117
+ transition = self.class._events(@state)[event]
118
+
119
+ @state = transition[:go]
120
+ #TODO machine
121
+ callback = transition[:callback]
122
+ callback.call(payload) if callback
123
+
124
+ @state
125
+ end
126
+
127
+ end
128
+ end
129
+ end
@@ -0,0 +1,97 @@
1
+ require_relative 'parser'
2
+
3
+ module Charyf
4
+ module Utils
5
+ module Parser
6
+ # noinspection RubyLiteralArrayInspection,RubyQuotedStringsInspection
7
+ # English string normalization
8
+ class English < Base
9
+
10
+ strategy_name :en
11
+
12
+ CONTRACTION = ["ain't", "aren't", "can't", "could've", "couldn't",
13
+ "didn't", "doesn't", "don't", "gonna", "gotta",
14
+ "hadn't", "hasn't", "haven't", "he'd", "he'll", "he's",
15
+ "how'd", "how'll", "how's", "I'd", "I'll", "I'm",
16
+ "I've", "isn't", "it'd", "it'll", "it's", "mightn't",
17
+ "might've", "mustn't", "must've", "needn't", "oughtn't",
18
+ "shan't", "she'd", "she'll", "she's", "shouldn't",
19
+ "should've", "somebody's", "someone'd", "someone'll",
20
+ "someone's", "that'll", "that's", "that'd", "there'd",
21
+ "there're", "there's", "they'd", "they'll", "they're",
22
+ "they've", "wasn't", "we'd", "we'll", "we're", "we've",
23
+ "weren't", "what'd", "what'll", "what're", "what's",
24
+ "whats",
25
+ "what've", "when's", "when'd", "where'd", "where's",
26
+ "where've", "who'd", "who'd've", "who'll", "who're",
27
+ "who's", "who've", "why'd", "why're", "why's", "won't",
28
+ "won't've", "would've", "wouldn't", "wouldn't've",
29
+ "y'all", "ya'll", "you'd", "you'd've", "you'll",
30
+ "y'aint", "y'ain't", "you're", "you've"].map(&:downcase).freeze
31
+
32
+ EXPANSION = ["is not", "are not", "can not", "could have",
33
+ "could not", "did not", "does not", "do not",
34
+ "going to", "got to", "had not", "has not",
35
+ "have not", "he would", "he will", "he is", "how did",
36
+ "how will", "how is", "I would", "I will", "I am",
37
+ "I have", "is not", "it would", "it will", "it is",
38
+ "might not", "might have", "must not", "must have",
39
+ "need not", "ought not", "shall not", "she would",
40
+ "she will", "she is", "should not", "should have",
41
+ "somebody is", "someone would", "someone will",
42
+ "someone is", "that will", "that is", "that would",
43
+ "there would", "there are", "there is", "they would",
44
+ "they will", "they are", "they have", "was not",
45
+ "we would", "we will", "we are", "we have",
46
+ "were not", "what did", "what will", "what are",
47
+ "what is",
48
+ "what is", "what have", "when is", "when did",
49
+ "where did", "where is", "where have", "who would",
50
+ "who would have", "who will", "who are", "who is",
51
+ "who have", "why did", "why are", "why is",
52
+ "will not", "will not have", "would have",
53
+ "would not", "would not have", "you all", "you all",
54
+ "you would", "you would have", "you will",
55
+ "you are not", "you are not", "you are", "you have"].map(&:downcase).freeze
56
+
57
+ TEXT_NUMBERS = ["zero", "one", "two", "three", "four", "five", "six",
58
+ "seven", "eight", "nine", "ten", "eleven", "twelve",
59
+ "thirteen", "fourteen", "fifteen", "sixteen",
60
+ "seventeen", "eighteen", "nineteen", "twenty"].map(&:downcase).freeze
61
+
62
+ ARTICLES = ["the", "a", "an"].map(&:downcase).freeze
63
+
64
+ def self.normalize(text, remove_articles: true)
65
+ words = text.split
66
+
67
+ normalized = ''
68
+
69
+ words.each do |word|
70
+ next if word.empty?
71
+ next if remove_articles && ARTICLES.include?(word.downcase)
72
+
73
+ # Expand common contractions, e.g. "isn't" -> "is not"
74
+ if CONTRACTION.include?(word.downcase)
75
+ capitalize = false
76
+ if word[0] == word[0].upcase
77
+ capitalize = true
78
+ end
79
+ word = EXPANSION[CONTRACTION.index(word.downcase)]
80
+
81
+ word.capitalize! if capitalize
82
+ end
83
+
84
+ if TEXT_NUMBERS.include?(word.downcase)
85
+ word = TEXT_NUMBERS.index(word.downcase)
86
+ end
87
+
88
+ normalized += " " + word
89
+ end
90
+
91
+ normalized.strip
92
+ end
93
+
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,37 @@
1
+ require_relative '../../support/string'
2
+ require_relative '../strategy'
3
+
4
+ module Charyf
5
+ module Utils
6
+ module Parser
7
+ class Base
8
+
9
+ include Charyf::Strategy
10
+ def self.base
11
+ Base
12
+ end
13
+
14
+ # TODO sig
15
+ def self.normalize(text, remove_articles: true)
16
+ raise Charyf::Utils::NotImplemented.new
17
+ end
18
+
19
+ end # End of base
20
+
21
+ def self.known
22
+ Base.known
23
+ end
24
+
25
+ def self.list
26
+ Base.list
27
+ end
28
+
29
+ # TODO sig
30
+ def self.get(language)
31
+ # TODO implement
32
+ Charyf::Utils::Parser::English
33
+ list[language]
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ if RUBY_VERSION < "2.2.2" && RUBY_ENGINE == "ruby"
4
+ desc = defined?(RUBY_DESCRIPTION) ? RUBY_DESCRIPTION : "ruby #{RUBY_VERSION} (#{RUBY_RELEASE_DATE})"
5
+ abort <<-end_message
6
+
7
+ Charyf [Alpha] requires Ruby 2.2.2 or newer.
8
+
9
+ You're running
10
+ #{desc}
11
+
12
+ Please upgrade to Ruby 2.2.2 or newer to continue.
13
+
14
+ end_message
15
+ end
@@ -0,0 +1,44 @@
1
+ require_relative '../strategy'
2
+
3
+ module Charyf
4
+ module Utils
5
+ module StorageProvider
6
+ class Base
7
+
8
+ include Charyf::Strategy
9
+ def self.base
10
+ Base
11
+ end
12
+
13
+ sig_self [['Module', 'String']], ['Charyf::Utils::StorageProvider::Base'],
14
+ def self.get_for(klass)
15
+ raise Charyf::Utils::NotImplemented.new
16
+ end
17
+
18
+ sig [nil], [nil],
19
+ def get(key)
20
+ raise Charyf::Utils::NotImplemented.new
21
+ end
22
+
23
+ sig [nil, nil], [nil],
24
+ def store(key, value)
25
+ raise Charyf::Utils::NotImplemented.new
26
+ end
27
+
28
+ sig [nil], [nil],
29
+ def remove(key)
30
+ raise Charyf::Utils::NotImplemented.new
31
+ end
32
+
33
+ end # End of Base
34
+
35
+ def self.known
36
+ Base.known
37
+ end
38
+
39
+ def self.list
40
+ Base.list
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,44 @@
1
+ module Charyf
2
+ module Strategy
3
+
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def inherited(subclass)
10
+ base._subclasses << subclass
11
+ end
12
+
13
+ def strategy_name(name = nil)
14
+ if name
15
+ @_strategy_name = name
16
+ base._aliases[name] = self
17
+ end
18
+
19
+ @_strategy_name
20
+ end
21
+
22
+ def _subclasses
23
+ @_subclasses ||= []
24
+ end
25
+
26
+ def _aliases
27
+ @_aliases ||= Hash.new
28
+ end
29
+
30
+ def known
31
+ base._subclasses
32
+ end
33
+
34
+ def list
35
+ base._aliases
36
+ end
37
+
38
+ def base
39
+ raise Charyf::Utils::NotImplemented.new("No base class found for #{self}")
40
+ end
41
+ end
42
+
43
+ end
44
+ end