@zane has joined the channel
set the channel description: Ad-hoc ClojureScript scripting of Mac applications via Apple’s Open Scripting Architecture. https://github.com/babashka/obb
@borkdude has joined the channel
@james427 has joined the channel
@simongray has joined the channel
Do anyone happen to know where Apple documents their own “standard library”? I.e. what is the MDN for Apple’s JS.
I guess this link in the README is the closest thing? https://developer.apple.com/library/archive/documentation/LanguagesUtilities/Conceptual/MacAutomationScriptingGuide/
The scripting guide you linked is great too.
You have access to Cocoa through JXA, so you can even create full-on applications if you want. But if you were to go down that path it might be worthwhile to just compile to JavaScript instead of running everything through obb.
Right.
I was thinking of creating an Input Method using Apple’s JS, so I might use this to get my feet wet
I also want to stress that this thing is in no way ready for prime time. There’ll be (lots of) bugs.
sure, it’s just fun, I get that 🙂
@zane I recommend putting these links in the README
@zane I also recommend watching the repo https://github.com/babashka/obb/watchers for issues :)
I created a couple of issues around the logistics of the project
Sounds good!
@borkdude All these suggestions sound great. Will get to them as I’m able.
Cool, no hurry! :)
@zane Is this something specific to #obb or something that is relevant to SCI as well? https://github.com/babashka/obb/commit/ae9783c3ded24d7eca109a8cdbc608011ed62c10
@borkdude I wanted to discuss that with you, actually. Those changes might belong upstream.
👍
This is handling a situation where you have a callable that for some reason isn’t an instance of Function &/or doesn’t have .apply.
I’m not sure how common that is outside of JXA.
@borkdude Yeah, I’m definitely going to add a lot more documentation. I wasn’t expecting eyes on the repository this quick. 😅
@soren has joined the channel
set the channel topic: https://github.com/babashka/obb
Another nice example for the README:
$ obb -e '(-> (js/Application "Google Chrome") (.-windows) (aget 0) (.activeTab) (.title))'
Slack | obb | clojuriansAdded to the README
Love it.
@gnhuy91 has joined the channel
@mmz has joined the channel
@haiyuan.vinurs has joined the channel
@zane Added a github workflow: https://github.com/babashka/obb/runs/4690744423?check_suite_focus=true
Happy to just follow your lead on all the release engineering.
@volcano0909 has joined the channel
Next highest priority is probably a better printer.
$ obb -e '(range 10)'
I:null, start:0, end:10, step:1, $a:null, Ub:null, L:null, G:32375006, P:140800@zane yes, the -e can just use prn
prn will blow up on object specifiers, no?
can make this conditional
Yep. There are a few other small design decisions to make, e.g. whether we want to default to osascript’s “human readable” output for object specifiers and the like. From man osascript:
> osascript normally prints its results in human-readable form: strings do not have quotes around them, characters are not escaped, braces for lists and records are omitted, etc. This is generally more useful, but can introduce ambiguities. For example, the lists ‘{“foo”, “bar”}’ and ‘{{“foo”, {“bar”}}}’ would both be displayed as ‘foo, bar’. To see the results in an unambiguous form that could be recompiled into the same value, use the s modifier.
For nbb I've chosen to always use prn but we can fall back on console.log for object specifiers
we could also default to no printing for normal scripts
this is what nbb does
Sounds like a plan.
see how it's done with #nbb
You can now install #obb with:
brew install babashka/brew/obb@kkharji has joined the channel
@rlhk.open has joined the channel
Great addition to then bb family. I guess https://github.com/Hammerspoon/hammerspoon could be replaced somehow?
Nice for the examples dir maybe?
Just added.
obb -e '(-> (js/Application "Spotify") (.-currentTrack) (.name))'Lots of fun to be had.
Aw yeah!
obb ❤️ bitbar / xbar / swiftbar
Put the result of any obb script in the menubar.
is there ways to explore these apps methods? 🤔
Yes!
Open Script . File > Open Dictionary.
Be sure to change the language dropdown to “JavaScript”.
ah, cool!
Ah, we need to add this trick to the README
Maybe under FAQ
or Tips and Tricks
Is there a way to convert a spotify Track to a normal object?
e.g to convert into a clojure map
Trying to remember how to do that.
ObjC.unwrap(apps)? 🤔
saw it in the jxa doc
anyway this works:
$ obb -e '(defn track->clj [track] {:artist (.artist track) :album (.album track) :name (.name track)}) (-> (js/Application "Spotify") (.-currentTrack) track->clj str)'
{:artist "The Gathering", :album "How to Measure a Planet? (Deluxe Edition)", :name "Travel"}@gnhuy91 I think that’s just for Objective-C objects.
(defn reminder->clj [reminder]
{:name (.name reminder)
:completed (.completed reminder)})
(-> (js/Application "Reminders")
(.-defaultList)
(.-reminders)
(aget 0)
(reminder->clj)
(clj->js))
had fun with RemindersI guess since SCI supports macros, you could write a macro to do (->clj obj .name .completed) or so
yea that'd be less verbose
Some returned objects will be records. For those there’s this: https://apps.apple.com/us/app/json-helper-for-applescript/id453114608
Works on, e.g. http://Things.app tasks.
That’s what I was trying to remember earlier.
Location Helper is similarly helpful. https://apps.apple.com/us/app/location-helper/id488536386
$ obb -e '(defmacro ->clj [obj & interops] (let [names (map #(clojure.string/replace (str %) #"[.-]" "") interops) ks (mapv keyword names) exprs (mapv #(list % obj) interops)] `(zipmap ~ks [~@exprs])))
(-> (js/Application "Spotify") (.-currentTrack) (->clj .artist .album .name) str)'
{:artist "The Gathering", :album "How to Measure a Planet? (Deluxe Edition)", :name "Travel"}@clj149 has joined the channel
Found a useful macro that will help with interop:
$ obb -e '
(defmacro ->clj [obj & interops]
(let [names (map #(clojure.string/replace (str %) #"[.-]" "") interops)
ks (mapv keyword names)
exprs (mapv #(list % obj) interops)]
`(zipmap ~ks [~@exprs])))
(-> (js/Application "Spotify") (.-currentTrack) (->clj .artist .album .name) str)'
{:artist "The Gathering", :album "How to Measure a Planet? (Deluxe Edition)", :name "Travel"}Added to README: https://github.com/babashka/obb#macros
@jesse.claven has joined the channel
@p4v4n has joined the channel
@cldwalker has joined the channel
@sgepigon has joined the channel
@chromalchemy has joined the channel
@bmcgavin has joined the channel
@pithyless has joined the channel
@lee has joined the channel
It would be nice to be able to extend IPrintWithWriter to support object specifiers, but I think the protocol retrieval logic will also crash on them.
yeah, this is something that should be supported in SCI for other targets (nbb, babashka) as well.
or do you mean, extending it in the precompiled obb? (yes, this is what you meant)
Yes.
what do you normally get with console.log on such a thing? also an error in JS?
If an expression evaluates to one you get back something akin to JS code that will produce it:
>> Application("Safari")
=> Application("Safari")console.logging one will actually crash:
>> console.log(Application("Safari"))
!! Error: Error: Symbol.toPrimitive is not a valid class for application Safariso what is it actually doing when it prints that? not console.log I assume? is there a special method they call on the object specifier to get this string? I'll be afk now, back tomorrow 💤
Yes.
js/Automation.getDisplayStringAh I see:
$ time obb -e '(-> (js/Application "Google Chrome") (.-windows) (aget 0) (.-tabs) (aget 0) js/Automation.getDisplayString pr-str)'
"Application(\"Google Chrome\").(0).(0)" and what happens if you extend the protocol to such a thing and then call this method on it?
Right. I had thought to just
(extend-protocol IPrintWithWriter
...
(-pr-writer [obj writer _]
(if (object-specifier? obj)
...
...)))
but we don’t get to that -pr-writer implementation. It crashes before that.I’m trying to track down exactly what’s triggering the crash, but it’s hard. 😓
what is on the first three dots?
I’ve tried function, object, and default for the types.
is there not a type like js/ObjectSpecifier that you can extend the protocol to?
Sadly, no.
>> typeof Application("Safari")
=> "function"we can also patch prn etc in the SCI context
string-print, probably.
probably. this stuff is in
but I was thinking {:namespaces {'clojure.core {'prn ...}}}
in the SCI opts
both are possible but the latter is less hacky.
but if console.log also crashes the thing, I'm not sure if we should try to fix it
don't improve on the JS behavior, just provide the same-but-CLJS behavior I'd say
when printing the return value with -e it's a different story, but there we can just write our own thing
Hmm. Fair!
We could provide a safe-print function in obb.core though, something to think about.
Need to think about whether that’ll work if an OS is in a collection.
Yeah, definitely.
oh right