scryglass 0.1.0 → 2.0.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 +4 -4
- data/.DS_Store +0 -0
- data/.irbrc +9 -0
- data/.tool-versions +1 -1
- data/CHANGELOG.md +119 -0
- data/Gemfile +0 -2
- data/Gemfile.lock +18 -14
- data/README.md +54 -18
- data/example_config.rb +13 -3
- data/lib/example_material.rb +1 -1
- data/lib/hexes.rb +1 -1
- data/lib/refinements/ansiless_string_refinement.rb +145 -0
- data/lib/refinements/array_fit_to_refinement.rb +38 -5
- data/lib/refinements/clip_string_refinement.rb +22 -7
- data/lib/scryglass.rb +80 -48
- data/lib/scryglass/binding_tracker.rb +10 -0
- data/lib/scryglass/config.rb +11 -2
- data/lib/scryglass/lens_helper.rb +52 -7
- data/lib/scryglass/lens_panel.rb +47 -23
- data/lib/scryglass/ro.rb +92 -27
- data/lib/scryglass/ro_builder.rb +96 -17
- data/lib/scryglass/session.rb +407 -157
- data/lib/scryglass/session_manager.rb +154 -0
- data/lib/scryglass/tree_panel.rb +42 -15
- data/lib/scryglass/version.rb +1 -1
- data/lib/scryglass/view_panel.rb +43 -1
- data/scryglass.gemspec +8 -4
- metadata +67 -19
@@ -8,11 +8,20 @@ module ArrayFitToRefinement
|
|
8
8
|
length_method = ignore_ansi_codes ? :ansiless_length : :length
|
9
9
|
length_result = string_array.join('').send(length_method)
|
10
10
|
|
11
|
+
if string_array.count < 2
|
12
|
+
return nonplural_solution(string_length_goal,
|
13
|
+
length_result,
|
14
|
+
fill: fill,
|
15
|
+
ignore_ansi_codes: ignore_ansi_codes)
|
16
|
+
end
|
11
17
|
|
12
18
|
if length_result > string_length_goal
|
13
|
-
string_array.compress_to(string_length_goal,
|
19
|
+
string_array.compress_to(string_length_goal,
|
20
|
+
ignore_ansi_codes: ignore_ansi_codes)
|
14
21
|
elsif length_result < string_length_goal
|
15
|
-
string_array.expand_to(string_length_goal,
|
22
|
+
string_array.expand_to(string_length_goal,
|
23
|
+
ignore_ansi_codes: ignore_ansi_codes,
|
24
|
+
fill: fill)
|
16
25
|
else # If it joins to the right length already, we still want to return the expected number of strings.
|
17
26
|
spacers = [''] * (string_array.count - 1)
|
18
27
|
string_array.zip(spacers).flatten.compact
|
@@ -32,9 +41,12 @@ module ArrayFitToRefinement
|
|
32
41
|
longest_string_length = working_array.map { |s| s.send(length_method) }.max
|
33
42
|
slider_index = slider % working_array.count
|
34
43
|
if working_array[slider_index].send(length_method) >= longest_string_length
|
35
|
-
working_array[slider_index]
|
36
|
-
|
37
|
-
|
44
|
+
length_less_one = working_array[slider_index].send(length_method) - 1
|
45
|
+
clipped_by_one = working_array[slider_index].clip_at(
|
46
|
+
length_less_one,
|
47
|
+
ignore_ansi_codes: ignore_ansi_codes
|
48
|
+
)
|
49
|
+
working_array[slider_index] = clipped_by_one
|
38
50
|
end
|
39
51
|
slider += 1
|
40
52
|
end
|
@@ -63,5 +75,26 @@ module ArrayFitToRefinement
|
|
63
75
|
|
64
76
|
working_array.zip(spacers).flatten.compact
|
65
77
|
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def nonplural_solution(string_length_goal,
|
82
|
+
length_result,
|
83
|
+
fill:,
|
84
|
+
ignore_ansi_codes:)
|
85
|
+
return [fill * string_length_goal] if self.empty?
|
86
|
+
|
87
|
+
string_array = self.map(&:to_s) # This also acts to dup
|
88
|
+
|
89
|
+
if length_result > string_length_goal
|
90
|
+
string_array.compress_to(string_length_goal,
|
91
|
+
ignore_ansi_codes: ignore_ansi_codes)
|
92
|
+
elsif length_result < string_length_goal
|
93
|
+
remaining_space = string_length_goal - length_result
|
94
|
+
string_array.append(fill * remaining_space)
|
95
|
+
else # If it joins to the right length already, we still want to return the expected number of strings.
|
96
|
+
self + ['']
|
97
|
+
end
|
98
|
+
end
|
66
99
|
end
|
67
100
|
end
|
@@ -6,21 +6,36 @@ module ClipStringRefinement
|
|
6
6
|
def clip_at(clip_length, ignore_ansi_codes: false)
|
7
7
|
length_method = ignore_ansi_codes ? :ansiless_length : :length
|
8
8
|
original_length = send(length_method)
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
|
10
|
+
clipped_string = if ignore_ansi_codes
|
11
|
+
self.ansi_slice(0...clip_length)
|
12
|
+
else
|
13
|
+
self[0...clip_length]
|
14
|
+
end
|
12
15
|
if clipped_string.send(length_method) < original_length
|
13
|
-
clipped_string =
|
16
|
+
clipped_string =
|
17
|
+
clipped_string.mark_as_abbreviated(ignore_ansi_codes: ignore_ansi_codes)
|
14
18
|
end
|
15
19
|
|
16
20
|
clipped_string
|
17
21
|
end
|
18
22
|
|
23
|
+
def ansiless_clip_at(clip_length)
|
24
|
+
self.clip_at(clip_length, ignore_ansi_codes: true)
|
25
|
+
end
|
26
|
+
|
19
27
|
# Warning: Still not going to work nicely if a string ends in an ansi code!
|
20
|
-
def mark_as_abbreviated
|
28
|
+
def mark_as_abbreviated(ignore_ansi_codes: false)
|
21
29
|
self_dup = dup
|
22
|
-
|
23
|
-
|
30
|
+
|
31
|
+
if ignore_ansi_codes
|
32
|
+
self_dup.ansiless_set!(-1, '…') if self_dup.ansiless_pick(-1)
|
33
|
+
self_dup.ansiless_set!(-2, '…') if self_dup.ansiless_pick(-2)
|
34
|
+
else
|
35
|
+
self_dup[-1] = '…' if self_dup[-1]
|
36
|
+
self_dup[-2] = '…' if self_dup[-2]
|
37
|
+
end
|
38
|
+
|
24
39
|
self_dup
|
25
40
|
end
|
26
41
|
end
|
data/lib/scryglass.rb
CHANGED
@@ -1,17 +1,23 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
## Bookkeeping and external tools:
|
3
|
+
## Bookkeeping
|
5
4
|
require "scryglass/version"
|
6
|
-
|
5
|
+
|
6
|
+
## External tools:
|
7
7
|
require 'io/console'
|
8
|
+
require 'stringio'
|
8
9
|
require 'pp'
|
10
|
+
require 'amazing_print' # For use as a lens
|
11
|
+
require 'method_source' # For use in lens_helper
|
12
|
+
require 'binding_of_caller'
|
13
|
+
require 'timeout'
|
9
14
|
|
10
15
|
## Refinements and sub-tools:
|
11
16
|
require 'refinements/ansiless_string_refinement'
|
12
17
|
require 'refinements/clip_string_refinement'
|
13
18
|
require 'refinements/constant_defined_string_refinement'
|
14
19
|
require 'refinements/array_fit_to_refinement'
|
20
|
+
require 'scryglass/lens_helper'
|
15
21
|
require 'hexes'
|
16
22
|
require 'prog'
|
17
23
|
|
@@ -19,7 +25,9 @@ require 'prog'
|
|
19
25
|
require 'scryglass/config'
|
20
26
|
require 'scryglass/ro'
|
21
27
|
require 'scryglass/ro_builder'
|
28
|
+
require 'scryglass/binding_tracker'
|
22
29
|
require 'scryglass/session'
|
30
|
+
require 'scryglass/session_manager'
|
23
31
|
require 'scryglass/view_wrapper'
|
24
32
|
require 'scryglass/view_panel'
|
25
33
|
require 'scryglass/tree_panel'
|
@@ -27,55 +35,67 @@ require 'scryglass/lens_panel'
|
|
27
35
|
|
28
36
|
## Testing and Demoing:
|
29
37
|
require 'example_material.rb'
|
30
|
-
|
38
|
+
#test
|
31
39
|
module Scryglass
|
32
|
-
HELP_SCREEN = <<~
|
33
|
-
|
40
|
+
HELP_SCREEN = <<~"HELPSCREENPAGE"
|
41
|
+
\e[36mq\e[0m : Quit Scry \e[36m?\e[0m : Cycle help panels (1/2)
|
34
42
|
|
35
43
|
BASIC NAVIGATION: · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
36
44
|
· ·
|
37
|
-
·
|
38
|
-
·
|
39
|
-
·
|
45
|
+
· \e[36mUP / DOWN\e[0m : Navigate (To move further, type a number first or use \e[36mSHIFT\e[0m) ·
|
46
|
+
· \e[36mRIGHT\e[0m : Expand current or selected row(s) ·
|
47
|
+
· \e[36mLEFT\e[0m : Collapse current or selected row(s) ·
|
40
48
|
· ·
|
41
|
-
·
|
49
|
+
· (\e[36mh/j/k/l\e[0m on the home row can also serve as arrow keys) ·
|
50
|
+
· ·
|
51
|
+
· \e[36mENTER\e[0m : Close Scry, returning current or selected object(s) (Key or Value) ·
|
42
52
|
· ·
|
43
53
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
44
54
|
|
45
55
|
INSPECTING WITH LENS VIEW: · · · · · · · · · · · · · ·
|
46
56
|
· ·
|
47
|
-
·
|
48
|
-
·
|
49
|
-
·
|
57
|
+
· \e[36mSPACEBAR\e[0m : Toggle Lens View ·
|
58
|
+
· \e[36m > \e[0m : Cycle through lens types ·
|
59
|
+
· \e[36m < \e[0m : Toggle subject (Key/Value of row) ·
|
50
60
|
· ·
|
51
61
|
· · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
52
62
|
|
53
63
|
MORE NAVIGATION: · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
54
64
|
· ·
|
55
|
-
·
|
56
|
-
· [a][s][d] (
|
65
|
+
· \e[36m [w] \e[0m : Move view window \e[36m0\e[0m : Reset view location ·
|
66
|
+
· \e[36m[a][s][d]\e[0m (\e[36mALT\e[0m increases speed) (Press again: reset cursor) ·
|
57
67
|
· ·
|
58
68
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
59
69
|
HELPSCREENPAGE
|
60
70
|
|
61
|
-
HELP_SCREEN_ADVANCED = <<~
|
62
|
-
|
71
|
+
HELP_SCREEN_ADVANCED = <<~"HELPSCREENADVANCEDPAGE"
|
72
|
+
\e[36mq\e[0m : Quit Scry \e[36m?\e[0m : Cycle help panels (2/2)
|
63
73
|
|
64
74
|
ADVANCED: · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
65
75
|
· DIGGING DEEPER: ·
|
66
76
|
· For current or selected row(s)... ·
|
67
|
-
·
|
68
|
-
·
|
69
|
-
· ( : Attempt to smart-build sub-rows, if Enumerable. Usually '@' is preferable. ·
|
77
|
+
· \e[36m@\e[0m : Build instance variable sub-rows ·
|
78
|
+
· \e[36m.\e[0m : Build ActiveRecord association sub-rows ·
|
79
|
+
· \e[36m(\e[0m : Attempt to smart-build sub-rows, if Enumerable. Usually '@' is preferable. ·
|
80
|
+
· \e[36mo\e[0m : Quick Open: builds the most likely helpful sub-rows ( '.' || '@' || '(' ) ·
|
70
81
|
· ·
|
71
82
|
· SELECTING ROWS: ·
|
72
|
-
·
|
73
|
-
·
|
74
|
-
·
|
83
|
+
· \e[36m*\e[0m : Select/Deselect ALL rows ·
|
84
|
+
· \e[36m|\e[0m : Select/Deselect every sibling row under the same parent row ·
|
85
|
+
· \e[36m-\e[0m : Select/Deselect current row ·
|
86
|
+
· ·
|
87
|
+
· MANAGING MULTIPLE SESSION TABS: ·
|
88
|
+
· \e[36mTab\e[0m : Change session tab (to the right) (\e[36mShift+Tab\e[0m moves left) ·
|
89
|
+
· \e[36mQ\e[0m : Close current session tab ·
|
75
90
|
· ·
|
76
91
|
· TEXT SEARCH: ·
|
77
|
-
·
|
78
|
-
·
|
92
|
+
· \e[36m/\e[0m : Begin a text search (in tree view) ·
|
93
|
+
· \e[36mn\e[0m : Move to next search result ·
|
94
|
+
· ·
|
95
|
+
· ·
|
96
|
+
· \e[36m=\e[0m : Open prompt to type a console handle for current or selected row(s) ·
|
97
|
+
· ·
|
98
|
+
· \e[36mEsc\e[0m : Resets selection, last search, and number-to-move. (or returns to Tree View) ·
|
79
99
|
· ·
|
80
100
|
· · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · · ·
|
81
101
|
HELPSCREENADVANCEDPAGE
|
@@ -94,7 +114,8 @@ module Scryglass
|
|
94
114
|
|
95
115
|
def self.load_silently
|
96
116
|
begin
|
97
|
-
|
117
|
+
add_kernel_method
|
118
|
+
create_scryglass_session_manager
|
98
119
|
{ success: true, error: nil }
|
99
120
|
rescue => e
|
100
121
|
{ success: false, error: e }
|
@@ -127,8 +148,7 @@ module Scryglass
|
|
127
148
|
| > my_object.scry
|
128
149
|
|
|
129
150
|
| To resume the previous session: (in same console session)
|
130
|
-
| > scry
|
131
|
-
| > scry_resume (if you're in a breakpoint pry)
|
151
|
+
| > scry
|
132
152
|
\e[0m
|
133
153
|
CONSOLE_HELP
|
134
154
|
|
@@ -137,39 +157,51 @@ module Scryglass
|
|
137
157
|
|
138
158
|
private
|
139
159
|
|
140
|
-
def self.
|
160
|
+
def self.create_scryglass_session_manager
|
161
|
+
$scry_session_manager = Scryglass::SessionManager.new
|
162
|
+
end
|
163
|
+
|
164
|
+
def self.add_kernel_method
|
141
165
|
Kernel.module_eval do
|
142
|
-
def scry(arg = nil,
|
143
|
-
#
|
166
|
+
def scry(arg = nil, _actions = nil)
|
167
|
+
# `actions` can't be a keyword arg due to this ruby issue:
|
168
|
+
# https://bugs.ruby-lang.org/issues/8316
|
144
169
|
|
145
|
-
|
170
|
+
Scryglass.config.validate!
|
171
|
+
|
172
|
+
current_console_binding = binding.of_caller(1)
|
173
|
+
|
174
|
+
receiver_is_just_the_console = self == current_console_binding.receiver
|
175
|
+
receiver = self unless receiver_is_just_the_console
|
146
176
|
# As in: `receiver.scry`,
|
147
177
|
# and no receiver means scry was called on 'main', (unless self is
|
148
178
|
# different in the because you've pry'd into something!)
|
149
179
|
|
150
180
|
seed_object = arg || receiver
|
151
181
|
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
end
|
159
|
-
|
160
|
-
# For the user, this is mainly just for pry sessions where `self` isn't `main`
|
161
|
-
def scry_resume(actions = nil)
|
162
|
-
Scryglass.config.validate!
|
182
|
+
if seed_object
|
183
|
+
# If it's been given an arg or receiver, create new session!
|
184
|
+
# The global variable is purposeful, and not accessible outside of
|
185
|
+
# the one particular console instance.
|
186
|
+
$scry_session_manager << Scryglass::Session.new(seed_object)
|
187
|
+
end
|
163
188
|
|
164
|
-
|
165
|
-
if no_previous_session
|
189
|
+
unless $scry_session_manager.current_session
|
166
190
|
raise ArgumentError,
|
167
|
-
'`scry` requires either an argument, a receiver, or a past' \
|
191
|
+
'`scry` requires either an argument, a receiver, or a past ' \
|
168
192
|
'session to reopen. try `Scryglass.help`'
|
169
193
|
end
|
170
194
|
|
171
|
-
|
172
|
-
|
195
|
+
$scry_session_manager.track_binding!(current_console_binding)
|
196
|
+
|
197
|
+
begin
|
198
|
+
Hexes.stdout_rescue do
|
199
|
+
$scry_session_manager.run_scry_ui
|
200
|
+
end
|
201
|
+
rescue => e # Here we ensure good visibility in case of errors
|
202
|
+
screen_height, _screen_width = $stdout.winsize
|
203
|
+
$stdout.write "\e[#{screen_height};1H\n" # (Moves console cursor to bottom left corner)
|
204
|
+
raise e
|
173
205
|
end
|
174
206
|
end
|
175
207
|
end
|
data/lib/scryglass/config.rb
CHANGED
@@ -26,16 +26,25 @@ module Scryglass
|
|
26
26
|
self.lenses = [ # Custom lenses can easily be added as name+lambda hashes! Or comment some out to turn them off.
|
27
27
|
{ name: 'Pretty Print (`pp`)',
|
28
28
|
lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { pp o } } },
|
29
|
+
{ name: 'Amazing Print (`ap`)',
|
30
|
+
lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { ap o } } }, # This has colors!
|
29
31
|
{ name: 'Inspect (`.inspect`)',
|
30
32
|
lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { puts o.inspect } } },
|
31
33
|
{ name: 'Yaml Print (`y`)',
|
32
34
|
lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { require 'yaml' ; y o } } }, # OR: `puts o.to_yaml`
|
33
35
|
{ name: 'Puts (`puts`)',
|
34
36
|
lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { puts o } } },
|
35
|
-
|
36
|
-
|
37
|
+
{ name: 'Method Showcase',
|
38
|
+
lambda: ->(o) { Scryglass::LensHelper.method_showcase_for(o) } },
|
37
39
|
]
|
38
40
|
|
41
|
+
## AmazingPrint defaults, if the user has not set their own:
|
42
|
+
::AmazingPrint.defaults ||= {
|
43
|
+
index: false, # (Don't display array indices).
|
44
|
+
raw: true, # (Recursively format instance variables).
|
45
|
+
}
|
46
|
+
# See https://github.com/amazing-print/amazing_print
|
47
|
+
|
39
48
|
## Building ActiveRecord association sub-rows:
|
40
49
|
self.include_empty_associations = true
|
41
50
|
self.include_through_associations = false
|
@@ -2,19 +2,64 @@
|
|
2
2
|
|
3
3
|
module Scryglass
|
4
4
|
module LensHelper
|
5
|
-
def method_showcase_for(object)
|
5
|
+
def self.method_showcase_for(object)
|
6
|
+
# method_list = object.methods - Object.methods
|
6
7
|
method_list = object.methods - Object.methods
|
8
|
+
return '' if method_list.empty?
|
9
|
+
|
7
10
|
label_space = [method_list.map(&:length).max, 45].min
|
8
11
|
method_list.sort.map do |method_name|
|
9
|
-
label = method_name.to_s
|
12
|
+
label = method_name.to_s
|
13
|
+
label_padding = ' ' * [(label_space - label.length), 0].max
|
14
|
+
label = "\e[1;34m#{label}\e[0m" # make blue and bold
|
15
|
+
|
10
16
|
begin
|
11
17
|
method = object.method(method_name)
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
|
19
|
+
method_source_location = method.source_location.to_a.join(':')
|
20
|
+
source_location_line =
|
21
|
+
unless method_source_location.empty?
|
22
|
+
" \e[36m\e[4m#{method_source_location}\e[0m\n" # Cyan, underlined
|
23
|
+
end
|
24
|
+
|
25
|
+
highlighted_space = "\e[7m\s\e[0m"
|
26
|
+
method_lines = Hexes.capture_io { puts method.source }.split("\n")
|
27
|
+
method_lines.prepend('')
|
28
|
+
method_source = method_lines.map do |line|
|
29
|
+
' ' + highlighted_space + line
|
30
|
+
end.join("\n")
|
31
|
+
|
32
|
+
translated_parameters = method.parameters.map do |pair|
|
33
|
+
arg_type = pair[0]
|
34
|
+
arg_name = pair[1]
|
35
|
+
|
36
|
+
case arg_type
|
37
|
+
when :req
|
38
|
+
"#{arg_name}"
|
39
|
+
when :opt
|
40
|
+
"#{arg_name} = ?"
|
41
|
+
when :keyreq
|
42
|
+
"#{arg_name}:"
|
43
|
+
when :key
|
44
|
+
"#{arg_name}: ?"
|
45
|
+
when :rest
|
46
|
+
"*#{arg_name}"
|
47
|
+
when :keyrest
|
48
|
+
"**#{arg_name}"
|
49
|
+
when :block
|
50
|
+
"&#{arg_name}"
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
arg_preview = "(#{translated_parameters.join(', ')})"
|
55
|
+
|
56
|
+
"#{label} #{arg_preview}\n" +
|
57
|
+
source_location_line +
|
58
|
+
"#{method_source}\n"
|
15
59
|
rescue => e
|
16
|
-
label
|
17
|
-
e.message
|
60
|
+
"#{label}#{label_padding} : " \
|
61
|
+
"Error: \e[31m#{e.message}\n\e[0m" +
|
62
|
+
(source_location_line || '')
|
18
63
|
end
|
19
64
|
end.join("\n")
|
20
65
|
end
|
data/lib/scryglass/lens_panel.rb
CHANGED
@@ -51,44 +51,64 @@ module Scryglass
|
|
51
51
|
|
52
52
|
## Here we cut down the (rectangular) display array in both dimensions (into a smaller rectangle), as needed, to fit the view.
|
53
53
|
sliced_lines = split_lines.map do |string|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
# opacify here, I need to account for nils when the view is fully
|
58
|
-
# beyond the shorter lines.
|
54
|
+
string.ansi_slice(current_view_coords[:x], screen_width) || '' # If I
|
55
|
+
# don't want to opacify here, I need to account for nils when the view
|
56
|
+
# is fully beyond the shorter lines.
|
59
57
|
end
|
60
58
|
sliced_list = sliced_lines[current_view_coords[:y], non_header_view_size]
|
61
59
|
|
62
|
-
sliced_list
|
60
|
+
sliced_list
|
63
61
|
end
|
64
62
|
|
65
63
|
def recalculate_y_boundaries
|
66
|
-
|
64
|
+
number_of_lines = uncut_body_string.count("\n") + 1
|
65
|
+
preview_row = 1
|
66
|
+
self.y_boundaries = 0...(number_of_lines + preview_row)
|
67
67
|
end
|
68
68
|
|
69
69
|
def recalculate_x_boundaries
|
70
70
|
_screen_height, screen_width = $stdout.winsize
|
71
71
|
|
72
72
|
split_lines = uncut_body_string.split("\n")
|
73
|
-
length_of_longest_line = split_lines.map(&:
|
73
|
+
length_of_longest_line = split_lines.map(&:ansiless_length).max || 0
|
74
74
|
max_line_length = [length_of_longest_line, screen_width].max
|
75
|
+
preview_column = 1
|
75
76
|
|
76
|
-
self.x_boundaries = 0...max_line_length
|
77
|
+
self.x_boundaries = 0...(max_line_length + preview_column)
|
77
78
|
end
|
78
79
|
|
79
80
|
def current_ro_subheader
|
80
81
|
current_ro = scry_session.current_ro
|
81
|
-
|
82
|
+
last_keypress = scry_session.last_keypress
|
82
83
|
|
83
84
|
row_above_string =
|
84
85
|
current_ro.next_visible_ro_up.to_s if current_ro.next_visible_ro_up
|
85
86
|
row_below_string =
|
86
87
|
current_ro.next_visible_ro_down.to_s if current_ro.next_visible_ro_down
|
87
88
|
|
88
|
-
|
89
|
-
|
89
|
+
tree_preview_related_keys = ::Scryglass::Session::KEY_MAP.slice(
|
90
|
+
:move_cursor_up,
|
91
|
+
:move_cursor_down,
|
92
|
+
:homerow_move_cursor_up,
|
93
|
+
:homerow_move_cursor_down,
|
94
|
+
:homerow_move_cursor_up_fast,
|
95
|
+
:homerow_move_cursor_down_fast,
|
96
|
+
:open_bucket,
|
97
|
+
:close_bucket,
|
98
|
+
:homerow_open_bucket,
|
99
|
+
:homerow_close_bucket,
|
100
|
+
:build_instance_variables,
|
101
|
+
:build_ar_relations,
|
102
|
+
:build_enum_children,
|
103
|
+
:smart_open,
|
104
|
+
:select_siblings,
|
105
|
+
:select_all,
|
106
|
+
:select_current,
|
107
|
+
:continue_search,
|
108
|
+
).values
|
109
|
+
|
90
110
|
ro_view_label =
|
91
|
-
if
|
111
|
+
if tree_preview_related_keys.include?(last_keypress)
|
92
112
|
"\e[7mVIEWING:\e[00m" # Color reversed
|
93
113
|
else
|
94
114
|
'VIEWING:'
|
@@ -108,7 +128,8 @@ module Scryglass
|
|
108
128
|
current_lens = scry_session.current_lens
|
109
129
|
current_subject_type = scry_session.current_subject_type
|
110
130
|
current_subject = scry_session.current_ro.current_subject
|
111
|
-
|
131
|
+
last_keypress = scry_session.last_keypress
|
132
|
+
key_map = ::Scryglass::Session::KEY_MAP
|
112
133
|
|
113
134
|
lens_count = LensPanel.lenses.count
|
114
135
|
lens_id = current_lens % lens_count
|
@@ -117,23 +138,26 @@ module Scryglass
|
|
117
138
|
longest_lens_name_length = LensPanel.lenses.map do |lens|
|
118
139
|
lens[:name].length
|
119
140
|
end.max
|
120
|
-
lens_type_header_length =
|
141
|
+
lens_type_header_length = 13 + (lens_count.to_s.length * 2)
|
121
142
|
+ longest_lens_name_length
|
122
|
-
subject_type_header = "SUBJECT: #{current_subject_type}".ljust(
|
143
|
+
subject_type_header = "[<] SUBJECT: #{current_subject_type}".ljust(18, ' ')
|
123
144
|
subject_class_header = " CLASS: #{current_subject.class}"
|
124
|
-
lens_type_header = " LENS #{lens_id + 1}/#{lens_count}: #{lens[:name]}"
|
145
|
+
lens_type_header = " [>] LENS #{lens_id + 1}/#{lens_count}: #{lens[:name]}"
|
125
146
|
.ljust(lens_type_header_length, ' ')
|
126
147
|
|
148
|
+
user_just_switched_lens = last_keypress == key_map[:switch_lens]
|
149
|
+
user_just_switched_subject_type = last_keypress == key_map[:switch_subject_type]
|
150
|
+
|
151
|
+
if user_just_switched_lens
|
152
|
+
lens_type_header = "\e[7m#{lens_type_header}\e[00m" # Color reversed
|
153
|
+
elsif user_just_switched_subject_type
|
154
|
+
subject_type_header = "\e[7m#{subject_type_header}\e[00m" # Color reversed
|
155
|
+
end
|
156
|
+
|
127
157
|
fit_lens_header = [
|
128
158
|
subject_type_header, subject_class_header, lens_type_header
|
129
159
|
].fit_to(screen_width)
|
130
160
|
|
131
|
-
if user_input == 'l'
|
132
|
-
fit_lens_header[4] = "\e[7m#{fit_lens_header[4]}" # Format to be ended by Hexes.opacify_screen_string() (using \e[00m)
|
133
|
-
elsif user_input == 'L'
|
134
|
-
fit_lens_header[0] = "\e[7m#{fit_lens_header[0]}\e[00m"
|
135
|
-
end
|
136
|
-
|
137
161
|
fit_lens_header.join('')
|
138
162
|
end
|
139
163
|
end
|