Binary Lion Studios

I code for fun and for food.

ZipKit example

Quick and easy way to inflate an archive using the fantastic ZipKit.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
- (void)inflateArchive {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

  NSString *archivePath = [self archivePath];
  ZKFileArchive *archive = [ZKFileArchive archiveWithArchivePath:archivePath];
  [archive setDelegate:self];
  [self setArchiveSize:[[[archive centralDirectory] valueForKeyPath:@"@sum.uncompressedSize"] unsignedLongValue]];
  [archive inflateToDiskUsingResourceFork:NO];

  // do something with inflated archive. 
  // zipkit puts all inflated files in the same directory as the archive.

  [self performSelectorOnMainThread:@selector(inflateComplete) withObject:nil waitUntilDone:NO];

  [pool drain];
}

- (void)inflateComplete {
  // do something after inflate finishes.
}

# pragma mark - ZKArchive delegate methods

- (void)onZKArchive:(ZKArchive *) archive didUpdateBytesWritten:(unsigned long long)byteCount {
  [self setArchiveProgress:[self archiveProgress] + byteCount];

  if ([self archiveSize] <= 0) return;

  [[self progressView] setProgress:(float)[self archiveProgress] / (float)[self archiveSize]];
}

- (BOOL)zkDelegateWantsSizes {
  return YES;
}

Using FileMerge for merges with Mercurial

As a follow-up to the last post, you can also use FileMerge to handle merges with Mercurial.

Write a script and put it on your $PATH

First, you need to write a script that will force opendiff to wait before returning during a merge. Name the script opendiff-w.

1
2
# opendiff-w
opendiff "$@" | cat

Then you need to make it executable.

1
$ chmod u+x opendiff-w

Finally, put the script on your $PATH. I put mine in a folder called ~/development/scripts/path, and added this to my ~/.profile:

1
export PATH=$PATH:~development/scripts/path

Source the file and make sure you can execute the file you just created.

1
2
3
$ source ~/.profile
$ opendiff-w
opendiff[1234:56f] too few arguments

Tell Mercurial to use opendiff-w for merges

Edit your ~/.hgrc file and add the following:

~/.hgrc
1
2
3
4
5
6
[merge-patterns]
** = filemerge

[merge-tools]
filemerge.executable = /Users/user.name/path/to/opendiff-w
filemerge.args = $local $other -ancestor $base -merge $output

Make sure your executable path includes the opendiff-w at the end. For example, mine is:

1
filemerge.executable = /Users/user.name/development/scripts/path/opendiff-w

You are good to go. Next time you do a hg merge, Mercurial will use FileMerge to let you manually fix the conflict.

Using FileMerge for diffs with Mercurial

Mercurial allows you to setup an external diff tool to handle viewing diffs. Here is how you can get Mercurial to use FileMerge (the merge tool that is installed with the OSX developer tools).

Install the fmscripts wrapper.

Download the scripts, unpack them, and install them.

1
2
3
4
5
$ cd ~/Downloads
$ curl -OL http://www.defraine.net/~brunod/fmdiff/fmscripts-20100225.tar.gz
$ tar xzvf fmscripts-20100225.tar.gz
$ cd fmscripts-20100225
$ sudo make install

Tell Mercurial to use FileMerge

Edit your ~/.hgrc file and add the following:

~/.hgrc
1
2
3
4
5
[extensions]
extdiff=

[extdiff]
cmd.opendiff = fmdiff

Use FileMerge to view a diff

If you have a dirty working copy, you can now view the diff between it and the tip by using the following command:

1
$ hg opendiff

Of course, you can still use all the normal diff options. For example, to view the differences between two revisions, do this:

1
$ hg opendiff -r100 -r101

Or for a single file:

1
$ hg opendiff -r100 -r101 views.py

Or to see the difference between a revision and your working copy for a single file:

1
$ hg opendiff -r101 views.py

