rufio 0.82.0 → 0.82.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 12227b8ad934dc15230c756490aa8fff59aaec22a8d535a08bab0598533d52b0
4
- data.tar.gz: 3fe89daae07e436eb27202a6dc3b0852daad7e45a5209a0c5178d139dfe27fc6
3
+ metadata.gz: 95f95e73aa18690cd88f4c18a1c1b4c7d5bccf7a07ba7c507cd569acdc3985e3
4
+ data.tar.gz: c7a636b0fe589fcfa516d3109186e310132bdb478a0357d0542be76239dfc6fc
5
5
  SHA512:
6
- metadata.gz: f614795b114ae1483947331a1f929e43cbf5b57b2e9f05923ccd0c143082836ee00740f43056279761fe36c462c5a40a9f9922de40c6ed72fc7910b332942b72
7
- data.tar.gz: 85c223ae9f1a6c678e65871eafa17fe65ecdb8bf9926a09fc9fa003df6c287f78f45dee76c79fa8b14e51c96c3577969b843b9d9cb62bd5f35e55bf720ea0ef4
6
+ metadata.gz: 5bfda6ac1bdd743ca4c54a5b5e6dc1c72614900ec280a8c972ae14e7effb1cb84d9d693ee4f74115595e5a68a7d8e81ec350a7fd03506ff413257c8d9a270066
7
+ data.tar.gz: 1ab9a355aaf8d5be8f8b66458935886b210fbd2bf17519b1b6793644fe6f0f2f69ccacd5cd376986d0a1dd6be7d0692200da61080172db5a1b6db2c24fd6e6c7
data/CHANGELOG.md CHANGED
@@ -5,6 +5,14 @@ All notable changes to rufio will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.82.1] - 2026-03-07
9
+
10
+ ### Fixed
11
+ - **Windows ESC key in command mode**: Fixed ESC key being silently ignored when exiting command mode on Windows
12
+ - On Windows, `IO.select([STDIN], nil, nil, 0)` with timeout 0 does not reliably detect ESC key events because Windows console handles are not standard file descriptors like on Unix
13
+ - Fix: On Windows, start a background thread that reads bytes from STDIN using blocking `STDIN.read(1)` (which correctly handles ESC via the Windows Console API) and stores them in a Queue; the main loop reads from this Queue non-blockingly instead of using `IO.select` + `read_nonblock`
14
+ - Unix behavior is unchanged
15
+
8
16
  ## [0.82.0] - 2026-02-28
9
17
 
10
18
  ### Added
@@ -185,6 +185,23 @@ module Rufio
185
185
  STDIN.raw!
186
186
  end
187
187
 
188
+ # Windows: IO.select + read_nonblockはコンソールハンドルのESCキーを
189
+ # 検出できない場合がある。バックグラウンドスレッドでSTDINを読み取り
190
+ # Queueに格納することで信頼性のある入力検出を実現する。
191
+ if windows?
192
+ @windows_input_queue = Queue.new
193
+ @windows_input_thread = Thread.new do
194
+ loop do
195
+ begin
196
+ byte = STDIN.read(1)
197
+ @windows_input_queue << byte if byte
198
+ rescue
199
+ break
200
+ end
201
+ end
202
+ end
203
+ end
204
+
188
205
  # re-acquire terminal size (just in case)
189
206
  update_screen_size
190
207
  end
@@ -196,12 +213,37 @@ module Rufio
196
213
  @screen_width, @screen_height = console.winsize.reverse
197
214
  end
198
215
 
216
+ def windows?
217
+ RUBY_PLATFORM =~ /mswin|mingw|cygwin/ ? true : false
218
+ end
219
+
220
+ # Windows: エスケープシーケンスの後続バイトをQueueから短いタイムアウトで読み取る
221
+ # VT対応ターミナルでの矢印キー(\e[A 等)の後続バイト読み取りに使用
222
+ def windows_read_next_byte
223
+ deadline = Process.clock_gettime(Process::CLOCK_MONOTONIC) + 0.005 # 5ms
224
+ loop do
225
+ begin
226
+ return @windows_input_queue.pop(true)
227
+ rescue ThreadError
228
+ return nil if Process.clock_gettime(Process::CLOCK_MONOTONIC) >= deadline
229
+ sleep 0.001
230
+ end
231
+ end
232
+ end
233
+
199
234
  def cleanup_terminal
