Dynamic method calling from applescript

Applescript comes handy sometimes when you need to do some automation job quick within the MAC OS. Though it lacks many of the features offered by the modern languages, you can sometimes simulate them doing some dirty tricks :). One of them is dynamic calling of the methods of a particular script. let’s take the case where you want for example to store some options for your script in a separate file though it might look like a fancy way of storing options. so it will look something like

on AppleOptions()
  return some options
end AppleOptions

on GrapesOptions()
  return some options
end GrapesOptions


on Options()
  --this should be a default option 
  return some sort of options
end Options

Now if the calling of these options depends on some context that changes every time you run your script, you can still call your methods without knowing beforehand what’s going to be called, like this:

set theFruit to some_value_that_came_from_current_context
set selScpt to path_to_the_options_script_file
set selScpt to load script selScpt
set scptOpt to Options() of selScpt
set _scptOpt to run script ("on run (inArgs)" & return & "set theCaller to item 1 of inArgs" & return & "tell (item 1 of inArgs) to " & theFruit & "Options()" & return & "end run") with parameters {selScpt}
--optionally check for empty list or string returned in the try block
end try
if (_scptOpt is not "" and _scptOpt is not {}) then
--display dialog "ok"
set scptOpt to _scptOpt
end if

Calling the above script with theFruit set as “Apple” (no case checking in the above script though) will call your imported script’s AppleOptions() or if not found will get the default Options method.

Free barcode generator for mac using postscriptbarcode

What’s this?
Simply a barcode generator made up from a few open-source tools. It works and it’s written with Applescript(but it’s easy portable to other platforms and/or languages because of the great library behind … PostScript Barcode written by Terry Burton).

How it works?
Well it simply uses the barcode.eps procedures for the dirty work of drawing the barcodes, and exports only the needed bits to an .eps file named after the barcode. Then ghostscript( the script uses the one provided by macports … you can however use the the gs library provided by mac replacing the /opt/local/bin/gs in the below script with the output of the which gs command executed in terminal ) helps us get the bounding box of the new created barcode and sed will make the needed replacements for us inside the .eps file.

What is needed?
Basic knowledge of a few unix tools and some applescript. Also the documentation of PostScriptBarcode must be read in order to find out the options that can be applied to a particular barcode.

Does it really work?
Well i used with success a modified version of the below script for a long time, and the results were at least as good as the ones from a commercial software for my particular case.

Some pointers …
My version of postscript barcode is slightly changed in order to fix some problems like missing fonts. The first part of my barcode.eps looks like this:

%!PS-Adobe-3.0 EPSF-3.0
%%Creator: spherix v0.6.1
%%DocumentPaperSizes: a4
%%DocumentFonts: OCRB
%%DocumentNeededFonts: OCRB
%%DocumentProcessColors: Black

% Barcode Writer in Pure PostScript - Version 2011-05-10

this script might need refining (make sure you change the defined paths to the ones of your system):

property the_save_dir : "/Volumes/Data/data/EANs"
--this is the path to the barcode.eps file
property the_posix_dir : "/Volumes/Data/Barcode App/"

