lib/scryglass/session.rb in scryglass-1.0.1 vs lib/scryglass/session.rb in scryglass-1.1.0
- old
+ new
@@ -9,11 +9,11 @@
attr_accessor :current_view_coords, :current_lens, :current_subject_type,
:view_panels, :current_panel_type,
:progress_bar
- attr_accessor :user_input, :last_search, :number_to_move
+ attr_accessor :user_signals, :last_search, :number_to_move
CURSOR_CHARACTER = '–' # These are en dashes (alt+dash), not hyphens or em dashes.
SEARCH_PROMPT = "\e[7mSearch for (regex, case-sensitive): /\e[00m"
@@ -31,11 +31,11 @@
self.current_lens = 0
self.current_subject_type = :value
self.current_panel_type = :tree
self.special_command_targets = []
self.number_to_move = ''
- self.user_input = nil
+ self.user_signals = []
self.progress_bar = Prog::Pipe.new
top_ro = roify(seed, parent_ro: nil, depth: 1)
top_ro.has_cursor = true
self.current_ro = top_ro
@@ -50,46 +50,58 @@
def run_scry_ui(actions:)
in_scry_session = true
redraw = true
- case actions
- when :record
- $scry_session_actions_performed = []
- when :playback
- if $scry_session_actions_performed.blank?
- raise 'Could not find recording of previous session\'s actions'
- end
- @input_stack = $scry_session_actions_performed.dup
- end
+ ## On hold: Record/Playback Functionality:
+ # case actions
+ # when :record
+ # $scry_session_actions_performed = []
+ # when :playback
+ # if $scry_session_actions_performed.blank?
+ # raise 'Could not find recording of previous session\'s actions'
+ # end
+ # @input_stack = $scry_session_actions_performed.dup
+ # end
# We print a full screen of lines so the first call of draw_screen doesn't
# write over any previous valuable content the user had in the console.
print Hexes.opacify_screen_string(Hexes.simple_screen_slice(boot_screen))
while in_scry_session
draw_screen if redraw
redraw = true
- case actions
- when :record
- self.user_input = $stdin.getch
- $scry_session_actions_performed << user_input
- when :playback
- if @input_stack.any? # (IV to be easily accessible for debugging)
- self.user_input = @input_stack.shift
- sleep 0.05
- else
- self.user_input = $stdin.getch
- end
- else
- self.user_input = $stdin.getch
- end
+ ## On hold: Record/Playback Functionality:
+ # case actions
+ # when :record
+ # self.user_input = $stdin.getch
+ # $scry_session_actions_performed << user_input
+ # when :playback
+ # if @input_stack.any? # (IV to be easily accessible for debugging)
+ # self.user_input = @input_stack.shift
+ # sleep 0.05
+ # else
+ # self.user_input = $stdin.getch
+ # end
+ # else
+ # self.user_input = $stdin.getch
+ # end
+ new_signal = fetch_user_signal
+
wait_start_time = Time.now
- case user_input
+ case new_signal
+ when nil
+ when 'esc'
+ case current_panel_type
+ when :lens
+ self.current_panel_type = :tree
+ when :tree
+ clear_tracked_values
+ end
when "\u0003"
set_console_cursor_below_content
raise IRB::Abort, 'Ctrl+C Detected'
when 'q'
in_scry_session = false
@@ -121,44 +133,38 @@
redraw = false
when '9'
self.number_to_move += '9'
redraw = false
when '0'
- if number_to_move.present? # You can append zeros to number_to_move...
+ if number_to_move[0] # You can append zeros to existing number_to_move...
self.number_to_move += '0'
redraw = false
else # ...but otherwise it's understood to be a view||cursor reset.
reset_the_view_or_cursor
end
when 'A' # Up arrow
- action_count = number_to_move.present? ? number_to_move.to_i : 1
+ action_count = !number_to_move.empty? ? number_to_move.to_i : 1
navigate_up_multiple(action_count)
self.number_to_move = ''
- lens_view.recalculate_boundaries if current_panel_type == :lens
tree_view.slide_view_to_cursor
when 'B' # Down arrow
- action_count = number_to_move.present? ? number_to_move.to_i : 1
+ action_count = !number_to_move.empty? ? number_to_move.to_i : 1
navigate_down_multiple(action_count)
self.number_to_move = ''
- lens_view.recalculate_boundaries if current_panel_type == :lens
tree_view.slide_view_to_cursor
when 'C' # Right arrow
expand_targets
when 'D' # Left arrow
collapse_targets
- lens_view.recalculate_boundaries if current_panel_type == :lens
when ' '
toggle_view_panel
- lens_view.recalculate_boundaries if current_panel_type == :lens
when 'l'
scroll_lens_type
- lens_view.recalculate_boundaries if current_panel_type == :lens
when 'L'
toggle_current_subject_type
- lens_view.recalculate_boundaries if current_panel_type == :lens
when 'w'
current_view_panel.move_view_up(5)
when 's'
current_view_panel.move_view_down(5)
when 'a'
@@ -175,19 +181,16 @@
current_view_panel.move_view_right(50)
when '?'
in_scry_session = run_help_screen_ui
when '@'
build_instance_variables_for_target_ros
- tree_view.recalculate_boundaries
tree_view.slide_view_to_cursor # Just a nice-to-have
when '.'
build_activerecord_relations_for_target_ros
- tree_view.recalculate_boundaries
tree_view.slide_view_to_cursor # Just a nice-to-have
when '('
build_enum_children_for_target_ros
- tree_view.recalculate_boundaries
tree_view.slide_view_to_cursor # Just a nice-to-have
when '|'
sibling_ros = if current_ro.top_ro?
[top_ro]
else
@@ -212,16 +215,19 @@
special_command_targets.delete(current_ro)
else
special_command_targets << current_ro
end
when '/'
+ _screen_height, screen_width = $stdout.winsize
$stdout.write "#{CSI}1;1H" # (Moves console cursor to top left corner)
- $stdout.write SEARCH_PROMPT
+ $stdout.print ' ' * screen_width
+ $stdout.write "#{CSI}1;1H" # (Moves console cursor to top left corner)
+ $stdout.print SEARCH_PROMPT
$stdout.write "#{CSI}1;#{SEARCH_PROMPT.ansiless_length + 1}H" # (Moves
# console cursor to just after the search prompt, before user types)
query = $stdin.gets.chomp
- if query.present?
+ unless query.empty?
self.last_search = query
go_to_next_search_result
end
when 'n'
if last_search
@@ -234,25 +240,36 @@
when "\r" # [ENTER]
visually_close_ui
return subjects_of_target_ros
end
- print "\a" if Time.now - wait_start_time > 4 && user_input != '?' # (Audio 'beep')
+ print "\a" if Time.now - wait_start_time > 4 && last_keypress != '?' # (Audio 'beep')
end
end
def top_ro
all_ros.first
end
+ def last_keypress
+ last_two_signals = user_signals.last(2)
+ last_two_signals.last || last_two_signals.first
+ end
+
private
+ def clear_tracked_values
+ self.special_command_targets = []
+ self.last_search = nil
+ self.number_to_move = ''
+ end
+
def print_progress_bar
screen_height, _screen_width = $stdout.winsize
bar = progress_bar.to_s
$stdout.write "#{CSI}#{screen_height};1H" # (Moves console cursor to bottom left corner)
- print bar if bar.present?
+ print bar unless bar.tr(' ', '').empty?
end
def current_view_panel
view_panels[current_panel_type]
end
@@ -323,10 +340,33 @@
$stdout.write "\e[7m#{wing + message + wing}\e[00m"
sleep 2
end
end
+ def fetch_user_signal
+ previous_signal = user_signals.last
+ new_signal =
+ begin
+ Timeout.timeout(0.1) { $stdin.getch }
+ rescue Timeout::Error
+ nil
+ end
+
+ ## Since many keys, including arrow keys, result in several signals being
+ ## sent (e.g. DOWN: "\e" then "[" then "B" in RAPID succession), the
+ ## *pause* after a genuine escape key press (also "\e") is the only way
+ ## to distinguish it precisely.
+ genuine_escape_key_press = new_signal.nil? && previous_signal == "\e"
+ if genuine_escape_key_press
+ new_signal = 'esc'
+ end
+
+ user_signals << new_signal unless new_signal.nil? && previous_signal.nil?
+
+ new_signal
+ end
+
def run_help_screen_ui
screen_height, _screen_width = $stdout.winsize
in_help_screen = true
current_help_screen_index = 0
@@ -335,13 +375,16 @@
while in_help_screen
current_help_screen = help_screens[current_help_screen_index]
sliced_help_screen = Hexes.simple_screen_slice(current_help_screen)
help_screen_string = Hexes.opacify_screen_string(sliced_help_screen)
Hexes.overwrite_screen(help_screen_string)
- help_screen_user_input = $stdin.getch
- case help_screen_user_input
+ new_signal = fetch_user_signal
+
+ case new_signal
+ when 'esc'
+ return true
when '?'
current_help_screen_index += 1
when 'q'
$stdout.write "#{CSI}#{screen_height};1H" # (Moves console cursor to
# bottom left corner). This helps 'q' not print the console prompt at
@@ -373,11 +416,10 @@
collapse!(current_ro.parent_ro)
end
move_cursor_to(current_ro.parent_ro) until current_ro.visible?
tree_view.slide_view_to_cursor
- tree_view.recalculate_boundaries # TODO: should these be conditional? If they are, I might need a potential tree view recalc after toggling lens view to tree view.
end
def expand_targets
if special_command_targets.any?
target_ros = special_command_targets.dup # dup because some commands
@@ -386,11 +428,10 @@
target_ros.each { |target_ro| expand!(target_ro) }
self.special_command_targets = []
else
expand!(current_ro)
end
- tree_view.recalculate_boundaries
end
def reset_the_view_or_cursor
if current_view_panel.current_view_coords != { x: 0, y: 0 }
current_view_panel.current_view_coords = { x: 0, y: 0 }
@@ -398,9 +439,11 @@
move_cursor_to(top_ro)
end
end
def draw_screen
+ current_view_panel.recalculate_boundaries # This now happens at every screen
+ # draw to account for the user changing the screen size. Otherwise glitch.
current_view_panel.ensure_correct_view_coords
screen_string = current_view_panel.screen_string
screen_string = colorize(screen_string) if Scryglass.config.dot_coloring
Hexes.overwrite_screen(screen_string)