I would like to know if it is possible to get the text output that is displayed in the terminal by running a shell script and display it in a Scrollable Text View, using applescript. for example:
The output that the command: git clone https://github.com/torvalds/linux.git
displays as shown in the image below would be displayed in a Scrollable Text view, would that be possible?
P.S:I'm sorry if the explanation was not clear, I hope someone understands and can help me!!
The steps for getting output from an asynchronous task like this are:
To help with converting from Objective-C, Apple provided a conversion guide with their AppleScriptObjC Release Notes, but other than examples posted on various web sites and forums, that is about it. In general, for specific information about the various Cocoa classes and methods, you will need to look them up in Apple's documentation (for Swift you can switch to the Objective-C equivalent).
Note that an NSTextView does not have any terminal emulation (ANSI escape codes, etc), which is not trivial (take a look at iTerm2 for an example terminal application), so there won't be any cursor control. Git is also a little weird in that the progress uses standard error, so that will need to be redirected to standard output.
For a plain Xcode example, create a new AppleScriptObjC project and add the following statements to the AppDelegate:
property textView : missing value -- IBOutlet
property task : missing value -- this will be the NSTask
to startTask()
tell current application's NSTask's alloc's init() -- set up the task
its setCurrentDirectoryURL:(current application's NSURL's fileURLWithPath:(POSIX path of (path to desktop folder))) -- currentDirectoryPath deprecated in 10.13
set gitPath to "/Applications/Xcode.app/Contents/Developer/usr/bin/git"
its setExecutableURL:(current application's NSURL's fileURLWithPath:"/bin/zsh") -- launchPath deprecated in 10.13
its setArguments:{"-c", gitPath & " clone --progress https://github.com/torvalds/linux.git 2>&1"} -- combine stderr with stdout
its setStandardOutput:(current application's NSPipe's pipe())
its standardOutput's fileHandleForReading's readInBackgroundAndNotify()
set my task to it -- update script property
end tell
# set up notification observers
set notificationCenter to current application's NSNotificationCenter's defaultCenter
set readNotification to current application's NSFileHandleReadCompletionNotification
notificationCenter's addObserver:me selector:"dataAvailable:" |name|:readNotification object:(task's standardOutput's fileHandleForReading)
set terminateNotification to current application's NSTaskDidTerminateNotification
notificationCenter's addObserver:me selector:"taskTerminated:" |name|:terminateNotification object:task
set {theResult, theError} to task's launchAndReturnError:(reference) -- |launch| deprecated in 10.13
if theError is missing value then
log "Task Launched"
else
log "Error launching task: " & (theError's localizedDescription() as text)
end if
end startTask
on dataAvailable:notification -- get some output from the task
set theData to notification's userInfo()'s objectForKey:(current application's NSFileHandleNotificationDataItem)
if theData is not missing value and theData's |length|() > 0 then showResult(theData)
notification's object's readInBackgroundAndNotify() -- notify again when more data is available
end dataAvailable:
to showResult(resultData) -- append data to the end of the text view
set resultString to current application's NSString's alloc()'s initWithData:resultData encoding:(current application's NSUTF8StringEncoding)
set attributedString to current application's NSMutableAttributedString's alloc()'s initWithString:resultString
set theFont to (current application's NSFont's fontWithName:"Menlo Regular" |size|:12)
set theRange to (current application's NSMakeRange(0, attributedString's |length|()))
attributedString's addAttribute:(current application's NSFontAttributeName) value:theFont range:theRange -- use monospaced font
textView's textStorage()'s appendAttributedString:attributedString
textView's scrollToEndOfDocument:me -- 10.14+
end showResult
on taskTerminated:notification
current application's NSNotificationCenter's defaultCenter's removeObserver:me
repeat -- get any early termination leftovers
set theData to notification's object's standardOutput's fileHandleForReading's availableData
if theData is not missing value and theData's |length|() > 0 then
showResult(theData)
else
exit repeat
end if
end repeat
set my task to missing value -- clear script property
log "Task Terminated"
end taskTerminated:
In the Interface Editor, add a scrollable text view to the main window and connect it to the textView
property, edit the currentDirectory and gitPath locations as needed, and put a statement in the applicationWillFinishLaunching
hander to call startTask()
.
For something a bit simpler (shorter) to test with that still has a little output, the task arguments can be changed to something like:
its setExecutableURL:(current application's NSURL's fileURLWithPath:"/usr/sbin/system_profiler")
its setArguments:{"-detailLevel", "basic"} -- mini, basic, full
-- or --
its setExecutableURL:(current application's NSURL's fileURLWithPath:"/bin/zsh")
its setArguments:{"-c", "find /Users/$USER -iname '*.scpt'" } -- find scripts