JuliaFormatter.jl icon indicating copy to clipboard operation
JuliaFormatter.jl copied to clipboard

Interacts poorly with ArgParse.jl

Open maxkapur opened this issue 1 year ago • 0 comments

Let me start by conceding that this is a pretty low-priority issue, and it's probably out of scope for any formatter to address the wide variety of table formats^1 that the ArgParse @add_arg_table! macro accepts.

... but, the following example from the first page of the ArgParse documentation^2 is formatted (IMO) poorly by JuliaFormatter on the default settings:

using ArgParse

function parse_commandline()
    s = ArgParseSettings()

    @add_arg_table! s begin
        "--opt1"
            help = "an option with an argument"
        "--opt2", "-o"
            help = "another option with an argument"
            arg_type = Int
            default = 0
        "--flag1"
            help = "an option without argument, i.e. a flag"
            action = :store_true
        "arg1"
            help = "a positional argument"
            required = true
    end

    return parse_args(s)
end

function main()
    parsed_args = parse_commandline()
    println("Parsed args:")
    for (arg,val) in parsed_args
        println("  $arg  =>  $val")
    end
end

main()

Formatting this flattens out all the arguments to the macro:

using ArgParse

function parse_commandline()
    s = ArgParseSettings()

    @add_arg_table! s begin
        "--opt1"
        help = "an option with an argument"
        "--opt2", "-o"
        help = "another option with an argument"
        arg_type = Int
        default = 0
        "--flag1"
        help = "an option without argument, i.e. a flag"
        action = :store_true
        "arg1"
        help = "a positional argument"
        required = true
    end

    return parse_args(s)
end

function main()
    parsed_args = parse_commandline()
    println("Parsed args:")
    for (arg, val) in parsed_args
        println("  $arg  =>  $val")
    end
end

main()

One way to get things working properly is to surround each of the argument arguments with begin ... end as follows:

using ArgParse

function parse_commandline()
    s = ArgParseSettings()

    @add_arg_table! s begin
        "--opt1"
        begin
            help = "an option with an argument"
        end
        "--opt2", "-o"
        begin
            help = "another option with an argument"
            arg_type = Int
            default = 0
        end
        "--flag1"
        begin
            help = "an option without argument, i.e. a flag"
            action = :store_true
        end
        "arg1"
        begin
            help = "a positional argument"
            required = true
        end
    end

    return parse_args(s)
end

function main()
    parsed_args = parse_commandline()
    println("Parsed args:")
    for (arg, val) in parsed_args
        println("  $arg  =>  $val")
    end
end

main()

JuliaFormatter leaves this one alone. But things get weird again if you put format_docstrings = true in the config:

using ArgParse

function parse_commandline()
    s = ArgParseSettings()

    @add_arg_table! s begin
        """
        --opt1
        """
        begin
            help = "an option with an argument"
        end
        "--opt2", "-o"
        begin
            help = "another option with an argument"
            arg_type = Int
            default = 0
        end
        """
        --flag1
        """
        begin
            help = "an option without argument, i.e. a flag"
            action = :store_true
        end
        """
        arg1
        """
        begin
            help = "a positional argument"
            required = true
        end
    end

    return parse_args(s)
end

function main()
    parsed_args = parse_commandline()
    println("Parsed args:")
    for (arg, val) in parsed_args
        println("  $arg  =>  $val")
    end
end

main()

Each of the argument names is parsed as a docstring and put between triple quotes. In this case, the formatting actually changes how ArgParse parses the macro arguments, and causes it to complain that command-line argument names can't contain whitespace:

ERROR: LoadError: illegal option name: opt1
 (contains whitespace)

I see a similar issue from 2019 (https://github.com/domluna/JuliaFormatter.jl/issues/37), which I see was closed by https://github.com/domluna/JuliaFormatter.jl/pull/41. But it seems that the ArgParse syntax and/or JuliaFormatter rules have drifted and this issue has surfaced again.

maxkapur avatar Dec 27 '23 00:12 maxkapur