Class: Reflex::TerminalView

Inherits:
View
  • Object
show all
Defined in:
lib/reflex/terminal_view.rb

Constant Summary collapse

DEFAULT_FONT_SIZE =
14
DEFAULT_FONT_NAME =
if    Xot.osx?   then 'Menlo'
elsif Xot.win32? then 'Consolas'
else                  'DejaVu Sans Mono'
end
0.5

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(*args, terminal: nil, command: nil, envs: {}, font: nil, font_size: DEFAULT_FONT_SIZE, **kwargs, &block) ⇒ TerminalView

Returns a new instance of TerminalView.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/reflex/terminal_view.rb', line 24

def initialize(
  *args,
  terminal:  nil, # attach this instead of spawning one
  command:   nil, # passed to Terminal#spawn ($SHELL if nil)
  envs:      {},  # child's env, a nil value removes one
  font:      nil, # a Font, a font name, or [name, size]
  font_size: DEFAULT_FONT_SIZE,
  **kwargs, &block)

  super(*args, **kwargs, &block)
  @terminal, @command, @envs = terminal, command, envs
  @renderer                  = ReflexTerminal::Renderer.new
  @cursor_blink              = true
  @prev_bells                = terminal&.bells || 0
  @font_size                 = font_size
  self.font                  = font || DEFAULT_FONT_NAME
end

Instance Attribute Details

#terminalObject (readonly)

Returns the value of attribute terminal.



42
43
44
# File 'lib/reflex/terminal_view.rb', line 42

def terminal
  @terminal
end

Instance Method Details

#fontObject



55
56
57
# File 'lib/reflex/terminal_view.rb', line 55

def font()
  @renderer.font
end

#font=(font) ⇒ Object



44
45
46
47
48
49
50
51
52
53
# File 'lib/reflex/terminal_view.rb', line 44

def font=(font)
  unless font.is_a? Font
    name, size = [font].flatten
    font       = Font.new name, size || @font_size
  end
  @renderer.font = font
  @font_size     = font.size
  resize_terminal
  redraw
end

#font_sizeObject



63
64
65
# File 'lib/reflex/terminal_view.rb', line 63

def font_size()
  font.size
end

#font_size=(size) ⇒ Object



59
60
61
# File 'lib/reflex/terminal_view.rb', line 59

def font_size=(size)
  self.font = [font.name, size]
end

#on_activate(e) ⇒ Object



80
81
82
# File 'lib/reflex/terminal_view.rb', line 80

def on_activate(e)
  update_cursor_blink
end

#on_attach(e) ⇒ Object



67
68
69
70
71
72
73
74
# File 'lib/reflex/terminal_view.rb', line 67

def on_attach(e)
  unless @terminal
    @terminal = Terminal.new
    @terminal.spawn(@envs, *[@command].compact)
  end
  resize_terminal
  focus
end

#on_bell(e) ⇒ Object



183
184
185
186
187
# File 'lib/reflex/terminal_view.rb', line 183

def on_bell(e)
  # Called with a BellEvent when the terminal received one or more BEL
  # characters (0x07). What a bell means is left to the application: a
  # sound, a flash of the window, a badge, or nothing at all.
end

#on_deactivate(e) ⇒ Object



84
85
86
# File 'lib/reflex/terminal_view.rb', line 84

def on_deactivate(e)
  update_cursor_blink
end

#on_detach(e) ⇒ Object



76
77
78
# File 'lib/reflex/terminal_view.rb', line 76

def on_detach(e)
  stop_cursor_blink
end

#on_draw(e) ⇒ Object



104
105
106
107
108
109
# File 'lib/reflex/terminal_view.rb', line 104

def on_draw(e)
  t = @terminal || return

  @renderer.draw e.painter, t, e.bounds
  draw_cursor e.painter, t
end

#on_focus(e) ⇒ Object



88
89
90
# File 'lib/reflex/terminal_view.rb', line 88

def on_focus(e)
  update_cursor_blink
end

#on_key_down(e) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/reflex/terminal_view.rb', line 111

def on_key_down(e)
  t = @terminal || return

  # typing changes what a selection covers, so it is dropped. A modifier
  # arrives here on its own, and one held with command is a shortcut for
  # the application rather than something typed
  typed = e.chars && (e.modifiers & %i[command win]).empty?
  t.deselect    if typed && t.selection?
  t.scroll_to 0 if t.scroll != 0
  t.write_key e
  start_cursor_blink
end

#on_key_up(e) ⇒ Object



124
125
126
# File 'lib/reflex/terminal_view.rb', line 124

def on_key_up(e)
  @terminal&.write_key e
end

#on_pointer_down(e) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/reflex/terminal_view.rb', line 128

def on_pointer_down(e)
  focus
  t = @terminal || return

  # the child process gets the mouse once it asks for it, unless shift
  # says this drag belongs to the user: the way a terminal lets text be
  # selected inside an application that tracks the mouse itself
  @selecting = e.left? && (!t.mouse_tracking? || e.modifiers.include?(:shift))
  return t.write_pointer(e) unless @selecting

  x, y = to_cell e.x, e.y
  case e.click_count
  when 1 then t.deselect
  when 2 then t.select_word x, y
  else        t.select_line y
  end
end

#on_pointer_move(e) ⇒ Object



152
153
154
155
156
157
158
159
160
161
162
163
164
# File 'lib/reflex/terminal_view.rb', line 152

def on_pointer_move(e)
  t = @terminal || return
  return t.write_pointer(e) unless @selecting
  return unless e.drag? && e.click_count == 1

  down     = e.down || return
  from, to = to_cell(down.x, down.y), to_cell(e.x, e.y)
  if from == to
    t.deselect if t.selection?
  else
    t.select(*from, *to)
  end
end

#on_pointer_up(e) ⇒ Object



146
147
148
149
150
# File 'lib/reflex/terminal_view.rb', line 146

def on_pointer_up(e)
  t = @terminal || return
  t.write_pointer e unless @selecting
  @selecting = false
end

#on_resize(e) ⇒ Object



179
180
181
# File 'lib/reflex/terminal_view.rb', line 179

def on_resize(e)
  resize_terminal
end

#on_update(e) ⇒ Object



92
93
94
95
96
97
98
99
100
101
102
# File 'lib/reflex/terminal_view.rb', line 92

def on_update(e)
  t = @terminal || return
  if t.update || @renderer.glyph_count == 0
    @renderer.bake_glyphs t
    redraw
  end
  if t.bells > @prev_bells
    bells, @prev_bells = t.bells - @prev_bells, t.bells
    on_bell BellEvent.new(bells)
  end
end

#on_wheel(e) ⇒ Object



166
167
168
169
170
171
172
173
174
175
176
177
# File 'lib/reflex/terminal_view.rb', line 166

def on_wheel(e)
  t = @terminal || return

  if t.mouse_tracking?
    t.write_wheel e
  else
    rows = (e.dy / @renderer.cell_height).round
    return if rows == 0
    t.scroll_by rows
    redraw
  end
end