%%! TEX program = lualatex
\ProvidesFile{rescansync.tex} [2022/07/09 v0.0.0 ]
\documentclass{l3doc}
\EnableCrossrefs
\CodelineIndex
\RecordChanges
\fvset{gobble=0,tabsize=4,frame=single,numbers=left,numbersep=3pt}
\usepackage{hyperref}
\usepackage{csquotes}

%\MakeOuterQuote{"}
\begin{document}
\GetFileInfo{\jobname.tex}

\title{\textsf{rescansync} --- Re-scan tokens with synctex information
\thanks{This file describes version \fileversion, last revised \filedate.}
}
\author{user202729%
%\thanks{E-mail: (not set)}
}
\date{Released \filedate}

\maketitle

\begin{abstract}
Allow users to execute saved code to typeset text while preserving Sync\TeX\ information.
\end{abstract}

\section{Simple interface}

\DescribeEnv{rescansyncSaveenvPacked}
Saves the environment body into the specified macro after the environment name, with additional information required to execute it later.

The macro is stored in some internal format. If the user want to modify the content, use one of the advanced interface described below.

Requires the \pkg{saveenv} and \pkg{currfile} package to be loaded. If you want to save the environment body using some other package, use the advanced interface.

\begin{function}{\rescansyncPacked}
  \begin{syntax}
	  \tn{rescansyncPacked} \meta{macro}
  \end{syntax}
  Execute the stored content in \meta{macro}.

  The content must be stored with \env{rescansyncSaveenvPacked} environment or similar.
\end{function}

To give an usage example: the following code
\begin{verbatim}
% the following line will save the content "123 456"
% and some auxiliary information into the macro \mycontent.
\begin{rescansyncSaveenvPacked}{\mycontent}
123

456
\end{rescansyncSaveenvPacked}

% the following line will typeset 789 as usual.
789

% the following line will typeset "123 456".
\rescansyncPacked{\mycontent}
\end{verbatim}
will typeset \enquote{789 123 456} as 3 separate paragraphs, with Sync\TeX\ information preserved.

If the engine is not \LuaTeX, there will still be limited Sync\TeX\ information that points to a temporary file, but the line number is preserved.

\DescribeEnv{rescansyncSaveenvghostPacked}
The usage of this environment is similar to the \env{rescansyncSaveenvPacked} above, except that the content is still typeset with Sync\TeX\ information preserved while it's stored.

In the example above, if this environment is used instead
\begin{verbatim}
\begin{rescansyncSaveenvghostPacked}{\mycontent}
123

456
\end{rescansyncSaveenvghostPacked}

789

\rescansyncPacked{\mycontent}
\end{verbatim}
the content typeset will be \enquote{123 456 789 123 456}.

As with \env{saveenvghost} environment (read \pkg{saveenv} package documentation for more details), the Sync\TeX\ information of the first section is guaranteed to be preserved, but there might be some performance hit.

\section{Advanced interface}

\begin{function}{\rescansync:nn}
  \begin{syntax}
	  \cs{rescansync:nn} \Arg{content} \Arg{line offset}
  \end{syntax}
  Execute (rescan) the \Arg{content}. Requires \pkg{currfile}.

  Details: \Arg{content} will be detokenized, and characters with char code 10 will be interpreted as a line break
  (the behavior is inherited from |\iow_now:Nn| function. As a consequence, it's not allowed to write literal character with char code 10 to the file;
  however this is not very useful regardless because on some operating systems this is equivalent to a real newline)

  \Arg{line offset} is some non-negative number. If it's 0 then the first line of \Arg{content} corresponds to the first line in the target file.

  Remark: If \pkg{newverbs}, \pkg{xparse} or \pkg{filecontentsdef} is used to collect multiline verbatim environment,
  they have the line separation characters separated by character with char code 13 by default, you need to
  manually replace them.

  Even though the Sync\TeX\ information points to the correct file, if there's some error the temporary file name (which has the form
  \texttt{RS\meta{number}-\meta{file name}} will be shown.

  Engines other than \LuaTeX\ has the limitations described above.
\end{function}

\begin{function}{\rescansync:nnn}
  \begin{syntax}
	  \cs{rescansync:nnn} \Arg{content} \Arg{line offset} \Arg{file name}
  \end{syntax}

  Similar to above, but use \Arg{file name} as the temporary file name. (only important in error messages, the Sync\TeX\ information
  points to the file that the content is scanned.)
\end{function}

\begin{function}{\rescansync:nnnn}
  \begin{syntax}
	  \cs{rescansync:nnnn} \Arg{content} \Arg{line offset} \Arg{file name} \Arg{Sync\TeX\ tag}
  \end{syntax}

  Similar to above, but you're allowed to specify the Sync\TeX\ tag.

  More details: each file ever read has an associated Sync\TeX\ tag value, which is a number. The Sync\TeX\ information will point to that file.

  On engines other than \LuaTeX, this feature is not supported and the function returns empty.
\end{function}

\begin{function}[EXP]{\rescansync_gettag:}
  \begin{syntax}
	  \cs{rescansync_gettag:}
  \end{syntax}

  Function that fully expands to some token list that represents the Sync\TeX\ tag that corresponds to some file.

  Note that if a file is |\input| more than once (or if |\file_get:nnN| \pkg{expl3} function is used on that file, which internally uses the \TeX\ |\input| primitive),
  the tag value will be different and forward search may fail to work.
\end{function}

As a full example, assume there's a file named \file{a.tex}:
\begin{verbatim}
\tl_set:Nx \mytag {\rescansync_gettag:}
\end{verbatim}
After it's executed, a file \file{b.tex} executes:
\begin{verbatim}
\rescansync:nnnV {abcdef} {3} {rescanned-a} \mytag
\end{verbatim}
then the text |abcdef| will be typesetted, the Sync\TeX\ information points to line $1+3=4$ in the file \file{a.tex}
(as the code |abcdef| is on the first line of the \Arg{content}, and the line offset is 3).

If there's any error while typesetting |abcdef|, the error file name will be reported as for example, \file{RS1-rescanned-a.tex} (the number |1| might vary) instead of \file{a.tex}.

\StopEventually{%
  \PrintChanges
  \PrintIndex
}
\Finale
\end{document}


