diff --git a/asino.d b/asino.d index 8b5e8a2..baf6fcb 100644 --- a/asino.d +++ b/asino.d @@ -1,12 +1,5 @@ /** Buridan's Donkey, Asino. - - ...a man, being just as hungry as thirsty, - and placed in between food and drink, - must necessarily remain where he is and starve to death. - - - Aristole - Copyright: Francesco Mecca License: GPLv3 Author: Francesco Mecca @@ -18,35 +11,67 @@ import std.random; import std.getopt; import std.file; import std.conv; +import std.array; +import std.algorithm; + +extern(C) +{ + struct pollfd { int fd; short events; short revents; } + int poll(pollfd *fds, int nfds, int timeout); +} + +string versionSt = "...a man, being just as hungry as thirsty, +and placed in between food and drink, +must necessarily remain where he is and starve to death. + +Aristole"; + void main (string[] args) { - bool num = false; + bool num, v; string engine = "mt"; + string div; auto cliOpts = getopt( args, "numbers|n", "enable number output on screen", &num, + "divider|d", "divide the arguments using a different divider", &div, + "version|v", "show version and exit", &v, "engine|e", "Choose the RNG between \"mt\" (Mersenne-Twister, default), \"x\" (xorshift), \"dr\" (/dev/random), \"du\" (/dev/urandom)", &engine ); - if (cliOpts.helpWanted){ - defaultGetoptPrinter("Buridan's Donkey", cliOpts.options); + if(cliOpts.helpWanted){ + defaultGetoptPrinter("Buridan's Donkey\nSort a list of strings randomly", cliOpts.options); return; + } else if(v){ + writeln(versionSt); } - args = args[1 .. $]; // remove program name - args.shuffle(engine); - //writeln(typeid(gen)); + string[] toProcess = void; + if(isaTTY()){ + // read stdin, ignore cli args + toProcess = to!(string[])(stdin.byLine().array()); + } else { + toProcess = args[1 .. $]; // remove program name + } - foreach (i, arg; args) { + auto res = toProcess.divide(div).shuffle(engine); + + foreach (i, arg; res) { if (!num) writeln(arg); else writefln("%s: %s", i, arg); } } -void shuffle(ref string[] args, string t) +string[] divide(string[] args, string div) +{ + if (div == "") return args; + else return to!(string[])(args.join.splitter(div).array); +} + +string[] shuffle(string[] args, string t) { if(t == "mt"){ Mt19937 gen; @@ -65,6 +90,7 @@ void shuffle(ref string[] args, string t) } else { throw new Exception("Wrong arguments"); } + return args; } @@ -84,38 +110,24 @@ template DevRandomGen(string gen) enum UIntType max = ubyte.max; string src = gen; - - /** - * Unused for /dev/random - */ void seed(UIntType x0) @safe pure nothrow @nogc {} - - - /** - * Returns the current number in the random sequence. - */ - @property - UIntType front() const// @safe pure nothrow @nogc - { - //auto a = to!UIntType("/dev/random".read(UIntType.sizeof)); - //return to!UIntType(a); - return (cast(ubyte[])(src.read(ubyte.sizeof)))[0]; - } - - - /** - * Advances the random sequence. - */ void popFront() @safe pure nothrow @nogc {} - - /** - * Captures a range state. - */ @property - typeof(this) save() @safe pure nothrow @nogc - { - return this; - } + UIntType front() const { return (cast(ubyte[])(src.read(ubyte.sizeof)))[0]; } + + @property + typeof(this) save() @safe pure nothrow @nogc { return this; } } } + +bool isaTTY() +{ + pollfd fds; + int ret; + + fds.fd = 0; + fds.events = 0; + ret = poll(&fds, 1, 0); + return ret > 0; +}