# How to replace string with value and the occurance number?

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}

\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}


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}? Feb 28 '18 at 16:26
• add frame_number instead of just number so that I can find a frame easily by searching. Feb 28 '18 at 16:32
• :12,42NumberFrames works but :%sNumberFrames doesn't work. 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 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. Feb 28 '18 at 17:18

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? Feb 28 '18 at 1:38
• I have updated the questino. 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. 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. 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. Feb 28 '18 at 15:29