Search code examples
rubycommand-line-interfacecurses

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?


Solution

  • 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/