class MapData

Constants

BIGINT_PROC
FLOAT_PROC
FLOAT_REGEXP
FMT_LETTERS
FMT_REGEXP
INT_PROC
INT_REGEXP
PERCENTAGE_PROC

Attributes

line[R]
line2[R]
pattern[R]
sizes[R]
split_regexp[R]

Public Class Methods

new(str, split_regexp = nil) click to toggle source
# File lib/cless/data.rb, line 276
def initialize(str, split_regexp = nil)
  @str = str
  @line = @line2 = 0
  @off = @off2 = 0    # @off  = first character of first line in cache
                      # @off2 = first character of first line past cache
  @cache = []
  @sizes = []
  @pattern = nil      # search pattern
  @formats = nil      # formating strings. When not nil, a hash.
  @ignores = nil      # line ignored index or pattern.
  @split_regexp = split_regexp        # split pattern
  @highlight_regexp = nil             # highlight pattern
  @need_more = false  # true if last cache_fill needs data
end

Public Instance Methods

add_ignore(pattern) click to toggle source
# File lib/cless/data.rb, line 483
def add_ignore(pattern)
  return nil unless [Integer, Range, Regexp].any? { |c| c === pattern }
  (@ignored ||= []) << pattern
  true
end
cache_fill(n) click to toggle source
# File lib/cless/data.rb, line 422
def cache_fill(n)
  @need_more = @cache.size < n
  cache_forward(n - @cache.size) if @need_more
end
clear_cache() click to toggle source
# File lib/cless/data.rb, line 427
def clear_cache
  @cache.clear
  @line2 = @line
  @off2 = @off
  @sizes.clear
end
file_path() click to toggle source
# File lib/cless/data.rb, line 291
def file_path; @str.file_path; end
formatted_column_list() click to toggle source
# File lib/cless/data.rb, line 481
def formatted_column_list; @formats ? @formats.keys : []; end
get_format_column(col) click to toggle source
# File lib/cless/data.rb, line 476
def get_format_column(col)
  return nil unless @formats
  @formats[col]
end
goto_end() click to toggle source
# File lib/cless/data.rb, line 334
def goto_end
  old_line = @line2
  @line2 = @str.lines
  return false if @line2 == old_line
  @line = @line2
  @off2 = @off = @str.size
  cache_size = @cache.size
  @cache.clear
  scroll(-cache_size)
  return true
end
goto_line(nb) click to toggle source
# File lib/cless/data.rb, line 346
def goto_line(nb)
  delta = nb - @line - 1
  scroll(delta)
end
goto_offset(off) click to toggle source
# File lib/cless/data.rb, line 359
def goto_offset(off)
  @str.lines(nil, off) if off > @str.size
  off -= 1 if @str[off] == ?\n && off > 0
  @off = @off2 = (@str.rindex("\n", off) || -1) + 1
  @line = @line2 = @str.count_lines_upto(@off)
  @cache.clear
end
goto_percent(percent) click to toggle source
# File lib/cless/data.rb, line 351
def goto_percent(percent)
  percent = 0.0 if percent < 0.0
  percent = 100.0 if percent > 100.0
  percent = percent.to_f
  line = (@str.lines * percent / 100).round
  goto_line(line)
end
goto_start() click to toggle source
# File lib/cless/data.rb, line 326
def goto_start
  return false if @line == 0
  @line = @line2 = 0
  @off = @off2 = 0
  @cache.clear
  return true
end
highlight_regexp=(regexp) click to toggle source
# File lib/cless/data.rb, line 494
def highlight_regexp=(regexp)
  @highlight_regexp = regexp
  clear_cache
end
ignore_pattern_list() click to toggle source
# File lib/cless/data.rb, line 510
def ignore_pattern_list; @ignored ? @ignored : []; end
lines(n) { |l| ... } click to toggle source

yield n lines with length len to be displayed

# File lib/cless/data.rb, line 319
def lines(n)
  @cache.each_with_index { |l, i|
    break if i >= n
    yield l
  }
end
max_offset() click to toggle source

Returns the maximum line offset of all lines in cache

# File lib/cless/data.rb, line 513
def max_offset
  @cache.collect { |l| l.off }.max
end
refresh() click to toggle source
# File lib/cless/data.rb, line 434
def refresh
  size = @cache.size
  clear_cache
  cache_fill(size)
end
remove_ignore(pattern) click to toggle source
# File lib/cless/data.rb, line 499
def remove_ignore(pattern)
  if pattern.nil?
    r, @ignored = @ignored, nil
    return r
  end
  return nil unless [Integer, Range, Regexp].any? { |c| c === pattern }
  r = @ignored.delete(pattern)
  @ignored = nil if @ignored.empty?
  r
end
scroll(delta) click to toggle source

delta > for scrolling down (forward in file)

# File lib/cless/data.rb, line 407
def scroll(delta)
  return if delta == 0
  cache_size = @cache.size
  if delta > 0
    skipped = skip_forward(delta) 
    @cache.slice!(0, skipped)
    cache_forward([cache_size, skipped].min)
  else
    skipped = skip_backward(-delta)
    delta = -@cache.size if -delta > @cache.size
    @cache.slice!((delta..-1))
    cache_backward([cache_size, skipped].min)
  end
end
search_clear() click to toggle source
# File lib/cless/data.rb, line 401
def search_clear
  @pattern = nil
  @cache.each { |l| l.clear_match }
end
select_fd(n) click to toggle source

Return a file descriptor to listen on (select) if there is less than n lines in the cache, or nil if not needed, or file is memory mapped and no listening is necessary.

