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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/lib/termgui.rb +1 -1
  3. metadata +40 -107
  4. data/Gemfile +0 -14
  5. data/README.md +0 -321
  6. data/src/action.rb +0 -58
  7. data/src/box.rb +0 -90
  8. data/src/color.rb +0 -174
  9. data/src/cursor.rb +0 -69
  10. data/src/editor/editor_base.rb +0 -152
  11. data/src/editor/editor_base_handlers.rb +0 -116
  12. data/src/element.rb +0 -61
  13. data/src/element_bounds.rb +0 -111
  14. data/src/element_box.rb +0 -64
  15. data/src/element_render.rb +0 -102
  16. data/src/element_style.rb +0 -51
  17. data/src/emitter.rb +0 -102
  18. data/src/emitter_state.rb +0 -19
  19. data/src/enterable.rb +0 -93
  20. data/src/event.rb +0 -92
  21. data/src/focus.rb +0 -102
  22. data/src/geometry.rb +0 -53
  23. data/src/image.rb +0 -60
  24. data/src/input.rb +0 -85
  25. data/src/input_grab.rb +0 -17
  26. data/src/input_time.rb +0 -97
  27. data/src/key.rb +0 -114
  28. data/src/log.rb +0 -24
  29. data/src/node.rb +0 -117
  30. data/src/node_attributes.rb +0 -27
  31. data/src/node_visit.rb +0 -52
  32. data/src/renderer.rb +0 -119
  33. data/src/renderer_cursor.rb +0 -18
  34. data/src/renderer_draw.rb +0 -28
  35. data/src/renderer_image.rb +0 -31
  36. data/src/renderer_print.rb +0 -40
  37. data/src/screen.rb +0 -96
  38. data/src/screen_element.rb +0 -59
  39. data/src/screen_input.rb +0 -43
  40. data/src/screen_renderer.rb +0 -53
  41. data/src/style.rb +0 -149
  42. data/src/tco/colouring.rb +0 -248
  43. data/src/tco/config.rb +0 -57
  44. data/src/tco/palette.rb +0 -603
  45. data/src/tco/tco_termgui.rb +0 -30
  46. data/src/termgui.rb +0 -29
  47. data/src/util.rb +0 -110
  48. data/src/util/css.rb +0 -98
  49. data/src/util/css_query.rb +0 -23
  50. data/src/util/easing.rb +0 -364
  51. data/src/util/hash_object.rb +0 -131
  52. data/src/util/imagemagick.rb +0 -27
  53. data/src/util/justify.rb +0 -20
  54. data/src/util/unicode-categories.rb +0 -572
  55. data/src/util/wrap.rb +0 -102
  56. data/src/widget/button.rb +0 -33
  57. data/src/widget/checkbox.rb +0 -47
  58. data/src/widget/col.rb +0 -30
  59. data/src/widget/image.rb +0 -106
  60. data/src/widget/inline.rb +0 -40
  61. data/src/widget/input_number.rb +0 -73
  62. data/src/widget/inputbox.rb +0 -85
  63. data/src/widget/label.rb +0 -33
  64. data/src/widget/modal.rb +0 -69
  65. data/src/widget/row.rb +0 -26
  66. data/src/widget/selectbox.rb +0 -100
  67. data/src/widget/textarea.rb +0 -54
  68. data/src/xml/xml.rb +0 -80
  69. data/test/action_test.rb +0 -34
  70. data/test/box_test.rb +0 -15
  71. data/test/css_test.rb +0 -39
  72. data/test/editor/editor_base_test.rb +0 -201
  73. data/test/element_bounds_test.rb +0 -77
  74. data/test/element_box_test.rb +0 -8
  75. data/test/element_render_test.rb +0 -124
  76. data/test/element_style_test.rb +0 -85
  77. data/test/element_test.rb +0 -10
  78. data/test/emitter_test.rb +0 -108
  79. data/test/event_test.rb +0 -19
  80. data/test/focus_test.rb +0 -37
  81. data/test/geometry_test.rb +0 -12
  82. data/test/input_test.rb +0 -47
  83. data/test/key_test.rb +0 -14
  84. data/test/log_test.rb +0 -21
  85. data/test/node_test.rb +0 -105
  86. data/test/performance/performance1.rb +0 -48
  87. data/test/renderer_test.rb +0 -74
  88. data/test/renderer_test_rect.rb +0 -4
  89. data/test/screen_test.rb +0 -58
  90. data/test/style_test.rb +0 -18
  91. data/test/termgui_test.rb +0 -10
  92. data/test/test_all.rb +0 -30
  93. data/test/util_hash_object_test.rb +0 -93
  94. data/test/util_test.rb +0 -26
  95. data/test/widget/checkbox_test.rb +0 -99
  96. data/test/widget/col_test.rb +0 -87
  97. data/test/widget/inline_test.rb +0 -40
  98. data/test/widget/label_test.rb +0 -94
  99. data/test/widget/row_test.rb +0 -40
  100. data/test/wrap_test.rb +0 -11
  101. data/test/xml_test.rb +0 -77
@@ -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
@@ -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
@@ -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
@@ -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