This repository has been archived by the owner on Jun 10, 2018. It is now read-only.
/
command.coffee
155 lines (127 loc) · 4.3 KB
/
command.coffee
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
fs = require "fs"
path = require "path"
sys = require "sys"
eco = require "."
{exec} = require "child_process"
{indent} = require "./util"
printUsage = ->
console.error """
Usage: eco [options] path/to/template.eco
-o, --output [DIR] set the directory for compiled JavaScript
-p, --print print the compiled JavaScript to stdout
-s, --stdio listen for and compile templates over stdio
-v, --version display Eco version
-h, --help display this help message
"""
process.exit 1
printVersion = ->
package = JSON.parse fs.readFileSync __dirname + "/../package.json", "utf8"
console.error "Eco version #{package.version}"
process.exit 0
preprocessArgs = (args) ->
result = []
for arg in args
if match = /^-([a-z]{2,})/.exec arg
for char in match[1].split ''
result.push "-#{char}"
else
result.push arg
result
parseOptions = (args) ->
options = files: []
option = null
for arg in preprocessArgs args
if option
options[option] = arg
option = null
else
switch arg
when "-o", "--output" then option = "output"
when "-p", "--print" then options.print = true
when "-s", "--stdio" then options.stdio = true
when "-v", "--version" then printVersion()
else (if /^-/.test arg then printUsage() else options.files.push arg)
printUsage() if option
options
read = (stream, callback) ->
buffer = ""
stream.setEncoding "utf8"
stream.on "data", (data) -> buffer += data
stream.on "end", -> callback? buffer
each = ([values...], callback) ->
do proceed = -> callback values.shift(), proceed
eachFile = (files, callback) ->
traverse = (root, dir, done) ->
fs.readdir dir, (err, entries) ->
return callback err if err
each entries, (entry, proceed) ->
return done() unless entry?
file = path.join dir, entry
fs.stat file, (err, stat) ->
return callback err if err
if stat.isFile() and /\.eco$/.test file
callback null, file, root, proceed
else if stat.isDirectory()
traverse root, file, proceed
else
proceed()
each files, (file, proceed) ->
return unless file?
fs.stat file, (err, stat) ->
return callback err if err
if stat.isDirectory()
traverse file, file, proceed
else
root = path.dirname file
callback null, file, root, proceed
stripExtension = (name) ->
name.replace /(\.eco)?$/, ""
compile = (infile, name, callback) ->
fs.readFile infile, "utf8", (err, source) ->
return callback err if err
template = indent eco.compile(source), 2
callback null, """
(function() {
this.ecoTemplates || (this.ecoTemplates = {});
this.ecoTemplates[#{JSON.stringify name}] = #{template.slice 2};
}).call(this);
"""
mkdir = (dir, callback) ->
exec "mkdir -p #{JSON.stringify dir}", (err, stdout, stderr) ->
callback err
compileToFile = (infile, root, outdir, callback) ->
root = path.join root, "/"
if root is infile.slice 0, root.length
name = stripExtension infile.slice root.length
else
name = stripExtension infile
outfile = path.join outdir ? root, name + ".js"
mkdir path.dirname(outfile), (err) ->
return callback err if err
compile infile, name, (err, result) ->
fs.writeFile outfile, result, "utf8", (err) ->
return callback err if err
callback null, outfile, name
exports.run = (args = process.argv.slice 2) ->
options = parseOptions args
if options.stdio
printUsage() if options.files.length or options.output
process.openStdin()
read process.stdin, (source) ->
sys.puts eco.compile source
else if options.print
printUsage() if options.files.length isnt 1 or options.output
infile = options.files[0]
name = stripExtension path.basename infile
compile infile, name, (err, result) ->
throw err if err
sys.puts result
else
printUsage() unless options.files.length
eachFile options.files, (err, infile, root, proceed) ->
throw err if err
return unless infile?
compileToFile infile, root, options.output, (err, outfile, name) ->
throw err if err
console.error "#{JSON.stringify name}: #{infile} -> #{outfile}"
proceed()