List folder sub-routine sometimes returns strange list

Hey Guys

I have this sub-routine that results in a list that has a dot before the name of the second file


on ListFolder()
	set theLi to {}
	set theF to (choose folder with prompt "Choose folder to make list of:")
	tell application "Finder" to set theFlist to every file of folder theF
	tell application "Finder"
		repeat with img_path in theFlist
			set img_name to name of img_path
			set theLi's end to img_name & return
		end repeat
		log (class of theLi)
		set the clipboard to theLi as text
	end tell
	display dialog theLi as text --& return & RawCounter as text
end ListFolder

sometimes returns
1.txt
.2.txt
.3.txt

Not sure if its related but finder seems to be sluggish as well takes a while to show folders in the “choose Folder” dialog??

Thanks

Hi rapdigital,

Those files with periods in front of the name are invisible files the system uses. Change this line:

tell application "Finder" to set theFlist to every file of folder theF whose name does not begin with "."

Edited: but, I’ve never seen something like “.2.txt”, etc… Don’t know what’s happening with that. I was thinking that, those may be backup files from some application.

gl,
kel

You probably have AppleScript’s text item delimiters set to “.” at the time you coerce theLi to text.

Hi Nigel,

Good deduction.

gl,
kel

Nigel is most likely right about TIDs being the cause of this anomaly.

Keep in mind too that the Finder doesn’t return invisible files - e.g. files whose name begins with dot.

For the O.P. (rapdigital),

It’s very processing intensive (slow) to ask the Finder for Finder-references and then iterate through them for names.

It is always faster to get items as an alias list from the Finder, although there are times when using whose clauses when you cannot coerce to one.

When dealing with file names it can be more efficient to grab the target path and file-name-list separately depending upon what you’re doing of course.

An example:

set _collate to {}

tell application "Finder"
	set _target to target of front window
	set pathStr to _target as text
	set nameList to name of files of _target
end tell

repeat with i in nameList
	if (contents of i) starts with "Apple" then
		set end of _collate to alias (pathStr & i)
	end if
end repeat

_collate

This runs in ~ 0.8 seconds on my system with a target folder containing 2166 items.

Hi ccstone,

I couldn’t remember which one list homemade dot files. It must be System Events.

Later,
kel

Yep I have another sub -routine that sets ASTID to “.” and unsets them but I guess if the script errors it might keep them. Is there a way to force reset on an error. And I’m guessing this is unlikely to happen when running as an app?

What about the laggy finder when running scripts? Anyone else notice that? Its not just this script that does it.

Thanks guys

Yes. You can use a ‘try’ block to catch any possible errors while the TIDs are at a non-default value and either reset them in the ‘on error’ section or after the block, depending on what you’re doing.

When a script’s opened as an applet, it starts off with a clean slate TIDs-wise, so misplaced TIDs don’t cause a problem on the next run.

However, it’s a good policy always to set them explicitly before coercing a list to text.

set astid to AppleScript's text item delimiters
set AppleScript's text item delimiters to {""} -- The default, or "" will do.
set theText to theLi as text
set AppleScript's text item delimiters to astid

set the clipboard to theText
display dialog theText

Hi rapdigital,

Here’s an example for catching your error and resettings tids:

set the_text to "012345"
set tids to AppleScript's text item delimiters
set AppleScript's text item delimiters to {"123"}
try
	set text_item_list to text items of the_text
	set AppleScript's text item delimiters to {"abc"}
	set new_text to text_item_list as string
	set AppleScript's text item delimiters to tids
on error err_msg
	set AppleScript's text item delimiters to tids
	display dialog err_msg
end try
return new_text

I use this in a ReplaceText sub-routine.

Edited: note that this is not the exact subroutine. I usually use ‘error’ instead of ‘display dialog’.

gl,
kel

Here’s the subroutine:

set the_text to "012345"
ReplaceText(the_text, "123", "abc")
--
on ReplaceText(t, s, r)
	set tids to AppleScript's text item delimiters
	set AppleScript's text item delimiters to s
	try
		set temp_list to text items of t
		set AppleScript's text item delimiters to r
		set new_text to temp_list as string
		set AppleScript's text item delimiters to tids
	on error err_msg
		set AppleScript's text item delimiters to tids
		error err_msg
	end try
	return new_text
end ReplaceText

gl,
kel

Hi,

an error occurs only, if the class of the variable t in the subroutine is not text.
Rather than a try block check the class of the variable


on ReplaceText(t, s, r)
	if class of t is not text then return missing value
	set tids to text item delimiters
	set text item delimiters to s
	set temp_list to text items of t
	set text item delimiters to r
	set new_text to temp_list as string
	set text item delimiters to tids
	return new_text
end ReplaceText

AppleScript’s in front of text item delimiters is only needed in a tell block
like me in front of a handler call

Hello.

I believe this to be slightly faster, because some other testing I have done seemed to unequivocally prove so.

on ReplaceText(t, s, r)
	if class of t is not text then return missing value
	tell (a reference to text item delimiters)
		set tids to contents
		set contents to s
		set temp_list to text items of t
		set contents to r
		set new_text to temp_list as string
		set contents to tids
	end tell
	return new_text
end ReplaceText

Nigel said that Applet’s started off with a clean slate what text items concerned higher up in this thread. That makes me wonder, why is then that we can speed up an Applet by generating a new script environment by using a run script, which does the grunt inside the run handler?. Not saying that the one excludes the other. I personally think it is, because we then get rid of some “cocoa-references” into the script environment.

And now, the real diversion. :slight_smile: When having had applets put up on Finder’s toolbar, I as many before me, have experienced that you then have to not click once, but twice at times, when something the applet referenced was changed. Today I wanted to get into the bottom of this, and I wanted to log what was going wrong, so in inserted try - end try blocks with an on error → log statment. it turned out, that the mere try block was enough to alleviate the situation. :confused:

Hi Stefan,

I’ve always wondered what to do in this situation. I think it depends on what you want to happen. Most of the time I’d rather be warned that the wrong data was sent. With ‘missing value’, you still need to check what was returned from the subroutine to find a bug. This has always been a tricky one for me.

gl,
kel

Actually if you (the scripter) make sure that you pass always text to the subroutine no test is needed at all.

I agree with kel on this one, but you have to make sure that you indeed see the error message when you fail, which you won’t if you just error inside a script you are running, so to avoid overhead, it is better to react on the condition outside, maybe test for class before the handler is called. (In an ideal world. :slight_smile: )

Since now the text item delimiters are reset at each run, you’re right, we don’t need the error block unless the call to the handler (ReplaceText) is in an error block. :slight_smile:

Trying to think logically on Sunday is hard. :smiley:

Edited: because in the past, If the script errored, the tids weren’t reset. I remember in the beginning, working on a script for a whole day because the text item delimiters were messing up things on each run.

I think I started off by running a rename file script early in my scripting career, and the text item delimiter were set to a comma! :slight_smile: So that is one of the things I have been wary of all of the times.

Slightly related topic is cyclomacy: when having to deal with resetting such things after an error has occured, then it is rather convenient, to have one entry point, and one exit point to a routine, so that you can conveniently catch all the cases in one place when your script ends. This said on a general basis, and not directed to anybody in particular, me being one of the cardinal sinners.

Hi McUsr,

So what did those try/error blocks tell you about the double clicking the icon in the toolbar?

Edited: oops straying.

kel

Nothing! But the effect which I accidently discovered, was that when I from now on drop a script on the icon, so that it is placed into the folder under the Application support folder. Then I don’t have to click the icon twice, to activate the application anymore!

Now explain that! :smiley: