Javascript Integration: General discussion, feature requests and bugs

Hi,

Using real javascript blazing fast compared to applescript.
I combined javascript and applescript then made some benchmarks results are very promising. Problem is applescript trying to recompile 500 line of script. i converted all if statements in applescript to javascript then only used applescipt as small scripts and i get 3x speed boost

I will share soon an improved version of "Enhanced Dock" and a script for Finder :gift: completely based on javascript

so why not improve javascript integration

here we go :slight_smile: probably will add more over time

//works
trigger_named_async_without_response({trigger_name:'swmfloat'})
//BTT crashes
trigger_named_async_without_response('swmfloat')
//works
trigger_named('swmfloat')

//"cancel_delayed" key might be useful for double / triple tap detection etc
//otherwise i have to call twice cancel_delayed_named_trigger_execution({trigger_name:'Action5'})
trigger_named_async_without_response({trigger_name: 'Action5',  wait_for_reply: false,delay:1,cancel_delayed:true})

//works
callBTT('cancel_delayed_named_trigger_execution',{trigger_name: singleTapNamedTrigger})
//i guess not working, tried for triple key press
cancel_delayed_named_trigger_execution({trigger_name:'Action5'})

//key trigger
(async()=>{
	G=await get_number_variable("OptQtapCount")
	C=(G=="")?0:G
	set_number_variable("OptQtapCount",C+1)
	try{
		cancel_delayed_named_trigger_execution({trigger_name:'MultiTapOptQ'})
	}catch{}
	trigger_named_async_without_response({trigger_name:'MultiTapOptQ',delay:0.5})
	returnToBTT(C)
})()

(async()=>{
	C=await get_number_variable("OptQtapCount")
	set_number_variable("OptQtapCount",0)
	if(C==1){
		paste_text({text:"Tapped 1"})
	}else if(C==2){
		paste_text({text:"Tapped 2"})
	}else{
		paste_text({text:"Tapped 3"})
	}
	returnToBTT(C)
})()

I ended with this solution



Using parameters instead of object for simple ones would be nice

//works
set_persistent_string_variable({variable_name:'SWM-FA',to:'somevalue'})
//partially works
set_persistent_string_variable('SWM-FA','somevalue')
//not works, you can try with SWM preset folder COM.js > line 19
//it could be related type of c is number if i remember correcly
//i guess you have to check type of parameters for all btt functions
set_persistent_string_variable('SWM-'+k,c)

//works
callBTT('resize_webview',VJ)
//not works in floating webview
resize_webview(VJ)

//works
runShellScript({script:"say hello"})
//not works
runShellScript(`say hello`)
//works
runAppleScript(`beep`)

//works
paste_text({text:"SomeText"})
//not works
paste_text("SomeText")

//Using message variable as number or object instead of string crashing BTT
trigger_action({json:JSON.stringify({
BTTPredefinedActionType:371,
	BTTAdditionalActionData:{
		BTTActionSendNotificationMessage:message,
		BTTActionSendNotificationTitle:"Enhanced Dock",
		BTTActionSendNotificationSound:s?"Morse":"Bottle"
	}
})})

//coudn't show hud like this on real javascript. not sure what caused this
trigger_action({json:JSON.stringify({
	BTTPredefinedActionType:254,
	BTTHUDActionConfiguration:{
		BTTActionHUDPosition:"6",
		BTTActionHUDWidth:"36",
		BTTActionHUDHeight:"36",
		BTTActionHUDBackground:"0.000000, 0.000000, 0.000000, 153.781290",
		BTTActionHUDBlur:"0",
		BTTActionHUDDisplayToUse:"1",
		BTTActionHUDSlideDirection:"0",
		BTTActionHUDHideWhenOtherHUDAppears:false,
		BTTActionHUDDuration:"0.15000000596046448",
		BTTActionHUDDetail:"x",
		BTTActionHUDTitle:"x",
		BTTActionHUDAttributedTitle:"x"
	}
})})

//works
set_clipboard_content({content:'test',format:'NSPasteboardTypeString'})
//BTT crashes
set_clipboard_content({content:1,format:'NSPasteboardTypeString'})
//not works
set_clipboard_content("test")

Feature requests


Autohotkey like sending keys, also i suggest you to look all their documentation
Im using AHK on windows with depth customizations. i can share my setup or if you need any help on AHK logic i can detail
their layout
alt key > !
shift key > +
ctrl > ^
win > #
tab > {tab}
< or > selects which modifier keys to use
...

Send_Keys("!+{M}")
//they are using sequences like this
Send_Keys("{Ctrl Down}{Alt Down}{M}{Ctrl Up}{Alt Up}{Down 7}{Enter}")

