1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
|
## Helper that is run after Nim's installation.
## We download mirror'ed mingw packages. The originals came from:
##
## https://sourceforge.net/projects/mingw-w64/files/Toolchains%20
## targetting%20Win32/Personal%20Builds/mingw-builds/6.3.0/threads-win32/
## dwarf/i686-6.3.0-release-win32-dwarf-rt_v5-rev1.7z/download
## https://sourceforge.net/projects/mingw-w64/files/Toolchains%20
## targetting%20Win64/Personal%20Builds/mingw-builds/6.3.0/threads-win32/
## seh/x86_64-6.3.0-release-win32-seh-rt_v5-rev1.7z/download
##
import
ui, asyncdispatch, httpclient, os, finish, registry, strutils, osproc
type
Actions = object
addToPath, startMenu, mingw, aporia: bool
Controls = object
apply: Button
bar: ProgressBar
lab: Label
const arch = $(sizeof(int)*8)
proc download(pkg: string; c: Controls) {.async.} =
let z = r"..\dist" / pkg & ".7z"
if fileExists(z):
c.lab.text = z & " already exists"
return
c.bar.value = 0
var client = newAsyncHttpClient()
proc onProgressChanged(total, progress, speed: BiggestInt) {.async.} =
c.lab.text = "Downloading " & pkg & " " & $(speed div 1000) & "kb/s"
c.bar.value = clamp(int(progress*100 div total), 0, 100)
client.onProgressChanged = onProgressChanged
await client.downloadFile("https://nim-lang.org/download/" & pkg & ".7z", z)
c.bar.value = 100
let p = osproc.startProcess("7zG.exe", getCurrentDir() / r"..\dist",
["x", pkg & ".7z"])
if p.waitForExit != 0:
c.lab.text = "Unpacking failed: " & z
proc apply(a: Actions; c: Controls) {.async.} =
if a.mingw:
await download("mingw" & arch & "-6.3.0", c)
if a.aporia:
await download("aporia-0.4.0", c)
if a.addToPath:
let desiredPath = expandFilename(getCurrentDir() / "bin")
let p = getUnicodeValue(r"Environment", "Path",
HKEY_CURRENT_USER)
var alreadyInPath = false
for x in p.split(';'):
if x.len == 0: continue
let y = try: expandFilename(if x[0] == '"' and x[^1] == '"':
substr(x, 1, x.len-2) else: x)
except: ""
if y == desiredPath: alreadyInPath = true
if not alreadyInPath:
addToPathEnv(desiredPath)
if a.startMenu:
createStartMenuEntry()
c.apply.text = "Quit"
proc main() =
var mainwin = newWindow("Nim installer", 640, 280, true)
mainwin.margined = true
mainwin.onClosing = (proc (): bool = return true)
let box = newVerticalBox(true)
mainwin.setChild(box)
var groupA = newGroup("Actions", true)
box.add(groupA, false)
var innerA = newVerticalBox(true)
groupA.child = innerA
let cbAddToPath = newCheckbox("Add Nim to PATH")
innerA.add cbAddToPath
let cbStartMenu = newCheckbox("Create start menu entry")
innerA.add cbStartMenu
var groupB = newGroup("Optional Components", true)
box.add(groupB, false)
var innerB = newVerticalBox(true)
groupB.child = innerB
let cbMingw = newCheckbox("Download Mingw")
innerB.add cbMingw
let cbAporia = newCheckbox("Download Aporia")
innerB.add cbAporia
var c = Controls(
apply: newButton("Apply"),
bar: newProgressBar(),
lab: newLabel(""))
innerB.add c.apply
innerB.add c.bar
innerB.add c.lab
proc apply() =
c.apply.text = "Abort"
asyncCheck apply(Actions(addToPath: cbAddToPath.checked,
startMenu: cbStartMenu.checked,
mingw: cbMingw.checked,
aporia: cbAporia.checked), c)
c.apply.onclick = proc () =
ui.quit()
system.quit()
c.apply.onclick = apply
show(mainwin)
pollingMainLoop((proc (timeout: int) =
if hasPendingOperations(): asyncdispatch.poll(timeout)), 10)
init()
main()
|