beniya 0.5.1 → 0.6.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.
@@ -4,14 +4,43 @@ require 'io/console'
4
4
 
5
5
  module Beniya
6
6
  class TerminalUI
7
+ # Layout constants
8
+ HEADER_HEIGHT = 2 # Header占有行数
9
+ FOOTER_HEIGHT = 1 # Footer占有行数
10
+ HEADER_FOOTER_MARGIN = 4 # Header + Footer分のマージン
11
+
12
+ # Panel layout ratios
13
+ LEFT_PANEL_RATIO = 0.5 # 左パネルの幅比率
14
+ RIGHT_PANEL_RATIO = 1.0 - LEFT_PANEL_RATIO
15
+
16
+ # Display constants
17
+ DEFAULT_SCREEN_WIDTH = 80 # デフォルト画面幅
18
+ DEFAULT_SCREEN_HEIGHT = 24 # デフォルト画面高さ
19
+ HEADER_PADDING = 2 # ヘッダーのパディング
20
+ BASE_INFO_RESERVED_WIDTH = 20 # ベースディレクトリ表示の予約幅
21
+ BASE_INFO_MIN_WIDTH = 10 # ベースディレクトリ表示の最小幅
22
+ FILTER_TEXT_RESERVED = 15 # フィルタテキスト表示の予約幅
23
+
24
+ # File display constants
25
+ ICON_SIZE_PADDING = 12 # アイコン、選択マーク、サイズ情報分
26
+ CURSOR_OFFSET = 1 # カーソル位置のオフセット
27
+
28
+ # Size display constants (bytes)
29
+ KILOBYTE = 1024
30
+ MEGABYTE = KILOBYTE * 1024
31
+ GIGABYTE = MEGABYTE * 1024
32
+
33
+ # Line offsets
34
+ CONTENT_START_LINE = 3 # コンテンツ開始行(ヘッダー2行スキップ)
35
+
7
36
  def initialize
8
37
  console = IO.console
9
38
  if console
10
39
  @screen_width, @screen_height = console.winsize.reverse
11
40
  else
12
41
  # fallback values (for test environments etc.)
13
- @screen_width = 80
14
- @screen_height = 24
42
+ @screen_width = DEFAULT_SCREEN_WIDTH
43
+ @screen_height = DEFAULT_SCREEN_HEIGHT
15
44
  end
16
45
  @running = false
17
46
  end
@@ -83,9 +112,9 @@ module Beniya
83
112
  entries = get_display_entries
84
113
  selected_entry = entries[@keybind_handler.current_index]
85
114
 
86
- # calculate height with header (2 lines) and footer margin
87
- content_height = @screen_height - 4 # ヘッダー(2行)とフッター分を除く
88
- left_width = @screen_width / 2
115
+ # calculate height with header and footer margin
116
+ content_height = @screen_height - HEADER_FOOTER_MARGIN
117
+ left_width = (@screen_width * LEFT_PANEL_RATIO).to_i
89
118
  right_width = @screen_width - left_width
90
119
 
91
120
  # adjust so right panel doesn't overflow into left panel
@@ -112,14 +141,14 @@ module Beniya
112
141
  end
113
142
 
114
143
  # abbreviate if path is too long
115
- if header.length > @screen_width - 2
144
+ if header.length > @screen_width - HEADER_PADDING
116
145
  if @keybind_handler.filter_active?
117
146
  # prioritize showing filter when active
118
147
  filter_text = " [Filter: #{@keybind_handler.filter_query}]"
119
- base_length = @screen_width - filter_text.length - 15
148
+ base_length = @screen_width - filter_text.length - FILTER_TEXT_RESERVED
120
149
  header = "📁 beniya - ...#{current_path[-base_length..-1]}#{filter_text}"
121
150
  else
122
- header = "📁 beniya - ...#{current_path[-(@screen_width - 15)..-1]}"
151
+ header = "📁 beniya - ...#{current_path[-(@screen_width - FILTER_TEXT_RESERVED)..-1]}"
123
152
  end
124
153
  end
125
154
 
@@ -143,15 +172,15 @@ module Beniya
143
172
  end
144
173
 
145
174
  # 長すぎる場合は省略
146
- if base_info.length > @screen_width - 2
175
+ if base_info.length > @screen_width - HEADER_PADDING
147
176
  if base_info.include?(" | Selected:")
148
177
  selected_part = base_info.split(" | Selected:").last
149
- available_length = @screen_width - 20 - " | Selected:#{selected_part}".length
178
+ available_length = @screen_width - BASE_INFO_RESERVED_WIDTH - " | Selected:#{selected_part}".length
150
179
  else
151
- available_length = @screen_width - 20
180
+ available_length = @screen_width - BASE_INFO_RESERVED_WIDTH
152
181
  end
153
182
 
