A cheap way to do this using external tools is just to select a region (or the entire buffer using C-x h
), and then run M-| cat -n
, then copy the output (M-|
is bound to shell-command-on-region
). Keep in mind that GNU Emacs is embedded inside of a *nix system, so invoking external utilities is something totally normal.
If you want a Elisp-solution, that respects the current line number if you are only selecting a sub-region, then consider the following
(defun kill-save-with-line-numbers (start end)
"Kill region between START and END with line numbers."
(interactive "r")
(let ((line (line-number-at-pos start))
(buffer (current-buffer)))
(with-temp-buffer
(insert-buffer-substring buffer start end)
(untabify (point-min) (point-max))
(goto-char (point-min))
(while (not (eobp))
(insert (format "%4d " line))
(forward-line)
(setq line (1+ line)))
(kill-new (buffer-string)))))
It can certainly be improved, so it only serves as a sketch (as an exercise, consider the case when the region doesn't start at the end of a line, or when the line number exceeds four digits).
Oh, and another idea would be to record a keyboard macro to change the buffer in place. For that to work, you need to make use of macro counters. Set it initially using C-x C-k C-c
to the value of the current line number and set a counter formatting using C-x C-k C-f
to something like "%4d "
, then record a macro like this
C-x ( C-a C-x C-k C-i C-x )
You can now select a region and apply the macro to each line using C-x C-k r
.
At the same time, consider not doing any of this if you want to paste snippets. That only makes it harder for someone to copy the code to their local editor (of course an Emacs user won't have much difficulties removing it, the real problem is deciding how: Rectangular selection, replacing a regular expression matching line numbers at the beginning of a line with the empty string, writing a custom command, etc.).
shell-command-on-region
and pass it a shell command written in (awk
,python
,shell
,perl
,C
,C++
, ...). Here's abash
script usingawk
that takes an optional beginning line number as argument:#! /bin/bash typeset -i init=${1:-1} awk ' BEGIN { ln = '$init'; } { printf("%6d: %s\n", ln, $0); ln += 1;} '
grep -n .
, although the line number display is not as nice. I'll try to remember to get back to this later on (I don't have time ATM).