%% %% This is file `piton.sty', %% generated with the docstrip utility. %% %% The original source files were: %% %% piton.dtx (with options: `STY') %% ------------------------------------------- %% Copyright (C) 2022-2024 by F. Pantigny %% %% This file may be distributed and/or modified under the %% conditions of the LaTeX Project Public License, either %% version 1.3 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.3 or later is part of all distributions of %% LaTeX version 2005/12/01 or later. %% ------------------------------------------- %% \def\PitonFileVersion{3.1a} \def\PitonFileDate{2024/08/12} \NeedsTeXFormat{LaTeX2e} \RequirePackage{l3keys2e} \ProvidesExplPackage {piton} {\PitonFileDate} {\PitonFileVersion} {Highlight informatic listings with LPEG on LuaLaTeX} \RequirePackage { amstext } \cs_new_protected:Npn \__piton_error:n { \msg_error:nn { piton } } \cs_new_protected:Npn \__piton_warning:n { \msg_warning:nn { piton } } \cs_new_protected:Npn \__piton_error:nn { \msg_error:nnn { piton } } \cs_new_protected:Npn \__piton_error:nnn { \msg_error:nnnn { piton } } \cs_new_protected:Npn \__piton_fatal:n { \msg_fatal:nn { piton } } \cs_new_protected:Npn \__piton_fatal:nn { \msg_fatal:nnn { piton } } \cs_new_protected:Npn \__piton_msg_new:nn { \msg_new:nnn { piton } } \cs_new_protected:Npn \__piton_gredirect_none:n #1 { \group_begin: \globaldefs = 1 \msg_redirect_name:nnn { piton } { #1 } { none } \group_end: } \cs_new_protected:Npn \__piton_msg_new:nnn #1 #2 #3 { \bool_if:NTF \g__piton_messages_for_Overleaf_bool { \msg_new:nnn { piton } { #1 } { #2 \\ #3 } } { \msg_new:nnnn { piton } { #1 } { #2 } { #3 } } } \cs_new_protected:Npn \__piton_error_or_warning:n { \bool_if:NTF \g__piton_messages_for_Overleaf_bool \__piton_warning:n \__piton_error:n } \bool_new:N \g__piton_messages_for_Overleaf_bool \bool_gset:Nn \g__piton_messages_for_Overleaf_bool { \str_if_eq_p:on \c_sys_jobname_str { _region_ } % for Emacs || \str_if_eq_p:on \c_sys_jobname_str { output } % for Overleaf } \__piton_msg_new:nn { LuaLaTeX~mandatory } { LuaLaTeX~is~mandatory.\\ The~package~'piton'~requires~the~engine~LuaLaTeX.\\ \str_if_eq:onT \c_sys_jobname_str { output } { If~you~use~Overleaf,~you~can~switch~to~LuaLaTeX~in~the~"Menu". \\} If~you~go~on,~the~package~'piton'~won't~be~loaded. } \sys_if_engine_luatex:F { \msg_critical:nn { piton } { LuaLaTeX~mandatory } } \RequirePackage { luatexbase } \RequirePackage { luacode } \__piton_msg_new:nnn { piton.lua~not~found } { The~file~'piton.lua'~can't~be~found.\\ This~error~is~fatal.\\ If~you~want~to~know~how~to~retrieve~the~file~'piton.lua',~type~H~. } { On~the~site~CTAN,~go~to~the~page~of~'piton':~https://ctan.org/pkg/piton.~ The~file~'README.md'~explains~how~to~retrieve~the~files~'piton.sty'~and~ 'piton.lua'. } \file_if_exist:nF { piton.lua } { \msg_fatal:nn { piton } { piton.lua~not~found } } \bool_new:N \g__piton_footnotehyper_bool \bool_new:N \g__piton_footnote_bool \bool_new:N \g__piton_math_comments_bool \bool_new:N \g__piton_beamer_bool \tl_new:N \g__piton_escape_inside_tl \keys_define:nn { piton / package } { footnote .bool_gset:N = \g__piton_footnote_bool , footnotehyper .bool_gset:N = \g__piton_footnotehyper_bool , beamer .bool_gset:N = \g__piton_beamer_bool , beamer .default:n = true , unknown .code:n = \__piton_error:n { Unknown~key~for~package } } \__piton_msg_new:nn { Unknown~key~for~package } { Unknown~key.\\ You~have~used~the~key~'\l_keys_key_str'~but~the~only~keys~available~here~ are~'beamer',~'footnote',~'footnotehyper'.~Other~keys~are~available~in~ \token_to_str:N \PitonOptions.\\ That~key~will~be~ignored. } \ProcessKeysOptions { piton / package } \IfClassLoadedTF { beamer } { \bool_gset_true:N \g__piton_beamer_bool } { } \IfPackageLoadedTF { beamerarticle } { \bool_gset_true:N \g__piton_beamer_bool } { } \lua_now:n { piton = piton~or~{ } } \bool_if:NT \g__piton_beamer_bool { \lua_now:n { piton.beamer = true } } \hook_gput_code:nnn { begindocument / before } { . } { \IfPackageLoadedTF { xcolor } { } { \usepackage { xcolor } } } \__piton_msg_new:nn { footnote~with~footnotehyper~package } { Footnote~forbidden.\\ You~can't~use~the~option~'footnote'~because~the~package~ footnotehyper~has~already~been~loaded.~ If~you~want,~you~can~use~the~option~'footnotehyper'~and~the~footnotes~ within~the~environments~of~piton~will~be~extracted~with~the~tools~ of~the~package~footnotehyper.\\ If~you~go~on,~the~package~footnote~won't~be~loaded. } \__piton_msg_new:nn { footnotehyper~with~footnote~package } { You~can't~use~the~option~'footnotehyper'~because~the~package~ footnote~has~already~been~loaded.~ If~you~want,~you~can~use~the~option~'footnote'~and~the~footnotes~ within~the~environments~of~piton~will~be~extracted~with~the~tools~ of~the~package~footnote.\\ If~you~go~on,~the~package~footnotehyper~won't~be~loaded. } \bool_if:NT \g__piton_footnote_bool { \IfClassLoadedTF { beamer } { \bool_gset_false:N \g__piton_footnote_bool } { \IfPackageLoadedTF { footnotehyper } { \__piton_error:n { footnote~with~footnotehyper~package } } { \usepackage { footnote } } } } \bool_if:NT \g__piton_footnotehyper_bool { \IfClassLoadedTF { beamer } { \bool_gset_false:N \g__piton_footnote_bool } { \IfPackageLoadedTF { footnote } { \__piton_error:n { footnotehyper~with~footnote~package } } { \usepackage { footnotehyper } } \bool_gset_true:N \g__piton_footnote_bool } } \lua_now:n { piton.BeamerCommands = lpeg.P ( "\\uncover" ) + "\\only" + "\\visible" + "\\invisible" + "\\alert" + "\\action" piton.beamer_environments = { "uncoverenv" , "onlyenv" , "visibleenv" , "invisibleenv" , "alertenv" , "actionenv" } piton.DetectedCommands = lpeg.P ( false ) piton.last_code = '' piton.last_language = '' } \str_new:N \l_piton_language_str \str_set:Nn \l_piton_language_str { python } \tl_new:N \g_piton_last_code_tl \seq_new:N \l__piton_path_seq \str_new:N \l__piton_path_write_str \bool_new:N \l__piton_in_PitonOptions_bool \bool_new:N \l__piton_in_PitonInputFile_bool \int_new:N \l__piton_nb_lines_int \int_new:N \l__piton_nb_non_empty_lines_int \int_new:N \g__piton_line_int \tl_new:N \g__piton_aux_tl \int_new:N \l__piton_splittable_int \int_set:Nn \l__piton_splittable_int { 100 } \tl_new:N \l__piton_split_separation_tl \tl_set:Nn \l__piton_split_separation_tl { \vspace { \baselineskip } \vspace { -1.25pt } } \clist_new:N \l__piton_bg_color_clist \tl_new:N \l__piton_prompt_bg_color_tl \str_new:N \l__piton_begin_range_str \str_new:N \l__piton_end_range_str \str_new:N \l__piton_file_name_str \int_new:N \g__piton_env_int \str_new:N \l__piton_write_str \seq_new:N \g__piton_write_seq \bool_new:N \l__piton_show_spaces_bool \bool_new:N \l__piton_break_lines_in_Piton_bool \bool_new:N \l__piton_indent_broken_lines_bool \tl_new:N \l__piton_continuation_symbol_tl \tl_set:Nn \l__piton_continuation_symbol_tl { + } \tl_new:N \l__piton_csoi_tl \tl_set:Nn \l__piton_csoi_tl { $ \hookrightarrow \; $ } \tl_new:N \l__piton_end_of_broken_line_tl \tl_set:Nn \l__piton_end_of_broken_line_tl { \hspace*{0.5em} \textbackslash } \bool_new:N \l__piton_break_lines_in_piton_bool \dim_new:N \l__piton_width_dim \dim_new:N \l__piton_line_width_dim \bool_new:N \l__piton_width_min_bool \dim_new:N \g__piton_tmp_width_dim \dim_new:N \l__piton_left_margin_dim \bool_new:N \l__piton_left_margin_auto_bool \dim_new:N \l__piton_numbers_sep_dim \dim_set:Nn \l__piton_numbers_sep_dim { 0.7 em } \seq_new:N \g__piton_languages_seq \int_new:N \l__piton_tab_size_int \int_set:Nn \l__piton_tab_size_int { 4 } \cs_new_protected:Npn \__piton_tab: { \bool_if:NTF \l__piton_show_spaces_bool { \hbox_set:Nn \l_tmpa_box { \prg_replicate:nn \l__piton_tab_size_int { ~ } } \dim_set:Nn \l_tmpa_dim { \box_wd:N \l_tmpa_box } \( \mathcolor { gray } { \hbox_to_wd:nn \l_tmpa_dim { \rightarrowfill } } \) } { \hbox:n { \prg_replicate:nn \l__piton_tab_size_int { ~ } } } \int_gadd:Nn \g__piton_indentation_int \l__piton_tab_size_int } \int_new:N \l__piton_gobble_int \tl_new:N \l__piton_space_tl \tl_set_eq:NN \l__piton_space_tl \nobreakspace \int_new:N \g__piton_indentation_int \cs_new_protected:Npn \__piton_an_indentation_space: { \int_gincr:N \g__piton_indentation_int } \cs_new_protected:Npn \__piton_beamer_command:n #1 { \str_set:Nn \l__piton_beamer_command_str { #1 } \use:c { #1 } } \cs_new_protected:Npn \__piton_label:n #1 { \bool_if:NTF \l__piton_line_numbers_bool { \@bsphack \protected@write \@auxout { } { \string \newlabel { #1 } { { \int_eval:n { \g__piton_visual_line_int + 1 } } { \thepage } } } \@esphack } { \__piton_error:n { label~with~lines~numbers } } } \cs_new_protected:Npn \__piton_marker_beginning:n #1 { } \cs_new_protected:Npn \__piton_marker_end:n #1 { } \cs_new_protected:Npn \__piton_open_brace: { \lua_now:n { piton.open_brace() } } \cs_new_protected:Npn \__piton_close_brace: { \lua_now:n { piton.close_brace() } } \tl_new:N \g__piton_begin_line_hook_tl \cs_new_protected:Npn \__piton_prompt: { \tl_gset:Nn \g__piton_begin_line_hook_tl { \tl_if_empty:NF \l__piton_prompt_bg_color_tl { \clist_set:NV \l__piton_bg_color_clist \l__piton_prompt_bg_color_tl } } } \cs_new_protected:Npn \__piton_replace_spaces:n #1 { \tl_set:Nn \l_tmpa_tl { #1 } \bool_if:NTF \l__piton_show_spaces_bool { \tl_set:Nn \l__piton_space_tl { ␣ } \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl % U+2423 } { \bool_if:NT \l__piton_break_lines_in_Piton_bool { \regex_replace_all:nnN { \x20 } { \c { __piton_breakable_space: } } \l_tmpa_tl } } \l_tmpa_tl } \cs_set_protected:Npn \__piton_begin_line: #1 \__piton_end_line: { \group_begin: \g__piton_begin_line_hook_tl \int_gzero:N \g__piton_indentation_int \bool_if:NTF \l__piton_width_min_bool \__piton_put_in_coffin_ii:n \__piton_put_in_coffin_i:n { \language = -1 \raggedright \strut \__piton_replace_spaces:n { #1 } \strut \hfil } \hbox_set:Nn \l_tmpa_box { \skip_horizontal:N \l__piton_left_margin_dim \bool_if:NT \l__piton_line_numbers_bool { \bool_if:nF { \str_if_eq_p:nn { #1 } { \PitonStyle { Prompt } { } } && \l__piton_skip_empty_lines_bool } { \int_gincr:N \g__piton_visual_line_int } \bool_if:nT { ! \str_if_eq_p:nn { #1 } { \PitonStyle { Prompt } { } } || ( ! \l__piton_skip_empty_lines_bool && \l__piton_label_empty_lines_bool ) } \__piton_print_number: } \clist_if_empty:NF \l__piton_bg_color_clist { \dim_compare:nNnT \l__piton_left_margin_dim = \c_zero_dim { \skip_horizontal:n { 0.5 em } } } \coffin_typeset:Nnnnn \l_tmpa_coffin T l \c_zero_dim \c_zero_dim } \box_set_dp:Nn \l_tmpa_box { \box_dp:N \l_tmpa_box + 1.25 pt } \box_set_ht:Nn \l_tmpa_box { \box_ht:N \l_tmpa_box + 1.25 pt } \clist_if_empty:NTF \l__piton_bg_color_clist { \box_use_drop:N \l_tmpa_box } { \vtop { \hbox:n { \__piton_color:N \l__piton_bg_color_clist \vrule height \box_ht:N \l_tmpa_box depth \box_dp:N \l_tmpa_box width \l__piton_width_dim } \skip_vertical:n { - \box_ht_plus_dp:N \l_tmpa_box } \box_use_drop:N \l_tmpa_box } } \vspace { - 2.5 pt } \group_end: \tl_gclear:N \g__piton_begin_line_hook_tl } \cs_set_protected:Npn \__piton_put_in_coffin_i:n { \vcoffin_set:Nnn \l_tmpa_coffin \l__piton_line_width_dim } \cs_set_protected:Npn \__piton_put_in_coffin_ii:n #1 { \hbox_set:Nn \l_tmpa_box { #1 } \dim_compare:nNnT { \box_wd:N \l_tmpa_box } > \g__piton_tmp_width_dim { \dim_gset:Nn \g__piton_tmp_width_dim { \box_wd:N \l_tmpa_box } } \hcoffin_set:Nn \l_tmpa_coffin { \hbox_to_wd:nn \l__piton_line_width_dim { \hbox_unpack:N \l_tmpa_box \hfil } } } \cs_set_protected:Npn \__piton_color:N #1 { \int_set:Nn \l_tmpa_int { \clist_count:N #1 } \int_set:Nn \l_tmpb_int { \int_mod:nn \g__piton_line_int \l_tmpa_int + 1 } \tl_set:Nx \l_tmpa_tl { \clist_item:Nn #1 \l_tmpb_int } \tl_if_eq:NnTF \l_tmpa_tl { none } { \dim_zero:N \l__piton_width_dim } { \exp_args:NV \__piton_color_i:n \l_tmpa_tl } } \cs_set_protected:Npn \__piton_color_i:n #1 { \tl_if_head_eq_meaning:nNTF { #1 } [ { \tl_set:Nn \l_tmpa_tl { #1 } \tl_set_rescan:Nno \l_tmpa_tl { } \l_tmpa_tl \exp_last_unbraced:No \color \l_tmpa_tl } { \color { #1 } } } \cs_new_protected:Npn \__piton_newline: { \int_gincr:N \g__piton_line_int \int_compare:nNnT \g__piton_line_int > { \l__piton_splittable_int - 1 } { \int_compare:nNnT { \l__piton_nb_lines_int - \g__piton_line_int + 1 } > \l__piton_splittable_int { \egroup \bool_if:NT \g__piton_footnote_bool \endsavenotes \par \mode_leave_vertical: \bool_if:NT \g__piton_footnote_bool \savenotes \vtop \bgroup } } } \cs_set_protected:Npn \__piton_breakable_space: { \discretionary { \hbox:n { \color { gray } \l__piton_end_of_broken_line_tl } } { \hbox_overlap_left:n { { \normalfont \footnotesize \color { gray } \l__piton_continuation_symbol_tl } \skip_horizontal:n { 0.3 em } \clist_if_empty:NF \l__piton_bg_color_clist { \skip_horizontal:n { 0.5 em } } } \bool_if:NT \l__piton_indent_broken_lines_bool { \hbox:n { \prg_replicate:nn { \g__piton_indentation_int } { ~ } { \color { gray } \l__piton_csoi_tl } } } } { \hbox { ~ } } } \bool_new:N \l__piton_line_numbers_bool \bool_new:N \l__piton_skip_empty_lines_bool \bool_set_true:N \l__piton_skip_empty_lines_bool \bool_new:N \l__piton_line_numbers_absolute_bool \tl_new:N \l__piton_line_numbers_format_bool \tl_set:Nn \l__piton_line_numbers_format_tl { \footnotesize \color { gray } } \bool_new:N \l__piton_label_empty_lines_bool \bool_set_true:N \l__piton_label_empty_lines_bool \int_new:N \l__piton_number_lines_start_int \bool_new:N \l__piton_resume_bool \bool_new:N \l__piton_split_on_empty_lines_bool \keys_define:nn { PitonOptions / marker } { beginning .code:n = \cs_set:Nn \__piton_marker_beginning:n { #1 } , beginning .value_required:n = true , end .code:n = \cs_set:Nn \__piton_marker_end:n { #1 } , end .value_required:n = true , include-lines .bool_set:N = \l__piton_marker_include_lines_bool , include-lines .default:n = true , unknown .code:n = \__piton_error:n { Unknown~key~for~marker } } \keys_define:nn { PitonOptions / line-numbers } { true .code:n = \bool_set_true:N \l__piton_line_numbers_bool , false .code:n = \bool_set_false:N \l__piton_line_numbers_bool , start .code:n = \bool_set_true:N \l__piton_line_numbers_bool \int_set:Nn \l__piton_number_lines_start_int { #1 } , start .value_required:n = true , skip-empty-lines .code:n = \bool_if:NF \l__piton_in_PitonOptions_bool { \bool_set_true:N \l__piton_line_numbers_bool } \str_if_eq:nnTF { #1 } { false } { \bool_set_false:N \l__piton_skip_empty_lines_bool } { \bool_set_true:N \l__piton_skip_empty_lines_bool } , skip-empty-lines .default:n = true , label-empty-lines .code:n = \bool_if:NF \l__piton_in_PitonOptions_bool { \bool_set_true:N \l__piton_line_numbers_bool } \str_if_eq:nnTF { #1 } { false } { \bool_set_false:N \l__piton_label_empty_lines_bool } { \bool_set_true:N \l__piton_label_empty_lines_bool } , label-empty-lines .default:n = true , absolute .code:n = \bool_if:NTF \l__piton_in_PitonOptions_bool { \bool_set_true:N \l__piton_line_numbers_absolute_bool } { \bool_set_true:N \l__piton_line_numbers_bool } \bool_if:NT \l__piton_in_PitonInputFile_bool { \bool_set_true:N \l__piton_line_numbers_absolute_bool \bool_set_false:N \l__piton_skip_empty_lines_bool } , absolute .value_forbidden:n = true , resume .code:n = \bool_set_true:N \l__piton_resume_bool \bool_if:NF \l__piton_in_PitonOptions_bool { \bool_set_true:N \l__piton_line_numbers_bool } , resume .value_forbidden:n = true , sep .dim_set:N = \l__piton_numbers_sep_dim , sep .value_required:n = true , format .tl_set:N = \l__piton_line_numbers_format_tl , format .value_required:n = true , unknown .code:n = \__piton_error:n { Unknown~key~for~line-numbers } } \keys_define:nn { PitonOptions } { detected-commands .code:n = \lua_now:n { piton.addDetectedCommands('#1') } , detected-commands .value_required:n = true , detected-commands .usage:n = preamble , detected-beamer-commands .code:n = \lua_now:n { piton.addBeamerCommands('#1') } , detected-beamer-commands .value_required:n = true , detected-beamer-commands .usage:n = preamble , detected-beamer-environments .code:n = \lua_now:n { piton.addBeamerEnvironments('#1') } , detected-beamer-environments .value_required:n = true , detected-beamer-environments .usage:n = preamble , begin-escape .code:n = \lua_now:e { piton.begin_escape = "\lua_escape:n{#1}" } , begin-escape .value_required:n = true , begin-escape .usage:n = preamble , end-escape .code:n = \lua_now:e { piton.end_escape = "\lua_escape:n{#1}" } , end-escape .value_required:n = true , end-escape .usage:n = preamble , begin-escape-math .code:n = \lua_now:e { piton.begin_escape_math = "\lua_escape:n{#1}" } , begin-escape-math .value_required:n = true , begin-escape-math .usage:n = preamble , end-escape-math .code:n = \lua_now:e { piton.end_escape_math = "\lua_escape:n{#1}" } , end-escape-math .value_required:n = true , end-escape-math .usage:n = preamble , comment-latex .code:n = \lua_now:n { comment_latex = "#1" } , comment-latex .value_required:n = true , comment-latex .usage:n = preamble , math-comments .bool_gset:N = \g__piton_math_comments_bool , math-comments .default:n = true , math-comments .usage:n = preamble , language .code:n = \str_set:Nx \l_piton_language_str { \str_lowercase:n { #1 } } , language .value_required:n = true , path .code:n = \seq_clear:N \l__piton_path_seq \clist_map_inline:nn { #1 } { \str_set:Nn \l_tmpa_str { ##1 } \seq_put_right:No \l__piton_path_seq \l_tmpa_str } , path .value_required:n = true , path .initial:n = . , path-write .str_set:N = \l__piton_path_write_str , path-write .value_required:n = true , gobble .int_set:N = \l__piton_gobble_int , gobble .value_required:n = true , auto-gobble .code:n = \int_set:Nn \l__piton_gobble_int { -1 } , auto-gobble .value_forbidden:n = true , env-gobble .code:n = \int_set:Nn \l__piton_gobble_int { -2 } , env-gobble .value_forbidden:n = true , tabs-auto-gobble .code:n = \int_set:Nn \l__piton_gobble_int { -3 } , tabs-auto-gobble .value_forbidden:n = true , split-on-empty-lines .bool_set:N = \l__piton_split_on_empty_lines_bool , split-on-empty-lines .default:n = true , split-separation .tl_set:N = \l__piton_split_separation_tl , split-separation .value_required:n = true , marker .code:n = \bool_lazy_or:nnTF \l__piton_in_PitonInputFile_bool \l__piton_in_PitonOptions_bool { \keys_set:nn { PitonOptions / marker } { #1 } } { \__piton_error:n { Invalid~key } } , marker .value_required:n = true , line-numbers .code:n = \keys_set:nn { PitonOptions / line-numbers } { #1 } , line-numbers .default:n = true , splittable .int_set:N = \l__piton_splittable_int , splittable .default:n = 1 , background-color .clist_set:N = \l__piton_bg_color_clist , background-color .value_required:n = true , prompt-background-color .tl_set:N = \l__piton_prompt_bg_color_tl , prompt-background-color .value_required:n = true , width .code:n = \str_if_eq:nnTF { #1 } { min } { \bool_set_true:N \l__piton_width_min_bool \dim_zero:N \l__piton_width_dim } { \bool_set_false:N \l__piton_width_min_bool \dim_set:Nn \l__piton_width_dim { #1 } } , width .value_required:n = true , write .str_set:N = \l__piton_write_str , write .value_required:n = true , left-margin .code:n = \str_if_eq:nnTF { #1 } { auto } { \dim_zero:N \l__piton_left_margin_dim \bool_set_true:N \l__piton_left_margin_auto_bool } { \dim_set:Nn \l__piton_left_margin_dim { #1 } \bool_set_false:N \l__piton_left_margin_auto_bool } , left-margin .value_required:n = true , tab-size .int_set:N = \l__piton_tab_size_int , tab-size .value_required:n = true , show-spaces .bool_set:N = \l__piton_show_spaces_bool , show-spaces .value_forbidden:n = true , show-spaces-in-strings .code:n = \tl_set:Nn \l__piton_space_tl { ␣ } , % U+2423 show-spaces-in-strings .value_forbidden:n = true , break-lines-in-Piton .bool_set:N = \l__piton_break_lines_in_Piton_bool , break-lines-in-Piton .default:n = true , break-lines-in-piton .bool_set:N = \l__piton_break_lines_in_piton_bool , break-lines-in-piton .default:n = true , break-lines .meta:n = { break-lines-in-piton , break-lines-in-Piton } , break-lines .value_forbidden:n = true , indent-broken-lines .bool_set:N = \l__piton_indent_broken_lines_bool , indent-broken-lines .default:n = true , end-of-broken-line .tl_set:N = \l__piton_end_of_broken_line_tl , end-of-broken-line .value_required:n = true , continuation-symbol .tl_set:N = \l__piton_continuation_symbol_tl , continuation-symbol .value_required:n = true , continuation-symbol-on-indentation .tl_set:N = \l__piton_csoi_tl , continuation-symbol-on-indentation .value_required:n = true , first-line .code:n = \__piton_in_PitonInputFile:n { \int_set:Nn \l__piton_first_line_int { #1 } } , first-line .value_required:n = true , last-line .code:n = \__piton_in_PitonInputFile:n { \int_set:Nn \l__piton_last_line_int { #1 } } , last-line .value_required:n = true , begin-range .code:n = \__piton_in_PitonInputFile:n { \str_set:Nn \l__piton_begin_range_str { #1 } } , begin-range .value_required:n = true , end-range .code:n = \__piton_in_PitonInputFile:n { \str_set:Nn \l__piton_end_range_str { #1 } } , end-range .value_required:n = true , range .code:n = \__piton_in_PitonInputFile:n { \str_set:Nn \l__piton_begin_range_str { #1 } \str_set:Nn \l__piton_end_range_str { #1 } } , range .value_required:n = true , resume .meta:n = line-numbers/resume , unknown .code:n = \__piton_error:n { Unknown~key~for~PitonOptions } , % deprecated all-line-numbers .code:n = \bool_set_true:N \l__piton_line_numbers_bool \bool_set_false:N \l__piton_skip_empty_lines_bool , all-line-numbers .value_forbidden:n = true , % deprecated numbers-sep .dim_set:N = \l__piton_numbers_sep_dim , numbers-sep .value_required:n = true } \cs_new_protected:Npn \__piton_in_PitonInputFile:n #1 { \bool_if:NTF \l__piton_in_PitonInputFile_bool { #1 } { \__piton_error:n { Invalid~key } } } \NewDocumentCommand \PitonOptions { m } { \bool_set_true:N \l__piton_in_PitonOptions_bool \keys_set:nn { PitonOptions } { #1 } \bool_set_false:N \l__piton_in_PitonOptions_bool } \NewDocumentCommand \__piton_fake_PitonOptions { } { \keys_set:nn { PitonOptions } } \int_new:N \g__piton_visual_line_int \cs_new_protected:Npn \__piton_incr_visual_line: { \bool_if:NF \l__piton_skip_empty_lines_bool { \int_gincr:N \g__piton_visual_line_int } } \cs_new_protected:Npn \__piton_print_number: { \hbox_overlap_left:n { { \l__piton_line_numbers_format_tl { \int_to_arabic:n \g__piton_visual_line_int } } \skip_horizontal:N \l__piton_numbers_sep_dim } } \cs_new_protected:Npn \__piton_write_aux: { \tl_if_empty:NF \g__piton_aux_tl { \iow_now:Nn \@mainaux { \ExplSyntaxOn } \iow_now:Nx \@mainaux { \tl_gset:cn { c__piton_ \int_use:N \g__piton_env_int _ tl } { \exp_not:o \g__piton_aux_tl } } \iow_now:Nn \@mainaux { \ExplSyntaxOff } } \tl_gclear:N \g__piton_aux_tl } \cs_new_protected:Npn \__piton_width_to_aux: { \tl_gput_right:Nx \g__piton_aux_tl { \dim_set:Nn \l__piton_line_width_dim { \dim_eval:n { \g__piton_tmp_width_dim } } } } \NewDocumentCommand { \NewPitonLanguage } { O { } m ! o } { \tl_if_novalue:nTF { #3 } { \__piton_NewPitonLanguage:nnn { #1 } { #2 } } { \__piton_NewPitonLanguage:nnnnn { #1 } { #2 } { #3 } } } \prop_new:N \g__piton_languages_prop \keys_define:nn { NewPitonLanguage } { morekeywords .code:n = , otherkeywords .code:n = , sensitive .code:n = , keywordsprefix .code:n = , moretexcs .code:n = , morestring .code:n = , morecomment .code:n = , moredelim .code:n = , moredirectives .code:n = , tag .code:n = , alsodigit .code:n = , alsoletter .code:n = , alsoother .code:n = , unknown .code:n = \__piton_error:n { Unknown~key~NewPitonLanguage } } \cs_new_protected:Npn \__piton_NewPitonLanguage:nnn #1 #2 #3 { \tl_set:Nx \l_tmpa_tl { \tl_if_blank:nF { #1 } { [ \str_lowercase:n { #1 } ] } \str_lowercase:n { #2 } } \keys_set:nn { NewPitonLanguage } { #3 } \prop_gput:Non \g__piton_languages_prop \l_tmpa_tl { #3 } \exp_args:NV \__piton_NewPitonLanguage:nn \l_tmpa_tl { #3 } } \cs_new_protected:Npn \__piton_NewPitonLanguage:nn #1 #2 { \hook_gput_code:nnn { begindocument } { . } { \lua_now:e { piton.new_language("#1","\lua_escape:n{#2}") } } } \cs_new_protected:Npn \__piton_NewPitonLanguage:nnnnn #1 #2 #3 #4 #5 { \tl_set:Nx \l_tmpa_tl { \tl_if_blank:nF { #3 } { [ \str_lowercase:n { #3 } ] } \str_lowercase:n { #4 } } \prop_get:NoNTF \g__piton_languages_prop \l_tmpa_tl \l_tmpb_tl { \__piton_NewPitonLanguage:nnno { #1 } { #2 } { #5 } \l_tmpb_tl } { \__piton_error:n { Language~not~defined } } } \cs_new_protected:Npn \__piton_NewPitonLanguage:nnnn #1 #2 #3 #4 { \__piton_NewPitonLanguage:nnn { #1 } { #2 } { #4 , #3 } } \cs_generate_variant:Nn \__piton_NewPitonLanguage:nnnn { n n n o } \NewDocumentCommand { \piton } { } { \peek_meaning:NTF \bgroup \__piton_piton_standard \__piton_piton_verbatim } \NewDocumentCommand { \__piton_piton_standard } { m } { \group_begin: \automatichyphenmode = 1 \cs_set_eq:NN \\ \c_backslash_str \cs_set_eq:NN \% \c_percent_str \cs_set_eq:NN \{ \c_left_brace_str \cs_set_eq:NN \} \c_right_brace_str \cs_set_eq:NN \$ \c_dollar_str \cs_set_eq:cN { ~ } \space \cs_set_protected:Npn \__piton_begin_line: { } \cs_set_protected:Npn \__piton_end_line: { } \tl_set:Nx \l_tmpa_tl { \lua_now:e { piton.ParseBis('\l_piton_language_str',token.scan_string()) } { #1 } } \bool_if:NTF \l__piton_show_spaces_bool { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423 { \bool_if:NT \l__piton_break_lines_in_piton_bool { \regex_replace_all:nnN { \x20 } { \x20 } \l_tmpa_tl } } \if_mode_math: \text { \ttfamily \l_tmpa_tl } \else: \ttfamily \l_tmpa_tl \fi: \group_end: } \NewDocumentCommand { \__piton_piton_verbatim } { v } { \group_begin: \ttfamily \automatichyphenmode = 1 \cs_set_protected:Npn \__piton_begin_line: { } \cs_set_protected:Npn \__piton_end_line: { } \tl_set:Nx \l_tmpa_tl { \lua_now:e { piton.Parse('\l_piton_language_str',token.scan_string()) } { #1 } } \bool_if:NT \l__piton_show_spaces_bool { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423 \l_tmpa_tl \group_end: } \cs_new_protected:Npn \__piton_piton:n #1 { \group_begin: \cs_set_protected:Npn \__piton_begin_line: { } \cs_set_protected:Npn \__piton_end_line: { } \cs_set:cpn { pitonStyle _ \l_piton_language_str _ Prompt } { } \cs_set:cpn { pitonStyle _ Prompt } { } \bool_lazy_or:nnTF \l__piton_break_lines_in_piton_bool \l__piton_break_lines_in_Piton_bool { \tl_set:Nx \l_tmpa_tl { \lua_now:e { piton.ParseTer('\l_piton_language_str',token.scan_string()) } { #1 } } } { \tl_set:Nx \l_tmpa_tl { \lua_now:e { piton.Parse('\l_piton_language_str',token.scan_string()) } { #1 } } } \bool_if:NT \l__piton_show_spaces_bool { \regex_replace_all:nnN { \x20 } { ␣ } \l_tmpa_tl } % U+2423 \l_tmpa_tl \group_end: } \cs_new_protected:Npn \__piton_piton_no_cr:n #1 { \group_begin: \cs_set_protected:Npn \__piton_newline: { \msg_fatal:nn { piton } { cr~not~allowed } } \__piton_piton:n { #1 } \group_end: } \cs_new:Npn \__piton_pre_env: { \automatichyphenmode = 1 \int_gincr:N \g__piton_env_int \tl_gclear:N \g__piton_aux_tl \dim_compare:nNnT \l__piton_width_dim = \c_zero_dim { \dim_set_eq:NN \l__piton_width_dim \linewidth } \cs_if_exist_use:c { c__piton _ \int_use:N \g__piton_env_int _ tl } \bool_if:NF \l__piton_resume_bool { \int_gzero:N \g__piton_visual_line_int } \dim_gzero:N \g__piton_tmp_width_dim \int_gzero:N \g__piton_line_int \dim_zero:N \parindent \dim_zero:N \lineskip \cs_set_eq:NN \label \__piton_label:n } \cs_new_protected:Npn \__piton_compute_left_margin:nn #1 #2 { \bool_lazy_and:nnT \l__piton_left_margin_auto_bool \l__piton_line_numbers_bool { \hbox_set:Nn \l_tmpa_box { \l__piton_line_numbers_format_tl \bool_if:NTF \l__piton_skip_empty_lines_bool { \lua_now:n { piton.#1(token.scan_argument()) } { #2 } \int_to_arabic:n { \g__piton_visual_line_int + \l__piton_nb_non_empty_lines_int } } { \int_to_arabic:n { \g__piton_visual_line_int + \l__piton_nb_lines_int } } } \dim_set:Nn \l__piton_left_margin_dim { \box_wd:N \l_tmpa_box + \l__piton_numbers_sep_dim + 0.1 em } } } \cs_generate_variant:Nn \__piton_compute_left_margin:nn { n o } \cs_new_protected:Npn \__piton_compute_width: { \dim_compare:nNnTF \l__piton_line_width_dim = \c_zero_dim { \dim_set_eq:NN \l__piton_line_width_dim \l__piton_width_dim \clist_if_empty:NTF \l__piton_bg_color_clist { \dim_sub:Nn \l__piton_line_width_dim \l__piton_left_margin_dim } { \dim_sub:Nn \l__piton_line_width_dim { 0.5 em } \dim_compare:nNnTF \l__piton_left_margin_dim = \c_zero_dim { \dim_sub:Nn \l__piton_line_width_dim { 0.5 em } } { \dim_sub:Nn \l__piton_line_width_dim \l__piton_left_margin_dim } } } { \dim_set_eq:NN \l__piton_width_dim \l__piton_line_width_dim \clist_if_empty:NTF \l__piton_bg_color_clist { \dim_add:Nn \l__piton_width_dim \l__piton_left_margin_dim } { \dim_add:Nn \l__piton_width_dim { 0.5 em } \dim_compare:nNnTF \l__piton_left_margin_dim = \c_zero_dim { \dim_add:Nn \l__piton_width_dim { 0.5 em } } { \dim_add:Nn \l__piton_width_dim \l__piton_left_margin_dim } } } } \NewDocumentCommand { \NewPitonEnvironment } { m m m m } { \use:x { \cs_set_protected:Npn \use:c { __piton_collect_ #1 :w } ####1 \c_backslash_str end \c_left_brace_str #1 \c_right_brace_str } { \group_end: \mode_if_vertical:TF { \noindent \mode_leave_vertical: } \newline \__piton_compute_left_margin:nn { CountNonEmptyLines } { ##1 } \__piton_compute_width: \ttfamily \dim_zero:N \parskip \noindent % added 2024/08/07 \str_if_empty:NTF \l__piton_path_write_str { \lua_now:e { piton.write = "\l__piton_write_str" } } { \lua_now:e { piton.write = "\l__piton_path_write_str / \l__piton_write_str" } } \str_if_empty:NTF \l__piton_write_str { \lua_now:n { piton.write = '' } } { \seq_if_in:NVTF \g__piton_write_seq \l__piton_write_str { \lua_now:n { piton.write_mode = "a" } } { \lua_now:n { piton.write_mode = "w" } \seq_gput_left:NV \g__piton_write_seq \l__piton_write_str } } \bool_if:NTF \l__piton_split_on_empty_lines_bool \__piton_gobble_split_parse:n \__piton_gobble_parse:n { ##1 } \bool_if:NT \l__piton_width_min_bool \__piton_width_to_aux: \end { #1 } \__piton_write_aux: } \NewDocumentEnvironment { #1 } { #2 } { \cs_set_eq:NN \PitonOptions \__piton_fake_PitonOptions #3 \__piton_pre_env: \int_compare:nNnT \l__piton_number_lines_start_int > \c_zero_int { \int_gset:Nn \g__piton_visual_line_int { \l__piton_number_lines_start_int - 1 } } \group_begin: \tl_map_function:nN { \ \\ \{ \} \$ \& \# \^ \_ \% \~ \^^I } \char_set_catcode_other:N \use:c { __piton_collect_ #1 :w } } { #4 } \AddToHook { env / #1 / begin } { \char_set_catcode_other:N \^^M } } \cs_new_protected:Npn \__piton_gobble_parse:n { \lua_now:e { piton.GobbleParse ( '\l_piton_language_str' , \int_use:N \l__piton_gobble_int , token.scan_argument ( ) ) } } \cs_new_protected:Npn \__piton_gobble_split_parse:n { \lua_now:e { piton.GobbleSplitParse ( '\l_piton_language_str' , \int_use:N \l__piton_gobble_int , token.scan_argument ( ) ) } } \bool_if:NTF \g__piton_beamer_bool { \NewPitonEnvironment { Piton } { d < > O { } } { \keys_set:nn { PitonOptions } { #2 } \tl_if_novalue:nTF { #1 } { \begin { uncoverenv } } { \begin { uncoverenv } < #1 > } } { \end { uncoverenv } } } { \NewPitonEnvironment { Piton } { O { } } { \keys_set:nn { PitonOptions } { #1 } } { } } \NewDocumentCommand { \PitonInputFileTF } { d < > O { } m m m } { \group_begin: \bool_set_false:N \l_tmpa_bool \seq_map_inline:Nn \l__piton_path_seq { \str_set:Nn \l__piton_file_name_str { ##1 / #3 } \file_if_exist:nT { \l__piton_file_name_str } { \__piton_input_file:nn { #1 } { #2 } \bool_set_true:N \l_tmpa_bool \seq_map_break: } } \bool_if:NTF \l_tmpa_bool { #4 } { #5 } \group_end: } \cs_new_protected:Npn \__piton_unknown_file:n #1 { \msg_error:nnn { piton } { Unknown~file } { #1 } } \NewDocumentCommand { \PitonInputFile } { d < > O { } m } { \PitonInputFileTF < #1 > [ #2 ] { #3 } { } { \__piton_unknown_file:n { #3 } } } \NewDocumentCommand { \PitonInputFileT } { d < > O { } m m } { \PitonInputFileTF < #1 > [ #2 ] { #3 } { #4 } { \__piton_unknown_file:n { #3 } } } \NewDocumentCommand { \PitonInputFileF } { d < > O { } m m } { \PitonInputFileTF < #1 > [ #2 ] { #3 } { } { #4 } } \cs_new_protected:Npn \__piton_input_file:nn #1 #2 { \tl_if_novalue:nF { #1 } { \bool_if:NTF \g__piton_beamer_bool { \begin { uncoverenv } < #1 > } { \__piton_error_or_warning:n { overlay~without~beamer } } } \group_begin: \int_zero_new:N \l__piton_first_line_int \int_zero_new:N \l__piton_last_line_int \int_set_eq:NN \l__piton_last_line_int \c_max_int \bool_set_true:N \l__piton_in_PitonInputFile_bool \keys_set:nn { PitonOptions } { #2 } \bool_if:NT \l__piton_line_numbers_absolute_bool { \bool_set_false:N \l__piton_skip_empty_lines_bool } \bool_if:nTF { ( \int_compare_p:nNn \l__piton_first_line_int > \c_zero_int || \int_compare_p:nNn \l__piton_last_line_int < \c_max_int ) && ! \str_if_empty_p:N \l__piton_begin_range_str } { \__piton_error_or_warning:n { bad~range~specification } \int_zero:N \l__piton_first_line_int \int_set_eq:NN \l__piton_last_line_int \c_max_int } { \str_if_empty:NF \l__piton_begin_range_str { \__piton_compute_range: \bool_lazy_or:nnT \l__piton_marker_include_lines_bool { ! \str_if_eq_p:NN \l__piton_begin_range_str \l__piton_end_range_str } { \int_decr:N \l__piton_first_line_int \int_incr:N \l__piton_last_line_int } } } \__piton_pre_env: \bool_if:NT \l__piton_line_numbers_absolute_bool { \int_gset:Nn \g__piton_visual_line_int { \l__piton_first_line_int - 1 } } \int_compare:nNnT \l__piton_number_lines_start_int > \c_zero_int { \int_gset:Nn \g__piton_visual_line_int { \l__piton_number_lines_start_int - 1 } } \int_compare:nNnT \g__piton_visual_line_int < \c_zero_int { \int_gzero:N \g__piton_visual_line_int } \mode_if_vertical:TF \mode_leave_vertical: \newline \lua_now:e { piton.CountLinesFile ( '\l__piton_file_name_str' ) } \__piton_compute_left_margin:no { CountNonEmptyLinesFile } \l__piton_file_name_str \__piton_compute_width: \ttfamily \lua_now:e { piton.ParseFile( '\l_piton_language_str' , '\l__piton_file_name_str' , \int_use:N \l__piton_first_line_int , \int_use:N \l__piton_last_line_int , \bool_if:NTF \l__piton_split_on_empty_lines_bool { 1 } { 0 } ) } \bool_if:NT \l__piton_width_min_bool \__piton_width_to_aux: \group_end: \tl_if_novalue:nF { #1 } { \bool_if:NT \g__piton_beamer_bool { \end { uncoverenv } } } \__piton_write_aux: } \cs_new_protected:Npn \__piton_compute_range: { \str_set:Nx \l_tmpa_str { \__piton_marker_beginning:n \l__piton_begin_range_str } \str_set:Nx \l_tmpb_str { \__piton_marker_end:n \l__piton_end_range_str } \exp_args:NnV \regex_replace_all:nnN { \\\# } \c_hash_str \l_tmpa_str \exp_args:NnV \regex_replace_all:nnN { \\\# } \c_hash_str \l_tmpb_str \lua_now:e { piton.ComputeRange ( '\l_tmpa_str' , '\l_tmpb_str' , '\l__piton_file_name_str' ) } } \NewDocumentCommand { \PitonStyle } { m } { \cs_if_exist_use:cF { pitonStyle _ \l_piton_language_str _ #1 } { \use:c { pitonStyle _ #1 } } } \NewDocumentCommand { \SetPitonStyle } { O { } m } { \str_clear_new:N \l__piton_SetPitonStyle_option_str \str_set:Nx \l__piton_SetPitonStyle_option_str { \str_lowercase:n { #1 } } \str_if_eq:onT \l__piton_SetPitonStyle_option_str { current-language } { \str_set_eq:NN \l__piton_SetPitonStyle_option_str \l_piton_language_str } \keys_set:nn { piton / Styles } { #2 } } \cs_new_protected:Npn \__piton_math_scantokens:n #1 { \normalfont \scantextokens { \begin{math} #1 \end{math} } } \clist_new:N \g__piton_styles_clist \clist_gset:Nn \g__piton_styles_clist { Comment , Comment.LaTeX , Discard , Exception , FormattingType , Identifier , InitialValues , Interpol.Inside , Keyword , Keyword.Constant , Keyword2 , Keyword3 , Keyword4 , Keyword5 , Keyword6 , Keyword7 , Keyword8 , Keyword9 , Name.Builtin , Name.Class , Name.Constructor , Name.Decorator , Name.Field , Name.Function , Name.Module , Name.Namespace , Name.Table , Name.Type , Number , Operator , Operator.Word , Preproc , Prompt , String.Doc , String.Interpol , String.Long , String.Short , Tag , TypeParameter , UserFunction , Directive } \clist_map_inline:Nn \g__piton_styles_clist { \keys_define:nn { piton / Styles } { #1 .value_required:n = true , #1 .code:n = \tl_set:cn { pitonStyle _ \str_if_empty:NF \l__piton_SetPitonStyle_option_str { \l__piton_SetPitonStyle_option_str _ } #1 } { ##1 } } } \keys_define:nn { piton / Styles } { String .meta:n = { String.Long = #1 , String.Short = #1 } , Comment.Math .tl_set:c = pitonStyle _ Comment.Math , ParseAgain.noCR .tl_set:c = pitonStyle _ ParseAgain.noCR , ParseAgain.noCR .value_required:n = true , unknown .code:n = \__piton_error:n { Unknown~key~for~SetPitonStyle } } \clist_gput_left:Nn \g__piton_styles_clist { String } \clist_gsort:Nn \g__piton_styles_clist { \str_compare:nNnTF { #1 } < { #2 } \sort_return_same: \sort_return_swapped: } \SetPitonStyle { Comment = \color[HTML]{0099FF} \itshape , Exception = \color[HTML]{CC0000} , Keyword = \color[HTML]{006699} \bfseries , Keyword.Constant = \color[HTML]{006699} \bfseries , Name.Builtin = \color[HTML]{336666} , Name.Decorator = \color[HTML]{9999FF}, Name.Class = \color[HTML]{00AA88} \bfseries , Name.Function = \color[HTML]{CC00FF} , Name.Namespace = \color[HTML]{00CCFF} , Name.Constructor = \color[HTML]{006000} \bfseries , Name.Field = \color[HTML]{AA6600} , Name.Module = \color[HTML]{0060A0} \bfseries , Name.Table = \color[HTML]{309030} , Number = \color[HTML]{FF6600} , Operator = \color[HTML]{555555} , Operator.Word = \bfseries , String = \color[HTML]{CC3300} , String.Doc = \color[HTML]{CC3300} \itshape , String.Interpol = \color[HTML]{AA0000} , Comment.LaTeX = \normalfont \color[rgb]{.468,.532,.6} , Name.Type = \color[HTML]{336666} , InitialValues = \__piton_piton:n , Interpol.Inside = \color{black}\__piton_piton:n , TypeParameter = \color[HTML]{336666} \itshape , Preproc = \color[HTML]{AA6600} \slshape , Identifier = \__piton_identifier:n , Directive = \color[HTML]{AA6600} , Tag = \colorbox{gray!10}, UserFunction = , Prompt = , ParseAgain.noCR = \__piton_piton_no_cr:n , Discard = \use_none:n } \AtBeginDocument { \bool_if:NT \g__piton_math_comments_bool { \SetPitonStyle { Comment.Math = \__piton_math_scantokens:n } } } \NewDocumentCommand { \SetPitonIdentifier } { o m m } { \clist_set:Nn \l_tmpa_clist { #2 } \tl_if_novalue:nTF { #1 } { \clist_map_inline:Nn \l_tmpa_clist { \cs_set:cpn { PitonIdentifier _ ##1 } { #3 } } } { \str_set:Nx \l_tmpa_str { \str_lowercase:n { #1 } } \str_if_eq:onT \l_tmpa_str { current-language } { \str_set_eq:NN \l_tmpa_str \l_piton_language_str } \clist_map_inline:Nn \l_tmpa_clist { \cs_set:cpn { PitonIdentifier _ \l_tmpa_str _ ##1 } { #3 } } } } \cs_new_protected:Npn \__piton_identifier:n #1 { \cs_if_exist_use:cF { PitonIdentifier _ \l_piton_language_str _ #1 } { \cs_if_exist_use:c { PitonIdentifier _ #1 } } { #1 } } \cs_new_protected:cpn { pitonStyle _ Name.Function.Internal } #1 { { \PitonStyle { Name.Function } { #1 } } \cs_gset_protected:cpn { PitonIdentifier _ \l_piton_language_str _ #1 } { \PitonStyle { UserFunction } } \seq_if_exist:cF { g__piton_functions _ \l_piton_language_str _ seq } { \seq_new:c { g__piton_functions _ \l_piton_language_str _ seq } } \seq_gput_right:cn { g__piton_functions _ \l_piton_language_str _ seq } { #1 } \seq_if_in:NVF \g__piton_languages_seq \l_piton_language_str { \seq_gput_left:NV \g__piton_languages_seq \l_piton_language_str } } \NewDocumentCommand \PitonClearUserFunctions { ! o } { \tl_if_novalue:nTF { #1 } { \__piton_clear_all_functions: } { \__piton_clear_list_functions:n { #1 } } } \cs_new_protected:Npn \__piton_clear_list_functions:n #1 { \clist_set:Nn \l_tmpa_clist { #1 } \clist_map_function:NN \l_tmpa_clist \__piton_clear_functions_i:n \clist_map_inline:nn { #1 } { \seq_gremove_all:Nn \g__piton_languages_seq { ##1 } } } \cs_new_protected:Npn \__piton_clear_functions_i:n #1 { \exp_args:Ne \__piton_clear_functions_ii:n { \str_lowercase:n { #1 } } } \cs_new_protected:Npn \__piton_clear_functions_ii:n #1 { \seq_if_exist:cT { g__piton_functions _ #1 _ seq } { \seq_map_inline:cn { g__piton_functions _ #1 _ seq } { \cs_undefine:c { PitonIdentifier _ #1 _ ##1} } \seq_gclear:c { g__piton_functions _ #1 _ seq } } } \cs_new_protected:Npn \__piton_clear_functions:n #1 { \__piton_clear_functions_i:n { #1 } \seq_gremove_all:Nn \g__piton_languages_seq { #1 } } \cs_new_protected:Npn \__piton_clear_all_functions: { \seq_map_function:NN \g__piton_languages_seq \__piton_clear_functions_i:n \seq_gclear:N \g__piton_languages_seq } \AddToHook { env / piton / begin } { \msg_fatal:nn { piton } { No~environment~piton } } \msg_new:nnn { piton } { No~environment~piton } { There~is~no~environment~piton!\\ There~is~an~environment~{Piton}~and~a~command~ \token_to_str:N \piton\ but~there~is~no~environment~ {piton}.~This~error~is~fatal. } \__piton_msg_new:nn { Language~not~defined } { Language~not~defined \\ The~language~'\l_tmpa_tl'~has~not~been~defined~previously.\\ If~you~go~on,~your~command~\token_to_str:N \NewPitonLanguage\ will~be~ignored. } \__piton_msg_new:nn { bad~version~of~piton.lua } { Bad~number~version~of~'piton.lua'\\ The~file~'piton.lua'~loaded~has~not~the~same~number~of~ version~as~the~file~'piton.sty'.~You~can~go~on~but~you~should~ address~that~issue. } \__piton_msg_new:nn { Unknown~key~NewPitonLanguage } { Unknown~key~for~\token_to_str:N \NewPitonLanguage.\\ The~key~'\l_keys_key_str'~is~unknown.\\ This~key~will~be~ignored.\\ } \__piton_msg_new:nn { Unknown~key~for~SetPitonStyle } { The~style~'\l_keys_key_str'~is~unknown.\\ This~key~will~be~ignored.\\ The~available~styles~are~(in~alphabetic~order):~ \clist_use:Nnnn \g__piton_styles_clist { ~and~ } { ,~ } { ~and~ }. } \__piton_msg_new:nn { Invalid~key } { Wrong~use~of~key.\\ You~can't~use~the~key~'\l_keys_key_str'~here.\\ That~key~will~be~ignored. } \__piton_msg_new:nn { Unknown~key~for~line-numbers } { Unknown~key. \\ The~key~'line-numbers / \l_keys_key_str'~is~unknown.\\ The~available~keys~of~the~family~'line-numbers'~are~(in~ alphabetic~order):~ absolute,~false,~label-empty-lines,~resume,~skip-empty-lines,~ sep,~start~and~true.\\ That~key~will~be~ignored. } \__piton_msg_new:nn { Unknown~key~for~marker } { Unknown~key. \\ The~key~'marker / \l_keys_key_str'~is~unknown.\\ The~available~keys~of~the~family~'marker'~are~(in~ alphabetic~order):~ beginning,~end~and~include-lines.\\ That~key~will~be~ignored. } \__piton_msg_new:nn { bad~range~specification } { Incompatible~keys.\\ You~can't~specify~the~range~of~lines~to~include~by~using~both~ markers~and~explicit~number~of~lines.\\ Your~whole~file~'\l__piton_file_name_str'~will~be~included. } \__piton_msg_new:nn { SyntaxError } { Your~code~of~the~language~"\l_piton_language_str"~is~not~ syntactically~correct.\\ It~won't~be~printed~in~the~PDF~file. } \__piton_msg_new:nn { begin~marker~not~found } { Marker~not~found.\\ The~range~'\l__piton_begin_range_str'~provided~to~the~ command~\token_to_str:N \PitonInputFile\ has~not~been~found.~ The~whole~file~'\l__piton_file_name_str'~will~be~inserted. } \__piton_msg_new:nn { end~marker~not~found } { Marker~not~found.\\ The~marker~of~end~of~the~range~'\l__piton_end_range_str'~ provided~to~the~command~\token_to_str:N \PitonInputFile\ has~not~been~found.~The~file~'\l__piton_file_name_str'~will~ be~inserted~till~the~end. } \__piton_msg_new:nn { Unknown~file } { Unknown~file. \\ The~file~'#1'~is~unknown.\\ Your~command~\token_to_str:N \PitonInputFile\ will~be~discarded. } \__piton_msg_new:nnn { Unknown~key~for~PitonOptions } { Unknown~key. \\ The~key~'\l_keys_key_str'~is~unknown~for~\token_to_str:N \PitonOptions.~ It~will~be~ignored.\\ For~a~list~of~the~available~keys,~type~H~. } { The~available~keys~are~(in~alphabetic~order):~ auto-gobble,~ background-color,~ begin-range,~ break-lines,~ break-lines-in-piton,~ break-lines-in-Piton,~ continuation-symbol,~ continuation-symbol-on-indentation,~ detected-beamer-commands,~ detected-beamer-environments,~ detected-commands,~ end-of-broken-line,~ end-range,~ env-gobble,~ gobble,~ indent-broken-lines,~ language,~ left-margin,~ line-numbers/,~ marker/,~ math-comments,~ path,~ path-write,~ prompt-background-color,~ resume,~ show-spaces,~ show-spaces-in-strings,~ splittable,~ split-on-empty-lines,~ split-separation,~ tabs-auto-gobble,~ tab-size,~ width~and~write. } \__piton_msg_new:nn { label~with~lines~numbers } { You~can't~use~the~command~\token_to_str:N \label\ because~the~key~'line-numbers'~is~not~active.\\ If~you~go~on,~that~command~will~ignored. } \__piton_msg_new:nn { cr~not~allowed } { You~can't~put~any~carriage~return~in~the~argument~ of~a~command~\c_backslash_str \l__piton_beamer_command_str\ within~an~ environment~of~'piton'.~You~should~consider~using~the~ corresponding~environment.\\ That~error~is~fatal. } \__piton_msg_new:nn { overlay~without~beamer } { You~can't~use~an~argument~<...>~for~your~command~ \token_to_str:N \PitonInputFile\ because~you~are~not~ in~Beamer.\\ If~you~go~on,~that~argument~will~be~ignored. } \cs_new_protected:Npn \__piton_test_version:n #1 { \str_if_eq:VnF \PitonFileVersion { #1 } { \__piton_error:n { bad~version~of~piton.lua } } } \hook_gput_code:nnn { begindocument } { . } { \lua_now:n { require ( "piton" ) tex.sprint ( luatexbase.catcodetables.CatcodeTableExpl , "\\__piton_test_version:n {" .. piton_version .. "}" ) } } \ExplSyntaxOff \begin{luacode*} lpeg.locale(lpeg) local P , alpha , C , space , S , V = lpeg.P , lpeg.alpha , lpeg.C , lpeg.space , lpeg.S , lpeg.V local function add(...) local s = P ( false ) for _ , x in ipairs({...}) do s = s + x end return s end local my_lpeg = P { "E" , E = ( V "F" * ( "," * V "F" ) ^ 0 ) / add , F = space ^ 0 * ( ( alpha ^ 1 ) / "\\%0" ) * space ^ 0 } function piton.addDetectedCommands( key_value ) piton.DetectedCommands = piton.DetectedCommands + my_lpeg : match ( key_value ) end function piton.addBeamerCommands( key_value ) piton.BeamerCommands = piton.BeamerCommands + my_lpeg : match ( key_value ) end local function insert(...) local s = piton.beamer_environments for _ , x in ipairs({...}) do table.insert(s,x) end return s end local my_lpeg_bis = P { "E" , E = ( V "F" * ( "," * V "F" ) ^ 0 ) / insert , F = space ^ 0 * ( alpha ^ 1 ) * space ^ 0 } function piton.addBeamerEnvironments( key_value ) piton.beamer_environments = my_lpeg_bis : match ( key_value ) end \end{luacode*} \endinput %% %% End of file `piton.sty'.