I'm using a BoxElement
from blessed to display a chat history.
Sentences are added using pushLine
. For clarity, days are divided by lines (another string added using pushLine
). Each line is as wide as the parent BoxElement
.
If the TUI is resized however, the line no longer fits.
I have 2 questions:
An example of the issue is shown below:
/**
* Example.ts
*/
import * as blessed from 'blessed';
const screen = blessed.screen({
smartCSR: true,
title: 'Chatr',
dockBorders: true
});
const chatBox = blessed.box({
parent: screen,
title: 'Chatbox',
top: 'top',
left: 'center',
height: '100%',
width: '100%',
border: {
type: 'line'
},
});
screen.append(chatBox);
screen.render();
chatBox.pushLine("This is the first line");
// This is the separator - and will not resize with the terminal
chatBox.pushLine("_".repeat(chatBox.width as number - 2));
chatBox.pushLine("This is a second line");
screen.render();
When the code is run ts-node ./Example.js
it renders this:
┌────────────────────────────────────────────────────────────────────────────────────────┐
│This is a line │
│________________________________________________________________________________________│
│This is a second line │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
└────────────────────────────────────────────────────────────────────────────────────────┘
Resizing the terminal gets this result:
┌──────────────────────────────────────────────────────────┐
│This is a line │
│__________________________________________________________│
│______________________________ │
│This is a second line │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
│ │
└──────────────────────────────────────────────────────────┘
It seems blessed
doesn't implement something like a separator, but we can simply implement them by ourselves with a simple class which stores the line index of each separator and change them on resize
event. Something like:
import * as blessed from "blessed";
// The required Separators class
class Separators {
private box: any;
private separators: number[] = [];
public constructor(box: any) {
this.box = box;
box.on("resize", () => {
const sep = this.sep();
this.separators.forEach(line => {
box.deleteLine(line);
box.insertLine(line, sep);
});
});
}
public add(): void {
const { box, separators } = this;
separators.push(box.getLines().length);
box.pushLine(this.sep());
}
private sep(): string {
return "_".repeat((this.box.width as number) - 3);
}
}
const screen = blessed.screen({
smartCSR: true,
title: "Chatr",
dockBorders: true
});
const chatBox = blessed.box({
parent: screen,
title: "Chatbox",
top: "top",
left: "center",
height: "100%",
width: "100%",
border: {
type: "line"
}
});
const sep = new Separators(chatBox); // <- the new Separator bound to the box
screen.append(chatBox);
screen.render();
chatBox.pushLine("This is the first line");
// This is the separator - and it resize with the terminal
sep.add();
chatBox.pushLine("This is a second line");
chatBox.pushLine("While this is the third line");
// This is another separator - it resize with the terminal as well
sep.add();
chatBox.pushLine("And last this is the last line");
screen.render();
About the bonus point, now it should be quite easy to achieve it; the hard part is to center a line longer than the box width: if we split it in more lines to center, all the line indexes (next to split centered line) will changes and could become harder to keep track of them.
A possible compromise could be to accept to center only lines shorter than box width, left padding them with the right amount of spaces.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With