200
235
  # rawモードを解除
201
236
  if STDIN.tty?
202
237
  STDIN.cooked!
203
238
  end
204
239
 
240
+ # Windowsバックグラウンド入力スレッドを停止
241
+ if @windows_input_thread
242
+ @windows_input_thread.kill rescue nil
243
+ @windows_input_thread = nil
244
+ @windows_input_queue = nil
245
+ end
246
+
205
247
  system('tput rmcup') # normal screen
206
248
  system('tput cnorm') # cursor normal
207
249
  puts ConfigLoader.message('app.terminated')
@@ -383,21 +425,31 @@ module Rufio
383
425
  private
384
426
 
385
427
  # ノンブロッキング入力処理(ゲームループ用)
386
- # IO.selectでタイムアウト付きで入力をチェック
428
+ # Windows: Queueベース、Unix: IO.select + read_nonblock
387
429
  def handle_input_nonblocking
388
- # 0msタイムアウトで即座にチェック(30FPS = 33.33ms/frame)
389
- ready = IO.select([STDIN], nil, nil, 0)
390
- return false unless ready
391
-
392
- begin
393
- # read_nonblockを使ってノンブロッキングで1文字読み取る
394
- input = STDIN.read_nonblock(1)
395
- rescue IO::WaitReadable, IO::EAGAINWaitReadable
396
- # 入力が利用できない
397
- return false
398
- rescue Errno::ENOTTY, Errno::ENODEV
399
- # ターミナルでない環境
400
- return false
430
+ # 入力バイトを1つ読み取る
431
+ if @windows_input_queue
432
+ # Windows: バックグラウンドスレッドのQueueからノンブロッキングで読み取る
433
+ begin
434
+ input = @windows_input_queue.pop(true)
435
+ rescue ThreadError
436
+ return false
437
+ end
438
+ else
439
+ # Unix: 0msタイムアウトで即座にチェック(30FPS = 33.33ms/frame)
440
+ ready = IO.select([STDIN], nil, nil, 0)
441
+ return false unless ready
442
+
443
+ begin
444
+ # read_nonblockを使ってノンブロッキングで1文字読み取る
445
+ input = STDIN.read_nonblock(1)
446
+ rescue IO::WaitReadable, IO::EAGAINWaitReadable
447
+ # 入力が利用できない
448
+ return false
449
+ rescue Errno::ENOTTY, Errno::ENODEV
450
+ # ターミナルでない環境
451
+ return false
452
+ end
401
453
  end
402
454
 
403
455
  # コマンドモードがアクティブな場合は、エスケープシーケンス処理をスキップ
@@ -409,17 +461,17 @@ module Rufio
409
461
 
410
462
  # 特殊キーの処理(エスケープシーケンス)(コマンドモード外のみ)
411
463
  if input == "\e"
412
- next_char = begin
413
- STDIN.read_nonblock(1)
414
- rescue StandardError
415
- nil
464
+ next_char = if @windows_input_queue
465
+ windows_read_next_byte
466
+ else
467
+ STDIN.read_nonblock(1) rescue nil
416
468
  end
417
469
  if next_char == '['
418
470
  # 矢印キーなどのシーケンス
419
- third_char = begin
420
- STDIN.read_nonblock(1)
421
- rescue StandardError
422
- nil
471
+ third_char = if @windows_input_queue
472
+ windows_read_next_byte
473
+ else
474
+ STDIN.read_nonblock(1) rescue nil
423
475
  end
424
476
  input = case third_char
425
477
  when 'A' then 'k' # Up arrow
data/lib/rufio/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rufio
4
- VERSION = '0.82.0'
4
+ VERSION = '0.82.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rufio
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.82.0
4
+ version: 0.82.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - masisz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-02-28 00:00:00.000000000 Z
11
+ date: 2026-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console