107 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
			
		
		
	
	
			107 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Haxe
		
	
	
	
	
	
| package haxe;
 | |
| 
 | |
| import haxe.ds.ReadOnlyArray;
 | |
| 
 | |
| class SysTools {
 | |
| 	/**
 | |
| 		Character codes of the characters that will be escaped by `quoteWinArg(_, true)`.
 | |
| 	**/
 | |
| 	public static final winMetaCharacters:ReadOnlyArray<Int> = [
 | |
| 		" ".code, "(".code, ")".code, "%".code, "!".code, "^".code, "\"".code, "<".code, ">".code, "&".code, "|".code, "\n".code, "\r".code, ",".code, ";".code
 | |
| 	];
 | |
| 
 | |
| 	/**
 | |
| 		Returns a String that can be used as a single command line argument
 | |
| 		on Unix.
 | |
| 		The input will be quoted, or escaped if necessary.
 | |
| 	**/
 | |
| 	public static function quoteUnixArg(argument:String):String {
 | |
| 		// Based on cpython's shlex.quote().
 | |
| 		// https://hg.python.org/cpython/file/a3f076d4f54f/Lib/shlex.py#l278
 | |
| 
 | |
| 		if (argument == "")
 | |
| 			return "''";
 | |
| 
 | |
| 		if (!~/[^a-zA-Z0-9_@%+=:,.\/-]/.match(argument))
 | |
| 			return argument;
 | |
| 
 | |
| 		// use single quotes, and put single quotes into double quotes
 | |
| 		// the string $'b is then quoted as '$'"'"'b'
 | |
| 		return "'" + StringTools.replace(argument, "'", "'\"'\"'") + "'";
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 		Returns a String that can be used as a single command line argument
 | |
| 		on Windows.
 | |
| 		The input will be quoted, or escaped if necessary, such that the output
 | |
| 		will be parsed as a single argument using the rule specified in
 | |
| 		http://msdn.microsoft.com/en-us/library/ms880421
 | |
| 
 | |
| 		Examples:
 | |
| 		```haxe
 | |
| 		quoteWinArg("abc") == "abc";
 | |
| 		quoteWinArg("ab c") == '"ab c"';
 | |
| 		```
 | |
| 	**/
 | |
| 	public static function quoteWinArg(argument:String, escapeMetaCharacters:Bool):String {
 | |
| 		// If there is no space, tab, back-slash, or double-quotes, and it is not an empty string.
 | |
| 		if (!~/^[^ \t\\"]+$/.match(argument)) {
 | |
| 			// Based on cpython's subprocess.list2cmdline().
 | |
| 			// https://hg.python.org/cpython/file/50741316dd3a/Lib/subprocess.py#l620
 | |
| 
 | |
| 			var result = new StringBuf();
 | |
| 			var needquote = argument.indexOf(" ") != -1 || argument.indexOf("\t") != -1 || argument == "";
 | |
| 
 | |
| 			if (needquote)
 | |
| 				result.add('"');
 | |
| 
 | |
| 			var bs_buf = new StringBuf();
 | |
| 			for (i in 0...argument.length) {
 | |
| 				switch (argument.charCodeAt(i)) {
 | |
| 					case "\\".code:
 | |
| 						// Don't know if we need to double yet.
 | |
| 						bs_buf.add("\\");
 | |
| 					case '"'.code:
 | |
| 						// Double backslashes.
 | |
| 						var bs = bs_buf.toString();
 | |
| 						result.add(bs);
 | |
| 						result.add(bs);
 | |
| 						bs_buf = new StringBuf();
 | |
| 						result.add('\\"');
 | |
| 					case var c:
 | |
| 						// Normal char
 | |
| 						if (bs_buf.length > 0) {
 | |
| 							result.add(bs_buf.toString());
 | |
| 							bs_buf = new StringBuf();
 | |
| 						}
 | |
| 						result.addChar(c);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			// Add remaining backslashes, if any.
 | |
| 			result.add(bs_buf.toString());
 | |
| 
 | |
| 			if (needquote) {
 | |
| 				result.add(bs_buf.toString());
 | |
| 				result.add('"');
 | |
| 			}
 | |
| 
 | |
| 			argument = result.toString();
 | |
| 		}
 | |
| 
 | |
| 		if (escapeMetaCharacters) {
 | |
| 			var result = new StringBuf();
 | |
| 			for (i in 0...argument.length) {
 | |
| 				var c = argument.charCodeAt(i);
 | |
| 				if (winMetaCharacters.indexOf(c) >= 0) {
 | |
| 					result.addChar("^".code);
 | |
| 				}
 | |
| 				result.addChar(c);
 | |
| 			}
 | |
| 			return result.toString();
 | |
| 		} else {
 | |
| 			return argument;
 | |
| 		}
 | |
| 	}
 | |
| }
 |