├── .npmingnore ├── .gitignore ├── .editorconfig ├── lib ├── editors │ ├── phpstorm.js │ ├── webstorm.js │ ├── idea14ce.js │ ├── index.js │ ├── common │ │ ├── terminal.js │ │ └── jetbrains.js │ ├── visualstudio.js │ ├── emacs.js │ ├── vim.js │ ├── atom.js │ ├── code.js │ ├── sublime.js │ └── visualstudio.vbs ├── check.js ├── detect.js ├── utils.js ├── index.js └── open.js ├── package.json ├── LICENSE ├── HISTORY.md ├── bin └── oe ├── .jscsrc └── README.md /.npmingnore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.swp 3 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | 4 | [*.js] 5 | charset = utf-8 6 | indent_style = space 7 | indent_size = 2 -------------------------------------------------------------------------------- /lib/editors/phpstorm.js: -------------------------------------------------------------------------------- 1 | var jetbrainsEditor = require('./common/jetbrains'); 2 | 3 | module.exports = jetbrainsEditor({ 4 | name: 'PhpStorm IDE', 5 | appFolder: 'PhpStorm', 6 | executable: 'phpstorm' 7 | }); 8 | -------------------------------------------------------------------------------- /lib/editors/webstorm.js: -------------------------------------------------------------------------------- 1 | var jetbrainsEditor = require('./common/jetbrains'); 2 | 3 | module.exports = jetbrainsEditor({ 4 | name: 'WebStorm IDE', 5 | appFolder: 'WebStorm', 6 | executable: 'webstorm' 7 | }); 8 | -------------------------------------------------------------------------------- /lib/editors/idea14ce.js: -------------------------------------------------------------------------------- 1 | var jetbrainsEditor = require('./common/jetbrains'); 2 | 3 | module.exports = jetbrainsEditor({ 4 | name: 'IDEA 14 CE', 5 | appFolder: 'IntelliJ IDEA 14 CE', 6 | executable: 'idea' 7 | }); 8 | -------------------------------------------------------------------------------- /lib/editors/index.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | atom: require('./atom'), 3 | code: require('./code'), 4 | sublime: require('./sublime'), 5 | webstorm: require('./webstorm'), 6 | phpstorm: require('./phpstorm'), 7 | idea14ce: require('./idea14ce'), 8 | vim: require('./vim'), 9 | visualstudio: require('./visualstudio'), 10 | emacs: require('./emacs') 11 | }; 12 | -------------------------------------------------------------------------------- /lib/editors/common/terminal.js: -------------------------------------------------------------------------------- 1 | var osascript = function(script) { 2 | return 'osascript -e \'' + script + '\''; 3 | }; 4 | 5 | var terminal = function(cmd) { 6 | return 'tell application "Terminal" to do script "' + cmd + '"'; 7 | }; 8 | 9 | var runInTerminal = function(cmd) { 10 | return osascript(terminal('cd {projectPath}; ' + cmd)); 11 | }; 12 | 13 | module.exports = runInTerminal; 14 | -------------------------------------------------------------------------------- /lib/editors/visualstudio.js: -------------------------------------------------------------------------------- 1 | var path = require('path'); 2 | var helperPath = path.resolve(__dirname, 'visualstudio.vbs'); 3 | 4 | var settings = { 5 | pattern: '{filename} {line} {column}' 6 | }; 7 | 8 | var detect = require('../detect').platformSupport(['win32'], 'Visual Studio', helperPath); 9 | var open = require('../open').detectAndOpenFactory(detect, settings); 10 | 11 | module.exports = { 12 | settings: settings, 13 | detect: detect, 14 | open: open 15 | }; 16 | -------------------------------------------------------------------------------- /lib/editors/emacs.js: -------------------------------------------------------------------------------- 1 | var runInTerminal = require('./common/terminal'); 2 | 3 | var settings = { 4 | patternOnly: true, 5 | escapeQuotes: true, 6 | pattern: runInTerminal('emacs --no-splash \\"+{line}:{column}\\" {filename}') 7 | }; 8 | 9 | var detect = require('../detect').platformSupport(['darwin'], 'vim'); 10 | var open = require('../open').detectAndOpenFactory(detect, settings); 11 | 12 | module.exports = { 13 | settings: settings, 14 | detect: detect, 15 | open: open 16 | }; 17 | -------------------------------------------------------------------------------- /lib/editors/vim.js: -------------------------------------------------------------------------------- 1 | var runInTerminal = require('./common/terminal'); 2 | 3 | var settings = { 4 | patternOnly: true, 5 | escapeQuotes: true, 6 | pattern: runInTerminal('vim {filename} \\"+call cursor({line}, {column})\\"') 7 | }; 8 | 9 | var detect = require('../detect').platformSupport(['darwin'], 'vim'); 10 | var open = require('../open').detectAndOpenFactory(detect, settings); 11 | 12 | module.exports = { 13 | settings: settings, 14 | detect: detect, 15 | open: open 16 | }; 17 | -------------------------------------------------------------------------------- /lib/editors/atom.js: -------------------------------------------------------------------------------- 1 | var atHomeDir = require('../utils').atHomeDir; 2 | 3 | var settings = { 4 | pattern: '{filename}:{line}:{column}' 5 | }; 6 | 7 | var detect = require('../detect').lazy('Atom Editor', ['atom'], '-h', { 8 | darwin: [ 9 | '/Applications/Atom.app/Contents/Resources/app/atom.sh' 10 | ], 11 | win32: [ 12 | atHomeDir('AppData/Local/atom/bin/atom.cmd') 13 | ] 14 | }); 15 | 16 | var open = require('../open').detectAndOpenFactory(detect, settings); 17 | 18 | module.exports = { 19 | settings: settings, 20 | detect: detect, 21 | open: open 22 | }; 23 | -------------------------------------------------------------------------------- /lib/editors/code.js: -------------------------------------------------------------------------------- 1 | var atHomeDir = require('../utils').atHomeDir; 2 | 3 | var settings = { 4 | pattern: '-r -g {filename}:{line}:{column}' 5 | }; 6 | 7 | var detect = require('../detect').lazy('Visual Studio Code', ['code'], '-h', { 8 | darwin: [ 9 | '/Applications/Visual Studio Code.app/Contents/MacOS/Electron' 10 | ], 11 | win32: [ 12 | 'C:/Program Files/Microsoft VS Code/bin/code.cmd', 13 | 'C:/Program Files (x86)/Microsoft VS Code/bin/code.cmd', 14 | atHomeDir('AppData/Local/Code/bin/code.cmd') 15 | ] 16 | }); 17 | 18 | var open = require('../open').detectAndOpenFactory(detect, settings); 19 | 20 | module.exports = { 21 | settings: settings, 22 | detect: detect, 23 | open: open 24 | }; 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "open-in-editor", 3 | "description": "Open file in editor", 4 | "version": "2.2.0", 5 | "author": "Roman Dvornov ", 6 | "license": "MIT", 7 | "repository": "lahmatiy/open-in-editor", 8 | "keywords": [ 9 | "open", 10 | "file", 11 | "editor", 12 | "atom", 13 | "code", 14 | "vscode", 15 | "idea", 16 | "phpstorm", 17 | "webstorm", 18 | "sublime", 19 | "visual studio", 20 | "vim", 21 | "emacs" 22 | ], 23 | "main": "./lib/index.js", 24 | "engines": { 25 | "node": ">=0.12.0" 26 | }, 27 | "bin": { 28 | "oe": "./bin/oe" 29 | }, 30 | "dependencies": { 31 | "clap": "^1.1.3", 32 | "os-homedir": "~1.0.2" 33 | }, 34 | "devDependencies": {}, 35 | "scripts": {} 36 | } 37 | -------------------------------------------------------------------------------- /lib/editors/sublime.js: -------------------------------------------------------------------------------- 1 | var settings = { 2 | pattern: '{filename}:{line}:{column}' 3 | }; 4 | 5 | var detect = require('../detect').lazy('Sublime Text', ['subl'], '-h', { 6 | darwin: [ 7 | '/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl' 8 | ], 9 | win32: [ 10 | 'C:/Program Files/Sublime Text/subl.exe', 11 | 'C:/Program Files/Sublime Text 2/subl.exe', 12 | 'C:/Program Files/Sublime Text 3/subl.exe', 13 | 'C:/Program Files (x86)/Sublime Text/subl.exe', 14 | 'C:/Program Files (x86)/Sublime Text 2/subl.exe', 15 | 'C:/Program Files (x86)/Sublime Text 3/subl.exe' 16 | ] 17 | }); 18 | 19 | var open = require('../open').detectAndOpenFactory(detect, settings); 20 | 21 | module.exports = { 22 | settings: settings, 23 | detect: detect, 24 | open: open 25 | }; 26 | -------------------------------------------------------------------------------- /lib/check.js: -------------------------------------------------------------------------------- 1 | var exec = require('child_process').exec; 2 | var fs = require('fs'); 3 | var quote = require('./utils').quote; 4 | 5 | function checkCommand(cmd, name, args) { 6 | if (!args) { 7 | return Promise.reject('No args to check command: ' + cmd); 8 | } 9 | 10 | return new Promise(function(resolve, reject) { 11 | exec(cmd + ' ' + args, function(err, output) { 12 | if (err || output.indexOf(name) !== 0) { 13 | reject(err); 14 | } else { 15 | resolve(cmd); 16 | } 17 | }); 18 | }); 19 | } 20 | 21 | function checkPath(path, name) { 22 | if (!fs.existsSync(path)) { 23 | return Promise.reject('Path does not exist: ' + path); 24 | } 25 | 26 | return Promise.resolve(path); 27 | } 28 | 29 | module.exports = { 30 | command: checkCommand, 31 | path: checkPath 32 | }; 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Roman Dvornov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /lib/detect.js: -------------------------------------------------------------------------------- 1 | var check = require('./check'); 2 | var any = require('./utils').any; 3 | 4 | function detect(name, commands, args, locations) { 5 | function run(task) { 6 | return this(task, name, args); 7 | } 8 | 9 | locations = locations[process.platform] || []; 10 | 11 | return any( 12 | [].concat( 13 | commands.map(run, check.command), 14 | locations.map(run, check.path) 15 | ), 16 | 'Not detected' 17 | ); 18 | } 19 | 20 | module.exports = detect; 21 | module.exports.lazy = function(name, commands, args, locations) { 22 | var memo; 23 | 24 | return function() { 25 | if (!memo) { 26 | memo = detect(name, commands, args, locations); 27 | } 28 | 29 | return memo; 30 | }; 31 | }; 32 | module.exports.platformSupport = function(platforms, editor, resolveValue) { 33 | return function() { 34 | // we use only system parts so we haven't to check anything except os 35 | if (platforms.indexOf(process.platform) !== -1) { 36 | return Promise.resolve(resolveValue); 37 | } 38 | 39 | return Promise.reject('"Open in ' + editor + '" does not implemented for your platform (' + process.platform + ')'); 40 | }; 41 | }; 42 | -------------------------------------------------------------------------------- /lib/editors/common/jetbrains.js: -------------------------------------------------------------------------------- 1 | var fs = require('fs'); 2 | var path = require('path'); 3 | var lazyDetect = require('../../detect').lazy; 4 | 5 | var settings = { 6 | pattern: '{projectPath} --line {line} {filename}' 7 | }; 8 | 9 | var winDirs = (function() { 10 | var jetbrainsFolder = 'c:/Program Files (x86)/JetBrains/'; 11 | 12 | if (!fs.existsSync(jetbrainsFolder)) { 13 | return []; 14 | } 15 | 16 | return fs.readdirSync(jetbrainsFolder) 17 | .map(function(name) { 18 | return path.join(jetbrainsFolder, name); 19 | }) 20 | .filter(function(path) { 21 | return fs.statSync(path).isDirectory(); 22 | }); 23 | })(); 24 | 25 | module.exports = function(config) { 26 | var detect = lazyDetect(config.name, [], '', { 27 | darwin: [ 28 | '/Applications/' + config.appFolder + '.app/Contents/MacOS/' + config.executable 29 | ], 30 | win32: winDirs.map(function(dir) { 31 | return dir + '/bin/' + config.executable + '.exe'; 32 | }) 33 | }); 34 | var open = require('../../open').detectAndOpenFactory(detect, settings); 35 | 36 | return { 37 | settings: settings, 38 | detect: detect, 39 | open: open 40 | }; 41 | }; 42 | -------------------------------------------------------------------------------- /HISTORY.md: -------------------------------------------------------------------------------- 1 | ## 2.2.0 (March 22, 2017) 2 | 3 | - Fixed passing settings to `open()` when only `cmd` option is set (#10) 4 | - Changed behaviour to use an editor settings as defaults when `editor` and `cmd` options are specified 5 | - Added `--pattern` option to CLI 6 | 7 | ## 2.1.0 (March 21, 2017) 8 | 9 | - Added basic support for `emacs` (thanks to @zefirka) 10 | - Fixed crash on attempt to use `vim` on non-`darwin` platform 11 | 12 | ## 2.0.0 (March 15, 2017) 13 | 14 | - Added basic support for `vim` (thanks to @pofigizm) 15 | - Added support for `Visual Studio` (thanks to @generalov) 16 | - Changed node.js support to `0.12` and greater 17 | 18 | ## 1.2.1 (November 14, 2016) 19 | 20 | - Added support for `Visual Studio Code` 21 | 22 | ## 1.2.0 (November 12, 2015) 23 | 24 | - Added support for JetBrains's IDEs on Windows (thanks to @Mavrin) 25 | 26 | ## 1.1.0 (November 8, 2015) 27 | 28 | - Added support for `WebStorm` (thanks to @chicoxyzzy) 29 | - Added support for `IDEA 14 CE` (thanks to @chicoxyzzy) 30 | - Added support for `PhpStorm` (thanks to @silentroach) 31 | - Removed `preferGlobal` option from `package.json` 32 | - Improved documentation 33 | 34 | ## 1.0 (September 24, 2015) 35 | 36 | - Initial release 37 | -------------------------------------------------------------------------------- /bin/oe: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | var clap = require('clap'); 4 | var version = require('../package.json').version; 5 | var editors = require('../lib/editors'); 6 | var fail = require('../lib/utils').fail; 7 | var main = require('../lib/index'); 8 | 9 | var command = clap.create('oe', '[filename]') 10 | .description('Open file in editor') 11 | .version(version) 12 | 13 | .option('-f, --file ', 'File to open') 14 | .option('-e, --editor ', 'Editor: ' + Object.keys(editors).join(', ')) 15 | .option('-p, --pattern ', 'Filename pattern and args, i.e. something going after cmd') 16 | .option('--cmd ', 'Command to open file') 17 | .option('--debug', 'Debug errors') 18 | 19 | .action(function(args) { 20 | main 21 | .configure(this.values, fail) 22 | .open(this.values.file || args[0]) 23 | .catch(function(err) { 24 | if (this.values.debug) { 25 | process.nextTick(function() { 26 | throw err; 27 | }); 28 | } else { 29 | fail(err); 30 | } 31 | }.bind(this)); 32 | }); 33 | 34 | try { 35 | command.run(); 36 | } catch (err) { 37 | if (err instanceof clap.Error == false) { 38 | throw err; 39 | } 40 | 41 | fail(err); 42 | } 43 | -------------------------------------------------------------------------------- /lib/utils.js: -------------------------------------------------------------------------------- 1 | var osHomeDir = require('os-homedir')(); 2 | var path = require('path'); 3 | 4 | module.exports = { 5 | number: function(value, fallback) { 6 | return isNaN(value) ? fallback : value; 7 | }, 8 | quote: function(value, escapeQuotes) { 9 | value = String(value) 10 | .replace(/\\/g, '\\\\') 11 | .replace(/"/g, '\"'); 12 | 13 | return escapeQuotes ? 14 | '\\"' + value + '\\"' : 15 | '"' + value + '"'; 16 | }, 17 | extractFilename: function(filename) { 18 | var parts = filename.match(/^(.+?)((?::\d+){0,4})$/); 19 | var segment = parts[2].split(':').slice(1); 20 | 21 | return { 22 | filename: parts[1], 23 | line: parseInt(segment[0] || 0, 10), 24 | column: parseInt(segment[1] || 0, 10) 25 | }; 26 | }, 27 | fail: function(msg) { 28 | console.error(String(msg).trimRight()); 29 | process.exit(2); 30 | }, 31 | atHomeDir: function(filename) { 32 | return path.join(osHomeDir, filename); 33 | }, 34 | any: function(promises, err) { 35 | return new Promise(function(resolve, reject) { 36 | Promise.all(promises.map(function(item) { 37 | if (item && typeof item.then == 'function') { 38 | return item.then( 39 | resolve, // any success resolves the main promise immediately 40 | function() { /* ignore any reject */ } 41 | ); 42 | } 43 | 44 | return item; 45 | })).then(function(results) { 46 | reject(err); 47 | }, reject); 48 | }); 49 | }, 50 | append: function(str, appendix) { 51 | return String(str).replace(/\s*$/, (str ? ' ' : '') + appendix); 52 | }, 53 | assign: function(dest, src) { 54 | for (var key in src) { 55 | if (Object.prototype.hasOwnProperty.call(src, key)) { 56 | dest[key] = src[key]; 57 | } 58 | } 59 | 60 | return dest; 61 | } 62 | }; 63 | -------------------------------------------------------------------------------- /lib/index.js: -------------------------------------------------------------------------------- 1 | var extractFilename = require('./utils').extractFilename; 2 | var number = require('./utils').number; 3 | var assign = require('./utils').assign; 4 | var editors = require('./editors'); 5 | var openFactory = require('./open').factory; 6 | 7 | module.exports = { 8 | configure: function(options, cb) { 9 | options = options || {}; 10 | cb = cb || function() {}; 11 | 12 | var sourceLineOffset = number(options.line, 1); 13 | var sourceColumnOffset = number(options.column, 1); 14 | var editor = options.editor; 15 | var cmd = options.cmd; 16 | var open; 17 | 18 | if (!cmd && !editor) { 19 | if (editors.hasOwnProperty(process.env.OPEN_FILE)) { 20 | editor = process.env.OPEN_FILE; 21 | } else { 22 | cmd = process.env.OPEN_FILE || 23 | process.env.VISUAL || 24 | process.env.EDITOR; 25 | } 26 | } 27 | 28 | // if editor option is set then fail on wrong value 29 | if (editor && !editors.hasOwnProperty(editor)) { 30 | cb('Wrong value for `editor` option: ' + editor); 31 | return; 32 | } 33 | 34 | if (cmd) { 35 | var settings = {}; 36 | 37 | // use editor settings as base 38 | if (editors.hasOwnProperty(editor)) { 39 | assign(settings, editors[editor].settings); 40 | } 41 | 42 | open = openFactory(cmd, assign(settings, options)); 43 | } else { 44 | if (!editor) { 45 | cb('Editor is not specified'); 46 | return; 47 | } 48 | 49 | open = editors[editor].open; 50 | } 51 | 52 | return { 53 | open: function(filename) { 54 | if (!filename) { 55 | return Promise.reject('File is not specified'); 56 | } 57 | 58 | var info = extractFilename(filename); 59 | 60 | return open([ 61 | info.filename, 62 | Math.max(info.line - sourceLineOffset, 0), 63 | Math.max(info.column - sourceColumnOffset, 0) 64 | ].join(':')); 65 | } 66 | }; 67 | } 68 | }; 69 | -------------------------------------------------------------------------------- /lib/open.js: -------------------------------------------------------------------------------- 1 | var exec = require('child_process').exec; 2 | var number = require('./utils').number; 3 | var quote = require('./utils').quote; 4 | var extractFilename = require('./utils').extractFilename; 5 | var append = require('./utils').append; 6 | 7 | function makeArguments(filename, settings) { 8 | var info = extractFilename(filename); 9 | var pattern = settings.pattern || ''; 10 | var values = { 11 | projectPath: process.env.PROJECT_PATH || process.PWD || process.cwd(), 12 | line: info.line + number(settings.line, 1), 13 | column: info.column + number(settings.column, 1) 14 | }; 15 | 16 | if (!/\{filename\}/.test(pattern)) { 17 | pattern = append(pattern, '{filename}:{line}:{column}'); 18 | } 19 | 20 | return pattern 21 | .replace( 22 | new RegExp('\\{(' + Object.keys(values).join('|') + ')\\}', 'g'), 23 | function(m, name) { 24 | return values[name]; 25 | } 26 | ) 27 | // replace `{filename}` and adjoined right string for quoted filename, 28 | // since filename can have spaces 29 | // 30 | // {filename} --line 1 --column 2 31 | // => "filename" --line 1 --column 2 32 | // 33 | // {filename}:1:2 34 | // => "filename:1:2" 35 | // 36 | .replace(/\{filename\}(\S*)/, function(m, rest) { 37 | return quote(info.filename + rest, settings.escapeQuotes); 38 | }); 39 | } 40 | 41 | function open(cmd, filename, settings) { 42 | return new Promise(function(resolve, reject) { 43 | var args; 44 | 45 | settings = settings || {}; 46 | args = makeArguments(filename, settings); 47 | cmd = settings.patternOnly ? args : append(quote(cmd), args); 48 | 49 | exec(cmd, function(err) { 50 | if (err) { 51 | reject(err); 52 | } else { 53 | resolve(); 54 | } 55 | }); 56 | }); 57 | } 58 | 59 | module.exports = open; 60 | module.exports.factory = function(cmd, settings) { 61 | return function openInEditor(filename) { 62 | return open(cmd, filename, settings); 63 | }; 64 | }; 65 | 66 | module.exports.detectAndOpenFactory = function(detect, settings) { 67 | return function openInEditor(filename) { 68 | return detect().then(function(cmd) { 69 | open(cmd, filename, settings); 70 | }); 71 | }; 72 | }; 73 | -------------------------------------------------------------------------------- /lib/editors/visualstudio.vbs: -------------------------------------------------------------------------------- 1 | ' Copyright (c) 2016, Evgeny Panasyuk 2 | 3 | ' Permission is hereby granted, free of charge, to any person or organization 4 | ' obtaining a copy of the software and accompanying documentation covered by 5 | ' this license (the "Software") to use, reproduce, display, distribute, 6 | ' execute, and transmit the Software, and to prepare derivative works of the 7 | ' Software, and to permit third-parties to whom the Software is furnished to 8 | ' do so, all subject to the following: 9 | ' 10 | ' The copyright notices in the Software and this entire statement, including 11 | ' the above license grant, this restriction and the following disclaimer, 12 | ' must be included in all copies of the Software, in whole or in part, and 13 | ' all derivative works of the Software, unless such copies or derivative 14 | ' works are solely in the form of machine-executable object code generated by 15 | ' a source language processor. 16 | ' 17 | ' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | ' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | ' FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | ' SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | ' FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ' ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | ' DEALINGS IN THE SOFTWARE. 24 | 25 | ' e-mail: E?????[dot]P???????[at]gmail.??? 26 | 27 | Option Explicit 28 | 29 | Dim filename, line, column 30 | Dim MSVS_versions, version 31 | Dim dte, fso, wshShell 32 | Dim fullpath 33 | 34 | filename = WScript.Arguments(0) 35 | line = WScript.Arguments(1) 36 | column = WScript.Arguments(2) 37 | 38 | MSVS_versions = Array _ 39 | ( _ 40 | "VisualStudio.DTE.7", _ 41 | "VisualStudio.DTE.7.1", _ 42 | "VisualStudio.DTE.8.0", _ 43 | "VisualStudio.DTE.9.0", _ 44 | "VisualStudio.DTE.10.0", _ 45 | "VisualStudio.DTE.11.0", _ 46 | "VisualStudio.DTE.12.0", _ 47 | "VisualStudio.DTE.14.0", _ 48 | "VisualStudio.DTE.15.0" _ 49 | ) 50 | 51 | On Error Resume Next 52 | 53 | For each version in MSVS_versions 54 | Err.Clear 55 | Set dte = getObject(,version) 56 | If Err.Number = 0 Then 57 | Exit For 58 | End If 59 | Next 60 | 61 | If Err.Number <> 0 Then 62 | Set dte = WScript.CreateObject("VisualStudio.DTE") 63 | Err.Clear 64 | End If 65 | 66 | Set wshShell = WScript.CreateObject("WScript.Shell") 67 | Set fso = WScript.CreateObject("Scripting.FileSystemObject") 68 | fullpath = fso.GetAbsolutePathName(filename) 69 | 70 | dte.MainWindow.Activate() 71 | dte.MainWindow.Visible = True 72 | dte.UserControl = True 73 | wshShell.AppActivate dte.MainWindow.Caption 74 | 75 | dte.ItemOperations.OpenFile fullpath 76 | dte.ActiveDocument.Selection.MoveToLineAndOffset line, column + 1 77 | 78 | if Err.Number <> 0 Then 79 | WScript.Quit Err.Number 80 | End If 81 | 82 | On Error Goto 0 83 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "excludeFiles": [ 3 | "node_modules/**" 4 | ], 5 | 6 | "disallowEmptyBlocks": true, 7 | 8 | "disallowImplicitTypeConversion": ["numeric", "boolean", "binary", "string"], 9 | 10 | "disallowKeywords": ["with"], 11 | 12 | "disallowKeywordsOnNewLine": ["else", "catch", "finally"], 13 | 14 | "disallowMixedSpacesAndTabs": true, 15 | 16 | "disallowMultipleLineStrings": true, 17 | 18 | "disallowNewlineBeforeBlockStatements": true, 19 | 20 | "disallowOperatorBeforeLineBreak": ["."], 21 | 22 | "disallowPaddingNewlinesInBlocks": true, 23 | 24 | "disallowQuotedKeysInObjects": "allButReserved", 25 | 26 | "disallowSpaceAfterObjectKeys": true, 27 | 28 | "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], 29 | 30 | "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], 31 | 32 | "disallowSpacesInCallExpression": true, 33 | 34 | "disallowSpacesInFunction": { 35 | "beforeOpeningRoundBrace": true 36 | }, 37 | 38 | "disallowSpacesInFunctionDeclaration": { 39 | "beforeOpeningRoundBrace": true 40 | }, 41 | 42 | "disallowSpacesInFunctionExpression": { 43 | "beforeOpeningRoundBrace": true 44 | }, 45 | 46 | "disallowSpacesInNamedFunctionExpression": { 47 | "beforeOpeningRoundBrace": true 48 | }, 49 | 50 | "disallowSpacesInsideArrayBrackets": "all", 51 | 52 | "disallowSpacesInsideParentheses": true, 53 | 54 | "disallowTrailingComma": true, 55 | 56 | "disallowTrailingWhitespace": true, 57 | 58 | "disallowYodaConditions": true, 59 | 60 | "requireBlocksOnNewline": true, 61 | 62 | "requireCamelCaseOrUpperCaseIdentifiers": true, 63 | 64 | "requireCapitalizedConstructors": true, 65 | 66 | "requireCommaBeforeLineBreak": true, 67 | 68 | "requireCurlyBraces": [ 69 | "if", 70 | "else", 71 | "for", 72 | "while", 73 | "do", 74 | "try", 75 | "catch", 76 | "finally" 77 | ], 78 | 79 | "requireDotNotation": true, 80 | 81 | "requireKeywordsOnNewLine": [ 82 | "return", 83 | "for", 84 | "try", 85 | "do", 86 | "switch", 87 | "case" 88 | ], 89 | 90 | "requireLineBreakAfterVariableAssignment": true, 91 | 92 | "requireLineFeedAtFileEnd": true, 93 | 94 | "disallowMultipleVarDecl": true, 95 | 96 | "requireOperatorBeforeLineBreak": [ 97 | "=", 98 | "+", 99 | "-", 100 | "/", 101 | "*", 102 | "==", 103 | "===", 104 | "!=", 105 | "!==", 106 | ">", 107 | ">=", 108 | "<", 109 | "<=" 110 | ], 111 | 112 | "requireParenthesesAroundIIFE": true, 113 | 114 | "requireSpaceAfterBinaryOperators": [ 115 | "=", 116 | ",", 117 | "+", 118 | "-", 119 | "/", 120 | "*", 121 | "==", 122 | "===", 123 | "!=", 124 | "!==", 125 | "<", 126 | ">", 127 | "<=", 128 | ">=", 129 | "%" 130 | ], 131 | 132 | "requireSpaceAfterKeywords": [ 133 | "if", 134 | "else", 135 | "for", 136 | "while", 137 | "do", 138 | "switch", 139 | "case", 140 | "return", 141 | "try", 142 | "catch", 143 | "finally", 144 | "typeof" 145 | ], 146 | 147 | "requireSpaceAfterLineComment": true, 148 | 149 | "requireSpaceBeforeBinaryOperators": [ 150 | "=", 151 | "+", 152 | "-", 153 | "/", 154 | "*", 155 | "==", 156 | "===", 157 | "!=", 158 | "!==", 159 | "<", 160 | ">", 161 | "<=", 162 | ">=", 163 | "%" 164 | ], 165 | 166 | "requireSpaceBeforeBlockStatements": true, 167 | 168 | "requireSpaceBeforeKeywords": [ 169 | "else", 170 | "while", 171 | "catch", 172 | "finally" 173 | ], 174 | 175 | "requireSpaceBeforeObjectValues": true, 176 | 177 | "requireSpaceBetweenArguments": true, 178 | 179 | "requireSpacesInConditionalExpression": { 180 | "afterTest": true, 181 | "beforeConsequent": true, 182 | "afterConsequent": true, 183 | "beforeAlternate": true 184 | }, 185 | 186 | "requireSpacesInForStatement": true, 187 | 188 | "requireSpacesInFunction": { 189 | "beforeOpeningCurlyBrace": true 190 | }, 191 | 192 | "requireSpacesInFunctionDeclaration": { 193 | "beforeOpeningCurlyBrace": true 194 | }, 195 | 196 | "requireSpacesInFunctionExpression": { 197 | "beforeOpeningCurlyBrace": true 198 | }, 199 | 200 | "requireSpacesInNamedFunctionExpression": { 201 | "beforeOpeningCurlyBrace": true 202 | }, 203 | 204 | "requireSemicolons": true, 205 | 206 | "requireSpacesInsideObjectBrackets": "all", 207 | 208 | "validateIndentation": 2, 209 | 210 | "validateLineBreaks": "LF", 211 | 212 | "validateParameterSeparator": ", ", 213 | 214 | "validateQuoteMarks": { "mark": "'", "escape": true } 215 | } 216 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![NPM version](https://img.shields.io/npm/v/open-in-editor.svg)](https://www.npmjs.com/package/open-in-editor) 2 | 3 | NPM package to open a file in editor. 4 | 5 | Supported editors: 6 | 7 | - [Sublime Text](http://www.sublimetext.com/) 8 | - [Atom Editor](https://atom.io/) 9 | - [Visual Studio Code](https://code.visualstudio.com/) 10 | - [WebStorm](https://www.jetbrains.com/webstorm/) 11 | - [PhpStorm](https://www.jetbrains.com/phpstorm/) 12 | - [IDEA 14 Community Edition](https://www.jetbrains.com/idea/download/) 13 | - [Vim](http://www.vim.org/) 14 | - [Emacs](https://www.gnu.org/software/emacs/) 15 | - [Visual Studio](https://www.visualstudio.com/) 16 | 17 | You also can use any other editor that is able to open files from command line. 18 | 19 | ## Installation 20 | 21 | ``` 22 | npm install open-in-editor 23 | ``` 24 | 25 | ## Usage 26 | 27 | First of all you should create an interface with your settings. 28 | 29 | ```js 30 | var openInEditor = require('open-in-editor'); 31 | var editor = openInEditor.configure({ 32 | // options 33 | }, function(err) { 34 | console.error('Something went wrong: ' + err); 35 | }); 36 | ``` 37 | 38 | Resulting object has a single method `open`. This method runs terminal command that opens an editor. Result of this method is a promise: 39 | 40 | ```js 41 | editor.open('path/to/file.js:3:10') 42 | .then(function() { 43 | console.log('Success!'); 44 | }, function(err) { 45 | console.error('Something went wrong: ' + err); 46 | }); 47 | ``` 48 | 49 | ## API 50 | 51 | ``` 52 | openInEditor.configure([options][, failCallback]); 53 | ``` 54 | 55 | Arguments: 56 | 57 | - `options` – *optional* is used to set up a command to launch an editor. If no options set it will try to get the command from [environment](#environment) 58 | - `failCallback` – *optional* function that is called when something's wrong with editor setup. 59 | 60 | If editor setup was successful `configure` method returns an interface with single method `open`. The method accepts file reference with the following format: `filename[:line[:column]]`, where `line` and `column` tell the editor where to place cursor when file is opened. 61 | 62 | ### Options 63 | 64 | #### editor 65 | 66 | Type: `String` or `null` 67 | Values: `'sublime'`, `'atom'`, `'code'`, `'webstorm'`, `'phpstorm'`, `'idea14ce'`, `'vim'`, `'emacs'`, `'visualstudio'` 68 | Default: `null` 69 | 70 | Editor to open a file. Once value is set, we try to detect a command to launch an editor. 71 | 72 | Supported editors: 73 | 74 | - `sublime` – Sublime Text 75 | - `atom` – Atom Editor 76 | - `code` – Visual Studio Code 77 | - `webstorm` – WebStorm 78 | - `phpstorm` - PhpStorm 79 | - `idea14ce` – IDEA 14 CE 80 | - `vim` – Vim (via Terminal, Mac OS only) 81 | - `emacs` – Emacs (via Terminal, Mac OS only) 82 | - `visualstudio` – Visual Studio 83 | 84 | #### cmd 85 | 86 | Type: `String` or `null` 87 | Default: `null` 88 | 89 | Command to launch an editor. 90 | 91 | ```js 92 | var openInEditor = require('open-in-editor'); 93 | var editor = openInEditor.configure({ 94 | cmd: '/path/to/editor/app' 95 | }); 96 | ``` 97 | 98 | If `editor` option is also set, an editor settings are using as default settings. 99 | 100 | ```js 101 | var openInEditor = require('open-in-editor'); 102 | var editor = openInEditor.configure({ 103 | editor: 'code', 104 | cmd: '/path/to/editor/app' // will be called as '/path/to/editor/app -r -g {filename}:{line}:{column}' 105 | }); 106 | ``` 107 | 108 | #### pattern 109 | 110 | Type: `String` or `null` 111 | Default: `null` 112 | 113 | Option to specify arguments for a command. Pattern can contain placeholders to be replaced by actual values. Supported placeholders: `filename`, `line` and `column`. 114 | 115 | ```js 116 | var openInEditor = require('open-in-editor'); 117 | var editor = openInEditor.configure({ 118 | cmd: 'code', 119 | pattern: '-r -g {filename}:{line}:{column}' 120 | }); 121 | ``` 122 | 123 | If there's no `{filename}` placeholder in the command then `{filename}:{line}:{column}` is appended. That way previous example can be simplified: 124 | 125 | ```js 126 | var openInEditor = require('open-in-editor'); 127 | var editor = openInEditor.configure({ 128 | cmd: 'code', 129 | pattern: '-r -g' // the same as '-r -g {filename}:{line}:{column}' 130 | }); 131 | ``` 132 | 133 | #### line 134 | 135 | Type: `Number` 136 | Default: `1` 137 | 138 | Defines the number of the first line in the editor. Usually it's `1`, but you can set it to `0`. 139 | 140 | #### column 141 | 142 | Type: `Number` 143 | Default: `1` 144 | 145 | Defines the number of the first column in the editor. Usually it's `1`, but you can set it to `0`. 146 | 147 | 148 | ## Environment 149 | 150 | If no `editor` or `cmd` option is specified, we try to get the command to launch an editor using environment settings. Following values can be used (in descending priority): 151 | 152 | - `process.env.OPEN_FILE` 153 | - `process.env.VISUAL` 154 | - `process.env.EDITOR` 155 | 156 | First value found is used. If it's `process.env.VISUAL` or `process.env.EDITOR`, it's used directly as `cmd` option. But `process.env.OPEN_FILE` is different: if value is a valid for `editor` option, it's used for it, otherwise it's used as a value for `cmd` option. 157 | 158 | You can set env settings per command: 159 | 160 | ``` 161 | OPEN_FILE=atom oe path/to/file.js:4:15 162 | OPEN_FILE="code -r -g" node script.js 163 | ``` 164 | 165 | ## CLI 166 | 167 | Package could be installed globally. 168 | 169 | ``` 170 | npm install open-in-editor -g 171 | ``` 172 | 173 | In this case `oe` command will be available in terminal. 174 | 175 | ``` 176 | Usage: 177 | 178 | oe [filename] [options] 179 | 180 | Options: 181 | 182 | --cmd Command to open file 183 | --debug Debug errors 184 | -e, --editor Editor: atom, code, sublime, webstorm, phpstorm, idea14ce, vim, visualstudio, emacs 185 | -f, --file File to open 186 | -h, --help Output usage information 187 | -p, --pattern Filename pattern and args, i.e. something going after cmd 188 | -v, --version Output the version 189 | ``` 190 | 191 | ## Related projects 192 | 193 | - [express-open-in-editor](https://github.com/lahmatiy/express-open-in-editor) – `Express` extension to open files from browser. 194 | - [babel-plugin-source-wrapper](https://github.com/restrry/babel-plugin-source-wrapper) – `Babel` plugin that instruments source code to associate objects with location they defined in code base. 195 | - [Component Inspector](https://github.com/lahmatiy/component-inspector) – developer tool to inspect components that can open component creation source location in editor. Has integrations for `React`, `Backbone` and can be adopted for other frameworks. 196 | 197 | ## License 198 | 199 | MIT 200 | --------------------------------------------------------------------------------