Page 1 of 1

portability of (perl) macros

Posted: 2010-01-28 01:01:46
by phspaelti
I am trying to write a macro to transform a file. Since I would like this macro to have some degree of portability (i.e. be usable independent of Nisus Writer) I have chosen to write the macro in perl. This works fine for me since perl macros run in Nisus as well.

However the following issues have come up.

The basic structure of the macro is like this:

Code: Select all

#!/usr/bin/perl -w
…
while (<STDIN>) {
…
print $myOutput, "\n";
…
That is, I use a while-loop to read the data in, and print to return the output. This works fine except for one issue. To get this to work in Nisus I need to use "<STDIN>", but when I use Textwrangler I need to use the diamond operator ("<>") instead. Can anybody explain why there is this difference? Why doesn't the diamond operator work in Nisus? (or why doesn't STDIN work in Textwrangler?). Alternately is there any way to write this so it works in both without change?

And one more thing, is it possible to run such a macro on a file without using Nisus (or Textwrangler)? That is, can I run this directly on the mac? (in terminal?) Is it perhaps necessary (preferable?) to write some more specific input/output specifications. Again if this is necessary, is it possible to write it in such a way that the macro still works from within Nisus as well?

Any help appreciated.
Philip

Re: portability of (perl) macros

Posted: 2010-01-28 09:55:38
by martin
phspaelti wrote:To get this to work in Nisus I need to use "<STDIN>", but when I use Textwrangler I need to use the diamond operator ("<>") instead. Can anybody explain why there is this difference?
The angle bracket operator <> is a little weird. When given an explicit file handle (eg: "<STDIN>") the behavior is exactly as you would expect: a line is read and returned from that handle. However, if no file handle is given here's what happens:
Input from <> comes either from standard input, or from each file listed on the command line. Here's how it works: the first time <> is evaluated, the @ARGV array is checked, and if it is null, $ARGV[0] is set to ``-'', which when opened gives you standard input. The @ARGV array is then processed as a list of filenames.
(Taken from here because perl.org isn't responding right now)
Why doesn't the diamond operator work in Nisus? (or why doesn't STDIN work in Textwrangler?).
The empty angle brackets don't work in Nisus because the first argument given to a NWP perl macro is "NisusWriterInvoked", which is not a file path. Instead, NWP provides the selected document text through standard input, which is why one must use <STDIN> in Nisus perl macros.

I haven't used TextWrangler's macros, but presumably instead of providing text via STDIN, they write the text to disk first and then pass that file path to your macro. Either that, or they do not provide your macro with any arguments, and thus <> will default to STDIN.
Alternately is there any way to write this so it works in both without change?
You can test the value of the first argument ($ARGV[0]) to see if the macro was run by Nisus Writer. Here's a simple example:

Code: Select all

# decide from where to get input
my $inputHandle;
my $firstArg = $ARGV[0];
if( (! $firstArg) || ($firstArg eq 'NisusWriterInvoked') ) {
	$inputHandle = \*STDIN;
}
else {
	# use file path
	open(INPUT, $firstArg);
	$inputHandle = \*INPUT;
}

# process input
while( $line = <$inputHandle> ) {
	print "READ: $line";
}
print "\nDONE!\n";
And one more thing, is it possible to run such a macro on a file without using Nisus (or Textwrangler)? That is, can I run this directly on the mac? (in terminal?)
Absolutely. If you save the above code as "echo.pl" then you could run it any of the following ways:

Code: Select all

perl echo.pl		    	# interactive mode; read from STDIN as the user types
perl echo.pl < test.txt	 # dump contents of test file to STDIN
perl echo.pl test.txt		# provide file path as first argument

Re: portability of (perl) macros

Posted: 2010-01-29 01:11:42
by phspaelti
Thanks Martin.
I am slowly starting to figure this out.

best
Philip