Introduce options, implement it on all the translators.

This commit is contained in:
Arthur Sonzogni
2018-03-31 19:33:37 +02:00
parent f5d1a5f974
commit 623a683d5f
25 changed files with 311 additions and 253 deletions
+4 -8
View File
@@ -25,8 +25,7 @@ configure_file(
#-------------------------------------------------------------------------------
add_subdirectory(screen)
add_subdirectory(translator/line_number_ascii)
add_subdirectory(translator/line_number_unicode)
add_subdirectory(translator/frame)
add_subdirectory(translator/planar_graph)
add_subdirectory(translator/sequence)
@@ -71,8 +70,7 @@ if (Web)
translator/Translator.cpp
)
target_link_libraries(main.js
translator_line_number_ascii
translator_line_number_unicode
translator_frame
translator_planar_graph
translator_sequence
screen
@@ -86,8 +84,7 @@ else()
translator/Translator.cpp
)
target_link_libraries(main
translator_line_number_ascii
translator_line_number_unicode
translator_frame
translator_planar_graph
translator_sequence
screen
@@ -99,8 +96,7 @@ else()
input_output_test.cpp
)
target_link_libraries(input_output_test
translator_line_number_ascii
translator_line_number_unicode
translator_frame
translator_planar_graph
translator_sequence
antlr4_static
+65 -7
View File
@@ -12,7 +12,7 @@
<!--Header-->
<div id="landing_page_content" class="flex">
<h1>Diagon</h1>
<h2><b>Diag</b>ram <b>On</b>line</h2>
<h2><b>Diag</b>ram</h2>
<p>Interactive text→text tools collection.</p>
<a href="#code_area" id="begin_button">Begin</a>
</div>
@@ -32,20 +32,26 @@
<div class="container vertical fill_space">
<!--1 Menu bar-->
<div id="menu_bar">
<div id="menu_bar_submenu">
<div id="menu_bar" class="container horizontal">
<!--A Tool selection-->
<div class="menu_bar_submenu">
<label for="tools">Tool:</label>
<select type="text" id="tools">
<option>Chargement...</option>
</select>
</div>
<div id="menu_bar_submenu">
<!--B Example selection-->
<div class="menu_bar_submenu">
<label for="examples">Example:</label>
<select type="text" id="examples">
<option>Chargement...</option>
</select>
</div>
<!--C Options selection selection-->
<div class="menu_bar_submenu container horizontal" id="options">
</div>
</div>
<!--2 Input / Output -->
@@ -71,6 +77,7 @@
let tools = document.getElementById('tools');
let examples = document.getElementById('examples');
let options = document.getElementById('options');
let input = document.getElementById('input');
let output = document.getElementById('output');
let errors = document.getElementById('errors');
@@ -101,6 +108,55 @@ function UpdateExamples() {
}
}
function UpdateOptions() {
// Clear.
while(options.firstChild) {
options.removeChild(options.firstChild);
}
let index = tools.value;
let tool = tools_data[index];
for(let i in tool.options) {
let option = tool.options[i];
let option_box = document.createElement('p');
option_box.className = "option";
let label = document.createElement('label');
label.innerText = option.label + ":";
option_box.appendChild(label);
if (option.type = "checkbox") {
let checkbox = document.createElement("input");
checkbox.type = "checkbox";
checkbox.data = option.name;
checkbox.checked = option.default;
checkbox.addEventListener("change", UpdateOutput);
option_box.appendChild(checkbox);
}
options.appendChild(option_box);
}
}
function GetOptions() {
let output = "";
let index = tools.value;
let tool = tools_data[index];
for(let i in tool.options) {
let option = tool.options[i];
let name;
let value;
if (option.type = "checkbox") {
name = options.childNodes[i].childNodes[1].data;
value = options.childNodes[i].childNodes[1].checked;
}
output += name + "\n";
output += value + "\n";
}
return output;
}
function UpdateInput() {
let tool_index = tools.value;
let example_index = examples.value;
@@ -121,13 +177,14 @@ function UpdateOutput() {
errors.value = '';
console.log("tool", tools_data[tools.value].tool, input.value);
console.log(translate);
translate(tools_data[tools.value].tool, input.value);
translate(tools_data[tools.value].tool, input.value, GetOptions());
}
function OnRuntimeInitialized() {
tools.addEventListener("input", UpdateExamples);
examples.addEventListener("input", UpdateInput);
tools.addEventListener("input", UpdateOutput);
tools.addEventListener("input", UpdateOptions);
examples.addEventListener("input", UpdateInput);
input.addEventListener('input', UpdateOutput);
fetch("tools.json")
@@ -136,9 +193,10 @@ function OnRuntimeInitialized() {
tools_data = data;
UpdateTools();
UpdateExamples()
UpdateOptions();
UpdateInput();
UpdateOutput();
translate = Module.cwrap('translate', 'void', ['string','string']);
translate = Module.cwrap('translate', 'void', ['string','string', 'string']);
})
}
+5 -5
View File
@@ -23,19 +23,19 @@ int main(int, const char**) {
std::string input_string((std::istreambuf_iterator<char>(input)),
std::istreambuf_iterator<char>());
std::string output_string((std::istreambuf_iterator<char>(output)),
std::string output_expected((std::istreambuf_iterator<char>(output)),
std::istreambuf_iterator<char>());
translator->Process(input_string);
std::string output_computed = (*translator)(input_string, "");
if (translator->Output() == output_string) {
if (output_computed == output_expected) {
std::cout << " [PASS] " << test << std::endl;
} else {
std::cout << " [FAIL] " << test << std::endl;
std::cout << "---[Output]------------------" << std::endl;
std::cout << translator->Output() << std::endl;
std::cout << output_computed << std::endl;
std::cout << "---[Expected]----------------" << std::endl;
std::cout << output_string << std::endl;
std::cout << output_expected << std::endl;
std::cout << "---------------------" << std::endl;
}
}
+1 -2
View File
@@ -8,8 +8,7 @@ int main(int, const char**) {
}
auto sequence = SequenceTranslator();
sequence->Process(input);
std::cout << sequence->Output() << std::endl;
std::cout << (*sequence)(input, "") << std::endl;
return 0;
}
+2 -4
View File
@@ -17,12 +17,10 @@ void replaceAll(std::string& str,
extern "C" {
void translate(const char* translator_name, const char* input) {
void translate(const char* translator_name, const char* input, const char* options) {
std::string translator_string = translator_name;
auto translator = TranslatorFromName(translator_name);
translator->Process(input);
std::string command = translator->Output();
std::string command = (*translator)(input, options);
replaceAll(command, "\n", "\\n");
replaceAll(command, "\"", "\\\"");
command = "output.value=\"" + command + "\";";
+41 -15
View File
@@ -56,31 +56,57 @@ std::string Screen::ToString() {
return ss.str();
}
void Screen::DrawHorizontalLine(int left, int right, int y) {
void Screen::DrawHorizontalLine(int left, int right, int y, wchar_t c) {
for (int x = left; x <= right; ++x) {
lines_[y][x] = U'';
lines_[y][x] = c;
}
}
void Screen::DrawVerticalLine(int top, int bottom, int x) {
void Screen::DrawVerticalLine(int top, int bottom, int x, wchar_t c) {
for (int y = top; y <= bottom; ++y) {
lines_[y][x] = U'';
}
}
void Screen::ASCIIfy() {
for(auto& line : lines_) {
for(auto& c : line) {
switch(c) {
case U'': c = '-'; break;
case U'': c = '|'; break;
case U'': c = '.'; break;
case U'': c = '`'; break;
case U'': c = '.'; break;
case U'': c = '\''; break;
case U'': c = '-'; break;
case U'': c = '-'; break;
void Screen::ASCIIfy(int style) {
if (style == 0) {
for(auto& line : lines_) {
for(auto& c : line) {
switch(c) {
case U'': c = '-'; break;
case U'': c = '|'; break;
case U'': c = '.'; break;
case U'': c = '\''; break;
case U'': c = '.'; break;
case U'': c = '\''; break;
case U'': c = '-'; break;
case U'': c = '-'; break;
case U'': c = '^'; break;
case U'': c = 'V'; break;
}
}
}
return;
}
if (style == 1) {
for(auto& line : lines_) {
for(auto& c : line) {
switch(c) {
case U'': c = '-'; break;
case U'': c = '|'; break;
case U'': c = '.'; break;
case U'': c = '\''; break;
case U'': c = '.'; break;
case U'': c = '\''; break;
case U'': c = '.'; break;
case U'': c = '\''; break;
case U'': c = '^'; break;
case U'': c = 'V'; break;
}
}
}
return;
}
}
+3 -3
View File
@@ -14,9 +14,9 @@ class Screen {
void DrawText(int x, int y, const std::wstring& text);
void DrawBox(int x, int y, int w, int h);
void DrawBoxedText(int x, int y, const std::wstring& text);
void DrawHorizontalLine(int left, int right, int y);
void DrawVerticalLine(int top, int bottom, int x);
void ASCIIfy();
void DrawHorizontalLine(int left, int right, int y, wchar_t c = U'');
void DrawVerticalLine(int top, int bottom, int x, wchar_t c = U'');
void ASCIIfy(int style = 0);
std::string ToString();
private:
+8 -1
View File
@@ -116,7 +116,7 @@ textarea {
border:1px solid gray;
}
#menu_bar_submenu {
.menu_bar_submenu {
padding:12px;
display:inline-block;
border-right: 1px solid gray;
@@ -126,3 +126,10 @@ select {
font:inherit;
size:50px;
}
.option {
margin:0px;
padding:0px;
padding-right:3px;
padding-left:3px;
}
+32 -25
View File
@@ -2,6 +2,14 @@
{
"tool": "Sequence",
"description": "Sequence diagram",
"options": [
{
"type":"checkbox",
"default":false,
"label":"ASCII-only",
"name":"ascii_only"
}
],
"examples": [
{
"title": "------------------------",
@@ -62,6 +70,14 @@
{
"tool": "PlanarGraph",
"description": "Planar graph",
"options": [
{
"type":"checkbox",
"default":false,
"label":"ASCII-only",
"name":"ascii_only"
}
],
"examples": [
{
"title": "------------------------",
@@ -180,8 +196,22 @@
]
},
{
"tool": "LineNumberUnicode",
"description": "Line number unicode",
"tool": "Frame",
"description": "Frame/border/line_number",
"options": [
{
"type":"checkbox",
"default":true,
"label":"Line number",
"name":"line_number"
},
{
"type":"checkbox",
"default":false,
"label":"ASCII-only",
"name":"ascii_only"
}
],
"examples": [
{
"title": "------------------------",
@@ -201,28 +231,5 @@
]
}
]
},
{
"tool": "LineNumberASCII",
"description": "Line number ASCII",
"examples": [
{
"title": "------------------------",
"empty": true
},
{
"title":"Hello world",
"content": [
"#include <iostream>",
"using namespace std;",
"",
"int main() ",
"{",
" cout << \"Hello, World!\";",
" return 0;",
"}"
]
}
]
}
]
+17 -4
View File
@@ -1,13 +1,26 @@
#include "translator/Translator.h"
#include <sstream>
#include <string>
std::unique_ptr<Translator> TranslatorFromName(const std::string name) {
if (name == "Sequence")
return SequenceTranslator();
if (name == "LineNumberASCII")
return LineNumberASCIITranslator();
if (name == "LineNumberUnicode")
return LineNumberUnicodeTranslator();
if (name == "Frame")
return FrameTranslator();
if (name == "PlanarGraph")
return PlanarGraphTranslator();
return nullptr;
}
// static
std::map<std::string, std::string> Translator::SerializeOption(
const std::string& options) {
std::map<std::string, std::string> m;
std::stringstream ss(options);
std::string label, value;
while (std::getline(ss, label) && std::getline(ss, value)) {
m[label] = value;
}
return m;
}
+7 -6
View File
@@ -1,21 +1,22 @@
#ifndef TRANSLATOR_TRANSLATOR
#define TRANSLATOR_TRANSLATOR
#include <string>
#include <map>
#include <memory>
#include <string>
class Translator {
public:
virtual ~Translator() = default;
virtual void Process(const std::string& input) = 0;
virtual std::string Output() = 0;
virtual std::string operator()(const std::string& input,
const std::string& options) = 0;
static std::map<std::string, std::string> SerializeOption(
const std::string& options);
};
std::unique_ptr<Translator> SequenceTranslator();
std::unique_ptr<Translator> LineNumberASCIITranslator();
std::unique_ptr<Translator> LineNumberUnicodeTranslator();
std::unique_ptr<Translator> FrameTranslator();
std::unique_ptr<Translator> PlanarGraphTranslator();
std::unique_ptr<Translator> TranslatorFromName(const std::string name);
#endif /* end of include guard: TRANSLATOR_TRANSLATOR */
+3
View File
@@ -0,0 +1,3 @@
add_library(translator_frame STATIC
Frame.cpp
)
+95
View File
@@ -0,0 +1,95 @@
#include <sstream>
#include <vector>
#include "screen/Screen.h"
#include "translator/Translator.h"
class Frame : public Translator {
public:
virtual ~Frame() = default;
virtual std::string operator()(const std::string& input,
const std::string& options_string) {
auto options = SerializeOption(options_string);
bool ascii_only = false;
if (options.count("ascii_only") && options.at("ascii_only") == "true")
ascii_only = true;
bool line_number = true;
if (options.count("line_number") && options.at("line_number") == "false")
line_number = false;
// cut by lines.
std::stringstream ss(input);
std::vector<std::wstring> lines;
std::string line;
while (std::getline(ss, line)) {
lines.push_back(to_wstring(line));
}
int number_length = 0;
int max_number = 1;
while (max_number <= (int)lines.size()) {
max_number *= 10;
number_length++;
}
int text_max_width = 0;
for (const auto& line : lines) {
text_max_width = std::max(text_max_width, (int)line.size());
}
int width, height, text_x;
if (line_number) {
width = number_length + text_max_width + 3;
height = lines.size() + 2 + ascii_only;
text_x = number_length + 2;
} else {
width = text_max_width + 2;
height = lines.size() + 2 + ascii_only;
text_x = 1;
}
int text_y = ascii_only ? 2 : 1;
Screen screen(width, height);
// Draw text.
for (int y = 0; y < lines.size(); ++y) {
screen.DrawText(text_x, text_y + y, lines[y]);
}
// Draw line number.
if (line_number) {
for (int y = 0; y < lines.size(); ++y) {
screen.DrawText(1, text_y + y, to_wstring(std::to_string(y + 1)));
}
}
// Draw box.
if (ascii_only) {
screen.DrawHorizontalLine(1, width - 2, 0, U'_');
screen.DrawHorizontalLine(1, width - 2, height - 1, U'_');
screen.DrawVerticalLine(1, height - 1, 0);
screen.DrawVerticalLine(1, height - 1, width - 1);
} else {
screen.DrawBox(0, 0, width, height);
}
// Draw the line number separator.
if (line_number) {
if (ascii_only) {
screen.DrawVerticalLine(1, height - 1, number_length + 1, U'|');
} else {
screen.DrawPixel(number_length + 1, 0, U'');
screen.DrawVerticalLine(1, height - 1, number_length + 1);
screen.DrawPixel(number_length + 1, height - 1, U'');
}
}
return screen.ToString();
}
};
std::unique_ptr<Translator> FrameTranslator() {
return std::make_unique<Frame>();
}
@@ -1,3 +0,0 @@
add_library(translator_line_number_ascii STATIC
LineNumberASCII.cpp
)
@@ -1,61 +0,0 @@
#include <sstream>
#include <vector>
#include "screen/Screen.h"
#include "translator/Translator.h"
class LineNumberASCII : public Translator {
public:
virtual ~LineNumberASCII() = default;
virtual void Process(const std::string& input) {
// cut by lines.
std::stringstream ss(input);
std::vector<std::wstring> lines;
std::string line;
while (std::getline(ss, line)) {
lines.push_back(to_wstring(line));
}
int number_length = 0;
int max_number = 1;
while (max_number <= (int)lines.size()) {
max_number *= 10;
number_length++;
}
int text_max_width = 0;
for (const auto& line : lines) {
text_max_width = std::max(text_max_width, (int)line.size());
}
int width = number_length + text_max_width + 3;
int height = lines.size() + 3;
Screen screen(width, height);
int y = 2;
for (const auto& line : lines) {
screen.DrawText(number_length + 2, y, line);
screen.DrawText(1, y, to_wstring(std::to_string(y-1)));
++y;
}
screen.DrawText(1, 0, std::wstring(width - 2, '_'));
screen.DrawText(1, height - 1, std::wstring(width - 2, '_'));
std::wstring vertical_bar = to_wstring("|");
for (int y = 1; y < height; ++y) {
screen.DrawText(0, y, vertical_bar);
screen.DrawText(number_length + 1, y, vertical_bar);
screen.DrawText(width - 1, y, vertical_bar);
}
output_ = screen.ToString();
}
virtual std::string Output() { return output_; }
private:
std::string output_;
};
std::unique_ptr<Translator> LineNumberASCIITranslator() {
return std::make_unique<LineNumberASCII>();
}
@@ -1,3 +0,0 @@
add_library(translator_line_number_unicode STATIC
LineNumberUnicode.cpp
)
@@ -1,57 +0,0 @@
#include <sstream>
#include <vector>
#include "screen/Screen.h"
#include "translator/Translator.h"
class LinNumberUnicode : public Translator {
public:
virtual ~LinNumberUnicode() = default;
virtual void Process(const std::string& input) {
// cut by lines.
std::stringstream ss(input);
std::vector<std::wstring> lines;
std::string line;
while (std::getline(ss, line)) {
lines.push_back(to_wstring(line));
}
int number_length = 0;
int max_number = 1;
while (max_number <= (int)lines.size()) {
max_number *= 10;
number_length++;
}
int text_max_width = 0;
for (const auto& line : lines) {
text_max_width = std::max(text_max_width, (int)line.size());
}
int width = number_length + text_max_width + 3;
int height = lines.size() + 2;
Screen screen(width, height);
int y = 1;
for (const auto& line : lines) {
screen.DrawText(number_length + 2, y, line);
screen.DrawText(1, y, to_wstring(std::to_string(y)));
++y;
}
screen.DrawBox(0, 0, width, height);
screen.DrawVerticalLine(1, height - 2, number_length + 1);
screen.DrawPixel(number_length + 1, 0, U'');
screen.DrawPixel(number_length + 1, height - 1, U'');
output_ = screen.ToString();
}
virtual std::string Output() { return output_; }
private:
std::string output_;
};
std::unique_ptr<Translator> LineNumberUnicodeTranslator() {
return std::make_unique<LinNumberUnicode>();
}
+10 -2
View File
@@ -78,9 +78,14 @@ struct PlanarGraph::DrawnVertex {
std::vector<DrawnEdge> edges;
};
void PlanarGraph::Process(const std::string& input) {
std::string PlanarGraph::operator()(const std::string& input,
const std::string& options_string) {
auto options = SerializeOption(options_string);
ascii_only_ = (options["ascii_only"] == "true");
Read(input);
Write();
return output_;
}
void PlanarGraph::Read(const std::string& input) {
@@ -313,6 +318,9 @@ void PlanarGraph::Write() {
edge.Draw(screen, *this);
}
}
if (ascii_only_)
screen.ASCIIfy(1);
output_ += screen.ToString();
};
@@ -379,5 +387,5 @@ void PlanarGraph::Write() {
}
}
Draw();
return Draw();
}
+3 -2
View File
@@ -20,11 +20,12 @@ struct Box {
class PlanarGraph : public Translator {
public:
virtual ~PlanarGraph() = default;
void Process(const std::string& input) override;
std::string Output() override { return output_; }
std::string operator()(const std::string& input,
const std::string& options) override;
//----------------------------------------------------------------------------
private:
bool ascii_only_;
std::string output_;
std::map<std::wstring, int> name_to_id;
+10 -42
View File
@@ -21,11 +21,15 @@ bool Sequence::Dependency::operator<(const Sequence::Dependency& other) const {
return to < other.to;
}
void Sequence::Process(const std::string& input) {
std::string Sequence::operator()(const std::string& input,
const std::string& options_string) {
auto options = SerializeOption(options_string);
ascii_only_ = (options["ascii_only"] == "true");
ComputeInternalRepresentation(input);
UniformizeInternalRepresentation();
Layout();
Draw();
return Draw();
}
void Sequence::ComputeInternalRepresentation(const std::string& input) {
@@ -690,7 +694,7 @@ void Sequence::Message::Draw(Screen& screen) {
}
}
void Sequence::Draw() {
std::string Sequence::Draw() {
// Estimate output dimension.
int width = actors.back().right;
int height = 0;
@@ -710,43 +714,7 @@ void Sequence::Draw() {
message.Draw(screen);
}
output_ = screen.ToString();
//std::wstringstream ss;
//for (auto& actor : actors) {
//ss << "Actor " << actor.name << '\n';
//for (auto& dependency : actor.dependencies) {
//ss << " * " << dependency.from << "<" << dependency.to << '\n';
//}
//ss << " - left = " << actor.left << '\n';
//ss << " - center = " << actor.center << '\n';
//ss << " - right = " << actor.right << '\n';
//ss << '\n';
//}
//for (auto& message : messages) {
//ss << "Message " << '\n';
//ss << " From " << message.from << '\n';
//ss << " To " << message.to << '\n';
//ss << " Id " << message.id << '\n';
//for (auto& i : message.messages) {
//ss << " " << i << '\n';
//}
//ss << '\n';
//}
//for (auto& it : message_index) {
//ss << "(" << it.first << "," << it.second << ")\n";
//}
//for (auto& it : actor_index) {
//ss << "(" << it.first << "," << it.second << ")\n";
//}
//ss << " width = " << width << " height = " << height << "\n";
//output_ += '\n' + to_string(ss.str());
}
std::string Sequence::Output() {
return output_;
if (ascii_only_)
screen.ASCIIfy(0);
return screen.ToString();
}
+5 -3
View File
@@ -14,8 +14,8 @@ class Screen;
class Sequence : public Translator {
public:
virtual ~Sequence() = default;
void Process(const std::string& input) override;
std::string Output() override;
std::string operator()(const std::string& input,
const std::string& options) override;
public: // Not really public.
struct Dependency {
@@ -66,6 +66,8 @@ class Sequence : public Translator {
std::map<std::wstring, int> actor_index;
std::map<int, int> message_index;
bool ascii_only_;
// 1) Parse.
void ComputeInternalRepresentation(const std::string& input);
void AddCommand(SequenceParser::CommandContext* command);
@@ -87,7 +89,7 @@ class Sequence : public Translator {
void LayoutComputeMessagesPositions();
// 4)
void Draw();
std::string Draw();
std::string output_;
};