diff options
author | Mario de la Ossa <mariodelaossa@gmail.com> | 2018-06-06 18:14:10 -0600 |
---|---|---|
committer | Mario de la Ossa <mariodelaossa@gmail.com> | 2018-06-19 09:30:09 -0600 |
commit | 7357209f91ae4c0b504f47e36220bd04a0e2feca (patch) | |
tree | 60311ff038dc68f9afd6ac00bac65f389a443ca6 /lib/gitlab/search/query.rb | |
parent | 60b102be3d0d40cd36141cfcea0aecff2f115a06 (diff) | |
download | gitlab-ce-ce-5024-filename-search.tar.gz |
Implement filtering by filename on code searchce-5024-filename-search
Diffstat (limited to 'lib/gitlab/search/query.rb')
-rw-r--r-- | lib/gitlab/search/query.rb | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/lib/gitlab/search/query.rb b/lib/gitlab/search/query.rb new file mode 100644 index 00000000000..8583bce7792 --- /dev/null +++ b/lib/gitlab/search/query.rb @@ -0,0 +1,55 @@ +module Gitlab + module Search + class Query < SimpleDelegator + def initialize(query, filter_opts = {}, &block) + @raw_query = query.dup + @filters = [] + @filter_options = { default_parser: :downcase.to_proc }.merge(filter_opts) + + self.instance_eval(&block) if block_given? + + @query = Gitlab::Search::ParsedQuery.new(*extract_filters) + # set the ParsedQuery as our default delegator thanks to SimpleDelegator + super(@query) + end + + private + + def filter(name, **attributes) + filter = { parser: @filter_options[:default_parser], name: name }.merge(attributes) + + @filters << filter + end + + def filter_options(**options) + @filter_options.merge!(options) + end + + def extract_filters + fragments = [] + + filters = @filters.each_with_object([]) do |filter, parsed_filters| + match = @raw_query.split.find { |part| part =~ /\A#{filter[:name]}:/ } + next unless match + + input = match.split(':')[1..-1].join + next if input.empty? + + filter[:value] = parse_filter(filter, input) + filter[:regex_value] = Regexp.escape(filter[:value]).gsub('\*', '.*?') + fragments << match + + parsed_filters << filter + end + + query = (@raw_query.split - fragments).join(' ') + + [query, filters] + end + + def parse_filter(filter, input) + filter[:parser].call(input) + end + end + end +end |