Tuesday, September 27, 2022

#1 2022-06-05 12:47:25 am

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Using Frontmost Application?

Hi folks.

I'm designing a script for Launchbar, which should copy the currently selected text, do something like substitute characters within that text (this is done in Ruby), then paste that text back where the original focus was. 

Example 1: Finder file filename is Plugable-ud-ultc4k-triple-4k-display-dock-ports_thumb800-2877640892.jpg and I want to change the dashes to proper spaces. 

In this instance, the app is the Finder igself.  But I want this script to sniff out what app I'm in, save that in a variable, do the text manipulation (Ruby), then go back to that same app and replace the text. BBEdit is where I live and I often just use these scripts there, but I'd like to extend this to any app.  Or hope to do so.  I can see some limitations as I have to activate the editing of the filename for the Finder to work.  All the same, it saves a lot of frustrating filename edits. 

Here is what I have for BBEdit so far, which works on a library of edits:

def osascript(script) = system 'osascript', *script.split(/\n/).map { |line| ['-e', line] }.flatten
mys=<<-TEXT
tell application "BBEdit" to set the clipboard to (selection as text)
TEXT
osascript(mys)

Clipboard.copy(Clipboard.paste.gsub('-', ' '))

mys=<<-TEXT
tell application "System Events" to keystroke "v" using command down
TEXT
osascript(mys)

The issue I have is with the return of the modified text to the original app. 

Applescript:

tell application "<original app>" to keystroke "v" using command down

Will that variable work in there?


Filed under: variable, frontmost app

Offline

 

#2 2022-06-05 06:30:58 am

alastor933
Member
From:: Utrecht, NL
Registered: 2008-09-12
Posts: 615

Re: Using Frontmost Application?

A Script Menu script I have does it like so:

Applescript:

tell application id "sevs" to set appFront to name of first process whose frontmost is true
-- <snip>
tell application id "sevs"
   tell process appFront
       keystroke "your text here"
   end tell
end tell

Offline

 

#3 2022-06-05 06:44:59 am

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Re: Using Frontmost Application?

Further investigation has me using this, which works in the Script Editor:

Applescript:

tell application "System Events" to set frontApp to name of first application process whose frontmost is true

However, when launched from Launchbar, that focus disappears.  So I can't even get to recognizing the text, because the script has no app reference.

Not sure how to get around this.  But ya, your fist line is the same as mine.

Offline

 

#4 2022-06-05 12:24:37 pm

KniazidisR
Member
From:: Greece
Registered: 2019-03-03
Posts: 2524

Re: Using Frontmost Application?

@dabee,

I would create Automator Quick Action (service), which receives: Text, from application: Any. Then I would assign system-wide shortcut in the System Preferences to this service.

When executing compiled script, current application (and frontmost) is editor. When executing script saved as application, current application (and frontmost) is script app. So, if you still prefer the usual script (or script app), then you should hide the current application to get other front process.

Applescript:


set thisAppName to name of current application

tell application "System Events"
   set visible of process thisAppName to false
   set frontApp to name of first application process whose frontmost is true
end tell

NOTE: all keystrokes goes to front window (of frontmost process) telling only to System Events.app. So, telling some other app to keystroke doesn't make any sense.

To test my suggestion, I created text in the TextEdit.app, then selected one piece of this text. Following script successfully replaces the selected piece of text with "Hello":

Applescript:


set thisAppName to name of current application

tell application "System Events"
   set visible of process thisAppName to false
   set frontApp to name of first application process whose frontmost is true
   keystroke "Hello"
end tell

Last edited by KniazidisR (2022-06-05 12:56:20 pm)


Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB

Offline

 

#5 2022-06-05 02:00:29 pm

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Re: Using Frontmost Application?

The keystrokes are about taking focus in the front app, then copying and pasting of modified text.  I've used keystrokes (like copy and paste) in other apps all the time.

I'm not trying to replace it with static text.  I need Ruby to modify the text accordingly.  This doesn't bring in that at all.  I have no need to replace text with "Hello". 

