Board Logo
« auto indent .bas file »

Welcome Guest. Please Login or Register.
Jan 16th, 2018, 3:37pm


Conforums Terms of Service | Membership Rules | Home | Search | Recent Posts | Notification | Format Your Message | Installation FAQ

Please use the forums Search feature before asking.
Please post code using the code box described in Format Your Messages.
This will keep indentation, separate it better form the message and prevent gibberish.
If the code is too long for one post or additional files are needed, upload a ZIP archive to the Just BASIC Files Archive Site.

« Previous Topic | Next Topic »
Pages: 1  Notify Send Topic Print
 thread  Author  Topic: auto indent .bas file  (Read 630 times)
zzz000abc
Full Member
ImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 268
xx auto indent .bas file
« Thread started on: Feb 23rd, 2017, 10:24pm »

hi,
here is a program to AutoIndent ,bas file
Code:
     tt=3
     key1$="for while function sub if"
     key2$="next;wend;end function;end sub;end if"
     input" enter .bas file name to indent";a$
     a$=word$(a$,1,".")
     open a$;".bas" for input as#1
     open "tmp";a$;".bas" for output as #2
     t=2
    while eof(#1)=0
       line input#1,l$
      for i=1 to 4
         if word$(l$,1)= word$(key1$,i) then t=t+2 :op=op+1:lp=1:tt=0:exit for
      next
       if word$(l$,1)="if" and word$(l$,2,"then")="" then t=t+2:op=op+1:lp=1:tt=0
      for i=1 to 5
         if word$(l$,1,";")=word$(key2$,i,";") then lp=2:exit for
      next

       if lp=2 then lp=0:op=op-1:tt=0
       print #2,space$(t+tt)+l$
       print space$(t+tt);l$
       if op<>0 and lp=0 then lp=1:t=t-2
       if tt=0 then tt=3
    wend
       close#1
       close#2
       name a$;".bas" as a$;".bkp"
       name "tmp";a$;".bas" as a$;".bas"

 
User IP Logged

tsh73
JB-Supporter


member is offline

Avatar




PM

Gender: Male
Posts: 3635
xx Re: auto indent .bas file
« Reply #1 on: Feb 24th, 2017, 2:36pm »

Gave it a few runs.
Found something:
* do /loop not included in keywords
* keywords recognised lowercase only
* comment on line after "then" makes it think IF single-line
* check for closing part is wrong
Code:
         if word$(l$,1,";")=word$(key2$,i,";") then lp=2:exit for
 
should actually be
Code:
         if word$(l$,1)=word$(key2$,i,";") then lp=2:exit for
 


Also somehow FOR/NEXT WHILE /WEND lines are out-indented by 1 symbol - is this by design?

Keep up good job.
User IP Logged

Q: "And if I took your codes and compile them, and sell them for a profit"?
A: Go ahead. I had my share of good then I coded it for fun, if you can make better use of it - please do.
(enjoying JB 1.01 on WinXP, netbook and desktop)
zzz000abc
Full Member
ImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 268
xx Re: auto indent .bas file
« Reply #2 on: Feb 24th, 2017, 3:40pm »

thank you tsh,nice feed back. I will work on it again.
User IP Logged

bplus
Senior Member
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 1255
xx Re: auto indent .bas file
« Reply #3 on: Feb 24th, 2017, 8:34pm »

This is good project, making code easy to read and you might even be able to catch errors with it like missing END IF in nested series of them. I am a little surprised not seeing TRIM$ anywhere, maybe because using WORD$.

Do you have plans for handling labels?
« Last Edit: Feb 24th, 2017, 8:39pm by bplus » User IP Logged

B+
zzz000abc
Full Member
ImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 268
xx Re: auto indent .bas file
« Reply #4 on: Feb 26th, 2017, 05:19am »

on Feb 24th, 2017, 2:36pm, tsh73 wrote:
Gave it a few runs.
* check for closing part is wrong
Code:
         if word$(l$,1,";")=word$(key2$,i,";") then lp=2:exit for
 
should actually be
Code:
         if word$(l$,1)=word$(key2$,i,";") then lp=2:exit for
 

Also somehow FOR/NEXT WHILE /WEND lines are out-indented by 1 symbol - is this by design?
Keep up good job.

Hi,
the closing part is not wrong but it is a bit tricky actually.If you write
if word$(l$,1)=word$(key2$,i,";") then lp=2:exit for
instead of if word$(l$,1,";")=word$(key2$,i,";") then lp=2:exit for
you will pick end instead end if which creats a bug.
Now here is the modified version which handles
*comments ,blank spaces , blank lines
*lower case as well as upper case letters
*includes keywords DO LOOP and SELECT END SELECT
Code:
global btfy,cc,t
tt0=6:tt=tt0:t0=2:t=t0:k=4
key1$="for;while;function;sub;if;do;select"
key2$="next;wend;end function;end sub;end if;end select;loop;else;case;default"
while 1
print"ChooseOption "
print "1. indent 2.indent & beautify 3.quit "
input"";a
if int(a)>0 and int(a)<4 then exit while
wend
if a=3 then[quit] else btfy=a-1
input" enter .bas file name to indent  ";a$
a$=word$(a$,1,".")
open a$;".bas" for input as#1
open "tmp";a$;".bas" for output as #2
while eof(#1)=0
line input#1,l$
 l$=trim$(l$):if l$="" then[skip]
 l1$=word$(l$,1,"'"):l2$=word$(l$,2,"'")
wc=cnt(key2$,";"):cc=cnt(l1$,":"):lp=0
l1$=lower$(l1$)
for i=1 to wc
if word$(key1$,i,";")=word$(l1$,1) and word$(l1$,2,"then")="" then
 t=t+k:lp=1:op=op+1
print nstr$(l$)
print #2,nstr$(l$)
exit for
end if
if word$(key2$,i,";")=word$(l1$,1,";") or word$(key2$,i,";")=word$(word$(l1$,1,";"),1)  then
print #2,nstr$(l$)
print nstr$(l$)
if i>7 then t=t+k:op=op+1
t=t-k:lp=1:op=op-1:exit for
end if
next
for j=2 to cc
if word$(key2$,i,";")=word$(l1$,j,":") then t=t-k:op=op-1: exit for
next
if btfy=1 then l$=lower$(l$)
if op=0 and lp=0 then tt=tt0
if lp=0 then
print #2,space$(t+tt)+l$
print space$(t+tt)+l$
end if
[skip]
wend
close#1
close#2
name a$;".bas" as a$;".bkp"
name "tmp";a$;".bas" as a$;".bas"
[quit]
end
'-------------------------------------------------
function cnt(l$,sep$)
while word$(l$,wc+1,sep$)<>""
wc=wc+1
cnt=wc
wend
end function
'-------------------------------------------------
function nstr$(l$)
sc=cnt(l$," ")
for i=2 to sc
tmp$=tmp$+" "+word$(l$,i)
next
if btfy=1 and cc=1 then
nstr$= space$(t)+" "+upper$(word$(l$,1))+tmp$
else
nstr$= space$(t)+l$
end if
end function
 

note1.
It works for most of the programs well but some exceptions are there.The best example being the code itself.To be more clear it cannot handle
the instruction like this:
if word$(key1$,i,";")=word$(l1$,1) and word$(l1$,2,"then")="" then
here the keyword 'then' written in quotes.If this is the case then the indention will be distorted slightly.I wish any advanced users come forward to make more better code.
2.This version has the option to beautify the code in the sense it capitalizes the pairing keywords.
COMMENTS ARE WELCOME
User IP Logged

zzz000abc
Full Member
ImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 268
xx Re: auto indent .bas file
« Reply #5 on: Feb 26th, 2017, 05:23am »

on Feb 24th, 2017, 8:34pm, bplus wrote:
Do you have plans for handling labels?

Thank you B+. labels part ... I may consider later.
User IP Logged

bplus
Senior Member
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 1255
xx Re: auto indent .bas file
« Reply #6 on: Feb 26th, 2017, 4:19pm »

zzzabc000 Quote:
I wish any advanced users come forward to make more better code.


OK here is my indent.txt code indented (by 7 spaces)
Code:
'indent.txt for JB [B+=MGA] 2017-02-26
'attempt to properly indent a BASIC file

fname$ = "indent"         '<<<<<<<<<<<<<<<<<<<<<<<<<< this indent file

fs$ = getFileString$(fname$;".txt") 'delimits with chr$(10)
lnCnt = wdCnt(fs$, chr$(10))        'count lines

indSize = 7 'my indent is set at 4 spaces
level = 0
fout$ = ""

for i = 1 to lnCnt
       fl$ = trim$(lower$(word$(fs$, i, chr$(10)))) 'lower case for compares
       orig$ = trim$(word$(fs$, i, chr$(10))) 'preserve case in line
       if len(fl$) then
              firstWd$ = word$(fl$, 1)
              if level > 0 and wInStr(firstWd$,"else next wend loop end ") > 0 then
                     level = level - 1
              end if
              'update fout$ with file line$
              fout$ = fout$;space$(level*indSize);orig$;chr$(10)
              if wInStr(firstWd$, "for while do else select sub function") then
                     'if line contains colon then it is likely a one complete loop
                     if instr(fl$, ":") = 0 then level = level + 1
              end if
              ' handle if/then on same line with chars following "then"
              if firstWd$ = "if" then
                     test$ = word$(fl$, wInStr("then", fl$) + 1)
                     if test$ = "" or left$(test$,1) = "'" then
                            level = level + 1
                     end if
              end if
       else
              fout$ = fout$;" ";chr$(10)
       end if
next
call saveToFile fname$;" indented.txt", fout$
print "Done, bye"

function wInStr(w$, s$) 'word place in string, 0 if not in it
       wInStr = 0
       wc = wCnt(s$)
       for i = 1 to wc
              if w$ = word$(s$, i) then
                     wInStr = i : exit function
              end if
       next
end function

sub saveToFile pathedFile$, s$
       open pathedFile$ for output as #2
       fsCnt = wdCnt(s$, chr$(10))
       for i = 1 to fsCnt
              p$ = word$(s$, i, chr$(10))
              print #2, p$
       next
       close #2
end sub

function getFileString$(pathedFile$)
       'avoid error on non existent file
       open pathedFile$ for append as #1
       print #1, ""
       close #1

       open pathedFile$ for input as #1
       while eof(#1) = 0
              line input #1, f$
              fString$ = fString$;f$;chr$(10)
       wend
       close #1
       getFileString$ = fString$
end function

function wdCnt(s$, d$) 'word delimited (non default delimited) string
       if s$ = "" then
              wdCnt = 0
       else
              w$ = word$(s$, 1, d$) 'we know if not "" then at least 1 word!
              while w$ <> ""
                     wc = wc + 1 : w$ = word$(s$, wc + 1, d$)
              wend
              wdCnt = wc
       end if
end function

function wCnt(s$) 'of default space delimited string
       while word$(s$, wc + 1) <> "" : wc = wc + 1 : wend
       wCnt = wc
end function

 


EDIT/APPEND: I just realigned my evalA.txt program with indent.txt and had to substitute STOP for END at all nested IF THEN's that catch fatal errors to END program execution.

2017-02-27 Do not like how 'case' is handled but my fix didn't fix.
« Last Edit: Feb 27th, 2017, 5:36pm by bplus » User IP Logged

B+
zzz000abc
Full Member
ImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 268
xx Re: auto indent .bas file
« Reply #7 on: Feb 27th, 2017, 12:53pm »

Thank You B+ for one more version it's very nice indeed.
Here is my version again now it is Bug Free : Code:
               global btfy,cc,t
        tt0=6:tt=tt0:t0=2:t=t0:k=4
        key1$="for;while;function;sub;do;select"
        key2$="next;wend;end function;end sub;end if;end select;loop;else;case;default"
       WHILE 1
            print"chooseoption "
            print "1. indent 2.indent & beautify 3.quit "
            input"";a
            if int(a)>0 and int(a)<4 then exit while
       WEND
        if a=3 then[quit] else btfy=a-1
        input" enter .bas file name to indent";a$
        a$=word$(a$,1,".")
        open a$;".bas" for input as#1
        open "tmp";a$;".bas" for output as #2
       WHILE eof(#1)=0
            line input#1,l$
            l$=trim$(l$):if l$="" then[skip]
            l1$=word$(l$,1,"'"):l2$=word$(l$,2,"'")
            wc=cnt(key2$,";"):cc=cnt(l1$,":"):lp=0
            l1$=lower$(l1$)
           FOR i=1 to wc
                if word$(key1$,i,";")=word$(l1$,1)_
                or ((mid$(l1$,1,2)="if")and ((mid$(l1$,(len(l1$)-3),4)="then")or (mid$(l1$,len(l1$),1)="_"))) then
                t=t+k:lp=1:op=op+1
                print nstr$(l$)
                print #2,nstr$(l$)
                exit for
           END if
           IF word$(key2$,i,";")=word$(l1$,1,";") or word$(key2$,i,";")=word$(word$(l1$,1,";"),1) then
                print #2,nstr$(l$)
                print nstr$(l$)
                if i>7 then t=t+k:op=op+1
                t=t-k:lp=1:op=op-1:exit for
           END if
       NEXT
       FOR j=2 to cc
            if word$(key2$,i,";")=word$(l1$,j,":") then t=t-k:op=op-1: exit for
       NEXT
        if btfy=1 then l$=lower$(l$)
        if op=0 and lp=0 then tt=tt0
       IF lp=0 then
            print #2,space$(t+tt)+l$
            print space$(t+tt)+l$
       END if
        [skip]
   WEND
    close#1
    close#2
    name a$;".bas" as a$;".bkp"
    name "tmp";a$;".bas" as a$;".bas"
    [quit]
    end
    '-------------------------------------------------
   FUNCTION cnt(l$,sep$)
       WHILE word$(l$,wc+1,sep$)<>""
            wc=wc+1
            cnt=wc
       WEND
   END function
    '-------------------------------------------------
   FUNCTION nstr$(l$)
        sc=cnt(l$," ")
       FOR i=2 to sc
            tmp$=tmp$+" "+word$(l$,i)
       NEXT
       IF btfy=1 and cc=1 then
            nstr$= space$(t)+" "+upper$(word$(l$,1))+tmp$
       ELSE
            nstr$= space$(t)+l$
       END if
   END function
 
« Last Edit: Feb 27th, 2017, 1:26pm by zzz000abc » User IP Logged

bplus
Senior Member
ImageImageImageImageImage


member is offline

Avatar




PM

Gender: Male
Posts: 1255
xx Re: auto indent .bas file
« Reply #8 on: Feb 27th, 2017, 5:51pm »

Following the way you did filing, I gave my indent program a huge diet plus I added a margin and code to handle a line label:
indent indented.txt Code:
   'indent.txt for JB [B+=MGA]
   '2017-02-26 attempt to properly indent a BASIC file
   '2017-02-27 add label flag, margin and remove filing stuff

   fname$ = "indent"         '<<<<<<<<<<<<<<<<<<<<<<<<<< this indent file
   open fname$;".txt" for input as #1
   open fname$;" indented.txt" for output as #2
   margin = 3  'so line labels stand out
   indSize = 5 'my indent is set at 4 spaces
   level = 0
   while eof(#1) = 0
        line input #1, fl$
        orig$ = trim$(fl$)  'original case
        fl$ = lower$(orig$) 'lower case for compares
        if len(fl$) then
             firstWd$ = word$(fl$, 1)
             if left$(firstWd$, 1) = "[" then labelF = 1 else labelF = 0
             if level > 0 and wInStr(firstWd$,"else next wend loop end") > 0 then
                  level = level - 1
             end if
             if labelF then 'print to indented file
                  print #2, orig$
             else
                  print #2, space$(level * indSize + margin);orig$
             end if  'update level for next line(s)
             if wInStr(firstWd$, "for while do else select sub function") then
                  'if line contains colon then it is likely a one complete loop
                  if instr(fl$, ":") = 0 then level = level + 1
             end if
             if firstWd$ = "if" then 'two forms of if/then: line or block
                  test$ = word$(fl$, wInStr("then", fl$) + 1)
                  if test$ = "" or left$(test$,1) = "'" then 'a block if/then
                       level = level + 1
                  end if
             end if
        else
             print #2, ""
        end if
   wend
   close #1 : close #2 : print "Done, bye"

   function wInStr(w$, s$)
        wInStr = 0 : wc = wCnt(s$)
        for i = 1 to wc
             if w$ = word$(s$, i) then wInStr = i : exit function
        next
   end function

   function wCnt(s$) 'of default space delimited string
        while word$(s$, wc + 1) <> "" : wc = wc + 1 : wend
        wCnt = wc
   end function
 
User IP Logged

B+
Pages: 1  Notify Send Topic Print
« Previous Topic | Next Topic »

Conforums Terms of Service | Membership Rules | Home | Search | Recent Posts | Notification | Format Your Message | Installation FAQ

Donate $6.99 for 50,000 Ad-Free Pageviews!

| |

This forum powered for FREE by Conforums ©
Sign up for your own Free Message Board today!
Terms of Service | Privacy Policy | Conforums Support | Parental Controls