The Texinfo language could have been seen to be overly verbose in
several ways.

One of those ways was the required inclusion of @menu blocks in nodes
to reference subsidiary nodes.  Now that texi2any can generate these
automatically, they can be omitted from Texinfo sources, saving users
the burden of keeping them up-to-date.  (Well, it wasn't that recent:
Texinfo 6.1 was released over 10 years ago.  However, the @nodedescription
commmand in support of this feature only came out in 2023.)

Although most Texinfo documents still use @menu, the automatic generation
of menus for Info output has probably made Texinfo more accessible to new
users, and eased maintenance in a few places.

Along with @menu, the other main defining aspect, in my opinion, of the
clunk of the language is the frequent duplication of a node name in a
sectioning command.  For example:

    @node Headers and Footers
    @subsection Headers and Footers

This is not a new complaint.  I don't have an exact reference to hand
and the history may be somewhat murky, but I remember from looking at
old Texinfo releases that this may have been part of the motivation
for the introduction of the "@macro" command to makeinfo, circa 1994,
by Brian Fox.  Later releases had a file "makeinfo/macro.texi", showing
an example of how macros could be used to avoid this duplication.  (See
Annex A, below.)

Texinfo 5.0, released in 2013, introduced "tree transformations", among
which was an option to add nodes automatically.  From the Texinfo manual:

    ‘TREE_TRANSFORMATIONS’
         The associated value is a comma separated list of transformations
         that can be applied to the Texinfo tree prior to outputting the
         result.  If more than one is specified, the ordering is irrelevant;
         each is always applied at the necessary point during processing.
    
         ...
    
         The following transformations are currently supported (many are
         used in the ‘pod2texi’ utility distributed with Texinfo; *note
         Invoking pod2texi::):
    
         ...
    
         ‘insert_nodes_for_sectioning_commands’
              Insert nodes for sectioning commands lacking a corresponding
              node.


