Browse Source

Rework command line argument parsing, closes #36.

pull/44/head
Fredrik Ekre 1 year ago
parent
commit
4a13a3fc4a
No known key found for this signature in database
GPG Key ID: DE82E6D5E364C0A2
  1. 110
      src/main.jl

110
src/main.jl

@ -47,7 +47,7 @@ function print_help()
<path>... <path>...
Input path(s) (files and/or directories) to process. For directories, Input path(s) (files and/or directories) to process. For directories,
all files (recursively) with the '*.jl' suffix are used as input files. all files (recursively) with the '*.jl' suffix are used as input files.
If path is `-` input is read from stdin and output written to stdout. If no path is given, or if path is `-`, input is read from stdin.
-c, --check -c, --check
Do not write output and exit with a non-zero code if the input is not Do not write output and exit with a non-zero code if the input is not
@ -55,23 +55,17 @@ function print_help()
-d, --diff -d, --diff
Print the diff between the input and formatted output to stderr. Print the diff between the input and formatted output to stderr.
Requires `git` or `diff` to be installed. Requires `git` to be installed.
--fail-fast
Exit immediately after the first error. Only applicable when formatting
multiple files in the same invocation.
--help --help
Print this message. Print this message.
-i, --inplace -i, --inplace
Edit files in place. This option is required when passing multiple input Format files in place.
paths.
-o, --output <file> -o <file>, --output=<file>
Output file to write formatted code to. If the specified file is `-` File to write formatted output to. If no output is given, or if the file
output is written to stdout. This option can not be used together with is `-`, output is written to stdout.
multiple input paths.
""", """,
) )
return return
@ -96,9 +90,6 @@ function main(argv)
# Reset errno # Reset errno
global errno = 0 global errno = 0
# Split argv entries with `=`
argv = mapreduce(x -> split(x, "="; limit = 2), append!, argv; init = String[])
# Default values # Default values
inputfiles = String[] inputfiles = String[]
outputfile = nothing outputfile = nothing
@ -130,86 +121,72 @@ function main(argv)
check = true check = true
elseif x == "-vv" || x == "--debug" elseif x == "-vv" || x == "--debug"
debug = verbose = true debug = verbose = true
elseif x == "-o" || x == "--output" elseif x == "-o"
if length(argv) < 1 if length(argv) < 1
return panic("expected output file as argument after `-o, --output`") return panic("expected output file argument after `-o`")
end end
outputfile = popfirst!(argv) outputfile = popfirst!(argv)
elseif (m = match(r"^--output=(.+)$", x); m !== nothing)
outputfile = String(m.captures[1]::SubString)
else else
# Remaining arguments must be inputfile(s) # Remaining arguments must be inputfile(s)
maybe_expand_directory!(inputfiles, x) maybe_expand_directory!(inputfiles, x)
for x in argv for x in argv
if x == "-" if x == "-"
return panic("input `-` can not be used with multiple files") return panic("input `-` can not be used with multiple files")
else
maybe_expand_directory!(inputfiles, x)
end end
maybe_expand_directory!(inputfiles, x)
end end
break break
end end
end end
# one of --check, --diff, --inplace, or --output must be specified input_is_stdin = length(inputfiles) == 0 || inputfiles[1] == "-"
stdio_mode = length(inputfiles) == 1 && inputfiles[1] == "-" &&
(outputfile === nothing || outputfile == "-")
if !(inplace || check || diff || stdio_mode)
return panic(
"at least one of options `-c, --check`, `-d, --diff`, `-i, --inplace`, " *
"or `-o, --output` must be specified",
)
end
# --check can not be used with --inplace # Check the arguments
if inplace && check if inplace && check
return panic("options `-c, --check` and `-i, --inplace` are mutually exclusive") return panic("options `--inplace` and `--check` are mutually exclusive")
end end
if inplace && outputfile !== nothing
# stdin is the default input return panic("options `--inplace` and `--output` are mutually exclusive")
if isempty(inputfiles)
return panic("no input files or directories specified")
end end
if check && outputfile !== nothing
# multiple files require --inplace or --check and no --output return panic("options `--check` and `--output` are mutually exclusive")
if length(inputfiles) > 1
if !(inplace || check)
return panic("option `-i, --inplace` or `-c, --check` is required for multiple input files")
elseif outputfile !== nothing
return panic("option `-o, --output` can not be used together with multiple input files")
end end
if inplace && input_is_stdin
return panic("option `--inplace` can not be used together with stdin input")
end end
if outputfile !== nothing && length(inputfiles) > 1
# --inplace can not be used when specifying output return panic("option `--output` can not be used together with multiple input files")
if inplace && outputfile !== nothing end
@assert length(inputfiles) == 1 if length(inputfiles) > 1 && !(inplace || check)
return panic("options `-i, --inplace` and `-o, --output` are mutually exclusive") return panic("option `--inplace` or `--check` required with multiple input files")
end end
# --inplace is incompatible with stdin as input if length(inputfiles) == 0
if inplace && first(inputfiles) == "-" push!(inputfiles, "-")
return panic("option `-i` is incompatible with stdin as input")
end end
# --diff currently requires git git = ""
git = nothing
if diff if diff
git = Sys.which("git") git = something(Sys.which("git"), git)
if git === nothing if isempty(git)
return panic("option `-d, --diff` requires `git` to be installed") return panic("option `--diff` requires `git` to be installed")
end end
end end
# Loop over the input files # Loop over the input files
for inputfile in inputfiles for inputfile in inputfiles
# Read the input # Read the input
input_is_file = true if input_is_stdin
if inputfile == "-" @assert length(inputfiles) == 1
input_is_file = false
sourcetext = try sourcetext = try
read(stdin, String) read(stdin, String)
catch err catch err
return panic("could not read input from stdin: ", err) return panic("could not read input from stdin: ", err)
end end
elseif isfile(inputfile) elseif isfile(inputfile)
@assert !input_is_stdin
sourcetext = try sourcetext = try
read(inputfile, String) read(inputfile, String)
catch err catch err
@ -221,14 +198,13 @@ function main(argv)
continue continue
end end
# Check output # Figure out output
output_is_file = false output_is_file = false
output_is_samefile = false output_is_samefile = false
if inplace if inplace
@assert outputfile === nothing @assert outputfile === nothing
@assert isfile(inputfile) @assert isfile(inputfile)
@assert input_is_file @assert !input_is_stdin
# @assert length(inputfiles) == 1 # checked above
output = inputfile output = inputfile
output_is_samefile = output_is_file = true output_is_samefile = output_is_file = true
elseif check elseif check
@ -236,11 +212,9 @@ function main(argv)
output = devnull output = devnull
else else
@assert length(inputfiles) == 1 @assert length(inputfiles) == 1
if stdio_mode if outputfile === nothing || outputfile == "-"
output = stdout output = stdout
elseif outputfile === nothing elseif isfile(outputfile) && !input_is_stdin && samefile(outputfile, inputfile)
return panic("no output file specified")
elseif isfile(outputfile) && input_is_file && samefile(outputfile, inputfile)
return panic("can not use same file for input and output, use `-i` to modify a file in place") return panic("can not use same file for input and output, use `-i` to modify a file in place")
else else
output = outputfile output = outputfile
@ -249,9 +223,9 @@ function main(argv)
end end
# Print file info unless quiet and unless stdin and/or stdout is involved # Print file info unless quiet and unless stdin and/or stdout is involved
print_progress = !(quiet || !input_is_file || !(output_is_file || check)) print_progress = !(quiet || input_is_stdin || !output_is_file)
# Print file info unless quiet and unless formatting stdin -> stdout # Print file info unless quiet and unless input/output is stdin/stdout
if print_progress if print_progress
input_pretty = relpath(inputfile) input_pretty = relpath(inputfile)
if check if check
@ -295,17 +269,19 @@ function main(argv)
print_progress && okln() print_progress && okln()
end end
elseif changed || !inplace elseif changed || !inplace
@assert output !== devnull
try try
write(output, seekstart(ctx.fmt_io)) write(output, seekstart(ctx.fmt_io))
catch err catch err
print_progress && errln() print_progress && errln()
panic("could not write to output: ", err) panic("could not write to output file `$(output)`: ", err)
end end
print_progress && okln() print_progress && okln()
else else
print_progress && okln() print_progress && okln()
end end
if diff if diff
@assert git !== ""
mktempdir() do dir mktempdir() do dir
a = mkdir(joinpath(dir, "a")) a = mkdir(joinpath(dir, "a"))
b = mkdir(joinpath(dir, "b")) b = mkdir(joinpath(dir, "b"))

Loading…
Cancel
Save