Search code examples
emacsreferencelinekillyank

How to copy/paste a region from emacs buffer with line + file reference?


From time to time I see people pasting portions of code with reference to the file name and line number. Something like

 ;; ----- line:3391   file: simple.el.gz -----;;; 

 (if (eq last-command 'kill-region)
      (kill-append (filter-buffer-substring beg end) (< end beg))
    (kill-new (filter-buffer-substring beg end)))

 ;; ----- line:3394 --------------------------;;;

This is mainly useful to send comments on code by mail. I can easily wrap a simple function for myself, but I am sure someone have already done this in a smart and pretty way.

Thanks.

[EDIT]

Because this functionality is needed only occasionally, and only for one copy/paste action, I ended up using an alternative solution to the toggling version proposed by @thisirs.

(defun kill-with-linenum (beg end)
  (interactive "r")
  (save-excursion
    (goto-char end)
    (skip-chars-backward "\n \t")
    (setq end (point))
    (let* ((chunk (buffer-substring beg end))
           (chunk (concat
                   (format "╭──────── #%-d ─ %s ──\n│ "
                           (line-number-at-pos beg)
                           (or (buffer-file-name) (buffer-name))
                           )
                   (replace-regexp-in-string "\n" "\n│ " chunk)
                   (format "\n╰──────── #%-d ─" 
                           (line-number-at-pos end)))))
      (kill-new chunk)))
  (deactivate-mark))

It is unicode based and produces this output:

╭──────── #3557 ─ /usr/share/emacs/24.1.50/lisp/simple.el.gz ──
│   (if (eq this-command t)
│       (setq this-command 'yank))
│   nil)
╰──────── #3559 ─

Solution

  • I have come up with this, using wrapper hook:

    (defun filter-buffer-substring-add-line (func beg end delete)
      (concat
       (format ";; line:%5d file: %s\n"
               (line-number-at-pos beg)
               (or (buffer-file-name) (buffer-name)))
       (funcall func beg end delete)
       (format "\n;; line:%5d" (line-number-at-pos end))))
    
    (defun kill-add-line-toggle ()
      (interactive)
      (if (memq 'filter-buffer-substring-add-line
                filter-buffer-substring-functions)
          (progn
            (setq filter-buffer-substring-functions
                  (delq 'filter-buffer-substring-add-line
                        filter-buffer-substring-functions))
            (message "Add line is off!"))
        (push 'filter-buffer-substring-add-line
              filter-buffer-substring-functions)
        (message "Add line is on!")))