completion.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. 'use strict'
  2. const glob = require('glob')
  3. const CUSTOM = ['']
  4. const BOOLEAN = false
  5. const options = {
  6. start: {
  7. '--port': CUSTOM,
  8. '--auto-watch': BOOLEAN,
  9. '--no-auto-watch': BOOLEAN,
  10. '--log-level': ['disable', 'debug', 'info', 'warn', 'error'],
  11. '--colors': BOOLEAN,
  12. '--no-colors': BOOLEAN,
  13. '--reporters': ['dots', 'progress'],
  14. '--no-reporters': BOOLEAN,
  15. '--browsers': ['Chrome', 'ChromeHeadless', 'ChromeCanary', 'Firefox', 'PhantomJS', 'Safari', 'Opera'],
  16. '--no-browsers': BOOLEAN,
  17. '--single-run': BOOLEAN,
  18. '--no-single-run': BOOLEAN,
  19. '--help': BOOLEAN
  20. },
  21. init: {
  22. '--log-level': ['disable', 'debug', 'info', 'warn', 'error'],
  23. '--colors': BOOLEAN,
  24. '--no-colors': BOOLEAN,
  25. '--help': BOOLEAN
  26. },
  27. run: {
  28. '--no-refresh': BOOLEAN,
  29. '--port': CUSTOM,
  30. '--help': BOOLEAN
  31. }
  32. }
  33. function opositeWord (word) {
  34. if (word.startsWith('-')) {
  35. return word.startsWith('--no-') ? `--${word.slice(5)}` : `--no-${word.slice(2)}`
  36. } else {
  37. return null
  38. }
  39. }
  40. function sendCompletion (possibleWords, env) {
  41. const regexp = new RegExp('^' + env.last)
  42. possibleWords
  43. .filter((word) => regexp.test(word) && !env.words.includes(word) && !env.words.includes(opositeWord(word)))
  44. .forEach((word) => {
  45. console.log(word)
  46. })
  47. }
  48. function sendCompletionFiles (env) {
  49. glob(env.last + '*', { mark: true, nocase: true }, (err, files) => {
  50. if (err) return console.error(err)
  51. if (files.length === 1 && files[0].endsWith('/')) {
  52. sendCompletionFiles({ last: files[0] })
  53. } else {
  54. console.log(files.join('\n'))
  55. }
  56. })
  57. }
  58. function complete (env) {
  59. if (env.count === 1) {
  60. return sendCompletion(env.words[0].startsWith('-') ? ['--help', '--version'] : Object.keys(options), env)
  61. } else if (env.count === 2 && !env.words[1].startsWith('-')) {
  62. return sendCompletionFiles(env)
  63. }
  64. const cmdOptions = options[env.words[0]]
  65. if (cmdOptions) {
  66. if (cmdOptions[env.prev] === CUSTOM && env.last) {
  67. console.log(env.last)
  68. } else {
  69. return sendCompletion(cmdOptions[env.prev] || Object.keys(cmdOptions), env)
  70. }
  71. }
  72. }
  73. function completion () {
  74. if (process.argv[3] === '--') {
  75. return complete({
  76. words: process.argv.slice(5),
  77. count: parseInt(process.env.COMP_CWORD, 10),
  78. last: process.argv[process.argv.length - 1],
  79. prev: process.argv[process.argv.length - 2]
  80. })
  81. }
  82. // just print out the karma-completion.sh
  83. const fs = require('graceful-fs')
  84. const path = require('path')
  85. fs.readFile(path.resolve(__dirname, '../scripts/karma-completion.sh'), 'utf8', function (err, data) {
  86. if (err) return console.error(err)
  87. process.stdout.write(data)
  88. process.stdout.on('error', function (error) {
  89. // Darwin is a real dick sometimes.
  90. //
  91. // This is necessary because the "source" or "." program in
  92. // bash on OS X closes its file argument before reading
  93. // from it, meaning that you get exactly 1 write, which will
  94. // work most of the time, and will always raise an EPIPE.
  95. //
  96. // Really, one should not be tossing away EPIPE errors, or any
  97. // errors, so casually. But, without this, `. <(karma completion)`
  98. // can never ever work on OS X.
  99. if (error.errno === 'EPIPE') {
  100. error = null
  101. }
  102. })
  103. })
  104. }
  105. // PUBLIC API
  106. exports.completion = completion
  107. // for testing
  108. exports.opositeWord = opositeWord
  109. exports.sendCompletion = sendCompletion
  110. exports.complete = complete