get_menubar_item({item:"(3):item"}) > returns true if exist
get_menubar_item({item:"(3):(2)},status:true) > returns true if enabled
get_menubar_item({item:"(3):(2)},name:true) > returns string of item


support for real javascripts as .js file like applescript
it will be time saver while developing


would be cool if we get related values as object
otherwise i have to call BTT too many times and it slows down script

get_properties_object("mouse_screen")
{x:0,y:0,width:1680,height:1050}
get_properties_object("focused_screen")
{x:0,y:0,width:1680,height:1050}
get_properties_object("visible_frame")
{x:0,y:25,width:1680,height:1025}
get_properties_object("screen")
{
	mouse_screen:{
		x:0,
		y:0,
		width:1680,
		height:1050
	},
	focused_screen:{
		x:0,
		y:0,
		width:1680,
		height:1050
	},
	visible_frame:{
		x:0,
		y:25,
		width:1680,
		height:1025
	}
}
get_properties_object('dist_active_win')
{
	x:{top_left:,top_right:,bottom_left:,bottom_right:},
	y:{top_left:,top_right:,bottom_left:,bottom_right:}
}

same object logic could be done for hovered_item_details, trackpad, magic mouse, Mouse Position, Mouse Position in window, window... and list goes on :slight_smile:

ofc im not sure about performance when you bundle all of it. but still bundling mouse_screen, focused_screen , visible_frame (and maybe a screens object) will be a nice improvement


get_string_variable("active_app_name")
returns "Voice Memos" and its not always usable on some apps even native ones
tell application "Voice Memos" to activate not works because real name is "VoiceMemos" on system. also many apps has this problem

im using like this on most of my scripts. short name works without problems on process scripting

//activating target app before this
runAppleScript(`short name of (info for (path to "egfp"))`)

might be useful if you add

get_string_variable("active_app_shortname")

if i try to use

runAppleScript(`tell app "System Events" to tell window 1 of process (name of app id "`+(await get_string_variable("BTTActiveAppBundleIdentifier"))+`")`

macOS starts to ask btt tries to control .. app


alert("something")

send a notification to system in webview but not in real javascript. that one really helpful while developing.

console.log("something")

also tried console.log but does nothing.
a basic notification system would be cool or a console for real javascript


trigger_action(290)

would be nice shorthand for most functions that not requires additional keys
currently does nothing


Thanks

Hey, thanks a lot for sharing these! I'll fix them asap.

If you are running a current macOS you can get a real console. You need to open Safari, go to Develop menu. There you'll see BTT's Java Script contexts:

Its a bit hidden. is that possible to open it from BTT interface. i guess it will be more more trusty when i tell others and will be more user friendly

looks like its possible for webview
• inspect element opens inspector in BTT process
Safari > Develop > Mac Model > Runners
• Opens inspector in Safari process

unfortunately there is no way to open it from within BTT. For the webview I'm using undocumented API, but no such exists for running Java Script outside of a webview.

Quick Status Update:

4.320 alpha should already fix a few of the mentioned things(but might also break stuff, I'm currently working on a good test suite for this stuff but it's not yet ready)
I'll create a full list of the fixes soon.

It also adds support for alert(), confirm() and prompt()

Thanks for infos, i guess most of bugs related with btt not stringify some and maybe removing json stringify thing from user side javascript will works better

trigger_action({json:JSON.stringify(BTTobject)})
//user dont have to use stringify if btt fix all things under the hood
trigger_action(BTTobject)

ofc i have no idea how you convert things on macOS side

also im wondering, is there a reason for using longer names instead of shorter ones. it can improve performance if its possible

{BTTPredefinedActionType:371,
    BTTAdditionalActionData:{
        BTTActionSendNotificationMessage:"message",
        BTTActionSendNotificationTitle:"Enhanced Finder",
        BTTActionSendNotificationSound:"Bottle"
    }
}
{Action:371,
    Data:{
        Message:"message",
        Title:"Enhanced Finder",
        Sound:"Bottle"
    }
}

and this one much better integrated for javascript

display_notification({title:'Enhanced Dock',subTitle:"message",soundName:"Bottle"})

I tried this one too but no response

display_notification('Enhanced Dock',"message")

I can't / won't change the names as they are what BTT uses internally. I would have to map everything to change them.
Also performance wise you won't see a difference between longer and shorter names. The only advantages would be better readability and smaller JS size, but it would just be too much work to map everything and keep it up to date.

I also can't easily get rid of the stringify stuff although I have some ideas to improve that. The problem is on the one hand the internal database structure of BTT which has grown over 10 years (when BTT was not scriptable at all) and also BTT uses the same scripting code for Apple Script, Java Script, HTTP Requests and custom url-schemes and just slightly different interfaces for the different use cases. That's also why I can't use different function signatures (apart from for some very common things) and just require a object to be passed as parameter.

//edit: actually found a good way to get rid of the stringify requirement. With the next release you'll be able to pass objects without stringifying

I know there is 400+ actions and 150+ of them has sub keys. that will be hard task to regenerate structure and most challenging part backward compatibility. actually i have reviewed structure for few actions and most of them has different but i understand like you said years between each of them

I don't mean to be rude, i can help on structure and matching if you decide to change. i'm sure you scratching your head enough with combining different languages

good to know there is a way to stringify. i'm sure it will fix most of first post

few more ideas

//scriptable choose from list
let result=choose_from_list(list:["item1","item2","item3"],ok:"Apply",cancel:"Cancel",default:"2")
//applescript not allows alert with mutiple buttons maybe that will be helpful too
let result=await display_alert({title:"title",subtitle:"subtitle",buttons:["choose1","choose2","choose3"})
//Highlighs elements shows a fading rounded rectangle or circle(for cursor)
//options Dock / Dock Icon / Menubar / Menubar Nth Menu / Menubar App Icons / Menubar Calendar / Active Window / Desktop / Nth Screen
//Hex value with alpha would be nice for colors
//shows with 100% opacity if fade false. disaapears when time ends
highlight_element({element:"Cursor",time:"0.5",fade:"true",fillcolor:"00000FF",bordercolor:"0000000"})

I did this with show hud action for enhanced dock

//Cancels next actions for parent trigger
Parent_Action({action:"Cancel"})
//Runs parent action with delay. Delay optional. Advantage user dont deals with UUID
Parent_Action({action:"Run",delay:5})
//might be useful re running script instead of full actions of trigger
//next actions waits for this script to done
rerun_script({delay:"2",cancelcurrent:"true",nextactionswait:"true"})