Browse Source

Implement CLI

master
Dylan Baker 5 years ago
parent
commit
4ae6bd884b
4 changed files with 192 additions and 63 deletions
  1. 112
    0
      bin/oslo.js
  2. 62
    63
      package-lock.json
  3. 6
    0
      package.json
  4. 12
    0
      src/index.js

+ 112
- 0
bin/oslo.js View File

@@ -0,0 +1,112 @@
1
+#!/usr/bin/env node
2
+
3
+const fs = require('fs')
4
+const path = require('path')
5
+const args = require('minimist')(process.argv.slice(2))
6
+
7
+const oslo = require('../src/index')
8
+
9
+class OsloCLI {
10
+  constructor(opts) {
11
+    let output
12
+
13
+    if (opts.f) {
14
+      output = this.file(path.join(process.cwd(), opts.f))
15
+    } else if (opts.d) {
16
+      if (!opts.o) {
17
+        console.log('Output directory required. Invoke oslo with `-o path/to/output/directory`')
18
+        process.exit()
19
+      }
20
+      output = this.directory(this.absolutePath(opts.d), this.absolutePath(opts.o))
21
+    } else if (opts.e) {
22
+      output = this.inline(opts.e)
23
+    } else {
24
+      this.printUsage()
25
+      process.exit()
26
+    }
27
+
28
+    if (opts.o) {
29
+      const absoluteOutputPath = this.absolutePath(opts.o)
30
+      if (opts.f || opts.e) {
31
+        fs.writeFile(absoluteOutputPath, output, function (err) {
32
+          if (err) throw err
33
+        })
34
+      } else if (opts.d) {
35
+        const absoluteInputPath = this.absolutePath(opts.d)
36
+        Object.keys(output).forEach(function (file) {
37
+          const absoluteOutputFilePath = file.replace(absoluteInputPath, absoluteOutputPath).replace(/\.oslo$/, '.html')
38
+          const parentDirectory = path.dirname(absoluteOutputFilePath)
39
+          if (!fs.existsSync(parentDirectory)) {
40
+            fs.mkdirSync(parentDirectory)
41
+          }
42
+          fs.writeFile(absoluteOutputFilePath, output[file], function (err) {
43
+            if (err) throw err
44
+            console.log(`Writing to ${absoluteOutputFilePath.replace(process.cwd(), '')}`)
45
+          })
46
+        })
47
+      }
48
+    } else {
49
+      process.stdout.write(output)
50
+      process.stdout.write('\n')
51
+    }
52
+  }
53
+
54
+  file(file) {
55
+    const contents = fs.readFileSync(file).toString()
56
+    return oslo(contents)
57
+  }
58
+
59
+  directory(directory) {
60
+    let files = {}
61
+    fs.readdirSync(directory).forEach(item => {
62
+      const absolutePath = this.absolutePath(item, directory)
63
+      if (fs.lstatSync(absolutePath).isDirectory()) {
64
+        files = Object.assign(files, this.directory(absolutePath))
65
+      } else {
66
+        let output = this.file(absolutePath)
67
+        files[absolutePath] = output
68
+      }
69
+    })
70
+    return files
71
+  }
72
+
73
+  inline(source) {
74
+    return oslo(source)
75
+  }
76
+
77
+  absolutePath(file, root = null) {
78
+    if (!root) {
79
+      root = process.cwd()
80
+    }
81
+    return path.join(root, file)
82
+  }
83
+
84
+  printUsage() {
85
+    console.log(
86
+`USAGE
87
+
88
+  -d The path to a directory. The directory will be recursively scanned. An
89
+     output directory is required with this option.
90
+
91
+     oslo -d templates
92
+
93
+  -e Pass oslo code directly.
94
+
95
+      oslo -e '(div "Hello world")'
96
+
97
+  -f The path to a single file.
98
+
99
+      oslo -f index.oslo
100
+
101
+  -o Where to direct the output. If no path is provided, output will be directed
102
+     to stdout. When used with -f, the argument should be the path to a file.
103
+     When used with -d, the argument should be the path to a directory, which
104
+     will be created if it does not already exist.
105
+
106
+      oslo -f index.oslo -o index.html
107
+      oslo -d templates -o html`
108
+    )
109
+  }
110
+}
111
+
112
+(new OsloCLI(args))

+ 62
- 63
package-lock.json View File

@@ -16,7 +16,7 @@
16 16
       "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
17 17
       "dev": true,
18 18
       "requires": {
19
-        "balanced-match": "1.0.0",
19
+        "balanced-match": "^1.0.0",
20 20
         "concat-map": "0.0.1"
21 21
       }
22 22
     },
@@ -44,8 +44,8 @@
44 44
       "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
45 45
       "dev": true,
46 46
       "requires": {
47
-        "foreach": "2.0.5",
48
-        "object-keys": "1.0.11"
47
+        "foreach": "^2.0.5",
48
+        "object-keys": "^1.0.8"
49 49
       }
50 50
     },
51 51
     "defined": {
@@ -66,11 +66,11 @@
66 66
       "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==",
67 67
       "dev": true,
68 68
       "requires": {
69
-        "es-to-primitive": "1.1.1",
70
-        "function-bind": "1.1.1",
71
-        "has": "1.0.1",
72
-        "is-callable": "1.1.3",
73
-        "is-regex": "1.0.4"
69
+        "es-to-primitive": "^1.1.1",
70
+        "function-bind": "^1.1.1",
71
+        "has": "^1.0.1",
72
+        "is-callable": "^1.1.3",
73
+        "is-regex": "^1.0.4"
74 74
       }
75 75
     },
76 76
     "es-to-primitive": {
@@ -79,9 +79,9 @@
79 79
       "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
80 80
       "dev": true,
81 81
       "requires": {
82
-        "is-callable": "1.1.3",
83
-        "is-date-object": "1.0.1",
84
-        "is-symbol": "1.0.1"
82
+        "is-callable": "^1.1.1",
83
+        "is-date-object": "^1.0.1",
84
+        "is-symbol": "^1.0.1"
85 85
       }
86 86
     },
87 87
     "faucet": {
@@ -91,12 +91,12 @@
91 91
       "dev": true,
92 92
       "requires": {
93 93
         "defined": "0.0.0",
94
-        "duplexer": "0.1.1",
94
+        "duplexer": "~0.1.1",
95 95
         "minimist": "0.0.5",
96
-        "sprintf": "0.1.5",
97
-        "tap-parser": "0.4.3",
98
-        "tape": "2.3.3",
99
-        "through2": "0.2.3"
96
+        "sprintf": "~0.1.3",
97
+        "tap-parser": "~0.4.0",
98
+        "tape": "~2.3.2",
99
+        "through2": "~0.2.3"
100 100
       },
101 101
       "dependencies": {
102 102
         "deep-equal": {
@@ -123,12 +123,12 @@
123 123
           "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
124 124
           "dev": true,
125 125
           "requires": {
126
-            "deep-equal": "0.1.2",
127
-            "defined": "0.0.0",
128
-            "inherits": "2.0.3",
129
-            "jsonify": "0.0.0",
130
-            "resumer": "0.0.0",
131
-            "through": "2.3.8"
126
+            "deep-equal": "~0.1.0",
127
+            "defined": "~0.0.0",
128
+            "inherits": "~2.0.1",
129
+            "jsonify": "~0.0.0",
130
+            "resumer": "~0.0.0",
131
+            "through": "~2.3.4"
132 132
           }
133 133
         }
134 134
       }
@@ -139,7 +139,7 @@
139 139
       "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=",
140 140
       "dev": true,
141 141
       "requires": {
142
-        "is-function": "1.0.1"
142
+        "is-function": "~1.0.0"
143 143
       }
144 144
     },
