Class: LineDisplay
- Inherits:
-
Object
- Object
- LineDisplay
- Defined in:
- lib/cless/display.rb
Constant Summary collapse
- ISNUM =
/^[+-]?[\d,]*\.?\d*(?:[eE][+-]?\d+)?$/
- DEFAULTS =
{ :line_highlight => true, # Wether to hilight every other line :line_highlight_period => 2, :line_highlight_shift => 0, :col_highlight => true, # Wether to hilight every other column :col_highlight_period => 2, :col_highlight_shift => 1, :column => false, # Wether to display column number :col_start => 1, # 1-based column numbering by default :col_width => 50, # Maximum column width :line => false, # Wether to display line number :line_offset => false, # Display line offset instead of number :col_names => false, # Wether to display column names :col_space => 1, # Width of separator between columns :separator => " ", # Separator caracter :padding => " ", # Padding caracter :right_align_re => ISNUM, # Matching columns are right align by default :hide_ignore => false # Hide lines that are ignored }
Instance Attribute Summary collapse
-
#col_headers ⇒ Object
Returns the value of attribute col_headers.
-
#col_offsets ⇒ Object
Returns the value of attribute col_offsets.
-
#hide_ignored ⇒ Object
Returns the value of attribute hide_ignored.
-
#prompt_line ⇒ Object
readonly
Returns the value of attribute prompt_line.
-
#sizes ⇒ Object
readonly
Returns the value of attribute sizes.
-
#widths ⇒ Object
Returns the value of attribute widths.
Instance Method Summary collapse
- #attr_names ⇒ Object
- #col_align(align, cols) ⇒ Object
- #col_hidden(with_start = true) ⇒ Object
- #col_hide(*args) ⇒ Object
-
#col_hide_clear ⇒ Object
columns to show or hide.
- #col_show(*args) ⇒ Object
- #col_space=(n) ⇒ Object
- #display_line(l, line_i, sline, highlighted, sift = true, force_center = false) ⇒ Object
- #end_active_status ⇒ Object
- #flush ⇒ Object
-
#initialize(data, args = {}) ⇒ LineDisplay
constructor
A new instance of LineDisplay.
- #initialize_curses ⇒ Object
- #nb_lines ⇒ Object
- #next_attribute ⇒ Object
- #next_background ⇒ Object
- #next_foreground ⇒ Object
- #padding=(s) ⇒ Object
- #prompt(ps, opts = {}) ⇒ Object
-
#read_line(y, x, opts = {}) ⇒ Object
read_line returns an array [string, last_cursor_position_in_string, keycode_of_terminating_enter_key].
- #refresh ⇒ Object
-
#refresh_column_headers ⇒ Object
Modifies @sizes.
- #refresh_prepare ⇒ Object
- #separator=(s) ⇒ Object
- #st_col ⇒ Object
- #st_col=(n) ⇒ Object
- #start_active_status(status) ⇒ Object
- #wait_status(status, wprompt) ⇒ Object
Constructor Details
#initialize(data, args = {}) ⇒ LineDisplay
Returns a new instance of LineDisplay.
150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# 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 |
Instance Attribute Details
#col_headers ⇒ Object
Returns the value of attribute col_headers.
149 150 151 |
# File 'lib/cless/display.rb', line 149 def col_headers @col_headers end |
#col_offsets ⇒ Object
Returns the value of attribute col_offsets.
137 138 139 |
# File 'lib/cless/display.rb', line 137 def col_offsets @col_offsets end |
#hide_ignored ⇒ Object
Returns the value of attribute hide_ignored.
149 150 151 |
# File 'lib/cless/display.rb', line 149 def hide_ignored @hide_ignored end |
#prompt_line ⇒ Object (readonly)
Returns the value of attribute prompt_line.
138 139 140 |
# File 'lib/cless/display.rb', line 138 def prompt_line @prompt_line end |
#sizes ⇒ Object (readonly)
Returns the value of attribute sizes.
138 139 140 |
# File 'lib/cless/display.rb', line 138 def sizes @sizes end |
#widths ⇒ Object
Returns the value of attribute widths.
137 138 139 |
# File 'lib/cless/display.rb', line 137 def widths @widths end |
Instance Method Details
#attr_names ⇒ Object
178 |
# File 'lib/cless/display.rb', line 178 def attr_names; @attr.names; end |
#col_align(align, cols) ⇒ Object
203 204 205 206 207 208 209 |
# 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_hidden(with_start = true) ⇒ Object
191 192 193 194 195 196 197 |
# File 'lib/cless/display.rb', line 191 def col_hidden(with_start = true) if with_start @col_hide.collect { |x| x + @col_start } else @col_hide end end |
#col_hide(*args) ⇒ Object
184 185 186 187 188 189 |
# 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 ⇒ Object
columns to show or hide. @col_start is taken into account when setting and getting the @col_hide variables, and for display.
183 |
# File 'lib/cless/display.rb', line 183 def col_hide_clear; @col_hide = []; end |
#col_show(*args) ⇒ Object
199 200 201 |
# File 'lib/cless/display.rb', line 199 def col_show(*args) @col_hide -= args.collect { |x| x - @col_start } end |
#col_space=(n) ⇒ Object
227 228 229 |
# 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) ⇒ Object
256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 |
# 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 ⇒ Object
482 483 484 485 |
# File 'lib/cless/display.rb', line 482 def end_active_status @active_th.kill if @active_th @active_th = nil end |
#flush ⇒ Object
487 488 489 |
# File 'lib/cless/display.rb', line 487 def flush Ncurses.refresh end |
#initialize_curses ⇒ Object
165 166 167 168 169 |
# 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 ⇒ Object
171 172 173 |
# File 'lib/cless/display.rb', line 171 def nb_lines Ncurses.stdscr.getmaxy - 1 - (@column ? 1 : 0) - (@col_names ? 1 : 0) end |
#next_attribute ⇒ Object
177 |
# File 'lib/cless/display.rb', line 177 def next_attribute; @attr.next_attribute; end |
#next_background ⇒ Object
176 |
# File 'lib/cless/display.rb', line 176 def next_background; @attr.next_background; end |
#next_foreground ⇒ Object
175 |
# File 'lib/cless/display.rb', line 175 def next_foreground; @attr.next_foreground; end |
#padding=(s) ⇒ Object
145 146 147 |
# File 'lib/cless/display.rb', line 145 def padding=(s) @padding = (!s || s.empty?) ? " " : s end |
#prompt(ps, opts = {}) ⇒ Object
491 492 493 494 495 496 497 498 499 500 501 |
# 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 = {}) ⇒ Object
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
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 |
# 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 ⇒ Object
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 |
# 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 ⇒ Object
Modifies @sizes
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 |
# 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 ⇒ Object
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 |
# 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) ⇒ Object
141 142 143 |
# File 'lib/cless/display.rb', line 141 def separator=(s) @separator = (!s || s.empty?) ? " " : s end |
#st_col ⇒ Object
211 |
# File 'lib/cless/display.rb', line 211 def st_col; @st_col; end |
#st_col=(n) ⇒ Object
213 214 215 216 217 218 219 220 221 222 223 224 225 |
# 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) ⇒ Object
461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 |
# 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) ⇒ Object
449 450 451 452 453 454 455 456 457 458 459 |
# 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 |