scryglass 2.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 69ff16003c6e5b4ceb6e93e9c5f9ee8aed269b50954db3869963fdf9ab64215b
4
- data.tar.gz: 6d5c2f92d50b86a1e837033646b7793ee08e5115df98c47c2772775132875337
3
+ metadata.gz: 8ad4ef5f3d5410c0e51263df62ce42683e10f6434222dca7952796a32fac75d2
4
+ data.tar.gz: 7018ee7c1fce2ef08f6f82769bd2644c62138bfcb60cde986143b36ec582f504
5
5
  SHA512:
6
- metadata.gz: 2f76204b2d6a0e67901e5cee79c5b4a1dcbe7fd08bf03c289cc95268b6e562d86bc49804f215a476e2239a7dfa388e66771c2ad1b1206b23b0b16aeee00607a1
7
- data.tar.gz: 25171585025b50992b202bff43a881715a11cb7e48c0cfef522281357ea9d2de0de2b584446ba36d979fce45eba7509b69531118f98ce55d3b02c03c5534129e
6
+ metadata.gz: 3bf1c0efce7dac36445bb2daaea5fdff89fc7390999694994d88a1f7f8f9854c63a4ec436f4e6b911d2438542cb3ac8a7f7fc7fdeb7d8aacbbee3e693f8201f4
7
+ data.tar.gz: f836192852e3115f85fa8e8807da0fa8053e81e510730144097f5eae24ad803b536887ea45ece8a103389fe87e1f7ca824b1710d780d9eb46466f9ed81981af0
data/CHANGELOG.md CHANGED
@@ -11,18 +11,31 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## Changed
13
13
 
14
+ ## Removed
15
+
14
16
  ## Fixed
15
17
 
16
- ## [2.0.2] - 2020-01-14
18
+ ## [2.1.0] - 2021-03-21
17
19
 
18
20
  ## Added
19
21
 
22
+ - Can now press `t`/`T` to create a new tab (or restart current tab) using the current/selected object(s) as the seed object.
23
+ - Can now press `c` to enter custom eval/method text to call on the current/selected object(s), producing a navigable sub-row(s) with the returned object(s).
24
+
20
25
  ## Changed
21
26
 
22
- - Added a default character limit to the method_showcase_for lens to speed it up (Some AR objects have over 1000 methods).
27
+ - Substantial speed improvements for large object sets.
23
28
 
24
29
  ## Fixed
25
30
 
31
+ - Fixed broken method_showcase_for (frozen string error).
32
+
33
+ ## [2.0.2] - 2020-01-14
34
+
35
+ ## Changed
36
+
37
+ - Added a default character limit to the method_showcase_for lens to speed it up (Some AR objects have over 1000 methods).
38
+
26
39
  ## [2.0.1] - 2020-01-13
27
40
 
28
41
  ## Changed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- scryglass (2.0.2)
4
+ scryglass (2.1.0)
5
5
  amazing_print
6
6
  binding_of_caller
7
7
  method_source
data/README.md CHANGED
@@ -159,11 +159,14 @@ Scryglass has two features to make wait time a little easier:
159
159
  | `.` | Build ActiveRecord association sub-rows for current or selected row(s) | If the `ActiveRecord` constant is not defined by the system, this will do nothing. If it is, this will navigate the reflections of the the class of the object (or value of a key-value pair) in order to find its AR Associations and turn them into key-value sub-items. Note: With the default configuration, the way it uses reflections *purposefully ignores `:through` relations and `scope`d relations (e.g. the extraneous `CURRENT_phone_numbers`).* Note: The `·` cursor indicator does not take the time to traverse all reflections, nor account for all configured filters. It's possible that `.` will produce no sub-rows despite the indicator. |
160
160
  | `(` | Attempt to smart-build sub-rows for current or selected row(s), if Enumerable. Usually '@' is preferable | Attempts a "smart reading" of the object (or value of a key-value pair) of the current or selected rows. If the object is an Enumerable, it will attempt to parse it into sub-items. if the object has keys, it will be parsed as key-value pairs like a hash, otherwise singular objects like an array. This can sometimes create sub-items that would otherwise be more neatly accesible under a single instance variable if instance variables are built instead, so default to trying that first. |
