如何防止在 Curses 导航菜单中输入两次?
How to prevent having to get input twice in Curses navigation menu?
我在 Curses 中制作了一个菜单,用户可以使用 'w' 和 's' 键或键盘上的上下箭头在 Curses 菜单中上下移动。
一旦按下回车键,就会调用系统命令'ls'。
我遇到的问题是,当用户尝试移入或移出 'Option 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
您可以使用 ungetch
函数将键码推回输入 FIFO:
curses.ungetch(ch)
Push ch so the next getch()
will return it.
Note: Only one ch can be pushed before getch()
is called.
实际上,可移植应用程序只能依靠推回一个字符。使用 ncurses 有一个限制,但它不止一个。
为什么不将 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 个键才能退出第一个菜单选项的原因是当您 'entered' 第一个菜单选项时(通过使 position
等于 0
) ,然后您将提示输入主循环之外的另一个字符(通过 menu.getch
)。所以你基本上需要 'cancel' 关闭第一个选项,然后你就可以自由移动了。
这样做,您将移动到第一个菜单选项,继续执行所有菜单选项需要执行的操作(draw_info
调用),然后在主循环中监听另一个键。在这里,他们可以使用箭头键立即离开选项或按 Enter。如果他们按 Enter 键,然后您检查他们是否在正确的菜单项上,如果是,则执行您的 ls
调用,否则忽略该键并照常继续。
最后的 if/else
链可能只是一个调用:
draw_info menu, "You selected option #{position}"
我在 Curses 中制作了一个菜单,用户可以使用 'w' 和 's' 键或键盘上的上下箭头在 Curses 菜单中上下移动。
一旦按下回车键,就会调用系统命令'ls'。
我遇到的问题是,当用户尝试移入或移出 'Option 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
您可以使用 ungetch
函数将键码推回输入 FIFO:
curses.ungetch(ch)
Push ch so the next
getch()
will return it. Note: Only one ch can be pushed beforegetch()
is called.
实际上,可移植应用程序只能依靠推回一个字符。使用 ncurses 有一个限制,但它不止一个。
为什么不将 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 个键才能退出第一个菜单选项的原因是当您 'entered' 第一个菜单选项时(通过使 position
等于 0
) ,然后您将提示输入主循环之外的另一个字符(通过 menu.getch
)。所以你基本上需要 'cancel' 关闭第一个选项,然后你就可以自由移动了。
这样做,您将移动到第一个菜单选项,继续执行所有菜单选项需要执行的操作(draw_info
调用),然后在主循环中监听另一个键。在这里,他们可以使用箭头键立即离开选项或按 Enter。如果他们按 Enter 键,然后您检查他们是否在正确的菜单项上,如果是,则执行您的 ls
调用,否则忽略该键并照常继续。
最后的 if/else
链可能只是一个调用:
draw_info menu, "You selected option #{position}"