As I said in the original post. I'm trying to modify the text that's selected. 

Plugable-ud-ultc4k-triple-4k-Port.jpg => Plugable ud ultc4k triple 4k Ports.jpg

Offline

 

#6 2022-06-05 10:16:49 pm

KniazidisR
Member
From:: Greece
Registered: 2019-03-03
Posts: 2524

Re: Using Frontmost Application?

I don't force you to send "Hello". This is just an example, isn't it obvious to you? You can send another keystroke, and somewhere in the middle of the actual script, Ruby has to modify the contents of the clipboard. My script simply demonstrates how to work with the right front process.

The copy and paste you use all time in other apps is commands of this other apps. And the keystroke command belongs only to System Events.app

Last edited by KniazidisR (2022-06-05 10:21:09 pm)


Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB

Offline

 

#7 2022-06-06 03:20:50 am

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Re: Using Frontmost Application?

The issue with your approach is that you said to make something in AutomatorTHIS is what takes Ruby out of the equation.  An Automator Quick Action in Launchbar means the script itself is run.  As standalone.  So there is no governing script that integrates Ruby at all.  A master governing Ruby script can implement AppleScript through the syntax that I posted.

I see what you did by shoving the (either Launchbar or Automator Quick Action) focus aside, leaving the second-in-line app (the editor) having focus.  Unfortunately this didn't do the trick either.  The problem is that this isn't about visibility.  You're still living in an AppleScript world with that instruction.  All this should be able to run in the background, as Launchbar disappears after you select an Action.  This is why I'm choosing Ruby to use AppleScripts to bounce around, as the master controller.  You know that AppleScript can instruct an application to accomplish something without having it visible or active. 

Here is the script and the error:

Applescript:

require 'clipboard'
def osascript(script) = system 'osascript', *script.split(/\n/).map { |line| ['-e', line] }.flatten

# mys=<<-TEXT
# tell application "System Events" to keystroke "c" using command down
# TEXT

mys=<<-TEXT
set thisAppName to name of current application
tell application "System Events"
set visible of process thisAppName to false
set the clipboard to the name of first application process whose frontmost is true
end tell
TEXT
osascript(mys)

r = ''
text = Clipboard.paste
text.strip.split("\n").each do |i|
begin
stuff = i.strip.split(/\s*:\s*/)
r += stuff.first.strip.rjust(find_largest_key(text)+5) + " : " + stuff[1].strip + "\n"
rescue
r += i
end
end

Clipboard.copy(r)

mys=<<-TEXT
tell application "System Events" to keystroke "v" using command down
TEXT
osascript(mys)

RF spacecase (com.viaduct.LaunchBar.action.RFspacecase): Script Error: 
58:62: execution error: Can’t make selection of application "" into type text. (-1700)

I think at this point, I simply need to get that app into the clipboard and reduce the rest of the functionality, to keep this simple.

require 'clipboard'
def osascript(script) = system 'osascript', *script.split(/\n/).map { |line| ['-e', line] }.flatten
r = ''

mys=<<-TEXT
tell application "System Events" to set the clipboard to name of first application process whose frontmost is true
TEXT
osascript(mys)

origapp = Clipboard.paste
r += "origapp: #{ origapp }\n"

mys = "tell application \"#{ origapp }\" to set the clipboard to (selection as text)"
r += "mys: #{ mys }\n"
osascript(mys)

Clipboard.copy(r)

mys=<<-TEXT
tell application "BBEdit" to activate
tell application "System Events" to keystroke "v" using command down
TEXT
osascript(mys)

Offline

 

#8 2022-06-06 04:53:30 am

KniazidisR
Member
From:: Greece
Registered: 2019-03-03
Posts: 2524

Re: Using Frontmost Application?

Unfortunately, I don't understand anything about Ruby.

The only thing I can say is that the description of the error tells you not to try to use the reserved word text (which is the name of the class, otherwise the name of the type) as a variable.

The error should be here:

text = Clipboard.paste

Last edited by KniazidisR (2022-06-06 04:55:42 am)


Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB

Offline

 

