summary refs log tree commit diff stats
path: root/lib/system/nimscript.nim
blob: c714f88ee77091027f245f6fbbfb37e117c7fa13 (plain) (blame)
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
#
#
#            Nim's Runtime Library
#        (c) Copyright 2015 Andreas Rumpf
#
#    See the file "copying.txt", included in this
#    distribution, for details about the copyright.
#


# Nim's configuration system now uses Nim for scripting. This module provides
# a few things that are required for this to work.

template builtin = discard

proc listDirs*(dir: string): seq[string] = builtin
proc listFiles*(dir: string): seq[string] = builtin

proc removeDir(dir: string) = builtin
proc removeFile(dir: string) = builtin
proc moveFile(src, dest: string) = builtin
proc createDir(dir: string) = builtin
proc getOsError: string = builtin
proc setCurrentDir(dir: string) = builtin
proc getCurrentDir(): string = builtin
proc paramStr*(i: int): string = builtin
proc paramCount*(): int = builtin

proc switch*(key: string, val="") = builtin
proc getCommand*(): string = builtin
proc setCommand*(cmd: string) = builtin
proc cmpIgnoreStyle(a, b: string): int = builtin

proc strip(s: string): string =
  var i = 0
  while s[i] in {' ', '\c', '\L'}: inc i
  result = s.substr(i)

template `--`*(key, val: untyped) = switch(astToStr(key), strip astToStr(val))
template `--`*(key: untyped) = switch(astToStr(key), "")

type
  ScriptMode* {.pure.} = enum
    Silent,
    Verbose,
    Whatif

var
  mode*: ScriptMode ## Set this to influence how mkDir, rmDir, rmFile etc.
                    ## behave

template checkOsError =
  let err = getOsError()
  if err.len > 0: raise newException(OSError, err)

template log(msg: string, body: untyped) =
  if mode == ScriptMode.Verbose or mode == ScriptMode.Whatif:
    echo "[NimScript] ", msg
  if mode != ScriptMode.WhatIf:
    body

proc rmDir*(dir: string) {.raises: [OSError].} =
  log "rmDir: " & dir:
    removeDir dir
    checkOsError()

proc rmFile*(dir: string) {.raises: [OSError].} =
  log "rmFile: " & dir:
    removeFile dir
    checkOsError()

proc mkDir*(dir: string) {.raises: [OSError].} =
  log "mkDir: " & dir:
    createDir dir
    checkOsError()

proc mvFile*(`from`, to: string) {.raises: [OSError].} =
  log "mvFile: " & `from` & ", " & to:
    moveFile `from`, to
    checkOsError()

proc exec*(command: string, input = "", cache = "") =
  ## Executes an external process.
  log "exec: " & command:
    echo staticExec(command, input, cache)

proc put*(key, value: string) =
  ## Sets a configuration 'key' like 'gcc.options.always' to its value.
  builtin

proc get*(key: string): string =
  ## Retrieves a configuration 'key' like 'gcc.options.always'.
  builtin

proc exists*(key: string): bool =
  ## Checks for the existance of a configuration 'key'
  ## like 'gcc.options.always'.
  builtin

proc nimcacheDir*(): string =
  ## Retrieves the location of 'nimcache'.
  builtin

proc thisDir*(): string =
  ## Retrieves the location of the current ``nims`` script file.
  builtin

proc cd*(dir: string) {.raises: [OSError].} =
  ## Changes the current directory.
  ##
  ## The change is permanent for the rest of the execution, since this is just
  ## a shortcut for `os.setCurrentDir()
  ## <http://nim-lang.org/os.html#setCurrentDir,string>`_ . Use the `withDir()
  ## <#withDir>`_ template if you want to perform a temporary change only.
  setCurrentDir(dir)
  checkOsError()

template withDir*(dir: string; body: untyped): untyped =
  ## Changes the current directory temporarily.
  ##
  ## If you need a permanent change, use the `cd() <#cd>`_ proc. Usage example:
  ##
  ## .. code-block:: nimrod
  ##   withDir "foo":
  ##     # inside foo
  ##   #back to last dir
  var curDir = getCurrentDir()
  try:
    cd(dir)
    body
  finally:
    cd(curDir)

template `==?`(a, b: string): bool = cmpIgnoreStyle(a, b) == 0

proc writeTask(name, desc: string) =
  if desc.len > 0:
    var spaces = " "
    for i in 0 ..< 20 - name.len: spaces.add ' '
    echo name, spaces, desc

template task*(name: untyped; description: string; body: untyped): untyped =
  ## Defines a task. Hidden tasks are supported via an empty description.
  proc `name Task`() = body

  let cmd = getCommand()
  if cmd.len == 0 or cmd ==? "help":
    setCommand "help"
    writeTask(astToStr(name), description)
  elif cmd ==? astToStr(name):
    setCommand "nop"
    `name Task`()

var
  packageName* = ""
  version*, author*, description*, license*, srcdir*,
    binDir*, backend*: string

  skipDirs*, skipFiles*, skipExt*, installDirs*, installFiles*,
    installExt*, bin*: seq[string]
  requiresData*: seq[string]

proc requires*(deps: varargs[string]) =
  for d in deps: requiresData.add(d)