Archive for the ‘OS X’ Category

VoodooPad and TextMate

Monday, February 16th, 2009

VoodooPad’s new HTML-savvy application-specific URLs are a great way to retrace your steps in TextMate.

I keep my worklog in VoodooPad. I do most of my code editing in TextMate. When I’m trying to understand a new chunk of code, I often need to jump around through the code base.

It’s hard to keep track of where I’ve been, so I can back out of a code path once I understand what it does. Until now I’ve just jotted down pathnames and line numbers in my worklog, so I could manually retrace my steps.

Puzzle Pieces

  • VoodooPad URLs. They let you inject HTML content — including hyperlinks — into an open VoodooPad document.
  • TextMate URLs of the form txmt://open?url=file://pathname&line=lineNum;column=colNum. Open one of these URLs and TextMate will open a window showing the specified line (and column, if specified) of the specified file.
  • Textmate commands and key equivalents.
    TextMate lets you define custom commands and trigger them with keyboard shortcuts that you specify.

Put these all together and what do you get?

Scenario

  • Select some code of interest in TextMate
  • Type your keyboard shortcut
  • A hyperlink pointing to the selected code is inserted into your VoodooPad document

Later, when you want to get back to that chunk of code, just click on the hyperlink in VoodooPad. TextMate will open the document and jump to the line of code referenced by the hyperlink.

Granted, you’re probably going to edit that code someday; and then your bookmarks will break. But this is a handy way to leave a trail of breadcrumbs while you’re trying to decipher a new body of code.

Code

Here’s a Python script which implements this “Bookmark in VoodooPad” capability in TextMate. You can use it by opening TextMate’s Bundle Editor (Bundles -> Bundle Editor -> Show Bundle Editor), creating a New Command using the tool menu at the bottom left of the Bundle Editor window, and pasting it into the resulting Command(s) text area:

#!/usr/bin/env python2.6
import os, datetime, urllib, subprocess

escape = urllib.quote

# What Textmate location are we bookmarking?
path = os.environ["TM_FILEPATH"]
lineNum = os.environ["TM_LINE_NUMBER"]
_tmURLTemplate = "txmt://open?url=file://{path}&line={lineNum}"
tmURL = _tmURLTemplate.format(path=path, lineNum=lineNum)

# Which VoodooPad worklog page should we add it to?
vpPageName = escape(datetime.date.today().strftime("%Y-%m-%d"))

# What text should Voodoopad show for the link?
currLine = os.environ.get("TM_SELECTED_TEXT", os.environ["TM_CURRENT_LINE"])

# How should the HTML be formatted?
_vpHTMLTemplate = '<a style="font:12px helvetica" href="{tmURL}">{currLine}</a>'
vpMarkup = _vpHTMLTemplate.format(tmURL=tmURL, currLine=currLine)

# What URL do we open to inject the HTML into VoodooPad?
_vpURLTemplate = "voodoopad:html={vpMarkup}&page={vpPageName}"
vpURL = _vpURLTemplate.format(vpMarkup=escape(vpMarkup), vpPageName=escape(vpPageName))

subprocess.check_call(["open", vpURL])

Specify a key equivalent such as ⌘-T (Command-T) and you’re off to the races.

