Replace text in an applescript using an applescript - applescript

I have several hundred lengthy applescripts to edit where I need to find and replace the following code snippet in various places in each script.
tell application "Adobe Photoshop CC 2015.5"
set myLayer to current layer of current document
if last character of mySport is "s" then
set contents of text object of myLayer to mySport & ""
else
set contents of text object of myLayer to mySport & "'s"
end if
end tell
I want to replace it with
tell application "Adobe Photoshop CC 2015.5"
set myLayer to current layer of current document
set contents of text object of myLayer to mySport & "'s"
end tell
Is there a way to write an applescript to find and replace several lines?
code screen grab
The second problem is how do I deal with the apostrophe contained inside the quotes?
You can probably tell that I'm an artist and not a developer or scripter! I tried to get an answer a while back but unsuccessfully and the problem is now become critical.
Many thanks in anticipation of an answer.

The best would have been to set this subroutine as a separate script library and call it it in each of your scripts. Doing so, only one change would be enough. I advice you to do this way for next time.
I dig to find a way to make change in a script, but that's not that easy. Script Editor as very limited capability for scripting. the work around is to use the GUI scripting, which means that any changes made by Apple in future versions may no longer work.
The script bellow simulate your keyboard action to search & replace CurString to NewString :
set myScript to "Users:imac27:Desktop:Testscript.scpt" -- path to your script
set CurString to "Set B to 2"
set NewString to "Set X to 5"
tell application "Script Editor"
open myScript
activate myScript
delay 2
tell application "System Events"
keystroke "f" using {option down, command down} --mode search & replace
keystroke tab using {shift down} -- got to search area
keystroke CurString -- set the search target
keystroke tab -- goto replace area
keystroke NewString -- set replace value
-- click on menu "Replace all " which is the 7th item of "Search" menu item (=item 14th of menu "Edit")
tell process "Script Editor" to click menu item 7 of menu of menu item 14 of menu 4 of menu bar 1
end tell
compile front document
save front document
close front document
end tell
This script opens the script, it does the search, replaces, clicks on "replace" menu, then it compiles new version, saves it and closes it. If you have many scripts, you must run it through a loop for each script.
I tested it OK with simple line : replace "Set B to 2" by new line "Set X to 5".
However, your issue is more complex because you want to replace several lines, not only 1. I did not found a way to set the search area with multiple lines. I tried with CR (13) or LF (10), but it does not work. May be someone has an idea for that part ?
Also, if you want to add a " in your search or replace patterns, you can use the following :
set Guil to ASCII character 34
Set CurString to "this is a " & Guil & "s" & Guil & " between quotes"
In this case, the CurString value will be : this is a "s" between quotes

I purchased Script Debugger from Late Night Software and it enables the script to access pieces of code and replace them. Mark Alldritt was amazing in the support he offered and the software is now my "first use" destination.

You are sure of your original script and the final script? In this case no hesitation to use xxd and sed below in hexadecimal script which you wrote you can test this script, no danger for your script. Naturally, you change your path and names at your convenience.
set thePath to POSIX path of (choose file)
tell application "Script Editor"
set doc to open thePath
save doc as "text" in POSIX file "/Users/yourname/Desktop/yourscriptold.txt"
close thePath
end tell
set scp to do shell script "xxd -p -c 100000 /Users/yourname/Desktop/yourscriptold.txt " & " | sed -e 's#74656c6c206170706c69636174696f6e202241646f62652050686f746f73686f7020434320323031352e35220a736574206d794c6179657220746f2063757272656e74206c61796572206f662063757272656e7420646f63756d656e740a6966206c61737420636861726163746572206f66206d7953706f727420697320227322207468656e0a73657420636f6e74656e7473206f662074657874206f626a656374206f66206d794c6179657220746f206d7953706f727420262022220a656c73650a73657420636f6e74656e7473206f662074657874206f626a656374206f66206d794c6179657220746f206d7953706f7274202620222773220a656e642069660a656e642074656c6c#74656c6c206170706c69636174696f6e202241646f62652050686f746f73686f7020434320323031352e35220a736574206d794c6179657220746f2063757272656e74206c61796572206f662063757272656e7420646f63756d656e740a73657420636f6e74656e7473206f662074657874206f626a656374206f66206d794c6179657220746f206d7953706f7274202620222773220a656e642074656c6c#' > /Users/yourname/Desktop/yourscriptnew.txt"
set scp to do shell script "xxd -r -p /Users/yourname/Desktop/yourscriptnew.txt >/Users/yourname/Desktop/yournewscript.txt"
do shell script "osacompile -o " & "/Users/yourname/Desktop/temporyname.scpt" & " /Users/yourname/Desktop/yournewscript.txt"
do shell script "rm -f /Users/yourname/Desktop/yourscriptold.txt "
do shell script "rm -f /Users/yourname/Desktop/yourscriptnew.txt "
do shell script "rm -f /Users/yourname/Desktop/yournewscript.txt "

