rufio 0.90.1 → 0.90.2

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: bd49ffece8a5770afb544c9b8ab5af6a0eba85accad094f7c19c892ae56107fa
4
- data.tar.gz: 0b40bdff2394bfc08902a488be62f141705625ed54304a1c90ae7dc32bcb35a5
3
+ metadata.gz: c00798dbb11b1a2c8d638fed1564515f48d6b8b8e6e1533c54a4a9b9ff889d13
4
+ data.tar.gz: f25b006d69c87f9cc856168b03e12a0d1e35597854ae9e8aaa6e79b37f072423
5
5
  SHA512:
6
- metadata.gz: 3f1d67a559eb62f96ec5b6011ed546b6c7686a1e6299b937f9df31fc862ab3be35dc20c0e7c4b878c22c210578bcf2b82acf968757ac0b04c0a8873b89fcd427
7
- data.tar.gz: cd96a42f6032304e441397b5f5ea1a304ef15656725f80f277c920c2b2ac43f530fea462abba5b7a9170609a969e052c1db4c8d84ae7747e68c5b49608b1ea2e
6
+ metadata.gz: b0cf35c4632d1e3259152ec1ae6276295aa3a34afc9809f7e9ab145634832e2b0e489404603bc6a668a1b1d33dd75ed321acbd75ed616fb9583698c9358d5898
7
+ data.tar.gz: b4eac6784961b3ac937c2518412654d8e2debaeeeb7edbd84101a63d42430461e25659e502ff041b577f35e4f964bb8262b3eea349dc999380bf59be1221b38d
data/CHANGELOG.md CHANGED
@@ -5,6 +5,16 @@ 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.90.2] - 2026-04-11
9
+
10
+ ### Added
11
+ - **Windows mouse support (Windows Terminal)**: Mouse click and scroll now work on Windows Terminal using button-events mode (`\e[?1000h\e[?1006h`) instead of any-event mode (`\e[?1003h`) which is unsupported on Windows
12
+ - Left click, double-click, and wheel scroll are supported (same as Unix)
13
+ - `read_next_mouse_byte` introduced with a 20ms timeout to handle Windows Console's per-byte event queuing for long SGR sequences
14
+ - `cleanup_terminal` sends the matching `\e[?1000l\e[?1006l` on Windows
15
+ - **CI: Windows GitHub Actions**: Added `test-windows` job (`windows-latest`, Ruby 3.2/3.3) running the full test suite plus `test_windows_console_input.rb`
16
+ - Covers ESC key, multibyte input, mouse SGR sequence parsing, and `IO.select` timeout behavior
17
+
8
18
  ## [0.90.1] - 2026-03-28
9
19
 
10
20
  ### Fixed
data/lib/rufio/config.rb CHANGED
@@ -86,7 +86,7 @@ module Rufio
86
86
  'health.windows_opener' => 'Windows file opener',
87
87
  'health.install_brew' => 'Install: brew install',
88
88
  'health.install_apt' => 'Install: apt install',
89
- 'health.install_guide' => 'Check installation guide for your platform',
89
+ 'health.install_guide' => 'Install: Check the installation guide for your platform',
90
90
  'health.rga_releases' => 'Install: https://github.com/phiresky/ripgrep-all/releases',
91
91
  'health.ruby_upgrade_needed' => 'Please upgrade Ruby to version 2.7.0 or higher'
92
92
  },
@@ -156,7 +156,7 @@ module Rufio
156
156
  'health.windows_opener' => 'Windows file opener',
157
157
  'health.install_brew' => 'Install: brew install',
158
158
  'health.install_apt' => 'Install: apt install',
159
- 'health.install_guide' => 'Check installation guide for your platform',
159
+ 'health.install_guide' => 'Install: Check the installation guide for your platform',
160
160
  'health.rga_releases' => 'Install: https://github.com/phiresky/ripgrep-all/releases',
161
161
  'health.ruby_upgrade_needed' => 'Please upgrade Ruby to version 2.7.0 or higher'
162
162
  }
@@ -88,12 +88,13 @@ module Rufio
88
88
  paths.each do |path|
89
89
  next unless Dir.exist?(path)
90
90
 
91
- Dir.foreach(path) do |file|
92
- next if file == '.' || file == '..'
93
-
94
- filepath = File.join(path, file)
95
- # 実行可能なファイルのみを追加
96
- commands << file if File.executable?(filepath) && !File.directory?(filepath)
91
+ begin
92
+ Dir.glob(File.join(path, '*')) do |filepath|
93
+ file = File.basename(filepath)
94
+ commands << file if File.executable?(filepath) && !File.directory?(filepath)
95
+ end
96
+ rescue StandardError
97
+ next
97
98
  end
98
99
  end
99
100
 
@@ -186,8 +186,16 @@ module Rufio
186
186
  STDIN.raw!
187
187
  end
188
188
 
189
- # SGR拡張マウスレポートを有効化(ボタン + ホイール + 任意位置クリック)
190
- print "\e[?1003h\e[?1006h"
189
+ # SGR拡張マウスレポートを有効化
190
+ # Unix: \e[?1003h (any-event) + \e[?1006h (SGR座標) → クリック・スクロール・移動
191
+ # Windows: \e[?1003h は Windows Terminal / conhost 非対応。
192
+ # \e[?1000h (button-events のみ) + \e[?1006h (SGR座標) で
193
+ # Windows Terminal 限定でクリック・スクロールに対応。
194
+ if windows?
195
+ print "\e[?1000h\e[?1006h"
196
+ else
197
+ print "\e[?1003h\e[?1006h"
198
+ end
191
199
  STDOUT.flush
192
200
 
193
201
  # re-acquire terminal size (just in case)
@@ -206,32 +214,27 @@ module Rufio
206
214
  RUBY_PLATFORM =~ /mswin|mingw/ ? true : false
207
215
  end
208
216
 
209
- # Windows: GetNumberOfConsoleInputEvents でコンソール入力バッファを確認する。
210
- # IO.select はWindowsコンソールハンドルでESCキーを取りこぼすため使用しない。
211
- # fiddle はRuby標準ライブラリなので追加gemは不要。
212
- def windows_console_input_available?
213
- require 'fiddle'
214
- @win32_kernel32 ||= Fiddle.dlopen('kernel32')
215
- @win32_get_std_handle ||= Fiddle::Function.new(
216
- @win32_kernel32['GetStdHandle'],
217
- [Fiddle::TYPE_INT], Fiddle::TYPE_VOIDP
218
- )
219
- @win32_get_num_events ||= Fiddle::Function.new(
220
- @win32_kernel32['GetNumberOfConsoleInputEvents'],
221
- [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], Fiddle::TYPE_INT
222
- )
223
- handle = @win32_get_std_handle.call(-10) # STD_INPUT_HANDLE = (DWORD)(-10)
224
- count_ptr = Fiddle::Pointer.malloc(4)
225
- @win32_get_num_events.call(handle, count_ptr)
226
- count_ptr[0, 4].unpack1('L') > 0
227
- rescue Fiddle::DLError
228
- # fiddle が使えない場合は常に入力ありとみなし read_nonblock に任せる
229
- true
217
+ # エスケープシーケンスの後続バイトを読み取る(矢印キー等の短いシーケンス用)。
218
+ # Windows: IO.select(timeout=0) ESCを取りこぼすため 5ms タイムアウトを使用。
219
+ def read_next_input_byte
220
+ if windows?
221
+ return nil unless IO.select([STDIN], nil, nil, 0.005)
222
+ STDIN.read_nonblock(1) rescue nil
223
+ else
224
+ STDIN.read_nonblock(1) rescue nil
225
+ end
230
226
  end
231
227
 
232
- # エスケープシーケンスの後続バイトを読み取る(Windows/Unix共通ヘルパー)
233
- def read_next_input_byte
234
- STDIN.read_nonblock(1) rescue nil
228
+ # SGRマウスシーケンスの後続バイトを読み取る。
229
+ # \e[<Btn;Col;RowM/m は最大 15 バイト程度になるため、
230
+ # Windows Console のイベントキューにバイトが積まれるまで 20ms 待つ。
231
+ def read_next_mouse_byte
232
+ if windows?
233
+ return nil unless IO.select([STDIN], nil, nil, 0.020)
234
+ STDIN.read_nonblock(1) rescue nil
235
+ else
236
+ STDIN.read_nonblock(1) rescue nil
237
+ end
235
238
  end
236
239
 
237
240
  def cleanup_terminal
@@ -240,8 +243,12 @@ module Rufio
240
243
  STDIN.cooked!
241
244
  end
242
245
 
243
- # マウスレポートを無効化
244
- print "\e[?1003l\e[?1006l"
246
+ # マウスレポートを無効化(setup_terminal と対称)
247
+ if windows?
248
+ print "\e[?1000l\e[?1006l"
249
+ else
250
+ print "\e[?1003l\e[?1006l"
251
+ end
245
252
  STDOUT.flush
246
253
 
247
254
  system('tput rmcup') # normal screen
@@ -425,13 +432,15 @@ module Rufio
425
432
  private
426
433
 
427
434
  # ノンブロッキング入力処理(ゲームループ用)
428
- # Windows: GetNumberOfConsoleInputEvents で入力確認後 read_nonblock
435
+ # Windows: IO.select(timeout=1ms) で入力確認後 read_nonblock
436
+ # timeout=0 だとESCキーを取りこぼす(コンソールの処理タイミング競合)ため
437
+ # 1ms の正のタイムアウトを使う。コンソールハンドルでも ConPTY パイプでも動作する。
429
438
  # Unix: IO.select(timeout=0) で入力確認後 read_nonblock
430
439
  def handle_input_nonblocking
431
440
  # 入力バイトを1つ読み取る
432
441
  if windows?
433
- # Windows: IO.selectはESCキーを取りこぼすため Win32 API で入力確認
434
- return false unless windows_console_input_available?
442
+ # Windows: timeout=0 ではESCキーを取りこぼすため 1ms タイムアウトを使用
443
+ return false unless IO.select([STDIN], nil, nil, 0.001)
435
444
  else
436
445
  # Unix: 0msタイムアウトで即座にチェック(30FPS = 33.33ms/frame)
437
446
  return false unless IO.select([STDIN], nil, nil, 0)
@@ -459,9 +468,11 @@ module Rufio
459
468
  third_char = read_next_input_byte
460
469
  if third_char == '<'
461
470
  # SGR拡張マウスイベント: \e[<Btn;Col;RowM/m
471
+ # Windows では各バイトが個別のコンソールイベントとして届くため
472
+ # read_next_mouse_byte(20ms タイムアウト)で読み取る
462
473
  mouse_seq = +""
463
474
  loop do
464
- ch = read_next_input_byte
475
+ ch = read_next_mouse_byte
465
476
  break if ch.nil?
466
477
  mouse_seq << ch
467
478
  break if ch == 'M' || ch == 'm'
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.90.1'
4
+ VERSION = '0.90.2'
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.90.1
4
+ version: 0.90.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - masisz
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-03-28 00:00:00.000000000 Z
11
+ date: 2026-04-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: io-console