scryglass 0.1.0
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 +7 -0
- data/.gitignore +8 -0
- data/.tool-versions +1 -0
- data/Gemfile +6 -0
- data/Gemfile.lock +33 -0
- data/LICENSE.txt +21 -0
- data/README.md +252 -0
- data/Rakefile +2 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/example_config.rb +30 -0
- data/lib/example_material.rb +97 -0
- data/lib/hexes.rb +135 -0
- data/lib/prog.rb +89 -0
- data/lib/refinements/ansiless_string_refinement.rb +11 -0
- data/lib/refinements/array_fit_to_refinement.rb +67 -0
- data/lib/refinements/clip_string_refinement.rb +27 -0
- data/lib/refinements/constant_defined_string_refinement.rb +11 -0
- data/lib/scryglass.rb +177 -0
- data/lib/scryglass/config.rb +103 -0
- data/lib/scryglass/lens_helper.rb +22 -0
- data/lib/scryglass/lens_panel.rb +140 -0
- data/lib/scryglass/ro.rb +237 -0
- data/lib/scryglass/ro_builder.rb +402 -0
- data/lib/scryglass/session.rb +514 -0
- data/lib/scryglass/tree_panel.rb +122 -0
- data/lib/scryglass/version.rb +3 -0
- data/lib/scryglass/view_panel.rb +91 -0
- data/lib/scryglass/view_wrapper.rb +23 -0
- data/scryglass.gemspec +46 -0
- metadata +117 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scryglass
|
4
|
+
class TreePanel < Scryglass::ViewPanel
|
5
|
+
using ClipStringRefinement
|
6
|
+
using AnsilessStringRefinement
|
7
|
+
|
8
|
+
def slide_view_to_cursor
|
9
|
+
cursor_tracking = Scryglass.config.cursor_tracking
|
10
|
+
|
11
|
+
current_ro = scry_session.current_ro
|
12
|
+
|
13
|
+
## Here we calculate the ro_in_center_of_view:
|
14
|
+
visible_ros_from_center = (body_screen_height / 2)
|
15
|
+
scanning_ro = top_visible_ro_of_tree_view
|
16
|
+
visible_ros_from_center.times do
|
17
|
+
next_visible_ro = scanning_ro.next_visible_ro_down
|
18
|
+
scanning_ro = next_visible_ro if next_visible_ro
|
19
|
+
end
|
20
|
+
ro_in_center_of_view = scanning_ro
|
21
|
+
|
22
|
+
## We don't need to do anything if current_ro is already in the center:
|
23
|
+
relative_index = current_ro.index - ro_in_center_of_view.index
|
24
|
+
return if relative_index.zero?
|
25
|
+
|
26
|
+
## Establish the number of visible ros between current_ro and center point
|
27
|
+
index_span = [ro_in_center_of_view.index, current_ro.index]
|
28
|
+
ros_between_them = scry_session.all_ros[index_span.min...index_span.max]
|
29
|
+
visible_count_between_them = ros_between_them.count(&:visible?)
|
30
|
+
|
31
|
+
direction = :up if relative_index.negative?
|
32
|
+
direction = :down if relative_index.positive?
|
33
|
+
|
34
|
+
## If view movement is needed, and how far, depends on the tracking config
|
35
|
+
case cursor_tracking
|
36
|
+
when :flexible_range
|
37
|
+
flex_range = body_screen_height / 3
|
38
|
+
if visible_count_between_them >= flex_range
|
39
|
+
distance_to_flex_range = visible_count_between_them - flex_range
|
40
|
+
move_view_up(distance_to_flex_range) if direction == :up
|
41
|
+
move_view_down(distance_to_flex_range) if direction == :down
|
42
|
+
end
|
43
|
+
when :dead_center
|
44
|
+
move_view_up(visible_count_between_them) if direction == :up
|
45
|
+
move_view_down(visible_count_between_them) if direction == :down
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def uncut_body_string
|
52
|
+
body_array_from_ro(top_visible_ro_of_tree_view).join("\n")
|
53
|
+
end
|
54
|
+
|
55
|
+
def uncut_header_string
|
56
|
+
_screen_height, screen_width = $stdout.winsize
|
57
|
+
header_string = "Press '?' for controls\n".rjust(screen_width, ' ') +
|
58
|
+
'·' * screen_width
|
59
|
+
if scry_session.special_command_targets.any?
|
60
|
+
special_targets_message = " (Next command will apply to all selected rows)"
|
61
|
+
header_string[0...special_targets_message.length] = special_targets_message
|
62
|
+
end
|
63
|
+
header_string
|
64
|
+
end
|
65
|
+
|
66
|
+
def visible_body_slice(uncut_body_string)
|
67
|
+
_screen_height, screen_width = $stdout.winsize
|
68
|
+
|
69
|
+
split_lines = uncut_body_string.split("\n")
|
70
|
+
sliced_lines = split_lines.map do |string|
|
71
|
+
ansi_length = string.length - string.ansiless.length
|
72
|
+
slice_length = screen_width + ansi_length
|
73
|
+
string[current_view_coords[:x], slice_length] || '' # If I don't want to
|
74
|
+
# opacify here, I need to account for nils when the view is fully
|
75
|
+
# beyond the shorter lines.
|
76
|
+
end
|
77
|
+
|
78
|
+
sliced_lines.join("\n")
|
79
|
+
end
|
80
|
+
|
81
|
+
def recalculate_y_boundaries
|
82
|
+
self.y_boundaries = 0...scry_session.all_ros.select(&:visible?).count
|
83
|
+
end
|
84
|
+
|
85
|
+
def recalculate_x_boundaries
|
86
|
+
_screen_height, screen_width = $stdout.winsize
|
87
|
+
|
88
|
+
split_lines = uncut_body_string.split("\n")
|
89
|
+
length_of_longest_line = split_lines.map(&:length).max
|
90
|
+
max_line_length = [length_of_longest_line, screen_width].max
|
91
|
+
self.x_boundaries = 0...max_line_length
|
92
|
+
end
|
93
|
+
|
94
|
+
def top_visible_ro_of_tree_view
|
95
|
+
top_ro = scry_session.top_ro
|
96
|
+
|
97
|
+
scanning_ro = top_ro
|
98
|
+
top_ros = [scanning_ro]
|
99
|
+
until top_ros.count > current_view_coords[:y] || scanning_ro.next_visible_ro_down.nil? #I shouldn't need this?
|
100
|
+
scanning_ro = scanning_ro.next_visible_ro_down
|
101
|
+
top_ros << scanning_ro
|
102
|
+
end
|
103
|
+
top_ros.last
|
104
|
+
end
|
105
|
+
|
106
|
+
def body_array_from_ro(ro)
|
107
|
+
y, _x = $stdout.winsize
|
108
|
+
non_header_view_size = y - visible_header_string.split("\n").count
|
109
|
+
display_array = []
|
110
|
+
|
111
|
+
scanning_ro = ro
|
112
|
+
display_array << scanning_ro.to_s
|
113
|
+
|
114
|
+
while scanning_ro.next_visible_ro_down && display_array.count < non_header_view_size
|
115
|
+
scanning_ro = scanning_ro.next_visible_ro_down
|
116
|
+
display_array << scanning_ro.to_s
|
117
|
+
end
|
118
|
+
|
119
|
+
display_array
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scryglass
|
4
|
+
class ViewPanel
|
5
|
+
using AnsilessStringRefinement
|
6
|
+
|
7
|
+
attr_accessor :current_view_coords, :x_boundaries, :y_boundaries
|
8
|
+
attr_accessor :scry_session
|
9
|
+
|
10
|
+
def initialize(scry_session:)
|
11
|
+
self.scry_session = scry_session
|
12
|
+
self.current_view_coords = { x: 0, y: 0 }
|
13
|
+
|
14
|
+
recalculate_boundaries
|
15
|
+
end
|
16
|
+
|
17
|
+
def ensure_correct_view_coords
|
18
|
+
_screen_height, screen_width = $stdout.winsize
|
19
|
+
top_boundary = y_boundaries.min
|
20
|
+
bottom_boundary = y_boundaries.max
|
21
|
+
left_boundary = x_boundaries.min
|
22
|
+
right_boundary = x_boundaries.max
|
23
|
+
|
24
|
+
## Snap View, Vertical
|
25
|
+
screen_bottom_index = (body_screen_height - 1)
|
26
|
+
top_edge_of_view = current_view_coords[:y]
|
27
|
+
bottom_edge_of_view = current_view_coords[:y] + screen_bottom_index
|
28
|
+
if bottom_edge_of_view > bottom_boundary
|
29
|
+
current_view_coords[:y] = [bottom_boundary - screen_bottom_index, 0].max
|
30
|
+
elsif top_edge_of_view < top_boundary
|
31
|
+
current_view_coords[:y] = top_boundary
|
32
|
+
end
|
33
|
+
|
34
|
+
## Snap View, Horizontal
|
35
|
+
screen_right_edge_index = (screen_width - 1)
|
36
|
+
left_edge_of_view = current_view_coords[:x]
|
37
|
+
right_edge_of_view = current_view_coords[:x] + screen_right_edge_index
|
38
|
+
if !x_boundaries.include?(left_edge_of_view)
|
39
|
+
current_view_coords[:x] = left_boundary
|
40
|
+
elsif !x_boundaries.include?(right_edge_of_view)
|
41
|
+
current_view_coords[:x] = right_boundary - screen_right_edge_index
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def move_view_up(distance)
|
46
|
+
current_view_coords[:y] -= distance
|
47
|
+
end
|
48
|
+
|
49
|
+
def move_view_down(distance)
|
50
|
+
current_view_coords[:y] += distance
|
51
|
+
end
|
52
|
+
|
53
|
+
def move_view_left(distance)
|
54
|
+
current_view_coords[:x] -= distance
|
55
|
+
end
|
56
|
+
|
57
|
+
def move_view_right(distance)
|
58
|
+
current_view_coords[:x] += distance
|
59
|
+
end
|
60
|
+
|
61
|
+
def screen_string
|
62
|
+
Hexes.opacify_screen_string(visible_header_string + "\n" + visible_body_string)
|
63
|
+
end
|
64
|
+
|
65
|
+
def recalculate_boundaries
|
66
|
+
recalculate_y_boundaries
|
67
|
+
recalculate_x_boundaries
|
68
|
+
end
|
69
|
+
|
70
|
+
def visible_header_string
|
71
|
+
visible_header_slice(uncut_header_string)
|
72
|
+
end
|
73
|
+
|
74
|
+
def visible_body_string
|
75
|
+
visible_body_slice(uncut_body_string)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def visible_header_slice(uncut_header_string)
|
81
|
+
Hexes.simple_screen_slice(uncut_header_string)
|
82
|
+
end
|
83
|
+
|
84
|
+
def body_screen_height
|
85
|
+
screen_height, _screen_width = $stdout.winsize
|
86
|
+
# It would be more efficient, but technically overall less accurate, to
|
87
|
+
# avoid recalculating visible_header_string here (and everywhere that calls this)
|
88
|
+
screen_height - visible_header_string.split("\n").count
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scryglass
|
4
|
+
class ViewWrapper
|
5
|
+
attr_accessor :model, :string, :string_lambda
|
6
|
+
|
7
|
+
def initialize(model, string: nil, string_lambda: nil)
|
8
|
+
unless !!string ^ !!string_lambda
|
9
|
+
raise ArgumentError, 'Must provide either `string` or `string_lambda`, ' \
|
10
|
+
'but not both.'
|
11
|
+
end
|
12
|
+
|
13
|
+
self.model = model
|
14
|
+
self.string = string
|
15
|
+
self.string_lambda = string_lambda
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
return string if string
|
20
|
+
return string_lambda.call(model) if string_lambda
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/scryglass.gemspec
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "scryglass/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "scryglass"
|
8
|
+
spec.version = Scryglass::VERSION
|
9
|
+
spec.authors = ["Gavin Myers"]
|
10
|
+
spec.email = ["gavin.myers@annkissam.com"]
|
11
|
+
|
12
|
+
spec.summary = 'Scryglass is a ruby console tool for visualizing ' \
|
13
|
+
'and actively exploring objects.'
|
14
|
+
spec.description = 'Scryglass is a ruby console tool for visualizing ' \
|
15
|
+
'and actively exploring objects (large, nested, interrelated, ' \
|
16
|
+
'or unfamiliar). You can navigate nested arrays, hashes, instance variables, ' \
|
17
|
+
'ActiveRecord relations, and unknown Enumerable types like an' \
|
18
|
+
"expandable/collapsable file tree in an intuitive UI.\n\n" \
|
19
|
+
'Objects and child objects can also be inspected through a variety of ' \
|
20
|
+
'display lenses, returned directly to the console, and more!'
|
21
|
+
spec.homepage = "https://github.com/annkissam/scryglass"
|
22
|
+
|
23
|
+
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
|
24
|
+
# to allow pushing to a single host or delete this section to allow pushing to any host.
|
25
|
+
if spec.respond_to?(:metadata)
|
26
|
+
spec.metadata["allowed_push_host"] = 'https://rubygems.org/'
|
27
|
+
else
|
28
|
+
raise "RubyGems 2.0 or newer is required to protect against " \
|
29
|
+
"public gem pushes."
|
30
|
+
end
|
31
|
+
|
32
|
+
# Specify which files should be added to the gem when it is released.
|
33
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
34
|
+
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
|
35
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
36
|
+
end
|
37
|
+
spec.bindir = "exe"
|
38
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
39
|
+
spec.require_paths = ["lib"]
|
40
|
+
|
41
|
+
spec.required_ruby_version = '>= 2.4.4'
|
42
|
+
|
43
|
+
spec.add_development_dependency 'activesupport', '~> 5.0'
|
44
|
+
spec.add_development_dependency 'bundler', '~> 2.1'
|
45
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
46
|
+
end
|
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: scryglass
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gavin Myers
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2020-09-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activesupport
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '5.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: bundler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '2.1'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '2.1'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rake
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '10.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '10.0'
|
55
|
+
description: |-
|
56
|
+
Scryglass is a ruby console tool for visualizing and actively exploring objects (large, nested, interrelated, or unfamiliar). You can navigate nested arrays, hashes, instance variables, ActiveRecord relations, and unknown Enumerable types like anexpandable/collapsable file tree in an intuitive UI.
|
57
|
+
|
58
|
+
Objects and child objects can also be inspected through a variety of display lenses, returned directly to the console, and more!
|
59
|
+
email:
|
60
|
+
- gavin.myers@annkissam.com
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files: []
|
64
|
+
files:
|
65
|
+
- ".gitignore"
|
66
|
+
- ".tool-versions"
|
67
|
+
- Gemfile
|
68
|
+
- Gemfile.lock
|
69
|
+
- LICENSE.txt
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- bin/console
|
73
|
+
- bin/setup
|
74
|
+
- example_config.rb
|
75
|
+
- lib/example_material.rb
|
76
|
+
- lib/hexes.rb
|
77
|
+
- lib/prog.rb
|
78
|
+
- lib/refinements/ansiless_string_refinement.rb
|
79
|
+
- lib/refinements/array_fit_to_refinement.rb
|
80
|
+
- lib/refinements/clip_string_refinement.rb
|
81
|
+
- lib/refinements/constant_defined_string_refinement.rb
|
82
|
+
- lib/scryglass.rb
|
83
|
+
- lib/scryglass/config.rb
|
84
|
+
- lib/scryglass/lens_helper.rb
|
85
|
+
- lib/scryglass/lens_panel.rb
|
86
|
+
- lib/scryglass/ro.rb
|
87
|
+
- lib/scryglass/ro_builder.rb
|
88
|
+
- lib/scryglass/session.rb
|
89
|
+
- lib/scryglass/tree_panel.rb
|
90
|
+
- lib/scryglass/version.rb
|
91
|
+
- lib/scryglass/view_panel.rb
|
92
|
+
- lib/scryglass/view_wrapper.rb
|
93
|
+
- scryglass.gemspec
|
94
|
+
homepage: https://github.com/annkissam/scryglass
|
95
|
+
licenses: []
|
96
|
+
metadata:
|
97
|
+
allowed_push_host: https://rubygems.org/
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 2.4.4
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubygems_version: 3.1.4
|
114
|
+
signing_key:
|
115
|
+
specification_version: 4
|
116
|
+
summary: Scryglass is a ruby console tool for visualizing and actively exploring objects.
|
117
|
+
test_files: []
|