10

I would like to include both input and output cells that look like Jupyter IPython cells. The "IPython Notebook cells with listings" at IPython Notebook cells with listings shows how to do a single input cell but I would like to display several lines with both input and output lines, something like this, for example, where Out[ ] does not advance the counter but In[ ] does: ,

1
  • Welcome to TeX.SX! Commented Nov 24, 2016 at 6:03

2 Answers 2

8

I also started with the link you provided and came up with this solution. Basically you define three listing environments (one for inputs, one for printed text, and one for output). I admit that the solution is not super-elegant (repeated definition of options) but it works well offering you automatic numbering and even supporting labeling/referencing.

\usepackage{xcolor}
\usepackage[most]{tcolorbox}
\usepackage{listings}

\definecolor{white}{rgb}{1,1,1}
\definecolor{mygreen}{rgb}{0,0.4,0}
\definecolor{light_gray}{rgb}{0.97,0.97,0.97}
\definecolor{mykey}{rgb}{0.117,0.403,0.713}

\tcbuselibrary{listings}
\newlength\inwd
\setlength\inwd{1.3cm}

\newcounter{ipythcntr}
\renewcommand{\theipythcntr}{\texttt{[\arabic{ipythcntr}]}}

\newtcblisting{pyin}[1][]{%
  sharp corners,
  enlarge left by=\inwd,
  width=\linewidth-\inwd,
  enhanced,
  boxrule=0pt,
  colback=light_gray,
  listing only,
  top=0pt,
  bottom=0pt,
  overlay={
    \node[
      anchor=north east,
      text width=\inwd,
      font=\footnotesize\ttfamily\color{mykey},
      inner ysep=2mm,
      inner xsep=0pt,
      outer sep=0pt
      ] 
      at (frame.north west)
      {\refstepcounter{ipythcntr}\label{#1}In \theipythcntr:};
  }
  listing engine=listing,
  listing options={
    aboveskip=1pt,
    belowskip=1pt,
    basicstyle=\footnotesize\ttfamily,
    language=Python,
    keywordstyle=\color{mykey},
    showstringspaces=false,
    stringstyle=\color{mygreen}
  },
}
\newtcblisting{pyprint}{
  sharp corners,
  enlarge left by=\inwd,
  width=\linewidth-\inwd,
  enhanced,
  boxrule=0pt,
  colback=white,
  listing only,
  top=0pt,
  bottom=0pt,
  overlay={
    \node[
      anchor=north east,
      text width=\inwd,
      font=\footnotesize\ttfamily\color{mykey},
      inner ysep=2mm,
      inner xsep=0pt,
      outer sep=0pt
      ] 
      at (frame.north west)
      {};
  }
  listing engine=listing,
  listing options={
      aboveskip=1pt,
      belowskip=1pt,
      basicstyle=\footnotesize\ttfamily,
      language=Python,
      keywordstyle=\color{mykey},
      showstringspaces=false,
      stringstyle=\color{mygreen}
    },
}
\newtcblisting{pyout}[1][\theipythcntr]{
  sharp corners,
  enlarge left by=\inwd,
  width=\linewidth-\inwd,
  enhanced,
  boxrule=0pt,
  colback=white,
  listing only,
  top=0pt,
  bottom=0pt,
  overlay={
    \node[
      anchor=north east,
      text width=\inwd,
      font=\footnotesize\ttfamily\color{mykey},
      inner ysep=2mm,
      inner xsep=0pt,
      outer sep=0pt
      ] 
      at (frame.north west)
      {\setcounter{ipythcntr}{\value{ipythcntr}}Out#1:};
  }
  listing engine=listing,
  listing options={
      aboveskip=1pt,
      belowskip=1pt,
      basicstyle=\footnotesize\ttfamily,
      language=Python,
      keywordstyle=\color{mykey},
      showstringspaces=false,
      stringstyle=\color{mygreen}
    },
}


\begin{document}

\begin{pyin}
print("Hello world")
\end{pyin}

\begin{pyprint}
Hello world
\end{pyprint}

And here we also have a return value in the last line of the input cell.
\begin{pyin}[labelOfTheSecondInput]
def twicify(arg):
    print("Received:", arg, "- Will double now...")
    return 2 * arg
twicify(1)
\end{pyin}

\begin{pyprint}
Received: 1 - Will double now...
\end{pyprint}

\begin{pyout}
2
\end{pyout}

You can also reference the labeled input \ref{labelOfTheSecondInput}.
\begin{pyin}
"and the counter will automatically do the right thing :)"
\end{pyin}
\begin{pyout}
'and the counter will automatically do the right thing :)'
\end{pyout}

\end{document}

Output

1
  • Welcome to TeX.SE. I think, this is a good answer. I'd tried it the same way.
    – Jan
    Commented Jan 24, 2017 at 18:18
1

I used moredelims option of the lstlisting package to get similar output but without boxes. If you need to document IPython shell, this may useful as you don't need so many \begin{} and \end{} statements, instead just copy from IPython shell, and replace the number inside the square brackets with a colon, i.e. In[9] changes to In[:], after pasting in the document.

Here is the MWE


\documentclass[a4paper, 11pt, onecolumn, openany, oneside]{article}
\usepackage[svgnames]{xcolor}
\usepackage[many]{tcolorbox}
\tcbuselibrary{listings}
\definecolor{ared}{rgb}{.647,.129,.149}

\definecolor{Dark}{gray}{.2}
\definecolor{MedDark}{gray}{.4}
\definecolor{Medium}{gray}{.6}
\definecolor{Light}{gray}{.8}

\definecolor{codegreen}{rgb}{0,0.6,0}
\definecolor{codered}{rgb}{0.6,0.1,0}
\definecolor{codegray}{rgb}{0.5,0.5,0.5}
\definecolor{codepurple}{rgb}{0.58,0,0.82}
\definecolor{backcolour}{rgb}{0.95,0.95,0.92}
\definecolor{lightgray}{gray}{0.95}
\definecolor{codeblue}{rgb}{0.117,0.403,0.713}

% IPython
\newcounter{ipythcntr}
\renewcommand{\theipythcntr}{\texttt{[\arabic{ipythcntr}]}}
\newcommand{\ipin}[1][]{
    \stepcounter{ipythcntr}
    \hspace{-10pt}
    \color{codeblue}In  \theipythcntr}
\newcommand{\ipout}[1][\theipythcntr]{
    \hspace{-10pt}
    \color{codered}Out \theipythcntr}
\lstset{
    language=Python, 
    moredelim=[is][\ipin]{In[}{]},
    moredelim=[is][\ipout]{Out[}{]},
    backgroundcolor=\color{lightgray},
    commentstyle=\color{codegreen},
    xleftmargin = 8pt,
    basicstyle=\footnotesize\ttfamily,
    keywordstyle=\color{codeblue},
    showstringspaces=false,
}
\begin{document}

\begin{lstlisting}[caption=MWE]
# Add two numbers
In[:] 9 + 3
Out[:] 12
# Multiline output
In[:] for i in range(4):
      print(i**2-1)
    -1
    0
    3
    8
\end{lstlisting}
\end{document}

MWE

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .