Monday, April 28, 2008

Indent


Content
=======
        1 Purpose:
        2 Psychological Factors:
                2.1 Pattern Recognition
                2.2 Switching between context/controls
                2.3 Eye movement
                2.4 Looking ahead
                2.5 Looking back
                2.6 Be consistent
                2.7 There's no one true style
        3. Techniques
                3.1 Spacing the Code
                        3.1.1 Horizontal Spacing
                        3.1.2 Vertical Spacing
                3.2 Grouping with Brace
                3.3 Positioning the Code Blocks
        4. Examples:
        5. Profile File
        6 References:

1 Purpose:
==========
        The prime purpose to convey the structure of the program to human readers in better and clear form.
        This is to help in better productivity, quality, maintainability and understandability

2 Psychological Factors:
========================

2.1 Pattern Recognition
-----------------------
        We survive in this world not by recognizing complete situations, nor by analyzing each situation from scratch, but by fitting the world into established recognizable patterns. For example in programming, the following represents traversing a list:
        while ( pTemp != NULL )
        {
                // Some Statements
                pTemp = pTemp->next;
        }
        
        Once patterns are in place it is very easy to **Filter** or **Search** for a pattern.

2.2 Switching between context/controls
--------------------------------------
        When you are talking about something, and get interrupted (and parentheses in a sentence like this is just such an example) then what you were thinking about before the interruption goes onto a 'mind stack'. Successive interruptions cause the previous context to be pushed onto the stack, and popped off again only when the interruption is completed.
        Similarly in the programming world, the code is split into contexts and controls. Usually the contexts are split using the braces and indentation.

2.3 Eye movement
----------------
        When you are reading, your eyes move from left to right and top to bottom
(unless, of course, you are Arabic or Chinese!). However, when you are reading fast, or scanning for a particular item (such as looking for a particular variable in a code procedure), the eyes skip, and prefer to move in a downwards direction only.
        Lesser the characters on the line, the more faster we read.

2.4 Looking ahead
-----------------
        When we drive we look well ahead, so we can be ready for any hazard. Similarly, as we are reading, we tend to peek ahead to absorb the context ahead of the current reading point. If it is laid out nicely, and everything looks familiar, then we relax and read comfortably at our own rate. If, however, the text ahead looks dense or unfamiliar, we tense up and start to think negatively. We are more likely to misunderstand and make mistakes if things look difficult and we are expecting to err.
        Thus, with the use of a consistent programming style, the reader is comforted simply by the 'look' of the code and can relax and concentrate on the current fragment.

2.5 Looking back
----------------
        When we reading something, particularly for the first time, and especially if we are trying to understand or learn it, we don't just read it once. We continually skip back and re-read chunks, particularly the difficult bits. There are flags in the written language to allow us to find the start of chunks, even when looking backwards. The capital at the start of a sentence helps. Splitting the text into paragraphs, with the first word indented, help too.
        The programming equivalent is to make the start of the statement group, block or function easier to find, by using white space, braces or comment blocks.

