Module: RETerm
- Defined in:
- lib/reterm.rb,
lib/reterm/init.rb,
lib/reterm/util.rb,
lib/reterm/panel.rb,
lib/reterm/config.rb,
lib/reterm/layout.rb,
lib/reterm/loader.rb,
lib/reterm/resize.rb,
lib/reterm/window.rb,
lib/reterm/layouts.rb,
lib/reterm/version.rb,
lib/reterm/terminal.rb,
lib/reterm/component.rb,
lib/reterm/color_pair.rb,
lib/reterm/components.rb,
lib/reterm/layouts/grid.rb,
lib/reterm/components/dial.rb,
lib/reterm/components/entry.rb,
lib/reterm/components/image.rb,
lib/reterm/components/label.rb,
lib/reterm/components/radio.rb,
lib/reterm/layouts/vertical.rb,
lib/reterm/mixins/nav_input.rb,
lib/reterm/components/button.rb,
lib/reterm/components/dialog.rb,
lib/reterm/components/matrix.rb,
lib/reterm/components/rocker.rb,
lib/reterm/components/splash.rb,
lib/reterm/components/hslider.rb,
lib/reterm/components/vslider.rb,
lib/reterm/components/youtube.rb,
lib/reterm/layouts/horizontal.rb,
lib/reterm/mixins/common_keys.rb,
lib/reterm/mixins/log_helpers.rb,
lib/reterm/mixins/mouse_input.rb,
lib/reterm/components/template.rb,
lib/reterm/mixins/item_helpers.rb,
lib/reterm/mixins/key_bindings.rb,
lib/reterm/mixins/nav_controls.rb,
lib/reterm/components/alphalist.rb,
lib/reterm/components/histogram.rb,
lib/reterm/components/isometric.rb,
lib/reterm/mixins/cdk_component.rb,
lib/reterm/components/ascii_text.rb,
lib/reterm/components/button_box.rb,
lib/reterm/components/cmd_output.rb,
lib/reterm/mixins/button_helpers.rb,
lib/reterm/components/scroll_list.rb,
lib/reterm/components/select_list.rb,
lib/reterm/mixins/common_controls.rb,
lib/reterm/mixins/component_input.rb,
lib/reterm/components/close_button.rb,
lib/reterm/mixins/event_dispatcher.rb,
lib/reterm/components/drop_down_menu.rb,
lib/reterm/components/password_entry.rb,
lib/reterm/components/scrolling_area.rb,
lib/reterm/components/revealing_label.rb,
lib/reterm/components/multi_line_entry.rb
Overview
The Ruby Enhanced Terminal interactive framework facilitating dynmaic/feature rich terminal applications.
Defined Under Namespace
Modules: ButtonHelpers, CDKComponent, CommonControls, CommonKeys, ComponentInput, Components, EventDispatcher, ItemHelpers, KeyBindings, Layouts, LogHelpers, MouseInput, NavControls, NavInput Classes: ColorPair, Component, Config, Layout, Loader, Panel, Terminal, Window
Constant Summary collapse
- SYNC_TIMEOUT =
in milliseconds if enabled
150
- NC =
XXX Ncurses is exposed so that users may employ any constants if desired. This should not be needed though and is discouraged to maintain portability
Ncurses
- ANSI_COLORS =
{ 1 => :bold, 30 => :black, 31 => :red, 32 => :green, 33 => :yellow, 34 => :blue, 35 => :magenta, 36 => :cyan, 37 => :white, # XXX techincally the 'bright' variations 90 => :black, 91 => :red, 92 => :green, 93 => :yellow, 94 => :blue, 95 => :magenta, 96 => :cyan, 97 => :white, }
- RESIZE_TIME =
Seconds between terminal size syncs
0.2
- VERSION =
"0.6.3"
Instance Method Summary collapse
-
#activate_sync! ⇒ Object
Enables the input timeout and component syncronization.
-
#cdk_enabled? ⇒ Boolean
Return boolean indicating if the CDK subsystem is enabled.
-
#cursor? ⇒ Boolean
Cursor.
- #disable_cursor! ⇒ Object
-
#enable_cdk! ⇒ Object
Enable the CDK subsystem.
- #enable_cursor! ⇒ Object
-
#file_append(f, t) ⇒ Object
Helper appending string to debug file.
-
#flush_input ⇒ Object
Flushes all input queues.
-
#init_reterm(opts = {}, &bl) ⇒ Object
Initializes the RETerm subsystem before invoking block.
-
#load_reterm(str) ⇒ Object
class Loader.
-
#on_resize(&bl) ⇒ Object
Set the global callback to be invoked on resize.
-
#parse_ansi(str) ⇒ Object
Converts specified ansi string to array of character data & corresponding control logic.
-
#process_alive?(pid) ⇒ Boolean
Helper returning boolean indicating if specified process is alive.
-
#reterm_opts ⇒ Object
Return copy of options specified to init_reterm.
-
#run_sync! ⇒ Object
Run the sync process, used internally.
-
#shutdown! ⇒ Object
Use to halt all operation and cleanup.
-
#shutdown? ⇒ Boolean
Boolean indicating if app in being halted.
-
#stop_track_resize ⇒ Object
Terminate resize tracking thread (if running).
-
#sync_enabled? ⇒ Boolean
Boonean indicating if component syncronization is enabled.
-
#track_resize ⇒ Object
Internal helper to track size of terminal.
-
#update_reterm(force_refresh = false) ⇒ Object
This method resyncs the visible terminal with the internal RETerm environment.
Instance Method Details
#activate_sync! ⇒ Object
Enables the input timeout and component syncronization.
Used internally by components that need to periodically be updated outside of user input.
186 187 188 189 190 191 |
# File 'lib/reterm/init.rb', line 186 def activate_sync! @@sync_activated = true Window.all.each { |w| w.win.timeout(SYNC_TIMEOUT) } end |
#cdk_enabled? ⇒ Boolean
Return boolean indicating if the CDK subsystem is enabled. CDK is a library used by various components providing many various ready to use ncurses widgets.
176 177 178 |
# File 'lib/reterm/init.rb', line 176 def cdk_enabled? !!@cdk_enabled end |
#cursor? ⇒ Boolean
Cursor
118 119 120 |
# File 'lib/reterm/init.rb', line 118 def cursor? !(@@cursor_disabled ||= false) end |
#disable_cursor! ⇒ Object
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 |
# File 'lib/reterm/init.rb', line 122 def disable_cursor! # store cursor state o = cursor? # set cursor state @@cursor_disabled = true Ncurses::curs_set(0) # invoke block if given return unless block_given? yield # restore cursor state after block enable_cursor! if o end |
#enable_cdk! ⇒ Object
Enable the CDK subsystem. Used by CDKbased components
160 161 162 163 164 165 166 167 168 169 170 171 |
# File 'lib/reterm/init.rb', line 160 def enable_cdk! return if @cdk_enabled @cdk_enabled = true require 'cdk' # XXX defines standard color pairs, but we use our own # for standarization across components, but we need # to set cdk components to the correct color scheme # manually # CDK::Draw.initCDKColor end |
#enable_cursor! ⇒ Object
138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/reterm/init.rb', line 138 def enable_cursor! # store cursor state o = cursor? # set cursor state @@cursor_disabled = false Ncurses::curs_set(1) # invoke block if given return unless block_given? yield # restore cursor state after block disable_cursor! unless o end |
#file_append(f, t) ⇒ Object
Helper appending string to debug file
113 114 115 |
# File 'lib/reterm/util.rb', line 113 def file_append(f, t) File.open(f, "a") { |f| f.write t } end |
#flush_input ⇒ Object
Flushes all input queues
118 119 120 |
# File 'lib/reterm/util.rb', line 118 def flush_input Ncurses.flushinp end |
#init_reterm(opts = {}, &bl) ⇒ Object
Initializes the RETerm subsystem before invoking block. After block is finished regardless of execution state (return, exception, etc) this will cleanup the terminal environment before returning control to the TTY.
This method is the first method the user should invoke after requiring the reterm library.
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/reterm/init.rb', line 23 def init_reterm(opts={}, &bl) @@shutdown = false @@reterm_opts = opts err = nil min = opts[:min_size] begin # XXX: must load terminal info before changing terminal settings # (else causes crash... not sure why) # But we also check min dimensions here Terminal.load(min) # shorten up the esc delay time ENV["ESCDELAY"] = 100.to_s stdscr = Ncurses::initscr initialized = true Ncurses::start_color Ncurses::noecho Ncurses::cbreak disable_cursor! unless !!opts[:cursor] Ncurses::keypad(stdscr, true) no_mouse = opts[:nomouse] || (opts.key?(:mouse) && !opts[:mouse]) Ncurses::mousemask(MouseInput::ALL_EVENTS, []) unless no_mouse track_resize if opts[:resize] bl.call rescue => e err = e ensure stop_track_resize Ncurses.curs_set(1) if !!initialized Window.top.each { |w| w.finalize! } CDK::SCREEN.endCDK if cdk_enabled? Ncurses.endwin if !!initialized #`reset -Q` # XXX only way to guarantee a full reset (see above) end if err puts "Unhandled error:" puts " " + err.to_s puts err.backtrace .collect { |b| " " + b }.join("\n") end end |
#load_reterm(str) ⇒ Object
class Loader
123 124 125 |
# File 'lib/reterm/loader.rb', line 123 def load_reterm(str) Loader.new(str).window end |
#on_resize(&bl) ⇒ Object
Set the global callback to be invoked on resize
6 7 8 |
# File 'lib/reterm/resize.rb', line 6 def on_resize(&bl) @on_resize = bl end |
#parse_ansi(str) ⇒ Object
Converts specified ansi string to array of character data & corresponding control logic
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/reterm/util.rb', line 37 def parse_ansi(str) require 'strscan' r = [] f = [] t = [] a = nil s = StringScanner.new(str) while(!s.eos?) # end of formatting if s.scan(/(\e|\[)\[0m/) t << f.pop t.compact! if f.empty? r << [a, t] t = [] a = nil end # basic formatter elsif s.scan(/\e\[(3[0-7]|90|1)m/) # FIXME need to register formatting for 'a' # up to this point (and reset 'a') (and below) f << ANSI_COLORS[s[1].to_i] # sgr # https://en.wikipedia.org/wiki/ANSI_escape_code#SGR_(Select_Graphic_Rendition)_parameters elsif s.scan(/\e\[(([0-9]+;?)+)m/) sgr = s[1].split(";").collect { |s| s.to_i } f << if (30..37).include?(sgr[0]) ANSI_COLORS[sgr[1]] elsif sgr[0] == 38 if sgr[1] == 5 if sgr[2] < 8 ANSI_COLORS[sgr[2]] elsif sgr[2] < 16 ANSI_COLORS[sgr[2]] elsif sgr[2] < 232 # TODO verify: # https://stackoverflow.com/questions/12338015/converting-8-bit-color-into-rgb-value re = (sgr[2] >> 5) * 32 gr = ((sgr[2] & 28) >> 2) * 32 bl = (sgr[2] & 3) * 64 [re, gr, bl] else # if srg[2] < 256 # TODO end else # if sgr[1] == 2 # TODO end # TODO other sgr commands end else a = "" if a.nil? a += s.scan(/./m) end end # handle remaining / lingering data r << [a, (t + f).compact] unless f.empty? r end |
#process_alive?(pid) ⇒ Boolean
Helper returning boolean indicating if specified process is alive
3 4 5 6 7 8 9 10 |
# File 'lib/reterm/util.rb', line 3 def process_alive?(pid) begin Process.getpgid( pid ) true rescue Errno::ESRCH false end end |
#reterm_opts ⇒ Object
Return copy of options specified to init_reterm
104 105 106 |
# File 'lib/reterm/init.rb', line 104 def reterm_opts @@_reterm_opts ||= Hash[@@reterm_opts] end |
#run_sync! ⇒ Object
Run the sync process, used internally
200 201 202 203 204 205 206 207 208 |
# File 'lib/reterm/init.rb', line 200 def run_sync! return unless sync_enabled? Window.all.each { |w| w.sync! } update_reterm end |
#shutdown! ⇒ Object
Use to halt all operation and cleanup.
213 214 215 |
# File 'lib/reterm/init.rb', line 213 def shutdown! @@shutdown = true end |
#shutdown? ⇒ Boolean
Boolean indicating if app in being halted
218 219 220 |
# File 'lib/reterm/init.rb', line 218 def shutdown? !!@@shutdown end |
#stop_track_resize ⇒ Object
Terminate resize tracking thread (if running)
34 35 36 37 |
# File 'lib/reterm/resize.rb', line 34 def stop_track_resize @track_resize = false @resize_thread.join if @resize_thread end |
#sync_enabled? ⇒ Boolean
Boonean indicating if component syncronization is enabled
195 196 197 |
# File 'lib/reterm/init.rb', line 195 def sync_enabled? defined?(@@sync_activated) && !!@@sync_activated end |
#track_resize ⇒ Object
Internal helper to track size of terminal. This is a simple mechanism that launches a worker thread to periodically poll terminal size.
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
# File 'lib/reterm/resize.rb', line 13 def track_resize @track_resize = true d = Terminal.dimensions @resize_thread = Thread.new { while @track_resize Terminal.reset! t = Terminal.dimensions if t != d && !shutdown? Terminal.resize! @on_resize.call if !!@on_resize end d = Terminal.dimensions sleep(RESIZE_TIME) end } end |
#update_reterm(force_refresh = false) ⇒ Object
This method resyncs the visible terminal with the internal RETerm environment. It should be called any time the user needs to update the UI after making changes.
89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/reterm/init.rb', line 89 def update_reterm(force_refresh=false) if force_refresh Window.top.each { |w| w.erase w.draw! } else Window.top.each { |w| w.noutrefresh } end #Ncurses::Panel.update_panels Ncurses.doupdate end |