Search code examples
perlemacsindentationternary-operatorcperl-mode

Can I customize the indentation of ternary operators in emacs' cperl-mode?


In emacs cperl-mode, ternary operators are not treated specially. If you break them over multiple lines, cperl-mode simply indents each line the same way it indents any continued statement, like this:

$result = ($foo == $bar)  ? 'result1' :
    ($foo == $baz)  ? 'result2' :
        ($foo == $qux)  ? 'result3' :
            ($foo == $quux) ? 'result4' : 
                'fail_result';

This is not very readable. Is there some way that I can convince cperl-mode indent like this?

$result = ($foo == $bar)  ? 'result1' :
          ($foo == $baz)  ? 'result2' :
          ($foo == $qux)  ? 'result3' :
          ($foo == $quux) ? 'result4' : 
                            'fail_result';

By the way, code example from this question.

EDIT

There seems to be a bug in cperl-mode's indentation of ternary operators. Take the following example, which was indented using Emacs 23.1.1, cperl-mode version 5.23:

my $result = ($foo == $bar)  ? 'result1' :
  ($foo == $baz)  ? 'result2' :
  ($foo == $qux)  ? 'result3' :
  ($foo == $quux) ? 'result4' :
  'fail_result';

{
  my $result = ($foo == $bar)  ? 'result1' :
    ($foo == $baz)  ? 'result2' :
      ($foo == $qux)  ? 'result3' :
        ($foo == $quux) ? 'result4' :
          'fail_result';
}

Notice that outside any braces, I basically get the indentation I want. But inside braces, the ternary operator is indented badly. Is there a fix for this?


Solution

  • What version of cperl-mode and Emacs are you using? In GNU Emacs 23.1, cperl-version 5.23, with no init file, I get:

    $result = ($foo == $bar)  ? 'result1' :
      ($foo == $baz)  ? 'result2' :
      ($foo == $qux)  ? 'result3' :
      ($foo == $quux) ? 'result4' :
      fail_result;
    

    If I want them to line up under the first, I'd add an extra set of parens:

    $result = (($foo == $bar)  ? 'result1' :
               ($foo == $baz)  ? 'result2' :
               ($foo == $qux)  ? 'result3' :
               ($foo == $quux) ? 'result4' :
               fail_result);
    

    I'm pretty sure that achieving your requested indentation (with fail_result lining up with the 'result' strings) would require some non-trivial changes to cperl-mode's indentation engine. You're welcome to try it, though. :-)