如何防止在Curses导航菜单中输入两次?

时间:2017-08-14 00:34:00

标签: ruby curses

我在Curses中创建了一个菜单,用户可以使用键盘上的'w'和's'键或上下箭头在Curses菜单中上下移动。

按下Enter键后,系统命令'ls'被调用。

我遇到的问题是当用户试图移入或移出“选项0”行时,他们必须按箭头键两次。我只希望他们必须像其他选项一样按Enter键。

有没有更好的方法我可以写下面的内容,以便用户只需按一次箭头键移动到另一个选项?

  if position == 0
    draw_info menu, 'You selected option 0'
    input = menu.getch
    if input == 13 # Curses recognizes 13 as Enter being pressed

        Curses.close_screen
        system "clear" or system "cls"
        system 'ls'
        puts "\n\nPress Enter to continue."

这是我的代码:

require 'curses'
include Curses

Curses.init_screen
Curses.curs_set(0)  # Invisible cursor

Curses.start_color

Curses.noecho # echo or noecho to display user input
Curses.cbreak # do not buffer commands until Enter is pressed
Curses.raw # disable interpretation of keyboard input
Curses.nonl
Curses.stdscr.nodelay = 1


begin


  # Building a static window

    def draw_menu(menu, active_index=nil)
      ["This is option 0.", "This is option 1.", "This is option 2.", "This is option 3."].each_with_index do |element, index|
      # "w" for word array
      # It's a shortcut for arrays
        menu.setpos(index + 1, 1)
        menu.attrset(index == active_index ? A_STANDOUT : A_NORMAL)
        menu.addstr("#{index} - %-10s" % element)   # %-Xs makes sure array words line up evenly if you place index after element
                                                    # you can change 17 to another number
      end
      menu.setpos(5, 1)
    end

    def draw_info(menu, text)
      menu.setpos(6, 1)  # sets the position of move up and down
                         # for example, menu.setpos(1, 10) moves to another
                         # location
      menu.attrset(A_NORMAL)
      menu.addstr text
    end

    position = 0

    menu = Window.new(20, 70, 2, 2)  # (height, width, top, left)
    menu.keypad = true  # enable keypad which allows arrow keys
    #menu.box('|', '-')
    draw_menu(menu, position)
    while ch = menu.getch
      stdscr.keypad = true
      case ch
      when KEY_UP, 'w'
        #draw_info menu, 'move up'
        position -= 1
      when KEY_DOWN, '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)
      if position == 0
        draw_info menu, 'You selected option 0'
        input = menu.getch
        if input == 13 # Curses recognizes 13 as Enter being pressed

            Curses.close_screen
            system "clear" or system "cls"
            system 'ls'
            puts "\n\nPress Enter to continue."

        end
      elsif position == 1
        draw_info menu, 'You selected option 1'
      elsif position == 2
        draw_info menu, 'You selected option 2'
      else position == 3
        draw_info menu, 'You selected option 3'
      end       
    end

rescue => ex
  Curses.close_screen
end

修改

这将允许用户只需按一次箭头键,但Curses.close_screen不会关闭屏幕,所以我可以正确运行'ls'。

require 'curses'
include Curses

Curses.init_screen
Curses.curs_set(0)  # Invisible cursor

Curses.start_color

Curses.noecho # echo or noecho to display user input
Curses.cbreak # do not buffer commands until Enter is pressed
Curses.raw # disable interpretation of keyboard input
Curses.nonl
Curses.stdscr.nodelay = 1


begin


  # Building a static window

    def draw_menu(menu, active_index=nil)
      ["This is option 0.", "This is option 1.", "This is option 2.", "This is option 3."].each_with_index do |element, index|
      # "w" for word array
      # It's a shortcut for arrays
        menu.setpos(index + 1, 1)
        menu.attrset(index == active_index ? A_STANDOUT : A_NORMAL)
        menu.addstr("#{index} - %-10s" % element)   # %-Xs makes sure array words line up evenly if you place index after element
                                                    # you can change 17 to another number
      end
      menu.setpos(5, 1)
    end

    def draw_info(menu, text)
      menu.setpos(6, 1)  # sets the position of move up and down
                         # for example, menu.setpos(1, 10) moves to another
                         # location
      menu.attrset(A_NORMAL)
      menu.addstr text
    end

    position = 0

    menu = Window.new(20, 70, 2, 2)  # (height, width, top, left)
    menu.keypad = true  # enable keypad which allows arrow keys
    #menu.box('|', '-')
    draw_menu(menu, position)
    while ch = menu.getch
      stdscr.keypad = true
      case ch
      when KEY_UP, 'w'
        #draw_info menu, 'move up'
        position -= 1
      when KEY_DOWN, 's'
        #draw_info menu, 'move down'
        position += 1
      when 13
        if position.zero?
          # draw_info menu, "You hit enter."
          Curses.close_screen
          system "clear" or system "cls"
          system 'ls'
          puts "\n\nPress Enter to continue."
        end
      when 'x'
        exit
      end
      position = 3 if position < 0
      position = 0 if position > 3
      draw_menu(menu, position)
      draw_info menu, "#{position}"   
    end

rescue => ex
  Curses.close_screen
end

2 个答案:

答案 0 :(得分:1)

为什么不将 Enter 的捕获移动到包含其余键的case语句中?

while ch = menu.getch
  case ch
  when KEY_UP, 'w'
    position -= 1
  when KEY_DOWN, 's'
    position += 1
  when 13
    if position.zero?
      Curses.close_screen
      system "clear" or system "cls"
      system 'ls'
      puts "\n\nPress Enter to continue."
      gets # waits for the user to press enter
    end
  when 'x'
    exit
  end

  position = 3 if position < 0
  position = 0 if position > 3
  draw_menu(menu, position)

  if position == 0
    draw_info menu, 'You selected option 0'
  elsif position == 1
    draw_info menu, 'You selected option 1'
  elsif position == 2
    draw_info menu, 'You selected option 2'
  else position == 3
    draw_info menu, 'You selected option 3'
  end
end

你必须按下2个键才能离开第一个菜单选项的原因是当你'输入'第一个菜单选项时(通过使position等于0),你会那么提示在主循环之外的另一个角色(通过menu.getch)。所以你需要基本上“取消”第一个选项,然后你可以随意移动。

这样做,你移动到第一个菜单选项,继续所有菜单选项需要做的事情,(draw_info调用),然后在主循环中侦听另一个键。在这里,他们可以使用箭头键立即移出选项或按 Enter 。如果他们按Enter键,然后检查他们是否在正确的菜单项上,如果是,则进行ls通话,否则只需忽略该键并继续照常进行。

最后,if/else链只能是一个电话:

draw_info menu, "You selected option #{position}"

答案 1 :(得分:0)

您可以使用ungetch功能将密钥代码推回输入 FIFO

  

curses.ungetch(ch)

     

ch ,以便下一个getch()将返回它。   注意:在调用getch()之前,只能推送一个 ch

实际上,便携式应用程序只能依靠推回一个字符。使用ncurses有一个限制,但它不止一个。