module CommandSearch::Normalizer
Public Instance Methods
cast_bool!(field, node)
click to toggle source
# File lib/command_search/normalizer.rb, line 7 def cast_bool!(field, node) type = field.is_a?(Hash) ? field[:type] : field if type == Boolean return if field.is_a?(Hash) && field[:general_search] && !node[:value][/\Atrue\Z|\Afalse\Z/i] node[:type] = Boolean node[:value] = !!node[:value][0][/t/i] return end return unless field.is_a?(Hash) && field[:allow_existence_boolean] return unless node[:type] == :str && node[:value][/\Atrue\Z|\Afalse\Z/i] node[:type] = :existence node[:value] = !!node[:value][0][/t/i] end
cast_numeric!(node)
click to toggle source
# File lib/command_search/normalizer.rb, line 66 def cast_numeric!(node) return unless node[:type] == :number node[:value] = node[:value].to_f end
cast_regex!(node)
click to toggle source
# File lib/command_search/normalizer.rb, line 53 def cast_regex!(node) type = node[:type] raw = node[:value] return unless raw.is_a?(String) return if node[:value] == '' str = Regexp.escape(raw) return node[:value] = /#{str}/i unless type == :quote return node[:value] = /\b#{str}\b/ unless raw[/(\A\W)|(\W\Z)/] border_a = '(^|[^:+\w])' border_b = '($|[^:+\w])' node[:value] = Regexp.new(border_a + str + border_b) end
cast_time!(node)
click to toggle source
# File lib/command_search/normalizer.rb, line 21 def cast_time!(node) search_node = node[:value][1] search_node[:type] = Time str = search_node[:value] if str == str.to_i.to_s search_node[:value] = [Time.new(str), Time.new(str.to_i + 1)] else time_str = str.tr('._-', ' ') times = Chronic.parse(time_str, { guess: nil }) times ||= Chronic.parse(str, { guess: nil }) if times search_node[:value] = [times.first, times.last] else time_parsed = Time.parse(str) rescue nil if time_parsed search_node[:value] = [time_parsed, time_parsed + 1] else search_node[:value] = nil return end end end return unless node[:type] == :compare op = node[:nest_op] if op == '<' || op == '>=' search_node[:value] = search_node[:value].first else search_node[:value] = search_node[:value].last search_node[:value] -= 1 end end
clean_comparison!(node, fields)
click to toggle source
# File lib/command_search/normalizer.rb, line 71 def clean_comparison!(node, fields) val = node[:value] return unless fields[val[1][:value].to_sym] if fields[val[0][:value].to_sym] node[:compare_across_fields] = true return end flip_ops = { '<' => '>', '>' => '<', '<=' => '>=', '>=' => '<=' } node[:nest_op] = flip_ops[node[:nest_op]] node[:value].reverse! end
dealias_key(key, fields)
click to toggle source
# File lib/command_search/normalizer.rb, line 83 def dealias_key(key, fields) key = fields[key.to_sym] while fields[key.to_sym].is_a?(Symbol) key end
normalize!(ast, fields, cast_all = false)
click to toggle source
TODO: default to false
# File lib/command_search/normalizer.rb, line 123 def normalize!(ast, fields, cast_all = false) ast.map! do |node| if node[:type] == :and || node[:type] == :or || node[:type] == :not normalize!(node[:value], fields, cast_all) next node end if node[:type] == :colon || node[:type] == :compare clean_comparison!(node, fields) if node[:type] == :compare key = dealias_key(node[:value][0][:value], fields) node[:value][0][:value] = key.to_s unless fields[key.to_sym] || fields[key.to_s] str_values = "#{key}#{node[:nest_op]}#{node[:value][1][:value]}" node = { type: :str, value: str_values } end end if node[:type] == :str || node[:type] == :quote || node[:type] == :number node = split_general_fields(node, fields) end if node[:type] == :or node[:value].each { |x| type_cast!(x, fields, cast_all) } else type_cast!(node, fields, cast_all) end node end end
split_general_fields(node, fields)
click to toggle source
# File lib/command_search/normalizer.rb, line 88 def split_general_fields(node, fields) general_fields = fields.select { |k, v| v.is_a?(Hash) && v[:general_search] }.keys general_fields = ['__CommandSearch_dummy_key__'] if general_fields.empty? new_val = general_fields.map! do |field| { type: :colon, value: [ { value: field.to_s }, { value: node[:value], type: node[:type] } ] } end return new_val.first if new_val.count < 2 { type: :or, value: new_val } end
type_cast!(node, fields, cast_all)
click to toggle source
# File lib/command_search/normalizer.rb, line 104 def type_cast!(node, fields, cast_all) (key_node, search_node) = node[:value] key = key_node[:value] field = fields[key.to_sym] || fields[key.to_s] return unless field type = field.is_a?(Class) ? field : field[:type] type = Numeric if type == Integer key_node[:field_type] = type cast_bool!(field, search_node) return cast_time!(node) if [Time, Date, DateTime].include?(type) return cast_numeric!(search_node) if Numeric == type if cast_all cast_regex!(search_node) else search_node[:type] = :str if search_node[:type] == :number end end