AS Help: Run Check Syntax on documentWillSave

28 views
Skip to first unread message

Brandon Schneider

unread,
Apr 13, 2019, 2:34:05 PM4/13/19
to BBEdit Talk
Hello list!

I've been banging my head against this, and could use some AppleScript experts here to give me a hand.

The idea is I want to run the #! command Check Syntax *before* a file saves (on its contents), and if there's an error, do not save. I've been able to achieve something close to this with calling external binaries, but I'd rather use the builtins of BBEdit.


Thanks,
- Brandon

Brandon Schneider

unread,
Apr 13, 2019, 3:56:36 PM4/13/19
to BBEdit Talk
I should add I've tried check syntax, but that seems very focused on HTML. My focus is on Python.

@lbutlr

unread,
Apr 13, 2019, 4:04:37 PM4/13/19
to BBEdit Talk
On 13 Apr 2019, at 12:26, Brandon Schneider <brandonsc...@gmail.com> wrote:
> The idea is I want to run the #! command Check Syntax *before* a file saves (on its contents), and if there's an error, do not save. I've been able to achieve something close to this with calling external binaries, but I'd rather use the builtins of BBEdit.

Attach a script to the save action.

Bottom of page 309, then check page 31 for where to put them.

But I don't know how you run the check syntax as it's not in the AppleScript dictionary (it is, but it is the HTML check syntax, not the shebang one).


--
You know what they say about paradigms: Shift happens.


Brandon Schneider

unread,
Apr 13, 2019, 10:07:32 PM4/13/19
to bbe...@googlegroups.com
Yeah that's what I've been trying for, but the lack of the shebang one in the dictionary is the problem. 

on documentWillSave(myDoc)
    on menu_click(mList)
        local appName, topMenu, r
    
        -- Validate our input
        if mList's length < 3 then error "Menu list is not long enough"
    
        -- Set these variables for clarity and brevity later on
        set {appName, topMenu} to (items 1 through 2 of mList)
        set r to (items 3 through (mList's length) of mList)
    
        -- This overly-long line calls the menu_recurse function with
        -- two arguments: r, and a reference to the top-level menu
        tell application "System Events" to my menu_click_recurse(r, ((process appName)'s ¬
            (menu bar 1)'s (menu bar item topMenu)'s (menu topMenu)))
    end menu_click

    on menu_click_recurse(mList, parentObject)
        local f, r
    
        -- `f` = first item, `r` = rest of items
        set f to item 1 of mList
        if mList's length > 1 then set r to (items 2 through (mList's length) of mList)
    
        -- either actually click the menu item, or recurse again
        tell application "System Events"
            if mList's length is 1 then
                click parentObject's menu item f
            else
                my menu_click_recurse(r, (parentObject's (menu item f)'s (menu f)))
            end if
        end tell
    end menu_click_recurse
    
tell application "BBEdit" to activate
menu_click({"BBEdit", "#!", "Check Syntax"})
end documentWillSave

Is the closest (and other variants) I've gotten, but the problem is the menu is grayed out, so it's not really a functional script.

I'm hoping somebody has a better idea.

-Brandon


--
This is the BBEdit Talk public discussion group. If you have a
feature request or need technical support, please email
"sup...@barebones.com" rather than posting to the group.
Follow @bbedit on Twitter: <https://www.twitter.com/bbedit>
---
You received this message because you are subscribed to a topic in the Google Groups "BBEdit Talk" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/bbedit/D5tO4hanw_A/unsubscribe.
To unsubscribe from this group and all its topics, send an email to bbedit+un...@googlegroups.com.
To post to this group, send email to bbe...@googlegroups.com.
Visit this group at https://groups.google.com/group/bbedit.

Bruce Van Allen

unread,
Apr 13, 2019, 10:07:33 PM4/13/19
to bbe...@googlegroups.com
On 4/13/19 at 11:26 AM, brandonsc...@gmail.com (Brandon
Schneider) wrote:
>The idea is I want to run the #! command Check Syntax *before* a file saves

BBEdit needs to know what language the script is in before it
can check the syntax.

Try setting the language to Python (or whatever you're writing
in), in the little pop-up in the bottom bar of the window, next
to where it shows the encoding and the line endings. You can do
that before saving, and that's enough for BBEdit to know which
language syntax to check for.