#9 2022-06-06 05:36:10 am

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Re: Using Frontmost Application?

Ya I've tried different things in that area.  The issue is that I still can't get the frontmost app, outside of any text manipulation.

Offline

 

#10 2022-06-06 10:22:39 am

estockly
Member
Registered: 2009-01-03
Posts: 128

Re: Using Frontmost Application?

daBee wrote:


tell application "System Events" to keystroke "v" using command down



I think here you need to send the keystroke to the target process:

Something like

Applescript:

set myProcess to first application process whose frontmost is true
set the clipboard to the name of myProccess

--<SNIP>--

tell application "System Events" to tell myProcess to keystroke "v" using command down

Last edited by estockly (2022-06-06 10:37:19 am)

Offline

 

#11 2022-06-06 10:32:28 am

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Re: Using Frontmost Application?

Ya I thought as much.  Problem is, myProcess is never defined.  It won't capture what I consider "my current app".

Offline

 

#12 2022-06-06 10:43:38 am

estockly
Member
Registered: 2009-01-03
Posts: 128

Re: Using Frontmost Application?

daBee wrote:

Ya I thought as much.  Problem is, myProcess is never defined.  It won't capture what I consider "my current app".



The first part of what I posted defines myProcess.

As I understand it your current app is behind LaunchBar when executed. When you set the visible of LaunchBar to false, that makes your current app frontmost. Next, set the variable myProcess to that process and then direct your UI commands to that process within System Events.

Or am I missing something?

Offline

 

#13 2022-06-06 12:24:23 pm

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Re: Using Frontmost Application?

Yes.  It doesn't work.

Offline

 

#14 2022-06-06 03:36:28 pm

estockly
Member
Registered: 2009-01-03
Posts: 128

Re: Using Frontmost Application?

OK, I can't help with any of your Ruby stuff, so I've commented that all out, and this is just the appleScript stuff.

What I think is happening is that because your appleScripts segments are not part of the same script they are not sharing variables, so the variable myProcess, defined in the first appleScript segment is not defined in the second.

But, there's a conflict in your script. When you do a command-c you're setting the same clipboard that the "set the clipboard to" command does, so that overwrites the value the script copies with command-c.

The solution is to define myProcess again. This should work because that app should still be frontmost.

I tried this with a few different apps (including BBEdit) and it worked (but without the Ruby stuff)

Applescript:


--require 'clipboard'
--def osascript(script) = system 'osascript', *script.split(/\n/).map { |line| ['-e', line] }.flatten
--
--# mys=<<-TEXT
----# tell application "System Events" to keystroke "c" using command down--<<This line conflicts with the clipboard command, and there's no need to have this script segment at all
--# TEXT
--
--mys=<<-TEXT
set thisAppName to name of current application
tell application "System Events"
   set visible of process thisAppName to false
   set myProcess to first application process whose frontmost is true
   --set processName to (the name of myProcess)
   tell myProcess
       keystroke "c" using command down
   end tell
   log (the clipboard)
   
end tell
--set the clipboard to processName--<<This line conflicts with the keystroke command and there's no need for it now either.
log (the clipboard)

--TEXT
--osascript(mys)
--
--r = ''
--text = Clipboard.paste
--text.strip.split("\n").each do |i|
-- begin
-- stuff = i.strip.split(/\s*:\s*/)
-- r += stuff.first.strip.rjust(find_largest_key(text)+5) + " : " + stuff[1].strip + "\n"
-- rescue
-- r += i
-- end
--end
--
--Clipboard.copy(r)
--
--mys=<<-TEXT
tell application "System Events"
   log (the clipboard)
   set myProcess to first application process whose frontmost is true
   tell myProcess
       keystroke "v" using command down
   end tell
end tell

--osascript(mys)



If this doesn't work you'll need to find a way to move variables from AppleScript to Ruby and from Ruby to AppleScript.

Hope that helps.

Last edited by estockly (2022-06-06 03:46:39 pm)

Offline

 

#15 2022-06-07 10:02:28 am

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Re: Using Frontmost Application?

