Handler to Determine IF Text Contains Item in List

lists
how-to

(Jim Underwood) #1

I had a need for this today, and could not find a solution in either my own library, or by extensive Internet searching, so I thought I’d share with everyone here my solution.

I hope that:

  • Others with find this useful
  • Maybe one of you smart gurus (like @NigelGarvey) might find some ways to improve on it. :smile:

Of course, I won’t be shocked if this already exists, I just couldn’t find it. :wink:

Handler

--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
on doesTextContainAnyListItem(pText, pList) -- @List @String @Search @Contains
  --–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
  (*  VER: 1.0    2017-12-23
    PURPOSE:  Determine if string (text) contains any item in the List
    PARAMETERS:
      • pText    |  text  | Text to search
      • pList    | list  | List of text items to search for
       
    RETURNS:  true    IF any item in the list was found in the text
              false   IF NOT
                
    AUTHOR:  JMichaelTX
  --–––––––––––––––––––––––––––––––––––––––––––––––––––––––––––––
  *)
  set foundItemBool to false
  repeat with aItem in pList
    if pText contains (contents of aItem) then
      set foundItemBool to true
      exit repeat
    end if
  end repeat
  return foundItemBool
end doesTextContainAnyListItem
--~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Here’s a real-world use case:

tell application "Finder" to set finderSelectionList to selection as alias list
if length of finderSelectionList = 0 then error "No files were selected in the Finder!"
set fileAlias to item 1 of finderSelectionList

set oFile to info for fileAlias
tell oFile
  set fileName to name
  set fileSize to size
  set fileKind to kind
end tell

set fileKindKWList to {"movie", "audio", "image", "video", "gif", "jpg", "png"}

set isKWFound to my doesTextContainAnyListItem(fileKind, fileKindKWList)
{fileKind, isKWFound}
-->{"MP3 audio", true}

BTW, as an aside, you might notice what is in common with my KW list – they are all audio/video/image media. Maybe I missed it, but I could not find any other common attribute/keyword that I could use. For example, a GIF file returns this:
kind: "Graphics Interchange Format (GIF)"
type identifier: "com.compuserve.gif"

Note the obviously missing keyword: “image”

So, if anyone should know how to identify any file that is either audio, video, or image, I’d love to know how.


(Shane Stanley) #2

I’m not sure if this is all that fast, but:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "AppKit"
use scripting additions

tell application "Finder" to set finderSelectionList to selection as alias list
if length of finderSelectionList = 0 then error "No files were selected in the Finder!"
set fileAlias to item 1 of finderSelectionList

tell current application's NSWorkspace's sharedWorkspace()
	set theUTI to its typeOfFile:(POSIX path of fileAlias) |error|:(missing value)
	return (its |type|:theUTI conformsToType:"public.movie") or (its |type|:theUTI conformsToType:"public.audio") or (its |type|:theUTI conformsToType:"public.image") or (its |type|:theUTI conformsToType:"com.adobe.pdf")
end tell

(Jim Underwood) #3

Thanks, Shane.

I like the form of your solution – it seems neater and more compact.
And, on a 10-run avg, it is the same speed as mine: 0.003 sec. (via Script Geek).

But the first time executed is a killer: 0.213 sec vs 0.014 sec.

I’ll definitely tuck your solution away for my use cases that are repetitive, but for many/most of my normal use cases, it is just needed for one run.


(Nigel Garvey) #4

Hi Jim.

Another way would be:

