@@ -5,116 +5,82 @@ import {
55 expandTargetPathArgument ,
66 ICustomIntegration ,
77 parseCustomIntegrationArguments ,
8- spawnCustomIntegration ,
98} from '../custom-integration'
109
11- /**
12- * Open a given file or folder in the desired external editor.
13- *
14- * @param fullPath A folder or file path to pass as an argument when launching the editor.
15- * @param editor The external editor to launch.
16- */
17- export async function launchExternalEditor (
18- fullPath : string ,
19- editor : FoundEditor
20- ) : Promise < void > {
21- const editorPath = editor . path
10+ async function launchEditor (
11+ editorPath : string ,
12+ args : readonly string [ ] ,
13+ editorName : string ,
14+ spawnAsDarwinApp : boolean
15+ ) {
2216 const exists = await pathExists ( editorPath )
2317 const label = __DARWIN__ ? 'Settings' : 'Options'
2418 if ( ! exists ) {
2519 throw new ExternalEditorError (
26- `Could not find executable for ' ${ editor . editor } ' at path '${ editor . path } '. Please open ${ label } and select an available editor.` ,
20+ `Could not find executable for ${ editorName } at path '${ editorPath } '. Please open ${ label } and select an available editor.` ,
2721 { openPreferences : true }
2822 )
2923 }
3024
31- const opts : SpawnOptions = {
32- // Make sure the editor processes are detached from the Desktop app.
33- // Otherwise, some editors (like Notepad++) will be killed when the
34- // Desktop app is closed.
35- detached : true ,
36- }
37-
38- try {
39- if ( __DARWIN__ ) {
40- // In macOS we can use `open`, which will open the right executable file
41- // for us, we only need the path to the editor .app folder.
42- spawn ( 'open' , [ '-a' , editorPath , fullPath ] , opts )
43- } else {
44- spawn ( editorPath , [ fullPath ] , opts )
25+ return new Promise < void > ( ( resolve , reject ) => {
26+ const opts : SpawnOptions = {
27+ // Make sure the editor processes are detached from the Desktop app.
28+ // Otherwise, some editors (like Notepad++) will be killed when the
29+ // Desktop app is closed.
30+ detached : true ,
31+ stdio : 'ignore' ,
4532 }
46- } catch ( error ) {
47- log . error ( `Error while launching ${ editor . editor } ` , error )
48- if ( error ?. code === 'EACCES' ) {
49- throw new ExternalEditorError (
50- `GitHub Desktop doesn't have the proper permissions to start '${ editor . editor } '. Please open ${ label } and try another editor.` ,
51- { openPreferences : true }
52- )
53- } else {
54- throw new ExternalEditorError (
55- `Something went wrong while trying to start '${ editor . editor } '. Please open ${ label } and try another editor.` ,
56- { openPreferences : true }
57- )
58- }
59- }
33+
34+ const child = spawnAsDarwinApp
35+ ? spawn ( 'open' , [ '-a' , editorPath , ...args ] , opts )
36+ : spawn ( editorPath , args , opts )
37+
38+ child . on ( 'error' , reject )
39+ child . on ( 'spawn' , resolve )
40+ child . unref ( ) // Don't wait for editor to exit
41+ } ) . catch ( ( e : unknown ) => {
42+ log . error (
43+ `Error while launching ${ editorName } ` ,
44+ e instanceof Error ? e : undefined
45+ )
46+ throw new ExternalEditorError (
47+ e && typeof e === 'object' && 'code' in e && e . code === 'EACCES'
48+ ? `GitHub Desktop doesn't have the proper permissions to start ${ editorName } . Please open ${ label } and try another editor.`
49+ : `Something went wrong while trying to start ${ editorName } . Please open ${ label } and try another editor.` ,
50+ { openPreferences : true }
51+ )
52+ } )
6053}
6154
55+ /**
56+ * Open a given file or folder in the desired external editor.
57+ *
58+ * @param fullPath A folder or file path to pass as an argument when launching the editor.
59+ * @param editor The external editor to launch.
60+ */
61+ export const launchExternalEditor = ( fullPath : string , editor : FoundEditor ) =>
62+ launchEditor ( editor . path , [ fullPath ] , `'${ editor . editor } '` , __DARWIN__ )
63+
6264/**
6365 * Open a given file or folder in the desired custom external editor.
6466 *
6567 * @param fullPath A folder or file path to pass as an argument when launching the editor.
6668 * @param customEditor The external editor to launch.
6769 */
68- export async function launchCustomExternalEditor (
70+ export const launchCustomExternalEditor = (
6971 fullPath : string ,
7072 customEditor : ICustomIntegration
71- ) : Promise < void > {
72- const editorPath = customEditor . path
73- const exists = await pathExists ( editorPath )
74- const label = __DARWIN__ ? 'Settings' : 'Options'
75- if ( ! exists ) {
76- throw new ExternalEditorError (
77- `Could not find executable for custom editor at path '${ customEditor . path } '. Please open ${ label } and select an available editor.` ,
78- { openPreferences : true }
79- )
80- }
81-
82- const opts : SpawnOptions = {
83- // Make sure the editor processes are detached from the Desktop app.
84- // Otherwise, some editors (like Notepad++) will be killed when the
85- // Desktop app is closed.
86- detached : true ,
87- }
88-
73+ ) => {
8974 const argv = parseCustomIntegrationArguments ( customEditor . arguments )
9075
9176 // Replace instances of RepoPathArgument with fullPath in customEditor.arguments
9277 const args = expandTargetPathArgument ( argv , fullPath )
9378
94- try {
95- if ( __DARWIN__ && customEditor . bundleID ) {
96- // In macOS we can use `open` if it's an app (i.e. if we have a bundleID),
97- // which will open the right executable file for us, we only need the path
98- // to the editor .app folder.
99- spawnCustomIntegration ( 'open' , [ '-a' , editorPath , ...args ] , opts )
100- } else {
101- spawnCustomIntegration ( editorPath , args , opts )
102- }
103- } catch ( error ) {
104- log . error (
105- `Error while launching custom editor at path ${ customEditor . path } with arguments ${ args } ` ,
106- error
107- )
108- if ( error ?. code === 'EACCES' ) {
109- throw new ExternalEditorError (
110- `GitHub Desktop doesn't have the proper permissions to start custom editor at path ${ customEditor . path } . Please open ${ label } and try another editor.` ,
111- { openPreferences : true }
112- )
113- } else {
114- throw new ExternalEditorError (
115- `Something went wrong while trying to start custom editor at path ${ customEditor . path } . Please open ${ label } and try another editor.` ,
116- { openPreferences : true }
117- )
118- }
119- }
79+ // In macOS we can use `open` if it's an app (i.e. if we have a bundleID),
80+ // which will open the right executable file for us, we only need the path
81+ // to the editor .app folder.
82+ const spawnAsDarwinApp = __DARWIN__ && customEditor . bundleID !== undefined
83+ const editorName = `custom editor at path '${ customEditor . path } '`
84+
85+ return launchEditor ( customEditor . path , args , editorName , spawnAsDarwinApp )
12086}
0 commit comments