From a710eb329212f47def6689f2ff8dcabe6c9554f6 Mon Sep 17 00:00:00 2001 From: Alex Kotliarskyi Date: Wed, 11 Nov 2015 13:43:11 -0800 Subject: [PATCH] Try to guess user's editor Summary: public Currently works only on OSX and supports Sublime (2/3) and Atom. The idea is to get the list of running processes and try to find some well-known editors there. Reviewed By: vjeux Differential Revision: D2642865 fb-gh-sync-id: d346902662354b2f633651a9bc54368146133651 --- local-cli/server/util/launchEditor.js | 53 +++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/local-cli/server/util/launchEditor.js b/local-cli/server/util/launchEditor.js index 0e0ce9036..a456eda59 100644 --- a/local-cli/server/util/launchEditor.js +++ b/local-cli/server/util/launchEditor.js @@ -10,7 +10,8 @@ var chalk = require('chalk'); var fs = require('fs'); -var spawn = require('child_process').spawn; +var path = require('path'); +var child_process = require('child_process'); function isTerminalEditor(editor) { switch (editor) { @@ -22,8 +23,19 @@ function isTerminalEditor(editor) { return false; } +// Map from full process name to binary that starts the process +// We can't just re-use full process name, because it will spawn a new instance +// of the app every time +var COMMON_EDITORS = { + '/Applications/Atom.app/Contents/MacOS/Atom': 'atom', + '/Applications/Sublime Text.app/Contents/MacOS/Sublime Text': + '/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl', + '/Applications/Sublime Text 2.app/Contents/MacOS/Sublime Text 2': + '/Applications/Sublime Text 2.app/Contents/SharedSupport/bin/subl', +}; + function getArgumentsForLineNumber(editor, fileName, lineNumber) { - switch (editor) { + switch (path.basename(editor)) { case 'vim': case 'mvim': return [fileName, '+' + lineNumber]; @@ -47,6 +59,33 @@ function getArgumentsForLineNumber(editor, fileName, lineNumber) { return [fileName]; } +function guessEditor() { + // Explicit config always wins + if (process.env.REACT_EDITOR) { + return process.env.REACT_EDITOR; + } + + // Using `ps x` on OSX we can find out which editor is currently running. + // Potentially we could use similar technique for Windows and Linux + if (process.platform === 'darwin') { + try { + var output = child_process.execSync('ps x').toString(); + var processNames = Object.keys(COMMON_EDITORS); + for (var i = 0; i < processNames.length; i++) { + var processName = processNames[i]; + if (output.indexOf(processName) !== -1) { + return COMMON_EDITORS[processName]; + } + } + } catch(error) { + // Ignore... + } + } + + // Last resort, use old skool env vars + return process.env.VISUAL || process.env.EDITOR; +} + function printInstructions(title) { console.log([ '', @@ -55,8 +94,8 @@ function printInstructions(title) { ' stack frame to jump to the source file. The packager will launch your ', ' editor of choice. It will first look at REACT_EDITOR environment ', ' variable, then at EDITOR. To set it up, you can add something like ', - ' REACT_EDITOR=atom to your ~/.bashrc or export REACT_EDITOR=atom to your', - ' ~/.zshrc depending on which shell you use.', + ' export REACT_EDITOR=atom to your ~/.bashrc or ~/.zshrc depending on ', + ' which shell you use.', '' ].join('\n')); } @@ -67,7 +106,7 @@ function launchEditor(fileName, lineNumber) { return; } - var editor = process.env.REACT_EDITOR || process.env.EDITOR; + var editor = guessEditor(); if (!editor) { printInstructions('PRO TIP'); return; @@ -86,7 +125,7 @@ function launchEditor(fileName, lineNumber) { _childProcess.kill('SIGKILL'); } - _childProcess = spawn(editor, args, {stdio: 'inherit'}); + _childProcess = child_process.spawn(editor, args, {stdio: 'inherit'}); _childProcess.on('exit', function(errorCode) { _childProcess = null; @@ -99,7 +138,7 @@ function launchEditor(fileName, lineNumber) { _childProcess.on('error', function(error) { console.log(chalk.red(error.message)); printInstructions('How to fix:'); - }) + }); } module.exports = launchEditor;