[Like many posts to this blog, this entry is also posted at http://bottledtext.blogspot.com.]

VoodooPad bookmarklets now support HTML

Monday, February 16th, 2009

VoodooPad bookmarklets are very useful. But they let you paste only plaintext from your web browser into your document — until now.

VoodooPad Application URLs

VoodooPad understands application-specific URLs of the form voodoopad:description=encoded_text&page=name_of_VoodooPad_document_page. When you open one of these URLs, VoodooPad inserts the encoded text into the indicated page of the current VP document.

You can open voodoopad: URLs from other applications, such as a web browser. That’s what’s so cool about VP bookmarklets — they let you quickly select some text in your web browser and paste it into a VP document, along with other information such as the URL where the text originated.

The only problem is, the description parameter can contain only plain text. So if you’ve selected part of a web page that contains hyperlinks, those hyperlinks won’t come along for the ride.

New Feature

Gus Mueller, VoodooPad’s creator, recently released a new build. It adds a new html parameter to VoodooPad URLs. Now you can select part of a web page and transfer it as HTML into your VoodooPad document.

Gus summarized the new feature thus:

The format of the bookmarklet is like so:
voodoopad:page=junk&html=<b>hello</b>%20world!

Here’s expanded code for a JavaScript bookmarklet which takes advantage of the new parameter. It works in both Safari and Firefox 3.0.x:

javascript: function pad(v) {
    var res=String(v);while(res.length<2) {
        res='0'+res;
    }
    return res;
};
var d=new Date();
var page=(String(d.getFullYear())+'-'+
          pad(d.getMonth()+1)+'-'+ pad(d.getDate()));
function selHTML() {
    var wr=document.createElement('div');
    var c=window.getSelection().getRangeAt(0).cloneContents();
    wr.appendChild(c);
    return wr.innerHTML;
};
location.href='voodoopad:html='+encodeURIComponent('<div style="font:12px helvetica">'+location.href+'<br/>"""<br/>'+selHTML()+'<br/>"""</div><br/>')+'&page='+page;

Worth noting: in this snippet the html content is wrapped up in a div which has an explicit font specification. The bookmarklet is transferring a chunk of HTML, but that chunk doesn’t include any of the CSS from the original web page. So if you don’t specify a style for the wrapper div, VoodooPad will use its own default style for the current VP page. (I think that’s something like Times Roman 10px.)

Django snippets: DebugFooter middleware with textmate links

Tuesday, January 20th, 2009

Django snippets: DebugFooter middleware with textmate links:

“This version adds TextMate links : if you are working on your local machine and using TextMate you can click on the template paths and they will be opened in TextMate. This speeds up development time considerably!

also, this works with django 1.0″

Very useful.

Removing old man pages from OS X Leopard

Saturday, November 1st, 2008

Back in January I posted about Leopard, ‘ls -l’ and extended attributes. The gist was that my man pages were out of date, so they didn’t explain what the @ character represented, in ‘ls -l’ output.

Some threads on the Apple discussion boards have investigated why the man pages don’t get updated. The conclusion is that Leopard installs a lot of gzip-compressed man pages without deleting the corresponding uncompressed man pages. (It may be that this is true only for upgrade installs.) A recommended workaround was to scan through the man page directories with a shell command, re-locating all uncompressed man pages which had corresponding compressed man pages.

I decided to be cowardly in doing this. Here’s a Python script which moves each uncompressed man page only if it is older than its corresponding gzipped man page.

The script must be run with superuser privileges, e.g.

$ sudo python mv_old_man_pages.py

It processes all of the man pages under /usr/share/man, moving old, uncompressed man page files to ~/tmp/old_man_pages.

I would post this to the Apple discussion forums, but it’s really overkill. The short shell scripts already posted should work fine, if you ignore the harmless error messages and process each man/man* directory manually.

#!/usr/bin/env python
# encoding: utf-8
"Remove obsolete uncompressed man pages on an OS X Leopard system."

import sys, os, logging

def candidateOldManPages():
    os.chdir("/usr/share/man")
    for dirpath, dirnames, filenames in os.walk("."):
        for f in filenames:
            if f.endswith(".gz"):
                fOld = f[:-3]
                if fOld in filenames:
                    yield os.path.join(dirpath, f), os.path.join(dirpath, fOld)

def findOldManPages():
    for p, pOld in candidateOldManPages():
        s = os.stat(p)
        try:
            sOld = os.stat(pOld)
        except os.error, info:
            # Some man pages may be broken symbolic links
            logging.warn("Can't stat (%s, %s): %s" % (p, pOld, info))
            if os.path.islink(pOld):
                yield pOld
        else:
            if s.st_mtime > sOld.st_mtime:
                yield pOld
                
def mvOldManPages():
    topDestDir = os.path.expanduser("~/tmp/old_man_pages")
    for relpath in findOldManPages():
        dirname = os.path.dirname(relpath)
        filename = os.path.basename(relpath)
        
        destDir = os.path.join(topDestDir, dirname)
        if not os.path.exists(destDir):
            os.makedirs(destDir)
        logging.debug("mv %s %s" % (relpath, os.path.join(destDir, filename)))
        os.rename(relpath, os.path.join(destDir, filename))

def main():
    """Mainline for standalone execution"""
    logging.basicConfig(level=logging.DEBUG,
                        format="%(levelname)s: %(message)s")
    mvOldManPages()

if __name__ == "__main__":
    main()

Compiling subversion 1.5.1 on OS X 10.5.4

Sunday, August 3rd, 2008

I’ve just tried to compile the subversion 1.5.1 client from its two source tarballs (subversion-1.5.1-tar.bz2 and subversion-deps-1.5.1-tar.bz2). I took care to first hide the /usr/local libraries from my existing subversion installation. Even so, the compilation failed, complaining

/usr/lib/libexpat.a: No such file or directory

The workaround was to temporarily move the system’s /usr/lib/libexpat* dynamic libraries, and then to rebuild.

Here’s the build script which worked for me:

#!/bin/sh
set -e
VERSION=1.5.1
rm -rf subversion-${VERSION}
tar xjf subversion-${VERSION}.tar.bz2
tar xjf subversion-deps-${VERSION}.tar.bz2
cd subversion-${VERSION}
./autogen.sh
./configure --without-apxs --with-ssl 
make
sudo make install
sudo make install-swig-py

New TextMate bundles

Saturday, August 2nd, 2008

These aren’t really new. I just wasn’t aware of them.

JavaScript Tools

The JavaScript Tools bundle helps you lint, format and compress your JavaScript code, and convert code to and from JavaScript bookmarklets.

My favorite feature: whenever you save a JavaScript file via Command-S, the bundle automatically runs it through jslint. If any errors or warnings are found, a tooltip appears which shows the number of warnings/errors.

If you run a full validation using Control-Shift-V, you’ll get a popup window showing “compilation” results — complete with syntax errors and clickable links to take you to the offending source code.

Installation

I installed under ~/Library/Application Support/. It may be better to use /Library/Application Support/.

$ cd ~/Library/Application Support/TextMate/Bundles
$ svn export http://bundles.bundleforge.com/trunk/bundles/JavaScript%20Tools.tmbundle/

BTW I’m not sure why export is preferred over checkout.

If TextMate is already running, you can load the bundle by selecting Bundles->Bundle Editor->Reload Bundles.

Sproutcore

I haven’t done much with Sproutcore yet, but it does already have its own TextMate bundle which provides a few tab-completion snippets.

Installation

$ cd ~/Library/Application Support/TextMate/Bundles
$ curl --location --get http://github.com/sproutit/sproutcore-tmbundle/tarball/master -o sproutcore-tmbundle.tar
$ tar xf sproutcore-tmbundle.tar

The curl --location option is required, since github will issue a redirect.

The extracted tarfile will have a root directory name of the form sproutit-sproutcore-tmbundle-.*, so a directory rename is needed.

$ mv sproutit-sproutcore-tmbundle-blah-blah.../ Sproutcore.tmbundle

Terminal.app hangs at startup

Thursday, July 24th, 2008

(Cross-posted from Bottled Text.)

I just got bit by this bug, under OS X 10.5.4. The symptoms are that sudo hangs, and Terminal.app hangs when opening a new tab or when starting up. Console.app shows messages of the form

7/24/08 7:04:44 AM kernel devfs: ttys001: name slot allocation failed (Errno=17)

rprr posted a workaround in the above thread which worked for me. I don’t know how to link to specific messages in the discussion thread (or whether that’s even allowed under the terms of use, egad), so here’s a recap:

1. Started Terminal. It hung up. Did Force Quit and Sent Crash report to Apple.

2. Since I had a working X11 application, I used it to open about 10 xterms using the Applications->Terminal Menu of X11.app

3. I started Terminal again. Now it works.

Visual Web Developer "Failed to start monitoring changes"

Friday, April 4th, 2008

I keep forgetting about this…

I’d like to do development on an ASP.NET web application which resides in a VMware Fusion shared folder. Unfortunately, as noted in the Microsoft Forums, Visual Web Developer 2005 Express Edition (at least) does not support hosting on a UNC share.

So, AFAICT, the only option is to do development in a local folder. To access that folder from the host operating system, it needs to be shared from the Windows VM.

VMware Fusion, OpenSUSE 10.3 x64, copy and paste

Friday, April 4th, 2008

I recently installed a 64-bit OpenSUSE 10.3 virtual machine under VMware Fusion. Everything worked fine except cut&paste — the vmware-user executable was not launching when X11 started.

ldd showed a dependency on libexpat.so.0, in addition to libexpat.so.1. I installed that using yast, rebooted, and — huzzah — cut&paste now works.

yast_install_libexpat.png

More details are available in the VMware Fusion discussions forum.

TUAW Terminal Tip: Safari 3.1 brings true one-window mode

Friday, March 21st, 2008

Terminal Tip: Safari 3.1 brings true one-window mode:

…true one-window mode is finally, finally, here for Safari. All you need to enter is the command below into Terminal, hit enter, and you’re sorted.

defaults write com.apple.Safari TargetedClicksCreateTabs -bool true

Yay!