log_bench 0.1.3 β 0.1.4
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 +4 -4
- data/README.md +1 -3
- data/lib/log_bench/app/input_handler.rb +16 -9
- data/lib/log_bench/app/main.rb +1 -1
- data/lib/log_bench/app/mouse_handler.rb +104 -0
- data/lib/log_bench/app/renderer/header.rb +3 -1
- data/lib/log_bench/app/screen.rb +5 -0
- data/lib/log_bench/app/state.rb +10 -1
- data/lib/log_bench/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f5ade69636de4054fff54cdb450391a0c238da4349b60be90b3d8faecd80040b
|
4
|
+
data.tar.gz: 7e28cf786b5ba7a54487da0ce6581a24a713eb1449f12127dfd922a7cf294e4f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e2199487aae647d6ea13619a6cc8506e65b2e26d569581b16151cbcde0bad0a674241d463b0d04771c378716e0c55ce3547f4a8d17978e8157925e6ecb0f8850
|
7
|
+
data.tar.gz: c9d41acd6b3497fcef99e326aed6655f02837c2fc6f27c9b2777aa7a76280a953202086566b29aafe5661011053ab61b05dd41d0c563b88daa399ff17a08d7ed
|
data/README.md
CHANGED
@@ -107,7 +107,7 @@ log_bench log/development.log
|
|
107
107
|
|
108
108
|
### Filtering
|
109
109
|
|
110
|
-
Press `f` to open the filter dialog.
|
110
|
+
Press `f` to open the filter dialog.
|
111
111
|
|
112
112
|
In the left pane you can filter by:
|
113
113
|
|
@@ -233,5 +233,3 @@ This gem is available as open source under the terms of the [MIT License](LICENS
|
|
233
233
|
## Support
|
234
234
|
|
235
235
|
- π **Bug reports**: [GitHub Issues](https://github.com/silva96/log_bench/issues)
|
236
|
-
- π‘ **Feature requests**: [GitHub Discussions](https://github.com/silva96/log_bench/discussions)
|
237
|
-
- π **Documentation**: [GitHub Wiki](https://github.com/silva96/log_bench/wiki)
|
@@ -17,15 +17,19 @@ module LogBench
|
|
17
17
|
# UI constants
|
18
18
|
DEFAULT_VISIBLE_HEIGHT = 20
|
19
19
|
|
20
|
-
def initialize(state)
|
20
|
+
def initialize(state, screen)
|
21
21
|
self.state = state
|
22
|
+
self.screen = screen
|
23
|
+
self.mouse_handler = MouseHandler.new(state, screen)
|
22
24
|
end
|
23
25
|
|
24
26
|
def handle_input
|
25
27
|
ch = getch
|
26
28
|
return if ch == -1 || ch.nil?
|
27
29
|
|
28
|
-
if
|
30
|
+
if ch == KEY_MOUSE
|
31
|
+
mouse_handler.handle_mouse_input
|
32
|
+
elsif filter_mode_active?
|
29
33
|
handle_filter_input(ch)
|
30
34
|
else
|
31
35
|
handle_navigation_input(ch)
|
@@ -34,7 +38,7 @@ module LogBench
|
|
34
38
|
|
35
39
|
private
|
36
40
|
|
37
|
-
attr_accessor :state
|
41
|
+
attr_accessor :state, :screen, :mouse_handler
|
38
42
|
|
39
43
|
def filter_mode_active?
|
40
44
|
state.filter_mode || state.detail_filter_mode
|
@@ -44,10 +48,10 @@ module LogBench
|
|
44
48
|
case ch
|
45
49
|
when 10, 13, 27
|
46
50
|
state.exit_filter_mode
|
47
|
-
when
|
51
|
+
when KEY_UP, "k", "K"
|
48
52
|
state.exit_filter_mode
|
49
53
|
state.navigate_up
|
50
|
-
when
|
54
|
+
when KEY_DOWN, "j", "J"
|
51
55
|
state.exit_filter_mode
|
52
56
|
state.navigate_down
|
53
57
|
when 127, 8 # Backspace
|
@@ -89,15 +93,15 @@ module LogBench
|
|
89
93
|
|
90
94
|
def handle_navigation_input(ch)
|
91
95
|
case ch
|
92
|
-
when
|
96
|
+
when KEY_LEFT, "h", "H"
|
93
97
|
state.switch_to_left_pane
|
94
|
-
when
|
98
|
+
when KEY_RIGHT, "l", "L"
|
95
99
|
state.switch_to_right_pane
|
96
100
|
when TAB
|
97
101
|
toggle_pane_focus
|
98
|
-
when
|
102
|
+
when KEY_UP, "k", "K"
|
99
103
|
handle_up_navigation
|
100
|
-
when
|
104
|
+
when KEY_DOWN, "j", "J"
|
101
105
|
handle_down_navigation
|
102
106
|
when CTRL_F
|
103
107
|
handle_page_down
|
@@ -125,6 +129,9 @@ module LogBench
|
|
125
129
|
state.cycle_sort_mode
|
126
130
|
when "q", "Q", CTRL_C
|
127
131
|
state.stop!
|
132
|
+
when "t", "T"
|
133
|
+
state.toggle_text_selection_mode
|
134
|
+
screen.turn_text_selection_mode(state.text_selection_mode?)
|
128
135
|
when ESC
|
129
136
|
handle_escape
|
130
137
|
end
|
data/lib/log_bench/app/main.rb
CHANGED
@@ -0,0 +1,104 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LogBench
|
4
|
+
module App
|
5
|
+
class MouseHandler
|
6
|
+
include Curses
|
7
|
+
|
8
|
+
# UI constants
|
9
|
+
DEFAULT_VISIBLE_HEIGHT = 20
|
10
|
+
|
11
|
+
def initialize(state, screen)
|
12
|
+
self.state = state
|
13
|
+
self.screen = screen
|
14
|
+
end
|
15
|
+
|
16
|
+
def handle_mouse_input
|
17
|
+
with_warnings_suppressed do
|
18
|
+
mouse_event = getmouse
|
19
|
+
|
20
|
+
return unless mouse_event
|
21
|
+
|
22
|
+
if mouse_event.bstate & BUTTON1_CLICKED != 0
|
23
|
+
handle_mouse_click(mouse_event.x, mouse_event.y)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
rescue
|
27
|
+
nil
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
attr_accessor :state, :screen
|
33
|
+
|
34
|
+
def handle_mouse_click(x, y)
|
35
|
+
if click_in_left_pane?(x, y)
|
36
|
+
# Switch to left pane if not already focused
|
37
|
+
state.switch_to_left_pane unless state.left_pane_focused?
|
38
|
+
|
39
|
+
# Convert click coordinates to request index
|
40
|
+
request_index = click_to_request_index(y)
|
41
|
+
return unless request_index
|
42
|
+
|
43
|
+
# Update selection
|
44
|
+
max_index = state.filtered_requests.size - 1
|
45
|
+
state.selected = [request_index, max_index].min
|
46
|
+
state.auto_scroll = false
|
47
|
+
state.adjust_scroll_for_selection(visible_height)
|
48
|
+
elsif click_in_right_pane?(x, y)
|
49
|
+
# Switch to right pane
|
50
|
+
state.switch_to_right_pane unless state.right_pane_focused?
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def click_in_left_pane?(x, y)
|
55
|
+
# Left pane spans from x=0 to panel_width
|
56
|
+
# Header takes up first HEADER_HEIGHT lines
|
57
|
+
# Request list starts at HEADER_HEIGHT + 1 (accounting for border)
|
58
|
+
panel_width = screen.panel_width
|
59
|
+
header_height = 5 # Screen::HEADER_HEIGHT
|
60
|
+
|
61
|
+
x >= 0 && x < panel_width && y > header_height
|
62
|
+
end
|
63
|
+
|
64
|
+
def click_in_right_pane?(x, y)
|
65
|
+
# Right pane starts after left panel + border width
|
66
|
+
# From Screen: panel_width + PANEL_BORDER_WIDTH
|
67
|
+
panel_width = screen.panel_width
|
68
|
+
border_width = 3 # Screen::PANEL_BORDER_WIDTH
|
69
|
+
header_height = 5 # Screen::HEADER_HEIGHT
|
70
|
+
|
71
|
+
right_pane_start = panel_width + border_width
|
72
|
+
|
73
|
+
x >= right_pane_start && y > header_height
|
74
|
+
end
|
75
|
+
|
76
|
+
def click_to_request_index(y)
|
77
|
+
# Header takes up first 5 lines
|
78
|
+
# Request list has 1 line border at top, then 1 line for column headers
|
79
|
+
# So actual request rows start at y = 7 (5 header + 1 border + 1 column header)
|
80
|
+
header_height = 5
|
81
|
+
list_header_offset = 2 # border + column header
|
82
|
+
|
83
|
+
row_in_list = y - header_height - list_header_offset
|
84
|
+
return nil if row_in_list < 0
|
85
|
+
|
86
|
+
# Convert to actual request index accounting for scroll
|
87
|
+
state.scroll_offset + row_in_list
|
88
|
+
end
|
89
|
+
|
90
|
+
def visible_height
|
91
|
+
# Approximate visible height for calculations
|
92
|
+
DEFAULT_VISIBLE_HEIGHT
|
93
|
+
end
|
94
|
+
|
95
|
+
def with_warnings_suppressed
|
96
|
+
old_verbose = $VERBOSE
|
97
|
+
$VERBOSE = nil
|
98
|
+
yield
|
99
|
+
ensure
|
100
|
+
$VERBOSE = old_verbose
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -77,12 +77,14 @@ module LogBench
|
|
77
77
|
header_win.attron(color_pair(3)) { header_win.addstr(state.auto_scroll ? "ON" : "OFF") }
|
78
78
|
header_win.addstr(") | f:Filter | c:Clear filter | s:Sort(")
|
79
79
|
header_win.attron(color_pair(3)) { header_win.addstr(state.sort.display_name) }
|
80
|
+
header_win.addstr(") | t:Text selection(")
|
81
|
+
header_win.attron(color_pair(3)) { header_win.addstr(state.text_selection_mode? ? "ON" : "OFF") }
|
80
82
|
header_win.addstr(") | q:Quit")
|
81
83
|
end
|
82
84
|
|
83
85
|
header_win.setpos(3, 2)
|
84
86
|
header_win.attron(A_DIM) do
|
85
|
-
header_win.addstr("ββ/hl:Switch Pane | ββ/jk:Navigate | g/G:Top/End")
|
87
|
+
header_win.addstr("ββ/hl:Switch Pane | ββ/jk/Click:Navigate | g/G:Top/End")
|
86
88
|
end
|
87
89
|
end
|
88
90
|
|
data/lib/log_bench/app/screen.rb
CHANGED
@@ -29,6 +29,7 @@ module LogBench
|
|
29
29
|
setup_colors
|
30
30
|
clear_screen_immediately
|
31
31
|
setup_windows
|
32
|
+
turn_text_selection_mode(false)
|
32
33
|
end
|
33
34
|
|
34
35
|
def cleanup
|
@@ -54,6 +55,10 @@ module LogBench
|
|
54
55
|
Curses.color_pair(n)
|
55
56
|
end
|
56
57
|
|
58
|
+
def turn_text_selection_mode(enabled)
|
59
|
+
enabled ? mousemask(0) : mousemask(BUTTON1_CLICKED)
|
60
|
+
end
|
61
|
+
|
57
62
|
private
|
58
63
|
|
59
64
|
attr_writer :header_win, :log_win, :panel_width, :detail_win
|
data/lib/log_bench/app/state.rb
CHANGED
@@ -4,7 +4,7 @@ module LogBench
|
|
4
4
|
module App
|
5
5
|
class State
|
6
6
|
attr_reader :main_filter, :sort, :detail_filter
|
7
|
-
attr_accessor :requests, :auto_scroll, :scroll_offset, :selected, :detail_scroll_offset
|
7
|
+
attr_accessor :requests, :auto_scroll, :scroll_offset, :selected, :detail_scroll_offset, :text_selection_mode
|
8
8
|
|
9
9
|
def initialize
|
10
10
|
self.requests = []
|
@@ -14,6 +14,7 @@ module LogBench
|
|
14
14
|
self.running = true
|
15
15
|
self.focused_pane = :left
|
16
16
|
self.detail_scroll_offset = 0
|
17
|
+
self.text_selection_mode = false
|
17
18
|
self.main_filter = Filter.new
|
18
19
|
self.detail_filter = Filter.new
|
19
20
|
self.sort = Sort.new
|
@@ -31,6 +32,14 @@ module LogBench
|
|
31
32
|
self.auto_scroll = !auto_scroll
|
32
33
|
end
|
33
34
|
|
35
|
+
def toggle_text_selection_mode
|
36
|
+
self.text_selection_mode = !text_selection_mode
|
37
|
+
end
|
38
|
+
|
39
|
+
def text_selection_mode?
|
40
|
+
text_selection_mode
|
41
|
+
end
|
42
|
+
|
34
43
|
def clear_filter
|
35
44
|
main_filter.clear
|
36
45
|
self.selected = 0
|
data/lib/log_bench/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: log_bench
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- BenjamΓn Silva
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-06-
|
10
|
+
date: 2025-06-07 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: zeitwerk
|
@@ -114,6 +114,7 @@ files:
|
|
114
114
|
- lib/log_bench/app/input_handler.rb
|
115
115
|
- lib/log_bench/app/main.rb
|
116
116
|
- lib/log_bench/app/monitor.rb
|
117
|
+
- lib/log_bench/app/mouse_handler.rb
|
117
118
|
- lib/log_bench/app/renderer/ansi.rb
|
118
119
|
- lib/log_bench/app/renderer/details.rb
|
119
120
|
- lib/log_bench/app/renderer/header.rb
|