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

REPL mode #88

Merged
merged 4 commits into from
Jan 21, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ See also the examples in the [examples directory](examples).
## Changes in release 1.0.0

* Drop support for Julia versions v0.6/v0.7
* Parsing does not exit julia by default when in interactive mode now
* Renamed function `import_settings` → `import_settings!`

## Changes in release 0.6.2

Expand Down
2 changes: 1 addition & 1 deletion src/ArgParse.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export
@add_arg_table,
add_arg_group,
set_default_arg_group,
import_settings,
import_settings!,
usage_string,
parse_args

Expand Down
14 changes: 9 additions & 5 deletions src/parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,9 @@ function usage_string(settings::ArgParseSettings)

lc_len_limit = 24

cmd_lst = Any[]
pos_lst = Any[]
opt_lst = Any[]
cmd_lst = String[]
pos_lst = String[]
opt_lst = String[]
for f in settings.args_table.fields
if is_cmd(f)
if !isempty(f.short_opt_name)
Expand Down Expand Up @@ -280,7 +280,7 @@ end

show_help(settings::ArgParseSettings; kw...) = show_help(stdout, settings; kw...)

function show_help(io::IO, settings::ArgParseSettings; exit_when_done = true)
function show_help(io::IO, settings::ArgParseSettings; exit_when_done = !isinteractive())

lc_len_limit = 24
lc_left_indent = 2
Expand Down Expand Up @@ -369,7 +369,7 @@ end

show_version(settings::ArgParseSettings; kw...) = show_version(stdout, settings; kw...)

function show_version(io::IO, settings::ArgParseSettings; exit_when_done = true)
function show_version(io::IO, settings::ArgParseSettings; exit_when_done = !isinteractive())
println(io, settings.version)
exit_when_done && exit(0)
return
Expand All @@ -379,6 +379,10 @@ has_cmd(settings::ArgParseSettings) = any(is_cmd, settings.args_table.fields)

# parse_args & friends
function default_handler(settings::ArgParseSettings, err, err_code::Int = 1)
isinteractive() ? debug_handler(settings, err) : cmdline_handler(settings, err, err_code)
end

function cmdline_handler(settings::ArgParseSettings, err, err_code::Int = 1)
println(stderr, err.text)
println(stderr, usage_string(settings))
exit(err_code)
Expand Down
44 changes: 27 additions & 17 deletions src/settings.jl
Original file line number Diff line number Diff line change
Expand Up @@ -171,21 +171,24 @@ This is the list of general settings currently available:
* `exc_handler` (default = `ArgParse.default_handler`): this is a function which is invoked when an
error is detected during parsing (e.g. an option is not recognized, a required argument is not
passed etc.). It takes two arguments: the `settings::ArgParseSettings` object and the
`err::ArgParseError` exception. The default handler prints the error text and the usage screen on
standard error and exits with error code 1:
`err::ArgParseError` exception. The default handler behaves differently depending on whether it's
invoked from a script or in an interactive environment (e.g. REPL/IJulia). In non-interactive
(script) mode, it calls `ArgParse.cmdline_handler`, which prints the error text and the usage
screen on standard error and exits Julia with error code 1:

```julia
function default_handler(settings::ArgParseSettings, err, err_code::Int = 1)
function cmdline_handler(settings::ArgParseSettings, err, err_code::Int = 1)
println(stderr, err.text)
println(stderr, usage_string(settings))
exit(err_code)
end
```
The module also provides a function `ArgParse.debug_handler` (not exported) which will just
rethrow the error.
* `exit_after_help` (default = `true`): exits Julia (with error code `0`) when the `:show_help` or
`:show_version` actions are triggered. If `false`, those actions will just stop the parsing and
make `parse_args` return `nothing`.

In interactive mode instead it calls the function `ArgParse.debug_handler`, which just rethrows
the error.
* `exit_after_help` (default = `!isinteractive()`): exit Julia (with error code `0`) when the
`:show_help` or `:show_version` actions are triggered. If `false`, those actions will just stop
the parsing and make `parse_args` return `nothing`.

