Paper size macro?

Get help using and writing Nisus Writer Pro macros.
Post Reply
jb
Posts: 86
Joined: 2007-11-09 15:27:25

Paper size macro?

Post by jb » 2009-07-27 06:25:35

I have a few hundred rtf files with the paper size (in File -> Page Setup) set to something ridiculously small. I'd like to change all of these to US Letter.

Is it possible to put together a macro or applescript to do this so that I can avoid opening each one individually and making the changes manually?

Kino
Posts: 400
Joined: 2008-05-17 04:02:32

Re: Paper size macro?

Post by Kino » 2009-07-27 09:18:36

Hello again,

This macro seems to work. Gather those files in a folder, run the macro which will ask you to choose a folder. It will produce new files whose paper size set to US Letter.

To achieve it, the macro changes values of rtf directives. That is feasible because rtf is a kind of markup language like html. Not very readable, though.

Code: Select all

### Change Paper Size ###

# From rtf files in a folder, this macro generates new files with page size set to $width and $height.

# This macro does not change margins. So resulting files may not look good.

# Only files having "rtf" as file extension are processed.

# Generated files will be saved in the same folder as that of the source file, that of the original if it is a symlink or alias.

# Files for which converted file already exists will be ignored.

# If "Keep prior copy of each files using the file name suffixv is enabled in "Preferences - Saving", backup files will be ignored.

Require Pro Version 1.3

$suffix = ' (US Letter)'  # settings for US Letter
$width = 12240
$height = 15840

#$suffix = ' (A4)'  # settings for A4
#$width = 11900
#$height = 16840

#$suffix = ' (JB5)'  # settings for JB5
#$width = 10320
#$height = 14580


$defaultFolderPath = '~/Documents'
$openButtonCaption = 'Choose a Folder'
$folderPath = Choose Folder $defaultFolderPath, $openButtonCaption
if $folderPath == undefined
	exit  # cancelled by the user
end

$fileNames = File.namesInFolderAtPath $folderPath
$keepLastCopy = Read User Default 'com.nisus.backup.keepLastCopy'

if $keepLastCopy == true
	$lastCopySuffix = Read User Default 'com.nisus.backup.lastCopySuffix'
	$lastCopySuffix = '\Q' & $lastCopySuffix
	$lastCopySuffix &= '.\E[^.]+$'
	foreach $i, $fileName in reversed $fileNames
		if $fileName.find $lastCopySuffix, 'E-i'
			$fileNames.removeValueAtIndex $i
		end
	end
end

$errors = ''
foreach $fileName in $fileNames
	if $fileName.filePathExtension == 'rtf'
		$filePath = $folderPath.filePathByAppendingComponent $fileName
		$filePath = $newPath = File.resolveLinkAtPath $filePath
		$newPath.findAndReplace '(?=\.rtf)', $suffix, 'E'
		if File.existsAtPath $newPath
			$errors &= "File converted from $fileName already exists.\n"
		else
			$data = File.readDataFromPath $filePath
			$data = Cast to String $data
			$data.replaceAll '(?<=\x5Cpaperw|\x5Cpgwsxn)[0-9]+', $width, 'E-i'
			$data.replaceAll '(?<=\x5Cpaperh|\x5Cpghsxn)[0-9]+', $height, 'E-i'
			File.writeDataToPath $data, $newPath
		end
	end
end

File.revealPathInFinder $folderPath

if $errors
	exit $errors
end

### end of macro ###

jb
Posts: 86
Joined: 2007-11-09 15:27:25

Re: Paper size macro?

Post by jb » 2009-07-27 09:45:13

Thank you, Kino. This is fabulous.
I don't know how you manage to perform such minor miracles, and so quickly.

All I can say is Nisus don't pay you enough.

I've made just a small change so that the newly created file has a different 'suffix' added. Just personal taste. (For me this is serious programming :)

Thanks many times.

User avatar
martin
Official Nisus Person
Posts: 4251
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: Paper size macro?

Post by martin » 2009-07-27 10:52:48

