I use Markdown on my blog for posts and comments, and I post at other sites that use Markdown (e.g. Stack Overflow). In Markdown, text indented four spaces is displayed as code, in
I find myself often writing code in Vim or Emacs and needing to copy/paste it into a browser in a Markdown-suitable way.it back. This is easy to do in Vim and Emacs, only a few keystrokes. But "a few" is still greater than "one", so the heck with that. Let's script it.
This keymapping in Vim will do it all for me:
vmap <Leader>y :s/^/ /<CR>gv"+ygv:s/^ //<CR>
One clumsy thing about Vim is needing to restore the previous visual selection after each regex-replacement. I could use the marks
'> as ranges to
:s instead, but that's more typing than simply doing
gv in the mapping. Copying to the system clipboard is easy because Vim has a register
"+ for that purpose.
This took me maybe 45 seconds to write, probably due to being pretty familiar with Vim already. But in Vim, mappings are easy. You just type the characters that you'd type if you were doing it manually.
Trying to do the same in Emacs was painful. My Emacs-fu is sorely inadequate, compared to my Vim-jitsu. This seems to work, but ugh:
;; adapted from http://www.emacswiki.org/emacs/.emacs-ChristianRovner.el (defun expand-region-linewise () (interactive) (let ((start (region-beginning)) (end (region-end))) (goto-char start) (beginning-of-line) (set-mark (point)) (goto-char end) (unless (bolp) (end-of-line)))) (defun markdown-copy () (interactive) (save-window-excursion (save-excursion (save-restriction (expand-region-linewise) (narrow-to-region (region-beginning) (region-end)) (goto-char (point-min)) (replace-regexp "^" " ") (clipboard-kill-ring-save (point-min) (point-max)) (goto-char (point-min)) (replace-regexp "^ " "")))))
Writing this involved a long journey through the Emacs documentation.
One difficulty was getting Emacs to play friendly with my fat-fingered region-marking. I don't always highlight from the beginning of the first line to the end of the last. That's why Vim's visual-line mode is awesome; the cursor can be anywhere on the line, it still selects the whole line. The handy function above (found on the Emacs wiki) takes care of that. I don't know how long it would've taken me to come up with that on my own.
Then it was a matter of rooting through millions of Emacs functions until I found the ones that move the point around and copy text to the clipboard. Along the way I discovered the wonders of "narrowing", which limits Emacs to work on some region of text, and all those macros to undo the messes I make while moving around.
Maybe I could've done this with an Emacs keyboard macro, and then called
apply-macro-to-region-lines. And maybe I could use
append-next-kill to build up the indented text one line at a time. But my efforts to do this or anything like it failed horribly.
In any case I thought it was an interesting comparison. Improvements to either version are welcome.
EDIT: This works too (thanks Holger Durer):
(defun markdown-copy () (interactive) (save-excursion (expand-region-linewise) (indent-rigidly (region-beginning) (region-end) 4) (clipboard-kill-ring-save (region-beginning) (region-end)) (indent-rigidly (region-beginning) (region-end) -4)))