Hacker News new | past | comments | ask | show | jobs | submit login
Jsfmt – Like Gofmt, but for JavaScript (github.com/rdio)
155 points by jimfleming on May 9, 2014 | hide | past | favorite | 47 comments



The key here is adoption. Go’s adoption of gofmt is that it was there from the start and the community has adopted it.

It’d be great to have it on the JS side too. It’s a question of everyone agreeing that it’s the right one and achieving critical mass.


I think you might be missing the point here. gofmt doesn't only enforce a style guide, it has allowed the Go team to change Go's syntax and automatically update everyone's code.

This tool, to me, looks really useful for updating old javascript codebases - removing old library calls and polyfills — bringing in new native techniques.


Nope, the point about adoption is spot on since you can already do this with esprima and other tools (e.g. substack's falafel/burrito or grasp) which already have a community. Outside of api flavour, they do the same thing. The differentiating factor is primarily which one will have stronger better community support.

My prediction is that since this is "go-flavoured", it will face some (unwarranted) adoption resistance amongst influential JS devs. This tool might attract new devs into the code manipulation space and they'll eventually converge on to the tool with strongest community support.


Well it's both really. The formatting fixes offered by gofmt are definitely a popular success. You always hear/read about how great it is to have completely removed the code formatting debates (and it is).


> it has allowed the Go team to change Go's syntax and automatically update everyone's code

That's go fix.


Gofix does the work, but it is only feasible because gofmt exists.


I think its more that the language enforces some formatting to a degree. Other languages are very free form in how you can structure your style and where to place your curly brace. In go it is a compiler error to deviate from their style.


It actually isn't a compiler error in Go to deviate from gofmt's specification* but it is a widely enforced rule in the community. Most major Go projects use gofmt and any Go code, such as the built-in libraries, are gofmt'ed. You're fighting against the tide if you format otherwise.

Given that, jsfmt doesn't need 100% adoption: using it in a single project or library would still be useful. Stating new contributions must be jsfmt'ed would be less trouble than most standard pull request requirements (pass + update any relevant testing code, ...).

I personally love these formatting tools and am looking forward to more of them, such as ClangFormat[1].

* You might be thinking of unused variables or imports resulting in compiler errors, which isn't the same as not compiling due to formatting?

[1]: http://clang.llvm.org/docs/ClangFormat.html


What I was referring to is curly brace placement.

func main() { }

vs

func main() { }

which produces the error "prog.go:4: syntax error: unexpected semicolon or newline before {". As I understand it this is because of the rules of where it will insert semicolons. It isn't enforcing everything about the format which is why I said "to a degree" but it is still one of the most opinionated compilers on format that I know of.

Either way, I'm glad they did it. The "where should the curly brace go" is one of the most annoying bike-sheds.


In case anyone else thinks they're insane, the two are the same. The second one should have been

    func main()
    {
    }


Oh thanks! Not sure how it got trashed.


How automatic semi-colon insertion works causes braces to be on the same line as a function signatures/ifs/switches/etc.

This program won't compile: http://play.golang.org/p/8DSev4ZjWZ


The clang-format tool from the LLVM project can also format Javascript. It's similarly AST-aware.

Reference: http://clang.llvm.org/docs/ClangFormatStyleOptions.html, heading "Language".


For a tool dedicated to searching and replacing JS in this way (AST aware), check out http://graspjs.com

You can use both CSS style selectors, and pattern matching, to both search and replace your code.


> js = jsfmt.rewrite(js, "_.each(a, b) -> a.forEach(b)");

Of course _.each handles objects (not just arrays) and returns its input (where Array#forEach returns undefined), and there does not seem to be any type-based conditions (or otherwise) so you've got a souped-up sed, not something you can add to any sort of automated workflow.


As far as I understand go fmt works on the AST, if your reformatter doesn't work on the AST then you will eventually have problems.

Also go fmt doesn't ever change your code, thats what go fix is for.


> As far as I understand go fmt works on the AST, if your reformatter doesn't work on the AST then you will eventually have problems.

JsFmt also works on the AST. Working on the AST does not mean your rewrite rules can be bulletproof, let alone are.


From the readme:

> Javascript formatters exist but most (all?) work on just strings, not the AST. Using Esprima under the hood we have access to the full AST and can do useful things like intelligent find and replace as in gofmt.


gofmt -r applies rewrite rules, and -s also performs source transformations; both change the code.


gofmt without flags does not change your code. Yes, you can ask it to change your code if you want it to, but by default, it won't.


You're correct it doesn't have type support which would make it vastly more useful. I honestly wasn't aware `forEach` returned anything when I wrote the example. The other example finding component dependencies is a little more realistic.


Also native `forEach` tends to be slower and not fully supported in all environments, so that rule seems to be pretty dangerous in general.


This is neat. I've created something equivalent for Markdown, and decided to post it today:

https://news.ycombinator.com/item?id=7724159

After getting so used to gofmt-on-save (err, rather goimports-on-save now), I find it very odd when I edit other file types and nothing happens to the obvious mis-formatting when I save. So I'm a big supporter of any new formats coming out in the future to come with some sort of similar automated formatter tool.

One important aspect that allows gofmt to succeed with effectively full adoption is that it still allows for (limited, but nice looking) custom formatting. If you want an extra newline between two lines, it will be preserved. It gives enough freedom that always having it on is quite acceptable.


This is really interesting. But wouldn't it work better as an Emacs or Vim plugin?

It ought to work at the editor level, and would be really easy to make this work with Emacs with a little lisp magic and the Emacs js interpreter.


This is an equally valid criticism of `gofmt`. I think the rational is two-fold: you aren't tied to any one editor to use the formatting tool, and the authors of the fmt tool may not know enough (or care to know enough) about the editor to integrate it.


It's nice that the go distribution comes with editor integrations though. It would be nice if there was a similar standard toolset for js that you could get up and running with if you were new to it.


UNIX philosophy. Do one thing right. Editor integration is a second thing.


Some of the go developers are also acme users so they get both. The Plan9 philosophy, I guess.


I can't speak to emacs, but vim has no problems with a program like this operating on the BufWritePre event. I use whitespace trimming and js-beautify that way already. This may or may not do a better job than js-beautify for it. I have it set as the equalprg so that vim will use beautify to format code on = when a visual selection is made.

From my vimrc:

> au FileType javascript setlocal equalprg=/usr/local/share/npm/bin/js-beautify\ -f\ -\ -q\ -t\ -j\ -w\ 140\ --good-stuff\ -b\ \"end-expand\"

edit: The same event (BufWritePre) is what I've got set for go fmt too. That IS a plugin, but it makes no significant difference as compared to js-beautify.


emacs js2-mode uses recursive-descent parser to build up js ast with full recognition of Ecma-262 language standard and exposes ast for use in other pugins

https://github.com/mooz/js2-mode/blob/master/js2-mode.el

11k amazing loc


Using it right now.

One of my favorite things installed on my computer.


Yes. Many thanks to Steve Yegge. js2-mode is why I use emacs.


Plugin? Both Emacs and Vim make it trivial to round-trip a buffer through an external command.


A command line utility can form the basis of an editor plugin. Go/vim users typically run `gofmt` on save, and the reformatted code appears within the editor.


It works better as a standalone tool because then everyone can use it.


     /**
      * Sets the light position for drawing.
      */
    -Isomer.prototype.setLightPosition = function (x, y, z) {
    +Isomer.prototype.setLightPosition = function(x, y, z) {

    ...

       var yMap = new Point(point.y * this.scale * Math.cos(Math.PI - this.angle),
    -                    point.y * this.scale * Math.sin(Math.PI - this.angle));
    +  point.y * this.scale * Math.sin(Math.PI - this.angle));
No thanks :( In all seriousness, cool library. What standard does it follow? Can't seem to find that anywhere.


Currently, its based on esformatter[0]. Most of the work so far has gone into search and replace and we don't yet expose many of the properties provided by esformatter[1].

[0] https://github.com/millermedeiros/esformatter [1] https://github.com/millermedeiros/esformatter/blob/master/li...


I really miss being able to search comments or code in Metrowerks Codewarrior. I wish there was a plugin for that in Xcode (a formatter would also be nice, its copy and paste is a little wonky for things like blocks and literals shorthand).


A package for atom.io and a grunt-plugin would be nice.


Here is the grunt plugin I started.

https://github.com/james2doyle/grunt-jsfmt


Why don't you write one?


That's rarely a productive question to ask.

It's just a slight variation on the totally unhelpful "Why don't you fix the bug yourself?" response that's sometimes given to people reporting a problem with an open source project.

They're useless questions because the answer is pretty much irrelevant.

Maybe he doesn't know how. Maybe he isn't qualified. Maybe he doesn't have the time. Maybe he doesn't have the money to fund somebody else doing it. Maybe he just doesn't want to.

It doesn't matter why he might not do it himself. But that in no way means he shouldn't publicly express such interest in such functionality, in case there is somebody else who is willing or interested in adding it.


Well, while we're being pedantic, publicly expressing an "interest in such functionality" deep in some HN thread is roughly as productive as asking him directly why he doesn't scratch his own itch.

This whole notion that saying "patches welcome" is insulting/dismissive/pointless is completely missing the point. Open Source mostly runs on people doing, not pontificating. It may be "unprofessional" or "rude" in other contexts, but it's a fundamental part of what makes Open Source work. I suspect you've never actually spent any considerable time working on such a project, otherwise you'd most likely have seen things from the other perspective and realized this already.


This is awesome. I want this for ruby.


+1 so hard my keyboard almost broke

Every language needs this except lisp and python :)

Note that the one trick gofmt has over say indent is that it truly understands go syntax. It's not just a pretty printer


Serious question: why not python?


No braces?




Join us for AI Startup School this June 16-17 in San Francisco!

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: