How our source code listings are produced

The listing file currently on the web site was produced by an AppleScript that pastes the code blocks into a pre-existing Apple Works drawing file as text labels. Unfortunately Snow Leopard and Rosetta screws up opening a pre-existing template, so last week I had to take a couple of days to rewrite it all.

This version of the ListingMaker.scpt script copies and pastes text blocks into either a preexisting Apple Pages document or a document created de-novo.


-- Make listing of class files
tell application "Finder" to set project_folder to container of (path to me) as string
set prevTIDs to AppleScript's text item delimiters
set AppleScript's text item delimiters to ":"
set project_name to text item -2 of project_folder
set AppleScript's text item delimiters to prevTIDs
set the_listing to open_listing given name:project_name, template:project_folder & "ListingTemplate.template"
-- New
set name of the_listing to (project_name & "Listing")
list_files out of (get_file_names given folder:project_folder & "Classes") onto the_listing
-- Could do other folders in the project here

-- Expand folder into filenames
to get_file_names given folder:the_folder
	tell application "Finder" to return files of folder the_folder
end get_file_names

-- Test if file exists
to test_file_existence given name:file_name
	tell application "Finder" to return (exists file (file_name as string))
end test_file_existence

-- Add files (of specific known types) to listing
to list_files out of list_of_names onto a_listing
	repeat with file_name in list_of_names
		set file_extension to name extension of file_name
		if file_extension is in ["h", "m", "mm"] then
			list_paged_file of (file_name as string) onto a_listing given page_mark:"// pragma page"
			-- Could add "else if" clauses for other recognized file types here
		end if
	end repeat
end list_files

-- List file containing page separators
to list_paged_file of file_name onto a_listing given page_mark:page_mark
	set file_text to read file (file_name as string)
	set prevTIDs to AppleScript's text item delimiters
	set AppleScript's text item delimiters to page_mark
	set the_pages to text items of file_text
	set AppleScript's text item delimiters to ASCII character 10
	set first_line to text item 1 of first item of the_pages
	set AppleScript's text item delimiters to prevTIDs
	if first_line begins with "//" then
		set heading_text to text 4 thru end of (first_line as string)
	else
		set heading_text to file_name
	end if
	tell application "Pages"
		if "" is equal to (body text of a_listing) then
			-- First "section" of document
		else
			-- this is bit of a kluge
			tell application "System Events"
				click menu item "Section Break" of ((process "Pages")'s (menu bar 1)'s ¬
					(menu bar item "Insert")'s (menu "Insert"))
			end tell
			set reuse headers and footers of last section of a_listing to false
		end if
		set odd header of last section of a_listing to heading_text
		set alignment of odd header of last section of a_listing to center
		set text_prefix to ""
		repeat with a_page in the_pages
			if last character of a_page is (ASCII character 10) then
				set a_page to characters 1 through -2 of a_page
			end if
			if "" is equal to text_prefix then
				-- First "page" of section
			else
				select (end of (body text of a_listing))
				insert page break (body text of a_listing)
			end if
			set (body text of last section of a_listing) to (body text of last section of a_listing) & text_prefix & a_page
			set text_prefix to page_mark
		end repeat
	end tell
end list_paged_file

-- Create listing file, either from template or de-novo
on open_listing given name:project_name, template:template_name
	set date_today to current date
	set date_eight to ((year of date_today) as string) & " "
	set mymonth to (month of date_today) as number
	if (10 is greater than mymonth) then set date_eight to date_eight & "0"
	set date_eight to date_eight & mymonth
	set myday to day of date_today
	if (10 is greater than myday) then set date_eight to date_eight & "0"
	set date_eight to date_eight & myday
	tell application "Pages"
		activate
		if (test_file_existence of me given name:template_name) then
			-- display dialog "exists"
			open template_name
			set new_listing to first document of application "Pages"
			select (first word of text of (odd footer of (first section of new_listing)))
			set selection to project_name
			select (last word of text of (odd footer of (first section of new_listing)))
			set selection to date_eight
		else
			set new_listing to make new document
			set left margin of new_listing to 0.25
			set right margin of new_listing to 0.25
			set top margin of new_listing to 0
			set header margin of new_listing to 0.25
			set footer margin of new_listing to 0.25
			set bottom margin of new_listing to 0
			set font name of (body text of new_listing) to "Courier"
			set font size of (body text of new_listing) to 8
			set line spacing of (body text of new_listing) to 80
			set footing to project_name & "	" & date_eight & "	" & "XpagenumberX"
			set (odd footer of first section of new_listing) to footing
			select (last word of text of (odd footer of (first section of new_listing)))
			tell application "System Events"
				click menu item "Page Number" of ((process "Pages")'s (menu bar 1)'s ¬
					(menu bar item "Insert")'s (menu "Insert"))
			end tell
		end if
		select body text of new_listing
	end tell
	return new_listing
end open_listing

The ListingTemplate.template is an empty Apple Pages file with a particular data pattern in the footer. The first word of the footer will be overlaid with the project name, and the last word of the footer will be overlaid with the current date. It is expected that the result of an "Insert Page Number" will be in the footer.

This script assumes the source code is in a directory called classes inside the same directory the script is executed from.

The script could be easily modified to pick up other subdirectories and process other source file types. After it runs, the Apple Pages document can be printed to a PDF file using the normal Apple print mechanisms.

Note: I've carefully written this script to avoid less than characters so it would format well on the web, but it was not possible to avoid the continuation character ¬ which I've manually edited to be ¬ so it would show faithfully. You need to remove it if you take this code.

I've been a professional computer programmer for almost 40 years, and I find AppleScript to be an incredibly brittle language to work with. My suggestion to those attempting to modify this code would be

  1. Start out by making a saved copy to fall back to if your strategy fails
  2. Make only incremental changes to get from point A to point B
  3. Save a copy of each incrementally successful step, to fall back to if a substrategy (tactic) fails

Good luck. You will need it.

Return to Developer’s Corner