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

Table truncates long strings #972

Open
theqbz opened this issue Dec 19, 2024 · 1 comment
Open

Table truncates long strings #972

theqbz opened this issue Dec 19, 2024 · 1 comment

Comments

@theqbz
Copy link

theqbz commented Dec 19, 2024

Sometimes I want to display a very long string in an ftxui::Table cell. In such a case, the table reaches the maximum possible size - for example, the edge of the screen - but the long string does not form a line break, even if I store it in a ftxui::paragraph instead of text. The end of the string is simply cut off. Can you suggest a method for how such long strings could be displayed properly in an ftxui::Table?

I think it is possible that perhaps the ftxui::paragraph does not know the boundaries within the table, within which it can extend, so the line break does not apply. If so, how can I pass this information to the paragraph?

Actual result:

First column  The Very Long String
───────────────────────────────────────────────────────────────────────────────────
something     012345678901234567890123456789012345678901234567890123456789012345678

Expected result:

First column  The Very Long String
───────────────────────────────────────────────────────────────────────────────────
something     012345678901234567890123456789012345678901234567890123456789012345678
              90123456789

Sorry for this poor illustration, I hope it helps you understand my idea.

I use ftxui::Table through a wrapper class, in two ways:

  • No interactive screen loop is running, just displaying data in the terminal. (using MyTable::print())
  • Interactive screen loop is running and I embed the Table as an ftxui::Element in an ftxui::hbox. (using MyTable::getRenderer())
// In MyTable.cpp
//
// Member variables used in the following functions:
// m_table is an ftxui::Table
// m_tableContent is a std::vector<ftxui::Elements>

void MyTable::setTableContent(const std::vector<std::vector<std::string>>& p_tableContent)
{
    m_tableContent.clear();
    std::vector<ftxui::Elements> table {};
    for (const std::vector<std::string>& row : p_tableContent) {
        ftxui::Elements tableRow {};
        for (const std::string& cell : row) {
            tableRow.push_back(ftxui::hbox(ftxui::paragraph(cell)));
        }
        m_tableContent.push_back(tableRow);
    }
}

void MyTable::print()
{
    if (m_tableContent.empty()) {
        return;
    }
    m_table = m_tableContent;
    m_table.SelectAll().SeparatorVertical(ftxui::EMPTY);
    m_table.SelectRow(0).BorderBottom(ftxui::LIGHT);
    ftxui::Element table { m_table.Render() };
    ftxui::Screen screen { ftxui::Screen::Create(ftxui::Dimension::Fit(table)) };
    ftxui::Render(screen, table);
    screen.Print();
}

ftxui::Element MyTable::getRenderer()
{
    if (!m_tableContent.empty()) {
        m_table = m_tableContent;
        m_table.SelectAll().SeparatorVertical(ftxui::LIGHT);
        m_table.SelectRow(0).BorderBottom(ftxui::LIGHT);
        m_table.SelectRow(0).DecorateCells(ftxui::bold);
    }
    return m_table.Render();
}
@ArthurSonzogni
Copy link
Owner

Hello @theqbz,

See the paragraph implementation using flexbox:

namespace {
Elements Split(const std::string& the_text) {
  Elements output;
  std::stringstream ss(the_text);
  std::string word;
  while (std::getline(ss, word, ' ')) {
    output.push_back(text(word));
  }
  return output;
}
}  // namespace

/// @brief Return an element drawing the paragraph on multiple lines.
/// @ingroup dom
/// @see flexbox.
Element paragraph(const std::string& the_text) {
  return paragraphAlignLeft(the_text);
}

/// @brief Return an element drawing the paragraph on multiple lines, aligned on
/// the left.
/// @ingroup dom
/// @see flexbox.
Element paragraphAlignLeft(const std::string& the_text) {
  static const auto config = FlexboxConfig().SetGap(1, 0);
  return flexbox(Split(the_text), config);
}

You see we split the text into words, and put each word into a flexbox. As a result, you can't split elsewhere than inside a space.

What you can try:

Element SplitableText(const std::string& the_text) {
  // Split every ~8 characters.
  Elements miniwords;
  for (size_t i = 0; i < the_text.size(); i += 8) {
    miniwords.push_back(text(the_text.substr(i, 8)));
  }
  return flexbox(std::move(miniwords));
}

I hope this will be working for you, but note that flexbox doesn't work flawlessly.
Note that flexbox is not working flawlessly. I hope

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

No branches or pull requests

2 participants