5

So emacs's java-mode handles indenting continued method invocations at the function body level out of the box, but it doesn't seem to handle them inside of an argument list. I'd like to override this behavior. I'm aware of C-c C-s, but in this particular example both the line that begins with Other and the line that begins with .newBuilder() are arglist-cont. I'd like to distinguish between these two cases. In the function-level example .newBuilder() is statement-cont, so that's why it's getting indented correctly. (I just realized that I do actually have (arglist-intro . +) set in my current style so that is why args[0] is getting indented once instead of aligning to the preceding parenthesis, but even without that setting, the .newBuilder() line still aligns with the other arguments instead of indenting one additional level.)

public class Foo {
    void main(String[] args) {
        /* This works just fine */
        Other
            .newBuilder()
            .fluent1()
            .fluent2()
            .build();
        /* This is how it works currently. */
        someMethodThatTakesOther(
            args[0],
            args[1],
            Other
            .newBuilder()
            .fluent1()
            .fluent2()
            .build());
        /* This is what I would like. */
        someMethodThatTakesOther(
            args[0],
            args[1],
            Other
                .newBuilder()
                .fluent1()
                .fluent2()
                .build());
    }
}
4

Disclaimer: I'm not that familiar with cc-mode styles, so there might be simpler ways to do that, and also unforeseen side-effects to my code.

(defun my-java-lineup-cascaded-calls (langelem)
  (save-excursion
    (back-to-indentation)
    (let ((operator (and (looking-at "\\.")
                         (regexp-quote (match-string 0))))
          (stmt-start (c-langelem-pos langelem)) col)

      (when (and operator
                 (looking-at operator)
                 (zerop (c-backward-token-2 1 t stmt-start)))
        (if (and (eq (char-after) ?\()
                 (zerop (c-backward-token-2 2 t stmt-start))
                 (looking-at operator))
            (progn
              (setq col (current-column))

              (while (and (zerop (c-backward-token-2 1 t stmt-start))
                          (eq (char-after) ?\()
                          (zerop (c-backward-token-2 2 t stmt-start))
                          (looking-at operator))
                (setq col (current-column)))
              (vector col))
          (vector (+ (current-column)
                     c-basic-offset)))))))

(add-to-list 'c-offsets-alist '(arglist-cont . my-java-lineup-cascaded-calls))

Explanation: this is a modified version of c-lineup-cascaded-calls that does almost what you want except that it aligns stuff like

a.foo()
 .bar()

So this code does that too, but in addition, when we're looking at the dot and we should not align like above, then we add an indentation level.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.