Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Curses array browsing with keyboard in Ruby

I'm trying to make a cli app in Ruby that takes a given array then then displays it as a list that I can browse with the arrow keys.

I feel like I've already seen a library in Ruby that does this already, but I can't remember the name of it.

I'm trying to reverse engineer the code from soundcloud2000 to do something similar, but his code is tightly-coupled to the use of the Soundcloud API.

I'm aware of the curses gem, I'm thinking with something with more abstraction.Ad

Has anyone seen a library that does it or some proof of concept Ruby code that could do this?

like image 826
Peter Souter Avatar asked Jan 05 '15 00:01

Peter Souter


People also ask

How do I release a new version of curses in Ruby?

To release a new version, update the version number in curses.gemspec, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org. curses is released under the Ruby and 2-clause BSD licenses.

Does Ruby 9c5b2fd require curses?

Formerly part of the Ruby standard library, curses was removed and placed in this gem with the release of Ruby 2.1.0. (see ruby/ruby@9c5b2fd) Requires ncurses or ncursesw (with wide character support).

What is a ruby binding for curses?

A Ruby binding for curses, ncurses, and PDCurses. curses is an extension library for text UI applications. Formerly part of the Ruby standard library, curses was removed and placed in this gem with the release of Ruby 2.1.0. (see ruby/ruby@9c5b2fd) Requires ncurses or ncursesw (with wide character support).

What happened to the Ruby curses library?

Formerly part of the Ruby standard library, curses was removed and placed in this gem with the release of Ruby 2.1.0. (see ruby/ruby@9c5b2fd) Requires ncurses or ncursesw (with wide character support). On Debian based distributions, you can install it with apt:


2 Answers

I don't know if this is what you are looking for but maybe you can use my idea.

Since I don't have more information of what you are trying to accomplish, what is your input and so on, this example will be very simple.

Let's say we have a class to work with called PlaylistDemo that will create a playlist with songs:

class PlaylistDemo
  attr_accessor :position

  def initialize songs
    @playlist = Array.new
    songs.each { |song| @playlist << song }
    @position = 0
  end

  def show_playlist
    @playlist.each_with_index.map do |song, index|
      position == index ? "[#{song}]" : " #{song} "
    end
  end

end

Prepare some songs:

# From billboard.com
songs = [
  "Taylor Swift -  Blank Space",
  "Mark Ronson Featuring Bruno Mars -  Uptown Funk!",
  "Hozier -  Take Me To Church",
  "Meghan Trainor - Lips Are Movin",
  "Meghan Trainor -  All About That Bass"
]

And go ahead and make an object:

pd = PlaylistDemo.new(songs)

Now my idea is to use dispel to manipulate position and see exactly where you are (and update the "UI" accordingly).

For this I've prepared a function that will make the UI for your CLI application:

def show_ui playlist_obj
  ["\n", playlist_obj.show_playlist, "\nCurrent position: #{playlist_obj.position + 1} "].join("\n")
end

Final piece of code:

Dispel::Screen.open do |screen|
  screen.draw show_ui(pd)

  Dispel::Keyboard.output do |key|
    case key
    when :up then pd.position -= 1
    when :down then pd.position += 1
    when "q" then break
    end

    screen.draw show_ui(pd)
  end
end

You can also use colorize but for that you'll need puts somewhere.

Please not that I didn't set a limit for position since this is only an example.

See my example here:

Full code: http://paste.debian.net/139651/

like image 57
radubogdan Avatar answered Sep 20 '22 23:09

radubogdan


You are looking for the curses ruby gem.

Example of menu created by @phoet.

require "curses"
include Curses

init_screen
start_color
noecho

def draw_menu(menu, active_index=nil)
  4.times do |i|
    menu.setpos(i + 1, 1)
    menu.attrset(i == active_index ? A_STANDOUT : A_NORMAL)
    menu.addstr "item_#{i}"
  end
end

def draw_info(menu, text)
  menu.setpos(1, 10)
  menu.attrset(A_NORMAL)
  menu.addstr text
end

position = 0

menu = Window.new(7,40,7,2)
menu.box('|', '-')
draw_menu(menu, position)
while ch = menu.getch
  case ch
  when 'w'
    draw_info menu, 'move up'
    position -= 1
  when 's'
    draw_info menu, 'move down'
    position += 1
  when 'x'
    exit
  end
  position = 3 if position < 0
  position = 0 if position > 3
  draw_menu(menu, position)
end
like image 20
eabraham Avatar answered Sep 18 '22 23:09

eabraham