js2-mode icon indicating copy to clipboard operation
js2-mode copied to clipboard

line break when passing callback messes up indentation

Open catphive opened this issue 12 years ago • 7 comments

this fork of js2-mode normally has nice indentation when using callbacks:

func(arg1, arg2, arg3, function(foo) {
    ...
});

However, if a newline is inserted in the first line (I often need to do this to fit in 80 columns) then indentation of the function boddy gets messed up:

func(arg1, arg2, arg3,
        function(foo) {
                ...
        });

Is there any way to force the first kind of indentation even if there's a newline? I'd prefer it looks like this:

func(arg1, arg2, arg3,
        function(foo) {
    ...
});

catphive avatar Nov 14 '12 00:11 catphive

In our defense, js-mode does the same thing. I guess we could check if our second innermost containing brackets are round and in this case indent lines relative to the line the opening bracket's on, as long as there's no complications.

Do you know an editor that does this your way? I could maybe adapt the algorithm.

dgutov avatar Nov 14 '12 07:11 dgutov

Isn't the right way to indent such expressions as follows?

call(arg1, arg2, arg3,
    function () {
        // ...
    }
);

(Assuming a tab is 4 spaces).

katspaugh avatar Nov 14 '12 07:11 katspaugh

@katspaugh Yes, that's how it currently works. I think OP mistyped somewhere.

dgutov avatar Nov 14 '12 08:11 dgutov

The markdown formatter wasn't using a fixed width font for some reason, so it made things not line up correctly.

Basically, I always want the function body to be indented only 1 level from the containing function. Otherwise any kind of nontrivial function gets unreadable fast. Then there's node js which tends to have multiple levels of nested callbacks...

I'm not sure of other editors that support this, but I've not seen a lot of javascript code that indents function bodies at the levels of arguments, probably due to the readability issue. I'm doing it by hand right now.

catphive avatar Nov 14 '12 22:11 catphive

@catphive I wonder, wouldn't adding a newline before the first argument solve most of the problem?

func(
  arg1, arg2, arg3,
  function(foo) {

  }
);

This gives just one level of added indentation, and as a bonus, lines up all args vertically.

Moving the first arg to a separate line is generally the way to pick between "indent to the function plus 1 level" and "indent to the opening paren" in the current indentation algorithm.

I've not seen a lot of javascript code that indents function bodies at the levels of arguments

Care to give an example?

dgutov avatar Feb 27 '13 20:02 dgutov

I've also been looking for a way to do indentation in the same way @catphive describes.

Perhaps most surprising is that the indentation works as expected as long as the opening curly brace of the callback function is on the same line as the opening paren of the function call:

func(1, 2, function() {
  var x = 42;
});

As soon as the opening curly brace is on the next line, the body of the callback is indented differently:

func(1, 2, function()
     {
       var x = 42;
     });

or more typically:

func(1, 2,
     function() {
       var x = 42;
     });

although we would find the following more readable:

func(1, 2,
     function() {
  var x = 42;
});

It would be okay if the bounce-indent positions allowed hitting that level of indentation, but unfortunately, it does not:

func(1, 2,
     function() {
       var x = 42; // bounce 1
         var x = 42; // bounce 2
var x = 42; // bounce 3
     var x = 42; // bounce 4 and looping to 1
});

I find that it is particularly significant when writing AMD or AngularJS modules:

define(['jquery', 'underscore', 'etc'],
       function() {
  // don't need extra indent here
});

var service = angular.module('someService', []);

service.factory('someFactory',
                ['otherDep', '$injector',
                function(otherDep, $injector) {
  // ditto, don't need extra indent here either
});

Would it be hard to make it an optional indentation behaviour, or to add it to the list of bounce indent levels? Perhaps you could point us to the functions we should be looking at if we were to try and implement it ourselves?

Thanks!

theefer avatar Jun 18 '13 21:06 theefer

The function is js2-proper-indentation, and you should look at its second half, starting with bracket. I guess the main part of the work would be try not to break the other cases this code is handling.

I wish we had some tests for those...

dgutov avatar Jun 19 '13 07:06 dgutov