11

I'm currently working on a JavaScript project using Backbone.js and I wonder how can I navigate between files, based on method and object definitions.

For example, I keep references to some of my views in the global object App.Views, and I would like to be able to navigate to each individual definition (App.Views.Home, App.Views.SomePage, etc.) if I encounter one. Also, there are a lot of closures used for avoiding namespace leaking, and I want to know how can I automatically follow these definitions.

I've seen tern but there are not many examples on how to configure it so I have not been able to do much.

What are some good tools for this?

itsjeyd
  • 14,586
  • 3
  • 58
  • 87
caisah
  • 4,056
  • 1
  • 23
  • 43
  • 1
    "... but there are not many examples on how to configure it ..." -- Under the "Documentation" heading on the `tern` home page it says "The reference manual should be your first stop for **figuring out** how to use Tern." At least they're honest o.O – itsjeyd Nov 04 '14 at 22:24

1 Answers1

9

I would absolutely recommend tern. I discovered it halfway through my internship (working in Node.js) last summer, and it worked wonderfully with company-mode and js2-mode.

js2-mode by itself is quite powerful. It can handle the usual M-. jumping within a file most of the time, and tern complements it nicely with inter-file/module jumping (esp. in the node ecosystem).

The first step to using tern is installing the binary. I personally used npm to do so:

$ sudo npm install -g tern

Then install in Emacs. The relevant section from my init.el is:

;;; tern
(package-require 'tern)
(add-hook 'js2-mode-hook (lambda () (tern-mode t)))

The final step is to set up a .tern-project file in the root directory of your project. For Node.js projects, I use this as a starting point:

{
    "loadEagerly": [
        "src/**.js"
    ],
    "plugins": {
        "node": {
        }
    }
}

If you use company-mode, then installing company-tern is also highly recommended:

(package-require 'company-tern)
(eval-after-load 'company
    '(add-to-list 'company-backends 'company-tern))

As a note, I did have some trouble with the tern server occasionally dying this past summer (2014). Running the following fixed it consistently:

M-: (delete-process "Tern") RET

I wasn't able to figure out exactly what was causing it, but it happened infrequently enough to be little more than a nuisance.

References:

J David Smith
  • 2,635
  • 1
  • 16
  • 27
  • This looks pretty much like the configuration I got. The thing is I'm almost always prompted with *No definition found*. That's why I thought there may be something wrong with my configuration. For example, in one file I have `app.eventBus = _({}).extend(Backbone.Events);` and in another I have `app.eventBus.trigger("changeURL","");`. But when I do `tern-find-definition` for my latter `eventBus` I get *No definition found*. Is there something I do wrong, or is just `tern` not supporting the kind of behaviour I imagine it would support? – caisah Nov 05 '14 at 16:36
  • With some frontend frameworks it has issues. It was almost always unable to figure out what to do with Angular (although I avoided the Angular bits and didn't try to figure out how to make it work with them). If the files are not referencing each other via RequireJS-style calls then you'll have to do more digging. It looks like [somebody got it working (?)](https://github.com/marijnh/tern/issues/95) but I don't have enough experience with that to tell. – J David Smith Nov 05 '14 at 19:12