beniya 0.1.1 → 0.2.0

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: 11ed7079e0eaea122bc96a04729adcab2490b3f111472433b5a13d08f2fc1d9c
4
- data.tar.gz: 4fa0fd0feab300b75ba97b1500b6d80492525cd814bd0a7a402900721746d4df
3
+ metadata.gz: b6ab1b0284a8b86ca20e3ba091dec0f285561c297418b922a436e66721a07e5b
4
+ data.tar.gz: db0b99cb3adf8534dfa89d2110a02079bad81e04b77ef129884e0cd4aa242c5b
5
5
  SHA512:
6
- metadata.gz: ecf5c4c846d7bd17d619bdbd545646d89d9322373f1ba94e024d75d37c7703711aa66179b61b85e4941b538dd967d1d252c8a90f2bfbc063d878f923f907b8b4
7
- data.tar.gz: 4d8ea0a3d7a815b4f83119a847c562dc9d87cf29de40cee238a8e394a4fde2e83588db849fc8b843c31108f2664131a15dd3f550d5ce438337f97326d5c989aa
6
+ metadata.gz: a508d6b782f008de95b1c1bc46f0ab1b3ff371c806d277f4bdb7a493134ea0be3ffd678d5a63ea9916afed0256e05f17e08e62178ee1d84b0636e81554bb3c56
7
+ data.tar.gz: 4474966812a065d193946935e65392eaa18265be92a3d4935655079ce54dc83c07325aa85b05753da0c0d202479e9db62595048028f6e4e9de978aebcef981be
data/README.md CHANGED
@@ -74,12 +74,14 @@ beniya --help # ヘルプメッセージを表示
74
74
  | `o` | 選択中のファイルを外部エディタで開く |
75
75
  | `e` | 現在のディレクトリをファイルエクスプローラーで開く |
76
76
  | `r` | ディレクトリ内容を更新 |
77
+ | `a` | 新しいファイルを作成 |
78
+ | `A` | 新しいディレクトリを作成 |
77
79
 
78
80
  #### リアルタイムフィルター機能
79
81
 
80
82
  | キー | 機能 |
81
83
  | ----------- | ------------------------------------------ |
82
- | `Space` | フィルターモード開始・再編集 |
84
+ | `s` | フィルターモード開始・再編集 |
83
85
  | 文字入力 | ファイル名で絞り込み(フィルターモード中) |
84
86
  | `Enter` | フィルター維持で通常モードに戻る |
85
87
  | `ESC` | フィルターをクリアして通常モードに戻る |
@@ -89,8 +91,8 @@ beniya --help # ヘルプメッセージを表示
89
91
 
90
92
  | キー | 機能 |
91
93
  | ---- | ----------------------------------------- |
92
- | `/` | fzfによるファイル名検索(プレビュー付き) |
93
- | `f` | rgaによるファイル内容検索 |
94
+ | `f` | fzfによるファイル名検索(プレビュー付き) |
95
+ | `F` | rgaによるファイル内容検索 |
94
96
 
95
97
  #### システム操作
96
98
 
@@ -100,36 +102,36 @@ beniya --help # ヘルプメッセージを表示
100
102
 
101
103
  ### フィルター機能の詳細
102
104
 
103
- #### リアルタイムフィルター (`Space`)
105
+ #### リアルタイムフィルター (`s`)
104
106
 
105
- - **フィルター開始**: `Space`キーを押してフィルターモードに入る
107
+ - **フィルター開始**: `s`キーを押してフィルターモードに入る
106
108
  - **文字入力による絞り込み**: 日本語・英数字・記号に対応
107
109
  - **リアルタイム更新**: 文字を入力するたびに表示が更新される
108
110
  - **フィルター維持**: `Enter`キーでフィルターを保持したまま通常操作に戻る
109
111
  - **フィルタークリア**: `ESC`キーでフィルターをクリアして通常表示に戻る
110
- - **再編集**: フィルター適用中に`Space`キーで再編集モード
112
+ - **再編集**: フィルター適用中に`s`キーで再編集モード
111
113
  - **文字削除**: `Backspace`で文字削除、全削除時は自動でフィルタークリア
112
114
 
113
115
  #### 使用例
114
116
 
115
117
  ```
116
- 1. Space → フィルターモード開始
118
+ 1. s → フィルターモード開始
117
119
  2. ".rb" → Rubyファイルのみ表示
118
120
  3. Enter → フィルター維持で通常操作
119
121
  4. j/k → フィルター結果内をナビゲーション
120
- 5. Space → フィルター再編集
122
+ 5. s → フィルター再編集
121
123
  6. ESC → フィルタークリア
122
124
  ```
123
125
 
124
126
  ### 検索機能の詳細
125
127
 
126
- #### ファイル名検索 (`/`)
128
+ #### ファイル名検索 (`f`)
127
129
 
128
130
  - `fzf`を使用したインタラクティブなファイル名検索
129
131
  - リアルタイムプレビュー表示
130
132
  - 選択したファイルは自動で外部エディタで開かれる
131
133
 
132
- #### ファイル内容検索 (`f`)
134
+ #### ファイル内容検索 (`F`)
133
135
 
134
136
  - `rga`(ripgrep-all)を使用した高度なファイル内容検索
135
137
  - PDF、Word文書、画像内テキストなども検索対象
data/README_EN.md CHANGED
@@ -74,12 +74,14 @@ beniya --help # Show help message
74
74
  | `o` | Open selected file with external editor |
75
75
  | `e` | Open current directory in file explorer |
76
76
  | `r` | Refresh directory contents |
77
+ | `a` | Create new file |
78
+ | `A` | Create new directory |
77
79
 
78
80
  #### Real-time Filter
79
81
 
80
82
  | Key | Function |
81
83
  | ----------- | -------------------------------------- |
82
- | `Space` | Start filter mode / Re-edit filter |
84
+ | `s` | Start filter mode / Re-edit filter |
83
85
  | Text input | Filter files by name (in filter mode) |
84
86
  | `Enter` | Keep filter and return to normal mode |
85
87
  | `ESC` | Clear filter and return to normal mode |
@@ -89,8 +91,8 @@ beniya --help # Show help message
89
91
 
90
92
  | Key | Function |
91
93
  | --- | ---------------------------------------- |
92
- | `/` | File name search with fzf (with preview) |
93
- | `f` | File content search with rga |
94
+ | `f` | File name search with fzf (with preview) |
95
+ | `F` | File content search with rga |
94
96
 
95
97
  #### System Operations
96
98
 
@@ -100,36 +102,36 @@ beniya --help # Show help message
100
102
 
101
103
  ### Filter Feature
102
104
 
103
- #### Real-time Filter (`Space`)
105
+ #### Real-time Filter (`s`)
104
106
 
105
- - **Start Filter**: Press `Space` to enter filter mode
107
+ - **Start Filter**: Press `s` to enter filter mode
106
108
  - **Text Input Filtering**: Supports Japanese, English, numbers, and symbols
107
109
  - **Real-time Updates**: Display updates with each character typed
108
110
  - **Keep Filter**: Press `Enter` to maintain filter while returning to normal operations
109
111
  - **Clear Filter**: Press `ESC` to clear filter and return to normal display
110
- - **Re-edit**: Press `Space` again while filter is active to re-edit
112
+ - **Re-edit**: Press `s` again while filter is active to re-edit
111
113
  - **Character Deletion**: Use `Backspace` to delete characters, auto-clear when empty
112
114
 
113
115
  #### Usage Example
114
116
 
115
117
  ```
116
- 1. Space → Start filter mode
118
+ 1. s → Start filter mode
117
119
  2. ".rb" → Show only Ruby files
118
120
  3. Enter → Keep filter, return to normal operations
119
121
  4. j/k → Navigate within filtered results
120
- 5. Space → Re-edit filter
122
+ 5. s → Re-edit filter
121
123
  6. ESC → Clear filter
122
124
  ```
123
125
 
124
126
  ### Search Features
125
127
 
126
- #### File Name Search (`/`)
128
+ #### File Name Search (`f`)
127
129
 
128
130
  - Interactive file name search using `fzf`
129
131
  - Real-time preview display
130
132
  - Selected files automatically open in external editor
131
133
 
132
- #### File Content Search (`f`)
134
+ #### File Content Search (`F`)
133
135
 
134
136
  - Advanced file content search using `rga` (ripgrep-all)
135
137
  - Searches PDFs, Word documents, text in images, and more
data/lib/beniya/config.rb CHANGED
@@ -29,6 +29,15 @@ module Beniya
29
29
  'keybind.search_text' => 'Search text: ',
30
30
  'keybind.no_matches' => 'No matches found.',
31
31
  'keybind.press_any_key' => 'Press any key to continue...',
32
+ 'keybind.input_filename' => 'Enter filename: ',
33
+ 'keybind.input_dirname' => 'Enter directory name: ',
34
+ 'keybind.invalid_filename' => 'Invalid filename (cannot contain / or \\)',
35
+ 'keybind.invalid_dirname' => 'Invalid directory name (cannot contain / or \\)',
36
+ 'keybind.file_exists' => 'File already exists',
37
+ 'keybind.directory_exists' => 'Directory already exists',
38
+ 'keybind.file_created' => 'File created',
39
+ 'keybind.directory_created' => 'Directory created',
40
+ 'keybind.creation_error' => 'Creation error',
32
41
 
33
42
  # UI messages
34
43
  'ui.operation_prompt' => 'Operation: ',
@@ -88,6 +97,15 @@ module Beniya
88
97
  'keybind.search_text' => '検索テキスト: ',
89
98
  'keybind.no_matches' => 'マッチするものが見つかりません。',
90
99
  'keybind.press_any_key' => '何かキーを押して続行...',
100
+ 'keybind.input_filename' => 'ファイル名を入力: ',
101
+ 'keybind.input_dirname' => 'ディレクトリ名を入力: ',
102
+ 'keybind.invalid_filename' => '無効なファイル名(/や\\を含むことはできません)',
103
+ 'keybind.invalid_dirname' => '無効なディレクトリ名(/や\\を含むことはできません)',
104
+ 'keybind.file_exists' => 'ファイルが既に存在します',
105
+ 'keybind.directory_exists' => 'ディレクトリが既に存在します',
106
+ 'keybind.file_created' => 'ファイルを作成しました',
107
+ 'keybind.directory_created' => 'ディレクトリを作成しました',
108
+ 'keybind.creation_error' => '作成エラー',
91
109
 
92
110
  # UI messages
93
111
  'ui.operation_prompt' => '操作: ',
@@ -22,6 +22,13 @@ module Beniya
22
22
  execute_command_with_line(application, file_path, line_number)
23
23
  end
24
24
 
25
+ def open_directory_in_explorer(directory_path)
26
+ return false unless File.exist?(directory_path)
27
+ return false unless File.directory?(directory_path)
28
+
29
+ execute_explorer_command(directory_path)
30
+ end
31
+
25
32
  private
26
33
 
27
34
  def find_application_for_file(file_path)
@@ -109,6 +116,25 @@ module Beniya
109
116
  argument
110
117
  end
111
118
  end
119
+
120
+ def execute_explorer_command(directory_path)
121
+ quoted_path = quote_shell_argument(directory_path)
122
+
123
+ case RbConfig::CONFIG['host_os']
124
+ when /mswin|mingw|cygwin/
125
+ # Windows
126
+ system("explorer #{quoted_path}")
127
+ when /darwin/
128
+ # macOS
129
+ system("open #{quoted_path}")
130
+ else
131
+ # Linux/Unix
132
+ system("xdg-open #{quoted_path}")
133
+ end
134
+ rescue StandardError => e
135
+ warn "ディレクトリを開けませんでした: #{e.message}"
136
+ false
137
+ end
112
138
  end
113
139
  end
114
140
 
@@ -7,6 +7,7 @@ module Beniya
7
7
  def initialize
8
8
  @current_index = 0
9
9
  @directory_listing = nil
10
+ @terminal_ui = nil
10
11
  @file_opener = FileOpener.new
11
12
  @filter_mode = false
12
13
  @filter_query = ""
@@ -19,6 +20,10 @@ module Beniya
19
20
  @current_index = 0
20
21
  end
21
22
 
23
+ def set_terminal_ui(terminal_ui)
24
+ @terminal_ui = terminal_ui
25
+ end
26
+
22
27
  def handle_key(key)
23
28
  return false unless @directory_listing
24
29
 
@@ -44,7 +49,9 @@ module Beniya
44
49
  refresh
45
50
  when 'o' # o
46
51
  open_current_file
47
- when ' ' # Space
52
+ when 'e' # e - open directory in file explorer
53
+ open_directory_in_explorer
54
+ when 's' # s - filter files
48
55
  if !@filter_query.empty?
49
56
  # フィルタが設定されている場合は再編集モードに入る
50
57
  @filter_mode = true
@@ -53,6 +60,8 @@ module Beniya
53
60
  # 新規フィルターモード開始
54
61
  start_filter_mode
55
62
  end
63
+ when ' ' # Space - disabled for future functionality
64
+ false
56
65
  when "\e" # ESC
57
66
  if !@filter_query.empty?
58
67
  # フィルタが設定されている場合はクリア
@@ -63,12 +72,16 @@ module Beniya
63
72
  end
64
73
  when 'q' # q
65
74
  exit_request
66
- when 'e' # e
67
- open_explorer
68
75
  when '/' # /
69
76
  fzf_search
70
- when 'f' # f
77
+ when 'f' # f - file name search with fzf
78
+ fzf_search
79
+ when 'F' # F - file content search with rga
71
80
  rga_search
81
+ when 'a' # a
82
+ create_file
83
+ when 'A' # A
84
+ create_directory
72
85
  else
73
86
  false # #{ConfigLoader.message('keybind.invalid_key')}
74
87
  end
@@ -151,6 +164,9 @@ module Beniya
151
164
  end
152
165
 
153
166
  def refresh
167
+ # ウィンドウサイズを更新して画面を再描画
168
+ @terminal_ui&.refresh_display
169
+
154
170
  @directory_listing.refresh
155
171
  if @filter_mode || !@filter_query.empty?
156
172
  # Re-apply filter with new directory contents
@@ -176,25 +192,16 @@ module Beniya
176
192
  end
177
193
  end
178
194
 
179
- def exit_request
180
- true # request exit
181
- end
182
-
183
- def open_explorer
195
+ def open_directory_in_explorer
184
196
  current_path = @directory_listing&.current_path || Dir.pwd
185
-
186
- case RUBY_PLATFORM
187
- when /darwin/ # macOS
188
- system("open", current_path)
189
- when /linux/ # Linux
190
- system("xdg-open", current_path)
191
- when /mswin|mingw|cygwin/ # Windows
192
- system("explorer", current_path)
193
- end
194
-
197
+ @file_opener.open_directory_in_explorer(current_path)
195
198
  true
196
199
  end
197
200
 
201
+ def exit_request
202
+ true # request exit
203
+ end
204
+
198
205
  def fzf_search
199
206
  return false unless fzf_available?
200
207
 
@@ -328,5 +335,105 @@ module Beniya
328
335
  # 既存メソッド(後方互換用)
329
336
  clear_filter_mode
330
337
  end
338
+
339
+ def create_file
340
+ current_path = @directory_listing&.current_path || Dir.pwd
341
+
342
+ # ファイル名の入力を求める
343
+ print ConfigLoader.message('keybind.input_filename')
344
+ filename = STDIN.gets.chomp
345
+ return false if filename.empty?
346
+
347
+ # 不正なファイル名のチェック
348
+ if filename.include?('/') || filename.include?('\\')
349
+ puts "\n#{ConfigLoader.message('keybind.invalid_filename')}"
350
+ print ConfigLoader.message('keybind.press_any_key')
351
+ STDIN.getch
352
+ return false
353
+ end
354
+
355
+ file_path = File.join(current_path, filename)
356
+
357
+ # ファイルが既に存在する場合の確認
358
+ if File.exist?(file_path)
359
+ puts "\n#{ConfigLoader.message('keybind.file_exists')}"
360
+ print ConfigLoader.message('keybind.press_any_key')
361
+ STDIN.getch
362
+ return false
363
+ end
364
+
365
+ begin
366
+ # ファイルを作成
367
+ File.write(file_path, '')
368
+
369
+ # ディレクトリ表示を更新
370
+ @directory_listing.refresh
371
+
372
+ # 作成したファイルを選択状態にする
373
+ entries = @directory_listing.list_entries
374
+ new_file_index = entries.find_index { |entry| entry[:name] == filename }
375
+ @current_index = new_file_index if new_file_index
376
+
377
+ puts "\n#{ConfigLoader.message('keybind.file_created')}: #{filename}"
378
+ print ConfigLoader.message('keybind.press_any_key')
379
+ STDIN.getch
380
+ true
381
+ rescue => e
382
+ puts "\n#{ConfigLoader.message('keybind.creation_error')}: #{e.message}"
383
+ print ConfigLoader.message('keybind.press_any_key')
384
+ STDIN.getch
385
+ false
386
+ end
387
+ end
388
+
389
+ def create_directory
390
+ current_path = @directory_listing&.current_path || Dir.pwd
391
+
392
+ # ディレクトリ名の入力を求める
393
+ print ConfigLoader.message('keybind.input_dirname')
394
+ dirname = STDIN.gets.chomp
395
+ return false if dirname.empty?
396
+
397
+ # 不正なディレクトリ名のチェック
398
+ if dirname.include?('/') || dirname.include?('\\')
399
+ puts "\n#{ConfigLoader.message('keybind.invalid_dirname')}"
400
+ print ConfigLoader.message('keybind.press_any_key')
401
+ STDIN.getch
402
+ return false
403
+ end
404
+
405
+ dir_path = File.join(current_path, dirname)
406
+
407
+ # ディレクトリが既に存在する場合の確認
408
+ if File.exist?(dir_path)
409
+ puts "\n#{ConfigLoader.message('keybind.directory_exists')}"
410
+ print ConfigLoader.message('keybind.press_any_key')
411
+ STDIN.getch
412
+ return false
413
+ end
414
+
415
+ begin
416
+ # ディレクトリを作成
417
+ Dir.mkdir(dir_path)
418
+
419
+ # ディレクトリ表示を更新
420
+ @directory_listing.refresh
421
+
422
+ # 作成したディレクトリを選択状態にする
423
+ entries = @directory_listing.list_entries
424
+ new_dir_index = entries.find_index { |entry| entry[:name] == dirname }
425
+ @current_index = new_dir_index if new_dir_index
426
+
427
+ puts "\n#{ConfigLoader.message('keybind.directory_created')}: #{dirname}"
428
+ print ConfigLoader.message('keybind.press_any_key')
429
+ STDIN.getch
430
+ true
431
+ rescue => e
432
+ puts "\n#{ConfigLoader.message('keybind.creation_error')}: #{e.message}"
433
+ print ConfigLoader.message('keybind.press_any_key')
434
+ STDIN.getch
435
+ false
436
+ end
437
+ end
331
438
  end
332
439
  end
@@ -21,6 +21,7 @@ module Beniya
21
21
  @keybind_handler = keybind_handler
22
22
  @file_preview = file_preview
23
23
  @keybind_handler.set_directory_listing(@directory_listing)
24
+ @keybind_handler.set_terminal_ui(self)
24
25
 
25
26
  @running = true
26
27
  setup_terminal
@@ -32,6 +33,12 @@ module Beniya
32
33
  end
33
34
  end
34
35
 
36
+ def refresh_display
37
+ # ウィンドウサイズを更新してから画面をクリアして再描画
38
+ update_screen_size
39
+ print "\e[2J\e[H" # clear screen, cursor to home
40
+ end
41
+
35
42
  private
36
43
 
37
44
  def setup_terminal
@@ -41,6 +48,10 @@ module Beniya
41
48
  print "\e[2J\e[H" # clear screen, cursor to home (first time only)
42
49
 
43
50
  # re-acquire terminal size (just in case)
51
+ update_screen_size
52
+ end
53
+
54
+ def update_screen_size
44
55
  console = IO.console
45
56
  return unless console
46
57
 
@@ -1,6 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Beniya
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
6
-
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beniya
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - masisz
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-08-17 00:00:00.000000000 Z
10
+ date: 2025-08-26 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: io-console