Skip to content

Commit

Permalink
Merge pull request #15 from Witiko/feat/porcelain
Browse files Browse the repository at this point in the history
Add a command-line option `--porcelain` for machine-readable output
  • Loading branch information
Witiko authored Dec 13, 2024
2 parents dbbe4ac + 317dde3 commit 70ace27
Show file tree
Hide file tree
Showing 3 changed files with 86 additions and 60 deletions.
13 changes: 11 additions & 2 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,17 @@
# Changes

## expltools 2024-MM-DD
## expltools 2024-12-13

### explcheck v0.1.2
### explcheck v0.2.0

#### Development

- Add a command-line option `--porcelain` for machine-readable output.
(suggested by @FrankMittelbach in #8, added in #14)

See <https://github.com/Witiko/expltools/pull/15#issuecomment-2542418484>
and below for a demonstration of how you might set up your text editor, so
that it automatically navigates you to lines with warnings and errors.

#### Fixes

Expand Down
22 changes: 15 additions & 7 deletions explcheck/src/explcheck-cli.lua
Original file line number Diff line number Diff line change
Expand Up @@ -82,11 +82,13 @@ local function check_pathname(pathname)
end

-- Process all input files.
local function main(pathnames, warnings_are_errors, max_line_length)
local function main(pathnames, warnings_are_errors, max_line_length, porcelain)
local num_warnings = 0
local num_errors = 0

print("Checking " .. #pathnames .. " " .. format.pluralize("file", #pathnames))
if not porcelain then
print("Checking " .. #pathnames .. " " .. format.pluralize("file", #pathnames))
end

for pathname_number, pathname in ipairs(pathnames) do

Expand All @@ -110,11 +112,13 @@ local function main(pathnames, warnings_are_errors, max_line_length)
::continue::
num_warnings = num_warnings + #issues.warnings
num_errors = num_errors + #issues.errors
format.print_results(pathname, issues, line_starting_byte_numbers, pathname_number == #pathnames)
format.print_results(pathname, issues, line_starting_byte_numbers, pathname_number == #pathnames, porcelain)
end

-- Print a summary.
format.print_summary(#pathnames, num_warnings, num_errors)
if not porcelain then
format.print_summary(#pathnames, num_warnings, num_errors, porcelain)
end

if(num_errors > 0) then
return 1
Expand All @@ -129,8 +133,9 @@ local function print_usage()
print("Usage: " .. arg[0] .. " [OPTIONS] FILENAMES\n")
print("Run static analysis on expl3 files.\n")
print("Options:")
print("\t--max-line-length=N\tThe maximum line length before the warning S103 (Line too long) is produced.")
print("\t--warnings-are-errors\tProduce a non-zero exit code if any warnings are produced by the analysis.")
print("\t--max-line-length=N The maximum line length before the warning S103 (Line too long) is produced.")
print("\t--porcelain Produce machine-readable output.")
print("\t--warnings-are-errors Produce a non-zero exit code if any warnings are produced by the analysis.")
end

local function print_version()
Expand All @@ -148,6 +153,7 @@ else
local warnings_are_errors = false
local only_pathnames_from_now_on = false
local max_line_length = nil
local porcelain = false
for _, argument in ipairs(arg) do
if only_pathnames_from_now_on then
table.insert(pathnames, argument)
Expand All @@ -161,6 +167,8 @@ else
os.exit(0)
elseif argument == "--warnings-are-errors" then
warnings_are_errors = true
elseif argument == "--porcelain" then
porcelain = true
elseif argument:sub(1, 18) == "--max-line-length=" then
max_line_length = tonumber(argument:sub(19))
elseif argument:sub(1, 2) == "--" then
Expand All @@ -183,6 +191,6 @@ else
end

-- Run the analysis.
local exit_code = main(pathnames, warnings_are_errors, max_line_length)
local exit_code = main(pathnames, warnings_are_errors, max_line_length, porcelain)
os.exit(exit_code)
end
111 changes: 60 additions & 51 deletions explcheck/src/explcheck-format.lua
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ local function convert_byte_to_line_and_column(line_starting_byte_numbers, byte_
end

-- Print the results of analyzing a file.
local function print_results(pathname, issues, line_starting_byte_numbers, is_last_file)
local function print_results(pathname, issues, line_starting_byte_numbers, is_last_file, porcelain)
-- Display an overview.
local all_issues = {}
local status
Expand All @@ -95,7 +95,7 @@ local function print_results(pathname, issues, line_starting_byte_numbers, is_la
), 1, 31
)
)
table.insert(all_issues, issues.errors)
table.insert(all_issues, {issues.errors, "error: "})
if(#issues.warnings > 0) then
status = (
status
Expand All @@ -108,7 +108,7 @@ local function print_results(pathname, issues, line_starting_byte_numbers, is_la
), 1, 33
)
)
table.insert(all_issues, issues.warnings)
table.insert(all_issues, {issues.warnings, "warning: "})
end
elseif(#issues.warnings > 0) then
status = colorize(
Expand All @@ -118,45 +118,50 @@ local function print_results(pathname, issues, line_starting_byte_numbers, is_la
.. pluralize("warning", #issues.warnings)
), 1, 33
)
table.insert(all_issues, issues.warnings)
table.insert(all_issues, {issues.warnings, "warning: "})
else
status = colorize("OK", 1, 32)
end

local max_overview_length = 72
local prefix = "Checking "
local formatted_pathname = format_pathname(
pathname,
math.max(
(
max_overview_length
- #prefix
- #(" ")
- #decolorize(status)
), 1
)
)
local overview = (
prefix
.. formatted_pathname
.. (" "):rep(
if not porcelain then
local max_overview_length = 72
local prefix = "Checking "
local formatted_pathname = format_pathname(
pathname,
math.max(
(
max_overview_length
- #prefix
- #(" ")
- #decolorize(status)
- #formatted_pathname
), 1
)
)
.. status
)
io.write("\n" .. overview)
local overview = (
prefix
.. formatted_pathname
.. (" "):rep(
math.max(
(
max_overview_length
- #prefix
- #decolorize(status)
- #formatted_pathname
), 1
)
)
.. status
)
io.write("\n" .. overview)
end

-- Display the errors, followed by warnings.
if #all_issues > 0 then
for _, warnings_or_errors in ipairs(all_issues) do
print()
for _, warnings_or_errors_and_porcelain_prefix in ipairs(all_issues) do
local warnings_or_errors, porcelain_prefix = table.unpack(warnings_or_errors_and_porcelain_prefix)
if not porcelain then
print()
end
-- Display the warnings/errors.
for _, issue in ipairs(issues.sort(warnings_or_errors)) do
local code = issue[1]
Expand All @@ -172,40 +177,44 @@ local function print_results(pathname, issues, line_starting_byte_numbers, is_la
local reserved_suffix_length = 30
local label_indent = (" "):rep(4)
local suffix = code:upper() .. " " .. message
formatted_pathname = format_pathname(
pathname,
math.max(
(
max_line_length
- #label_indent
- reserved_position_length
- #(" ")
- math.max(#suffix, reserved_suffix_length)
), 1
)
)
local line = (
label_indent
.. formatted_pathname
.. position
.. (" "):rep(
if not porcelain then
local formatted_pathname = format_pathname(
pathname,
math.max(
(
max_line_length
- #label_indent
- #formatted_pathname
- #decolorize(position)
- reserved_position_length
- #(" ")
- math.max(#suffix, reserved_suffix_length)
), 1
)
)
.. suffix
.. (" "):rep(math.max(reserved_suffix_length - #suffix, 0))
)
io.write("\n" .. line)
local line = (
label_indent
.. formatted_pathname
.. position
.. (" "):rep(
math.max(
(
max_line_length
- #label_indent
- #formatted_pathname
- #decolorize(position)
- math.max(#suffix, reserved_suffix_length)
), 1
)
)
.. suffix
.. (" "):rep(math.max(reserved_suffix_length - #suffix, 0))
)
io.write("\n" .. line)
else
print(pathname .. position .. " " .. porcelain_prefix .. suffix)
end
end
end
if(not is_last_file) then
if not is_last_file and not porcelain then
print()
end
end
Expand Down

0 comments on commit 70ace27

Please sign in to comment.