ncumbra 0.1.0

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.
@@ -0,0 +1,220 @@
1
+ ##
2
+ # Basic widget class superclass. Anything embedded in a form should
3
+ # extend this, if it wants to be repainted or wants focus. Otherwise.
4
+ # form will be unaware of it.
5
+ # 2018-03-08 -
6
+ #require 'umbra/form' # for EventHandler !!!
7
+ require 'umbra/eventhandler' # for register_events and fire_handler etc
8
+ require 'umbra/keymappinghandler' # for bind_key and process_key
9
+
10
+ module Umbra
11
+ class FieldValidationException < RuntimeError
12
+ end
13
+ class Widget
14
+ include EventHandler
15
+ include KeyMappingHandler
16
+ # common interface for text related to a field, label, textview, button etc
17
+ attr_accessor :text, :width, :height
18
+
19
+ # foreground and background colors when focussed. Currently used with buttons and field
20
+ # Form checks and repaints on entry if these are set.
21
+ attr_accessor :highlight_color_pair
22
+ attr_accessor :highlight_attr
23
+
24
+ # NOTE: 2018-03-04 - user will have to call repaint_required if he changes color or coordinates.
25
+ attr_accessor :row, :col # location of object
26
+ #attr_writer :color, :bgcolor # normal foreground and background 2018-03-08 - now color_pair
27
+ # moved to a method which calculates color 2011-11-12
28
+ attr_accessor :color_pair # instead of colors give just color_pair
29
+ attr_accessor :attr # attribute bold, normal, reverse
30
+ attr_accessor :name # name to refr to or recall object by_name
31
+ attr_accessor :curpos # cursor position inside object - column, not row.
32
+ attr_reader :config # can be used for popping user objects too
33
+ #attr_accessor :form # made accessor 2008-11-27 22:32 so menu can set
34
+ attr_accessor :graphic # window which should be set by form when adding 2018-03-19
35
+ attr_accessor :state # normal, selected, highlighted
36
+ attr_reader :row_offset, :col_offset # where should the cursor be placed to start with
37
+ attr_accessor :visible # boolean # 2008-12-09 11:29
38
+ # if changing focusable property of a field after form creation, you may need to call
39
+ # pack again, or atl east update_focusables
40
+ attr_reader :focusable # boolean can this get focus # 2018-03-21 - 23:13
41
+ # 2018-03-04 - we should use modified as accessor unless it is due to setting forms modified
42
+ # 2018-03-22 - making it accessor
43
+ attr_accessor :modified # boolean, value modified or not (moved from field 2009-01-18 00:14 )
44
+ #attr_accessor :help_text # added 2009-01-22 17:41 can be used for status/tooltips
45
+
46
+ #attr_accessor :parent_component # added 2010-01-12 23:28 BUFFERED - to bubble up
47
+
48
+ # NOTE state takes care of this and is set by form. boolean
49
+ attr_reader :focussed # is this widget in focus, so they may paint differently
50
+
51
+ # height percent and width percent used in stacks and flows.
52
+ #attr_accessor :height_pc, :width_pc # may bring this back
53
+
54
+ # descriptions for each key set in _key_map
55
+ # 2018-03-07 - NOT_SURE
56
+ attr_reader :key_label
57
+ attr_reader :handler # event handler
58
+ # adding as attr_accessor 2018-03-22 -
59
+ # is a repaint required or not, boolean
60
+ attr_accessor :repaint_required
61
+
62
+ def initialize aconfig={}, &block
63
+ @row_offset ||= 0
64
+ @col_offset ||= 0
65
+ @state = :NORMAL
66
+
67
+ @handler = nil # we can avoid firing if nil
68
+ # These are standard events for most widgets which will be fired by
69
+ # Form. In the case of CHANGED, form fires if it's editable property is set, so
70
+ # it does not apply to all widgets.
71
+ # 2018-03-18 - proporty change is deprecated since we don't use dsl_property any longer
72
+ register_events( [:ENTER, :LEAVE, :CHANGED, :PROPERTY_CHANGE])
73
+ @repaint_required = true # added 2018-03-20 - so all widgets get it
74
+
75
+ aconfig.each_pair { |k,v| variable_set(k,v) }
76
+ #instance_eval &block if block_given?
77
+ if block_given?
78
+ if block.arity > 0
79
+ yield self
80
+ else
81
+ self.instance_eval(&block)
82
+ end
83
+ end
84
+ end
85
+
86
+ def variable_set var, val
87
+ send("#{var}=", val)
88
+ end
89
+ def init_vars
90
+ # just in case anyone does a super. Not putting anything here
91
+ # since i don't want anyone accidentally overriding
92
+ end
93
+
94
+ # modified
95
+ ##
96
+ # typically read will be overridden to check if value changed from what it was on enter.
97
+ # getter and setter for modified (added 2009-01-18 12:31 )
98
+ def modified?
99
+ @modified
100
+ end
101
+ #def set_modified tf=true
102
+ #@modified = tf
103
+ #end
104
+ #alias :modified :set_modified
105
+
106
+ # triggered whenever a widget is entered.
107
+ # TODO should we not fix cursor at this point ?
108
+ def on_enter
109
+ @state = :HIGHLIGHTED # duplicating since often these are inside containers
110
+ @focussed = true
111
+ if @handler && @handler.has_key?(:ENTER)
112
+ fire_handler :ENTER, self
113
+ end
114
+ end
115
+ ## Called when user exits a widget
116
+ # 2018-03-04 - Are we keeping this at all, can we avoid NOT_SURE
117
+ def on_leave
118
+ @state = :NORMAL # duplicating since often these are inside containers
119
+ @focussed = false
120
+ if @handler && @handler.has_key?(:LEAVE)
121
+ fire_handler :LEAVE, self
122
+ end
123
+ end
124
+ ##
125
+ # @return row and col of a widget where painting data actually starts
126
+ # row and col is where a widget starts. offsets usually take into account borders.
127
+ # the offsets typically are where the cursor should be positioned inside, upon on_enter.
128
+ def rowcol
129
+ return @row+@row_offset, @col+@col_offset
130
+ end
131
+ ## return the value of the widget.
132
+ def getvalue
133
+ @text
134
+ end
135
+ ##
136
+ # Am making a separate method since often value for print differs from actual value
137
+ def getvalue_for_paint
138
+ getvalue
139
+ end
140
+ ##
141
+ # default repaint method. Called by form for all widgets.
142
+ # widget does not have display_length.
143
+ def repaint
144
+ r,c = rowcol
145
+ $log.debug("widget repaint : r:#{r} c:#{c} col:#{@color_pair}" )
146
+ value = getvalue_for_paint
147
+ len = @width || value.length
148
+ acolor = @color_pair
149
+ @graphic.printstring r, c, "%-*s" % [len, value], acolor, attr()
150
+ end
151
+
152
+ def destroy
153
+ $log.debug "DESTROY : widget #{@name} "
154
+ panel = @window.panel
155
+ Ncurses::Panel.del_panel(panel.pointer) if !panel.nil?
156
+ @window.delwin if !@window.nil?
157
+ end
158
+
159
+ # puts cursor on correct row.
160
+ def set_form_row
161
+ raise "uncalled set_form_row"
162
+ r, c = rowcol
163
+ setrowcol row, nil # does not exist any longer
164
+ end
165
+ # set cursor on correct column, widget
166
+ # Ideally, this should be overriden, as it is not likely to be correct.
167
+ # NOTE: this is okay for some widgets but NOT for containers
168
+ # that will call their own components SFR and SFC
169
+ #Currently, Field has overriden this. +setrowcol+ does not exist any longer.
170
+ def set_form_col col1=@curpos
171
+ @curpos = col1 || 0 # 2010-01-14 21:02
172
+ #@form.col = @col + @col_offset + @curpos
173
+ c = @col + @col_offset + @curpos
174
+ #$log.warn " #{@name} empty set_form_col #{c}, curpos #{@curpos} , #{@col} + #{@col_offset} #{@form} "
175
+ setrowcol nil, c
176
+ end
177
+
178
+ ##
179
+ # to be added at end of handle_key of widgets so instlalled actions can be checked
180
+ def handle_key(ch)
181
+ ret = process_key ch, self
182
+ return :UNHANDLED if ret == :UNHANDLED
183
+ 0
184
+ end
185
+
186
+ # is the entire widget to be repainted including things like borders and titles
187
+ # earlier took a default of true, now must be explicit. Perhaps, not used currently.
188
+ def repaint_all(tf)
189
+ @repaint_all = tf
190
+ @repaint_required = tf
191
+ end
192
+ # shortcut for users to indicate that a widget should be redrawn since some property has been changed.
193
+ def touch
194
+ @repaint_required = true
195
+ end
196
+
197
+
198
+ # a general method for all widgets to override with their favorite or most meaninful event
199
+ # Ideally this is where the block in the constructor should land up.
200
+ # @since 1.5.0 2011-11-21
201
+ # 2018-03-08 - NOT_SURE
202
+ def command *args, &block
203
+ if event? :PRESS
204
+ bind_event :PRESS, *args, &block
205
+ else
206
+ bind_event :CHANGED, *args, &block
207
+ end
208
+ end
209
+ def _form=(aform)
210
+ @_form = aform
211
+ end
212
+ def focusable=(bool)
213
+ $log.debug " inside focusable= with #{bool} "
214
+ @focusable = bool
215
+ @_form.update_focusables if @_form
216
+ end
217
+ #
218
+ ## ADD HERE WIDGET
219
+ end #
220
+ end # module
@@ -0,0 +1,270 @@
1
+ require 'ffi-ncurses'
2
+ require 'ffi-ncurses/widechars'
3
+
4
+ module Umbra
5
+
6
+ # attribute constants, use them to specify an attrib for a widget or window.
7
+ BOLD = FFI::NCurses::A_BOLD
8
+ REVERSE = FFI::NCurses::A_REVERSE
9
+ UNDERLINE = FFI::NCurses::A_UNDERLINE
10
+ NORMAL = FFI::NCurses::A_NORMAL
11
+
12
+ # color constants, use these when creating a color
13
+ COLOR_BLACK = FFI::NCurses::BLACK
14
+ COLOR_WHITE = FFI::NCurses::WHITE
15
+ COLOR_BLUE = FFI::NCurses::BLUE
16
+ COLOR_RED = FFI::NCurses::RED
17
+ COLOR_GREEN = FFI::NCurses::GREEN
18
+ COLOR_CYAN = FFI::NCurses::CYAN
19
+ COLOR_MAGENTA = FFI::NCurses::MAGENTA
20
+
21
+ # Initialize ncurses before any program.
22
+ # Reduce the value of $ncurses_timeout if you want a quicker response to Escape keys or continuous updates.
23
+ # I have set the default to 1000.
24
+ def init_curses
25
+ FFI::NCurses.initscr
26
+ FFI::NCurses.curs_set 1
27
+ FFI::NCurses.raw
28
+ FFI::NCurses.noecho
29
+ FFI::NCurses.keypad FFI::NCurses.stdscr, true
30
+ FFI::NCurses.scrollok FFI::NCurses.stdscr, true
31
+ if FFI::NCurses.has_colors
32
+ FFI::NCurses.start_color
33
+ std_colors
34
+ end
35
+
36
+ end
37
+
38
+ # COLOR_BLACK 0
39
+ # COLOR_RED 1
40
+ # COLOR_GREEN 2
41
+ # COLOR_YELLOW 3
42
+ # COLOR_BLUE 4
43
+ # COLOR_MAGENTA 5
44
+ # COLOR_CYAN 6
45
+ # COLOR_WHITE 7
46
+
47
+ # In case, the init_pairs are changed, then update these as well, so that the programs use the correct pairs.
48
+ CP_BLACK = 0
49
+ CP_RED = 1
50
+ CP_GREEN = 2
51
+ CP_YELLOW = 3
52
+ CP_BLUE = 4
53
+ CP_MAGENTA = 5
54
+ CP_CYAN = 6
55
+ CP_WHITE = 7
56
+ # defining various colors
57
+ # NOTE this should be done by application or else we will be changing this all the time.
58
+ def std_colors
59
+ FFI::NCurses.use_default_colors
60
+ # 2018-03-17 - changing it to ncurses defaults
61
+ FFI::NCurses.init_pair(0, FFI::NCurses::BLACK, -1)
62
+ FFI::NCurses.init_pair(1, FFI::NCurses::RED, -1)
63
+ FFI::NCurses.init_pair(2, FFI::NCurses::GREEN, -1)
64
+ FFI::NCurses.init_pair(3, FFI::NCurses::YELLOW, -1)
65
+ FFI::NCurses.init_pair(4, FFI::NCurses::BLUE, -1)
66
+ FFI::NCurses.init_pair(5, FFI::NCurses::MAGENTA, -1)
67
+ FFI::NCurses.init_pair(6, FFI::NCurses::CYAN, -1)
68
+ FFI::NCurses.init_pair(7, FFI::NCurses::WHITE, -1)
69
+ # ideally the rest should be done by application
70
+ #FFI::NCurses.init_pair(8, FFI::NCurses::WHITE, -1)
71
+ #FFI::NCurses.init_pair(9, FFI::NCurses::BLUE, -1)
72
+ FFI::NCurses.init_pair(10, FFI::NCurses::BLACK, FFI::NCurses::CYAN)
73
+ FFI::NCurses.init_pair(12, FFI::NCurses::BLACK, FFI::NCurses::BLUE)
74
+ FFI::NCurses.init_pair(13, FFI::NCurses::BLACK, FFI::NCurses::MAGENTA)
75
+
76
+ FFI::NCurses.init_pair(14, FFI::NCurses::WHITE, FFI::NCurses::CYAN)
77
+ =begin
78
+ FFI::NCurses.init_pair(8, FFI::NCurses::WHITE, FFI::NCurses::BLUE)
79
+ FFI::NCurses.init_pair(9, FFI::NCurses::BLUE, FFI::NCurses::BLUE)
80
+ FFI::NCurses.init_pair(10, FFI::NCurses::BLACK, FFI::NCurses::GREEN)
81
+ FFI::NCurses.init_pair(11, FFI::NCurses::BLACK, FFI::NCurses::YELLOW)
82
+ FFI::NCurses.init_pair(12, FFI::NCurses::BLACK, FFI::NCurses::BLUE)
83
+ FFI::NCurses.init_pair(13, FFI::NCurses::BLACK, FFI::NCurses::MAGENTA)
84
+ FFI::NCurses.init_pair(14, FFI::NCurses::BLACK, FFI::NCurses::CYAN)
85
+ FFI::NCurses.init_pair(15, FFI::NCurses::BLACK, FFI::NCurses::WHITE)
86
+ =end
87
+ end
88
+
89
+ # create and return a color_pair for a combination of bg and fg.
90
+ # This will always return the same color_pair so a duplicate one will not be created.
91
+ # @param bgcolor [Integer] color of background e.g., COLOR_BLACK
92
+ # @param fgcolor [Integer] color of foreground e.g., COLOR_WHITE
93
+ # @return [Integer] - color_pair which can be passed to #printstring, or used directly as #COLOR_PAIR(int)
94
+ def create_color_pair(bgcolor, fgcolor)
95
+ code = (bgcolor*10) + fgcolor
96
+ FFI::NCurses.init_pair(code, fgcolor, bgcolor)
97
+ return code
98
+ end
99
+ #
100
+ ## Window class
101
+ # Creates and manages the underlying window in which we write or place a form and fields.
102
+ # The two important methods here are the constructor, and +destroy()+.
103
+ # +pointer+ is important for making further direct calls to FFI::NCurses.
104
+ class Window
105
+ # pointer to FFI routines, use when calling FFI directly.
106
+ attr_reader :pointer # window pointer
107
+ attr_reader :panel # panel associated with window
108
+ attr_reader :width, :height, :top, :left
109
+
110
+ # creates a window with given height, width, top and left.
111
+ # If no args given, creates a root window (i.e. full size).
112
+ # @param height [Integer]
113
+ # @param width [Integer]
114
+ # @param top [Integer]
115
+ # @param left [Integer]
116
+ def initialize h=0, w=0, top=0, left=0
117
+ @height, @width, @top, @left = h, w, top, left
118
+
119
+ @height = FFI::NCurses.LINES if @height == 0 # 2011-11-14 added since tired of checking for zero
120
+ @width = FFI::NCurses.COLS if @width == 0
121
+ @pointer = FFI::NCurses.newwin(@height, @width, @top, @left) # added FFI 2011-09-6
122
+
123
+ @panel = FFI::NCurses.new_panel(@pointer)
124
+ FFI::NCurses.keypad(@pointer, true)
125
+ return @pointer
126
+ end
127
+
128
+ # print string at x, y coordinates. replace this with the original one below
129
+ # @deprecated
130
+ def printstr(str, x=0,y=0)
131
+ win = @pointer
132
+ FFI::NCurses.wmove(win, x, y)
133
+ FFI::NCurses.waddstr win, str
134
+ end
135
+
136
+ # 2018-03-08 - taken from canis reduced
137
+ # print given string at row, col with given color and attributes
138
+ # @param row [Integer] row to print on
139
+ # @param col [Integer] column to print on
140
+ # @param color [Integer] color_pair created earlier
141
+ # @param attr [Integer] any of the four FFI attributes, e.g. A_BOLD, A_REVERSE
142
+ def printstring(r,c,string, color=0, att = FFI::NCurses::A_NORMAL)
143
+
144
+ #$log.debug "printstring recvd nil row #{r} or col #{c}, color:#{color},att:#{att}." if $log
145
+ raise "printstring recvd nil row #{r} or col #{c}, color:#{color},att:#{att} " if r.nil? || c.nil?
146
+ att ||= FFI::NCurses::A_NORMAL
147
+ color ||= 0
148
+ raise "color is nil " unless color
149
+ raise "att is nil " unless att
150
+
151
+ FFI::NCurses.wattron(@pointer, FFI::NCurses.COLOR_PAIR(color) | att)
152
+ FFI::NCurses.mvwprintw(@pointer, r, c, "%s", :string, string);
153
+ FFI::NCurses.wattroff(@pointer, FFI::NCurses.COLOR_PAIR(color) | att)
154
+ end
155
+ ##
156
+ # Get a key from the standard input.
157
+ #
158
+ # This will get control keys and function keys but not Alt keys.
159
+ # This is usually called in a loop by the main program.
160
+ # It returns the ascii code (integer).
161
+ # 1 is Ctrl-a .... 27 is Esc
162
+ # FFI already has constants declared for function keys and control keys for checkin against.
163
+ # Can return a 3 or -1 if user pressed Control-C.
164
+ #
165
+ # NOTE: For ALT keys we need to check for 27/Esc and if so, then do another read
166
+ # with a timeout. If we get a key, then resolve. Otherwise, it is just ESC
167
+ # NOTE: this was working fine with nodelay. However, that would not allow an app to continuously
168
+ # update the screen, as the getch was blocked. wtimeout allows screen to update without a key
169
+ # being pressed. 2018-04-07
170
+ # @return [Integer] ascii code of key. For undefined keys, returns a String representation.
171
+ def getch
172
+ FFI::NCurses.wtimeout(@pointer, $ncurses_timeout || 1000)
173
+ c = FFI::NCurses.wgetch(@pointer)
174
+ if c == 27
175
+
176
+ # don't wait for another key
177
+ FFI::NCurses.nodelay(@pointer, true)
178
+ k = FFI::NCurses.wgetch(@pointer)
179
+ if k == -1
180
+ # wait for key
181
+ #FFI::NCurses.nodelay(@pointer, false)
182
+ return 27
183
+ else
184
+ buf = ""
185
+ loop do
186
+ n = FFI::NCurses.wgetch(@pointer)
187
+ break if n == -1
188
+ buf += n.chr
189
+ end
190
+ # wait for next key
191
+ #FFI::NCurses.nodelay(@pointer, false)
192
+
193
+ # this works for all alt-keys but it messes with shift-function keys
194
+ # shift-function keys start with M-[ (91) and then have more keys
195
+ if buf == ""
196
+ return k + 128
197
+ end
198
+ #$log.debug " getch buf is #{k.chr}#{buf} "
199
+ # returning a string key here which is for Shift-Function keys or other undefined keys.
200
+ key = 27.chr + k.chr + buf
201
+ return key
202
+
203
+ end
204
+ end
205
+ #FFI::NCurses.nodelay(@pointer, false) # this works but trying out for continueous updates
206
+ c
207
+ rescue SystemExit, Interrupt
208
+ 3 # is C-c
209
+ rescue StandardError
210
+ -1 # is C-c
211
+ end
212
+
213
+ # this works fine for basic, control and function keys
214
+ def OLDgetch
215
+ c = FFI::NCurses.wgetch(@pointer)
216
+ rescue SystemExit, Interrupt
217
+ 3 # is C-c
218
+ rescue StandardError
219
+ -1 # is C-c
220
+ end
221
+ alias :getkey :getch
222
+
223
+ # refresh the window (wrapper)
224
+ # To be called after printing on a window.
225
+ def wrefresh
226
+ FFI::NCurses.wrefresh(@pointer)
227
+ end
228
+ # destroy the window and the panel.
229
+ # This is important. It should be placed in the ensure block of caller application, so it happens.
230
+ def destroy
231
+ FFI::NCurses.del_panel(@panel) if @panel
232
+ FFI::NCurses.delwin(@pointer) if @pointer
233
+ @panel = @pointer = nil # prevent call twice
234
+ end
235
+ # route other methods to ffi. {{{
236
+ # This should preferable NOT be used. Better to use the direct call itself.
237
+ # It attempts to route other calls to FFI::NCurses by trying to add w to the name and passing the pointer.
238
+ # I would like to remove this at some time.
239
+ def method_missing(name, *args)
240
+ name = name.to_s
241
+ if (name[0,2] == "mv")
242
+ test_name = name.dup
243
+ test_name[2,0] = "w" # insert "w" after"mv"
244
+ if (FFI::NCurses.respond_to?(test_name))
245
+ return FFI::NCurses.send(test_name, @pointer, *args)
246
+ end
247
+ end
248
+ test_name = "w" + name
249
+ if (FFI::NCurses.respond_to?(test_name))
250
+ return FFI::NCurses.send(test_name, @pointer, *args)
251
+ end
252
+ FFI::NCurses.send(name, @pointer, *args)
253
+ end # }}}
254
+ # make a box around the window. Just a wrapper
255
+ def box
256
+ FFI::NCurses.box(@pointer, 0, 0)
257
+ end
258
+ # print a centered title on top of window
259
+ # This should be called after box, or else box will erase the title
260
+ # @param str [String] title to print
261
+ # @param color [Integer] color_pair
262
+ # @param att [Integer] attribute constant
263
+ def title str, color=0, att=BOLD
264
+ strl = str.length
265
+ col = (@width - strl)/2
266
+ printstring(0,col, str, color, att)
267
+ end
268
+
269
+ end # window
270
+ end # module
data/lib/umbra.rb ADDED
@@ -0,0 +1,47 @@
1
+ require "umbra/version"
2
+ #require 'ffi-ncurses'
3
+ require "umbra/window"
4
+ require "umbra/form"
5
+
6
+ module Umbra
7
+ def alert str, config={}
8
+ require 'umbra/dialog'
9
+ #title = config[:title] || "Alert"
10
+ #cp = config[:color_pair] || create_color_pair( COLOR_BLUE, COLOR_WHITE )
11
+ #attr = config[:attrib] || NORMAL
12
+
13
+ config[:text] ||= str
14
+ config[:title] ||= "Alert"
15
+ config[:window_color_pair] ||= create_color_pair( COLOR_BLUE, COLOR_WHITE )
16
+ config[:window_attr] ||= NORMAL
17
+ config[:buttons] ||= ["Ok"]
18
+
19
+ #m = Dialog.new text: str, title: title, window_color_pair: cp, window_attr: attr
20
+ m = Dialog.new config
21
+ m.run
22
+ end
23
+ # confirmation dialog which prompts message with Ok and Cancel and returns true or false.
24
+ def confirm str, config={}
25
+ require 'umbra/dialog'
26
+
27
+ config[:text] ||= str
28
+ config[:title] ||= "Confirm"
29
+ config[:window_color_pair] ||= create_color_pair( COLOR_BLUE, COLOR_WHITE )
30
+ config[:window_attr] ||= NORMAL
31
+ config[:buttons] ||= ["Ok", "Cancel"]
32
+
33
+ m = Dialog.new config
34
+ ret = m.run
35
+ return ret == 0
36
+ end
37
+
38
+ # view an array in a popup window
39
+ def view array, config={}
40
+ require 'umbra/pad'
41
+ title = config[:title] || "Viewer"
42
+ cp = config[:color_pair] || create_color_pair( COLOR_BLUE, COLOR_WHITE )
43
+ attr = config[:attrib] || NORMAL
44
+ m = Pad.new list: array, height: FFI::NCurses.LINES-2, width: FFI::NCurses.COLS-10, title: title, color_pair: cp, attrib: attr
45
+ m.run
46
+ end
47
+ end
data/umbra.gemspec ADDED
@@ -0,0 +1,27 @@
1
+
2
+ lib = File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require "umbra/version"
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "ncumbra"
8
+ spec.version = Umbra::VERSION
9
+ spec.authors = ["kepler"]
10
+ spec.email = ["githubkepler.50s@gishpuppy.com"]
11
+
12
+ spec.summary = %q{tiny ncurses library for creating simple apps}
13
+ spec.description = %q{minimal, provides forms and a few basic widgets}
14
+ spec.homepage = "https://github.com/mare-imbrium/umbra"
15
+ spec.license = "MIT"
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.16"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_runtime_dependency "ffi-ncurses", ">= 0.4.0", ">= 0.4.0"
27
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ncumbra
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - kepler
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2018-04-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.16'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.16'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: ffi-ncurses
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: 0.4.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 0.4.0
55
+ description: minimal, provides forms and a few basic widgets
56
+ email:
57
+ - githubkepler.50s@gishpuppy.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".gitignore"
63
+ - Gemfile
64
+ - LICENSE
65
+ - README.md
66
+ - README.md.bak
67
+ - Rakefile
68
+ - bin/console
69
+ - bin/setup
70
+ - examples/ex1.rb
71
+ - examples/ex2.rb
72
+ - examples/ex21.rb
73
+ - examples/ex3.rb
74
+ - examples/ex4.rb
75
+ - examples/ex5.rb
76
+ - examples/exbox.rb
77
+ - examples/exm1.rb
78
+ - examples/keys.rb
79
+ - examples/tt.rb
80
+ - lib/umbra.rb
81
+ - lib/umbra/box.rb
82
+ - lib/umbra/button.rb
83
+ - lib/umbra/buttongroup.rb
84
+ - lib/umbra/checkbox.rb
85
+ - lib/umbra/dialog.rb
86
+ - lib/umbra/eventhandler.rb
87
+ - lib/umbra/field.rb
88
+ - lib/umbra/form.rb
89
+ - lib/umbra/keymappinghandler.rb
90
+ - lib/umbra/label.rb
91
+ - lib/umbra/labeledfield.rb
92
+ - lib/umbra/listbox.rb
93
+ - lib/umbra/menu.rb
94
+ - lib/umbra/messagebox.rb
95
+ - lib/umbra/pad.rb
96
+ - lib/umbra/radiobutton.rb
97
+ - lib/umbra/textbox.rb
98
+ - lib/umbra/togglebutton.rb
99
+ - lib/umbra/version.rb
100
+ - lib/umbra/widget.rb
101
+ - lib/umbra/window.rb
102
+ - umbra.gemspec
103
+ homepage: https://github.com/mare-imbrium/umbra
104
+ licenses:
105
+ - MIT
106
+ metadata: {}
107
+ post_install_message:
108
+ rdoc_options: []
109
+ require_paths:
110
+ - lib
111
+ required_ruby_version: !ruby/object:Gem::Requirement
112
+ requirements:
113
+ - - ">="
114
+ - !ruby/object:Gem::Version
115
+ version: '0'
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ">="
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 2.7.6
124
+ signing_key:
125
+ specification_version: 4
126
+ summary: tiny ncurses library for creating simple apps
127
+ test_files: []