groff-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[groff] 08/08: Implement PDF bookmark support for man pages.


From: G. Branden Robinson
Subject: [groff] 08/08: Implement PDF bookmark support for man pages.
Date: Thu, 27 Jan 2022 11:05:54 -0500 (EST)

gbranden pushed a commit to branch master
in repository groff.

commit 98112bfecad04b5568755cc531cc86d0b4553cf5
Author: G. Branden Robinson <g.branden.robinson@gmail.com>
AuthorDate: Fri Jan 28 02:33:22 2022 +1100

    Implement PDF bookmark support for man pages.
    
    Limitation: A (sub)section can only be bookmarked if it is specified in
    the arguments to the `SH` or `SS` requests, not on the next line in an
    input trap.  Thanks to Deri James for providing the fundamentals (blame
    me for any weird bits).
    
    * tmac/an.tmac (an-prepare-page-title): Define a new string,
      `an*page-ref-string`, which is the man page's own reference (such as
      "groff(1)") without any abbreviation, ellipsis, or font selection or
      italic correction escape sequences.
    
      (SS): Define a new string, `an*subsection-heading`, storing the macro
      arguments (if any).  These could contain font selection escape
      sequences, for instance, a fact that becomes important later.
    
      (initialization):
      - Recognize `BM` register to enable PDF bookmarks (only on the 'pdf'
        output device); defaults on.  Recognize `BN` register to set a base
        level/depth for the bookmarks; this is to ease embedding of man
        pages in other PDF documents that already use bookmarks.  The
        default is 0.  The registers are not yet documented.
      - If the output device is 'pdf' and bookmarks are enabled, set
        `PDFOUTLINE.FOLDLEVEL` and `PDFHREF.VIEW.LEADING` registers
        (recognized by 'pdf.tmac').  Append to `TH`, `SH`, `SS` to get the
        `an*page-ref-string`, `an-section-heading`, and
        `an*subsection-heading` bookmarks in the document at the applicable
        levels.
    
    * tmac/mdoc/doc-common: Add straw-man implementation--it doesn't support
      the `BM` and `BN` configuration parameters yet.  (This is enough to
      get the groff_mdoc(7) page to correctly appear in the new
      'groff-man-pages.pdf' document.)
    
      (Dt, Sh, Ss): If the output device is 'pdf', place bookmarks in the
      document at levels 1, 2, and 3.
---
 ChangeLog            | 37 +++++++++++++++++++++++++++++++++++++
 tmac/an.tmac         | 43 +++++++++++++++++++++++++++++++++++++++++--
 tmac/mdoc/doc-common | 14 ++++++++++++++
 3 files changed, 92 insertions(+), 2 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index efa2a0fb..c0d91afa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,40 @@
+2022-01-27  G. Branden Robinson <g.branden.robinson@gmail.com>
+
+       Implement PDF bookmark support for man pages.  Limitation: A
+       {sub}section can only be bookmarked if it is specified in the
+       arguments to the `SH` or `SS` requests, not on the next line in
+       an input trap.  Thanks to Deri James for providing the
+       fundamentals (blame me for any weird bits).
+
+       * tmac/an.tmac (an-prepare-page-title): Define a new string,
+       `an*page-ref-string`, which is the man page's own reference
+       {such as "groff(1)"} without any abbreviation, ellipsis, or font
+       selection or italic correction escape sequences.
+       (SS): Define a new string, `an*subsection-heading`, storing the
+       macro arguments (if any).  These could contain font selection
+       escape sequences, for instance, a fact that becomes important
+       later.
+       (initialization):
+       - Recognize `BM` register to enable PDF bookmarks (only on the
+         'pdf' output device); defaults on.  Recognize `BN` register to
+         set a base level/depth for the bookmarks; this is to ease
+         embedding of man pages in other PDF documents that already use
+         bookmarks.  The default is 0.  The registers are not yet
+         documented.
+       - If the output device is 'pdf' and bookmarks are enabled, set
+         `PDFOUTLINE.FOLDLEVEL` and `PDFHREF.VIEW.LEADING` registers
+         {recognized by 'pdf.tmac'}.  Append to `TH`, `SH`, `SS` to get
+         the `an*page-ref-string`, `an-section-heading`, and
+         `an*subsection-heading` bookmarks in the document at the
+         applicable levels.
+
+       * tmac/mdoc/doc-common: Add straw-man implementation--it doesn't
+       support the `BM` and `BN` configuration parameters yet.  (This
+       is enough to get the groff_mdoc(7) page to correctly appear in
+       the new 'groff-man-pages.pdf' document.)
+       (Dt, Sh, Ss): If the output device is 'pdf', place bookmarks in
+       the document at levels 1, 2, and 3.
+
 2022-01-26  Deri James  <deri@chuzzlewit.myzen.co.uk>
 
        [gropdf]: Allow multiline text in .pdfinfo
diff --git a/tmac/an.tmac b/tmac/an.tmac
index 4ec18386..c39276e5 100644
--- a/tmac/an.tmac
+++ b/tmac/an.tmac
@@ -360,9 +360,12 @@
 .\" string an-pageref defined for use in .PT and .an-footer.  Also
 .\" leaves an-title-abbv for possible use by .PT and .BT re-definers.
 .de an-prepare-page-title
-.  ds an-title-abbv \\*[an-title]\"
+.  ds an-title-abbv \\*[an-title]\" might not get abbreviated at all
 .  ds an-title-string \\*[an-title]\"
 .  ds an-ellipsis \|.\|.\|.\|\"
+.  \" an*page-ref-string is left unmodified for internal use, such as
+.  \" PDF bookmarks.
+.  ds an*page-ref-string \\*[an-title](\\*[an-section])\"
 .  ds an-pageref \\*[an-title-abbv](\\*[an-section])\"
 .  nr an-header-width \\w'\\*[an-pageref]\\*[an-extra3]\\*[an-pageref]'
 .  while (\\n[an-header-width] >= \\n[.lt]) \{\
@@ -613,7 +616,10 @@
 .  ne (2v + 1u)
 .  ft \\*[HF]
 .  if \\n[an-remap-I-style-in-headings] .ftr I \\*[an-heading-family]BI
-.  if \\n[.$] \&\\$*
+.  if \\n[.$] \{\
+.    nop \&\\$*
+.    ds an*subsection-heading \\$*\"
+.  \}
 .  if \\n[an-remap-I-style-in-headings] .ftr I I
 ..
 .
@@ -1017,6 +1023,39 @@
 .\" Set each rendering parameter only if its -[dr] option or man.local
 .\" did not.
 .
+.\" Enable within-page navigation via bookmarks--only operational with
+.\" output device 'pdf', but could be extended to others contingent on
+.\" their supporting features.
+.if !r BM .nr BM 1
+.
+.\" base depth for bookmarks (for embedding man pages in other docs)
+.if !r BN .nr BN 0
+.
+.\" Make man pages navigable in PDF output.  Thanks to Deri James.
+.if '\*[.T]'pdf' \{\
+.  if \n[BM] \{\
+.    nr PDFOUTLINE.FOLDLEVEL 1
+.    nr PDFHREF.VIEW.LEADING 10p
+.    am1 TH
+.      nr an*bookmark-depth \n[BN]+1
+.      pdfbookmark \\n[an*bookmark-depth] \\*[an*page-ref-string]
+.      rr an*bookmark-depth
+.    .
+.
+.    am1 SH
+.      nr an*bookmark-depth \n[BN]+2
+.      pdfbookmark \\n[an*bookmark-depth] \\*[an-section-heading]
+.      rr an*bookmark-depth
+.    .
+.
+.    am1 SS
+.      nr an*bookmark-depth \n[BN]+3
+.      pdfbookmark \\n[an*bookmark-depth] \\*[an*subsection-heading]
+.      rr an*bookmark-depth
+.    .
+.  \}
+.\}
+.
 .\" continuous rendering (one long page)
 .if !r cR \{\
 .  ie n .nr cR 1
diff --git a/tmac/mdoc/doc-common b/tmac/mdoc/doc-common
index e9aa3d9c..08be3b09 100644
--- a/tmac/mdoc/doc-common
+++ b/tmac/mdoc/doc-common
@@ -392,6 +392,9 @@
 .
 .  if \n[nl] \
 .    bp
+.
+.  if '\*[.T]'pdf' \
+.    pdfbookmark 1 "\*[doc-document-title](\*[doc-section])"
 ..
 .ec
 .
@@ -1331,6 +1334,9 @@
 .      ne 3
 .    fi
 .
+.  if '\*[.T]'pdf' \
+.    pdfbookmark 2 "\*[doc-sec-head]"
+.
 .    if t \{\
 .      nr doc-reg-Sh \n[.ss]
 .      nr doc-reg-Sh1 \n[.sss]
@@ -1361,6 +1367,9 @@
 .\" NS Ss user macro (not callable)
 .\" NS   subsection
 .\" NS
+.\" NS modifies:
+.\" NS   doc-subsection-heading
+.\" NS
 .\" NS local variable:
 .\" NS   doc-reg-Ss
 .\" NS   doc-reg-Ss1
@@ -1397,11 +1406,16 @@
 .    ds doc-macro-name Ss
 .    doc-parse-args \$@
 .
+.    ds doc-subsection-heading \$*
+.
 .    sp
 .    if !\n[cR] \
 .      ne 3
 .    ti -.25i
 .
+.    if '\*[.T]'pdf' \
+.      pdfbookmark 3 "\*[doc-subsection-heading]"
+.
 .    nr doc-reg-Ss \n[.ss]
 .    nr doc-reg-Ss1 \n[.sss]
 .    ss (\n[.ss] * 5 / 4) (\n[.sss] * 5 / 4)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]