% File: rescansync.sty % Copyright 2022 user202729 % % This work may be distributed and/or modified under the conditions of the % LaTeX Project Public License (LPPL), either version 1.3c of this license or % (at your option) any later version. The latest version of this license is in % the file: % % http://www.latex-project.org/lppl.txt % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is user202729. \ProvidesExplPackage{rescansync}{2022/07/09}{0.0.0}{Re-scan tokens with synctex information} \cs_generate_variant:Nn \regex_replace_all:nnN {nxN} \cs_generate_variant:Nn \tl_replace_all:Nnn {Nxn} \msg_new:nnn {rescansync} {currfile-package-not-loaded} {currfile~package~is~needed~for~this~functionality} \msg_new:nnn {rescansync} {saveenv-package-not-loaded} {saveenv~package~is~needed~for~this~functionality} \makeatletter \sys_if_engine_luatex:TF { \let \_RS_optionaldirectlua \directlua \cs_new:Npn \rescansync_gettag: { \directlua{ tex.sprint(tex.get_synctex_tag()) } } } { \let \_RS_optionaldirectlua \@gobble \let \rescansync_gettag: \empty } %\let \rescansyncTMPfixsync \undefined \tl_gset:Nn \_RS_count {0} \edef \_RS_j_tl {\char_generate:nn {`\^^J} {12}} \iow_new:N \_RS_file % #1: the content (will be detokenized) % #2: the number (line offset) % #3: the file name % #4: the synctex tag (get from \rescansync_gettag:) % % content is an expl3 string with ^^J represent line break -- same format as expected by iow_now % % NOTE: because filecontentsdef make character >= 128 in pdftex active character and % they cannot be \write safely, we detokenize it then replace ^^M later. \cs_new_protected:Npn \rescansync:nnnn #1 #2 #3 #4 { \tl_gset:Nx \_RS_count {\int_eval:n {\_RS_count+1}} \tl_set:Nx \_RS_filename {RS\_RS_count-#3} \begingroup % will be closed by the active `~` later \iow_open:Nn \_RS_file {\_RS_filename} \iow_now:Nx \_RS_file { % print some initial padding newlines first \prg_replicate:nV {#2} \_RS_j_tl % prepend some content to the start of the line... \c_backslash_str a \c_backslash_str _RS_optionaldirectlua{tex.set_synctex_tag( #4 )} \c_tilde_str % this one works % note that the directlua must be directly inside the file, not indirectly invoked through some macro % print the content \detokenize{#1} } \iow_close:N \_RS_file \int_step_inline:nnn {33} {125} {\catcode ##1=11~} % set all to letter \catcode `\~ \active \catcode `\\ 0 \catcode `\{ 1 \catcode `\} 2~ % just so that the content '\_RS_optionaldirectlua{tex.set_synctex_tag( ... )}~' is interpreted correctly... \char_set_active_eq:NN \~ \endgroup \exp_args:NNNo \expandafter \_RS_skip_initial_endlinechars \@@input {\_RS_filename} } \cs_new_protected:Npn \rescansync:nnn #1 #2 #3 { \rescansync:nnnn {#1} {#2} {#3} {\rescansync_gettag:} % #4 will be expanded inside } \cs_new_protected:Npn \_RS_skip_initial_endlinechars #1 \a {} % #1: tokens generated by endlinechar \NewDocumentEnvironment {rescansyncSaveenvPacked} {m} { \edef \_RS_lineno {\the\inputlineno} \cs_if_free:NT \saveenv { \msg_error:nn {rescansync} {saveenv-package-not-loaded} } \cs_if_free:NT \currfilename { \msg_error:nn {rescansync} {currfile-package-not-loaded} } \saveenv \_RS_body } { \endsaveenv \global\edef #1 { {\_RS_body} {\_RS_lineno} {\currfilename} } %\pretty:V #1 } \NewDocumentEnvironment {rescansyncSaveenvghostPacked} {m} { \edef \_RS_lineno {\the\inputlineno} \cs_if_free:NT \saveenv { \msg_error:nn {rescansync} {saveenv-package-not-loaded} } \cs_if_free:NT \currfilename { \msg_error:nn {rescansync} {currfile-package-not-loaded} } \saveenvghost \_RS_body } { \endsaveenvghost \global\edef #1 { {\_RS_body} {\_RS_lineno} {\currfilename} } %\pretty:V #1 } \NewDocumentCommand \rescansyncPacked {m} { %\pretty:V {#1} \exp_last_unbraced:Nx \rescansync:nnn {#1} } \cs_generate_variant:Nn \iow_now:Nn {No} \cs_generate_variant:Nn \prg_replicate:nn {nV} % #1: the macro that contain the content, #2: the number (line offset) \cs_new_protected:Npn \rescansync:nn #1 #2 { \cs_if_free:NT \currfilename { \msg_error:nn {rescansync} {currfile-package-not-loaded} } \rescansync:nnn {#1} {#2} {\currfilename} }