texlive[60095] Master/texmf-dist: pyluatex (27jul21)

commits+karl at tug.org commits+karl at tug.org
Tue Jul 27 22:36:32 CEST 2021


Revision: 60095
          http://tug.org/svn/texlive?view=revision&revision=60095
Author:   karl
Date:     2021-07-27 22:36:31 +0200 (Tue, 27 Jul 2021)
Log Message:
-----------
pyluatex (27jul21)

Modified Paths:
--------------
    trunk/Master/texmf-dist/doc/lualatex/pyluatex/README.md
    trunk/Master/texmf-dist/doc/lualatex/pyluatex/pyluatex.pdf
    trunk/Master/texmf-dist/doc/lualatex/pyluatex/pyluatex.tex
    trunk/Master/texmf-dist/tex/lualatex/pyluatex/pyluatex.lua
    trunk/Master/texmf-dist/tex/lualatex/pyluatex/pyluatex.sty

Modified: trunk/Master/texmf-dist/doc/lualatex/pyluatex/README.md
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/pyluatex/README.md	2021-07-27 20:36:19 UTC (rev 60094)
+++ trunk/Master/texmf-dist/doc/lualatex/pyluatex/README.md	2021-07-27 20:36:31 UTC (rev 60095)
@@ -7,6 +7,11 @@
 
 ## Example
 1\. LaTeX document `example.tex`
+
+**Note:** PyLuaTeX starts Python 3 using the command `python3` by default.
+If `python3` does not start Python 3 on your system, find the correct command
+and replace `\usepackage{pyluatex}` with `\usepackage[executable={your python command}]{pyluatex}`.
+For example, `\usepackage[executable=python.exe]{pyluatex}`.
 ```latex
 \documentclass{article}
 
@@ -31,6 +36,7 @@
 \randint{2}{5}
 \end{document}
 ```
