ruby/ext/curses/view2.rb

150 строки
3.1 KiB
Ruby

#!/usr/local/bin/ruby
require "curses"
# A curses based file viewer
class FileViewer
# Create a new fileviewer, and view the file.
def initialize(filename)
@data_lines = []
@screen = nil
@top = nil
init_curses
load_file(filename)
interact
end
# Perform the curses setup
def init_curses
# signal(SIGINT, finish)
Curses.init_screen
Curses.nonl
Curses.cbreak
Curses.noecho
@screen = Curses.stdscr
@screen.scrollok(true)
#$screen.keypad(true)
end
# Load the file into memory, and put
# the first part on the curses display.
def load_file(filename)
fp = open(filename, "r") do |fp|
# slurp the file
fp.each_line { |l|
@data_lines.push(l.chop)
}
end
@top = 0
@data_lines[0..@screen.maxy-1].each_with_index{|line, idx|
@screen.setpos(idx, 0)
@screen.addstr(line)
}
@screen.setpos(0,0)
@screen.refresh
rescue
raise "cannot open file '#{filename}' for reading"
end
# Scroll the display up by one line
def scroll_up
if( @top > 0 )
@screen.scrl(-1)
@top -= 1
str = @data_lines[@top]
if( str )
@screen.setpos(0, 0)
@screen.addstr(str)
end
return true
else
return false
end
end
# Scroll the display down by one line
def scroll_down
if( @top + @screen.maxy < @data_lines.length )
@screen.scrl(1)
@top += 1
str = @data_lines[@top + @screen.maxy - 1]
if( str )
@screen.setpos(@screen.maxy - 1, 0)
@screen.addstr(str)
end
return true
else
return false
end
end
# Allow the user to interact with the display.
# This uses EMACS-like keybindings, and also
# vi-like keybindings as well, except that left
# and right move to the beginning and end of the
# file, respectively.
def interact
while true
result = true
c = Curses.getch
case c
when Curses::KEY_DOWN, Curses::KEY_CTRL_N, ?j
result = scroll_down
when Curses::KEY_UP, Curses::KEY_CTRL_P, ?k
result = scroll_up
when Curses::KEY_NPAGE, ?\s # white space
for i in 0..(@screen.maxy - 2)
if( ! scroll_down )
if( i == 0 )
result = false
end
break
end
end
when Curses::KEY_PPAGE
for i in 0..(@screen.maxy - 2)
if( ! scroll_up )
if( i == 0 )
result = false
end
break
end
end
when Curses::KEY_LEFT, Curses::KEY_CTRL_T, ?h
while( scroll_up )
end
when Curses::KEY_RIGHT, Curses::KEY_CTRL_B, ?l
while( scroll_down )
end
when ?q
break
else
@screen.setpos(0,0)
@screen.addstr("[unknown key `#{Curses.keyname(c)}'=#{c}] ")
end
if( !result )
Curses.beep
end
@screen.setpos(0,0)
end
Curses.close_screen
end
end
# If we are being run as a main program...
if __FILE__ == $0
if ARGV.size != 1 then
printf("usage: #{$0} file\n");
exit
end
viewer = FileViewer.new(ARGV[0])
end