Applescript for copying the current line of text? - text

I'd like to create an applescript that will copy the entire line that the carat is currently on. After doing a fair amount of googling, however, I have come up empty. Any ideas?

(*
Save this as an application
Right click the application and select "Show Package Contents"
Add this to Info.plist between <dict> and </dict>
<key>LSBackgroundOnly</key>
<true/>
launch the application with spotlight (command space)
*)
tell application "System Events"
key code 123 using {command down, shift down}
key code 124 using {command down, shift down}
keystroke "c" using {command down}
end tell

Below is some code I wrote for Xcode 9 (I finally got it working as of updated 3-5-18). I wanted a feature that every text editor I've used in the past 25 years. A copy with no selection would copy the current line. The code figures out what paragraph (line) the caret is on and if there is any text selected. The same code can be modified to include Cut.
I execute this code using Keyboard Maestro. Add the below (3) actions. You must disable the "Execute Applescript" macro before executing it otherwise the Command+C that is sent from within the code will cause an infinite loop:
Disable Macro "the current macro"
Execute Applescript "paste the AppleScript code in the edit box"
Enable Macro "the current macro"
Also, enable Xcode 9 key bindings to have Command+L do a select line. Use the "Text" tab to see less actions.
I also add the following to the DefaultKeyBinding.dict file.
https://www.maketecheasier.com/fix-home-end-button-for-external-keyboard-mac/
{
/* Remap Home/End keys to be like Windows */
"\UF729" = "moveToBeginningOfLine:"; /* Home */
"\UF72B" = "moveToEndOfLine:"; /* End */
"$\UF729" = "moveToBeginningOfLineAndModifySelection:"; /* Shift + Home */
"$\UF72B" = "moveToEndOfLineAndModifySelection:"; /* Shift + End */
/* page up/down and move the caret like Windows*/
"\UF72C" = "pageUp:";
"\UF72D" = "pageDown:";
/* Option Home/End keys Beginning/End of Document like Mac */
"~\UF729" = "moveToBeginningOfDocument:"; /* Ctrl + Home */
"~\UF72B" = "moveToEndOfDocument:"; /* Ctrl + End */
"$~\UF729" = "moveToBeginningOfDocumentAndModifySelection:"; /* Shift + Ctrl + Home */
"$~\UF72B" = "moveToEndOfDocumentAndModifySelection:"; /* Shift + Ctrl + End */
/* Ctrl Home/End keys Beginning/End of Document like Mac */
"^\UF729" = "moveToBeginningOfDocument:"; /* Ctrl + Home */
"^\UF72B" = "moveToEndOfDocument:"; /* Ctrl + End */
"$^\UF729" = "moveToBeginningOfDocumentAndModifySelection:"; /* Shift + Ctrl + Home */
"$^\UF72B" = "moveToEndOfDocumentAndModifySelection:"; /* Shift + Ctrl + End */
}
use AppleScript version "2.4" -- Yosemite (10.10) or later
use scripting additions
use application "Xcode-beta"
global appName
set appName to "Xcode-beta"
-- for some reason pressing command+C only works ever other time without this
--delay 0.1
tell application appName
activate
set theDocuments to every source document
-- exit if no source documents are found
if theDocuments is equal to {} then
-- copy command must go somewhere i.e. the user might have copied an Icon.
tell application "System Events" to keystroke "c" using {command down}
do shell script "logger -t 'AS DEBUG' " & "Applescript CopyCurrentLine - exit if no source documents are found"
return -- exit script
end if
-- Note:
-- window 1 is where source documents live
-- It sure would've been nice if window contained a reference to its source document but it doesn't
-- if window has been edited its' name ends with " — Edited" and it needs to be trimed off
set windowName to name of window 1
if windowName ends with " — Edited" then
set windowName to my trimText(windowName, " — Edited", "end")
end if
-- try to find the windows' current source document by matching window name to source document name
repeat with theDoc in theDocuments
set theDocName to name of theDoc
if theDocName is equal to windowName then
exit repeat -- found the document
else
set theDocName to "" -- didn't find the document
end if
end repeat
-- exit if the window is not a source document
if theDocName is equal to "" then
-- copy command must go somewhere i.e. the user might have copied an Icon.
tell application "System Events" to keystroke "c" using {command down}
do shell script "logger -t 'AS DEBUG' " & "Applescript CopyCurrentLine - exit if the window is not a source document"
return -- exit script
end if
--set theDoc to last source document
set docText to the text of theDoc
-- get location of selected text
set {startPos, endPos} to selected character range of theDoc
if (my isSelectedTextRangeEmpty(theDoc)) then
-- select current line
-- I set a keybinding in Xcode so Command+L would call the Command 'Select Line'
tell application "System Events" to keystroke "l" using {command down}
end if
-- copy the selection to the clipboard
set selectedText to my getSelectedText(theDoc, docText)
-- restore insertion point to original location
set selected character range of theDoc to {startPos, endPos}
set the clipboard to selectedText
end tell
on getSelectedText(theContainer, docText)
-- get the selected text
set {startPos, endPos} to selected character range of theContainer
if {endPos < startPos} then
return ""
else
return (text startPos thru endPos) in docText
end if
end getSelectedText
on isSelectedTextRangeEmpty(theContainer)
set selectedCharacterRange to selected character range of theContainer
set {startPos, endPos} to selectedCharacterRange
if {endPos < startPos} or ¬
(selectedCharacterRange is equal to {}) or ¬
(length of selectedCharacterRange is equal to 0) then
return true
else
return false
end if
end isSelectedTextRangeEmpty
on trimText(theText, theCharactersToTrim, theTrimDirection)
-- "beginning", "end", "both"
set theTrimLength to the length of the theCharactersToTrim
-- TRIM BEGINNING
if the theTrimDirection is in {"beginning", "both"} then
repeat while theText begins with the theCharactersToTrim
try
set theText to characters (theTrimLength + 1) thru -1 of theText as string
on error
-- the text contains nothing but the trim characters
return ""
end try
end repeat
end if
-- TRIM ENDING
if the theTrimDirection is in {"end", "both"} then
repeat while theText ends with the theCharactersToTrim
try
set theText to characters 1 thru -(theTrimLength + 1) of theText as string
on error
-- the text contains nothing but the trim characters
return ""
end try
end repeat
end if
return theText
end trimText

Related

How to find whether a certain bluetooth device is connected?

I want to use applescript to do a periodic (every second) check to see if a specific bluetooth devices is connected, and if so, to flash up a quick notification. To frame it, I want a popup when my Airpods connect, since sometimes when I pull them out, the connect to my computer, and sometimes to my iPhone.
I've got everything figured out, except for the bluetooth check part. I've used this as a starting point, but can't get it to work. Any help would be appreciated.
repeat
set statusOld to checkStatus()
set statusNew to checkStatus()
repeat while statusOld is equal to statusNew
delay 1 --for 1 second checks
set statusNew to checkStatus()
end repeat
if statusNew is true then
display dialog "Device Added - put some real code here"
else
display dialog "Device Removed - put some real code here"
end if
end repeat
on checkStatus()
(*Delete the 2 lines below when done testing*)
--set myString to button returned of (display dialog "Connected?" buttons {"Yes", "No"})
--set myString to "name: DR-BT101 Connected: " & myString
(*uncomment line below when done testing*)
set myString to do shell script "system_profiler SPBluetoothDataTyp"
--initial check if it's not even there
if myString does not contain "Christian’s AirPods" then
return false
else
--find out if connected/disconnected
set AppleScript's text item delimiters to "name:"
set myList to the text items of myString --each item of mylist is now one of the devices
set numberOfDevices to count of myList
set counter to 1
repeat numberOfDevices times --loop through each devices checking for Connected string
if item counter of myList contains "Christian’s AirPods" then
if item counter of myList contains "Connected: Yes" then
return true
else if item counter of myList contains "Connected: No" then
return false
else
display dialog "Error Parsing" --this shouldn't happen
end if
end if
set counter to counter + 1
end repeat
end if
end checkStatus
You're missing the e:
set myString to do shell script "system_profiler SPBluetoothDataType"
^
I'm working on something similar. This seems to work well on macOS Mojave:
use framework "IOBluetooth"
use scripting additions -- https://stackoverflow.com/a/52806598/6962
on isDeviceConnected(substring)
repeat with device in (current application's IOBluetoothDevice's pairedDevices() as list)
if device's isConnected and (device's nameOrAddress as string) contains substring then return true
end repeat
return false
end isDeviceConnected
-- Usage example:
isDeviceConnected("AirPods")
I combined it with a launch agent like this: https://gist.github.com/henrik/3d4c622a5567cdf2bf461352f48ad4dd

How to select a word with special characters in LIvecode

How to select a word with with special characters (eg: usa-uk). the following code will select text but it's doesn't select the words like usa-uk. How I change my code
select the mouseText
If you don't have a huge text in your field you might use:
on mouseMove
if the mouseLoc is within the rect of me then
put the mouseChunk into tChunk
# Check if chars before or after is a "spacing char"
put word 2 of tChunk into tstart
put word 4 of tChunk into tEnd
repeat with i = tStart down to 1 step -1
if matchText(char i of me, "\s") then exit repeat
end repeat
put i+1 into tStart
repeat with i = tEnd to the number of chars of me
if matchText(char i of me, "\s") then exit repeat
end repeat
put i-1 into tEnd
select char tstart to tEnd of me
end if
end mouseMove
How are you selecting? For example, if this was in the field script:
on mousemove
select the mouseText
end mouse move
You would be selecting the text under the cursor. In order to select compound text such as "usa-uk" you would have to group that text fragment. This sets the textStyle of that fragment to "link".
Craig Newman

