diff --git a/spec/atom-environment-spec.js b/spec/atom-environment-spec.js index 2a44b24042..bd8f27f9ad 100644 --- a/spec/atom-environment-spec.js +++ b/spec/atom-environment-spec.js @@ -488,6 +488,61 @@ describe('AtomEnvironment', () => { }); }); + describe('init script handling', () => { + let pulsar + afterEach(() => { + if(pulsar) { + pulsar.unloadEditorWindow(); + pulsar.destroy(); + } + }) + + describe('when the config to reload init scripts is not set', () => { + it('loads the script and requires it, but will not reload the init script', () => { + pulsar = new AtomEnvironment({ + applicationDelegate: atom.applicationDelegate + }); + pulsar.config.set('core.autoReloadInitScript', false) + + let initPath = path.join(__dirname, 'fixtures', 'init-script.js') + pulsar.getUserInitScriptPath = () => initPath + pulsar.requireUserInitScript(); + let commands = atom.commands.findCommands({target: window}) + .filter(({name}) => name.match(/test-case/)) + expect(commands).toEqual([{name: 'test-case', displayName: 'Test Case'}]) + + initPath = path.join(__dirname, 'fixtures', 'different-init-script.js') + pulsar.requireUserInitScript(); + commands = atom.commands.findCommands({target: window}) + .filter(({name}) => name.match(/test-case/)) + expect(commands).toEqual([{name: 'test-case', displayName: 'Test Case'}]) + }) + }) + + describe('when the config to reload init scripts is set', () => { + it('allows for the init script to be reloaded', () => { + pulsar = new AtomEnvironment({ + applicationDelegate: atom.applicationDelegate + }); + pulsar.config.set('core.autoReloadInitScript', true) + + let initPath = path.join(__dirname, 'fixtures', 'reloadable-init-script.js') + pulsar.getUserInitScriptPath = () => initPath + pulsar.requireUserInitScript(); + let commands = atom.commands.findCommands({target: window}) + .filter(({name}) => name.match(/test-case/)) + expect(commands).toEqual([{name: 'test-case', displayName: 'Test Case'}]) + + initPath = path.join(__dirname, 'fixtures', 'different-init-script.js') + pulsar.getUserInitScriptPath = () => initPath + pulsar.requireUserInitScript(); + commands = atom.commands.findCommands({target: window}) + .filter(({name}) => name.match(/test-case/)) + expect(commands).toEqual([{name: 'test-case-2', displayName: 'Test Case 2'}]) + }) + }) + }) + describe('attemptRestoreProjectStateForPaths(state, projectPaths, filesToOpen)', () => { describe('when the window is clean (empty or has only unnamed, unmodified buffers)', () => { beforeEach(async () => { diff --git a/spec/fixtures/different-init-script.js b/spec/fixtures/different-init-script.js new file mode 100644 index 0000000000..04c60a5b19 --- /dev/null +++ b/spec/fixtures/different-init-script.js @@ -0,0 +1,3 @@ +disposable.add(atom.commands.add(window, 'test-case-2', () => { + atom.notifications.addInfo("Hello!") +})) diff --git a/spec/fixtures/init-script.js b/spec/fixtures/init-script.js new file mode 100644 index 0000000000..92af0405bc --- /dev/null +++ b/spec/fixtures/init-script.js @@ -0,0 +1,3 @@ +atom.commands.add(window, 'test-case', () => { + atom.notifications.addInfo("Hello!") +}) diff --git a/spec/fixtures/reloadable-init-script.js b/spec/fixtures/reloadable-init-script.js new file mode 100644 index 0000000000..81aa1352f7 --- /dev/null +++ b/spec/fixtures/reloadable-init-script.js @@ -0,0 +1,3 @@ +disposable.add(atom.commands.add(window, 'test-case', () => { + atom.notifications.addInfo("Hello!") +})) diff --git a/src/atom-environment.js b/src/atom-environment.js index acdd901edc..94750ee52f 100644 --- a/src/atom-environment.js +++ b/src/atom-environment.js @@ -75,6 +75,7 @@ class AtomEnvironment { this.loadTime = null; this.emitter = new Emitter(); this.disposables = new CompositeDisposable(); + this.initScriptDisposables = new CompositeDisposable(); this.pathsWithWaitSessions = new Set(); /** @type {DeserializerManager} */ @@ -1563,7 +1564,19 @@ or use Pane::saveItemAs for programmatic saving.`); const userInitScriptPath = this.getUserInitScriptPath(); if (userInitScriptPath) { try { - if (fs.isFileSync(userInitScriptPath)) require(userInitScriptPath); + if (fs.isFileSync(userInitScriptPath)) { + if(this.config.get('core.autoReloadInitScript')) { + this.disposables.delete(this.initScriptDisposables) + this.initScriptDisposables.dispose() + this.initScriptDisposables = new CompositeDisposable(); + this.disposables.add(this.initScriptDisposables) + let contents = fs.readFileSync(userInitScriptPath, 'utf-8') + contents = `((disposable) => { ${contents}\n })(this.initScriptDisposables)` + eval(contents) + } else { + require(userInitScriptPath); + } + } } catch (error) { this.notifications.addError( `Failed to load \`${userInitScriptPath}\``, diff --git a/src/config-schema.js b/src/config-schema.js index d1a2ed2fe4..c8a75a248b 100644 --- a/src/config-schema.js +++ b/src/config-schema.js @@ -410,7 +410,13 @@ const configSchema = { default: false, title: 'Allow Window Transparency', description: `Allows editor windows to be see-through. When this setting is enabled, UI themes and user stylesheets can use background colors with an alpha channel to make editor windows translucent. Takes effect after a restart of Pulsar.` - } + }, + autoReloadInitScript: { + type: 'boolean', + default: false, + description: + 'Automatically reloads the init script when the file was changed. Adds a global `disposable` object that can be used at the init script to dispose old commands, old callbacks, etc. DO NOT enable this without using `disposable` in your init script, otherwise you will have duplicated commands.' + }, } }, editor: {