diff options
author | Karl Berry <karl@freefriends.org> | 2022-08-05 21:34:16 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2022-08-05 21:34:16 +0000 |
commit | ff9132493e098d65f121944f67b3f52769155e2e (patch) | |
tree | cee7a4213ac13e84f4815b9e0d9646c4b1c6df8c | |
parent | 168e2e89b88f33f5f4940a07636b697f9a69dac6 (diff) |
texlogsieve (5aug22)
git-svn-id: svn://tug.org/texlive/trunk@64060 c570f23f-e606-0410-a88d-b1316a301751
-rwxr-xr-x | Build/source/texk/texlive/linked_scripts/texlogsieve/texlogsieve | 340 | ||||
-rw-r--r-- | Master/texmf-dist/doc/man/man1/texlogsieve.1 | 43 | ||||
-rw-r--r-- | Master/texmf-dist/doc/man/man1/texlogsieve.man1.pdf | bin | 40199 -> 41838 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/support/texlogsieve/texlogsieve.pdf | bin | 59279 -> 60077 bytes | |||
-rw-r--r-- | Master/texmf-dist/doc/support/texlogsieve/texlogsieve.tex | 64 | ||||
-rwxr-xr-x | Master/texmf-dist/scripts/texlogsieve/texlogsieve | 340 |
6 files changed, 567 insertions, 220 deletions
diff --git a/Build/source/texk/texlive/linked_scripts/texlogsieve/texlogsieve b/Build/source/texk/texlive/linked_scripts/texlogsieve/texlogsieve index 3520efd7448..331651fd55f 100755 --- a/Build/source/texk/texlive/linked_scripts/texlogsieve/texlogsieve +++ b/Build/source/texk/texlive/linked_scripts/texlogsieve/texlogsieve @@ -176,7 +176,13 @@ in the LaTeX log file: is indented to start after the end of the first, as in the example above. If the content of a line does not fit, a part of it (the beginning for the first line and the end for the second line) may - be replaced by "...". + be replaced by "...". error_line must be < 255 and half_error_line + must be < error_line -15. If error_line >= max_print_line or + half_error_line >= max_print_line, TeX does line wrapping as usual + (see below). If either is exactly max_print_line (which is true + for the default values), things get confusing, so TeX may add a + blank line when wrapping. + LaTeX errors usually follow the format @@ -620,10 +626,8 @@ function moreData() while Lines:numLines() < 15 do tmp = logfile:read("*line") if tmp == nil then break end - -- We *need* to remove blank lines here because - -- sometimes a wrapped line is followed by a blank - -- line, which messes our detection of wrapped lines. - if tmp ~= "" then Lines:append(tmp) end + -- Do not skip blank lines here, we need to do it in Lines:append() + Lines:append(tmp) end -- proceed to the next line @@ -744,6 +748,9 @@ function initializeGlobals() -- messages, this is set to true (used in showSummary) SHOULD_RERUN_LATEX = false + -- If there were parse errors, we should say so in showSummary + PARSE_ERROR = false + -- Did we detect any error messages? ERRORS_DETECTED = false @@ -898,42 +905,7 @@ function detectEngine() Lines:append(line) end -function processCommandLine(args) - HEARTBEAT = true - PAGE_DELAY = true - ONLY_SUMMARY = false - SHOW_SUMMARY = true - SHOW_SHIPOUTS = false - RAW = false - SILENCE_REPETITIONS = true - MINLEVEL = WARNING - BE_REDUNDANT = false - FILE_BANNER = true - DETAILED_UNDEROVER_SUMMARY = true - DETAILED_REFERENCE_SUMMARY = true - DETAILED_CITATION_SUMMARY = true - - COLOR = false - - SILENCE_STRINGS = {} - SILENCE_PKGS = {} -- just the package names - SEMISILENCE_FILES = {} -- filenames (without leading path), file globs work - SILENCE_FILES_RECURSIVE = {} -- same - - -- The user may redefine the severity level of some messages. - FORCED_DEBUG = {} - FORCED_INFO = {} - FORCED_WARNING = {} - FORCED_CRITICAL = {} - - -- "-l level -c configFile" - local optionsWithArgs = "lc" - local vars = simpleGetopt(args, optionsWithArgs) - - --help - -- "-h" - if vars.help or vars.h then - local msg = [[ +helpmsg = [[ Usage: texlogsieve [OPTION]... [INPUT FILE] texlogsieve reads a LaTeX log file (or the standard input), filters out less relevant messages, and displays a summary report. @@ -994,23 +966,60 @@ Options: text EXCERPT to CRITICAL; can be used multiple times -c cfgfile, --config-file=cfgfile read options from given config file - in addition to texlogsieverc + in addition to default config files + -v, --verbose Display info on texlogsieve config -h, --help give this help list --version print program version]] - for _, line in ipairs(linesToTable(msg)) do print(line) end +versionmsg = [[ +texlogsieve 1.3.0 +Copyright (C) 2021, 2022 Nelson Lago <lago@ime.usp.br> +License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law.]] + +function processCommandLine(args) + HEARTBEAT = true + PAGE_DELAY = true + ONLY_SUMMARY = false + SHOW_SUMMARY = true + SHOW_SHIPOUTS = false + RAW = false + SILENCE_REPETITIONS = true + MINLEVEL = WARNING + BE_REDUNDANT = false + FILE_BANNER = true + DETAILED_UNDEROVER_SUMMARY = true + DETAILED_REFERENCE_SUMMARY = true + DETAILED_CITATION_SUMMARY = true + + COLOR = false + + SILENCE_STRINGS = {} + SILENCE_PKGS = {} -- just the package names + SEMISILENCE_FILES = {} -- filenames (without leading path), file globs work + SILENCE_FILES_RECURSIVE = {} -- same + + -- The user may redefine the severity level of some messages. + FORCED_DEBUG = {} + FORCED_INFO = {} + FORCED_WARNING = {} + FORCED_CRITICAL = {} + + -- "-l level -c configFile" + local optionsWithArgs = "lc" + local vars = simpleGetopt(args, optionsWithArgs) + + --help + -- "-h" + if vars.help or vars.h then + for _, line in ipairs(linesToTable(helpmsg)) do print(line) end os.exit(0) end --version if vars.version then - print("texlogsieve 1.2.0") - print("Copyright (C) 2021, 2022 Nelson Lago <lago@ime.usp.br>") - print("License GPLv3+: GNU GPL version 3 or later " - .. "<https://gnu.org/licenses/gpl.html>.") - print("This is free software: you are free to change " - .. "and redistribute it.") - print("There is NO WARRANTY, to the extent permitted by law.") + for _, line in ipairs(linesToTable(versionmsg)) do print(line) end os.exit(0) end @@ -1029,6 +1038,21 @@ Options: local filename = kpse.find_file('texlogsieverc') if filename ~= nil then table.insert(configFileNames, 1, filename) end + if os.type == "unix" then + filename = kpse.find_file(os.getenv("HOME") .. "/.texlogsieverc") + else + -- https://docs.microsoft.com/en-us/windows/deployment/usmt/usmt-recognized-environment-variables + -- %LOCALAPPDATA% corresponds to C:\Users\<username>\AppData\Local . + filename = kpse.find_file(os.getenv("%LOCALAPPDATA%") .. "/texlogsieverc") + if filename == nil then + -- %APPDATA% is "C:\Users\<username>\AppData\Roaming" or + -- "C:\Documents and Settings\<username>\Application Data" + filename = kpse.find_file(os.getenv("%APPDATA%") .. "/texlogsieverc") + end + end + + if filename ~= nil then table.insert(configFileNames, 1, filename) end + for _, filename in ipairs(configFileNames) do local configFile = assert(io.open(filename, "r")) vars = processConfigFile(configFile, vars) @@ -1353,6 +1377,39 @@ Options: vars['set-to-level-critical'] = nil + --verbose + -- "-v" + if vars['verbose'] or vars.v then + local msg = "" + + for _, name in ipairs(configFileNames) do msg = msg .. name .. ", " end + + if msg == "" then + print("texlogsieve: no config files, using defaults") + else + msg = string.sub(msg, 1, -3) + print("texlogsieve: using config files: " .. msg) + end + + msg = "texlogsieve: minlevel is " + if MINLEVEL == 0 then msg = msg .. 'DEBUG' + elseif MINLEVEL == 1 then msg = msg .. 'INFO' + elseif MINLEVEL == 2 then msg = msg .. 'WARNING' + elseif MINLEVEL == 3 then msg = msg .. 'CRITICAL' + else msg = msg .. 'UNKNOWN' + end + + print(msg) + + if RAW then + print("texlogsieve: using raw (unwrap-only) mode") + end + end + + vars['verbose'] = nil + vars.v = nil + + local unknown_options = false for k, v in pairs(vars) do print(' texlogsieve: unknown option "' .. k .. '"') @@ -1581,13 +1638,13 @@ function finishProcessingMessages() end function showFileBanner(msg) + if msg.filename == "DUMMY" then PARSE_ERROR = true end + if not FILE_BANNER then return end if msg.filename ~= nil and msg.filename ~= "" and msg.filename ~= lastFileBanner - -- TODO: "DUMMY" should never happen, but - -- what should we do if it does? then lastFileBanner = msg.filename local txt = "From file " .. msg.filename .. ":" @@ -1674,7 +1731,7 @@ end function showSummary() local somethingInSummary = false - if SHOULD_RERUN_LATEX or ERRORS_DETECTED then + if SHOULD_RERUN_LATEX or ERRORS_DETECTED or PARSE_ERROR then somethingInSummary = true else for _, summary in ipairs(summaries) do @@ -1716,6 +1773,15 @@ function showSummary() print() end + if PARSE_ERROR then + local txt = "** texlogsieve got confused during log processing **" .. + "\n" .. " messages may be missing or filenames may be" .. + "\n" .. " incorrect, check the LaTeX logfile directly" + if COLOR then txt = red(txt) end + print(txt) + print() + end + if ERRORS_DETECTED then local txt = "** There were errors during processing! Generated PDF is probably defective **" if COLOR then txt = red(txt) end @@ -2169,8 +2235,10 @@ function fpHandler:process() else -- This should never happen, but if it does -- we will probably end up in an endless loop - io.stderr:write(" texlogsieve: parsing error in " - .. "fpHandler:process()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum .. " (fpHandler:process)\n") + + PARSE_ERROR = true dispatch(self.message) self.message = nil @@ -2199,8 +2267,10 @@ function fpHandler:processClose(last) Lines:handledChars(last) if self.stack:pop() == nil then - io.stderr:write(" texlogsieve: parsing error in " - .. "fpHandler:processClose()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum .. " (fpHandler:processClose)\n") + + PARSE_ERROR = true end if self.stack:empty() then @@ -2276,8 +2346,11 @@ function underOverFullBoxHandler:handleFirstLine() end if last == nil then - io.stderr:write(" texlogsieve: parsing error in " - .. "underOverFullBoxHandler:handleFirstLine()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (underOverFullBoxHandler:handleFirstLine)\n") + + PARSE_ERROR = true self.doit = self.handleFirstLine dispatch(self.message) @@ -2439,8 +2512,11 @@ function stringsHandler:handleLines() for _, val in ipairs(tmp) do table.insert(self.captures, val) end if last == nil then - io.stderr:write(" texlogsieve: parsing error in " - .. "stringsHandler:handleLines()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (stringsHandler:handleLines)\n") + + PARSE_ERROR = true dispatch(self.message) self.message = nil @@ -3570,9 +3646,11 @@ function openParensHandler:doit() flushUnrecognizedMessages() local last = unwrapUntilStringMatches(data.filename) if last == nil then - io.stderr:write(" texlogsieve: parsing error in " - .. "openParensHandler:doit()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (openParensHandler:doit)\n") + PARSE_ERROR = true else Lines:handledChars(last) end @@ -3772,9 +3850,11 @@ function openSquareBracketHandler:doit() flushUnrecognizedMessages() local last = unwrapUntilStringMatches(data.latexPage) if last == nil then - io.stderr:write(" texlogsieve: parsing error in " - .. "openSquareBracketHandler:doit()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (openSquareBracketHandler:doit)\n") + PARSE_ERROR = true else Lines:handledChars(last) end @@ -3993,9 +4073,11 @@ function utf8FontMapHandler:handleSecondLine() -- "processing UTF-8 mapping" - this should never happen dispatch(self.message) self.message = nil - io.stderr:write(" texlogsieve: parsing error in " - .. "utf8FontMapHandler:handleSecondLine()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (utf8FontMapHandler:handleSecondLine)\n") + PARSE_ERROR = true Lines:handledChars() self.doit = self.handleFirstLine return true @@ -4025,9 +4107,11 @@ function utf8FontMapHandler:handleOtherLines() dispatch(self.message) self.message = nil flushUnrecognizedMessages() - io.stderr:write(" texlogsieve: parsing error in " - .. "utf8FontMapHandler:handleOtherLines()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (utf8FontMapHandler:handleOtherLines)\n") + PARSE_ERROR = true self.numTries = 0 self.foundOtherLines = false self.doit = self.handleFirstLine @@ -4972,8 +5056,8 @@ function SummaryPrototype:pageAndFileList(messages) if files[msg.filename] == nil then files[msg.filename] = {} end - if msg.linenum ~= "" then - table.insert(files[msg.filename], msg.linenum) + if tonumber(msg.linenum) then + table.insert(files[msg.filename], tonumber(msg.linenum)) end end end @@ -5147,22 +5231,6 @@ end unusedLabelsSummary = citationsSummary:new() unusedLabelsSummary.header = 'Unused labels:' -function unusedLabelsSummary:processSingleMessageList(messages) - local text = "" - local pages, files = self:pageAndFileList(messages) - local key = messages[1].key - if key == "" then key = '???' end - - if self:detailed() then - if COLOR then key = red(key) end - text = key .. ' in ' .. pages .. " (" .. files .. ")" - else - text = key - end - - return text -end - -- This is a little different from the others; we do not want to -- treat different messages differently, only report that there were @@ -5371,6 +5439,66 @@ function Stack:empty() end +--[[ ##### QUEUE ##### ]]-- +-- Adapted from https://www.lua.org/pil/11.4.html (in 2022) +-- We use this for the input line counter + +Queue = {} + +function Queue:new() + local o = {} + setmetatable(o, self) + self.__index = self + o.first = 0 + o.last = -1 + return o +end + +function Queue:pushleft(val) + self.first = self.first -1 + self[self.first] = val +end + +function Queue:pushright(val) + self.last = self.last +1 + self[self.last] = val +end + +function Queue:popleft() + if self.first > self.last then return nil end + local val = self[self.first] + self[self.first] = nil + self.first = self.first +1 + return val +end + +function Queue:popright() + if self.first > self.last then return nil end + local val = self[self.last] + self[self.last] = nil + self.last = self.last -1 + return val +end + +function Queue:peekleft() + if self.first > self.last then return nil end + return self[self.first] +end + +function Queue:peekright() + if self.first > self.last then return nil end + return self[self.last] +end + +function Queue:size() + return self.last - self.first +1 +end + +function Queue:empty() + return self.first > self.last +end + + --[[ ##### GLOBTOPATTERN ##### ]]-- -- convert a file glob to a lua pattern @@ -5644,12 +5772,20 @@ original length was max_print_line characters). Lines = {} Lines.wrapped = {} -- memoization +Lines.linenum = 0 +Lines.blankLines = Queue:new() function Lines:gotoNextLine() self.current = table.remove(self, 1) self.currentWrapped = table.remove(self.wrapped, 1) self.atBeginningOfLine = true + self.linenum = self.linenum +1 + -- blank lines have to be counted too + if not self.blankLines:empty() then + self.linenum = self.linenum + self.blankLines:popleft() + end + -- When unwrapping lines, we need to check whether a line is of -- the "right" size. However, we modify the content of currentLine -- during processing, so we capture its initial length here. See @@ -5691,8 +5827,23 @@ function Lines:len(n) end function Lines:append(x) - table.insert(self, x) - table.insert(self.wrapped, "unknown") -- cannot use "nil" + -- We *need* to remove blank lines here because sometimes a wrapped + -- line is followed by a blank line, which messes our detection of + -- wrapped lines. However, the line we skip here is not the line we + -- are processing right now; we will encounter it in the future. So, + -- to keep line numbers right, we need to adjust the count later too. + if x == "" then + if not self.blankLines:empty() then + self.blankLines:pushright(self.blankLines:popright() +1) + else + self.blankLines:pushright(1) + end + else + self.blankLines:pushright(0) + + table.insert(self, x) + table.insert(self.wrapped, "unknown") -- cannot use "nil" + end end function Lines:get(n) @@ -5847,9 +5998,11 @@ function unwrapUntilPatternMatches(pat) if Lines:seemsWrapped() then Lines:unwrapOneLine() else - io.stderr:write(" texlogsieve: parsing error in " - .. "unwrapUntilPatternMatches()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (unwrapUntilPatternMatches)\n") + PARSE_ERROR = true break end end @@ -6008,9 +6161,10 @@ function guessQuotedFilename(line, position) -- no closing quote or the line is too short; can we unwrap this line? if not Lines:seemsWrapped(position) then - io.stderr:write(" texlogsieve: parsing error in " - .. "guessQuotedFilename()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum .. " (guessQuotedFilename)\n") + PARSE_ERROR = true return true, nil end diff --git a/Master/texmf-dist/doc/man/man1/texlogsieve.1 b/Master/texmf-dist/doc/man/man1/texlogsieve.1 index 4628d1ec54f..b39e33eff2f 100644 --- a/Master/texmf-dist/doc/man/man1/texlogsieve.1 +++ b/Master/texmf-dist/doc/man/man1/texlogsieve.1 @@ -1,4 +1,4 @@ -.TH TEXLOGSIEVE "1" "July 2022" "texlogsieve 1.2.0" "User Commands" +.TH TEXLOGSIEVE "1" "August 2022" "texlogsieve 1.3.0" "User Commands" .SH NAME @@ -198,8 +198,13 @@ severity level of many different messages. .TP \fB\-c\fR \fI\,CFGFILE\/\fR, \fB\-\-config\-file\fR=\fI\,CFGFILE\/\fR -Read options from the given configuration file in addition to -\fI\,texlogsieverc\/\fR. +Read options from the given configuration file in addition to the +default config files (see the \fBCONFIGURATION FILE\fR section). + +.TP +\fB\-v\fR, \fB\-\-verbose\fR +Print the list of configuration files read and a short summary of the +most important active configuration options. .TP \fB\-h\fR, \fB\-\-help\fR @@ -226,13 +231,14 @@ list of messages known to the program. .SH CONFIGURATION FILE texlogsieve always searches automatically for the (optional) -\fI\,texlogsieverc\/\fR configuration file in the TeX path (i.e., it searches -using Kpathsea). In the default configuration, the current directory is in -the search path, so adding a config file with that name to the project -directory is enough to make it work. Options in the config file are exactly -the same as the long command-line options described above, but without the -preceding \[lq]\-\-\[rq] characters. Lines starting with a \[lq]#\[rq] sign -are comments. An example configuration file: +\fI\,texlogsieverc\/\fR configuration file in \fI\,$TEXINPUTS\/\fR (i.e., +it searches using Kpathsea). In the default configuration, the current +directory is in \fI\,$TEXINPUTS\/\fR, so adding a config file with that +name to the project directory is enough to make it work. Options in +the config file are exactly the same as the long command-line options +described above, but without the preceding \[lq]\-\-\[rq] characters. +Lines starting with a \[lq]#\[rq] sign are comments. An example +configuration file: .RS .EX @@ -256,13 +262,22 @@ silence\-files = *.sty .EE .RE +If you'd like to also have a generic configuration file for all your projects +(a good idea), put it at \fI\,$HOME/.texlogsieverc\/\fR in unix-like systems; +in Windows, put it either at \fI\,%LOCALAPPDATA%\etexlogsieverc\/\fR +(\fI\,C:\eUsers\e<username>\eAppData\eLocal\/\fR) +or \fI\,%APPDATA%\etexlogsieverc\/\fR (\fI\,C:\eDocuments and +Settings\e<username>\eApplication Data\/\fR or +\fI\,C:\eUsers\e<username>\eAppData\eRoaming). + .SH LIMITATIONS texlogsieve does not try to do anything smart about error messages (but it -shows a warning in the summary if one is detected); if there is an error, -you probably want to take a look directly at the log file anyway. It also -cannot detect if LaTeX stops for user input, so you should \fBreally\fR -run LaTeX in \fI\,nonstopmode\/\fR when texlogsieve is reading from a pipe. +shows a warning in the summary if one is detected; check the \fBTIPS\fR +section of the pdf documentation regarding this); if there is an error, you +probably want to take a look directly at the log file anyway. It also cannot +detect if LaTeX stops for user input, so you should \fBreally\fR run LaTeX +in \fI\,nonstopmode\/\fR when texlogsieve is reading from a pipe. Since it needs to know what messages to expect, texlogsieve is currently geared towards LaTeX; I have no idea how it would work with ConTeXt or plain diff --git a/Master/texmf-dist/doc/man/man1/texlogsieve.man1.pdf b/Master/texmf-dist/doc/man/man1/texlogsieve.man1.pdf Binary files differindex f65d3e70087..099832b51db 100644 --- a/Master/texmf-dist/doc/man/man1/texlogsieve.man1.pdf +++ b/Master/texmf-dist/doc/man/man1/texlogsieve.man1.pdf diff --git a/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.pdf b/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.pdf Binary files differindex f37bc1ab309..1891667c3d6 100644 --- a/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.pdf +++ b/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.pdf diff --git a/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.tex b/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.tex index 6270e27ffe1..40323ceb2ac 100644 --- a/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.tex +++ b/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.tex @@ -37,6 +37,8 @@ \usepackage{microtype} \usepackage{metalogo} +\hyphenation{tex-log-sieve tex-log-sieverc} + \RecordChanges \changes{1.0.0-beta-1}{2021/12/16}{First public prerelease} @@ -84,12 +86,18 @@ \changes{1.2.0}{2022/07/21}{Summary messages use singular and plural for pages and files} \changes{1.2.0}{2022/07/21}{Add unused labels to summary} +\changes{1.3.0}{2022/08/05}{Sort line numbers in summary} +\changes{1.3.0}{2022/08/05}{Indicate whether there were parse errors + in summary} +\changes{1.3.0}{2022/08/05}{Add line number to parse error messages} +\changes{1.3.0}{2022/08/05}{Add \texttt{-\/-verbose} option} +\changes{1.3.0}{2022/08/05}{Search for a config file in the user's homedir too} \begin{document} \title{\textsf{texlogsieve}:\thanks{This document -corresponds to \textsf{texlogsieve}~1.2.0, -dated~2022-07-21.}\\[.3\baselineskip] +corresponds to \textsf{texlogsieve}~1.3.0, +dated~2022-08-05.}\\[.3\baselineskip] {\normalsize(yet another program to)\\[-.6\baselineskip]} {\large filter and summarize \LaTeX\ log files} } @@ -138,12 +146,12 @@ spirit to tools such as \href{https://ctan.org/pkg/texfot}{\texttt{texfot}}, \href{https://gricad-gitlab.univ-grenoble-alpes.fr/labbeju/latex-packages} {\texttt{texlogfilter}}, and others. -Note that it does not try to do anything smart about error messages -(but it shows a warning in the summary if one is detected); if there -is an error, you probably want to take a look directly at the log file -anyway. It also cannot detect if \LaTeX{} stops for user input, so -you should \textbf{really} run \LaTeX\ in \texttt{nonstopmode} when -\texttt{texlogsieve} is reading from a pipe. +Note that it does not try to do anything smart about error messages (but +it shows a warning in the summary if one is detected; check the ``Tips'' +section regarding this); if there is an error, you probably want to take +a look directly at the log file anyway. It also cannot detect if \LaTeX{} +stops for user input, so you should \textbf{really} run \LaTeX\ in +\texttt{nonstopmode} when \texttt{texlogsieve} is reading from a pipe. \texttt{texlogsieve} \textbf{must} be run from the same directory as \verb/[pdf|lua|xe]latex/, because it searches for the files used during @@ -223,13 +231,14 @@ options to add it to the list of messages known to the program. \section{Configuration File} \texttt{texlogsieve} always searches automatically for the (optional) -\texttt{texlogsieverc} configuration file in the \TeX\ path (i.e., it -searches using \texttt{Kpathsea}). In the default configuration, the -current directory is in the search path, so adding a config file with that -name to the project directory is enough to make it work. Options in the -config file are exactly the same as the long command-line options described -below, but without the preceding ``\texttt{-\/-}'' characters. Lines -starting with a ``\#'' sign are comments. An example configuration file: +\texttt{texlogsieverc} configuration file in \texttt{\$TEXINPUTS} (i.e., +it searches using \texttt{Kpathsea}). In the default configuration, the +current directory is in \texttt{\$TEXINPUTS}, so adding a config file +with that name to the project directory is enough to make it work. +Options in the config file are exactly the same as the long command-line +options described below, but without the preceding ``\texttt{-\/-}'' +characters. Lines starting with a ``\#'' sign are comments. An example +configuration file: \begin{quote} \begin{verbatim} @@ -246,6 +255,16 @@ silence-files = *.sty \end{verbatim} \end{quote} +If you'd like to also have a generic configuration file for all your projects +(a good idea), put it at \texttt{\$HOME/.texlogsieverc} in unix-like systems; +in Windows, put it either at \texttt{\%LOCALAPPDATA\%\textbackslash{}% +texlogsieverc} (\texttt{C:\textbackslash{}Users\textbackslash{}<username>% +\textbackslash{}AppData\textbackslash{}Local}) or \texttt{\%APPDATA\%% +\textbackslash{}texlogsieverc} (\texttt{C:\textbackslash{}Documents and +Settings\textbackslash{}<username>\textbackslash{}Application Data} or +\texttt{C:\textbackslash{}Users\textbackslash{}<username>\textbackslash{}% +AppData\textbackslash{}Roaming}). + \section{Options} \begin{description} @@ -426,8 +445,14 @@ the severity level of many different messages. \begin{description} \item[\texttt{-c CFGFILE}, \texttt{-\/-config-file=CFGFILE}]~\\ -Read options from the given configuration file in addition to -\texttt{texlogsieverc}. +Read options from the given configuration file in addition to the +default config files (see the ``Configuration File'' section). +\end{description} + +\begin{description} +\item[\texttt{-v}, \texttt{-\/-verbose}]~\\ +Print the list of configuration files read and a short summary of the +most important active configuration options. \end{description} \begin{description} @@ -449,9 +474,8 @@ Print program version. \texttt{silence-[something]} and \texttt{set-to-level-[something]} options: You will get reasonably quiet output but still be notified of problems. Since you probably always use essentially the same set of packages and classes, - the file will be useable in other \LaTeX\ projects too (you may even put - it somewhere in your \TeX\ path, like \texttt{\$HOME/texmf/tex/latex} on - Unix-like systems). + the file will be useable in other \LaTeX\ projects too; just put it in one + of the places discussed in the ``Configuration File'' section. \item \texttt{texlogsieve} has no smarts to deal with error messages, but you may use options \texttt{-l unknown -\/-no-page-delay -\/-no-summary diff --git a/Master/texmf-dist/scripts/texlogsieve/texlogsieve b/Master/texmf-dist/scripts/texlogsieve/texlogsieve index 3520efd7448..331651fd55f 100755 --- a/Master/texmf-dist/scripts/texlogsieve/texlogsieve +++ b/Master/texmf-dist/scripts/texlogsieve/texlogsieve @@ -176,7 +176,13 @@ in the LaTeX log file: is indented to start after the end of the first, as in the example above. If the content of a line does not fit, a part of it (the beginning for the first line and the end for the second line) may - be replaced by "...". + be replaced by "...". error_line must be < 255 and half_error_line + must be < error_line -15. If error_line >= max_print_line or + half_error_line >= max_print_line, TeX does line wrapping as usual + (see below). If either is exactly max_print_line (which is true + for the default values), things get confusing, so TeX may add a + blank line when wrapping. + LaTeX errors usually follow the format @@ -620,10 +626,8 @@ function moreData() while Lines:numLines() < 15 do tmp = logfile:read("*line") if tmp == nil then break end - -- We *need* to remove blank lines here because - -- sometimes a wrapped line is followed by a blank - -- line, which messes our detection of wrapped lines. - if tmp ~= "" then Lines:append(tmp) end + -- Do not skip blank lines here, we need to do it in Lines:append() + Lines:append(tmp) end -- proceed to the next line @@ -744,6 +748,9 @@ function initializeGlobals() -- messages, this is set to true (used in showSummary) SHOULD_RERUN_LATEX = false + -- If there were parse errors, we should say so in showSummary + PARSE_ERROR = false + -- Did we detect any error messages? ERRORS_DETECTED = false @@ -898,42 +905,7 @@ function detectEngine() Lines:append(line) end -function processCommandLine(args) - HEARTBEAT = true - PAGE_DELAY = true - ONLY_SUMMARY = false - SHOW_SUMMARY = true - SHOW_SHIPOUTS = false - RAW = false - SILENCE_REPETITIONS = true - MINLEVEL = WARNING - BE_REDUNDANT = false - FILE_BANNER = true - DETAILED_UNDEROVER_SUMMARY = true - DETAILED_REFERENCE_SUMMARY = true - DETAILED_CITATION_SUMMARY = true - - COLOR = false - - SILENCE_STRINGS = {} - SILENCE_PKGS = {} -- just the package names - SEMISILENCE_FILES = {} -- filenames (without leading path), file globs work - SILENCE_FILES_RECURSIVE = {} -- same - - -- The user may redefine the severity level of some messages. - FORCED_DEBUG = {} - FORCED_INFO = {} - FORCED_WARNING = {} - FORCED_CRITICAL = {} - - -- "-l level -c configFile" - local optionsWithArgs = "lc" - local vars = simpleGetopt(args, optionsWithArgs) - - --help - -- "-h" - if vars.help or vars.h then - local msg = [[ +helpmsg = [[ Usage: texlogsieve [OPTION]... [INPUT FILE] texlogsieve reads a LaTeX log file (or the standard input), filters out less relevant messages, and displays a summary report. @@ -994,23 +966,60 @@ Options: text EXCERPT to CRITICAL; can be used multiple times -c cfgfile, --config-file=cfgfile read options from given config file - in addition to texlogsieverc + in addition to default config files + -v, --verbose Display info on texlogsieve config -h, --help give this help list --version print program version]] - for _, line in ipairs(linesToTable(msg)) do print(line) end +versionmsg = [[ +texlogsieve 1.3.0 +Copyright (C) 2021, 2022 Nelson Lago <lago@ime.usp.br> +License GPLv3+: GNU GPL version 3 or later <https://gnu.org/licenses/gpl.html>. +This is free software: you are free to change and redistribute it. +There is NO WARRANTY, to the extent permitted by law.]] + +function processCommandLine(args) + HEARTBEAT = true + PAGE_DELAY = true + ONLY_SUMMARY = false + SHOW_SUMMARY = true + SHOW_SHIPOUTS = false + RAW = false + SILENCE_REPETITIONS = true + MINLEVEL = WARNING + BE_REDUNDANT = false + FILE_BANNER = true + DETAILED_UNDEROVER_SUMMARY = true + DETAILED_REFERENCE_SUMMARY = true + DETAILED_CITATION_SUMMARY = true + + COLOR = false + + SILENCE_STRINGS = {} + SILENCE_PKGS = {} -- just the package names + SEMISILENCE_FILES = {} -- filenames (without leading path), file globs work + SILENCE_FILES_RECURSIVE = {} -- same + + -- The user may redefine the severity level of some messages. + FORCED_DEBUG = {} + FORCED_INFO = {} + FORCED_WARNING = {} + FORCED_CRITICAL = {} + + -- "-l level -c configFile" + local optionsWithArgs = "lc" + local vars = simpleGetopt(args, optionsWithArgs) + + --help + -- "-h" + if vars.help or vars.h then + for _, line in ipairs(linesToTable(helpmsg)) do print(line) end os.exit(0) end --version if vars.version then - print("texlogsieve 1.2.0") - print("Copyright (C) 2021, 2022 Nelson Lago <lago@ime.usp.br>") - print("License GPLv3+: GNU GPL version 3 or later " - .. "<https://gnu.org/licenses/gpl.html>.") - print("This is free software: you are free to change " - .. "and redistribute it.") - print("There is NO WARRANTY, to the extent permitted by law.") + for _, line in ipairs(linesToTable(versionmsg)) do print(line) end os.exit(0) end @@ -1029,6 +1038,21 @@ Options: local filename = kpse.find_file('texlogsieverc') if filename ~= nil then table.insert(configFileNames, 1, filename) end + if os.type == "unix" then + filename = kpse.find_file(os.getenv("HOME") .. "/.texlogsieverc") + else + -- https://docs.microsoft.com/en-us/windows/deployment/usmt/usmt-recognized-environment-variables + -- %LOCALAPPDATA% corresponds to C:\Users\<username>\AppData\Local . + filename = kpse.find_file(os.getenv("%LOCALAPPDATA%") .. "/texlogsieverc") + if filename == nil then + -- %APPDATA% is "C:\Users\<username>\AppData\Roaming" or + -- "C:\Documents and Settings\<username>\Application Data" + filename = kpse.find_file(os.getenv("%APPDATA%") .. "/texlogsieverc") + end + end + + if filename ~= nil then table.insert(configFileNames, 1, filename) end + for _, filename in ipairs(configFileNames) do local configFile = assert(io.open(filename, "r")) vars = processConfigFile(configFile, vars) @@ -1353,6 +1377,39 @@ Options: vars['set-to-level-critical'] = nil + --verbose + -- "-v" + if vars['verbose'] or vars.v then + local msg = "" + + for _, name in ipairs(configFileNames) do msg = msg .. name .. ", " end + + if msg == "" then + print("texlogsieve: no config files, using defaults") + else + msg = string.sub(msg, 1, -3) + print("texlogsieve: using config files: " .. msg) + end + + msg = "texlogsieve: minlevel is " + if MINLEVEL == 0 then msg = msg .. 'DEBUG' + elseif MINLEVEL == 1 then msg = msg .. 'INFO' + elseif MINLEVEL == 2 then msg = msg .. 'WARNING' + elseif MINLEVEL == 3 then msg = msg .. 'CRITICAL' + else msg = msg .. 'UNKNOWN' + end + + print(msg) + + if RAW then + print("texlogsieve: using raw (unwrap-only) mode") + end + end + + vars['verbose'] = nil + vars.v = nil + + local unknown_options = false for k, v in pairs(vars) do print(' texlogsieve: unknown option "' .. k .. '"') @@ -1581,13 +1638,13 @@ function finishProcessingMessages() end function showFileBanner(msg) + if msg.filename == "DUMMY" then PARSE_ERROR = true end + if not FILE_BANNER then return end if msg.filename ~= nil and msg.filename ~= "" and msg.filename ~= lastFileBanner - -- TODO: "DUMMY" should never happen, but - -- what should we do if it does? then lastFileBanner = msg.filename local txt = "From file " .. msg.filename .. ":" @@ -1674,7 +1731,7 @@ end function showSummary() local somethingInSummary = false - if SHOULD_RERUN_LATEX or ERRORS_DETECTED then + if SHOULD_RERUN_LATEX or ERRORS_DETECTED or PARSE_ERROR then somethingInSummary = true else for _, summary in ipairs(summaries) do @@ -1716,6 +1773,15 @@ function showSummary() print() end + if PARSE_ERROR then + local txt = "** texlogsieve got confused during log processing **" .. + "\n" .. " messages may be missing or filenames may be" .. + "\n" .. " incorrect, check the LaTeX logfile directly" + if COLOR then txt = red(txt) end + print(txt) + print() + end + if ERRORS_DETECTED then local txt = "** There were errors during processing! Generated PDF is probably defective **" if COLOR then txt = red(txt) end @@ -2169,8 +2235,10 @@ function fpHandler:process() else -- This should never happen, but if it does -- we will probably end up in an endless loop - io.stderr:write(" texlogsieve: parsing error in " - .. "fpHandler:process()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum .. " (fpHandler:process)\n") + + PARSE_ERROR = true dispatch(self.message) self.message = nil @@ -2199,8 +2267,10 @@ function fpHandler:processClose(last) Lines:handledChars(last) if self.stack:pop() == nil then - io.stderr:write(" texlogsieve: parsing error in " - .. "fpHandler:processClose()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum .. " (fpHandler:processClose)\n") + + PARSE_ERROR = true end if self.stack:empty() then @@ -2276,8 +2346,11 @@ function underOverFullBoxHandler:handleFirstLine() end if last == nil then - io.stderr:write(" texlogsieve: parsing error in " - .. "underOverFullBoxHandler:handleFirstLine()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (underOverFullBoxHandler:handleFirstLine)\n") + + PARSE_ERROR = true self.doit = self.handleFirstLine dispatch(self.message) @@ -2439,8 +2512,11 @@ function stringsHandler:handleLines() for _, val in ipairs(tmp) do table.insert(self.captures, val) end if last == nil then - io.stderr:write(" texlogsieve: parsing error in " - .. "stringsHandler:handleLines()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (stringsHandler:handleLines)\n") + + PARSE_ERROR = true dispatch(self.message) self.message = nil @@ -3570,9 +3646,11 @@ function openParensHandler:doit() flushUnrecognizedMessages() local last = unwrapUntilStringMatches(data.filename) if last == nil then - io.stderr:write(" texlogsieve: parsing error in " - .. "openParensHandler:doit()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (openParensHandler:doit)\n") + PARSE_ERROR = true else Lines:handledChars(last) end @@ -3772,9 +3850,11 @@ function openSquareBracketHandler:doit() flushUnrecognizedMessages() local last = unwrapUntilStringMatches(data.latexPage) if last == nil then - io.stderr:write(" texlogsieve: parsing error in " - .. "openSquareBracketHandler:doit()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (openSquareBracketHandler:doit)\n") + PARSE_ERROR = true else Lines:handledChars(last) end @@ -3993,9 +4073,11 @@ function utf8FontMapHandler:handleSecondLine() -- "processing UTF-8 mapping" - this should never happen dispatch(self.message) self.message = nil - io.stderr:write(" texlogsieve: parsing error in " - .. "utf8FontMapHandler:handleSecondLine()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (utf8FontMapHandler:handleSecondLine)\n") + PARSE_ERROR = true Lines:handledChars() self.doit = self.handleFirstLine return true @@ -4025,9 +4107,11 @@ function utf8FontMapHandler:handleOtherLines() dispatch(self.message) self.message = nil flushUnrecognizedMessages() - io.stderr:write(" texlogsieve: parsing error in " - .. "utf8FontMapHandler:handleOtherLines()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (utf8FontMapHandler:handleOtherLines)\n") + PARSE_ERROR = true self.numTries = 0 self.foundOtherLines = false self.doit = self.handleFirstLine @@ -4972,8 +5056,8 @@ function SummaryPrototype:pageAndFileList(messages) if files[msg.filename] == nil then files[msg.filename] = {} end - if msg.linenum ~= "" then - table.insert(files[msg.filename], msg.linenum) + if tonumber(msg.linenum) then + table.insert(files[msg.filename], tonumber(msg.linenum)) end end end @@ -5147,22 +5231,6 @@ end unusedLabelsSummary = citationsSummary:new() unusedLabelsSummary.header = 'Unused labels:' -function unusedLabelsSummary:processSingleMessageList(messages) - local text = "" - local pages, files = self:pageAndFileList(messages) - local key = messages[1].key - if key == "" then key = '???' end - - if self:detailed() then - if COLOR then key = red(key) end - text = key .. ' in ' .. pages .. " (" .. files .. ")" - else - text = key - end - - return text -end - -- This is a little different from the others; we do not want to -- treat different messages differently, only report that there were @@ -5371,6 +5439,66 @@ function Stack:empty() end +--[[ ##### QUEUE ##### ]]-- +-- Adapted from https://www.lua.org/pil/11.4.html (in 2022) +-- We use this for the input line counter + +Queue = {} + +function Queue:new() + local o = {} + setmetatable(o, self) + self.__index = self + o.first = 0 + o.last = -1 + return o +end + +function Queue:pushleft(val) + self.first = self.first -1 + self[self.first] = val +end + +function Queue:pushright(val) + self.last = self.last +1 + self[self.last] = val +end + +function Queue:popleft() + if self.first > self.last then return nil end + local val = self[self.first] + self[self.first] = nil + self.first = self.first +1 + return val +end + +function Queue:popright() + if self.first > self.last then return nil end + local val = self[self.last] + self[self.last] = nil + self.last = self.last -1 + return val +end + +function Queue:peekleft() + if self.first > self.last then return nil end + return self[self.first] +end + +function Queue:peekright() + if self.first > self.last then return nil end + return self[self.last] +end + +function Queue:size() + return self.last - self.first +1 +end + +function Queue:empty() + return self.first > self.last +end + + --[[ ##### GLOBTOPATTERN ##### ]]-- -- convert a file glob to a lua pattern @@ -5644,12 +5772,20 @@ original length was max_print_line characters). Lines = {} Lines.wrapped = {} -- memoization +Lines.linenum = 0 +Lines.blankLines = Queue:new() function Lines:gotoNextLine() self.current = table.remove(self, 1) self.currentWrapped = table.remove(self.wrapped, 1) self.atBeginningOfLine = true + self.linenum = self.linenum +1 + -- blank lines have to be counted too + if not self.blankLines:empty() then + self.linenum = self.linenum + self.blankLines:popleft() + end + -- When unwrapping lines, we need to check whether a line is of -- the "right" size. However, we modify the content of currentLine -- during processing, so we capture its initial length here. See @@ -5691,8 +5827,23 @@ function Lines:len(n) end function Lines:append(x) - table.insert(self, x) - table.insert(self.wrapped, "unknown") -- cannot use "nil" + -- We *need* to remove blank lines here because sometimes a wrapped + -- line is followed by a blank line, which messes our detection of + -- wrapped lines. However, the line we skip here is not the line we + -- are processing right now; we will encounter it in the future. So, + -- to keep line numbers right, we need to adjust the count later too. + if x == "" then + if not self.blankLines:empty() then + self.blankLines:pushright(self.blankLines:popright() +1) + else + self.blankLines:pushright(1) + end + else + self.blankLines:pushright(0) + + table.insert(self, x) + table.insert(self.wrapped, "unknown") -- cannot use "nil" + end end function Lines:get(n) @@ -5847,9 +5998,11 @@ function unwrapUntilPatternMatches(pat) if Lines:seemsWrapped() then Lines:unwrapOneLine() else - io.stderr:write(" texlogsieve: parsing error in " - .. "unwrapUntilPatternMatches()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum + .. " (unwrapUntilPatternMatches)\n") + PARSE_ERROR = true break end end @@ -6008,9 +6161,10 @@ function guessQuotedFilename(line, position) -- no closing quote or the line is too short; can we unwrap this line? if not Lines:seemsWrapped(position) then - io.stderr:write(" texlogsieve: parsing error in " - .. "guessQuotedFilename()\n") + io.stderr:write(" texlogsieve: parsing error near input line " + .. Lines.linenum .. " (guessQuotedFilename)\n") + PARSE_ERROR = true return true, nil end |