Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I'm preparing some Unix training material and I'd like to show some vertically scrolling text of the commands as if simulating text entry in a terminal. My idea was to split the frame into 2 columns, with the left column showing commands to be entered and the right column having the explanation.

I haven't got past the first part of a scrolling text (vertical marquee text). I've tried the animate package and it only overlays the earlier text. This is what I tried

\documentclass{beamer}
\usepackage{tikz}
\usepackage{animate}
\begin{document}
  \begin{frame}
    \frametitle{MD5SUM}
     \begin{animateinline}[autoplay,loop]{1}
      cat a
      \newframe
      cat b
      \newframe
      md5sum a
     \end{animateinline}
   \end{frame}
 \end{document}

Now beamer has those overlay specifications but I don't think any one of them is suitable for scrolling text. I don't want to hit enter everytime to uncover the next command, just play the command sequences at a specified rate.

Alternately, is there a better way to achieve this? All the animations are going to be text with probably no images.

UPDATE: With Alexander's answer, I tried to use it with Beamer with mixed results.

I've prepared a minimal example where the previous animateinline text is coming through to the next slide. Can anyone tell me, what exactly is going on and where I'm incorrect?

 \documentclass{beamer}
  \usepackage{beamerthemeWarsaw}
  \usepackage{animate}
  \usepackage{expl3}
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  %command for simulating terminal in/output
  %\scroll{<width as TeX dim>}{<number of lines>}{terminal text line}
  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  \ExplSyntaxOn
  \seq_new:N\g_linebuffer_seq
  \newcommand\scroll[3]{
    \ttfamily
    \seq_gput_right:Nx\g_linebuffer_seq{#3}
    \int_compare:nT{\seq_length:N\g_linebuffer_seq>#2}{
    \seq_gpop_left:NN\g_linebuffer_seq\dummy
    }
    \fbox{\begin{minipage}[t][#2\baselineskip]{#1}
    \seq_map_inline:Nn\g_linebuffer_seq{\mbox{##1}\\}
    \end{minipage}}
    }
  \ExplSyntaxOff

\begin{document}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{frame}[fragile]
  \frametitle{Random records}
  How do you randomly select, say 1000 records from a large file?  Use
  the \verb|shuf| command
  \begin{animateinline}[autoplay,loop]{1}
    \scroll{0.8\linewidth}{10}{ cat a}%
    \newframe
     \scroll{0.8\linewidth}{10}{clear}
    \end{animateinline}
%
\end{frame}
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
\begin{frame}[fragile]
  \frametitle{Checking for Duplicate Files}
  How do you quickly check whether 2 files are the same? Use the
  \verb|md5sum| command.
  \begin{animateinline}[autoplay,loop]{1}
    \scroll{0.8\linewidth}{8}{\# echo 1 2 3 > a}
    \newframe
    \scroll{0.8\linewidth}{8}{clear}
  \end{animateinline}
\end{frame}
\end{document}
share|improve this question
add comment

1 Answer

up vote 18 down vote accepted

For simulating terminal output you will have to maintain a line buffer. In the example below I am using the sequence data type of LaTeX3 for this purpose. A minipage of given width and number of lines height is used to mimick the terminal window. If the number of lines in the buffer goes past the height of the minipage, the top line in the buffer will be removed.

EDIT: New command \clearbuf clears the line buffer. Recommended use before first \scroll in an animateinline environment and to simulate clear (screen) shell command.

EDIT 2: This new version allows for ''multiline'' text as argument to \scroll. However, line breaks must be explicitly denoted in the argument using a marker string. The default is §§ which is rarely seen on terminals. But any user defined sequence of letters is possible. User defined marker strings must be passed as optional first argument, enclosed between [ and ] to \scroll.

EDIT 3: Note that macros within the text argument of \scroll are expanded before being added to the line buffer. The reason is to make macros which are called more than once but change their content between calls to \scroll, such as the line numbers \i in the example, work correctly.

Use \noexpand if you want to defer expansion of macros to the time when the whole line buffer is typeset. This is useful for escaping special characters or for text formatting macros (colour, typeface). See the updated example.

\documentclass{article}
\usepackage{courier}
\usepackage{animate}  
\usepackage{expl3}

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
%commands for simulating terminal in/output  
%\scroll[<line separator string>]{<width as TeX dim>} 
%                             {<number of lines>}{terminal text line}  
%\clearbuf  %clears line buffer  
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%  
\ExplSyntaxOn
\seq_new:N\g_linebuffer_seq
\seq_new:N\g_inputline_seq
\newcommand\scroll[4][§§]{
  \seq_set_split:Nnn\g_inputline_seq{#1}{#4}
  \seq_map_inline:Nn\g_inputline_seq{
    \seq_gput_right:Nx\g_linebuffer_seq{##1}
    \int_compare:nT{\seq_count:N\g_linebuffer_seq>#3}{
      \seq_gpop_left:NN\g_linebuffer_seq\dummy
    }
  }
  \fbox{\begin{minipage}[t][#3\baselineskip]{#2}
    \ttfamily
    \seq_map_inline:Nn\g_linebuffer_seq{\mbox{##1}\\}
  \end{minipage}}
}
\newcommand\clearbuf{\seq_gclear:N\g_linebuffer_seq}
\ExplSyntaxOff

\begin{document}  

  \begin{animateinline}[controls,loop]{1}  
      \scroll{0.9\linewidth}{8}{cat a}  
    \newframe 
      \scroll{0.9\linewidth}{8}{cat b} 
    \newframe 
      \scroll{0.9\linewidth}{8}{John§§Linda§§Albert§§Francis}  
    \newframe 
      \scroll{0.9\linewidth}{8}{ln -s a empty.txt}
    \newframe 
      \scroll{0.9\linewidth}{8}{md5sum empty.txt}
    \newframe
      \scroll{0.9\linewidth}{8}{d41d8cd98f00b204e9800998ecf8427e  empty.txt}
    \newframe 
      \scroll{0.9\linewidth}{8}{clear}\clearbuf  
    \newframe 
      \scroll{0.9\linewidth}{8}{}\clearbuf
    \newframe  
    \multiframe{10}{i=1+1}{
       \scroll{0.9\linewidth}{8}{\noexpand\# Line \i}
    }  
  \end{animateinline}  

  \begin{animateinline}[controls,loop]{1}  
      \clearbuf\scroll{0.9\linewidth}{8}{cd /usr/bin}
    \newframe  
      \scroll{0.9\linewidth}{8}{echo \noexpand\$PWD} 
    \newframe 
      \scroll{0.9\linewidth}{8}{/usr/bin}
    \newframe
      \scroll{0.9\linewidth}{8}{ls -l md5sum} 
    \newframe 
      \scroll{0.9\linewidth}{8}{% 
        -rwxr-xr-x 1 root root 30172 Dec 14 2010
        \noexpand\bfseries\noexpand\color{red}md5sum
      } 
    \newframe
      \scroll{0.9\linewidth}{8}{clear}\clearbuf
    \newframe 
      \scroll{0.9\linewidth}{8}{}\clearbuf
  \end{animateinline}  

\end{document}
share|improve this answer
    
Fantastic! This works beautifully in article and beamer classes. However in my big beamer tex file, I get ! TeX capacity exceeded, sorry [input stack size=5000]. \not@math@alphabet ...@error {Command \noexpand #1 invalid in math mode}{Plea... l.111 \end{frame} ! ==> Fatal error occurred, no output PDF file produced! Transcript written on Datahacks.log. How do I fix this,please? –  Sivaram Dec 12 '11 at 17:39
    
belay that. there were some \$ in the env which were causing it. Removing it made the tex error go away. {<number of lines>}, why is it repeated for every scroll command? –  Sivaram Dec 12 '11 at 17:58
    
there seems to be a minor bug. If you repeat the animateinline env in another frame, it shows the first animation and then the 2nd one in the new frame. I just tested a minimal example with the same env repeated in 2 different frames and it replicates everything in the 2nd frame. –  Sivaram Dec 12 '11 at 18:45
    
updated original post with minimal example that fails. –  Sivaram Dec 13 '11 at 8:55
1  
Of course, the line buffer must be cleared before reuse in another animation, as it survives \end{animateinline}. See the improved code example. –  AlexG Dec 13 '11 at 9:45
show 7 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.