Class: DiffLineMapper
- Inherits:
-
Object
- Object
- DiffLineMapper
- Defined in:
- lib/vimamsa/diff_buffer.rb
Overview
Map a “line number in a unified diff output” to the corresponding line in the new/changed file (the + side), together with the file it belongs to.
Handles multi-file diffs: each — / +++ pair sets the active file; each @@ hunk header resets the line counters. Walking hunk lines:
' ' => old++, new++
'-' => old++
'+' => new++
Returns [new_path, old_path, line_no] or nil for deleted / unmappable lines.
Constant Summary collapse
- HUNK_RE =
/^@@\s+-(\d+)(?:,(\d+))?\s+\+(\d+)(?:,(\d+))?\s+@@/
Instance Method Summary collapse
-
#initialize(diff_text) ⇒ DiffLineMapper
constructor
A new instance of DiffLineMapper.
-
#new_line_for_diff_lineno(diff_lineno) ⇒ Object
Given a 1-based line number in the diff output, return: - [new_path, old_path, Integer]: raw +++ path, raw — path, 1-based new-file line - nil: if the diff line is a deletion (‘-’) or cannot be mapped.
Constructor Details
#initialize(diff_text) ⇒ DiffLineMapper
Returns a new instance of DiffLineMapper.
15 16 17 |
# File 'lib/vimamsa/diff_buffer.rb', line 15 def initialize(diff_text) @lines = diff_text.lines end |
Instance Method Details
#new_line_for_diff_lineno(diff_lineno) ⇒ Object
Given a 1-based line number in the diff output, return:
- [new_path, old_path, Integer]: raw +++ path, raw --- path, 1-based new-file line
- nil: if the diff line is a deletion ('-') or cannot be mapped
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 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 76 77 78 79 |
# File 'lib/vimamsa/diff_buffer.rb', line 22 def new_line_for_diff_lineno(diff_lineno) raise ArgumentError, "diff line number must be >= 1" if diff_lineno.to_i < 1 idx = diff_lineno.to_i - 1 return nil if idx >= @lines.length old_path = nil new_path = nil old = nil new_ = nil in_hunk = false @lines.each_with_index do |line, i| # File headers reset hunk state and record current file paths. # These appear outside hunks, but guard against malformed diffs too. if line.start_with?('--- ') old_path = line[4..].split("\t").first.strip in_hunk = false old = new_ = nil next end if line.start_with?('+++ ') new_path = line[4..].split("\t").first.strip in_hunk = false old = new_ = nil next end if (m = line.match(HUNK_RE)) old = m[1].to_i new_ = m[3].to_i in_hunk = true next end next unless in_hunk if i == idx return nil unless new_ case line.getbyte(0) when '+'.ord then return [new_path, old_path, new_] when ' '.ord then return [new_path, old_path, new_] when '-'.ord then return nil else return nil end end next unless old && new_ case line.getbyte(0) when ' '.ord then old += 1; new_ += 1 when '-'.ord then old += 1 when '+'.ord then new_ += 1 end end nil end |