# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#
# Description
# ==============================================================================
#
#   Helpers.
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

export @help, @stdout_to_pager, @out2pr

"""
    @help(f)

Open the documentation of the function `f` in pager.

# Examples

```julia-repl
julia> @help write
```
"""
macro help(f)
    ex_out = quote
        @doc($(esc(f))) |> pager
    end

    return ex_out
end

"""
    @stdout_to_pager(ex_in)

Capture the `stdout` generated by `ex_in` and show inside a pager.

!!! note
    The command **must** write to `stdout` explicitly. For example,
    `@stdout_to_pager 1` shows a blank screen since `1` does not write to
    `stdout`, but returns `1`. `@stdout_to_pager show(1)`, on the other hand,
    shows the number `1` inside the pager.

!!! note
    This macro can also be called using the shorter name `@out2pr`.
"""
macro stdout_to_pager(ex_in)
    ex_out = quote
        hascolor = get(stdout, :color, true)
        old_stdout = stdout
        buf = IOBuffer()
        io = IOContext(buf, :color => hascolor, :limit => false)
        try
            Base.eval(:(stdout = $io))
            $(esc(ex_in))
            Base.eval(:(stdout = $old_stdout))
            String(take!(buf)) |> pager
            close(io)
        finally
            Base.eval(:(stdout = $old_stdout))
        end
    end

    return ex_out
end

macro out2pr(ex)
    return :(@stdout_to_pager $(esc(ex)))
end
