1- import std / [os, strutils]
1+ import std / [os, strutils, asyncdispatch, osproc, streams, sugar ]
22import nimibook / [types, commands, themes]
33import nimib
44
5- proc buildNim * (entry: Entry , srcDir: string , nimOptions: seq [string ]): bool =
5+ proc buildNim * (entry: Entry , srcDir: string , nimOptions: seq [string ]): Future [ bool ] {. async .} =
66 let
77 cmd = " nim"
88 args = @ [" r" ] & nimOptions & @ [srcDir / entry.path]
99 # "-d:release", "-f", "--verbosity:0", "--hints:off"
1010 debugEcho " [Executing] " , cmd, " " , args.join (" " )
11- if execShellCmd (cmd & " " & args.join (" " )) != 0 :
12- echo " [nimibook.error] error while processing " , entry.path
13- return false
14- return true
11+
12+ let process = startProcess (cmd, args = args, options = {poUsePath, poStdErrToStdOut})
13+ defer : process.close ()
14+ while process.running ():
15+ await sleepAsync (10 )
16+
17+ result = process.peekexitCode == 0
18+ if not result :
19+ # Process failed so we write a '.log'
20+ let logPath = entry.path.changeFileExt (" log" )
21+ discard tryRemoveFile (logPath)
22+ let fs = openFileStream (logPath, fmWrite)
23+ defer : fs.close ()
24+ for line in process.lines:
25+ fs.writeLine (line)
1526
1627proc buildMd * (entry: Entry ): bool =
1728 try :
@@ -24,25 +35,36 @@ proc buildMd*(entry: Entry): bool =
2435 echo " [nimibook.error] error while processing " , entry.path
2536 return false
2637
27- proc build * (entry: Entry , srcDir: string , nimOptions: seq [string ]): bool =
38+ proc build * (entry: Entry , srcDir: string , nimOptions: seq [string ]): Future [ bool ] {. async .} =
2839 let splitted = entry.path.splitFile ()
29- if splitted.ext == " .nim" :
30- return buildNim (entry, srcDir, nimOptions)
31- elif splitted.ext == " .md" :
40+ case splitted.ext
41+ of " .nim" :
42+ return await buildNim (entry, srcDir, nimOptions)
43+ of " .md" :
3244 return buildMd (entry)
3345 else :
3446 echo " [nimibook.error] invalid file extension (must be one of .nim, .md): " , splitted.ext
3547 return false
3648
3749proc build * (book: Book , nimOptions: seq [string ] = @ []) =
38- var buildErrors: seq [string ]
50+ var
51+ buildErrors: seq [string ]
52+ buildFutures: seq [Future [bool ]]
3953 dump book
40- for entry in book.toc.entries:
54+ for i in 0 .. book.toc.entries.high:
55+ let entry = book.toc.entries[i] # use index since `items` returns `lent` in `1.7.x+`
4156 if entry.isDraft:
4257 continue
4358 echo " [nimibook] build entry: " , entry.path
44- if not build (entry, book.srcDir, nimOptions):
45- buildErrors.add entry.path
59+ buildFutures.add build (entry, book.srcDir, nimOptions)
60+ closureScope:
61+ let path = entry.path
62+ buildFutures[^ 1 ].addCallback do (f: Future [bool ]):
63+ if not f.read ():
64+ buildErrors.add path
65+
66+ discard waitFor all buildFutures
67+
4668 if len (buildErrors) > 0 :
4769 echo " [nimibook.error] " , len (buildErrors), " build errors:"
4870 for err in buildErrors:
0 commit comments