Search code examples
rubycurses

How to print elements of array line by line and select each individual line with Ruby Curses?


I am currently print lines 0-3 in Ruby Curses. I also created an array with animal names. My program currently outputs

dog + 0cat + 0bird + 0rat + 0
dog + 1cat + 1bird + 1rat + 1
dog + 2cat + 2bird + 2rat + 2
dog + 3cat + 3bird + 3rat + 3

I want it to output something like

dog  + 0
cat  + 1
bird + 2
rat  + 3

Is there a way to list each element of the array on a different line and be able to select each individual line?

Here is the function I am working on

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)

    arr = []
    arr << "dog"
    arr << "cat"
    arr << "bird"
    arr << "rat"

    arr.each do |item|

      menu.addstr "#{item} + #{i}"
    end
  end
end

I have tried using arr.each and arr.each_index but it gives me the same output.

Here is the complete program.

UPDATE

The below makes the menu look how I want but when pressing 'w' or 's' to scroll through the menu, it selects all 4 elements at the same time. Is there a way to make it where only 1 element can be selected at a time?

require "curses"
include Curses

init_screen
start_color
noecho

def draw_menu(menu, active_index=nil)
  4.times do |i|
    menu.setpos(1, 1)
    menu.attrset(i == active_index ? A_STANDOUT : A_NORMAL)

    arr = []
    arr << "dog"
    arr << "cat"
    arr << "bird"
    arr << "rat"

    arr.each_with_index do |element, index|
      menu.addstr "#{element} + #{index}\n"
    end    
  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

Solution

  • Not sure what that 4.times was trying to do, but I think it was setting the same text 4 times into the same position on the screen. For each of the 4, if the current set of 4 items was the same as active_index, you'd set all 4 of them to the same style (A_STANDOUT instead of A_NORMAL).

    What seems to be working for me and what I assume was intended is something like:

    def draw_menu(menu, active_index=nil)
      %w(dog cat bird rat).each_with_index do |element, index|
        menu.setpos(index + 1, 1)
        menu.attrset(index == active_index ? A_STANDOUT : A_NORMAL)
    
        menu.addstr("%-4s + #{index}" % element)
      end
    
      menu.setpos(5, 1) # set the cursor on the line after the menu items
    end
    

    and then in your draw_info I couldn't see where the text was being output, but if I changed it to setpos(5, 1) it became visible on the line after the menu:

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