guess.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. const path = require('path')
  2. const shellQuote = require('shell-quote')
  3. const childProcess = require('child_process')
  4. // Map from full process name to binary that starts the process
  5. // We can't just re-use full process name, because it will spawn a new instance
  6. // of the app every time
  7. const COMMON_EDITORS_OSX = require('./editor-info/osx')
  8. const COMMON_EDITORS_LINUX = require('./editor-info/linux')
  9. const COMMON_EDITORS_WIN = require('./editor-info/windows')
  10. module.exports = function guessEditor (specifiedEditor) {
  11. if (specifiedEditor) {
  12. return shellQuote.parse(specifiedEditor)
  13. }
  14. if (process.versions.webcontainer) {
  15. return [process.env.EDITOR || 'code']
  16. }
  17. // We can find out which editor is currently running by:
  18. // `ps x` on macOS and Linux
  19. // `Get-Process` on Windows
  20. try {
  21. if (process.platform === 'darwin') {
  22. const output = childProcess
  23. .execSync('ps x', {
  24. stdio: ['pipe', 'pipe', 'ignore']
  25. })
  26. .toString()
  27. const processNames = Object.keys(COMMON_EDITORS_OSX)
  28. for (let i = 0; i < processNames.length; i++) {
  29. const processName = processNames[i]
  30. if (output.indexOf(processName) !== -1) {
  31. return [COMMON_EDITORS_OSX[processName]]
  32. }
  33. }
  34. } else if (process.platform === 'win32') {
  35. const output = childProcess
  36. .execSync('powershell -Command "Get-Process | Select-Object Path"', {
  37. stdio: ['pipe', 'pipe', 'ignore']
  38. })
  39. .toString()
  40. const runningProcesses = output.split('\r\n')
  41. for (let i = 0; i < runningProcesses.length; i++) {
  42. // `Get-Process` sometimes returns empty lines
  43. if (!runningProcesses[i]) {
  44. continue
  45. }
  46. const fullProcessPath = runningProcesses[i].trim()
  47. const shortProcessName = path.basename(fullProcessPath)
  48. if (COMMON_EDITORS_WIN.indexOf(shortProcessName) !== -1) {
  49. return [fullProcessPath]
  50. }
  51. }
  52. } else if (process.platform === 'linux') {
  53. // --no-heading No header line
  54. // x List all processes owned by you
  55. // -o comm Need only names column
  56. const output = childProcess
  57. .execSync('ps x --no-heading -o comm --sort=comm', {
  58. stdio: ['pipe', 'pipe', 'ignore']
  59. })
  60. .toString()
  61. const processNames = Object.keys(COMMON_EDITORS_LINUX)
  62. for (let i = 0; i < processNames.length; i++) {
  63. const processName = processNames[i]
  64. if (output.indexOf(processName) !== -1) {
  65. return [COMMON_EDITORS_LINUX[processName]]
  66. }
  67. }
  68. }
  69. } catch (error) {
  70. // Ignore...
  71. }
  72. // Last resort, use old skool env vars
  73. if (process.env.VISUAL) {
  74. return [process.env.VISUAL]
  75. } else if (process.env.EDITOR) {
  76. return [process.env.EDITOR]
  77. }
  78. return [null]
  79. }