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

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
       "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
16
       "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
17
       "dev": true,
17
       "dev": true,
18
       "requires": {
18
       "requires": {
19
-        "balanced-match": "1.0.0",
19
+        "balanced-match": "^1.0.0",
20
         "concat-map": "0.0.1"
20
         "concat-map": "0.0.1"
21
       }
21
       }
22
     },
22
     },
44
       "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
44
       "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=",
45
       "dev": true,
45
       "dev": true,
46
       "requires": {
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
     "defined": {
51
     "defined": {
66
       "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==",
66
       "integrity": "sha512-ZnQrE/lXTTQ39ulXZ+J1DTFazV9qBy61x2bY071B+qGco8Z8q1QddsLdt/EF8Ai9hcWH72dWS0kFqXLxOxqslA==",
67
       "dev": true,
67
       "dev": true,
68
       "requires": {
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
     "es-to-primitive": {
76
     "es-to-primitive": {
79
       "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
79
       "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=",
80
       "dev": true,
80
       "dev": true,
81
       "requires": {
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
     "faucet": {
87
     "faucet": {
91
       "dev": true,
91
       "dev": true,
92
       "requires": {
92
       "requires": {
93
         "defined": "0.0.0",
93
         "defined": "0.0.0",
94
-        "duplexer": "0.1.1",
94
+        "duplexer": "~0.1.1",
95
         "minimist": "0.0.5",
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
       "dependencies": {
101
       "dependencies": {
102
         "deep-equal": {
102
         "deep-equal": {
123
           "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
123
           "integrity": "sha1-Lnzgox3wn41oUWZKcYQuDKUFevc=",
124
           "dev": true,
124
           "dev": true,
125
           "requires": {
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
       "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=",
139
       "integrity": "sha1-LEBFC5NI6X8oEyJZO6lnBLmr1NQ=",
140
       "dev": true,
140
       "dev": true,
141
       "requires": {
141
       "requires": {
142
-        "is-function": "1.0.1"
142
+        "is-function": "~1.0.0"
143
       }
143
       }
144
     },
144
     },
145
     "foreach": {
145
     "foreach": {
166
       "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
166
       "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
167
       "dev": true,
167
       "dev": true,
168
       "requires": {
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
     "has": {
177
     "has": {
180
       "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
180
       "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=",
181
       "dev": true,
181
       "dev": true,
182
       "requires": {
182
       "requires": {
183
-        "function-bind": "1.1.1"
183
+        "function-bind": "^1.0.2"
184
       }
184
       }
185
     },
185
     },
186
     "inflight": {
186
     "inflight": {
189
       "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
189
       "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
190
       "dev": true,
190
       "dev": true,
191
       "requires": {
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
     "inherits": {
196
     "inherits": {
223
       "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
223
       "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
224
       "dev": true,
224
       "dev": true,
225
       "requires": {
225
       "requires": {
226
-        "has": "1.0.1"
226
+        "has": "^1.0.1"
227
       }
227
       }
228
     },
228
     },
229
     "is-symbol": {
229
     "is-symbol": {
250
       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
250
       "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
251
       "dev": true,
251
       "dev": true,
252
       "requires": {
252
       "requires": {
253
-        "brace-expansion": "1.1.11"
253
+        "brace-expansion": "^1.1.7"
254
       }
254
       }
255
     },
255
     },
256
     "minimist": {
256
     "minimist": {
257
       "version": "1.2.0",
257
       "version": "1.2.0",
258
       "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
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
     "object-inspect": {
261
     "object-inspect": {
263
       "version": "1.5.0",
262
       "version": "1.5.0",
277
       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
276
       "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
278
       "dev": true,
277
       "dev": true,
279
       "requires": {
278
       "requires": {
280
-        "wrappy": "1.0.2"
279
+        "wrappy": "1"
281
       }
280
       }
282
     },
281
     },
283
     "path-is-absolute": {
282
     "path-is-absolute": {
304
       "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
303
       "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=",
305
       "dev": true,
304
       "dev": true,
306
       "requires": {
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
         "isarray": "0.0.1",
308
         "isarray": "0.0.1",
310
-        "string_decoder": "0.10.31"
309
+        "string_decoder": "~0.10.x"
311
       }
310
       }
312
     },
311
     },
313
     "resolve": {
312
     "resolve": {
316
       "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
315
       "integrity": "sha512-hgoSGrc3pjzAPHNBg+KnFcK2HwlHTs/YrAGUr6qgTVUZmXv1UEXXl0bZNBKMA9fud6lRYFdPGz0xXxycPzmmiw==",
317
       "dev": true,
316
       "dev": true,
318
       "requires": {
317
       "requires": {
319
-        "path-parse": "1.0.5"
318
+        "path-parse": "^1.0.5"
320
       }
319
       }
321
     },
320
     },
322
     "resumer": {
321
     "resumer": {
325
       "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
324
       "integrity": "sha1-8ej0YeQGS6Oegq883CqMiT0HZ1k=",
326
       "dev": true,
325
       "dev": true,
327
       "requires": {
326
       "requires": {
328
-        "through": "2.3.8"
327
+        "through": "~2.3.4"
329
       }
328
       }
330
     },
329
     },
331
     "sprintf": {
330
     "sprintf": {
340
       "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
339
       "integrity": "sha1-0E3iyJ4Tf019IG8Ia17S+ua+jOo=",
341
       "dev": true,
340
       "dev": true,
342
       "requires": {
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
     "string_decoder": {
347
     "string_decoder": {
357
       "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=",
356
       "integrity": "sha1-pOrhkMENdsehEZIf84u+TVjwnuo=",
358
       "dev": true,
357
       "dev": true,
359
       "requires": {
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
     "tape": {
363
     "tape": {
367
       "integrity": "sha512-j0jO9BiScfqtPBb9QmPLL0qvxXMz98xjkMb7x8lKipFlJZwNJkqkWPou+NU4V6T9RnVh1kuSthLE8gLrN8bBfw==",
366
       "integrity": "sha512-j0jO9BiScfqtPBb9QmPLL0qvxXMz98xjkMb7x8lKipFlJZwNJkqkWPou+NU4V6T9RnVh1kuSthLE8gLrN8bBfw==",
368
       "dev": true,
367
       "dev": true,
369
       "requires": {
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
     "through": {
384
     "through": {
394
       "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
393
       "integrity": "sha1-6zKE2k6jEbbMis42U3SKUqvyWj8=",
395
       "dev": true,
394
       "dev": true,
396
       "requires": {
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
     "wrappy": {
400
     "wrappy": {
410
       "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
409
       "integrity": "sha1-bv7MKk2tjmlixJAbM3znuoe10os=",
411
       "dev": true,
410
       "dev": true,
412
       "requires": {
411
       "requires": {
413
-        "object-keys": "0.4.0"
412
+        "object-keys": "~0.4.0"
414
       },
413
       },
415
       "dependencies": {
414
       "dependencies": {
416
         "object-keys": {
415
         "object-keys": {

+ 6
- 0
package.json View File

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

+ 12
- 0
src/index.js View File

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