Linux application in livecode

Spell Check is a default application in Linux. With the help of that application, can we check the spelling of a text field while users enter data?
Some (or many?) Linux distributions contain a command line utility that is called spell. If you run this with words as parameters, you need to press return a second time, but if you use a file as a paramater, you don't need to press return again. This means that a solution could be:
write the text of a field to a file
run the command line utility from LiveCode's shell function with the file as parameter
parse the result returned by the shell function
Before you try this, open your terminal on Linux and type spell. Press enter to see if the command is recognised. If yes, then the script below should work.
This script writes the text of a field to a file, does a spell check on the file and returns the incorrect words to LiveCode. I haven't tested the script and you may have to tweak it a little.
function spellCheck theText
// works on Linux only
if the platform is "Linux" then
// remove everything that isn't a word
put replaceText(theText,"[^\w]","") into myWords
// write clean data to a temporary file
put the tempName into myTempFile
put myWords into url ("file:" & myTempFile)
// call spell with shell
put "spell" && myTempFile into myShell
// only return the incorrect words
put line 2 to -1 of shell(myShell) into myCorrections
// return the incorrect words to calling handler
return myCorrections
else
// this isn't Linux
return "error"
end if
end spellCheck
//theField is the short name of a field
on checkField theField
// call above function
put spellCheck(the text of fld theField) into myWords
// myWords should now contain the incorrect words
if myWords is not "error" then
lock screen
// parse incorrect words and mark them in the field
repeat with x = 1 to number of words of field theField
if myWord is among the lines of myWords then
// an incorrect word has been found and is marked red
set the textColor of word x of fld theField to red
end if
end repeat
unlock screen
end if
end checkField
Usage: checkField shortNameOfTheField

Applescript if else statement inside of an if else statement with several repeats

