class LineDisplay
Constants
- DEFAULTS
- ISNUM
Attributes
col_headers[RW]
col_offsets[RW]
hide_ignored[RW]
prompt_line[R]
sizes[R]
widths[RW]
Public Class Methods
new(data, args = {})
click to toggle source
# File lib/cless/display.rb, line 150 def initialize(data, args = {}) DEFAULTS.each { |k, v| self.send("#{k}=", args[k].nil? ? v : args[k]) } @data = data @col_hide = [] @align = [] # column alignment: nil (i.e. auto), :left, :right, :center @widths = [] # max column widths @col_offsets = [] # offsets for large columns @col_headers = nil # Actual names @col_off = 0 @st_col = 0 @args = args end
Public Instance Methods
attr_names()
click to toggle source
# File lib/cless/display.rb, line 178 def attr_names; @attr.names; end
col_align(align, cols)
click to toggle source
# File lib/cless/display.rb, line 203 def col_align(align, cols) cols.each { |x| x -= @col_start next if x < 0 @align[x] = align } end
col_hide(*args)
click to toggle source
# File lib/cless/display.rb, line 184 def col_hide(*args) args = args.collect { |x| x - @col_start } @col_hide.push(*args) @col_hide.uniq! @col_hide.sort! end
col_hide_clear()
click to toggle source
@col_hide always store the 0 based indices of the columns to show or hide. @col_start is taken into account when setting and getting the @col_hide variables, and for display.
# File lib/cless/display.rb, line 183 def col_hide_clear; @col_hide = []; end
col_show(*args)
click to toggle source
# File lib/cless/display.rb, line 199 def col_show(*args) @col_hide -= args.collect { |x| x - @col_start } end
col_space=(n)
click to toggle source
# File lib/cless/display.rb, line 227 def col_space=(n) @col_space = [1, n.to_i].max end
display_line(l, line_i, sline, highlighted, sift = true, force_center = false)
click to toggle source
# File lib/cless/display.rb, line 256 def display_line(l, line_i, sline, highlighted, sift = true, force_center = false) if @line Ncurses.attron(Ncurses::A_REVERSE) if l.has_match Ncurses.attron(Ncurses::A_UNDERLINE) if IgnoredLine === l s = @line_offset ? l.off : line_i Ncurses.mvaddstr(sline, 0, @col_fmt % [@linec, s]) Ncurses.attroff(Ncurses::A_REVERSE) if l.has_match Ncurses.attroff(Ncurses::A_UNDERLINE) if IgnoredLine === l end if Line === l a = sift ? l.values_at(*@col_show) : l.values_at(0..-1) # Now always display one field at a time ms = sift ? l.matches_at(*@col_show) : l.matches_at(0..-1) clen = @len @sizes.zip(ms).each_with_index { |sm, i| chilighted = !highlighted && @col_highlight chilighted &&= ((@st_col - @col_highlight_shift + i) % @col_highlight_period == 0) @attr.on if chilighted s, m = *sm align = force_center ? :center : @align[i] align = (@right_align_re && a[i] =~ @right_align_re) ? :right : :left if align.nil? # Handle max column width cwidth = [s, clen, @widths_show[i]].min # Actual width of column lcwidth = cwidth # lcwdith is width left in column if m string_length = m.string.length large = string_length > cwidth if !large if align == :right Ncurses.addstr(str = (" " * (cwidth - string_length))) lcwidth -= str.length elsif align == :center Ncurses.addstr(str = (" " * ((cwidth - string_length) / 2))) lcwidth -= str.length end Ncurses.addstr(str = m.pre_match[0, lcwidth]) lcwidth -= str.length Ncurses.attron(Ncurses::A_REVERSE) Ncurses.addstr(str = m[0][0, lcwidth]) Ncurses.attroff(Ncurses::A_REVERSE) lcwidth -= str.length Ncurses.addstr(str = m.post_match[0, lcwidth]) lcwidth -= str.length if align == :left Ncurses.addstr(str = (" " * (cwidth - string_length))) lcwidth -= str.length elsif align == :center space = cwidth - string_length Ncurses.addstr(str = (" " * (space / 2 + space % 2))) lcwidth -= str.length end else # large loff = @offsets_show[i] || 0 # Offset left to skip cap_str = proc { |x| if x.length > loff Ncurses.addstr(str = x[loff..-1][0, lcwidth]) lcwidth -= str.length loff = 0 else loff -= x.length end } cap_str[m.pre_match] Ncurses.attron(Ncurses::A_REVERSE) cap_str[m[0]] Ncurses.attroff(Ncurses::A_REVERSE) cap_str[m.post_match] Ncurses.addstr(" " * lcwidth) if lcwidth > 0 end else # No match col_string = a[i] || "" if col_string.length <= cwidth case align when :left str = col_string.ljust(cwidth) when :right str = col_string.rjust(cwidth) when :center str = col_string.center(cwidth) end else str = (col_string[@offsets_show[i], cwidth] || "").ljust(cwidth) end Ncurses.addstr(str[0, cwidth]) end clen -= cwidth; break if clen <= 0 @attr.off if chilighted Ncurses.addstr(str = @sep[0, clen]) clen -= str.length; break if clen <= 0 } @attr.reset if @col_highlight Ncurses.addstr(" " * clen) if clen > 0 # else # # No match, display all at once # str = (@format % @sizes.zip(a).flatten).ljust(@len)[0, @len] # Ncurses.addstr(str) # end else # l is an ignored line off = @col_off clen = @len if @hide_ignored Ncurses.addstr(" " * clen) if clen > 0 elsif l.has_match m = l.matches s = m.pre_match if s.length > off && clen > 0 Ncurses.addstr(str = s[off, clen]) clen -= str.length off = 0 else off -= s.length end s = m[0] if s.length > off && clen > 0 Ncurses.attron(Ncurses::A_REVERSE) Ncurses.addstr(str = s[off, clen]) Ncurses.attroff(Ncurses::A_REVERSE) clen -= str.length off = 0 else off -= s.length end s = m.post_match if s.length > off && clen > 0 Ncurses.addstr(str = s[off, clen]) clen -= str.length end Ncurses.addstr(" " * clen) if clen > 0 else # l.has_match s = l.str if s.length > off && clen > 0 Ncurses.addstr(str = s[off, @len].ljust(clen)[0, clen]) clen -= str.length end Ncurses.addstr(" " * clen) if clen > 0 end end end
end_active_status()
click to toggle source
# File lib/cless/display.rb, line 482 def end_active_status @active_th.kill if @active_th @active_th = nil end
flush()
click to toggle source
# File lib/cless/display.rb, line 487 def flush Ncurses.refresh end
initialize_curses()
click to toggle source
# File lib/cless/display.rb, line 165 def initialize_curses @attr = Attr.new(@args) @col_names &= @col_headers # Disable col_names if no headers @args = nil end
nb_lines()
click to toggle source
# File lib/cless/display.rb, line 171 def nb_lines Ncurses.stdscr.getmaxy - 1 - (@column ? 1 : 0) - (@col_names ? 1 : 0) end
next_attribute()
click to toggle source
# File lib/cless/display.rb, line 177 def next_attribute; @attr.next_attribute; end
next_background()
click to toggle source
# File lib/cless/display.rb, line 176 def next_background; @attr.next_background; end
next_foreground()
click to toggle source
# File lib/cless/display.rb, line 175 def next_foreground; @attr.next_foreground; end
padding=(s)
click to toggle source
# File lib/cless/display.rb, line 145 def padding=(s) @padding = (!s || s.empty?) ? " " : s end
prompt(ps, opts = {})
click to toggle source
# File lib/cless/display.rb, line 491 def prompt(ps, opts = {}) stdscr = Ncurses.stdscr len = stdscr.getmaxx Ncurses.attrset(Ncurses.COLOR_PAIR(0)) Ncurses.mvaddstr(stdscr.getmaxy-1, 0, ps.ljust(len)[0, len]) s, pos, key = read_line(stdscr.getmaxy-1, ps.length, opts) Ncurses.mvaddstr(stdscr.getmaxy-1, 0, " " * len) return (key == ?\e.ord) ? nil : s rescue KeyboardInterrupt return nil end
read_line(y, x, opts = {})
click to toggle source
read_line
returns an array [string, last_cursor_position_in_string, keycode_of_terminating_enter_key]. options recognize: :window What window to work with :max_len Width of window :string Initial value :cursor_pos Initial cursor position :history Array
containing the history to use with up and down arrows
# File lib/cless/display.rb, line 511 def read_line(y, x, opts = {}) window = opts[:window] || Ncurses.stdscr max_len = opts[:max_len] || (window.getmaxx - x - 1) @prompt_line = opts[:init] || "" cursor_pos = opts[:cursor_pos] || @prompt_line.size other = opts[:other] extra = opts[:extra] history = opts[:history] || [] history_pos = 0 save_line = "" loop do window.mvaddstr(y,x,@prompt_line) window.move(y,x+cursor_pos) extra.call if extra ch = window.getch case ch when Ncurses::KEY_LEFT, Curses::CTRL_B cursor_pos = [0, cursor_pos-1].max when Ncurses::KEY_RIGHT, Curses::CTRL_F cursor_pos = [@prompt_line.length, cursor_pos+1].min when Ncurses::KEY_ENTER, ?\n.ord, ?\r.ord return @prompt_line, cursor_pos, ch # Which return key has been used? when Ncurses::KEY_HOME, Curses::CTRL_A cursor_pos = 0 when Ncurses::KEY_END, Curses::CTRL_E cursor_pos = [max_len, @prompt_line.length].min when Ncurses::KEY_DC, Curses::CTRL_D @prompt_line.slice!(cursor_pos) window.mvaddstr(y, x+@prompt_line.length, " ") when Curses::CTRL_K window.mvaddstr(y, x+cursor_pos, " " * (@prompt_line.length - cursor_pos)) @prompt_line = @prompt_line[0, cursor_pos] when Ncurses::KEY_BACKSPACE, ?\b.ord if cursor_pos > 0 cursor_pos -= 1 @prompt_line.slice!(cursor_pos) window.mvaddstr(y, x+@prompt_line.length, " ") else return "", 0, ?\e.ord end when ?\e.ord # ESCAPE return "", 0, ch when Ncurses::KEY_UP if history_pos < history.size save_line = @prompt_line if history_pos == 0 window.mvaddstr(y, x, " " * @prompt_line.length) @prompt_line = history[history_pos].dup history_pos += 1 cursor_pos = @prompt_line.size end when Ncurses::KEY_DOWN if history_pos > 0 window.mvaddstr(y, x, " " * @prompt_line.length) history_pos -= 1 @prompt_line = history_pos > 0 ? history[history_pos - 1].dup : save_line cursor_pos = @prompt_line.size end when C::SPACE..255 # remaining printables if (cursor_pos < max_len) @prompt_line[cursor_pos,0] = ch.chr cursor_pos += 1 else Ncurses.beep end end other[ch] if other end end
refresh()
click to toggle source
# File lib/cless/display.rb, line 231 def refresh Ncurses.move(0, 0) Ncurses.attrset(Ncurses.COLOR_PAIR(0)) lines = refresh_prepare i = 0 line_i = @data.line + 1 sline = refresh_column_headers @data.lines(lines) { |l| highlighted = @line_highlight && ((line_i - @line_highlight_shift) % @line_highlight_period == 0) highlighted ||= l.highlight? highlighted ? @attr.set : @attr.reset display_line(l, line_i, sline, highlighted) i += 1 line_i += 1 sline += 1 } Ncurses.clrtobot ensure Ncurses.refresh end
refresh_column_headers()
click to toggle source
Modifies @sizes
# File lib/cless/display.rb, line 401 def refresh_column_headers @col_names &= @col_headers # Disable col_names if no headers if @column cnumber = @col_show.map { |x| (x + @col_start).to_s } cnumber.each_with_index { |s, i| s.replace("< #{s} >") if @sizes[i] > @widths_show[i] } @sizes.max_update(cnumber.collect { |x| x.size }) end if @col_names column_headers = @col_headers.values_at(*@col_show).map { |x| x || "" } hs = col_headers.map { |s| s.size } @sizes.max_update(hs) end sline = 0 if @column Ncurses.attron(Ncurses::A_UNDERLINE) if !@col_names display_line(Line.new(cnumber), "", sline, false, false, true) Ncurses.attroff(Ncurses::A_UNDERLINE) if !@col_names sline += 1 end if @col_names Ncurses.attron(Ncurses::A_UNDERLINE) display_line(Line.new(column_headers), "", sline, false, false) Ncurses.attroff(Ncurses::A_UNDERLINE) sline += 1 end sline end
refresh_prepare()
click to toggle source
# File lib/cless/display.rb, line 430 def refresh_prepare lines = nb_lines @len = Ncurses.stdscr.getmaxx @col_show = (@st_col..(@st_col + @col_hide.size + @len / 2)).to_a @col_show -= @col_hide @sizes = @data.sizes.values_at(*@col_show).map { |x| x || 0 } @widths_show = @widths.values_at(*@col_show).map { |x| x || @col_width } @offsets_show = @col_offsets.values_at(*@col_show).map { |x| x || 0 } if @line @linec = @line_offset ? @data.max_offset : (@data.line + lines) @linec = @linec.to_s.size end @len -= @linec + @col_space if @line @sep = @separator.center(@col_space, @padding) @col_fmt = "%*s#{@sep}" @format = @col_fmt * @col_show.size return lines end
separator=(s)
click to toggle source
# File lib/cless/display.rb, line 141 def separator=(s) @separator = (!s || s.empty?) ? " " : s end
st_col()
click to toggle source
# File lib/cless/display.rb, line 211 def st_col; @st_col; end
st_col=(n)
click to toggle source
# File lib/cless/display.rb, line 213 def st_col=(n) n = 0 if n < 0 n = @data.sizes.size if n > @data.sizes.size return @st_col if n == @st_col range, sign = (n > @st_col) ? [@st_col...n, 1] : [n...@st_col, -1] @col_off += sign * @data.sizes[range].inject(0) { |acc, x| acc + x + @sep.size } @col_off = [@col_off, 0].max @col_off = 0 if n == 0 @st_col = n end
start_active_status(status)
click to toggle source
# File lib/cless/display.rb, line 461 def start_active_status(status) len = Ncurses.stdscr.getmaxx astatus = status[0, len - 2] Ncurses.attrset(Ncurses::A_NORMAL) Ncurses.mvaddstr(Ncurses.stdscr.getmaxy-1, 0, status[0, len - 2]) nlen = len - astatus.length Ncurses.addstr('|'.rjust(nlen)[0, nlen]) Ncurses.refresh @active_th = Thread.new { loop { ['/', '-', '\\', '|'].each { |c| sleep(0.5) Ncurses.mvaddstr(Ncurses.stdscr.getmaxy-1, len - 1, c) Ncurses.refresh } } } end
wait_status(status, wprompt)
click to toggle source
# File lib/cless/display.rb, line 449 def wait_status(status, wprompt) len = Ncurses.stdscr.getmaxx aprompt = wprompt[0, len - 1] Ncurses.attrset(Ncurses::A_NORMAL) Ncurses.mvaddstr(Ncurses.stdscr.getmaxy-1, 0, aprompt) nlen = len - aprompt.length Ncurses.attrset(Ncurses::A_BOLD) Ncurses.addstr(status.rjust(nlen)[0, nlen]) Ncurses.attrset(Ncurses::A_NORMAL) end