Related

Applescript Occasionally Freezes Automator

I'm trying to use this applescript to modify a file path written to a text file, copy the modified path to the clipboard, set it as variable thePath, use it to pull a Google Drive link from a list, and then copy that link to the clipboard.
Running it within Automator, it sometimes works perfectly but other times it stalls while running this applescript and crashes textedit, and then eventually times out without any specific error messages. Are there any issues with my code that would be causing Automator to freeze?
Note that I've substituted the actual links with link1, link2, etc. for privacy reasons.
on run {input, parameters}
tell application "TextEdit" to activate
tell application "System Events"
key code 125
key code 123 using shift down
key code 123 using shift down
key code 123 using shift down
key code 123 using shift down
key code 123 using shift down
key code 123 using shift down
key code 123 using shift down
key code 123 using shift down
keystroke "x" using command down
keystroke "a" using command down
key code 51
keystroke "v" using command down
keystroke "s" using command down
keystroke "w" using command down
delay 2
end tell
set thePath to the clipboard
set myList to {"link1","link2","link3","link4","link5","link6","link7","link8","link9","link10","link11","link12","link13","link14","link15","link16","link17","link18","link19","link20","link21","link22","link23","link24","link25","link26","link27","link28","link29","link30","link31","link32","link33","link34","link35","link36","link37","link38","link39","link40","link41","link42","link43","link44","link45","link46","link47","link48","link49","link50","link51","link52","link53","link54","link55","link56","link57","link58","link59","link60","link61","link62","link63","link64","link65","link66","link67","link68","link69","link70","link71","link72","link73","link74","link75","link76","link77","link78","link79","link80","link81","link82","link83","link84","link85","link86","link87","link88","link89","link90","link91","link92","link93","link94","link95","link96","link97","link98","link99","link100","link101","link102","link103","link104","link105","link106","link107","link108","link109","link110","link111","link112","link113","link114","link115","link116","link117","link118","link119","link120","link121","link122","link123","link124","link125","link126","link127","link128","link129","link130","link131","link132","link133","link134","link135","link136","link137","link138","link139","link140","link141","link142","link143","link144","link145","link146","link147","link148","link149","link150","link151","link152","link153","link154","link155","link156","link157","link158","link159","link160","link161","link162","link163","link164","link165","link166","link167","link168","link169","link170","link171","link172","link173","link174","link175","link176","link177","link178","link179","link180","link181","link182","link183","link184","link185","link186","link187","link188","link189","link190","link191","link192","link193","link194","link195","link196","link197","link198","link199","link200","link201","link202","link203","link204","link205","link206","link207","link208","link209","link210","link211","link212","link213","link214","link215","link216","link217","link218","link219","link220","link221","link222","link223","link224","link225","link226","link227","link228","link229","link230","link231","link232","link233","link234","link235","link236","link237","link238","link239","link240","link241","link242","link243","link244","link245","link246","link247","link248","link249","link250","link251","link252","link253","link254","link255","link256","link257","link258","link259","link260","link261","link262","link263","link264","link265","link266","link267","link268","link269","link270","link271","link272","link273","link274","link275","link276","link277","link278","link279","link280","link281","link282","link283","link284","link285","link286","link287","link288","link289","link290","link291","link292","link293","link294","link295","link296","link297","link298"}
set the clipboard to item thePath of myList
return input
end run
You could do this with AppleScript, but it would be much more sensible to do this with a shell script, by way of the Run Shell Script action in Automator, selecting the option to pass the input "as arguments". The default shell in macOS is zsh, so stick with that.
The script is short and sweet:
( PATH=/usr/bin:$PATH
basename "$1" | bc
) 2>/dev/null
basename extracts last path component, which, in this case, is the name of the folder, even if the path ends with a trailing slash. The result of this command is then piped through to bc, which performs basic calculations: this is purely to parse the folder name as a number, so that "00007" simply returns "7".
How to make use of this value is entirely dependent on how and where you store the various links from which it selects. Here's one suggestion, which is reasonably simple:
This allows you to hard-code your 300 or so links into a single Automator variable, which a second shell script reads and returns the specific link associated (by line number) with the value obtained from the previous shell script. The link then placed onto the clipboard.

