Org-Mode

March 8th, 2010

Since the last time I blogged about org-mode, I’ve been using it much more extensively. I now use it for basically all of my organization, both at home and for work. I try and reflect on my workflow and how it could be improved regularly; what I describe in this entry is just my current one.

My org-mode agenda files are all in the same level. Each one represents either a project or collection of smaller projects - I like to keep the number of agenda files I have down, so for example smaller programming projects are all in ‘technical.org’. These files are generally trees of TODO items, most of which are either scheduled or depend on another item. These scheduled dates are more of a suggestion; they ensure that I see the item at some point in the near future, but I often do them either before or after they are scheduled.

At this point, I’ll start describing my customizations and how I use them. First, I get the latest version of org-mode; the one that comes with Emacs doesn’t have all the features I use.

;;Checkout the latest version of org mode, if I don't already have it.
(unless (file-exists-p "~/.emacs.d/elisp/org-mode/")
  (let ((default-directory "~/.emacs.d/elisp/"))
    (shell-command "git clone git://repo.or.cz/org-mode.git")
    (shell-command "make -C org-mode/")
    (normal-top-level-add-subdirs-to-load-path)))
(add-to-list 'load-path "~/.emacs.d/elisp/org-mode/lisp/")
(add-to-list 'load-path "~/.emacs.d/elisp/org-mode/contrib/lisp/")
(require 'org-install)

I have a few customizations for my general agenda view. I change the color of upcoming deadlines, as the default had the same color as regular items. I have my agenda start on the current day; no point in seeing previous day’s schedules. Items that have deadlines are displayed 10 days in advance, and I don’t display items that are done in my agenda.

(setq org-upcoming-deadline '(:foreground "blue" :weight bold))
(setq org-agenda-start-on-weekday nil)
(setq org-deadline-warning-days 10)
(setq org-agenda-skip-deadline-if-done t)
(setq org-agenda-skip-scheduled-if-done t)

One feature that I’ve started to use more, but often forget about, is org’s clocking mechanism. It will record how much tieme you spend on tasks. The variables I define here will make the clock persist in case you close emacs, and prompt for splitting the time if you leave while clocked in. The function and hook will prompt for an effort estimate when clocking in to a task if it doesn’t already have one; I plan on using both the clocking and estimating to improve my estimation and scheduling skills.

(org-clock-persistence-insinuate)
(setq org-clock-idle-time 15)
(setq org-clock-out-remove-zero-time-clocks t)
(setq org-clock-persist 'history)
 
(defun my-org-mode-ask-effort ()
  "Ask for an effort estimate when clocking in."
  (unless (org-entry-get (point) "Effort")
    (let ((effort
           (completing-read
            "Effort: "
            (org-entry-get-multivalued-property (point) "Effort"))))
      (unless (equal effort "")
        (org-set-property "Effort" effort)))))
(add-hook 'org-clock-in-prepare-hook 'my-org-mode-ask-effort)

org-remember is used to take quick notes and store them for later. Many people have a fairly customized version; I personally have a very simple one. When I press C-r, a buffer pops up with a TODO entry begun that I can write into. When I close the buffer, this note is saved into a file that I go through on a weekly basis and move tasks to their correct location. This is helped by refiling, which will prompt for a location and send the region or headline you are on to it. The locations I have set up are my agenda files, and their level-1 headings.

(org-remember-insinuate)
(setq org-remember-templates
      `(("Todo" ?t "* TODO %?\n  %i\n " ,(concat org-directory "remember.org") "Tasks")))
(setq org-default-notes-file (concat org-directory "/remember.org"))
(setq org-outline-path-complete-in-steps t)
(setq org-refile-use-outline-path 'file)
(setq org-refile-targets '((org-agenda-files . (:level . 1))))

These are just some general org-mode customizations to make org better. I don’t like org inserting blank lines, and I do like ido. org-insert-heading-respect-content will make new headings appear after the content for the current one, which is usually the behavior I want. Allowing return to follow links makes navigation much easier. org-special-ctrl-a/e will rebind ctrl-a and ctrl-e to make more sense in org mode, going to the beginning and end of the heading instead of the current line. This is actually a bit inaccurate - ctrl-a cycles between beginning of heading and beginning of line, which helps with speed commands. Enabling speed commands will rebind certain one-letter keybindings when the cursor is at the beginning of the row - most notably ‘t’ for org-todo instead of ‘C-c C-t’, a huge increase in efficiency.

Each of my agenda files has a corresponding archive file, where I put completed tasks with org-archive-subtree. Unfortunately, org-archive-subtree doesn’t keep the context of the tree you archive, except in a string; I’ve been meaning to take a look at fixing this, but don’t have the time. If you have a solution, please let me know about it.

(setq org-blank-before-new-entry '((heading . nil) (plain-list-item . nil)))
(setq org-completion-use-ido t)
(setq org-insert-heading-respect-content t)
(setq org-return-follows-link t)
(setq org-special-ctrl-a/e t)
(setq org-use-speed-commands t)
(setq org-speed-commands-user nil)
(setq org-startup-align-all-tables t)
(setq org-treat-S-cursor-todo-selection-as-state-change nil)
(setq org-archive-location (concat org-directory "archive/%s_archive::"))

org-depends is a module that allows you to enforce dependencies of tasks that have the same parent. If you add the following :PROPERTIES: string to a task:

:PROPERTIES:
:TRIGGER:  chain-siblings-scheduled chain-siblings(TODO)
:END:

Once the task is set to DONE, it will automatically schedule the next item in the subtree for the current day and set it to TODO. I would prefer for it to be able to schedule for an offset from the current day, but this in itself is fairly useful.

(when (locate-library "org-depend") (require 'org-depend))
(setq org-enforce-todo-dependencies t)

I also have customized my TODO commands. Instead of the default states of TODO and DONE, I’ve added CANCELED, STALLED, FUTURE, and PENDING, to more accurately represent the state my tasks can be in. I log the time a task is either completed or put into a PENDING, CANCELED, or STALLED state, and setting an item to either CANCELED, STALLED, or PENDING will prompt for a reason and log this reason. Each command has a ’short’ keybinding that can be used to quickly changed the state.

(setq org-log-done 'time)
(setq org-todo-keywords
      '((sequence "TODO(t)" "|" "DONE(d!)")
        (sequence "|" "CANCELED(c@/!)")
        (sequence "|" "STALLED(s@/!)")
        (sequence "FUTURE(f)" "|")
        (sequence "PENDING(p@/!)" "|" )))
(setq org-todo-keyword-faces
      '(("CANCELED"  . (:foreground "blue" :weight bold))
        ("STALLED"  . (:foreground "RED" :weight bold))
        ("FUTURE" . (:foreground "dark green" :weight bold))
        ("PENDING"  . (:foreground "orange" :weight bold))))

I use PENDING to represent tasks that need some input from others, and so I need to periodically review these tasks to see if I have said input. To do this, I created an agenda command which will display every pending task in my agenda files:

(setq org-agenda-custom-commands
      (quote (("p" "Pending Tasks" todo "PENDING" ((org-agenda-todo-ignore-scheduled nil)
                                                   (org-agenda-todo-ignore-deadlines nil)
                                                   (org-agenda-todo-ignore-with-date nil))))))

The following function just adds a timestamp for the current time, making logging easier

(defun bh/insert-inactive-timestamp ()
  "Insert a timestamp for the current time at point."
  (interactive)
  (save-excursion
    (insert "\n")
    (org-cycle)
    (org-insert-time-stamp nil t t nil nil nil)))

I rebind a few keys for org-mode to make it more efficient. I don’t use the arrow keys to navigate, so I rebind them to promote and demote subtrees, and have a few other convenient keybindings.

(define-key org-mode-map (kbd "<left>") 'org-promote-subtree)
(define-key org-mode-map (kbd "C-t") 'org-todo)
(define-key org-mode-map (kbd "<right>") 'org-demote-subtree)
(global-set-key (kbd "C-c i") 'bh/insert-inactive-timestamp)
(global-set-key "\C-ca" 'org-agenda)
(global-set-key "\C-cl" 'org-store-link)
(define-key global-map "\C-cr" 'org-remember)

Another org feature I use is habit tracking. Add the following :PROPERTIES: drawer to your tree for a repeating task, and in your agenda you will be shown a neat graph of how well you’ve been doing at keeping to the habit. I use it more than I should, since it also hides the item from view until it is scheduled, which I haven’t found a way to do on a per-item basis yet.

   :PROPERTIES:
   :LAST_REPEAT: [2010-02-15 Mon 07:35]
   :STYLE:    habit
   :END:
(setq org-habit-graph-column 60)
(add-to-list 'org-modules 'org-habit)

Finally, activate org and ‘C-a a’ will take you to your agenda!

(require 'org)

Emacs Package Management

February 22nd, 2010

One of the thing’s I’ve been thinking about recently is package management for my emacs customizations. I have a large number of emacs packages that are at least intrinsically external to my own repository - 42, I believe - and I have to install Emacs on a new system roughly once every four months. When I recently switched from SVN to HG for hosting my repository, this prompted me to think a lot about how to organize it, and this problem in particular.

Unfortunately, this seems to be a nontrivial problem. The easiest solution would be for all of these packages to be added to emacs core; this is rather unfortunately not going to happen. The three main possible solutions I thought of are the following:

The first option, which I did for a long time, is to just check each package into your emacs customizations repository. This overall is a decent solution; it’s probably what most people use. It has the advantage of making your repository stand-alone - nothing but it has to be checked out. However, it makes it difficult to detect updates to packages you use and to apply those updates. This tends to end up with you having fewer features and more bugs than you otherwise could have, which lead me in search of other solutions.

Option #2 - Hand-rolled package management

The solution I currently have in-place is a set of utilities that will download the latest version of a library if it exists. While this does mostly solve the problem of difficult updates(at the time of a fresh Emacs install, I am fully up-to-date, and can juts use native VC to update further), it introduces a new set of problems. For one, it makes the repository not be packaged together, making it harder to distribute to others. It also requires installing a lot of different version control systems - I think the various modes I need to check out use six different ones. Finally, there are cases when I don’t want the latest version, or need to apply a patch, because it is broken.

The only one of these problems I currently solve is the last one. My repository contains a directory with modes that can’t be managed by the utilities I described above. This can be because they are hard to download pragmatically or the latest version is broken - clojure-mode is an example of the latter, member-functions.el the former. This is essentially Option #1 on a slightly smaller scale.

Option #3 - ELPA

What I’d really like is a finished ELPA, included in a base Emacs distribution. ELPA is the Emacs Lisp Package Archive, a package manager for Emacs, slated for addition to Emacs 24. I’ve tried it, and while it’s a good idea, right now it is not good enough to use - hopefully, this can be fixed, because it seems like this would be a solution to most of my issues. However, right now, there’s the following reasons I don’t currently use it:

  1. Ease of upload - This only seems like it should be an issue for package developers, and thus not affect my use of it in my repository, but I think it’s one reason for later items. Essentially, if it’s hard to upload a new package to ELPA, more package maintainers will just not bother doing so. Right now, the process seems to be to email the package to the ELPA maintainer, who will put it in or update the package, which is clearly not scalable or particularly easy. Ideally, I would be able to register some version control location with ELPA, and have it pick up any changes I make to it.
  2. Requirements for packages - The packages included must meet some irritating requirements, with comments in specific formats and other issues. These aren’t too bad - ELPA needs some way of finding dependencies and requirements - but it also doesn’t support multi-file packages very well. This is a fairly big issue, since without this it can only be used for smaller modes.
  3. Availability of packages - Right now, fewer than 10% of the packages I use are in ELPA. This is a combination of reasons, such as some packages being old, some not meeting the requirements described below, or the developer is just lazy. Whatever the reason, I’d like it to contain more of the packages I personally use, although I’d be willing to help convince others to put their packages on ELPA if my other problems were solved.
  4. Old package versions - Some of the package versions on ELPA, such as eproject, are quite old. I suspect this relates to issue #1 above.
  5. No update/revert mechanism - Once you’ve installed a package, there’s no way to update it if ELPA receives an update. There also isn’t a way to revert to a previous deployment.

For now, I don’t really have a good solution. Hopefully, ELPA will improve - I may work on that some myself - but in the meantime, if you have your own system for managing external packages, please let me know in the comments.

Emacs Minor-Modes: mic-paren, pager, dired-isearch, whichfunc, winpoint, and highlight-parentheses

February 15th, 2010

I haven’t written about recent additions I’ve made to my emacs configuration, so I’ll go through a number of them here. These are all passive minor modes; once you set them up, they work automatically. You don’t have to remember any keybindings to use them, or activate them in a buffer; they just work.

Mic-Paren

mic-paren is a package that enhances emacs’ parenthesis highlighting. It recognizes escaped parentheses, as well as matching parentheses both in front and back of point. It also has other options, such as highlighting other delimiters and the containing s-expressions. You’ll have to download this from http://www.emacswiki.org/emacs/download/mic-paren.el and then activate it with:

(require 'mic-paren)
(paren-activate)

Pager

Pager is a library for fixing emac’s paging. Without it, doing a page down followed by a page up has no guarantee of moving point back to it’s original location. Download pager from wget http://user.it.uu.se/~mic/pager.el and activate it with:

(require                  'pager)
  (global-set-key "\C-v"	'pager-page-down)
  (global-set-key [next]	'pager-page-down)
  (global-set-key "\ev"     'pager-page-up)
  (global-set-key [prior]	'pager-page-up)
  (global-set-key '[M-up]	'pager-row-up)
  (global-set-key '[M-kp-8] 'pager-row-up)
  (global-set-key '[M-down] 'pager-row-down)
  (global-set-key '[M-kp-2] 'pager-row-down)

which-func

Which-func is a minor-mode that will add the function point is inside to the mode-line. This is mainly useful if you are looking at large functions, but it could also be nice if you use vertical splits. Which-func mode is built into emacs, so you have to go through very little work to enable it.

(setq which-func-modes t)
(which-func-mode 1)

winpoint

Winpoint is a package that enhances multiple-window viewing of a file. Normally, if you have two windows open to the same buffer at different locations, and temporarily use one window to view something else, when you return to the original buffer it will have point be located where the other window’s point is. This is usually not the behavior I want, and winpoint fixes this so that point is kept on a per-window basis. To get this, you must first put winpoint.el, available from wget http://www.emacswiki.org/emacs/download/winpoint.el, in your .emacs.d directory, and then add the following to your .emacs file:

(require 'winpoint)
(winpoint-mode t)

dired-isearch

This package will replace the regular isearch commands with commands that will only match filenames when in dired-mode. This is normally what I want to do, so this package just makes it slightly easier. It is available from http://emacswiki.wikiwikiweb.de/cgi-bin/wiki/download/dired-isearch.el, with the following required in your .emacs file:

(require 'dired-isearch)
  (define-key dired-mode-map (kbd "C-s") 'dired-isearch-forward)
  (define-key dired-mode-map (kbd "C-r") 'dired-isearch-backward)
  (define-key dired-mode-map (kbd "ESC C-s") 'dired-isearch-forward-regexp)
  (define-key dired-mode-map (kbd "ESC C-r") 'dired-isearch-backward-regexp)

highlight-parentheses

The last package I’ll cover today is for highlighting parentheses around the current point, not just ones matching the current point. This is useful for telling you when the containing expression starts or ends, for example. This requires a bit more customizations than the other ones, for two reasons:

  • It does not define a global mode, so you have to do this yourself.
  • The default colors I find are pretty terrible.

Given that, my customizations are as follows:

(require 'highlight-parentheses)
(defun turn-on-highlight-parentheses-mode ()
(highlight-parentheses-mode t))
(define-global-minor-mode global-highlight-parentheses-mode
  highlight-parentheses-mode
  turn-on-highlight-parentheses-mode)
(global-highlight-parentheses-mode)
(setq hl-paren-background-colors '("green"))

The “green” is just what I am using now; change that to whatever color you wish.

Emacs, Overlays, and Point-Motion

February 9th, 2010

One feature that’s missing from Emacs is the ability to run a hook when the point moves into an overlay. Now, there are several use cases for this; the most obvious one being displaying messages when you are looking at some specific part of the code. For example, flymake displaying the specific syntax error when the point is in the highlighted part. This could also be used for completions.

Now, there are ways to do similar things in emacs. You can assign functions to the ‘point-entered and ‘point-left text properties, and they are run when the point enters the function. However, in some cases it would be easier to use an overlay; for example, js2-mode uses an overlay for the error checking, but must set this property on the actual text. This is clearly suboptimal; b oth setting up and cleaning up overlays requires remembering about this text property. Help-at-pt.el can also help, but it can only display messages, and only display arbitrary actions.

This isn’t a problem that can be solved on the emacs-lisp side of things; a behavior like this needs to be added at the C level of emacs. I decided to delve in and investigate how you’d accomplish this; I ended up finding the correct places to add this functionality - a function called command_loop_1. There was additional helper code in other places, but the code that actually called the functions was here.

However, after discussing it on the emacs development mailing list, the interface for defining a hook got uglier to make it more general. Currently, the hook takes five arguments; the last point position, the current point position, the overlay/text property that contains the hook, the previous buffer, and the previous window. This is to support being able to support executing when the point leaves because it went to a different window, etc. The hook is called on every point motion; entering or leaving the overlay/text property, including by way of buffer or window switching, and motion inside the property.

Combined with the ugliness, there was no real use case I could think of other than the display, where there are the above-mentioned workarounds. The patch is currently languishing on the bug tracker; if you want it, please comment on the bug report at http://emacsbugs.donarmstrong.com/cgi-bin/bugreport.cgi?bug=5397. My patch is also located at point-motion.patch, if you wish to apply it and try it on your emacs system. To use it once you’ve patched your emacs, just add functions to the ‘point-motion text or overlay property.

Emacs Bugfixes: Dirtrack Errors, Python Highlighting, and VC-Revert Window Clobbering

February 1st, 2010

I’ve recently gotten involved in the emacs development community. I’m not a commiter or anything, but I’m working on improving Java support for cc-mode, have a lrage patch(that is unfortunately currently in limbo), and have been submitting bugfixes for problems I’ve been running into. This post describes the fixes for a few of these bugs that you can add to your emacs configuration and fix right now.

The first patch is to dirtrack. If you have a somewhat incorrectly-specified regexp for your shell, dirtrack will sometimes eat output from your shell buffer and error out. Specifically, this happens when a non-existent directory is matched. This is clearly not what you want; instead, in most cases I want dirtrack to just ignore this, not switch the buffer, and proceed as normal. The following function does this, although it still messages you about an incorrect match:

(defun dirtrack (input)
  "Determine the current directory by scanning the process output for a prompt.
The prompt to look for is the first item in `dirtrack-list'.
 
You can toggle directory tracking by using the function `dirtrack-mode'.
 
If directory tracking does not seem to be working, you can use the
function `dirtrack-debug-mode' to turn on debugging output."
  (unless (or (null dirtrack-mode)
              (eq (point) (point-min)))     ; no output?
    (let (prompt-path
          (current-dir default-directory)
          (dirtrack-regexp    (nth 0 dirtrack-list))
          (match-num	      (nth 1 dirtrack-list))
          ;; Currently unimplemented, it seems.  --Stef
          (multi-line	      (nth 2 dirtrack-list)))
      (save-excursion
        ;; No match
        (if (not (string-match dirtrack-regexp input))
            (dirtrack-debug-message
             (format "Input `%s' failed to match `dirtrack-list'" input))
          (setq prompt-path (match-string match-num input))
          ;; Empty string
          (if (not (> (length prompt-path) 0))
              (dirtrack-debug-message "Match is empty string")
            ;; Transform prompts into canonical forms
            (setq prompt-path (funcall dirtrack-directory-function
                                       prompt-path)
                  current-dir (funcall dirtrack-canonicalize-function
                                       current-dir))
            (dirtrack-debug-message
             (format "Prompt is %s\nCurrent directory is %s"
                     prompt-path current-dir))
            ;; Compare them
            (if (or (string= current-dir prompt-path)
                    (string= current-dir (abbreviate-file-name prompt-path)))
                (dirtrack-debug-message (format "Not changing directory"))
              ;; It's possible that Emacs will think the directory
              ;; won't exist (eg, rlogin buffers)
              (if (file-accessible-directory-p prompt-path)
                  ;; Change directory
                  (and (shell-process-cd prompt-path)
                       (run-hooks 'dirtrack-directory-change-hook)
                       (dirtrack-debug-message
                        (format "Changing directory to %s" prompt-path)))
                (progn (message "Directory %s does not exist" prompt-path) input)))
            )))))
  input)

Another small patch is to python.el’s syntax highlighting. In the current form, def and class are only highlighted as keywords when the function/class name is started. This is clearly wrong, and led to me spending a few minutes looking up python method declaration syntax, as it looked like ‘def’ wasn’t a keyword. To fix this, put this in your .emacs file:

 
    (,(rx symbol-start "None" symbol-end)	; see � Keywords in 2.5 manual
     . font-lock-constant-face)
    ;; Definitions
    (,(rx symbol-start (group "class") (? (1+ space) (group (1+ (or word ?_)))))
     (1 font-lock-keyword-face) (2 font-lock-type-face))
    (,(rx symbol-start (group "def") (? (1+ space) (group (1+ (or word ?_)))))
     (1 font-lock-keyword-face) (2 font-lock-function-name-face))
    ;; Top-level assignments are worth highlighting.
    (,(rx line-start (group (1+ (or word ?_))) (0+ space) "=")
     (1 font-lock-variable-name-face))
    ;; decorators
    (,(rx line-start (* (any " \t")) (group "@" (1+ (or word ?_ ?.))))
     (1 font-lock-type-face))
    ;; Built-ins.  (The next three blocks are from
    ;; `__builtin__.__dict__.keys()' in Python 2.5.1.  Now modified
    ;; for Python 2/3 compatibility.)  These patterns are debateable,
    ;; but they at least help to spot possible shadowing of builtins.
    (,(rx symbol-start (or
                        ;; exceptions
                        "ArithmeticError" "AssertionError" "AttributeError"
                        "BaseException" "DeprecationWarning" "EOFError"
                        "EnvironmentError" "Exception" "FloatingPointError"
                        "FutureWarning" "GeneratorExit" "IOError" "ImportError"
                        "ImportWarning" "IndentationError" "IndexError" "KeyError"
                        "KeyboardInterrupt" "LookupError" "MemoryError" "NameError"
                        "NotImplemented" "NotImplementedError" "OSError"
                        "OverflowError" "PendingDeprecationWarning" "ReferenceError"
                        "RuntimeError" "RuntimeWarning" "StandardError"
                        "StopIteration" "SyntaxError" "SyntaxWarning" "SystemError"
                        "SystemExit" "TabError" "TypeError" "UnboundLocalError"
                        "UnicodeDecodeError" "UnicodeEncodeError" "UnicodeError"
                        "UnicodeTranslateError" "UnicodeWarning" "UserWarning"
                        "ValueError" "Warning" "ZeroDivisionError") symbol-end)
     . font-lock-type-face)
    (,(rx (or line-start (not (any ". \t"))) (* (any " \t")) symbol-start
          (group (or
                  ;; callable built-ins, fontified when not appearing as
                  ;; object attributes
                  "abs" "all" "any" "bool"
                  "chr" "classmethod" "cmp" "compile" "complex"
                  "copyright" "credits" "delattr" "dict" "dir" "divmod"
                  "enumerate" "eval" "exit" "filter" "float"
                  "frozenset" "getattr" "globals" "hasattr" "hash" "help"
                  "hex" "id" "input" "int" "isinstance" "issubclass"
                  "iter" "len" "license" "list" "locals" "map" "max"
                  "min" "object" "oct" "open" "ord" "pow" "property" "quit"
                  "range" "repr" "reversed"
                  "round" "set" "setattr" "slice" "sorted" "staticmethod"
                  "str" "sum" "super" "tuple" "type" "vars"
                  "xrange" "zip")) symbol-end)
     (1 font-lock-builtin-face))
    (,(rx symbol-start (or
                        ;; other built-ins
                        "True" "False" "Ellipsis"
                        "_" "__debug__" "__doc__" "__import__" "__name__") symbol-end)
     . font-lock-builtin-face)))

The last small patch is a fix for vc-revert-file. Right now, if you have a split window and call vc-revert-file, your other window will be closed in the process of reverting the file. This is clearly wrong; the following function replaces vc-revert-file to leave your window configuration alone after reverting the file.

(defun vc-revert () "This asks for confirmation if the buffer contents are not identical to the working revision (except for keyword expansion)." (interactive) (save-window-excursion (let* ((vc-fileset (vc-deduce-fileset)) (files (cadr vc-fileset))) ;; If any of the files is visited by the current buffer, make ;; sure buffer is saved. If the user says `no', abort since ;; we cannot show the changes and ask for confirmation to ;; discard them. (when (or (not files) (memq (buffer-file-name) files)) (vc-buffer-sync nil)) (dolist (file files) (let ((buf (get-file-buffer file))) (when (and buf (buffer-modified-p buf)) (error "Please kill or save all modified buffers before reverting"))) (when (vc-up-to-date-p file) (unless (yes-or-no-p (format "%s seems up-to-date. Revert anyway? " file)) (error "Revert canceled")))) (when (vc-diff-internal vc-allow-async-revert vc-fileset nil nil) (unless (yes-or-no-p (format "Discard changes in %s? " (let ((str (vc-delistify files)) (nfiles (length files))) (if (< (length str) 50) str (format "%d file%s" nfiles (if (= nfiles 1) "" "s")))))) (error "Revert canceled")) (delete-windows-on "*vc-diff*") (kill-buffer "*vc-diff*")) (dolist (file files) (message "Reverting %s..." (vc-delistify files)) (vc-revert-file file) (message "Reverting %s...done" (vc-delistify files))))))

C-Eldoc Speedups

January 25th, 2010

I’ve been using c-eldoc-mode, the C plugin for eldoc, on and off for some time now. On one hand, the functionality of eldoc is amazing; it is very nice to have function signatures displayed in the echo area when you are in the argument list. When making function calls, you can easily ensure that you are putting arguments in the right order; when reading code, you can tell what the arguments correspond to. However, c-eldoc.el was quite slow on larger codebases such as the emacs source code; each movement command could halt processing for up to a second, which is completely unacceptable.

I decided to see what I could do to speed it up. On reading the source code, I found the main problem; for each lookup, the C preprocessor was called on the file, and grep was called on the results. While the ability to use grep, speeding up regex lookups, was the original point of doing this, in a a large project running the C preprocessor so much would completely kill performance. The easiest way to fix this was just to cache the C preprocessor output for some amount of time; in my case, I decided regenerating the buffer every 120 seconds was good enough. After implementing this, performance was greatly enhanced, and I haven’t had any performance problems so far; if you still are, please let me know, preferably with some details of how large the preprocessor output is.

Mostly, the improvements of c-eldoc involved caching the results of running the c preprocessor, instead of running it on each symbol change. For this, I wanted a cached hash table; one where the key-value pairs would expire after some amount of time. Since Emacs does not have one of these built in, and it is a general enough concept that I may need it outside of c-eldoc, I wrote the cache in it’s own library. c-eldoc still contains the cache code, as I didn’t want to annoy users of it, but the cache is also available standalone.

cache.el, which you can download here, currently provides only three functions; cache-make-cache, cache-gethash, and cache-puthash. Three arguments are provided to cache-make-cache, as well as the key arguments that are also given to make-hash-table; an initialization function, a test function, and a cleanup function. The initialization function is called with no arguments when a value is first put into the cache; the value it returns is stored along with the value put into the cache. The test function is called when a value is retrieved; It is passed the previously computed value of the initialization function, and returns t if the value has expired. If so, the key-value pair is removed from the hash table, and the cleanup function is called with the value of the key-value pair.

The cache structure is designed to emulate the hash tables of emacs as much as possible: there is no difference in interface or semantics of return value between cache-gethash and gethash, or cache-puthash and puthash. Additionally, all key arguments to make-hash-table can also be passed to cache-make-cache, and are used in the hash table backing the cache.

The cache data structure is just a list of a hash table and the three functions passed to cache-make-cache; this allows all the normal hash functions to be called on the car of the result returned by cache-make-cache. I believe that this will suffice without much irritation; however, if the lack of some utility does make the cache more difficult to use, please tell me and I will implement them.

C/C++ Dependency Graphs

January 11th, 2010

While working on my raytracer, I became curious as to what the dependency graph of my code looked like. To accomplish this, I wrote a Python script that will scan a given directory and generate the dependency graph as a PDF file. This graph can either help you find unnecessary dependencies, locate circular dependencies, or just satisfy your curiosity.




This script requires both Python 2.6 and dot. If you are running Ubuntu, you can install dot with:

sudo apt-get install graphviz

Running the script with python is done as follows:

python cppdepends.py dir outfile

Where dir contains the source tree you wish to generate a graph for, and outfile is the pdf file you wish to output to.

This program is located at http://github.com/nflath.cppdepends. If you have any suggestions or improvements, or even if you just used it, please let me know.

Save-Visited-Files v1.2

January 4th, 2010

A while ago, I released save-visited-files-mode, a mode I wrote to keep files open between Emacs sessions. A few people including me have been using it since then; I’ve written about it before here and here. A few weeks ago, Jonathan Kotta emailed me a patch that fixed a few minor issues, as well as cleaned up the code. After applying the patch, I’m now releasing version 1.2. The changes from version 1.1 are as follows:

  • Changed the default location of the persistence file so a new directory doesn’t have to be created.
  • Makes sure that save-visited-files-location is writable; if not, displays an error.
  • Doesn’t print a message every time it saves the file list.
  • Miscellaneous code cleanup.

I’ve also moved save-visited-files-mode.el to a github repository, located at http://github.com/nflath/save-visited-files.This is a much better solution than keeping a copy just in my emacs customization subversion, since I am distributing this as a stand-alone project. I’ll continue posting updates here, as well, but the source will be committed to that repository.

CUDA setup

December 24th, 2009

I’ve started playing around with CUDA, attempting to make a ray-traced pacman clone. Instructions for how to set up the CUDA SDK on Ubuntu are located at http://lifeofaprogrammergeek.blogspot.com/2008/05/cuda-development-in-ubuntu.html; There were a few others instructions that I tried that didn’t end up working. As a note to all of you on Ubuntu 9.10: CUDA does not work with the version of GCC that comes with Ubuntu 9.10. To be able to do CUDA development, you need to downgrade your GCC version to 4.3.

Once the SDK is set up, you can start coding for CUDA. The most useful documents for helping me do this so far have been the CUDA Programming Guide, NVidia’s official guide and reference manual to CUDA, and Dr. Dobb’s CUDA: Supercomputing from the Masses. These have been enough to get me started; currently, my Pacman clone is having some memory issues that causes my program to work in device emulation mode, but I’ve gotten their simpler examples working and understand the basics.

For editing CUDA files, I use cuda-mode. This is an extension to c-mode that provides syntax highlighting for the new constructs, such as __device__ and __global__. It doesn’t do much else, but CUDA shares enough syntax(virtually all of it) with C so that cc-mode is sufficient for editing it. Once you’ve added cuda-mode.el to your load-path, all you have to do to enable it is add the following to your initialization file:

(require 'cuda-mode)

Languages Matter

December 21st, 2009

Languages Matter
http://www.youtube.com/watch?v=ix2DeCzuckc

The world is driven by computers, but most people don’t love them -
they consider them mere tools. The people who love computers,
programmers, are the ones who change the world. Languages matter,
since all software is written in some language, and computers don’t
work without software.

Similarly to the issue with computers, most programmers don’t love
languages. However, languages are important to programmers - they help programmers think, five inspiration, and affect productivity. Different languages will enlighten programmers in different ways - BASIC did not teach me recursion.

In summary, you should be happy using a language.