Join Lines By A Separator in Emacs


So sometimes I need to join a few lines by a separator while I'm coding, for example, turn the below lines,

foo
bar
baz

into foo + bar + baz. (This is a silly example, I will update if I come up with a better one :-P )

When I was in a rush in the past, I usually baked a keyboard macro temporarily and then applied it to achieve this goal, thought reliable, it's a little bit cumbersome to record it. So I wonder maybe it would be a good idea to have a command for it.

The first version

(defun w/join-lines (specify-separator)
  "Join lines in the active region by a separator, by default a comma.
Specify the separator by typing C-u before executing this command.

Note: it depends on s.el."
  (interactive "P")
  (require 's)
  (unless (region-active-p)
    (message "select a region of lines first."))
  (let* ((separator (if (not specify-separator)
                        ","
                      (read-string "Separator: ")))
         (text (buffer-substring-no-properties
               (region-beginning)
               (region-end)))
         (lines (split-string text "\n"))
         (result (s-join separator lines)))
    (delete-region (region-beginning) (region-end))
    (insert result)))

So when the task comes up the next time, with this command, I will just select the lines as a region and then M-x w/join-lines to join the lines there. And, if I want a separator other than a comma, I can do that by typing C-u M-x w/join-lines, then it will prompt me to type a separator first, before doing the job.

The second version

After using the first version for some time, I realize that it's more possible that the separator used in a serial would be same, so if it happens to not be a comma, I need to specify the separator every time, which is definitely cumbersome.

So here is an improved version, which keeps the last used separator. We only have to specify it when we want to change it to a different one.

(defvar w/join-lines--last-separator ","
  "Keep the last used separator for `w/join-lines', a comma by default.")

(defun w/join-lines (&optional specify-separator)
  "Join lines in the active region by a separator, by default the last used.
Specify the separator by typing C-u before executing this command.

Note: it depends on s.el."
  (interactive "P")
  (require 's)
  (unless (region-active-p)
    (error "select a region of lines first."))
  (let* ((separator (if (not specify-separator)
                        w/join-lines--last-separator
                      (read-string "Separator: ")))
         (text (buffer-substring-no-properties
               (region-beginning)
               (region-end)))
         (lines (split-string text "\n"))
         (result (s-join separator lines)))
    (delete-region (region-beginning) (region-end))
    (insert result)
    (setq w/join-lines--last-separator separator)))
Emacs 

See also

comments powered by Disqus