mavensmate
Version:
Core APIs that drive MavensMate IDEs for Salesforce1/Force.com
219 lines (197 loc) • 6.85 kB
JavaScript
/**
* @file Responsible for launching MavensMate UIs and opening files in the client self.editor
* @author Joseph Ferraro <@joeferraro>
*/
;
var Promise = require('bluebird');
var _ = require('lodash');
var which = require('which');
var spawn = require('child_process').spawn;
var logger = require('winston');
var util = require('../util');
var config = require('../../config');
var path = require('path');
var os = require('os');
var fs = require('fs-extra');
var open = require('open');
var querystring = require('querystring');
/**
* Service to handle interaction with the self.editor (sublime, atom, etc.)
* @param {String} self.editor - name of the self.editor
*/
var EditorService = function(editor, openWindowFn) {
this.editor = editor;
this.openWindowFn = openWindowFn;
this.supportedEditors = this._getSupportedEditors();
if (this.editor && !this._isSupportedEditor(this.editor)) {
throw new Error(this.editor+' was not found in list of supported editors. Please check your global settings to ensure the self.editor path for '+this.editor+' is configured correctly.');
}
};
EditorService.prototype._isSupportedEditor = function(editor) {
if (!this.supportedEditors[this.editor]) {
logger.error('Unsupported editor. Supported editors: ', this.supportedEditors);
return false;
}
return true;
};
EditorService.prototype._getSupportedEditors = function() {
var editors = {};
var atomLocationConfig = config.get('mm_atom_exec_path')[util.platformConfigKey] || config.get('mm_atom_exec_path');
var vsCodeLocationConfig = config.get('mm_vscode_exec_path')[util.platformConfigKey] || config.get('mm_vscode_exec_path');
var pathAtomLocation, pathSublLocation, pathVsCodeLocation;
try { pathVsCodeLocation = which.sync('code'); } catch(e){}
try { pathAtomLocation = which.sync('atom'); } catch(e){}
var sublLocationConfig = config.get('mm_subl_location')[util.platformConfigKey] || config.get('mm_subl_location');
try { pathSublLocation = which.sync('subl'); } catch(e){}
var atomPath = fs.existsSync(atomLocationConfig) ? atomLocationConfig : pathAtomLocation;
var sublPath = fs.existsSync(sublLocationConfig) ? sublLocationConfig : pathSublLocation;
var vsCodePath = fs.existsSync(vsCodeLocationConfig) ? vsCodeLocationConfig : pathVsCodeLocation;
if (atomPath) {
editors.atom = atomPath;
}
if (sublPath) {
editors.sublime = sublPath;
}
if (vsCodePath) {
editors.vscode = vsCodePath;
}
return editors;
};
/**
* Launches the MavensMate UI in either MavensMateWindowServer.app (osx) or the web browser (Linux/Windows)
* @param {String} commandName
* @return {Nothing}
*/
EditorService.prototype.launchUI = function(appPath, urlParams) {
var self = this;
return new Promise(function(resolve, reject) {
var portNumber = process.env.MAVENSMATE_SERVER_PORT;
if (!portNumber) {
return reject(new Error('Could not detect local MavensMate server port. Set MAVENSMATE_SERVER_PORT environment variable.'));
}
var url = 'http://localhost:'+portNumber+'/app/'+appPath;
if (self.editor && urlParams) {
urlParams.editor = self.editor;
} else if (self.editor) {
urlParams = {};
urlParams.editor = self.editor;
}
if (urlParams) {
url += '?'+querystring.stringify(urlParams);
}
logger.debug('opening url --->');
logger.debug(url);
// todo: refactor windowopener (this is used by mavensmate-desktop)
if (self.openWindowFn) {
self.openWindowFn(url);
resolve();
} else {
// open web browser
open(url, function() {
if (process.env.MAVENSMATE_CONTEXT === 'cli') {
resolve();
process.exit(0);
} else {
resolve();
}
});
}
});
};
/**
* Opens the specified URL in the user's browser (should probably be located in util, but oh well)
* @param {String} url - url to open in the browser
*/
EditorService.prototype.openUrl = function(url) {
var self = this;
return new Promise(function(resolve, reject) {
try {
if (self.openWindowFn) {
self.openWindowFn(url);
resolve();
} else if (os.platform() === 'darwin') {
var browserChildProcess = spawn('open', [url], {
detached: true
});
browserChildProcess.on('close', function (code) {
if (code === 0) {
resolve();
}
});
} else {
// open web browser
open(url, function() {
resolve();
});
}
} catch(e) {
reject(e);
}
});
};
EditorService.prototype.runCommand = function(commandName) {
var self = this;
return new Promise(function(resolve, reject) {
if (self.editor === 'sublime') {
var editorExe = spawn(self.supportedEditors[self.editor], ['--command', commandName]);
editorExe.stdout.on('data', function (data) {
logger.debug('editor command STDOUT:');
logger.debug(data);
});
editorExe.stderr.on('data', function (data) {
logger.error('ERROR: Result of run command in editor: ');
logger.error(data);
return resolve(); // we resolve bc this is not a life/death operation
});
editorExe.on('close', function(code) {
logger.debug('editorExe close: ');
logger.debug(code);
if (code !== 0) {
logger.error('Could not run command in '+self.editor);
resolve();
} else {
resolve();
}
});
editorExe.on('error', function(err) {
logger.error(err);
resolve();
});
} else {
resolve();
}
});
};
/**
* Open a specific path in the editor
* @param {String} path - path to open
* @return {Nothing}
*/
EditorService.prototype.open = function(path) {
var self = this;
return new Promise(function(resolve, reject) {
var editorExe = spawn(self.supportedEditors[self.editor], [ path ]);
editorExe.stdout.on('data', function (data) {
logger.debug('editorExe STDOUT:');
logger.debug(data);
});
editorExe.stderr.on('data', function (data) {
logger.error('Result of path open in self.editor: ');
logger.error(data);
return reject(new Error('Could not open in editor'));
});
editorExe.on('close', function(code) {
logger.debug('editorExe close: ');
logger.debug(code);
if (code !== 0) {
reject(new Error('Could not open path in '+self.editor+'. Check your MavensMate global settings to ensure self.editor paths are configured properly for '+self.editor));
} else {
resolve();
}
});
editorExe.on('error', function(err) {
return reject(err);
});
});
};
module.exports = EditorService;