Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations IamaSherpa on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

How to nicely format program code for posting in the forum 8

Status
Not open for further replies.

Mike Lewis

Programmer
Jan 10, 2003
17,516
Scotland
When posting messages in the forum, it is very common to include snippets of program code - see example, below. (Note: the actual code I'm showing here is not important. The point I want to make concerns the appearance of the code. I chose this snippet at random from another thread, and no criticism is intended of the code itself or the person who originally posted it.)

Define Class TimeTimer as Timer
Interval=1000 && every second
oLabel = .null.

Procedure Init()
_screen.AddObject('lblTime','Label')
This.oLabel = _screen.lblTime
This.oLabel.Visible = .f.
ENDPROC

Procedure Timer()

SELECT pendlog

DO WHILE .t.

IF RECCOUNT("pendlog") = 0
loop
ELSE
exit
ENDIF

ENDDO

GO top
DO WHILE !EOF()

IF ALLTRIM(UPPER(pendlog.status)) = "PENDING"

REPLACE STATUS WITH "Transferred"

IF pendlog.nctr = 5

CLOSE DATABASES

RELEASE ALL

ENDIF
ENDIF
SKIP
ENDDO

Endproc
Enddefine

This is fine as far as it goes. But, clearly, the snippet would look much better if it was nicely formatted, like this:

Code:
DEFINE CLASS TimeTimer AS TIMER
  INTERVAL=1000 && every second
  oLabel = .NULL.

  PROCEDURE INIT()
    _SCREEN.ADDOBJECT('lblTime','Label')
    THIS.oLabel = _SCREEN.lblTime
    THIS.oLabel.VISIBLE = .F.
  ENDPROC

  PROCEDURE TIMER()

  SELECT pendlog

  DO WHILE .T.

    IF RECCOUNT("pendlog") = 0
      LOOP
    ELSE
      EXIT
    ENDIF

  ENDDO

  GO TOP
  DO WHILE !EOF()

    IF ALLTRIM(UPPER(pendlog.STATUS)) = "PENDING"

      REPLACE STATUS WITH "Transferred"

      IF pendlog.nctr = 5

        CLOSE DATABASES

        RELEASE ALL

      ENDIF
    ENDIF
    SKIP
  ENDDO

  ENDPROC
ENDDEFINE

There are some obvious advantages to this:

1. The code stands out from the surrounding text. It is easy to see where it starts and ends.

2. The code is rendered in a mono-spaced font. This makes it easy to see small characters, such as dots and commas.

3. Most importantly, the indentation is preserved. Indentation is one of the most useful tools for seeing at a glance the structure of a program.

How to do it

The easiest way to apply this formatting is to highlight the block of code, and then click on the "Code" button in the toolbar (at the top of the edit window). This button is in the right-hand half of the toolbar, between "Quote" and "Spoiler". You will be prompted to specify the code's language, which you can just leave blank.

An alternative method is to type the tag [ignore]
Code:
[/ignore] at the start of the code, and [ignore]
[/ignore] at the end.

Of course, many of us already format our code in this way. If you don't, please consider doing so - for the reasons stated above.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thanks to all those of you who starred this thread. I'm pleased that it was of some interest. If I may now make a follow-up suggestion:

When posting formatted code in this way, please also pay attention to its width. To illustrate, consider this example:

Code:
SELECT SomeTable
SCAN 
	  IF Status > 1
		    INSERT INTO SomeOtherTable (ID, Name, Item_Date) SELECT ID, Name, Item_Date FROM ThirdTable WHERE Item_Date > DATE() - 100
	  ENDIF
ENDSCAN

This block of code is 135 characters wide. How it appears in your browser will depend in part on your screen size, its resolution and possibly the choice of browser. But the chances are that the code will be too wide for the editing window and so a horizontal scroll bar will appear at the bottom of the code.

This is clearly a nuisance with a small block of code like this example. But it is much worse with a large block, where you would actually have to scroll down just to reach the scroll bar. You would then scroll across to the point where the right-hand end of the line would be visible, then scroll up again to actually read that line.

I'm sure you will agree that the following is a much better rendering of the same code:

Code:
SELECT SomeTable
SCAN 
  IF Status > 1
    INSERT INTO SomeOtherTable (ID, Name, Item_Date) ;
      SELECT ID, Name, Item_Date FROM ThirdTable ;
      WHERE Item_Date > DATE() - 100
  ENDIF
ENDSCAN

Functionally, it is the same code as in the first example, but it is now only 55 characters wide. In this case, the horizontal scrolling will probably have disappeared (again, depending on your screen size, etc.)

As you can see, I achieved that in two ways:

1. By splitting the long INSERT statement into multiple lines, with a semi-colon as the continuation character.

2. By reducing the indentation to two spaces for each level (compared to eight in the first example).

A quick way of reducing the indentation is to use VFP's Beautify feature - which in any case is worth getting to know if you aren't already familiar with it. In the Beautify Options dialogue, set the "Type of indent" to spaces, and the number of spaces to 2. Then go ahead and run the Beautify and then paste the code into the forum.

Please consider these points the next time you post program code. It's not much effort and it can do a lot to improve the readability of your code.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Hello Mike

I was interested to read your notes on the formatting of code.

I have adopted a perhaps-personalised formatting style. Absolutely agree the monospaced font, but have chosen three spaces as the extra spaces for each level of detail (within an IF . . . or SCAN . . . or DO WHILE . . . &c). And then, within such a block of code, I reduce that to two spaces with an ‘interjectory’ clause like “ELSE” or “CASE”.

And I also continue to indent (with three spaces) the closing statement of the IF . . . or SCAN . . . or DO WHILE code block. The reason for this latter technique is so that – on a casual reading - the programmer can easily identify the main sequence of instructions in the procedure &c, by looking down and seeing which lines are not indented.


Code:
DEFINE CLASS TimeTimer AS TIMER
   INTERVAL=1000 && every second
   oLabel = .NULL.

   PROCEDURE INIT()
      _SCREEN.ADDOBJECT('lblTime','Label')
      THIS.oLabel = _SCREEN.lblTime
      THIS.oLabel.VISIBLE = .F.
      ENDPROC

   PROCEDURE TIMER()
      SELECT pendlog
      DO WHILE .T.
         IF RECCOUNT("pendlog") = 0
            LOOP
           ELSE
            EXIT
            ENDIF
         ENDDO

      GO TOP
      DO WHILE !EOF()
         IF ALLTRIM(UPPER(pendlog.STATUS)) = "PENDING"
            REPLACE STATUS WITH "Transferred"
            IF pendlog.nctr = 5
               CLOSE DATABASES
               RELEASE ALL
               ENDIF
            ENDIF
         SKIP
         ENDDO
      ENDPROC
   ENDDEFINE

Or even not indenting the first statement after ‘Define Class’ because then about 98% of the code
would have the 3 or 4 space indent, which is a bit of a waste of space, and doesn’t add much clarity.

Code:
DEFINE CLASS TimeTimer AS TIMER
INTERVAL=1000 && every second
oLabel = .NULL.

PROCEDURE INIT()
   _SCREEN.ADDOBJECT('lblTime','Label')
   THIS.oLabel = _SCREEN.lblTime
   THIS.oLabel.VISIBLE = .F.
   ENDPROC

PROCEDURE TIMER()
   SELECT pendlog
   DO WHILE .T.
      IF RECCOUNT("pendlog") = 0
         LOOP
        ELSE
         EXIT
         ENDIF
      ENDDO

   GO TOP
   DO WHILE !EOF()
      IF ALLTRIM(UPPER(pendlog.STATUS)) = "PENDING"
         REPLACE STATUS WITH "Transferred"
         IF pendlog.nctr = 5
            CLOSE DATABASES
            RELEASE ALL
            ENDIF
         ENDIF
      SKIP
      ENDDO
   ENDPROC
   ENDDEFINE

It’s a bit personalised - cannot remember where I got this style from, or whether I invented it myself !

Best wishes - Andrew Mozley



 
The HTML of Tek-Tips is making the code windows adapt, but it's not just a matter of the forum to keep code readable. Not extending the width of your display or a forum maximum width of a code area is not a standard to achieve, but honestly I think 1920 width displays are a norm, more and more even go to 2560. Just always keep in mind, while the wider aspect ratio of 16:9 replaced 4:3 displays as the human vison has a preference for horizontal view newspapers for centuries work with text columns that are far narrower than the paper itself, no matter if it's a large format newspaper or a small magazine or letter size format.

Though code isn't text and indentation has such a useful meaning making code better understandable that narrow columns won't work for code, but I also support Mike in saying too long lines are not an advantage, even if display resoltion allows for it. I also support using spaces for indentation, but I understand many prefer tabs for several reasons. Just notice how tabs become 8 characters wide here in the tek-tips forum instead of 4 in the VFP IDE. I prefer 3 spaces as that indents nicely for IF statements:
Code:
If condition
   Do something
Endif
But that's a matter of taste. Anything is better than no code tags removing any indentation.

Line continuation in VFP with semicolons always strikes me as odd, because it's the inverse of what any other language uses, but on the other side code lines most often are so short I'm happy to not need to end every line with a semicolon. I just think there would be better characters for line continuation.

Some things have to be done with caution. Beatify will not add indentation to the text of a TEXT..ENDTEXT section as it would actually become part of the result string and change it depending on indentation. So Beautify does never change the result of code. Here, for example, from a yousfi blog post (sic):
Code:
Procedure command6.Click

   Local m.myvar
   TEXT to m.myvar noshow
this is a custom windows mediaplayer embed as olecontrol on a vfp form.
Its always difficult to maintain the position and the size ration for WMP.
On a form i made the uimode="none" : it worked and not shows the menubar.On a
prg that dont work (as you can test).
i made some custom controls as (trackbar,sound,...)
It allows to vfp developper o see how to play with this olecontrol.
Its an universal tool and can work on disc and on the web, for all medias.
   ENDTEXT
   Messagebox(m.myvar,0+32+4096,"Summary help")
Endproc

But it's possible to have this nicely indented and still no indentation in the string result with PRETEXT 1:
Code:
Procedure command6.Click

   Local m.myvar
   TEXT to m.myvar PRETEXT 1 noshow
      This is a custom windows mediaplayer embedded as 
      olecontrol on a vfp form. It's always difficult to main-
      tain the position and the size ratio.
      
      On a form i made the uimode="none". That worked and hides
      the menubar. In a PRG that doesn't work (as you can test).
      
      I made some custom controls (trackbar,sound,...),
      which allow a VFP developer to see how to play 
      with this olecontrol.
      
      It's an universal tool and can work on disc and on the web, 
      for all medias.
   ENDTEXT
   Messagebox(m.myvar,0+32+4096,"Summary help")
Endproc

I changed the text to better work on Win10 messageboxes, but the main point is: Try the same indented TEXT..ENDTEXT as is in comparison with PRETEXT 0 or no PRETEXT option.
This shows you can improve on the beautify result and allow indentation of TEXT..ENDTEXT with the help of PRETEXT. One helpful detail to know, I thin.

Chriss
 
I can also understand why beautify wasn't modified to automatically add PRETEXT 1, that would be a change of code other than its formatting, and you can have cases where you want some indentation of text, for example beginning every paragraph of text with an indentation. And Pretext 1 would remove that.

Chriss
 
Andrew and Chris, thank you both for your interesting comments.

You have both raised a couple of points about indentation. To start with, I have never been sure whether to indent functions and procedures. In other words, is it better to do this:

Code:
PROCEDURE SomeProc
LOCAL Var1, Var2
IF SomeCondition
  * Do something here
ENDIF
ENDPROC

FUNCTION MyFunc
LPARAMETERS tuParam1, tuParam2
IF SomeCondition
  * Do something here
ENDIF
RETURN luResult
ENDFUNC

or this:

Code:
PROCEDURE SomeProc
  LOCAL Var1, Var2
  IF SomeCondition
    * Do something here
  ENDIF
ENDPROC

FUNCTION MyFunc
  LPARAMETERS tuParam1, tuParam2
  IF SomeCondition
    * Do something here
  ENDIF
  RETURN luResult
ENDFUNC

I am inclined to favour Example B, but Example A is more economical on space (Andrew made this same point regarding DEFINE CLASS / ENDDEFINE).

A related point concerns DO CASE. Would you favour not indenting between the DO CASE and the first CASE, like this:

Code:
DO CASE
CASE Status = 1
  IF SomeCondition
    * Do something
  ENDIF 
CASE Status = 2
  IF SomeCondition
    * Do something else
  ENDIF   
ENDCASE

or do you prefer this:

Code:
DO CASE
  CASE Status = 1
    IF SomeCondition
      * Do something
    ENDIF 
  CASE Status = 2
    IF SomeCondition
      * Do something else
   ENDIF   
ENDCASE

I always used to indent within the CASE /ENDCASE (as in Example D), but lately I have moved to not indenting (Example C) - partly because you never have any code between the DO CASE and the first CASE so there is never any doubt about the logic, and partly because indenting would cause an imbalance at the end of the construct: there would be two indentation levels between the last line of the last CASE and the ENDCASE.

Finally, what about comments? I've noticed a few programmers do something like this:

Code:
SCAN
  IF SomeCondition
    IF SomeOtherCondition
* Do some sort of processing here
    ENDIF
  ENDIF
ENDSCAN

In other words, they always start all comments at column 1. This looks wrong to me. I think the comment should be at the same indentation level as the code to which it most closely relates:

Code:
SCAN
  IF SomeCondition
    IF SomeOtherCondition
      * Do some sort of processing here
    ENDIF
  ENDIF
ENDSCAN

As both Chris and Andrew pointed out, all this is - up to a point - a matter of personal taste. Whatever conventions you choose, the important thing is that it accurately reflects the logic of the program. But I would still be interested in hearing other programmer's views on this.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I agree with you that C and F are the most logic ways.
 
Personally I prefer D and F

Regards

Griff
Keep [Smile]ing

There are 10 kinds of people in the world, those who understand binary and those who don't.

I'm trying to cut down on the use of shrieks (exclamation marks), I'm told they are !good for you.

There is no place like G28 X0 Y0 Z0
 
I also prefer D and F and have used this method in my applications.

Regards,

David

Recreational Developer and End User of VFP for my personal use in 'Amateur Radio' and 'British Railways' related Applications.
 
My blood type is BDF, with 3 spaces. The preference for spaces came before I noticed how wide tabs are rendered here in this forum. I always dislike how editors use other value for tabs. I could imagine an editor that allows you to set the tab positions like you can do in Word, so you'd have varying depths, especially less indentation for higher nesting. But it's also good this alone prevents you from nesting too many levels, so I also tend to nest procedures within definiiotns. And I wonder why you would not indent CASEs in aa DO CASE, With 3 space it makes every CASE word align, even that in ENDCASE.

Code:
DO CASE
   CASE Status = 1
      * Do something
   CASE Status = 2
      * Do something else
   OTHERWISE
      * Do this in any other case
ENDCASE
Does it really look odd to anyone?

Chriss
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top