Class: BenchRb::Console

Inherits:
Object show all
Defined in:
lib/benchrb.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(opts = {}) ⇒ Console

Returns a new instance of Console.



309
310
311
312
313
# File 'lib/benchrb.rb', line 309

def initialize opts={}
  @max_history = opts[:max_history] || 1000
  @history     = Array(opts[:history])
  @prompt      = opts[:prompt] || ">> "
end

Instance Attribute Details

#historyObject

Returns the value of attribute history.



307
308
309
# File 'lib/benchrb.rb', line 307

def history
  @history
end

#max_historyObject

Returns the value of attribute max_history.



307
308
309
# File 'lib/benchrb.rb', line 307

def max_history
  @max_history
end

#promptObject

Returns the value of attribute prompt.



307
308
309
# File 'lib/benchrb.rb', line 307

def prompt
  @prompt
end

Instance Method Details

#read_charObject



436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
# File 'lib/benchrb.rb', line 436

def read_char
  c = ""

  begin
    # save previous state of stty
    #old_state = `stty -g`
    # disable echoing and enable raw (not having to press enter)
    #system "stty raw -echo"
    c = $stdin.getc.chr
    # gather next two characters of special keys
    if(c=="\e")
      extra_thread = Thread.new{
        c = c + $stdin.getc.chr
        c = c + $stdin.getc.chr
      }
      # wait just long enough for special keys to get swallowed
      extra_thread.join(0.0001)
      # kill thread so not-so-long special keys don't wait on getc
      extra_thread.kill
    end

  rescue => ex
    puts "#{ex.class}: #{ex.message}"
  #ensure
    # restore previous state of stty
    #system "stty #{old_state}"
  end

  return c
end

#read_lineObject



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
399
400
401
402
403
404
405
406
407
408
409
410
411
412
# File 'lib/benchrb.rb', line 316

def read_line
  old_state = `stty -g`
  system "stty raw -echo"

  hindex = @history.length
  cpos   = write_line ""

  line = ""
  disp = line

  loop do
    ch = read_char

    case ch
    when "\e"
      # Got escape by itself. Do nothing.

    when "\u0001" # ctrl+A - BOL
      cpos = set_wpos(0)

    when "\u0005" # ctrl+E - EOL
      cpos = set_wpos(disp.length)

    when "\u0017" # ctrl+W - erase word
      i = disp.rstrip.rindex(" ")
      disp = i ? disp[0..i] : ""
      cpos = write_line disp

    when "\u0015" # ctrl+U - erase all
      disp.clear
      cpos = write_line disp

    when "\u0003" # ctrl+C - SIGINT
      set_cpos(0)
      Process.kill "INT", Process.pid
      break

    when "\e[A", "\u0010" # Up Arrow, Ctrl+P
      hindex = hindex - 1
      hindex = 0 if hindex < 0
      if @history[hindex]
        disp = @history[hindex].dup
        cpos = write_line disp
      end

    when "\e[B", "\u000E" # Down Arrow, Ctrl+N
      hindex = hindex + 1
      hindex = @history.length if hindex > @history.length
      disp = hindex == @history.length ? line : @history[hindex].dup
      cpos = write_line disp

    when "\e[C", "\u0006" # Right Arrow, Ctrl+F
      if cpos < (@prompt.length + disp.length + 1)
        cpos = cpos + 1
        $stdout.print "\e[#{cpos}G"
      end

    when "\e[D", "\u0002" # Left Arrow, Ctrl+B
      if cpos > @prompt.length + 1
        cpos = set_cpos(cpos - 1)
      end

    when "\r", "\n" # Enter - commit line
      line = disp
      $stdout.puts ch
      break

    when "\u007F", "\b" # Delete
      if cpos > @prompt.length + 1
        cpos = cpos - 1
        wpos = cpos - @prompt.length - 1
        disp[wpos,1] = ""
        write_line disp
        set_cpos cpos
      end

    when "\t" # Tab

    else
      wpos = cpos - @prompt.length - 1
      disp[wpos,0] = ch
      write_line disp
      cpos = set_cpos(cpos + 1)
    end

    $stdout.flush
  end

  @history << line unless line.strip.empty? || @history[-1] == line
  @history = @history[@history.length-@max_history..-1] if
    @history.length > @max_history

  line

ensure
  system "stty #{old_state}"
end

#set_cpos(num) ⇒ Object



430
431
432
433
# File 'lib/benchrb.rb', line 430

def set_cpos num
  $stdout.print "\e[#{num}G"
  num
end

#set_wpos(num) ⇒ Object



423
424
425
426
427
# File 'lib/benchrb.rb', line 423

def set_wpos num
  pos = @prompt.length + num + 1
  $stdout.print "\e[#{pos}G"
  pos
end

#write_line(line) ⇒ Object



415
416
417
418
419
420
# File 'lib/benchrb.rb', line 415

def write_line line
  text = "#{@prompt}#{line}"
  $stdout.print "\e[2K\e[0G#{text}"
  $stdout.flush
  text.length + 1
end