145 145
     "foreach": {
@@ -166,12 +166,12 @@
166 166
       "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
167 167
       "dev": true,
168 168
       "requires": {
169
-        "fs.realpath": "1.0.0",
170
-        "inflight": "1.0.6",
171
-        "inherits": "2.0.3",
172
-        "minimatch": "3.0.4",
173
-        "once": "1.4.0",
174
-        "path-is-absolute": "1.0.1"
169
+        "fs.realpath": "^1.0.0",
170
+        "inflight": "^1.0.4",
171
+        "inherits": "2",
172
+        "minimatch": "^3.0.4",
173
+        "once": "^1.3.0",
174
+        "path-is-absolute": "^1.0.0"
175 175
       }
176 176
     },
177 177
     "has": {
@@ -180,7 +180,7 @@
180 180
       "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
181 181
       "dev": true,
182 182
       "requires": {
183
-        "function-bind": "1.1.1"
183
+        "function-bind": "^1.0.2"
184 184
       }
185 185
     },
186 186
     "inflight": {
@@ -189,8 +189,8 @@
189 189
       "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
190 190
       "dev": true,
191 191
       "requires": {
192
-        "once": "1.4.0",
193
-        "wrappy": "1.0.2"
192
+        "once": "^1.3.0",
193
+        "wrappy": "1"
194 194
       }
195 195
     },
196 196
     "inherits": {
@@ -223,7 +223,7 @@
223 223
       "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
224 224
       "dev": true,
225 225
       "requires": {
226
-        "has": "1.0.1"
226
+        "has": "^1.0.1"
227 227
       }
228 228
     },
229 229
     "is-symbol": {
@@ -250,14 +250,13 @@
250 250
       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
251 251
       "dev": true,
252 252
       "requires": {
253
-        "brace-expansion": "1.1.11"
253
+        "brace-expansion": "^1.1.7"
254 254
       }
255 255
     },
256 256
     "minimist": {
257 257
       "version": "1.2.0",
258 258
       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
259
-      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=",
260
-      "dev": true
259
+      "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
261 260
     },
262 261
     "object-inspect": {
263 262
       "version": "1.5.0",
@@ -277,7 +276,7 @@
277 276
       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
278 277
       "dev": true,
279 278
       "requires": {
280
-        "wrappy": "1.0.2"
279
+        "wrappy": "1"
281 280
       }
282 281
     },
283 282
     "path-is-absolute": {
@@ -304,10 +303,10 @@
304 303
       "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
305 304
       "dev": true,
306 305
       "requires": {
307
-        "core-util-is": "1.0.2",
308
-        "inherits": "2.0.3",
306
+        "core-util-is": "~1.0.0",
307
+        "inherits": "~2.0.1",
309 308
         "isarray": "0.0.1",
310
-        "string_decoder": "0.10.31"
309
+        "string_decoder": "~0.10.x"
311 310
       }
312 311
     },
313 312
     "resolve": {
@@ -316,7 +315,7 @@
316 315
       "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
317 316
       "dev": true,
318 317
       "requires": {
319
-        "path-parse": "1.0.5"
318
+        "path-parse": "^1.0.5"
320 319
       }
321 320
     },
322 321
     "resumer": {
@@ -325,7 +324,7 @@
325 324
       "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
326 325
       "dev": true,
327 326
       "requires": {
328
-        "through": "2.3.8"
327
+        "through": "~2.3.4"
329 328
       }
330 329
     },
331 330
     "sprintf": {
@@ -340,9 +339,9 @@
340 339
       "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
341 340
       "dev": true,
342 341
       "requires": {
343
-        "define-properties": "1.1.2",
344
-        "es-abstract": "1.11.0",
345
-        "function-bind": "1.1.1"
342
+        "define-properties": "^1.1.2",
343
+        "es-abstract": "^1.5.0",
344
+        "function-bind": "^1.0.2"
346 345
       }
347 346
     },
348 347
     "string_decoder": {
@@ -357,8 +356,8 @@
357 356
       "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=",
358 357
       "dev": true,
359 358
       "requires": {
360
-        "inherits": "2.0.3",
361
-        "readable-stream": "1.1.14"
359
+        "inherits": "~2.0.1",
360
+        "readable-stream": "~1.1.11"
362 361
       }
363 362
     },
364 363
     "tape": {
@@ -367,19 +366,19 @@
367 366
       "integrity": "sha512-j0jO9BiScfqtPBb9QmPLL0qvxXMz98xjkMb7x8lKipFlJZwNJkqkWPou+NU4V6T9RnVh1kuSthLE8gLrN8bBfw==",
368 367
       "dev": true,
369 368
       "requires": {
370
-        "deep-equal": "1.0.1",
371
-        "defined": "1.0.0",
372
-        "for-each": "0.3.2",
373
-        "function-bind": "1.1.1",
374
-        "glob": "7.1.2",
375
-        "has": "1.0.1",
376
-        "inherits": "2.0.3",
377
-        "minimist": "1.2.0",
378
-        "object-inspect": "1.5.0",
379
-        "resolve": "1.5.0",
380
-        "resumer": "0.0.0",
381
-        "string.prototype.trim": "1.1.2",
382
-        "through": "2.3.8"
369
+        "deep-equal": "~1.0.1",
370
+        "defined": "~1.0.0",
371
+        "for-each": "~0.3.2",
372
+        "function-bind": "~1.1.1",
373
+        "glob": "~7.1.2",
374
+        "has": "~1.0.1",
375
+        "inherits": "~2.0.3",
376
+        "minimist": "~1.2.0",
377
+        "object-inspect": "~1.5.0",
378
+        "resolve": "~1.5.0",
379
+        "resumer": "~0.0.0",
380
+        "string.prototype.trim": "~1.1.2",
381
+        "through": "~2.3.8"
383 382
       }
384 383
     },
385 384
     "through": {
@@ -394,8 +393,8 @@
394 393
       "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
395 394
       "dev": true,
396 395
       "requires": {
397
-        "readable-stream": "1.1.14",
398
-        "xtend": "2.1.2"
396
+        "readable-stream": "~1.1.9",
397
+        "xtend": "~2.1.1"
399 398
       }
400 399
     },
401 400
     "wrappy": {
@@ -410,7 +409,7 @@
410 409
       "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
411 410
       "dev": true,
412 411
       "requires": {
413
-        "object-keys": "0.4.0"
412
+        "object-keys": "~0.4.0"
414 413
       },
415 414
       "dependencies": {
416 415
         "object-keys": {

+ 6
- 0
package.json View File

@@ -10,9 +10,15 @@
10 10
   "keywords": [],
11 11
   "author": "",
12 12
   "license": "MIT",
13
+  "bin": {
14
+    "oslo": "./bin/oslo.js"
15
+  },
13 16
   "devDependencies": {
14 17
     "faucet": "0.0.1",
15 18
     "prettier": "^1.12.1",
16 19
     "tape": "^4.9.0"
20
+  },
21
+  "dependencies": {
22
+    "minimist": "~1.2.0"
17 23
   }
18 24
 }

+ 12
- 0
src/index.js View File

@@ -0,0 +1,12 @@
1
+const Lexer = require('./lexer')
2
+const Parser = require('./parser')
3
+const Compiler = require('./compiler')
4
+
5
+module.exports = function oslo(source, context) {
6
+  const lexer = new Lexer()
7
+  const tokens = lexer.scan(source)
8
+  const parser = new Parser(tokens)
9
+  const tree = parser.parse()
10
+  const compiler = new Compiler(tree, context)
11
+  return compiler.compile()
12
+}

Loading…
Cancel
Save