Programming / Scripting

Dynamic method calling from applescript

0

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


--script_options.scpt
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:

--main.scpt
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
try
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

0

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
%%BoundingBox%%
%%DocumentPaperSizes: a4
%%DocumentFonts: OCRB
%%DocumentNeededFonts: OCRB
%%DocumentProcessColors: Black
%%EndComments

% 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\"" & " "}
		else
			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"
	try
		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

Removing chosen jquery select box replacement

0

$("select").removeClass("chzn-done").css('display', 'inline').data('chosen', null);
$("*[class*=chzn]").remove();

Pin problem with eclipse-php in Windows 7

0

Eclipse 3.0.2 tends to be stubborn about pinning nicely to the Windows 7 taskbar … the solution for me was to add these to the eclipse-php.ini
–launcher.vm
C:\Program Files\Java\jre7\bin

where C:\Program Files\Java\jre7\bin is the path of the installed jre on your system.

Embedding multiple forms with symfony … hardcore :)

0

Well this should be one of the last posts about branch 1.x of symfony. The 2nd version should come to alpha soon so there is no real need to go further with it. Anyway … some time ago I desperately needed a quick and reliable way to embed multiple symfony forms on one page and submit them at once. I generally take the time to look into the source files, but this time i was in a hurry. So this is the “hacky” way i got around:

function executeMoo(sfWebRequest $request) {
$this->forms = array();

$it = 0;

foreach($some_model as $s) {

$f = new MooForm($s);

$f->getWidgetSchema()->setNameFormat('foo[' . $form->getName() . $it . '][%s]');

$this->form->embedForm($it, $form);
$this->forms[] = $this->form;
$it++;

}
}

The presentation part should be as simple as:

<form ...>
<table>
<tr>
<td><table>
<?php
foreach($forms as $form) :
   echo $form;
endforeach;
?>
</table></td>
</tr>
</table>
</form>
</pre>

Ok now for the validation part:

public function executeSubmit_Foo(sfWebRequest $request) {
         $this->forward404Unless($request->isMethod(sfRequest::POST));

   	$base_forms = $request->getParameter('foo');

	foreach($base_forms as $base_form) {
		$f = new MooForm();
		$f->bind($base_form,null);
		if($f->isValid()) {
			$f->save();
		}
	}
}

What’s the catch?
Well the catch is in this line: $f->getWidgetSchema()->setNameFormat(‘foo[' . $form->getName() . $it . '][%s]‘);
What it really does? it generates the form fields like foo['forms_name1'] … so the only thing you have to do is grabbing the foo var from request and looping through to get the embedded forms.
Sure there are better ways, but this worked nice with a minimum ammount of time spent.
Hope it helps.

[rb]Custom doctrine count query

0

Sometimes you may need to use count with the index column rather than *, because of some dark corners of sql driven databases. Though this is somehow rare, this is how you could do it with Doctrine … this example is part of a symfony 1.4 project(place the file in any of the /lib dirs … app ones or global one):

<?php

class Custom_Doctrine_Query extends Doctrine_Query {

public static function create($conn = null, $class = null)
{
if ( ! $class) {
$class = 'Custom_Doctrine_Query';
}
return new $class($conn);

}

public function getCustomCountSqlQuery()
{
// triggers dql parsing/processing
$this->getSqlQuery(array(), false); // this is ugly

// initialize temporary variables
$where   = $this->_sqlParts['where'];
$having  = $this->_sqlParts['having'];
$groupby = $this->_sqlParts['groupby'];

$rootAlias = $this->getRootAlias();
$tableAlias = $this->getSqlTableAlias($rootAlias);
$primaryKey = $tableAlias . '.' .  $this->_queryComponents[$rootAlias]['table']->getColumnName( $this->_queryComponents[$rootAlias]['table']->getIdentifier());

// Build the query base
$q = 'SELECT COUNT(' .  $primaryKey . ') AS ' . $this->_conn->quoteIdentifier('num_results') . ' FROM ';

// Build the from clause
$from = $this->_buildSqlFromPart(true);

// Build the where clause
$where = ( ! empty($where)) ? ' WHERE ' . implode(' ', $where) : '';

// Build the group by clause
$groupby = ( ! empty($groupby)) ? ' GROUP BY ' . implode(', ', $groupby) : '';

// Build the having clause
$having = ( ! empty($having)) ? ' HAVING ' . implode(' AND ', $having) : '';

// Building the from clause and finishing query
if (count($this->_queryComponents) == 1 && empty($having)) {
$q .= $from . $where . $groupby . $having;
} else {
// Subselect fields will contain only the pk of root entity
$ta = $this->_conn->quoteIdentifier($tableAlias);

$map = $this->getRootDeclaration();
$idColumnNames = $map['table']->getIdentifierColumnNames();

$pkFields = $ta . '.' . implode(', ' . $ta . '.', $this->_conn->quoteMultipleIdentifier($idColumnNames));

// We need to do some magic in select fields if the query contain anything in having clause
$selectFields = $pkFields;

if ( ! empty($having)) {
// For each field defined in select clause
foreach ($this->_sqlParts['select'] as $field) {
// We only include aggregate expressions to count query
// This is needed because HAVING clause will use field aliases
if (strpos($field, '(') !== false) {
$selectFields .= ', ' . $field;
}
}
// Add having fields that got stripped out of select
preg_match_all('/`[a-z0-9_]+`\.`[a-z0-9_]+`/i', $having, $matches, PREG_PATTERN_ORDER);
if (count($matches[0]) > 0) {
$selectFields .= ', ' . implode(', ', array_unique($matches[0]));
}
}

// If we do not have a custom group by, apply the default one
if (empty($groupby)) {
$groupby = ' GROUP BY ' . $pkFields;
}

$q .= '(SELECT ' . $selectFields . ' FROM ' . $from . $where . $groupby . $having . ') '
. $this->_conn->quoteIdentifier('dctrn_count_query');
}

return $q;
}

public function count($params = array())
{
$q = $this->getCustomCountSqlQuery();
$params = $this->getCountQueryParams($params);
$params = $this->_conn->convertBooleans($params);

if ($this->_resultCache) {
$conn = $this->getConnection();
$cacheDriver = $this->getResultCacheDriver();
$hash = $this->getResultCacheHash($params).'_count';
$cached = ($this->_expireResultCache) ? false : $cacheDriver->fetch($hash);

if ($cached === false) {
// cache miss
$results = $this->getConnection()->fetchAll($q, $params);
$cacheDriver->save($hash, serialize($results), $this->getResultCacheLifeSpan());
} else {
$results = unserialize($cached);
}
} else {
$results = $this->getConnection()->fetchAll($q, $params);
}

if (count($results) > 1) {
$count = count($results);
} else {
if (isset($results[0])) {
$results[0] = array_change_key_case($results[0], CASE_LOWER);
$count = $results[0]['num_results'];
} else {
$count = 0;
}
}

return (int) $count;
}

}

