Term Repr
Note: by repr here we refer generically to how information about an object is represented in the terminal, not the repr
function in Julia.
Type REPR
You can use Term.jl
to create a styled type display in your console.
The easiest way to explain it is by way of example. Let's say you define a type, and create an instance of it:
struct myType
name::String
height::Int
width::Int
mass::Float64
end
obj = myType("Rocket", 10, 10, 99.9)
Main.myType("Rocket", 10, 10, 99.9)
as you can see the default way to represent your object in the console is not very exciting. But we can improve that with a simple macro!
using Term.Repr
@with_repr struct myFancyType
name::String
height::Int
width::Int
mass::Float64
end
obj = myFancyType("Rocket", 10, 10, 99.9)
╭──────────────────────────╮
│ name::String Rocket │
│ height::Int64 10 │
│ width::Int64 10 │
│ mass::Float64 99.9 │
│ │
╰──────── Main.__ate... ───╯
now every time we display an instance of myFancyType
in the console, we get a nice representation (note that that's not true for print(obj)
!).
Ooopss... it looks like the Panel
display in the example above is not working out in the Docs. It will look fine in your REPL though!
Termshow
Very nice, but what if I don't have access to where the types are created (perhaps they are in another package) but still want to have the nice display? One way is to use termshow
:
dullobj = myType("Rocket", 10, 10, 99.9)
termshow(dullobj)
╭──────────────────────────╮
│ name::String Rocket │
│ height::Int64 10 │
│ width::Int64 10 │
│ mass::Float64 99.9 │
│ │
╰──────── Main.__ate... ───╯
easy!
But wait, there's more!
termshow(termshow) # or any other function
╭──── Function: termshow ──────────────────────────────────────────────╮
│ │
│ (1) termshow(io::IO, e::Expr; kwargs...) │
│ (2) │
│ (3) termshow(io::IO, obj::AbstractDict; kwargs...) │
│ (4) │
│ (5) termshow(io::IO, mtx::AbstractMatrix; kwargs...) │
│ (6) │
│ (7) termshow(io::IO, vec::Union {Tuple, AbstractVecto │
│ r} ; kwargs...) │
│ (8) │
│ (9) termshow(io::IO, arr::AbstractArray; kwargs...) │
│ (10) │
│ │
╰─────────────────────────────────────────────────────── 18 methods ───╯
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Docstring ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────────────────────────────────────────────────────┐
│ termshow │
└─────────────────────────────────────────────────────────┘
Styled string representation of any object.
`termshow` prints to stdout (or any other IO) a styled representation
of the object. Dedicated methods create displays for specify types
such as `Dict` or `Vector`.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────────────────────────────────────────────────────┐
│ termshow(io::IO, obj) │
└─────────────────────────────────────────────────────────┘
Generic method for any object not caught by dedicated methods. Creates
a `Panel` with the object's fields and contents.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────────────────────────────────────────────────────┐
│ termshow(io::IO, e::Expr; kwargs...) │
└─────────────────────────────────────────────────────────┘
Show an expression's head and arguments.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────────────────────────────────────────────────────┐
│ termshow(io::IO, d::Dict; kwargs...) │
└─────────────────────────────────────────────────────────┘
Show a dictionary's keys and values and their data types.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────────────────────────────────────────────────────┐
│ termshow(io::IO, mtx::AbstractMatrix; kwargs...) │
└─────────────────────────────────────────────────────────┘
Show a matrix content as a 2D table visualization.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────────────────────────────────────────────────────┐
│ termshow(io::IO, vec::Union {Tuple,AbstractVector} │
│ ; kwargs...) │
└─────────────────────────────────────────────────────────┘
Show a vector's content as a 1D table visualization.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────────────────────────────────────────────────────┐
│ termshow(io::IO, arr::AbstractArray; kwargs...) │
└─────────────────────────────────────────────────────────┘
Show the content of a multidimensional array as a series of 2D slices.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────────────────────────────────────────────────────┐
│ termshow(io::IO, obj::DataType; kwargs...) │
└─────────────────────────────────────────────────────────┘
Show a type's arguments, constructors and docstring.
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌─────────────────────────────────────────────────────────┐
│ termshow(io::IO, fun::Function; kwargs...) │
└─────────────────────────────────────────────────────────┘
Show a function's methods and docstring.
Fancy right? It shows the function, various methods for it and it's docstrings (by parsing the Markdown). It works with types too
import Term: Panel
termshow(Panel)
╭─────────────────────────────────────────────────────────────────────────╮
│ │
│ Panel <: Term.Panels.AbstractPanel │
│ │segments ::Vector │
│ │ measure ::Term.Measures.Measure │
│ │
╰─────────────────────────────────────────────────────────────────────────╯
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Docstring ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌──────────────────────────────────────────────────────────────────┐
│ Panel │
└──────────────────────────────────────────────────────────────────┘
`Renderable` with a panel surrounding some content:
┌──────────────────────────────────────────────────────────────────┐
│ ╭──────────╮ │
│ │ my panel │ │
│ ╰──────────╯ │
└──────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
When constructing a Panel, several keyword arguments can be used to set its
appearance:
• box::Symbol sets the `Box` type for the Panel's border
• style::String sets the box's style (e.g., color)
• title::Union sets the Panel's title
• title_style::Union sets the title's style
• title_justify::Symbol sets the location of the title
• subtitle::Union sets the Panel's subtitle
• subtitle_style::Union sets the subtitle's style
• subtitle_justify::Symbol sets the location of the subtitle
• justify::Symbol sets text's alignment (:left, :rigth, :center, :justify)
┌──────────────────────────────────────────────────────────────────┐
│ Panel(; │
│ fit::Bool = false, │
│ height::Int = 2, │
│ width::Int = 80, │
│ padding::Union{{Vector,Padding,NTuple}} = Padding(0, │
│ 0, 0, 0), │
│ kwargs..., │
│ ) │
└──────────────────────────────────────────────────────────────────┘
Construct a `Panel` with no content.
Examples
┌──────────────────────────────────────────────────────────────────┐
│ julia> Panel(height=5, width=10) │
│ ╭────────╮ │
│ │ │ │
│ │ │ │
│ │ │ │
│ ╰────────╯ │
│ │
│ julia> Panel(height=3, width=5) │
│ ╭───╮ │
│ │ │ │
│ ╰───╯ │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ Panel( │
│ content::Union{{AbstractString,AbstractRenderable}}; │
│ fit::Bool = false, │
│ padding::Union{{Nothing,Padding,NTuple}} = nothing, │
│ kwargs..., │
│ ) │
└──────────────────────────────────────────────────────────────────┘
Construct a `Panel` around an `AbstractRenderable` or `AbstractString`.
This is the main Panel-creating function, it dispatches to other methods based
on the value of `fit` to either fith the `Panel` to its content or vice versa.
`kwargs` can be used to set various aspects of the `Panel`'s appearance like
the presence and style of titles, box type etc... see render (@ref) below.
┌──────────────────────────────────────────────────────────────────┐
│ Panel( │
│ content::Union{{AbstractString,AbstractRenderable}}, │
│ ::Val{{true}}, │
│ padding::Padding; │
│ height::Union{{Nothing,Int}} = nothing, │
│ width::Union{{Nothing,Int}} = nothing, │
│ trim::Bool = true, │
│ kwargs..., │
│ ) │
└──────────────────────────────────────────────────────────────────┘
Construct a `Panel` fitting the content's width.
╭──── Warning ─────────────────────────────────────────────────────────╮
│ If the content is larger than the console terminal's width, │
│ it will │
│ get trimmed │
│ to avoid overflow, unless `trim=false` is given. │
╰──────────────────────────────────────────────────────────────────────╯
┌──────────────────────────────────────────────────────────────────┐
│ Panel( │
│ content::Union{{AbstractString,AbstractRenderable}}, │
│ ::Val{{false}}, │
│ padding::Padding; │
20 lines omitted...
and in general you can display almost any object
termshow(Dict(:x => 1, :y => 2))
termshow(zeros(3, 3))
╭──── Dict ──────╮
│ │
│ y => 2 │
│ x => 1 │
│ │
│ │
╰─────────────────────────────────╯
╭──── Matrix ... ─╮
│ │
│ │
│ (1) (2) (3) │
│ │
│ (1) 0.0 0.0 0.0 │
│ (2) 0.0 0.0 0.0 │
│ (3) 0.0 0.0 0.0 │
│ │
│ │
╰──────────────── 3 × 3 ───╯
install term repr
Okay, termshow
is pretty cool (even if I say so myself), but we need to call it every time we need to display something. I just want to type a variable name in the REPL (devs are lazy you know). Well, there's a solution for that too of course:
install_term_repr()
Panel
╭─────────────────────────────────────────────────────────────────────────╮
│ │
│ Panel <: Term.Panels.AbstractPanel │
│ │segments ::Vector │
│ │ measure ::Term.Measures.Measure │
│ │
╰─────────────────────────────────────────────────────────────────────────╯
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ Docstring ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
┌──────────────────────────────────────────────────────────────────┐
│ Panel │
└──────────────────────────────────────────────────────────────────┘
`Renderable` with a panel surrounding some content:
┌──────────────────────────────────────────────────────────────────┐
│ ╭──────────╮ │
│ │ my panel │ │
│ ╰──────────╯ │
└──────────────────────────────────────────────────────────────────┘
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
When constructing a Panel, several keyword arguments can be used to set its
appearance:
• box::Symbol sets the `Box` type for the Panel's border
• style::String sets the box's style (e.g., color)
• title::Union sets the Panel's title
• title_style::Union sets the title's style
• title_justify::Symbol sets the location of the title
• subtitle::Union sets the Panel's subtitle
• subtitle_style::Union sets the subtitle's style
• subtitle_justify::Symbol sets the location of the subtitle
• justify::Symbol sets text's alignment (:left, :rigth, :center, :justify)
┌──────────────────────────────────────────────────────────────────┐
│ Panel(; │
│ fit::Bool = false, │
│ height::Int = 2, │
│ width::Int = 80, │
│ padding::Union{{Vector,Padding,NTuple}} = Padding(0, │
│ 0, 0, 0), │
│ kwargs..., │
│ ) │
└──────────────────────────────────────────────────────────────────┘
Construct a `Panel` with no content.
Examples
┌──────────────────────────────────────────────────────────────────┐
│ julia> Panel(height=5, width=10) │
│ ╭────────╮ │
│ │ │ │
│ │ │ │
│ │ │ │
│ ╰────────╯ │
│ │
│ julia> Panel(height=3, width=5) │
│ ╭───╮ │
│ │ │ │
│ ╰───╯ │
└──────────────────────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────────┐
│ Panel( │
│ content::Union{{AbstractString,AbstractRenderable}}; │
│ fit::Bool = false, │
│ padding::Union{{Nothing,Padding,NTuple}} = nothing, │
│ kwargs..., │
│ ) │
└──────────────────────────────────────────────────────────────────┘
Construct a `Panel` around an `AbstractRenderable` or `AbstractString`.
This is the main Panel-creating function, it dispatches to other methods based
on the value of `fit` to either fith the `Panel` to its content or vice versa.
`kwargs` can be used to set various aspects of the `Panel`'s appearance like
the presence and style of titles, box type etc... see render (@ref) below.
┌──────────────────────────────────────────────────────────────────┐
│ Panel( │
│ content::Union{{AbstractString,AbstractRenderable}}, │
│ ::Val{{true}}, │
│ padding::Padding; │
│ height::Union{{Nothing,Int}} = nothing, │
│ width::Union{{Nothing,Int}} = nothing, │
│ trim::Bool = true, │
│ kwargs..., │
│ ) │
└──────────────────────────────────────────────────────────────────┘
Construct a `Panel` fitting the content's width.
╭──── Warning ─────────────────────────────────────────────────────────╮
│ If the content is larger than the console terminal's width, │
│ it will │
│ get trimmed │
│ to avoid overflow, unless `trim=false` is given. │
╰──────────────────────────────────────────────────────────────────────╯
┌──────────────────────────────────────────────────────────────────┐
│ Panel( │
│ content::Union{{AbstractString,AbstractRenderable}}, │
│ ::Val{{false}}, │
│ padding::Padding; │
20 lines omitted...
now showing anything in the REPL goes through termshow
If you're writing code just for yourself, go ahead and use install_term_repr
. Enjoy it. But, if the code you're writing is intended for others you should really avoid doing that. It will modify the behavior of the REPL for them too and that's confusing and possibly error prone.
@showme
One of Julia's most loved features is multiple dispatch. However, sometimes it can be hard to know which method gets called by your code and what that method is doing. There's lots of tools out there to help with this, including some built in in Julia's base code. Here we show a nifty little macro that builds upon CodeTracking
by Tim Holy to directly show you the method your code is calling:
import Term.Repr: @showme
@showme tprint(stdout, "this is TERM") # which method is being called?
────────────────────────────────────────────────────────────────────────────────
╭──── @showme ─────────────────────────────────────────────────────────╮
│ Showing definition for method called by: `tprint(stdout, "this is │
│ TERM")` │
╰──────────────────────────────────────────────────────────────────────╯
Arguments
⨀ stdout::Symbol
⨀ "this is TERM"::String
Method definition
┌────────────────────────────────────────────────────────────────────┐
│ function tprint(io::IO, x::AbstractString; highlight = true) │
│ x = (highlight ? apply_style ∘ highlighter : apply_style)( │
│ x) │
│ │
│ x = │
│ Measure(x).w <= console_width(io) ? x : │
│ string(RenderableText(string(x), width = console_width │
│ (io))) │
│ print(io, sprint_no_color(x)) │
│ end │
└────────────────────────────────────────────────────────────────────┘
/home/runner/work/Term.jl/Term.jl/src/tprint.jl:41
as you can see, it shows the source code of the particular tprint
method being called by the combination of arguments, for different arguments different methods will be invoked:
@showme tprint("this is also TERM") # different method
────────────────────────────────────────────────────────────────────────────────
╭──── @showme ─────────────────────────────────────────────────────────╮
│ Showing definition for method called by: `tprint("this is also │
│ TERM")` │
╰──────────────────────────────────────────────────────────────────────╯
Arguments
⨀ "this is also TERM"::String
Method definition
┌────────────────────────────────────────────────────────────────────┐
│ tprint(x; highlight = true) = tprint(stdout, x; highlight │
│ = highlight) │
└────────────────────────────────────────────────────────────────────┘
/home/runner/work/Term.jl/Term.jl/src/tprint.jl:31
You can also list all methods for the function you're calling, should you wish to do so
@showme tprint("still TERM") show_all_methods=true
────────────────────────────────────────────────────────────────────────────────
╭──── @showme ─────────────────────────────────────────────────────────╮
│ Showing definition for method called by: `tprint("still TERM")` │
╰──────────────────────────────────────────────────────────────────────╯
Arguments
⨀ "still TERM"::String
Method definition
┌────────────────────────────────────────────────────────────────────┐
│ tprint(x; highlight = true) = tprint(stdout, x; highlight │
│ = highlight) │
└────────────────────────────────────────────────────────────────────┘
/home/runner/work/Term.jl/Term.jl/src/tprint.jl:31
╭──── all methods ─────────────────────────────────────────────────────────╮
│ │
│ (1) tprint(io::IO, x::AbstractString; highlight) │
│ (2) │
│ (3) tprint(io::IO, x::Term.Renderables.AbstractRender │
│ able; highlight) │
│ (4) │
│ (5) tprint(io::IO, md::Markdown.MD; kwargs...) │
│ (6) │
│ (7) tprint(io::IO, x; highlight) │
│ (8) │
│ (9) tprint(io::IO, args...; highlight) │
│ (10) │
│ (11) tprint(md::Markdown.MD; kwargs...) │
│ (12) │
│ (13) tprint(x; highlight) │
│ (14) │
│ (15) tprint(args...; highlight) │
│ (16) │
│ │
╰──────────────────────────────────────────────────────────────────────────╯
Enjoy.