Pages

Saturday, October 30, 2010

Passing code as a text stream into a program

A text stream is a line of text terminated by the newline character, '\n'. The standard library function getchar() retrieves one character at a time from the text stream. 


In the first chapter of Kernighan and Ritchie's The C Programming Language 2e, this function is used in programs of increasing complexity, from a character counter to a rudimentary syntax checker. 


Testing these programs in Xcode's Debugger Console can only be very limited. As soon as the user presses Enter, the text stream is happily processed, and the program expects additional input. But what if you want to test input spanning multiple lines?




In K&R C section 1.6, the first example program counts the frequency of different characters, like digits and blanks. Sample output is from "the program on itself." Near the end of the chapter, Exercise 1-23 asks to "write a program to remove all comments from a C program." There has to be some way to pre-populate the text stream, so that your program processes it to an EOF. 


Using cat, we can pipe the output of a file, such as main.c, to our program. Since we're using Xcode, the path to our project directory can be pretty long to type every time. Instead, we'll write an AppleScript script to tell Xcode to build the project, and to tell Terminal to activate and execute the cat pipe:





The script uses some parts from my previous AppleScript tutorial. Fortunately, all paths are POSIX formatted rather than aliases formatted as HFS paths.  


The one new thing is the use of quoted form, which lets me pass a directory with spaces, like /Programming Exercises/, without escaping the blanks.


With this script, the same program now processes a text stream all the way to EOF:



And the output:




I'm not sure how much use this will be beyond the first chapter, but now that I can pass text streams to EOF in my programs, I feel better about going through these exercises. Instead of one-liner "tests," I can pass whole files as representative input.


References

Sunday, October 24, 2010

Scrambling text for NaNoWriMo using AppleScript, Pages 09 and TextEdit

During National Novel Writing Month, or NaNoWriMo, people try to write a 50,000-word novel in thirty days. You can upload a text file of your progress to get an official word count. Instructions are included on the web site for scrambling your work before submission, if there is any worry of "untrustworthy, word-counting goons." However, only the following methods are detailed.


  • Microsoft Word supports regular expressions, so a quick Save As to a .txt file, and a straightforward [a-zA-Z0-9] wildcard expression with Find and Replace, does the trick. However, you have to manually overwrite further scrambled text files. 
  • Open Office works similarly, but again - you must manually delete a text file full of strings of the character 'a'. 
  • Use Find and Replace twenty-five times. 


I have Pages '09, so in this article I discuss using AppleScript to generate a scrambled text file from that application.

Given a Pages '09 document, generate a scrambled .txt file to the Desktop for upload to NaNoWriMo. Any intermediate files should be deleted after use. 


How would I do this by hand? 
  1. Save my Pages document as a plain text file using Save As. 
  2. Run a couple command-line programs to process the text.
  3. Redirect the output to a "upload_me.txt" file. 
  4. Delete the text file that Pages made.
  5. (Upload to NaNoWriMo's word-counting thing.)
Let's translate this to AppleScript. I will introduce each section and then give some explanations. 


You can find the Pastebin source here, and the script file itself on MegaUpload. I encourage you to compile the script for yourself, or to just run it from the script editor.




First, we ask the user to choose a .pages document with choose file. The activate keyword shifts focus to the file chooser dialog. We get the name and path of the chosen Pages document, and we return if the user cancels out. Note that the directories are separated by colons, and the presence of the word alias. AppleScript formats paths in two ways, and this is one. The alias path is formatted as an HFS path.

The file chooser repeats until a valid Pages document is chosen. Fortunately, even if a document is simply named "test," internally the file is recognized as "test.pages."

After we harvest the file information, we tell Pages to save the document as a plain text file, and we run cat and sed to process the text proper.

I tried redirection > to a file after sed, but I received error message -10004, or that a "privilege violation" occurred. A Technical Note (referenced below) gives some advice on granting admin-level access, but I'm creating a text file. So I decided to use TextEdit. This is the power of scripting: chaining application abilities together into an automated process.

There are more types than just SLDocumentTypePlainText. There's also 
  • SLDocumentTypeMSWord,
  • SLDocumentTypePDF,
  • SLDocumentRichText, and 
  • SLDocumentRichTextBundle.
We name the new text file by using the ampersand operator to concatenate the file path and name to the ".txt" extension. The POSIX path specifier gives us the path with '/' as the directory separator. This is the second way paths are formatted in AppleScript. If you pass an HFS path to a Unix tool like cat, it will return the error "No such file or directory."


Pages doesn't receive the activate command, but doesn't need to because its job is to simply Save As and close a file. The open command not only opens a document, but returns the document's id. This is very useful; exploit this as much as possible. 


With the scrambled text after cat/sed stored in the scramble_text variable, we can now use TextEdit's features to generate a text file. 


Question: at runtime, can an AppleScript variable store a string consisting of 50,000 words? I used a Pages document with 101,233 words spanning 278 pages consisting of 431,954 characters (excluding spaces), and the script took about three seconds. 




Here we tell TextEdit to create a new document, to populate it with the scrambled text, and to save to Desktop. Now a user can visit NaNoWriMo and upload this text file. Successive uses of this script will overwrite the "upload_me.txt" file, so we no longer have to confirm a file overwrite as with Word or Open Office. Error number 0 indicates success.


And there you have it: a script to make your novel one long shout. Try experimenting with AppleScript, and consider signing up for NaNoWriMo! :)