HTH
--

- Bruce

_bruce__van_allen__santa_cruz__ca_

Brandon Schneider

unread,
Apr 14, 2019, 6:43:29 AM4/14/19
to bbe...@googlegroups.com
Hi Bruce,

Yes BBEdit is aware that the files are Python, the Check syntax command works great manually. It’s the ability to script it that’s proving troublesome :)

--
This is the BBEdit Talk public discussion group. If you have a
feature request or need technical support, please email
"sup...@barebones.com" rather than posting to the group.
Follow @bbedit on Twitter: <https://www.twitter.com/bbedit>
---
You received this message because you are subscribed to a topic in the Google Groups "BBEdit Talk" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/bbedit/D5tO4hanw_A/unsubscribe.
To unsubscribe from this group and all its topics, send an email to bbedit+un...@googlegroups.com.
To post to this group, send email to bbe...@googlegroups.com.
Visit this group at https://groups.google.com/group/bbedit.
--
-Brandon

Christopher Stone

unread,
Apr 14, 2019, 2:53:27 PM4/14/19
to BBEdit-Talk
On 04/13/2019, at 15:28, Brandon Schneider <brandonsc...@gmail.com> wrote:
Is the closest (and other variants) I've gotten, but the problem is the menu is grayed out, so it's not really a functional script.


Hey Brandon,

BBEdit cannot run UI-Scripts against itself.  It chokes, although Rich has apparently fixed the hang that used to occur.

So your menu-click script won't work in this context.

You'll have to call out to FastScripts or Keyboard Maestro or something else to activate the menu item.

--
Best Regards,
Chris

Brandon Schneider

unread,
Apr 15, 2019, 9:54:34 AM4/15/19
to bbe...@googlegroups.com
That was really helpful Chris, it occurred to me I completely forgot to try using a shortcut instead.

This gets me 90% of the way there (posting the small script for time travelers):
tell application "BBEdit" to activate
tell application "BBEdit" to tell document 1 to save
tell application "System Events" to keystroke "k" using command down

The ordering of the save seemed to cause a race condition, so this doesn't obviously meet the criteria of not saving if there's an error, but it certainly helps run it each save instead of me forgetting and giving me a nice big window.

I bound the script to command + s and it all works great!
-Brandon


Christopher Stone

unread,
Apr 15, 2019, 3:36:47 PM4/15/19
to BBEdit-Talk
On 04/14/2019, at 15:49, Brandon Schneider <brandonsc...@gmail.com> wrote:
That was really helpful Chris, it occurred to me I completely forgot to try using a shortcut instead.

This gets me 90% of the way there (posting the small script for time travelers):
tell application "BBEdit" to activate
tell application "BBEdit" to tell document 1 to save
tell application "System Events" to keystroke "k" using command down


Hey Brandon,

I'd write that something like this:

------------------------------------------------------------

try

    

    tell application "BBEdit"
        -- No need for activate, since the script originates in BBEdit.
        tell document 1 to save
    end tell

    

    tell application "System Events"
        -- Isolate the keystroke to BBEdit – not required but is better practice.
        tell application process "BBEdit"
            keystroke "k" using command down
        end tell
    end tell

    

on error e number n
    stdErr(e, n, true, true) of me
end try

------------------------------------------------------------
--» HANDLERS
------------------------------------------------------------
on stdErr(e, n, beepFlag, ddFlag)
    set e to e & return & return & "Num: " & n
    if beepFlag = true then
        beep
    end if
    if ddFlag = true then
        if n ≠ -128 then
            try
                tell application (path to frontmost application as text) to set ddButton to button returned of ¬
                    (display dialog e with title "ERROR!" buttons {"Copy Error Message", "Cancel", "OK"} ¬
                        default button "OK" giving up after 30)
                if ddButton = "Copy Error Message" then set the clipboard to e
            end try
        end if
    else
        return e
    end if
end stdErr
------------------------------------------------------------

The ordering of the save seemed to cause a race condition, so this doesn't obviously meet the criteria of not saving if there's an error, but it certainly helps run it each save instead of me forgetting and giving me a nice big window.

Note the error handler in the above script.  Perhaps you can use one to mitigate this.

I bound the script to command + s and it all works great!

Excellent!

--
Best Regards,
Chris

Reply all
Reply to author
Forward
0 new messages