1

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.

Jamie Poitra
  • 431
  • 4
  • 15

1 Answers1

5

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.

Graham P Heath
  • 7,009
  • 3
  • 31
  • 45
  • Appreciate the help. I suppose some of this was glaringly obvious and I just found some of the TextMate docs on building commands which I somehow missed. Discovered an issue though. $TM_FILE doesn't seem to work I switched it to $TM_FILEPATH: `acorn --silent ${TM_FILEPATH};` except that this returns an env: node: No such file or directory error when I try to run it. Oddly enough if I just echo out the command as a string everything looks fine and it runs fine if I try it in a terminal window. It just doesn't work within TextMate. Any ideas? – Jamie Poitra Aug 17 '17 at 00:17
  • I'm not sure what I had done wrong but it's working now. This has me to the point where I'm approaching what I want. Thanks. – Jamie Poitra Aug 17 '17 at 00:46
  • Glad its working now. Please post back (or feel free to edit) with the improved acorn script, it looks like an interesting tool! – Graham P Heath Aug 17 '17 at 00:59
  • Yeah, I'm working out how to get something that functions closer to the PHP one. I'd like it to drop you off at the line where the syntax error occurred for instance. – Jamie Poitra Aug 17 '17 at 02:44
  • Once you get to a point where you know what line/file that is, have a look at the txmt:// url scheme: https://manual.macromates.com/en/using_textmate_from_terminal.html – Graham P Heath Aug 17 '17 at 16:06
  • Do you have any experience capturing the output of a command to a variable? As I understand it this should work `ACORN_OUTPUT=$(acorn --silent ${TMPDIR}acorn-validation.js;);` but acorn still seems to echo out it's output and the variable ends up empty. – Jamie Poitra Aug 17 '17 at 17:19
  • So definitely something strange going on with acorn that I don't understand. Even this isn't behaving as I'd expect: `acorn --silent ${TMPDIR}acorn-validation.js; > ${TMPDIR}acorn-output` the output from acorn still gets spit out into the terminal window rather than written to the file specified. I'm at a bit of an impasse. :) – Jamie Poitra Aug 17 '17 at 19:23
  • Drop the semicolon to use the `>`. `acorn --silent ${TMPDIR}acorn-validation.js > ${TMPDIR}acorn-output` – Graham P Heath Aug 17 '17 at 19:36
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/152194/discussion-between-graham-p-heath-and-jamie-poitra). – Graham P Heath Aug 17 '17 at 19:37