Oso wrote: ↑Fri Jul 29, 2022 11:18 pm
jacdelad wrote: ↑Fri Jul 29, 2022 11:11 pm
Yes. And the parameters have to be exact the same as in the procedure.
Just out of curiosity: What speaks against declaring the procedures before the main code? My codes look like
- EnableExplicit
- Use
xxx-commands
- Enumerations
- Structures
- declaration of variables
- XIncludes
- procedures
- main code
...but this is just my prototype and has to be adapted sometimes.
Okay, I understand your established sequence in your code. I think that's fine if all your code follows that pattern. A lot of the time with languages, it's important to follow the conventions that other developers use. For me, coming to this as a new developer, it seems strange to have the procedures above 'main()' but for other PureBasic coders, it seems logical.
There are different paradigms among every programmer I think.
When it comes to smaller projects, I think it could suffice to have the procedures first and then the main code.
For larger projects I'd like to follow a top-down rule. Start with the highest abstraction level and slowly go down to the lowest level.
Furthermore, when the projects are even larger, the code might benefit from being written in modules (Module - End Module). By that you isolate selectable resources inside a module. Even though that is a bit outside what you started this thread for, I believe it can help you to a speed start to be able to write more complex projects.
One thing though. Resources, like file numbers, window numbers, gadget numbers and so on, are shared among the whole project. I'd suggest you to use global lists for saving the resource-# in, not to risc using the same number where it's not intended. But variables, macros, procedures and so on that are not declared in the DeclareModule-block, will be isolated to that same module.
Here is some code snippets from one of my projects:
a piece from my main module:
Code: Select all
DeclareModule GerberPeek
EnableExplicit
Global windowMain, menuMain
EndDeclareModule
XIncludeFile "Common.pbi"
XIncludeFile "Misc.pbi"
XIncludeFile "Gfx.pbi"
XIncludeFile "GerberPeekData.pbi"
XIncludeFile "Gerber.pbi"
Module GerberPeek
UseModule Common
UseModule Gerber
UseModule Gfx
Enumeration MenuItems
;project
#mClose
#mOpen
#mPrint
#mSizes
...
...
...
... and here is a compressed snippet of one of the modules:
Code: Select all
DeclareModule GerberPeekData
EnableExplicit ; this forces you to define all variables.
#statusUnknown = 0
#statusOkay = 1
#statusFileNotFound = 2
#statusLinkBroken = 4
#statusOrphan = 8
#statusTextDirty = #SOH$ + "Gerber not updated"
#statusTextLinkBroken = #SOH$ + "Broken Link"
#statusTextFileNotFound = #SOH$ + "File not found"
#statusTextOrphan = #SOH$ + "no Gerber to match"
#statusTextDfxAsVariant = #SOH$ + "dxf used as variant (deprecated)"
#statusTextNoError = #SOH$ + "Status okay"
#maxPause = 40 ; delay in ms for status progress bar
Structure entry
fullName.s
variantID.l
variantName.s
Alignment.l
qty.l
status.l
EndStructure
Structure tree
path.s
pathModified.l ; datum något i mappen uppdaterades
name.s
ext.s
capsName.s ; name in CAPS (för att lura sorteringsrutinens loppa som skiljer mellan stora och små svenska tecken trots nocase-flagga...)
modified.l ; datum filen modifierades
dirtyFlag.l ; visa om denna entry är av äldre datum än beståndsdelarna.
List dirtyTriggers.s() ; filer som triggar dirty-flaggan.
errDxfAsVariant.l ; innehåller minst en dxf som används som variant - en icke rekommenderad egenskap
status.l
newInDatabase.l ; fil av senare datum än databasens eller helt ny. Nu ska vi se:
; Om en mapp visar uppdaterat datum senare än innehållet i mappen så har någon fil tagits bort. Hitta denna i databasen och ta bort den och dess länkar (måste kolla alla filer inom den mappen)
; Om en mapp har senare datum än innehållet så ska alla filer verifieras mot databas. De som har nyare datum ska uppdateras (radera består av om det finns)
; Om mapp saknas. Radera allt inom den mappen i databasen.
;består av...
List consistOfPattern.entry()
List consistOfVariant.entry()
List consistOfMarker.entry()
;ingår i...
List partOfVariant.entry()
List partOfMarker.entry()
List partOfGBR.entry()
;relaterade (forks)
List forkedMarker.entry()
List forkedVariant.entry()
;List forkedPattern.entry() ; mönster som har samma geometri, antal vektorer, antal hack, etc men olika mått - vet inte hur jag ska artbestämma detta dock. En romb och en kvadrat är inte en fork t ex. Eller?
EndStructure
Global gbrFolder$, dataRoot$, extRoot$, gbrPeek$, readXMLMarker, readXMLVariant, prefsFile$
Define folderCnt, patternCnt, variantCnt, markerCnt, gerberCnt
prefsFile$ = GetUserDirectory(#PB_Directory_ProgramData) + "GerberPeek\GerberPeekData.ini" ;(user dir - appdata)
Declare CountDirectories(n, path.s)
Declare DoDirectoryLevel(n, newPath$, count = 1)
Declare.l Find(List target.tree(), search$)
Declare.l BinFind(List myList.tree(), search$)
Declare ParseVariant(file$)
Declare ParseMarker(file$)
NewList marker.tree()
NewList variant.tree()
NewList pattern.tree()
NewList gerber.tree()
NewList path.s()
EndDeclareModule
Module GerberPeekData
; These procedures will only be reachable within this module since they are declared inside the actual Module
Declare InitPaths()
Declare.l ChooseNode(xmlFile, path2Find$)
; You can even put code here that will be executed when the module is included. I prefer XInclude, not to risc including the same module twice.
Procedure CountDirectories(n, path.s)
EndProcedure
Procedure DoDirectoryLevel(n, newPath.s, count = 1)
; Läser igenom en nivå i en mappstruktur och rekurserar igenom alla lägre nivåer
Shared marker(), variant(), pattern(), path(), gerber(),
folderCnt, patternCnt, variantCnt, markerCnt, gerberCnt
Static progress
Define nil, timer
progress + 1
If Int(progress / 50) * 50 = progress
StatusBarProgress(0, 1, progress, #PB_StatusBar_BorderLess, 0, folderCnt/2)
EndIf
AddElement(path())
path() = newPath
If path() = dataRoot$ Or path() = gbrFolder$
ExamineDirectory(n, path(), "")
EndIf
While NextDirectoryEntry(n)
nil = WindowEvent()
;Debug Str(DirectoryEntryType(1))+" "+DirectoryEntryName(1)+" "+Str(DirectoryEntryAttributes(1))+" "+Str(DirectoryEntrySize(1))
If DirectoryEntryType(n) = #PB_DirectoryEntry_Directory And path() <> gbrFolder$ And UCase(Right(path(), 9)) <> "\MÖNSTER\" And UCase(Right(path(), 8)) <> "\MODELL\"
If DirectoryEntryName(n) <> "." And DirectoryEntryName(n) <> ".."
;Debug path() + DirectoryEntryName(n)
folderCnt + 1
ExamineDirectory(n + 1, path() + DirectoryEntryName(n) + "\", "")
DoDirectoryLevel(n + 1, path() + DirectoryEntryName(n) + "\")
EndIf
Else
If Left(path(), Len(dataRoot$)) = dataRoot$
;Debug GetExtensionPart(DirectoryEntryName(n))
If UCase(GetExtensionPart(DirectoryEntryName(n))) = "DXF" Or UCase(GetExtensionPart(DirectoryEntryName(n))) = "CPX"
ElseIf UCase(GetExtensionPart(DirectoryEntryName(n))) = "CMX"
AddElement(marker())
marker()\path = path()
marker()\name = DirectoryEntryName(n)
marker()\ext = GetExtensionPart(marker()\name)
marker()\name = GetFilePart(marker()\name, #PB_FileSystem_NoExtension)
marker()\modified = GetFileDate(path() + DirectoryEntryName(n), #PB_Date_Modified)
markerCnt + 1
ElseIf UCase(GetExtensionPart(DirectoryEntryName(n))) = "CVX"
EndIf
Else
If UCase(GetExtensionPart(DirectoryEntryName(n))) = "GBR"
;Debug "gerber "+DirectoryEntryName(n)
AddElement(gerber())
gerber()\path = path()
gerber()\name = DirectoryEntryName(n)
gerber()\ext = GetExtensionPart(gerber()\name)
gerber()\name = GetFilePart(gerber()\name, #PB_FileSystem_NoExtension)
gerber()\capsName = UCase(gerber()\name)
gerber()\modified = GetFileDate(path() + DirectoryEntryName(n), #PB_Date_Modified)
gerberCnt + 1
EndIf
EndIf
EndIf
Wend
FinishDirectory(n)
DeleteElement(path())
EndProcedure
Macro ParseLinkTrees(parent, child, quantity, dirtTest = #False)
EndMacro
Procedure ParseVariant(file$)
Shared variant.tree(), pattern.tree()
Define xml, message$, *node, *child, a$, found, whereToInsertReference
readXMLVariant + 1
xml = LoadXML(#PB_Any, file$)
If xml = 0
Debug "Variant wasn't found - returning..."
EndIf
If XMLStatus(xml) <> #PB_XML_Success
message$ = "Error in the XML file:" + Chr(13)
message$ + "Message: " + XMLError(xml) + Chr(13)
message$ + "Line: " + Str(XMLErrorLine(xml)) + " Character: " + Str(XMLErrorPosition(xml))
MessageRequester("Error", message$)
EndIf
*node = MainXMLNode(xml)
If *node = 0 Or XMLNodeType(*node) <> #PB_XML_Normal
ProcedureReturn
EndIf
*node = ChildXMLNode(*node)
If *node = 0 Or XMLNodeType(*node) <> #PB_XML_Normal
;Debug "bla"
ProcedureReturn
EndIf
While NextXMLNode(*node)
Select UCase(GetXMLNodeName(*node))
Case "PATTERNS"
;Debug file$
;Debug "patterns found"
*child = ChildXMLNode(*node)
While *child
If *child And UCase(GetXMLNodeName(*child)) = "PATTERN" And ExamineXMLAttributes(*child) = #True
a$ = GetXMLNodeText(*child)
If Left(a$, 2) = ".\"
a$ = dataRoot$ + Right(a$, Len(a$) - 2)
EndIf
ParseLinkTrees(variant, pattern, Val(GetXMLAttribute(*child, "Qty")))
EndIf
*child = NextXMLNode(*child)
Wend
EndSelect
*node = NextXMLNode(*node)
Wend
EndProcedure
Procedure ParseMarker(file$)
EndProcedure
Procedure.l Find(List target.tree(), search$)
EndProcedure
Procedure.l BinFind(List myList.tree(), search$)
Define min, max, idx, loop, index$
search$ = UCase(GetFilePart(search$, #PB_FileSystem_NoExtension))
max = ListSize(myList()) - 1
min = 0
idx = max / 2
If Not SelectElement(myList(), idx)
Debug "Houston we have a problem!"
ProcedureReturn -2
EndIf
index$ = UCase(GetFilePart(myList()\name, #PB_FileSystem_NoExtension))
Repeat
loop + 1
;Debug "loop nr "+Str(loop)
If search$ > index$ ; längre bak i listan tack
If idx < max
min = idx
idx + (max - min + 1) / 2
EndIf
ElseIf search$ < index$ ; hälften fram i listan, tack
If idx > min
max = idx
idx - (max - min + 1) / 2
EndIf
Else
ProcedureReturn idx
EndIf
SelectElement(myList(), idx)
index$ = UCase(GetFilePart(myList()\name, #PB_FileSystem_NoExtension))
Until idx = min Or idx = max
If index$ > search$ And idx > 0
idx - 1
EndIf
ProcedureReturn -idx - 1
EndProcedure
Macro AddStructure(bomList, listHeader)
If ListSize(dataList()\bomList()) > 0
AddGadgetItem(gadget, #PB_Any, listHeader + " - " + Str(ListSize(dataList()\bomList())) + " item(s)", 0, 1)
ForEach dataList()\bomList()
AddGadgetItem(gadget, #PB_Any, Mid("! ?0§123¤456&nonsense", dataList()\bomList()\status + 1, 1) + " " +
GetFilePart(MakePathString(dataList()\bomList()\fullName)) + " (qty: " +
Str(dataList()\bomList()\qty) + ") path: " +
GetPathPart(MakePathString(dataList()\bomList()\fullName)), 0, 2)
If dataList()\bomList()\status = MarkData::#statusFileNotFound
SetGadgetItemColor(gadget, CountGadgetItems(gadget) - 1, #PB_Gadget_FrontColor, RGB(200,200,200))
EndIf
If datalist()\bomList()\qty = 0
SetGadgetItemColor(gadget, CountGadgetItems(gadget) - 1, #PB_Gadget_FrontColor, RGB(200,200,200))
EndIf
Next
EndIf
EndMacro
Procedure InitPaths()
EndProcedure
Procedure.l ChooseNode(xmlFile, path2Find$)
EndProcudure
EndModule