From: zimba-tm Date: 2005-12-03T11:40:21+09:00 Subject: Curses about libcurse ------=_Part_6032_7248194.1133577613783 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Hello, I hate curses. Not that much, but it's really not that easy to build ruby console applications using it. Are there other libraries I could use instead of libcurses ? My main complains are : * you can't access the screen like a character matrix * i want callbacks (onresize) * you need to move the cursor where you want to write * the "window"ing system is not cool * it really feels like an old-skool C library in ruby I started overriding the curses library to implement what I think is nicer (which is subjective). Is anybody interested in this ? Also, what is so special in the libcurse ? Is it because it supports VT100 that people are still using it ? The joined file containes the modified curses class plus an class that demonstrates how to use it (however it doesn't run) -- Cheers, zimba http://zimba.oree.ch ------=_Part_6032_7248194.1133577613783 Content-Type: application/octet-stream; name=interface.rb Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename="interface.rb" require 'curses' # curses sanitization module Curses @windows = Array.new def self.windows @windows end class Window def init(buffer_size = 100, wrap = true) @buffer = Array.new buffer_size, '' @buffer_x = 0 @buffer_y = 0 @cursor_x = 0 @cursor_y = 0 @windows = Array.new @line_wrap = wrap Curses.windows.push self end def [](line_num) @buffer[line_num] end def []=(line_num, line) # TODO: check if data is in screen @buffer[line_num] = line old_setpos(line_num, 0) if @line_wrap && line.length > maxx addstr line[0..maxx] + "\n" addstr line[maxx..line.length] else addstr line end # fill addstr " " * (maxx - line.length) old_setpos(line_num, line.length) end def puts(line) # storage if @cursor_x == @buffer.length-1 @buffer.pop @buffer.push line else @cursor_x += 1 @buffer[@cursor_x] = line end # draw if @line_wrap && line.length > maxx addstr line[0..maxx] + "\n" addstr line[maxx..line.length] else addstr line end end alias :<< :puts def putc(char, y=nil, x=nil) if y == nil y = @cursor_y end if x == nil x = @cursor_x end diff = @buffer[x].length - y if diff < 0 @buffer[y] += " " * diff end @buffer[y][x] << char end alias :putc :addch alias :gets :getstr alias :getc :getch alias :old_refresh :refresh def refresh old_refresh end alias :old_clear :clear def clear setpos(0,0) @buffer.fill('') super end alias :old_setpos :setpos def setpos(y, x) @cursor_y = y @cursor_x = x old_setpos y, x end alias :old_move :move def move(y, x) setpos(@cursor_y + y, @cursor_x + x) end alias :old_subwin :subwin def subwin(height, width, top, left) subwin = old_subwin height, width, top, left subwin.init @windows.push subwin return subwin end alias :old_close :close def close @windows.each do |window| window.close end Curses.windows.delete self Curses.close_screen if Curses.windows.length == 0 old_close end end end module Interface class Cursed def initialize(server) @server = server Signal.trap('INT') do exit end end def run Curses::init_screen # binds curses to the current interface Curses::raw # cbreak or raw, allows direct char handling Curses::noecho # we will manage user output ourselves # keypad(true) # allow handling of the keypad keys Curses::nonl lines = Curses::lines cols = Curses::cols # interface setup @w = Curses::Window.new(lines, cols, 0, 0) @w.init @title = @w.subwin(1, cols, 0, 0) @title[0] = "*** Welcome in zchat ***" @title.refresh @main = @w.subwin(lines-3, cols, 1, 0) @main.scrollok(true) @main.refresh @status = @w.subwin(1, cols, lines-2, 0) @status[0] = @server.hostname + ": " + @server.channel.keys.join(', ') @status.refresh @input = @w.subwin(1, cols, lines-1, 0) @input[0] = ENV['USER']+'@'+@server.hostname+'/#test$ ' @input.refresh @server.channel["#test"].on_read do |line| @main.puts line @main.refresh @input.refresh end # keyboard input handling t = Thread.new do buffer = '' line = @input[0] while true chr = @input.getc case chr when 13 # ?\n case buffer when /^ls/ $server['#test'].puts '/NAMES #test' when /^echo\s/ command = buffer[5..buffer.length-1] @server['#test'].puts command + "\n" if command.length > 0 when /^join\s/ command = buffer[5..buffer.length-1] @server.puts '/j ' + command when '\quit', ':q', 'exit', 'quit' exit else @status[0] = "command not found..." @status.refresh end buffer = '' @input.setpos(0, 0) when 279168 # Curses::KEY_LEFT @input.move(0, -1) when 279167 # Curses::KEY_RIGHT @input.move(0, +1) when ?\C-c exit when ?\C-? # Curses::KEY_BACKSPACE if buffer.length > 1 buffer = buffer[0..buffer.length-2] if buffer.length > 1 @input.move(0, -1) else buffer = '' @input.setpos(0, 0) end else buffer << chr end @input[0] = line + buffer @input.refresh end end t.join end def exit @w.close puts "Exiting zchat..." @server.exit Kernel.exit end end end ------=_Part_6032_7248194.1133577613783--