Search code examples
javascripttextmatetextmate2

Textmate Javascript Validate Syntax Command


I spend a lot of time in TextMate 2 writing PHP and a lesser amount writing Javascript.

I've always found the Validate Syntax command in Textmate very useful as a final quick sanity check before saving. I was wondering today if there were a way to do something similar for Javascript and I think I've found a solution in acorn:

https://github.com/ternjs/acorn

Running something along these lines:

acorn --silent <file-here>; echo $?

Returns either a 0 if it's valid or a 1 if it's not. If not it also returns an error with the line where the syntax error occurs:

Unexpected token (50:1)
1

Seems like it's almost perfect for use in a simple Validate Syntax command.

But that's where I ran into a brick wall of ignorance. I'm not sure how to get from there to an actual command in TextMate and looking at the PHP example and a few others left me no further along partly because I've got almost no Ruby experience and it appears to that's how commands are usually written in TextMate.

Anyone with more experience writing TextMate commands care to take a pass at it?


Based on Graham's suggestion and additional help here's a working command:

#!/usr/bin/env bash
#Write scope of JS to a temp file
echo "$(</dev/stdin)" > ${TMPDIR}acorn-validation.js;
#Capture output of acorn syntax check (Note that acorn sends the output to STDERR thus the 2>&1)
ACORN_OUTPUT=$( (acorn --silent ${TMPDIR}acorn-validation.js) 2>&1 );

echo 'Running syntax check with acorn...';

if [[ "" == $ACORN_OUTPUT ]]; then
    echo 'No syntax errors detected';
fi

if [[ "" != $ACORN_OUTPUT ]]; then
    #Find the line/column value
    LINE=$(echo $ACORN_OUTPUT | grep -oE '([0-9]+:[0-9]+)';);
    echo '';
    echo 'Syntax error on '${LINE};
    echo ${ACORN_OUTPUT/($LINE)/};
    #Send cursor to the place where the error occured
    LINE=(${LINE//:/ });
    open "txmt://open/?url=file://${TM_FILEPATH}&line=${LINE[0]}&column=${LINE[1]}";
fi

Make sure Input is set to Scope and Output is set to Show in Tool Tip.


Solution

  • Install Acorn globally:

    npm install -g acorn
    

    Find out where acorn been installed:

    which acorn
    

    Mine said (because I use nvm):

    ~/.nvm/versions/node/v6.2.2/bin/acorn
    

    Add that bin folder to your TextMate Path, use a colon to delineate:

    TextMate's Settings - Variables tab with PATH updated

    So my PATH is:

    $PATH:/opt/local/bin:/usr/local/bin:/usr/texbin:/usr/local/bin:$HOME/.nvm/versions/node/v6.2.2/bin:$HOME/.rvm/rubies/ruby-2.3.3/bin
    

    Now open the bundle editor:

    Create a bundle, or open an existing, and press cmd+n to create a new file, select "command" from the dropdown.

    Paste this into the command, cmd+s to save.

    Update: This command has been brought from proof of concept to functional by (OP) Jamie Poitra, so check the question for his script.

    #!/usr/bin/env bash
    acorn ${TM_FILE}
    

    All set.