Yes, Kino's macros and help are fantastic- we are very lucky to have such a dedicated user! :)

Interpreting RTF is tricky business, and there is one danger with the way Kino's macro is written. Although RTF may appear to be "plain text" codes, like HTML, it actually must be handled as a binary stream, as it is legal to embed arbitrary binary data inside (eg: an image). When Kino's macro converts the RTF to text and then resaves it, there is the possibility that binary data could be corrupted, depending. I would say the chances of this are quite slim, because most of the time the binary data feature of RTF is not used, but I wanted to mention it.

jb
Posts: 86
Joined: 2007-11-09 15:27:25

Re: Paper size macro?

Post by jb » 2009-07-27 12:21:23

Thanks for the tip, Martin.

I'm dealing with pure text files which have minimal formatting. So I take it the danger you mention is moot for me at the moment.

But are there examples of such "arbitrary binary data" other than images that one ought to watch out for?

Thanks

User avatar
martin
Official Nisus Person
Posts: 4251
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: Paper size macro?

Post by martin » 2009-07-27 15:12:51

In thinking about this a little more, there may not be any problem after all. Since the macro only modifies the "plain text" part of the RTF code, the binary data should remain intact.

While loading up the data directly via "readDataFromPath" and casting it to a string will interpret the data as UTF-8 or similar, saving it out should produce the same original data. I can't guarantee this, because we use Apple's text encoding services, but it should be a safe bet.

Kino
Posts: 400
Joined: 2008-05-17 04:02:32

Re: Paper size macro?

Post by Kino » 2009-07-28 02:30:18

Thank you, Martin, very much for the explanation. Unfortunately, the macro does not work with rtf files containing binary data. I tested it with an unzipped zrtf file (Release Notes.zrtf), for which Cast to String seems to return nothing. I'd like to have something like Cast to String $data, bytes (feature request ;-)

With ordinary rtf files, the macro does not have a problem, though. Images are stored in them as ASCII strings.

But I have not checked all kinds of objects and this may change in a future version of Nisus Writer Pro, for example, when it supports audio or movie (?). Thus, I modified the macro so that it uses Perl to change the values of the rtf directives.

Also, now you can define $folderNameSuffix and $fileNameSuffix. If you set $folderNameSuffix to something, converted files will be saved in a new folder (folder name + $folderNameSuffix) under the same parent directory. In that case, you can set $fileNameSuffix to nothing ($fileNameSuffix = '') so that the converted files have the same file names.

With $folderNameSuffix set to nothing ($folderNameSuffix = '') and $fileNameSuffix set to something (e.g. $fileNameSuffix = ' (US Letter)'), the macro works almost in the same way as the first version.

Code: Select all

### Change Paper Size ###

# From rtf files in a folder, this macro generates new files with page size set to $width and $height.

# The macro does not change margins. So resulting files may not look good.

# Only files in RTF format (rtf, nwm and non-binary doc) are processed.

# Converted files (file name + $fileNameSuffix) will be saved in a new folder (folder name + $folderNameSuffix) under the same parent directory. However, if you set $folderNameSuffix to nothing ($folderNameSuffix = ''), converted files will be saved in the source folder.

# If you set $fileNameSuffix to nothing ($fileNameSuffix = ''), the same file names will be used. In that case, you cannot set $folderNameSuffix to nothing.

# Files for which a converted file already exists will be skipped.

# If "Keep prior copy of each files using the file name suffixv is enabled in "Preferences - Saving", backup files will be ignored.

Require Pro Version 1.3

$folderNameSuffix = ' (US Letter)'  # settings for US Letter
$fileNameSuffix = ''
$width = 12240
$height = 15840

#$folderNameSuffix = ' (A4)'  # settings for A4
#$fileNameSuffix = '_A4'
#$width = 11900
#$height = 16840

#$folderNameSuffix = ' (JB5)'  # settings for JB5
#$fileNameSuffix = '_JB5'
#$width = 10320
#$height = 14580

if $folderNameSuffix == undefined
	if $fileNameSuffix == undefined
		exit 'You have to define $fileNameSuffix and $folderNameSuffix, one of them at least.'
	end