Excellent.  THIS works. 

Not sure what log (the clipboard) means.  Any chance you can elaborate on that quickly?

Here's the final script:

require 'clipboard'
def osascript(script) = system 'osascript', *script.split(/\n/).map { |line| ['-e', line] }.flatten

mys=<<-TEXT
set thisAppName to name of current application
tell application "System Events"
	set visible of process thisAppName to false
	set myProcess to first application process whose frontmost is true
	tell myProcess
		keystroke "c" using command down
	end tell
end tell
TEXT
osascript(mys)

Clipboard.copy(Clipboard.paste.gsub('-', ' '))

mys=<<-TEXT
tell application "System Events"
	set myProcess to first application process whose frontmost is true
	tell myProcess
		keystroke "v" using command down
	end tell
end tell
TEXT
osascript(mys)

Offline

 

#16 2022-06-07 10:21:58 am

KniazidisR
Member
From:: Greece
Registered: 2019-03-03
Posts: 2524

Re: Using Frontmost Application?

As I see it, the correct solution is using my suggestion of process visibility. Let me remind you that @daBee answered me literally the following:

"I see what you did by shoving the (either Launchbar or Automator Quick Action) focus aside, leaving the second-in-line app (the editor) having focus. Unfortunately this didn't do the trick either. The problem is that this isn't about visibility."

Also, I remind you that the keystroke commands belong to the System Events application itself. Therefore, processes do not need to be told.

mys=<<-TEXT
tell application "System Events" to keystroke "v" using command down
TEXT
osascript(mys)


The same with keystroke "c"

mys=<<-TEXT
set thisAppName to name of current application
tell application "System Events"
    set visible of process thisAppName to false
    set myProcess to first application process whose frontmost is true
    keystroke "c" using command down
end tell
TEXT
osascript(mys)

Last edited by KniazidisR (2022-06-07 10:40:48 am)


Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB

Offline

 

#17 2022-06-07 10:34:47 am

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Re: Using Frontmost Application?

Well, then visibility would have told me that the current focus on activating the LaunchBar script, would be something as frontmost application, which didn't occur.  It returned nil result.  Automator further shields any interaction.  Automator I would only use for direct applications, however packaged. 

In any case, I'm happy it works now, which is the goal.  Having to push aside an empty focus, is an AS issue.  Other implementations using LaunchBar, is straight forward.  Managing operations in specific applications is predictable.

Offline

 

#18 2022-06-07 02:15:12 pm

estockly
Member
Registered: 2009-01-03
Posts: 128

Re: Using Frontmost Application?

daBee wrote:

Excellent.  THIS works. 

Not sure what log (the clipboard) means.  Any chance you can elaborate on that quickly?



Glad it worked.

If you're editing AppleScripts in Script Editor or Script Debugger the log command shows you the value of whatever your are logging at that moment during execution of your script.

It's ignored at runtime.

Speaking of automator, I believe you could use automator to build a service that would do the same thing, via a menu item. (Once that service is built and saved Automator would be out of the picture)

Offline

 

#19 2022-06-07 02:18:38 pm

estockly
Member
Registered: 2009-01-03
Posts: 128

Re: Using Frontmost Application?

KniazidisR wrote:

Also, I remind you that the keystroke commands belong to the System Events application itself. Therefore, processes do not need to be told.



All the Apple documentations I've seen and all the expert tools (ScriptDebugger; UI Browser) all address UI commands to the process within System Events that own the UI elements.

It wasn't long ago where someone was posting UI scripts that required delays without sending the commands to the process inside SE, and did not require delays once that was corrected.

Offline

 

#20 2022-06-07 05:57:06 pm

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Re: Using Frontmost Application?

OK, log X isn't what I can use. 

Automator is the last thing I would use.  I live in another language and Launchbar allows that.  It also allows the AS and Automator options, but they have been quite convoluted for...decades. 

The errors/results that I see are in the Console, and even with successful results, Launchbar successes are...not presenting as I would expect. 

Cheers.

Hey thanks for the insight/conversation.  New stuff for an application (Launchbar) that isn't clear. 



