summary refs log tree commit diff stats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/nimgrep.nim4
-rw-r--r--tools/niminst/buildbat.tmpl2
-rw-r--r--tools/niminst/buildsh.tmpl14
-rw-r--r--tools/niminst/debcreation.nim2
-rw-r--r--tools/niminst/deinstall.tmpl2
-rw-r--r--tools/niminst/inno.tmpl4
-rw-r--r--tools/niminst/install.tmpl2
-rw-r--r--tools/niminst/makefile.tmpl168
-rw-r--r--tools/niminst/niminst.nim158
-rw-r--r--tools/niminst/nsis.tmpl26
-rw-r--r--tools/nimrepl.nim2
-rw-r--r--tools/nimweb.nim36
-rw-r--r--tools/website.tmpl339
13 files changed, 484 insertions, 275 deletions
diff --git a/tools/nimgrep.nim b/tools/nimgrep.nim
index a38f2a88f..72e4adc07 100644
--- a/tools/nimgrep.nim
+++ b/tools/nimgrep.nim
@@ -24,7 +24,7 @@ Options:
   --re                pattern is a regular expression (default); extended 
                       syntax for the regular expression is always turned on
   --recursive         process directories recursively
-  --confirm           confirm each occurence/replacement; there is a chance 
+  --confirm           confirm each occurrence/replacement; there is a chance 
                       to abort any time without touching the file
   --stdin             read pattern from stdin (to avoid the shell's confusing
                       quoting rules)
@@ -109,7 +109,7 @@ proc highlight(s, match, repl: string, t: tuple[first, last: int],
   for i in t.last+1 .. y: stdout.write(s[i])
   stdout.write("\n")
   if showRepl:
-    stdout.write(repeatChar(alignment-1), "-> ")
+    stdout.write(spaces(alignment-1), "-> ")
     for i in x .. t.first-1: stdout.write(s[i])
     writeColored(repl)
     for i in t.last+1 .. y: stdout.write(s[i])
diff --git a/tools/niminst/buildbat.tmpl b/tools/niminst/buildbat.tmpl
index 415574273..3a11715bf 100644
--- a/tools/niminst/buildbat.tmpl
+++ b/tools/niminst/buildbat.tmpl
@@ -1,5 +1,5 @@
 #! stdtmpl(subsChar='?') | standard
-#proc generateBuildBatchScript(c: TConfigData, winIndex, cpuIndex: int): string = 
+#proc generateBuildBatchScript(c: ConfigData, winIndex, cpuIndex: int): string = 
 #  result = "@echo off\nREM Generated by niminst\n"
 SET CC=gcc
 SET LINKER=gcc
diff --git a/tools/niminst/buildsh.tmpl b/tools/niminst/buildsh.tmpl
index 4966af07a..52da351be 100644
--- a/tools/niminst/buildsh.tmpl
+++ b/tools/niminst/buildsh.tmpl
@@ -1,7 +1,7 @@
 #! stdtmpl(subsChar='?') | standard
-#proc generateBuildShellScript(c: TConfigData): string = 
+#proc generateBuildShellScript(c: ConfigData): string = 
 #  result = "#! /bin/sh\n# Generated from niminst\n" &
-#           "# Template is in tools/buildsh.tmpl\n" &
+#           "# Template is in tools/niminst/buildsh.tmpl\n" &
 #           "# To regenerate run ``niminst csource`` or ``koch csource``\n"
 
 set -e
@@ -54,10 +54,16 @@ case $uos in
     myos="linux" 
     LINK_FLAGS="$LINK_FLAGS -ldl -lm"
     ;;
-  *freebsd* | *dragonfly* ) 
+  *dragonfly* )
     myos="freebsd"
     LINK_FLAGS="$LINK_FLAGS -lm"
     ;;
+  *freebsd* )
+    myos="freebsd"
+    CC="clang"
+    LINKER="clang"
+    LINK_FLAGS="$LINK_FLAGS -lm"
+    ;;
   *openbsd* )
     myos="openbsd" 
     LINK_FLAGS="$LINK_FLAGS -lm"
@@ -105,7 +111,7 @@ case $ucpu in
       LINK_FLAGS="$LINK_FLAGS -m64"
     fi
     mycpu="powerpc64" ;;
-  *power*|*Power*|*ppc* ) 
+  *power*|*ppc* ) 
     mycpu="powerpc" ;;
   *mips* ) 
     mycpu="mips" ;;
diff --git a/tools/niminst/debcreation.nim b/tools/niminst/debcreation.nim
index 574f7ea6b..bbd997981 100644
--- a/tools/niminst/debcreation.nim
+++ b/tools/niminst/debcreation.nim
@@ -84,7 +84,7 @@ proc createCopyright(pkgName, mtnName, mtnEmail, version: string,
     addN("Files: " & f)
     addN("License: " & license)
 
-proc formatDateTime(t: TTimeInfo, timezone: string): string =
+proc formatDateTime(t: TimeInfo, timezone: string): string =
   var day = ($t.weekday)[0..2] & ", "
   
   return "$1$2 $3 $4 $5:$6:$7 $8" % [day, intToStr(t.monthday, 2),
diff --git a/tools/niminst/deinstall.tmpl b/tools/niminst/deinstall.tmpl
index 15f912af6..c4717a257 100644
--- a/tools/niminst/deinstall.tmpl
+++ b/tools/niminst/deinstall.tmpl
@@ -1,5 +1,5 @@
 #! stdtmpl(subsChar='?') | standard
-#proc generateDeinstallScript(c: TConfigData): string = 
+#proc generateDeinstallScript(c: ConfigData): string = 
 #  result = "#! /bin/sh\n# Generated by niminst\n"
 #  var proj = c.name.toLower
 
diff --git a/tools/niminst/inno.tmpl b/tools/niminst/inno.tmpl
index 3460c22a2..4acf0557c 100644
--- a/tools/niminst/inno.tmpl
+++ b/tools/niminst/inno.tmpl
@@ -1,5 +1,5 @@
 #! stdtmpl | standard
-#proc generateInnoSetup(c: TConfigData): string =
+#proc generateInnoSetup(c: ConfigData): string =
 #  result = ""
 ; Default Template for NimInst
 [Setup]
@@ -19,7 +19,7 @@ ChangesEnvironment=yes
 Name: english; MessagesFile: compiler:Default.isl
 
 [Files] 
-  #for i in low(TFileCategory)..fcWindows:
+  #for i in low(FileCategory)..fcWindows:
   #  for f in items(c.cat[i]):
 Source: ${expandFilename(f).toWin}; DestDir: {app}\${splitFile(f).dir.toWin}; Flags: ignoreversion
   #  end for
diff --git a/tools/niminst/install.tmpl b/tools/niminst/install.tmpl
index 437e13dfb..3ec42c287 100644
--- a/tools/niminst/install.tmpl
+++ b/tools/niminst/install.tmpl
@@ -1,5 +1,5 @@
 #! stdtmpl(subsChar = '?') | standard
-#proc generateInstallScript(c: TConfigData): string = 
+#proc generateInstallScript(c: ConfigData): string = 
 #  result = "#! /bin/sh\n# Generated by niminst\n"
 #  var proj = c.name.toLower
 
diff --git a/tools/niminst/makefile.tmpl b/tools/niminst/makefile.tmpl
new file mode 100644
index 000000000..8ab3b89d1
--- /dev/null
+++ b/tools/niminst/makefile.tmpl
@@ -0,0 +1,168 @@
+#! stdtmpl(subsChar='?') | standard
+#proc generateMakefile(c: ConfigData): string = 
+#  result = "# Generated from niminst\n" &
+#           "# Template is in tools/niminst/makefile.tmpl\n" &
+#           "# To regenerate run ``niminst csource`` or ``koch csource``\n"
+
+CC = gcc
+LINKER = gcc
+COMP_FLAGS = ?{c.ccompiler.flags}
+LINK_FLAGS = ?{c.linker.flags}
+binDir = ?{firstBinPath(c).toUnix}
+
+koch := $(shell sh -c 'test -s ../koch.nim && echo "yes"')
+ifeq ($(koch),yes)
+	binDir = ../bin
+endif
+
+ucpu := $(shell sh -c 'uname -m | tr "[:upper:]" "[:lower:]"')
+uos := $(shell sh -c 'uname | tr "[:upper:]" "[:lower:]"')
+
+ifeq ($(uos),linux)
+	myos = linux
+	LINK_FLAGS += -ldl -lm
+endif
+ifeq ($(uos),dragonfly)
+	myos = freebsd
+	LINK_FLAGS += -lm
+endif
+ifeq ($(uos),freebsd)
+	myos= freebsd
+	CC = clang
+	LINKER = clang
+	LINK_FLAGS += -lm
+endif
+ifeq ($(uos),openbsd)
+	myos = openbsd
+	LINK_FLAGS += -lm
+endif
+ifeq ($(uos),netbsd)
+	myos = netbsd
+	LINK_FLAGS += -lm
+endif
+ifeq ($(uos),darwin)
+	myos = macosx
+	CC = clang
+	LINKER = clang
+	LINK_FLAGS += -ldl -lm
+	ifeq ($HOSTTYPE,x86_64)
+		ucpu = amd64
+	endif
+endif
+ifeq ($(uos),aix)
+	myos = aix
+	LINK_FLAGS += -dl -lm
+endif
+ifeq ($(uos),solaris)
+	myos = solaris
+	LINK_FLAGS += -ldl -lm -lsocket -lnsl
+endif
+ifeq ($(uos),sun)
+	myos = solaris
+	LINK_FLAGS += -ldl -lm -lsocket -lnsl
+endif
+ifeq ($(uos),haiku)
+	myos = haiku
+endif
+ifndef uos
+	@echo "Error: unknown operating system: $(uos)"
+	@exit 1
+endif
+
+ifeq ($(ucpu),i386)
+	mycpu = i386
+endif
+ifeq ($(ucpu),i486)
+	mycpu = i386
+endif
+ifeq ($(ucpu),i586)
+	mycpu = i386
+endif
+ifeq ($(ucpu),i686)
+	mycpu = i386
+endif
+ifeq ($(ucpu),bepc)
+	mycpu = i386
+endif
+ifeq ($(ucpu),i86pc)
+	mycpu = i386
+endif
+ifeq ($(ucpu),amd64)
+	mycpu = amd64
+endif
+ifeq ($(ucpu),x86-64)
+	mycpu = amd64
+endif
+ifeq ($(ucpu),x86_64)
+	mycpu = amd64
+endif
+ifeq ($(ucpu),sparc)
+	mycpu = sparc
+endif
+ifeq ($(ucpu),sun)
+	mycpu = sparc
+endif
+ifeq ($(ucpu),ppc64)
+	mycpu = powerpc64
+	ifeq ($(myos),linux)
+		COMP_FLAGS += -m64
+		LINK_FLAGS += -m64
+	endif
+endif
+ifeq ($(ucpu),powerpc)
+	mycpu = powerpc
+endif
+ifeq ($(ucpu),ppc)
+	mycpu = ppc
+endif
+ifeq ($(ucpu),mips)
+	mycpu = mips
+endif
+ifeq ($(ucpu),arm)
+	mycpu = arm
+endif
+ifeq ($(ucpu),armeb)
+	mycpu = arm
+endif
+ifeq ($(ucpu),armel)
+	mycpu = arm
+endif
+ifeq ($(ucpu),armv6l)
+	mycpu = arm
+endif
+ifndef ucpu
+	@echo "Error: unknown processor : $(ucpu)"
+	@exit 1
+endif
+
+# for osA in 1..c.oses.len:
+ifeq ($(myos),?{c.oses[osA-1]})
+#   for cpuA in 1..c.cpus.len:
+	ifeq ($(mycpu),?{c.cpus[cpuA-1]})
+#     var oFiles = ""
+#     for ff in c.cfiles[osA][cpuA].items:
+#       oFiles.add(" " & changeFileExt(ff.toUnix, "o"))
+#     end for
+		oFiles =?oFiles
+	endif
+#   end for
+endif
+# end for
+
+ifeq ($(strip $(oFiles)),)
+	@echo "Error: no C code generated for: [$(myos): $(mycpu)]"
+	@exit 1
+endif
+
+%.o: %.c
+	$(CC) $(COMP_FLAGS) -Ic_code -c $< -o $@
+
+?{"$(binDir)/" & toLower(c.name)}: $(oFiles)
+	@mkdir -p $(binDir)
+	$(LINKER) -o $@ $^ $(LINK_FLAGS)
+	@echo "SUCCESS"
+
+.PHONY: clean
+
+clean:
+	rm -f $(oFiles) ?{"$(binDir)/" & toLower(c.name)}
diff --git a/tools/niminst/niminst.nim b/tools/niminst/niminst.nim
index 9ee3eb9b9..f0ae45484 100644
--- a/tools/niminst/niminst.nim
+++ b/tools/niminst/niminst.nim
@@ -1,7 +1,7 @@
 #
 #
 #        The Nim Installation Generator
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -22,21 +22,23 @@ const
   buildShFile = "build.sh"
   buildBatFile32 = "build.bat"
   buildBatFile64 = "build64.bat"
+  makeFile = "makefile"
   installShFile = "install.sh"
   deinstallShFile = "deinstall.sh"
 
 type
-  TAppType = enum appConsole, appGUI
-  TAction = enum
+  AppType = enum appConsole, appGUI
+  Action = enum
     actionNone,   # action not yet known
     actionCSource # action: create C sources
     actionInno,   # action: create Inno Setup installer
     actionNsis,   # action: create NSIS installer
     actionScripts # action: create install and deinstall scripts
     actionZip,    # action: create zip file
+    actionTargz,  # action: create targz file
     actionDeb     # action: prepare deb package
 
-  TFileCategory = enum
+  FileCategory = enum
     fcWinBin,     # binaries for Windows
     fcConfig,     # configuration files
     fcData,       # data files
@@ -48,19 +50,19 @@ type
     fcUnixBin,    # binaries for Unix
     fcDocStart    # links to documentation for Windows installer
 
-  TConfigData = object of TObject
-    actions: set[TAction]
-    cat: array[TFileCategory, seq[string]]
+  ConfigData = object of RootObj
+    actions: set[Action]
+    cat: array[FileCategory, seq[string]]
     binPaths, authors, oses, cpus, downloads: seq[string]
     cfiles: array[1..maxOS, array[1..maxCPU, seq[string]]]
     platforms: array[1..maxOS, array[1..maxCPU, bool]]
     ccompiler, linker, innosetup, nsisSetup: tuple[path, flags: string]
     name, displayName, version, description, license, infile, outdir: string
-    libpath: string
+    mainfile, libpath: string
     innoSetupFlag, installScript, uninstallScript: bool
     explicitPlatforms: bool
-    vars: PStringTable
-    app: TAppType
+    vars: StringTableRef
+    app: AppType
     nimArgs: string
     debOpts: TDebOptions
 
@@ -69,9 +71,9 @@ const
     "$configdir", "$datadir", "$docdir", "$libdir"
   ]
 
-proc initConfigData(c: var TConfigData) =
+proc iniConfigData(c: var ConfigData) =
   c.actions = {}
-  for i in low(TFileCategory)..high(TFileCategory): c.cat[i] = @[]
+  for i in low(FileCategory)..high(FileCategory): c.cat[i] = @[]
   c.binPaths = @[]
   c.authors = @[]
   c.oses = @[]
@@ -87,6 +89,7 @@ proc initConfigData(c: var TConfigData) =
   c.description = ""
   c.license = ""
   c.infile = ""
+  c.mainfile = ""
   c.outdir = ""
   c.nimArgs = ""
   c.libpath = ""
@@ -100,7 +103,7 @@ proc initConfigData(c: var TConfigData) =
   c.debOpts.shortDesc = ""
   c.debOpts.licenses = @[]
 
-proc firstBinPath(c: TConfigData): string =
+proc firstBinPath(c: ConfigData): string =
   if c.binPaths.len > 0: result = c.binPaths[0]
   else: result = ""
 
@@ -122,6 +125,7 @@ proc skipRoot(f: string): string =
 include "inno.tmpl"
 include "nsis.tmpl"
 include "buildsh.tmpl"
+include "makefile.tmpl"
 include "buildbat.tmpl"
 include "install.tmpl"
 include "deinstall.tmpl"
@@ -132,7 +136,7 @@ const
   Version = "1.0"
   Usage = "niminst - Nim Installation Generator Version " & Version & """
 
-  (c) 2014 Andreas Rumpf
+  (c) 2015 Andreas Rumpf
 Usage:
   niminst [options] command[;command2...] ini-file[.ini] [compile_options]
 Command:
@@ -144,6 +148,8 @@ Command:
   deb                 create files for debhelper
 Options:
   -o, --output:dir    set the output directory
+  -m, --main:file     set the main nim file, by default ini-file with .nim
+                      extension
   --var:name=value    set the value of a variable
   -h, --help          shows this help
   -v, --version       shows the version
@@ -151,7 +157,7 @@ Compile_options:
   will be passed to the Nim compiler
 """
 
-proc parseCmdLine(c: var TConfigData) =
+proc parseCmdLine(c: var ConfigData) =
   var p = initOptParser()
   while true:
     next(p)
@@ -166,6 +172,7 @@ proc parseCmdLine(c: var TConfigData) =
           of "csource": incl(c.actions, actionCSource)
           of "scripts": incl(c.actions, actionScripts)
           of "zip": incl(c.actions, actionZip)
+          of "targz": incl(c.actions, actionTargz)
           of "inno": incl(c.actions, actionInno)
           of "nsis": incl(c.actions, actionNsis)
           of "deb": incl(c.actions, actionDeb)
@@ -176,13 +183,14 @@ proc parseCmdLine(c: var TConfigData) =
         break
     of cmdLongoption, cmdShortOption:
       case normalize(key.string)
-      of "help", "h": 
+      of "help", "h":
         stdout.write(Usage)
         quit(0)
-      of "version", "v": 
+      of "version", "v":
         stdout.write(Version & "\n")
         quit(0)
       of "o", "output": c.outdir = val
+      of "m", "main": c.mainfile = changeFileExt(val, "nim")
       of "var":
         var idx = val.find('=')
         if idx < 0: quit("invalid command line")
@@ -190,6 +198,7 @@ proc parseCmdLine(c: var TConfigData) =
       else: quit(Usage)
     of cmdEnd: break
   if c.infile.len == 0: quit(Usage)
+  if c.mainfile.len == 0: c.mainfile = changeFileExt(c.infile, "nim")
 
 proc walkDirRecursively(s: var seq[string], root: string) =
   for k, f in walkDir(root):
@@ -209,19 +218,19 @@ proc addFiles(s: var seq[string], patterns: seq[string]) =
         inc(i)
       if i == 0: echo("[Warning] No file found that matches: " & p)
 
-proc pathFlags(p: var TCfgParser, k, v: string,
+proc pathFlags(p: var CfgParser, k, v: string,
                t: var tuple[path, flags: string]) =
   case normalize(k)
   of "path": t.path = v
   of "flags": t.flags = v
   else: quit(errorStr(p, "unknown variable: " & k))
 
-proc filesOnly(p: var TCfgParser, k, v: string, dest: var seq[string]) =
+proc filesOnly(p: var CfgParser, k, v: string, dest: var seq[string]) =
   case normalize(k)
   of "files": addFiles(dest, split(v, {';'}))
   else: quit(errorStr(p, "unknown variable: " & k))
 
-proc yesno(p: var TCfgParser, v: string): bool =
+proc yesno(p: var CfgParser, v: string): bool =
   case normalize(v)
   of "yes", "y", "on", "true":
     result = true
@@ -233,9 +242,9 @@ proc incl(s: var seq[string], x: string): int =
   for i in 0.. <s.len:
     if cmpIgnoreStyle(s[i], x) == 0: return i
   s.add(x)
-  result = s.len-1 
+  result = s.len-1
 
-proc platforms(c: var TConfigData, v: string) =
+proc platforms(c: var ConfigData, v: string) =
   for line in splitLines(v):
     let p = line.find(": ")
     if p <= 1: continue
@@ -246,9 +255,9 @@ proc platforms(c: var TConfigData, v: string) =
       let cpuIdx = c.cpus.incl(cpu)
       c.platforms[c.oses.len][cpuIdx+1] = true
 
-proc parseIniFile(c: var TConfigData) =
+proc parseIniFile(c: var ConfigData) =
   var
-    p: TCfgParser
+    p: CfgParser
     section = ""
     hasCpuOs = false
   var input = newFileStream(c.infile, fmRead)
@@ -270,17 +279,17 @@ proc parseIniFile(c: var TConfigData) =
           of "name": c.name = v
           of "displayname": c.displayName = v
           of "version": c.version = v
-          of "os": 
+          of "os":
             c.oses = split(v, {';'})
             hasCpuOs = true
             if c.explicitPlatforms:
               quit(errorStr(p, "you cannot have both 'platforms' and 'os'"))
-          of "cpu": 
+          of "cpu":
             c.cpus = split(v, {';'})
             hasCpuOs = true
             if c.explicitPlatforms:
               quit(errorStr(p, "you cannot have both 'platforms' and 'cpu'"))
-          of "platforms": 
+          of "platforms":
             platforms(c, v)
             c.explicitPlatforms = true
             if hasCpuOs:
@@ -358,15 +367,15 @@ proc parseIniFile(c: var TConfigData) =
       of cfgOption: quit(errorStr(p, "syntax error"))
       of cfgError: quit(errorStr(p, k.msg))
     close(p)
-    if c.name.len == 0: c.name = changeFileExt(extractFilename(c.infile), "")
+    if c.name.len == 0: c.name = changeFileExt(extractFilename(c.mainfile), "")
     if c.displayName.len == 0: c.displayName = c.name
   else:
     quit("cannot open: " & c.infile)
 
 # ------------------------- generate source based installation ---------------
 
-proc readCFiles(c: var TConfigData, osA, cpuA: int) =
-  var p: TCfgParser
+proc readCFiles(c: var ConfigData, osA, cpuA: int) =
+  var p: CfgParser
   var f = splitFile(c.infile).dir / "mapping.txt"
   c.cfiles[osA][cpuA] = @[]
   var input = newFileStream(f, fmRead)
@@ -382,7 +391,7 @@ proc readCFiles(c: var TConfigData, osA, cpuA: int) =
       of cfgKeyValuePair:
         case section
         of "ccompiler": pathFlags(p, k.key, k.value, c.ccompiler)
-        of "linker": 
+        of "linker":
           pathFlags(p, k.key, k.value, c.linker)
           # HACK: we conditionally add ``-lm -ldl``, so remove them from the
           # linker flags:
@@ -402,11 +411,11 @@ proc readCFiles(c: var TConfigData, osA, cpuA: int) =
 proc buildDir(os, cpu: int): string =
   return "c_code" / ($os & "_" & $cpu)
 
-proc getOutputDir(c: var TConfigData): string =
+proc getOutputDir(c: var ConfigData): string =
   if c.outdir.len > 0: c.outdir else: "build"
 
 proc writeFile(filename, content, newline: string) =
-  var f: TFile
+  var f: File
   if open(f, filename, fmWrite):
     for x in splitLines(content):
       write(f, x)
@@ -415,7 +424,7 @@ proc writeFile(filename, content, newline: string) =
   else:
     quit("Cannot open for writing: " & filename)
 
-proc removeDuplicateFiles(c: var TConfigData) =
+proc removeDuplicateFiles(c: var ConfigData) =
   for osA in countdown(c.oses.len, 1):
     for cpuA in countdown(c.cpus.len, 1):
       if c.cfiles[osA][cpuA].isNil: c.cfiles[osA][cpuA] = @[]
@@ -433,13 +442,15 @@ proc removeDuplicateFiles(c: var TConfigData) =
                 removeFile(dup)
                 c.cfiles[osA][cpuA][i] = orig
 
-proc writeInstallScripts(c: var TConfigData) =
+proc writeInstallScripts(c: var ConfigData) =
   if c.installScript:
     writeFile(installShFile, generateInstallScript(c), "\10")
+    inclFilePermissions(installShFile, {fpUserExec, fpGroupExec, fpOthersExec})
   if c.uninstallScript:
     writeFile(deinstallShFile, generateDeinstallScript(c), "\10")
+    inclFilePermissions(deinstallShFile, {fpUserExec, fpGroupExec, fpOthersExec})
 
-proc srcdist(c: var TConfigData) =
+proc srcdist(c: var ConfigData) =
   if not existsDir(getOutputDir(c) / "c_code"):
     createDir(getOutputDir(c) / "c_code")
   for x in walkFiles(c.libpath / "lib/*.h"):
@@ -462,8 +473,7 @@ proc srcdist(c: var TConfigData) =
       var cmd = ("nim compile -f --symbolfiles:off --compileonly " &
                  "--gen_mapping --cc:gcc --skipUserCfg" &
                  " --os:$# --cpu:$# $# $#") %
-                 [osname, cpuname, c.nimArgs,
-                 changeFileExt(c.infile, "nim")]
+                 [osname, cpuname, c.nimArgs, c.mainfile]
       echo(cmd)
       if execShellCmd(cmd) != 0:
         quit("Error: call to nim compiler failed")
@@ -476,6 +486,8 @@ proc srcdist(c: var TConfigData) =
   # second pass: remove duplicate files
   removeDuplicateFiles(c)
   writeFile(getOutputDir(c) / buildShFile, generateBuildShellScript(c), "\10")
+  inclFilePermissions(getOutputDir(c) / buildShFile, {fpUserExec, fpGroupExec, fpOthersExec})
+  writeFile(getOutputDir(c) / makeFile, generateMakefile(c), "\10")
   if winIndex >= 0:
     if intel32Index >= 0:
       writeFile(getOutputDir(c) / buildBatFile32,
@@ -486,7 +498,7 @@ proc srcdist(c: var TConfigData) =
   writeInstallScripts(c)
 
 # --------------------- generate inno setup -----------------------------------
-proc setupDist(c: var TConfigData) =
+proc setupDist(c: var ConfigData) =
   let scrpt = generateInnoSetup(c)
   let n = "build" / "install_$#_$#.iss" % [toLower(c.name), c.version]
   writeFile(n, scrpt, "\13\10")
@@ -503,7 +515,7 @@ proc setupDist(c: var TConfigData) =
       quit("External program failed")
 
 # --------------------- generate NSIS setup -----------------------------------
-proc setupDist2(c: var TConfigData) =
+proc setupDist2(c: var ConfigData) =
   let scrpt = generateNsisSetup(c)
   let n = "build" / "install_$#_$#.nsi" % [toLower(c.name), c.version]
   writeFile(n, scrpt, "\13\10")
@@ -521,9 +533,9 @@ proc setupDist2(c: var TConfigData) =
 
 # ------------------ generate ZIP file ---------------------------------------
 when haveZipLib:
-  proc zipDist(c: var TConfigData) =
-    var proj = toLower(c.name)
-    var n = "$#_$#.zip" % [proj, c.version]
+  proc zipDist(c: var ConfigData) =
+    var proj = toLower(c.name) & "-" & c.version
+    var n = "$#.zip" % proj
     if c.outdir.len == 0: n = "build" / n
     else: n = c.outdir / n
     var z: TZipArchive
@@ -531,6 +543,7 @@ when haveZipLib:
       addFile(z, proj / buildBatFile32, "build" / buildBatFile32)
       addFile(z, proj / buildBatFile64, "build" / buildBatFile64)
       addFile(z, proj / buildShFile, "build" / buildShFile)
+      addFile(z, proj / makeFile, "build" / makeFile)
       addFile(z, proj / installShFile, installShFile)
       addFile(z, proj / deinstallShFile, deinstallShFile)
       for f in walkFiles(c.libpath / "lib/*.h"):
@@ -547,30 +560,71 @@ when haveZipLib:
     else:
       quit("Cannot open for writing: " & n)
 
+proc targzDist(c: var ConfigData) =
+  let proj = toLower(c.name) & "-" & c.version
+  var n = "$#.tar.gz" % proj
+  let tmpDir = if c.outdir.len == 0: "build" else: c.outdir
+
+  template processFile(z, dest, src) =
+    let s = src
+    let d = dest
+    echo "Copying ", s, " to ", tmpDir / d
+    let destdir = tmpdir / d.splitFile.dir
+    if not dirExists(destdir): createDir(destdir)
+    copyFile(s, tmpDir / d)
+
+  processFile(z, proj / buildBatFile32, "build" / buildBatFile32)
+  processFile(z, proj / buildBatFile64, "build" / buildBatFile64)
+  processFile(z, proj / buildShFile, "build" / buildShFile)
+  processFile(z, proj / makeFile, "build" / makeFile)
+  processFile(z, proj / installShFile, installShFile)
+  processFile(z, proj / deinstallShFile, deinstallShFile)
+  for f in walkFiles(c.libpath / "lib/*.h"):
+    processFile(z, proj / "c_code" / extractFilename(f), f)
+  for osA in 1..c.oses.len:
+    for cpuA in 1..c.cpus.len:
+      var dir = buildDir(osA, cpuA)
+      for k, f in walkDir("build" / dir):
+        if k == pcFile: processFile(z, proj / dir / extractFilename(f), f)
+
+  for cat in items({fcConfig..fcOther, fcUnix}):
+    for f in items(c.cat[cat]): processFile(z, proj / f, f)
+
+  let oldDir = getCurrentDir()
+  setCurrentDir(tmpDir)
+  try:
+    #if execShellCmd("7z a -ttar $1.tar $1" % proj) != 0 or
+    #   execShellCmd("7z a -tgzip $1.tar.gz $1.tar" % proj) != 0 or
+    if execShellCmd("7z a -tzip $1.zip $1" % proj) != 0:
+      echo("External program failed")
+  finally:
+    setCurrentDir(oldDir)
+
 # -- prepare build files for .deb creation
 
-proc debDist(c: var TConfigData) =
+proc debDist(c: var ConfigData) =
   if not existsFile(getOutputDir(c) / "build.sh"): quit("No build.sh found.")
   if not existsFile(getOutputDir(c) / "install.sh"): quit("No install.sh found.")
-  
+
   if c.debOpts.shortDesc == "": quit("shortDesc must be set in the .ini file.")
   if c.debOpts.licenses.len == 0:
     echo("[Warning] No licenses specified for .deb creation.")
-  
+
   # -- Copy files into /tmp/..
   echo("Copying source to tmp/niminst/deb/")
   var currentSource = getCurrentDir()
   var workingDir = getTempDir() / "niminst" / "deb"
   var upstreamSource = (c.name.toLower() & "-" & c.version)
-  
+
   createDir(workingDir / upstreamSource)
-  
+
   template copyNimDist(f, dest: string): stmt =
     createDir((workingDir / upstreamSource / dest).splitFile.dir)
     copyFile(currentSource / f, workingDir / upstreamSource / dest)
-  
+
   # Don't copy all files, only the ones specified in the config:
   copyNimDist(buildShFile, buildShFile)
+  copyNimDist(makeFile, makeFile)
   copyNimDist(installShFile, installShFile)
   createDir(workingDir / upstreamSource / "build")
   for f in walkFiles(c.libpath / "lib/*.h"):
@@ -595,8 +649,8 @@ proc debDist(c: var TConfigData) =
 
 # ------------------- main ----------------------------------------------------
 
-var c: TConfigData
-initConfigData(c)
+var c: ConfigData
+iniConfigData(c)
 parseCmdLine(c)
 parseIniFile(c)
 if actionInno in c.actions:
@@ -612,5 +666,7 @@ if actionZip in c.actions:
     zipDist(c)
   else:
     quit("libzip is not installed")
+if actionTargz in c.actions:
+  targzDist(c)
 if actionDeb in c.actions:
   debDist(c)
diff --git a/tools/niminst/nsis.tmpl b/tools/niminst/nsis.tmpl
index 40e171d41..843a8cf44 100644
--- a/tools/niminst/nsis.tmpl
+++ b/tools/niminst/nsis.tmpl
@@ -1,5 +1,5 @@
 #! stdtmpl(subsChar='?') | standard
-#proc generateNsisSetup(c: TConfigData): string = 
+#proc generateNsisSetup(c: ConfigData): string =
 #  result = "; NSIS script generated by niminst\n" &
 #           "; To regenerate run ``niminst nsis`` or ``koch nsis``\n"
 
@@ -35,8 +35,8 @@
 
   ; Default installation folder
   ; This is changed later (in .onInit) to the root directory, if possible.
-  InstallDir "$LOCALAPPDATA\?{c.name}"
-  
+  InstallDir "$LOCALAPPDATA\?{c.name}-?{c.version}"
+
   ; Get installation folder from registry if available
   InstallDirRegKey HKCU "Software\c.name\c.version" ""
 
@@ -50,8 +50,8 @@
   SetCompressor /SOLID /FINAL lzma
 
   ; Installer and Uninstaller Icons
-  ; Icon "nimrod.ico"
-  ; UninstallIcon "nimrod.ico"
+  ; Icon "nim.ico"
+  ; UninstallIcon "nim.ico"
 
   ; Set installation details to be shown by default
   ShowInstDetails show
@@ -86,14 +86,14 @@
 
   !insertmacro MUI_PAGE_INSTFILES
   !insertmacro MUI_PAGE_FINISH
-  
+
   ; Setup the uninstaller pages
   !insertmacro MUI_UNPAGE_CONFIRM
   !insertmacro MUI_UNPAGE_INSTFILES
-  
+
 ;--------------------------------
 ;Languages
- 
+
   !insertmacro MUI_LANGUAGE "English"
 
 ;--------------------------------
@@ -104,7 +104,7 @@
   ; Nim binary.
   Section "Core Files" CoreSection
     ; This is a mandotory section
-    SectionIn RO 
+    SectionIn RO
 
     ; Output files to the base installation directory
     SetOutPath "$INSTDIR"
@@ -113,7 +113,7 @@
     SetOverwrite ifnewer
 
     ; Write all the files to the output directory.
-    #for i in low(TFileCategory)..fcWindows:
+    #for i in low(FileCategory)..fcWindows:
     #  for f in items(c.cat[i]):
          SetOutPath "$INSTDIR\?{splitFile(f).dir.toWin}"
          File "?{expandFilename(f).toWin}"
@@ -128,7 +128,7 @@
     ; Write application registry keys
     WriteRegStr HKCU "${PRODUCT_DIR_REGKEY}" "" "$INSTDIR\bin\?{c.name}.exe"
     WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayName" "$(^Name)"
-    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninst.exe"
+    WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "UninstallString" "$INSTDIR\uninstaller.exe"
     WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayIcon" "$INSTDIR\bin\?{c.name}.exe"
     WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "DisplayVersion" "${PRODUCT_VERSION}"
     WriteRegStr ${PRODUCT_UNINST_ROOT_KEY} "${PRODUCT_UNINST_KEY}" "Publisher" "${PRODUCT_PUBLISHER}"
@@ -164,7 +164,7 @@
 
   ; The downloadable sections. These sections are automatically generated by
   ; niminst and the template filters.
-  #var i = 0 
+  #var i = 0
   #for download in c.downloads:
   #  inc i
   #  let d = download.split('|')
@@ -207,7 +207,7 @@
         CreateShortCut "$SMPROGRAMS\$ICONS_GROUP\?{e}.lnk" "$INSTDIR\?dir\?{startMenuEntry.toWin}"
       !insertmacro MUI_STARTMENU_WRITE_END
     #  end if
-    
+
     ignore:
   SectionEnd
   #end
diff --git a/tools/nimrepl.nim b/tools/nimrepl.nim
index 0c9f94616..3d818a556 100644
--- a/tools/nimrepl.nim
+++ b/tools/nimrepl.nim
@@ -130,7 +130,7 @@ proc initControls() =
   
   pack_start(MainBox, TopMenu, False, False, 0)
 
-  # VPaned - Seperates the InputTextView and the OutputTextView
+  # VPaned - Separates the InputTextView and the OutputTextView
   var paned = vpaned_new()
   set_position(paned, 450)
   pack_start(MainBox, paned, True, True, 0)
diff --git a/tools/nimweb.nim b/tools/nimweb.nim
index bbd3776d7..a7301195e 100644
--- a/tools/nimweb.nim
+++ b/tools/nimweb.nim
@@ -1,7 +1,7 @@
 #
 #
 #           Nim Website Generator
-#        (c) Copyright 2014 Andreas Rumpf
+#        (c) Copyright 2015 Andreas Rumpf
 #
 #    See the file "copying.txt", included in this
 #    distribution, for details about the copyright.
@@ -23,6 +23,7 @@ type
     gitCommit: string
     quotations: Table[string, tuple[quote, author: string]]
     numProcessors: int # Set by parallelBuild:n, only works for values > 0.
+    gaId: string  # google analytics ID, nil means analytics are disabled
   TRssItem = object
     year, month, day, title: string
   TAction = enum
@@ -47,7 +48,7 @@ proc initConfigData(c: var TConfigData) =
   c.logo = ""
   c.ticker = ""
   c.vars = newStringTable(modeStyleInsensitive)
-  c.gitRepo = "https://github.com/Araq/Nimrod/tree"
+  c.gitRepo = "https://github.com/Araq/Nim/tree"
   c.gitCommit = "master"
   c.numProcessors = countProcessors()
   # Attempts to obtain the git current commit.
@@ -65,7 +66,7 @@ const
   version = "0.7"
   usage = "nimweb - Nim Website Generator Version " & version & """
 
-  (c) 2014 Andreas Rumpf
+  (c) 2015 Andreas Rumpf
 Usage:
   nimweb [options] ini-file[.ini] [compile_options]
 Options:
@@ -98,8 +99,8 @@ macro updated(e: expr): expr {.immediate.} =
 proc updatedDate(year, month, day: string): string =
   ## wrapper around the update macro with easy input.
   result = updated("$1-$2-$3T00:00:00Z" % [year,
-    repeatStr(2 - len(month), "0") & month,
-    repeatStr(2 - len(day), "0") & day])
+    repeat("0", 2 - len(month)) & month,
+    repeat("0", 2 - len(day)) & day])
 
 macro entry(e: expr): expr {.immediate.} =
   ## generates the rss xml ``entry`` element.
@@ -144,7 +145,12 @@ proc parseCmdLine(c: var TConfigData) =
         c.vars[substr(val, 0, idx-1)] = substr(val, idx+1)
       of "website": action = actOnlyWebsite
       of "pdf": action = actPdf
-      else: quit(usage)
+      of "googleanalytics":
+        c.gaId = val
+        c.nimArgs.add("--doc.googleAnalytics:" & val & " ")
+      else:
+        echo("Invalid argument $1" % [key])
+        quit(usage)
     of cmdEnd: break
   if c.infile.len == 0: quit(usage)
 
@@ -262,24 +268,26 @@ proc buildDocSamples(c: var TConfigData, destPath: string) =
   exec("nim doc2 $# -o:$# $#" %
     [c.nimArgs, destPath / "docgen_sample2.html", src])
 
+proc pathPart(d: string): string = splitFile(d).dir.replace('\\', '/')
+
 proc buildDoc(c: var TConfigData, destPath: string) =
   # call nim for the documentation:
   var
     commands = newSeq[string](len(c.doc) + len(c.srcdoc) + len(c.srcdoc2))
     i = 0
   for d in items(c.doc):
-    commands[i] = "nim rst2html $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim rst2html $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
   for d in items(c.srcdoc):
-    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
   for d in items(c.srcdoc2):
-    commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$# -o:$# --index:on $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$#/$# -o:$# --index:on $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, d.pathPart,
       destPath / changeFileExt(splitFile(d).name, "html"), d]
     i.inc
 
@@ -311,8 +319,8 @@ proc buildAddDoc(c: var TConfigData, destPath: string) =
   # build additional documentation (without the index):
   var commands = newSeq[string](c.webdoc.len)
   for i, doc in pairs(c.webdoc):
-    commands[i] = "nim doc $# --docSeeSrcUrl:$#/$# -o:$# $#" %
-      [c.nimArgs, c.gitRepo, c.gitCommit,
+    commands[i] = "nim doc2 $# --docSeeSrcUrl:$#/$#/$# -o:$# $#" %
+      [c.nimArgs, c.gitRepo, c.gitCommit, doc.pathPart,
       destPath / changeFileExt(splitFile(doc).name, "html"), doc]
   mexec(commands, c.numProcessors)
 
diff --git a/tools/website.tmpl b/tools/website.tmpl
index 6f7a216a5..bc3ed8e2c 100644
--- a/tools/website.tmpl
+++ b/tools/website.tmpl
@@ -1,142 +1,142 @@
 #! stdtmpl | standard
 #proc generateHTMLPage(c: var TConfigData, currentTab, content, rss: string): string = 
 #  result = ""
-<!DOCTYPE html>

+<!DOCTYPE html>
 <html>
-  <head>

-    <meta http-equiv="content-type" content="text/html; charset=utf-8">

-    <title>$c.projectTitle</title>

+  <head>
+    <meta http-equiv="content-type" content="text/html; charset=utf-8">
+    <title>$c.projectTitle</title>
     <link rel="stylesheet" type="text/css" href="assets/style.css" />
-
-    <link rel="shortcut icon" href="assets/images/favicon.ico">

+    <link rel="shortcut icon" href="assets/images/favicon.ico">
   #if len(rss) > 0:
     <link href="$rss" title="Recent changes" type="application/atom+xml" rel="alternate">
   #end if
-  </head>

-  <body>

-    <header id="head">

-      <div class="page-layout tall">

-        <div id="head-logo"></div>

-        <a id="head-logo-link" href="http://nim-lang.org/index.html"></a>

+  </head>
+  <body>
+    <header id="head">
+      <div class="page-layout tall">
+        <div id="head-logo"></div>
+        <a id="head-logo-link" href="index.html"></a>
         <nav id="head-links">
       #for i in 0.. c.tabs.len-1:
-      #  var name = c.tabs[i].key
-      #  var t = c.tabs[i].val
-        #if currentTab == t:
-          <a class="active" 
-        #elif t == "community" or t == "news":
-        #  continue
-        #else:
-          <a
-        #end if
-        #if t.contains('.'):
-          href="${t}" title = "$c.projectName - $name">$name</a>
-        #else:
-          href="${t}.html" title = "$c.projectName - $name">$name</a>
-        #end if
+      # let t = c.tabs[i].val
+      # if t != "index" and t != "community" and t != "news":
+      #   let name = c.tabs[i].key
+      #   if currentTab == t:
+            <a class="active" 
+      #   else:
+            <a
+      #   end if
+      #   if t.contains('.'):
+            href="${t}" title = "$c.projectName - $name">$name</a>
+      #   else:
+            href="${t}.html" title = "$c.projectName - $name">$name</a>
+      #   end if
+      # end if
       #end for
-        </nav>

-      </div>

-    </header>

+        </nav>
+      </div>
+    </header>
 
 #  if currentTab == "index":
     <section id="neck" class="home">
 #  else:
     <section id="neck">
-#  end

-      <div class="page-layout tall">

+#  end
+      <div class="page-layout tall">
         <div id="glow-arrow"></div>
 
-#  if currentTab == "index":

-        <div id="slideshow">

+#  if currentTab == "index":
+        <div id="slideshow">
           <!-- slides -->
-          <div id="slide0" class="">

-            <div>

-              <h2>Nim looks like this..</h2>

-<pre><span class="cmt"># compute average line length</span>

-<span class="kwd">var</span>

-<span class="tab">  </span>sum = <span class="val">0</span>

-<span class="tab end">  </span>count = <span class="val">0</span>

-

-<span class="kwd">for</span> line <span class="kwd">in</span> stdin.lines:

-<span class="tab">  </span>sum += line.len

-<span class="tab end">  </span>count += <span class="val">1</span>

-

-echo(<span class="val">"Average line length: "</span>,

-  <span class="kwd">if</span> count: sum / count <span class="kwd">else</span>: <span class="val">0</span>)

-</pre>

-            </div>

-            <div>

-               <h2>..and this...</h2>

-<pre><span class="cmt"># create and greet someone</span>

-<span class="kwd">type</span> <span class="def">Person</span> = <span class="typ">object</span>

-<span class="tab">  </span>name: <span class="typ">string</span>

-<span class="tab end">  </span>age: <span class="typ">int</span>

-

-<span class="kwd">proc</span> <span class="def">greet</span>(p: <span class="typ">Person</span>) =

-<span class="tab">  </span>echo <span class="val">"Hi, I'm "</span>, p.name, <span class="val">"."</span>

-<span class="tab end">  </span>echo <span class="val">"I am "</span>, p.age, <span class="val">" years old."</span>

-

-<span class="kwd">var</span> p = <span class="typ">Person</span>(name:<span class="val">"Jon"</span>, age:<span class="val">18</span>)

-p.greet() <span class="cmt"># or greet(p)</span>

-</pre>

-             </div>

-          </div>  <!-- slide0 -->
-          <div id="slide1" class="active">
-             <h2><a name="why-should-i-be-excited">Why should I be excited?</a></h2>
-             <span class="desc">
-               Nim is the only language that leverages automated proof technology
-               to perform a <i>disjoint check</i> for your parallel
-               code. Working on disjoint data means no locking is
-               required and yet data races are impossible:</span>
-             <pre>
+          <div id="slide0" class="active">
+            <h2><a name="why-should-i-be-excited">Why should I be excited?</a></h2>
+            <span class="desc">Nim is the only language that leverages automated proof technology to perform a <i>disjoint check</i> for your parallel code. Working on disjoint data means no locking is required and yet data races are impossible:</span><br><br>
+<pre>
 <span class="kwd">parallel</span>:
 <span class="tab">  </span><span class="kwd">var</span> i = <span class="val">0</span>
 <span class="tab">  </span><span class="kwd">while</span> i <= a.high:
-<span class="tab">    </span>spawn f(a[i])
-<span class="tab">    </span>spawn f(a[i+<span class="val">1</span>])
-<span class="tab">    </span><span class="cmt"># ERROR: cannot prove a[i] is disjoint from a[i+1]</span>
-<span class="tab">    </span><span class="cmt"># BUT: replace 'i += 1' with 'i += 2' and the code compiles!</span>
-<span class="tab end">    </span>i += <span class="val">1</span>
-            </pre>
+<span class="tab">  <span class="tab">  </span></span></span><span class="kwd">spawn</span> f(a[i])
+<span class="tab">  <span class="tab">  </span></span></span><span class="kwd">spawn</span> f(a[i+<span class="val">1</span>])
+<span class="tab">  <span class="tab">  </span></span></span><span class="cmt"># ERROR: cannot prove a[i] is disjoint from a[i+1]</span>
+<span class="tab">  <span class="tab">  </span></span></span><span class="cmt"># BUT: replace 'i += 1' with 'i += 2' and the code compiles!</span>
+<span class="tab end">  <span class="tab end">  </span></span>i += <span class="val">1</span>
+</pre>
+          </div>
+          <div id="slide1">
+            <div>
+              <h2>Nim is simple..</h2>
+<pre>
+<span class="cmt"># compute average line length</span>
+<span class="kwd">var</span>
+<span class="tab">  </span>sum = <span class="val">0</span>
+<span class="tab end">  </span>count = <span class="val">0</span>
+
+<span class="kwd">for</span> line <span class="kwd">in</span> stdin.lines:
+<span class="tab">  </span>sum += line.len
+<span class="tab end">  </span>count += <span class="val">1</span>
+
+echo(<span class="val">"Average line length: "</span>,
+  <span class="kwd">if</span> count &gt; <span class="val">0</span>: sum / count <span class="kwd">else</span>: <span class="val">0</span>)
+</pre>
+            </div>
+            <div>
+               <h2>..and type safe...</h2>
+<pre>
+<span class="cmt"># create and greet someone</span>
+<span class="kwd">type</span> <span class="def">Person</span> = <span class="kwd">object</span>
+<span class="tab">  </span>name: <span class="typ">string</span>
+<span class="tab end">  </span>age: <span class="typ">int</span>
+
+<span class="kwd">proc</span> <span class="def">greet</span>(p: <span class="typ">Person</span>) =
+<span class="tab">  </span>echo <span class="val">"Hi, I'm "</span>, p.name, <span class="val">"."</span>
+<span class="tab end">  </span>echo <span class="val">"I am "</span>, p.age, <span class="val">" years old."</span>
+
+<span class="kwd">let</span> p = <span class="typ">Person</span>(name:<span class="val">"Jon"</span>, age:<span class="val">18</span>)
+p.greet() <span class="cmt"># or greet(p)</span>
+</pre>
+             </div>
           </div>
           <div id="slide2" class="">
             <div>
-            <h2>interfacing with C..</h2>
-            <pre>
-<span class="kwd">proc</span> <span class="def">unsafeScanf</span>(f: <span class="typ">File</span>; s: <span class="typ">cstring</span>)
-<span class="tab">  </span>{.importc: <span class="val">"fscanf"</span>, 
-<span class="tab end">    </span>header: <span class="val">"&lt;stdio.h&gt;"</span>, varargs.}
-
-<span class="kwd">var</span> x: cint
-unsafeScanf(stdin, <span class="val">"%d"</span>, <span class="kwd">addr</span> x)
-            </pre></div>
-
+              <h2>C FFI is easy in Nim..</h2>
+<pre>
+<span class="cmt"># declare a C procedure..</span>
+<span class="kwd">proc</span> <span class="def">unsafeScanf</span>(f: <span class="typ">File</span>, s: <span class="typ">cstring</span>)
+<span class="tab">  </span>{.varargs,
+<span class="tab">    </span>importc: <span class="val">"fscanf"</span>, 
+<span class="tab end">    </span>header: <span class="val">"&lt;stdio.h&gt;"</span>.}
+
+<span class="cmt"># ..and use it...</span>
+<span class="kwd">var</span> x: <span class="typ">cint</span>
+stdin.unsafeScanf(<span class="val">"%d"</span>, <span class="kwd">addr</span> x)
+</pre>
+              <p><span class="desc"><b>Compile and run with:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;&#36; nim c -r example.nim</span></p>
+            </div>
             <div>
-              <h2>..and DSLs made easy</h2>
+              <h2>..and DSLs are too...</h2>
 <pre>
-<span class="kwd">import</span> jester, asyncdispatch, htmlgen
+<span class="cmt"># a simple html server</span>
+<span class="kwd">import</span>
+  jester, asyncdispatch, htmlgen
 
-routes:
-<span class="tab">  </span>get <span class="val">"/"</span>:
-<span class="tab end">    </span>resp h1(<span class="val">"Hello world"</span>)
+<span class="kwd">routes</span>:
+<span class="tab">  </span><span class="kwd">get</span> <span class="val">"/"</span>:
+<span class="tab end">  <span class="tab end">  </span></span><span class="kwd">resp</span> h1(<span class="val">"Hello world"</span>)
 
 runForever()
-</pre><p><span class="desc">
-Compile and run with:<br />
-nim c -r example.nim<br />
-View at: localhost:5000
-</span></p>
+</pre>
+              <p><span class="desc"><b>View in browser at:</b><br>&nbsp;&nbsp;&nbsp;&nbsp;localhost:5000</span></p>
             </div>
           </div>
-        </div>

-        <div id="slideshow-nav">

-          <div id="slideControl0" onclick="slideshow_click(0)"></div>

-          <div id="slideControl1" onclick="slideshow_click(1)" class="active"></div>

-          <div id="slideControl2" onclick="slideshow_click(2)"></div>

         </div>
-#  end

-        <aside id="sidebar">

+        <div id="slideshow-nav">
+          <div id="slideControl0" onclick="slideshow_click(0)" class="active"></div>
+          <div id="slideControl1" onclick="slideshow_click(1)"></div>
+          <div id="slideControl2" onclick="slideshow_click(2)"></div>
+        </div>
+#  end
+        <aside id="sidebar">
 
 #  if len(c.links) > 0:
           <h3>More Links</h3>
@@ -146,94 +146,65 @@ View at: localhost:5000
 #         end for
           </div>
 #  end if
-					<h3 class="blue">Latest News</h3>

-					<div id="sidebar-news">
 #  if len(c.ticker) > 0:
+					<h3 class="blue">Latest News</h3>
+					<div id="sidebar-news">
           $c.ticker
-#  end if

-					</div>

-				</aside>

-			</div>

-		</section>

-
-		<section id="body">

-			<div id="body-border"></div>

-			<div id="glow-line"></div>

-			<div class="page-layout">

+					</div>
+#  end if
+				</aside>
+			</div>
+		</section>
+
+		<section id="body">
+			<div id="body-border"></div>
+			<div id="glow-line"></div>
+			<div class="page-layout">
 				<article id="content" class="page">
-				$content

-				</article>

-			</div>

-		</section>

-

-		<!--- #foot --->

-		<footer id="foot" class="home">

-			<div class="page-layout tall">

-				<div id="foot-links">

-					<div>

-						<h4>Documentation</h4>

-						<a href="documentation.html">Stable Documentation</a>

-					<!--	<a href="">Development Documentation</a> -->

-						<a href="https://github.com/Araq/Nimrod">Issues &amp; Requests</a>

-					</div>

-					<div>

-						<h4>Community</h4>

-						<a href="http://forum.nim-lang.org">User Forum</a>

-            <a href="http://webchat.freenode.net/?channels=nimlang">Online IRC</a>

-            <a href="http://irclogs.nim-lang.org/">IRC Logs</a>

-					</div>

-				</div>

-				<div id="foot-legal">

-					<h4>Written in Nim - Powered by <a href="https://github.com/dom96/jester">Jester</a></h4>

-					Web Design by <a href="http://reign-studios.net/philipwitte/">Philip Witte</a> &amp; <a href="http://picheta.me/">Dominik Picheta</a><br>

-					Copyright © 2014 - <a href="http://nim-lang.org/blog/">Andreas Rumpf</a> &amp; <a href="https://github.com/Araq/Nimrod/graphs/contributors">Contributors</a>

-				</div>

-			</div>

-		</footer>

-

+				$content
+				</article>
+			</div>
+		</section>
+
+		<!--- #foot --->
+		<footer id="foot" class="home">
+			<div class="page-layout tall">
+				<div id="foot-links">
+					<div>
+						<h4>Documentation</h4>
+						<a href="documentation.html">Stable Documentation</a>
+						<a href="learn.html">Learning Resources</a>
+					<!--	<a href="">Development Documentation</a> -->
+						<a href="https://github.com/Araq/Nimrod">Issues &amp; Requests</a>
+					</div>
+					<div>
+						<h4>Community</h4>
+						<a href="http://forum.nim-lang.org">User Forum</a>
+            <a href="http://webchat.freenode.net/?channels=nim">Online IRC</a>
+            <a href="http://irclogs.nim-lang.org/">IRC Logs</a>
+					</div>
+				</div>
+				<div id="foot-legal">
+					<h4>Written in Nim - Powered by <a href="https://github.com/dom96/jester">Jester</a></h4>
+					Web Design by <a href="http://reign-studios.net/philipwitte/">Philip Witte</a> &amp; <a href="http://picheta.me/">Dominik Picheta</a><br>
+					Copyright © 2015 - <a href="http://nim-lang.org/blog/">Andreas Rumpf</a> &amp; <a href="https://github.com/Araq/Nimrod/graphs/contributors">Contributors</a>
+				</div>
+			</div>
+		</footer>
+  
+#  if currentTab == "index":
+  <script src="assets/index.js"></script>
+# end if
+#  if c.gaId != nil:
   <script>
     (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
     (i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
     m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
     })(window,document,'script','//www.google-analytics.com/analytics.js','ga');
 
-    ga('create', 'UA-48159761-1', 'nim-lang.org');
+    ga('create', '${c.gaId}', 'nim-lang.org');
     ga('send', 'pageview');
-
-var timer;
-var prevIndex = 0;
-
-function setSlideShow(index, short) {
-  if (index > 2) index = 0;
-  for (var i = 0; i < 10; ++i) {
-    var x = document.getElementById("slide"+i);
-    if (!x) break;
-    x.className = "";
-    document.getElementById("slideControl"+i).className = "";
-  }
-  document.getElementById("slide"+index).className = "active";
-  document.getElementById("slideControl"+index).className = "active";
-  prevIndex = index;
-  startTimer(short ? 8000 : 32000);
-}
-
-function nextSlide() { setSlideShow(prevIndex + 1, true); }
-function startTimer(t) { timer = setTimeout(nextSlide, t); }
-
-function slideshow_enter() { clearTimeout(timer); }
-function slideshow_exit () { startTimer(16000); }
-
-function slideshow_click(index) {
-  clearTimeout(timer);
-  setSlideShow(index, false);
-}
-
-window.onload = function() {
-  var slideshow = document.getElementById("slideshow");
-  slideshow.onmouseenter = slideshow_enter;
-  slideshow.onmouseleave = slideshow_exit;
-  startTimer(8000);
-};
   </script>
+#  end if
 </body>
 </html>