Browse Source

main: help message, check mode

pull/19/head
Fredrik Ekre 2 years ago
parent
commit
32ba9d345b
No known key found for this signature in database
GPG Key ID: DE82E6D5E364C0A2
  1. 11
      src/Runic.jl
  2. 128
      src/main.jl

11
src/Runic.jl

@ -36,6 +36,8 @@ mutable struct Context @@ -36,6 +36,8 @@ mutable struct Context
verbose::Bool
assert::Bool
debug::Bool
check::Bool
diff::Bool
# Current state
# node::Union{JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}, Nothing}
prev_sibling::Union{JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}, Nothing}
@ -43,7 +45,10 @@ mutable struct Context @@ -43,7 +45,10 @@ mutable struct Context
# parent::Union{JuliaSyntax.GreenNode{JuliaSyntax.SyntaxHead}, Nothing}
end
function Context(src_str; assert::Bool = true, debug::Bool = false, verbose::Bool = debug)
function Context(
src_str; assert::Bool = true, debug::Bool = false, verbose::Bool = debug,
diff::Bool = false, check::Bool = false,
)
src_io = IOBuffer(src_str)
src_tree = JuliaSyntax.parseall(JuliaSyntax.GreenNode, src_str; ignore_warnings = true)
fmt_io = IOBuffer()
@ -52,8 +57,8 @@ function Context(src_str; assert::Bool = true, debug::Bool = false, verbose::Boo @@ -52,8 +57,8 @@ function Context(src_str; assert::Bool = true, debug::Bool = false, verbose::Boo
verbose = debug ? true : verbose
assert = debug ? true : assert
return Context(
src_str, src_tree, src_io, fmt_io, fmt_tree, verbose, assert, debug, nothing,
nothing,
src_str, src_tree, src_io, fmt_io, fmt_tree,
verbose, assert, debug, check, diff, nothing, nothing,
)
end

128
src/main.jl

@ -20,65 +20,147 @@ function panic(msg...) @@ -20,65 +20,147 @@ function panic(msg...)
return errno
end
# Print a typical cli program help message
function print_help()
io = stdout
printstyled(io, "NAME\n", bold = true)
println(io, " Runic.main - format Julia source code")
println(io)
printstyled(io, "SYNOPSIS\n", bold = true)
println(io, " julia -m Runic [<options>] <path>...")
println(io)
printstyled(io, "DESCRIPTION\n", bold = true)
println(io, """
`Runic.main` (typically invoked as `julia -m Runic`) formats Julia source
code using the Runic.jl formatter.
""")
printstyled(io, "OPTIONS\n", bold = true)
println(io, """
<path>...
Input path(s) (files and/or directories) to process. For directories,
all files (recursively) with the '*.jl' suffix are used as input files.
If no path is given, or if path is `-`, input is read from stdin.
-c, --check
Do not write output and exit with a non-zero code if the input is not
formatted correctly.
-d, --diff
Print the diff between the input and formatted output to stderr.
Requires `git` or `diff` to be installed.
--help
Print this message.
-i, --inplace
Edit files in place. This option is required when passing multiple input
paths.
-o, --output <file>
Output file to write formatted code to. If no output file is given, or
if the specified file is `-`, output is written to stdout. This option
can not be used together with multiple input paths.
""")
return
end
function maybe_expand_directory!(outfiles, dir)
if !isdir(dir)
# Assumed a file, checked when using it
push!(outfiles, dir)
return
end
for (root, _, files) in walkdir(dir; onerror = (err) -> nothing)
for file in files
if endswith(file, ".jl")
push!(outfiles, joinpath(root, file))
end
end
end
end
function main(argv)
# Reset errno
global errno = 0
# Split argv entries with `=`
argv = mapreduce(x -> split(x, "="; limit = 2), append!, argv; init = String[])
# Default values
inputfiles = String[]
outputfile = nothing
verbose = false
debug = false
inplace = false
diff = false
check = false
# Parse the arguments
while length(argv) > 0
x = popfirst!(argv)
if x == "-i"
if x == "-i" || x == "--inplace"
inplace = true
elseif x == "-v"
elseif x == "-v" || x == "--verbose"
verbose = true
elseif x == "-vv"
elseif x == "-d" || x == "--diff"
diff = true
elseif x == "c" || x == "--check"
check = true
elseif x == "-vv" || x == "--debug"
debug = verbose = true
elseif x == "-o"
elseif x == "-o" || x == "--output"
if length(argv) < 1
return panic("expected output file as argument after `-o`")
return panic("expected output file as argument after `-o, --output`")
end
outputfile = popfirst!(argv)
else
# Remaining arguments must be inputfile(s)
push!(inputfiles, x)
maybe_expand_directory!(inputfiles, x)
for x in argv
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
push!(inputfiles, x)
end
break
end
end
# one of --check, --diff, --inplace, or --output must be specified
if !(inplace || check || diff || outputfile !== nothing)
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
if inplace && check
return panic("options `-c, --check` and `-i, --inplace` are mutually exclusive")
end
# stdin is the default input
if isempty(inputfiles)
push!(inputfiles, "-")
end
# multiple files require -i and no -o
# multiple files require --inplace or --check and no --output
if length(inputfiles) > 1
if !inplace
return panic("option `-i` is required for multiple input files")
if !(inplace || check)
return panic("option `-i, --inplace` or `-c, --check` is required for multiple input files")
elseif outputfile !== nothing
return panic("option `-o` is incompatible with multiple input files")
return panic("option `-o, --output` can not be used together with multiple input files")
end
end
# inplace = true is incompatible with given output
# --inplace can not be used when specifying output
if inplace && outputfile !== nothing
@assert length(inputfiles) == 1
return panic("option `-i` is incompatible with option `-o $(outputfile)`")
return panic("options `-i, --inplace` and `-o, --output` are mutually exclusive")
end
# inplace = true is incompatible with stdin as input
# --inplace is incompatible with stdin as input
if inplace && first(inputfiles) == "-"
return panic("option `-i` is incompatible with stdin as input")
end
@ -113,6 +195,9 @@ function main(argv) @@ -113,6 +195,9 @@ function main(argv)
@assert input_is_file
# @assert length(inputfiles) == 1 # checked above
output = inputfile
elseif check
@assert outputfile === nothing
output = devnull
else
@assert length(inputfiles) == 1
if outputfile === nothing || outputfile == "-"
@ -126,7 +211,7 @@ function main(argv) @@ -126,7 +211,7 @@ function main(argv)
# Call the library to format the text
ctx = try
ctx = Context(sourcetext; verbose = verbose, debug = debug)
ctx = Context(sourcetext; verbose = verbose, debug = debug, diff = diff, check = check)
format_tree!(ctx)
ctx
catch err
@ -134,9 +219,13 @@ function main(argv) @@ -134,9 +219,13 @@ function main(argv)
continue
end
# Write the output, but skip if inplace and it didn't change
# Output the result
changed = ctx.fmt_tree !== ctx.src_tree
if changed || !inplace
if check
if changed
global errno = 1
end
elseif changed || !inplace
try
write(output, take!(ctx.fmt_io))
catch err
@ -145,6 +234,9 @@ function main(argv) @@ -145,6 +234,9 @@ function main(argv)
else
# Log if verbose perhaps
end
if diff
error("todo")
end
end # inputfile loop

Loading…
Cancel
Save