161
161
  | `o` | Quick Open: builds the most likely helpful sub-rows ( '.' \|\| '@' \|\| '(' ) | "Quick Open" first tries opening AR Associations. If none are produced, it tries for instance variables. If none are produced, it attempts to open as it would an unknown Enumerable type. Can be pressed repeatedly to produce all types of sub-rows. |
162
+ | `c` | Enter method text to call on object(s), results becomes navigable sub-rows | The text is eval'd, and allows formats like (obj)`.count(nil)` & (obj)`[:test].select { |s| s.include?(@named_string) }`. The execution CAN be used to mutate/destroy objects, though the rows representing those objects, and lenses which were already loaded for it, won't change (this is available but not formally supported). |
162
163
  | `*` | Select/Deselect ALL rows | This includes hidden rows. If all rows are already selected, they will be unselected, regardless of how they became selected. |
163
164
  | `\|` | Select/Deselect every sibling row under the same parent row | If all siblings under that parent row are already selected, they will be unselected, regardless of how they became selected. |
164
165
  | `-` | Select/Deselect current row | If these objects are later returned, the order in which they were selected will determine their order in the returned array. |
165
166
  | `Tab` | Change session tab (to the right) (`Shift`+`Tab` moves left) | Changes which scry session is the current one, and brings up the tab bar for a couple seconds. |
166
- | `Q` | Close current session tab | Permanently exits the current session tab, but keeps scry running if another tab remains. Switches one tab to left if there is one.
167
+ | `Q` | Close current session tab | Permanently exits the current session tab, but keeps scry running if another tab remains. Switches one tab to left if there is one. |
168
+ | `t` | Open new session tab with current or selected row(s) as the seed | The seed subject of the tab will either be the current row's subject or an array of the selected rows' subjects. |
169
+ | `T` | Restart session tab with current or selected row(s) as the seed | This will delete the current session tab and replace it. The seed subject of the new tab will either be the current row's subject or an array of the selected rows' subjects. This can be useful for managing memory load. |
167
170
  | `/` | Begin a text search (in tree view) | Begins a case-sensitive regex search of all items, in a loop, starting with just below the current row. For a matching object to be found, the search must match its *truncated sample string in tree view* (regardless of what is on or off screen) (it must match either the key or the value, not the full line they create) (known enumerable types, like `[•••]`, may count as a match if they contain the string in the backend). |
168
171
  | `n` | Move to next search result | Will, using the most recent search entry, move the cursor on to the next match downward, cycling through all rows. This follows the same matching rules as the original search. |
169
172
  | `=` | Open prompt to type a console handle for current or selected row(s) | Gets text from user (not including the '@') and saves the current subject, or array of selected row(s) subjects, under that instance variable name. These variables live in the console itself: the binding of wherever `scry` was called. Care is taken not to allow them to conflict with preexisting IV names or method names. Note: But still, if you are prying inside an object/context, your IVs will be defined on that object. Note: If you switch from one pry context to another and then back, your first pry's instance variables will be there despite not being listed in the IV outro message. |
data/lib/scryglass.rb CHANGED
@@ -76,8 +76,10 @@ module Scryglass
76
76
  · For current or selected row(s)... ·