on DoRun(symbology, theBarcodesFile, indexFieldIndex, separatorChar, theFont, theOptions)
	--display dialog separatorChar
	set symbology to do shell script ("echo '" & symbology & "' | sed 's/[-\\s]//g'")
	set oDelim to AppleScript's text item delimiters

	do shell script ("sed -e s/\\r\\n/\\r/g '" & theBarcodesFile & "'")
	set theContents to my readfile(theBarcodesFile)
	set psLine to "10 10 moveto (%s) (%s) /%s /uk.co.terryburton.bwipp findresource exec"
	set master to "barcode.eps"

	repeat with i from 1 to (count of (paragraphs of theContents))
		repeat 1 times
			set options to {}
			if (paragraph i of theContents is "") then
				exit repeat
			end if
			set AppleScript's text item delimiters to {separatorChar}
			set options to options & {text item indexFieldIndex of paragraph i of theContents}
			--display dialog "Options:" & options

			if theFont is not "" then
				do shell script ("sed \"s/Helvetica/" & theFont & "/g\" '" & the_posix_dir & "/" & "barcode.ps' > '" & the_posix_dir & "/barcode_" & theFont & ".ps'")
				set master to "barcode_" & theFont & ".ps"
			end if

			set _options to {}
			repeat with opt in items of theOptions
				if item 2 of opt is not false then
					set _opt to item 1 of opt
					set _opt2 to item 2 of opt

					if (_opt2 is not "" and _opt2 is not true and _opt2 is not false) then
						--display dialog "not null"
						set _opt to _opt & "=" & _opt2
					end if
					set _options to _options & _opt
				end if
			end repeat

			set AppleScript's text item delimiters to {" "}
			--display dialog theOptions as string
			set options to options & {("'" & _options as string) & "'"}
			set options to options & {symbology}

			set psLineComp to do shell script ("printf '" & psLine & "' " & (options as string))
			set AppleScript's text item delimiters to {separatorChar}

			--display dialog psLineComp
			if (text item indexFieldIndex of paragraph i of theContents is "") then
				exit repeat
			end if
			my makeEPS(master, the_save_dir & "/" & text item indexFieldIndex of paragraph i of theContents, psLineComp, symbology)
		end repeat
	end repeat
	set AppleScript's text item delimiters to oDelim
end DoRun

on readfile(unixPath)
	set foo to (open for access (POSIX file unixPath))
	set txt to (read foo for (get eof foo))
	close access foo
	return txt
end readfile

on writeFile(unixPath, content)
	set foo to open for access (POSIX file unixPath) with write permission
	set eof of foo to 0
	write content to foo
	close access foo
end writeFile

on getRequirements(targetFile, symbology)
	set requirements to "sed -n -e \"/% --BEGIN ENCODER " & symbology & "--/,/% --END ENCODER " & symbology & "--/p\" " & targetFile & " | sed -n -e \"s/^dup \\/\\([^\\s]\\)/\\1/p\""
	set reqlines to do shell script (requirements)
	set oDelim to AppleScript's text item delimiters
	set reqList to {}
	set renderers to {"renlinear", "renmatrix", "renmaximatrix"}

	repeat with i from 1 to (length of paragraphs of reqlines)
		set AppleScript's text item delimiters to {" "}
		set _req to text item 1 of paragraph i of reqlines
		if _req is in renderers then
			set reqList to reqList & {"-e \"/% --BEGIN RENDERER " & _req & "--/,/% --END RENDERER " & _req & "--/p\"" & " "}
			set reqList to reqList & {"-e \"/% --BEGIN ENCODER " & _req & "--/,/% --END ENCODER " & _req & "--/p\"" & " "}
		end if
	end repeat

	set command to "sed -n -e \"/%\\!PS-Adobe-2.0/,/% --END PREAMBLE--/p\" "
	if (length of reqList > 0) then

		repeat with j in reqList
			set command to command & j & " "
		end repeat
	end if

	set command to command & "-e \"/% --BEGIN ENCODER ean13--/,/% --END ENCODER ean13--/p\" " & targetFile

	set fileContents to do shell script (command)

	return fileContents
end getRequirements

on makeEPS(master, unixPath, content, symbology)
	set EPInstr to my getRequirements("/Volumes/Data/Barcode App/" & master, symbology)
	set EPInstr to EPInstr & content
	my writeFile(unixPath, EPInstr)
	set bbox to "%%BoundingBox: 0 0 97 76"
		set bbox to do shell script ("/opt/local/bin/gs -dNOPAUSE -dBATCH -q -sDEVICE=bbox " & unixPath & " 2>&1")
	end try
	do shell script ("sed -i \"\" 's/%%BoundingBox%%/" & bbox & "/g' " & unixPath)

	set theFile to POSIX file unixPath as string
	tell application "Finder" to set file type of alias theFile to "EPSF"
end makeEPS

Calling the script to generate barcodes from a particular file:

my DoRun("the symbology: eg ean13 - must match postscript's barcode intern definitions", "csv data file", "index of the barcode field in csv file", "csv file separator", "font to use with barcode", "options as a list where every option is defined as a list eg: {postscript barcode option, value of the option - in case there is no value put true in the second value(false will ignore option)} => example of an option list {{\"includetext\", true}, {\"height\", cheight / 25.4}, {\"textsize", 11}}\") of myBarcodeGenerator