Skip to content

Commit

Permalink
Summarize (#19)
Browse files Browse the repository at this point in the history
* Add [z] to summarize arrays
  • Loading branch information
tshort authored Jan 9, 2022
1 parent 4fc4dc9 commit 0e051c7
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 3 deletions.
3 changes: 2 additions & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
name = "Eyeball"
uuid = "ce36242b-ad83-4f84-8519-47cd8aeefd60"
authors = ["Tom Short <[email protected]>"]
version = "0.3.1"
version = "0.4.0"

[deps]
AbstractTrees = "1520ce14-60c1-5f80-bbc7-55ef81b5835c"
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
REPL = "3fa0cd96-eef1-5676-8a61-b3b8758bbffb"
Statistics = "10745b16-79ce-11e8-11f9-7d13ad32a3b2"
TerminalPager = "0c614874-6106-40ed-a7c2-2f1cd0bff883"

[compat]
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ The user can interactively browse the object tree using the following keys:
* `r` -- Return tree. Return the tree (a `FoldingTrees.Node`).
* `s` -- Show object.
* `t` -- Typeof. Show the type of the object in a new tree view.
* `z` -- Summarize. Toggle a summary of the object and child objects.
For arrays, this shows the mean and 0, 25, 50, 75, and 100% quantiles (skipping missings).
* `0`-`9` -- Fold to depth. Also toggles expansion of items normally left folded.
* `enter` -- Return the object.
* `q` -- Quit.
Expand All @@ -38,6 +40,7 @@ Notes:
* Some types are not recursed into. This includes modules. You can use `o` to open these in a new tree view.
* `O` and `all = true` adds a wrapper `Eyeball.All` around the object.
This is mainly for use with modules where options are taken with `name(module, all = true)`.
* Summarize `z` shows a summary of child objects. That's useful for DataFrames, nested arrays, and similar types.

## Examples

Expand Down Expand Up @@ -243,6 +246,9 @@ That's done internally for `Module`s, `Method`s, and a few other types.
This is useful for types where the components usually don't need to be shown.
This defaults to `false`.
To add additional "summarize" options, define `Base.show(io::IO, x::Eyeball.Summarize{T})` for type `T`.
## Under the Hood
`Eyeball` uses [FoldingTrees](https://github.com/JuliaCollections/FoldingTrees.jl) for display of trees and interactivity.
Expand Down
63 changes: 61 additions & 2 deletions src/Eyeball.jl
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import REPL.TerminalMenus: request
using AbstractTrees

import TerminalPager
using Statistics


# TODO: de-vendor once changes are upstreamed.
include("vendor/FoldingTrees/src/FoldingTrees.jl")
Expand Down Expand Up @@ -44,6 +46,8 @@ During interactive browsing of the object tree, the following keys are available
* `r` -- Return tree. Return the tree (a `FoldingTrees.Node`).
* `s` -- Show object.
* `t` -- Typeof. Show the type of the object in a new tree view.
* `z` -- Summarize. Toggle a summary of the object and child objects.
For arrays, this shows the mean and 0, 25, 50, 75, and 100% quantiles (skipping missings).
* `0`-`9` -- Fold to depth. Also toggles expansion of items normally left folded.
* `enter` -- Return the object.
* `q` -- Quit.
Expand Down Expand Up @@ -163,6 +167,24 @@ function eye(x = Main, depth = 10; interactive = true, all = false)
println(term.out_stream, "\n\nOpening typeof(`$(node.data.key)`) ...\n")
choice = eye(typeof(node.data.value))
resetterm()
elseif i == Int('z')
node = FoldingTrees.setcurrent!(menu, menu.cursoridx)
d = node.data
d.summarize[] = !d.summarize[]
if d.summarize[]
d.string[] = tostring(d.key, Summarize(d.value))
else
d.string[] = tostring(d.key, d.value)
end
for n in node.children
dc = n.data
dc.summarize[] = d.summarize[]
if dc.summarize[]
dc.string[] = tostring(dc.key, Summarize(dc.value))
else
dc.string[] = tostring(dc.key, dc.value)
end
end
elseif i in Int.('0':'9')
node = FoldingTrees.setcurrent!(menu, menu.cursoridx)
expandall = foldctx.cursoridx == menu.cursoridx && foldctx.depth == i && foldctx.expandall
Expand All @@ -178,7 +200,7 @@ function eye(x = Main, depth = 10; interactive = true, all = false)
term = default_terminal()
while true
menu = TreeMenu(root, pagesize = REPL.displaysize(term)[1] - 2, dynamic = true, keypress = keypress)
choice = TerminalMenus.request(term, "[f] fields [d] docs [e] expand [m/M] methodswith [o] open [r] tree [s] show [t] typeof [q] quit", menu; cursor=cursor)
choice = TerminalMenus.request(term, "[f] fields [d] docs [e] expand [m/M] methodswith [o] open [r] tree [s] show [t] typeof [z] summarize [q] quit", menu; cursor=cursor)
choice !== nothing && return returnfun(choice)
if redo
redo = false
Expand All @@ -198,7 +220,10 @@ struct ObjectWrapper{K,V}
value::V
string::Base.RefValue{Union{Nothing,String}}
showfields::Base.RefValue{Bool}
ObjectWrapper{K,V}(key, value, string = Ref{Union{Nothing,String}}(nothing), showfields = Ref(false)) where {K,V} = new(key, value, string, showfields)
summarize::Base.RefValue{Bool}
ObjectWrapper{K,V}(key, value, string = Ref{Union{Nothing,String}}(nothing), showfields = Ref(false), summarize = Ref(false)) where {K,V} =
new(key, value, string, showfields, summarize
)
end

Base.show(io::IO, x::ObjectWrapper) = print(io, tostring(x.key, x.value))
Expand All @@ -217,6 +242,28 @@ struct All{T}
value
end
All(x) = All{typeof(x)}(x)

struct Summarize{T}
value
end
Summarize(x) = Summarize{typeof(x)}(x)
# Don't wrap some types
Summarize(x::ExpandPlaceholder) = x
Summarize(x::UNDEFPlaceholder) = x

function Base.show(io::IO, x::Summarize{<:AbstractArray{T}}) where T<:Union{Real,Missing}
if eltype(x) >: Missing
#nm = nmissing(x)
v = skipmissing(x.value)
else
v = x
end
print(io, "x̅=", mean(v), ", q=", quantile(v, [0, .25, 0.5, 0.75, 1]))
# nm > 0 && print(io, ", nm=", nm)
nothing
end
Base.show(io::IO, x::Summarize) = show(io, x.value)

getdoc(x) = doc(x)
getdoc(x::Method) = doc(x.module.eval(x.name))

Expand Down Expand Up @@ -320,15 +367,27 @@ function tostring(key, value)
extras(value), " ",
svalue)
end

function tostring(key, value::UNDEFPlaceholder)
string(style(string(key), color = :cyan), ": #undef")
end

function tostring(key, value::ExpandPlaceholder)
N = length(value.itr.itr)
n = length(value.itr)
string(style(string(key), color = :red), " Showing items 1-", N-n, " of ", N, ". Items remaining=", n, ". Hit [e] to expand.")
end

function tostring(key, x::Summarize)
io = IOContext(IOBuffer(), :compact => true, :limit => true, :color => true)
show(io, x)
svalue = String(take!(io.io))
string(style(string(key), color = :cyan), ": ",
style(string(typeof(x.value)), color = :green), " ",
extras(x.value), " ",
svalue)
end


"""
```
Expand Down

0 comments on commit 0e051c7

Please sign in to comment.