Compare commits

...

4 Commits

Author SHA1 Message Date
Tristan B. Velloza Kildaire 1281aaba31
Merge 838ddbb9db into 0e232822fa 2024-04-26 13:37:05 +00:00
Tristan B. Velloza Kildaire 838ddbb9db Tree (unittests)
- Added missing assertions
2024-04-26 15:36:54 +02:00
Tristan B. Velloza Kildaire e44caf3643 VisitationTree (unittests)
- Added missing assertions
2024-04-26 15:35:29 +02:00
Tristan B. Velloza Kildaire 0e232822fa
Feature: Prompting framework (#16)
* Prompter

- Added

Prompt

- Added

* Prompter

- Fixed source `File` check

Prompter (unittests)

- Added a unittest

* Prompter

- Fixed `prompt()`

Prompter (unittests)

- `flush()` pipe write end

* Prompter (unittests)

- Cleaned up

* Prompter (unittests)

- Cleaned up

* Prompter (unittests)

- Fixed missing import

* Prompter

- Added more docs

* Prompter

- Added more docs

* Prompt

- Documented

* Prompter

- Cleand up

* Prompter (unittests)

- Removed unittest

* README

- Updated
2024-04-15 10:45:16 +02:00
3 changed files with 213 additions and 1 deletions

View File

@ -40,6 +40,8 @@ is expected to grow over time.
* `niknaks.containers`
* Some useful container types
* Things such as `CacheMap`
* `niknaks.mechanisms`
* User-defined input prompter, retry mechanisms
## License

View File

@ -747,6 +747,11 @@ unittest
string[] result = treeOfStrings.dfs(strat, touch);
writeln("dfs: ", result);
assert(result[0] == "1");
assert(result[1] == "2");
assert(result[2] == "3");
assert(result[3] == "Top");
}
public class VisitationTree(T) : Tree!(T)
@ -797,6 +802,10 @@ unittest
root.appendNode(thing);
thing.appendNode(root);
writeln(root.linearize());
string[] linearized = root.linearize();
writeln(linearized);
assert(linearized[0] == "subtree");
assert(linearized[1] == "root");
}

View File

@ -9,6 +9,8 @@ import std.functional : toDelegate;
import std.datetime : Duration;
import std.datetime.stopwatch : StopWatch, AutoStart;
import core.thread : Thread;
import std.stdio : File, write;
import std.string : strip;
/**
* 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
}