Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: print multiple tables, side-by-side #375

Open
jrr opened this issue Jun 20, 2021 · 4 comments
Open

Feature request: print multiple tables, side-by-side #375

jrr opened this issue Jun 20, 2021 · 4 comments
Labels
enhancement New feature or request

Comments

@jrr
Copy link

jrr commented Jun 20, 2021

Thanks for this library. I really appreciate how easy it was to quickly understand and apply. Nice job on the docs and API design!

I found myself printing a couple narrow tables, where they could have fit side-by-side in my terminal. Something like this:

       Table One               Table Two 
┌───────┬──────┬──────┐ ┌───────┬──────┬──────┐
│ Foo   │ Bar  │ Baz  │ │ Foo   │ Bar  │ Baz  │
├───────┼──────┼──────┤ ├───────┼──────┼──────┤
│ aaa   │   13 │    8 │ │ aaa   │   43 │    8 │
│ bbb   │   99 │   10 │ │ bbb   │   12 │   10 │
│ ccc   │   91 │    9 │ │ ccc   │   12 │    9 │
│ ddd   │   45 │    6 │ │ ddd   │   75 │    6 │
│ eee   │   32 │    4 │ │ eee   │   62 │    4 │
│ fff   │   31 │    4 │ │ fff   │   61 │    4 │
│ ggg   │   26 │    3 │ │ ggg   │   56 │    3 │
│ hhh   │   12 │    7 │ └───────┴──────┴──────┘
│ iii   │   21 │    7 │ 
└───────┴──────┴──────┘ 

Would you be open to a PR that adds something like this? I'm thinking the API could be something like:

import { printTables } from "console-table-printer";
// ...
printTables(table1,table2);
@jrr
Copy link
Author

jrr commented Jun 20, 2021

It would be fun to generalize this to n tables, but for now here's a quick-and-dirty solution for two:

function printTables(table1: Table, table2: Table) {
  const t1 = table1.render().split("\n");
  const t2 = table2.render().split("\n");

  const t1EmptyRow = " ".repeat(t1[1].length);

  const together = _.zip(t1, t2).map(
    ([a, b]) => `${a || t1EmptyRow} ${b || ""}`
  );

  together.forEach((line) => console.log(line));
}

@ayonious
Copy link
Owner

ayonious commented Jul 2, 2021

@jrr thanks for the idea.

It does not seem to be a very Common usecase. If this is preferred by many others I will reconsider. I will keep this Issue open to see how many people prefers this.

@ayonious ayonious added the enhancement New feature or request label Jul 2, 2021
@ArjixWasTaken
Copy link

ArjixWasTaken commented Aug 5, 2021

@jrr

It would be fun to generalize this to n tables, but for now here's a quick-and-dirty solution for two:

Old Code
const zip = (...args) => {
    // https://stackoverflow.com/a/55648257/13077523
    const iterators = args.map((arr) => arr[Symbol.iterator]());
    let iterateInstances = iterators.map((i) => i.next());
    ret = [];
    while (iterateInstances["some"]((it) => !it.done)) {
        ret.push(iterateInstances.map((it) => it.value));
        iterateInstances = iterators.map((i) => i.next());
    }
    return ret;
};

const printTables = (...tables) => {
    const tablesLines = tables.map((table) => table.render().split("\n"));
    const emptyRows = tablesLines.map((t) => " ".repeat(t[1].length));
    const together = [];

    zip(...tablesLines).forEach((row) => {
        let out = "";

        row.forEach((t, index) => {
            out += t || emptyRows[index];
            out += " ";
        });
        together.push(out);
    });

    together.forEach((line) => console.log(line));
};

There you go!

Honestly you could directly console.log(out) w/o saving to an array, but oh well.

This does not take into account the console size, so it is bound to break on a big number of tables.

New code that considers the terminal's width.
const zip = (...args) => {
    // https://stackoverflow.com/a/55648257/13077523
    const iterators = args.map((arr) => arr[Symbol.iterator]());
    let iterateInstances = iterators.map((i) => i.next());
    ret = [];
    while (iterateInstances["some"]((it) => !it.done)) {
        ret.push(iterateInstances.map((it) => it.value));
        iterateInstances = iterators.map((i) => i.next());
    }
    return ret;
};

const printTables = (...tables) => {
    const tablesLines = tables.map((table) => table.render().split("\n"));
    const emptyRows = tablesLines.map((t) => " ".repeat(t[1].length));
    const together = [];
    const groups = [];

    if (
        emptyRows.reduce((a, b) => a + b).length + emptyRows.length - 2 >
        (process.stdout.columns || 80)
    ) {
        let group = [];
        let size = emptyRows.length - 1;
        let index = 0;

        while (emptyRows[index] && size < (process.stdout.columns || 80)) {
            if (
                size + emptyRows[index].length >
                (process.stdout.columns || 80)
            ) {
                size = 0;
                groups.push(Array.from(group));
                group.length = 0;
            } else {
                group.push(tablesLines[index]);
                size += emptyRows[index].length;
                index++;
            }
        }
        if (group.length != 0) {
            groups.push(group);
        }
    } else {
        groups.push(tablesLines);
    }
    for (const group of groups) {
        zip(...group).forEach((row) => {
            let out = "";

            row.forEach((t, index) => {
                out += t || emptyRows[index];
                out += " ";
            });
            together.push(out.trim());
        });
    }

    together.forEach((line) => console.log(line));
};
Example output if the console's width is 40 characters long
    Table 1         Table 2    
┌───────┬─────┐ ┌───────┬─────┐
│ index │ num │ │ index │ num │
├───────┼─────┤ ├───────┼─────┤
│     0 │   1 │ │     0 │   1 │
│     1 │   2 │ │     1 │   2 │
│     0 │   1 │ │     0 │   1 │
│     1 │   2 │ │     1 │   2 │
└───────┴─────┘ └───────┴─────┘
Example output if the console's width is 20 characters long
    Table 1    
┌───────┬─────┐
│ index │ num │
├───────┼─────┤
│     0 │   1 │
│     1 │   2 │
│     0 │   1 │
│     1 │   2 │
└───────┴─────┘
    Table 2    
┌───────┬─────┐
│ index │ num │
├───────┼─────┤
│     0 │   1 │
│     1 │   2 │
│     0 │   1 │
│     1 │   2 │
└───────┴─────┘

@ArjixWasTaken
Copy link

Wow, I wasted 4 hours of my life trying to make it consider the terminal's width....
But at least I did it!

I'll never do shit like this again. 🤣🤣🤣

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

3 participants