Omitting Git-ignored files in Emacs dired

Adding the following snippet to your .emacs file will cause Emacs’ dired mode to omit all files ignored by Git. This only works if you have dired-omit-mode on, which is ordinarily bound to Meta-o.

(add-hook ‘dired-load-hook #’(lambda nil (load “dired-x” t)))

(eval-after-load “dired-x”
  ‘(progn
     (defvar dired-omit-regexp-orig (symbol-function ‘dired-omit-regexp))

     (defun dired-omit-regexp ()
       (let ((file (expand-file-name “.git”))
             parent-dir)
         (while (and (not (file-exists-p file))
                     (progn
                       (setq parent-dir
                             (file-name-directory
                              (directory-file-name
                               (file-name-directory file))))
                       ;; Give up if we are already at the root dir.
                       (not (string= (file-name-directory file)
                                     parent-dir))))
           ;; Move up to the parent dir and try again.
           (setq file (expand-file-name “.git” parent-dir)))
         ;; If we found a change log in a parent, use that.
         (if (file-exists-p file)
             (let ((regexp (funcall dired-omit-regexp-orig)))
               (assert (stringp regexp))
               (concat
                regexp
                (if (> (length regexp) 0)
                    “\\|” “”)
                “\\(“
                (mapconcat
                 #’(lambda (str)
                     (concat “^”
                             (regexp-quote
                              (substring str 13
                                         (if (= ?/ (aref str (1- (length str))))
                                             (1- (length str))
                                           nil)))
                             “$”))
                 (split-string (shell-command-to-string
                                “git clean -d -x -n”)
                               “\n” t)
                 “\\|”)
                “\\)”))
           (funcall dired-omit-regexp-orig))))))

A note to fellow Emacs coders: I tried writing this as a piece of defadvice, rather than hijacking the definition of dired-omit-regexp, but for some reason it never called this function.

|

A new Ledger mailing list

The Ledger project now has a new mailing list, hosted at Google Groups. This was requested by several users who were not happy with the current web forums being used. Note that you do not have to join the group just to post a question. I’ll be keeping the web forums up for another year or so, but will start discouraging their use.

Also, you can find a few of us on IRC at irc.freenode.net, on the channel #ledger. My own nick is “johnw”. Come say hello!

|

Using Git as a versioned data store in Python

Git has sometimes been described as a versioning file-system which happens to support the underlying notions of version control. And while most people do simply use Git as a version control system, it remains true that it can be used for other tasks as well.

For example, if you ever need to store mutating data in a series of snapshots, Git may be just what you need. It’s fast, efficient, and offers a large array of command-line tools for examining and mutating the resulting data store.

To support this kind of usage — for the upcoming purpose of maintaining issue tracking data in a Git repository — I’ve created a Python class that wraps Git as a basic shelve object.

Read More...
|

Emacs Chess now hosted at GitHub

Emacs Chess is a fully featured chess client written entirely in Emacs Lisp. You can use it to play against other people on freechess.org, or against popular chess engines like gnuchess and crafty. It supports graphical rendering of chess boards within Emacs (in 2D), ASCII displays, and even electronic chess boards, or producing output appropriate braille for readers. Adding a new back-end is trivial. It also comes with a library for inspecting and reasoning about chess positions.

This project is looking for someone who loves Emacs, Lisp and the game of chess, to fork it and take over as maintainer. The FSF has agreed to include Emacs Chess as part of the Emacs distribution, but I’ve held off because of a few remaining issues I want to see resolved before it goes mainstream. It does work quite well, however, and I have friends who use it as their sole client for playing chess online.

Emacs Chess is now being hosted at GitHub, which should make it easier for others to contribute:

http://github.com/jwiegley/emacs-chess

If you’d like to just clone it and try it out, run the following and then see the README:

git clone git://github.com/jwiegley/emacs-chess.git
cd emacs-chess
git submodule init
git submodule update      # grab the 2D pieces and sound sets
make

After it compiles, add the emacs-chess directory to your load-path, load chess.el, and then type M-x chess!

If anyone is interested in taking over as the maintainer, or would like to contribute those last few weeks of work necessary to getting this project delivered with GNU Emacs, please contact me.

|

Ready Lisp version 20080428 now available

There is a new version of Ready Lisp for Mac OS X available. This version is based on SBCL 1.0.16, and requires OS X Leopard 10.5. The most notable change from the previous version is that 64-bit mode and experimental threading are no longer supported, since both have been known to have issues on OS X, while the purpose of Ready Lisp is to smoothly introduce Common Lisp to new users.

What is Ready Lisp? It’s a binding together of several popular Lisp packages for OS X, including: Aquamacs, SBCL and SLIME. Once downloaded, you’ll have a single application bundle which you can double-click — and find yourself in a fully configured Common Lisp REPL. It’s ideal for OS X users who want to try out Lisp with a minimum of hassle. The download is approximately 76 megabytes.

There is a GnuPG signature for this file in the same directory; append .asc to the above filename to download it. To install my public key onto your keyring, use this command:

