2

I have a beamer(LaTeX) file containing many \begin{frame} lines. I want to debug the code to viewing the output of its. The pdf output shows frame number. When I try to change a specific numbered frame in source I have to give more time to find out that frame as there is no fame numbering in source code.

So, I want to give frame number as comment in each \begin{frame} as \begin{frame}%frame_no when it is not commented yet.

But, I don't want to write this each time when I add a frame and calculate the number. I want to make this autonomous such that when I press :w or any user command it add the frame number.

Sample file -

\documentclass[usenames,dvipsnames]{beamer}
\usepackage{xcolor}
\usepackage{tikz}
\usepackage{listings}
\usepackage{algpseudocode}
\usefonttheme[onlymath]{serif}
\usepackage{amsmath}
\usetheme{Madrid}


\algnewcommand\algorithmicinput{\textbf{Input:}}
\algnewcommand\algorithmicoutput{\textbf{Output:}}
\algnewcommand\algorithmicinitialization{\textbf{Initialize:}}
\algnewcommand\Input{\item[\algorithmicinput]}%
\algnewcommand\Output{\item[\algorithmicoutput]}%
\algnewcommand\Initialize{\item[\algorithmicinitialization]}%


\logo{%
  \includegraphics[width=1cm,height=1.5cm,keepaspectratio]{Image/DUlogo}%
  \hspace{\dimexpr\paperwidth-2cm-5pt}%
  \includegraphics[width=1cm,height=1cm,keepaspectratio]{Image/GNR.png}%
}
\begin{document}
  \title{Cross-Layer  Resource  Allocation With  Elastic Service Scaling in Cloud Radio Access Network}
  \author[alhelal \& Jobayed Ullah]{
  \parbox{2.5cm}{
\centering Md.Al-Helal\\Roll:SH-51}\hspace{1cm}
\parbox{2.5cm}{
{\centering Jobayed Ullah\\Roll:EK-107}}
}
\institute[CSEDU]{Computer Science \& Engineering\\CSEDU}
\date{February 25, 2018}
\begin{frame}
  \maketitle
\end{frame}
  \title{Cross-Layer  Resource  Allocation With  Elastic Service Scaling in Cloud Radio Access Network}
  \author{Jianhua Tang\\ Wee Pen Tay\\ Tony Q. S. Quek}
\institute{IEEE Transactions on Wireless Communications, vol 14, no. 9}
\date{September 2015}
\begin{frame}
  \maketitle
\end{frame}
  \author{alhelal \& Jobayed Ullah}
\institute{CSEDU}
\begin{frame}
\maketitle
\end{frame}
\end{document}
1

There is another way to proceed without needing to define an helper function.

The idea is to fill a list and to inject the list size with :s\=.

:let counter=[]
:%s/\\begin{frame}\zs\(%\d\+\)\=/\='%'.len(add(counter, 42))

Or as a command in a ~/.vim/ftplugin/tex/count-frames.vim ftplugin file:

command! -b -range=% -nargs=0 NumberFrames 
    \ :let g:counter=[]|:<line1>,<line2>s/\\begin{frame}.\{-}\zs\(%frame_\d\+\|$\)/\='%frame_'.len(add(g:counter, 42))

Which will work on the whole buffer by default, or only on a given range that can be defined explicitly (:12,42NumberFrames) or with a visual selection ('<,'>NumberRanges)

  • would you edit your answer so that it put framenumber at end of the line for \begin{frame}{\relax}? – alhelal Feb 28 '18 at 16:26
  • add frame_number instead of just number so that I can find a frame easily by searching. – alhelal Feb 28 '18 at 16:32
  • :12,42NumberFrames works but :%sNumberFrames doesn't work. – alhelal Feb 28 '18 at 16:43
  • This is normal. To delete or to yank, we don't type %sd or %sy. We type %d or %y. %s is for %substitute. The range for the whole file is %, not %s. :h :range – Luc Hermitte Feb 28 '18 at 17:03
  • yes you are right. I know s for substitute, but as I use this all times, I forgot that NumberFrames is not substitution. Thank you. Please,Consider my 1st 2 comments. – alhelal Feb 28 '18 at 17:18
2

If I understand you correctly, you should be able to to it with e.g. a custom command. Something like this should work:

function NumberFrame(match)
    let g:number+=1
    return a:match.'%'.g:number
endfunction

:com! NumberFrame :let g:number=0|:%s#\(\\begin{frame}\)\(%\d\+\)\?#\=NumberFrame(submatch(1))#

That uses a custom command :NumberFrame, that first initializes the counter, followed by a :s command that looks for \begin{frame} followed by an optional comment, takes the input to a function that increments the counter and returns the input followed by your comment. So in your Latex document simply call :NumberFrame.

You can put that definition into ~/.vim/vimrc (or whatever vimrc file you are using) or you can put that into ~/.vim/ftplugin/tex.vim to make that command filetype specific (e.g. it will only be available in tex documents). Make sure you have a line :filetype plugin on in your .vimrc to enable filetype specific plugins. In that case you should probably put a :let b:undo_ftplugin=':delcommand NumberFrame' to delete the command when another filetype is loaded. See the help at :h undo_ftplugin

You can get more fancy about it (e.g. add some more error conditions, refine your regular expression, recount on BufWritePre autocommands, etc). But as such it is a simple solution that shows how to do the main thing.

See the help at :h sub-replace-expression

  • Please, mention where(e.g.,.vimrc) I put those and what is the command to execute this function? – alhelal Feb 28 '18 at 1:38
  • I have updated the questino. – Christian Brabandt Feb 28 '18 at 6:37
  • both the function NumberFrame and :com! ... line in tex.vim? I put NumberFrame in tex.vim and execute com! ... in command mode inside vim, that doesn't work. – alhelal Feb 28 '18 at 6:59
  • Put both inside tex.vim that should be loaded by vim whenever it detects the filetype tex. See :h ftplugins. If it still does not work, you might want to ask another question. – Christian Brabandt Feb 28 '18 at 11:06
  • The command should be defined buffer-wise with command -b. I'm not sure we really need to undefine the command if the end-user wants to change the current filetype to something else for files ending in .tex in a simple (undistributed) case. And in that case, it should be let b:undo_ftplugin .= -- several ftplugin files can coexist. – Luc Hermitte Feb 28 '18 at 15:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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