Module: RuVim::RichView::JsonRenderer

Defined in:
lib/ruvim/rich_view/json_renderer.rb

Class Method Summary collapse

Class Method Details

.char_offset_for(lines, row, col) ⇒ Object

Compute character offset in joined text from cursor row/col.



119
120
121
122
123
124
125
126
127
128
# File 'lib/ruvim/rich_view/json_renderer.rb', line 119

def char_offset_for(lines, row, col)
  offset = 0
  lines.each_with_index do |line, i|
    if i == row
      return offset + [col, line.length].min
    end
    offset += line.length + 1 # +1 for "\n"
  end
  offset
end

.line_for_significant_count(text, target_count) ⇒ Object

Find the line number in text where the N-th significant character falls.



81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/ruvim/rich_view/json_renderer.rb', line 81

def line_for_significant_count(text, target_count)
  return 0 if target_count <= 0

  in_string = false
  escape = false
  count = 0
  line = 0
  text.each_char do |ch|
    if ch == "\n" && !in_string
      line += 1
      next
    end
    if in_string
      if escape
        escape = false
      elsif ch == "\\"
        escape = true
      elsif ch == '"'
        in_string = false
      end
      count += 1
    else
      case ch
      when '"'
        in_string = true
        count += 1
      when " ", "\r", "\t"
        # skip
      else
        count += 1
      end
    end
    return line if count >= target_count
  end
  line
end

.open_view!(editor) ⇒ Object

Signal that this renderer creates a virtual buffer instead of entering rich mode on the same buffer.



12
13
14
15
16
17
18
19
20
21
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
# File 'lib/ruvim/rich_view/json_renderer.rb', line 12

def open_view!(editor)
  buffer = editor.current_buffer
  window = editor.current_window
  text = buffer.lines.join("\n")

  begin
    parsed = JSON.parse(text)
  rescue JSON::ParserError => e
    editor.echo_error("JSON parse error: #{e.message}")
    return
  end

  # Compute cursor's significant char offset before formatting
  cursor_offset = char_offset_for(buffer.lines, window.cursor_y, window.cursor_x)
  sig_count = significant_char_count(text, cursor_offset + 1)

  formatted = JSON.pretty_generate(parsed)
  lines = formatted.lines(chomp: true)

  target_line = line_for_significant_count(formatted, sig_count)

  buf = editor.add_virtual_buffer(
    kind: :json_formatted,
    name: "[JSON Formatted]",
    lines: lines,
    filetype: "json",
    readonly: true,
    modifiable: false
  )
  editor.switch_to_buffer(buf.id)
  RichView.bind_close_keys(editor, buf.id)
  window.cursor_y = [target_line, lines.length - 1].min
  window.cursor_x = 0
  editor.echo("[JSON Formatted] #{lines.length} lines")
end

.significant_char_count(text, byte_offset) ⇒ Object

Count significant (non-whitespace-outside-strings) characters in text.



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
# File 'lib/ruvim/rich_view/json_renderer.rb', line 50

def significant_char_count(text, byte_offset)
  in_string = false
  escape = false
  count = 0
  text.each_char.with_index do |ch, i|
    break if i >= byte_offset
    if in_string
      if escape
        escape = false
      elsif ch == "\\"
        escape = true
      elsif ch == '"'
        in_string = false
      end
      count += 1
    else
      case ch
      when '"'
        in_string = true
        count += 1
      when " ", "\n", "\r", "\t"
        # skip whitespace outside strings
      else
        count += 1
      end
    end
  end
  count
end