Module: Ace::Search::Atoms::ResultParser

Defined in:
lib/ace/search/atoms/result_parser.rb

Overview

ResultParser provides parsing of ripgrep and fd output into structured format This is an atom - pure function for parsing search output

Class Method Summary collapse

Class Method Details

.parse_fd_output(output, options = {}) ⇒ Object

Parse fd output into structured results



30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/ace/search/atoms/result_parser.rb', line 30

def parse_fd_output(output, options = {})
  return [] if output.nil? || output.empty?

  lines = output.lines.map(&:strip).reject(&:empty?)

  lines.map do |line|
    {
      type: :file,
      path: line,
      absolute_path: options[:absolute_path] ? line : File.expand_path(line),
      basename: File.basename(line),
      dirname: File.dirname(line),
      extension: File.extname(line)[1..] || ""
    }
  end
end

.parse_ripgrep_counts(output) ⇒ Object

Parse ripgrep –count output (file:count)



112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/ace/search/atoms/result_parser.rb', line 112

def parse_ripgrep_counts(output)
  output.lines.map(&:strip).reject(&:empty?).filter_map do |line|
    match = line.match(/\A(.+?):(\d+)\z/)
    next unless match

    {
      type: :count,
      path: match[1],
      count: match[2].to_i
    }
  end
end

.parse_ripgrep_files_only(output) ⇒ Object

Parse files-only output (just file paths)



102
103
104
105
106
107
108
109
# File 'lib/ace/search/atoms/result_parser.rb', line 102

def parse_ripgrep_files_only(output)
  output.lines.map(&:strip).reject(&:empty?).map do |file_path|
    {
      type: :file,
      path: file_path
    }
  end
end

.parse_ripgrep_json(output) ⇒ Object

Parse ripgrep JSON output



48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ace/search/atoms/result_parser.rb', line 48

def parse_ripgrep_json(output)
  results = []

  output.lines.each do |line|
    line = line.strip
    next if line.empty?

    begin
      json_obj = JSON.parse(line)

      case json_obj["type"]
      when "match"
        data = json_obj["data"]
        results << {
          type: :match,
          path: data["path"]["text"],
          line: data["line_number"],
          column: data["submatches"]&.first&.dig("start") || 0,
          text: data["lines"]["text"]&.strip || ""
        }
      end
    rescue JSON::ParserError
      next
    end
  end

  results
end

.parse_ripgrep_output(output, format = :text) ⇒ Object

Parse ripgrep output into structured results



14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/ace/search/atoms/result_parser.rb', line 14

def parse_ripgrep_output(output, format = :text)
  return [] if output.nil? || output.empty?

  case format
  when :json
    parse_ripgrep_json(output)
  when :files_only
    parse_ripgrep_files_only(output)
  when :counts
    parse_ripgrep_counts(output)
  else
    parse_ripgrep_text(output)
  end
end

.parse_ripgrep_text(output) ⇒ Object

Parse ripgrep text output (default format)



78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/ace/search/atoms/result_parser.rb', line 78

def parse_ripgrep_text(output)
  results = []

  output.lines.each do |line|
    line = line.chomp
    next if line.empty?

    # Format: file:line:content or file:line:column:content
    if line.match?(/^([^:]+):(\d+):(\d+)?:?(.*)$/)
      match = line.match(/^([^:]+):(\d+):(\d+)?:?(.*)$/)
      results << {
        type: :match,
        path: match[1],
        line: match[2].to_i,
        column: match[3] ? match[3].to_i : 0,
        text: (match[4] || "").strip
      }
    end
  end

  results
end