UNPKG

2.31 kBJavaScriptView Raw
1import process from 'node:process';
2import execa from 'execa';
3import {getEditor, defaultEditor} from 'env-editor';
4import {parseLineColumnPath, stringifyLineColumnPath} from 'line-column-path';
5import open from 'open';
6
7export function getEditorInfo(files, options = {}) {
8 if (!Array.isArray(files)) {
9 throw new TypeError(`Expected an \`Array\`, got ${typeof files}`);
10 }
11
12 const editor = options.editor ? getEditor(options.editor) : defaultEditor();
13 const editorArguments = [];
14
15 if (['vscode', 'vscodium'].includes(editor.id)) {
16 editorArguments.push('--goto');
17 }
18
19 for (const file of files) {
20 const parsed = parseLineColumnPath(file);
21
22 if (['sublime', 'atom', 'vscode', 'vscodium'].includes(editor.id)) {
23 editorArguments.push(stringifyLineColumnPath(parsed));
24
25 if (options.wait) {
26 editorArguments.push('--wait');
27 }
28
29 continue;
30 }
31
32 if (['webstorm', 'intellij'].includes(editor.id)) {
33 editorArguments.push(stringifyLineColumnPath(parsed, {column: false}));
34
35 if (options.wait) {
36 editorArguments.push('--wait');
37 }
38
39 continue;
40 }
41
42 if (editor.id === 'textmate') {
43 editorArguments.push(
44 '--line',
45 stringifyLineColumnPath(parsed, {
46 file: false,
47 }),
48 parsed.file,
49 );
50
51 if (options.wait) {
52 editorArguments.push('--wait');
53 }
54
55 continue;
56 }
57
58 if (['vim', 'neovim'].includes(editor.id)) {
59 editorArguments.push(
60 `+call cursor(${parsed.line}, ${parsed.column})`,
61 parsed.file,
62 );
63
64 continue;
65 }
66
67 editorArguments.push(parsed.file);
68 }
69
70 return {
71 binary: editor.binary,
72 arguments: editorArguments,
73 isTerminalEditor: editor.isTerminalEditor,
74 };
75}
76
77export default async function openEditor(files, options = {}) {
78 const result = getEditorInfo(files, options);
79 const stdio = result.isTerminalEditor ? 'inherit' : 'ignore';
80
81 const subprocess = execa(result.binary, result.arguments, {
82 detached: true,
83 stdio,
84 });
85
86 // Fallback
87 subprocess.on('error', () => {
88 const result = getEditorInfo(files, {
89 ...options,
90 editor: '',
91 });
92
93 for (const file of result.arguments) {
94 open(file);
95 }
96 });
97
98 if (options.wait) {
99 return new Promise(resolve => {
100 subprocess.on('exit', resolve);
101 });
102 }
103
104 if (result.isTerminalEditor) {
105 subprocess.on('exit', process.exit);
106 } else {
107 subprocess.unref();
108 }
109}