Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pager support in the repl #6921

Open
BobPortmann opened this issue May 22, 2014 · 7 comments
Open

Pager support in the repl #6921

BobPortmann opened this issue May 22, 2014 · 7 comments
Labels
help wanted Indicates that a maintainer wants help on an issue or pull request REPL Julia's REPL (Read Eval Print Loop)

Comments

@BobPortmann
Copy link
Contributor

I often find myself wishing for a pager in the repl when outputting large amount of output. I see that there is a Base.less but it is only used on files and not for outputting other stuff in the repl. In fact, it would be great to have support for less, head, and tail like functionality for looking at arrays, hashes, etc. Thus to be able to do, e.g., arr |> less or less(arr) or arr |> tail.

In addition, I think having the output of show() automatically go through less if it is longer that one page would be great. I hate seeing 100's of pages of output fly by when, e.g., a huge hash gets "shown" at the prompt (I just cannot seem to get in the habit of typing the ; at the right time). This behavior could be configurable of course.

NOTE: see also https://groups.google.com/forum/#!topic/julia-users/2SbdNdW_EEM

@jacobcvt12
Copy link

Hello all. A pager would be useful, especially for viewing lengthy documentation. I'd like to work on this issue if no one else is. Any tips on where to start?

@quipa
Copy link

quipa commented Apr 12, 2018

This is probably a bit naive (still learning Julia), but I had a similar need and asking around in Slack and wrapped up the advice I got into a function like this

function pager(text)
    run(pipeline(`echo $text`,`less`))
end

Try this example (notice that markdown doesn't get parsed though). Seems to work ok, although I am sure it can be improved.

julia> pager(@doc print)

@digital-carver
Copy link
Contributor

Thanks @quipa, that's quite useful. I modified it to:

more(content) = more(reprmime("text/plain", content))
more(content::Markdown.MD) = more(Markdown.term(Core.CoreSTDOUT(), content))
function more(content::AbstractString)
    run(pipeline(`echo $(content)`, `less`))
end

which gives better output of data - Arrays, Dicts, etc. are displayed as usually done in the REPL, instead of a single-line long chain of values, and markdown output works too. (The markdown output includes an extra line at the end like (2, 52) though, which seems to be the return value of the Markdown.term function. I left it in since it's probably more work than worth it to remove that single line.)

julia> @doc(less) |> more
  less(file::AbstractString, [line::Integer])

  Show a file using the default pager, optionally providing a starting line
  number. Returns to the julia prompt when you quit the pager.

  less(function, [types])

  Show the definition of a function using the default pager, optionally
  specifying a tuple of types to indicate which method to see.
(2, 62)

julia> rand(1:99, 4, 5) |> more
4×5 Array{Int64,2}:
 41  68  55  66  77
 61  92  27  44  17
 82  40  71  80  47
 73  94  37  33   5

(PS: my actual run(pipeline( line goes like this: inJupyter ? content : run(pipeline(`echo $(content)`, `less`)), where inJupyter is a variable I've previously defined in my startup.jl file as inJupyter = isdefined(Main, :IJulia) && Main.IJulia.inited.)

@NightMachinery
Copy link

NightMachinery commented Apr 18, 2020

My version:

more(content) = more(repr("text/plain", content))
# using Markdown
# more(content::Markdown.MD) = more(Markdown.term(Core.CoreSTDOUT(), content))
function more(content::AbstractString)
    run(pipeline(`echo $(content)`, `less`))
    return nothing
end
macro d(body)
    :(more(Core.@doc($(esc(body)))))
end
@d rand

@kyllingstad
Copy link

Interpolating a string as the argument(s) to echo seems brittle. Here is yet another version of the workaround based on an example in the Julia manual:

more(content) = more(repr("text/plain", content))
function more(text::AbstractString)
    open(`less`, "w", stdout) do io
        print(io, text)
    end
end

@digital-carver
Copy link
Contributor

The best way to get this feature today is to use the TerminalPager package.

Once loaded in your startup.jl (or in a Startup package loaded from there), it provides a pager function that works reliably and preserves the colors, formatting, etc. It also adds a neat pager-mode to the REPL - you can press | to go into pager mode, after which any long output is automatically paged, without having to explicitly call the pager function.

(So perhaps this issue changes to the question of whether that package should be integrated into the REPL stdlib - it would be a nice usability improvement for a new user, and though the trend is to move things away from the stdlib, there are so many long docstrings in the Julia ecosystem that it seems justified in this case to make an exception to add this in.)

@mahiki
Copy link
Contributor

mahiki commented Feb 8, 2024

Today I learned about pager mode in TerminalPager. Great!

pager>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
help wanted Indicates that a maintainer wants help on an issue or pull request REPL Julia's REPL (Read Eval Print Loop)
Projects
None yet
Development

No branches or pull requests

10 participants