% ---------------------------------------------------------------------------- % the XSIMVERB package % % write environments verbatim to files % % ---------------------------------------------------------------------------- % Clemens Niederberger % Web: https://github.com/cgnieder/xsim % E-Mail: clemens@cnltx.de % ---------------------------------------------------------------------------- % Copyright 2017--2022 Clemens Niederberger % % This work may be distributed and/or modified under the % conditions of the LaTeX Project Public License, either version 1.3c % of this license or (at your option) any later version. % The latest version of this license is in % http://www.latex-project.org/lppl.txt % and version 1.3c or later is part of all distributions of LaTeX % version 2008/05/04 or later. % % This work has the LPPL maintenance status `maintained'. % % The Current Maintainer of this work is Clemens Niederberger. % ---------------------------------------------------------------------------- % If you have any ideas, questions, suggestions or bugs to report, please % feel free to contact me. % ---------------------------------------------------------------------------- \RequirePackage {l3keys2e} \ExplSyntaxOn \tl_const:Nn \c_xsimverb_date_tl {2022/02/12} \tl_const:Nn \c_xsimverb_version_major_number_tl {0} \tl_const:Nn \c_xsimverb_version_minor_number_tl {4} \tl_const:Nn \c_xsimverb_version_subrelease_tl {} \tl_const:Nx \c_xsimverb_version_number_tl { \c_xsimverb_version_major_number_tl . \c_xsimverb_version_minor_number_tl } \tl_const:Nx \c_xsimverb_version_tl { \c_xsimverb_version_number_tl \c_xsimverb_version_subrelease_tl } \tl_const:Nn \c_xsimverb_info_tl {write~ environments~ verbatim~ to~ files} \ProvidesExplPackage {xsimverb} {\c_xsimverb_date_tl} {\c_xsimverb_version_tl} {\c_xsimverb_info_tl} % options, information \cs_new_protected:Npn \xsimverb_bool_provide:N #1 { \bool_if_exist:NF #1 { \bool_new:N #1 } } \xsimverb_bool_provide:N \g__xsim_final_bool \xsimverb_bool_provide:N \g__xsim_verbose_bool \xsimverb_bool_provide:N \g_xsim_clear_aux_bool \xsimverb_bool_provide:N \g__xsim_write_to_file_bool \xsimverb_bool_provide:N \g_xsim_use_aux_bool \xsimverb_bool_provide:N \g__xsim_rerun_bool \xsimverb_bool_provide:N \g__xsim_debug_bool \xsimverb_bool_provide:N \g__xsim_blank_bool \keys_define:nn {xsimverb} { final .bool_gset:N = \g__xsim_final_bool , verbose .bool_gset:N = \g__xsim_verbose_bool , debug .bool_gset:N = \g__xsim_debug_bool , clear-aux .bool_gset:N = \g_xsim_clear_aux_bool , use-files .bool_gset:N = \g__xsim_write_to_file_bool , use-files .initial:n = false , no-files .choice: , no-files / true .meta:n = { use-files = false } , no-files / false .meta:n = { use-files = true } , no-files .default:n = true , use-aux .bool_gset:N = \g_xsim_use_aux_bool , use-aux .initial:n = false , blank .bool_gset:N = \g__xsim_blank_bool , blank .initial:n = false } \ProcessKeysPackageOptions {xsimverb} \cs_if_exist:NF \xsim_if_final:T { \prg_new_conditional:Npnn \xsim_if_final: {p,T,F,TF} { \bool_if:NTF \g__xsim_final_bool { \prg_return_true: } { \prg_return_false: } } \prg_new_conditional:Npnn \xsim_if_verbose: {p,T,F,TF} { \bool_if:NTF \g__xsim_verbose_bool { \prg_return_true: } { \prg_return_false: } } } \cs_if_exist:NF \xsim_verbose:n { \cs_new_protected:Npn \xsim_verbose:n #1 { \xsim_if_verbose:T { \msg_info:nnn {xsim} {verbose} {#1} } } \cs_generate_variant:Nn \xsim_verbose:n {x} } % -------------------------------------------------------------------------- % #1: name % #2: description \cs_set_protected:Npn \XSIMmodule #1#2 {} \cs_set_protected:Npn \XSIMmoduleend {} % -------------------------------------------------------------------------- \XSIMmodule{verbwrite}{write contents of environments verbatim to files} \int_new:N \l__xsimverb_tmpa_int \tl_new:N \l__xsimverb_tmpa_tl \iow_new:N \l__xsim_file_contents_iow \tl_new:N \l_xsim_file_begin_tl \tl_new:N \l_xsim_file_end_tl \int_new:N \l_xsim_line_gobble_int \int_zero:N \l_xsim_line_gobble_int \tl_const:Nx \c__xsim_backslash_char_tl { \cs_to_str:N \\ } \group_begin: \char_set_catcode_other:n {37} \tl_const:Nn \c__xsim_percent_char_tl {%} \group_end: % ---------------------------------------------------------------------------- \bool_new:N \l__xsim_stream_open_bool % the `final' option will prevent writing to files: % #1: write stream % #2: file name \cs_new_protected:Npn \__xsim_open_stream:Nn #1#2 { \file_if_exist:nTF {#2} { \xsim_if_final:F { \bool_set_true:N \l__xsim_stream_open_bool \iow_open:Nn #1 {#2} } } { \bool_set_true:N \l__xsim_stream_open_bool \iow_open:Nn #1 {#2} } } % #1: write stream \cs_new_protected:Npn \__xsim_close_stream:N #1 { \bool_if:NT \l__xsim_stream_open_bool { \iow_close:N #1 } } % #1: write stream % #2: contents \cs_new_protected:Npn \__xsim_write_to_stream:Nn #1#2 { \xsim_if_final:F { % remove the /one/ space token with catcode 10 that is inserted if % no options are given to the surrounding environment: \tl_set:Nn \l__xsimverb_tmpa_tl {#2} \tl_remove_once:Nn \l__xsimverb_tmpa_tl {~} % \tl_show:N \l__xsimverb_tmpa_tl % \int_show:n { \tl_count:N \l__xsimverb_tmpa_tl } % \tl_analysis_show:N \l__xsimverb_tmpa_tl \int_zero:N \l__xsimverb_tmpa_int \int_while_do:nn { \l__xsimverb_tmpa_int < \l_xsim_line_gobble_int } { \int_incr:N \l__xsimverb_tmpa_int \tl_set:Nx \l__xsimverb_tmpa_tl { \tl_tail:N \l__xsimverb_tmpa_tl } } \iow_now:NV #1 \l__xsimverb_tmpa_tl } } \cs_generate_variant:Nn \__xsim_write_to_stream:Nn {Nx} \cs_generate_variant:Nn \iow_now:Nn {NV} \cs_new:Npn \__xsim_tab: { \c_space_tl \c_space_tl } \cs_new:Npn \__xsim_par: { ^^J ^^J } % the following is inspired by the definition of the `filecontents' % environment: % #1: boolean - if true an active eol needs to be inserted before % starting to write % #2: file name \cs_new_protected:Npn \xsim_file_write_start:nn #1#2 { % we need to insert an active ^^M if no options are given % see http://tex.stackexchange.com/q/9035/5049 reasons \use:nx { \__xsim_file_write_start:n {#2} } { \bool_if:nF {#1} { \exp_not:V \c__xsim_active_eol_tl } } } \cs_generate_variant:Nn \xsim_file_write_start:nn {nV} \cs_generate_variant:Nn \use:nn {nx} \cs_new_protected:Npn \__xsim_set_verb_catcodes: { \seq_map_inline:Nn \l_char_special_seq { \char_set_catcode_other:N ##1 } \int_step_inline:nnnn {128} {1} {255} { \char_set_catcode_letter:n {##1} } } \group_begin: \char_set_catcode_active:n {13} % ^^M (carriage return, endlinechar) \char_set_catcode_active:n {12} % ^^L (form feed) \char_set_catcode_active:n {9} % ^^I (horizontal tab) % \tl_const:Nn \c__xsim_active_eol_tl {^^M} % % % #1: file name \cs_new_protected:Npn \__xsim_file_write_start:n #1 % { % \group_begin: % \xsim_if_final:TF % { \xsim_verbose:x { Not~ (re-)writing~ file~ `#1'. } } % { \xsim_verbose:x { (Re-)writing~ file~ `#1'. } } % \__xsim_open_stream:Nn \l__xsim_file_contents_iow {#1} % \tl_if_blank:VF \l_xsim_file_begin_tl % { % \xsim_if_final:F % { % \iow_now:Nx \l__xsim_file_contents_iow % { \exp_not:V \l_xsim_file_begin_tl } % } % } % \__xsim_set_verb_catcodes: % \tl_set:Nx \l__xsimverb_tmpa_tl % { \c__xsim_backslash_char_tl end \cs_to_str:N \{ \@currenvir \cs_to_str:N \} } % \use:x % { % \cs_set:cpn {__xsim_tmpa:www} % ####1 \l__xsimverb_tmpa_tl % ####2 \l__xsimverb_tmpa_tl % ####3 \exp_not:N \q_stop: % } % { % \tl_if_blank:nTF {##3} % { \__xsim_write_to_stream:Nn \l__xsim_file_contents_iow {##1} } % { % \cs_set:Npx \__xsim_M:w { \exp_not:N \end {\@currenvir} } % \char_set_active_eq:nN {13} \__xsim_M:w % % the last line is `##1 \end{\@currenvir} ##2': \tl_if_blank:nF {##1} % { \__xsim_write_to_stream:Nn \l__xsim_file_contents_iow {##1} }% \tl_if_blank:nF {##2} % {} % } % ^^M % } % \char_set_catcode_active:n {13} % \char_set_catcode_active:n {12} % \char_set_catcode_active:n {9} % \cs_set:Npx \__xsim_M:w ##1 ^^M % { % \exp_not:N \__xsim_tmpa:www ##1 % \l__xsimverb_tmpa_tl % \l__xsimverb_tmpa_tl % \exp_not:N \q_stop: % } % \char_set_active_eq:nN {13} \__xsim_M:w % \char_set_active_eq:nN {12} \__xsim_par: % \char_set_active_eq:nN {9} \__xsim_tab: % } % \group_end: \cs_new_protected:Npn \xsim_file_write_stop: { \tl_if_blank:VF \l_xsim_file_end_tl { \xsim_if_final:F { \iow_now:Nx \l__xsim_file_contents_iow { \exp_not:V \l_xsim_file_end_tl } } } \__xsim_close_stream:N \l__xsim_file_contents_iow \group_end: } % ---------------------------------------------------------------------------- \cs_generate_variant:Nn \tl_set:Nn {Ne} \NewDocumentCommand \XSIMfilewritestart {sm} { \IfBooleanTF {#1} { \xsim_file_write_start:nn { \c_false_bool } {#2} } { \xsim_file_write_start:nn { \c_true_bool } {#2} } } \NewDocumentCommand \XSIMfilewritestop {} { \xsim_file_write_stop: } \NewDocumentCommand \XSIMsetfilebegin {+m} { \tl_set:Nn \l_xsim_file_begin_tl {#1} } \NewDocumentCommand \XSIMsetfilebeginX {+m} { \tl_set:Ne \l_xsim_file_begin_tl {#1} } \NewDocumentCommand \XSIMsetfileend {+m} { \tl_set:Nn \l_xsim_file_end_tl {#1} } \NewDocumentCommand \XSIMsetfileendX {+m} { \tl_set:Ne \l_xsim_file_end_tl {#1} } \NewDocumentCommand \XSIMgobblechars {m} { \int_set:Nn \l_xsim_line_gobble_int {#1} } \XSIMmoduleend