Skip to content

Commit

Permalink
Add a shortcode transformer
Browse files Browse the repository at this point in the history
  • Loading branch information
jsgoldstein committed Sep 27, 2023
1 parent dd3880c commit 33a1928
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 2 deletions.
2 changes: 1 addition & 1 deletion app/lib/search_query_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ class SearchQueryParser < Parslet::Parser
rule(:space) { match('\s').repeat(1) }
rule(:operator) { (str('+') | str('-')).as(:operator) }
rule(:prefix) { term >> colon }
rule(:shortcode) { (colon >> term >> colon.maybe).as(:shortcode) }
rule(:shortcode) { (operator.maybe >> colon >> term >> colon.maybe).as(:shortcode) }
rule(:phrase) { (quote >> (match('[^\s"]').repeat(1).as(:term) >> space.maybe).repeat >> quote).as(:phrase) }
rule(:clause) { (operator.maybe >> prefix.maybe.as(:prefix) >> (phrase | term | shortcode)).as(:clause) | prefix.as(:clause) | quote.as(:junk) }
rule(:query) { (clause >> space.maybe).repeat.as(:query) }
Expand Down
23 changes: 22 additions & 1 deletion app/lib/search_query_transformer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -222,10 +222,29 @@ def language_code_from_term(term)
end
end

class ShortCodeClause
attr_reader :operator, :prefix, :shortcode

def initialize(operator, shortcode)
@operator = Operator.symbol(operator)
@shortcode = shortcode
end

def to_query
{ multi_match: { type: 'most_fields', query: @shortcode, fields: ['text', 'text.stemmed'], operator: 'and' } }
end
end

rule(clause: subtree(:clause)) do
prefix = clause[:prefix][:term].to_s if clause[:prefix]
operator = clause[:operator]&.to_s
term = clause[:phrase] ? clause[:phrase].map { |term| term[:term].to_s }.join(' ') : clause[:term].to_s
if clause[:phrase]

Check failure on line 241 in app/lib/search_query_transformer.rb

View workflow job for this annotation

GitHub Actions / lint

[Correctable] Style/ConditionalAssignment: Use the return of the conditional for variable assignment and comparison.

Check failure on line 241 in app/lib/search_query_transformer.rb

View workflow job for this annotation

GitHub Actions / lint

[Correctable] Style/ConditionalAssignment: Use the return of the conditional for variable assignment and comparison.
term = clause[:phrase].map { |term| term[:term].to_s }.join(' ')

Check warning on line 242 in app/lib/search_query_transformer.rb

View workflow job for this annotation

GitHub Actions / lint

Lint/ShadowingOuterLocalVariable: Shadowing outer local variable - term.

Check warning on line 242 in app/lib/search_query_transformer.rb

View workflow job for this annotation

GitHub Actions / lint

Lint/ShadowingOuterLocalVariable: Shadowing outer local variable - term.
elsif clause[:shortcode]
term = clause[:shortcode][:term].to_s
else
term = clause[:term].to_s
end

if clause[:prefix] && SUPPORTED_PREFIXES.include?(prefix)
PrefixClause.new(prefix, operator, term, current_account: current_account)
Expand All @@ -235,6 +254,8 @@ def language_code_from_term(term)
TermClause.new(operator, term)
elsif clause[:phrase]
PhraseClause.new(operator, term)
elsif clause[:shortcode]
ShortCodeClause.new(operator, term)
else
raise "Unexpected clause type: #{clause}"
end
Expand Down
4 changes: 4 additions & 0 deletions spec/lib/search_query_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
it 'consumes ":foo:"' do
expect(parser.shortcode).to parse(':foo:')
end

it 'consumes "+:foo:"' do
expect(parser.shortcode).to parse('+:foo:')
end
end

context 'with phrase' do
Expand Down
20 changes: 20 additions & 0 deletions spec/lib/search_query_transformer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,26 @@
end
end

context 'with ":foo:"' do
let(:query) { ':foo:' }

it 'transforms clauses' do
expect(subject.send(:must_clauses).map(&:shortcode)).to contain_exactly('foo')
expect(subject.send(:must_not_clauses)).to be_empty
expect(subject.send(:filter_clauses)).to be_empty
end
end

context 'with "-:foo:"' do
let(:query) { '-:foo:' }

it 'transforms clauses' do
expect(subject.send(:must_clauses)).to be_empty
expect(subject.send(:must_not_clauses).map(&:shortcode)).to contain_exactly('foo')
expect(subject.send(:filter_clauses)).to be_empty
end
end

context 'with \'"hello world"\'' do
let(:query) { '"hello world"' }

Expand Down

0 comments on commit 33a1928

Please sign in to comment.