2.6 Be consistent
-----------------
        Changing the way things are done is a certain way to cause confusion in the reader, and could lead to serious error. When a style is chosen, it must be used consistently.
        The consistency principle applies to all elements of style, including naming, commenting, layout and usage. It should also be applied to the selection of standards. If, for example, one brace style is selected, then the same style should be used for both code blocks and declarations (including struct's, union's and enum's).

2.7 There's no one true style
-----------------------------
        There is no such thing as a 'correct' style. There are almost as many styles as there are programmers. Some are more sensible than others, but there is no one style that can be clearly agreed upon as being the best style to use.
        But in the end, one style must be chosen. You have to say, "This is the style that we will use. We have argued over which one to use, and the consensus is that this is it". Doubters and dissenters may have to be persuaded or coerced, for although your style is not perfect, it has been chosen to be standard.
        A maintenance note: If you happen to be changing a program that does not use your style, then the professional approach is to use the style that the program uses, rather than to use your normal style. Maintaining poor style is difficult enough - maintaining several styles at once is hell!

3. Techniques
=============

3.1 Spacing the Code
--------------------
3.1.1 Horizontal Spacing
        Spacing the code increases readability by identifying the tokens in the statement. However, using more space cost you the horizontal line. A simple rule could be used:
        a. No space with object reference. Eg: pObj->member, Obj.member
        b. No spaces between unary operators and their operands. Eg: *ptr, ++i, -num
        c. All other binary operators have an equal number of spaces either side.

Indent Options:
        a. Put a space between sizeof and its argument. --blank-before-sizeof
        b. Put a space after a cast operator. --space-after-cast
        c. Insert a space between the name of the procedure being called and the
`('. --space-after-procedure-calls
        d. Put a space after every '(' and before every ')'.
--space-after-parentheses
        e. Put a space after each for. --space-after-for
        f. Put a space after each if. --space-after-if
        g. Put a space after each while. --space-after-while
        h. On one-line for and while statments, force a blank before the semicolon.
--space-special-semicolon

3.1.2 Vertical Spacing
        One means of providing a context is grouping similar statements together and differentiating between groups by a new lines:

Indent Options:
        a. Split the declarations and code. Force blank lines after the declarations. --blank-lines-after-declarations
        b. Force blank lines after procedure bodies. --blank-lines-after-procedures
        c. Force blank lines before block comments. Usually block comments are use for a sequence of statements performing a particular task.
--blank-lines-before-block-comments
        d. When compared to
                int nLenSentence, nI;                and
                int        nLenSentence,
                        nI;
                In the former, it is easier to search for "nI". Force newline after comma in declaration. --blank-lines-after-commas

3.2 Grouping with Brace
-----------------------
        Besides Vertical Spacing, another means of grouping is using Code Body Block, after branching controls.

Indent Options:
        a. Put braces on line after if, etc. --braces-after-if-line
        b. Put braces on the line after struct declaration lines.
--braces-after-struct-decl-line
        c. Group the while in do-while with the close brace. --dont-cuddle-do-while
        d. don't group the brace with else. --dont-cuddle-else
        e. For block comments, it easier to identy comments when the begin with a star. Put the ‘*’ character at the left of comments. --start-left-side-of-comments


3.3 Positioning the Code Blocks
-------------------------------
        Indentation is one major tools to define structural and control code blocks. Positioning of the braces also helps in maintaining the start and end of the code blocks.

Indent Options:
        a. Zeroth law, use tabs instead of spaces. None is interested to key in 4 spaces when compared to a tab. --use-tabs
        b. Usually a tab is considered to be 8 spaces, this will waste a lot of line space, hence specify the tab size to 4. --tab-size4
        c. Each level/hierarchy should be indented by 4 again. Set indentation level to 4 spaces. --indent-level4
        d. Put comments to the right of code in column 41. --comment-indentation41
        e. By default the case body brace is put 2 characters after the case. Indent braces after a case label 0 spaces. --case-brace-indentation0
        f. Put comments to the right of the declarations in column 41.
--declaration-comment-column41
        g. It is important to know that comment has ended, which can be identified by using the comment delimiter on a new line. Put comment delimiters on blank lines. --comment-delimiters-on-blank-lines
        h. Set maximum size of a single line to 80 characters. --line-length80
        i. The above sets the line size for a non-comment line. Set maximum size of a single comment line to 80 characters. --comment-line-length80
        j. Best place to break a long line would be binary operator. Prefer to break long lines before boolean operators. --break-before-boolean-operator
        k. When a huge line is broken (which does not contain a parenthesis), then align the next line by an offset of 4 spaces. --continuation-indentation4
        l. When a huge line is broken (which does contain a parenthesis), then align with open parenthesis. --continue-at-parentheses
        m. If you use the `-bl' option, you must specify the `-bli' option. This option specifies the number of spaces by which braces are indented. `-bli2', the default, gives the result below:
                        if (x > 0)
                         {
                                x--;
                         }

                `-bli0' results in the following:
                        if (x > 0)
                        {
                                x--;
                        }
                Indent braces 0 spaces, --brace-indent0
        n. Case label indent of 4 spaces. --case-indentation4
        o. Similarly, the brace for case should also be 0 indented. Indent braces after a case label 0 spaces. --case-brace-indentation0
        p. Similarly, the brace for struct should also be 0 indented. Indent braces of a struct, union or enum 0 spaces. --struct-brace-indentation0

3.4 Changing some Default Settings of indent
        a. By default GNU Style is used for functions --dont-break-procedure-type
        b. To format all the comments use --format-all-comments and
--format-first-column-comments

4. Examples:
============
$ indent --blank-before-sizeof
INPUT:
sizeof(int);

OUTPUT:
sizeof (int);

******************************
$ indent --space-after-cast
INPUT:
(int)'a';

OUTPUT:
(int) 'a';

******************************
$ indent --space-after-procedure-calls
INPUT:
foo(10);

OUTPUT:
foo (10);

******************************
$ indent --space-after-parentheses
INPUT:
(a+b)*c*((x-y)*(x-y));

OUTPUT:
( a + b ) * c * ( ( x - y ) * ( x - y ) );

******************************
$ indent --space-after-for
INPUT:
for(;;);

OUTPUT:
for (;;);

******************************
$ indent --space-after-if
INPUT:
if(1);

OUTPUT:
if (1);

******************************
$ indent --space-after-while
INPUT:
while(0);

OUTPUT:
while (0);

******************************
$ indent --space-special-semicolon
INPUT:
for(initial_state;loopig_condition;increment);
while(looping_condition);

OUTPUT:
for (initial_state; loopig_condition; increment) ;
while (looping_condition) ;

******************************
$ indent --blank-lines-after-declarations
INPUT:
int a = 10;
int b = 20;
int c;
c = a + b;

OUTPUT:
int a = 10;
int b = 20;
int c;

c = a + b;

******************************
$ indent --blank-lines-after-procedures
INPUT:
void foo ( )
{
        /* Do Something */
}
void bar ( )
{
        /* Do yet another thing */
}

OUTPUT:
void
foo ()
{
/* Do Something */
}

void
bar ()
{
/* Do yet another thing */
}

******************************
$ indent --blank-lines-before-block-comments
INPUT:
end_of_sequence_statements_performing_task_A;
/*
* Task B
*
* Some Alogorithms is mentioned
* Step 1: Blah
* Step 2: Blah Blah
* Step 3: More Blahs
*/
step_1;
step_2;
step_3;

OUTPUT:
end_of_sequence_statements_performing_task_A;

/*
* Task B
*
* Some Alogorithms is mentioned
* Step 1: Blah
* Step 2: Blah Blah
* Step 3: More Blahs
*/
step_1;
step_2;
step_3;

******************************
$ indent --blank-lines-after-commas
INPUT:
int nLenSentence = 0, nI;

OUTPUT:
int nLenSentence = 0,
nI;

******************************
$ indent --braces-after-if-line
INPUT:
if ( condition ) {
        some_statement;
}

OUTPUT:
if (condition)
{
some_statement;
}

******************************
$ indent --braces-after-struct-decl-line
INPUT:
struct someStruct {
        int int_member;
        char char_member;
};

OUTPUT:
struct someStruct
{
int int_member;
char char_member;
};

******************************
$ indent --dont-cuddle-do-while
INPUT:
do
{
        body_of_loop;
        increment;
} while ( looping_condition );

OUTPUT:
do
{
body_of_loop;
increment;
}
while (looping_condition);

******************************
$ indent --dont-cuddle-else
INPUT:
if ( cond )
{
        do_something;
} else
{
        do_nothing;
}

OUTPUT:
if (cond)
{
do_something;
}
else
{
do_nothing;
}

******************************
$ indent --comment-indentation41
INPUT:
sum=operaand1+operand2;        /* Adds two operands */

OUTPUT:
sum = operaand1 + operand2;                                /* Adds two operands */

******************************
$ indent --case-brace-indentation0
INPUT:
switch ( value )
{
case const1:
                {
                        do_something;
                }
                break;
}

OUTPUT:
switch (value)
{
case const1:
{
do_something;
}
break;
}

******************************
$ indent --declaration-comment-column41
INPUT:
int nLenWord = 0;        /* No of characters in word */

OUTPUT:
int nLenWord = 0;                                                /* No of characters in word */

******************************
$ indent --line-length80
INPUT:
if ( ( ( date.year % 4 ) == 0 && ( date.year % 100 ) != 0 ) && date.month == 2 && date.day == 29 )
{
        do_some_valid_operation;
}

OUTPUT:
if (((date.year % 4) == 0 && (date.year % 100) != 0) && date.month == 2
&& date.day == 29)
{
do_some_valid_operation;
}

******************************
$ indent --line-length80 --break-before-boolean-operator --continuation-indentation4
INPUT:
bValidDay = ( ( date.year % 4 ) == 0 && ( date.year % 100 ) != 0 ) && date.month == 2 && date.day == 29 ;

OUTPUT:
bValidDay = ((date.year % 4) == 0 && (date.year % 100) != 0) && date.month == 2
&& date.day == 29;

******************************
$ indent --line-length80 --break-before-boolean-operator --continuation-indentation4 --continue-at-parentheses
INPUT:
bValidDay = ( ( ( ( date.year % 4 ) == 0 ) && ( ( date.year % 100 ) != 0 ) ) && ( date.month == 2 ) && ( date.day == 29 ) );

OUTPUT:
bValidDay = ((((date.year % 4) == 0) && ((date.year % 100) != 0))
                 && (date.month == 2) && (date.day == 29));

******************************
$ indent --braces-after-if-line --brace-indent0
INPUT:
if ( cond ) {
        do_something;
}

OUTPUT:
if (cond)
{
do_something;
}

******************************
$ indent --braces-after-struct-decl-line --struct-brace-indentation0I
INPUT:
struct someStruct {
        int a;
        char b;
};

OUTPUT:
struct someStruct
{
int a;
char b;
};

******************************

5. Profile File
===============
        If you find that you often use indent with the same options, you may put those options into a file named ‘.indent.pro’. indent will look for a profile file in three places. First it will check the environment variable INDENT_PROFILE. If that exists its value is expected to name the file that is to be used. If the environment variable does not exist, indent looks for ‘.indent.pro’ in the current directory and use that if found. Finally indent will search your home directory for ‘.indent.pro’ and use that file if it is found. This behaviour is different from that of other versions of indent, which load both files if they both exist.

        The format of ‘.indent.pro’ is simply a list of options, just as they would appear on the command line, separated by white space (tabs, spaces, and newlines). Options in ‘.indent.pro’ may be surrounded by C or C++ comments, in which case they are ignored.

********** COPY THE BELOW IN .indent.pro file
--blank-before-sizeof
--space-after-cast
--space-after-procedure-calls
--space-after-parentheses
--space-after-for
--space-after-if
--space-after-while
--space-special-semicolon

--blank-lines-after-declarations
--blank-lines-after-procedures
--blank-lines-before-block-comments
--blank-lines-after-commas

--braces-after-if-line
--braces-after-struct-decl-line
--dont-cuddle-do-while
--dont-cuddle-else
--start-left-side-of-comments

--use-tabs
--tab-size4
--indent-level4
--comment-indentation41
--case-brace-indentation0
--declaration-comment-column41
--comment-delimiters-on-blank-lines
--line-length80
--comment-line-length80
--break-before-boolean-operator
--continuation-indentation4
--continue-at-parentheses
--brace-indent0
--case-indentation4
--case-brace-indentation0
--struct-brace-indentation0

--dont-break-procedure-type
--format-all-comments
--format-first-column-comments
************* COPY TILL THE ABOVE LINE TO .indent.pro

6 References:
=============
        a. C Style: Standards and Guidelines        -        http://syque.com/cstyle/
        b. Indent Style (Wikipedia)        -        http://en.wikipedia.org/wiki/Indent_style
        c. Indent Man Pages        -        http://www.linuxmanpages.com/man1/indent.1.php

This document is licensed under the Creative
Commons Attribution 3.0 Unported License (
http://creativecommons.org/licenses/by/3.0/ )

No comments: