Getting name of frontmost application

Hi everyone,

I did a search here and found a number of topics on this but none of them gave me exactly the result I wanted. What I’m looking for is an Applescript that will give me the name of the frontmost application. I’m using an application (menufela) that hides the menubar, which I like, but it makes it a tad annoying to figure out which app is frontmost, so I’m looking for a script to do it (i’d display the script with Geektool).

My search turned up this:

tell application "Finder" to ¬
	name of file (path to frontmost application as text)

The problem is it results in “the application name.app” Is there a way to remove the “.app” part from the result?

Sorry if this is a really dumb question… I’m a complete noob…:rolleyes:

Thank you for your help,
-Pascal

Try this, Pascal:


short name of (info for (path to frontmost application))


Excellent. That does exactly what I want. :slight_smile:
Edit:
Hmm… For most applications it works perfectly, but for some, like CandyBar it returns “missing value” I assume this is because CandyBar doesn’t have a short name for some reason. I thought maybe I could have the script use the regular name method (with the “.app”) if the result was “missing value” but what I tried doesn’t change anything…

set shortname to short name of (info for (path to frontmost application))

if shortname is "missing value" then
	set longname to name of (info for (path to frontmost application))
	set output to longname
else
	set output to shortname
end if

Any ideas on how to either fix this script or make a different one that works with Candybar?

Thanks!
-Pascal

Try this:

set N to name of (info for (alias "ACB-G5_1:Applications:Drawing:CandyBar:CandyBar.app:"))
set {d, text item delimiters} to {text item delimiters, "."}
set sN to first text item of N
set text item delimiters to d
sN --> CandyBar

There’s also:


tell application "System Events" to name of first process where it is frontmost


If you wanted to stick with frontmost application then, for most practical purposes, you could probably get away with:


text 1 thru -5 of name of (info for (path to frontmost application))


However, if you had reservations about that, then you might try something like this variation:


set {name:n, name extension:{length:l}} to info for (path to frontmost application)
tell l + 1 to n's text 1 thru -(1 mod it + it)


That one does the trick! :slight_smile:

Thanks again!
-Pascal

Ahhhh, pure genius!! 1 mod 1, I love it.

What else can go in the second level braces?

That’s interesting. Can someone explain how/what this one is doing? I see a lot of things there that I haven’t seen before? (I.E- the nameextension:{length:I}} and tell I + 1 to n’s text 1thru -(1 mod it + it))

Perhaps parsing it will help:

set _app to "ACB-G5_1:Applications:Internet:Camino.app"
set _info to (info for _app) -- get a record of 22 items
set {name:n} to _info
n --> "Camino.app"
set {name extension:ne} to _info
ne --> "app"
set {name extension:{length:l}} to _info
l --> 3
-- which is the same as:
set {length:l} to ne
l --> 3
tell l + 1 to set b to -(1 mod it + it)
b --> -5
set bn to text 1 thru b of n
bn --> "Camino"
-- and by the way
set mm to 1 mod (l + 1)
mm --> 1

I know what he’s doing, pure grenius btw, but I wouldn’t have come up with it myself and woudl have an equally hard time explaining how exactly he came up with the last part of it… perhaps Kai or Adam can enlighten us all =)

This works too (with or without extension):

set {name:n, name extension:e} to (info for (choose file)) -- (or path to frontmost application)
set baseName to n's text 1 thru ((my (offset of ("." & e) in n)) - 1)

I get the “tell l+1” part - really clever.

I am still trying to figure out why the “name extension:{length:l}” part works. If this is the property “length”, it doesn’t seem to follow the syntax “length of x”; and if it is supposed to be an element of the “name extension” element in the record returned from “info for”, it doesn’t appear in the record.

Also, trying to code {name extension:{class:c}} errors, so it does not appear to be a way to get every property. “class of name extension” returns “Unicode Text” as expected though.

“length” doesn’t appear in the “file information” dictionary entry either.

I want to hear what other functions or properties I can put in there!

I know the end result here, but am having trouble actual break it down… care to elaborate on whats acctally happening.

I think it’s the ‘mod’ part that confuses folks. Consider this:

1 mod (any positive number > 1) = 1, but 1 mod 1 = 0, so 1 mod 2 + 2 = 3, but 1 mod 1 + 1 = 1

If the name doesn’t have an extension, it doesn’t have a period either, so with no extension we want text 1 thru -1 of the name, i.e. beginning thru end, but with an extension we want to back off length of the extension + 1, i.e. text 1 thru -(length of extension + 1)

Using mod this way does that, because we are starting with “it” being (length + 1) so if length is 0 (or missing value), 1 mod 1 is 0

Extremely clever, of course (as Kai often is). Mod and div are powerful weapons - I encourage you to play with them.

In my solution (repeated below), I have to accomplish the same thing by incorporating the “.” in the offset statement. Offset returns 0 if the sub-string isn’t found, so I’m left with the right distance to go forward for the second limit if there is an extension, going to -1 if not, but the offset with concatination is significantly more time-consuming than Kai’s solution.

set {name:n, name extension:e} to (info for (choose file)) -- (or path to frontmost application)
set baseName to n's text 1 thru ((my (offset of ("." & e) in n)) - 1)

Note change in sign above

Hi guys. Sorry I wasn’t around at the time to enjoy this discussion (didn’t realise that the code would attract quite so much interest). However, perhaps I can still throw in my 2¢ on the subject. Apologies in advance for the length of this…

Let’s first take a quick look at the ways in which we could extract properties from a record or object (for the sake of anyone who isn’t already aware of them).

Probably the most common method is to extract each property individually:

set i to info for (path to documents folder) without size
set n to i's name
set k to i's kind
display alert "The name of the " & k & " is \"" & n & "\"."

Another way is to specify the required properties using a list:

set {n, k} to {name, kind} of (info for (path to applications folder) without size)
display alert "The name of the " & k & " is \"" & n & "\"."

Yet another approach is to use a record to extract the values:

set {name:n, kind:k} to info for (path to music folder) without size
display alert "The name of the " & k & " is \"" & n & "\"."

The length property here refers to the (Unicode) text of the name extension property. Normally, when dealing with external objects, we might determine this in a couple of hits ” the first to get the text value, the second to get its length:

tell application "Finder"
    set {n, e} to {name, name extension} of (choose file)
    set l to length of e
    display alert "File name: " & n message "Length of name extension: " & l
end tell

(With this form, the count command could be used as an alternative to the length property ” although, in the context of this discussion, that’s rather by the way. Also, Finder is used here in preference to the info for command since, if a file has no name extension, the latter may return a class of ‘missing value’ ” rather than the more sensible empty string.)

As we’ve seen, by using nested records, we could extract both values in a single statement:

tell application "Finder"
    set {name:n, name extension:{length:l}} to choose file
    display alert "File name: " & n message "Length of name extension: " & l
end tell

Pretty much any property that exists at a subsequent level. The technique isn’t necessarily restricted to just a couple of levels, either:

tell application "Finder"
    activate
    open (path to pictures folder) (* just to give us a demo window *)
    set {class:c1, name:n1, target:{class:c2, name:n2, container:{class:c3, name:n3, container:{class:c4, name:n4, container:{class:c5, name:n5}}}}} to Finder window 1
    display alert "Front Window:" message (c1 as string) & " \"" & n1 & "\" of " & c2 & " \"" & n2 & "\"" & " of " & c3 & " \"" & n3 & "\"" & " of " & c4 & " \"" & n4 & "\"" & " of " & c5 & " \"" & n5 & "\"."
end tell

Finder has some more useful examples of nested properties, too:

tell application "Finder" to tell Finder window 1
    if not (exists) then return display alert "No Finder windows open" message "Please open any folder and try again."
    set {name:n, sidebar width:b, statusbar visible:v, list view options:{icon size:i, calculates folder sizes:c, uses relative dates:r, sort column:{name:s, width:w, sort direction:d}}} to it
    display alert "Example of nested Finder window properties:" message "FINDER WINDOW:
    name: " & n & "
    sidebar width: " & b & "
    statusbar visible: " & v & "
    
    LIST VIEW OPTIONS:
        icon size: " & i & "
        calculates folder sizes: " & c & "
        uses relative dates: " & r & "
    
        SORT COLUMN:
            name: " & s & "
            width: " & w & "
            sort direction: " & d
end tell

While applications like Finder and System Events return a full evaluation of the required properties with this technique, the file information returned from info for evidently doesn’t:

set some_file to choose file without invisibles
try
    set {name extension:{class:info_for_class}} to info for some_file
on error err_msg
    set info_for_class to "[error] " & err_msg
end try
try
    tell application "System Events" to set {name extension:{class:SysEvents_class}} to some_file
on error err_msg
    set SysEvents_class to "[error] " & err_msg
end try
try
    tell application "Finder" to set {name extension:{class:Finder_class}} to some_file
on error err_msg
    set Finder_class to "[error] " & err_msg
end try
display alert "Class of name extension results:" message "info for: " & info_for_class & return & return & "System Events: " & SysEvents_class & return & return & "Finder: " & Finder_class

However, an evaluation can be invoked by either first setting a variable to the file information record, using an explicit get statement ” or making the info for call the target of a tell statement…

setting a variable:

set some_variable to (info for (choose file without invisibles))
set {name extension:{class:c}} to some_variable
display alert "Class of name extension: " & c

using an explicit get statement:

set {name extension:{class:c}} to get info for (choose file without invisibles)
display alert "Class of name extension: " & c

using a tell statement:

tell (info for (choose file without invisibles)) to set {name extension:{class:c}} to it
display alert "Class of name extension: " & c

Right. In this context, length is actually the property of the resulting AppleScript text object, rather than a direct property of the returned file information.

In AppleScript, value classes fall basically into 2 categories: simple values (such as integers and real numbers) ” which contain no other values, and composite values (such as lists and records) ” which do. Some value classes (such as lists, records, strings [plain, styled or international text] and Unicode text) have a length property. Some may have other properties, such as contents (for a reference).

Date values, of course, have a range of properties ” such as day, weekday, month, year, time, date string and time string ” which can also be extracted using nested records:

set {name:n, kind:k, creation date:{date string:d, time string:t}} to info for (choose file)
display alert k & ": " & n message "The " & k & " was created on " & d & " at " & t & "."

And here’s how a couple of AppleScript’s list properties, rest and reverse, might be used to extract the width and height dimensions of the desktop:

tell application "Finder"
    set {bounds:{rest:{rest:{w, h}}}} to desktop's window
    display alert "Desktop dimensions:" message "Width:" & tab & w & return & "Height:" & tab & h
end tell

tell application "Finder"
    set {bounds:{reverse:{h, w}}} to desktop's window
    display alert "Desktop dimensions:" message "Width:" & tab & w & return & "Height:" & tab & h
end tell

In case there are still any lingering doubts, let’s just try to clarify further a couple of the techniques used here…

The first possible cause of confusion might be the particular use here of a tell statement. Tell statements specify the default target for any other statements they contain, and AppleScript defines the variable it as a reference to that target. In more conventional cases, the target will be an application or application object. However, in this instance, it’s the result of a calculation: l + 1.

The other potential source of uncertainty might be, as already mentioned, the use of the mod function ” which is simply a binary arithmetic operator that divides the number to its left by the number to its right, and returns the remainder.

As Adam explained, the trick here is to produce 2 different types of result. If the length (l) of the name extension is 0, we need the ‘cut-off character’ to be -1 (so the resulting text will be “xxx”'s text 1 thru -1). In every other instance, it should be the equivalent of -[l + 2] (so that, if the value of l is, say, 3 ” then we’ll get “xxx.abc”'s text 1 thru -5).

We can’t use l’s value directly with mod since, if it’s 0, the calculation will error. So we add 1 to l first (hence the expression ‘tell l + 1…’). Then we can refer to the result of that, using the variable ‘it’, to perform the rest of the calculation.

To help illustrate how this works over a range of different extension lengths, the following script summarises the calculations ” as well as detailing some of the evaluations involved:

property extn_list : {"", "a", "ab", "abc", "abcd", "abcde"}
property list_count : count extn_list

tell tab & tab to set {result_list, col_pad, tab2, tab3} to {{}, it, it, it & tab}

