Curses非阻塞输入探索

Mark24Code/curses-examples

我们以 include Curses 的例子为例,这里主要是 设置 timeout=

Sets block and non-blocking reads for the window.

    If delay is negative, blocking read is used (i.e., waits indefinitely for input).

    If delay is zero, then non-blocking read is used (i.e., read returns ERR if no input is waiting).

    If delay is positive, then read blocks for delay milliseconds, and returns ERR if there is still no input.

负数是永远阻塞,0 是非阻塞,正数 则是非阻塞延迟,单位是毫秒。

#!/usr/bin/env ruby
require "curses"
include Curses
init_screen
noecho

stdscr.timeout = 500 # 正数等待 一定时间 unit: ms; 0 不等待; -1 阻塞

trap(0) { echo }

while (c = getch) != ?\e
  if c
    setpos(0, 0)
    addstr("You typed #{c.chr.inspect}")
  else
    p c
  end

  sleep 0.5
end

如果我们想带上 Curses类来工作

require "curses"

Curses.init_screen
Curses.noecho

Curses.stdscr.timeout = 500

win = Curses::Window.new(Curses.lines, Curses.cols, 0, 0)
win.box(0, 0)
win.refresh

count = 0
while (c = Curses.getch) != ?\e
  count += 1
  win.clear
  if c
    win.setpos(0, 0)
    win.addstr("#{count}@#{c.chr.inspect}")
  else
    # do nothing
  end
  win.refresh
  sleep 1.0 / 60
end

在 Curses lib 中除了 Curses 提供的 timeout= ,还有 对 window 子类也提供了 timeout= 这样可以针对具体的 window 下的 getch 来设置。

require "curses"

Curses.init_screen
Curses.noecho

win = Curses::Window.new(Curses.lines, Curses.cols, 0, 0)
win.timeout = 500
win.box(0, 0)
win.refresh

count = 0
while (c = win.getch) != ?\e
  count += 1
  win.clear
  if c
    win.setpos(0, 0)
    win.addstr("#{count}@#{c.chr.inspect}")
  else
    # do nothing
  end
  win.refresh
  sleep 1.0 / 60
end

# 设置 win 的  timeout=,
# win的 getch 也在生效

一旦输入变成非阻塞模式,必须通过循环来读取。

这里设置了count,通过不同频率的count增幅不同可以观察并非同步。

二、特殊覆盖

屏幕是父,在此基础上的 win、subwin …… 他们的设置会覆盖全局设置。

这里 Curses 设置为 100ms 的非阻塞。子类window 对象的设置是 -1 阻塞方式工作。

这里最终 win 上是 阻塞设置进行工作的。

require "curses"

Curses.init_screen
Curses.noecho

Curses.stdscr.timeout = 100

win = Curses::Window.new(Curses.lines, Curses.cols, 0, 0)
win.box(0, 0)
win.timeout = -1 # 这里会和全局冲突
win.refresh

count = 0
while (c = win.getch) != ?\e
  count += 1
  win.clear
  if c
    win.setpos(0, 0)
    win.addstr("#{count}@#{c.chr.inspect}")
  else
    # do nothing
  end
  win.refresh
  sleep 1.0 / 60
end

Mark24

Everything can Mix.