parse-command-line.js
1 'use strict'; 2 3 const dedent = require('dedent'); 4 const yargs = require('yargs'); 5 const { app } = require('electron'); 6 7 module.exports = function parseCommandLine(processArgs) { 8 const options = yargs(processArgs).wrap(yargs.terminalWidth()); 9 const version = app.getVersion(); 10 options.usage( 11 dedent`Atom Editor v${version} 12 13 Usage: 14 atom 15 atom [options] [path ...] 16 atom file[:line[:column]] 17 18 One or more paths to files or folders may be specified. If there is an 19 existing Atom window that contains all of the given folders, the paths 20 will be opened in that window. Otherwise, they will be opened in a new 21 window. 22 23 A file may be opened at the desired line (and optionally column) by 24 appending the numbers right after the file name, e.g. \`atom file:5:8\`. 25 26 Paths that start with \`atom://\` will be interpreted as URLs. 27 28 Environment Variables: 29 30 ATOM_DEV_RESOURCE_PATH The path from which Atom loads source code in dev mode. 31 Defaults to \`~/github/atom\`. 32 33 ATOM_HOME The root path for all configuration files and folders. 34 Defaults to \`~/.atom\`.` 35 ); 36 // Deprecated 1.0 API preview flag 37 options 38 .alias('1', 'one') 39 .boolean('1') 40 .describe('1', 'This option is no longer supported.'); 41 options 42 .boolean('include-deprecated-apis') 43 .describe( 44 'include-deprecated-apis', 45 'This option is not currently supported.' 46 ); 47 options 48 .alias('d', 'dev') 49 .boolean('d') 50 .describe('d', 'Run in development mode.'); 51 options 52 .alias('f', 'foreground') 53 .boolean('f') 54 .describe('f', 'Keep the main process in the foreground.'); 55 options 56 .alias('h', 'help') 57 .boolean('h') 58 .describe('h', 'Print this usage message.'); 59 options 60 .alias('l', 'log-file') 61 .string('l') 62 .describe('l', 'Log all output to file.'); 63 options 64 .alias('n', 'new-window') 65 .boolean('n') 66 .describe('n', 'Open a new window.'); 67 options 68 .boolean('profile-startup') 69 .describe( 70 'profile-startup', 71 'Create a profile of the startup execution time.' 72 ); 73 options 74 .alias('r', 'resource-path') 75 .string('r') 76 .describe( 77 'r', 78 'Set the path to the Atom source directory and enable dev-mode.' 79 ); 80 options 81 .boolean('safe') 82 .describe( 83 'safe', 84 'Do not load packages from ~/.atom/packages or ~/.atom/dev/packages.' 85 ); 86 options 87 .boolean('benchmark') 88 .describe( 89 'benchmark', 90 'Open a new window that runs the specified benchmarks.' 91 ); 92 options 93 .boolean('benchmark-test') 94 .describe( 95 'benchmark-test', 96 'Run a faster version of the benchmarks in headless mode.' 97 ); 98 options 99 .alias('t', 'test') 100 .boolean('t') 101 .describe( 102 't', 103 'Run the specified specs and exit with error code on failures.' 104 ); 105 options 106 .alias('m', 'main-process') 107 .boolean('m') 108 .describe('m', 'Run the specified specs in the main process.'); 109 options 110 .string('timeout') 111 .describe( 112 'timeout', 113 'When in test mode, waits until the specified time (in minutes) and kills the process (exit code: 130).' 114 ); 115 options 116 .alias('v', 'version') 117 .boolean('v') 118 .describe('v', 'Print the version information.'); 119 options 120 .alias('w', 'wait') 121 .boolean('w') 122 .describe('w', 'Wait for window to be closed before returning.'); 123 options 124 .alias('a', 'add') 125 .boolean('a') 126 .describe('add', 'Open path as a new project in last used window.'); 127 options.string('user-data-dir'); 128 options 129 .boolean('clear-window-state') 130 .describe('clear-window-state', 'Delete all Atom environment state.'); 131 options 132 .boolean('enable-electron-logging') 133 .describe( 134 'enable-electron-logging', 135 'Enable low-level logging messages from Electron.' 136 ); 137 options.boolean('uri-handler'); 138 139 let args = options.argv; 140 141 // If --uri-handler is set, then we parse NOTHING else 142 if (args.uriHandler) { 143 args = { 144 uriHandler: true, 145 'uri-handler': true, 146 _: args._.filter(str => str.startsWith('atom://')).slice(0, 1) 147 }; 148 } 149 150 if (args.help) { 151 process.stdout.write(options.help()); 152 process.exit(0); 153 } 154 155 if (args.version) { 156 process.stdout.write( 157 `Atom : ${app.getVersion()}\n` + 158 `Electron: ${process.versions.electron}\n` + 159 `Chrome : ${process.versions.chrome}\n` + 160 `Node : ${process.versions.node}\n` 161 ); 162 process.exit(0); 163 } 164 165 const addToLastWindow = args['add']; 166 const safeMode = args['safe']; 167 const benchmark = args['benchmark']; 168 const benchmarkTest = args['benchmark-test']; 169 const test = args['test']; 170 const mainProcess = args['main-process']; 171 const timeout = args['timeout']; 172 const newWindow = args['new-window']; 173 let executedFrom = null; 174 if (args['executed-from'] && args['executed-from'].toString()) { 175 executedFrom = args['executed-from'].toString(); 176 } else { 177 executedFrom = process.cwd(); 178 } 179 180 if (newWindow && addToLastWindow) { 181 process.stderr.write( 182 `Only one of the --add and --new-window options may be specified at the same time.\n\n${options.help()}` 183 ); 184 185 // Exiting the main process with a nonzero exit code on MacOS causes the app open to fail with the mysterious 186 // message "LSOpenURLsWithRole() failed for the application /Applications/Atom Dev.app with error -10810." 187 process.exit(0); 188 } 189 190 let pidToKillWhenClosed = null; 191 if (args['wait']) { 192 pidToKillWhenClosed = args['pid']; 193 } 194 195 const logFile = args['log-file']; 196 const userDataDir = args['user-data-dir']; 197 const profileStartup = args['profile-startup']; 198 const clearWindowState = args['clear-window-state']; 199 let pathsToOpen = []; 200 let urlsToOpen = []; 201 let devMode = args['dev']; 202 203 for (const path of args._) { 204 if (path.startsWith('atom://')) { 205 urlsToOpen.push(path); 206 } else { 207 pathsToOpen.push(path); 208 } 209 } 210 211 if (args.resourcePath || test) { 212 devMode = true; 213 } 214 215 if (args['path-environment']) { 216 // On Yosemite the $PATH is not inherited by the "open" command, so we have to 217 // explicitly pass it by command line, see http://git.io/YC8_Ew. 218 process.env.PATH = args['path-environment']; 219 } 220 221 return { 222 pathsToOpen, 223 urlsToOpen, 224 executedFrom, 225 test, 226 version, 227 pidToKillWhenClosed, 228 devMode, 229 safeMode, 230 newWindow, 231 logFile, 232 userDataDir, 233 profileStartup, 234 timeout, 235 clearWindowState, 236 addToLastWindow, 237 mainProcess, 238 benchmark, 239 benchmarkTest, 240 env: process.env 241 }; 242 };