texlive[63954] trunk: texlogsieve (21jul22)

commits+karl at tug.org commits+karl at tug.org
Thu Jul 21 22:15:17 CEST 2022


Revision: 63954
          http://tug.org/svn/texlive?view=revision&revision=63954
Author:   karl
Date:     2022-07-21 22:15:16 +0200 (Thu, 21 Jul 2022)
Log Message:
-----------
texlogsieve (21jul22)

Modified Paths:
--------------
    trunk/Build/source/texk/texlive/linked_scripts/texlive/fmtutil.pl
    trunk/Build/source/texk/texlive/linked_scripts/texlogsieve/texlogsieve
    trunk/Master/texmf-dist/doc/man/man1/texlogsieve.1
    trunk/Master/texmf-dist/doc/man/man1/texlogsieve.man1.pdf
    trunk/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.pdf
    trunk/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.tex
    trunk/Master/texmf-dist/scripts/texlogsieve/texlogsieve

Modified: trunk/Build/source/texk/texlive/linked_scripts/texlive/fmtutil.pl
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/texlive/fmtutil.pl	2022-07-21 20:14:53 UTC (rev 63953)
+++ trunk/Build/source/texk/texlive/linked_scripts/texlive/fmtutil.pl	2022-07-21 20:15:16 UTC (rev 63954)
@@ -1,5 +1,5 @@
 #!/usr/bin/env perl
-# $Id: fmtutil.pl 60154 2021-08-03 21:55:56Z karl $
+# $Id: fmtutil.pl 63934 2022-07-19 01:58:57Z preining $
 # fmtutil - utility to maintain format files.
 # (Maintained in TeX Live:Master/texmf-dist/scripts/texlive.)
 # 
@@ -24,11 +24,11 @@
   TeX::Update->import();
 }
 
-my $svnid = '$Id: fmtutil.pl 60154 2021-08-03 21:55:56Z karl $';
-my $lastchdate = '$Date: 2021-08-03 23:55:56 +0200 (Tue, 03 Aug 2021) $';
+my $svnid = '$Id: fmtutil.pl 63934 2022-07-19 01:58:57Z preining $';
+my $lastchdate = '$Date: 2022-07-19 03:58:57 +0200 (Tue, 19 Jul 2022) $';
 $lastchdate =~ s/^\$Date:\s*//;
 $lastchdate =~ s/ \(.*$//;
-my $svnrev = '$Revision: 60154 $';
+my $svnrev = '$Revision: 63934 $';
 $svnrev =~ s/^\$Revision:\s*//;
 $svnrev =~ s/\s*\$$//;
 my $version = "r$svnrev ($lastchdate)";
@@ -808,6 +808,13 @@
   if ($opts{"dry-run"}) {
     print_info("would copy log file to: $destdir/$logfile\n");
   } else {
+    # Add the actual invocation to the end of the log file
+    if (open(my $fd, ">>", $logfile)) {
+      print $fd "# actual command line used during this run\n# $cmdline\n";
+      close($fd);
+    } else {
+      print_deferred_error("cannot append cmdline to log file");
+    }
     # Here and in the following we use copy instead of move
     # to make sure that in SElinux enabled cases the rules of
     # the destination directory are applied.

Modified: trunk/Build/source/texk/texlive/linked_scripts/texlogsieve/texlogsieve
===================================================================
--- trunk/Build/source/texk/texlive/linked_scripts/texlogsieve/texlogsieve	2022-07-21 20:14:53 UTC (rev 63953)
+++ trunk/Build/source/texk/texlive/linked_scripts/texlogsieve/texlogsieve	2022-07-21 20:15:16 UTC (rev 63954)
@@ -784,6 +784,7 @@
   table.insert(beginningOfLineHandlers, citationHandler)
   table.insert(beginningOfLineHandlers, referenceHandler)
   table.insert(beginningOfLineHandlers, labelHandler)
+  table.insert(beginningOfLineHandlers, unusedLabelHandler)
   table.insert(beginningOfLineHandlers, genericLatexHandler)
   table.insert(beginningOfLineHandlers, latex23MessageHandler)
   table.insert(beginningOfLineHandlers, genericLatexVariantIHandler)
@@ -821,6 +822,7 @@
   table.insert(summaries, underOverSummary)
   table.insert(summaries, missingCharSummary)
   table.insert(summaries, repetitionsSummary)
+  table.insert(summaries, unusedLabelsSummary)
   table.insert(summaries, citationsSummary)
   table.insert(summaries, referencesSummary)
   table.insert(summaries, labelsSummary)
@@ -1002,7 +1004,7 @@
 
   --version
   if vars.version then
-      print("texlogsieve 1.1.3")
+      print("texlogsieve 1.2.0")
       print("Copyright (C) 2021, 2022 Nelson Lago <lago at ime.usp.br>")
       print("License GPLv3+: GNU GPL version 3 or later "
             .. "<https://gnu.org/licenses/gpl.html>.")
@@ -1443,6 +1445,7 @@
     "The morewrites package is unnecessary",
     'Unused \\captionsetup%b[]',
     "Unknown feature `' in font %b`'", -- empty feature, not a problem
+    "Package refcheck Warning: Unused label %b`'", -- we process these specially
   }
 
   DEFAULT_FORCED_WARNING = {}
@@ -2741,6 +2744,9 @@
   -- From libertinust1math.sty
   '^amsthm loaded',
   '^amsthm NOT loaded',
+
+  -- refcheck
+  '^options: showrefs, showcites, msgs, chckunlbld',
 }
 
 