+
 2\. Compile using LuaLaTeX (shell escape is required)
 ```
 lualatex -shell-escape example.tex

Modified: trunk/Master/texmf-dist/doc/lualatex/pyluatex/pyluatex.pdf
===================================================================
(Binary files differ)

Modified: trunk/Master/texmf-dist/doc/lualatex/pyluatex/pyluatex.tex
===================================================================
--- trunk/Master/texmf-dist/doc/lualatex/pyluatex/pyluatex.tex	2021-07-27 20:36:19 UTC (rev 60094)
+++ trunk/Master/texmf-dist/doc/lualatex/pyluatex/pyluatex.tex	2021-07-27 20:36:31 UTC (rev 60095)
@@ -15,7 +15,7 @@
 \usepackage{url}
 \title{The \emph{pyluatex} package}
 \author{Tobias Enderle\\\url{https://github.com/tndrle/PyLuaTeX}}
-\date{v0.1.3 (2021/07/15)}
+\date{v0.2.0 (2021/07/26)}
 \begin{document}
 \maketitle
 \raggedright
@@ -28,7 +28,11 @@
 
 \section{Example}
 \begin{enumerate}
-\item  \LaTeX{} document \inlcode|example.tex|
+\item  \LaTeX{} document \inlcode|example.tex|\\[0.5ex]
+\textbf{Note:} PyLuaTeX starts Python 3 using the command \inlcode|python3| by default.
+If \inlcode|python3| does not start Python 3 on your system, find the correct command
+and replace \inlcode|\usepackage{pyluatex}| with \inlcode|\usepackage[executable={your python command}]{pyluatex}|.
+For example, \inlcode|\usepackage[executable=python.exe]{pyluatex}|.
 \begin{tcblisting}{breakable,listing only,
     size=fbox,colframe=black!8,boxrule=3pt,colback=black!8}
 \documentclass{article}
@@ -54,6 +58,8 @@
 \randint{2}{5}
 \end{document}
 \end{tcblisting}
+\end{enumerate}
+\begin{enumerate}
 \item  Compile using Lua\LaTeX{} (shell escape is required)
 \begin{tcblisting}{breakable,listing only,
     size=fbox,colframe=black!8,boxrule=3pt,colback=black!8}
@@ -76,13 +82,21 @@
   Demonstrates how \textit{matplotlib} plots can be generated and included in a document
 \item \inlcode|matplotlib-pgf.tex|\\[0.5ex]
   Demonstrates how \textit{matplotlib} plots can be generated and included in a document using \textit{PGF}
+\item \inlcode|typesetting-example.tex|\\[0.5ex]
+  The code typesetting example below
+\item \inlcode|typesetting-listings.tex|\\[0.5ex]
+  A detailed example for typesetting code and output with the \textit{listings} package
+\item \inlcode|typesetting-minted.tex|\\[0.5ex]
+  A detailed example for typesetting code and output with the \textit{minted} package
 \end{itemize}
 For more intricate use cases have a look at our tests in the folder \inlcode|test|.
 
 \section{Installation}
-PyLuaTeX is available on CTAN\footnote{\url{https://ctan.org/pkg/pyluatex}} and in MiKTeX.
-It will be available in TeX Live soon (when you read this it probably already is).
+PyLuaTeX is available in TeX Live, MiKTeX, and on CTAN\footnote{\url{https://ctan.org/pkg/pyluatex}} as \inlcode|pyluatex|.
 
+To install PyLuaTeX in \textbf{TeX Live} run \inlcode|tlmgr install pyluatex|.\\[0.5ex]
+In \textbf{MiKTeX}, PyLuaTeX can be installed in the \textit{MiKTeX Console}.
+
 To install PyLuaTeX \textbf{manually}, do the following steps:
 \begin{enumerate}
 \item  Locate your local \textit{TEXMF} folder\\[0.5ex]
@@ -106,6 +120,12 @@
 \section{Reference}
 PyLuaTeX offers a simple set of options, macros and environments.
 
+Most macros and environments are available as \textit{quiet} versions as well.
+They have the suffix \inlcode|q| in their name, e.g. \inlcode|\pycq| or \inlcode|\pyfileq|.
+The quiet versions suppress any output, even if the Python code explicitly calls \inlcode|print()|.
+This is helpful if you want to process code or output further and do your own typesetting.
+For an example, see the Typesetting Code section.
+
 \subsection{Package Options}
 \begin{itemize}
 \item \inlcode|verbose|\\[0.5ex]
@@ -118,14 +138,23 @@
 \subsection{Macros}
 \begin{itemize}
 \item \inlcode|\py{code}|\\[0.5ex]
-  Executes \inlcode|code| and writes the output to the document.\\[0.5ex]
+  Executes (object-like) \inlcode|code| and writes its string representation to the document.\\[0.5ex]
   \textit{Example:} \inlcode|\py{3 + 7}|
+\item \inlcode|\pyq{code}|\\[0.5ex]
+  Executes (object-like) \inlcode|code|. Any output is suppressed.\\[0.5ex]
+  \textit{Example:} \inlcode|\pyq{3 + 7}|
 \item \inlcode|\pyc{code}|\\[0.5ex]
-  Executes \inlcode|code|\\[0.5ex]
-  \textit{Example:} \inlcode|\pyc{x = 5}|
+  Executes \inlcode|code|. Output (e.g. from a call to \inlcode|print()|) is written to the document.\\[0.5ex]
+  \textit{Examples:} \inlcode|\pyc{x = 5}|, \inlcode|\pyc{print('hello')}|
+\item \inlcode|\pycq{code}|\\[0.5ex]
+  Executes \inlcode|code|. Any output is suppressed.\\[0.5ex]
+  \textit{Example:} \inlcode|\pycq{x = 5}|
 \item \inlcode|\pyfile{path}|\\[0.5ex]
-  Executes the Python file specified by \inlcode|path|.\\[0.5ex]
+  Executes the Python file specified by \inlcode|path|. Output (e.g. from a call to \inlcode|print()|) is written to the document.\\[0.5ex]
   \textit{Example:} \inlcode|\pyfile{main.py}|
+\item \inlcode|\pyfileq{path}|\\[0.5ex]
+  Executes the Python file specified by \inlcode|path|. Any output is suppressed.\\[0.5ex]
+  \textit{Example:} \inlcode|\pyfileq{main.py}|
 \item \inlcode|\pysession{session}|\\[0.5ex]
   Selects \inlcode|session| as Python session for subsequent Python code.\\[0.5ex]
   The session that is active at the beginning is \inlcode|default|.\\[0.5ex]
@@ -146,6 +175,8 @@
     print(x)
 \end{python}
 \end{tcblisting}
+\item \inlcode|pythonq|\\[0.5ex]
+  Same as the \inlcode|python| environment, but any output is suppressed.
 \end{itemize}
 \section{Requirements}
 \begin{itemize}
@@ -156,6 +187,59 @@
 Our automated tests currently use TeX Live 2021 and Python 3.7+ on
 Ubuntu 20.04, macOS Catalina 10.15 and Windows Server 2019.
 
+\section{Typesetting Code}
+Sometimes, in addition to having Python code executed and the output written to your document, you also want to show the code itself in your document.
+PyLuaTeX does not offer any macros or environments that directly typeset code.
+However, PyLuaTeX has a \textbf{code and output buffer} which you can use to create your own typesetting functionality.
+This provides a lot of flexibility for your typesetting.
+
+After a PyLuaTeX macro or environment has been executed, the corresponding Python code and output can be accessed via the Lua functions \inlcode|pyluatex.get_last_code()| and \inlcode|pyluatex.get_last_output()|, respectively.
+Both functions return a Lua table\footnote{\url{https://www.lua.org/pil/2.5.html}} where each table item corresponds to a line of code or output.
+
+A simple example for typesetting code and output using the \textit{listings} package would be:
+\begin{tcblisting}{breakable,listing only,
+    size=fbox,colframe=black!8,boxrule=3pt,colback=black!8}
+\documentclass{article}
+
+\usepackage{pyluatex}
+\usepackage{listings}
+\usepackage{luacode}
+
+\begin{luacode}
+function pytypeset()
+    tex.print("\\begin{lstlisting}[language=Python]")
+    tex.print(pyluatex.get_last_code())
+    tex.print("\\end{lstlisting}")
+    tex.print("") -- ensure newline
+end
+\end{luacode}
+
+\newcommand*{\pytypeset}{%
+    \noindent\textbf{Input:}
+    \directlua{pytypeset()}
+    \textbf{Output:}
+    \begin{center}
+        \directlua{tex.print(pyluatex.get_last_output())}
+    \end{center}
+}
+
+\begin{document}
+
+\begin{pythonq}
+greeting = 'Hello PyLuaTeX!'
+print(greeting)
+\end{pythonq}
+\pytypeset
+
+\end{document}
+\end{tcblisting}
+
+Notice that we use the \inlcode|pythonq| environment, which suppresses any output.
+After that, the custom macro \inlcode|\pytypeset| is responsible for typesetting the code and its output.
+
+Using a different code listings package like \textit{minted}, or typesetting inline code is very easy.
+See the \inlcode|typesetting-*.tex| examples in the \inlcode|example| folder.
+
 \section{How It Works}
 PyLuaTeX runs a Python \inlcode|InteractiveInterpreter|\footnote{\url{https://docs.python.org/3/library/code.html#code.InteractiveInterpreter}} (actually several if you use different sessions) in the background for on the fly code execution.
 Python code from your \LaTeX{} file is sent to the background interpreter through a TCP socket.

Modified: trunk/Master/texmf-dist/tex/lualatex/pyluatex/pyluatex.lua
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/pyluatex/pyluatex.lua	2021-07-27 20:36:19 UTC (rev 60094)
+++ trunk/Master/texmf-dist/tex/lualatex/pyluatex/pyluatex.lua	2021-07-27 20:36:31 UTC (rev 60095)
@@ -35,10 +35,11 @@
 local script = file.join(folder, "pyluatex-interpreter.py")
 local tcp = nil
 
-local python_lines = {}
-local python_output = nil
+local env_end = nil
+local env_lines = nil
 
-local env_end = "\\end{python}"
+local last_code = nil
+local last_output = nil
 
 local function err_cmd(message)
     return "\\PackageError{PyLuaTeX}{" .. message .. "}{}"
@@ -80,74 +81,100 @@
     texio.write_nl("PyLuaTeX output: " .. code)
 end
 
-local function print_lines(str)
-    for s in str:gmatch("[^\r\n]+") do
-        tex.sprint(s)
+local function split_lines(str)
+    if str:sub(-1) ~= "\n" then
+        str = str .. "\n"
     end
+
+    local t = {}
+    for s in str:gmatch("(.-)\r?\n") do
+        table.insert(t, s)
+    end
+    return t
 end
 
-function pyluatex.execute(code, write)
-    if pyluatex.verbose then log_input(code) end
+function pyluatex.execute(code, auto_print, write)
+    local full_code
+    if auto_print then
+        full_code = "print(str(" .. code .. "), end='')"
+    else
+        full_code = code
+    end
 
-    local success, output = request({ session = pyluatex.session, code = code })
+    if pyluatex.verbose then log_input(full_code) end
+
+    local success, output = request({ session = pyluatex.session, code = full_code })
+    last_code = split_lines(code)
+    last_output = split_lines(output)
+
     if success then
         if pyluatex.verbose then log_output(output) end
+
         if write then
-            print_lines(output)
-        else
-            return output
+            tex.print(last_output)
         end
     else
-        if not pyluatex.verbose then log_input(code) end
+        if not pyluatex.verbose then log_input(full_code) end
         log_output(output)
         if write then
             tex.sprint(err_cmd("Python error (see above)"))
         end
     end
-    return nil
+
+    return success
 end
 
 function pyluatex.print_env()
-    if python_output ~= nil then
-        print_lines(python_output)
-        python_output = nil
+    if last_output ~= nil then
+        tex.print(last_output)
     end
 end
 
 local function record_line(line)
-    local s, e = line:find(env_end)
+    local s, e = line:find(env_end, 1, true)
     if s ~= nil then
         luatexbase.remove_from_callback("process_input_buffer", "pyluatex_record_line")
-        table.insert(python_lines, line:sub(1, s - 1))
-        local code = table.concat(python_lines, "\n")
-        local output = pyluatex.execute(code, false)
-        if output ~= nil then
-            python_output = output
+        table.insert(env_lines, line:sub(1, s - 1))
+        local code = table.concat(env_lines, "\n")
+        local success = pyluatex.execute(code, false, false)
+        if success then
             return line:sub(s)
         else
             return env_end .. err_cmd("Python error (see above)") .. line:sub(e + 1)
         end
     else
-        table.insert(python_lines, line)
+        table.insert(env_lines, line)
         return ""
     end
 end
 
-function pyluatex.record_env()
-    python_lines = {}
-    python_output = nil
+function pyluatex.record_env(quiet)
+    if quiet then
+        env_end = "\\end{pythonq}"
+    else
+        env_end = "\\end{python}"
+    end
+    env_lines = {}
     luatexbase.add_to_callback("process_input_buffer", record_line, "pyluatex_record_line")
 end
 
-function pyluatex.run_file(path)
+function pyluatex.run_file(path, write)
     local f = io.open(path, "r")
     if f then
         local code = f:read("*a")
         f:close()
-        pyluatex.execute(code, true)
+        pyluatex.execute(code, false, write)
     else
         tex.sprint(err_cmd("File not found: " .. path))
     end
 end
 
+function pyluatex.get_last_code()
+    return last_code
+end
+
+function pyluatex.get_last_output()
+    return last_output
+end
+
 return pyluatex

Modified: trunk/Master/texmf-dist/tex/lualatex/pyluatex/pyluatex.sty
===================================================================
--- trunk/Master/texmf-dist/tex/lualatex/pyluatex/pyluatex.sty	2021-07-27 20:36:19 UTC (rev 60094)
+++ trunk/Master/texmf-dist/tex/lualatex/pyluatex/pyluatex.sty	2021-07-27 20:36:31 UTC (rev 60095)
@@ -9,7 +9,7 @@
 %% version 2005/12/01 or later.
 
 \NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{pyluatex}[2021/07/15 v0.1.3 Execute Python code on the fly]
+\ProvidesPackage{pyluatex}[2021/07/26 v0.2.0 Execute Python code on the fly]
 
 \RequirePackage{expl3}
 \ExplSyntaxOn
@@ -30,17 +30,22 @@
 
 \directlua{pyluatex.start([==[\pyluatex at executable]==])}
 
-\newenvironment{python}{\directlua{pyluatex.record_env()}}%
+\newenvironment{python}{\directlua{pyluatex.record_env(false)}}%
 {\directlua{pyluatex.print_env()}}
 
-\newcommand*{\py}[1]{%
-\directlua{pyluatex.execute([==[print(str(#1), end='')]==], true)}%
-}
+\newenvironment{pythonq}{\directlua{pyluatex.record_env(true)}}{}
 
-\newcommand*{\pyc}[1]{\directlua{pyluatex.execute([==[#1]==], true)}}
+\newcommand*{\python at inline}[3]{\directlua{pyluatex.execute([==[#1]==], #2, #3)}}
 
+\newcommand*{\py}[1]{\python at inline{#1}{true}{true}}
+\newcommand*{\pyq}[1]{\python at inline{#1}{true}{false}}
+
+\newcommand*{\pyc}[1]{\python at inline{#1}{false}{true}}
+\newcommand*{\pycq}[1]{\python at inline{#1}{false}{false}}
+
 \newcommand*{\pysession}[1]{\directlua{pyluatex.session = [==[#1]==]}}
 
-\newcommand*{\pyfile}[1]{\directlua{pyluatex.run_file([==[#1]==])}}
+\newcommand*{\pyfile}[1]{\directlua{pyluatex.run_file([==[#1]==], true)}}
+\newcommand*{\pyfileq}[1]{\directlua{pyluatex.run_file([==[#1]==], false)}}
 
 \endinput



More information about the tex-live-commits mailing list.