Cursing Windows
18 February 2015
AKA ‘How On earth do I make a window?!’
This post uses ncurses-ruby I’d recommend looking through some of the examples with the caveat that they are not quite idiomatic Ruby. They are helpful enough to get started.
require 'ncurses'
Ncurses::initscr()
Ncurses::start_color()
Ncurses::noecho()
Ncurses::cbreak()
Ncurses::keypad(Ncurses.stdscr, true)
begin
win = Ncurses::WINDOW.new(10, 10, 10, 10)
win.printw("lol")
win.getch()
rescue => e
raise e
ensure
Ncurses::endwin()
end
First off we’re starting ncurses which has a top level window that other things will be drawn into.
Then we create a sub window with Ncurses::WINDOW.new(height, width, y, x)
and use
win.printw("some_string")
to print into it, and we wait for user input
by using getch
.
Note: x and y refer to the top left corner of the window, also they’re backwards from what you would expect in a normal coordinate. This is repeated in nCurses and has bitten me more than once ;-)
I wrapped up the main window drawing stuff in a begin/ensure because if something exits with an error without ending/cleaning up the main window noecho/cbreak it will bork your terminal! :D. Let’s push this setup into a utility/wrapper so we don’t have to think about it.
If you want to read more about this initial setup/options I mostly just fiddled with what I found at The Linux Documentation Project init section.
require 'ncurses'
class SwearWords
def start_cursing(&block)
set_options
begin
block.call
rescue => exception
raise exception
ensure
Ncurses::endwin()
end
end
private
def set_options
Ncurses::initscr()
Ncurses::start_color()
Ncurses::noecho()
Ncurses::cbreak()
Ncurses::keypad(Ncurses.stdscr, true)
end
end
Later we can maybe come back and setup some way of handing in setup options but for now this will do.
SwearWords.new.start_cursing do
win = Ncurses::WINDOW.new(10, 10, 10, 10)
win.printw("lol")
win.getch
end
We have a window! Super useful right? Let’s see if we can move it around.
SwearWords.new.start_cursing do
win = Ncurses::WINDOW.new(10, 10, 10, 10)
win.printw("lol")
win.getch
win.mvwin(15,15)
win.getch
end
This redraws the window in a new location but the old one is still floating
around :‘(. Turns out what we need here is a call to Ncurses.refresh
SwearWords.new.start_cursing do
win = Ncurses::WINDOW.new(10, 10, 10, 10)
win.printw("lol")
win.getch
win.mvwin(15,15)
Ncurses.refresh
win.getch
end
Currently the text is being written to the (0,0)
location within
the window. To change this we can move the cursor with win.move(y, x)
or
we could do it in one step with win.mvaddstr(y, x, "some_string")
.
SwearWords.new.start_cursing do
win = Ncurses::WINDOW.new(10, 10, 10, 10)
win.mvaddstr(5,2, "lol")
win.getch
win.mvwin(15,15)
Ncurses.refresh
win.getch
end
The last thing I wanted to try was adding borders around the window. This
is easily done by passing 8 0
s as an argument to win.border()
idk = Array.new(8) { 0 }
win.border(*idk)
It’s not ideal, and I have no idea why it works, but this is enough to get started playing with windows. I’ll leave the fiddling with the borders as an exercise for a later post. :-)