Class: FuncPanel

Inherits:
Object
  • Object
show all
Defined in:
lib/vimamsa/gui_func_panel.rb

Overview

Left-side panel that displays LSP-provided functions/methods for the current buffer, grouped by the class or module they belong to.

Constant Summary collapse

COL_NAME =

Tree column index: display name (class name or function name)

0
COL_LINE =

Tree column index: 1-based line number to jump to; 0 = not a jump target

1

Instance Method Summary collapse

Constructor Details

#initializeFuncPanel

Returns a new instance of FuncPanel.



7
8
9
10
11
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
47
48
49
50
51
52
53
# File 'lib/vimamsa/gui_func_panel.rb', line 7

def initialize
  # @store is the data model: a tree (not flat list) so we can nest functions
  # under their parent class. Two columns: the display string and the line number.
  @store = Gtk::TreeStore.new(String, Integer)

  # @tree is the GTK widget that renders @store. It holds expand/collapse state
  # and handles row selection. Backed by @store — clearing @store clears the view.
  @tree = Gtk::TreeView.new(@store)
  @tree.headers_visible = false
  @tree.activate_on_single_click = true

  # Single text column; ellipsize at end so long names don't overflow the panel width.
  renderer = Gtk::CellRendererText.new
  renderer.ellipsize = Pango::EllipsizeMode::END
  col = Gtk::TreeViewColumn.new("", renderer, text: COL_NAME)
  col.expand = true
  @tree.append_column(col)

  # Jump to the function's line when a row is clicked.
  # Class header rows have COL_LINE = 0 and are skipped (no jump).
  @tree.signal_connect("row-activated") do |_tv, path, _col|
    iter = @store.get_iter(path)
    next if iter.nil?
    line = iter[COL_LINE]
    next if line <= 0
    vma.buf.jump_to_line(line)
  end

  sw = Gtk::ScrolledWindow.new
  sw.set_policy(:never, :automatic)
  sw.set_child(@tree)
  sw.vexpand = true

  header = Gtk::Label.new("<span weight='ultrabold'>Functions</span> (click to jump)")
  header.use_markup = true

  header.xalign = 0.0
  header.margin_start = 6
  header.margin_top = 4
  header.margin_bottom = 2

  # @box is the outermost widget: header label on top, scrollable tree below.
  @box = Gtk::Box.new(:vertical, 0)
  @box.set_size_request(160, -1)
  @box.append(header)
  @box.append(sw)
end

Instance Method Details

#refreshObject

Asynchronously fetch functions from the LSP server and repopulate @store. The LSP call runs in a background thread; the GTK update is marshalled back to the main thread via GLib::Idle.add to avoid threading issues.



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
# File 'lib/vimamsa/gui_func_panel.rb', line 63

def refresh
  buf = vma.buf
  unless buf&.fname
    set_placeholder("(no file)")
    return
  end
  lsp = LangSrv.get(buf.lang)
  unless lsp
    set_placeholder("(no LSP)")
    return
  end
  fpath = buf.fname
  Thread.new {
    # groups: [{name:, line:, functions: [{name:, line:}, ...]}, ...]
    # name: nil means top-level functions with no enclosing class.
    groups = lsp.document_functions_grouped(fpath)
    GLib::Idle.add {
      @store.clear
      if groups.nil? || groups.empty?
        set_placeholder("(no functions)")
      else
        populate(groups)
      end
      false  # returning false removes this idle callback after one run
    }
  }
end

#widgetObject

Returns the outermost widget to embed in the paned layout.



56
57
58
# File 'lib/vimamsa/gui_func_panel.rb', line 56

def widget
  @box
end