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,116 +0,0 @@
1
- require_relative '../cursor'
2
- require_relative '../log'
3
- require_relative '../key'
4
-
5
- module TermGui
6
- module EditorBaseHandlers
7
- def handle_enter
8
- if current_x >= current_line.length
9
- @lines.insert(current_y + 1, '')
10
- else
11
- line1 = current_x == 0 ? '' : current_line[0..[current_x - 1, 0].max]
12
- line2 = current_line[[current_x, current_line.length].min..current_line.length]
13
- @lines.delete_at(current_y)
14
- @lines.insert(current_y, line1, line2)
15
- end
16
- self.current_y += 1
17
- self.current_x = 0
18
- end
19
-
20
- def insert_chars(s)
21
- prefix = current_x < 1 ? '' : current_line[0..[current_x - 1, 0].max] || ''
22
- postfix = current_line[[current_x, 0].max..current_line.length] || ''
23
- self.current_line = prefix + s + postfix
24
- self.current_x += s.length
25
- end
26
-
27
- def handle_delete
28
- if current_x >= current_line.length && current_y >= @lines.length - 1
29
- @screen.alert
30
- else
31
- if current_line.length <= 1
32
- self.current_x = 0
33
- self.current_line = ''
34
- else
35
- prefix = current_line[0..[current_x - 1, 0].max]
36
- postfix = current_line[[current_x + 1, current_line.length].min..current_line.length] || ''
37
- self.current_line = prefix + postfix
38
- # TODO: join lines if at the end of line and there's a following
39
- end
40
- end
41
- end
42
-
43
- def cursor_down
44
- if self.current_y == @lines.length - 1
45
- if current_x > current_line.length
46
- @screen.alert
47
- else
48
- self.current_x = current_line.length
49
- end
50
- else
51
- self.current_y = self.current_y == @lines.length - 1 ? current_y : current_y + 1
52
- self.current_x = [current_x, current_line.length].min
53
- end
54
- end
55
-
56
- def cursor_right
57
- if current_x >= current_line.length
58
- if current_y < @lines.length - 1
59
- self.current_y += 1
60
- self.current_x = 0
61
- else
62
- @screen.alert
63
- end
64
- else
65
- self.current_x += 1
66
- end
67
- end
68
-
69
- def cursor_left
70
- if current_x < 1
71
- if current_y > 0
72
- self.current_y -= 1
73
- self.current_x = current_line.length
74
- else
75
- @screen.alert
76
- end
77
- else
78
- self.current_x -= 1
79
- end
80
- end
81
-
82
- def handle_backspace
83
- if current_x < 1 && current_y <= 0
84
- @screen.alert
85
- elsif current_x < 1
86
- old_line = (@lines.delete_at(current_y) unless @lines.empty?) || ''
87
- self.current_y = [current_y - 1, 0].max
88
- self.current_x = current_line.length
89
- self.current_line = current_line + old_line
90
- elsif current_line.length <= 1
91
- self.current_x = 0
92
- self.current_line = ''
93
- else
94
- prefix = current_line[0..[current_x - 2, 0].max]
95
- postfix = current_line[[current_x, current_line.length].min..current_line.length] || ''
96
- self.current_line = prefix + postfix
97
- self.current_x = [current_x - 1, 0].max
98
- end
99
- end
100
-
101
- def cursor_up
102
- if self.current_y == 0
103
- if self.current_x == 0
104
- @screen.alert
105
- else
106
- self.current_x = 0
107
- end
108
- else
109
- self.current_y = [current_y - 1, 0].max
110
- self.current_x = [current_x, current_line.length - 1].min
111
- end
112
- end
113
- end
114
- end
115
-
116
- EditorBaseHandlers = TermGui::EditorBaseHandlers
@@ -1,61 +0,0 @@
1
- require_relative 'node'
2
- require_relative 'style'
3
- require_relative 'renderer'
4
- require_relative 'element_bounds'
5
- require_relative 'element_box'
6
- require_relative 'element_render'
7
- require_relative 'element_style'
8
-
9
- module TermGui
10
- # Node responsible of
11
- # * x, y, width, height, abs_x, abs_y
12
- # * rendering text, wrap (TODO)
13
- # * border, margin & padding & abs_* update (TODO)
14
- # * scroll
15
- # TODO: separate each responsibility on its module or subclass
16
- class Element < Node
17
- include ElementBounds
18
- include ElementBox
19
- include ElementRender
20
- include ElementStyle
21
-
22
- def initialize(**args)
23
- super
24
- install(%i[focus blur action enter escape])
25
- args[:attributes] = { x: args[:x] || 0, y: args[:y] || 0, width: args[:width] || 0, height: args[:height] || 0 } if args[:attributes] == nil
26
- a = {}.merge(args, args[:attributes] || {})
27
- a[:style] = default_style.assign(Style.from_hash(a[:attributes][:style])).assign(Style.from_hash(a[:style]))
28
- self.attributes = a
29
- self.style = a[:style]
30
- on(%i[focus blur action enter escape]) do |e|
31
- s = root_screen
32
- if s
33
- if e.name == 'action'
34
- set_attribute('actioned', true)
35
- render s
36
- s.set_timeout(get_attribute('actioned-interval') || 0.2) do
37
- set_attribute('actioned', false)
38
- render s
39
- end
40
- else
41
- render s
42
- end
43
- end
44
- end
45
- end
46
-
47
- def focus
48
- if get_attribute('focusable')
49
- root_screen&.focus&.focused = self
50
- trigger :bounds_change
51
- end
52
- end
53
-
54
- def text=(v)
55
- @text = v
56
- trigger :bounds_change
57
- end
58
- end
59
- end
60
-
61
- Element = TermGui::Element
@@ -1,111 +0,0 @@
1
- require_relative 'util'
2
- require_relative 'geometry'
3
-
4
- # Adds support for Element's x, y, abs_x, abs_y, width, height, abs_width, abs_height, offset (scroll viewport)
5
- module ElementBounds
6
- def initialize(**args)
7
- super
8
- install(:bounds_change)
9
- end
10
-
11
- def x=(x)
12
- set_attribute('x', x)
13
- trigger :bounds_change
14
- end
15
-
16
- def x
17
- get_attribute('x') || 0
18
- end
19
-
20
- def abs_x
21
- val = if is_percent x
22
- ((@parent ? @parent.abs_x : 0) + x * (@parent ? @parent.abs_width : abs_width)).truncate
23
- else
24
- ((@parent ? @parent.abs_x : 0) + x).truncate
25
- end
26
- o = @parent && parent.offset
27
- val -= o.left if o
28
- # val -= 1 if border
29
- val
30
- end
31
-
32
- def offset
33
- v = get_attribute('offset')
34
- set_attribute('offset', v = Offset.new) unless v
35
- v
36
- end
37
-
38
- def offset=(value)
39
- set_attribute('offset', value)
40
- trigger :bounds_change
41
- end
42
-
43
- def abs_x=(value)
44
- # TODO: parent offset
45
- self.x = value - (@parent ? @parent.abs_x : 0).truncate
46
- end
47
-
48
- def y=(y)
49
- set_attribute('y', y)
50
- trigger :bounds_change
51
- end
52
-
53
- def y
54
- get_attribute('y') || 0
55
- end
56
-
57
- def abs_y
58
- val = if is_percent y
59
- ((@parent ? @parent.abs_y : 0) + y * (@parent ? @parent.abs_height : abs_height)).truncate
60
- else
61
- ((@parent ? @parent.abs_y : 0) + y).truncate
62
- end
63
- o = @parent && parent.offset
64
- val -= o.top if o
65
- # val += 1 if border
66
- val
67
- end
68
-
69
- def abs_y=(value)
70
- # TODO: parent offset
71
- self.y = value - (@parent ? @parent.abs_y : 0).truncate
72
- end
73
-
74
- def width=(width)
75
- set_attribute('width', width)
76
- trigger :bounds_change
77
- end
78
-
79
- def width
80
- get_attribute('width') || 0
81
- end
82
-
83
- def abs_width
84
- val = if (is_percent width) && @parent
85
- (@parent.abs_width * width).truncate
86
- else
87
- width.truncate
88
- end
89
- val += 2 if border
90
- val
91
- end
92
-
93
- def height=(height)
94
- set_attribute('height', height)
95
- trigger :bounds_change
96
- end
97
-
98
- def height
99
- get_attribute('height') || 0
100
- end
101
-
102
- def abs_height
103
- val = if is_percent height
104
- (@parent ? @parent.abs_height * height : 0).truncate
105
- else
106
- height.truncate
107
- end
108
- val += 2 if border&.style
109
- val
110
- end
111
- end
@@ -1,64 +0,0 @@
1
- require_relative 'geometry'
2
- require_relative 'element_bounds'
3
- require_relative 'util/hash_object'
4
-
5
- # Adds html-like box-model support for Element: margin, padding, border
6
- module ElementBox
7
- include ElementBounds
8
-
9
- def abs_content_x
10
- abs_x + abs_padding.left + (border ? 1 : 0)
11
- end
12
-
13
- def abs_content_y
14
- abs_y + abs_padding.top + (border ? 1 : 0)
15
- end
16
-
17
- def abs_content_width
18
- m = abs_padding
19
- abs_width - m.left - m.right - (border ? 2 : 0)
20
- end
21
-
22
- def abs_content_height
23
- m = abs_padding
24
- abs_height - m.top - m.bottom - (border ? 2 : 0)
25
- end
26
-
27
- def abs_content_bounds
28
- y = abs_content_y
29
- x = abs_content_x
30
- Bounds.new(left: x, right: x + abs_content_width, top: y, bottom: y + abs_content_height)
31
- end
32
-
33
- def abs_content_box
34
- Rectangle.new(x: abs_content_x, y: abs_content_y, width: abs_content_width, height: abs_content - abs_content_height)
35
- end
36
-
37
- # returns padding as Offset instance
38
- def padding
39
- padding = get_style('padding')
40
- if !padding
41
- Bounds.new
42
- elsif padding.instance_of? Hash
43
- Offset.from_hash(padding)
44
- else
45
- padding
46
- end
47
- end
48
-
49
- def padding=(padding)
50
- set_style('padding', padding)
51
- trigger :bounds_change
52
- end
53
-
54
- # computes absolute padding transforming padding percents to absolute pixel amounts.
55
- def abs_padding
56
- p = padding
57
- Bounds.new(
58
- top: is_percent(p.top) ? (p.top * abs_height).truncate : p.top,
59
- bottom: is_percent(p.bottom) ? (p.bottom * abs_height).truncate : p.bottom,
60
- left: is_percent(p.left) ? (p.left * abs_width).truncate : p.left,
61
- right: is_percent(p.right) ? (p.right * abs_width).truncate : p.right
62
- )
63
- end
64
- end
@@ -1,102 +0,0 @@
1
- require_relative 'element_box'
2
- require_relative 'element_style'
3
- require_relative 'util'
4
- require_relative 'util/wrap'
5
- require_relative 'log'
6
- require_relative 'box'
7
-
8
- # implements element rendering (self, border, child, text) for which it depends on ElementBox
9
- module ElementRender
10
- include ElementBox
11
- include ElementStyle
12
-
13
- attr_accessor :dirty
14
-
15
- def initialize(**args)
16
- super
17
- @render_cache = args[:render_cache] || false
18
- @dirty = true
19
- @render_cache_data = nil
20
- on(:bounds_change) do
21
- @dirty = true
22
- end
23
- end
24
-
25
- def border
26
- style&.border
27
- end
28
-
29
- def render(screen = root_screen, force = false)
30
- self.dirty = true if force
31
- return '' unless screen
32
-
33
- trigger(:before_render)
34
-
35
- layout
36
- if @render_cache && !dirty && @render_cache_data
37
- screen.write @render_cache_data
38
- else
39
- @render_cache_data = [
40
- render_border(screen),
41
- render_self(screen),
42
- render_text(screen)
43
- ].join('')
44
- end
45
- trigger(:after_render)
46
- self.dirty = false if @render_cache
47
- [@render_cache_data, render_children(screen)].join('')
48
- end
49
-
50
- def root_screen
51
- @parent&.root_screen
52
- end
53
-
54
- def clear
55
- root_screen.rect(x: abs_x, y: abs_y, width: abs_width, height: abs_height, style: parent.final_style) if parent && root_screen
56
- end
57
-
58
- protected
59
-
60
- def render_self(screen)
61
- screen.rect(
62
- x: abs_x + (border ? 1 : 0),
63
- y: abs_y + (border ? 1 : 0),
64
- width: abs_width - (border ? 2 : 0),
65
- height: abs_height - (border ? 2 : 0),
66
- ch: get_attribute('ch'),
67
- style: final_style
68
- )
69
- end
70
-
71
- # IMPORTANT: border is rendered in a +2 bigger rectangle that sourounds actual element bounds (abs_* methods)
72
- def render_border(screen)
73
- border ? screen.box(abs_x, abs_y, abs_width, abs_height, border.style, border_style) : ''
74
- end
75
-
76
- def render_text(screen)
77
- (render_text_lines.map.with_index do |line, i|
78
- screen.text(x: abs_content_x, y: abs_content_y + i, text: line, style: final_style)
79
- end).join('')
80
- end
81
-
82
- def render_children(screen)
83
- (@children.map do |c|
84
- c.render(screen)
85
- end).join('')
86
- end
87
-
88
- def render_text_lines(text = @text || '')
89
- text&.length ? (style.wrap ? wrap_text(text, abs_content_width) : text.split('\n')) : []
90
- end
91
-
92
- # can be used by text widgets like labels or buttons to automatically set preffered size according to its text
93
- def render_text_size(text = @text)
94
- lines = render_text_lines(text)
95
- width = lines.map(&:length).max
96
- height = lines.length
97
- { width: width, height: height }
98
- end
99
-
100
- def layout
101
- end
102
- end