Simple configurable code indenter.

Previous topic - Next topic

jestermon

Redent is my latest little text based toy to fix up the indents in GLBAsic source code, that go haywire in a web page or a iOs pub ducument.
No rocket science here. But it has been written so that new keywords and rules can be easily added. Why write another indenter if there are so many? Simply because I can, and I love doing it.

The rules (at the end of the code snippit) should be extracted into a rules file in order to be used. Simply extend the rules file without changing any program code to add new keys.
The program runs on a command line, with the source program passed as a parameter. The output file generated is named RedentOut.gbas

The rest should be straight forward enough.
Have fun

Code (glbasic) Select
// Project: ReDent
// IDE Version: 10.283
// Author: jestermonster@gmail.com (jestermon)

GLOBAL infile$
GLOBAL prtLine = 0;
GLOBAL fdata$, rule$
GLOBAL rcount
GLOBAL filler$ = ""
GLOBAL limits = FALSE
GLOBAL NumSpaces = 4 //Tabs not used here. but simple to add with "fill" subroutines.
DIM code$[0]
DIM cmds$[0]
DIM dent$[0]
DIM linfo$[0]
DIM job$[0]


//Get command line
line$ = GETCOMMANDLINE$()

count = SPLITSTR(line$, cmds$[], " ", TRUE)

//Here we add a test document, if none is specified
IF count < 2
infile$ = "testmy.gbas"
ELSE
infile$ = cmds$[1]
ENDIF


//Load the redents rules file
res0 = OPENFILE(2, "Redent.keys", 1)
WHILE ENDOFFILE(2) <> 1
READLINE 2, rule$
IF LEFT$(rule$,1) <> "#"
DIMPUSH dent$[], rule$
ENDIF
WEND
CLOSEFILE 2


//load the source file for reading
res = OPENFILE(1, infile$, 1)
WHILE ENDOFFILE(1) <> 1
READLINE 1, fdata$
DIMPUSH code$[], fdata$
WEND
CLOSEFILE 1
rcount = LEN(dent$)

//remove ALL leading spaces
count = LEN(code$)
FOR i=0 TO count-1
code$[i] = LTRIM$(code$[i], " \t\r\n\v\f")
NEXT

//go through indent rules
i = -1
WHILE i < count -1
i = i + 1
limits = FALSE
    SPLITSTR(code$[i], linfo$[], " ", TRUE)
    //only if there is some code in the line. . .
    IF LEN(linfo$) > 0
    //for each rule
    FOR r = 0 TO LEN(dent$) -1
    //flatten the rule
    SPLITSTR(dent$[r], job$[], " ", TRUE)
    IF LEN(job$)> 0
    IF job$[0] = linfo$[0]

    IF job$[1] = "<<"
    GOSUB fillZero
    limits = FALSE
    ENDIF

    IF job$[1] = "<"
    GOSUB fillLess
    code$[i] = filler$ + code$[i]
    limits = TRUE
    ENDIF

    IF job$[1] = ">"
    code$[i] = filler$ + code$[i]
    GOSUB fillMore
    limits = TRUE
    //ignore IF-THEN combos
    IF INSTR(code$[i],"IF ") >0 AND INSTR(code$[i],"THEN ") > 0
    DEBUG code$[i]
    GOSUB fillLess
    ENDIF
    ENDIF


    IF job$[1] = "<>"
    GOSUB fillLess
    code$[i] = filler$ + code$[i]
    GOSUB fillMore
    limits = TRUE
    ENDIF

    IF job$[1] = "<<>"
    GOSUB fillZero
    code$[i] = filler$ + code$[i]
    GOSUB fillMore
    limits = TRUE
    ENDIF

    ENDIF
ENDIF
    NEXT
    ENDIF
    IF limits = FALSE
    code$[i] = filler$ + code$[i]
    ENDIF
    dump(code$[i])
WEND

//Save output
res = OPENFILE(1, "RedentOut.gbas", 0)
FOR i = 0 TO LEN(code$) - 1
WRITELINE 1, code$[i]
NEXT
CLOSEFILE 1

//used only for debug
//SHOWSCREEN
//MOUSEWAIT



SUB fillMore:
FOR n = 1 TO NumSpaces
filler$ = filler$ + " "
NEXT
ENDSUB

SUB fillLess:
filler$ = LEFT$(filler$,LEN(filler$)-NumSpaces)
ENDSUB

SUB fillZero:
filler$ = ""
ENDSUB

//simple console print emulation
FUNCTION dump: msg$
prtLine = prtLine + 20
PRINT msg$, 0, prtLine
ENDFUNCTION


//----------------------------------------------------------------------------------------
// The following text needs to be placed in a file named Redent.keys (with the "//" removed)
// Or if you are in the mood, you can stick the info onto a DATA stack or string array
//----------------------------------------------------------------------------------------

//#=================================================================
//# Redent Rules
//#=================================================================
//#
//# Simply add more BASIC commands that need IN/out dents applied TO them
//#
//# #     Comment
//# >     Indent all following lines / NOT current line
//# <>    Outdent current line, THEN Indent all following lines
//# <     Outdent current line
//# <<    Outdent TO zero
//# <<>   Outdent TO zero, THEN indent all following lines
//#
//
//IF >
//ELSE <>
//ELSEIF <>
//ENDIF <
//WHILE >
//WEND <
//FOR >
//NEXT <
//FUNCTION <<>
//ENDFUNCTION <<
//SUB <<>
//ENDSUB <<
//TRY >
//CATCH <>
//FINALLY <
//INLINE >
//ENDINLINE <
//FOREACH >
//GLOBAL <<
//REPEAT >
//UNTIL <
//STARTDATA >
//ENDDATA <
//TYPE >
//ENDTYPE <




bigsofty

Cool, many thanks, I am sure this will be useful at some point!  :good:
Cheers,

Ian.

"It is practically impossible to teach good programming style to students that have had prior exposure to BASIC.  As potential programmers, they are mentally mutilated beyond hope of regeneration."
(E. W. Dijkstra)

Slim

Talk about good timing; I have a use for exactly this right now.
Thanks.