* C-style quotes a filename, encoding special characters as escape sequences * and non-ASCII bytes as octal escapes. This is the inverse of * `parseQuotedFileName` in parse.ts. * * Non-ASCII bytes are encoded as UTF-8 before being emitted as octal escapes. * This matches the behaviour of both G
(s: string)
| 27 | * If the filename doesn't need quoting, returns it as-is. |
| 28 | */ |
| 29 | function quoteFileNameIfNeeded(s: string): string { |
| 30 | if (!needsQuoting(s)) { |
| 31 | return s; |
| 32 | } |
| 33 | |
| 34 | let result = '"'; |
| 35 | const bytes = new TextEncoder().encode(s); |
| 36 | let i = 0; |
| 37 | while (i < bytes.length) { |
| 38 | const b = bytes[i]; |
| 39 | |
| 40 | // See https://en.wikipedia.org/wiki/Escape_sequences_in_C#Escape_sequences |
| 41 | if (b === 0x07) { |
| 42 | result += '\\a'; |
| 43 | } else if (b === 0x08) { |
| 44 | result += '\\b'; |
| 45 | } else if (b === 0x09) { |
| 46 | result += '\\t'; |
| 47 | } else if (b === 0x0a) { |
| 48 | result += '\\n'; |
| 49 | } else if (b === 0x0b) { |
| 50 | result += '\\v'; |
| 51 | } else if (b === 0x0c) { |
| 52 | result += '\\f'; |
| 53 | } else if (b === 0x0d) { |
| 54 | result += '\\r'; |
| 55 | } else if (b === 0x22) { |
| 56 | result += '\\"'; |
| 57 | } else if (b === 0x5c) { |
| 58 | result += '\\\\'; |
| 59 | } else if (b >= 0x20 && b <= 0x7e) { |
| 60 | // Just a printable ASCII character that is neither a double quote nor a |
| 61 | // backslash; no need to escape it. |
| 62 | result += String.fromCharCode(b); |
| 63 | } else { |
| 64 | // Either part of a non-ASCII character or a control character without a |
| 65 | // special escape sequence; needs escaping as a 3-digit octal escape |
| 66 | result += '\\' + b.toString(8).padStart(3, '0'); |
| 67 | } |
| 68 | i++; |
| 69 | } |
| 70 | result += '"'; |
| 71 | return result; |
| 72 | } |
| 73 | |
| 74 | type StructuredPatchCallbackAbortable = (patch: StructuredPatch | undefined) => void; |
| 75 | type StructuredPatchCallbackNonabortable = (patch: StructuredPatch) => void; |
no test coverage detected