The usage of the above class should be something like this:

$query = Custom_Doctrine_Query::create()->from('TargetTable t');
$count = $query->count();

or the bulky way omitting the static create method:

$query = Doctrine_Query::create(null, 'Custom_Doctrine_Query')->from('TargetTable t');
$count = $query->count();

The result of the above queries should be something like “SELECT COUNT(index_field) from target_table”.

WTH swiftmailer

0

Now it’s kindda obvious that swift mailer is the best php mail library, but as any other great php library it sometimes lets you right in the middle of nowhere, when you’re thinking everything should be fine. This was the case with a freshly downloaded version … everything went fine until Swift_KeyCache_KeyCacheInputStream interface not found in … to shorten the story … swift looks for that interface which is expected to be in the file KeyCache.php … the declaration seems to be missing from the downloaded package … the fix is pretty simple(though there is probably a good reason why it isn’t there anymore, but for a quick fix will do) … open /classes/Swift/KeyCache.php and add these lines:

interface Swift_KeyCache_KeyCacheInputStream extends Swift_InputByteStream
{

	public function setKeyCache(Swift_KeyCache $keyCache);

	public function setNsKey($nsKey);
	public function setItemKey($itemKey);
	public function setWriteThroughStream(Swift_InputByteStream $is);
	public function __clone();
}

save it … and you’re good to go.

[rb]symfony’s 1.4 sfForm isValid()

0

Someone asked me a few days ago how can he use the sfform validation feature to validate an object created “by hand”. While i’m not quite sure yet of the usage of such a thing, here’s my approach(we’ll assume we have a table called Selections with 4 fields like id(incremental/key/bigint), target_id(bigint), type(varchar), name(varchar)):

public function executeAdd(sfWebRequest $request) {
if($request->isXmlHttpRequest()) {

$this->setLayout(false);

$this->forward404Unless($id = $request->getParameter('id'));
$this->forward404Unless($type = $request->getParameter('type'));
$selection = new Selections();
$selection->setTargetId($id);
$selection->setType(ucfirst($type));
$selection->setName('DEFAULT');

$form = new SelectionsForm(null, array(), false);
$values = $selection->toArray();
$form->bind($values);

if($form->isValid()) { $form->save(); echo 'OK'; }
else {
echo 'ERROR';
}

return sfView::NONE;
} else $this->forward404();
}

[rb] Removing textframe linkage with applescript

0

You may sometimes need to be able to remove linkage between text frames in a particular document in Indesign. this script might come to the rescue:

tell application "Adobe InDesign CS2"
	set theObjs to selection

	if theObjs is equal to {} then
		set theObjs to every text frame of document 1
	end if
	tell document 1 to set thebaseframe to make new text frame

	repeat with tos in theObjs
		if (class of tos as string) = "text frame" then
			if end text frame of tos is not tos then
				set next text frame of tos to next text frame of thebaseframe
				set previous text frame of tos to previous text frame of thebaseframe
				set autoflow thread orphaned of tos to true
			end if
		end if
	end repeat
	tell document 1 to delete thebaseframe
end tell

Extending illustrator capabilities with applescript

0

While Illustrator offers a range of selection options that most of the time are enough for a particular scope, you might sometimes need to deal with a lot of stuff that come from other programs. This tiny script scrap might  come to the rescue in many occasions:

tell application "Adobe Illustrator"
	set sel to selection
	set target to item 1 of sel
	set cls to class of target

	set objs to every page item of document 1

	repeat with o in objs
		if (class of o is equal to cls) then
			set selected of o to true
		end if
	end repeat

end tell
Go to Top