end


$defaultFolderPath = '~/Documents'
$openButtonCaption = 'Choose a Folder'
$folderPath = Choose Folder $defaultFolderPath, $openButtonCaption
if $folderPath == undefined
	exit  # cancelled by the user
end

$fileNames = File.namesInFolderAtPath $folderPath
$keepLastCopy = Read User Default 'com.nisus.backup.keepLastCopy'

if $keepLastCopy == true
	$lastCopySuffix = Read User Default 'com.nisus.backup.lastCopySuffix'
	$lastCopySuffix = '\Q' & $lastCopySuffix
	$lastCopySuffix &= '.\E[^.]+$'
end

$newPaths = Hash.new
$newFolder = $folderPath & $folderNameSuffix

foreach $fileName in $fileNames
	$notLastCopy = true
	if $keepLastCopy == true
		if $fileName.find $lastCopySuffix, 'E-i'
			$notLastCopy = false
		end
	end
	if $notLastCopy == true
		$filePath = $folderPath.filePathByAppendingComponent $fileName
		$filePath = File.resolveLinkAtPath $filePath
		$newPath = $newFolder.filePathByAppendingComponent $fileName
		$newPath.findAndReplace '(?=\.[^.]+$)', $fileNameSuffix, 'E'
		$newPaths{$filePath} = $newPath
	end
end

$errors = ''
Set Exported Perl Variables 'newPaths', 'newFolder', 'width', 'height', 'errors'
Set Include Perl UTF Preamble false

begin Perl
	foreach my $path (keys (%newPaths)) {
		my $newPath = $newPaths{$path};
		if ( -e $newPath ) {
			$errors .= "'$newPath' already exists.\n";
		} else {
			my $fileType = `/usr/bin/file -b --mime "$path"`;
			$fileType =~ s/[\n\r]+$//;
			if ( $fileType eq 'text/rtf' ) {
				if ( ! -f $newFolder ) {
					`mkdir -p "$newFolder"`;
				};
				open (IN, "<:bytes", $path);
				open (OUT, ">:bytes", $newPath);
				local undef $/;
				my $data = <IN>;
				$data =~ s/(?<=\x5Cpaperw|\x5Cpgwsxn)[0-9]+/$width/g;
				$data =~ s/(?<=\x5Cpaperh|\x5Cpghsxn)[0-9]+/$height/g;
				print OUT $data;
				close IN;
				close OUT;
			} else {
				$errors .= "'$path' is not an RTF file.\n";
			}
		}
	};
end

File.revealPathInFinder $newFolder

if $errors
	exit $errors
end

### end of macro ###

jb
Posts: 86
Joined: 2007-11-09 15:27:25

Re: Paper size macro?

Post by jb » 2009-07-28 10:10:09

Kino, you've anticipated my every wish.
If I thought it appropriate, i would have asked for this versatility. Fortunately, you got there first.

This is just the thing.

Thanks again.

User avatar
martin
Official Nisus Person
Posts: 4251
Joined: 2002-07-11 17:14:10
Location: San Diego, CA
Contact:

Re: Paper size macro?

Post by martin » 2009-07-28 10:30:02

Kino wrote:Thank you, Martin, very much for the explanation. Unfortunately, the macro does not work with rtf files containing binary data. I tested it with an unzipped zrtf file (Release Notes.zrtf), for which Cast to String seems to return nothing.
Offhand I would guess that the data in the file somehow produces an invalid Unicode string. For example, unmatched surrogate pairs may cause the whole conversion to fail.
But I have not checked all kinds of objects and this may change in a future version of Nisus Writer Pro, for example, when it supports audio or movie (?). Thus, I modified the macro so that it uses Perl to change the values of the rtf directives.
This would be the safest. Even things that one does not normally think of as binary data can be saved in odd ways in RTF. For example, list style formats often use low ASCII characters (like 0x01 and 0x02) as placeholders. This wouldn't be an issue for the UTF-8 conversion, but the point stands that RTF files must be treated as binary.

Post Reply