From 8ad7971304ca539668ab27b3e21dde14e831f831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Star=C3=BD=20Novotn=C3=BD?= Date: Fri, 13 Dec 2024 16:47:28 +0100 Subject: [PATCH 1/5] Add a command-line option `--porcelain` for machine-readable output --- explcheck/src/explcheck-cli.lua | 22 +++++-- explcheck/src/explcheck-format.lua | 102 ++++++++++++++++------------- 2 files changed, 70 insertions(+), 54 deletions(-) diff --git a/explcheck/src/explcheck-cli.lua b/explcheck/src/explcheck-cli.lua index b29b580..cee9584 100644 --- a/explcheck/src/explcheck-cli.lua +++ b/explcheck/src/explcheck-cli.lua @@ -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 @@ -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 @@ -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() @@ -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) @@ -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 @@ -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 diff --git a/explcheck/src/explcheck-format.lua b/explcheck/src/explcheck-format.lua index e4a8cbb..d1478ff 100644 --- a/explcheck/src/explcheck-format.lua +++ b/explcheck/src/explcheck-format.lua @@ -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 @@ -123,40 +123,44 @@ local function print_results(pathname, issues, line_starting_byte_numbers, is_la 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() + if not porcelain then + print() + end -- Display the warnings/errors. for _, issue in ipairs(issues.sort(warnings_or_errors)) do local code = issue[1] @@ -172,40 +176,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) + 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 .. " " .. suffix) + end end end - if(not is_last_file) then + if not is_last_file and not porcelain then print() end end From 165ed69c1bde5ab2ca3d061ec2549074a3f910db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Star=C3=BD=20Novotn=C3=BD?= Date: Fri, 13 Dec 2024 16:54:45 +0100 Subject: [PATCH 2/5] Update `CHANGES.md` --- CHANGES.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index bd73d94..08f9a0b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,7 +2,12 @@ ## expltools 2024-MM-DD -### 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) #### Fixes From 4e4ce736e3864d92142961d66ce67ec733beda27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Star=C3=BD=20Novotn=C3=BD?= Date: Fri, 13 Dec 2024 16:57:34 +0100 Subject: [PATCH 3/5] Make `line` into a local variable --- explcheck/src/explcheck-format.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/explcheck/src/explcheck-format.lua b/explcheck/src/explcheck-format.lua index d1478ff..f2d9e98 100644 --- a/explcheck/src/explcheck-format.lua +++ b/explcheck/src/explcheck-format.lua @@ -189,7 +189,7 @@ local function print_results(pathname, issues, line_starting_byte_numbers, is_la ), 1 ) ) - line = ( + local line = ( label_indent .. formatted_pathname .. position From 0a4aa68235c5c45648742d51298636b82806c0bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Star=C3=BD=20Novotn=C3=BD?= Date: Fri, 13 Dec 2024 22:47:29 +0100 Subject: [PATCH 4/5] Add `error: ` and `warning: ` to machine-readable output --- explcheck/src/explcheck-format.lua | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/explcheck/src/explcheck-format.lua b/explcheck/src/explcheck-format.lua index f2d9e98..dfe13b3 100644 --- a/explcheck/src/explcheck-format.lua +++ b/explcheck/src/explcheck-format.lua @@ -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 @@ -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( @@ -118,7 +118,7 @@ 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 @@ -157,7 +157,8 @@ local function print_results(pathname, issues, line_starting_byte_numbers, is_la -- Display the errors, followed by warnings. if #all_issues > 0 then - for _, warnings_or_errors in ipairs(all_issues) do + 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 @@ -209,7 +210,7 @@ local function print_results(pathname, issues, line_starting_byte_numbers, is_la ) io.write("\n" .. line) else - print(pathname .. position .. " " .. suffix) + print(pathname .. position .. " " .. porcelain_prefix .. suffix) end end end From 317dde398722932dc5d58c6463ded0500d668ebe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=ADt=20Star=C3=BD=20Novotn=C3=BD?= Date: Fri, 13 Dec 2024 22:59:34 +0100 Subject: [PATCH 5/5] Update `CHANGES.md` --- CHANGES.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES.md b/CHANGES.md index 08f9a0b..39d3a6c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,6 @@ # Changes -## expltools 2024-MM-DD +## expltools 2024-12-13 ### explcheck v0.2.0 @@ -9,6 +9,10 @@ - Add a command-line option `--porcelain` for machine-readable output. (suggested by @FrankMittelbach in #8, added in #14) + See + 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 - In the command-line interface, forbid the checking of .ins and .dtx files.