Kate: “C++/boost Style” Indenter

Greetings from the Kate land again. This time, Alex Turbov will spend a few words about his “C++/boost Style” indenter that is part of Kate Part for several releases.

The Initial Motivation

This indenter (initially) was designed to help code typing in a “boost::mpl” style (i.e. with leading comma in formatted (template) parameters list). One may read the rationale of such approach in the “C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond” by David Abrahams and Aleksey Gurtovoy. It is really easy to miss a comma when invoke metafunctions and it usually leads to a lot of complicated compile errors. The indenting technique should help to visualize the control syntax and prevent stupid errors like missed commas.

Small example:

typedef typename boost::mpl::fold<
    typename boost::mpl::transform_view<
      , boost::remove_pointer
  , boost::mpl::long_
  , boost::mpl::eval_if<
      , boost::mpl::_2
      , boost::mpl::_1
  >::type type;

In practice I’ve noticed that this style can be used to format long function calls or even `for` statements. Actually everything that can be split into several lines could be formatted that way. And yes, it is convenient to have a delimiter (comma, semicolon, whatever) as a leading character to make it visually noticeable.

// Inheritance list formatting
struct sample
  : public base_1
  , public base_2
  , ...
  , public base_N
    // Parameter list formatting
    void foo(
        const std::string& param_1                      ///< A string parameter
      , double param_2                                  ///< A double parameter
      , ...
      , const some_type& param_N                        ///< An user defined type parameter
        // Split `for` parts into few shorter lines
        for (
            auto first = std::begin(param_1)
          , last = std::end(param_1)
          ; it != last && !is_found && !is_exit_requested
          ; ++it
            auto val = check_some_condition()
              ? get_then_value()
              : get_else_value()

It looks unusual for awhile :) but later it becomes (quite) normal and easy to read and edit :) Really! When you want to add one more parameter to a function declaration it takes less typing if compare to a “traditional” way :) (especially if you have some help from an editor, like move/duplicate the current line or a selected block up/down by a hot-key or having an indenter like this :)

Next improvements was designed to simplify typing C++ code, using most common syntactic rules, like:

Further improvements bring to the indenter some cute features and nowadays I’d prefer to consider it similar to a T9 (input method) for C++ coding, but not as a “real indenter” in contrast to others, shipped with kate out of the box :) Particularly this indenter “exploit” can see “impossible” syntax and (try to) transform it to something “reasonable” — i.e. just like T9 it tries to be a predictive.

For example, if you have autobrackets plugin turned ON, when typing `some(nested(` gives you `some(nested(|))` w/ `|` indicating a current cursor position. If you press `,` at this position, it gives you the following snippet `some(nested(), |)` supposing that you want to add one more parameter to a `some()` call. While typing `;` looks like you’ve done with that nested calls and gives you the `some(nested());|` snippet. Both cases help you to avoid couple of redundant key presses ;)

… but do not even try to use this indenter to (re)format blocks of code! :) It can do some really simple/primitive formatting, but far from good — as I’ve mentioned above: this “not quite indenter”™ designed to help you to __”do little more with less typing”__ for C++ ;)

Some of the Features

some_call_with_long parameters_list(|param1, …, paramN); // Comment starts here… // After pressing ENTER: keep comment at the original line some_call_with_long parameters_list( // Comment starts here… |param1, …, paramN);

    <span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">Also try to use _ENTER_ in the middle of a comment text ;-)</span></li> 
      * <pre><span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">typing `///` gives you `/// ` (with a space) or `///&lt; ` depending on presence of code at the current line</span></pre>
      * <span style="font-family: Georgia, 'Times New Roman', 'Bitstream Charter', Times, serif; font-size: 13px; line-height: 19px;">from time to time I use grouping in a doxygen documentation, so typing `//@` gives you:</span> 

| //@}

      * always add a space after \`,\` character &#8212; simple, but really convenient! really soon you&#8217;ve stopped typing a space after any comma and feel yourself inconvenient with other indenters ;)
      * typing \`<\` without a space after some identifier adds a closing angle bracket (like notorious autobrackets plugin do for other bracket types), because template instantiation guessed. So typing \`std::vector<|\` gives you \`std::vector<|>\`. But \`std::cout<|>\` turns into \`std::cout << |\` after pressing one more \`<\` ;-)
      * a lot punctuation characters being typed withing parenthesis is a some operator (or at least part of), so will be moved out of parenthesis (most likely call expression). Try to type various punctuators at marked position in the following snippet \`some(|)\`&#8230;
      * typing a backslash in on a line of a long \`MACRO\` definition cause realign all others to fit to a longest line: 
        <pre>#define PP_FORM_A_ROW(State, Data, Elem)    \

, manage_config_keys::action::GET

      * * typing \`R&#8221;\` will initiate a raw string literal</ul> 
    This advanced indenter  has some other (smaller) features to reduce typing. Hope, you&#8217;ll like them if found! ;)
    PS: The other things I&#8217;ve found useful when typing C++ code can be plugged with some Python plugins dedicated to C++.
Tags:  planet 

See also: