Repository: lahmatiy/open-in-editor Branch: master Commit: 64cddf8d5ae7 Files: 27 Total size: 28.1 KB Directory structure: gitextract_ejkaplpq/ ├── .editorconfig ├── .gitignore ├── .jscsrc ├── .npmingnore ├── HISTORY.md ├── LICENSE ├── README.md ├── bin/ │ └── oe ├── lib/ │ ├── check.js │ ├── detect.js │ ├── editors/ │ │ ├── atom.js │ │ ├── code.js │ │ ├── common/ │ │ │ ├── jetbrains.js │ │ │ └── terminal.js │ │ ├── emacs.js │ │ ├── idea14ce.js │ │ ├── index.js │ │ ├── phpstorm.js │ │ ├── sublime.js │ │ ├── vim.js │ │ ├── visualstudio.js │ │ ├── visualstudio.vbs │ │ └── webstorm.js │ ├── index.js │ ├── open.js │ └── utils.js └── package.json ================================================ FILE CONTENTS ================================================ ================================================ FILE: .editorconfig ================================================ [*] end_of_line = lf [*.js] charset = utf-8 indent_style = space indent_size = 2 ================================================ FILE: .gitignore ================================================ node_modules *.swp ================================================ FILE: .jscsrc ================================================ { "excludeFiles": [ "node_modules/**" ], "disallowEmptyBlocks": true, "disallowImplicitTypeConversion": ["numeric", "boolean", "binary", "string"], "disallowKeywords": ["with"], "disallowKeywordsOnNewLine": ["else", "catch", "finally"], "disallowMixedSpacesAndTabs": true, "disallowMultipleLineStrings": true, "disallowNewlineBeforeBlockStatements": true, "disallowOperatorBeforeLineBreak": ["."], "disallowPaddingNewlinesInBlocks": true, "disallowQuotedKeysInObjects": "allButReserved", "disallowSpaceAfterObjectKeys": true, "disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"], "disallowSpaceBeforePostfixUnaryOperators": ["++", "--"], "disallowSpacesInCallExpression": true, "disallowSpacesInFunction": { "beforeOpeningRoundBrace": true }, "disallowSpacesInFunctionDeclaration": { "beforeOpeningRoundBrace": true }, "disallowSpacesInFunctionExpression": { "beforeOpeningRoundBrace": true }, "disallowSpacesInNamedFunctionExpression": { "beforeOpeningRoundBrace": true }, "disallowSpacesInsideArrayBrackets": "all", "disallowSpacesInsideParentheses": true, "disallowTrailingComma": true, "disallowTrailingWhitespace": true, "disallowYodaConditions": true, "requireBlocksOnNewline": true, "requireCamelCaseOrUpperCaseIdentifiers": true, "requireCapitalizedConstructors": true, "requireCommaBeforeLineBreak": true, "requireCurlyBraces": [ "if", "else", "for", "while", "do", "try", "catch", "finally" ], "requireDotNotation": true, "requireKeywordsOnNewLine": [ "return", "for", "try", "do", "switch", "case" ], "requireLineBreakAfterVariableAssignment": true, "requireLineFeedAtFileEnd": true, "disallowMultipleVarDecl": true, "requireOperatorBeforeLineBreak": [ "=", "+", "-", "/", "*", "==", "===", "!=", "!==", ">", ">=", "<", "<=" ], "requireParenthesesAroundIIFE": true, "requireSpaceAfterBinaryOperators": [ "=", ",", "+", "-", "/", "*", "==", "===", "!=", "!==", "<", ">", "<=", ">=", "%" ], "requireSpaceAfterKeywords": [ "if", "else", "for", "while", "do", "switch", "case", "return", "try", "catch", "finally", "typeof" ], "requireSpaceAfterLineComment": true, "requireSpaceBeforeBinaryOperators": [ "=", "+", "-", "/", "*", "==", "===", "!=", "!==", "<", ">", "<=", ">=", "%" ], "requireSpaceBeforeBlockStatements": true, "requireSpaceBeforeKeywords": [ "else", "while", "catch", "finally" ], "requireSpaceBeforeObjectValues": true, "requireSpaceBetweenArguments": true, "requireSpacesInConditionalExpression": { "afterTest": true, "beforeConsequent": true, "afterConsequent": true, "beforeAlternate": true }, "requireSpacesInForStatement": true, "requireSpacesInFunction": { "beforeOpeningCurlyBrace": true }, "requireSpacesInFunctionDeclaration": { "beforeOpeningCurlyBrace": true }, "requireSpacesInFunctionExpression": { "beforeOpeningCurlyBrace": true }, "requireSpacesInNamedFunctionExpression": { "beforeOpeningCurlyBrace": true }, "requireSemicolons": true, "requireSpacesInsideObjectBrackets": "all", "validateIndentation": 2, "validateLineBreaks": "LF", "validateParameterSeparator": ", ", "validateQuoteMarks": { "mark": "'", "escape": true } } ================================================ FILE: .npmingnore ================================================ node_modules ================================================ FILE: HISTORY.md ================================================ ## 2.2.0 (March 22, 2017) - Fixed passing settings to `open()` when only `cmd` option is set (#10) - Changed behaviour to use an editor settings as defaults when `editor` and `cmd` options are specified - Added `--pattern` option to CLI ## 2.1.0 (March 21, 2017) - Added basic support for `emacs` (thanks to @zefirka) - Fixed crash on attempt to use `vim` on non-`darwin` platform ## 2.0.0 (March 15, 2017) - Added basic support for `vim` (thanks to @pofigizm) - Added support for `Visual Studio` (thanks to @generalov) - Changed node.js support to `0.12` and greater ## 1.2.1 (November 14, 2016) - Added support for `Visual Studio Code` ## 1.2.0 (November 12, 2015) - Added support for JetBrains's IDEs on Windows (thanks to @Mavrin) ## 1.1.0 (November 8, 2015) - Added support for `WebStorm` (thanks to @chicoxyzzy) - Added support for `IDEA 14 CE` (thanks to @chicoxyzzy) - Added support for `PhpStorm` (thanks to @silentroach) - Removed `preferGlobal` option from `package.json` - Improved documentation ## 1.0 (September 24, 2015) - Initial release ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2015 Roman Dvornov Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ================================================ FILE: README.md ================================================ [![NPM version](https://img.shields.io/npm/v/open-in-editor.svg)](https://www.npmjs.com/package/open-in-editor) NPM package to open a file in editor. Supported editors: - [Sublime Text](http://www.sublimetext.com/) - [Atom Editor](https://atom.io/) - [Visual Studio Code](https://code.visualstudio.com/) - [WebStorm](https://www.jetbrains.com/webstorm/) - [PhpStorm](https://www.jetbrains.com/phpstorm/) - [IDEA 14 Community Edition](https://www.jetbrains.com/idea/download/) - [Vim](http://www.vim.org/) - [Emacs](https://www.gnu.org/software/emacs/) - [Visual Studio](https://www.visualstudio.com/) You also can use any other editor that is able to open files from command line. ## Installation ``` npm install open-in-editor ``` ## Usage First of all you should create an interface with your settings. ```js var openInEditor = require('open-in-editor'); var editor = openInEditor.configure({ // options }, function(err) { console.error('Something went wrong: ' + err); }); ``` Resulting object has a single method `open`. This method runs terminal command that opens an editor. Result of this method is a promise: ```js editor.open('path/to/file.js:3:10') .then(function() { console.log('Success!'); }, function(err) { console.error('Something went wrong: ' + err); }); ``` ## API ``` openInEditor.configure([options][, failCallback]); ``` Arguments: - `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) - `failCallback` – *optional* function that is called when something's wrong with editor setup. 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. ### Options #### editor Type: `String` or `null` Values: `'sublime'`, `'atom'`, `'code'`, `'webstorm'`, `'phpstorm'`, `'idea14ce'`, `'vim'`, `'emacs'`, `'visualstudio'` Default: `null` Editor to open a file. Once value is set, we try to detect a command to launch an editor. Supported editors: - `sublime` – Sublime Text - `atom` – Atom Editor - `code` – Visual Studio Code - `webstorm` – WebStorm - `phpstorm` - PhpStorm - `idea14ce` – IDEA 14 CE - `vim` – Vim (via Terminal, Mac OS only) - `emacs` – Emacs (via Terminal, Mac OS only) - `visualstudio` – Visual Studio #### cmd Type: `String` or `null` Default: `null` Command to launch an editor. ```js var openInEditor = require('open-in-editor'); var editor = openInEditor.configure({ cmd: '/path/to/editor/app' }); ``` If `editor` option is also set, an editor settings are using as default settings. ```js var openInEditor = require('open-in-editor'); var editor = openInEditor.configure({ editor: 'code', cmd: '/path/to/editor/app' // will be called as '/path/to/editor/app -r -g {filename}:{line}:{column}' }); ``` #### pattern Type: `String` or `null` Default: `null` Option to specify arguments for a command. Pattern can contain placeholders to be replaced by actual values. Supported placeholders: `filename`, `line` and `column`. ```js var openInEditor = require('open-in-editor'); var editor = openInEditor.configure({ cmd: 'code', pattern: '-r -g {filename}:{line}:{column}' }); ``` If there's no `{filename}` placeholder in the command then `{filename}:{line}:{column}` is appended. That way previous example can be simplified: ```js var openInEditor = require('open-in-editor'); var editor = openInEditor.configure({ cmd: 'code', pattern: '-r -g' // the same as '-r -g {filename}:{line}:{column}' }); ``` #### line Type: `Number` Default: `1` Defines the number of the first line in the editor. Usually it's `1`, but you can set it to `0`. #### column Type: `Number` Default: `1` Defines the number of the first column in the editor. Usually it's `1`, but you can set it to `0`. ## Environment 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): - `process.env.OPEN_FILE` - `process.env.VISUAL` - `process.env.EDITOR` 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. You can set env settings per command: ``` OPEN_FILE=atom oe path/to/file.js:4:15 OPEN_FILE="code -r -g" node script.js ``` ## CLI Package could be installed globally. ``` npm install open-in-editor -g ``` In this case `oe` command will be available in terminal. ``` Usage: oe [filename] [options] Options: --cmd Command to open file --debug Debug errors -e, --editor Editor: atom, code, sublime, webstorm, phpstorm, idea14ce, vim, visualstudio, emacs -f, --file File to open -h, --help Output usage information -p, --pattern Filename pattern and args, i.e. something going after cmd -v, --version Output the version ``` ## Related projects - [express-open-in-editor](https://github.com/lahmatiy/express-open-in-editor) – `Express` extension to open files from browser. - [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. - [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. ## License MIT ================================================ FILE: bin/oe ================================================ #!/usr/bin/env node var clap = require('clap'); var version = require('../package.json').version; var editors = require('../lib/editors'); var fail = require('../lib/utils').fail; var main = require('../lib/index'); var command = clap.create('oe', '[filename]') .description('Open file in editor') .version(version) .option('-f, --file ', 'File to open') .option('-e, --editor ', 'Editor: ' + Object.keys(editors).join(', ')) .option('-p, --pattern ', 'Filename pattern and args, i.e. something going after cmd') .option('--cmd ', 'Command to open file') .option('--debug', 'Debug errors') .action(function(args) { main .configure(this.values, fail) .open(this.values.file || args[0]) .catch(function(err) { if (this.values.debug) { process.nextTick(function() { throw err; }); } else { fail(err); } }.bind(this)); }); try { command.run(); } catch (err) { if (err instanceof clap.Error == false) { throw err; } fail(err); } ================================================ FILE: lib/check.js ================================================ var exec = require('child_process').exec; var fs = require('fs'); var quote = require('./utils').quote; function checkCommand(cmd, name, args) { if (!args) { return Promise.reject('No args to check command: ' + cmd); } return new Promise(function(resolve, reject) { exec(cmd + ' ' + args, function(err, output) { if (err || output.indexOf(name) !== 0) { reject(err); } else { resolve(cmd); } }); }); } function checkPath(path, name) { if (!fs.existsSync(path)) { return Promise.reject('Path does not exist: ' + path); } return Promise.resolve(path); } module.exports = { command: checkCommand, path: checkPath }; ================================================ FILE: lib/detect.js ================================================ var check = require('./check'); var any = require('./utils').any; function detect(name, commands, args, locations) { function run(task) { return this(task, name, args); } locations = locations[process.platform] || []; return any( [].concat( commands.map(run, check.command), locations.map(run, check.path) ), 'Not detected' ); } module.exports = detect; module.exports.lazy = function(name, commands, args, locations) { var memo; return function() { if (!memo) { memo = detect(name, commands, args, locations); } return memo; }; }; module.exports.platformSupport = function(platforms, editor, resolveValue) { return function() { // we use only system parts so we haven't to check anything except os if (platforms.indexOf(process.platform) !== -1) { return Promise.resolve(resolveValue); } return Promise.reject('"Open in ' + editor + '" does not implemented for your platform (' + process.platform + ')'); }; }; ================================================ FILE: lib/editors/atom.js ================================================ var atHomeDir = require('../utils').atHomeDir; var settings = { pattern: '{filename}:{line}:{column}' }; var detect = require('../detect').lazy('Atom Editor', ['atom'], '-h', { darwin: [ '/Applications/Atom.app/Contents/Resources/app/atom.sh' ], win32: [ atHomeDir('AppData/Local/atom/bin/atom.cmd') ] }); var open = require('../open').detectAndOpenFactory(detect, settings); module.exports = { settings: settings, detect: detect, open: open }; ================================================ FILE: lib/editors/code.js ================================================ var atHomeDir = require('../utils').atHomeDir; var settings = { pattern: '-r -g {filename}:{line}:{column}' }; var detect = require('../detect').lazy('Visual Studio Code', ['code'], '-h', { darwin: [ '/Applications/Visual Studio Code.app/Contents/MacOS/Electron' ], win32: [ 'C:/Program Files/Microsoft VS Code/bin/code.cmd', 'C:/Program Files (x86)/Microsoft VS Code/bin/code.cmd', atHomeDir('AppData/Local/Code/bin/code.cmd') ] }); var open = require('../open').detectAndOpenFactory(detect, settings); module.exports = { settings: settings, detect: detect, open: open }; ================================================ FILE: lib/editors/common/jetbrains.js ================================================ var fs = require('fs'); var path = require('path'); var lazyDetect = require('../../detect').lazy; var settings = { pattern: '{projectPath} --line {line} {filename}' }; var winDirs = (function() { var jetbrainsFolder = 'c:/Program Files (x86)/JetBrains/'; if (!fs.existsSync(jetbrainsFolder)) { return []; } return fs.readdirSync(jetbrainsFolder) .map(function(name) { return path.join(jetbrainsFolder, name); }) .filter(function(path) { return fs.statSync(path).isDirectory(); }); })(); module.exports = function(config) { var detect = lazyDetect(config.name, [], '', { darwin: [ '/Applications/' + config.appFolder + '.app/Contents/MacOS/' + config.executable ], win32: winDirs.map(function(dir) { return dir + '/bin/' + config.executable + '.exe'; }) }); var open = require('../../open').detectAndOpenFactory(detect, settings); return { settings: settings, detect: detect, open: open }; }; ================================================ FILE: lib/editors/common/terminal.js ================================================ var osascript = function(script) { return 'osascript -e \'' + script + '\''; }; var terminal = function(cmd) { return 'tell application "Terminal" to do script "' + cmd + '"'; }; var runInTerminal = function(cmd) { return osascript(terminal('cd {projectPath}; ' + cmd)); }; module.exports = runInTerminal; ================================================ FILE: lib/editors/emacs.js ================================================ var runInTerminal = require('./common/terminal'); var settings = { patternOnly: true, escapeQuotes: true, pattern: runInTerminal('emacs --no-splash \\"+{line}:{column}\\" {filename}') }; var detect = require('../detect').platformSupport(['darwin'], 'vim'); var open = require('../open').detectAndOpenFactory(detect, settings); module.exports = { settings: settings, detect: detect, open: open }; ================================================ FILE: lib/editors/idea14ce.js ================================================ var jetbrainsEditor = require('./common/jetbrains'); module.exports = jetbrainsEditor({ name: 'IDEA 14 CE', appFolder: 'IntelliJ IDEA 14 CE', executable: 'idea' }); ================================================ FILE: lib/editors/index.js ================================================ module.exports = { atom: require('./atom'), code: require('./code'), sublime: require('./sublime'), webstorm: require('./webstorm'), phpstorm: require('./phpstorm'), idea14ce: require('./idea14ce'), vim: require('./vim'), visualstudio: require('./visualstudio'), emacs: require('./emacs') }; ================================================ FILE: lib/editors/phpstorm.js ================================================ var jetbrainsEditor = require('./common/jetbrains'); module.exports = jetbrainsEditor({ name: 'PhpStorm IDE', appFolder: 'PhpStorm', executable: 'phpstorm' }); ================================================ FILE: lib/editors/sublime.js ================================================ var settings = { pattern: '{filename}:{line}:{column}' }; var detect = require('../detect').lazy('Sublime Text', ['subl'], '-h', { darwin: [ '/Applications/Sublime Text.app/Contents/SharedSupport/bin/subl' ], win32: [ 'C:/Program Files/Sublime Text/subl.exe', 'C:/Program Files/Sublime Text 2/subl.exe', 'C:/Program Files/Sublime Text 3/subl.exe', 'C:/Program Files (x86)/Sublime Text/subl.exe', 'C:/Program Files (x86)/Sublime Text 2/subl.exe', 'C:/Program Files (x86)/Sublime Text 3/subl.exe' ] }); var open = require('../open').detectAndOpenFactory(detect, settings); module.exports = { settings: settings, detect: detect, open: open }; ================================================ FILE: lib/editors/vim.js ================================================ var runInTerminal = require('./common/terminal'); var settings = { patternOnly: true, escapeQuotes: true, pattern: runInTerminal('vim {filename} \\"+call cursor({line}, {column})\\"') }; var detect = require('../detect').platformSupport(['darwin'], 'vim'); var open = require('../open').detectAndOpenFactory(detect, settings); module.exports = { settings: settings, detect: detect, open: open }; ================================================ FILE: lib/editors/visualstudio.js ================================================ var path = require('path'); var helperPath = path.resolve(__dirname, 'visualstudio.vbs'); var settings = { pattern: '{filename} {line} {column}' }; var detect = require('../detect').platformSupport(['win32'], 'Visual Studio', helperPath); var open = require('../open').detectAndOpenFactory(detect, settings); module.exports = { settings: settings, detect: detect, open: open }; ================================================ FILE: lib/editors/visualstudio.vbs ================================================ ' Copyright (c) 2016, Evgeny Panasyuk ' Permission is hereby granted, free of charge, to any person or organization ' obtaining a copy of the software and accompanying documentation covered by ' this license (the "Software") to use, reproduce, display, distribute, ' execute, and transmit the Software, and to prepare derivative works of the ' Software, and to permit third-parties to whom the Software is furnished to ' do so, all subject to the following: ' ' The copyright notices in the Software and this entire statement, including ' the above license grant, this restriction and the following disclaimer, ' must be included in all copies of the Software, in whole or in part, and ' all derivative works of the Software, unless such copies or derivative ' works are solely in the form of machine-executable object code generated by ' a source language processor. ' ' THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR ' IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, ' FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT ' SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE ' FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, ' ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER ' DEALINGS IN THE SOFTWARE. ' e-mail: E?????[dot]P???????[at]gmail.??? Option Explicit Dim filename, line, column Dim MSVS_versions, version Dim dte, fso, wshShell Dim fullpath filename = WScript.Arguments(0) line = WScript.Arguments(1) column = WScript.Arguments(2) MSVS_versions = Array _ ( _ "VisualStudio.DTE.7", _ "VisualStudio.DTE.7.1", _ "VisualStudio.DTE.8.0", _ "VisualStudio.DTE.9.0", _ "VisualStudio.DTE.10.0", _ "VisualStudio.DTE.11.0", _ "VisualStudio.DTE.12.0", _ "VisualStudio.DTE.14.0", _ "VisualStudio.DTE.15.0" _ ) On Error Resume Next For each version in MSVS_versions Err.Clear Set dte = getObject(,version) If Err.Number = 0 Then Exit For End If Next If Err.Number <> 0 Then Set dte = WScript.CreateObject("VisualStudio.DTE") Err.Clear End If Set wshShell = WScript.CreateObject("WScript.Shell") Set fso = WScript.CreateObject("Scripting.FileSystemObject") fullpath = fso.GetAbsolutePathName(filename) dte.MainWindow.Activate() dte.MainWindow.Visible = True dte.UserControl = True wshShell.AppActivate dte.MainWindow.Caption dte.ItemOperations.OpenFile fullpath dte.ActiveDocument.Selection.MoveToLineAndOffset line, column + 1 if Err.Number <> 0 Then WScript.Quit Err.Number End If On Error Goto 0 ================================================ FILE: lib/editors/webstorm.js ================================================ var jetbrainsEditor = require('./common/jetbrains'); module.exports = jetbrainsEditor({ name: 'WebStorm IDE', appFolder: 'WebStorm', executable: 'webstorm' }); ================================================ FILE: lib/index.js ================================================ var extractFilename = require('./utils').extractFilename; var number = require('./utils').number; var assign = require('./utils').assign; var editors = require('./editors'); var openFactory = require('./open').factory; module.exports = { configure: function(options, cb) { options = options || {}; cb = cb || function() {}; var sourceLineOffset = number(options.line, 1); var sourceColumnOffset = number(options.column, 1); var editor = options.editor; var cmd = options.cmd; var open; if (!cmd && !editor) { if (editors.hasOwnProperty(process.env.OPEN_FILE)) { editor = process.env.OPEN_FILE; } else { cmd = process.env.OPEN_FILE || process.env.VISUAL || process.env.EDITOR; } } // if editor option is set then fail on wrong value if (editor && !editors.hasOwnProperty(editor)) { cb('Wrong value for `editor` option: ' + editor); return; } if (cmd) { var settings = {}; // use editor settings as base if (editors.hasOwnProperty(editor)) { assign(settings, editors[editor].settings); } open = openFactory(cmd, assign(settings, options)); } else { if (!editor) { cb('Editor is not specified'); return; } open = editors[editor].open; } return { open: function(filename) { if (!filename) { return Promise.reject('File is not specified'); } var info = extractFilename(filename); return open([ info.filename, Math.max(info.line - sourceLineOffset, 0), Math.max(info.column - sourceColumnOffset, 0) ].join(':')); } }; } }; ================================================ FILE: lib/open.js ================================================ var exec = require('child_process').exec; var number = require('./utils').number; var quote = require('./utils').quote; var extractFilename = require('./utils').extractFilename; var append = require('./utils').append; function makeArguments(filename, settings) { var info = extractFilename(filename); var pattern = settings.pattern || ''; var values = { projectPath: process.env.PROJECT_PATH || process.PWD || process.cwd(), line: info.line + number(settings.line, 1), column: info.column + number(settings.column, 1) }; if (!/\{filename\}/.test(pattern)) { pattern = append(pattern, '{filename}:{line}:{column}'); } return pattern .replace( new RegExp('\\{(' + Object.keys(values).join('|') + ')\\}', 'g'), function(m, name) { return values[name]; } ) // replace `{filename}` and adjoined right string for quoted filename, // since filename can have spaces // // {filename} --line 1 --column 2 // => "filename" --line 1 --column 2 // // {filename}:1:2 // => "filename:1:2" // .replace(/\{filename\}(\S*)/, function(m, rest) { return quote(info.filename + rest, settings.escapeQuotes); }); } function open(cmd, filename, settings) { return new Promise(function(resolve, reject) { var args; settings = settings || {}; args = makeArguments(filename, settings); cmd = settings.patternOnly ? args : append(quote(cmd), args); exec(cmd, function(err) { if (err) { reject(err); } else { resolve(); } }); }); } module.exports = open; module.exports.factory = function(cmd, settings) { return function openInEditor(filename) { return open(cmd, filename, settings); }; }; module.exports.detectAndOpenFactory = function(detect, settings) { return function openInEditor(filename) { return detect().then(function(cmd) { open(cmd, filename, settings); }); }; }; ================================================ FILE: lib/utils.js ================================================ var osHomeDir = require('os-homedir')(); var path = require('path'); module.exports = { number: function(value, fallback) { return isNaN(value) ? fallback : value; }, quote: function(value, escapeQuotes) { value = String(value) .replace(/\\/g, '\\\\') .replace(/"/g, '\"'); return escapeQuotes ? '\\"' + value + '\\"' : '"' + value + '"'; }, extractFilename: function(filename) { var parts = filename.match(/^(.+?)((?::\d+){0,4})$/); var segment = parts[2].split(':').slice(1); return { filename: parts[1], line: parseInt(segment[0] || 0, 10), column: parseInt(segment[1] || 0, 10) }; }, fail: function(msg) { console.error(String(msg).trimRight()); process.exit(2); }, atHomeDir: function(filename) { return path.join(osHomeDir, filename); }, any: function(promises, err) { return new Promise(function(resolve, reject) { Promise.all(promises.map(function(item) { if (item && typeof item.then == 'function') { return item.then( resolve, // any success resolves the main promise immediately function() { /* ignore any reject */ } ); } return item; })).then(function(results) { reject(err); }, reject); }); }, append: function(str, appendix) { return String(str).replace(/\s*$/, (str ? ' ' : '') + appendix); }, assign: function(dest, src) { for (var key in src) { if (Object.prototype.hasOwnProperty.call(src, key)) { dest[key] = src[key]; } } return dest; } }; ================================================ FILE: package.json ================================================ { "name": "open-in-editor", "description": "Open file in editor", "version": "2.2.0", "author": "Roman Dvornov ", "license": "MIT", "repository": "lahmatiy/open-in-editor", "keywords": [ "open", "file", "editor", "atom", "code", "vscode", "idea", "phpstorm", "webstorm", "sublime", "visual studio", "vim", "emacs" ], "main": "./lib/index.js", "engines": { "node": ">=0.12.0" }, "bin": { "oe": "./bin/oe" }, "dependencies": { "clap": "^1.1.3", "os-homedir": "~1.0.2" }, "devDependencies": {}, "scripts": {} }