# File lib/cless/data.rb, line 308
def select_fd(n)
  @cache.size < n ? @str.more_fd : nil
end
set_format_column(fmt, *cols) click to toggle source
# File lib/cless/data.rb, line 455
def set_format_column(fmt, *cols)
  if fmt =~ FMT_REGEXP
    a = case $3
        when "b", "c", "d", "i", "o", "u", "X", "x"; [fmt, INT_REGEXP, INT_PROC]
        when "E", "e", "f", "G", "g"; [fmt, FLOAT_REGEXP, FLOAT_PROC]
        when "I"; ["#{$`}#{$1}#{$2}s#{$'}", FLOAT_REGEXP, BIGINT_PROC]
        when "p"; ["#{$`}#{$1}#{$2}f%#{$'}", FLOAT_REGEXP, PERCENTAGE_PROC]
        end
  end
  @formats ||= {}
  cols.each { |c| @formats[c] = a }
  true
end
split_regexp=(regexp) click to toggle source
# File lib/cless/data.rb, line 489
def split_regexp=(regexp)
  @split_regexp = regexp
  clear_cache
end
unset_format_column(col) click to toggle source
# File lib/cless/data.rb, line 469
def unset_format_column(col)
  return nil unless @formats
  r = @formats.delete(col)
  @formats = nil if @formats.empty?
  r
end
write_to(fd) click to toggle source
# File lib/cless/data.rb, line 292
def write_to(fd)
  @str.lines          # Make sure we have all the data
  block = 64*1024

  (@str.size / block).times do |i|
    fd.syswrite(@str[i*block, block])
  end
  if (r = @str.size % block) > 0
    fd.syswrite(@str[@str.size - r, r])
  end
  @str.size
end

Private Instance Methods

cache_backward(n) click to toggle source
# File lib/cless/data.rb, line 589
def cache_backward(n)
  lnb = @line - 1
  n.times do |i|
    break if @off == 0
    ooff = @off
    @off = search_backward_to_new_line(@off)
    @cache.unshift(line_massage(@str[@off, ooff - @off - 1], lnb - i, @off))
  end
  @line = @line2 - @cache.size
end
cache_forward(n) click to toggle source
# File lib/cless/data.rb, line 579
def cache_forward(n)
  lnb = @line + @cache.size
  n.times do |i|
    noff2 = @str.index("\n", @off2) or break
    @cache << line_massage(@str[@off2, noff2 - @off2], lnb + i, @off2)
    @off2 = noff2 + 1
  end
  @line2 = @line + @cache.size
end
line_ignore?(str, i) click to toggle source
# File lib/cless/data.rb, line 553
def line_ignore?(str, i)
  @ignored.any? do |pat|
    case pat
    when Range, Integer; pat === i
    when Regexp; pat === str
    else false
    end
  end
end
line_massage(str, i, off) click to toggle source

str = line i = line number

# File lib/cless/data.rb, line 565
def line_massage(str, i, off)
  if @ignored && line_ignore?(str, i)
    l = IgnoredLine.new(str, off)
  else
    onl, nl = nil, str.split(@split_regexp)
    onl = reformat(nl) if @formats
    @sizes.max_update(nl.collect { |x| x.size })
    l = Line.new(nl, onl, off)
  end
  l.match(@pattern) if @pattern
  l.highlight = @highlight_regexp && (@highlight_regexp =~ str)
  l
end
reformat(nl) click to toggle source
# File lib/cless/data.rb, line 541
def reformat(nl)
  onl = nl.dup
  @formats.each do |i, f|
    s = nl[i] or next
    fmt, cond, proc = *f
    cond =~ s or next
    s = proc[s] if proc
    nl[i] = fmt % s rescue "###"
  end
  onl
end
search_backward_to_new_line(start) click to toggle source
# File lib/cless/data.rb, line 600
def search_backward_to_new_line(start)
  return 0 if start < 2
  npos = @str.rindex("\n", start - 2)
  return npos ? npos + 1 : 0
end
search_next(dir = :forward) click to toggle source
# File lib/cless/data.rb, line 518
def search_next(dir = :forward)
  if dir == :forward
    m = @str.search_index(@pattern, @off2)
  else
    m = @str.search_rindex(@pattern, @off)
  end
  return false if !m
  if dir == :forward
    old_off2, old_line2 = @off2, @line2
    @off = @off2 = (@str.rindex("\n", m) || -1) + 1
    @line = @line2 = old_line2 + @str[old_off2..@off2].count("\n")
    @cache.clear
  else
    old_off, old_line = @off, @line
    @off = @off2 = (@str.rindex("\n", m) || -1) + 1
    @line = @line2 = old_line - @str[@off..old_off].count("\n")
    cache_size = @cache.size
    @cache.clear
    scroll(-cache_size+1)
  end
  return true
end
skip_backward(n) click to toggle source

Move @off2 back by n lines. Make sure that @off <= @off2

# File lib/cless/data.rb, line 621
def skip_backward(n)
  i = 0
  n.times do
    break if @off2 == 0
    @off2 = search_backward_to_new_line(@off2)
    i += 1
  end
  @off = @off2 if @off > @off2
  @line2 -= i
  @line = @line2 if @line2 < @line
  i
end
skip_forward(n) click to toggle source

Move @off by n lines. Make sure that @off2 >= @off

# File lib/cless/data.rb, line 607
def skip_forward(n)
  i = 0
  n.times do 
    noff = @str.search_index("\n", @off) or break
    @off = noff + 1
    i += 1
  end
  @off2 = @off if @off2 < @off
  @line += i
  @line2 = @line if @line > @line2
  i
end