mirror of https://github.com/deavmi/niknaks
Compare commits
3 Commits
1281aaba31
...
e5a46f8652
Author | SHA1 | Date |
---|---|---|
Tristan B. Velloza Kildaire | e5a46f8652 | |
Tristan B. Velloza Kildaire | 41ebad0768 | |
Tristan B. Velloza Kildaire | 0e232822fa |
|
@ -40,6 +40,8 @@ is expected to grow over time.
|
||||||
* `niknaks.containers`
|
* `niknaks.containers`
|
||||||
* Some useful container types
|
* Some useful container types
|
||||||
* Things such as `CacheMap`
|
* Things such as `CacheMap`
|
||||||
|
* `niknaks.mechanisms`
|
||||||
|
* User-defined input prompter, retry mechanisms
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|
|
@ -591,6 +591,105 @@ unittest
|
||||||
destroy(map);
|
destroy(map);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Given [0, 1, 5]
|
||||||
|
// and shift right at index 1
|
||||||
|
// then 0 moves into 1's place
|
||||||
|
// 0's position is then filled with T.init
|
||||||
|
|
||||||
|
public T[] shift(T)(T[] array, size_t position, bool rightwards = false, bool shrink = false)
|
||||||
|
{
|
||||||
|
// Out of range
|
||||||
|
if(position >= array.length)
|
||||||
|
{
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if rightwards
|
||||||
|
if(rightwards)
|
||||||
|
{
|
||||||
|
// nothing further left than index 0
|
||||||
|
if(!position)
|
||||||
|
{
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t i = position; i > 0; i--)
|
||||||
|
{
|
||||||
|
array[i] = array[i-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
// no shrink, then fill with T.init
|
||||||
|
if(!shrink)
|
||||||
|
{
|
||||||
|
array[0] = T.init;
|
||||||
|
}
|
||||||
|
// chomp left-hand side
|
||||||
|
else
|
||||||
|
{
|
||||||
|
array = array[1..$];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
// rightwards testung (no shrink)
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
int[] numbas = [1, 5, 2];
|
||||||
|
numbas = numbas.shift(1, true);
|
||||||
|
|
||||||
|
// should now be [0, 1, 2]
|
||||||
|
writeln(numbas);
|
||||||
|
assert(numbas == [0, 1, 2]);
|
||||||
|
|
||||||
|
numbas = [1, 5, 2];
|
||||||
|
numbas = numbas.shift(0, true);
|
||||||
|
|
||||||
|
// should now be [1, 5, 2]
|
||||||
|
writeln(numbas);
|
||||||
|
assert(numbas == [1, 5, 2]);
|
||||||
|
|
||||||
|
numbas = [1, 5, 2];
|
||||||
|
numbas = numbas.shift(2, true);
|
||||||
|
|
||||||
|
// should now be [0, 1, 5]
|
||||||
|
writeln(numbas);
|
||||||
|
assert(numbas == [0, 1, 5]);
|
||||||
|
|
||||||
|
numbas = [1, 2];
|
||||||
|
numbas = numbas.shift(1, true);
|
||||||
|
|
||||||
|
// should now be [0, 1]
|
||||||
|
writeln(numbas);
|
||||||
|
assert(numbas == [0, 1]);
|
||||||
|
|
||||||
|
numbas = [1, 2];
|
||||||
|
numbas = numbas.shift(0, true);
|
||||||
|
|
||||||
|
// should now be [1, 2]
|
||||||
|
writeln(numbas);
|
||||||
|
assert(numbas == [1, 2]);
|
||||||
|
|
||||||
|
numbas = [];
|
||||||
|
numbas = numbas.shift(0, true);
|
||||||
|
|
||||||
|
// should now be []
|
||||||
|
writeln(numbas);
|
||||||
|
assert(numbas == []);
|
||||||
|
}
|
||||||
|
|
||||||
|
public T[] remove(T)(T[] array, size_t idx)
|
||||||
|
{
|
||||||
|
// Return your array on this
|
||||||
|
if(!(idx < array.length))
|
||||||
|
{
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: make delegate kak
|
// TODO: make delegate kak
|
||||||
// public interface InclusionStratergy(T)
|
// public interface InclusionStratergy(T)
|
||||||
// {
|
// {
|
||||||
|
@ -650,16 +749,36 @@ public class Tree(T)
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void appendValue(T value)
|
this()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setValue(T value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
public void appendNode(Tree!(T) node)
|
public void appendNode(Tree!(T) node)
|
||||||
{
|
{
|
||||||
this.children ~= node;
|
this.children ~= node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool removeNode(Tree!(T) node)
|
||||||
|
{
|
||||||
|
bool found = false;
|
||||||
|
for(size_t i = 0; i < this.children.length; i++)
|
||||||
|
{
|
||||||
|
found = this.children[i] == node;
|
||||||
|
if(found)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public T[] dfs
|
public T[] dfs
|
||||||
(
|
(
|
||||||
InclusionStratergy!(T) strat = toDelegate(&Always!(T)),
|
InclusionStratergy!(T) strat = toDelegate(&Always!(T)),
|
||||||
|
|
|
@ -9,6 +9,8 @@ import std.functional : toDelegate;
|
||||||
import std.datetime : Duration;
|
import std.datetime : Duration;
|
||||||
import std.datetime.stopwatch : StopWatch, AutoStart;
|
import std.datetime.stopwatch : StopWatch, AutoStart;
|
||||||
import core.thread : Thread;
|
import core.thread : Thread;
|
||||||
|
import std.stdio : File, write;
|
||||||
|
import std.string : strip;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A verdict-providing function
|
* A verdict-providing function
|
||||||
|
@ -291,4 +293,203 @@ unittest
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A user-defined prompt
|
||||||
|
*/
|
||||||
|
public struct Prompt
|
||||||
|
{
|
||||||
|
private string query;
|
||||||
|
private string value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new prompt
|
||||||
|
* with the given query
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* query = the prompt
|
||||||
|
* query itself
|
||||||
|
*/
|
||||||
|
this(string query)
|
||||||
|
{
|
||||||
|
this.query = query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the prompt query
|
||||||
|
*
|
||||||
|
* Returns: the query
|
||||||
|
*/
|
||||||
|
public string getQuery()
|
||||||
|
{
|
||||||
|
return this.query;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves this prompt's
|
||||||
|
* answer
|
||||||
|
*
|
||||||
|
* Returns: the answer
|
||||||
|
*/
|
||||||
|
public string getValue()
|
||||||
|
{
|
||||||
|
return this.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill this prompt's
|
||||||
|
* query with a corresponding
|
||||||
|
* answer
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* value = the answer
|
||||||
|
*/
|
||||||
|
public void fill(string value)
|
||||||
|
{
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A prompting mechanism
|
||||||
|
* which can be filled up
|
||||||
|
* with questions and a
|
||||||
|
* file-based source to
|
||||||
|
* read answers in from
|
||||||
|
* and associate with
|
||||||
|
* their original respective
|
||||||
|
* questions
|
||||||
|
*/
|
||||||
|
public class Prompter
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Source file
|
||||||
|
*/
|
||||||
|
private File source;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether or not to close
|
||||||
|
* the source file on destruction
|
||||||
|
*/
|
||||||
|
private bool closeOnDestruct;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prompts to query by
|
||||||
|
*/
|
||||||
|
private Prompt[] prompts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new prompter
|
||||||
|
* with the given file source
|
||||||
|
* from where the input is to
|
||||||
|
* be read from.
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* source = the `File` to
|
||||||
|
* read from
|
||||||
|
* closeOnDestruct = if
|
||||||
|
* set to `true` then on
|
||||||
|
* destruction we will close
|
||||||
|
* the source, if `false` it
|
||||||
|
* is left untouched
|
||||||
|
*
|
||||||
|
* Throws:
|
||||||
|
* Exception if the provided
|
||||||
|
* `File` is not open
|
||||||
|
*/
|
||||||
|
this(File source, bool closeOnDestruct = false)
|
||||||
|
{
|
||||||
|
if(!source.isOpen())
|
||||||
|
{
|
||||||
|
throw new Exception("Source not open");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.closeOnDestruct = closeOnDestruct;
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the given prompt
|
||||||
|
*
|
||||||
|
* Params:
|
||||||
|
* prompt = the prompt
|
||||||
|
*/
|
||||||
|
public void addPrompt(Prompt prompt)
|
||||||
|
{
|
||||||
|
this.prompts ~= prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the prompting
|
||||||
|
* by querying each attached
|
||||||
|
* prompt for an answer
|
||||||
|
* which is then associated
|
||||||
|
* with the given prompt
|
||||||
|
*
|
||||||
|
* Returns: the answered
|
||||||
|
* prompts
|
||||||
|
*/
|
||||||
|
public Prompt[] prompt()
|
||||||
|
{
|
||||||
|
char[] buff;
|
||||||
|
|
||||||
|
foreach(ref Prompt prompt; this.prompts)
|
||||||
|
{
|
||||||
|
scope(exit)
|
||||||
|
{
|
||||||
|
buff.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Perform the query
|
||||||
|
write(prompt.getQuery());
|
||||||
|
this.source.readln(buff);
|
||||||
|
|
||||||
|
// Fill answer into prompt
|
||||||
|
prompt.fill(strip(cast(string)buff));
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.prompts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destructor
|
||||||
|
*/
|
||||||
|
~this()
|
||||||
|
{
|
||||||
|
if(this.closeOnDestruct)
|
||||||
|
{
|
||||||
|
this.source.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version(unittest)
|
||||||
|
{
|
||||||
|
import std.process : pipe, Pipe;
|
||||||
|
import std.conv : to;
|
||||||
|
import std.stdio : writeln;
|
||||||
|
}
|
||||||
|
|
||||||
|
unittest
|
||||||
|
{
|
||||||
|
Pipe pipe = pipe();
|
||||||
|
|
||||||
|
// Create a prompter with some prompts
|
||||||
|
Prompter p = new Prompter(pipe.readEnd());
|
||||||
|
p.addPrompt(Prompt("What is your name?"));
|
||||||
|
p.addPrompt(Prompt("How old are you"));
|
||||||
|
|
||||||
|
// Fill up pipe with data for read end
|
||||||
|
File writeEnd = pipe.writeEnd();
|
||||||
|
writeEnd.writeln("Tristan Brice Velloza Kildaire");
|
||||||
|
writeEnd.writeln(1);
|
||||||
|
writeEnd.flush();
|
||||||
|
|
||||||
|
// Perform the prompt and get the
|
||||||
|
// answers back out
|
||||||
|
Prompt[] ans = p.prompt();
|
||||||
|
|
||||||
|
writeln(ans);
|
||||||
|
|
||||||
|
assert(ans[0].getValue() == "Tristan Brice Velloza Kildaire");
|
||||||
|
assert(to!(int)(ans[1].getValue()) == 1); // TODO: Allow union conversion later
|
||||||
|
}
|
Loading…
Reference in New Issue