how to pass single quote to applescript by zsh alias

i am use applescript to login ssh by gateway。
alias sshtoxxxx="osascript ~/workspace/script/applescript/fox/ssh_xxxx.applescript root#10.10.1.199 hFVDa4d\'vLe"
when password contains ' , it will can not login.
and the applescript is below also it is no use
on run argv
set arg1 to (item 1 of argv)
set arg2 to (item 2 of argv)
testFunc(arg1,arg2)
sshxxx(arg1,arg2)
end run
on sshxxx(target,password)
tell application "iTerm"
reopen
activate
tell the current window
create tab with default profile
tell the current tab
tell the current session
write text "clear"
write text "logfin the gate way host"
delay 0.2
repeat until "xxxxx" is in contents
end repeat
write text "clear"
set targetText to "ssh " & target
write text targetText
repeat until "password" is in contents
end repeat
write text password
end tell
end tell
end tell
end tell
end sshxxx
The question is not related to Applescript. Zsh doesn't care, what programming language the called executable is written in.
If you want to use an alias, your approach is correct. Applescript will see the password parameter as hFVDa4d'vL. However, for ease of debugging, I recommend using a Zsh function instead of an alias; here you have to drop the backslash:
function sshtoxxxx {
osascript ~/workspace/script/applescript/fox/ssh_xxxx.applescript root#10.10.1.199 "hFVDa4d'vLe"
}

Invoke copy & paste commands from terminal

Is is possible to invoke a copy command (as if the user pressed Cmd+C) from a bash script? Basically I want to write a simple script that I run with a global hotkey and it should take the current selection from the active app, replace something and paste the result. Is this possible?
The best I could come up so far is using pbpaste and pbcopy, but I'd like to automate that if possible.
If you're just trying to modify a text selection, you could use AppleScript.
osascript -e 'try
set old to the clipboard
end try
try
delay 0.3
tell application "System Events" to keystroke "c" using command down
delay 0.2
set text item delimiters to linefeed
set input to (paragraphs of (the clipboard as text)) as text
set the clipboard to do shell script "shopt -u xpg_echo; echo -n " & quoted form of input & " | rev" without altering line endings
tell application "System Events" to keystroke "v" using command down
delay 0.05
end try
try
set the clipboard to old
end try'
The first delay is for releasing modifier keys if the script is run with a shortcut that has other modifier keys than command. The second delay could also be reduced to something like 0.05, but long selections or for example web views often need a longer delay. Without the third delay, the clipboard would sometimes be set to old before the text would get pasted.
the clipboard as text and do shell script convert line endings to carriage returns by default. shopt -u xpg_echo is needed because the echo in sh interprets backslashes inside single quotes by default. If the input is longer than getconf ARG_MAX bytes, you can't use echo and have to either write it to a temporary file or use pbpaste.
pbpaste and pbcopy replace non-ASCII characters with question marks by default in the environment used by do shell script You can prevent that by setting LC_CTYPE to UTF-8.
Telling System Events to click menu bar items would often be even slower, and it wouldn't work in applications that don't have a menu bar or in full screen windows.
Another option would be to create an Automator service. But they also have small delays before they are run. There's a bug where the shortcuts for services don't always work until the services menu has been shown once on the menu bar. And the services aren't available when the frontmost application doesn't have a menu bar or a services menu.