repeat with extn in extn_list
    set l to length of extn
    
    if l > 0 then
        set extn to "." & extn
        if l is 4 then set col_pad to tab
    end if
    
    set long_name to "xxx" & extn
    tell l + 1 to set cut_off to -(1 mod it + it)
    set result_list's end to "\"" & long_name & "\"" & col_pad & l & tab3 & cut_off & tab2 & "\"" & long_name's text 1 thru cut_off & "\""
end repeat

set {tid, text item delimiters} to {text item delimiters, return & return}
set {result_list, text item delimiters} to {result_list as string, tid}

display alert "long" & tab & "length of" & tab & "cut-off" & tab2 & "short" & tab & return & "name" & tab & "extension" & tab & "character" & tab & "name" & tab message result_list buttons {"Done", "Show Detail."} cancel button 1
end

set {dir_button, curr_item, e, c, r} to {">", 1, return & "-->" & tab, return & return & tab, return & tab & "”””"}

repeat
    set extn to extn_list's item curr_item
    set l to length of extn
    if l > 0 then set extn to "." & extn
    set n to "xxx" & extn
    set s to l + 1
    set m to 1 mod s
    set p to m + s
    
    set dir_button to button returned of (display alert tab & "long file name:" & tab2 & "n = \"" & n & "\"" & return & tab & "extension length:" & tab & " l = " & l message return & tab & "tell l + 1 to n's text 1 thru -(1 mod it + it)" & c & "l = " & l & e & "tell " & l & " + 1 to n's text 1 thru -(1 mod it + it)" & c & l & " + 1 = " & s & e & "tell " & s & " to n's text 1 thru -(1 mod it + it)" & c & "it = target of tell statement = " & s & e & "n's text 1 thru -(1 mod " & s & " + " & s & ")" & c & "1 mod " & s & " = " & m & e & "n's text 1 thru -(" & m & " + " & s & ")" & c & "-(" & m & " + " & s & ") = -" & p & e & "n's text 1 thru -" & p & c & " n = \"" & n & "\"" & e & "\"" & n & "\"'s text 1 thru -" & p & return & r & e & "\"" & n's text 1 thru -p & "\"" & r buttons {"Done", "<", ">"} cancel button 1 default button dir_button)
    
    if dir_button is ">" then
        set curr_item to curr_item mod list_count + 1
    else
        set curr_item to (curr_item + list_count - 2) mod list_count + 1
    end if
end repeat

(Incidentally, at the end of the above script, there’s another example of the mod operator ” used this time to produce a ‘perpetual’ dialog loop.)

Bear in mind, too, that it’s generally safer to count back from the end of a name, since some filenames may contain more than one stop/period character. The following routine might show a few examples of what I mean:

set l to (list folder (path to preferences folder)) & (list folder (path to preferences folder from local domain))
set {d, text item delimiters} to {text item delimiters, "."}
repeat with i from 1 to count l
    if (count text items of my l's item i) < 3 then set my l's item i to false
end repeat
set text item delimiters to d
every Unicode text of l

I’m always grateful for how much information you provide.

Thanks.

j

I studied every example and I am filing this away in my Reference folder.

Thanks so much. I learned more from one post than from whole books I have bought.

Wonderful as always, Kai. I particularly admire the continuing (but endless ring) dialog in either direction. Tres elegant.

In my offset solution, I avoid the several full-stop problem by concatinating the period with the extension so unless the extension appears twice: myFile.ext.ext, I won’t be fooled with the offset of “.” & ext. Nonetheless, as I said, yours is the more elegant and efficient way to go.

Now the pitch, Kai: a cogent, example-filled explanation like yours of yesterday in this thread deserves a broader showing than it will get in a thread not everyone followed. With a bit of a header section, it would make a perfect addition to the MacScripter cover and would be archived after its one-week run in unScripted. Can I persuade you?

Or even something like: myFile.extras.ext. Seems unlikely, Adam ” but I’ll let you know if I ever come across an example… :wink:

If you think it suitable then, of course, I’d be more than happy to oblige. :slight_smile:

Something like: Extracting Properties from AppleScript Records & Objects? It would be a valued addition.

Adam