1

Consider the following C/C++ code

{
    auto x = f(g(h(
                     "aaa")));
}

The "aaa" is indented this way, because c-offset-alist has (arglist-intro . +) (I think that’s the default), which makes it indent one “unit” (4 spaces per my setting) more based on the location of h.

I want the "aaa" to indent based on the beginning of the previous line, like this:

{
    auto x = f(g(h(
        "aaa")));
}

How do I do that?

1 Answer 1

0

Quoting c-offset-alist documentation:

As described below, each cons cell in this list has the form:

(SYNTACTIC-SYMBOL . OFFSET)

[…]

OFFSET can specify an offset in several different ways:

[…]

  • If OFFSET is a function or a lambda expression then it’s called with a single argument containing the cons of the syntactic symbol and the anchor position (or nil if there is none). The return value from the function is then reinterpreted as an offset specification.

So you can write a function that would return + for the first call and 0 for subsequent calls and assign it to arglist-intro, arglist-cont and arglist-intro. They all constitute being part of the parameters in the function, so when within a single line you get 3 of these, you want to ignore all calls but the first one.

I've hacked up some code that seems to do the job. Since indenting may call the function multiple times for a single line, we save the last line number so we can check if it's still the same one and return 0 for subsequent calls. In addition, to make sure a user may successfully call the function subsequently, we add a hook to post-command-hook that resets the line-number. So every time the user re-indents it will return + for the first call and 0 for subsequent ones.

(defvar c-arglist-indent-last-line 0)

(defun calc-c-arglist-indent(_)
  "Returns + for the first call and 0 for subsequent ones. Thus similar
nested \"structures\" will be indented as if there's only one"
  ;; compare the line to check whether we were called here
  (let ((line-num (line-number-at-pos)))
    (if (= line-num c-arglist-indent-last-line)
        0
      (setq c-arglist-indent-last-line line-num)
      '+)))
(c-set-offset 'arglist-cont-nonempty 'calc-c-arglist-indent)
(c-set-offset 'arglist-cont          'calc-c-arglist-indent)
(c-set-offset 'arglist-intro         'calc-c-arglist-indent)

(defun flush-c-argslist-indent-state()
  "Reset `c-arglist-indent-last-line' so the next time user calls
indentation the line will be unset"
  (setq c-arglist-indent-last-line 0))
(add-hook 'post-command-hook 'flush-c-argslist-indent-state())

With this code the following C++ gets indented for me just as you want:

{
    auto x = f(foo,
        "aaa");

    auto x = f(g(foo,
        "aaa"));

    auto x = f(g(h(
        "aaa")));
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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