References

Update 11/1/2010. Had to use quoted form for the directory when passing in to the shell script. My file was called "Chapter 1.pages," and the script wouldn't work. The links to MegaUpload and to Pastebin have been updated. See screenshot:


Wednesday, October 13, 2010

Setting up Flex, flixel and Xcode

In this tutorial, you will build and run a flixel project from Xcode. You will use Xcode to edit ActionScript 4 files, and you will see how Xcode uses an External Build Target to run the AS4 compiler mxmlc, much like how Eclipse uses javac behind the scenes to compile .java files, or how Mac OS X uses open to launch Preview when you double-click on a PDF file. At the end of this post, you will find links to three comprehensive, excellent flixel tutorials.

Flixel is a game development library created by Adam Saltsman that leverages the Adobe Flex framework. Both the flixel library and the Flex SDK will be needed. Additional files include the flixel template file and the syntax highlighter specification folder (SHSF)The template file will make things easier for both of us: first, your project should build out of the box: you'll have a working flixel application right from the start, in Xcode. Second, many steps can be referenced rather than explicitly enumerated. 

The SHSF has files to enable syntax highlighting of AS4 files in Xcode. We will use the specification files of Nathan Roberton, a UX designer in CTO Product Incubation at Microsoft. 

Before we begin, please note that this tutorial is for flixel 2.35, Adobe Flex 4.1.0.16076 and Xcode 3.2.2. I assume you have Xcode installed. Let's get started.

The tutorial has the following steps:
  1. Download files.
  2. Move and rename files.
  3. Open Xcode, start a new flixel project, and build.
  4. Run the SWF in Safari.
Step 1: Download files.

We need to download the following: 
* The last download goes to Nathan Roberton's own tutorial on Xcode and AS3. Scroll to the bottom, to step eight, and download the "Actionscript specification files." 

Extract any compressed files.

Step 2: Move and rename files.

Next, move the flixel folder and the Flex SDK folder to the /Developer/Library/SDKs directory. 

Move the "Flixel Game" folder to the ~/Library/Application Support/Developer/Shared/Xcode/Project Templates/Other directory. 

Move the individual specification files into the ~/Library/Application Support/Developer/Shared/Xcode/Specifications directory. 

You will need to make folders, because some of these directories will not exist. 

At this point, you are free to rename the flixel library folder and the Flex SDK folder. For the purposes of this tutorial, rename them to "flixel_2.35" and "flex_4.1.0.16076," respectively. Omit the double quotes.


Why these specific directories? The Flex SDK is 273 MB, and I do not want Time Machine to back it up if I place it in my ~ (home) directory. The /Developer/SDKs directory is for "system SDKs," according to the Xcode Installation Guide

Step 3: Open Xcode, start a new flixel project, and build.

Launch Xcode. Go to File -> New Project. Choose "Other" under User Templates, select the "Flixel Game" template, and click Choose. Name your new project.

Under the Groups & Files sidebar, expand Targets, and then double-click on "mxmlc." Note the following:
  • In the Build Tool field, the path leads to the mxmlc program. This is the Adobe Flex compiler. 
  • In the Arguments field, there are two flags set: -compiler.source-path, and -static-link-runtime-shared-libraries=true. The first flag refers the compiler to the flixel libraries, and the second fixes an obscure [Embed()] issue. 
  • In the Product Name field, note that spaces must be escaped, and that decimals are okay. Also notice the shorthand ${PRODUCT_NAME} used in the Arguments field.
  • In the Build Settings section lower down, there is only PRODUCT_NAME. Most default Xcode projects will have GCC environment variables set here. They have been removed, because we are making SWFs. (Oh, and "Pass build settings in environment" is unchecked.)
Go to the Build Menu and click Build, or press Command+B. Xcode will invoke the Flex compiler. Build results may be viewed by clicking the right-most icon. This is where error messages will show up. See screenshots:



A successful build creates a SWF file in the ./bin/ directory of your project. 

Step 4: Run the SWF in Safari.

Drag the SWF file into a new Safari window. Your journey has just begun.

flixel Tutorials