HI I am having trouble getting this code to work properly. Here is the code:
property firstRow : 2051
property lastRow : 5584
set r to firstRow
-- highly recommended
-- close all of Safari's windows before...
tell application "Safari"
close windows
end tell
-- loop through the given row numbers
repeat until r is (lastRow + 1)
-- get the search value for Safari auto completion (column J)
try
tell application "Microsoft Excel"
tell active sheet
set searchTerm to string value of range ("J" & r) of active sheet
end tell
end tell
on error
-- no document open, exit the script
return
end try
-- open Safari and make a new window
tell application "Safari"
activate
make new document with properties {URL:""}
delay 0.5
set pageLoaded to false
end tell
-- type the search value into the address field and hit return (aka select and open the first proposal)
tell application "System Events"
-- here with Safari 6.1 text field 1 of group 2 of tool bar 1 of window 1 points to the URL field
set focused of text field 1 of group 2 of toolbar 1 of window 1 of process "Safari" to true
delay 0.5
keystroke searchTerm
delay 1.5
keystroke return
end tell
-- let open Safari the suggested web page and read out the finally used URL
tell application "Safari"
repeat while not pageLoaded -- keep doing this loop until loading complete
delay 5
if (do JavaScript "document.readyState" in document 1) is "complete" then
set pageLoaded to true
else
-- not sure if this second else is needed, why not just wait until the first access has finished...
-- close document 1
-- make new document with properties {URL:""}
-- tell application "System Events"
-- delay 1.5
-- set focused of text field 1 of group 2 of tool bar 1 of window 1 of process "Safari" to true
-- delay 1.5
-- keystroke searchTerm
-- delay 1.5
-- keystroke return
-- end tell
end if
set thisULR to "NO SITE"
end repeat
try
set thisURL to URL of document 1
on error
set thisURL to "NO SITE"
end try
close document 1
end tell
-- write the result into the cell next to the key word (column K)
tell application "Microsoft Excel"
if thisURL ≠ "NO SITE" then
tell active sheet
make new hyperlink of cell ("K" & r) with properties {address:thisURL, name:thisURL}
end tell
else
tell active sheet
make new cell ("K" & r) with properties {name:"NO SITE"}
end tell
end if
end tell
set r to r + 1
end repeat
I am having trouble getting the code to not crash if there is no URL saved as variable thisURL.
However, it is still crashing. It often says thisURL is not defined and then it stops the script from going to the next r value instead of adding "NO SITE" to the cell. Not sure why its not working.
It was a big chaos with all your end telland end ifetc. Another thing is that I don't understand why you need the second nested repeat-loop...
But I think I figured it out: You want to
read a value from an excel sheet
pretend to type the read out value into Safari's address bar
use the autofill and read out the URL of the found site
write the result into the adjacent excel cell
After your post edit I edited the code to this:
property firstRow : 62
property lastRow : 5584
set r to firstRow
-- highly recommended
-- close all of Safari's windows before...
tell application "Safari"
close windows
end tell
-- loop through the given row numbers
repeat until r is (lastRow + 1)
-- get the search value for Safari auto completion (column J)
try
tell application "Microsoft Excel"
tell active sheet
set searchTerm to string value of range ("J" & r) of active sheet
end tell
end tell
on error
-- no document open, exit the script
return
end try
-- open Safari and make a new window
tell application "Safari"
activate
make new document with properties {URL:""}
set pageLoaded to false
end tell
-- type the search value into the address field and hit return (aka select and open the first proposal)
tell application "System Events"
-- here with Safari 6.1 text field 1 of group 2 of tool bar 1 of window 1 points to the URL field
set focused of text field 1 of group 2 of tool bar 1 of window 1 of process "Safari" to true
keystroke searchTerm
delay 1.5
keystroke return
end tell
-- let open Safari the suggested web page and read out the finally used URL
tell application "Safari"
try
repeat while not pageLoaded -- keep doing this loop until loading complete
delay 10
if (do JavaScript "document.readyState" in document 1) is "complete" then
set pageLoaded to true
end if
end repeat
set thisURL to URL of document 1
close document 1
on error
set thisURL to "NO SITE"
try
close windows
end try
end try
end tell
-- write the result into the cell next to the key word (column K)
tell application "Microsoft Excel"
if thisURL ≠ "NO SITE" then
tell active sheet
make new hyperlink of cell ("K" & r) with properties {address:thisURL, name:thisURL}
end tell
else
tell active sheet
make new cell ("K" & r) with properties {name:"NO SITE"}
end tell
end if
end tell
set r to r + 1
end repeat
Greetings, Michael / Hamburg
Here is another solution. I tested with different delay values inside the System Events part and found a better way of getting the URL from Safari. Have a look at the two main parts of the script, everything else don't need changes:
-- type the search value into the address field and hit return (aka select and open the first proposal)
tell application "System Events"
tell process "Safari"
-- give time to prepare the window
delay 0.5
set focused of text field 1 of group 2 of toolbar 1 of window 1 to true
-- give time to prepare the address field
delay 0.5
keystroke searchTerm
-- give time to get the proposals
delay 0.5
keystroke return
end tell
end tell
-- let Safari open the suggested web page and read out the finally used URL
tell application "Safari"
-- setting the default value
set thisURL to "NO SITE"
try
-- 6 tries with 5 seconds pause (-> max. 30 sec.)
repeat 6 times
try
-- give time to load
delay 5
-- try to access the URL, if it is not available, an error occurs and the repeat loop starts again
set thisURL to URL of document 1
-- close the document
close document 1
-- no error till now, exit the repeat loop
exit repeat
end try
end repeat
on error
-- just to be sure: close all windows
try
close windows
end try
end try
end tell
Greetings, Michael / Hamburg

Applescript file search using data from a spreadsheet

I am currently using this Applescript I found that searches for a file name and returns the file path in a text doc. This works fine for finding 1 or 2 files, but I would like to find 500 files that are spread over hundreds of folders. My ideal script would use data from an excel spreadsheet or csv, perform a search, find the file and make a copy of it in a designated folder on my desktop. Any help is appreciated.
Here is the script I found:
tell application "System Events"
activate
set thePattern to text returned of (display dialog "Search for" default answer "")
end tell
if thePattern = "" then return
try
set foundFiles to do shell script "mdfind -name " & quoted form of thePattern & " | /usr/bin/egrep -i " & quoted form of thePattern & "[^/]*/?$ | /usr/bin/grep -vi " & quoted form of thePattern & ".*" & quoted form of thePattern
on error
set foundFiles to "Nothing Returned"
end try
if foundFiles = "" then set foundFiles to "Nothing Returned"
tell application "TextEdit"
activate
delay 0.5
try
set theDoc to document 1
get text of theDoc
if result is not "" then
make new document
set theDoc to result
end if
on error
make new document
set theDoc to result
end try
set text of theDoc to foundFiles
end tell
You need to read the data from the text file, then turn it into a return or linefeed delimited list and do a repeat over the items of this list. Then turn each item (which is actually a line) into e.g. a tab delimited list and again do a (nested) repeat loop over the items of this list. If you know that e.g. item 3 is the file path, you can set a variable to item 3 of the line as text and use this variable in your shell script.
I think you need to show that you understand the concept of repeat loops by posting your own attempt of implementing this. If you do, I'll be happy to come back and help you with the next step.
Kind regards,
Mark

Resources