Thursday, April 02, 2015

The Joy of An elisp Powered Code Review

Back in the day, when I was a team lead, I did more than my fair share of code reviews. What made the process relatively painless (at least for me, the reviewer) was a handy elisp function that made citing code from within emacs a breeze. I'd mark a region, hit a keystroke, and I was ready to paste the discussion-worthy code into an e-mail message. Having this function was like having a spell checker in your code editor; a seemingly superfluous feature, until you realize that you're utterly dependent on it.

Unfortunately, somewhere over the years I've lost this magic bit emacs code. Surely there's a whole package dedicated to citing code, but for the life of me, I couldn't find it. And so when I needed to review someone's code yesterday (something I apparently haven't done in years), I rewrote this function.

Now, I can set a region in emacs and type M-x code-review-region and poof! the code is annotated with the file name I grabbed it from, the line number, and a bit of ASCII art to show the item as being quoted. For example, I just ran this function on some utility PHP code:

+---[web/shared/lib/util.php:25]
| function dev_env() {
|   return strtolower(g($_SERVER, 'SERVER_NAME')) == 'localhost';
| }
+---

And here's the elisp function. Happy code reviewing!

(defun code-review-region (beg end)
  (interactive "r")
  (let* ((text (chomp (buffer-substring-no-properties beg end)))
         (line-number (line-number-at-pos))
         (file (buffer-file-name))
         (path (replace-regexp-in-string "^.*branches/" ""
                                         (replace-regexp-in-string 
                                          "^.*trunk/" "" file))))
     (with-temp-buffer
       (insert text)
       (goto-char (point-min))
       (while (re-search-forward "^" nil t)
         (replace-match "| " nil nil))
       (goto-char (point-min))
       (insert (format "+---[%s:%s]\n" path line-number))
       (goto-char (point-max))
       (insert "\n+---\n")
       (kill-region (point-min) (point-max)))))

7 comments:

  1. Anonymous7:22 PM

    If you have boxquote.el installed, you could use box-quote-region and boxquote-title to make the box around the code you're quoting :-)

    ReplyDelete
  2. Ahhhh yes, boxquote.el! That's almost certainly the original package that inspired me, but I couldn't recall. Thanks!

    ReplyDelete
  3. If you use `region-binding-mode`, it would go perfect with such a function. You simply select a region and and hit a key binding to execute this command. I have a similar function inspired from a Stackoverflow answer ( https://github.com/kaushalmodi/.emacs.d/tree/3c01a24d5c2e85d3cb00e3543b304849e9918e67/setup-files/setup-editing.el#L224 ). Using `region- binding-mode`, I simply select a region of code I want to share and hit `c` or `C-u c` to copy the code with non-unicode or unicode characters to form the code border.

    ReplyDelete
  4. Where is your chomp function coming from?

    ReplyDelete
  5. D'oh. Here you go:

    (defun chomp (str)
    "Chomp leading and tailing whitespace from STR."
    (replace-regexp-in-string (rx (or (: bos (* (any " \t\n")))
    (: (* (any " \t\n")) eos)))
    ""
    str))

    ReplyDelete
  6. Nice! Very similar to how I do it, but I often stay in Emacs and do some more reviewing and commenting there, so I setup a special buffer for that. I don't do the fancy box thing, but perhaps I should add it :)

    Here is the main part of my code review review stuff:

    https://gist.github.com/mathiasdahl/56b9ae8ce0f39c43f209

    ReplyDelete
  7. Mathias - thanks for sharing!

    ReplyDelete