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: add DoNotFillSpaceWhenEndOfLine option #318

Closed

Conversation

nexustar
Copy link

@nexustar nexustar commented Apr 10, 2024

Proposed Changes

  • Allow not fill space on the last column. It is useful to draw table without border when table is wider then screen

Fixes #<insert Issue # here if applicable>.
before:
pic 2024-04-10 20-58-56
after:
pic 2024-04-10 20-58-08

Copy link

sonarcloud bot commented Apr 10, 2024

Quality Gate Passed Quality Gate passed

Issues
0 New issues
0 Accepted issues

Measures
0 Security Hotspots
No data about Coverage
0.0% Duplication on New Code

See analysis details on SonarCloud

@coveralls
Copy link

Pull Request Test Coverage Report for Build 8631686475

Details

  • 1 of 11 (9.09%) changed or added relevant lines in 2 files are covered.
  • 1 unchanged line in 1 file lost coverage.
  • Overall coverage decreased (-0.3%) to 99.69%

Changes Missing Coverage Covered Lines Changed/Added Lines %
table/table.go 1 5 20.0%
text/align.go 0 6 0.0%
Files with Coverage Reduction New Missed Lines %
table/table.go 1 99.03%
Totals Coverage Status
Change from base Build 8592698758: -0.3%
Covered Lines: 3538
Relevant Lines: 3549

💛 - Coveralls

@jedib0t
Copy link
Owner

jedib0t commented Apr 11, 2024

@nexustar while I appreciate this contribution, I feel this feature is just adding a lot of logic to a library when this can be easily achieved outside the library by the caller. In fact your example shows how making the last column empty is bad when borders are enabled.

Here is how you'd get it done outside the library:

package main

import (
	"fmt"
	"strings"

	"github.com/jedib0t/go-pretty/v6/table"
)

func main() {
	tw := table.NewWriter()
	tw.AppendHeader(table.Row{"#", "First Name", "Last Name", "Salary"})
	tw.AppendRows([]table.Row{
		{1, "Arya", "Stark", 3000},
		{20, "Jon", "Snow", 2000, "You know nothing, Jon Snow!"},
		{300, "Tyrion", "Lannister", 5000},
	})
	tw.Style().Options.DrawBorder = false

	for _, line := range strings.Split(tw.Render(), "\n") {
		fmt.Println(strings.TrimRight(line, " "))
	}
}

Output:

   # | FIRST NAME | LAST NAME | SALARY |
-----+------------+-----------+--------+-----------------------------
   1 | Arya       | Stark     |   3000 |
  20 | Jon        | Snow      |   2000 | You know nothing, Jon Snow!
 300 | Tyrion     | Lannister |   5000 |

Comment on lines +773 to +780
// ┌─────┬────────────┬───────────┬────────┬─────────────────────────────┐
// │ # │ FIRST NAME │ LAST NAME │ SALARY ││
// ├─────┼────────────┼───────────┼────────┼─────────────────────────────┤
// │ 1 │ Arya │ Stark │ 3000 ││
// │ 20 │ Jon │ Snow │ 2000 │ You know nothing, Jon Snow! │
// │ 300 │ Tyrion │ Lannister │ 5000 │test│
// │ │ │ TOTAL │ 10000 │anothertest│
// └─────┴────────────┴───────────┴────────┴─────────────────────────────┘
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the example I was referring to.

@jedib0t
Copy link
Owner

jedib0t commented Apr 11, 2024

An alternate approach would be to set the maximum length you want for each column, esp the last column in your example since it seems to be the longest. Rendering columns with really long text is usually not a great idea since you never know how wide a terminal will be at the end user. If you expect abnormally long text in a column, I highly recommend controlling the width.

Here's how you'd restrict the width of a column:

package main

import (
	"fmt"
	"strings"

	"github.com/jedib0t/go-pretty/v6/table"
	"github.com/jedib0t/go-pretty/v6/text"
)

func main() {
	tw := table.NewWriter()
	tw.AppendHeader(table.Row{"#", "First Name", "Last Name", "Salary"})
	tw.AppendRows([]table.Row{
		{1, "Arya", "Stark", 3000},
		{20, "Jon", "Snow", 2000, "You know nothing, Jon Snow!"},
		{300, "Tyrion", "Lannister", 5000},
	})
	tw.Style().Options.DrawBorder = false

	tw.SetColumnConfigs([]table.ColumnConfig{
		{Number: 5, WidthMax: 10, WidthMaxEnforcer: text.WrapText},
		// Number: 5 corresponds to 5th column
		// Try other enforcers, for ex. text.WrapSoft
	})

	fmt.Println(tw.Render())
}

Output:

   # | FIRST NAME | LAST NAME | SALARY |            
-----+------------+-----------+--------+------------
   1 | Arya       | Stark     |   3000 |            
  20 | Jon        | Snow      |   2000 | You know n 
     |            |           |        | othing, Jo 
     |            |           |        | n Snow!    
 300 | Tyrion     | Lannister |   5000 |            

@nexustar
Copy link
Author

nexustar commented Apr 11, 2024

@nexustar while I appreciate this contribution, I feel this feature is just adding a lot of logic to a library when this can be easily achieved outside the library by the caller. In fact your example shows how making the last column empty is bad when borders are enabled.

Here is how you'd get it done outside the library:

package main

import (
	"fmt"
	"strings"

	"github.com/jedib0t/go-pretty/v6/table"
)

func main() {
	tw := table.NewWriter()
	tw.AppendHeader(table.Row{"#", "First Name", "Last Name", "Salary"})
	tw.AppendRows([]table.Row{
		{1, "Arya", "Stark", 3000},
		{20, "Jon", "Snow", 2000, "You know nothing, Jon Snow!"},
		{300, "Tyrion", "Lannister", 5000},
	})
	tw.Style().Options.DrawBorder = false

	for _, line := range strings.Split(tw.Render(), "\n") {
		fmt.Println(strings.TrimRight(line, " "))
	}
}

Output:

   # | FIRST NAME | LAST NAME | SALARY |
-----+------------+-----------+--------+-----------------------------
   1 | Arya       | Stark     |   3000 |
  20 | Jon        | Snow      |   2000 | You know nothing, Jon Snow!
 300 | Tyrion     | Lannister |   5000 |

I agree that most logic of this PR could be achieved by caller. But I think "AlignDisabled" is useful for upstream. The example you mentioned will lost spaces that intentionally added by the user.(Although I can't imagine why users would do this now)

@nexustar
Copy link
Author

An alternate approach would be to set the maximum length you want for each column, esp the last column in your example since it seems to be the longest. Rendering columns with really long text is usually not a great idea since you never know how wide a terminal will be at the end user. If you expect abnormally long text in a column, I highly recommend controlling the width.

Here's how you'd restrict the width of a column:

package main

import (
	"fmt"
	"strings"

	"github.com/jedib0t/go-pretty/v6/table"
	"github.com/jedib0t/go-pretty/v6/text"
)

func main() {
	tw := table.NewWriter()
	tw.AppendHeader(table.Row{"#", "First Name", "Last Name", "Salary"})
	tw.AppendRows([]table.Row{
		{1, "Arya", "Stark", 3000},
		{20, "Jon", "Snow", 2000, "You know nothing, Jon Snow!"},
		{300, "Tyrion", "Lannister", 5000},
	})
	tw.Style().Options.DrawBorder = false

	tw.SetColumnConfigs([]table.ColumnConfig{
		{Number: 5, WidthMax: 10, WidthMaxEnforcer: text.WrapText},
		// Number: 5 corresponds to 5th column
		// Try other enforcers, for ex. text.WrapSoft
	})

	fmt.Println(tw.Render())
}

Output:

   # | FIRST NAME | LAST NAME | SALARY |            
-----+------------+-----------+--------+------------
   1 | Arya       | Stark     |   3000 |            
  20 | Jon        | Snow      |   2000 | You know n 
     |            |           |        | othing, Jo 
     |            |           |        | n Snow!    
 300 | Tyrion     | Lannister |   5000 |            

Thanks for your suggestion,it does look more beautiful.But when I want to display a table that could be read by both human and programs,I need to just display it in one line and not fill spaces on last culumn

@jedib0t
Copy link
Owner

jedib0t commented Apr 11, 2024

I agree that most logic of this PR could be achieved by caller. But I think "AlignDisabled" is useful for upstream. The example you mentioned will lost spaces that intentionally added by the user.(Although I can't imagine why users would do this now)

AlignDisabled or AlignCenterWithoutRightSpace does not make any sense in a table that is supposed to have even spacing for all columns. A table library's most important functionality is to align stuff, and the above is just negating that core functionality by saying... "hey stop being a table library for this one column".

Here is what I mean:

package main

import (
	"fmt"

	"github.com/jedib0t/go-pretty/v6/table"
	"github.com/jedib0t/go-pretty/v6/text"
)

func main() {
	tw := table.NewWriter()
	tw.AppendHeader(table.Row{"#", "First Name", "Last Name", "Salary"})
	tw.AppendRows([]table.Row{
		{1, "Arya", "Stark", 3000},
		{20, "Jon", "Snow", 2000, "You know nothing, Jon Snow!"},
		{300, "Tyrion", "Lannister", 5000},
	})

	tw.SetColumnConfigs([]table.ColumnConfig{
		{Number: 2, Align: text.AlignCenterWithoutRightSpace},
		{Number: 3, Align: text.AlignDisabled},
	})

	fmt.Println(tw.Render())
}

Output:

+-----+------------+-----------+--------+-----------------------------+
|   # | FIRST NAME | LAST NAME | SALARY |                             |
+-----+------------+-----------+--------+-----------------------------+
|   1 |    Arya | Stark |   3000 |                             |
|  20 |     Jon | Snow |   2000 | You know nothing, Jon Snow! |
| 300 |   Tyrion | Lannister |   5000 |                             |
+-----+------------+-----------+--------+-----------------------------+

Thanks for your suggestion,it does look more beautiful.But when I want to display a table that could be read by both human and programs,I need to just display it in one line and not fill spaces on last culumn

I highly recommend steering away from making programs read the table layout. If you want programs to consume the data, there are so many better formats (CSV/JSON/any-number-of-structured-formats). That said, the program has to deal with empty spaces in columns that are not the last column anyway. So with this solve, you wouldn't be solving the problem you are defining.

@jedib0t jedib0t closed this Apr 12, 2024
@jedib0t
Copy link
Owner

jedib0t commented Apr 12, 2024

@nexustar I just realized I'd already implemented the trimming of trailing spaces some time back with the SuppressTrailingSpaces interface. Check it out... it does the split and trim for you internally.

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

Successfully merging this pull request may close these issues.

None yet

3 participants