Syntax Coloring Demo for Cocoa

All of this code is really, really old! And not very good! You’re better off looking somewhere else!

4 Sep 2002

For NetNewsWire I recently did simple syntax coloring—when you view the source of an RSS feed, all tags are colorized. Here’s a screen shot to show what I mean.

It turned out to be delightfully simple—as so many things in Cocoa are. So I figured I’d write it up.

Who this article is for

This article assumes some basic knowledge of Cocoa. It will not show how to do connections between Interface Builder and Project Builder, for instance. If you’re not familiar with Cocoa yet, but want to be, I strongly recommend starting with one of the various books on the subject.

Download

SyntaxColoringDemo.sit includes project and source files. It was built on Mac OS X 10.1.5 with the May Developer Tools.

In order to be utterly clear, the code is placed under the open source BSD license—which means you can use it in your apps, whether they’re open source or commercial or whatever.

App Overview

The app has at the top a place to type in a URL. A Get button causes the app to download the URL then display the source with syntax coloring in a text view.

If you launch the app and try it out, you’ll see a window that looks something like this screen shot.

The first thing I did was create a new project and create the interface in Interface Builder. Then I created SyntaxColoringDemo.m and .h, and connected the two outlets (one for the URL field, one for the text view) and one action (for the Get button).

Clicking the Get button

The Get button is connected to the fetchAndDisplayURL action which is implemented in SyntaxColoringDemo.m.

In a nutshell, this method gets the URL the user entered, downloads the data at that URL, converts the data to a string, applies syntax coloring, then displays the colorized string in the text view.

The method of downloading used in this demo is totally simple—but also not one I would recommend for anything but demo apps. It creates an NSURLHandle, then gets the associated data with the NSURLHandle’s resourceData method. (That method blocks until the data is returned, which is why it’s not so great outside of demo apps. I recommend CURLHandle for real apps.)

The code is pretty simple:

urlHandle = [url URLHandleUsingCache: NO];

pageData = [urlHandle resourceData];

(In fact, there’s an even easier way to do this, but whatever.)

Next the returned data is converted to a string via NSString’s initWithData method, then the local method colorize is called to do the syntax coloring. (More on that in a minute.)

Finally the syntax-colored string is displayed in the text view.

colorize

Here’s where all the fun is. The key to the delicious goodness of this routine is the NSScanner class (which I hadn’t used before).

A scanner object finds strings within a string. The beauty of it is is that it remembers where it left off.

The colorize method uses an NSScanner to find each < character. When it finds one, it looks for the next > character. Then it colorizes those two characters and everything in between. When the scanner reaches the end of the string, it stops.

At the top of the method a scanner object is created with the source string. A mutable attributed string is also created with the source string. (Attributed strings are strings with style information.) tagColor is the color that will be used to colorize all tags. The atts dictionary specifies the color attribute.

The meat of this method is the following loop:

while (![scanner isAtEnd]) {

   int ixLeft, ixRight;
		
   /*Find next < character.*/
		
   [scanner scanUpToString: @"<" intoString: nil];
			
   ixLeft = [scanner scanLocation];
		
   /*Find next > character.*/
		
   if (![scanner scanUpToString: @">" intoString: nil])
      break;
		
   ixRight = [scanner scanLocation] + 1;
		
   /*Set the color style for everything between the
   found < and > characters. (And for the < and >
   characters themselves.)*/
		
   [attString setAttributes: atts
      range: NSMakeRange (ixLeft, ixRight - ixLeft)];
   } /*while*/

The loop terminates when the scanner reaches the end of the source string. The first thing the loop does is find the next < character, starting from where the scanner left off. Of course, the first time through the loop the scanner is at the beginning of the source string, so the first < character it finds is the first < character in the source string.

Then it finds the first > character from where the scanner left off. In other words, it finds the first > character that’s after the < character it found.

Along the way, the loop has set the local variables ixLeft and ixRight to the index of the < and > characters. NSScanner’s scanLocation returns the index of the found string.

Finally the color attributes are set in the attributed string for the range specified by ixLeft and ixRight.

Once the loop is finished, the colorize method returns the attributed string, which fetchAndDisplayURL then displays to the user in the text view.

Piece of cake.

© 1995-2014 Ranchero Software, LLC