termgui 0.0.4 → 0.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/termgui.rb +1 -1
- metadata +40 -107
- data/Gemfile +0 -14
- data/README.md +0 -321
- data/src/action.rb +0 -58
- data/src/box.rb +0 -90
- data/src/color.rb +0 -174
- data/src/cursor.rb +0 -69
- data/src/editor/editor_base.rb +0 -152
- data/src/editor/editor_base_handlers.rb +0 -116
- data/src/element.rb +0 -61
- data/src/element_bounds.rb +0 -111
- data/src/element_box.rb +0 -64
- data/src/element_render.rb +0 -102
- data/src/element_style.rb +0 -51
- data/src/emitter.rb +0 -102
- data/src/emitter_state.rb +0 -19
- data/src/enterable.rb +0 -93
- data/src/event.rb +0 -92
- data/src/focus.rb +0 -102
- data/src/geometry.rb +0 -53
- data/src/image.rb +0 -60
- data/src/input.rb +0 -85
- data/src/input_grab.rb +0 -17
- data/src/input_time.rb +0 -97
- data/src/key.rb +0 -114
- data/src/log.rb +0 -24
- data/src/node.rb +0 -117
- data/src/node_attributes.rb +0 -27
- data/src/node_visit.rb +0 -52
- data/src/renderer.rb +0 -119
- data/src/renderer_cursor.rb +0 -18
- data/src/renderer_draw.rb +0 -28
- data/src/renderer_image.rb +0 -31
- data/src/renderer_print.rb +0 -40
- data/src/screen.rb +0 -96
- data/src/screen_element.rb +0 -59
- data/src/screen_input.rb +0 -43
- data/src/screen_renderer.rb +0 -53
- data/src/style.rb +0 -149
- data/src/tco/colouring.rb +0 -248
- data/src/tco/config.rb +0 -57
- data/src/tco/palette.rb +0 -603
- data/src/tco/tco_termgui.rb +0 -30
- data/src/termgui.rb +0 -29
- data/src/util.rb +0 -110
- data/src/util/css.rb +0 -98
- data/src/util/css_query.rb +0 -23
- data/src/util/easing.rb +0 -364
- data/src/util/hash_object.rb +0 -131
- data/src/util/imagemagick.rb +0 -27
- data/src/util/justify.rb +0 -20
- data/src/util/unicode-categories.rb +0 -572
- data/src/util/wrap.rb +0 -102
- data/src/widget/button.rb +0 -33
- data/src/widget/checkbox.rb +0 -47
- data/src/widget/col.rb +0 -30
- data/src/widget/image.rb +0 -106
- data/src/widget/inline.rb +0 -40
- data/src/widget/input_number.rb +0 -73
- data/src/widget/inputbox.rb +0 -85
- data/src/widget/label.rb +0 -33
- data/src/widget/modal.rb +0 -69
- data/src/widget/row.rb +0 -26
- data/src/widget/selectbox.rb +0 -100
- data/src/widget/textarea.rb +0 -54
- data/src/xml/xml.rb +0 -80
- data/test/action_test.rb +0 -34
- data/test/box_test.rb +0 -15
- data/test/css_test.rb +0 -39
- data/test/editor/editor_base_test.rb +0 -201
- data/test/element_bounds_test.rb +0 -77
- data/test/element_box_test.rb +0 -8
- data/test/element_render_test.rb +0 -124
- data/test/element_style_test.rb +0 -85
- data/test/element_test.rb +0 -10
- data/test/emitter_test.rb +0 -108
- data/test/event_test.rb +0 -19
- data/test/focus_test.rb +0 -37
- data/test/geometry_test.rb +0 -12
- data/test/input_test.rb +0 -47
- data/test/key_test.rb +0 -14
- data/test/log_test.rb +0 -21
- data/test/node_test.rb +0 -105
- data/test/performance/performance1.rb +0 -48
- data/test/renderer_test.rb +0 -74
- data/test/renderer_test_rect.rb +0 -4
- data/test/screen_test.rb +0 -58
- data/test/style_test.rb +0 -18
- data/test/termgui_test.rb +0 -10
- data/test/test_all.rb +0 -30
- data/test/util_hash_object_test.rb +0 -93
- data/test/util_test.rb +0 -26
- data/test/widget/checkbox_test.rb +0 -99
- data/test/widget/col_test.rb +0 -87
- data/test/widget/inline_test.rb +0 -40
- data/test/widget/label_test.rb +0 -94
- data/test/widget/row_test.rb +0 -40
- data/test/wrap_test.rb +0 -11
- data/test/xml_test.rb +0 -77
data/src/action.rb
DELETED
@@ -1,58 +0,0 @@
|
|
1
|
-
require_relative 'event'
|
2
|
-
require_relative 'emitter'
|
3
|
-
require_relative 'util'
|
4
|
-
|
5
|
-
module TermGui
|
6
|
-
# action manager - it notifies focused elements on user input
|
7
|
-
# WIP
|
8
|
-
# defines action concept semantics like "action", "input"
|
9
|
-
# "focus": user press tab and it set focus on the next focusable element
|
10
|
-
# "enter": user focus a button and press enter or space. The button will receive an "action" event.
|
11
|
-
# "input": user focus a textarea, press enter ("action") and this enters in the "edit" mode
|
12
|
-
# meaning all user input now it's being notified ONLY to the textarea. Nor even the focus manager or
|
13
|
-
# others will be notified.
|
14
|
-
# "escape": when in a textarea "edit" mode, user press ESCAPE to exit it, meaning now user input will
|
15
|
-
# be notified to all listeners. Example: when in edit mode, pressing TAB will just print a tab in the
|
16
|
-
# textarea and it won't change focus as usual. For that to happen user presses escape to exit the "edit" mode.
|
17
|
-
# Attributes enabling each action:
|
18
|
-
# "enterable"
|
19
|
-
# "focusable"
|
20
|
-
# in the case of scape it will be enabled iff enterable is true
|
21
|
-
# For example a Label is not focusable or enterable. A Button is focusable but not enterable. A textatra is focusable and enterable.
|
22
|
-
class ActionManager < Emitter
|
23
|
-
attr_accessor :keys
|
24
|
-
|
25
|
-
def initialize(event: nil, focus: nil)
|
26
|
-
super()
|
27
|
-
@event = event
|
28
|
-
@focus = focus
|
29
|
-
@event.add_any_key_listener { |e| handle_key e }
|
30
|
-
install(:action)
|
31
|
-
@keys = ['enter']
|
32
|
-
end
|
33
|
-
|
34
|
-
def handle_key(e)
|
35
|
-
focused = @focus.focused
|
36
|
-
return unless focused && !focused.get_attribute('entered')
|
37
|
-
|
38
|
-
action_keys = to_array(focused.get_attribute('action-keys') || keys)
|
39
|
-
if action_keys.include?(e.key) && focused.get_attribute('focusable')
|
40
|
-
event = ActionEvent.new focused, e
|
41
|
-
focused_action = focused.get_attribute('action')
|
42
|
-
focused_action&.call(event)
|
43
|
-
trigger event.name, event
|
44
|
-
focused.trigger event.name, event
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
# An event representing an action, like a button "clicked"
|
50
|
-
class ActionEvent < NodeEvent
|
51
|
-
def initialize(target, original_event = nil)
|
52
|
-
super 'action', target, original_event
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
ActionEvent = TermGui::ActionEvent
|
58
|
-
ActionManager = TermGui::ActionManager
|
data/src/box.rb
DELETED
@@ -1,90 +0,0 @@
|
|
1
|
-
BOXES = {
|
2
|
-
single: {
|
3
|
-
topLeft: '┌',
|
4
|
-
topRight: '┐',
|
5
|
-
bottomRight: '┘',
|
6
|
-
bottomLeft: '└',
|
7
|
-
vertical: '│',
|
8
|
-
horizontal: '─'
|
9
|
-
},
|
10
|
-
double: {
|
11
|
-
topLeft: '╔',
|
12
|
-
topRight: '╗',
|
13
|
-
bottomRight: '╝',
|
14
|
-
bottomLeft: '╚',
|
15
|
-
vertical: '║',
|
16
|
-
horizontal: '═'
|
17
|
-
},
|
18
|
-
round: {
|
19
|
-
topLeft: '╭',
|
20
|
-
topRight: '╮',
|
21
|
-
bottomRight: '╯',
|
22
|
-
bottomLeft: '╰',
|
23
|
-
vertical: '│',
|
24
|
-
horizontal: '─'
|
25
|
-
},
|
26
|
-
bold: {
|
27
|
-
topLeft: '┏',
|
28
|
-
topRight: '┓',
|
29
|
-
bottomRight: '┛',
|
30
|
-
bottomLeft: '┗',
|
31
|
-
vertical: '┃',
|
32
|
-
horizontal: '━'
|
33
|
-
},
|
34
|
-
single_double: {
|
35
|
-
topLeft: '╓',
|
36
|
-
topRight: '╖',
|
37
|
-
bottomRight: '╜',
|
38
|
-
bottomLeft: '╙',
|
39
|
-
vertical: '║',
|
40
|
-
horizontal: '─'
|
41
|
-
},
|
42
|
-
double_single: {
|
43
|
-
topLeft: '╒',
|
44
|
-
topRight: '╕',
|
45
|
-
bottomRight: '╛',
|
46
|
-
bottomLeft: '╘',
|
47
|
-
vertical: '│',
|
48
|
-
horizontal: '═'
|
49
|
-
},
|
50
|
-
classic: {
|
51
|
-
topLeft: '+',
|
52
|
-
topRight: '+',
|
53
|
-
bottomRight: '+',
|
54
|
-
bottomLeft: '+',
|
55
|
-
vertical: '|',
|
56
|
-
horizontal: '-'
|
57
|
-
}
|
58
|
-
}.freeze
|
59
|
-
|
60
|
-
def boxes
|
61
|
-
BOXES
|
62
|
-
end
|
63
|
-
|
64
|
-
def draw_box(width: 0, height: 0, style: :single, content: ' ')
|
65
|
-
box = BOXES[style ? style.to_sym : :single]
|
66
|
-
lines = []
|
67
|
-
|
68
|
-
(0..height - 1).each do |y|
|
69
|
-
line = []
|
70
|
-
(0..width - 1).each do |x|
|
71
|
-
line .push(if y.zero? && x.zero?
|
72
|
-
box[:topLeft]
|
73
|
-
elsif y == height - 1 && x.zero?
|
74
|
-
box[:bottomLeft]
|
75
|
-
elsif y.zero? && x == width - 1
|
76
|
-
box[:topRight]
|
77
|
-
elsif y == height - 1 && x == width - 1
|
78
|
-
box[:bottomRight]
|
79
|
-
elsif y == height - 1 || y.zero?
|
80
|
-
box[:horizontal]
|
81
|
-
elsif x == width - 1 || x.zero?
|
82
|
-
box[:vertical]
|
83
|
-
else
|
84
|
-
content
|
85
|
-
end)
|
86
|
-
end
|
87
|
-
lines.push(line.join(''))
|
88
|
-
end
|
89
|
-
lines
|
90
|
-
end
|
data/src/color.rb
DELETED
@@ -1,174 +0,0 @@
|
|
1
|
-
# # # fast acceptable color comparision by myself
|
2
|
-
# # def color_distance1(c1, c2)
|
3
|
-
# # sum = 0
|
4
|
-
# # c1.each_index do |i|
|
5
|
-
# # sum += (c1[i].abs2 - c2[i].abs2).abs
|
6
|
-
# # end
|
7
|
-
# # sum
|
8
|
-
# # end
|
9
|
-
|
10
|
-
# def color_distance3(c1, c2)
|
11
|
-
# sum = 0
|
12
|
-
# coef = [1, 1, 1]
|
13
|
-
# c1.each_index do |i|
|
14
|
-
# sum += ((c1[i] - c2[i]) * coef[i]).abs2
|
15
|
-
# end
|
16
|
-
# sum
|
17
|
-
# end
|
18
|
-
|
19
|
-
# # // As it happens, comparing how similar two colors are is really hard. Here is
|
20
|
-
# # // one of the simplest solutions, which doesn't require conversion to another
|
21
|
-
# # // color space, posted on stackoverflow[1]. Maybe someone better at math can
|
22
|
-
# # // propose a superior solution.
|
23
|
-
# # // [1] http://stackoverflow.com/questions/1633828
|
24
|
-
# def color_distance2(c1, c2)
|
25
|
-
# # function colorDistance(r1, g1, b1, r2, g2, b2) {
|
26
|
-
# # return Math.pow(30 * (r1 - r2), 2)
|
27
|
-
# # + Math.pow(59 * (g1 - g2), 2)
|
28
|
-
# # + Math.pow(11 * (b1 - b2), 2);
|
29
|
-
# # }
|
30
|
-
# (30 * (c1[0] - c2[0])).abs2 + (59 * (c1[1] - c2[1])).abs2 + (11 * (c1[2] - c2[2])).abs2
|
31
|
-
# end
|
32
|
-
|
33
|
-
# # // This might work well enough for a terminal's colors: treat RGB as XYZ in a
|
34
|
-
# # // 3-dimensional space and go midway between the two points.
|
35
|
-
# # exports.mixColors = function(c1, c2, alpha) {
|
36
|
-
# # // if (c1 === 0x1ff) return c1;
|
37
|
-
# # // if (c2 === 0x1ff) return c1;
|
38
|
-
# # if (c1 === 0x1ff) c1 = 0;
|
39
|
-
# # if (c2 === 0x1ff) c2 = 0;
|
40
|
-
# # if (alpha == null) alpha = 0.5;
|
41
|
-
|
42
|
-
# # c1 = exports.vcolors[c1];
|
43
|
-
# # var r1 = c1[0];
|
44
|
-
# # var g1 = c1[1];
|
45
|
-
# # var b1 = c1[2];
|
46
|
-
|
47
|
-
# # c2 = exports.vcolors[c2];
|
48
|
-
# # var r2 = c2[0];
|
49
|
-
# # var g2 = c2[1];
|
50
|
-
# # var b2 = c2[2];
|
51
|
-
|
52
|
-
# # r1 += (r2 - r1) * alpha | 0;
|
53
|
-
# # g1 += (g2 - g1) * alpha | 0;
|
54
|
-
# # b1 += (b2 - b1) * alpha | 0;
|
55
|
-
|
56
|
-
# # return exports.match([r1, g1, b1]);
|
57
|
-
# # };
|
58
|
-
|
59
|
-
# # the rest is obsoleted by src/tco
|
60
|
-
|
61
|
-
# # color enumerations and utilities. See http://ascii-table.com/ansi-escape-sequences.phpsss
|
62
|
-
# require_relative 'key'
|
63
|
-
|
64
|
-
# # obsolete
|
65
|
-
# COLORS = {
|
66
|
-
# black: 0,
|
67
|
-
# red: 1,
|
68
|
-
# green: 2,
|
69
|
-
# yellow: 3,
|
70
|
-
# blue: 4,
|
71
|
-
# magenta: 5,
|
72
|
-
# cyan: 6,
|
73
|
-
# white: 7
|
74
|
-
# }.freeze
|
75
|
-
|
76
|
-
# # obsolete
|
77
|
-
# def color_names
|
78
|
-
# %w[black red green yellow blue magenta cyan white]
|
79
|
-
# end
|
80
|
-
|
81
|
-
# # obsolete
|
82
|
-
# def random_color
|
83
|
-
# color_names.sample
|
84
|
-
# end
|
85
|
-
|
86
|
-
# # obsolete
|
87
|
-
# def color_text(content, fg = nil, bg = nil)
|
88
|
-
# colored = color(fg, bg)
|
89
|
-
# colored << content
|
90
|
-
# colored << "#{CSI}0m"
|
91
|
-
# end
|
92
|
-
|
93
|
-
# # obsolete
|
94
|
-
# def color(fg = nil, bg = nil)
|
95
|
-
# colored = ''
|
96
|
-
# colored << color_to_escape(fg, 30) if fg
|
97
|
-
# colored << color_to_escape(bg, 40) if bg
|
98
|
-
# end
|
99
|
-
|
100
|
-
# # obsolete
|
101
|
-
# def color_to_escape(name, layer)
|
102
|
-
# short_name = name.to_s.sub(/\Abright_/, '')
|
103
|
-
# color = COLORS.fetch(short_name.to_sym)
|
104
|
-
# escape = "#{CSI}#{layer + color}"
|
105
|
-
# escape << ';1' if short_name.size < name.size
|
106
|
-
# escape << 'm'
|
107
|
-
# escape
|
108
|
-
# end
|
109
|
-
|
110
|
-
# # # https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_parameters
|
111
|
-
# # ATTRIBUTES = {
|
112
|
-
# # normal: 0,
|
113
|
-
|
114
|
-
# # bold: 1,
|
115
|
-
# # boldOff: 22,
|
116
|
-
|
117
|
-
# # faint: 2,
|
118
|
-
# # faintOff: 22,
|
119
|
-
|
120
|
-
# # italic: 3,
|
121
|
-
# # italicOff: 23,
|
122
|
-
|
123
|
-
# # underline: 4,
|
124
|
-
# # underlineOff: 24,
|
125
|
-
|
126
|
-
# # blink: 5,
|
127
|
-
# # slowBlink: 5,
|
128
|
-
# # rapidBlink: 6,
|
129
|
-
# # blinkOff: 25,
|
130
|
-
# # slowBlinkOff: 25,
|
131
|
-
# # rapidBlinkOff: 25,
|
132
|
-
|
133
|
-
# # inverse: 7,
|
134
|
-
# # inverseOff: 27,
|
135
|
-
|
136
|
-
# # defaultForeground: 39,
|
137
|
-
# # defaultBackground: 49,
|
138
|
-
|
139
|
-
# # invisible: 8,
|
140
|
-
# # invisibleOff: 28,
|
141
|
-
|
142
|
-
# # fraktur: 20,
|
143
|
-
# # frakturOff: 23,
|
144
|
-
|
145
|
-
# # framed: 51,
|
146
|
-
# # encircled: 52,
|
147
|
-
# # overlined: 53,
|
148
|
-
|
149
|
-
# # framedOff: 54,
|
150
|
-
# # encircledOff: 54
|
151
|
-
# # }.freeze
|
152
|
-
|
153
|
-
# # # Usage: screen.write attributes(blink: true).
|
154
|
-
# # # Attributes supported: bold, inverse, blink, slowBlink, rapidBlink, invisible, fraktur, framed, encircled, normal,
|
155
|
-
# # # italic, underline, faint
|
156
|
-
# # #
|
157
|
-
# # # Esc[Value;...;Valuem Set Graphics Mode:
|
158
|
-
# # # Calls the graphics functions specified by the following values.
|
159
|
-
# # # These specified functions remain active until the next occurrence of this escape sequence. Graphics mode changes the
|
160
|
-
# # # colors and attributes of text (such as bold and underline) displayed on the screen
|
161
|
-
# # def attributes(**args)
|
162
|
-
# # output = []
|
163
|
-
# # args.keys.each do |key|
|
164
|
-
# # if args[key] == true
|
165
|
-
# # output.push ATTRIBUTES[key].to_s
|
166
|
-
# # elsif args[key] == false
|
167
|
-
# # output.push ATTRIBUTES[:blinkOff].to_s if key == :blink
|
168
|
-
# # output.push "#{CSI}#{ATTRIBUTES[:boldOff]}" if key == :bold
|
169
|
-
# # # TODO: the rest
|
170
|
-
# # end
|
171
|
-
# # end
|
172
|
-
# # # p output
|
173
|
-
# # !output.empty? ? "#{CSI}#{output.join(';')}m" : ''
|
174
|
-
# # end
|
data/src/cursor.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
require_relative 'style'
|
2
|
-
module TermGui
|
3
|
-
# minimalist artificial screen cursor. TODO: cursor can be manipulated via ansi escape codes - see npm.org/blessed
|
4
|
-
class Cursor
|
5
|
-
attr_accessor :interval, :x, :y, :enabled, :off, :on
|
6
|
-
|
7
|
-
def initialize(
|
8
|
-
on_interval: 0.3, off_interval: on_interval / 2,
|
9
|
-
x: 0, y: 0, enabled: false,
|
10
|
-
# by default we render the cursor next to its real x-coordinate
|
11
|
-
x_offset: 1,
|
12
|
-
screen: nil, off: ' ', on: '_',
|
13
|
-
on_style: Style.new(bg: 'white', fg: 'black'), off_style: Style.new(bg: 'black', fg: 'white')
|
14
|
-
)
|
15
|
-
@x = x
|
16
|
-
@y = y
|
17
|
-
@on_interval = on_interval
|
18
|
-
@off_interval = off_interval
|
19
|
-
@enabled = enabled
|
20
|
-
@x_offset = x_offset
|
21
|
-
@screen = screen
|
22
|
-
throw 'screen must be provided' unless @screen
|
23
|
-
@state = 0
|
24
|
-
@off = off
|
25
|
-
@on = on
|
26
|
-
@on_style = on_style
|
27
|
-
@off_style = off_style
|
28
|
-
end
|
29
|
-
|
30
|
-
def enable
|
31
|
-
disable
|
32
|
-
@enabled = true
|
33
|
-
@state = 0
|
34
|
-
tick
|
35
|
-
end
|
36
|
-
|
37
|
-
def draw_off
|
38
|
-
@screen.text(x: @x + @x_offset, y: @y, text: @off, style: @off_style)
|
39
|
-
end
|
40
|
-
|
41
|
-
def draw_on
|
42
|
-
@screen.text(x: @x + @x_offset, y: @y, text: @on, style: @on_style)
|
43
|
-
end
|
44
|
-
|
45
|
-
def disable
|
46
|
-
@enabled = false
|
47
|
-
@screen.clear_timeout @timeout if @timeout
|
48
|
-
end
|
49
|
-
|
50
|
-
protected
|
51
|
-
|
52
|
-
# renders the cursor according to its state, toggling the state and finally schedulling to call it self according to on_interval, off_interval
|
53
|
-
def tick
|
54
|
-
if @state == 0
|
55
|
-
@state = 1
|
56
|
-
draw_on
|
57
|
-
elsif @state == 1
|
58
|
-
@state = 0
|
59
|
-
draw_off
|
60
|
-
else
|
61
|
-
throw 'unknown state ' + @state
|
62
|
-
end
|
63
|
-
@screen.clear_timeout @timeout if @timeout
|
64
|
-
@timeout = @screen.set_timeout(@state == 0 ? @on_interval : @off_interval) { tick } if @enabled
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
Cursor = TermGui::Cursor
|
data/src/editor/editor_base.rb
DELETED
@@ -1,152 +0,0 @@
|
|
1
|
-
require_relative '../cursor'
|
2
|
-
require_relative '../log'
|
3
|
-
require_relative '../key'
|
4
|
-
require_relative 'editor_base_handlers'
|
5
|
-
|
6
|
-
# See TODO.md section Editor for status and TODOs
|
7
|
-
module TermGui
|
8
|
-
class EditorBase
|
9
|
-
include EditorBaseHandlers
|
10
|
-
|
11
|
-
attr_accessor :x, :y, :width, :height
|
12
|
-
|
13
|
-
def initialize(
|
14
|
-
text: '', screen: nil, x: 0, y: 0,
|
15
|
-
width: screen.width, height: screen.height,
|
16
|
-
cursor_x: nil, cursor_y: nil,
|
17
|
-
# if true other party will listen keys and call handle_key - if false it will listen any key by itlself
|
18
|
-
managed: false
|
19
|
-
)
|
20
|
-
@screen = screen || (throw 'screen not given')
|
21
|
-
@x = x
|
22
|
-
@y = y
|
23
|
-
@width = width
|
24
|
-
@height = height
|
25
|
-
@managed = managed
|
26
|
-
@cursor = Cursor.new(screen: @screen)
|
27
|
-
self.text = text
|
28
|
-
@cursor.y = @y + cursor_y if cursor_y
|
29
|
-
@cursor.x = @x + cursor_x if cursor_x
|
30
|
-
end
|
31
|
-
|
32
|
-
def cursor_x
|
33
|
-
@cursor.x - @x
|
34
|
-
end
|
35
|
-
|
36
|
-
def cursor_y
|
37
|
-
@cursor.y - @y
|
38
|
-
end
|
39
|
-
|
40
|
-
def text=(text)
|
41
|
-
@lines = text.split('\n')
|
42
|
-
@cursor.y = @y + @lines.length - 1
|
43
|
-
@cursor.x = @x + current_line.length - 1
|
44
|
-
end
|
45
|
-
|
46
|
-
def value=(v)
|
47
|
-
self.text = v
|
48
|
-
end
|
49
|
-
|
50
|
-
def text
|
51
|
-
@lines.join('\n')
|
52
|
-
end
|
53
|
-
|
54
|
-
def value
|
55
|
-
text
|
56
|
-
end
|
57
|
-
|
58
|
-
def enable(and_render = true)
|
59
|
-
disable
|
60
|
-
@cursor.enable
|
61
|
-
unless @managed
|
62
|
-
@key_listener = @screen.event.add_any_key_listener do |event|
|
63
|
-
handle_key event
|
64
|
-
end
|
65
|
-
end
|
66
|
-
render if and_render
|
67
|
-
end
|
68
|
-
|
69
|
-
def disable
|
70
|
-
@cursor.disable
|
71
|
-
@screen.event.remove_any_key_listener @key_listener if @key_listener
|
72
|
-
@key_listener = nil
|
73
|
-
end
|
74
|
-
|
75
|
-
def enabled
|
76
|
-
@cursor.enabled
|
77
|
-
end
|
78
|
-
|
79
|
-
def render
|
80
|
-
@screen.clear
|
81
|
-
# @screen.rect(x: x, y: y, width: width, height: height, style: Style.new)
|
82
|
-
@screen.render
|
83
|
-
@lines.each_with_index do |line, i|
|
84
|
-
@screen.text(x: @x, y: @y + i, text: line)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
# public so keys can be programmatically simlated - useful for tests instead of calling screen.event.handle_keythat emits globally.
|
89
|
-
def handle_key(event)
|
90
|
-
if !enabled
|
91
|
-
return
|
92
|
-
elsif ['down'].include? event.key
|
93
|
-
cursor_down
|
94
|
-
elsif ['up'].include? event.key
|
95
|
-
cursor_up
|
96
|
-
elsif ['right'].include? event.key
|
97
|
-
cursor_right
|
98
|
-
elsif ['left'].include? event.key
|
99
|
-
cursor_left
|
100
|
-
elsif ['enter'].include? event.key
|
101
|
-
handle_enter
|
102
|
-
elsif ['tab'].include? event.key
|
103
|
-
insert_chars(' ') # TODO: hack - adding a tab will break since we assume all chars width is 1 (1 column per char) - it will also fail for unicode chars width>1
|
104
|
-
elsif ['S-tab'].include? event.key
|
105
|
-
# TODO: remove tab line prefix
|
106
|
-
elsif event.key == 'backspace'
|
107
|
-
handle_backspace
|
108
|
-
elsif event.key == 'delete'
|
109
|
-
handle_delete
|
110
|
-
elsif alphanumeric?(event.raw) || %w[space tab].include?(event.key)
|
111
|
-
insert_chars(event.raw)
|
112
|
-
end
|
113
|
-
|
114
|
-
@cursor.off = current_char || @cursor.off
|
115
|
-
@cursor.on = current_char || @cursor.on
|
116
|
-
render
|
117
|
-
@cursor.draw_on
|
118
|
-
end
|
119
|
-
|
120
|
-
protected
|
121
|
-
|
122
|
-
def current_line
|
123
|
-
@lines[current_y] || ''
|
124
|
-
end
|
125
|
-
|
126
|
-
def current_line=(value)
|
127
|
-
@lines[current_y] = value || ''
|
128
|
-
end
|
129
|
-
|
130
|
-
def current_char
|
131
|
-
current_line[[[current_x, current_line.length].min, 0].max] || ' '
|
132
|
-
end
|
133
|
-
|
134
|
-
def current_x
|
135
|
-
@cursor.x - @x
|
136
|
-
end
|
137
|
-
|
138
|
-
def current_x=(x)
|
139
|
-
@cursor.x = @x + x
|
140
|
-
end
|
141
|
-
|
142
|
-
def current_y
|
143
|
-
@cursor.y - @y
|
144
|
-
end
|
145
|
-
|
146
|
-
def current_y=(y)
|
147
|
-
@cursor.y = @y + y
|
148
|
-
end
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
|
-
EditorBase = TermGui::EditorBase
|