Programmatically launch Terminal.app with a specified command (and custom colors)

I can launch an xterm from the command line (or a program, via a system call) like so:
/usr/X11/bin/xterm -fg SkyBlue -bg black -e myscript
That will launch an xterm with blue text and a black background, and run an arbitrary script inside it.
My question: How do I do the equivalent with Terminal.app?
You can open an app by bundle id too, and give other parameters.
If there's an executable script test.sh in the current directory, the following command will open and run it in Terminal.app
open -b com.apple.terminal test.sh
The only down side that I can find is that Terminal doesn't appear to inherit your current environment, so you'll have to arrange another way to pass parameters through to the script that you want to run. I guess building the script on the fly to embed the parameters would be one approach (taking into account the security implications of course...)
Assuming you already have the colors you want in one of your Terminal profiles, here's what I came up with (with some help from Juha's answer and from this Serverfault answer).
Update:
On reflection, I think this echo business is too complicated. It turns out you can use osascript to make an executable AppleScript file with a shebang line:
#!/usr/bin/osascript
on run argv
if length of argv is equal to 0
set command to ""
else
set command to item 1 of argv
end if
if length of argv is greater than 1
set profile to item 2 of argv
runWithProfile(command, profile)
else
runSimple(command)
end if
end run
on runSimple(command)
tell application "Terminal"
activate
set newTab to do script(command)
end tell
return newTab
end runSimple
on runWithProfile(command, profile)
set newTab to runSimple(command)
tell application "Terminal" to set current settings of newTab to (first settings set whose name is profile)
end runWithProfile
Save that as term.scpt, make it executable with chmod +x, and use it the same way as below, e.g. term.scpt "emacs -nw" "Red Sands".
Original answer:
Assuming we save the script below as term.sh...
#!/bin/sh
echo '
on run argv
if length of argv is equal to 0
set command to ""
else
set command to item 1 of argv
end if
if length of argv is greater than 1
set profile to item 2 of argv
runWithProfile(command, profile)
else
runSimple(command)
end if
end run
on runSimple(command)
tell application "Terminal"
activate
set newTab to do script(command)
end tell
return newTab
end runSimple
on runWithProfile(command, profile)
set newTab to runSimple(command)
tell application "Terminal" to set current settings of newTab to (first settings set whose name is profile)
end runWithProfile
' | osascript - "$#" > /dev/null
...it can be invoked as follows:
term.sh
opens a new terminal window, nothing special
term.sh COMMAND
opens a new terminal window, executing the specified command. Commands with arguments can be enclosed in quotes, e.g. term.sh "emacs -nw" to open a new terminal and run (non-windowed) emacs
term.sh COMMAND PROFILE
opens a new terminal window, executing the specified command, and sets it to the specified profile. Profiles with spaces in their names can be enclosed in quotes, e.g. term.sh "emacs -nw" "Red Sands" to open a new terminal and run (non-windowed) emacs with the Red Sands profile.
If you invoke it with a bad command name, it'll still open the window and set the profile, but you'll get bash's error message in the new window.
If you invoke it with a bad profile name, the window will still open and the command will still execute but the window will stick with the default profile and you'll get an error message (to stderr wherever you launched it) along the lines of
525:601: execution error: Terminal got an error: Can’t get settings set 1 whose name = "elvis". Invalid index. (-1719)
The invocation is slightly hacky, and could probably be improved if I took the time to learn getopt (e.g., something like term.sh -p profile -e command would be better and would, for instance, allow you to easily open a new terminal in the specified profile without invoking a command). And I also wouldn't be surprised if there are ways to screw it up with complex quoting. But it works for most purposes.
Almost all (every?) osx program can be launched from command line using:
appName.app/Contents/MacOS/command
For terminal the command is:
/Applications/Utilities/Terminal.app/Contents/MacOS/Terminal
You can use the autocomplete (tab) or ls to find the correct filenames. ".app" is basically a folder.
To change the colors and run a script... I think you cannot do it with shell scripts as Terminal does not accept arguments ("Terminal myScript.sh" does not launch myScript). With iTerm this works.
Workaround is to use applescript (wrapped in a shell script):
#!/bin/sh
osascript -e '
tell application "Terminal"
activate
tell window 1
do script "sleep 5; exit"
set background color to {0, 11111, 11111}
set win_id to id
end tell
set w_ids to (id of every window)
repeat while w_ids contains win_id
delay 1
set w_ids to (id of every window)
end repeat
end tell'
Ok, now it should behave exactly the same as the xterm example. The drawback is the constant polling of the window ids (which is bad programming).
edit: A bit more elegant applescript would use the 'busy' property of Terminal. I will leave the original code as is works for a general program (not just terminal).
tell application "Terminal"
tell window 1
do script "sleep 2"
set background color to {0, 11111, 11111}
repeat while busy
delay 1
end repeat
close
end tell
end tell
Also for perfectly correct program, one should check that whether the terminal is running or not. It affects the number of windows opened. So, this should be run first (again a nasty looking hack, that I will edit later as I find a working solution).
tell application "System Events"
if (count (processes whose name is "Terminal")) is 0 then
tell application "Terminal"
tell window 1
close
end tell
end tell
end if
end tell
br,
Juha
You can also go into terminal GUI, completely configure the options to your heart's content, and export them to a ".terminal" file, and/or group the configurations into a Window Group and export that to a terminal file "myGroup.terminal". Then
open myGroup.terminal
will open the terminal(s) at once, with all your settings and startup commands as configured.
you can launch terminal with the following command, not sure how to specify colors:
open /Applications/Utilities/Terminal.app/
The answer from #david-moles above works but run the terminal and command in ~ rather the current working directory where term was launched. This variation adds a cd command.
#!/usr/bin/env bash
# based on answer by #david-moles in
# https://stackoverflow.com/questions/4404242/programmatically-launch-terminal-app-with-a-specified-command-and-custom-colors
echo "
on run argv
if length of argv is equal to 0
set command to \"\"
else
set command to item 1 of argv
end if
set command to \"cd '"$PWD"' ;\" & command
if length of argv is greater than 1
set profile to item 2 of argv
runWithProfile(command, profile)
else
runSimple(command)
end if
end run
on runSimple(command)
tell application \"Terminal\"
activate
set newTab to do script(command)
end tell
return newTab
end runSimple
on runWithProfile(command, profile)
set newTab to runSimple(command)
tell application \"Terminal\" to set current settings of newTab to (first settings set whose name is profile)
end runWithProfile
" | osascript - "$#" > /dev/null
There may be a way to set PWD this with applescript.
Note: When I use this, I sometimes two Terminal windows, one a shell running in ~ and a second which runs the cd command and command from argv[1]. Seems to happen if Terminal is not already running; perhaps it is opening old state (even tho I had no open terminals when I closed it).

Applescript conversion to Bash

I would like to make sure that an applescript can be converted to bash. Are there any ideas on how to do this? And if so, I'll place a simple applescript below to give you an example of how the script runs. In more clarity, I simply want a bash script or shell script to do what my applescript is doing. I want it to "enable" or change the default of the switch in system preferences, under "energy saver" that reads ...'start up automatically after a power failure'...:
set uiScript to "click checkbox \"Start up automatically after a power failure\" of list 2 of group 1 of window \"Energy Saver\" of application process \"System Preferences\""
run script "tell application \"System Events\"
" & uiScript & "
end tell"
any ideas on how to convert this script?
Thanks,
-Unimachead
You may not actually need to convert it - you can run AppleScript from within a bash script, using osascript.
$ man osascript
Note that you can run AppleScript either from a file or just include the source on the command line.

Resources