We have discussed this occasionally but never really came up with a proposal
for eliminating this duplication.  (I am sure there has been mail on it
but can't easily find it now.)

A major problem (as noted by Patrice in one of the emails I couldn't find)
is that it is not incorrect in the Texinfo language to have two sectioning
commands using the same title: for example, "@section Usage" could appear
as a section in two different chapters.

I've come back to this issue, and have an idea for how the need for a
@node line could be avoided in many cases.

My idea is that sectioning commands should create a so-called "shadow target"
(that's my working name, although there may be a better name):

  * If a section name appears once, and there is no @node (or @anchor
    or @namedanchor) using that name, then cross references to that
    section name go to that section.
  
  * If a section name is used twice or more, then the shadow targets
    created by those sections are disabled.  This prevents any ambiguity
    about which section a cross reference should go to.

  * If @node (or @anchor etc.) is used with the same name as a sectioning
    command, the @node (etc.) takes priority.

I believe this approach would be backwards-compatible with existing
documents.

I have implemented this in texinfo.tex; patch below in Annex D.  It will
likely need more testing and refinement.

In my current implementation, shadow targets are only created for sectioning
commands without an associated @node line.

The patch works by outputting data for the "shadow targets" to the .aux
file with @xrshad rather than @xrdef.  @xrshad is defined when reading
in .aux file such that if the same shadow information is given more than
once, it is disabled (bullet point two above).  Then when retrieving
xref target data, the shadow information is checked if a real target
(with @node etc.) was not defined.

Here's a sample input file demonstraing these points:

  \input texinfo
  
  @xref{two}. --- fails
  
  @chapter foo
  
  Aaaaaaaaaa.  @xref{bar}.
  
  @chapter bar
  
  Bbbbbbbbbbb.  @xref{foo}. -- goes to baz chapter.
  
  @section two
  
  CCCCCCC.
  
  @xref{baz}. --- fails
  
  @node foo
  @chapter baz
  
  LLLLLLLLLLL.
  
  @section two
  
  DDDDDDDDD.
  
  
  @bye


The cross reference to the bare "bar" chapter succeeds.  The
cross reference to "foo" goes to the @node, not the @chapter.
The cross reference to "two" fails because there are two @section's
titled "two".  Finally, the reference to "baz" fails because the
"baz" chapter is associated with a node, so no shadow target was
defined therefor.

Likely if this was implemented in texi2any, it could give better
diagnostics as to why cross references failed.

Hopefully this would be a welcomed modification to the language.  Any
comments?

(We could also consider allowing automatic anchors to index entries.
(I did find an email about this - Robert Weiner, 2016-07-01 "Is it possible
to make a Texinfo cross-reference to an index item?"  Quoted below in
Annex B.)  This should probably be enabled explicitly with an option, otherwise
too many targets would be created.)

https://lists.gnu.org/archive/html/help-texinfo/2016-07/msg00000.html

%

Annex A

@c Define a macro which is used to define other macros.  This one makes
@c a macro which creates a node and gives it a sectioning command.  Note
@c that the created macro uses the original definition within the
@c expansion text.  This takes advantage of the non-recursion feature of
@c macro execution.
@macro node_define{orig-name}
@macro \orig-name\{title}
@node \title\
@\orig-name\ \title\
@end macro
@end macro

@c Now actually define a new set of sectioning commands.
@node_define {chapter}
@node_define {section}
@node_define {subsection}
@end ifinfo

@chapter The Macro Facility

This chapter describes the new macro facility.

%

Annex B

> Say I have a 10 line table and I make an index entry for each line in the 
> table.
> Then elsewhere in the manual, I want to provide a cross-reference to
> an item in the table (not just the section that the item is in)?  Is
> this possible?  If not, could it be added without too much work?
> We already have the index entries that provide hyperlinks to their
> associated items, so what I want is an indirect reference that finds
> the index entry and goes to its item.
> 
> Thanks,
> 
> Bob

https://lists.gnu.org/archive/html/help-texinfo/2016-07/msg00000.html

%

Annex D

diff --git a/doc/texinfo.tex b/doc/texinfo.tex
index 528d53be6c..869dea384d 100644
--- a/doc/texinfo.tex
+++ b/doc/texinfo.tex
@@ -9162,7 +9162,9 @@ might help (with 'rm \jobname.?? \jobname.??s')%
 % type (Ynumbered, Yappendix, Ynothing).  #2 is the section title.
 %
 \def\donoderef#1#2{%
-  \ifx\lastnode\empty\else
+  \ifx\lastnode\empty
+    \setrefshadow{#1}{#2}%
+  \else
     \setref{\lastnode}{#1}{#2}%
     \global\let\lastnode=\empty
     \setnodeseenonce
@@ -9225,6 +9227,39 @@ might help (with 'rm \jobname.?? \jobname.??s')%
   \fi
 }
 
+% similar to \setref
+\def\setrefshadow#1#2{%
+  % FIXME may have duplicate target names, resulting in e.g.:
+  % pdfTeX warning (ext4): destination with the same identifier
+  % (name{XXSHADOW-bar} ) has been already used, duplicate ignored
+  \pdfmkdest{XXSHADOW-#2}%
+  \iflinks
+    {%
+      \requireauxfile
+      \atdummies  % preserve commands, but don't expand them
+      \def\value##1{##1}%
+      \edef\writexrshad##1##2{%
+       \write\auxfile{@xrshad{#2-%
+         ##1}{##2}}%
+      }%
+      \edef\writexrdef##1##2{%
+       \write\auxfile{@xrdef{#2-%
+         ##1}{##2}}%
+      }%
+      \toks0 = {#2}%
+      %
+      % Write information about this target using @xrshad instead
+      % of @xrdef.  This avoids any possible confusion about whether
+      % values came from @node/@anchor or not, e.g. if \setref ran
+      % multiple times on the same page.
+      % 
+      \immediate \writexrshad{title}{\the\toks0 }%
+      \immediate \writexrshad{snt}{\csname #1\endcsname}%
+      \safewhatsit{\writexrshad{pg}{\folio}}%
+    }%
+  \fi
+}
+
 % @xrefautosectiontitle on|off says whether @section(ing) names are used
 % automatically in xrefs, if the third arg is not explicitly specified.
 % This was provided as a "secret" @set xref-automatic-section-title
@@ -9270,7 +9305,17 @@ might help (with 'rm \jobname.?? \jobname.??s')%
   \def\infofilename{\ignorespaces #4}%
   \setbox\infofilenamebox = \hbox{\infofilename\unskip}%
   %
-  \startxreflink{#1}{#4}%
+  \ifdim \wd\printedmanualbox = 0pt
+    \shadowactive{#1}\countA
+    \expandafter\ifnum\countA = 1
+      \startxreflink{XXSHADOW-#1}{}%
+    \else
+      \startxreflink{#1}{}%
+    \fi
+  \else
+    \startxreflink{#1}{#4}%
+  \fi
+  %
   \getrefx{#1-title}\Xthisreftitle
   %
   % Float references are printed completely differently: "Figure 1.2"
@@ -9536,29 +9581,62 @@ might help (with 'rm \jobname.?? \jobname.??s')%
   \fi
 }
 
+\def\xrdefctxt{%
+  % Context for expanding the node or anchor name to remove control sequences.
+  % \turnoffactive stops 8-bit characters being changed to commands
+  % like @'e.
+  \indexnofonts
+  \turnoffactive
+  \def\value##1{##1}%
+}
+
 % Set #2 to xref string #1
 \def\getrefx#1#2{%
   \requireauxfile
   {%
-    \indexnofonts
-    \turnoffactive
-    \def\value##1{##1}%
+    \xrdefctxt
     \expandafter\global\expandafter\let\expandafter#2\csname XR#1\endcsname
+    \ifx#2\relax
+      % try a shadow definition
+      \expandafter\global\expandafter\let\expandafter#2\csname SXR#1\endcsname
+      \ifx#2\empty
+        \let#2\relax
+      \fi
+    \fi
   }%
 }
 
+% Check if shadow definitions are active for target name #1
+\def\shadowactive#1#2{%
+  \requireauxfile
+  {%
+    \xrdefctxt
+    \expandafter\global\expandafter\let\expandafter\tmp\csname 
SXR#1-title\endcsname
+  }%
+  \ifx\tmp\relax
+    #2=0 % no definitions made
+  \else
+    \ifx\tmp\empty
+      #2=0 % shadow definitions were disabled
+    \else
+      \expandafter\let\expandafter\tmp\csname XR#1-title\endcsname
+      \ifx\tmp\relax
+        #2=1 % yes, shadow definitions are active
+      \else
+        #2=0 % no, a real definition was made.
+      \fi
+    \fi
+  \fi
+}%
+
 % This is the macro invoked by entries in the aux file.  Define a control 
 % sequence for a cross-reference target (we prepend XR to the control sequence 
 % name to avoid collisions).  The value is the page number.  If this is a 
float 
 % type, we have more work to do.
 %
 \def\xrdef#1#2{%
-  {% Expand the node or anchor name to remove control sequences.
-   % \turnoffactive stops 8-bit characters being changed to commands
-   % like @'e.  \refx does the same to retrieve the value in the definition.
-    \indexnofonts
-    \turnoffactive
-    \def\value##1{##1}%
+  {%
+    \xrdefctxt
     \xdef\safexrefname{#1}%
   }%
   %
@@ -9592,6 +9670,24 @@ might help (with 'rm \jobname.?? \jobname.??s')%
   \ignorespaces % ignore ends of line in aux file
 }
 
+% Used for "shadow" definitions
+\def\xrshad#1#2{%
+  {\xrdefctxt \xdef\safexrefname{#1}}%
+  \bgroup
+    \expandafter\ifx\csname XR\safexrefname\endcsname\relax
+      \expandafter\ifx\csname SXR\safexrefname\endcsname\relax
+        % safe to make shadow definition.
+        \expandafter\gdef\csname SXR\safexrefname\endcsname{#2}%
+      \else
+        % earlier SXR definition.  disable.
+        \expandafter\gdef\csname SXR\safexrefname\endcsname{}%
+      \fi
+    \else
+      % blocked by XR definition
+    \fi
+  \egroup
+}
+
 % If working on a large document in chapters, it is convenient to
 % be able to disable indexing, cross-referencing, and contents, for test runs.
 % This is done with @novalidate at the beginning of the file.


Reply via email to