Skip to content

Commit

Permalink
Merge #1018
Browse files Browse the repository at this point in the history
1018: Provide more intuitive help interface r=00vareladavid a=00vareladavid

This makes help syntax consistent with the command syntax for compound commands e.g. `pkg> registry add` and `pkg> help registry add`.

Also provides filtered and sorted help for "super" commands e.g. `pkg> help registry`

Resolves #988 



Co-authored-by: David Varela <00.varela.david@gmail.com>
  • Loading branch information
bors[bot] and 00vareladavid committed Feb 1, 2019
2 parents a44137c + 7ea26df commit 379ff32
Showing 1 changed file with 36 additions and 16 deletions.
52 changes: 36 additions & 16 deletions src/REPLMode.jl
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,7 @@ end

is_opt(word::AbstractString) = first(word) == '-'

function core_parse(words)
function core_parse(words; only_cmd=false)
# prelude
statement = Statement()
word = nothing
Expand Down Expand Up @@ -280,6 +280,8 @@ function core_parse(words)
end
statement.spec = command

only_cmd && return statement, word # hack to hook in `help` command

next_word!() || return statement, word

while is_opt(word)
Expand Down Expand Up @@ -578,24 +580,35 @@ function CommandSpec(command_name::String)::Union{Nothing,CommandSpec}
return get(super, m.captures[2], nothing)
end

function parse_command(words::Vector{String})
statement, word = core_parse(words; only_cmd=true)
if statement.super === nothing && statement.spec === nothing
pkgerror("invalid input: `$word` is not a command")
end
return statement.spec === nothing ? statement.super : statement.spec
end

function do_help!(command::PkgCommand, repl::REPL.AbstractREPL)
disp = REPL.REPLDisplay(repl)
if isempty(command.arguments)
Base.display(disp, help)
return
end
help_md = md""
for arg in command.arguments
spec = CommandSpec(arg)
if spec === nothing
pkgerror("'$arg' does not name a command")

cmd = parse_command(command.arguments)
if cmd isa String
# gather all helps for super spec `cmd`
all_specs = sort!(unique(values(super_specs[cmd]));
by=(spec->spec.canonical_name))
for spec in all_specs
isempty(help_md.content) || push!(help_md.content, md"---")
push!(help_md.content, spec.help)
end
spec.help === nothing &&
pkgerror("Sorry, I don't have any help for the `$arg` command.")
isempty(help_md.content) ||
push!(help_md.content, md"---")
push!(help_md.content, spec.help)
elseif cmd isa CommandSpec
push!(help_md.content, cmd.help)
end
!isempty(command.arguments) && @warn "More than one command specified, only rendering help for first"
Base.display(disp, help_md)
end

Expand Down Expand Up @@ -787,6 +800,14 @@ function canonical_names()
return names
end

function complete_help(options, partial)
names = String[]
for cmds in values(super_specs)
append!(names, [spec.canonical_name for spec in values(cmds)])
end
return sort!(unique!(append!(names, collect(keys(super_specs)))))
end

function complete_installed_packages(options, partial)
env = try EnvCache()
catch err
Expand Down Expand Up @@ -1047,19 +1068,18 @@ julia is started with `--startup-file=yes`.
:name => "help",
:short_name => "?",
:arg_count => 0 => Inf,
:completions => ((opt, partial) -> canonical_names()),
:completions => complete_help,
:description => "show this message",
:help => md"""
help
Display this message.
help cmd ...
List available commands along with short descriptions.
Display usage information for commands listed.
help cmd
Available commands: `help`, `status`, `add`, `rm`, `up`, `preview`, `gc`, `test`, `build`, `free`, `pin`, `develop`.
If `cmd` is a partial command, display help for all subcommands.
If `cmd` is a full command, display help for `cmd`.
""",
],[ :kind => CMD_INSTANTIATE,
:name => "instantiate",
Expand Down

0 comments on commit 379ff32

Please sign in to comment.