Hi, I'm hand editing CNC Gcode text files and need a way to reference locations in the file and on the toolpath. I want to modify each line in the text file so that it begins with the the upper case N character followed by line numbers which increment in tens for every successive line, then a whitespace,followed by the original text file. Can I do this in vi?
I'm not sure about vi, but (since you're using the vim tag) Vim allows you to accomplish your task as follows:
Adjust the first line by hand (insert a
N10
at the beginning of the line), then put the cursor at the beginning of the next line.Press
qb
to start recording a macro (theb
names the register used to store the macro; feel free to use a different letter -- and definitely do use a different letter if you've got something useful stashed away inb
).Move the cursor upward to the beginning of the previous line (which you have adjusted by hand). Press
v
to start visual selection mode, thenf
to move the cursor to the next space on the line (if you use a single space as your whitespace separator, that is; adjust this step if you're using a tab or multiple spaces).Press
y
to yank the selected text. This will also remove the visual selection.Move the cursor to the beginning of the next line. Press
P
to insert the previously yanked text before the cursor, that is, on the very beginning of the line.Move the cursor to the numeric part of the line header. Press
10 C-a
(1, 0, control + A) to increment that number by 10.Move the cursor to the beginning of the next line. Press
q
to stop recording the macro.Press
10000000 @b
to execute the macro 10000000 times or until it hits the end of the file. This should be enough to take care of all the lines in your file, unless it is really huge, in which case use a bigger number.
...or use Vim to write a simple script to do the job in whichever language you like best, then run it from a terminal (or from withing Vim with something like :!./your-script-name
). ;-)
There is two possible ways of doing that without using external tools: macro or Vim-script. The first way is a little cumbersome (and probably not as effective as solution listed below), in my opinion.
The second way could be implemented like this (put the code into your .vimrc
or source it other way):
function! NumberLines(format) range
let lfmt = (empty(a:format) ? 'N%04d' : a:format[0]) . ' %s'
for lnum in range(a:firstline, a:lastline)
call setline(lnum, printf(lfmt, lnum, getline(lnum)))
endfor
endfunction
command! -range=% -nargs=? NumberLines <line1>,<line2>call NumberLines([<f-args>])
NumberLines
function enumerates all lines of the file in a given range and prepends to each line its number according to given printf-format (by default, 'N%04d'). To simplify usage of this function I create a new command here that accepts range of lines to process (by default, the whole file) and optional argument—format of the line number.
The following command will prepend 'N<line number * 10>' to every line.
:g/^/exe 'normal! 0iN' . (line('.')*10) . ' '
You can do it easily in Vim with this:
:%s/^/\=line(".")*10 . " "/
This replaces the start of every line with the result of an expression that gives the line number times ten, followed by a space.
I have not timed it, but I suspect it is noticeably faster than the other Vim solutions.