154
- if available_length > 10
183
+ if available_length > BASE_INFO_MIN_WIDTH
155
184
  # パスの最後の部分を表示
156
185
  dir_part = base_info.split(": ").last.split(" | ").first
157
186
  short_base_dir = "...#{dir_part[-available_length..-1]}"
@@ -170,7 +199,7 @@ module Beniya
170
199
 
171
200
  (0...height).each do |i|
172
201
  entry_index = start_index + i
173
- line_num = i + 3 # skip header (2 lines)
202
+ line_num = i + CONTENT_START_LINE
174
203
 
175
204
  print "\e[#{line_num};1H" # set cursor position
176
205
 
@@ -181,7 +210,7 @@ module Beniya
181
210
  draw_entry_line(entry, width, is_selected)
182
211
  else
183
212
  # 左ペイン専用の安全な幅で空行を出力
184
- safe_width = [width - 1, @screen_width / 2 - 1].min
213
+ safe_width = [width - CURSOR_OFFSET, (@screen_width * LEFT_PANEL_RATIO).to_i - CURSOR_OFFSET].min
185
214
  print ' ' * safe_width
186
215
  end
187
216
  end
@@ -192,14 +221,14 @@ module Beniya
192
221
  icon, color = get_entry_display_info(entry)
193
222
 
194
223
  # 左ペイン専用の安全な幅を計算(右ペインにはみ出さないよう)
195
- safe_width = [width - 1, @screen_width / 2 - 1].min
224
+ safe_width = [width - CURSOR_OFFSET, (@screen_width * LEFT_PANEL_RATIO).to_i - CURSOR_OFFSET].min
196
225
 
197
226
  # 選択マークの追加
198
227
  selection_mark = @keybind_handler.is_selected?(entry[:name]) ? "✓ " : " "
199
228
 
200
229
  # ファイル名(必要に応じて切り詰め)
201
230
  name = entry[:name]
202
- max_name_length = safe_width - 12 # アイコン、選択マーク、サイズ情報分を除く
231
+ max_name_length = safe_width - ICON_SIZE_PADDING
203
232
  name = name[0...max_name_length - 3] + '...' if max_name_length > 0 && name.length > max_name_length
204
233
 
205
234
  # サイズ情報
@@ -260,22 +289,22 @@ module Beniya
260
289
  def format_size(size)
261
290
  return ' ' if size == 0
262
291
 
263
- if size < 1024
292
+ if size < KILOBYTE
264
293
  "#{size}B".rjust(6)
265
- elsif size < 1024 * 1024
266
- "#{(size / 1024.0).round(1)}K".rjust(6)
267
- elsif size < 1024 * 1024 * 1024
268
- "#{(size / (1024.0 * 1024)).round(1)}M".rjust(6)
294
+ elsif size < MEGABYTE
295
+ "#{(size / KILOBYTE.to_f).round(1)}K".rjust(6)
296
+ elsif size < GIGABYTE
297
+ "#{(size / MEGABYTE.to_f).round(1)}M".rjust(6)
269
298
  else
270
- "#{(size / (1024.0 * 1024 * 1024)).round(1)}G".rjust(6)
299
+ "#{(size / GIGABYTE.to_f).round(1)}G".rjust(6)
271
300
  end
272
301
  end
273
302
 
274
303
  def draw_file_preview(selected_entry, width, height, left_offset)
275
304
  (0...height).each do |i|
276
- line_num = i + 3 # skip header (2 lines)
305
+ line_num = i + CONTENT_START_LINE
277
306
  # カーソル位置を左パネルの右端に設定
278
- cursor_position = left_offset + 1
307
+ cursor_position = left_offset + CURSOR_OFFSET
279
308
 
280
309
  # 画面の境界を厳密に計算
281
310
  max_chars_from_cursor = @screen_width - cursor_position
@@ -450,7 +479,7 @@ module Beniya
450
479
 
451
480
  def draw_footer
452
481
  # 最下行から1行上に表示してスクロールを避ける
453
- footer_line = @screen_height - 1
482
+ footer_line = @screen_height - FOOTER_HEIGHT
454
483
  print "\e[#{footer_line};1H"
455
484
 
456
485
  if @keybind_handler.filter_active?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Beniya
4
- VERSION = '0.5.1'
4
+ VERSION = '0.6.1'
5
5
  end
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.5.1
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - masisz
8
8
  bindir: bin
9
9
  cert_chain: []
10
- date: 2025-09-23 00:00:00.000000000 Z
10
+ date: 2025-10-19 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: io-console
@@ -119,6 +119,7 @@ files:
119
119
  - CHANGELOG.md
120
120
  - CHANGELOG_v0.4.0.md
121
121
  - CHANGELOG_v0.5.0.md
122
+ - CHANGELOG_v0.6.0.md
122
123
  - README.md
123
124
  - README_EN.md
124
125
  - Rakefile