diff options
Diffstat (limited to 'Master/texmf-dist/tex/lualatex/piton')
-rw-r--r-- | Master/texmf-dist/tex/lualatex/piton/piton.lua | 1232 | ||||
-rw-r--r-- | Master/texmf-dist/tex/lualatex/piton/piton.sty | 1709 |
2 files changed, 1637 insertions, 1304 deletions
diff --git a/Master/texmf-dist/tex/lualatex/piton/piton.lua b/Master/texmf-dist/tex/lualatex/piton/piton.lua new file mode 100644 index 00000000000..5c9d3e539db --- /dev/null +++ b/Master/texmf-dist/tex/lualatex/piton/piton.lua @@ -0,0 +1,1232 @@ + + +if piton.comment_latex == nil then piton.comment_latex = ">" end +piton.comment_latex = "#" .. piton.comment_latex +function piton.open_brace () + tex.sprint("{") +end +function piton.close_brace () + tex.sprint("}") +end +local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc +local Cf, Cs , Cg , Cmt , Cb = lpeg.Cf, lpeg.Cs, lpeg.Cg , lpeg.Cmt , lpeg.Cb +local R = lpeg.R +local function Q(pattern) + return Ct ( Cc ( luatexbase.catcodetables.CatcodeTableOther ) * C ( pattern ) ) +end +local function L(pattern) + return Ct ( C ( pattern ) ) +end +local function Lc(string) + return Cc ( { luatexbase.catcodetables.expl , string } ) +end +local function K(style, pattern) + return + Lc ( "{\\PitonStyle{" .. style .. "}{" ) + * Q ( pattern ) + * Lc ( "}}" ) +end +local function WithStyle(style,pattern) + return + Ct ( Cc "Open" * Cc ( "{\\PitonStyle{" .. style .. "}{" ) * Cc "}}" ) + * pattern + * Ct ( Cc "Close" ) +end +Escape = P ( false ) +if piton.begin_escape ~= nil +then + Escape = + P(piton.begin_escape) + * L ( ( 1 - P(piton.end_escape) ) ^ 1 ) + * P(piton.end_escape) +end +EscapeMath = P ( false ) +if piton.begin_escape_math ~= nil +then + EscapeMath = + P(piton.begin_escape_math) + * Lc ( "\\ensuremath{" ) + * L ( ( 1 - P(piton.end_escape_math) ) ^ 1 ) + * Lc ( "}" ) + * P(piton.end_escape_math) +end +lpeg.locale(lpeg) +local alpha, digit = lpeg.alpha, lpeg.digit +local space = P " " +local letter = alpha + P "_" + + P "â" + P "à" + P "ç" + P "é" + P "è" + P "ê" + P "ë" + P "ï" + P "î" + + P "ô" + P "û" + P "ü" + P "Â" + P "À" + P "Ç" + P "É" + P "È" + P "Ê" + + P "Ë" + P "Ï" + P "Î" + P "Ô" + P "Û" + P "Ü" + +local alphanum = letter + digit +local identifier = letter * alphanum ^ 0 +local Identifier = K ( 'Identifier' , identifier) +local Number = + K ( 'Number' , + ( digit^1 * P "." * digit^0 + digit^0 * P "." * digit^1 + digit^1 ) + * ( S "eE" * S "+-" ^ -1 * digit^1 ) ^ -1 + + digit^1 + ) +local Word +if piton.begin_escape ~= nil -- before : '' +then Word = Q ( ( ( 1 - space - P(piton.begin_escape) - P(piton.end_escape) ) + - S "'\"\r[()]" - digit ) ^ 1 ) +else Word = Q ( ( ( 1 - space ) - S "'\"\r[()]" - digit ) ^ 1 ) +end +local Space = ( Q " " ) ^ 1 + +local SkipSpace = ( Q " " ) ^ 0 + +local Punct = Q ( S ".,:;!" ) + +local Tab = P "\t" * Lc ( '\\l__piton_tab_tl' ) +local SpaceIndentation = Lc ( '\\__piton_an_indentation_space:' ) * ( Q " " ) +local Delim = Q ( S "[()]" ) +local VisualSpace = space * Lc "\\l__piton_space_tl" +local Beamer = P ( false ) +local BeamerBeginEnvironments = P ( true ) +local BeamerEndEnvironments = P ( true ) +if piton_beamer +then + local BeamerNamesEnvironments = + P "uncoverenv" + P "onlyenv" + P "visibleenv" + P "invisibleenv" + + P "alertenv" + P "actionenv" + BeamerBeginEnvironments = + ( space ^ 0 * + L + ( + P "\\begin{" * BeamerNamesEnvironments * "}" + * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1 + ) + * P "\r" + ) ^ 0 + BeamerEndEnvironments = + ( space ^ 0 * + L ( P "\\end{" * BeamerNamesEnvironments * P "}" ) + * P "\r" + ) ^ 0 + function OneBeamerEnvironment(name,lpeg) + return + Ct ( Cc "Open" + * C ( + P ( "\\begin{" .. name .. "}" ) + * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 + ) + * Cc ( "\\end{" .. name .. "}" ) + ) + * ( + C ( ( 1 - P ( "\\end{" .. name .. "}" ) ) ^ 0 ) + / ( function (s) return lpeg : match(s) end ) + ) + * P ( "\\end{" .. name .. "}" ) * Ct ( Cc "Close" ) + end +end +local languages = { } +local Operator = + K ( 'Operator' , + P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" + + P "//" + P "**" + S "-~+/*%=<>&.@|" + ) + +local OperatorWord = + K ( 'Operator.Word' , P "in" + P "is" + P "and" + P "or" + P "not" ) + +local Keyword = + K ( 'Keyword' , + P "as" + P "assert" + P "break" + P "case" + P "class" + P "continue" + + P "def" + P "del" + P "elif" + P "else" + P "except" + P "exec" + + P "finally" + P "for" + P "from" + P "global" + P "if" + P "import" + + P "lambda" + P "non local" + P "pass" + P "return" + P "try" + + P "while" + P "with" + P "yield" + P "yield from" ) + + K ( 'Keyword.Constant' ,P "True" + P "False" + P "None" ) + +local Builtin = + K ( 'Name.Builtin' , + P "__import__" + P "abs" + P "all" + P "any" + P "bin" + P "bool" + + P "bytearray" + P "bytes" + P "chr" + P "classmethod" + P "compile" + + P "complex" + P "delattr" + P "dict" + P "dir" + P "divmod" + + P "enumerate" + P "eval" + P "filter" + P "float" + P "format" + + P "frozenset" + P "getattr" + P "globals" + P "hasattr" + P "hash" + + P "hex" + P "id" + P "input" + P "int" + P "isinstance" + P "issubclass" + + P "iter" + P "len" + P "list" + P "locals" + P "map" + P "max" + + P "memoryview" + P "min" + P "next" + P "object" + P "oct" + P "open" + + P "ord" + P "pow" + P "print" + P "property" + P "range" + P "repr" + + P "reversed" + P "round" + P "set" + P "setattr" + P "slice" + P "sorted" + + P "staticmethod" + P "str" + P "sum" + P "super" + P "tuple" + P "type" + + P "vars" + P "zip" ) + +local Exception = + K ( 'Exception' , + P "ArithmeticError" + P "AssertionError" + P "AttributeError" + + P "BaseException" + P "BufferError" + P "BytesWarning" + P "DeprecationWarning" + + P "EOFError" + P "EnvironmentError" + P "Exception" + P "FloatingPointError" + + P "FutureWarning" + P "GeneratorExit" + P "IOError" + P "ImportError" + + P "ImportWarning" + P "IndentationError" + P "IndexError" + P "KeyError" + + P "KeyboardInterrupt" + P "LookupError" + P "MemoryError" + P "NameError" + + P "NotImplementedError" + P "OSError" + P "OverflowError" + + P "PendingDeprecationWarning" + P "ReferenceError" + P "ResourceWarning" + + P "RuntimeError" + P "RuntimeWarning" + P "StopIteration" + + P "SyntaxError" + P "SyntaxWarning" + P "SystemError" + P "SystemExit" + + P "TabError" + P "TypeError" + P "UnboundLocalError" + P "UnicodeDecodeError" + + P "UnicodeEncodeError" + P "UnicodeError" + P "UnicodeTranslateError" + + P "UnicodeWarning" + P "UserWarning" + P "ValueError" + P "VMSError" + + P "Warning" + P "WindowsError" + P "ZeroDivisionError" + + P "BlockingIOError" + P "ChildProcessError" + P "ConnectionError" + + P "BrokenPipeError" + P "ConnectionAbortedError" + P "ConnectionRefusedError" + + P "ConnectionResetError" + P "FileExistsError" + P "FileNotFoundError" + + P "InterruptedError" + P "IsADirectoryError" + P "NotADirectoryError" + + P "PermissionError" + P "ProcessLookupError" + P "TimeoutError" + + P "StopAsyncIteration" + P "ModuleNotFoundError" + P "RecursionError" ) + +local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q ( P "(" ) + +local Decorator = K ( 'Name.Decorator' , P "@" * letter^1 ) +local DefClass = + K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier ) +local ImportAs = + K ( 'Keyword' , P "import" ) + * Space + * K ( 'Name.Namespace' , + identifier * ( P "." * identifier ) ^ 0 ) + * ( + ( Space * K ( 'Keyword' , P "as" ) * Space + * K ( 'Name.Namespace' , identifier ) ) + + + ( SkipSpace * Q ( P "," ) * SkipSpace + * K ( 'Name.Namespace' , identifier ) ) ^ 0 + ) +local FromImport = + K ( 'Keyword' , P "from" ) + * Space * K ( 'Name.Namespace' , identifier ) + * Space * K ( 'Keyword' , P "import" ) +local PercentInterpol = + K ( 'String.Interpol' , + P "%" + * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1 + * ( S "-#0 +" ) ^ 0 + * ( digit ^ 1 + P "*" ) ^ -1 + * ( P "." * ( digit ^ 1 + P "*" ) ) ^ -1 + * ( S "HlL" ) ^ -1 + * S "sdfFeExXorgiGauc%" + ) +local SingleShortString = + WithStyle ( 'String.Short' , + Q ( P "f'" + P "F'" ) + * ( + K ( 'String.Interpol' , P "{" ) + * K ( 'Interpol.Inside' , ( 1 - S "}':" ) ^ 0 ) + * Q ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1 + * K ( 'String.Interpol' , P "}" ) + + + VisualSpace + + + Q ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 ) + ) ^ 0 + * Q ( P "'" ) + + + Q ( P "'" + P "r'" + P "R'" ) + * ( Q ( ( P "\\'" + 1 - S " '\r%" ) ^ 1 ) + + VisualSpace + + PercentInterpol + + Q ( P "%" ) + ) ^ 0 + * Q ( P "'" ) ) + +local DoubleShortString = + WithStyle ( 'String.Short' , + Q ( P "f\"" + P "F\"" ) + * ( + K ( 'String.Interpol' , P "{" ) + * Q ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' ) + * ( K ( 'String.Interpol' , P ":" ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1 + * K ( 'String.Interpol' , P "}" ) + + + VisualSpace + + + Q ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 ) + ) ^ 0 + * Q ( P "\"" ) + + + Q ( P "\"" + P "r\"" + P "R\"" ) + * ( Q ( ( P "\\\"" + 1 - S " \"\r%" ) ^ 1 ) + + VisualSpace + + PercentInterpol + + Q ( P "%" ) + ) ^ 0 + * Q ( P "\"" ) ) + +local ShortString = SingleShortString + DoubleShortString +local balanced_braces = + P { "E" , + E = + ( + P "{" * V "E" * P "}" + + + ShortString + + + ( 1 - S "{}" ) + ) ^ 0 + } +if piton_beamer +then + Beamer = + L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) + + + Ct ( Cc "Open" + * C ( + ( + P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible" + + P "\\invisible" + P "\\action" + ) + * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 + * P "{" + ) + * Cc "}" + ) + * ( C ( balanced_braces ) / (function (s) return MainLoopPython:match(s) end ) ) + * P "}" * Ct ( Cc "Close" ) + + OneBeamerEnvironment ( "uncoverenv" , MainLoopPython ) + + OneBeamerEnvironment ( "onlyenv" , MainLoopPython ) + + OneBeamerEnvironment ( "visibleenv" , MainLoopPython ) + + OneBeamerEnvironment ( "invisibleenv" , MainLoopPython ) + + OneBeamerEnvironment ( "alertenv" , MainLoopPython ) + + OneBeamerEnvironment ( "actionenv" , MainLoopPython ) + + + L ( + ( P "\\alt" ) + * P "<" * (1 - P ">") ^ 0 * P ">" + * P "{" + ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}{" ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}" ) + + + L ( + ( P "\\temporal" ) + * P "<" * (1 - P ">") ^ 0 * P ">" + * P "{" + ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}{" ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}{" ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}" ) +end +local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1 +local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 ) +local EOL = + P "\r" + * + ( + ( space^0 * -1 ) + + + Ct ( + Cc "EOL" + * + Ct ( + Lc "\\__piton_end_line:" + * BeamerEndEnvironments + * BeamerBeginEnvironments + * PromptHastyDetection + * Lc "\\__piton_newline: \\__piton_begin_line:" + * Prompt + ) + ) + ) + * + SpaceIndentation ^ 0 +local SingleLongString = + WithStyle ( 'String.Long' , + ( Q ( S "fF" * P "'''" ) + * ( + K ( 'String.Interpol' , P "{" ) + * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "'''" ) ^ 0 ) + * Q ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1 + * K ( 'String.Interpol' , P "}" ) + + + Q ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 ) + + + EOL + ) ^ 0 + + + Q ( ( S "rR" ) ^ -1 * P "'''" ) + * ( + Q ( ( 1 - P "'''" - S "\r%" ) ^ 1 ) + + + PercentInterpol + + + P "%" + + + EOL + ) ^ 0 + ) + * Q ( P "'''" ) ) + +local DoubleLongString = + WithStyle ( 'String.Long' , + ( + Q ( S "fF" * P "\"\"\"" ) + * ( + K ( 'String.Interpol', P "{" ) + * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) + * Q ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1 + * K ( 'String.Interpol' , P "}" ) + + + Q ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 ) + + + EOL + ) ^ 0 + + + Q ( ( S "rR" ) ^ -1 * P "\"\"\"" ) + * ( + Q ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 ) + + + PercentInterpol + + + P "%" + + + EOL + ) ^ 0 + ) + * Q ( P "\"\"\"" ) + ) +local LongString = SingleLongString + DoubleLongString +local StringDoc = + K ( 'String.Doc' , P "\"\"\"" ) + * ( K ( 'String.Doc' , (1 - P "\"\"\"" - P "\r" ) ^ 0 ) * EOL + * Tab ^ 0 + ) ^ 0 + * K ( 'String.Doc' , ( 1 - P "\"\"\"" - P "\r" ) ^ 0 * P "\"\"\"" ) +local CommentMath = + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" + +local Comment = + WithStyle ( 'Comment' , + Q ( P "#" ) + * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) + * ( EOL + -1 ) +local CommentLaTeX = + P(piton.comment_latex) + * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" + * L ( ( 1 - P "\r" ) ^ 0 ) + * Lc "}}" + * ( EOL + -1 ) +local expression = + P { "E" , + E = ( P "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'" + + P "\"" * (P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\"" + + P "{" * V "F" * P "}" + + P "(" * V "F" * P ")" + + P "[" * V "F" * P "]" + + ( 1 - S "{}()[]\r," ) ) ^ 0 , + F = ( P "{" * V "F" * P "}" + + P "(" * V "F" * P ")" + + P "[" * V "F" * P "]" + + ( 1 - S "{}()[]\r\"'" ) ) ^ 0 + } +local Param = + SkipSpace * Identifier * SkipSpace + * ( + K ( 'InitialValues' , P "=" * expression ) + + Q ( P ":" ) * SkipSpace * K ( 'Name.Type' , letter ^ 1 ) + ) ^ -1 +local Params = ( Param * ( Q "," * Param ) ^ 0 ) ^ -1 +local DefFunction = + K ( 'Keyword' , P "def" ) + * Space + * K ( 'Name.Function.Internal' , identifier ) + * SkipSpace + * Q ( P "(" ) * Params * Q ( P ")" ) + * SkipSpace + * ( Q ( P "->" ) * SkipSpace * K ( 'Name.Type' , identifier ) ) ^ -1 + * K ( 'ParseAgain' , ( 1 - S ":\r" )^0 ) + * Q ( P ":" ) + * ( SkipSpace + * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL + * Tab ^ 0 + * SkipSpace + * StringDoc ^ 0 -- there may be additionnal docstrings + ) ^ -1 +local ExceptionInConsole = Exception * Q ( ( 1 - P "\r" ) ^ 0 ) * EOL +local MainPython = + EOL + + Space + + Tab + + Escape + EscapeMath + + CommentLaTeX + + Beamer + + LongString + + Comment + + ExceptionInConsole + + Delim + + Operator + + OperatorWord * ( Space + Punct + Delim + EOL + -1 ) + + ShortString + + Punct + + FromImport + + RaiseException + + DefFunction + + DefClass + + Keyword * ( Space + Punct + Delim + EOL + -1 ) + + Decorator + + Builtin * ( Space + Punct + Delim + EOL + -1 ) + + Identifier + + Number + + Word +MainLoopPython = + ( ( space^1 * -1 ) + + MainPython + ) ^ 0 +local python = P ( true ) + +python = + Ct ( + ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 + * BeamerBeginEnvironments + * PromptHastyDetection + * Lc '\\__piton_begin_line:' + * Prompt + * SpaceIndentation ^ 0 + * MainLoopPython + * -1 + * Lc '\\__piton_end_line:' + ) +languages['python'] = python +local Delim = Q ( P "[|" + P "|]" + S "[()]" ) +local Punct = Q ( S ",:;!" ) +local cap_identifier = R "AZ" * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 +local Constructor = K ( 'Name.Constructor' , cap_identifier ) +local ModuleType = K ( 'Name.Type' , cap_identifier ) +local identifier = + ( R "az" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 +local Identifier = K ( 'Identifier' , identifier ) +local expression_for_fields = + P { "E" , + E = ( P "{" * V "F" * P "}" + + P "(" * V "F" * P ")" + + P "[" * V "F" * P "]" + + P "\"" * (P "\\\"" + 1 - S "\"\r" )^0 * P "\"" + + P "'" * ( P "\\'" + 1 - S "'\r" )^0 * P "'" + + ( 1 - S "{}()[]\r;" ) ) ^ 0 , + F = ( P "{" * V "F" * P "}" + + P "(" * V "F" * P ")" + + P "[" * V "F" * P "]" + + ( 1 - S "{}()[]\r\"'" ) ) ^ 0 + } +local OneFieldDefinition = + ( K ( 'KeyWord' , P "mutable" ) * SkipSpace ) ^ -1 + * K ( 'Name.Field' , identifier ) * SkipSpace + * Q ":" * SkipSpace + * K ( 'Name.Type' , expression_for_fields ) + * SkipSpace + +local OneField = + K ( 'Name.Field' , identifier ) * SkipSpace + * Q "=" * SkipSpace + * ( C ( expression_for_fields ) / ( function (s) return LoopOCaml:match(s) end ) ) + * SkipSpace + +local Record = + Q "{" * SkipSpace + * + ( + OneFieldDefinition * ( Q ";" * SkipSpace * OneFieldDefinition ) ^ 0 + + + OneField * ( Q ";" * SkipSpace * OneField ) ^ 0 + ) + * + Q "}" +local DotNotation = + ( + K ( 'Name.Module' , cap_identifier ) + * Q "." + * ( Identifier + Constructor + Q "(" + Q "[" + Q "{" ) + + + + Identifier + * Q "." + * K ( 'Name.Field' , identifier ) + ) + * ( Q "." * K ( 'Name.Field' , identifier ) ) ^ 0 +local Operator = + K ( 'Operator' , + P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" + + P "||" + P "&&" + P "//" + P "**" + P ";;" + P "::" + P "->" + + P "+." + P "-." + P "*." + P "/." + + S "-~+/*%=<>&@|" + ) + +local OperatorWord = + K ( 'Operator.Word' , + P "and" + P "asr" + P "land" + P "lor" + P "lsl" + P "lxor" + + P "mod" + P "or" ) + +local Keyword = + K ( 'Keyword' , + P "assert" + P "as" + P "begin" + P "class" + P "constraint" + P "done" + + P "downto" + P "do" + P "else" + P "end" + P "exception" + P "external" + + P "for" + P "function" + P "functor" + P "fun" + P "if" + + P "include" + P "inherit" + P "initializer" + P "in" + P "lazy" + P "let" + + P "match" + P "method" + P "module" + P "mutable" + P "new" + P "object" + + P "of" + P "open" + P "private" + P "raise" + P "rec" + P "sig" + + P "struct" + P "then" + P "to" + P "try" + P "type" + + P "value" + P "val" + P "virtual" + P "when" + P "while" + P "with" ) + + K ( 'Keyword.Constant' , P "true" + P "false" ) + +local Builtin = + K ( 'Name.Builtin' , P "not" + P "incr" + P "decr" + P "fst" + P "snd" ) +local Exception = + K ( 'Exception' , + P "Division_by_zero" + P "End_of_File" + P "Failure" + + P "Invalid_argument" + P "Match_failure" + P "Not_found" + + P "Out_of_memory" + P "Stack_overflow" + P "Sys_blocked_io" + + P "Sys_error" + P "Undefined_recursive_module" ) +local Char = + K ( 'String.Short' , P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" ) +local balanced_braces = + P { "E" , + E = + ( + P "{" * V "E" * P "}" + + + P "\"" * ( 1 - S "\"" ) ^ 0 * P "\"" -- OCaml strings + + + ( 1 - S "{}" ) + ) ^ 0 + } +if piton_beamer +then + Beamer = + L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) + + + Ct ( Cc "Open" + * C ( + ( + P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible" + + P "\\invisible" + P "\\action" + ) + * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 + * P "{" + ) + * Cc "}" + ) + * ( C ( balanced_braces ) / (function (s) return MainLoopOCaml:match(s) end ) ) + * P "}" * Ct ( Cc "Close" ) + + OneBeamerEnvironment ( "uncoverenv" , MainLoopOCaml ) + + OneBeamerEnvironment ( "onlyenv" , MainLoopOCaml ) + + OneBeamerEnvironment ( "visibleenv" , MainLoopOCaml ) + + OneBeamerEnvironment ( "invisibleenv" , MainLoopOCaml ) + + OneBeamerEnvironment ( "alertenv" , MainLoopOCaml ) + + OneBeamerEnvironment ( "actionenv" , MainLoopOCaml ) + + + L ( + ( P "\\alt" ) + * P "<" * (1 - P ">") ^ 0 * P ">" + * P "{" + ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}{" ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}" ) + + + L ( + ( P "\\temporal" ) + * P "<" * (1 - P ">") ^ 0 * P ">" + * P "{" + ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}{" ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}{" ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}" ) +end +local EOL = + P "\r" + * + ( + ( space^0 * -1 ) + + + Ct ( + Cc "EOL" + * + Ct ( + Lc "\\__piton_end_line:" + * BeamerEndEnvironments + * BeamerBeginEnvironments + * PromptHastyDetection + * Lc "\\__piton_newline: \\__piton_begin_line:" + * Prompt + ) + ) + ) + * + SpaceIndentation ^ 0 +local ocaml_string = + Q ( P "\"" ) + * ( + VisualSpace + + + Q ( ( 1 - S " \"\r" ) ^ 1 ) + + + EOL + ) ^ 0 + * Q ( P "\"" ) +local String = WithStyle ( 'String.Long' , ocaml_string ) +local ext = ( R "az" + P "_" ) ^ 0 +local open = "{" * Cg(ext, 'init') * "|" +local close = "|" * C(ext) * "}" +local closeeq = + Cmt ( close * Cb('init'), + function (s, i, a, b) return a==b end ) +local QuotedStringBis = + WithStyle ( 'String.Long' , + ( + VisualSpace + + + Q ( ( 1 - S " \r" ) ^ 1 ) + + + EOL + ) ^ 0 ) + +local QuotedString = + C ( open * ( 1 - closeeq ) ^ 0 * close ) / + ( function (s) return QuotedStringBis : match(s) end ) +local Comment = + WithStyle ( 'Comment' , + P { + "A" , + A = Q "(*" + * ( V "A" + + Q ( ( 1 - P "(*" - P "*)" - S "\r$\"" ) ^ 1 ) -- $ + + ocaml_string + + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" -- $ + + EOL + ) ^ 0 + * Q "*)" + } ) +local balanced_parens = + P { "E" , + E = + ( + P "(" * V "E" * P ")" + + + ( 1 - S "()" ) + ) ^ 0 + } +local Argument = + K ( 'Identifier' , identifier ) + + Q "(" * SkipSpace + * K ( 'Identifier' , identifier ) * SkipSpace + * Q ":" * SkipSpace + * K ( 'Name.Type' , balanced_parens ) * SkipSpace + * Q ")" +local DefFunction = + K ( 'Keyword' , P "let open" ) + * Space + * K ( 'Name.Module' , cap_identifier ) + + + K ( 'Keyword' , P "let rec" + P "let" + P "and" ) + * Space + * K ( 'Name.Function.Internal' , identifier ) + * Space + * ( + Q "=" * SkipSpace * K ( 'Keyword' , P "function" ) + + + Argument + * ( SkipSpace * Argument ) ^ 0 + * ( + SkipSpace + * Q ":" + * K ( 'Name.Type' , ( 1 - P "=" ) ^ 0 ) + ) ^ -1 + ) +local DefModule = + K ( 'Keyword' , P "module" ) * Space + * + ( + K ( 'Keyword' , P "type" ) * Space + * K ( 'Name.Type' , cap_identifier ) + + + K ( 'Name.Module' , cap_identifier ) * SkipSpace + * + ( + Q "(" * SkipSpace + * K ( 'Name.Module' , cap_identifier ) * SkipSpace + * Q ":" * SkipSpace + * K ( 'Name.Type' , cap_identifier ) * SkipSpace + * + ( + Q "," * SkipSpace + * K ( 'Name.Module' , cap_identifier ) * SkipSpace + * Q ":" * SkipSpace + * K ( 'Name.Type' , cap_identifier ) * SkipSpace + ) ^ 0 + * Q ")" + ) ^ -1 + * + ( + Q "=" * SkipSpace + * K ( 'Name.Module' , cap_identifier ) * SkipSpace + * Q "(" + * K ( 'Name.Module' , cap_identifier ) * SkipSpace + * + ( + Q "," + * + K ( 'Name.Module' , cap_identifier ) * SkipSpace + ) ^ 0 + * Q ")" + ) ^ -1 + ) + + + K ( 'Keyword' , P "include" + P "open" ) + * Space * K ( 'Name.Module' , cap_identifier ) +local TypeParameter = K ( 'TypeParameter' , P "'" * alpha * # ( 1 - P "'" ) ) +MainOCaml = + EOL + + Space + + Tab + + Escape + EscapeMath + + Beamer + + TypeParameter + + String + QuotedString + Char + + Comment + + Delim + + Operator + + Punct + + FromImport + + Exception + + DefFunction + + DefModule + + Record + + Keyword * ( Space + Punct + Delim + EOL + -1 ) + + OperatorWord * ( Space + Punct + Delim + EOL + -1 ) + + Builtin * ( Space + Punct + Delim + EOL + -1 ) + + DotNotation + + Constructor + + Identifier + + Number + + Word + +LoopOCaml = MainOCaml ^ 0 + +MainLoopOCaml = + ( ( space^1 * -1 ) + + MainOCaml + ) ^ 0 +local ocaml = P ( true ) + +ocaml = + Ct ( + ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 + * BeamerBeginEnvironments + * Lc ( '\\__piton_begin_line:' ) + * SpaceIndentation ^ 0 + * MainLoopOCaml + * -1 + * Lc ( '\\__piton_end_line:' ) + ) +languages['ocaml'] = ocaml +local Operator = + K ( 'Operator' , + P "!=" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + + P "||" + P "&&" + S "-~+/*%=<>&.@|!" + ) + +local Keyword = + K ( 'Keyword' , + P "alignas" + P "asm" + P "auto" + P "break" + P "case" + P "catch" + + P "class" + P "const" + P "constexpr" + P "continue" + + P "decltype" + P "do" + P "else" + P "enum" + P "extern" + + P "for" + P "goto" + P "if" + P "nexcept" + P "private" + P "public" + + P "register" + P "restricted" + P "return" + P "static" + P "static_assert" + + P "struct" + P "switch" + P "thread_local" + P "throw" + P "try" + + P "typedef" + P "union" + P "using" + P "virtual" + P "volatile" + + P "while" + ) + + K ( 'Keyword.Constant' , + P "default" + P "false" + P "NULL" + P "nullptr" + P "true" + ) + +local Builtin = + K ( 'Name.Builtin' , + P "alignof" + P "malloc" + P "printf" + P "scanf" + P "sizeof" + ) + +local Type = + K ( 'Name.Type' , + P "bool" + P "char" + P "char16_t" + P "char32_t" + P "double" + + P "float" + P "int" + P "int8_t" + P "int16_t" + P "int32_t" + + P "int64_t" + P "long" + P "short" + P "signed" + P "unsigned" + + P "void" + P "wchar_t" + ) + +local DefFunction = + Type + * Space + * K ( 'Name.Function.Internal' , identifier ) + * SkipSpace + * # P "(" +local DefClass = + K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier ) +local String = + WithStyle ( 'String.Long' , + Q "\"" + * ( VisualSpace + + K ( 'String.Interpol' , + P "%" * ( S "difcspxXou" + P "ld" + P "li" + P "hd" + P "hi" ) + ) + + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 ) + ) ^ 0 + * Q "\"" + ) +local balanced_braces = + P { "E" , + E = + ( + P "{" * V "E" * P "}" + + + String + + + ( 1 - S "{}" ) + ) ^ 0 + } +if piton_beamer +then + Beamer = + L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) + + + Ct ( Cc "Open" + * C ( + ( + P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible" + + P "\\invisible" + P "\\action" + ) + * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 + * P "{" + ) + * Cc "}" + ) + * ( C ( balanced_braces ) / (function (s) return MainLoopC:match(s) end ) ) + * P "}" * Ct ( Cc "Close" ) + + OneBeamerEnvironment ( "uncoverenv" , MainLoopC ) + + OneBeamerEnvironment ( "onlyenv" , MainLoopC ) + + OneBeamerEnvironment ( "visibleenv" , MainLoopC ) + + OneBeamerEnvironment ( "invisibleenv" , MainLoopC ) + + OneBeamerEnvironment ( "alertenv" , MainLoopC ) + + OneBeamerEnvironment ( "actionenv" , MainLoopC ) + + + L ( + ( P "\\alt" ) + * P "<" * (1 - P ">") ^ 0 * P ">" + * P "{" + ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}{" ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}" ) + + + L ( + ( P "\\temporal" ) + * P "<" * (1 - P ">") ^ 0 * P ">" + * P "{" + ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}{" ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}{" ) + * K ( 'ParseAgain.noCR' , balanced_braces ) + * L ( P "}" ) +end +local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1 +local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 ) +local EOL = + P "\r" + * + ( + ( space^0 * -1 ) + + + Ct ( + Cc "EOL" + * + Ct ( + Lc "\\__piton_end_line:" + * BeamerEndEnvironments + * BeamerBeginEnvironments + * PromptHastyDetection + * Lc "\\__piton_newline: \\__piton_begin_line:" + * Prompt + ) + ) + ) + * + SpaceIndentation ^ 0 +local Preproc = + K ( 'Preproc' , P "#" * (1 - P "\r" ) ^ 0 ) * ( EOL + -1 ) +local CommentMath = + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" + +local Comment = + WithStyle ( 'Comment' , + Q ( P "//" ) + * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) + * ( EOL + -1 ) + +local LongComment = + WithStyle ( 'Comment' , + Q ( P "/*" ) + * ( CommentMath + Q ( ( 1 - P "*/" - S "$\r" ) ^ 1 ) + EOL ) ^ 0 + * Q ( P "*/" ) + ) -- $ +local CommentLaTeX = + P(piton.comment_latex) + * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" + * L ( ( 1 - P "\r" ) ^ 0 ) + * Lc "}}" + * ( EOL + -1 ) +local MainC = + EOL + + Space + + Tab + + Escape + EscapeMath + + CommentLaTeX + + Beamer + + Preproc + + Comment + LongComment + + Delim + + Operator + + String + + Punct + + DefFunction + + DefClass + + Type * ( Q ( "*" ) ^ -1 + Space + Punct + Delim + EOL + -1 ) + + Keyword * ( Space + Punct + Delim + EOL + -1 ) + + Builtin * ( Space + Punct + Delim + EOL + -1 ) + + Identifier + + Number + + Word +MainLoopC = + ( ( space^1 * -1 ) + + MainC + ) ^ 0 +languageC = + Ct ( + ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 + * BeamerBeginEnvironments + * PromptHastyDetection + * Lc '\\__piton_begin_line:' + * Prompt + * SpaceIndentation ^ 0 + * MainLoopC + * -1 + * Lc '\\__piton_end_line:' + ) +languages['c'] = languageC +function piton.Parse(language,code) + local t = languages[language] : match ( code ) + if t == nil + then + tex.sprint("\\PitonSyntaxError") + return -- to exit in force the function + end + local left_stack = {} + local right_stack = {} + for _ , one_item in ipairs(t) + do + if one_item[1] == "EOL" + then + for _ , s in ipairs(right_stack) + do tex.sprint(s) + end + for _ , s in ipairs(one_item[2]) + do tex.tprint(s) + end + for _ , s in ipairs(left_stack) + do tex.sprint(s) + end + else + if one_item[1] == "Open" + then + tex.sprint( one_item[2] ) + table.insert(left_stack,one_item[2]) + table.insert(right_stack,one_item[3]) + else + if one_item[1] == "Close" + then + tex.sprint( right_stack[#right_stack] ) + left_stack[#left_stack] = nil + right_stack[#right_stack] = nil + else + tex.tprint(one_item) + end + end + end + end +end +function piton.ParseFile(language,name,first_line,last_line) + local s = '' + local i = 0 + for line in io.lines(name) + do i = i + 1 + if i >= first_line + then s = s .. '\r' .. line + end + if i >= last_line then break end + end + if string.byte(s,1) == 13 + then if string.byte(s,2) == 239 + then if string.byte(s,3) == 187 + then if string.byte(s,4) == 191 + then s = string.sub(s,5,-1) + end + end + end + end + piton.Parse(language,s) +end +function piton.ParseBis(language,code) + local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( code ) + return piton.Parse(language,s) +end +function piton.ParseTer(language,code) + local s = ( Cs ( ( P '\\__piton_breakable_space:' / ' ' + 1 ) ^ 0 ) ) + : match ( code ) + return piton.Parse(language,s) +end +local function gobble(n,code) + function concat(acc,new_value) + return acc .. new_value + end + if n==0 + then return code + else + return Cf ( + Cc ( "" ) * + ( 1 - P "\r" ) ^ (-n) * C ( ( 1 - P "\r" ) ^ 0 ) + * ( C ( P "\r" ) + * ( 1 - P "\r" ) ^ (-n) + * C ( ( 1 - P "\r" ) ^ 0 ) + ) ^ 0 , + concat + ) : match ( code ) + end +end +local function add(acc,new_value) + return acc + new_value +end +local AutoGobbleLPEG = + ( space ^ 0 * P "\r" ) ^ -1 + * Cf ( + ( + ( P " " ) ^ 0 * P "\r" + + + Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add ) + * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 * P "\r" + ) ^ 0 + * + ( Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add ) + * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 , + math.min + ) +local TabsAutoGobbleLPEG = + ( space ^ 0 * P "\r" ) ^ -1 + * Cf ( + ( + ( P "\t" ) ^ 0 * P "\r" + + + Cf ( Cc(0) * ( P "\t" * Cc(1) ) ^ 0 , add ) + * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 * P "\r" + ) ^ 0 + * + ( Cf ( Cc(0) * ( P "\t" * Cc(1) ) ^ 0 , add ) + * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 , + math.min + ) +local EnvGobbleLPEG = + ( ( 1 - P "\r" ) ^ 0 * P "\r" ) ^ 0 + * Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add ) * -1 +function piton.GobbleParse(language,n,code) + if n==-1 + then n = AutoGobbleLPEG : match(code) + else if n==-2 + then n = EnvGobbleLPEG : match(code) + else if n==-3 + then n = TabsAutoGobbleLPEG : match(code) + end + end + end + piton.Parse(language,gobble(n,code)) +end +function piton.CountLines(code) + local count = 0 + for i in code : gmatch ( "\r" ) do count = count + 1 end + tex.sprint( + luatexbase.catcodetables.expl , + '\\int_set:Nn \\l__piton_nb_lines_int {' .. count .. '}' ) +end +function piton.CountNonEmptyLines(code) + local count = 0 + count = + ( Cf ( Cc(0) * + ( + ( P " " ) ^ 0 * P "\r" + + ( 1 - P "\r" ) ^ 0 * P "\r" * Cc(1) + ) ^ 0 + * (1 - P "\r" ) ^ 0 , + add + ) * -1 ) : match (code) + tex.sprint( + luatexbase.catcodetables.expl , + '\\int_set:Nn \\l__piton_nb_non_empty_lines_int {' .. count .. '}' ) +end +function piton.CountLinesFile(name) + local count = 0 + for line in io.lines(name) do count = count + 1 end + tex.sprint( + luatexbase.catcodetables.expl , + '\\int_set:Nn \\l__piton_nb_lines_int {' .. count .. '}' ) +end +function piton.CountNonEmptyLinesFile(name) + local count = 0 + for line in io.lines(name) + do if not ( ( ( P " " ) ^ 0 * -1 ) : match ( line ) ) + then count = count + 1 + end + end + tex.sprint( + luatexbase.catcodetables.expl , + '\\int_set:Nn \\l__piton_nb_non_empty_lines_int {' .. count .. '}' ) +end +function piton.ComputeRange(marker_beginning,marker_end,file_name) + local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( marker_beginning ) + local t = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( marker_end ) + local first_line = -1 + local count = 0 + local last_found = false + for line in io.lines(file_name) + do if first_line == -1 + then if string.sub(line,1,#s) == s + then first_line = count + end + else if string.sub(line,1,#t) == t + then last_found = true + break + end + end + count = count + 1 + end + if first_line == -1 + then tex.sprint("\\PitonBeginMarkerNotFound") + else if last_found == false + then tex.sprint("\\PitonEndMarkerNotFound") + end + end + tex.sprint( + luatexbase.catcodetables.expl , + '\\int_set:Nn \\l__piton_first_line_int {' .. first_line .. ' + 2 }' + .. '\\int_set:Nn \\l__piton_last_line_int {' .. count .. ' }' ) +end + diff --git a/Master/texmf-dist/tex/lualatex/piton/piton.sty b/Master/texmf-dist/tex/lualatex/piton/piton.sty index 43df8801425..a23aa1d0320 100644 --- a/Master/texmf-dist/tex/lualatex/piton/piton.sty +++ b/Master/texmf-dist/tex/lualatex/piton/piton.sty @@ -4,7 +4,7 @@ %% %% The original source files were: %% -%% piton.dtx (with options: `package') +%% piton.dtx (with options: `STY') %% %% Copyright (C) 2022-2023 by F. Pantigny %% @@ -18,8 +18,8 @@ %% and version 1.3 or later is part of all distributions of %% LaTeX version 2005/12/01 or later. %% -\def\myfileversion{2.0} -\def\myfiledate{2023/08/01} +\def\myfileversion{2.1} +\def\myfiledate{2023/08/26} \NeedsTeXFormat{LaTeX2e} @@ -29,7 +29,14 @@ {\myfiledate} {\myfileversion} {Highlight Python codes with LPEG on LuaLaTeX} -\msg_new:nnn { piton } { LuaLaTeX~mandatory } +\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 } } +\__piton_msg_new:nn { LuaLaTeX~mandatory } { LuaLaTeX~is~mandatory.\\ The~package~'piton'~requires~the~engine~LuaLaTeX.\\ @@ -39,59 +46,71 @@ } \sys_if_engine_luatex:F { \msg_critical:nn { piton } { LuaLaTeX~mandatory } } \RequirePackage { luatexbase } -\bool_new:N \c__piton_footnotehyper_bool -\bool_new:N \c__piton_footnote_bool -\bool_new:N \c__piton_math_comments_bool -\bool_new:N \c__piton_beamer_bool +\__piton_msg_new:nn { piton.lua~not~found } + { + The~file~'piton.lua'~can't~be~found.\\ + The package~'piton'~won't be loaded. + } +\file_if_exist:nF { piton.lua } + { \msg_critical: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_set:N = \c__piton_footnote_bool , - footnotehyper .bool_set:N = \c__piton_footnotehyper_bool , - escape-inside .tl_set:N = \c__piton_escape_inside_tl , - escape-inside .initial:n = , - comment-latex .code:n = { \lua_now:n { comment_latex = "#1" } } , - comment-latex .value_required:n = true , - math-comments .bool_set:N = \c__piton_math_comments_bool , - math-comments .default:n = true , - beamer .bool_set:N = \c__piton_beamer_bool , - beamer .default:n = true , - unknown .code:n = \msg_error:nn { piton } { unknown~key~for~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 , + + escape-inside .code:n = \__piton_error:n { key-escape-inside-deleted } , + math-comments .code:n = \__piton_error:n { moved~to~preamble } , + comment-latex .code:n = \__piton_error:n { moved~to~preamble } , + + unknown .code:n = \__piton_error:n { Unknown~key~for~package } + } +\__piton_msg_new:nn { key-escape-inside-deleted } + { + The~key~'escape-inside'~has~been~deleted.~You~must~now~use~ + the~keys~'begin-escape'~and~'end-escape'~in~ + \token_to_str:N \PitonOptions.\\ + That~key~will~be~ignored. } -\msg_new:nnn { piton } { unknown~key~for~package } +\__piton_msg_new:nn { moved~to~preamble } + { + The~key~'\l_keys_key_str'~*must*~now~be~used~with~ + \token_to_str:N \PitonOptions`in~the~preamble~of~your~ + document.\\ + That~key~will~be~ignored. + } +\__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',~'comment-latex',~'escape-inside',~'footnote',~'footnotehyper'~and~ - 'math-comments'.~Other~keys~are~available~in~\token_to_str:N \PitonOptions.\\ + are~'beamer',~'footnote',~'footnotehyper'.~Other~keys~are~available~in~ + \token_to_str:N \PitonOptions.\\ That~key~will~be~ignored. } \ProcessKeysOptions { piton / package } -\begingroup -\cs_new_protected:Npn \__piton_set_escape_char:nn #1 #2 - { - \lua_now:n { piton_begin_escape = "#1" } - \lua_now:n { piton_end_escape = "#2" } - } -\cs_generate_variant:Nn \__piton_set_escape_char:nn { x x } -\__piton_set_escape_char:xx - { \tl_head:V \c__piton_escape_inside_tl } - { \tl_tail:V \c__piton_escape_inside_tl } -\endgroup -\@ifclassloaded { beamer } { \bool_set_true:N \c__piton_beamer_bool } { } -\bool_if:NT \c__piton_beamer_bool { \lua_now:n { piton_beamer = true } } +\@ifclassloaded { beamer } { \bool_gset_true:N \g__piton_beamer_bool } { } +\@ifpackageloaded { beamerarticle } { \bool_gset_true:N \g__piton_beamer_bool } { } +\bool_if:NT \g__piton_beamer_bool { \lua_now:n { piton_beamer = true } } \hook_gput_code:nnn { begindocument } { . } { \@ifpackageloaded { xcolor } { } { \msg_fatal:nn { piton } { xcolor~not~loaded } } } -\msg_new:nnn { piton } { xcolor~not~loaded } +\__piton_msg_new:nn { xcolor~not~loaded } { xcolor~not~loaded \\ The~package~'xcolor'~is~required~by~'piton'.\\ This~error~is~fatal. } -\msg_new:nnn { piton } { footnote~with~footnotehyper~package } +\__piton_msg_new:nn { footnote~with~footnotehyper~package } { Footnote~forbidden.\\ You~can't~use~the~option~'footnote'~because~the~package~ @@ -101,7 +120,7 @@ of~the~package~footnotehyper.\\ If~you~go~on,~the~package~footnote~won't~be~loaded. } -\msg_new:nnn { piton } { footnotehyper~with~footnote~package } +\__piton_msg_new:nn { footnotehyper~with~footnote~package } { You~can't~use~the~option~'footnotehyper'~because~the~package~ footnote~has~already~been~loaded.~ @@ -110,29 +129,33 @@ of~the~package~footnote.\\ If~you~go~on,~the~package~footnotehyper~won't~be~loaded. } -\bool_if:NT \c__piton_footnote_bool +\bool_if:NT \g__piton_footnote_bool { \@ifclassloaded { beamer } - { \bool_set_false:N \c__piton_footnote_bool } + { \bool_gset_false:N \g__piton_footnote_bool } { \@ifpackageloaded { footnotehyper } { \__piton_error:n { footnote~with~footnotehyper~package } } { \usepackage { footnote } } } } -\bool_if:NT \c__piton_footnotehyper_bool +\bool_if:NT \g__piton_footnotehyper_bool { \@ifclassloaded { beamer } - { \bool_set_false:N \c__piton_footnote_bool } + { \bool_gset_false:N \g__piton_footnote_bool } { \@ifpackageloaded { footnote } { \__piton_error:n { footnotehyper~with~footnote~package } } { \usepackage { footnotehyper } } - \bool_set_true:N \c__piton_footnote_bool + \bool_gset_true:N \g__piton_footnote_bool } } +\lua_now:n { piton = piton~or { } } \str_new:N \l__piton_language_str \str_set:Nn \l__piton_language_str { python } +\bool_new:N \l__piton_in_PitonOptions_bool +\bool_new:N \l__piton_in_PitonInputFile_bool +\bool_new:N \g__piton_in_document_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 @@ -141,6 +164,9 @@ \int_set:Nn \l__piton_splittable_int { 100 } \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 \bool_new:N \l__piton_show_spaces_bool \bool_new:N \l__piton_break_lines_in_Piton_bool @@ -194,12 +220,12 @@ } \@esphack } - { \msg_error:nn { piton } { label~with~lines~numbers } } + { \__piton_error:n { label~with~lines~numbers } } } -\cs_new_protected:Npn \__piton_open_brace: - { \directlua { piton.open_brace() } } -\cs_new_protected:Npn \__piton_close_brace: - { \directlua { piton.close_brace() } } +\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: { \directlua { piton.open_brace() } } +\cs_new_protected:Npn \__piton_close_brace: { \directlua { piton.close_brace() } } \tl_new:N \g__piton_begin_line_hook_tl \cs_new_protected:Npn \__piton_prompt: { @@ -246,9 +272,22 @@ \skip_horizontal:N \l__piton_left_margin_dim \bool_if:NT \l__piton_line_numbers_bool { - \bool_if:NF \l__piton_all_line_numbers_bool - { \tl_if_eq:nnF { #1 } { \PitonStyle {Prompt}{} } } + \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 { @@ -321,9 +360,9 @@ { \l__piton_nb_lines_int - \g__piton_line_int } > \l__piton_splittable_int { \egroup - \bool_if:NT \c__piton_footnote_bool { \end { savenotes } } + \bool_if:NT \g__piton_footnote_bool { \end { savenotes } } \par \mode_leave_vertical: % \newline - \bool_if:NT \c__piton_footnote_bool { \begin { savenotes } } + \bool_if:NT \g__piton_footnote_bool { \begin { savenotes } } \vtop \bgroup } } @@ -355,10 +394,108 @@ { \hbox { ~ } } } \bool_new:N \l__piton_line_numbers_bool -\bool_new:N \l__piton_all_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 +\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 +\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_if:NTF \l__piton_in_PitonOptions_bool + { Invalid~key } + { + \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 + } + \bool_lazy_or:nnF + \l__piton_in_PitonInputFile_bool + \l__piton_in_PitonOptions_bool + { \__piton_error:n { Invalid~key } } , + 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 , + + unknown .code:n = \__piton_error:n { Unknown~key~for~line-numbers } + } \keys_define:nn { PitonOptions } { + 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_set: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 , @@ -370,21 +507,27 @@ 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 , - line-numbers .bool_set:N = \l__piton_line_numbers_bool , - line-numbers .default:n = true , - all-line-numbers .code:n = - \bool_set_true:N \l__piton_line_numbers_bool - \bool_set_true:N \l__piton_all_line_numbers_bool , - all-line-numbers .value_forbidden:n = true , - resume .bool_set:N = \l__piton_resume_bool , - resume .value_forbidden: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 = + + width .code:n = \str_if_eq:nnTF { #1 } { min } { \bool_set_true:N \l__piton_width_min_bool @@ -394,7 +537,8 @@ \bool_set_false:N \l__piton_width_min_bool \dim_set:Nn \l__piton_width_dim { #1 } } , - width .value_required:n = true , + width .value_required:n = true , + left-margin .code:n = \str_if_eq:nnTF { #1 } { auto } { @@ -406,8 +550,7 @@ \bool_set_false:N \l__piton_left_margin_auto_bool } , left-margin .value_required:n = true , - numbers-sep .dim_set:N = \l__piton_numbers_sep_dim , - numbers-sep .value_required:n = true , + tab-size .code:n = \__piton_set_tab_tl:n { #1 } , tab-size .value_required:n = true , show-spaces .bool_set:N = \l__piton_show_spaces_bool , @@ -428,17 +571,68 @@ 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 , - unknown .code:n = - \msg_error:nn { piton } { Unknown~key~for~PitonOptions } + + 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 { } { \keys_set:nn { PitonOptions } } +\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 + } +\hook_gput_code:nnn { begindocument } { . } + { \bool_gset_true:N \g__piton_in_document_bool } \int_new:N \g__piton_visual_line_int \cs_new_protected:Npn \__piton_print_number: { - \int_gincr:N \g__piton_visual_line_int \hbox_overlap_left:n { - { \color { gray } \footnotesize \int_to_arabic:n \g__piton_visual_line_int } + { + \color { gray } + \footnotesize + \int_to_arabic:n \g__piton_visual_line_int + } \skip_horizontal:N \l__piton_numbers_sep_dim } } @@ -589,13 +783,6 @@ \dim_zero:N \parindent \cs_set_eq:NN \label \__piton_label:n } -\keys_define:nn { PitonInputFile } - { - first-line .int_set:N = \l__piton_first_line_int , - first-line .value_required:n = true , - last-line .int_set:N = \l__piton_last_line_int , - last-line .value_required:n = true , - } \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 @@ -603,11 +790,7 @@ \hbox_set:Nn \l_tmpa_box { \footnotesize - \bool_if:NTF \l__piton_all_line_numbers_bool - { - \int_to_arabic:n - { \g__piton_visual_line_int + \l__piton_nb_lines_int } - } + \bool_if:NTF \l__piton_skip_empty_lines_bool { \lua_now:n { piton.#1(token.scan_argument()) } @@ -615,6 +798,10 @@ \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 } @@ -663,7 +850,7 @@ \__piton_compute_width: \ttfamily \dim_zero:N \parskip % added 2023/07/06 - \bool_if:NT \c__piton_footnote_bool { \begin { savenotes } } + \bool_if:NT \g__piton_footnote_bool { \begin { savenotes } } \vtop \bgroup \lua_now:e { @@ -677,7 +864,7 @@ { ##1 } \vspace { 2.5 pt } \egroup - \bool_if:NT \c__piton_footnote_bool { \end { savenotes } } + \bool_if:NT \g__piton_footnote_bool { \end { savenotes } } \bool_if:NT \l__piton_width_min_bool \__piton_width_to_aux: \end { #1 } \__piton_write_aux: @@ -686,6 +873,8 @@ { #3 \__piton_pre_env: + \int_compare:nNnT \l__piton_number_lines_start_int > 0 + { \int_gset:Nn \g__piton_visual_line_int { \l__piton_number_lines_start_int - 1 } } \group_begin: \tl_map_function:nN { \ \\ \{ \} \$ \& \# \^ \_ \% \~ \^^I } @@ -695,65 +884,116 @@ { #4 } \AddToHook { env / #1 / begin } { \char_set_catcode_other:N \^^M } } -\bool_if:NTF \c__piton_beamer_bool +\bool_if:NTF \g__piton_beamer_bool { \NewPitonEnvironment { Piton } { d < > O { } } { - \PitonOptions { #2 } + \keys_set:nn { PitonOptions } { #2 } \IfValueTF { #1 } { \begin { uncoverenv } < #1 > } { \begin { uncoverenv } } } { \end { uncoverenv } } } - { \NewPitonEnvironment { Piton } { O { } } - { \PitonOptions { #1 } } + { + \NewPitonEnvironment { Piton } { O { } } + { \keys_set:nn { PitonOptions } { #1 } } { } } \NewDocumentCommand { \PitonInputFile } { d < > O { } m } { \file_if_exist:nTF { #3 } { \__piton_input_file:nnn { #1 } { #2 } { #3 } } - { \msg_error:nnn { piton } { unknown~file } { #3 } } + { \msg_error:nnn { piton } { Unknown~file } { #3 } } } \cs_new_protected:Npn \__piton_input_file:nnn #1 #2 #3 { + \str_set:Nn \l__piton_file_name_str { #3 } \tl_if_novalue:nF { #1 } { - \bool_if:NTF \c__piton_beamer_bool + \bool_if:NTF \g__piton_beamer_bool { \begin { uncoverenv } < #1 > } - { \msg_error:nn { piton } { overlay~without~beamer } } + { \__piton_error: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 - \keys_set:nn { PitonInputFile } { #2 } + \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 > 0 + || \int_compare_p:nNn \l__piton_last_line_int < \c_max_int + ) + && ! \str_if_empty_p:N \l__piton_begin_range_str + } + { + \__piton_error: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 > 0 + { + \int_gset:Nn \g__piton_visual_line_int + { \l__piton_number_lines_start_int - 1 } + } + \int_compare:nNnT \g__piton_visual_line_int < 0 + { \int_gzero:N \g__piton_visual_line_int } \mode_if_vertical:TF \mode_leave_vertical: \newline - \lua_now:n { piton.CountLinesFile(token.scan_argument()) } { #3 } + \lua_now:e { piton.CountLinesFile('\l__piton_file_name_str') } \__piton_compute_left_margin:nn { CountNonEmptyLinesFile } { #3 } \__piton_compute_width: \ttfamily - \bool_if:NT \c__piton_footnote_bool { \begin { savenotes } } + \bool_if:NT \g__piton_footnote_bool { \begin { savenotes } } \vtop \bgroup \lua_now:e { piton.ParseFile( - '\l__piton_language_str', - token.scan_argument() , + '\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 ) } - { #3 } \egroup - \bool_if:NT \c__piton_footnote_bool { \end { savenotes } } + \bool_if:NT \g__piton_footnote_bool { \end { savenotes } } \bool_if:NT \l__piton_width_min_bool \__piton_width_to_aux: \group_end: \tl_if_novalue:nF { #1 } - { \bool_if:NT \c__piton_beamer_bool { \end { uncoverenv } } } + { \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 } { \use:c { pitonStyle #1 } } \NewDocumentCommand { \SetPitonStyle } { } { \keys_set:nn { piton / Styles } } \cs_new_protected:Npn \__piton_math_scantokens:n #1 @@ -812,7 +1052,7 @@ ParseAgain.noCR .tl_set:c = pitonStyle ParseAgain.noCR , ParseAgain.noCR .value_required:n = true , unknown .code:n = - \msg_error:nn { piton } { Unknown~key~for~SetPitonStyle } + \__piton_error:n { Unknown~key~for~SetPitonStyle } } \clist_gput_left:Nn \g__piton_styles_clist { String } \clist_gsort:Nn \g__piton_styles_clist @@ -853,7 +1093,7 @@ ParseAgain.noCR = \__piton_piton_no_cr:n , ParseAgain = \__piton_piton:n , } -\bool_if:NT \c__piton_math_comments_bool { \SetPitonStyle { Comment.Math } } +\bool_if:NT \g__piton_math_comments_bool { \SetPitonStyle { Comment.Math } } \cs_new_protected:Npn \__piton_identifier:n #1 { \cs_if_exist_use:c { PitonIdentifier _ \l__piton_language_str _ #1 } { #1 } } \keys_define:nn { PitonOptions } @@ -903,21 +1143,71 @@ \token_to_str:N \piton\ but~there~is~no~environment~ {piton}.~This~error~is~fatal. } -\msg_new:nnn { piton } { Unknown~key~for~SetPitonStyle } +\__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~ }. } -\msg_new:nnn { piton } { syntax~error } +\__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 { syntax~error } { Your~code~is~not~syntactically~correct.\\ It~won't~be~printed~in~the~PDF~file. } \NewDocumentCommand \PitonSyntaxError { } - { \msg_error:nn { piton } { syntax~error } } -\msg_new:nnn { piton } { unknown~file } + { \__piton_error:n { syntax~error } } +\__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. + } +\NewDocumentCommand \PitonBeginMarkerNotFound { } + { \__piton_error:n { begin~marker~not~found } } +\NewDocumentCommand \PitonEndMarkerNotFound { } + { \__piton_error:n { end~marker~not~found } } +\__piton_msg_new:nn { Unknown~file } { Unknown~file. \\ The~file~'#1'~is~unknown.\\ @@ -932,7 +1222,6 @@ } { The~available~keys~are~(in~alphabetic~order):~ - all-line-numbers,~ auto-gobble,~ background-color,~ break-lines,~ @@ -941,13 +1230,15 @@ continuation-symbol,~ continuation-symbol-on-indentation,~ end-of-broken-line,~ + end-range,~ env-gobble,~ gobble,~ identifiers,~ indent-broken-lines,~ language,~ left-margin,~ - line-numbers,~ + line-numbers/,~ + marker/,~ prompt-background-color,~ resume,~ show-spaces,~ @@ -956,14 +1247,13 @@ tabs-auto-gobble,~ tab-size~and~width. } -\msg_new:nnn { piton } { label~with~lines~numbers } +\__piton_msg_new:nn { label~with~lines~numbers } { You~can't~use~the~command~\token_to_str:N \label\ - because~the~key~'line-numbers'~(or~'all-line-numbers')~ - is~not~active.\\ + because~the~key~'line-numbers'~is~not~active.\\ If~you~go~on,~that~command~will~ignored. } -\msg_new:nnn { piton } { cr~not~allowed } +\__piton_msg_new:nn { cr~not~allowed } { You~can't~put~any~carriage~return~in~the~argument~ of~a~command~\c_backslash_str @@ -972,1206 +1262,17 @@ corresponding~environment.\\ That~error~is~fatal. } -\msg_new:nnn { piton } { overlay~without~beamer } +\__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. } -\msg_new:nnn { Piton } { Python~error } +\__piton_msg_new:nn { Python~error } { A~Python~error~has~been~detected. } -\ExplSyntaxOff -\RequirePackage{luacode} -\begin{luacode*} -piton = piton or { } -if piton.comment_latex == nil then piton.comment_latex = ">" end -piton.comment_latex = "#" .. piton.comment_latex -function piton.open_brace () - tex.sprint("{") -end -function piton.close_brace () - tex.sprint("}") -end -local P, S, V, C, Ct, Cc = lpeg.P, lpeg.S, lpeg.V, lpeg.C, lpeg.Ct, lpeg.Cc -local Cf, Cs , Cg , Cmt , Cb = lpeg.Cf, lpeg.Cs, lpeg.Cg , lpeg.Cmt , lpeg.Cb -local R = lpeg.R -local function Q(pattern) - return Ct ( Cc ( luatexbase.catcodetables.CatcodeTableOther ) * C ( pattern ) ) -end -local function L(pattern) - return Ct ( C ( pattern ) ) -end -local function Lc(string) - return Cc ( { luatexbase.catcodetables.expl , string } ) -end -local function K(style, pattern) - return - Lc ( "{\\PitonStyle{" .. style .. "}{" ) - * Q ( pattern ) - * Lc ( "}}" ) -end -local function WithStyle(style,pattern) - return - Ct ( Cc "Open" * Cc ( "{\\PitonStyle{" .. style .. "}{" ) * Cc "}}" ) - * pattern - * Ct ( Cc "Close" ) -end -local Escape = - P(piton_begin_escape) - * L ( ( 1 - P(piton_end_escape) ) ^ 1 ) - * P(piton_end_escape) -lpeg.locale(lpeg) -local alpha, digit = lpeg.alpha, lpeg.digit -local space = P " " -local letter = alpha + P "_" - + P "â" + P "à" + P "ç" + P "é" + P "è" + P "ê" + P "ë" + P "ï" + P "î" - + P "ô" + P "û" + P "ü" + P "Â" + P "À" + P "Ç" + P "É" + P "È" + P "Ê" - + P "Ë" + P "Ï" + P "Î" + P "Ô" + P "Û" + P "Ü" - -local alphanum = letter + digit -local identifier = letter * alphanum ^ 0 -local Identifier = K ( 'Identifier' , identifier) -local Number = - K ( 'Number' , - ( digit^1 * P "." * digit^0 + digit^0 * P "." * digit^1 + digit^1 ) - * ( S "eE" * S "+-" ^ -1 * digit^1 ) ^ -1 - + digit^1 - ) -local Word -if piton_begin_escape ~= '' -then Word = Q ( ( ( 1 - space - P(piton_begin_escape) - P(piton_end_escape) ) - - S "'\"\r[()]" - digit ) ^ 1 ) -else Word = Q ( ( ( 1 - space ) - S "'\"\r[()]" - digit ) ^ 1 ) -end -local Space = ( Q " " ) ^ 1 - -local SkipSpace = ( Q " " ) ^ 0 - -local Punct = Q ( S ".,:;!" ) - -local Tab = P "\t" * Lc ( '\\l__piton_tab_tl' ) -local SpaceIndentation = Lc ( '\\__piton_an_indentation_space:' ) * ( Q " " ) -local Delim = Q ( S "[()]" ) -local VisualSpace = space * Lc "\\l__piton_space_tl" -local Beamer = P ( false ) -local BeamerBeginEnvironments = P ( true ) -local BeamerEndEnvironments = P ( true ) -if piton_beamer -then - local BeamerNamesEnvironments = - P "uncoverenv" + P "onlyenv" + P "visibleenv" + P "invisibleenv" - + P "alertenv" + P "actionenv" - BeamerBeginEnvironments = - ( space ^ 0 * - L - ( - P "\\begin{" * BeamerNamesEnvironments * "}" - * ( P "<" * ( 1 - P ">" ) ^ 0 * P ">" ) ^ -1 - ) - * P "\r" - ) ^ 0 - BeamerEndEnvironments = - ( space ^ 0 * - L ( P "\\end{" * BeamerNamesEnvironments * P "}" ) - * P "\r" - ) ^ 0 - function OneBeamerEnvironment(name,lpeg) - return - Ct ( Cc "Open" - * C ( - P ( "\\begin{" .. name .. "}" ) - * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 - ) - * Cc ( "\\end{" .. name .. "}" ) - ) - * ( - C ( ( 1 - P ( "\\end{" .. name .. "}" ) ) ^ 0 ) - / ( function (s) return lpeg : match(s) end ) - ) - * P ( "\\end{" .. name .. "}" ) * Ct ( Cc "Close" ) - end -end -local languages = { } -local Operator = - K ( 'Operator' , - P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" - + P "//" + P "**" + S "-~+/*%=<>&.@|" - ) - -local OperatorWord = - K ( 'Operator.Word' , P "in" + P "is" + P "and" + P "or" + P "not" ) - -local Keyword = - K ( 'Keyword' , - P "as" + P "assert" + P "break" + P "case" + P "class" + P "continue" - + P "def" + P "del" + P "elif" + P "else" + P "except" + P "exec" - + P "finally" + P "for" + P "from" + P "global" + P "if" + P "import" - + P "lambda" + P "non local" + P "pass" + P "return" + P "try" - + P "while" + P "with" + P "yield" + P "yield from" ) - + K ( 'Keyword.Constant' ,P "True" + P "False" + P "None" ) - -local Builtin = - K ( 'Name.Builtin' , - P "__import__" + P "abs" + P "all" + P "any" + P "bin" + P "bool" - + P "bytearray" + P "bytes" + P "chr" + P "classmethod" + P "compile" - + P "complex" + P "delattr" + P "dict" + P "dir" + P "divmod" - + P "enumerate" + P "eval" + P "filter" + P "float" + P "format" - + P "frozenset" + P "getattr" + P "globals" + P "hasattr" + P "hash" - + P "hex" + P "id" + P "input" + P "int" + P "isinstance" + P "issubclass" - + P "iter" + P "len" + P "list" + P "locals" + P "map" + P "max" - + P "memoryview" + P "min" + P "next" + P "object" + P "oct" + P "open" - + P "ord" + P "pow" + P "print" + P "property" + P "range" + P "repr" - + P "reversed" + P "round" + P "set" + P "setattr" + P "slice" + P "sorted" - + P "staticmethod" + P "str" + P "sum" + P "super" + P "tuple" + P "type" - + P "vars" + P "zip" ) - -local Exception = - K ( 'Exception' , - P "ArithmeticError" + P "AssertionError" + P "AttributeError" - + P "BaseException" + P "BufferError" + P "BytesWarning" + P "DeprecationWarning" - + P "EOFError" + P "EnvironmentError" + P "Exception" + P "FloatingPointError" - + P "FutureWarning" + P "GeneratorExit" + P "IOError" + P "ImportError" - + P "ImportWarning" + P "IndentationError" + P "IndexError" + P "KeyError" - + P "KeyboardInterrupt" + P "LookupError" + P "MemoryError" + P "NameError" - + P "NotImplementedError" + P "OSError" + P "OverflowError" - + P "PendingDeprecationWarning" + P "ReferenceError" + P "ResourceWarning" - + P "RuntimeError" + P "RuntimeWarning" + P "StopIteration" - + P "SyntaxError" + P "SyntaxWarning" + P "SystemError" + P "SystemExit" - + P "TabError" + P "TypeError" + P "UnboundLocalError" + P "UnicodeDecodeError" - + P "UnicodeEncodeError" + P "UnicodeError" + P "UnicodeTranslateError" - + P "UnicodeWarning" + P "UserWarning" + P "ValueError" + P "VMSError" - + P "Warning" + P "WindowsError" + P "ZeroDivisionError" - + P "BlockingIOError" + P "ChildProcessError" + P "ConnectionError" - + P "BrokenPipeError" + P "ConnectionAbortedError" + P "ConnectionRefusedError" - + P "ConnectionResetError" + P "FileExistsError" + P "FileNotFoundError" - + P "InterruptedError" + P "IsADirectoryError" + P "NotADirectoryError" - + P "PermissionError" + P "ProcessLookupError" + P "TimeoutError" - + P "StopAsyncIteration" + P "ModuleNotFoundError" + P "RecursionError" ) - -local RaiseException = K ( 'Keyword' , P "raise" ) * SkipSpace * Exception * Q ( P "(" ) - -local Decorator = K ( 'Name.Decorator' , P "@" * letter^1 ) -local DefClass = - K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier ) -local ImportAs = - K ( 'Keyword' , P "import" ) - * Space - * K ( 'Name.Namespace' , - identifier * ( P "." * identifier ) ^ 0 ) - * ( - ( Space * K ( 'Keyword' , P "as" ) * Space - * K ( 'Name.Namespace' , identifier ) ) - + - ( SkipSpace * Q ( P "," ) * SkipSpace - * K ( 'Name.Namespace' , identifier ) ) ^ 0 - ) -local FromImport = - K ( 'Keyword' , P "from" ) - * Space * K ( 'Name.Namespace' , identifier ) - * Space * K ( 'Keyword' , P "import" ) -local PercentInterpol = - K ( 'String.Interpol' , - P "%" - * ( P "(" * alphanum ^ 1 * P ")" ) ^ -1 - * ( S "-#0 +" ) ^ 0 - * ( digit ^ 1 + P "*" ) ^ -1 - * ( P "." * ( digit ^ 1 + P "*" ) ) ^ -1 - * ( S "HlL" ) ^ -1 - * S "sdfFeExXorgiGauc%" - ) -local SingleShortString = - WithStyle ( 'String.Short' , - Q ( P "f'" + P "F'" ) - * ( - K ( 'String.Interpol' , P "{" ) - * K ( 'Interpol.Inside' , ( 1 - S "}':" ) ^ 0 ) - * Q ( P ":" * (1 - S "}:'") ^ 0 ) ^ -1 - * K ( 'String.Interpol' , P "}" ) - + - VisualSpace - + - Q ( ( P "\\'" + P "{{" + P "}}" + 1 - S " {}'" ) ^ 1 ) - ) ^ 0 - * Q ( P "'" ) - + - Q ( P "'" + P "r'" + P "R'" ) - * ( Q ( ( P "\\'" + 1 - S " '\r%" ) ^ 1 ) - + VisualSpace - + PercentInterpol - + Q ( P "%" ) - ) ^ 0 - * Q ( P "'" ) ) - -local DoubleShortString = - WithStyle ( 'String.Short' , - Q ( P "f\"" + P "F\"" ) - * ( - K ( 'String.Interpol' , P "{" ) - * Q ( ( 1 - S "}\":" ) ^ 0 , 'Interpol.Inside' ) - * ( K ( 'String.Interpol' , P ":" ) * Q ( (1 - S "}:\"") ^ 0 ) ) ^ -1 - * K ( 'String.Interpol' , P "}" ) - + - VisualSpace - + - Q ( ( P "\\\"" + P "{{" + P "}}" + 1 - S " {}\"" ) ^ 1 ) - ) ^ 0 - * Q ( P "\"" ) - + - Q ( P "\"" + P "r\"" + P "R\"" ) - * ( Q ( ( P "\\\"" + 1 - S " \"\r%" ) ^ 1 ) - + VisualSpace - + PercentInterpol - + Q ( P "%" ) - ) ^ 0 - * Q ( P "\"" ) ) - -local ShortString = SingleShortString + DoubleShortString -local balanced_braces = - P { "E" , - E = - ( - P "{" * V "E" * P "}" - + - ShortString - + - ( 1 - S "{}" ) - ) ^ 0 - } -if piton_beamer -then - Beamer = - L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) - + - Ct ( Cc "Open" - * C ( - ( - P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible" - + P "\\invisible" + P "\\action" - ) - * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 - * P "{" - ) - * Cc "}" - ) - * ( C ( balanced_braces ) / (function (s) return MainLoopPython:match(s) end ) ) - * P "}" * Ct ( Cc "Close" ) - + OneBeamerEnvironment ( "uncoverenv" , MainLoopPython ) - + OneBeamerEnvironment ( "onlyenv" , MainLoopPython ) - + OneBeamerEnvironment ( "visibleenv" , MainLoopPython ) - + OneBeamerEnvironment ( "invisibleenv" , MainLoopPython ) - + OneBeamerEnvironment ( "alertenv" , MainLoopPython ) - + OneBeamerEnvironment ( "actionenv" , MainLoopPython ) - + - L ( - ( P "\\alt" ) - * P "<" * (1 - P ">") ^ 0 * P ">" - * P "{" - ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}" ) - + - L ( - ( P "\\temporal" ) - * P "<" * (1 - P ">") ^ 0 * P ">" - * P "{" - ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}" ) -end -local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1 -local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 ) -local EOL = - P "\r" - * - ( - ( space^0 * -1 ) - + - Ct ( - Cc "EOL" - * - Ct ( - Lc "\\__piton_end_line:" - * BeamerEndEnvironments - * BeamerBeginEnvironments - * PromptHastyDetection - * Lc "\\__piton_newline: \\__piton_begin_line:" - * Prompt - ) - ) - ) - * - SpaceIndentation ^ 0 -local SingleLongString = - WithStyle ( 'String.Long' , - ( Q ( S "fF" * P "'''" ) - * ( - K ( 'String.Interpol' , P "{" ) - * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "'''" ) ^ 0 ) - * Q ( P ":" * (1 - S "}:\r" - P "'''" ) ^ 0 ) ^ -1 - * K ( 'String.Interpol' , P "}" ) - + - Q ( ( 1 - P "'''" - S "{}'\r" ) ^ 1 ) - + - EOL - ) ^ 0 - + - Q ( ( S "rR" ) ^ -1 * P "'''" ) - * ( - Q ( ( 1 - P "'''" - S "\r%" ) ^ 1 ) - + - PercentInterpol - + - P "%" - + - EOL - ) ^ 0 - ) - * Q ( P "'''" ) ) - -local DoubleLongString = - WithStyle ( 'String.Long' , - ( - Q ( S "fF" * P "\"\"\"" ) - * ( - K ( 'String.Interpol', P "{" ) - * K ( 'Interpol.Inside' , ( 1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) - * Q ( P ":" * (1 - S "}:\r" - P "\"\"\"" ) ^ 0 ) ^ -1 - * K ( 'String.Interpol' , P "}" ) - + - Q ( ( 1 - P "\"\"\"" - S "{}\"\r" ) ^ 1 ) - + - EOL - ) ^ 0 - + - Q ( ( S "rR" ) ^ -1 * P "\"\"\"" ) - * ( - Q ( ( 1 - P "\"\"\"" - S "%\r" ) ^ 1 ) - + - PercentInterpol - + - P "%" - + - EOL - ) ^ 0 - ) - * Q ( P "\"\"\"" ) - ) -local LongString = SingleLongString + DoubleLongString -local StringDoc = - K ( 'String.Doc' , P "\"\"\"" ) - * ( K ( 'String.Doc' , (1 - P "\"\"\"" - P "\r" ) ^ 0 ) * EOL - * Tab ^ 0 - ) ^ 0 - * K ( 'String.Doc' , ( 1 - P "\"\"\"" - P "\r" ) ^ 0 * P "\"\"\"" ) -local CommentMath = - P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" - -local Comment = - WithStyle ( 'Comment' , - Q ( P "#" ) - * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) - * ( EOL + -1 ) -local CommentLaTeX = - P(piton.comment_latex) - * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" - * L ( ( 1 - P "\r" ) ^ 0 ) - * Lc "}}" - * ( EOL + -1 ) -local expression = - P { "E" , - E = ( P "'" * ( P "\\'" + 1 - S "'\r" ) ^ 0 * P "'" - + P "\"" * (P "\\\"" + 1 - S "\"\r" ) ^ 0 * P "\"" - + P "{" * V "F" * P "}" - + P "(" * V "F" * P ")" - + P "[" * V "F" * P "]" - + ( 1 - S "{}()[]\r," ) ) ^ 0 , - F = ( P "{" * V "F" * P "}" - + P "(" * V "F" * P ")" - + P "[" * V "F" * P "]" - + ( 1 - S "{}()[]\r\"'" ) ) ^ 0 - } -local Param = - SkipSpace * Identifier * SkipSpace - * ( - K ( 'InitialValues' , P "=" * expression ) - + Q ( P ":" ) * SkipSpace * K ( 'Name.Type' , letter ^ 1 ) - ) ^ -1 -local Params = ( Param * ( Q "," * Param ) ^ 0 ) ^ -1 -local DefFunction = - K ( 'Keyword' , P "def" ) - * Space - * K ( 'Name.Function.Internal' , identifier ) - * SkipSpace - * Q ( P "(" ) * Params * Q ( P ")" ) - * SkipSpace - * ( Q ( P "->" ) * SkipSpace * K ( 'Name.Type' , identifier ) ) ^ -1 - * K ( 'ParseAgain' , ( 1 - S ":\r" )^0 ) - * Q ( P ":" ) - * ( SkipSpace - * ( EOL + CommentLaTeX + Comment ) -- in all cases, that contains an EOL - * Tab ^ 0 - * SkipSpace - * StringDoc ^ 0 -- there may be additionnal docstrings - ) ^ -1 -local ExceptionInConsole = Exception * Q ( ( 1 - P "\r" ) ^ 0 ) * EOL -local MainPython = - EOL - + Space - + Tab - + Escape - + CommentLaTeX - + Beamer - + LongString - + Comment - + ExceptionInConsole - + Delim - + Operator - + OperatorWord * ( Space + Punct + Delim + EOL + -1 ) - + ShortString - + Punct - + FromImport - + RaiseException - + DefFunction - + DefClass - + Keyword * ( Space + Punct + Delim + EOL + -1 ) - + Decorator - + Builtin * ( Space + Punct + Delim + EOL + -1 ) - + Identifier - + Number - + Word -MainLoopPython = - ( ( space^1 * -1 ) - + MainPython - ) ^ 0 -local python = P ( true ) - -python = - Ct ( - ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 - * BeamerBeginEnvironments - * PromptHastyDetection - * Lc '\\__piton_begin_line:' - * Prompt - * SpaceIndentation ^ 0 - * MainLoopPython - * -1 - * Lc '\\__piton_end_line:' - ) -languages['python'] = python -local Delim = Q ( P "[|" + P "|]" + S "[()]" ) -local Punct = Q ( S ",:;!" ) -local cap_identifier = R "AZ" * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 -local Constructor = K ( 'Name.Constructor' , cap_identifier ) -local ModuleType = K ( 'Name.Type' , cap_identifier ) -local identifier = - ( R "az" + P "_") * ( R "az" + R "AZ" + S "_'" + digit ) ^ 0 -local Identifier = K ( 'Identifier' , identifier ) -local expression_for_fields = - P { "E" , - E = ( P "{" * V "F" * P "}" - + P "(" * V "F" * P ")" - + P "[" * V "F" * P "]" - + P "\"" * (P "\\\"" + 1 - S "\"\r" )^0 * P "\"" - + P "'" * ( P "\\'" + 1 - S "'\r" )^0 * P "'" - + ( 1 - S "{}()[]\r;" ) ) ^ 0 , - F = ( P "{" * V "F" * P "}" - + P "(" * V "F" * P ")" - + P "[" * V "F" * P "]" - + ( 1 - S "{}()[]\r\"'" ) ) ^ 0 - } -local OneFieldDefinition = - ( K ( 'KeyWord' , P "mutable" ) * SkipSpace ) ^ -1 - * K ( 'Name.Field' , identifier ) * SkipSpace - * Q ":" * SkipSpace - * K ( 'Name.Type' , expression_for_fields ) - * SkipSpace - -local OneField = - K ( 'Name.Field' , identifier ) * SkipSpace - * Q "=" * SkipSpace - * ( C ( expression_for_fields ) / ( function (s) return LoopOCaml:match(s) end ) ) - * SkipSpace - -local Record = - Q "{" * SkipSpace - * - ( - OneFieldDefinition * ( Q ";" * SkipSpace * OneFieldDefinition ) ^ 0 - + - OneField * ( Q ";" * SkipSpace * OneField ) ^ 0 - ) - * - Q "}" -local DotNotation = - ( - K ( 'Name.Module' , cap_identifier ) - * Q "." - * ( Identifier + Constructor + Q "(" + Q "[" + Q "{" ) - - + - Identifier - * Q "." - * K ( 'Name.Field' , identifier ) - ) - * ( Q "." * K ( 'Name.Field' , identifier ) ) ^ 0 -local Operator = - K ( 'Operator' , - P "!=" + P "<>" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" + P ":=" - + P "||" + P "&&" + P "//" + P "**" + P ";;" + P "::" + P "->" - + P "+." + P "-." + P "*." + P "/." - + S "-~+/*%=<>&@|" - ) - -local OperatorWord = - K ( 'Operator.Word' , - P "and" + P "asr" + P "land" + P "lor" + P "lsl" + P "lxor" - + P "mod" + P "or" ) - -local Keyword = - K ( 'Keyword' , - P "assert" + P "as" + P "begin" + P "class" + P "constraint" + P "done" - + P "downto" + P "do" + P "else" + P "end" + P "exception" + P "external" - + P "for" + P "function" + P "functor" + P "fun" + P "if" - + P "include" + P "inherit" + P "initializer" + P "in" + P "lazy" + P "let" - + P "match" + P "method" + P "module" + P "mutable" + P "new" + P "object" - + P "of" + P "open" + P "private" + P "raise" + P "rec" + P "sig" - + P "struct" + P "then" + P "to" + P "try" + P "type" - + P "value" + P "val" + P "virtual" + P "when" + P "while" + P "with" ) - + K ( 'Keyword.Constant' , P "true" + P "false" ) - -local Builtin = - K ( 'Name.Builtin' , P "not" + P "incr" + P "decr" + P "fst" + P "snd" ) -local Exception = - K ( 'Exception' , - P "Division_by_zero" + P "End_of_File" + P "Failure" - + P "Invalid_argument" + P "Match_failure" + P "Not_found" - + P "Out_of_memory" + P "Stack_overflow" + P "Sys_blocked_io" - + P "Sys_error" + P "Undefined_recursive_module" ) -local Char = - K ( 'String.Short' , P "'" * ( ( 1 - P "'" ) ^ 0 + P "\\'" ) * P "'" ) -local balanced_braces = - P { "E" , - E = - ( - P "{" * V "E" * P "}" - + - P "\"" * ( 1 - S "\"" ) ^ 0 * P "\"" -- OCaml strings - + - ( 1 - S "{}" ) - ) ^ 0 - } -if piton_beamer -then - Beamer = - L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) - + - Ct ( Cc "Open" - * C ( - ( - P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible" - + P "\\invisible" + P "\\action" - ) - * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 - * P "{" - ) - * Cc "}" - ) - * ( C ( balanced_braces ) / (function (s) return MainLoopOCaml:match(s) end ) ) - * P "}" * Ct ( Cc "Close" ) - + OneBeamerEnvironment ( "uncoverenv" , MainLoopOCaml ) - + OneBeamerEnvironment ( "onlyenv" , MainLoopOCaml ) - + OneBeamerEnvironment ( "visibleenv" , MainLoopOCaml ) - + OneBeamerEnvironment ( "invisibleenv" , MainLoopOCaml ) - + OneBeamerEnvironment ( "alertenv" , MainLoopOCaml ) - + OneBeamerEnvironment ( "actionenv" , MainLoopOCaml ) - + - L ( - ( P "\\alt" ) - * P "<" * (1 - P ">") ^ 0 * P ">" - * P "{" - ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}" ) - + - L ( - ( P "\\temporal" ) - * P "<" * (1 - P ">") ^ 0 * P ">" - * P "{" - ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}" ) -end -local EOL = - P "\r" - * - ( - ( space^0 * -1 ) - + - Ct ( - Cc "EOL" - * - Ct ( - Lc "\\__piton_end_line:" - * BeamerEndEnvironments - * BeamerBeginEnvironments - * PromptHastyDetection - * Lc "\\__piton_newline: \\__piton_begin_line:" - * Prompt - ) - ) - ) - * - SpaceIndentation ^ 0 -local ocaml_string = - Q ( P "\"" ) - * ( - VisualSpace - + - Q ( ( 1 - S " \"\r" ) ^ 1 ) - + - EOL - ) ^ 0 - * Q ( P "\"" ) -local String = WithStyle ( 'String.Long' , ocaml_string ) -local ext = ( R "az" + P "_" ) ^ 0 -local open = "{" * Cg(ext, 'init') * "|" -local close = "|" * C(ext) * "}" -local closeeq = - Cmt ( close * Cb('init'), - function (s, i, a, b) return a==b end ) -local QuotedStringBis = - WithStyle ( 'String.Long' , - ( - VisualSpace - + - Q ( ( 1 - S " \r" ) ^ 1 ) - + - EOL - ) ^ 0 ) - -local QuotedString = - C ( open * ( 1 - closeeq ) ^ 0 * close ) / - ( function (s) return QuotedStringBis : match(s) end ) -local Comment = - WithStyle ( 'Comment' , - P { - "A" , - A = Q "(*" - * ( V "A" - + Q ( ( 1 - P "(*" - P "*)" - S "\r$\"" ) ^ 1 ) -- $ - + ocaml_string - + P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" -- $ - + EOL - ) ^ 0 - * Q "*)" - } ) -local balanced_parens = - P { "E" , - E = - ( - P "(" * V "E" * P ")" - + - ( 1 - S "()" ) - ) ^ 0 - } -local Argument = - K ( 'Identifier' , identifier ) - + Q "(" * SkipSpace - * K ( 'Identifier' , identifier ) * SkipSpace - * Q ":" * SkipSpace - * K ( 'Name.Type' , balanced_parens ) * SkipSpace - * Q ")" -local DefFunction = - K ( 'Keyword' , P "let open" ) - * Space - * K ( 'Name.Module' , cap_identifier ) - + - K ( 'Keyword' , P "let rec" + P "let" + P "and" ) - * Space - * K ( 'Name.Function.Internal' , identifier ) - * Space - * ( - Q "=" * SkipSpace * K ( 'Keyword' , P "function" ) - + - Argument - * ( SkipSpace * Argument ) ^ 0 - * ( - SkipSpace - * Q ":" - * K ( 'Name.Type' , ( 1 - P "=" ) ^ 0 ) - ) ^ -1 - ) -local DefModule = - K ( 'Keyword' , P "module" ) * Space - * - ( - K ( 'Keyword' , P "type" ) * Space - * K ( 'Name.Type' , cap_identifier ) - + - K ( 'Name.Module' , cap_identifier ) * SkipSpace - * - ( - Q "(" * SkipSpace - * K ( 'Name.Module' , cap_identifier ) * SkipSpace - * Q ":" * SkipSpace - * K ( 'Name.Type' , cap_identifier ) * SkipSpace - * - ( - Q "," * SkipSpace - * K ( 'Name.Module' , cap_identifier ) * SkipSpace - * Q ":" * SkipSpace - * K ( 'Name.Type' , cap_identifier ) * SkipSpace - ) ^ 0 - * Q ")" - ) ^ -1 - * - ( - Q "=" * SkipSpace - * K ( 'Name.Module' , cap_identifier ) * SkipSpace - * Q "(" - * K ( 'Name.Module' , cap_identifier ) * SkipSpace - * - ( - Q "," - * - K ( 'Name.Module' , cap_identifier ) * SkipSpace - ) ^ 0 - * Q ")" - ) ^ -1 - ) - + - K ( 'Keyword' , P "include" + P "open" ) - * Space * K ( 'Name.Module' , cap_identifier ) -local TypeParameter = K ( 'TypeParameter' , P "'" * alpha * # ( 1 - P "'" ) ) -MainOCaml = - EOL - + Space - + Tab - + Escape - + Beamer - + TypeParameter - + String + QuotedString + Char - + Comment - + Delim - + Operator - + Punct - + FromImport - + Exception - + DefFunction - + DefModule - + Record - + Keyword * ( Space + Punct + Delim + EOL + -1 ) - + OperatorWord * ( Space + Punct + Delim + EOL + -1 ) - + Builtin * ( Space + Punct + Delim + EOL + -1 ) - + DotNotation - + Constructor - + Identifier - + Number - + Word - -LoopOCaml = MainOCaml ^ 0 - -MainLoopOCaml = - ( ( space^1 * -1 ) - + MainOCaml - ) ^ 0 -local ocaml = P ( true ) - -ocaml = - Ct ( - ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 - * BeamerBeginEnvironments - * Lc ( '\\__piton_begin_line:' ) - * SpaceIndentation ^ 0 - * MainLoopOCaml - * -1 - * Lc ( '\\__piton_end_line:' ) - ) -languages['ocaml'] = ocaml -local Operator = - K ( 'Operator' , - P "!=" + P "==" + P "<<" + P ">>" + P "<=" + P ">=" - + P "||" + P "&&" + S "-~+/*%=<>&.@|!" - ) - -local Keyword = - K ( 'Keyword' , - P "alignas" + P "asm" + P "auto" + P "break" + P "case" + P "catch" - + P "class" + P "const" + P "constexpr" + P "continue" - + P "decltype" + P "do" + P "else" + P "enum" + P "extern" - + P "for" + P "goto" + P "if" + P "nexcept" + P "private" + P "public" - + P "register" + P "restricted" + P "return" + P "static" + P "static_assert" - + P "struct" + P "switch" + P "thread_local" + P "throw" + P "try" - + P "typedef" + P "union" + P "using" + P "virtual" + P "volatile" - + P "while" - ) - + K ( 'Keyword.Constant' , - P "default" + P "false" + P "NULL" + P "nullptr" + P "true" - ) - -local Builtin = - K ( 'Name.Builtin' , - P "alignof" + P "malloc" + P "printf" + P "scanf" + P "sizeof" - ) - -local Type = - K ( 'Name.Type' , - P "bool" + P "char" + P "char16_t" + P "char32_t" + P "double" - + P "float" + P "int" + P "int8_t" + P "int16_t" + P "int32_t" - + P "int64_t" + P "long" + P "short" + P "signed" + P "unsigned" - + P "void" + P "wchar_t" - ) - -local DefFunction = - Type - * Space - * K ( 'Name.Function.Internal' , identifier ) - * SkipSpace - * # P "(" -local DefClass = - K ( 'Keyword' , P "class" ) * Space * K ( 'Name.Class' , identifier ) -local String = - WithStyle ( 'String.Long' , - Q "\"" - * ( VisualSpace - + K ( 'String.Interpol' , - P "%" * ( S "difcspxXou" + P "ld" + P "li" + P "hd" + P "hi" ) - ) - + Q ( ( P "\\\"" + 1 - S " \"" ) ^ 1 ) - ) ^ 0 - * Q "\"" - ) -local balanced_braces = - P { "E" , - E = - ( - P "{" * V "E" * P "}" - + - String - + - ( 1 - S "{}" ) - ) ^ 0 - } -if piton_beamer -then - Beamer = - L ( P "\\pause" * ( P "[" * ( 1 - P "]" ) ^ 0 * P "]" ) ^ -1 ) - + - Ct ( Cc "Open" - * C ( - ( - P "\\uncover" + P "\\only" + P "\\alert" + P "\\visible" - + P "\\invisible" + P "\\action" - ) - * ( P "<" * (1 - P ">") ^ 0 * P ">" ) ^ -1 - * P "{" - ) - * Cc "}" - ) - * ( C ( balanced_braces ) / (function (s) return MainLoopC:match(s) end ) ) - * P "}" * Ct ( Cc "Close" ) - + OneBeamerEnvironment ( "uncoverenv" , MainLoopC ) - + OneBeamerEnvironment ( "onlyenv" , MainLoopC ) - + OneBeamerEnvironment ( "visibleenv" , MainLoopC ) - + OneBeamerEnvironment ( "invisibleenv" , MainLoopC ) - + OneBeamerEnvironment ( "alertenv" , MainLoopC ) - + OneBeamerEnvironment ( "actionenv" , MainLoopC ) - + - L ( - ( P "\\alt" ) - * P "<" * (1 - P ">") ^ 0 * P ">" - * P "{" - ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}" ) - + - L ( - ( P "\\temporal" ) - * P "<" * (1 - P ">") ^ 0 * P ">" - * P "{" - ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}{" ) - * K ( 'ParseAgain.noCR' , balanced_braces ) - * L ( P "}" ) -end -local PromptHastyDetection = ( # ( P ">>>" + P "..." ) * Lc ( '\\__piton_prompt:' ) ) ^ -1 -local Prompt = K ( 'Prompt' , ( ( P ">>>" + P "..." ) * P " " ^ -1 ) ^ -1 ) -local EOL = - P "\r" - * - ( - ( space^0 * -1 ) - + - Ct ( - Cc "EOL" - * - Ct ( - Lc "\\__piton_end_line:" - * BeamerEndEnvironments - * BeamerBeginEnvironments - * PromptHastyDetection - * Lc "\\__piton_newline: \\__piton_begin_line:" - * Prompt - ) - ) - ) - * - SpaceIndentation ^ 0 -local Preproc = - K ( 'Preproc' , P "#" * (1 - P "\r" ) ^ 0 ) * ( EOL + -1 ) -local CommentMath = - P "$" * K ( 'Comment.Math' , ( 1 - S "$\r" ) ^ 1 ) * P "$" - -local Comment = - WithStyle ( 'Comment' , - Q ( P "//" ) - * ( CommentMath + Q ( ( 1 - S "$\r" ) ^ 1 ) ) ^ 0 ) - * ( EOL + -1 ) - -local LongComment = - WithStyle ( 'Comment' , - Q ( P "/*" ) - * ( CommentMath + Q ( ( 1 - P "*/" - S "$\r" ) ^ 1 ) + EOL ) ^ 0 - * Q ( P "*/" ) - ) -- $ -local CommentLaTeX = - P(piton.comment_latex) - * Lc "{\\PitonStyle{Comment.LaTeX}{\\ignorespaces" - * L ( ( 1 - P "\r" ) ^ 0 ) - * Lc "}}" - * ( EOL + -1 ) -local MainC = - EOL - + Space - + Tab - + Escape - + CommentLaTeX - + Beamer - + Preproc - + Comment + LongComment - + Delim - + Operator - + String - + Punct - + DefFunction - + DefClass - + Type * ( Q ( "*" ) ^ -1 + Space + Punct + Delim + EOL + -1 ) - + Keyword * ( Space + Punct + Delim + EOL + -1 ) - + Builtin * ( Space + Punct + Delim + EOL + -1 ) - + Identifier - + Number - + Word -MainLoopC = - ( ( space^1 * -1 ) - + MainC - ) ^ 0 -languageC = - Ct ( - ( ( space - P "\r" ) ^0 * P "\r" ) ^ -1 - * BeamerBeginEnvironments - * PromptHastyDetection - * Lc '\\__piton_begin_line:' - * Prompt - * SpaceIndentation ^ 0 - * MainLoopC - * -1 - * Lc '\\__piton_end_line:' - ) -languages['c'] = languageC -function piton.Parse(language,code) - local t = languages[language] : match ( code ) - if t == nil - then - tex.sprint("\\PitonSyntaxError") - return -- to exit in force the function - end - local left_stack = {} - local right_stack = {} - for _ , one_item in ipairs(t) - do - if one_item[1] == "EOL" - then - for _ , s in ipairs(right_stack) - do tex.sprint(s) - end - for _ , s in ipairs(one_item[2]) - do tex.tprint(s) - end - for _ , s in ipairs(left_stack) - do tex.sprint(s) - end - else - if one_item[1] == "Open" - then - tex.sprint( one_item[2] ) - table.insert(left_stack,one_item[2]) - table.insert(right_stack,one_item[3]) - else - if one_item[1] == "Close" - then - tex.sprint( right_stack[#right_stack] ) - left_stack[#left_stack] = nil - right_stack[#right_stack] = nil - else - tex.tprint(one_item) - end - end - end - end -end -function piton.ParseFile(language,name,first_line,last_line) - local s = '' - local i = 0 - for line in io.lines(name) - do i = i + 1 - if i >= first_line - then s = s .. '\r' .. line - end - if i >= last_line then break end - end - if string.byte(s,1) == 13 - then if string.byte(s,2) == 239 - then if string.byte(s,3) == 187 - then if string.byte(s,4) == 191 - then s = string.sub(s,5,-1) - end - end - end - end - piton.Parse(language,s) -end -function piton.ParseBis(language,code) - local s = ( Cs ( ( P '##' / '#' + 1 ) ^ 0 ) ) : match ( code ) - return piton.Parse(language,s) -end -function piton.ParseTer(language,code) - local s = ( Cs ( ( P '\\__piton_breakable_space:' / ' ' + 1 ) ^ 0 ) ) - : match ( code ) - return piton.Parse(language,s) -end -local function gobble(n,code) - function concat(acc,new_value) - return acc .. new_value - end - if n==0 - then return code - else - return Cf ( - Cc ( "" ) * - ( 1 - P "\r" ) ^ (-n) * C ( ( 1 - P "\r" ) ^ 0 ) - * ( C ( P "\r" ) - * ( 1 - P "\r" ) ^ (-n) - * C ( ( 1 - P "\r" ) ^ 0 ) - ) ^ 0 , - concat - ) : match ( code ) - end -end -local function add(acc,new_value) - return acc + new_value -end -local AutoGobbleLPEG = - ( space ^ 0 * P "\r" ) ^ -1 - * Cf ( - ( - ( P " " ) ^ 0 * P "\r" - + - Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add ) - * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 * P "\r" - ) ^ 0 - * - ( Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add ) - * ( 1 - P " " ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 , - math.min - ) -local TabsAutoGobbleLPEG = - ( space ^ 0 * P "\r" ) ^ -1 - * Cf ( - ( - ( P "\t" ) ^ 0 * P "\r" - + - Cf ( Cc(0) * ( P "\t" * Cc(1) ) ^ 0 , add ) - * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 * P "\r" - ) ^ 0 - * - ( Cf ( Cc(0) * ( P "\t" * Cc(1) ) ^ 0 , add ) - * ( 1 - P "\t" ) * ( 1 - P "\r" ) ^ 0 ) ^ -1 , - math.min - ) -local EnvGobbleLPEG = - ( ( 1 - P "\r" ) ^ 0 * P "\r" ) ^ 0 - * Cf ( Cc(0) * ( P " " * Cc(1) ) ^ 0 , add ) * -1 -function piton.GobbleParse(language,n,code) - if n==-1 - then n = AutoGobbleLPEG : match(code) - else if n==-2 - then n = EnvGobbleLPEG : match(code) - else if n==-3 - then n = TabsAutoGobbleLPEG : match(code) - end - end - end - piton.Parse(language,gobble(n,code)) -end -function piton.CountLines(code) - local count = 0 - for i in code : gmatch ( "\r" ) do count = count + 1 end - tex.sprint( - luatexbase.catcodetables.expl , - '\\int_set:Nn \\l__piton_nb_lines_int {' .. count .. '}' ) -end -function piton.CountNonEmptyLines(code) - local count = 0 - count = - ( Cf ( Cc(0) * - ( - ( P " " ) ^ 0 * P "\r" - + ( 1 - P "\r" ) ^ 0 * P "\r" * Cc(1) - ) ^ 0 - * (1 - P "\r" ) ^ 0 , - add - ) * -1 ) : match (code) - tex.sprint( - luatexbase.catcodetables.expl , - '\\int_set:Nn \\l__piton_nb_non_empty_lines_int {' .. count .. '}' ) -end -function piton.CountLinesFile(name) - local count = 0 - for line in io.lines(name) do count = count + 1 end - tex.sprint( - luatexbase.catcodetables.expl , - '\\int_set:Nn \\l__piton_nb_lines_int {' .. count .. '}' ) -end -function piton.CountNonEmptyLinesFile(name) - local count = 0 - for line in io.lines(name) - do if not ( ( ( P " " ) ^ 0 * -1 ) : match ( line ) ) - then count = count + 1 - end - end - tex.sprint( - luatexbase.catcodetables.expl , - '\\int_set:Nn \\l__piton_nb_non_empty_lines_int {' .. count .. '}' ) -end -\end{luacode*} +\hook_gput_code:nnn { begindocument } { . } + { \lua_now:e { require("piton.lua") } } \endinput %% |