lib/scryglass/ro.rb in scryglass-1.1.0 vs lib/scryglass/ro.rb in scryglass-2.0.0
- old
+ new
@@ -41,18 +41,26 @@
## Open up ViewWrappers and grab their objects and their custom strings
if key.class == Scryglass::ViewWrapper
self.key_string = key.to_s.clip_at(key_clip_length)
self.key = key.model
else
- self.key_string = key.inspect.clip_at(key_clip_length)
+ # Note: `.inspect` may return *true newlines* for objects with a custom
+ # `.inspect`, which will sabotage scry's display, so we gsub thusly:
+ self.key_string = key.inspect
+ .gsub("\n", "\\n")
+ .clip_at(key_clip_length)
self.key = key
end
if val.class == Scryglass::ViewWrapper
self.value_string = val.to_s.clip_at(value_clip_length)
self.value = val.model
else
- self.value_string = val.inspect.clip_at(value_clip_length)
+ # Note: `.inspect` may return *true newlines* for objects with a custom
+ # `.inspect`, which will sabotage scry's display, so we gsub thusly:
+ self.value_string = val.inspect
+ .gsub("\n", "\\n")
+ .clip_at(value_clip_length)
self.value = val
end
self.sub_ros = []
self.parent_ro = parent_ro
@@ -76,13 +84,14 @@
value_indicator =
bucket? ? bucket_indicator : value_string
key_value_spacer =
key_value_pair? ? key_string + key_value_relationship_indicator : ''
-
+ dot = '•'
+ dot = "\e[36m#{dot}\e[00m" if Scryglass.config.dot_coloring # cyan then back to *default*
special_sub_ro_expansion_indicator =
- special_sub_ros.any? && !expanded ? '•' : ' '
+ special_sub_ros.any? && !expanded ? dot : ' '
left_fill_string + special_sub_ro_expansion_indicator +
key_value_spacer + value_indicator
end
@@ -166,16 +175,16 @@
def key_value_pair?
!!key_value_relationship_indicator
end
- private
-
def special_sub_ros
sub_ros.select(&:special_sub_ro_type)
end
+ private
+
def normal_sub_ros
sub_ros.reject(&:special_sub_ro_type)
end
def bucket_indicator
@@ -185,11 +194,13 @@
# Number of dots indicating order of magnitude for Enumerable's count:
# Turning this off (the consistent three dots is more like an ellipsis,
# communicating with a solid preexisting symbol), but keeping the idea here:
# sub_ros_order_of_magnitude = normal_sub_ros.count.to_s.length
# wrappers.dup.insert(1, '•' * sub_ros_order_of_magnitude)
- wrappers.dup.insert(1, '•••')
+ dots = '•••'
+ dots = "\e[36m#{dots}\e[00m" if Scryglass.config.dot_coloring # cyan then back to *default*
+ wrappers.dup.insert(1, dots)
else
wrappers
end
end
@@ -212,22 +223,80 @@
consistent_margin = [4 - tab_length, 0].max
(tab_length * depth) + consistent_margin
end
+ def cursor_char
+ Scryglass::Session::CURSOR_CHARACTER
+ end
+
def cursor_string
- cursor = Scryglass::Session::CURSOR_CHARACTER * cursor_length
+ cursor = cursor_char * cursor_length
- if nugget? && has_cursor && value.is_a?(Enumerable) &&
- value.any? &&
- enum_sub_ros.empty?
- cursor[0] = '('
+ cursor[0] = enum_status_char
+ cursor[1] = iv_status_char
+ cursor[2] = ar_status_char
+
+ cursor
+ end
+
+ def enum_status_char
+ enum_worth_checking = nugget? && value.is_a?(Enumerable)
+ return cursor_char unless enum_worth_checking
+
+ enum_check = Scryglass::Ro.safe_quick_check do
+ # value.any? Can take an eternity for a few specific objects, breaking
+ # the session when the cursor passes over them. Also breaks on read-
+ # locked IO objects.
+ enum_sub_ros.empty? && value.any?
end
- if value.instance_variables.any? && iv_sub_ros.empty?
- cursor[1] = '@'
+ return 'X' if enum_check.nil?
+
+ return '(' if enum_check
+
+ cursor_char
+ end
+
+ def iv_status_char
+ return cursor_char unless iv_sub_ros.empty?
+
+ iv_check = Scryglass::Ro.safe_quick_check do
+ value.instance_variables.any?
end
- cursor
+ return 'X' if iv_check.nil?
+
+ return '@' if iv_check
+
+ cursor_char
+ end
+
+ def ar_status_char
+ return cursor_char unless ar_sub_ros.empty?
+
+ iv_check = Scryglass::Ro.safe_quick_check do
+ # Currently, this will always indicate hidden secrets if the object, with
+ # the given Scryglass config, doesn't yield any ar_sub_ros upon trying '.'
+ value.class.respond_to?(:reflections) # TODO: maybe dig more here?
+ end
+
+ return 'X' if iv_check.nil?
+
+ return '·' if iv_check
+
+ cursor_char
+ end
+
+ class << self
+ def safe_quick_check
+ begin
+ Timeout.timeout(0.05) do
+ yield
+ end
+ rescue
+ nil
+ end
+ end
end
end
end