lunes, 28 de enero de 2013

a simple pattern to shorten the feedback cycle

Lately I had to do some work on nginx configuration and lua-scripting (here is the detailed info on augmenting an API through nginx and lua). To do so, the development cycle is the following:
  1. edit nginx conf file or lua file called from the nginx conf file.
  2. restart or reload nginx.
  3. check in nginx log file for errors
  4. Try the feature via curl or browser
I 'nulled' the 2nd step via a very simple pattern that I've been using lately. It's dead simple, but involves a few elisp-ities you may or may not know. Anyway, check it out.
The 'trick' is to use buffer local variables to run the appropiate commands in each buffer. So you should set a variable called run-command, to the string that will be executed when saving.
Hint: here's the pattern for the prop-line in case you want emacs to set the variable automatically when you open the file.
# -*- run-command: "/opt/openresty/nginx/sbin/nginx -c /home/rgrau/workspace/nginx-translator/config_nginx.conf -p /tmp/nginx/  -s reload"; -*

For more fancyness, there's also add-file-local-variable-prop-line which can help you.
And the tiny code to hook the command to after-save hook.
(defun rgc/run-command ()
  (interactive)
  (when (boundp 'run-command)
    (shell-command run-command)))

(add-to-list 'after-save-hook 'rgc/run-command)
To speed up the 3rd step, you can play with tailing the log file in a shell-mode buffer, or use auto-reverse-tail-mode. But let's leave it for another post :) Btw, Next weekend I'll be the next FOSDEM. If anyone wants to meet and hack some elisp or discuss vim vs emacs with a beer, ping me (raimonster at gmail dot com)

miércoles, 9 de enero de 2013

Parsing elisp code with elisp

Today, in Reddit there was this guy presenting a utility library for elisp.


In the comments, there was a discussion about generating documentation
from an elisp file. The approach there is fine: parsing the file via
regexen and asking for the documentation to the elisp system itself.

Here's another version I wrote that walks through the code looking for
defuns and defmacros.  The code parses a buffer, and picks the
docstring from the code itself, so it catches it even if the methods
haven't been evaluated.  It's not a real advantage as you won't
probably try to document a code you aren't evaluating, but just for
the sake of the exmple, I think it's a good learning exercice.

So here's the code:

 (defun fetch-defuns (buffer)
   (interactive)
   (save-excursion
     (goto-char (point-min))
     (let (sexp
          (defuns nil)
          (defmacros nil))
       (condition-case nil
          (while t
            (setq sexp (read buffer))
            (when (listp sexp)
              (case (car sexp)
                (defun (push (cons (cadr sexp) (doc-if-any sexp)) defuns))
                (defmacro (push (cons (cadr sexp) (doc-if-any sexp)) defmacros)))))
        (error nil))
       (generate-docs defuns))))
 
 (defun doc-if-any (sexp)
   "search for the doc"
   (when (stringp (cadddr sexp))
     (cadddr sexp)))
 
 (defun generate-docs (defuns)
   "generate a simple org with the docs"
   (mapconcat (lambda (x) (format "* %s
   %s" (car x) (or (cdr x) "-undocumented-"))) defuns "\n\n"))

M-: (fetch-defuns (current-buffer)) will return a minimal org-file skeleton with the function names and their docs.

The cool way to ask for the documentation of a function, however, is just (documentation 'name-of-fun). try it. It's great.

Happy emacs hacking!