$ gpg —keyserver pgp.mit.edu —recv 0x824715A0

Once installed, you can verify the download using the following command:

$ gpg —verify ReadyLisp.dmg.asc

For more information, see the Ready Lisp project page.

|

Git from the bottom up

In my pursuit to understand Git, it’s been helpful for me to understand it from the bottom up — rather than look at it only in terms of its high-level commands. And since Git is so beautifully simple when viewed this way, I thought others might be interested to read what I’ve found, and perhaps avoid the pain I went through finding it.

The following article offers what I’ve learned on this journey so far. I hope it can help others to comprehend this wonderful system, and discover some of the joy I’ve experienced in the past few weeks. NOTE: After receiving more than fifty corrections by e-mail from very helpful readers, I’ve updated the PDF to reflect their input. The date at the front should read “Fri, 2 May 2008” if you have the latest version.

Here is a summary from the table of contents:

  • Introduction
  • Repository: Directory content tracking
  • Introducing the blob
  • Blobs are stored in trees
  • How trees are made
  • The beauty of commits
  • A commit by any other name…
  • Branching and the power of rebase
  • Index Cache: Meet the middle man
  • Taking the index cache farther
  • To reset, or not to reset
  • Last links in the chain: Stashing and the reflog
|

Diving into Git

This week I decided to convert my Ledger repository over to Git. Previously I’d been using Subversion for about 4 years, and CVS for 1 year before that. There was a brief flirt with Darcs, and Mercurial, but neither ever attracted me enough to convert the repository officially.

Why did I choose Git? Actually, I’d looked at Git before, maybe a year ago, and decided it was too complex and funky. But some recent articles — and new versions of Git — prompted me to look again. Yes, it still looks complex, but then again, UNIX is complex and I’ve never stopped loving that since I made my first terminal connection. In fact, when you look at Git in terms of the UNIX philosophy, rather than as a single application, it starts making a whole lot more sense. (It was written by a UNIX-ish kernel developer, after all).

Migrating my official repository represented a special challenge, because I decided I wanted my entire history, not just the Subversion parts of it. I mean, I wanted to pull the CVS repo out of the archives and thread it along with the Subversion repo into a nice, coherent history going all the way back to version 0.1.

With other tools — even Mercurial — I would have shied away from such an undertaking. But Git not only made it possible, it was even straightforward and rather fun to do. This article chronicles my adventures at manually pasting together a version control history, and how powerfully Git was able to handle this task — which would have been patently impossible using CVS or Subversion.

Read More...
|

Run the Spotlight indexer at a lower priority

I realized the other day that on OS X, the Spotlight indexing process is started using launchd. This makes it very easy to modify the launchd configuration script to insure that background indexing uses the least amount of CPU and I/O bandwidth possible.

Edit the configuration script by running this command as root:

# open /System/Library/LaunchDaemons/com.apple.metadata.mds.plist

You should find yourself in the Property List Editor application. Now add two keys at the top-level, one named LowPriorityIO, which is a boolean set to true, and another named Nice which should be an integer set to 20.

Now whenever the mds spawns mdworker processes to index recent changes to the file system, it won’t get in your way quite as much as before. (Without this change, mdworker processes run at the same priority as user processes, according to output from the ps axl command).

|

Script of the week: linkdups

It's been a while since I've posted a script; life has been distracting lately. I also wanted to let this current script mature a lot more before sharing it, as it has the potential to be destructive. Use wisely!

It's name is linkdups, and it's a Python program to recursively walk through a directory tree and hard-links any files together whose contents match exactly. That means that if you have two files, each taking up 10 Kb, afterwards they will be linked to the same contents for a total savings of 10 Kb. Read More...
|

Defragmentation and disk images

There has been a small debate among some Mac users about whether defragmenting your disks is necessary for the smooth operation of OS X. I’ve always been in the camp of those who do it regularly, because I’ve seen what my disk ends up looking like after a few weeks of not doing it (and how pretty the graph looks afterwards). It could all be psychological, but I find the progress bar rather hypnotizing, and my wife has been known to find me staring at it for hours on end. Ok, very psychological.

Well, I’ve found one circumstance where defragmentation is definitively helpful: compressing sparse disk images.

I have a habit of creating encrypted disk images for every client I work for. A lot happens in those images, which tend to grow and shrink quite a bit. OS X has a command to squeeze out the unused space, which looks like this:

$ hdiutil compact DiskImage.sparseimage

I just ran this command on one of my work images, and it reported a savings of 786 Mb out of 3 Gb. Just for interest’s sake, I ran iDefrag on the same volume, which eliminated the small amount of fragmentation that had built up, and compacted the files down toward the beginning of the image.

Running hdiutil compact on the same disk image again resulted in a further savings of 518 Mb! Given that the image itself is now 1.4 Gb, that’s about a 30% further reduction.

So, if you’re like me and you use lots of virtual disk images — and you’ve always wondered if defragmentation tools were worth anything at all — here’s one reason to consider it.

|
© 2008 John Wiegley