@@ -2881,6 +2887,8 @@
    .. '%S+, %S+ Mbit/s\n'
    .. 'extracting files from ' .. filepat .. '%.%.%.\n'
    .. '======================================================================',
+  "^Label %b`' newly defined as it shall be overriden\n"
+   .. "although it is yet undefined",
 }
 
 
@@ -3304,6 +3312,7 @@
 -- citationHandler
 -- referenceHandler
 -- labelHandler
+-- unusedLabelHandler
 -- (from genericLatexHandler)
 --
 -- They differ from the prototype by the set of patterns to search for, by
@@ -3314,7 +3323,9 @@
 
 citationHandler.patterns = {
   "^(LaTeX)%s+(Warning): (Citation) ('.-') on page (.-) undefined",
+  "^(LaTeX)%s+(Warning): (Citation) (%b`') on page (.-) undefined",
   "^(LaTeX)%s+(Warning): (Citation) ('.-') undefined",
+  "^(LaTeX)%s+(Warning): (Citation) (%b`') undefined",
 }
 
 function citationHandler:unpackData(data)
@@ -3361,7 +3372,35 @@
   return labelMessage:new()
 end
 
+-- These messages are generated by the package refcheck
+unusedLabelHandler = genericLatexHandler:new()
 
+unusedLabelHandler.patterns = {
+  "^(Package)%s+(refcheck)%s+(Warning): Unused label (%b`')",
+}
+
+function unusedLabelHandler:unpackData(data)
+  local last = data[1]
+  local what = data[2]
+  local name = data[3]
+  local severity = data[4]
+  local key = string.sub(data[5], 2, -2) -- remove quotes
+
+  self.message.what = what
+  self.message.name = name
+  self.message.severity = self:parseSeverity(severity)
+  self.message.key = key
+  self:findPrefix(last, name, what)
+  self.message.prefix = self.prefix
+
+  self:unwrapLines()
+  self.message.content = Lines.current
+end
+
+function unusedLabelHandler:newMessage()
+  return unusedLabelMessage:new()
+end
+
 -------------------------------------------------------------------------------
 -- providesHandler
 -- (from genericLatexHandler)
@@ -4803,7 +4842,13 @@
   labelsSummary:add(self)
 end
 
+unusedLabelMessage = Message:new()
 
