5

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?

Peter Souter
  • 5,110
  • 1
  • 33
  • 62

2 Answers2

6

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/

radubogdan
  • 2,744
  • 1
  • 19
  • 27
2

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
eabraham
  • 4,094
  • 1
  • 23
  • 29