1 | fs = require "fs"
|
2 | os = require "os"
|
3 | colors = require "colors"
|
4 | {spawn} = require "child_process"
|
5 |
|
6 | shuffle = (array) ->
|
7 | i = array.length
|
8 | return if i is 0
|
9 |
|
10 | while --i
|
11 | j = Math.floor Math.random() * ( i + 1 )
|
12 | temp = array[i]
|
13 | array[i] = array[j]
|
14 | array[j] = temp
|
15 |
|
16 | random = (max)-> Math.floor Math.random() * max
|
17 |
|
18 | keygen = (length, options = {}) ->
|
19 | keys = []
|
20 | chars = "0123456789abcdefghijklmnopqrstuvwxyz"
|
21 | rest = length
|
22 | for i in [0..length]
|
23 | rand = random chars.length
|
24 | upper = length * random(length) % 2
|
25 | char = chars.substring rand, rand+1
|
26 | unless options.lower
|
27 | char = if upper then char.toUpperCase() else char
|
28 | keys.push char
|
29 | keys.join ""
|
30 | shuffle(keys).join ""
|
31 |
|
32 | ask = (question, {format, hidden, callback, error})->
|
33 | {stdin, stdout} = process
|
34 | stdout.write "#{question} "
|
35 | stdin.resume()
|
36 | stdin.setEncoding "utf8"
|
37 | unless hidden
|
38 | stdin.once "data", (answer)->
|
39 | answer = answer.toString().trim()
|
40 | if format?.test? answer
|
41 | callback answer
|
42 | else
|
43 | if error
|
44 | error answer.toString().trim()
|
45 | else
|
46 | stdout.write "Please enter a valid answer.\n"
|
47 | ask question, {format, callback, error}
|
48 | else
|
49 | stdin.setRawMode true
|
50 | stdout.write "\n"
|
51 | buffer = []
|
52 | stdin.on "data", (key)->
|
53 | process.exit 0 if key is "\u0003" or key is "\u0004"
|
54 | if key is "\u000D"
|
55 | answer = buffer.join ""
|
56 | callback answer
|
57 | else
|
58 | key = key.toString().trim()
|
59 | buffer.push key
|
60 |
|
61 | logger = (namespace="kd")->(message, color="yellow")->
|
62 | message?.toString?().split("\n").forEach (line)->
|
63 | nocolor = ~process.argv.indexOf "--nocolor"
|
64 | if nocolor
|
65 | console.log "#{namespace}:", line
|
66 | else
|
67 | console.log colors[color]("#{namespace}:"), line
|
68 |
|
69 | compileDebug = (path, source, error)->
|
70 | data = source.toString()
|
71 | if error.location
|
72 | {first_line, last_line, first_column, last_column} = error.location
|
73 | lines = data.split os.EOL
|
74 | trace = lines.slice(first_line, last_line+1).join os.EOL
|
75 | point = ""
|
76 | for i in [0..last_column]
|
77 | if i < first_column then point+=" " else point+="^"
|
78 | point+= " #{error.message}"
|
79 |
|
80 | first_line++; last_line++;
|
81 | spaces = Array((first_line+"").length+1).join " "
|
82 | curr = first_line
|
83 | prev = first_line - 1
|
84 | next = first_line + 1
|
85 |
|
86 | previous_line = if first_line > 1 then "#{prev} #{lines[prev-1]}" else ""
|
87 | next_line = if lines.length > next then "#{next} #{lines[next-1]}" else ""
|
88 | """
|
89 |
|
90 | at #{path} line #{first_line}:#{last_line} column #{first_column}:#{last_column}
|
91 |
|
92 | #{previous_line}
|
93 | #{colors.red curr} #{colors.red trace}
|
94 | #{spaces} #{colors.green point}
|
95 | #{next_line}
|
96 | """
|
97 |
|
98 | spawner = ({exec, params, data, error, exit})->
|
99 | timeStart = Date.now()
|
100 | child = spawn executable, params
|
101 | child.stdout.on "data",(data)-> data? data
|
102 | child.stderr.on "data",(data)-> error? data
|
103 | child.on "exit",(code)->
|
104 | exit? code, "child pid:#{child.pid} was alive #{(Date.now()-timeStart)/1000}msecs"
|
105 | return child
|
106 |
|
107 | module.exports = {shuffle, random, keygen, ask, logger, compileDebug, spawner}
|