ncumbra 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []