UNPKG

4.19 kBJavaScriptView Raw
1var CUSTOM = ['']
2var BOOLEAN = false
3
4var options = {
5 start: {
6 '--port': CUSTOM,
7 '--auto-watch': BOOLEAN,
8 '--no-auto-watch': BOOLEAN,
9 '--log-level': ['disable', 'debug', 'info', 'warn', 'error'],
10 '--colors': BOOLEAN,
11 '--no-colors': BOOLEAN,
12 '--reporters': ['dots', 'progress'],
13 '--no-reporters': BOOLEAN,
14 '--browsers': ['Chrome', 'ChromeCanary', 'Firefox', 'PhantomJS', 'Safari', 'Opera'],
15 '--no-browsers': BOOLEAN,
16 '--single-run': BOOLEAN,
17 '--no-single-run': BOOLEAN,
18 '--help': BOOLEAN
19 },
20 init: {
21 '--log-level': ['disable', 'debug', 'info', 'warn', 'error'],
22 '--colors': BOOLEAN,
23 '--no-colors': BOOLEAN,
24 '--help': BOOLEAN
25 },
26 run: {
27 '--no-refresh': BOOLEAN,
28 '--port': CUSTOM,
29 '--help': BOOLEAN
30 }
31}
32
33var parseEnv = function (argv, env) {
34 var words = argv.slice(5)
35
36 return {
37 words: words,
38 count: parseInt(env.COMP_CWORD, 10),
39 last: words[words.length - 1],
40 prev: words[words.length - 2]
41 }
42}
43
44var opositeWord = function (word) {
45 if (word.charAt(0) !== '-') {
46 return null
47 }
48
49 return word.substr(0, 5) === '--no-' ? '--' + word.substr(5) : '--no-' + word.substr(2)
50}
51
52var sendCompletionNoOptions = function () {}
53
54var sendCompletion = function (possibleWords, env) {
55 var regexp = new RegExp('^' + env.last)
56 var filteredWords = possibleWords.filter(function (word) {
57 return regexp.test(word) && env.words.indexOf(word) === -1 &&
58 env.words.indexOf(opositeWord(word)) === -1
59 })
60
61 if (!filteredWords.length) {
62 return sendCompletionNoOptions(env)
63 }
64
65 filteredWords.forEach(function (word) {
66 console.log(word)
67 })
68}
69
70var glob = require('glob')
71var globOpts = {
72 mark: true,
73 nocase: true
74}
75
76var sendCompletionFiles = function (env) {
77 glob(env.last + '*', globOpts, function (err, files) {
78 if (err) return console.error(err)
79
80 if (files.length === 1 && files[0].charAt(files[0].length - 1) === '/') {
81 sendCompletionFiles({last: files[0]})
82 } else {
83 console.log(files.join('\n'))
84 }
85 })
86}
87
88var sendCompletionConfirmLast = function (env) {
89 console.log(env.last)
90}
91
92var complete = function (env) {
93 if (env.count === 1) {
94 if (env.words[0].charAt(0) === '-') {
95 return sendCompletion(['--help', '--version'], env)
96 }
97
98 return sendCompletion(Object.keys(options), env)
99 }
100
101 if (env.count === 2 && env.words[1].charAt(0) !== '-') {
102 // complete files (probably karma.conf.js)
103 return sendCompletionFiles(env)
104 }
105
106 var cmdOptions = options[env.words[0]]
107 var previousOption = cmdOptions[env.prev]
108
109 if (!cmdOptions) {
110 // no completion, wrong command
111 return sendCompletionNoOptions()
112 }
113
114 if (previousOption === CUSTOM && env.last) {
115 // custom value with already filled something
116 return sendCompletionConfirmLast(env)
117 }
118
119 if (previousOption) {
120 // custom options
121 return sendCompletion(previousOption, env)
122 }
123
124 return sendCompletion(Object.keys(cmdOptions), env)
125}
126
127var completion = function () {
128 if (process.argv[3] === '--') {
129 return complete(parseEnv(process.argv, process.env))
130 }
131
132 // just print out the karma-completion.sh
133 var fs = require('graceful-fs')
134 var path = require('path')
135
136 fs.readFile(path.resolve(__dirname, '../scripts/karma-completion.sh'), 'utf8', function (err, data) {
137 if (err) return console.error(err)
138
139 process.stdout.write(data)
140 process.stdout.on('error', function (error) {
141 // Darwin is a real dick sometimes.
142 //
143 // This is necessary because the "source" or "." program in
144 // bash on OS X closes its file argument before reading
145 // from it, meaning that you get exactly 1 write, which will
146 // work most of the time, and will always raise an EPIPE.
147 //
148 // Really, one should not be tossing away EPIPE errors, or any
149 // errors, so casually. But, without this, `. <(karma completion)`
150 // can never ever work on OS X.
151 if (error.errno === 'EPIPE') {
152 error = null
153 }
154 })
155 })
156}
157
158// PUBLIC API
159exports.completion = completion
160
161// for testing
162exports.opositeWord = opositeWord
163exports.sendCompletion = sendCompletion
164exports.complete = complete