Notes were rendered as a bullet list, which beamer does not do. Reading
beamerbasenotes.sty: a plain \note appends its text to a running block with
no separator at all, and \note[item] accumulates separately into an
enumerate printed after that block.
Match both. talk-notes.sty takes \note<spec>[item]{text}, as beamer does,
and records which kind it is. The one deviation is a paragraph break
between plain notes instead of running them together, which is easier to
read on a page.
The notes half is laid out like beamer's too: a grey band across the head
carrying the section and the position in the talk, the current slide flush
into the outer corner, and the notes below. The heading is set in the
sans face against the roman body so it reads as apparatus rather than as
part of the notes.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
84 lines
3.1 KiB
TeX
84 lines
3.1 KiB
TeX
% talk-notes.sty -- capture speaker notes for assembly outside LaTeX.
|
|
%
|
|
% The ltx-talk class has no \note command (upstream issue #156 is open, and the
|
|
% maintainer has said notes are wanted but unimplemented). This package fills
|
|
% the gap without touching the slides themselves: \note{...} typesets nothing
|
|
% and instead records its text to \jobname.notes, which the mknotes program
|
|
% reads to build the presenter PDF.
|
|
%
|
|
% The awkward part of doing this outside LaTeX is that a frame does not
|
|
% correspond to a page: overlays expand one frame into several slides, and the
|
|
% source cannot predict how many. That is why the page records are written from
|
|
% the shipout hook, which is the first point at which the frame and slide
|
|
% identity of a page is actually known.
|
|
|
|
\NeedsTeXFormat{LaTeX2e}
|
|
\ProvidesPackage{talk-notes}[2026-08-14 v0.1 Capture speaker notes for ltx-talk]
|
|
|
|
\ExplSyntaxOn
|
|
|
|
\iow_new:N \g__talknotes_iow
|
|
\tl_new:N \g__talknotes_section_tl
|
|
\tl_new:N \g__talknotes_subsection_tl
|
|
|
|
\AddToHook { begindocument }
|
|
{ \iow_open:Nn \g__talknotes_iow { \c_sys_jobname_str .notes } }
|
|
% The stream is deliberately not closed by hand: LaTeX closes it at the end of
|
|
% the run, and closing it from the enddocument hook races the final shipout.
|
|
|
|
% Track the section and subsection so the notes page can show where we are.
|
|
% ltx-talk exposes the current title as \l__talk_section_tl; guard the lookup
|
|
% so that a class change does not turn this into an error.
|
|
\AddToHook { section/begin }
|
|
{
|
|
\cs_if_exist:NT \l__talk_section_tl
|
|
{
|
|
\tl_gset:NV \g__talknotes_section_tl \l__talk_section_tl
|
|
\tl_gclear:N \g__talknotes_subsection_tl
|
|
}
|
|
}
|
|
\AddToHook { subsection/begin }
|
|
{
|
|
\cs_if_exist:NT \l__talk_subsection_tl
|
|
{ \tl_gset:NV \g__talknotes_subsection_tl \l__talk_subsection_tl }
|
|
}
|
|
|
|
% One record per shipped page.
|
|
\AddToHook { shipout/before }
|
|
{
|
|
\iow_now:Nx \g__talknotes_iow
|
|
{
|
|
PAGE ~ \arabic { page } |
|
|
FRAME ~ \int_use:N \g__talk_frame_int |
|
|
SLIDE ~ \int_use:N \g__talk_slide_int
|
|
}
|
|
\iow_now:Nx \g__talknotes_iow
|
|
{ SECTION ~ \tl_to_str:N \g__talknotes_section_tl }
|
|
\iow_now:Nx \g__talknotes_iow
|
|
{ SUBSECTION ~ \tl_to_str:N \g__talknotes_subsection_tl }
|
|
}
|
|
|
|
% \note<overlay spec>[item]{text}
|
|
%
|
|
% Follows beamer's interface. A plain \note contributes running text; \note[item]
|
|
% contributes an entry to a numbered list printed after that text.
|
|
%
|
|
% The body is written out stringified, so LaTeX markup inside a note survives
|
|
% to be typeset again on the notes page. A note is recorded once per slide of
|
|
% its frame (the frame body is re-run for each), so mknotes deduplicates.
|
|
% Records are bracketed by ENDNOTE because a long note may be broken across
|
|
% output lines.
|
|
\NewDocumentCommand \note { d<> o +m }
|
|
{
|
|
\iow_now:Nx \g__talknotes_iow
|
|
{
|
|
NOTE ~ FRAME ~ \int_use:N \g__talk_frame_int |
|
|
SPEC ~ \IfNoValueTF {#1} { - } { \tl_to_str:n {#1} } |
|
|
KIND ~ \IfNoValueTF {#2} { text } { \tl_to_str:n {#2} }
|
|
}
|
|
\iow_now:Nx \g__talknotes_iow { TEXT ~ \tl_to_str:n {#3} }
|
|
\iow_now:Nn \g__talknotes_iow { ENDNOTE }
|
|
}
|
|
|
|
\ExplSyntaxOff
|