Class: MapData

Inherits:
Object
  • Object
show all
Defined in:
lib/cless/data.rb

Constant Summary collapse

FMT_LETTERS =
"bcdEefGgiIosuXxp"
FMT_REGEXP =
/(^|[^%])(%[ \d#+*.-]*)([#{FMT_LETTERS}])/
FLOAT_REGEXP =
/^[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?$/
INT_REGEXP =
/^[-+]?[0-9]+$/
FLOAT_PROC =
proc { |x| x.to_f }
INT_PROC =
proc { |x| x.to_i }
BIGINT_PROC =
proc { |x|
  x = x.to_f.round
  neg = (x < 0)
  x = x.abs.to_s.reverse.gsub(/(...)/, '\1,').chomp(",").reverse
  neg ? "-#{x}" : x
}
PERCENTAGE_PROC =
proc { |x|
  x.to_f * 100.0
}

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(str, split_regexp = nil) ⇒ MapData

Returns a new instance of MapData.



276
277
278
279
280
281
282
283
284
285
286
287
288
289
# 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

Instance Attribute Details

#lineObject (readonly)

Returns the value of attribute line.



275
276
277
# File 'lib/cless/data.rb', line 275

def line
  @line
end

#line2Object (readonly)

Returns the value of attribute line2.



275
276
277
# File 'lib/cless/data.rb', line 275

def line2
  @line2
end

#patternObject (readonly)

Returns the value of attribute pattern.



275
276
277
# File 'lib/cless/data.rb', line 275

def pattern
  @pattern
end

#sizesObject (readonly)

Returns the value of attribute sizes.



275
276
277
# File 'lib/cless/data.rb', line 275

def sizes
  @sizes
end

#split_regexpObject

Returns the value of attribute split_regexp.



275
276
277
# File 'lib/cless/data.rb', line 275

def split_regexp
  @split_regexp
end

Instance Method Details

#add_ignore(pattern) ⇒ Object



483
484
485
486
487
# 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) ⇒ Object



422
423
424
425
# 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_cacheObject



427
428
429
430
431
432
# File 'lib/cless/data.rb', line 427

def clear_cache
  @cache.clear
  @line2 = @line
  @off2 = @off
  @sizes.clear
end

#file_pathObject



291
# File 'lib/cless/data.rb', line 291

def file_path; @str.file_path; end

#formatted_column_listObject



481
# File 'lib/cless/data.rb', line 481

def formatted_column_list; @formats ? @formats.keys : []; end

#get_format_column(col) ⇒ Object



476
477
478
479
# File 'lib/cless/data.rb', line 476

def get_format_column(col)
  return nil unless @formats
  @formats[col]
end

#goto_endObject



334
335
336
337
338
339
340
341
342
343
344
# 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) ⇒ Object



346
347
348
349
# File 'lib/cless/data.rb', line 346

def goto_line(nb)
  delta = nb - @line - 1
  scroll(delta)
end

#goto_offset(off) ⇒ Object



359
360
361
362
363
364
365
# 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) ⇒ Object



351
352
353
354
355
356
357
# 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_startObject



326
327
328
329
330
331
332
# 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) ⇒ Object



494
495
496
497
# File 'lib/cless/data.rb', line 494

def highlight_regexp=(regexp)
  @highlight_regexp = regexp
  clear_cache
end

#ignore_pattern_listObject



510
# File 'lib/cless/data.rb', line 510

def ignore_pattern_list; @ignored ? @ignored : []; end

#lines(n) ⇒ Object

yield n lines with length len to be displayed



319
320
321
322
323
324
# File 'lib/cless/data.rb', line 319

def lines(n)
  @cache.each_with_index { |l, i|
    break if i >= n
    yield l
  }
end

#max_offsetObject

Returns the maximum line offset of all lines in cache



513
514
515
# File 'lib/cless/data.rb', line 513

def max_offset
  @cache.collect { |l| l.off }.max
end

#refreshObject



434
435
436
437
438
# File 'lib/cless/data.rb', line 434

def refresh
  size = @cache.size
  clear_cache
  cache_fill(size)
end

#remove_ignore(pattern) ⇒ Object



499
500
501
502
503
504
505
506
507
508
# 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

#repeat_search(dir = :forward) ⇒ Object



384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
# File 'lib/cless/data.rb', line 384

def repeat_search(dir = :forward)
  first_line = nil
  cache = (dir == :forward) ? @cache : @cache.reverse
  cache[1..-1].each_with_index { |l, i|
    if l.has_match
      first_line = i
      break
    end
  }
  if first_line
    scroll((dir == :forward) ? first_line + 1 : -first_line - 1)
    return true
  else
    return search_next(dir)
  end
end

#scroll(delta) ⇒ Object

delta > for scrolling down (forward in file)



407
408
409
410
411
412
413
414
415
416
417
418
419
420
# 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(pattern, dir = :forward) ⇒ Object

Return true if pattern found, false otherwise



368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/cless/data.rb', line 368

def search(pattern, dir = :forward)
  search_clear if @pattern
  @pattern = pattern
  first_line = nil
  cache = (dir == :forward) ? @cache : @cache.reverse
  cache.each_with_index { |l, i|
    l.match(@pattern) and first_line ||= i
  }
  if first_line
    scroll((dir == :forward) ? first_line : -first_line)
    return true
  else
    return search_next(dir)
  end
end

#search_clearObject



401
402
403
404
# File 'lib/cless/data.rb', line 401

def search_clear
  @pattern = nil
  @cache.each { |l| l.clear_match }
end

#select_fd(n) ⇒ Object

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.



308
309
310
# File 'lib/cless/data.rb', line 308

def select_fd(n)
  @cache.size < n ? @str.more_fd : nil
end

#set_format_column(fmt, *cols) ⇒ Object



455
456
457
458
459
460
461
462
463
464
465
466
467
# 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

#unset_format_column(col) ⇒ Object



469
470
471
472
473
474
# 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) ⇒ Object



292
293
294
295
296
297
298
299
300
301
302
303
# 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