const path = require('path') const _ = require('underscore-plus') const {TextEditor, BufferedProcess, CompositeDisposable, Disposable} = require('atom') const fs = require('fs-plus') module.exports = class PackageGeneratorView { constructor () { this.disposables = new CompositeDisposable() this.element = document.createElement('div') this.element.classList.add('package-generator') this.miniEditor = new TextEditor({mini: true}) this.element.appendChild(this.miniEditor.element) this.error = document.createElement('div') this.error.classList.add('error') this.element.appendChild(this.error) this.message = document.createElement('div') this.message.classList.add('message') this.element.appendChild(this.message) this.disposables.add(atom.commands.add('atom-workspace', { 'package-generator:generate-package': () => this.attach('package'), 'package-generator:generate-language-package': () => this.attach('language'), 'package-generator:generate-syntax-theme': () => this.attach('theme') })) const blurHandler = () => this.close() this.miniEditor.element.addEventListener('blur', blurHandler) this.disposables.add(new Disposable(() => this.miniEditor.element.removeEventListener('blur', blurHandler))) this.disposables.add(atom.commands.add(this.element, { 'core:confirm': () => this.confirm(), 'core:cancel': () => this.close() })) } destroy () { if (this.panel != null) this.panel.destroy() this.disposables.dispose() } attach (mode) { this.mode = mode if (this.panel == null) this.panel = atom.workspace.addModalPanel({item: this, visible: false}) this.previouslyFocusedElement = document.activeElement this.panel.show() this.message.textContent = `Enter ${this.mode} path` if (this.mode === 'package') { this.setPathText('my-package') } else if (this.mode === 'language') { this.setPathText('language-my-language', [9, Infinity]) } else { this.setPathText('my-theme-syntax', [0, 8]) } this.miniEditor.element.focus() } setPathText (placeholderName, rangeToSelect) { if (rangeToSelect == null) rangeToSelect = [0, placeholderName.length] const packagesDirectory = this.getPackagesDirectory() this.miniEditor.setText(path.join(packagesDirectory, placeholderName)) const pathLength = this.miniEditor.getText().length const endOfDirectoryIndex = pathLength - placeholderName.length this.miniEditor.setSelectedBufferRange([[0, endOfDirectoryIndex + rangeToSelect[0]], [0, endOfDirectoryIndex + rangeToSelect[1]]]) } close () { if (!this.panel.isVisible()) return this.panel.hide() if (this.previouslyFocusedElement != null) this.previouslyFocusedElement.focus() } confirm () { if (this.validPackagePath()) { this.createPackageFiles(() => { const packagePath = this.getPackagePath() atom.open({pathsToOpen: [packagePath]}) this.close() }) } } getPackagePath () { const packagePath = fs.normalize(this.miniEditor.getText().trim()) const packageName = _.dasherize(path.basename(packagePath)) return path.join(path.dirname(packagePath), packageName) } getPackagesDirectory () { return process.env.ATOM_REPOS_HOME || atom.config.get('core.projectHome') || path.join(fs.getHomeDirectory(), 'github') } validPackagePath () { if (fs.existsSync(this.getPackagePath())) { this.error.textContent = `Path already exists at '${this.getPackagePath()}'` this.error.style.display = 'block' return false } else { return true } } getInitOptions (packagePath) { const options = [`--${this.mode}`, packagePath] if (this.mode !== 'theme') { return [...options, '--syntax', atom.config.get('package-generator.packageSyntax')] } else { return options } } initPackage (packagePath, callback) { const command = ['init'].concat(this.getInitOptions(packagePath)) this.runCommand(atom.packages.getApmPath(), command, callback) } linkPackage (packagePath, callback) { const args = ['link'] if (atom.config.get('package-generator.createInDevMode')) args.push('--dev') args.push(packagePath.toString()) this.runCommand(atom.packages.getApmPath(), args, callback) } isStoredInDotAtom (packagePath) { const packagesPath = path.join(atom.getConfigDirPath(), 'packages', path.sep) if (packagePath.startsWith(packagesPath)) return true const devPackagesPath = path.join(atom.getConfigDirPath(), 'dev', 'packages', path.sep) return packagePath.startsWith(devPackagesPath) } createPackageFiles (callback) { const packagePath = this.getPackagePath() if (this.isStoredInDotAtom(packagePath)) { this.initPackage(packagePath, callback) } else { this.initPackage(packagePath, () => this.linkPackage(packagePath, callback)) } } runCommand (command, args, exit) { this.process = new BufferedProcess({command, args, exit}) } }