Uli's Web Site
[ Zathras.de - Uli's Web Site ]
Other Sites: Stories
Pix
Abi 2000
Stargate: Resurgence
Lost? Site Map!
 
 
     home | articles | moose | programming | articles >> blog

 Blog
 
 Blog Topics
 
 Archive
 

15 Most Recent [RSS]

 All you need to know about the Mac keboard
2010-08-09 @488
 
 Review: Sherlock
2010-07-31 @978
 
 Playing with Objective C on Debian
2010-05-08 @456
 
 Fruit vs. Obst
2010-05-08 @439
 
 Mixed-language ambiguity
2010-04-15 @994
 
 Uli's 12:07 AM Law
2010-04-12 @881
 
 Uli's 1:24 AM Law
2010-04-12 @874
 
 Uli's 6:28 AM Law
2010-04-12 @869
 
 Uli's 3:57 PM Law
2010-04-12 @867
 
 Uli's 4:41 PM Law
2010-04-12 @864
 
 Uli's 7:25 AM Law
2010-04-12 @862
 
 Uli's 9:36 PM Law
2010-04-12 @861
 
 Typesafe typecasts
2010-04-12 @471
 
 Porting to the Macintosh
2010-04-09 @592
 
 Uli's source code is on Github!
2010-03-05 @986
 

More...

Helpful Xcode User Scripts

One of the more annoying tasks when writing Cocoa code is defining symbolic constants for all those keys when doing key-value coding. I've already posted my trick for getting auto-validated key-value-observing constants, but there are constants that aren't accessors. Does lazy Uli have a trick for these as well?

[Xcode's User Script editing window and the User Scripts menu]

Yes! Xcode has a really neat feature called "User scripts". It takes the form of a little black scripture roll in the menu bar. If you open it, there is an "Edit User Scripts..." menu item. Choose it, and it shows a list of the scripts that come with Xcode, plus an edit field on the right where you can edit the current script.

The neat thing here is: These are just unix shell scripts. Notice the shebang at the top? That means you can specify every script interpreter, and you aren't stuck with those terrible search-and-replace-with-side-effects-languages like bash or zsh. You could use Perl, or Ruby, or ... heck, why not use PHP? Let's do that, let's solve our problem with constants in PHP. Click the "+" button and add a new script, change its name and give it a nice keyboard shortcut (I chose Cmd-Ctrl-K, K as in Konstant - C was already taken). Then paste in the folowing script:

#!/usr/bin/php
<?php
$fd = fopen( "php://stdin", "r" );
$the_ident = fgets($fd);
echo "NSString*\t$the_ident = @\"$the_ident\";\n";
?>
Make sure the "Input" popup is set to "Selection", and the "Output" is set to "Place on Clipboard". Now, whenever you need a new string constant as a dictionary key in Cocoa, you can just write the constant's symbolic name
MyAppShouldOpenUntitledWindowPrefsKey
select it by double-clicking, hit Cmd-Ctrl-K, and then paste a finished declaration for it at the top of your source file:
NSString*   MyShouldOpenUntitledDocPrefsKey = @"MyShouldOpenUntitledDocPrefsKey";

Of course that's just one of the neat macro things you can do. Since most scripting languages these days support regular expressions, you can do things like turn detect string literals on a line and generate a .strings file entry from it (or vice versa), put brackets and angle brackets around the selected expression (set the output to also be "Selection"), and do a multitude of other handy things.

Okay, you don't really have to write code for putting brackets around certain expressions. Just look in the Edit -> Insert Text Macro -> C and Edit -> Insert Text Macro -> Objective-C submenus. You can use the Preferences window's Key Bindings page to specify keyboard shortcuts (I chose Cmd-Ctrl-9, the key where my UK keyboard has the opening bracket, for Parenthesize Expression and Cmd-Ctrl-[ for Bracket Expression).

Of course, you can also put scripts in this menu that talk to the command line tool for your version control system of choice. For example, if you're as addicted to GUI clients as I am, you'll want the following script:

#!/bin/bash

# Find current document's repository root and cd to it:
MYPATH=`osascript -e "tell application \"Xcode\" to (path of document 1)"`
while [[ -n "$MYPATH" && "$MYPATH" != "/" && ! -e "$MYPATH/.git" ]]
do
	MYPATH=`dirname "$MYPATH"`
done
cd "$MYPATH"

if [[ -n "$MYPATH" && "$MYPATH" != "/" ]]
then
	# Now do our magic!
	open -a GitX.app "$MYPATH"
fi

This opens the current Xcode file's Git repository in GitX so you can get yourself some hot merging and staging goodness. You can write a lot of code following this principle. For example, here is a script that does a git push on the project folder in a Terminal window, so you can actually type something into the password prompt:

#!/bin/bash

# Find current document's repository root and cd to it:
MYPATH=`osascript -e 'tell application "Xcode" to (path of document 1)'`
while [[ -n "$MYPATH" && "$MYPATH" != "/" && ! -e "$MYPATH/.git" ]]
do
	MYPATH=`dirname "$MYPATH"`
done
cd "$MYPATH"

if [[ -n "$MYPATH" && "$MYPATH" != "/" ]]
then
	# Now do our magic!
	IGNORE=`osascript -e "tell application \"Terminal\" to do script \"cd \" & quote & \"${MYPATH}\" & quote & \"; git push\""`
fi

Any other suggestions for other useful scripts for coding that one may want to put in this menu?

Reader Comments: (RSS Feed)
Dirk writes:
You might also like this one that I originally developed for iPhone development but also work on Mac code. It handles all the property stuff which is quite redundant in Objective-C: http://github.com/holtwick/xobjc
Andy Lee writes:
Here's a script idea I *think* should be doable but have been too lazy to try as yet: http://www.notesfromandy.com/2009/09/04/app-idea-extract-method-name-from-selected-text/
Julián Romero writes:
I use this one a lot. It adds a log of the selected variable: #! /bin/sh echo -n 'NSLog(@"%%%{PBXSelectedText}%%% => %@", %%%{PBXSelectedText}%%%%%%{PBXSelection}%%%);'
Ross Carter writes:
I'm not a good typist, so I use user scripts to type things for me, like a divider: #! /usr/bin/perl -w # -- PB User Script Info -- # %%%{PBXName=NSLog}%%% # %%%{PBXOutput=ReplaceSelection}%%% use strict; my $object = <<'SELECTION'; %%%{PBXSelectedText}%%% SELECTION chomp $object; print "//------------------------------------------------------- // xxxxxxxxxxxx //------------------------------------------------------- "; exit 0; or logging the method selector: (same as above but with:) print "NSLog(@\"%s\", _cmd);"; or localized strings: print "NSLocalizedStringFromTable(@\"%%%{PBXSelectedText}%%%\", @\"TABLEGOESHERE\", @\"%%%{PBXSelectedText}%%%\")"; NSStringFrom (type re or ra to get autocompletion for Rect, Range, etc): print "NSStringFrom"; and various pragmas, to promote consistency in how I organize code within a file: print "#pragma mark -\n"; print "#pragma mark IBActions\n";
Uli Kusterer replies:
Dirk, that's a neat script, though it's unfortunate that it needs to mark up the ivars in a way that requires changes to the actual code. I wouldn't be able to use this on many open source projects unless I can convince everyone to use it.
Uli Kusterer replies:
Andy, that sounds like a neat idea, and Peter's command line tool looks like a good start. Would love to see what becomes of this. Along similar lines, I'd love a script that auto-adds method declarations to the @interface for a method I just declared in @interface. I.e. I write the implementation, leave the cursor somewhere nearby, start the script, and it finds the method signature, opens the header, finds the @implementation in there and inserts the prototype there. It'd be even cooler to be able to do that from a call: Double-click opening bracket and it'll analyze the types of the parameters and generate the right signature, then create an empty implementation and interface declaration. But I guess for that one might need Clang to actually parse the code.
Uli Kusterer replies:
Julian, that one is neat. Short, sweet, and will log any object type. Would be interesting to see if one could do a localized search and try to determine the type of that variable, then also make it work for ints etc.
Linus writes:
A naive and simple way of generating the implementation body for a declaration. Select the declarations you want to generate a body for and run the script below. It simply replaces the ';' with "{}". It is indeed simple, but good enough for me. #! /usr/bin/python # -*- coding: utf-8 -*- import sys print "".join(sys.stdin.readlines()).replace(";\n", "\n{\n}\n"),
Thomas Westfeld writes:
This script can be used to strip of Apple's legal disclaimer from their sample code for better readability.
mario writes:
Hi there and thank you for this great resource! I would like to create a script that replaces the number within the following line of code, duplicate it and then paste it. (basically increment the numbers and paste) [UIImage imageNamed:@"myImage1.png"], How do I do that?
Comment on this article:
Name:
E-Mail: (not shown, hashed for Gravatar)
Web Site URL: (optional)
Comment: (plain text only)
Please Enter the following word:
Or E-Mail Uli privately.

 
Created: 2009-11-01 @735 Last change: 2010-09-02 @784 | Home | Admin | Edit
© Copyright 2003-2010 by M. Uli Kusterer, all rights reserved.