.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / cross-spawn / lib / parse.js
1 'use strict';
2
3 const path = require('path');
4 const resolveCommand = require('./util/resolveCommand');
5 const escape = require('./util/escape');
6 const readShebang = require('./util/readShebang');
7
8 const isWin = process.platform === 'win32';
9 const isExecutableRegExp = /\.(?:com|exe)$/i;
10 const isCmdShimRegExp = /node_modules[\\/].bin[\\/][^\\/]+\.cmd$/i;
11
12 function detectShebang(parsed) {
13     parsed.file = resolveCommand(parsed);
14
15     const shebang = parsed.file && readShebang(parsed.file);
16
17     if (shebang) {
18         parsed.args.unshift(parsed.file);
19         parsed.command = shebang;
20
21         return resolveCommand(parsed);
22     }
23
24     return parsed.file;
25 }
26
27 function parseNonShell(parsed) {
28     if (!isWin) {
29         return parsed;
30     }
31
32     // Detect & add support for shebangs
33     const commandFile = detectShebang(parsed);
34
35     // We don't need a shell if the command filename is an executable
36     const needsShell = !isExecutableRegExp.test(commandFile);
37
38     // If a shell is required, use cmd.exe and take care of escaping everything correctly
39     // Note that `forceShell` is an hidden option used only in tests
40     if (parsed.options.forceShell || needsShell) {
41         // Need to double escape meta chars if the command is a cmd-shim located in `node_modules/.bin/`
42         // The cmd-shim simply calls execute the package bin file with NodeJS, proxying any argument
43         // Because the escape of metachars with ^ gets interpreted when the cmd.exe is first called,
44         // we need to double escape them
45         const needsDoubleEscapeMetaChars = isCmdShimRegExp.test(commandFile);
46
47         // Normalize posix paths into OS compatible paths (e.g.: foo/bar -> foo\bar)
48         // This is necessary otherwise it will always fail with ENOENT in those cases
49         parsed.command = path.normalize(parsed.command);
50
51         // Escape command & arguments
52         parsed.command = escape.command(parsed.command);
53         parsed.args = parsed.args.map((arg) => escape.argument(arg, needsDoubleEscapeMetaChars));
54
55         const shellCommand = [parsed.command].concat(parsed.args).join(' ');
56
57         parsed.args = ['/d', '/s', '/c', `"${shellCommand}"`];
58         parsed.command = process.env.comspec || 'cmd.exe';
59         parsed.options.windowsVerbatimArguments = true; // Tell node's spawn that the arguments are already escaped
60     }
61
62     return parsed;
63 }
64
65 function parse(command, args, options) {
66     // Normalize arguments, similar to nodejs
67     if (args && !Array.isArray(args)) {
68         options = args;
69         args = null;
70     }
71
72     args = args ? args.slice(0) : []; // Clone array to avoid changing the original
73     options = Object.assign({}, options); // Clone object to avoid changing the original
74
75     // Build our parsed object
76     const parsed = {
77         command,
78         args,
79         options,
80         file: undefined,
81         original: {
82             command,
83             args,
84         },
85     };
86
87     // Delegate further parsing to shell or non-shell
88     return options.shell ? parsed : parseNonShell(parsed);
89 }
90
91 module.exports = parse;