diff options
author | Karl Berry <karl@freefriends.org> | 2020-10-04 21:14:27 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2020-10-04 21:14:27 +0000 |
commit | 8da0fe7c28fc64a420c051b3f3a4f2dec81dda8e (patch) | |
tree | 37b71cfebdc7f0b51da0cb7805a1bc29abaa5c91 /Master/texmf-dist/tex/latex/runcode | |
parent | e242e2da315de7f5e9c7c7ab8f078f17cdcde5e6 (diff) |
runcode (4oct20)
git-svn-id: svn://tug.org/texlive/trunk@56539 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Master/texmf-dist/tex/latex/runcode')
-rw-r--r-- | Master/texmf-dist/tex/latex/runcode/runcode.sty | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/Master/texmf-dist/tex/latex/runcode/runcode.sty b/Master/texmf-dist/tex/latex/runcode/runcode.sty new file mode 100644 index 00000000000..0059a17b862 --- /dev/null +++ b/Master/texmf-dist/tex/latex/runcode/runcode.sty @@ -0,0 +1,268 @@ +% +% Haim Bar haim.bar@uconn.edu +% HaiYing Wang haiying.wang@uconn.edu +% +% This package is based on an ongoing work by Haim Bar and HaiYing Wang, and comments and questions are welcome! + +\newif\ifruncode +% Change to \runcodefalse if you want to suspend code execution +\runcodetrue +\DeclareOption{run}{\runcodetrue} +\DeclareOption{cache}{\runcodefalse} + +\newif\ifminted +\mintedtrue +\DeclareOption{nominted}{\mintedfalse} + +\DeclareOption{R}{ + % create a configuration file for R server if it does not exist. + \IfFileExists{R.config}{}{ + \newwrite\tempfile + \immediate\openout\tempfile=R.config + \immediate\write\tempfile{[SERVERCONFIG]} + \immediate\write\tempfile{PORT = 65432} + \immediate\write\tempfile{DEBUGFILE = Rdebug.txt} + \immediate\write\tempfile{PIPETIMEOUT = 300} + \immediate\closeout\tempfile + } + % Start the server. Need to run just once. Can comment out after the first + % compilation, but remember to terminate the server + \immediate\write18{python3 -c 'from talk2stat.talk2stat import server,client; server("./","R") if not client("./","R","``` ```") else print("server is already running")'} + % Some editors terminate all child processes after LaTeX compiling such as Emacs with Auctex. For this case, use the following line instead of the above line. + % \immediate\write18{nohup python3 -c 'from talk2stat.talk2stat import server,client; server("./","R") if not client("./","R","``` ```") else print("server is already running")' &} +} + +\DeclareOption{julia}{ + % create a configuration file for R server if it does not exist. + \IfFileExists{julia.config}{}{ + \newwrite\tempfile + \immediate\openout\tempfile=julia.config + \immediate\write\tempfile{[SERVERCONFIG]} + \immediate\write\tempfile{PORT = 65431} + \immediate\write\tempfile{DEBUGFILE = juliadebug.txt} + \immediate\write\tempfile{PIPETIMEOUT = 300} + \immediate\closeout\tempfile + } + % Start the server. Need to run just once. Can comment out after the first + % compilation, but remember to terminate the server + \immediate\write18{python3 -c 'from talk2stat.talk2stat import server,client; server("./","julia") if not client("./","julia","``` ```") else print("server is already running")'} + % \immediate\write18{nohup python3 -c 'from talk2stat.talk2stat import server,client; server("./","julia") if not client("./","julia","``` ```") else print("server is already running")' &} +} + +\DeclareOption{matlab}{ + % create a configuration file for R server if it does not exist. + \IfFileExists{matlab.config}{}{ + \newwrite\tempfile + \immediate\openout\tempfile=matlab.config + \immediate\write\tempfile{[SERVERCONFIG]} + \immediate\write\tempfile{PORT = 65430} + \immediate\write\tempfile{DEBUGFILE = matlabdebug.txt} + \immediate\write\tempfile{PIPETIMEOUT = 300} + \immediate\closeout\tempfile + } + % Start the server. Need to run just once. Can comment out after the first + % compilation, but remember to terminate the server + \immediate\write18{python3 -c 'from talk2stat.talk2stat import server,client; server("./","matlab") if not client("./","matlab","``` ```") else print("server is already running")'} + % \immediate\write18{nohup python3 -c 'from talk2stat.talk2stat import server,client; server("./","matlab") if not client("./","matlab","``` ```") else print("server is already running")' &} +} + +\DeclareOption{stopserver}{ + \AtEndDocument{ + %% stop the server when the pdf compilation is done. + \immediate\write18{python3 -c 'from talk2stat.talk2stat import client; client("./","R","QUIT")'} + \immediate\write18{python3 -c 'from talk2stat.talk2stat import client; client("./","julia","QUIT")'} + \immediate\write18{python3 -c 'from talk2stat.talk2stat import client; client("./","matlab","QUIT")'} +}} + +\ProcessOptions* + +\usepackage[many]{tcolorbox} % to put boxes around text +\usepackage{xcolor} % for highlighting +\usepackage[utf8x]{inputenc} +\usepackage{textgreek} +\usepackage{filecontents} +\usepackage{xifthen} +\usepackage{xparse} +\usepackage{xstring} + +% Use minted if it is loaded; otherwise use fvextra +\ifminted +\usepackage[cache=false]{minted} +\else +\usepackage{fvextra} +\fi + +\immediate\write18{mkdir tmp} + +\definecolor{bg}{rgb}{0.95,0.95,0.95} % code block background color + +\newcounter{codelisting} +\renewcommand{\thecodelisting}{\arabic{codelisting}} +\newenvironment{codelisting}[1][]{ + \par\vspace{\baselineskip}\noindent + \refstepcounter{codelisting} + \begin{ttfamily} + \noindent \textbf{Listing~\thecodelisting. #1} +} +{ + \end{ttfamily} + \noindent\ignorespacesafterend + } + +% counter for code output temporary file names +\newcounter{codeOutput} +\setcounter{codeOutput}{0} + +% a command to set the temporary file name for code output +\newcommand{\setvalue}[2]{ + \ifdefined #1 + \renewcommand{#1}{#2} + \else + \newcommand{#1}{#2} + \fi +} +\setvalue{\tmpname}{} % initialize with a blank + + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \showCode prints the source code, using minted for a pretty layout +% Arg #1 is the programming language, +% Arg #2 is the source file name, +% Args #3 and #4 are the first and last line to show (optional). + +\NewDocumentCommand{\showCode}{m m O{} O{}}{% \-\\ + \ifthenelse{\isempty{#3}}{ + \ifminted + \inputminted[fontsize=\footnotesize,linenos, frame=single, bgcolor=bg, breaklines=true]{#1}{#2} + \else + \VerbatimInput[fontsize=\footnotesize,frame=single,breaklines]{#2} + \fi + }{ + \ifminted + \inputminted[fontsize=\footnotesize,linenos,frame=single, bgcolor=bg, breaklines=true, firstline=#3, lastline=#4, firstnumber=1]{#1}{#2} + \else + \VerbatimInput[fontsize=\footnotesize,frame=single,breaklines, firstline=#3, lastline=#4, firstnumber=1]{#2} + \fi + } +} + + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \runExtCode runs an external code. +% Arg #1 is the executable program, +% Arg #2 is the source file name, +% Arg #3 is the output file name (optional - if not given, the counter +% codeOutput is used). +% Arg #4 controls when to run the code (optional - if not given, it listens +% to \runcode; run = force the code to run; cache or anything else = +% use cache) +\NewDocumentCommand{\runExtCode}{m m m O{}}{ + \stepcounter{codeOutput} + \ifthenelse{\isempty{#3}} + { \setvalue{\tmpname}{tmp/\jobname_tmp\thecodeOutput.tex} } + { \setvalue{\tmpname}{tmp/#3.tex} } + % toggle \runcode above if you want to enable/disable code execution + \ifthenelse{\isempty{#4}} + { \ifruncode + \immediate\write18{#1 #2 > \tmpname } + \fi + }{ + \ifstrequal{#4}{run}{\immediate\write18{#1 #2 > \tmpname }}{} + } +} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \includeOutput[Arg #1]{Arg #2} is used to embed the output from executed code. +% Arg #1 is the output file name (optional - if not given, the counter +% codeOutput is used). +% Arg #2 is the optional type output with default "vbox" +% (vbox = verbatim in a box, tex = pure latex, or inline) + +\NewDocumentCommand{\includeOutput}{m O{vbox}}{\- + \ifthenelse{\isempty{#1}} + {\setvalue{\tmpname}{tmp/\jobname_tmp\thecodeOutput.tex}} + {\unskip\setvalue{\tmpname}{tmp/#1.tex}\unskip}\unskip + % even if the code is not executed, but we ran it before, we can use a + % cached version if it exists. + \IfFileExists{\tmpname} + { + \ifstrequal{#2}{vbox} + {\begin{tcolorbox}[breakable,colback=red!5!white,colframe=red!75!black] + \ifminted\unskip + \inputminted[fontsize=\footnotesize,breaklines=true]{text}{\tmpname}\unskip + \else\unskip + \VerbatimInput[fontsize=\footnotesize,breaklines]{\tmpname}\unskip + \fi + \end{tcolorbox}} + {\unskip\ifstrequal{#2}{inline} + {\unskip\input{\tmpname}\unskip} + {\input{\tmpname}}}} + % if code execution disabled, and no cache: + {\begin{tcolorbox} + Code execution disabled (cache not available). + \end{tcolorbox}}} + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% \inln{Arg #1}{Arg #2}[Arg #3] is used to execute short source code +% and embed resulting output. +% Arg #1 is the executable program; +% Arg #2 is the source code +% Arg #3 is the type output (if skipped or with empty value the default type is +% inline; vbox = verbatim in a box); + +\NewDocumentCommand{\inln}{m m O{inline}}{\- + \stepcounter{codeOutput}\unskip + \unskip\setvalue{\tmpname}{tmp/\jobname_inln\thecodeOutput}\unskip\unskip\unskip + \IfBeginWith{#2}{```}{\ifruncode\immediate\write18{#1 > \tmpname.tex}\unskip\fi} + {\newwrite\tempfile + \immediate\openout\tempfile=\tmpname.txt + \immediate\write\tempfile{#2} + \immediate\closeout\tempfile + \ifruncode + \immediate\write18{#1 \tmpname.txt > \tmpname.tex}\unskip + \fi} + \IfFileExists{\tmpname.tex} + {\unskip + \ifstrequal{#3}{vbox} + {\begin{tcolorbox}[breakable,colback=red!5!white,colframe=red!75!black] + \ifminted\unskip + \inputminted[fontsize=\footnotesize,breaklines=true]{text}{\tmpname.tex}\unskip + \else\unskip + \VerbatimInput[fontsize=\footnotesize,breaklines]{\tmpname.tex}\unskip + \fi + \end{tcolorbox}} + {\unskip\input{\tmpname.tex}\unskip}} + {\textcolor{red}{notrun}}} + +\NewDocumentCommand{\runR}{O{python3 -c 'from talk2stat.talk2stat import client; client("./","R","#2")'} m m O{}} +{ + \def\runcmd{python3 -c 'from talk2stat.talk2stat import client; client("./","R","#2")'} + \ifstrequal{#1}{\runcmd} + {\runExtCode{#1}{}{#3}[#4]} + {\runExtCode{#1}{#2}{#3}[#4]} +} + +\NewDocumentCommand{\inlnR}{O{python3 -c 'from talk2stat.talk2stat import client; client("./","R","\tmpname.txt")'} m O{inline}}{\IfBeginWith{#2}{```}{\inln{python3 -c 'from talk2stat.talk2stat import client;client("./","R","#2")'}{#2}[#3]}{\inln{#1}{#2}[#3]}} + +\NewDocumentCommand{\runJulia}{O{python3 -c 'from talk2stat.talk2stat import client; client("./","julia","#2")'} m m O{}} +{ + \def\runcmd{python3 -c 'from talk2stat.talk2stat import client; client("./","julia","#2")'} + \ifstrequal{#1}{\runcmd} + {\runExtCode{#1}{}{#3}[#4]} + {\runExtCode{#1}{#2}{#3}[#4]} +} + +\NewDocumentCommand{\inlnJulia}{O{python3 -c 'from talk2stat.talk2stat import client; client("./","julia","\tmpname.txt")'} m O{inline}}{\IfBeginWith{#2}{```}{\inln{python3 -c 'from talk2stat.talk2stat import client;client("./","julia","#2")'}{#2}[#3]}{\inln{#1}{#2}[#3]}} + +\NewDocumentCommand{\runMatlab}{O{python3 -c 'from talk2stat.talk2stat import client; client("./","matlab","#2")'} m m O{}} +{ + \def\runcmd{python3 -c 'from talk2stat.talk2stat import client; client("./","matlab","#2")'} + \ifstrequal{#1}{\runcmd} + {\runExtCode{#1}{}{#3}[#4]} + {\runExtCode{#1}{#2}{#3}[#4]} +} + +\NewDocumentCommand{\inlnMatlab}{O{python3 -c 'from talk2stat.talk2stat import client; client("./","matlab","\tmpname.txt")'} m O{inline}}{\IfBeginWith{#2}{```}{\inln{python3 -c 'from talk2stat.talk2stat import client;client("./","matlab","#2")'}{#2}[#3]}{\inln{#1}{#2}[#3]}} + +\endinput |