Here is a usage example:

Expand Down Expand Up @@ -259,7 +262,7 @@ mutable struct ArgParseSettings
exc_handler::Function = default_handler,
preformatted_description::Bool = false,
preformatted_epilog::Bool = false,
exit_after_help::Bool = true
exit_after_help::Bool = !isinteractive()
)
fromfile_prefix_chars = check_prefix_chars(fromfile_prefix_chars)
return new(
Expand All @@ -277,8 +280,8 @@ ArgParseSettings(desc::AbstractString; kw...) = ArgParseSettings(; description =

function show(io::IO, s::ArgParseSettings)
println(io, "ArgParseSettings(")
for f in setdiff(fieldnames(ArgParseSettings), )
f ∈ [:args_groups, :args_table] && continue
for f in fieldnames(ArgParseSettings)
f ∈ (:args_groups, :args_table) && continue
println(io, " ", f, "=", getfield(s, f))
end
println(io, " >> ", usage_string(s))
Expand Down Expand Up @@ -1150,7 +1153,7 @@ function set_default_arg_group(settings::ArgParseSettings, name::Union{AbstractS
return
end

# import_settings & friends
# import_settings! & friends
function override_conflicts_with_commands(settings::ArgParseSettings, new_cmd::AbstractString)
ids0 = Int[]
for ia in 1:length(settings.args_table.fields)
Expand Down Expand Up @@ -1270,8 +1273,15 @@ function fix_commands_fields(fields::Vector{ArgParseField})
end
end

# TODO: remove after minor version bump
export import_settings
function import_settings(args...; kw...)
@warn "`import_settings` is depreacted, use `import_settings!`"
import_settings!(args...; kw...)
end

"""
import_settings(settings, other_settings [,args_only])
import_settings!(settings, other_settings [,args_only])

Imports `other_settings` into `settings`, where both are [`ArgParseSettings`](@ref) objects. If
`args_only` is `true` (this is the default), only the argument table will be imported; otherwise,
Expand All @@ -1293,9 +1303,9 @@ will not have any effect on `settings`.

This function can be used at any time.
"""
function import_settings(settings::ArgParseSettings,
other::ArgParseSettings,
args_only::Bool = true)
function import_settings!(settings::ArgParseSettings,
other::ArgParseSettings,
args_only::Bool = true)
check_settings_are_compatible(settings, other)

fields = settings.args_table.fields
Expand Down Expand Up @@ -1356,7 +1366,7 @@ function import_settings(settings::ArgParseSettings,
elseif !isempty(cmd_prog_hint)
settings[subk].prog = "$(settings.prog) $cmd_prog_hint"
end
import_settings(settings[subk], subs, args_only)
import_settings!(settings[subk], subs, args_only)
end
return settings
end
6 changes: 3 additions & 3 deletions test/argparse_test04.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ function ap_settings4()
error_on_conflict = false, # do not error-out when trying to override an option
exc_handler = ArgParse.debug_handler)

import_settings(s, s0) # now s has all of s0 arguments (except help/version)
import_settings!(s, s0) # now s has all of s0 arguments (except help/version)

@add_arg_table s begin
"-o" # this will partially override s0's --parent-flag
Expand Down Expand Up @@ -69,7 +69,7 @@ function ap_settings4b()
s = ArgParseSettings("Test 4 for ArgParse.jl",
version = "Version 1.0")

import_settings(s, s0, false) # args_only set to false
import_settings!(s, s0, false) # args_only set to false

@add_arg_table s begin
"-o"
Expand Down Expand Up @@ -172,7 +172,7 @@ end
let s = ap_settings4_base()

for s0 = [ap_settings4_conflict1(), ap_settings4_conflict2()]
@ee_test_throws import_settings(s, s0)
@ee_test_throws import_settings!(s, s0)
end
end

Expand Down
2 changes: 1 addition & 1 deletion test/argparse_test05.jl
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ function ap_settings5b()
action = :store_true
end

import_settings(s, s0)
import_settings!(s, s0)

return s
end
Expand Down