package-generator-view.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. const path = require('path')
  2. const _ = require('underscore-plus')
  3. const {TextEditor, BufferedProcess, CompositeDisposable, Disposable} = require('atom')
  4. const fs = require('fs-plus')
  5. module.exports =
  6. class PackageGeneratorView {
  7. constructor () {
  8. this.disposables = new CompositeDisposable()
  9. this.element = document.createElement('div')
  10. this.element.classList.add('package-generator')
  11. this.miniEditor = new TextEditor({mini: true})
  12. this.element.appendChild(this.miniEditor.element)
  13. this.error = document.createElement('div')
  14. this.error.classList.add('error')
  15. this.element.appendChild(this.error)
  16. this.message = document.createElement('div')
  17. this.message.classList.add('message')
  18. this.element.appendChild(this.message)
  19. this.disposables.add(atom.commands.add('atom-workspace', {
  20. 'package-generator:generate-package': () => this.attach('package'),
  21. 'package-generator:generate-language-package': () => this.attach('language'),
  22. 'package-generator:generate-syntax-theme': () => this.attach('theme')
  23. }))
  24. const blurHandler = () => this.close()
  25. this.miniEditor.element.addEventListener('blur', blurHandler)
  26. this.disposables.add(new Disposable(() => this.miniEditor.element.removeEventListener('blur', blurHandler)))
  27. this.disposables.add(atom.commands.add(this.element, {
  28. 'core:confirm': () => this.confirm(),
  29. 'core:cancel': () => this.close()
  30. }))
  31. }
  32. destroy () {
  33. if (this.panel != null) this.panel.destroy()
  34. this.disposables.dispose()
  35. }
  36. attach (mode) {
  37. this.mode = mode
  38. if (this.panel == null) this.panel = atom.workspace.addModalPanel({item: this, visible: false})
  39. this.previouslyFocusedElement = document.activeElement
  40. this.panel.show()
  41. this.message.textContent = `Enter ${this.mode} path`
  42. if (this.mode === 'package') {
  43. this.setPathText('my-package')
  44. } else if (this.mode === 'language') {
  45. this.setPathText('language-my-language', [9, Infinity])
  46. } else {
  47. this.setPathText('my-theme-syntax', [0, 8])
  48. }
  49. this.miniEditor.element.focus()
  50. }
  51. setPathText (placeholderName, rangeToSelect) {
  52. if (rangeToSelect == null) rangeToSelect = [0, placeholderName.length]
  53. const packagesDirectory = this.getPackagesDirectory()
  54. this.miniEditor.setText(path.join(packagesDirectory, placeholderName))
  55. const pathLength = this.miniEditor.getText().length
  56. const endOfDirectoryIndex = pathLength - placeholderName.length
  57. this.miniEditor.setSelectedBufferRange([[0, endOfDirectoryIndex + rangeToSelect[0]], [0, endOfDirectoryIndex + rangeToSelect[1]]])
  58. }
  59. close () {
  60. if (!this.panel.isVisible()) return
  61. this.panel.hide()
  62. if (this.previouslyFocusedElement != null) this.previouslyFocusedElement.focus()
  63. }
  64. confirm () {
  65. if (this.validPackagePath()) {
  66. this.createPackageFiles(() => {
  67. const packagePath = this.getPackagePath()
  68. atom.open({pathsToOpen: [packagePath]})
  69. this.close()
  70. })
  71. }
  72. }
  73. getPackagePath () {
  74. const packagePath = fs.normalize(this.miniEditor.getText().trim())
  75. const packageName = _.dasherize(path.basename(packagePath))
  76. return path.join(path.dirname(packagePath), packageName)
  77. }
  78. getPackagesDirectory () {
  79. return process.env.ATOM_REPOS_HOME || atom.config.get('core.projectHome') || path.join(fs.getHomeDirectory(), 'github')
  80. }
  81. validPackagePath () {
  82. if (fs.existsSync(this.getPackagePath())) {
  83. this.error.textContent = `Path already exists at '${this.getPackagePath()}'`
  84. this.error.style.display = 'block'
  85. return false
  86. } else {
  87. return true
  88. }
  89. }
  90. getInitOptions (packagePath) {
  91. const options = [`--${this.mode}`, packagePath]
  92. if (this.mode !== 'theme') {
  93. return [...options, '--syntax', atom.config.get('package-generator.packageSyntax')]
  94. } else {
  95. return options
  96. }
  97. }
  98. initPackage (packagePath, callback) {
  99. const command = ['init'].concat(this.getInitOptions(packagePath))
  100. this.runCommand(atom.packages.getApmPath(), command, callback)
  101. }
  102. linkPackage (packagePath, callback) {
  103. const args = ['link']
  104. if (atom.config.get('package-generator.createInDevMode')) args.push('--dev')
  105. args.push(packagePath.toString())
  106. this.runCommand(atom.packages.getApmPath(), args, callback)
  107. }
  108. isStoredInDotAtom (packagePath) {
  109. const packagesPath = path.join(atom.getConfigDirPath(), 'packages', path.sep)
  110. if (packagePath.startsWith(packagesPath)) return true
  111. const devPackagesPath = path.join(atom.getConfigDirPath(), 'dev', 'packages', path.sep)
  112. return packagePath.startsWith(devPackagesPath)
  113. }
  114. createPackageFiles (callback) {
  115. const packagePath = this.getPackagePath()
  116. if (this.isStoredInDotAtom(packagePath)) {
  117. this.initPackage(packagePath, callback)
  118. } else {
  119. this.initPackage(packagePath, () => this.linkPackage(packagePath, callback))
  120. }
  121. }
  122. runCommand (command, args, exit) {
  123. this.process = new BufferedProcess({command, args, exit})
  124. }
  125. }