charyf 0.1.1

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.
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