Code Formatting in Xcode 4

Automatic indentation and cleanup of code seems to have improved in Xcode 4 (Editor menu – Structure – Re-Indent) but it still doesn’t offer full code reformatting or the flexibility of a tool like Uncrustify. If you’re used to having external code formatting in Xcode available you might be disappointed to find the User Scripts menu missing in Xcode 4.

Thankfully Tony Arnold demonstrated one possible solution with his Xcode 4 Uncrustify Automator Services. Here’s how you can get your external code formatting tool up and running again with Xcode 4.

Install Uncrustify (port install uncrustify, brew install uncrustify, or directly from http://uncrustify.sourceforge.net/)

Open Automator and create a new Service.

Creating a Service in Automator

Creating a new Automator Service

Inputs to Automator Services are more limited than the options available in Xcode 3′s User Scripts. To reformat selected text we can still pass the input from Xcode to a Run Shell Script action.

uncrustify -l OC -q -c ~/.uncrustify/uncrustify_obj_c.cfg
The "uncrustify selected text" service in Automator

Uncrustify Selected Text

To reformat open files we need to use AppleScript to get the paths to those files so that we can pass them to Uncrustify. I wasn’t able to find a reliable way to select only the currently visible source file so I settled on the following script to reformat all open and modified source files instead.

tell application id "com.apple.dt.Xcode"
	repeat with current_document in (source documents whose modified is true)
		set current_document_path to path of current_document
		set raw_source to text of current_document
		set formatted_source to do shell script "uncrustify -l OC -q -c ~/.uncrustify/uncrustify_obj_c.cfg -f " & current_document_path
		set text of current_document to formatted_source
	end repeat
end tell
The "uncrustify modified documents" service in Automator

Uncrustify Modified Documents

Open Xcode, find the new Services available in the “Xcode” menu. Use the Services Preferences to bind these Services to keyboard shortcuts to your liking.

The Xcode and Services menus

Services available in Xcode

Enjoy cleaner code.

This entry was posted in Mobile and tagged , . Bookmark the permalink.
  • Pingback: Code Formatting in Xcode | Carbon Five Community

  • http://www.juripakaste.fi/blog/ Juri Pakaste

    Good stuff. One addition: it probably makes sense to replace the & current_document_path in the script with & quoted form of current_document_path to make it work with documents with spaces, quotes etc in their paths.

  • Shreyas

    You can use Editor — > Structure — > Re – Indent.

    • Jonah

      That’s true (and mentioned in the first paragraph) but code reformatting can include far more complex rules than just correcting indentation.

  • taewoo kim

    Thanks, you have been extremely helpful.
    I was able to get currently visible file by using
    “set current_document to last source document”.

    “first source document” sometimes made mistake.

  • YoungJae

    Thanks for the great tip!

  • http://www.yanchuanli.com Yanchuan Li

    Hello Jonah,
    it seemed it doesn’t work at all.
    I’ve followed the instructions here and uncrustify also works already in the terminal.
    But when I just clicked the service, nothing changed in my xcode4.
    Any ideas for this?

    • Jonah

      Sorry to hear that you’re having trouble. If you open the service in Automator you should be able to capture its inputs and outputs to determine where the problem is.

      For example you could add a “Get Specified Text” step to the beginning of the “Uncrustify Selected Text” service to send it some known code snippet and inspect the result to make sure the shell script action is correctly passing that text to Uncrustify.
      Similarly if you return the raw_source or formatted_source from the “Uncrustify Modified Documents” service’s AppleScript action you should be able to confirm if you got text from Xcode and Uncrustify.

      Hopefully that allows you to determine if the Uncrustify shell script calls are incorrect for your machine or if there is some problem with the services interacting with Xcode.

      • http://www.yanchuanli.com Yanchuan Li

        When I run this Applescript in Applescript-Editor, I’ve got following info from the console:

        tell application “Xcode”
        count every source document whose modified = true
        –> 0
        end tell

        It seemed that my xcode cannot return the opened document to our service?

        • Jonah

          That seems to be the case. I wonder if Xcode relies on VCS integration to identify modified files. Do you have Xcode setup to be aware of whatever version control you are using?

  • http://www.yanchuanli.com Yanchuan Li

    Besides, what I’ve done is build this service according to your blog first. And then open one of my .m file in my xcode and click this service. However it doesn’t change anything …

  • phil

    Uncrustify works for me very well on the terminal. As soon as I try to run the script via Automator I’ll get a “Run Shell Script failed – 1 error” message:
    /Users/phil/uncrustify_obj_c.cfg:37 Unknown symbol in ‘nl_before_return’
    This config file works well when using it directly in terminal.

    Any ideas?

  • Pingback: XCode3 User Scripts | Geeklu

  • Pingback: Code Formatting in Xcode | Geeklu

  • mC

    Installed uncrusty with the command “brew install uncrustify” but i don’t got some workflow and cfg files -.-

  • Anonymous

    Thank you very much for the info but there’s several serious problems going on here.

    The first issue is minor: the source code is HTML escaped so you have to go in and manually change the quotes and ampersands. Not a big issue for a developer but also something a developer wouldn’t want on their site.

    I’m guessing you did some upgrade to your code formatter and don’t have to use escaped code anymore but didn’t change the older posts to reflect this.

    The next issue is there is no ~/.uncrustify/ directory so of course there is no uncrustify_obj_c.cfg file. This causes both scripts to crash and burn… but not in a good way.

    It’s not immediately clear that we need to read your other article to find the file nor is it clear at all if I do or do not need to also install UniversalIndentGUI to make this all work. I don’t but it’s a bit confusing to someone muddling through.

    Next you need to modify the AppleScript line with do shell script so it calls the exact path to the uncrustify app since do shell script doesn’t appear to run the .bashrc file even if you specify /bin/bash in the line. This means it has no idea where uncrustify is at.

    This also needs to be done for the selected text script.

    While changing the script to the exact path fixes the issue of the shell not knowing where uncrustify is this just gets us to the next problem which is AppleScripts inability to handle the return data from the shell script. Since the return value is non-zero it gets all confused it thinks this is an error.

    I got around this by echoing the output to a temp file and putting ; echo 0 at the end of the line. I then load the file with another do shell script where I cat the file.

    Here’s the monstrosity I ended up with after all that misery.


    tell application id "com.apple.dt.Xcode"
    repeat with current_document in (source documents whose modified is true)
    set current_document_path to path of current_document
    set raw_source to text of current_document
    set temp_file to "/tmp/uncrustify_tmp.txt"

    set script_code to "/usr/local/bin/uncrustify -l OC -q -c ~/.uncrustify/uncrustify_obj_c.cfg -f " & current_document_path & " > " & temp_file & " ; echo 0"
    do shell script script_code

    set formatted_source to (do shell script "cat '" & temp_file & "'")
    set text of current_document to formatted_source

    do shell script "rm " & temp_file

    end repeat
    end tell

    I think this just goes to show you no one should ever, ever use AppleScript since it is clearly the most evil, stupid language ever devised.

    Thanks again though for the info even if I did have to delve in the bowels of AppleScript to fix some of it.

  • Pingback: 使用Uncrustify在Xcode中格式化Objective-C代码 | Igotit的空间

  • Pingback: Javascript formatting in xcode - Learning xcode.

  • Pingback: Javascript formatting in xcode - Learning xcode.

  • http://twitter.com/dshevchenko_biz Denis Shevchenko

    Try Style Revisor (http://style-revisor.com). This app cannot be integrated in Xcode, but IMHO it’s even better.

  • Pingback: Code Formatting in Xcode 4 | Coding Farmer

  • Pingback: 使用Uncrustify在Xcode中格式化Objective-C代码(转) | CouldHll's Blog