Class: Rcurses::Popup

Inherits:
Pane
  • Object
show all
Defined in:
lib/rcurses/popup.rb

Constant Summary

Constants included from Cursor

Cursor::CSI, Cursor::ESC

Instance Attribute Summary

Attributes inherited from Pane

#align, #bg, #border, #emoji, #emoji_refresh, #fg, #h, #history, #index, #ix, #moredown, #moreup, #multiline_buffer, #prompt, #record, #scroll, #scroll_fg, #text, #update, #w, #x, #y

Instance Method Summary collapse

Methods inherited from Pane

#ask, #border_refresh, #bottom, #cleanup, #clear, #down, #edit, #editline, finalizer_proc, #full_refresh, #left, #line_count, #linedown, #lineup, #move, #pagedown, #pageup, #parse, #refresh, #right, #say, #textformat, #top, #up

Methods included from Input

#getchr

Methods included from Cursor

clear_char, clear_line, clear_line_after, clear_line_before, clear_screen_down, col, colget, down, hide, left, next_line, pos, prev_line, restore, right, row, rowget, save, scroll_down, scroll_up, set, show, up

Constructor Details

#initialize(x: nil, y: nil, w: 40, h: 15, fg: 255, bg: 236) ⇒ Popup

Creates a popup overlay. Defaults to centered, bordered, dark background.

Usage:

popup = Rcurses::Popup.new(w: 50, h: 20)          # auto-centered
popup = Rcurses::Popup.new(x: 10, y: 5, w: 50, h: 20)  # explicit position

# Simple modal (blocks until ESC/ENTER, returns selected line index or nil)
result = popup.modal(content_string)

# Manual control
popup.show(content_string)
# ... your own input loop ...
popup.dismiss(refresh_panes: [pane1, pane2])


17
18
19
20
21
22
23
24
25
# File 'lib/rcurses/popup.rb', line 17

def initialize(x: nil, y: nil, w: 40, h: 15, fg: 255, bg: 236)
  max_h, max_w = IO.console ? IO.console.winsize : [24, 80]
  # Auto-center if position not specified
  px = x || ((max_w - w) / 2 + 1)
  py = y || ((max_h - h) / 2 + 1)
  super(px, py, w, h, fg, bg)
  @border = true
  @scroll = true
end

Instance Method Details

#clear_areaObject

Blank the screen region occupied by this popup (including border)



93
94
95
96
97
98
99
100
101
102
# File 'lib/rcurses/popup.rb', line 93

def clear_area
  top = @y - (@border ? 1 : 0)
  bot = @y + @h - 1 + (@border ? 1 : 0)
  left = @x - (@border ? 1 : 0)
  width = @w + (@border ? 2 : 0)
  (top..bot).each do |row|
    STDOUT.print "\e[#{row};#{left}H\e[0m#{' ' * width}"
  end
  STDOUT.flush
end

#dismiss(refresh_panes: []) ⇒ Object

Clear the popup area and optionally refresh underlying panes



85
86
87
88
89
90
# File 'lib/rcurses/popup.rb', line 85

def dismiss(refresh_panes: [])
  clear_area
  refresh_panes.each do |p|
    p.full_refresh if p.respond_to?(:full_refresh)
  end
end

Modal: show content, handle scroll/navigation, return on ESC or ENTER. Returns the selected line index on ENTER, or nil on ESC. Optional block receives each keypress for custom handling; return :dismiss from the block to close, or a String to return that value.



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
80
81
82
# File 'lib/rcurses/popup.rb', line 38

def modal(content, &on_key)
  @text = content
  @ix = 0
  @index = 0

  loop do
    full_refresh

    chr = getchr(flush: false)
    case chr
    when 'ESC'
      return nil
    when 'ENTER'
      return @index
    when 'UP', 'k'
      @index = [@index - 1, 0].max
      scroll_to_index
    when 'DOWN', 'j'
      total = (@text || "").split("\n").size
      @index = [@index + 1, total - 1].min
      scroll_to_index
    when 'PgUP'
      @index = [@index - @h + 1, 0].max
      scroll_to_index
    when 'PgDOWN'
      total = (@text || "").split("\n").size
      @index = [@index + @h - 1, total - 1].min
      scroll_to_index
    when 'HOME'
      @index = 0
      @ix = 0
    when 'END'
      total = (@text || "").split("\n").size
      @index = [total - 1, 0].max
      scroll_to_index
    end

    # Custom key handler
    if block_given?
      result = on_key.call(chr, @index)
      return nil if result == :dismiss
      return result if result.is_a?(String)
    end
  end
end

#show(content) ⇒ Object

Show content in the popup (non-blocking, just renders)



28
29
30
31
32
# File 'lib/rcurses/popup.rb', line 28

def show(content)
  @text = content
  @ix = 0
  full_refresh
end