estockly wrote:
daBee wrote:

Excellent.  THIS works. 

Not sure what log (the clipboard) means.  Any chance you can elaborate on that quickly?



Glad it worked.

If you're editing AppleScripts in Script Editor or Script Debugger the log command shows you the value of whatever your are logging at that moment during execution of your script.

It's ignored at runtime.

Speaking of automator, I believe you could use automator to build a service that would do the same thing, via a menu item. (Once that service is built and saved Automator would be out of the picture)

Offline

 

#21 2022-06-07 06:44:15 pm

estockly
Member
Registered: 2009-01-03
Posts: 128

Re: Using Frontmost Application?

Automator is the last thing I would use.



I'm no fan of Automator, but I believe it's the easiest way to install an AppleScript (and thereby a shell script or ruby script) as a service. Once it's installed you don't have to bother with Automator.

Offline

 

#22 2022-06-07 11:12:41 pm

KniazidisR
Member
From:: Greece
Registered: 2019-03-03
Posts: 2524

Re: Using Frontmost Application?

estockly wrote:

It wasn't long ago where someone was posting UI scripts that required delays without sending the commands to the process inside SE, and did not require delays once that was corrected.


The keystroke command does not exist for applications. So I can assure you that it should be directed to System Events.

And the fact that someone once accidentally succeeded with delays is explained in a completely different way. Namely, the fact that AppleScript is famous for its "fool-proof" because it automatically redirects many erroneous commands to the right application. Of course, fixing a user error slows down the script, which creates some unpredictable delay, giving the impression of a "working" script.

In fact, the script itself should control the delay. Every time after opening a new window, menu or dialog. Using automated delay like this:

Applescript:

repeat until window 1 of process theProcess exists
delay 0.1
end repeat

Then you can send the keystroke to System Events, and it keystrokes to this new window.

I didn’t want to be clever here and continue the topic, but I always want users not to get lost in their work. Of course, this is my personal opinion: understanding how everything works is important for writing durable and stable scripts.

Last edited by KniazidisR (2022-06-07 11:13:48 pm)


Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB

Offline

 

#23 2022-06-08 12:15:05 am

estockly
Member
Registered: 2009-01-03
Posts: 128

Re: Using Frontmost Application?

Best practice:

Applescript:


tell application "Safari" to activate
tell application "System Events"
tell process "Safari"
-- Perform user interface scripting tasks
end tell
end tell

From Apple:


Mac Automation Scripting Guide: Automating the User Interface

https://developer.apple.com/library/arc … 9-CH69-SW1

User interface scripting terminology is found in the Processes Suite of the System Events scripting dictionary. This suite includes terminology for interacting with most types of user interface elements, including windows, buttons, checkboxes, menus, radio buttons, text fields, and more. In System Events, the process class represents a running app. Listing 37-1 shows how to target an app using this class.


Listing 37-1
AppleScript: Targeting an app for user interface scripting

Applescript:


tell application "System Events"
tell process "Safari"
-- Perform user interface scripting tasks
end tell
end tell

Last edited by estockly (2022-06-08 12:17:59 am)

Offline

 

#24 2022-06-08 06:57:46 am

KniazidisR
Member
From:: Greece
Registered: 2019-03-03
Posts: 2524

Re: Using Frontmost Application?

So what? I have already seen this documentation. So we read the same thing but understand it differently. The examples in the documentation are for UI element commands (for example, click) and have no connection with the keystroke and key code commands of the System Events application.

I don't want to explain it any more.


Model: MacBook Pro
OS X: Catalina 10.15.7
Web Browser: Safari 14.1
Ram: 4 GB

Offline

 

#25 2022-06-08 07:24:59 am

daBee
Member
From:: Toronto
Registered: 2010-02-09
Posts: 199

Re: Using Frontmost Application?

Keystrokes in the System Events application pertain 100% to the UI.  When pasting using System Events, it's focus is the application that has the attention.  It's completely relevant.

Offline

 

Board footer

Powered by FluxBB

RSS (new topics) RSS (active topics)