Skip to content

Commit

Permalink
cleaning up for 2.x release
Browse files Browse the repository at this point in the history
* improved the dispose pattern for BGAtomPlugin
* BGAtomPlugin: added  watchConfig, watchPackage, watchPreCommand, watchPostCommand
* moved BGStylesheet from here to  bg-atom-redom-ui
* organized pkg helpers into bg-packageManager accessing via atom2.packages
* added bg-promise
*
  • Loading branch information
bobjunga committed May 1, 2020
1 parent a573225 commit bc8f212
Show file tree
Hide file tree
Showing 8 changed files with 466 additions and 586 deletions.
113 changes: 95 additions & 18 deletions BGAtomPlugin.js
@@ -1,8 +1,6 @@

import { Disposable, CompositeDisposable } from 'atom';
import { Disposables } from 'bg-atom-redom-ui';
import { FirstParamOf } from './miscellaneous';


// BGAtomPlugin makes writing Atom plugin packages easier.
// Atom Entry Points:
// initialize: maps to static PluginClass.Initialize()
Expand All @@ -14,8 +12,10 @@ import { FirstParamOf } from './miscellaneous';
// when the package is activated via settings-view, this will still be called after the tick that the constructor is in settles
// Members:
// lastSessionsState : contains the deserialization state passed from the atom activate call
// disposables : an instance of CompositeDisposable to add things that need to be undone in destroy
// addCommand() : wrapper to atom.commands.add()
// disposables : an instance of Disposables to add things that need to be undone in destroy
// addCommand() : wrapper to atom.commands.add(). associates the commands with this plugin and unregisters them in deactivate
// watchConfig() : get notified when a configKey's value changes
// watchPackages() : get notified when a package's activation state changes
// Plugin Registry:
// window.bgPlgins['my-plugin'] : other packages and user init.js can find your package's services dynamically
// Example:
Expand All @@ -36,16 +36,19 @@ export class BGAtomPlugin {
// usage: pkgName, lastSessionsState
constructor(...p) {
this.pkgName = FirstParamOf('string', ...p);
this.lastSessionsState = FirstParamOf('object', ...p);
this.lastSessionsState = FirstParamOf('object', ...p) || {};
this.PluginClass = new.target;


// subscriptions is a place to put things that need to be cleaned up on deativation
this.disposables = new CompositeDisposable();
this.disposables = new Disposables();
// make an alias to support transitioning to this.disposables name
this.subscriptions = this.disposables;

this.registeredCommands = [];
// When the derived class uses our methods to create resources, they are tracked in these Maps and automatically disposed.
this.registeredCommands = new DisposableMap();
this.watchedConfig = new DisposableMap();
this.watchedPacakges = new DisposableMap();
this.watchedPreCmd = new DisposableMap();
this.watchedPostCmd = new DisposableMap();

console.assert(!this.PluginClass.instance, 'Package plugin being constructed twice. Should be a singleton. pacakgeName='+this.pkgName);
this.PluginClass.instance = this;
Expand All @@ -66,20 +69,85 @@ export class BGAtomPlugin {
//lateActivate(state) {}

destroy() {
this.disposables.dispose();
// this.registeredCommands.forEach(v=>v.dispose()); this.registeredCommands.clear();
// this.watchedConfig.forEach(v=>v.dispose()); this.watchedConfig.clear();
// this.watchedPacakges.forEach(v=>v.dispose()); this.watchedPacakges.clear();

for (const name of Object.getOwnPropertyNames(this)) {
const prop = this[name];
if (typeof prop == 'object' && typeof prop.dispose == 'function') {
//console.log(`!!!found ${name} to dispose`);
prop.dispose();
}
}

this.PluginClass.instance = null
delete BGAtomPlugin.plugins[this.pkgName];
}

serialize() {
return ;
}
serialize() {}

// add to atom's command pallette
// call this with a null callback to remove the command
addCommand(name, callback) {
this.registeredCommands.push(name);
var obj = {}
obj[name] = callback;
this.disposables.add(atom.commands.add('atom-workspace', obj));
const prevValue = this.registeredCommands.get(name);
if (prevValue) {
prevValue.dispose;
this.registeredCommands.delete(name);
}
callback && this.registeredCommands.set(name, atom.commands.add('atom-workspace', {[name]:callback}));
}

// callback gets invoked whenever thespecified configKey changes value
// call this with a null callback to stop watching
watchConfig(configKey, callback) {
const prevValue = this.watchedConfig.get(configKey);
if (prevValue) {
prevValue.dispose;
this.watchedConfig.delete(configKey)
}
callback && this.watchedConfig.set(configKey, atom.config.onDidChange(configKey, {}, callback));
}

// callback gets invoked whenever a specified pkgName changes activation state. Callback is passed the name of the package and
// a boolean indicating the current activation state.
// call this with a null callback to stop watching
watchPackage(pkgNames, callback) {
typeof pkgNames == 'string' && (pkgNames = pkgNames.split(','));
for (const pkgName of pkgNames) {
const prevValue = this.watchedPacakges.get(pkgName);
if (prevValue) {
prevValue.dispose;
this.watchedPacakges.delete(configKey)
}
callback && this.watchedPacakges.set(pkgName, {
onAct: atom.packages.onDidActivatePackage( (pkg)=>{if (pkgName==pkg.name) callback(pkg.name, true);}),
onDea: atom.packages.onDidDeactivatePackage((pkg)=>{if (pkgName==pkg.name) callback(pkg.name, false);}),
dispose: function () {this.onAct.dispose(); this.onDea.dispose()}
});
}
}

watchPreCommand(cmdSpec, callback) {
typeof cmdSpec == 'string' && (cmdSpec = new RegExp(cmdSpec));
const key = cmdSpec.toString();
const prevValue = this.watchedPreCmd.get(key);
if (prevValue) {
prevValue.dispose;
this.watchedPreCmd.delete(key)
}
callback && this.watchedPreCmd.delete(key, atom.commands.onWillDispatch((e)=>{if (cmdSpec.test(e.type)) callback(e.type,e);}));
}

watchPostCommand(cmdSpec, callback) {
typeof cmdSpec == 'string' && (cmdSpec = new RegExp(cmdSpec));
const key = cmdSpec.toString();
const prevValue = this.watchedPostCmd.get(key);
if (prevValue) {
prevValue.dispose;
this.watchedPostCmd.delete(key)
}
callback && this.watchedPostCmd.delete(key, atom.commands.onDidDispatch((e)=>{if (cmdSpec.test(e.type)) callback(e.type,e);}));
}

// Use this static method to export your MyPluginClass that extends BGAtomPlugin
Expand All @@ -95,5 +163,14 @@ export class BGAtomPlugin {
}
}

// helper class to manage containers of resorces that we need to dispose of when deactivated
class DisposableMap extends Map {
dispose() {
this.forEach(v=>v.dispose());
this.clear();
}
}


BGAtomPlugin.plugins = {};
global.bgPlugins = BGAtomPlugin.plugins;

0 comments on commit bc8f212

Please sign in to comment.