on doesTextContainAnyListItem(pText, pList) -- @List @String @Search @Contains
	set astid to AppleScript's text item delimiters
	set AppleScript's text item delimiters to pList
	set foundItemBool to ((count pText's text items) > 1)
	set AppleScript's text item delimiters to astid
	return foundItemBool
end doesTextContainAnyListItemNG

I wouldn’t say it’s any better than yours. Neither’s apparently faster on my machine until the handler calls are repeated 5000 times or so. :wink: And even then, it depends on the input. The repeat loop time is obviously influenced by whereabouts in fileKindKWList any match actually occurs. The text item count time depends on how many delimiters there are (how many items in fileKindKWList).

Asides:

info for, used in your real-world test, has been deprecated for a while now. The StandardAdditions dictionary says to tell System Events to get the item’s properties instead. I must admit, though, I still find info for handy for quick tests. :wink:

In days of yore, count used to have an optional each parameter which could be used instead of an ‘every’ reference:

(count pText each text item)

It still works, but I haven’t seen it mentioned anywhere for years, even to say it’s deprecated, so I presume it’s use is discouraged nowadays.


(Shane Stanley) #5

Ii’d be curious to know how you timed it. Because it of the way it’s constructed, there’s likely to be a bit of difference with, say, a movie file and with a file that fails all four tests.

OK, you sucked me in :slight_smile: I just did a quick test, and it takes around 0.004 sec here. But if I cut out all but the first statement addressed to the Finder, it still takes 0.003 seconds.

I wouldn’t pay that a lot of heed. That sounds like loading of frameworks, which is going to happen only once per host application (per launch), so unless this is the only script you run that calls uses Foundation and AppKit, it’s just noise for the first script you happen to run that uses ASObjC.


(Jim Underwood) #6

Nigel, thanks for sharing your solution. I would never have thought of it.

I don’t doubt your word that info for is deprecated, but how do we know which commands have been deprecated?

OK, I searched the ASLG for “deprecated”, and found 13 references, including these:

image

I could not find any reference to info for – ASLG being deprecated.

IAC, I have done extensive testing and find that info for is both easier to use and faster than System Events to get the properties of a file. I understand that it may be slower for folders with large numbers of files.

However, apparently this can be mitigated using size false:

Because getting the size of a folder requires getting the sizes of all the files inside it, size true may take a long time for large folders such as /System. If you do not need the size, ask to not get it using size false.

Also worth noting is that I found this statement in the ASLG section on info for to be incorrect:

Special Considerations
Because info for returns so much information, it can be slow, and because it only works on one file at a time, it can be difficult to use. The recommended technique is to use System Events or Finder to ask for the particular properties you want.

I have found that System Events reference to a file returns more properties than info for, so I don’t get the reference to “Because info for returns so much information”.
And I have found info for to be faster than System Events:

So, I don’t see any reason to not use info for for many use cases. For dealing with large numbers of files, I would probably use ASObjC.

If I have missed something about info for, then I’d ask you, @ShaneStanley, or anyone to please point it out. :wink:


Getting File/Folder Sizes: System Events vs Info For
(Jim Underwood) #7

I used your Script Geek tool.

First with a .mp4 file selected:

To your point, after the 1st run, the “First run time” is much faster:

Test with a .scpt file (not in my list):

(not really any material difference if file type is not in my list, or yours)

So, it seems to me that both methods are fine.


(Shane Stanley) #8

Look it up in the dictionary of Standard Additions:

This command is deprecated; use ‘tell application "System Events" to get the properties of …’.

I believe it was deprecated at the same time as list disks and list folder, so I’m not sure why it’s not mentioned in ASLG.


(Jim Underwood) #9

Thanks, Shane.

Is there a list somewhere of deprecated commands?

OK, so info for is deprecated. What is the real-world impact of that?
The fact that it has been deprecated for years suggests to me that Apple is not really doing anything about it – leaving it in place.

When is the last time that Apple actually removed an deprecated AppleScript command from the system?

And why not leave it in place? What’s the harm?

So, I understand the normal meaning:

Software deprecation

While a deprecated software feature remains in the software, its use may raise warning messages recommending alternative practices; deprecated status may also indicate the feature will be removed in the future. Features are deprecated rather than immediately removed, to provide backward compatibility, and to give programmers time to bring affected code into compliance with the new standard.


(Shane Stanley) #10

Speed-wise, certainly. As I mentioned, most of the time is taken by the part addressed to the Finder anyway. The only advantages of the ASObjC method are that it’s language independent, and it doesn’t rely on developers using particular words in their file descriptions. For example, a .ai file is an image file, but its kind is listed as Adobe Illustrator Document. Similarly for .psd.


(Shane Stanley) #11

Not that I know of – I think the dictionary is the canonical source.

At this stage, none.

My guess is what happened is this: Apple depreciated the underlying APIs that the commands are based on (probably older Carbon APIs), and rather than re-write the commands using new APIs, the AppleScript team decided that the functionality was duplicated by System Events, so they’d just deprecate the commands. If I’m correct, any decisions on when or if they stop working is out of the hands of the people working on AppleScript. And if/when it happens, we can’t say we weren’t warned.

Who knows? In some sense, I think there was more cause for caution in the releases immediately after it was deprecated, with the passage of time making the picture a bit clearer. However — and especially in the case of list disks and list folder — it’s entirely possible that some older Carbon APIs will be a casualty of the introduction of APFS. But that’s entirely speculation.


(Jim Underwood) #12

Excellent point – and I think that is the deciding factor for me.
So I switch to your ASObjC method.

Thanks again.


(Alberto González Ramírez) #13

Thanks everyone for this thread.
You can not imagine how slow pupils as me are learning with you.