+function unusedLabelMessage:toSummary()
+  unusedLabelsSummary:add(self)
+end
+
+
 --[[ ##################################################################### ]]--
 --[[ ############################ SUMMARIES ############################## ]]--
 --[[ ##################################################################### ]]--
@@ -4849,7 +4894,7 @@
 end
 
 -- we use this for --no-ref-detail and --no-cite-detail
-function SummaryPrototype:showDetails()
+function SummaryPrototype:detailed()
   return true
 end
 
@@ -4863,7 +4908,7 @@
 
   if self.header ~= "" then
       if COLOR then self.header = green(self.header) end
-      if self:showDetails() then
+      if self:detailed() then
           self.header = self.header .. '\n'
       else
           self.header = self.header .. ' '
@@ -4884,8 +4929,8 @@
   for _, messagesSublist in pairsSortedByKeys(self.messages) do
       local tmp = self:processSingleMessageList(messagesSublist)
       if tmp ~= "" then
-          if self:showDetails() then
-              allText = allText .. '\n\n' .. tmp
+          if self:detailed() then
+              allText = allText .. '\n' .. tmp
           else
               allText = allText .. ", " .. tmp
           end
@@ -4892,8 +4937,10 @@
       end
   end
 
-  -- remove leading '\n\n' or ', '
-  return string.sub(allText, 3)
+  -- remove leading '\n' or ', '
+  local _, last = string.find(allText, '^[\n, ]+')
+  if last then allText = string.sub(allText, last +1) end
+  return allText
 end
 
 -- This is where we process each individual sublist, generating
@@ -4903,11 +4950,17 @@
   return ""
 end
 
--- This receives a list of (equal) messages and returns
--- the list of pages and files where they were found.
+-- This receives a list of (equal) messages and returns the list of pages
+-- and files where they were found. For messages that the program "sees"
+-- as equal even if they include different line numbers (such as undefined
+-- references), this also shows the line numbers grouped by input file.
+-- If there is a line number but not a file name (this should not really
+-- happen), the line number is *not* shown; not great, but fixing this is
+-- more trouble than it's worth.
 function SummaryPrototype:pageAndFileList(messages)
 
-    -- Build a Set with the page numbers to eliminate repetitions...
+    -- Build Sets with the page numbers and file names
+    -- to eliminate repetitions...
     local pages = {}
     local files = {}
     for _, msg in ipairs(messages) do
@@ -4914,12 +4967,18 @@
         if msg.physicalPage ~= nil then
             pages[msg.physicalPage] = true
         end
+
         if msg.filename ~= nil then
-            files[msg.filename] = true
+            if files[msg.filename] == nil then
+                files[msg.filename] = {}
+            end
+            if msg.linenum ~= "" then
+                table.insert(files[msg.filename], msg.linenum)
+            end
         end
     end
 
-    -- and convert it to a "normal" table so we can sort it
+    -- and convert them to "normal" tables so we can sort them
     local tmp = {}
     for page, _ in pairs(pages) do -- not ipairs!
         table.insert(tmp, page)
@@ -4928,14 +4987,34 @@
     table.sort(pages)
 
     tmp = {}
-    for file, _ in pairs(files) do
-        table.insert(tmp, file)
+    for filename, listOfLines in pairs(files) do
+        local text = filename
+        if next(listOfLines) ~= nil then -- check if the table is empty
+            -- same thing here for the list of lines: generate a Set to
+            -- eliminate duplicates, turn it into an array and sort it
+            local setOfLines = {}
+            for _, line in ipairs(listOfLines) do
+                setOfLines[line] = true
+            end
+
+            listOfLines = {}
+            for line, _ in pairs(setOfLines) do
+                table.insert(listOfLines, line)
+            end
+            table.sort(listOfLines)
+
+            local lines = listToCommaSeparatedString(listOfLines,
+                                                     "line", "lines")
+
+            text = text .. ": " .. lines
+        end
+        table.insert(tmp, text)
     end
     files = tmp
     table.sort(files)
 
-    pages = listToCommaSeparatedString(pages)
-    files = listToCommaSeparatedString(files)
+    pages = listToCommaSeparatedString(pages, "page", "pages")
+    files = listToCommaSeparatedString(files, "file", "files", ';')
 
     return pages, files
 end
@@ -4958,11 +5037,11 @@
 
       local where
       if pages ~= "" and files ~= "" then
-          where = 'in pages ' .. pages .. ' (files ' .. files .. ') - '
+          where = 'in ' .. pages .. ' (' .. files .. ') - '
       elseif pages == "" and files ~= "" then
-          where = 'in files ' .. files .. ' - '
+          where = 'in ' .. files .. ' - '
       elseif pages ~= "" and files == "" then
-          where = 'in pages ' .. pages .. ' - '
+          where = 'in ' .. pages .. ' - '
       end
 
       local content = messages[1]:toString()
@@ -4988,9 +5067,12 @@
   local char = messages[1].char
   local font = messages[1].font
 
-  text = 'char ' .. char .. ', font ' .. font .. '\n'
-         .. 'in pages ' .. pages .. " (files " .. files .. ")"
+  text = 'char ' .. char .. ', font ' .. font
 
+  if COLOR then text = red(text) end
+
+  text = text .. ' in ' .. pages .. " (" .. files .. ")"
+
   return text
 end
 
@@ -4999,7 +5081,7 @@
 citationsSummary.bypassMostFilters = true
 citationsSummary.header = 'Undefined citations:'
 
-function citationsSummary:showDetails()
+function citationsSummary:detailed()
   return DETAILED_CITATION_SUMMARY
 end
 
@@ -5034,9 +5116,9 @@
   local key = messages[1].key
   if key == "" then key = '???' end
 
-  if self:showDetails() then
-      text = key .. '\n'
-         .. 'in pages ' .. pages .. " (files " .. files .. ")"
+  if self:detailed() then
+      if COLOR then key = red(key) end
+      text = key .. ' in ' .. pages .. " (" .. files .. ")"
   else
       text = key
   end
@@ -5048,7 +5130,7 @@
 referencesSummary = citationsSummary:new()
 referencesSummary.header = 'Undefined references:'
 
-function referencesSummary:showDetails()
+function referencesSummary:detailed()
   return DETAILED_REFERENCE_SUMMARY
 end
 
@@ -5057,11 +5139,31 @@
 labelsSummary.header = 'Multiply defined labels:'
 
 -- LaTeX does not supply details for these
-function labelsSummary:showDetails()
+function labelsSummary:detailed()
   return false
 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
 -- under/overfull boxes in pages X, Y, and Z. So we store messages
@@ -5098,8 +5200,7 @@
   else
       output = "Under/overfull boxes"
       if COLOR then output = green(output) end
-      output = output .. " in pages "
-                      .. pages .. " (files " .. files .. ")"
+      output = output .. " in " .. pages .. " (" .. files .. ")"
 
   end
 
@@ -5194,16 +5295,23 @@
       return iter
     end
 
-function listToCommaSeparatedString(list)
-  local tmp = ""
-    for _, item in ipairs(list) do
-        tmp = tmp .. ", " .. item
-    end
+function listToCommaSeparatedString(list, singular, plural, sep)
+  sep = sep or ','
+  if #list == 0 then return end
 
-    local _, last = string.find(tmp, '^, ')
-    if last ~= nil then tmp = string.sub(tmp, last +1) end
+  local tmp
+  if #list == 1 then
+      tmp = singular .. " "
+  else
+      tmp = plural .. " "
+  end
 
-    return tmp
+  for _, item in ipairs(list) do
+      tmp = tmp .. item .. sep .. " "
+  end
+
+  tmp = string.sub(tmp, 1, -3) -- remove the final ", "
+  return tmp
 end
 
 function green(s)

Modified: trunk/Master/texmf-dist/doc/man/man1/texlogsieve.1
===================================================================
--- trunk/Master/texmf-dist/doc/man/man1/texlogsieve.1	2022-07-21 20:14:53 UTC (rev 63953)
+++ trunk/Master/texmf-dist/doc/man/man1/texlogsieve.1	2022-07-21 20:15:16 UTC (rev 63954)
@@ -1,4 +1,4 @@
-.TH TEXLOGSIEVE "1" "April 2022" "texlogsieve 1.1.3" "User Commands"
+.TH TEXLOGSIEVE "1" "July 2022" "texlogsieve 1.2.0" "User Commands"
 
 .SH NAME
 

Modified: trunk/Master/texmf-dist/doc/man/man1/texlogsieve.man1.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.tex
===================================================================
--- trunk/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.tex	2022-07-21 20:14:53 UTC (rev 63953)
+++ trunk/Master/texmf-dist/doc/support/texlogsieve/texlogsieve.tex	2022-07-21 20:15:16 UTC (rev 63954)
@@ -77,12 +77,19 @@
 \changes{1.1.2}{2022/03/14}{Fix bug unwrapping lines starting with ``]''}
 \changes{1.1.3}{2022/04/22}{Be more careful with continuation lines in error
                             msgs}
+\changes{1.2.0}{2022/07/21}{Fix bug with missing citations}
+\changes{1.2.0}{2022/07/21}{Colored keys with missing citations / chars}
+\changes{1.2.0}{2022/07/21}{Improved example latexmkrc in TIPS section}
+\changes{1.2.0}{2022/07/21}{Summary messages include line numbers}
+\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}
 
 \begin{document}
 
 \title{\textsf{texlogsieve}:\thanks{This document
-corresponds to \textsf{texlogsieve}~1.1.3,
-dated~2022-04-22.}\\[.3\baselineskip]
+corresponds to \textsf{texlogsieve}~1.2.0,
+dated~2022-07-21.}\\[.3\baselineskip]
 {\normalsize(yet another program to)\\[-.6\baselineskip]}
 {\large filter and summarize \LaTeX\ log files}
 }
@@ -115,7 +122,7 @@
 
 \end{abstract}
 
-\section{Introduction}
+\section*{Introduction}
 
 The \LaTeX\ log file is very verbose, which is useful when debugging but
 a hindrance during document preparation, as warnings such as ``missing
@@ -470,6 +477,7 @@
 $silence_logfile_warnings = 1;
 
 END {
+  local $?; # do not override previous exit status
   if (-s "$root_filename.blg"
               and open my $bibfile, '<', "$root_filename.blg") {
 

Modified: trunk/Master/texmf-dist/scripts/texlogsieve/texlogsieve
===================================================================
--- trunk/Master/texmf-dist/scripts/texlogsieve/texlogsieve	2022-07-21 20:14:53 UTC (rev 63953)
+++ trunk/Master/texmf-dist/scripts/texlogsieve/texlogsieve	2022-07-21 20:15:16 UTC (rev 63954)
@@ -784,6 +784,7 @@
   table.insert(beginningOfLineHandlers, citationHandler)
   table.insert(beginningOfLineHandlers, referenceHandler)
   table.insert(beginningOfLineHandlers, labelHandler)
+  table.insert(beginningOfLineHandlers, unusedLabelHandler)
   table.insert(beginningOfLineHandlers, genericLatexHandler)
   table.insert(beginningOfLineHandlers, latex23MessageHandler)
   table.insert(beginningOfLineHandlers, genericLatexVariantIHandler)
@@ -821,6 +822,7 @@
   table.insert(summaries, underOverSummary)
   table.insert(summaries, missingCharSummary)
   table.insert(summaries, repetitionsSummary)
+  table.insert(summaries, unusedLabelsSummary)
   table.insert(summaries, citationsSummary)
   table.insert(summaries, referencesSummary)
   table.insert(summaries, labelsSummary)
@@ -1002,7 +1004,7 @@
 
   --version
   if vars.version then
-      print("texlogsieve 1.1.3")
+      print("texlogsieve 1.2.0")
       print("Copyright (C) 2021, 2022 Nelson Lago <lago at ime.usp.br>")
       print("License GPLv3+: GNU GPL version 3 or later "
             .. "<https://gnu.org/licenses/gpl.html>.")
@@ -1443,6 +1445,7 @@
     "The morewrites package is unnecessary",
     'Unused \\captionsetup%b[]',
     "Unknown feature `' in font %b`'", -- empty feature, not a problem
+    "Package refcheck Warning: Unused label %b`'", -- we process these specially
   }
 
   DEFAULT_FORCED_WARNING = {}
@@ -2741,6 +2744,9 @@
   -- From libertinust1math.sty
   '^amsthm loaded',
   '^amsthm NOT loaded',
+
+  -- refcheck
+  '^options: showrefs, showcites, msgs, chckunlbld',
 }
 
 
@@ -2881,6 +2887,8 @@
    .. '%S+, %S+ Mbit/s\n'
    .. 'extracting files from ' .. filepat .. '%.%.%.\n'
    .. '======================================================================',
+  "^Label %b`' newly defined as it shall be overriden\n"
+   .. "although it is yet undefined",
 }
 
 
@@ -3304,6 +3312,7 @@
 -- citationHandler
 -- referenceHandler
 -- labelHandler
+-- unusedLabelHandler
 -- (from genericLatexHandler)
 --
 -- They differ from the prototype by the set of patterns to search for, by
@@ -3314,7 +3323,9 @@
 
 citationHandler.patterns = {
   "^(LaTeX)%s+(Warning): (Citation) ('.-') on page (.-) undefined",
+  "^(LaTeX)%s+(Warning): (Citation) (%b`') on page (.-) undefined",
   "^(LaTeX)%s+(Warning): (Citation) ('.-') undefined",
+  "^(LaTeX)%s+(Warning): (Citation) (%b`') undefined",
 }
 
 function citationHandler:unpackData(data)
@@ -3361,7 +3372,35 @@
   return labelMessage:new()
 end
 
+-- These messages are generated by the package refcheck
+unusedLabelHandler = genericLatexHandler:new()
 
+unusedLabelHandler.patterns = {
+  "^(Package)%s+(refcheck)%s+(Warning): Unused label (%b`')",
+}
+
+function unusedLabelHandler:unpackData(data)
+  local last = data[1]
+  local what = data[2]
+  local name = data[3]
+  local severity = data[4]
+  local key = string.sub(data[5], 2, -2) -- remove quotes
+
+  self.message.what = what
+  self.message.name = name
+  self.message.severity = self:parseSeverity(severity)
+  self.message.key = key
+  self:findPrefix(last, name, what)
+  self.message.prefix = self.prefix
+
+  self:unwrapLines()
+  self.message.content = Lines.current
+end
+
+function unusedLabelHandler:newMessage()
+  return unusedLabelMessage:new()
+end
+
 -------------------------------------------------------------------------------
 -- providesHandler
 -- (from genericLatexHandler)
@@ -4803,7 +4842,13 @@
   labelsSummary:add(self)
 end
 
+unusedLabelMessage = Message:new()
 
+function unusedLabelMessage:toSummary()
+  unusedLabelsSummary:add(self)
+end
+
+
 --[[ ##################################################################### ]]--
 --[[ ############################ SUMMARIES ############################## ]]--
 --[[ ##################################################################### ]]--
@@ -4849,7 +4894,7 @@
 end
 
 -- we use this for --no-ref-detail and --no-cite-detail
-function SummaryPrototype:showDetails()
+function SummaryPrototype:detailed()
   return true
 end
 
@@ -4863,7 +4908,7 @@
 
   if self.header ~= "" then
       if COLOR then self.header = green(self.header) end
-      if self:showDetails() then
+      if self:detailed() then
           self.header = self.header .. '\n'
       else
           self.header = self.header .. ' '
@@ -4884,8 +4929,8 @@
   for _, messagesSublist in pairsSortedByKeys(self.messages) do
       local tmp = self:processSingleMessageList(messagesSublist)
       if tmp ~= "" then
-          if self:showDetails() then
-              allText = allText .. '\n\n' .. tmp
+          if self:detailed() then
+              allText = allText .. '\n' .. tmp
           else
               allText = allText .. ", " .. tmp
           end
@@ -4892,8 +4937,10 @@
       end
   end
 
-  -- remove leading '\n\n' or ', '
-  return string.sub(allText, 3)
+  -- remove leading '\n' or ', '
+  local _, last = string.find(allText, '^[\n, ]+')
+  if last then allText = string.sub(allText, last +1) end
+  return allText
 end
 
 -- This is where we process each individual sublist, generating
@@ -4903,11 +4950,17 @@
   return ""
 end
 
--- This receives a list of (equal) messages and returns
--- the list of pages and files where they were found.
+-- This receives a list of (equal) messages and returns the list of pages
+-- and files where they were found. For messages that the program "sees"
+-- as equal even if they include different line numbers (such as undefined
+-- references), this also shows the line numbers grouped by input file.
+-- If there is a line number but not a file name (this should not really
+-- happen), the line number is *not* shown; not great, but fixing this is
+-- more trouble than it's worth.
 function SummaryPrototype:pageAndFileList(messages)
 
-    -- Build a Set with the page numbers to eliminate repetitions...
+    -- Build Sets with the page numbers and file names
+    -- to eliminate repetitions...
     local pages = {}
     local files = {}
     for _, msg in ipairs(messages) do
@@ -4914,12 +4967,18 @@
         if msg.physicalPage ~= nil then
             pages[msg.physicalPage] = true
         end
+
         if msg.filename ~= nil then
-            files[msg.filename] = true
+            if files[msg.filename] == nil then
+                files[msg.filename] = {}
+            end
+            if msg.linenum ~= "" then
+                table.insert(files[msg.filename], msg.linenum)
+            end
         end
     end
 
-    -- and convert it to a "normal" table so we can sort it
+    -- and convert them to "normal" tables so we can sort them
     local tmp = {}
     for page, _ in pairs(pages) do -- not ipairs!
         table.insert(tmp, page)
@@ -4928,14 +4987,34 @@
     table.sort(pages)
 
     tmp = {}
-    for file, _ in pairs(files) do
-        table.insert(tmp, file)
+    for filename, listOfLines in pairs(files) do
+        local text = filename
+        if next(listOfLines) ~= nil then -- check if the table is empty
+            -- same thing here for the list of lines: generate a Set to
+            -- eliminate duplicates, turn it into an array and sort it
+            local setOfLines = {}
+            for _, line in ipairs(listOfLines) do
+                setOfLines[line] = true
+            end
+
+            listOfLines = {}
+            for line, _ in pairs(setOfLines) do
+                table.insert(listOfLines, line)
+            end
+            table.sort(listOfLines)
+
+            local lines = listToCommaSeparatedString(listOfLines,
+                                                     "line", "lines")
+
+            text = text .. ": " .. lines
+        end
+        table.insert(tmp, text)
     end
     files = tmp
     table.sort(files)
 
-    pages = listToCommaSeparatedString(pages)
-    files = listToCommaSeparatedString(files)
+    pages = listToCommaSeparatedString(pages, "page", "pages")
+    files = listToCommaSeparatedString(files, "file", "files", ';')
 
     return pages, files
 end
@@ -4958,11 +5037,11 @@
 
       local where
       if pages ~= "" and files ~= "" then
-          where = 'in pages ' .. pages .. ' (files ' .. files .. ') - '
+          where = 'in ' .. pages .. ' (' .. files .. ') - '
       elseif pages == "" and files ~= "" then
-          where = 'in files ' .. files .. ' - '
+          where = 'in ' .. files .. ' - '
       elseif pages ~= "" and files == "" then
-          where = 'in pages ' .. pages .. ' - '
+          where = 'in ' .. pages .. ' - '
       end
 
       local content = messages[1]:toString()
@@ -4988,9 +5067,12 @@
   local char = messages[1].char
   local font = messages[1].font
 
-  text = 'char ' .. char .. ', font ' .. font .. '\n'
-         .. 'in pages ' .. pages .. " (files " .. files .. ")"
+  text = 'char ' .. char .. ', font ' .. font
 
+  if COLOR then text = red(text) end
+
+  text = text .. ' in ' .. pages .. " (" .. files .. ")"
+
   return text
 end
 
@@ -4999,7 +5081,7 @@
 citationsSummary.bypassMostFilters = true
 citationsSummary.header = 'Undefined citations:'
 
-function citationsSummary:showDetails()
+function citationsSummary:detailed()
   return DETAILED_CITATION_SUMMARY
 end
 
@@ -5034,9 +5116,9 @@
   local key = messages[1].key
   if key == "" then key = '???' end
 
-  if self:showDetails() then
-      text = key .. '\n'
-         .. 'in pages ' .. pages .. " (files " .. files .. ")"
+  if self:detailed() then
+      if COLOR then key = red(key) end
+      text = key .. ' in ' .. pages .. " (" .. files .. ")"
   else
       text = key
   end
@@ -5048,7 +5130,7 @@
 referencesSummary = citationsSummary:new()
 referencesSummary.header = 'Undefined references:'
 
-function referencesSummary:showDetails()
+function referencesSummary:detailed()
   return DETAILED_REFERENCE_SUMMARY
 end
 
@@ -5057,11 +5139,31 @@
 labelsSummary.header = 'Multiply defined labels:'
 
 -- LaTeX does not supply details for these
-function labelsSummary:showDetails()
+function labelsSummary:detailed()
   return false
 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
 -- under/overfull boxes in pages X, Y, and Z. So we store messages
@@ -5098,8 +5200,7 @@
   else
       output = "Under/overfull boxes"
       if COLOR then output = green(output) end
-      output = output .. " in pages "
-                      .. pages .. " (files " .. files .. ")"
+      output = output .. " in " .. pages .. " (" .. files .. ")"
 
   end
 
@@ -5194,16 +5295,23 @@
       return iter
     end
 
-function listToCommaSeparatedString(list)
-  local tmp = ""
-    for _, item in ipairs(list) do
-        tmp = tmp .. ", " .. item
-    end
+function listToCommaSeparatedString(list, singular, plural, sep)
+  sep = sep or ','
+  if #list == 0 then return end
 
-    local _, last = string.find(tmp, '^, ')
-    if last ~= nil then tmp = string.sub(tmp, last +1) end
+  local tmp
+  if #list == 1 then
+      tmp = singular .. " "
+  else
+      tmp = plural .. " "
+  end
 
-    return tmp
+  for _, item in ipairs(list) do
+      tmp = tmp .. item .. sep .. " "
+  end
+
+  tmp = string.sub(tmp, 1, -3) -- remove the final ", "
+  return tmp
 end
 
 function green(s)



More information about the tex-live-commits mailing list.