Can we change the Julia help from bottom-up to top-down?

When you type ? in Julia and then type <something>, you get all the help information about <something> but if this information does not fit in the screen, you will get the tail of the information (like in a bottom-up view). So, you should scroll up to the top to read the information. In linux, for example, if you type man <something> you will get the help information about <something> in a top-down view and you use space to move down as you read.

I do not how to better formulate my question but in my opinion the top-down view should be the default behaviour, if possible.

1 Like

I think it would be better to pipe the help output into a pager. IIRC, there was a recent PR to do this that was approved at triage, but it requires a few bugs in the pager to be fixed first.

It’s one of those things where the core devs are absolutely on board, but someone just needs to put in the work and write the code (it could be you! :slight_smile: )

Edit: It’s these:

1 Like

I honestly don’t think the problem is the direction of the help scrolling or the lack of paging. For me at least is primary issue is what I call β€œdoc pollution”. In complex packages with a lot of dependencies, a common function gets concatenated docs for all sorts of obscure methods that most users are not interested in. This is the cruft you have to scroll past to get to the basic usage at the very top. For example:

help?> first    # no loaded packages, so relatively brief
search: first firstindex popfirst! pushfirst! uppercasefirst lowercasefirst findfirst searchsortedfirst

  first(coll)

  Get the first element of an iterable collection. Return the start point of an AbstractRange even if it is empty.

  See also: only, firstindex, last.

  Examples
  ≑≑≑≑≑≑≑≑≑≑

  julia> first(2:2:10)
  2

  julia> first([1; 2; 3; 4])
  1

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(itr, n::Integer)

  Get the first n elements of the iterable collection itr, or fewer elements if itr is not long enough.

  See also: startswith, Iterators.take.

  β”‚ Julia 1.6
  β”‚
  β”‚  This method requires at least Julia 1.6.

  Examples
  ≑≑≑≑≑≑≑≑≑≑

  julia> first(["foo", "bar", "qux"], 2)
  2-element Vector{String}:
   "foo"
   "bar"

  julia> first(1:6, 10)
  1:6

  julia> first(Bool[], 1)
  Bool[]

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(s::AbstractString, n::Integer)

  Get a string consisting of the first n characters of s.

  Examples
  ≑≑≑≑≑≑≑≑≑≑

  julia> first("βˆ€Ο΅β‰ 0: ϡ²>0", 0)
  ""

  julia> first("βˆ€Ο΅β‰ 0: ϡ²>0", 1)
  "βˆ€"

  julia> first("βˆ€Ο΅β‰ 0: ϡ²>0", 3)
  "βˆ€Ο΅β‰ "

julia>

Compare with:

julia> using DataFrames

help?> first
search: first firstindex popfirst! pushfirst! uppercasefirst lowercasefirst findfirst searchsortedfirst

  first(coll)

  Get the first element of an iterable collection. Return the start point of an AbstractRange even if it is empty.

  See also: only, firstindex, last.

  Examples
  ≑≑≑≑≑≑≑≑≑≑

  julia> first(2:2:10)
  2

  julia> first([1; 2; 3; 4])
  1

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(itr, n::Integer)

  Get the first n elements of the iterable collection itr, or fewer elements if itr is not long enough.

  See also: startswith, Iterators.take.

  β”‚ Julia 1.6
  β”‚
  β”‚  This method requires at least Julia 1.6.

  Examples
  ≑≑≑≑≑≑≑≑≑≑

  julia> first(["foo", "bar", "qux"], 2)
  2-element Vector{String}:
   "foo"
   "bar"

  julia> first(1:6, 10)
  1:6

  julia> first(Bool[], 1)
  Bool[]

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(s::AbstractString, n::Integer)

  Get a string consisting of the first n characters of s.

  Examples
  ≑≑≑≑≑≑≑≑≑≑

  julia> first("βˆ€Ο΅β‰ 0: ϡ²>0", 0)
  ""

  julia> first("βˆ€Ο΅β‰ 0: ϡ²>0", 1)
  "βˆ€"

  julia> first("βˆ€Ο΅β‰ 0: ϡ²>0", 3)
  "βˆ€Ο΅β‰ "

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(q::Deque)

  Returns the first element of the deque q.

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(D::CircularDeque)

  Get the item at the front of the queue.

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(s::Stack)

  Get the top item from the stack. Sometimes called peek.

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(h::BinaryHeap)

  Returns the element at the top of the heap h.

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(h::BinaryMinMaxHeap)

  Get the first (minimum) of the heap.

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(sc)

  Argument sc is a SortedDict, SortedMultiDict or SortedSet. This function returns the first item (a k=>v pair for
  SortedDict and SortedMultiDict or a key for SortedSet) according to the sorted order in the container. Thus,
  first(sc) is equivalent to deref((sc,startof(sc))). It is an error to call this function on an empty container.
  Time: O(log n)

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(sc)

  Argument sc is a SortedDict, SortedMultiDict or SortedSet. This function returns the first item (a k=>v pair for
  SortedDict and SortedMultiDict or a key for SortedSet) according to the sorted order in the container. Thus,
  first(sc) is equivalent to deref((sc,startof(sc))). It is an error to call this function on an empty container.
  Time: O(log n)

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(sc)

  Argument sc is a SortedDict, SortedMultiDict or SortedSet. This function returns the first item (a k=>v pair for
  SortedDict and SortedMultiDict or a key for SortedSet) according to the sorted order in the container. Thus,
  first(sc) is equivalent to deref((sc,startof(sc))). It is an error to call this function on an empty container.
  Time: O(log n)

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(cb::CircularBuffer)

  Get the first element of CircularBuffer.

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(df::AbstractDataFrame)

  Get the first row of df as a DataFrameRow.

  ────────────────────────────────────────────────────────────────────────────────────────────────────────────────────

  first(df::AbstractDataFrame, n::Integer; view::Bool=false)

  Get a data frame with the n first rows of df.

  If view=false a freshly allocated DataFrame is returned. If view=true then a SubDataFrame view into df is returned.

julia>

There are much worse examples, this was literally the first (haha) function I tried.

1 Like

How would one decide if a method is a method that users are interested in? Presumably, if it’s documented and loaded, then it’s of interest to the user?

You can filter the help docs by typing e.g. help?> first(::Any), or similar for other signatures.

2 Likes

TerminalPager is your friend:

julia> using TerminalPager

#enter |? and you get a help prompt with pager:

pager?> 
5 Likes

In my example, getting help for first(df::AbstractDataFrame) and first(df::AbstractDataFrame, n::Integer; view::Bool=false) is certainly relevant if you’ve loaded DataFrames. But maybe not so much all the incidental stuff DataFrames needs to work, e.g. CircularBuffer, SortedMultiDict, BinaryMinMaxHeap, CircularDeque.

Maybe the help viewer could have basic and extended help, the latter accessed using a shortcut something like the [number]Ctrl-Q shortcut to jump to errors in stack traces?

2 Likes

Maybe that could be a good idea… although I can foresee a lot of issues where people ask why, when they type foo in the help, the method they are looking for does not show up when others does. In order words, I feel like that would be just replacing one inconveniency with another.

Extended Help is already possible.

https://github.com/JuliaData/DataFrames.jl/issues/2248

1 Like