I think that both displayed methods are valid. Similar to tuples, there can be a trailing comma after a non-empty argument list:
julia> abs(-1,)
1
I think that both displayed methods are valid. Similar to tuples, there can be a trailing comma after a non-empty argument list:
julia> abs(-1,)
1
Thanks, I didnāt know this. Hmm, I wonder whether this is a feature or an anti-feature. I understand why we have it for tuples and arrays as you might have your elements in separate lines and just want to add another line without caring whether it is the last line.
However, for callables, this only seem to make sense for varargs, which are the exception and not the norm, as otherwise you hardly add or remove some arguments.
Does anyone use this syntax in the REPL and would expect help for the single-argument method after writing the comma?
No I think if youāve typed f('a', and then press TAB itās reasonable for help to assume you want at least 2 arguments.
Definitely a feature. You want to be able to add and remove lines from calls like this:
foo(
bar,
baz,
)
Lua has the rule that you canāt have a trailing comma in function calls and itās awful.
Besides, as the manual says
Tuples are an abstraction of the arguments of a function ā without the function itself.
so it would be weird if their syntax were incompatible.
Thatās not to say anything about what the REPL help mode should do, I donāt have a strong opinion on that.
The reason that the arguments are effectively a Tuple and if it is supported there, it should also be supported for callables, is a strong one.
Could you provide a real-life example for foo where you actually use it? As adding an element changes the method, I would really only expect it to be used for Varargs methods.
Most commonly when there are optional keyword args, which is perhaps less relevant for the help mode discussion (though keyword only-methods do exist). Also when iterating on my own code and signatures change (also less relevant for help mode).
This is implemented in the newly released version 0.6.7 of TerminalPager.jl. So you will always get the extended help with <F1> and <alt> + <h>.
Does this have to be enabled somehow, or have some known limitations? When I do using TerminalPager, then type IOContext (for example), and press Alt-h, it does nothing (this is on Windows, on both the Terminal app and on Wezterm). Pressing F1 for some reason types an A at that location.
I can open an issue if needed, just wanted to make sure Iām not misunderstanding something or running into known limitations.
It should be enabled after you loaded the package. We already had reports of working correctly on Windows, so it should work.
Is your text cursor above or at the very end of IOContext when you hit <Alt>+<h> (i.e. not after a trailing space)?
Which version of TerminalPager.jl do you currently use (TerminalPager |> pkgversion)?
Alt+h not working was indeed a vesion issue. I had an older locally checked out version of TerminalPager added, so it hadnāt been updated with the other packages. Now after adding the registry version, Alt+h works great.
F1 still produces an A at the location (whether at the end of the text or in the middle of it), both on Wezterm and Terminal.
The Alt-h is a great usability improvement btw, a major step forward for the Julia REPL and makes TerminalPager.jl an even more essential part of the REPL for me. Thank you for adding it.
Great that you have found and fixed the main issue. I am glad that you like the functionality.
Regarding <F1>: Could it be that your keyboard is sending the multimedia keycode instead of the <F1> keycode? Could you try using <Fn>+<F1> and report what this is doing?
I think for everyone with advanced typing skills, <alt>+<h> is the superior solution (at least on a Linux and Windows keyboard), but <F1> is the more common shortcut and therefore more discoverable. Therefore it would still nice to understand why that one is not working, although not strictly necessary.
Itās F1 on an external keyboard that does this (and Fn+F1 on the main laptop keyboard also leads to A). It seems to be a general Julia REPL thing btw, happens without TerminalPager loaded too. Searching it up, I found an old obscure issue Function keys i.e. F5 and F6 input random characters on windows console Ā· Issue #28799 Ā· JuliaLang/julia Ā· GitHub so it looks like this has been this way since Julia pre-1.0 days!
Thereās a lot going on in julia/stdlib/REPL/src/LineEdit.jl at master Ā· JuliaLang/julia Ā· GitHub and Iām guessing somewhere in there, some part of the input codes generated for F1-F5 keys on Windows is getting gobbled up, leaving only an A (or B C D or E) behind - probably something unintentionally written with Linux assumptions early on.
Iāve updated the issue #28799 with a bit more detail.
Meanwhile, Iāll see if F10 or something can be made to work on Windows as a temporary alternative until this is fixed - F6 and above donāt have this particular issue, but I donāt know if the REPL code is still processing them incorrectly in some other way, but Iāll give it a try sometime in the next week.
Thanks for nailing it down to a general Julia Windows problem.
So this is beyond what we can fix in TerminalPager.jl.
Letās see whether someone has fun (or is being payed for) fixing the problem for a proprietary system. I assume that escape_defaults and default_keymap might be good starting points.
I updated the issue thread on this, but basically it looks like this was fixed a few months ago (possibly inadvertently, while fixing pasting) and will work fine in the 1.13 Julia release.
Meanwhile, for 1.12, LTS, etc., I have this in my startup.jl to make F10 work like F1 was supposed to (since the original issue only affects F1-F5 keys, not the rest of them):
module Startup
# Configure F10 as pager-help key since F1 doesn't work on Windows on Julia 1.12 or lower
if isinteractive()
F10_MAPPED::Bool = false
# This section of the code is largely from BasicAutoloads.jl
is_repl_ready() = isdefined(Base, :active_repl_backend) && isdefined(Base.active_repl_backend, :ast_transforms)
function register_ast_transform_when_ready()
iter = 0
while !is_repl_ready() && iter < 120
iter += 1
sleep(0.02 * iter)
end
if is_repl_ready()
push!(Base.active_repl_backend.ast_transforms, map_f10_pager)
else
@warn "Timed out waiting for `Base.active_repl_backend.ast_transforms` to become available. F10 for paged help will not work."
end
end
function map_f10_pager(ast)
if !F10_MAPPED && isdefined(Main, :TerminalPager) && Main.TerminalPager isa Module &&
isdefined(Main.TerminalPager, :_show_pager_extended_help)
LE = Base.REPL_MODULE_REF[].LineEdit
main_modes = filter(Base.active_repl.interface.modes) do m
m isa LE.Prompt && LE.prompt_string(m) in ["julia> ", "pager> "]
end
for m in main_modes
escapes = m.keymap_dict['\e']
escapes['[']['2']['1'] = Dict{Char,Any}()
escapes['[']['2']['1']['~'] = Main.TerminalPager._show_pager_extended_help # <F10>
end
global F10_MAPPED = true
end
return ast
end
@async register_ast_transform_when_ready()
end
end
Kinda hacky to use ast_transforms for this (among other internals), but thatās the best way I could think of and it seems to work reliably.
Version 0.6.8 of TerminalPager.jl adds an inline about functionality close in spirit to the inline help of this Discourse topic.
After loading both About.jl and TerminalPager.jl (e.g. in your startup) and positioning your REPL text cursor on any identifier you cannot only get help with <alt>+<h>, but you get the output from about with <alt>+<a>. Itās both shown in a pager, so you get back to where you were after pressing <q>.
If, for example, you want to use a lazy iterator, you might be tempted to enter Iterators followed by <alt>+<h> just to be disappointed by this return
search: Iterators Base.IteratorSize numerator iterate Base.IteratorEltype Base.Generator
Methods for working with Iterators.
which creates appetite for more, but canāt satisfy it.
You could have entered Iterators. followed by <tab>, but then you get
julia> Iterators.
Accumulate Base Count Cycle
Drop DropWhile Enumerate Filter
Flatten IterableStatePairs IterationCutShort PartitionIterator
ProductIterator Repeated Rest Reverse
Stateful Take TakeWhile Zip
_approx_iter_type _diff_length _flatten_iteratorsize _flatteneltype
_min_length _only _pairs_elt _pisdone
_piterate _piterate1 _prod_axes1 _prod_eltype
_prod_indices _prod_size _prod_size1 _promote_tuple_shape
_zip_any_isdone _zip_isdone _zip_iterate_all _zip_iterate_interleave
_zip_iterate_some _zip_lengths_finite_equal _zip_min_length accumulate
and_iteratoreltype and_iteratorsize approx_iter_type convert
countfrom cycle doiterate drop
drop_iteratorsize dropwhile enumerate filter
flatmap flatten flatten_iteratorsize flatten_length
map only partition partition_iteratorsize
peel prod_iteratorsize product repeated
reset! rest rest_iteratorsize reverse
take take_iteratorsize takewhile zip
zip_iteratoreltype zip_iteratorsize
which
I think itās better to enter Iterators followed by <alt>+<a> to get this:
Module Base.Iterators
Re-exports 21 names (from Base):
⢠Iterators ⢠drop ⢠flatmap ⢠peel ⢠reverse ⢠Stateful
⢠accumulate ⢠dropwhile ⢠flatten ⢠product ⢠take
⢠countfrom ⢠enumerate ⢠map ⢠repeated ⢠takewhile
⢠cycle ⢠filter ⢠partition ⢠rest ⢠zip
This does not even do it justice, as in the REPL it will be nicely formatted and colored.
You can, of course, use it on all the other things About.jl supports, which is basically everything in Julia.
Technically, I implemented it as a package extension for About.jl inside of TerminalPager.jl using a bit of glue code to connect the functionality of both.
Thanks to @tecosaur and to @Ronis_BR for creating great packages with About.jl and TerminalPager.jl, respectively, doing the majority of the work!
Thank you for the amazing work @PatrickHaecker ! TerminalPager.jl is way more useful now after your contributions!