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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2ba13f5c4e89b1e2750fd307557d9093cbc8194fa3696fc314515011322786cf
4
- data.tar.gz: 853762f415aada3e416f20beb12b1033620d60747a5ca49c76a1f4ab53af7073
3
+ metadata.gz: 794955e1442681f7888649a777bba632228df242fb61506623900f8b301f7e68
4
+ data.tar.gz: a91831413fb4c87d28281a2ab9bab126666d9646c56d9056563785e41914ceaf
5
5
  SHA512:
6
- metadata.gz: c58c3f36b278b03c0ab7105eb7e72eb6ae0db614945623752096ce07e5ca8401b03d3e23761fc79336f335d63d4ee9ef9dc12a3c9ede29121e74cf966124940a
7
- data.tar.gz: 1f80a280e9a45cf1407377bf5128c222c4384154b9971992c68b98c8ba02128132d7424c7c12672c4dacf6a22b34616e5630b4ce5b27492580a684e0fb231db8
6
+ metadata.gz: dcc4c9b7d57a5f57c34ebddf4f4cd94cc1eec0d47dc28818efeb3be964c2a8533fb79cc85127b479759b318c1eb380a12a917bcd30b5942861d5de16738ad56c
7
+ data.tar.gz: fac7a9f0f29d291b3711b7d5e8750c2af9567afda592666b58924bbc9d658a2cc36b7b040f735c245957ab4c62d2b16f8f24e76eb16463472c9fc367c2a6ef23
Binary file
data/.irbrc ADDED
@@ -0,0 +1,9 @@
1
+ Scryglass.load
2
+
3
+ def th
4
+ Scryglass.test_hash
5
+ end
6
+
7
+ def dh
8
+ Scryglass.demo_hash
9
+ end
@@ -1 +1 @@
1
- ruby 2.4.4
1
+ ruby 2.5.3
@@ -0,0 +1,119 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## Added
11
+
12
+ ## Changed
13
+
14
+ ## Fixed
15
+
16
+ ## [2.0.1] - 2020-01-13
17
+
18
+ ## Changed
19
+
20
+ - The named-an-object message now stays for 3 seconds instead of 2.
21
+
22
+ ## Fixed
23
+
24
+ - Typo in spec.description in scryglass.gemspec.
25
+ - Negative sign error on method_showcase_for while calculating padding for very long method names.
26
+
27
+ ## [2.0.0] - 2021-01-13
28
+
29
+ ## Added
30
+
31
+ - Turned on ANSI formatted/colored support with AnsiSliceStringRefinement.
32
+ - Added 'AmazingPrint' lens (colored) and gem.
33
+ - Added color formatting to (beta) method_showcase_for.
34
+ - Added "Smart Open" command 'o', which attempts to create sub-rows of the (next) most helpful type.
35
+ - README and help screen now point out that holding SHIFT will increase up/down step distance.
36
+ - Bottom and right edges of screen now indicate, with dots, when there is more beyond the view's edge.
37
+ - Added the VIM home row keybindings `h`/`j`/`k`/`l` as optional arrow keys.
38
+ - Now if the scry session hits an error, it will first ensure the error and console prompt appear below the present screen.
39
+ - Can now press `=` to give a console instance variable name to current objects without leaving scry session.
40
+ - Added popup messages for when the user attempts to create sub-rows for the current row and no sub-items are found.
41
+ - Added tab functionality to manage multiple scry session tabs for easy reference and comparison.
42
+ - Scryglass version now shows up in top right corner of the tree view when the header has no values to track.
43
+ - Improved and enabled 'Method Showcase' lens by default.
44
+ - Added `[<]`/`[>]` key reminders to Lens View.
45
+
46
+ ## Changed
47
+
48
+ - Changed user_signal timeout period from 0.1sec to 0.3sec to reduce number of coincidentally dropped inputs.
49
+ - Changed AnsiSliceStringRefinement syntax even closer to 'string'[args] (supporting [i, l] syntax).
50
+ - Changed the keys for switching subject type and lens from `L`/`l` to `<`/`>` (To make room for vim h/j/k/l keybindings)
51
+ - Expanded list of "Patient Actions" which won't beep even if that procedure (sometimes user input) took longer than 4 seconds.
52
+ - Improved popup messages QOL (they now stack properly and don't make the user wait for them to disappear).
53
+ - Removed `scry_resume` command; bare `scry` now always resumes last session even if the current console receiver isn't `main`.
54
+ - Made help screen key text blue.
55
+
56
+ ## Fixed
57
+
58
+ - Some more fixes to support (BETA) method_showcase_for:
59
+ - Added method_source gem.
60
+ - Now requiring lens_helper.
61
+ - Changed method to be callable externally
62
+ - Extra view margin no longer producible at far end of ANSI strings
63
+ - Escape true newlines returned by objects with unexpected `.inspect` results, which otherwise messes up the display.
64
+ - Cursor indicators ( `(`/`@`/`·` ) can no longer stall or error on exceptional objects; they now show up as `X` if they error or take too long (0.05s).
65
+ - When quitting from the help screen, cursor and prompt are now set all the way at the bottom of the display, rather than where the content ends on the current *non-help* panel.
66
+
67
+ ## [1.1.0] - 2020-09-21
68
+
69
+ ## Added
70
+
71
+ - Added ability to distinguish genuine escape key presses, and added escape key functionality.
72
+ - Added ability (AnsiSliceStringRefinement) to slice strings while effectively maintaining their ANSI formatting, as our eyes would expect.
73
+ - Added some dynamic header items to Tree View that track the following:
74
+ - Multiple targets count and message
75
+ - Last search text (what will be searched again by hitting 'n')
76
+ - Number-to-move, if digits are typed
77
+ - ('?' controls reminder now only displays when header is otherwise empty)
78
+
79
+ ## Changed
80
+
81
+ - Now inputs check and screen redraws every 0.1 seconds even without user keypresses.
82
+ - (ArrayFitToRefinement now allows non-plural array counts)
83
+
84
+ ## Removed
85
+
86
+ - Temporarily removed record/playback functionality
87
+ - Removed all dependency on activesupport
88
+
89
+ ## Fixed
90
+
91
+ - Fixed issue where shrinking the console screen size enough would create a visual glitch until one of the boundary-resizing commands was received.
92
+
93
+ ## [1.0.1] - 2020-09-18
94
+
95
+ ### Added
96
+
97
+ - Added `require 'stringio'` for StringIO
98
+
99
+ ### Removed
100
+
101
+ - Removed development_dependency 'io-console'
102
+
103
+ ## [1.0.0] - 2020-09-18
104
+
105
+ ### Added
106
+
107
+ - add_development_dependency 'io-console'
108
+ - Added table of contents to README
109
+
110
+ ### Changed
111
+
112
+ - Bumped required_ruby_version from '>= 2.4.4' to '>= 2.5.3'
113
+ - Bumped rake version from '~> 10.0' to '~> 12.0'
114
+
115
+ ## [0.1.0] - 2020-09-17
116
+
117
+ ### Added
118
+
119
+ - The First Commit!
data/Gemfile CHANGED
@@ -2,5 +2,3 @@ source "https://rubygems.org"
2
2
 
3
3
  # Specify your gem's dependencies in scryglass.gemspec
4
4
  gemspec
5
-
6
- gem "rake", "~> 12.0"
@@ -1,31 +1,35 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- scryglass (0.1.0)
4
+ scryglass (2.0.1)
5
+ amazing_print
6
+ binding_of_caller
7
+ method_source
5
8
 
6
9
  GEM
7
10
  remote: https://rubygems.org/
8
11
  specs:
9
- activesupport (5.2.4.4)
10
- concurrent-ruby (~> 1.0, >= 1.0.2)
11
- i18n (>= 0.7, < 2)
12
- minitest (~> 5.1)
13
- tzinfo (~> 1.1)
14
- concurrent-ruby (1.1.7)
15
- i18n (1.8.5)
16
- concurrent-ruby (~> 1.0)
17
- minitest (5.14.2)
12
+ amazing_print (1.2.1)
13
+ binding_of_caller (0.8.0)
14
+ debug_inspector (>= 0.0.1)
15
+ coderay (1.1.3)
16
+ debug_inspector (0.0.3)
17
+ interception (0.5)
18
+ method_source (1.0.0)
19
+ pry (0.13.1)
20
+ coderay (~> 1.1)
21
+ method_source (~> 1.0)
22
+ pry-rescue (1.5.2)
23
+ interception (>= 0.5)
24
+ pry (>= 0.12.0)
18
25
  rake (12.3.3)
19
- thread_safe (0.3.6)
20
- tzinfo (1.2.7)
21
- thread_safe (~> 0.1)
22
26
 
23
27
  PLATFORMS
24
28
  ruby
25
29
 
26
30
  DEPENDENCIES
27
- activesupport (~> 5.0)
28
31
  bundler (~> 2.1)
32
+ pry-rescue
29
33
  rake (~> 12.0)
30
34
  scryglass!
31
35
 
data/README.md CHANGED
@@ -11,6 +11,28 @@ It facilitates:
11
11
  - Education, learning the structure of objects and their relationships
12
12
  - Comparing/Scanning sub-items in an Enumerable (e.g. Person.first.library_records.scry)
13
13
 
14
+
15
+ # Table of Contents
16
+
17
+ [🔮 Scryglass Intro Summary](#-scryglass)
18
+ - [⚡️ tl;dr SUPER Quick Start](#%EF%B8%8F-tldr-super-quick-start)
19
+ - [Installing Scryglass](#installing-scryglass)
20
+ - [Enabling Scryglass](#enabling-scryglass)
21
+ - [Launching a Scry Session](#launching-a-scry-session)
22
+ - [Basic Usage](#basic-usage)
23
+ - [Reading the UI](#reading-the-ui)
24
+ - [Tree View (default) Row Sample Strings](#tree-view-default-row-sample-strings)
25
+ - [Known Enumerables](#known-enumerables)
26
+ - [The Cursor, and Unknown Enumerables](#the-cursor-and-unknown-enumerables)
27
+ - [Waiting!](#waiting)
28
+ - [In-Depth Control Rundown](#in-depth-control-rundown)
29
+ - [Configuration / Customization (all optional)](#configuration--customization-all-optional)
30
+ - [A Note on Adding Your Own Lenses](#a-note-on-adding-your-own-lenses)
31
+ - [Controlling How Some Objects Are Displayed in Tree View / Using Scryglass as the UI for Another Tool](#controlling-how-some-objects-are-displayed-in-tree-view--using-scryglass-as-the-ui-for-another-tool)
32
+ - [Miscellaneous Troubleshooting Notes](#miscellaneous-troubleshooting-notes)
33
+ - [Contributing](#contributing)
34
+
35
+
14
36
  ## ⚡️ tl;dr SUPER Quick Start
15
37
 
16
38
  If you're in a real hurry to get your hands in it (though not necessarily in the most efficient way), here are the quickest steps!
@@ -38,7 +60,7 @@ $ gem install scryglass
38
60
  ```
39
61
  ## Enabling Scryglass
40
62
 
41
- For the `scry` method syntax to work as cleanly as it does, Scryglass needs to add the method to the Kernel module. While this is safe, it was safest to have this only happen on a console session basis. To enable the `scry` method, call `Scryglass.load`. Thus, to automatically enable Scryglass when opening a console, you add one of the following lines to your `./irbrc` (and `./pryrc` for rails or pry sessions):
63
+ For the `scry` method syntax to work as cleanly as it does, Scryglass needs to add the method to the Kernel module. While this is safe, it was safest to have this only happen on a console session basis. To enable the `scry` method, call `Scryglass.load`. Thus, to automatically enable Scryglass when opening a console, you add one of the following lines to your `./.irbrc` (and `./.pryrc` for rails or pry sessions):
42
64
  ```ruby
43
65
  Scryglass.load
44
66
  ```
@@ -65,9 +87,6 @@ To start a Scry Session, call:
65
87
  **A note about passing an argument without parentheses:**
66
88
  > The arg syntax (`scry my_object`) will get confused if it's given a hash direcly (`scry {a: [1, 2] }`), thinking you're trying to pass a block, unless you use parentheses (`scry({a: [1, 2] })`).
67
89
 
68
- **A note about using the resume session command, while in a pry:**
69
- > The straight resume command, the bare `scry`, relies on the assumption that the method receiver is `main`. When your console is a pry in some other code, `self` is no longer `main`, but some other object, and so you are actually calling `scry` on that, overwriting your previous session. If you still want to resume session in that context, you can use `scry_resume`.
70
-
71
90
  ## Basic Usage
72
91
 
73
92
  Use the arrow keys to move around and open/close known Enumerable types! Hit `'?'` to view all the controls and learn how to do much much more.
@@ -108,40 +127,47 @@ The cursor, movable by arrow keys, is represented by a straight line (`–––
108
127
  | `––––` | ...no secret contents |
109
128
  | `(–––` | ...a non-empty Enumerable of an unknown type (openable with `'('`) |
110
129
  | `–@––` | ...instance variables on the object (openable with `'@'`) |
111
- | `(@––` | ...both! ***Generally* instance variables yield more sub-items with more info.** |
130
+ | `––·–` | ...ActiveRecord associations (openable with `'.'`) |
131
+ | `(@·–` | ...all three! (Note: ***Generally* IVs yield more sub-items with more info than using `'('`).** |
112
132
 
113
- ActiveRecord objects are no secret; you can press `'.'` on them to build their AR Association sub-items.
133
+ An `X` in place of any of these characters indicates an error or a timeout (if the "counting" process takes longer than 0.05 seconds)
114
134
 
115
135
  A single `•` will mark the presence of user-added rows when they are hidden.
116
136
 
117
137
  ### Waiting!
118
138
  Scryglass has two features to make wait time a little easier:
119
- - If any process takes longer than 4 seconds between you pressing a key and the process completing, it **makes a beep sound!** This means if something seems like it might take a bit, you can switch to another tab or window without worry, and it will tell you when to check back.
139
+ - If any process (with a couple exceptions for user input) takes longer than 4 seconds between you pressing a key and the process completing, it **makes a beep sound!** This means if something seems like it might take a bit, you can switch to another tab or window without worry, and it will tell you when to check back.
120
140
  - While there are no time estimates (for a number of reasons), many subprocesses are linked to a **progress bar**, which will display at the bottom of the screen. If multiple nested processes are running one within another, the progress bar will divide itself into parts to show each process. The leftmost bar is the base level iteration task.
121
141
 
122
142
  ## In-Depth Control Rundown
123
143
 
124
- | Key | Help Screen Snippet | Verbose Description |
144
+ | Key | Help_Screen_Snippet | Verbose Description |
125
145
  |:---:|---------------------|---------------------|
126
146
  | `?` | Press '?' for controls | `?` will cycle through the help panels, then back to the scry session. |
127
147
  | `q` | Quit Scry | Exits the scry session, returning nil. The cursor (and exit message) is then placed below the last line console line with content in order to take up no more space than needed. |
128
- | `UP`/`DOWN` | Navigate (You can type a number first) | Moves the cursor one step upward or downward in the tree view (this can be done while in lens view). If a number (of any number of digits) is typed out before pressing `UP` or `DOWN`, then the cursor will move that many steps in that direction. If the number of steps goes past the edge of the list, the cursor will sit safely at that edge. |
129
- | `RIGHT` | Expand current or selected row(s) | If any rows are *selected* this attempts to expand all of them, and will expand the ones it can. If none are selected, then it will attempt to expand the current row where the cursor is. If the current row has preexisting sub-items, but they are hidden because the current ro is collapsed, this will reveal them in the tree view. |
148
+ | `UP`/`DOWN` | Navigate (To move further, type a number first or use SHIFT) | Moves the cursor one step upward or downward in the tree view (this can be done while in lens view). If a number (of any number of digits) is typed out before pressing `UP` or `DOWN`, then the cursor will move that many steps in that direction. If `SHIFT` is held while pressing, then the cursor will move 12 steps in that direction. If the number of steps goes past the edge of the list, the cursor will sit safely at that edge. |
149
+ | `RIGHT` | Expand current or selected row(s) | If any rows are *selected* this attempts to expand all of them, and will expand the ones it can. If none are selected, then it will attempt to expand the current row where the cursor is. If the current row has preexisting sub-items, but they are hidden because the current row is collapsed, this will reveal them in the tree view. |
130
150
  | `LEFT` | Collapse current or selected row(s) | If any rows are *selected* this attempts to collapse all of them, and will collapse the ones it can. If none are selected, then it will attempt to collapse the current row where the cursor is. If the current row either has no sub-items or is already collapsed, this action will collapse its parent row instead and place the cursor there. |
151
+ | `h`/`j`/`k`/`l` | (These keys on the home row can also serve as arrow keys) | This is for those familiar with VIM keybindings! Shift speeds up k/j to 12 steps just the same as UP/DOWN. |
131
152
  | `ENTER` | Close Scry, returning current or selected object(s) (Key or Value) | Returns the subject object (based on current subject type, :value or :key) of the current item, or, if any items are selected (`->`), it returns all of those in an array. The order matches the order in which they were marked as selected. In the case of \| and \*, the order of the array will be top to bottom. If the current Subject Type (toggled by `L`) is :key, rows without "keys" will return `nil`. |
132
153
  | `SPACEBAR` | Toggle Lens View | Switches between Tree View and Lens View. This will not change the view position of the lens view, but the view position of the tree view will still follow the cursor if the cursor moves while in lens view. |
133
- | `l` | Cycle through lens types | Cycles through the different lens types in the lens view. These all take the current row, at either the "key" or the "value" object depending on the current subject type (toggled by `L`), and display a string of it, transformed through that particular lens. New lenses can be written in the config. |
134
- | `L` | Toggle subject (Key/Value of row) | This change is only perceptible in the lens view, but does also change which objects are returned by `ENTER`. Any objects without "keys" will return nil for their :key if they don't have one. |
135
- | `w`/`a`/`s`/`d` | Move view window (ALT increases speed) | The W/A/S/D keys form a second set of arrow keys for moving around the "screen" through which you view the tree view and the lens view, when the contents don't all fit on the screen at once. They move 5 cells in the specificied direction, or 50 if ALT is held before pressing. Can be held down for continuous movement. |
154
+ | `>` | Cycle through lens types | Cycles through the different lens types in the lens view. These all take the current row, at either the "key" or the "value" object depending on the current subject type (toggled by `L`), and display a string of it, transformed through that particular lens. New lenses can be written in the config. |
155
+ | `<` | Toggle subject (Key/Value of row) | This change is only perceptible in the lens view, but does also change which objects are returned by `ENTER`. Any objects without "keys" will return nil for their :key if they don't have one. |
156
+ | `w`/`a`/`s`/`d` | Move view window (ALT increases speed) | The W/A/S/D keys form a second set of arrow keys for moving around the "screen" through which you view the tree view and the lens view, when the contents don't all fit on the screen at once. They move 5 cells in the specified direction, or 50 if ALT is held before pressing. Can be held down for continuous movement. |
136
157
  | `0` | Reset view location (Press again: reset cursor) | This resets/zeros the current view (tree or lens). If you are in the tree view, and the view is in the zero (top left) position, then this will instead move the cursor there. |
137
158
  | `@` | Build instance variable sub-rows for current or selected row(s) | Identifies all instance variables on the object (or value of a key-value pair) of the current or selected rows. Then these instance variables are turned into a list of keys, called on the original object, and then paired with the resulting objects. Known Enumerables are recursively navigable as always. |
138
- | `.` | 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`).* |
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. |
139
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
+ | `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. |
140
162
  | `*` | Select/Deselect ALL rows | This includes hidden rows. If all rows are already selected, they will be unselected, regardless of how they became selected. |
141
163
  | `\|` | 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. |
142
164
  | `-` | 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
+ | `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.
143
167
  | `/` | 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). |
144
168
  | `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
+ | `=` | 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. |
170
+ | `Esc` | Resets selection, last search, and number-to-move. (or returns to Tree View) | (Essentially, clears the values represented in the Tree View header if you're in the Tree View; otherwise it returns you to the Tree View) |
145
171
 
146
172
  ## Configuration / Customization (all optional)
147
173
 
@@ -167,18 +193,28 @@ Scryglass.configure do |config|
167
193
  ## UX
168
194
  # config.cursor_tracking = [:flexible_range, :dead_center][0] # Default: [0]
169
195
  # config.lenses = [ # Custom lenses can easily be added as name+lambda hashes! Or comment some out to turn them off.
196
+ # { name: 'Amazing Print (`ap`)',
197
+ # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { ap o } } }, # This has colors!
170
198
  # { name: 'Pretty Print (`pp`)',
171
199
  # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { pp o } } },
172
200
  # { name: 'Inspect (`.inspect`)',
173
201
  # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { puts o.inspect } } },
174
202
  # { name: 'Yaml Print (`y`)',
175
- # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { y o } } }, # OR: `puts o.to_yaml`
203
+ # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { require 'yaml' ; y o } } }, # OR: `puts o.to_yaml`
176
204
  # { name: 'Puts (`puts`)',
177
205
  # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { puts o } } },
178
- # # { name: 'Method Showcase', # Not included by default
179
- # # lambda: ->(o) { Scryglass::LensHelper.method_showcase_for(o) } },
206
+ # { name: 'Method Showcase',
207
+ # lambda: ->(o) { Scryglass::LensHelper.method_showcase_for(o) } },
180
208
  # ]
181
209
 
210
+ ## AmazingPrint defaults, if the user has not set their own:
211
+ # AmazingPrint.defaults ||= {
212
+ # index: false, # (Don't display array indices).
213
+ # raw: true, # (Recursively format instance variables).
214
+ # }
215
+ # See https://github.com/amazing-print/amazing_print
216
+
217
+
182
218
  ## Building ActiveRecord association sub-rows:
183
219
  # config.include_empty_associations = true # Default: true
184
220
  # config.include_through_associations = false # Default: false
@@ -205,7 +241,7 @@ Here are some explanations of some less obvious configurations:
205
241
 
206
242
  For properly capturing out*put* methods of various kinds, and for the ability to truncate strings of cosmic scale before they've been *entirely* printed to the invisible IO (can be minutes and trillions of characters), we highly recommend using the `Hexes.capture_io` method with the `char_limit:` keyword argument as seen in the template config file (and Scryglass code). `capture_io` captures console output as a string; `char_limit:` will run the capture in a separate thread which can be truncated before it finishes printing.
207
243
 
208
- ## Controlling how some objects are displayed in tree view / Using Scryglass as the UI for another tool
244
+ ### Controlling how some objects are displayed in tree view / Using Scryglass as the UI for another tool
209
245
 
210
246
  Scryglass originally started as a small subtool to be used as the UI for another console project, which, in short, would output a large branching hash which was then to be navigated. To have more control over the tree panel display, you can wrap objects in a Scryglass::ViewWrapper. For example, by default, this array item: `[unsightly_object]` will appear in the tree view in its `inspect`ed form, "#<UnsightlyObject:0x00007f9ac8224e78>". But say you want it to show it's best face to the user, using the sightly return of it's `best_face` method. You can instead hand scryglass the following item:
211
247
  ```ruby
@@ -12,16 +12,26 @@ Scryglass.configure do |config|
12
12
  # config.lenses = [ # Custom lenses can easily be added as name+lambda hashes! Or comment some out to turn them off.
13
13
  # { name: 'Pretty Print (`pp`)',
14
14
  # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { pp o } } },
15
+ # { name: 'Amazing Print (`ap`)',
16
+ # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { ap o } } }, # This has colors!
15
17
  # { name: 'Inspect (`.inspect`)',
16
18
  # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { puts o.inspect } } },
17
19
  # { name: 'Yaml Print (`y`)',
18
- # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { y o } } }, # OR: `puts o.to_yaml`
20
+ # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { require 'yaml' ; y o } } }, # OR: `puts o.to_yaml`
19
21
  # { name: 'Puts (`puts`)',
20
22
  # lambda: ->(o) { Hexes.capture_io(char_limit: 20_000) { puts o } } },
21
- # # { name: 'Method Showcase', # Not included by default
22
- # # lambda: ->(o) { Scryglass::LensHelper.method_showcase_for(o) } },
23
+ # { name: 'Method Showcase',
24
+ # lambda: ->(o) { Scryglass::LensHelper.method_showcase_for(o) } },
23
25
  # ]
24
26
 
27
+ ## AmazingPrint defaults, if the user has not set their own:
28
+ # AmazingPrint.defaults ||= {
29
+ # index: false, # (Don't display array indices).
30
+ # raw: true, # (Recursively format instance variables).
31
+ # }
32
+ # See https://github.com/amazing-print/amazing_print
33
+
34
+
25
35
  ## Building ActiveRecord association sub-rows:
26
36
  # config.include_empty_associations = true # Default: true
27
37
  # config.include_through_associations = false # Default: false
@@ -35,7 +35,7 @@ module Scryglass
35
35
  "A lambda" => ->(o) { puts o.inspect.upcase.reverse },
36
36
  "\n\n\n" => "If you want to know what that lambda does, move your cursor to it, press ENTER, and it will be returned to your console for you to play with!",
37
37
  'Allll the coolest stuff' => [
38
- Scryglass::ViewWrapper.new('TODO add link', string: '...Is really in the help screens (`?`) and the README. Press spacebar for README link in lens view'),
38
+ Scryglass::ViewWrapper.new('https://github.com/annkissam/scryglass', string: '...Is really in the help screens (`?`) and the README. Press spacebar for README link in lens view'),
39
39
  ],
40
40
  :delicious_data => {
41
41
  :whoa_now => ([1]*800).map { rand(2) }.insert($stdout.winsize.first, 'Press zero to reset view position, then again to reset cursor there!'),
@@ -107,7 +107,7 @@ module Hexes
107
107
  necessary_constants_defined = necessary_constants.all?(&:constant_defined?)
108
108
  return yield unless necessary_constants_defined
109
109
 
110
- rails_logger_defined = 'Rails'.constant_defined? && Rails.try(:logger).present?
110
+ rails_logger_defined = 'Rails'.constant_defined? && !!Rails.try(:logger)
111
111
 
112
112
  ## These are purposefully preserved as global variables so retrieval, in
113
113
  ## debugging or errored usage, is as easy as possible.
@@ -7,5 +7,150 @@ module AnsilessStringRefinement
7
7
  def ansiless_length
8
8
  ansiless.length
9
9
  end
10
+
11
+ ## Splits string into characters, with each ANSI escape code being its own
12
+ ## grouped item, like so:
13
+ ## irb> "PLAIN\e[32mCOLOR\e[0mPLAIN".ansi_string_breakout
14
+ ## => ["P", "L", "A", "I", "N", "\e[32m", "C", "O", "L", "O", "R",
15
+ ## "\e[0m", "P", "L", "A", "I", "N"]
16
+ def ansi_string_breakout
17
+ breakout_array = []
18
+ working_self = self.dup
19
+
20
+ while working_self[0]
21
+ if (working_self =~ /\e\[[\d\;]*m/) == 0 # if begins with
22
+ end_of_escape_code = (working_self.index('m'))
23
+ leading_escape_code = working_self[0..end_of_escape_code]
24
+ breakout_array << leading_escape_code
25
+ working_self = working_self[(end_of_escape_code + 1)..-1]
26
+ else
27
+ leading_character = working_self[0]
28
+ breakout_array << leading_character
29
+ working_self = working_self[1..-1]
30
+ end
31
+ end
32
+
33
+ breakout_array
34
+ end
35
+
36
+ def is_ansi_escape_code?
37
+ (self =~ /^\e\[[\d\;]*m$/) == 0
38
+ end
39
+
40
+ ## Returns the indexed character of the real string, determined by the index
41
+ ## given in reference to its ANSIless display form. e.g.:
42
+ ## > s = "\e[31mTEST\e[00m"
43
+ ## > puts s
44
+ ## TEST
45
+ ## > s.ansiless_pick(1) = 'y'
46
+ ## > s
47
+ ## => "\e[31mTyST\e[00m"
48
+ def ansiless_pick(given_index)
49
+ ansiless_self = self.ansiless
50
+
51
+ return nil if ansiless_self[given_index].nil?
52
+
53
+ given_index = (given_index + ansiless_self.length) if given_index.negative?
54
+
55
+ mock_index = 0 # A scanning index that *doesn't* count ANSI codes
56
+ real_index = 0 # A scanning index that *does* count ANSI codes
57
+
58
+ ansi_string_array = ansi_string_breakout
59
+
60
+ until mock_index == given_index
61
+ while ansi_string_array.first.is_ansi_escape_code?
62
+ real_index += (ansi_string_array.shift.length)
63
+ end
64
+
65
+ ansi_string_array.shift
66
+
67
+ while ansi_string_array.first.is_ansi_escape_code?
68
+ real_index += (ansi_string_array.shift.length)
69
+ end
70
+
71
+ mock_index += 1
72
+ real_index += 1
73
+ end
74
+
75
+ self[real_index]
76
+ end
77
+
78
+ ## Like ansiless_pick, but it can set that found string character instead
79
+ def ansiless_set!(given_index, string)
80
+ raise ArgumentError, 'First argument must be an Integer' unless given_index.is_a?(Integer)
81
+ raise ArgumentError, 'Second argument must be a String' unless string.is_a?(String)
82
+
83
+ ansiless_self = self.ansiless
84
+
85
+ return nil if ansiless_self[given_index].nil?
86
+
87
+ given_index = (given_index + ansiless_self.length) if given_index.negative?
88
+
89
+
90
+ new_string = string.to_s
91
+
92
+ mock_index = 0 # A scanning index that *doesn't* count ANSI codes
93
+ real_index = 0 # A scanning index that *does* count ANSI codes
94
+
95
+ ansi_string_array = ansi_string_breakout
96
+
97
+ until mock_index == given_index
98
+ while ansi_string_array.first.is_ansi_escape_code?
99
+ real_index += (ansi_string_array.shift.length)
100
+ end
101
+
102
+ ansi_string_array.shift
103
+
104
+ while ansi_string_array.first.is_ansi_escape_code?
105
+ real_index += (ansi_string_array.shift.length)
106
+ end
107
+
108
+ mock_index += 1
109
+ real_index += 1
110
+ end
111
+
112
+ self[real_index] = new_string
113
+ end
114
+
115
+ def ansi_slice(arg1, arg2 = nil) # i.e. like 'test'[0..2] and 'test'[2, 1]
116
+ unless (arg1.is_a?(Range) && arg2.nil?) ||
117
+ (arg1.is_a?(Integer) && arg2.is_a?(Integer))
118
+ raise ArgumentError, 'ansi_slice takes either a single Range ' \
119
+ 'or two integers (index and length) as its arguments.'
120
+ end
121
+
122
+ target_range = arg1.is_a?(Range) ? arg1 : (arg1...(arg1 + arg2))
123
+
124
+ if target_range.min.negative? || target_range.max.negative?
125
+ raise ArgumentError, 'Range must be entirely positive!'
126
+ end
127
+
128
+ args = [arg1, arg2].compact
129
+ return self[*args] if (self =~ /\e\[[\d\;]*m/).nil? # No work need be done
130
+
131
+ ## And here we match the normal `:[]` behavior outside of boundaries, e.g:
132
+ ## irb> 'TEST'[4..9]
133
+ ## => ""
134
+ ## irb> 'TEST'[5..9]
135
+ ## => nil
136
+ return nil if target_range.min > self.ansiless_length
137
+
138
+ mock_index = 0 # A scanning index that *doesn't* count ANSI codes
139
+ result_string_array = []
140
+
141
+ ansi_string_breakout.each do |char|
142
+ char_is_ansi_escape_code = char.is_ansi_escape_code?
143
+ within_target_range =
144
+ target_range.include?(mock_index)
145
+
146
+ if within_target_range || char_is_ansi_escape_code
147
+ result_string_array << char
148
+ end
149
+
150
+ mock_index += 1 unless char_is_ansi_escape_code
151
+ end
152
+
153
+ result_string_array.join('')
154
+ end
10
155
  end
11
156
  end