diff options
Diffstat (limited to 'source/util.d')
-rw-r--r-- | source/util.d | 197 |
1 files changed, 194 insertions, 3 deletions
diff --git a/source/util.d b/source/util.d index 3624d88..0e3fc18 100644 --- a/source/util.d +++ b/source/util.d @@ -10,9 +10,16 @@ import std.path; import std.conv : to; +/// MAXCOLS refers to terminal width enum byte MAXCOLS = 80; +/** + Print a wordwrapped string encapsulated by `ch` +Params: + ch = ASCII character to create border + s = string to print + */ void banner(const char ch, string s) { string ruler; byte i = 0; @@ -36,17 +43,54 @@ void banner(const char ch, string s) { } -static auto getenv(string[string] base=null, string preface=null) { +/** + Dump the parent shell runtime environment and convert it into an associative + array + +Params: + base = use an existing mapping as the base environment + preface = command to execute prior to dumping the environment + +Returns: + an associative array containing the runtime environment + +Example: +--- +import std.stdio; +import util; + +void main() +{ + string exfile = "example.sh"; + File(exfile, "w+").write("export EXAMPLE_FILE=parsed\n"); + scope(exit) exfile.remove; + + auto myenv = getenv(); + myenv["EXAMPLE"] = "works"; + + auto myenv2 = getenv(myenv); + writeln(myenv2["EXAMPLE"]); + + auto myenv3 = getenv(myenv2, "source example.sh"); + writeln(myenv3["EXAMPLE"]); + writeln(myenv3["EXAMPLE_FILE"]); +} +--- + */ +string[string] getenv(string[string] base=null, string preface=null) { const char delim = '='; char delim_line = '\n'; string[string] env; string cmd = "env"; + /// Under GNU we have the option to use nul-terminated strings, which means + /// we can safely parse awful pairs generated by `env-modules` version (linux) { cmd ~= " -0"; delim_line = '\0'; } + /// Untested version (Windows) { cmd = "set"; delim_line = "\r\n"; @@ -78,10 +122,54 @@ static auto getenv(string[string] base=null, string preface=null) { } +/** + Produce a single-quoted string + +Params: + s = string to quote + +Returns: + single-quoted string + +Example: +--- +import std.stdio; +import util; + +void main() +{ + writeln(safe_spec("single-quoted")); + // 'single-quoted' +} +--- + */ string safe_spec(string s) { return "'" ~ s ~ "'"; } + +/** + Produces conda/pip compatible installation arguments + +Params: + specs = array of string arguments + +Returns: + string of single-quoted arguments + +Example: +--- +import std.stdio; +import util; + +void main() +{ + string[] arguments = ["a", "b", "c"]; + writeln(safe_install(arguments)); + // 'a' 'b' 'c' +} +--- + */ string safe_install(string[] specs) { string[] result; foreach (record; specs) { @@ -90,6 +178,30 @@ string safe_install(string[] specs) { return result.join(" "); } + +/** + Produces `conda`/`pip` compatible installation arguments by splitting on white + space + + Params: + specs = a string containing arguments + + Returns: + string of single quoted arguments + + Example: + --- + import std.stdio; + import util; + + void main() + { + string arguments = "a b c"; + writeln(safe_install(arguments)); + // 'a' 'b' 'c' + } + --- + */ string safe_install(string specs) { string[] result; foreach (record; specs.split(" ")) { @@ -99,7 +211,19 @@ string safe_install(string specs) { } +/** + pytest emits invalid junit, so this rewrites the local configuration + file (i.e. `setup.cfg`, `pytest.ini`, etc) to include the proper + `junit_family` settings. + +Params: + filename = path to configuration file + +Returns: + new configuration file contents as string + */ string pytest_xunit2(string filename) { + // Generate the requested file if need be if (!filename.exists) { auto dummy = File(filename, "w+"); dummy.write(""); @@ -139,6 +263,7 @@ string pytest_xunit2(string filename) { return data ~ format("\n%s\n%s\n", section, cfgitem); } + // figure out when/where we should write our revisions to the config foreach (rec; splitLines(data)) { if (!has_section) { break; @@ -163,6 +288,16 @@ string pytest_xunit2(string filename) { } +/** + Find all occurences of character in a string + +Params: + s = string to read + ch = character to find + +Returns: + array of offsets + */ ulong[] indexOfAll(string s, char ch) { ulong[] result; for (ulong i = 0; i < s.length; i++) { @@ -174,6 +309,7 @@ ulong[] indexOfAll(string s, char ch) { } +/// Unused string expander(string[string] aa, string name, char delim = '$') { string s = aa[name].dup; ulong[] needles = indexOfAll(s, delim); @@ -200,25 +336,57 @@ string expander(string[string] aa, string name, char delim = '$') { } + +/** + Perform variable interpolation on a string given a named environment + +Params: + aa = assoc. array to use (i.e. runtime environment) + str = string to scan for variables + delim = character to trigger parsing variable + +Returns: + string with variables replaced + +Note: + When a variable cannot be mapped the variable text in the string is not + modified. + +Example: +--- +import std.stdio; +import util; + +void main() +{ + string[string] aa = ["my_var": "example"]; + string my_str = "This is the ${my_var}."; + writeln(interpolate(aa, my_str)); +} +--- + */ string interpolate(string[string]aa, string str, char delim = '$') { import std.ascii; string s = str.dup; ulong[] needles = indexOfAll(s, delim); string[] found; + // scan any indicies we've found foreach (needle; needles) { string tmp = ""; + // trigger variable parsing on delimiter for (ulong i = needle; i < s.length; i++) { if (s[i] == delim) continue; - else if (s[i] == '{' || s[i] == '}') + else if (s[i] == '{' || s[i] == '}') // ${} also supported continue; - else if (!s[i].isAlphaNum && s[i] != '_' ) + else if (!s[i].isAlphaNum && s[i] != '_') // unusable, die break; tmp ~= s[i]; } found ~= tmp; } + // rewrite string with substitutions foreach (match; found) { foreach (pair; aa.byPair) { if (pair.key != match) @@ -232,6 +400,29 @@ string interpolate(string[string]aa, string str, char delim = '$') { } +/** + Produce a short/compact version + +Params: + vrs = version string + +Returns: + shortened version string + +Example: +--- +import std.stdio; +import util; + +void main() +{ + writeln(short_version("3.6.8")); + // 36 + writeln(short_version("2.7.66")); + // 27 +} +--- + */ string short_version(string vrs) { string tmp = vrs.dup; tmp = tmp.replace(".", ""); |