77
77
  · \e[36m@\e[0m : Build instance variable sub-rows ·
78
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. ·
79
+ · \e[36m(\e[0m : Attempt to smart-build sub-rows, if Enumerable. Usually '@' is preferable ·
80
80
  · \e[36mo\e[0m : Quick Open: builds the most likely helpful sub-rows ( '.' || '@' || '(' ) ·
81
+ · · ·
82
+ · \e[36mc\e[0m : Enter method text to call on object(s), results becomes navigable sub-rows ·
81
83
  · ·
82
84
  · SELECTING ROWS: ·
83
85
  · \e[36m*\e[0m : Select/Deselect ALL rows ·
@@ -87,13 +89,15 @@ module Scryglass
87
89
  · MANAGING MULTIPLE SESSION TABS: ·
88
90
  · \e[36mTab\e[0m : Change session tab (to the right) (\e[36mShift+Tab\e[0m moves left) ·
89
91
  · \e[36mQ\e[0m : Close current session tab ·
92
+ · \e[36mt\e[0m : [Open new]... session tab with current or selected row(s) as the seed ·
93
+ · \e[36mT\e[0m : [Restart]... session tab with current or selected row(s) as the seed ·
90
94
  · ·
91
95
  · TEXT SEARCH: ·
92
96
  · \e[36m/\e[0m : Begin a text search (in tree view) ·
93
97
  · \e[36mn\e[0m : Move to next search result ·
94
98
  · ·
95
99
  · ·
96
- · \e[36m=\e[0m : Open prompt to type a console handle for current or selected row(s) ·
100
+ · \e[36m=\e[0m : Open prompt to type a console handle for current or selected row(s) ·
97
101
  · ·
98
102
  · \e[36mEsc\e[0m : Resets selection, last search, and number-to-move. (or returns to Tree View) ·
99
103
  · ·
@@ -11,7 +11,7 @@ module Scryglass
11
11
 
12
12
  label_space = [method_list.map(&:length).max, 45].min
13
13
  method_list.sort!
14
- running_method_showcase = ''
14
+ running_method_showcase = ''.dup
15
15
 
16
16
  method_list.each do |method_name|
17
17
  label = method_name.to_s
data/lib/scryglass/ro.rb CHANGED
@@ -89,20 +89,43 @@ module Scryglass
89
89
  dot = '•'
90
90
  dot = "\e[36m#{dot}\e[00m" if Scryglass.config.dot_coloring # cyan then back to *default*
91
91
  special_sub_ro_expansion_indicator =
92
- special_sub_ros.any? && !expanded ? dot : ' '
92
+ any_special_sub_ros? && !expanded ? dot : ' '
93
93
 
94
94
  left_fill_string + special_sub_ro_expansion_indicator +
95
95
  key_value_spacer + value_indicator
96
96
  end
97
97
 
98
98
  def next_visible_ro_down
99
- subsequent_ros = scry_session.all_ros[(index + 1)..-1]
100
- subsequent_ros.find(&:visible?)
99
+ raise '(Must be called on a "visible" row)' unless visible?
100
+
101
+ first_sub_ro = sub_ros.first
102
+ return first_sub_ro if expanded && first_sub_ro
103
+ return nil if top_ro?
104
+
105
+ next_sibling = sibling_down
106
+ return next_sibling if next_sibling
107
+
108
+ # Note: since this ro is known to be visible, all its parents are, too.
109
+ upward_feeler_ro = self.parent_ro
110
+ parents_lower_sibling = upward_feeler_ro.sibling_down
111
+ until parents_lower_sibling || upward_feeler_ro.top_ro?
112
+ upward_feeler_ro = upward_feeler_ro.parent_ro
113
+ parents_lower_sibling = upward_feeler_ro.sibling_down
114
+ end
115
+
116
+ parents_lower_sibling
101
117
  end
102
118
 
103
119
  def next_visible_ro_up
104
- preceding_ros = scry_session.all_ros[0...index]
105
- preceding_ros.reverse.find(&:visible?)
120
+ raise '(Must be called on a "visible" row)' unless visible?
121
+
122
+ return nil if top_ro?
123
+
124
+ next_sibling = sibling_up
125
+ return next_sibling if next_sibling
126
+
127
+ # Note: since this ro is known to be visible, all its parents are, too.
128
+ parent_ro
106
129
  end
107
130
 
108
131
  def current_subject
@@ -124,8 +147,8 @@ module Scryglass
124
147
  # (Used for recalculate_indeces after new Ros have been injected)
125
148
  def next_ro_without_using_index
126
149
  return sub_ros.first if sub_ros.first
127
- return nil if top_ro?
128
150
  return sibling_down if sibling_down
151
+ return nil if top_ro?
129
152
 
130
153
  upward_feeler_ro = self
131
154
  until upward_feeler_ro.sibling_down || upward_feeler_ro.top_ro?
@@ -144,6 +167,16 @@ module Scryglass
144
167
  siblings[self_index + 1]
145
168
  end
146
169
 
170
+ def sibling_up
171
+ return nil if top_ro?
172
+
173
+ siblings = parent_ro.sub_ros
174
+ self_index = siblings.index(self)
175
+ return nil if self_index.zero?
176
+
177
+ siblings[self_index - 1]
178
+ end
179
+
147
180
  ## This exists so that an easy *unordered array match* can occur elsewhere.
148
181
  def <=>(other)
149
182
  unless self.class == other.class
@@ -187,10 +220,20 @@ module Scryglass
187
220
  sub_ros.reject(&:special_sub_ro_type)
188
221
  end
189
222
 
223
+ def any_normal_sub_ros?
224
+ !!sub_ros.find { |ro| !ro.special_sub_ro_type }
225
+ end
226
+
227
+ def any_special_sub_ros?
228
+ !!sub_ros.last&.special_sub_ro_type
229
+ end
230
+
190
231
  def bucket_indicator
191
- if expanded && normal_sub_ros.any?
232
+ return wrappers unless any_normal_sub_ros?
233
+
234
+ if expanded
192
235
  wrappers[0]
193
- elsif normal_sub_ros.any?
236
+ else
194
237
  # Number of dots indicating order of magnitude for Enumerable's count:
195
238
  # Turning this off (the consistent three dots is more like an ellipsis,
196
239
  # communicating with a solid preexisting symbol), but keeping the idea here:
@@ -199,8 +242,6 @@ module Scryglass
199
242
  dots = '•••'
200
243
  dots = "\e[36m#{dots}\e[00m" if Scryglass.config.dot_coloring # cyan then back to *default*
201
244
  wrappers.dup.insert(1, dots)
202
- else
203
- wrappers
204
245
  end
205
246
  end
206
247
 
@@ -175,6 +175,32 @@ module Scryglass
175
175
  recalculate_indeces unless new_ro_count == original_ro_count
176
176
  end
177
177
 
178
+ def build_method_results_for_target_ros(method_text)
179
+ if special_command_targets.any?
180
+ task = Prog::Task.new(max_count: special_command_targets.count)
181
+ progress_bar << task
182
+
183
+ target_ros = special_command_targets.dup # dup because some commands
184
+ # create ros which are added to all_ros and then this process starts
185
+ # adding them to the list of things it tries to act on!
186
+ target_ros.each.with_index do |target_ro, index|
187
+ build_method_result_sub_ros_for(target_ro,
188
+ method_text: method_text,
189
+ index: index)
190
+ task.tick
191
+ print_progress_bar
192
+ end
193
+ self.special_command_targets = []
194
+ else
195
+ build_method_result_sub_ros_for(current_ro,
196
+ method_text: method_text)
197
+
198
+ expand!(current_ro)
199
+ end
200
+
201
+ recalculate_indeces
202
+ end
203
+
178
204
  def build_instance_variables_for_target_ros
179
205
  original_ro_count = all_ros.count
180
206
  original_iv_sub_ro_count = current_ro.iv_sub_ros.count
@@ -303,6 +329,38 @@ module Scryglass
303
329
  task.force_finish # Just in case
304
330
  end
305
331
 
332
+ def build_method_result_sub_ros_for(ro, method_text:, index: false)
333
+ current_console_binding = session_manager.current_console_binding
334
+
335
+ ro_eval_string =
336
+ if index
337
+ "$scry_session_manager.current_session.subjects_of_target_ros[#{index}]"
338
+ else
339
+ '$scry_session_manager.current_session.current_ro.current_subject'
340
+ end
341
+
342
+ console_eval_string = "#{ro_eval_string}#{method_text}"
343
+
344
+ method_result =
345
+ rescue_to_viewwrapped_error do
346
+ Hexes.hide_db_outputs do
347
+ # COULD implement Timeout.timeout(10)
348
+ current_console_binding.eval(console_eval_string)
349
+ end
350
+ end
351
+
352
+ method_key = Scryglass::ViewWrapper.new(method_text,
353
+ string: "_#{method_text}")
354
+ ro.sub_ros << roify(method_result,
355
+ parent_ro: ro,
356
+ key: method_key,
357
+ key_value_relationship_indicator: ' -> ',
358
+ special_sub_ro_type: :method_result,
359
+ depth: ro.depth + 1)
360
+
361
+ true
362
+ end
363
+
306
364
  def build_iv_sub_ros_for(ro)
307
365
  return if ro.iv_sub_ros.any?
308
366
 
@@ -9,7 +9,9 @@ class Scryglass::Session
9
9
 
10
10
  attr_accessor :current_view_coords, :current_lens, :current_subject_type,
11
11
  :view_panels, :current_panel_type,
12
- :progress_bar, :current_warning_messages
12
+ :progress_bar, :current_warning_messages,
13
+ :content_shape_changed,
14
+ :previous_screen_dimensions
13
15
 
14
16
  attr_accessor :user_signals, :last_search, :number_to_move
15
17
 
@@ -17,16 +19,13 @@ class Scryglass::Session
17
19
  :tab_icon, :session_view_start_time
18
20
 
19
21
  CURSOR_CHARACTER = '–' # These are en dashes (alt+dash), not hyphens or em dashes.
20
-
21
22
  SEARCH_PROMPT = "\e[7mSearch for (regex, case-sensitive): /\e[00m"
22
-
23
23
  VARNAME_PROMPT = "\e[7mName your object(s): @\e[00m"
24
-
24
+ METHOD_NAME_PROMPT = "\e[7mMethod(s) to call on object(s): object\e[00m"
25
25
  SUBJECT_TYPES = [
26
26
  :value,
27
27
  :key
28
28
  ].freeze
29
-
30
29
  CSI = "\e[" # "(C)ontrol (S)equence (I)ntroducer" for ANSI sequences
31
30
 
32
31
  KEY_MAP = {
@@ -36,6 +35,8 @@ class Scryglass::Session
36
35
  delete_session_tab: 'Q',
37
36
  change_session_right: "\t", # Tab
38
37
  change_session_left: 'Z', # Shift+Tab (well, one of its signals, after "\e" and "[")
38
+ start_new_session_from_target: 't',
39
+ restart_session_from_target: 'T',
39
40
  digit_1: '1',
40
41
  digit_2: '2',
41
42
  digit_3: '3',
@@ -50,12 +51,12 @@ class Scryglass::Session
50
51
  move_cursor_down: 'B', # Down arrow (well, one of its signals, after "\e" and "[")
51
52
  open_bucket: 'C', # Right arrow (well, one of its signals, after "\e" and "[")
52
53
  close_bucket: 'D', # Left arrow (well, one of its signals, after "\e" and "[")
53
- homerow_move_cursor_up: 'k', # To be like VIM arrow keys
54
+ homerow_move_cursor_up: 'k', # To be like VIM arrow keys
54
55
  homerow_move_cursor_up_fast: 'K', # To be like VIM arrow keys
55
- homerow_move_cursor_down: 'j', # To be like VIM arrow keys
56
+ homerow_move_cursor_down: 'j', # To be like VIM arrow keys
56
57
  homerow_move_cursor_down_fast: 'J', # To be like VIM arrow keys
57
- homerow_open_bucket: 'l', # To be like VIM arrow keys
58
- homerow_close_bucket: 'h', # To be like VIM arrow keys
58
+ homerow_open_bucket: 'l', # To be like VIM arrow keys
59
+ homerow_close_bucket: 'h', # To be like VIM arrow keys
59
60
  # Note, shift-UP and shift-DOWN are not here, as those work very
60
61
  # differently: by virtue of the type-a-number-first functionality.
61
62
  toggle_view_panel: ' ',
@@ -74,6 +75,7 @@ class Scryglass::Session
74
75
  build_ar_relations: '.',
75
76
  build_enum_children: '(',
76
77
  smart_open: 'o',
78
+ build_method_results: 'c',
77
79
  select_siblings: '|',
78
80
  select_all: '*',
79
81
  select_current: '-',
@@ -104,6 +106,8 @@ class Scryglass::Session
104
106
  self.tab_icon = nil
105
107
  self.session_is_current = false
106
108
  self.session_view_start_time = nil
109
+ self.content_shape_changed = true
110
+ self.previous_screen_dimensions = $stdout.winsize
107
111
 
108
112
  top_ro = roify(seed, parent_ro: nil, depth: 1)
109
113
  top_ro.has_cursor = true
@@ -128,7 +132,7 @@ class Scryglass::Session
128
132
 
129
133
  def run_scry_ui
130
134
  redraw = true
131
- signal_to_manager = nil
135
+ self.signal_to_manager = nil
132
136
  self.session_view_start_time = Time.now # For this particular tab/session
133
137
 
134
138
  ## On hold: Record/Playback Functionality:
@@ -280,15 +284,23 @@ class Scryglass::Session
280
284
 
281
285
  when KEY_MAP[:build_instance_variables]
282
286
  build_instance_variables_for_target_ros
287
+ self.content_shape_changed = true
283
288
  tree_view.slide_view_to_cursor # Just a nice-to-have
284
289
  when KEY_MAP[:build_ar_relations]
285
290
  build_activerecord_relations_for_target_ros
291
+ self.content_shape_changed = true
286
292
  tree_view.slide_view_to_cursor # Just a nice-to-have
287
293
  when KEY_MAP[:build_enum_children]
288
294
  build_enum_children_for_target_ros
295
+ self.content_shape_changed = true
289
296
  tree_view.slide_view_to_cursor # Just a nice-to-have
290
297
  when KEY_MAP[:smart_open]
291
298
  smart_open_target_ros
299
+ self.content_shape_changed = true
300
+ tree_view.slide_view_to_cursor # Just a nice-to-have
301
+ when KEY_MAP[:build_method_results]
302
+ build_method_result_ros
303
+ self.content_shape_changed = true
292
304
  tree_view.slide_view_to_cursor # Just a nice-to-have
293
305
 
294
306
  when KEY_MAP[:select_siblings]
@@ -323,13 +335,19 @@ class Scryglass::Session
323
335
  when KEY_MAP[:start_search]
324
336
  initiate_search
325
337
  when KEY_MAP[:continue_search]
338
+ # TODO: extract in separate commit
326
339
  if last_search
327
340
  go_to_next_search_result
328
341
  else
329
342
  message = { text: 'No Search has been entered', end_time: Time.now + 2 }
330
343
  self.current_warning_messages << message
331
344
  end
332
-
345
+ when KEY_MAP[:start_new_session_from_target]
346
+ self.signal_to_manager = :start_new_session_from_target
347
+ return subjects_of_target_ros
348
+ when KEY_MAP[:restart_session_from_target]
349
+ self.signal_to_manager = :restart_session_from_target
350
+ return subjects_of_target_ros
333
351
  when KEY_MAP[:change_session_right]
334
352
  self.signal_to_manager = :change_session_right
335
353
  return
@@ -340,9 +358,7 @@ class Scryglass::Session
340
358
  name_subjects_of_target_ros
341
359
  when KEY_MAP[:return_objects]
342
360
  self.signal_to_manager = :return
343
- subjects = subjects_of_target_ros
344
- self.special_command_targets = []
345
- return subjects
361
+ return subjects_of_target_ros
346
362
  end
347
363
 
348
364
  beep_if_user_had_to_wait(wait_start_time)
@@ -414,6 +430,8 @@ class Scryglass::Session
414
430
 
415
431
  self.number_to_move = ''
416
432
  tree_view.slide_view_to_cursor
433
+
434
+ self.content_shape_changed = true if current_panel_type == :lens
417
435
  end
418
436
 
419
437
  def move_cursor_down_action(action_count = nil)
@@ -422,6 +440,8 @@ class Scryglass::Session
422
440
 
423
441
  self.number_to_move = ''
424
442
  tree_view.slide_view_to_cursor
443
+
444
+ self.content_shape_changed = true if current_panel_type == :lens
425
445
  end
426
446
 
427
447
  def clear_tracked_values
@@ -507,8 +527,7 @@ class Scryglass::Session
507
527
  scanning_ro = scanning_ro.parent_ro
508
528
  end
509
529
 
510
- tree_view.recalculate_boundaries # Yes, necessary :)
511
- lens_view.recalculate_boundaries # Yes, necessary :)
530
+ self.content_shape_changed = true # Needed here even if ros weren't expanded.
512
531
  tree_view.current_view_coords = { y: 0, x: 0 }
513
532
  tree_view.slide_view_to_cursor
514
533
  else
@@ -593,6 +612,7 @@ class Scryglass::Session
593
612
  end
594
613
 
595
614
  move_cursor_to(current_ro.parent_ro) until current_ro.visible?
615
+ self.content_shape_changed = true
596
616
  tree_view.slide_view_to_cursor
597
617
  end
598
618
 
@@ -606,6 +626,8 @@ class Scryglass::Session
606
626
  else
607
627
  expand!(current_ro)
608
628
  end
629
+
630
+ self.content_shape_changed = true
609
631
  end
610
632
 
611
633
  def reset_the_view_or_cursor
@@ -617,8 +639,17 @@ class Scryglass::Session
617
639
  end
618
640
 
619
641
  def draw_screen
620
- current_view_panel.recalculate_boundaries # This now happens at every screen
621
- # draw to account for the user changing the screen size. Otherwise glitch.
642
+ current_screen_dimensions = $stdout.winsize
643
+ screen_size_changed = current_screen_dimensions != previous_screen_dimensions
644
+ self.previous_screen_dimensions = current_screen_dimensions
645
+
646
+ if content_shape_changed || screen_size_changed
647
+ current_view_panel.recalculate_boundaries
648
+ # ^This no longer happens at every screen draw, but only when
649
+ # determined necessary.
650
+ self.content_shape_changed = false
651
+ end
652
+
622
653
  current_view_panel.ensure_correct_view_coords
623
654
  screen_string = current_view_panel.screen_string
624
655
 
@@ -640,6 +671,41 @@ class Scryglass::Session
640
671
  $stdin.gets.chomp
641
672
  end
642
673
 
674
+ def get_method_text_from_user
675
+ _screen_height, screen_width = $stdout.winsize
676
+ $stdout.write "#{CSI}1;1H" # (Moves console cursor to top left corner)
677
+ $stdout.print ' ' * screen_width
678
+ $stdout.write "#{CSI}1;1H" # (Moves console cursor to top left corner)
679
+ $stdout.print METHOD_NAME_PROMPT
680
+ $stdout.write "#{CSI}1;#{METHOD_NAME_PROMPT.ansiless_length + 1}H" # (Moves
681
+ # console cursor to just after the search prompt, before user types)
682
+ $stdin.gets.chomp
683
+ end
684
+
685
+ def build_method_result_ros
686
+ method_text = get_method_text_from_user
687
+
688
+ if method_text.empty?
689
+ message = { text: 'Call text cannot be blank',
690
+ end_time: Time.now + 2 }
691
+ self.current_warning_messages << message
692
+ print "\a" # (Audio 'beep')
693
+ return
694
+ end
695
+
696
+ if method_text[0] =~ /[a-z]|[A-Z]/
697
+ message = { text: 'Call text must start with \'.\' or other symbol',
698
+ end_time: Time.now + 3 }
699
+ self.current_warning_messages << message
700
+ print "\a" # (Audio 'beep')
701
+ return
702
+ end
703
+
704
+ build_method_results_for_target_ros(method_text)
705
+
706
+ self.special_command_targets = []
707
+ end
708
+
643
709
  def name_subjects_of_target_ros
644
710
  typed_name = get_subject_name_from_user
645
711
  typed_name = typed_name.tr(' ', '')
@@ -722,6 +788,8 @@ class Scryglass::Session
722
788
  when :lens
723
789
  :tree
724
790
  end
791
+
792
+ self.content_shape_changed = true
725
793
  end
726
794
 
727
795
  def toggle_current_subject_type
@@ -732,10 +800,13 @@ class Scryglass::Session
732
800
  when :key
733
801
  :value
734
802
  end
803
+
804
+ self.content_shape_changed = true
735
805
  end
736
806
 
737
807
  def scroll_lens_type
738
808
  self.current_lens += 1
809
+ self.content_shape_changed = true
739
810
  end
740
811
 
741
812
  def move_cursor_to(new_ro)
@@ -79,18 +79,16 @@ module Scryglass
79
79
  visually_close_ui(floor_the_cursor: true)
80
80
  return
81
81
  when :delete
82
- old_session = current_session
83
- visually_close_ui
84
- if scry_sessions.index(old_session) > 0
85
- change_session_left!
86
- else
87
- change_session_right!
88
- end
89
- delete_session!(old_session)
82
+ visually_close_ui if scry_sessions.count == 1
83
+ delete_current_session!
90
84
  when :change_session_left # and if there's only one session?
91
85
  change_session_left!
92
86
  when :change_session_right # and if there's only one session?
93
87
  change_session_right!
88
+ when :start_new_session_from_target
89
+ start_new_session_from_target!(session_return)
90
+ when :restart_session_from_target
91
+ restart_session_from_target!(session_return)
94
92
  end
95
93
  end
96
94
  end
@@ -120,8 +118,15 @@ module Scryglass
120
118
  puts current_user_named_variables.map { |s| " #{s}\n" }
121
119
  end
122
120
 
123
- def delete_session!(session)
124
- scry_sessions.delete(session)
121
+ def delete_current_session!
122
+ old_session = current_session
123
+ if scry_sessions.index(old_session) > 0
124
+ change_session_left!
125
+ else
126
+ change_session_right!
127
+ end
128
+
129
+ scry_sessions.delete(old_session)
125
130
  end
126
131
 
127
132
  def session_right_of(session)
@@ -146,6 +151,22 @@ module Scryglass
146
151
  set_current_session!(next_session)
147
152
  end
148
153
 
154
+ def start_new_session_from_target!(session_return)
155
+ new_session = Scryglass::Session.new(session_return)
156
+ self << new_session
157
+ set_current_session!(new_session)
158
+ end
159
+
160
+ def restart_session_from_target!(session_return)
161
+ old_session = current_session
162
+
163
+ new_session = Scryglass::Session.new(session_return)
164
+ self << new_session
165
+ set_current_session!(new_session)
166
+
167
+ scry_sessions.delete(old_session)
168
+ end
169
+
149
170
  def set_current_session!(session)
150
171
  scry_sessions.each { |session| session.session_is_current = false }
151
172
  session.session_is_current = true
@@ -102,6 +102,7 @@ module Scryglass
102
102
  end
103
103
 
104
104
  def recalculate_y_boundaries
105
+ # number_of_lines is 41% of the runtime when slogging through massive array
105
106
  number_of_lines = scry_session.all_ros.select(&:visible?).count
106
107
  preview_row = 1
107
108
  self.y_boundaries = 0...(number_of_lines + preview_row)
@@ -118,6 +119,7 @@ module Scryglass
118
119
  self.x_boundaries = 0...(max_line_length + preview_column)
119
120
  end
120
121
 
122
+ # Scales linearly with number of visible ros above view... can be harsh with lower parts of colossal sets.
121
123
  def top_visible_ro_of_tree_view
122
124
  top_ro = scry_session.top_ro
123
125
 
@@ -1,3 +1,3 @@
1
1
  module Scryglass
2
- VERSION = "2.0.2"
2
+ VERSION = "2.1.0"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: scryglass
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.2
4
+ version: 2.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gavin Myers
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-01-15 00:00:00.000000000 Z
11
+ date: 2021-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler