Log all open Preview documents and/or Open Preview documents in log

I’m not sure if this is the appropriate place for this question. The following Applescripts work as far as I can tell. I’m really just looking for suggestions to improve them.

The first script lists all currently open documents in the Preview app and writes the full path of those documents to a file.

set text item delimiters to "\n"
tell application "Preview"
	set theDocs to get path of every document as text
	tell application "Finder"
		set time_stamp to (do shell script "date \"+%m-%d-%y\"")
		set myFile to "/Users/path/to/file_" & time_stamp & ".txt"
		do shell script "echo " & quoted form of theDocs & " >> " & myFile
	end tell
end tell

This script reads the list of files created in the script above and prompts the user to choose which files to open.

tell application "Finder"
	set file_list to {}
	set my_files to paragraphs of (read "Users/path/to/file")
	repeat with nextLine in my_files
		if length of nextLine is greater than 0 then
			copy nextLine to the end of file_list
		end if
	end repeat
	choose from list file_list with multiple selections allowed
	set chosen_Files to the result
	repeat with next_file in chosen_Files
		do shell script "open " & next_file
	end repeat
end tell

I’m not very experienced with Applescript so I’m just looking for some constructive criticism on how these scripts could be improved. Should I use run handlers? Should I use try blocks? Anything you can think of I’d be ever so grateful. Thanks.

As I see no real need for using do shell script and/or Finder, I would use :

tell (current date) to set time_stamp to text -2 thru -1 of ((100 + (its month)) as text) & "-" & text -2 thru -1 of ((100 + (its day)) as text) & "-" & text -2 thru -1 of ((100 + (its year)) as text)

set myFile to ((path to desktop as text) & time_stamp & ".txt")
set text item delimiters to return
tell application "Preview"
	set theDocs to get path of every document
end tell

my writeto(myFile, theDocs as text, «class utf8», false)

#=====
(*
Handler borrowed to Regulus6633 - http://macscripter.net/viewtopic.php?id=36861
*)
on writeto(targetFile, theData, dataType, apendData)
	-- targetFile is the path to the file you want to write
	-- theData is the data you want in the file.
	-- dataType is the data type of theData and it can be text, list, record etc.
	-- apendData is true to append theData to the end of the current contents of the file or false to overwrite it
	try
		set targetFile to targetFile as «class furl»
		set openFile to open for access targetFile with write permission
		if not apendData then set eof of openFile to 0
		write theData to openFile starting at eof as dataType
		close access openFile
		return true
	on error
		try
			close access targetFile
		end try
		return false
	end try
end writeto

#=====

and

set theLog to choose file with prompt "Choose the log file" of type {"txt"} default location (path to desktop folder)
set my_files to paragraphs of (read theLog as «class utf8») # Added after Nigel comment
set file_list to {}
repeat with nextLine in my_files
	if (nextLine as text) is not "" then
		set end of file_list to nextLine
	end if
end repeat
set chosen_Files to choose from list file_list with multiple selections allowed

repeat with next_file in chosen_Files
	tell application "Preview" to open (next_file as «class furl»)
end repeat

Yvan KOENIG running Sierra 10.12.5 in French (VALLAURIS, France) mardi 16 mai 2017 16:38:01

Hi Sharkbone.

First script:

  1. Ideally, the text item delimiters should be set back to their default value after use, so that they don’t interfere with any other scripts run by the same application (or by the same script later on). Some scripters store the current delimiter value in a variable and restore the value to that afterwards. Others don’t bother and simply hard-set the value to “” or {“”} afterwards.
  2. For various reasons, it’s not a good idea to nest ‘tell’ statements addressed to different applications. And in fact there’s nothing in your Finder ‘tell’ statement which requires the use of either Preview or the Finder.
  3. There are other ways, some of them more efficient, of doing what your shell scripts do. But if your understanding of shell scripting’s better than your understanding of AppleScript, there’s nothing wrong with using them.
set astid to AppleScript's text item delimiters
set text item delimiters to return
tell application "Preview" to set theDocs to (get path of every document) as text
set AppleScript's text item delimiters to astid

set time_stamp to (do shell script "date \"+%m-%d-%y\"")
set myFile to "/Users/path/to/file_" & time_stamp & ".txt"
do shell script "echo " & quoted form of theDocs & " >> " & quoted form of myFile

Second script:

  1. Similarly, there’s nothing in the code which requires the use of the Finder.
  2. Unlike other dialogs, ‘choose from list’ returns ‘false’ if the Cancel button’s clicked, so you should make provision to catch that.
  3. The ‘open’ shell script can in fact open multiple files, so you could make things go a little faster by building a sequence of the paths and using ‘do shell script’ just once.
set file_list to {}
set my_files to paragraphs of (read "Users/path/to/file")
repeat with nextLine in my_files
	if length of nextLine is greater than 0 then
		set end of file_list to quoted form of nextLine
	end if
end repeat
choose from list file_list with multiple selections allowed
set chosen_Files to the result
if (chosen_Files is false) then error number -128 -- The "User canceled." error issued by other dialogs stop script execution.

set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to space
set chosen_Files to chosen_Files as text
set AppleScript's text item delimiters to astid

do shell script "open " & chosen_Files

I see Yvan’s also posted some good alternatives to the shell scripts.

Oh wow thank you both for the quick response. That handler look like some real professional quality applescript :slight_smile:

Every script has a run handler anyway, but it can be either explicit (with ‘on run’ and ‘end run’ ines) or implicit (without them). It’s usually a matter of personal taste which you use. The only difference between them that I can think of offhand is that the explicit type can be written to accept parameters passed to the script when it’s run, which isn’t needed here.

One thing to bear in mind with either type of run handler is that the variables used in it are “persistent” in the same way as globals or properties. The values they have when the script finishes are saved back into the script file, which can cause problems if the data are very bulky, such as with long or numerous lists or texts. It’s unlikely to be a problem here unless you have hundreds of documents open in Preview! If in doubt, you can set such variables to something low-bulk like “” just before the end of the script. Or you can declare them local before using them, in which case the variables simply cease to exist when the script exits and their values aren’t saved to the file. I personally prefer this latter approach as it annoys the hell out of me to have a script’s modification date change every time I use it! To save having loads of local declarations, I put the main action into an ordinary handler ” where all the variables are local anyway unless declared otherwise ” and just have the call to that handler in the ‘run’ handler:

-- on run
mainHandler()
-- end run

on mainHandler()

	-- Main action here instead of in the run handler.

end mainHandler

Nigel wrote me offlist that I failed to sepcify “as «class utf8»” in the instruction reading the file written using this encoding.
I don’t remember using this statement in my numerous scripts but Nigel IS right so I edited the script accordingly in message #2.

Yvan KOENIG running Sierra 10.12.5 in French (VALLAURIS, France) mercredi 17 mai 2017 14:40:25