Yay, I’m a celebrity now!

Posted: December 9, 2011 in Uncategorized

I’ve just received an email from wordpress congratulating me that my blog has gotten its first follower. I run that blog for about five years now, and I didn’t even know that there is some following functionality! Well, now I can see that button.  Prior to that, it was just one of the 378 other buttons in the wordpress interface I have no clue for what they are good for.

Seems like I am an old fart, totally Web 0.1… ;-)

A quick pop-up shell for emacs

Posted: October 12, 2011 in Emacs, Emacs Lisp
Tags:

Some file managers provide a shortcut to quickly embed some terminal that’s initialized with the current directory as cwd. Wouldn’t that be cool to have in emacs?

For example, you edit some file, and then you want to quickly commit it. Using the code below, you can do that like this:

  • Edit the file and save: C-x C-s
  • Popup a shell: F12
  • Check changes and commit (using svn):
    $ svn diff | colordiff
    $ svn ci -m "some changes" RET
  • Close the popup shell again: F12
  • Here’s the code:

    (defvar th-shell-popup-buffer nil)
    
    (defun th-shell-popup ()
      "Toggle a shell popup buffer with the current file's directory as cwd."
      (interactive)
      (unless (buffer-live-p th-shell-popup-buffer)
        (save-window-excursion (shell "*Popup Shell*"))
        (setq th-shell-popup-buffer (get-buffer "*Popup Shell*")))
      (let ((win (get-buffer-window th-shell-popup-buffer))
    	(dir (file-name-directory (or (buffer-file-name)
    				      ;; dired
    				      dired-directory
    				      ;; use HOME
    				      "~/"))))
        (if win
    	(quit-window nil win)
          (pop-to-buffer th-shell-popup-buffer nil t)
          (comint-send-string nil (concat "cd " dir "\n")))))
    
    (global-set-key (kbd "<f12>") 'th-shell-popup)

    Using that, hitting F12 will popup a *Popup Shell* buffer, initialized in the directory containing the file your are currently editing. If the current buffer is not associated with a file, then the shell’s cwd is your HOME directory.

    Hitting F12 while the popup shell buffer is visible will hide it again. So you can use it as a simple toggle.

    The code ensures that the same shell buffer is reused over and over again (unless you kill it), so that you don’t end up with hundredth of them.

    And here’s a screenshot:

    UPDATES:

    • 2011-10-13 08:03: Made it work for dired buffers.
    • 2012-02-24 14:41: Use quit-window instead of delete-window.

    defmacro! revisited

    Posted: September 28, 2011 in Clojure
    Tags: ,

    In my last post, I’ve introduced the defmacro! macro, which is just like defmacro, except that it guarantees that all of the arguments are evaluated once only.

    However, in contrast to Doug Hoyte’s defmacro! he introduced in Let over Lambda, my macro expanded into a normal defmacro form that expanded into a form where all args were evaluated exactly once.

    Clearly, this was totally flawed, because in, say, new control structures, you may want to have some argument evaluated never.

    So here’s a better version which allows for better control about evaluation. All args with trailing ! (BANG, in Clojure speak) will be evaluated exactly once, and the rest of the args stays under the programmer’s control (note that this version also takes a mandatory docstring):

    (defn bang-symbol?
      "Returns true, if sym is a symbol with name ending in a exclamation
      mark (bang)."
      [sym]
      (and (symbol? sym)
           (= (last (name sym)) \!)))
    
    (defmacro defmacro!
      "Defines a macro name with the given docstring, args, and body.
      All args ending in an exclamation mark (!, bang) will be evaluated only once
      in the expansion, even if they are unquoted at several places in body.  This
      is especially important for args whose evaluation has side-effecs or who are
      expensive to evaluate."
      [name docstring args & body]
      (let [bang-syms (filter bang-symbol? args)
            rep-map (apply hash-map
                           (mapcat (fn [s] [s `(quote ~(gensym))])
                                   bang-syms))]
        `(defmacro ~name
           ~docstring
           ~args
           `(let ~~(vec (mapcat (fn [[s t]] [t s]) rep-map))
              ~(clojure.walk/postwalk-replace ~rep-map ~@body)))))

    Using that, we can now easily implement the numeric if, nif, you can find in On Lisp and Let over Lambda:

    (defmacro! nif
      "Numeric if: evals test! (only once) and executes either pos, zero, or neg
      depending on the result."
      [test! pos zero neg]
      `(cond
        (pos? ~test!)  ~pos
        (zero? ~test!) ~zero
        :else          ~neg))

    When evaluating (nif 1 (println "pos") (println "zero") (println "neg")), now there’s only “pos” printed. With the previous defmacro! version, “pos”, “zero”, and “neg” were printed.

    UPDATE: Stefan Kamphausen noticed that defmacro! doesn’t work as intended if destructuring is done in the argument list. So here’s yet another version that flattens the argument list when collecting the bang-symbols.

    (defmacro defmacro!
      "Defines a macro name with the given docstring, args, and body.
      All args ending in an exclamation mark (!, bang) will be evaluated only once
      in the expansion, even if they are unquoted at several places in body.  This
      is especially important for args whose evaluation has side-effecs or who are
      expensive to evaluate."
      [name docstring args & body]
      (let [bang-syms (filter bang-symbol? (flatten args)) ;; <==
            rep-map (apply hash-map
                           (mapcat (fn [s] [s `(quote ~(gensym))])
                                   bang-syms))]
        `(defmacro ~name
           ~docstring
           ~args
           `(let ~~(vec (mapcat (fn [[s t]] [t s]) rep-map))
              ~(clojure.walk/postwalk-replace ~rep-map ~@body)))))

    Using that, you can define a strange nif variant that wants a vector, where the first entry is a vector containing the test, and the second entry is a vector of the pos, zero, neg entries.

    (defmacro! strange-nif
      "Like nif, but with strange destructuring"
      [[[test!] [pos zero neg]]]
      `(cond
        (pos? ~test!)  ~pos
        (zero? ~test!) ~zero
        :else          ~neg))
    
    ;; Trying it...
    user> (strange-nif [[1] [:pos :zero :neg]])
    :pos
    user> (macroexpand '(strange-nif [[1] [:pos :zero :neg]]))
    (let [G__1974 1]
         (cond (pos? G__1974) :pos (zero? G__1974) :zero :else :neg))

    Once-only evaluation for Clojure macros

    Posted: September 23, 2011 in Clojure
    Tags: ,

    When programming macros, it’s often desired to have its arguments evaluated only once. Let’s have a look at a simple example:

    user> (defmacro square [x] `(* ~x ~x))
    #'user/square
    user> (square 5)
    25

    At a first glance, it seems to work. But see what happens here:

    user> (def c (let [a (atom 4)] #(swap! a inc)))
    #'user/c

    This defines a counter function, which will increase it’s count on every call. Now let’s feed that to our macro:

    user> (square (c))
    30

    Oh, shouldn’t that be 25, because we’re increasing our counter to 5? No, because the macroexpansion is

    user> (macroexpand-1 '(square (c)))
    (clojure.core/* (c) (c))

    So our counter is increased twice resulting in (* 5 6). The lesson to be learned is that when writing a macro, one should take care that every argument is evaluated once, i.e., if you feel the need to unquote an argument more than once, you have to let-bind its value to some gensym and use that later on. This is a fixed version of the square macro.

    user> (defmacro square [x] `(let [x# ~x] (* x# x#)))
    #'user/square
    user> (macroexpand-1 '(square (c)))
    (clojure.core/let [x__5139__auto__ (c)]
      (clojure.core/* x__5139__auto__ x__5139__auto__))

    As you can see, now our counter is incremented only once, and its new value is bound to a generated variable which is used in the body.

    But why not do exactly that by default? Here’s a macro that does that:

    (defmacro defmacro!
      "Defines a macro in which all args are evaled only once."
      [name args & body]
      (let [rep-map (apply hash-map
                           (mapcat (fn [s] [s `(quote ~(gensym))])
                                   args))]
        `(defmacro ~name ~args
           `(let ~~(vec (mapcat (fn [[s t]] [t s]) rep-map))
              ~(clojure.walk/postwalk-replace ~rep-map ~@body)))))

    Using this macrowriting macro, we can now safely use our first implementation of square:

    user> (defmacro! square [x]
      `(* ~x ~x))
    #'user/square
    user> (macroexpand-1 '(square (c)))
    (clojure.core/let [G__5491 (c)] (clojure.core/* G__5491 G__5491))
    user> (square (c))
    49

    Great, seems to work.

    UPDATE: This version of defmacro! has one serious design flaw. The completely expanded form will evaluate all arguments exactly once, but often you want to be able to have some argument evaluated never. See this sequel post for an enhanced version.

    I’ve switched to another tiling window manager called awesome and it’s really like its name suggests. It’s more a window manager framework that can be programmed in lua to create a window manager that does exactly what you want it to do.

    Awesome has a lua library called naughty for displaying notifications. Now my idea was that whenever my mouse pointer enters the region of the textbox widget that shows the current date and time in a wibox, a popup should show the agenda for this week and dispose automatically when I move the mouse away.

    Ok, so here’s the code on the emacs side. It assures that the file /tmp/org-agenda.txt always contains a plain-text export of the current org agenda. It’s created once on emacs startup and after each change to any org agenda file it’ll be updated.

    ;; update agenda file after changes to org files
    (defun th-org-mode-init ()
      (add-hook 'after-save-hook 'th-org-update-agenda-file t t))
    
    (add-hook 'org-mode-hook 'th-org-mode-init)
    
    ;; that's the export function
    (defun th-org-update-agenda-file (&optional force)
      (interactive)
      (save-excursion
        (save-window-excursion
          (let ((file "/tmp/org-agenda.txt"))
            (org-agenda-list)
            (org-write-agenda file)))))
    
    ;; do it once at startup
    (th-org-update-agenda-file t)

    And here’s the lua code on the awesome side:

    -- the current agenda popup
    org_agenda_pupup = nil
    
    -- do some highlighting and show the popup
    function show_org_agenda ()
       local fd = io.open("/tmp/org-agenda.txt", "r")
       if not fd then
          return
       end
       local text = fd:read("*a")
       fd:close()
       -- highlight week agenda line
       text = text:gsub("(Week%-agenda[ ]+%(W%d%d?%):)", "<span style="text-decoration: underline;">%1</span>")
       -- highlight dates
       text = text:gsub("(%w+[ ]+%d%d? %w+ %d%d%d%d[^n]*)", "%1")
       -- highlight times
       text = text:gsub("(%d%d?:%d%d)", "%1")
       -- highlight tags
       text = text:gsub("(:[^ ]+:)([ ]*n)", "%1%2")
       -- highlight TODOs
       text = text:gsub("(TODO) ", "<strong>%1</strong> ")
       -- highlight categories
       text = text:gsub("([ ]+%w+:) ", "%1 ")
       org_agenda_pupup = naughty.notify(
          { text     = text,
            timeout  = 999999999,
            width    = 600,
            position = "bottom_right",
            screen   = mouse.screen })
    end
    
    -- dispose the popup
    function dispose_org_agenda ()
       if org_agenda_pupup ~= nil then
          naughty.destroy(org_agenda_pupup)
          org_agenda_pupup = nil
       end
    end
    
    mydatebox = widget({ type = "textbox", align = "right" }) -- shows the date
    mydatebox.mouse_enter = show_org_agenda
    mydatebox.mouse_leave = dispose_org_agenda
    
    -- after that the mydatebox is added to some wibox, of course...

    And that’s how it looks like.

    The Org Agenda in an Awesome/Naughty popup

    The Org Agenda in an Awesome/Naughty popup

    I use Carsten Dominik’s great emacs package org-mode for project planning, appointments and TODOs (org-mode homepage). One cool feature is that it integrates nicely with the remember package. So when an idea comes into my mind I need to remember for later, I hit M-x org-remember RET which presents me a buffer with a custom template, I type my note and hit C-c C-c. The note is filed then and the buffer is gone, so there’s really no interruption.

    One cool thing is that org-remember automatically inserts a link to the “thing” you had open when adding the note. This “thing” could be a info buffer, a mail, a usenet article, an image,…

    I thought it would be nice to use that facility to make TODO-bookmarks like “TODO read that great blog entry!” from inside my browser conkeror. And so I did.

    Here’s the emacs side of the code (put it in your ~/.emacs):

    (setq org-remember-templates 
          '(
            ;; lot of other templates...
            ("TODO"    ?t "* TODO %?
      :PROPERTIES:
      :created: %U
      :link: %a
      :END:
      %i")))
    
    (defun th-org-remember-conkeror (url)
      (interactive "s")
      (org-remember nil ?t)
      (save-excursion
        (insert "\n\n  [[" url "]]"))
      (local-set-key (kbd "C-c C-c")
             (lambda ()
               (interactive)
               (org-ctrl-c-ctrl-c)
               (delete-frame nil t))))

    And that’s the conkeror side (put it in your ~/.conkerorrc):

    function org_remember(url, window) {
        var cmd_str = 'emacsclient -c --eval \'(th-org-remember-conkeror "' + url + '")\'';
        if (window != null) {
        window.minibuffer.message('Issuing ' + cmd_str);
        }
        shell_command_blind(cmd_str);
    }
    
    interactive("org-remember", "Remember the current url with org-remember",
            function (I) {
            org_remember(I.buffer.display_URI_string, I.window);
            });

    This code may require emacs 23, I’m not too sure. What you need in every case is a running emacs server, so that you can connect to it with emacsclient.

    UPDATE: Now I use org-protocol instead of something home-brewn.

    Here’s the updated code for your ~/.conkerorrc. On the emacs side nothing is needed anymore.

    function org_remember(url, title, text, window) {
        var eurl = encodeURIComponent(url);
        var etitle = encodeURIComponent(title);
        var etext = encodeURIComponent(text);
        var cmd_str = "emacsclient -c org-protocol://remember://" + eurl + "/" + etitle + "/" + etext; 
        window.minibuffer.message("Issuing " + cmd_str);
        shell_command_blind(cmd_str);
    }
    
    interactive("org-remember", "Remember the current url with org-remember",
            function (I) {
              org_remember(I.buffer.display_uri_string,
                           I.buffer.document.title,
                           I.buffer.top_frame.getSelection(),
                           I.window);
            });

    I have my emacs running as server and two small wrapper scripts ec and et which connect to it with emacsclient (either creating a new frame or opening a terminal frame).

    Because I want to do all my system administration (editing files in /etc/) with emacs and don’t want to start another emacs instance as root, I use TRAMP to switch to superuser mode automagically if the opened file is read-only.

    Here’s the code (UPDATED: Uses defadvice instead of hooking into find-file-hook, which had the bad effect of find-file-hook running twice.):

    (defun th-rename-tramp-buffer ()
      (when (file-remote-p (buffer-file-name))
        (rename-buffer
         (format "%s:%s"
                 (file-remote-p (buffer-file-name) 'method)
                 (buffer-name)))))
    
    (add-hook 'find-file-hook
              'th-rename-tramp-buffer)
    
    (defadvice find-file (around th-find-file activate)
      "Open FILENAME using tramp's sudo method if it's read-only."
      (if (and (not (file-writable-p (ad-get-arg 0)))
               (y-or-n-p (concat "File "
                                 (ad-get-arg 0)
                                 " is read-only.  Open it as root? ")))
          (th-find-file-sudo (ad-get-arg 0))
        ad-do-it))
    
    (defun th-find-file-sudo (file)
      "Opens FILE with root privileges."
      (interactive "F")
      (set-buffer (find-file (concat "/sudo::" file))))

    Now whenever I type ec /some/file/i/have/no/permissions/to/write (or emacsclient [-c|-t] /some/root/file, emacs asks me to re-open it using TRAMP’s sudo method.