This code looks a bit ugly and we need to manually position items by changing the arguments given to cursor::Goto. For example, sizey / 2 - 2 means two lines above the middle line. If I want to add another line to that list and move all of them down, I need to change this part of every line.
The cursor::Left(line.len() as u16 / 2) part positions the text in the center - this snippet is repeated for every line. What's even worse is if the text in that line includes special characters such as colors, this will not work because it will consider those hidden characters too! To get around that, I use this hack: https://github.com/Samyak2/toipe/blob/fae300576c4f83e50ca969c588217bbd3c8cb581/src/lib.rs#L285-L299
As you can see, I need to repeat the formatting characters again in a separate string containing only them and then subtract their length from line.len() like cursor::Left((line.len() - zerowidths.len()) as u16 / 2).
How to fix?
Honestly, I'm not sure. I opened this issue to force myself to document the problem.
The solution will definitely involve abstracting this UI rendering into a different module. Abstracting the cursor::Gotos is simple - take a vec/iter/slice of strings and change the y-position when printing each one such that they are approximately in the middle. cursor::Left(line.len() as u16 / 2) is easy too, as long as the given string contains single-width characters. I'm not sure how zero-width and other characters can be handled here. Perhaps this problem is solved elsewhere?
What?
Currently, the terminal UI in toipe is rendered by directly writing to
stdout
with cursor positioning and colors provided by termion.Example: https://github.com/Samyak2/toipe/blob/fae300576c4f83e50ca969c588217bbd3c8cb581/src/lib.rs#L263-L271
This code looks a bit ugly and we need to manually position items by changing the arguments given to
cursor::Goto
. For example,sizey / 2 - 2
means two lines above the middle line. If I want to add another line to that list and move all of them down, I need to change this part of every line.The
cursor::Left(line.len() as u16 / 2)
part positions the text in the center - this snippet is repeated for every line. What's even worse is if the text in that line includes special characters such as colors, this will not work because it will consider those hidden characters too! To get around that, I use this hack: https://github.com/Samyak2/toipe/blob/fae300576c4f83e50ca969c588217bbd3c8cb581/src/lib.rs#L285-L299As you can see, I need to repeat the formatting characters again in a separate string containing only them and then subtract their length from
line.len()
likecursor::Left((line.len() - zerowidths.len()) as u16 / 2)
.How to fix?
Honestly, I'm not sure. I opened this issue to force myself to document the problem.
The solution will definitely involve abstracting this UI rendering into a different module. Abstracting the
cursor::Goto
s is simple - take a vec/iter/slice of strings and change the y-position when printing each one such that they are approximately in the middle.cursor::Left(line.len() as u16 / 2)
is easy too, as long as the given string contains single-width characters. I'm not sure how zero-width and other characters can be handled here. Perhaps this problem is solved elsewhere?I'm always open to suggestions!