2023-12-18 13:12:25 +08:00
const path = require ( 'path' )
const shellQuote = require ( 'shell-quote' )
const childProcess = require ( 'child_process' )
// 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
const COMMON _EDITORS _OSX = require ( './editor-info/osx' )
const COMMON _EDITORS _LINUX = require ( './editor-info/linux' )
const COMMON _EDITORS _WIN = require ( './editor-info/windows' )
module . exports = function guessEditor ( specifiedEditor ) {
if ( specifiedEditor ) {
return shellQuote . parse ( specifiedEditor )
}
2024-01-16 21:26:16 +08:00
if ( process . env . LAUNCH _EDITOR ) {
return [ process . env . LAUNCH _EDITOR ]
}
if ( process . versions . webcontainer ) {
return [ process . env . EDITOR || 'code' ]
}
2023-12-18 13:12:25 +08:00
// We can find out which editor is currently running by:
// `ps x` on macOS and Linux
// `Get-Process` on Windows
try {
if ( process . platform === 'darwin' ) {
2024-01-16 21:26:16 +08:00
const output = childProcess
. execSync ( 'ps x -o comm=' , {
stdio : [ 'pipe' , 'pipe' , 'ignore' ]
} )
. toString ( )
2023-12-18 13:12:25 +08:00
const processNames = Object . keys ( COMMON _EDITORS _OSX )
2024-01-16 21:26:16 +08:00
const processList = output . split ( '\n' )
2023-12-18 13:12:25 +08:00
for ( let i = 0 ; i < processNames . length ; i ++ ) {
const processName = processNames [ i ]
2024-01-16 21:26:16 +08:00
// Find editor by exact match.
2023-12-18 13:12:25 +08:00
if ( output . indexOf ( processName ) !== - 1 ) {
return [ COMMON _EDITORS _OSX [ processName ] ]
}
2024-01-16 21:26:16 +08:00
const processNameWithoutApplications = processName . replace ( '/Applications' , '' )
// Find editor installation not in /Applications.
if ( output . indexOf ( processNameWithoutApplications ) !== - 1 ) {
// Use the CLI command if one is specified
if ( processName !== COMMON _EDITORS _OSX [ processName ] ) {
return [ COMMON _EDITORS _OSX [ processName ] ]
}
// Use a partial match to find the running process path. If one is found, use the
// existing path since it can be running from anywhere.
const runningProcess = processList . find ( ( procName ) => procName . endsWith ( processNameWithoutApplications ) )
if ( runningProcess !== undefined ) {
return [ runningProcess ]
}
}
2023-12-18 13:12:25 +08:00
}
} else if ( process . platform === 'win32' ) {
const output = childProcess
2024-01-16 21:26:16 +08:00
. execSync (
'powershell -NoProfile -Command "Get-CimInstance -Query \\"select executablepath from win32_process where executablepath is not null\\" | % { $_.ExecutablePath }"' ,
{
stdio : [ 'pipe' , 'pipe' , 'ignore' ]
}
)
2023-12-18 13:12:25 +08:00
. toString ( )
const runningProcesses = output . split ( '\r\n' )
for ( let i = 0 ; i < runningProcesses . length ; i ++ ) {
const fullProcessPath = runningProcesses [ i ] . trim ( )
const shortProcessName = path . basename ( fullProcessPath )
if ( COMMON _EDITORS _WIN . indexOf ( shortProcessName ) !== - 1 ) {
return [ fullProcessPath ]
}
}
} else if ( process . platform === 'linux' ) {
// --no-heading No header line
// x List all processes owned by you
// -o comm Need only names column
const output = childProcess
2024-01-16 21:26:16 +08:00
. execSync ( 'ps x --no-heading -o comm --sort=comm' , {
stdio : [ 'pipe' , 'pipe' , 'ignore' ]
} )
2023-12-18 13:12:25 +08:00
. toString ( )
const processNames = Object . keys ( COMMON _EDITORS _LINUX )
for ( let i = 0 ; i < processNames . length ; i ++ ) {
const processName = processNames [ i ]
if ( output . indexOf ( processName ) !== - 1 ) {
return [ COMMON _EDITORS _LINUX [ processName ] ]
}
}
}
} catch ( error ) {
// Ignore...
}
// Last resort, use old skool env vars
if ( process . env . VISUAL ) {
return [ process . env . VISUAL ]
} else if ( process . env . EDITOR ) {
return [ process . env . EDITOR ]
}
return [ null ]
}