Yay, Mercurial.

Dynamic model form

Create a ModelForm for a given model and list of fields.

1
2
3
4
5
6
7
def model_to_modelform(cls, fs):
    from django import forms
    class DynaForm(forms.ModelForm):
        class Meta:
            model = cls
            fields = fs
    return DynaForm

Now use it.

1
2
3
# perhaps use it in a view
form = model_to_modelform(User, ('username', 'email',))
dynamic_form = form(instance=request.user)

Sources:

http://www.agmweb.ca/blog/andy/2249/

Installing pygraphviz OSX

Download and install the latest version of graphviz.

Download and unpack the latest version of pygraphviz.

Update the library_path and include_path in setup.py.

setup.py
1
2
library_path='/usr/local/lib/graphviz/'
include_path='/usr/local/include/graphviz/'

Install as usual:

1
$ sudo python setup.py install

Test the install.

Important: Before you enter the python interpreter, make sure you leave the pygraphviz directory.

1
2
3
4
$ cd ~
$ python
>>> import pygraphviz
>>>

Sources:

http://bradmontgomery.blogspot.com/2010/07/pygraphviz-on-os-x-sl-with-virtualenv.html

Create a list with same value repeated

A handy way to create a list with the same value repeated.

1
2
3
>>> n = 10
>>> [0] * n
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

This trick is also nifty for plotting data, where you need all points on the y-axis without a value to be a given number (usually 0).

1
2
3
4
5
6
7
8
>>> n = 5
>>> x = range(5)
>>> x
[0, 1, 2, 3, 4]
>>> zip(x, [0] * n)
[(0, 0), (1, 0), (2, 0), (3, 0), (4, 0)]
>>> dict(zip(x, [0] * n))
{0: 0, 1: 0, 2: 0, 3: 0, 4: 0}

Sort groups in Xcode 3.x

You can sort groups in Xcode 3.x, but it’s not very intuitive. Select the group you want to sort, then do Edit->Sort->By Name. That will sort the group, but it doesn’t keep it sorted. Because sorting is in the menu, it’s very easy to assign a key binding (I did ctrl+alt+command+s).

Xcode group

Source: http://forums.macrumors.com/showthread.php?t=564590

Alter table in SQLite when table contains data

SQLite’s alter table command only supports renaming the table and adding a column. If you need to alter a column (say, to change it’s length), the high-level process looks like this: export the data, drop the table, recreate the table with the updated column, then import the data. You can use SQLite’s dot commands to achieve that with minimal fuss.

1
2
3
4
5
6
7
8
$ sqlite3 dbfile.db
sqlite> .mode insert [tablename]
sqlite> .output [tablename].txt
sqlite> select * from [tablename];
sqlite> drop table [tablename];
sqlite> create table [tablename] ...;
sqlite> .read [tablename].txt
[ctrl+d]

If you’re using Django, it’ll take care of creating the table for you. Just update your models.py to reflect your new changes, then the workflow looks like this:

1
2
3
4
5
6
7
8
9
$ sqlite3 dbfile.db
sqlite> .mode insert [tablename]
sqlite> .output [tablename].txt
sqlite> select * from [tablename];
sqlite> drop table [tablename];
[ctrl+d]
$ python manage.py syncdb
sqlite> .read [tablename].txt
[ctrl+d]

You could also consider looking at the South project which is billed as intelligent schema and data migrations for Django.

RegexKitLite 3.3

If you’re looking for RegexKitLite 3.3, it’s a little less than intuitive to find it. I eventually found it here after just grabbing the URL for the 4.0 release and changing it to 3.3.

Why would you want an older version? According this this post on the Cocoa Dev mailing list apps have been rejected for using RegexKitLite 4.0. You can either replace your 4.0 version with 3.3, or just add the -DRKL_BLOCKS=0 flag to your OTHER_CFLAGS build settings in Xcode (much simpler in my opinion).