feat: render a table given a definition
This commit is contained in:
parent
21714ee614
commit
db599fa123
@ -10,7 +10,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.App {
|
.App {
|
||||||
background-color: #282c34;
|
background-color: #1E1E1E;
|
||||||
|
color: #CAD6DC;
|
||||||
min-height: 100vh;
|
min-height: 100vh;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
|||||||
37
src/App.tsx
37
src/App.tsx
@ -1,15 +1,16 @@
|
|||||||
import React, { useState } from 'react';
|
|
||||||
import './App.css';
|
import './App.css';
|
||||||
import TableMethodCode from './TableMethodCode';
|
import TableMethodCodeBlock from './TableMethodCodeBlock';
|
||||||
|
import { TableDefinition } from './TableMethodGenerator';
|
||||||
export interface TableDefinition {
|
import TableRenderer from './TableRenderer';
|
||||||
names?: string[]
|
|
||||||
fields?: (string|undefined)[]
|
|
||||||
widths?: (number|undefined)[]
|
|
||||||
alighments?: ("left"|"right")[]
|
|
||||||
}
|
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
|
let definition: TableDefinition = {
|
||||||
|
names: ["Miestas", "Atsakingas", "Vardas", "Adresas", "Metai"],
|
||||||
|
fields: ["City", "Manager", "Name", "Address", "Year"],
|
||||||
|
widths: [10, 20, 18, 15, 5],
|
||||||
|
alignments: ["left", "left", "left", "left", "right"]
|
||||||
|
}
|
||||||
|
|
||||||
let data = {
|
let data = {
|
||||||
method_name: "PrintLocations",
|
method_name: "PrintLocations",
|
||||||
empty_message: "Nėra",
|
empty_message: "Nėra",
|
||||||
@ -18,17 +19,23 @@ function App() {
|
|||||||
entry_name: "l",
|
entry_name: "l",
|
||||||
entry_type: "Location",
|
entry_type: "Location",
|
||||||
|
|
||||||
definition: {
|
definition
|
||||||
names: ["Miestas", "Atsakingas", "Vardas", "Adresas", "Metai"],
|
|
||||||
fields: ["City", "Manager", "Name", "Address", "Year"],
|
|
||||||
widths: [10, 20, 18, 15, 5]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let test_entries = [
|
||||||
|
["Alytus", "AlytausMuziejusA", "Jonas Jonaitis", "GatveA", "1999"],
|
||||||
|
["Alytus", "AlytausMuziejusB", "Ona Onaite", "GatveB", "2018"],
|
||||||
|
["Kaunas", "KaunasMuziejusC", "Jonas Jonaitis", "GatveC", "2004"],
|
||||||
|
["Klaipėda", "KlaipėdaMuziejusD", "Ona Onaite", "GatveD", "1988"],
|
||||||
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="App">
|
<div className="App">
|
||||||
{TableMethodCode(data)}
|
|
||||||
<main>
|
<main>
|
||||||
|
<hr />
|
||||||
|
{TableMethodCodeBlock(data)}
|
||||||
|
<hr />
|
||||||
|
<TableRenderer definition={definition} entries={test_entries} />
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@ -1,103 +0,0 @@
|
|||||||
import SyntaxHighlighter from 'react-syntax-highlighter';
|
|
||||||
import { docco } from 'react-syntax-highlighter/dist/esm/styles/hljs';
|
|
||||||
import { TableDefinition } from './App';
|
|
||||||
|
|
||||||
export interface TableMethodGeneratorProps {
|
|
||||||
definition: TableDefinition
|
|
||||||
|
|
||||||
method_name?: string
|
|
||||||
empty_message?: string
|
|
||||||
|
|
||||||
container_type?: string
|
|
||||||
container_name?: string
|
|
||||||
entry_type?: string
|
|
||||||
entry_name?: string
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateTableMethod(props: TableMethodGeneratorProps): string {
|
|
||||||
const section_names = props.definition.names || []
|
|
||||||
const method_name = props.method_name || "PrintTable"
|
|
||||||
if (section_names.length == 0) {
|
|
||||||
return `static void ${method_name}()\n{\n}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
const empty_message = props.empty_message || "Empty"
|
|
||||||
const container_name = props.container_name || "container"
|
|
||||||
const container_type = props.container_type || "Container"
|
|
||||||
const entry_name = props.entry_name || "e"
|
|
||||||
const entry_type = props.entry_type || "Entry"
|
|
||||||
const section_widths = props.definition.widths || []
|
|
||||||
const section_alignments = props.definition.alighments || []
|
|
||||||
const section_fields = props.definition.fields || []
|
|
||||||
|
|
||||||
// Total width
|
|
||||||
let total_width = 0
|
|
||||||
for (let i = 0; i < section_names.length; i++) {
|
|
||||||
const section = section_names[i]
|
|
||||||
total_width += section_widths[i] || section.length
|
|
||||||
}
|
|
||||||
total_width += 2 + 2;
|
|
||||||
total_width += 3*(section_names.length-1);
|
|
||||||
|
|
||||||
// Table row
|
|
||||||
let row_components: string[] = []
|
|
||||||
for (let i = 0; i < section_names.length; i++) {
|
|
||||||
const section = section_names[i]
|
|
||||||
const width = section_widths[i] || section.length
|
|
||||||
const alighment = section_alignments[i] || "right"
|
|
||||||
if (alighment == "left") {
|
|
||||||
row_components.push(`{${i},-${width}}`)
|
|
||||||
} else {
|
|
||||||
row_components.push(`{${i},${width}}`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let table_row = "";
|
|
||||||
if (row_components.length > 0) {
|
|
||||||
table_row = "| " + row_components.join(" | ") + " |"
|
|
||||||
}
|
|
||||||
|
|
||||||
// Section names
|
|
||||||
const joined_names = section_names.map((n) => `"${n}"`).join(", ")
|
|
||||||
|
|
||||||
// Section fields
|
|
||||||
const formatted_fields = []
|
|
||||||
for (let i = 0; i < section_names.length; i++) {
|
|
||||||
if (section_fields[i]) {
|
|
||||||
formatted_fields.push(`${entry_name}.${section_fields[i]}`)
|
|
||||||
} else {
|
|
||||||
formatted_fields.push(`"-"`)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const joined_fields = formatted_fields.join(", ")
|
|
||||||
|
|
||||||
// Final code string
|
|
||||||
return `static void ${method_name}(${container_type} ${container_name})\n{
|
|
||||||
if (${container_name}.Count == 0)
|
|
||||||
{
|
|
||||||
Console.WriteLine("${empty_message}");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine(new string('-', ${total_width}));
|
|
||||||
Console.WriteLine("${table_row}", ${joined_names});
|
|
||||||
Console.WriteLine(new string('-', ${total_width}));
|
|
||||||
for (int i = 0; i < ${container_name}.Count; i++)
|
|
||||||
{
|
|
||||||
${entry_type} ${entry_name} = ${container_name}.Get(i);
|
|
||||||
Console.WriteLine("${table_row}", ${joined_fields});
|
|
||||||
}
|
|
||||||
Console.WriteLine(new string('-', ${total_width}));\n}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function TableMethodCode(props: TableMethodGeneratorProps) {
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<SyntaxHighlighter language="csharp" style={docco}>
|
|
||||||
{generateTableMethod(props)}
|
|
||||||
</SyntaxHighlighter>
|
|
||||||
</div>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
export default TableMethodCode
|
|
||||||
16
src/TableMethodCodeBlock.tsx
Normal file
16
src/TableMethodCodeBlock.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
|
||||||
|
import csharp from 'react-syntax-highlighter/dist/esm/languages/hljs/csharp';
|
||||||
|
import { vs2015 } from 'react-syntax-highlighter/dist/esm/styles/hljs';
|
||||||
|
import { generate, TableMethodGeneratorOptions } from './TableMethodGenerator';
|
||||||
|
|
||||||
|
SyntaxHighlighter.registerLanguage('csharp', csharp);
|
||||||
|
|
||||||
|
function TableMethodCodeBlock(props: TableMethodGeneratorOptions) {
|
||||||
|
return (
|
||||||
|
<SyntaxHighlighter language="csharp" style={vs2015}>
|
||||||
|
{generate(props)}
|
||||||
|
</SyntaxHighlighter>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TableMethodCodeBlock
|
||||||
146
src/TableMethodGenerator.ts
Normal file
146
src/TableMethodGenerator.ts
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
type Alignment = "left"|"right"
|
||||||
|
|
||||||
|
export interface TableDefinition {
|
||||||
|
names?: string[]
|
||||||
|
fields?: (string|undefined)[]
|
||||||
|
widths?: (number|undefined)[]
|
||||||
|
alignments?: (Alignment|undefined)[]
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TableMethodGeneratorOptions {
|
||||||
|
definition: TableDefinition
|
||||||
|
|
||||||
|
method_name?: string
|
||||||
|
empty_message?: string
|
||||||
|
|
||||||
|
container_type?: string
|
||||||
|
container_name?: string
|
||||||
|
entry_type?: string
|
||||||
|
entry_name?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_total_width(definition: TableDefinition): number {
|
||||||
|
let names = definition.names || []
|
||||||
|
if (names.length == 0) { return 0; }
|
||||||
|
|
||||||
|
let total_width = 0
|
||||||
|
let widths = definition.widths || []
|
||||||
|
for (let i = 0; i < names.length; i++) {
|
||||||
|
const name = names[i]
|
||||||
|
total_width += widths[i] || name.length
|
||||||
|
}
|
||||||
|
total_width += 2 + 2;
|
||||||
|
total_width += 3*(names.length-1);
|
||||||
|
|
||||||
|
return total_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generate(options: TableMethodGeneratorOptions): string {
|
||||||
|
const section_names = options.definition.names || []
|
||||||
|
const method_name = options.method_name || "PrintTable"
|
||||||
|
if (section_names.length == 0) {
|
||||||
|
return `static void ${method_name}()\n{\n}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const empty_message = options.empty_message || "Empty"
|
||||||
|
const container_name = options.container_name || "container"
|
||||||
|
const container_type = options.container_type || "Container"
|
||||||
|
const entry_name = options.entry_name || "e"
|
||||||
|
const entry_type = options.entry_type || "Entry"
|
||||||
|
const section_widths = options.definition.widths || []
|
||||||
|
const section_alignments = options.definition.alignments || []
|
||||||
|
const section_fields = options.definition.fields || []
|
||||||
|
|
||||||
|
// Total width
|
||||||
|
const total_width = get_total_width(options.definition)
|
||||||
|
|
||||||
|
// Table row
|
||||||
|
let row_components: string[] = []
|
||||||
|
for (let i = 0; i < section_names.length; i++) {
|
||||||
|
const section = section_names[i]
|
||||||
|
const width = section_widths[i] || section.length
|
||||||
|
const alighment = section_alignments[i] || "right"
|
||||||
|
if (alighment == "left") {
|
||||||
|
row_components.push(`{${i},-${width}}`)
|
||||||
|
} else {
|
||||||
|
row_components.push(`{${i},${width}}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let table_row = "";
|
||||||
|
if (row_components.length > 0) {
|
||||||
|
table_row = "| " + row_components.join(" | ") + " |"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Section names
|
||||||
|
const joined_names = section_names.map((n) => `"${n}"`).join(", ")
|
||||||
|
|
||||||
|
// Section fields
|
||||||
|
const formatted_fields = []
|
||||||
|
for (let i = 0; i < section_names.length; i++) {
|
||||||
|
if (section_fields[i]) {
|
||||||
|
formatted_fields.push(`${entry_name}.${section_fields[i]}`)
|
||||||
|
} else {
|
||||||
|
formatted_fields.push(`"-"`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const joined_fields = formatted_fields.join(", ")
|
||||||
|
|
||||||
|
// Final code string
|
||||||
|
return `static void ${method_name}(${container_type} ${container_name})\n{
|
||||||
|
if (${container_name}.Count == 0)
|
||||||
|
{
|
||||||
|
Console.WriteLine("${empty_message}");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine(new string('-', ${total_width}));
|
||||||
|
Console.WriteLine("${table_row}", ${joined_names});
|
||||||
|
Console.WriteLine(new string('-', ${total_width}));
|
||||||
|
for (int i = 0; i < ${container_name}.Count; i++)
|
||||||
|
{
|
||||||
|
${entry_type} ${entry_name} = ${container_name}.Get(i);
|
||||||
|
Console.WriteLine("${table_row}", ${joined_fields});
|
||||||
|
}
|
||||||
|
Console.WriteLine(new string('-', ${total_width}));\n}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function render_table_row(definition: TableDefinition, entry: string[]): string {
|
||||||
|
let names = definition.names || []
|
||||||
|
if (names.length == 0) { return ""; }
|
||||||
|
|
||||||
|
const columns: string[] = []
|
||||||
|
const alighments = definition.alignments || []
|
||||||
|
const widths = definition.widths || []
|
||||||
|
for (let i = 0; i < names.length; i++) {
|
||||||
|
const value = entry[i] || "";
|
||||||
|
const alighment = alighments[i] || "right"
|
||||||
|
const width = widths[i] || names[i].length
|
||||||
|
|
||||||
|
const filler = " ".repeat(Math.max(width - value.length, 0));
|
||||||
|
if (alighment == "left") {
|
||||||
|
columns.push(value + filler);
|
||||||
|
} else {
|
||||||
|
columns.push(filler + value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return "| " + columns.join(" | ") + " |"
|
||||||
|
}
|
||||||
|
|
||||||
|
export function render_table(definition: TableDefinition, entries: string[][]): string {
|
||||||
|
if (!definition.names) {return ""; }
|
||||||
|
|
||||||
|
const total_width = get_total_width(definition)
|
||||||
|
const seperator = "-".repeat(total_width)
|
||||||
|
|
||||||
|
const lines = []
|
||||||
|
lines.push(seperator)
|
||||||
|
lines.push(render_table_row(definition, definition.names))
|
||||||
|
lines.push(seperator)
|
||||||
|
for (let i = 0; i < entries.length; i++) {
|
||||||
|
lines.push(render_table_row(definition, entries[i]))
|
||||||
|
}
|
||||||
|
lines.push(seperator)
|
||||||
|
|
||||||
|
return lines.join("\n")
|
||||||
|
}
|
||||||
16
src/TableRenderer.tsx
Normal file
16
src/TableRenderer.tsx
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { render_table, TableDefinition } from "./TableMethodGenerator"
|
||||||
|
|
||||||
|
export interface TableRendererProps {
|
||||||
|
definition: TableDefinition,
|
||||||
|
entries: string[][]
|
||||||
|
}
|
||||||
|
|
||||||
|
function TableRenderer(props: TableRendererProps) {
|
||||||
|
return (
|
||||||
|
<pre>
|
||||||
|
{render_table(props.definition, props.entries)}
|
||||||
|
</pre>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default TableRenderer
|
||||||
Loading…
Reference in New Issue
Block a user