Closed pmonks closed 11 months ago
What's your use case exactly ? It's a bad idea to depend on those cursor movements if the terminal can not use it and Jansi is somewhat limited when it comes to mimic ansi sequences. The original goal is to allow rendering colors and strip them on unsupported terminal and emulate on windows. Anything more advanced should really use a better suited library and I would recommend looking at JLine3 (on top of jansi) which has full terminal support.
The project is here, but in a nutshell the use case is a text-mode "spinner" for long-running command line processes, which involves these steps:
This is done in a loop that spins through the frames in the caller's chosen spinner animation.
From a quick evaluation it appears that JLine3 is unsuitable for my use case given that:
jansi
already provides these APIs - it's just that it only provides one variant of what ended up (for historical reasons) as two distinct ANSI escape sequences. Modern programs need to be able to use either or both, since some modern terminals (including, notably, the default Terminal.app on macOS) lack support for the SCO sequences that jansi
currently emits.And just to be crystal clear, I'm not asking for termcap/terminfo capabilities. I personally think that's well beyond the scope of jansi
. Instead I'm simply asking for two new APIs that will (unconditionally) emit the DEC sequences for cursor save & restore when called (while maintaining the existing saveCursorPosition
and restoreCursorPosition
APIs that emit the SCO sequences). Leaving terminal capability detection to the jansi
client (in this case my library) is absolutely fine by me (in fact I encourage that).
Here's my workaround, which I've tested in various terminal emulators on both macOS and Linux.
As previously mentioned, it would be ideal if jansi
added new APIs to emit the DEC sequences for save cursor position and restore cursor position, as it's highly implausible that my library is the only one that has run into this problem.
@pmonks would the #262 PR fix your problem ?
@gnodet I believe it would - that's the approach I took in my own code. However there may be folks who need finer-grained control over which sequences(s) are sent, so I'd probably suggest splitting this into multiple methods, perhaps something like:
public Ansi saveCursorPosition() {
saveCursorPositionSCO();
return saveCursorPositionDEC();
}
// SCO command
public Ansi saveCursorPositionSCO() {
return appendEscapeSequence('s');
}
// DEC command
public Ansi saveCursorPositionDEC {
builder.append(FIRST_ESC_CHAR);
builder.append('7');
return this;
}
public Ansi restoreCursorPosition() {
restoreCursorPositionSCO();
return restoreCursorPositionDEC();
}
// SCO command
public Ansi restoreCursorPositionSCO() {
return appendEscapeSequence('u');
}
// DEC command
public Ansi restoreCursorPositionDEC() {
builder.append(FIRST_ESC_CHAR);
builder.append('8');
return this;
}
Background
The escape sequences for "save cursor position" and "restore cursor position" were never standardised as part of the ANSI (or subsequent) specs, resulting in two different sequences known in some circles as "DEC" and "SCO":
ESC7
(save) andESC8
(restore)ESC[s
(save) andESC[u
(restore)Different terminals (and OSes) support different combinations of these sequences (one, the other, neither or both); for example the iTerm2 terminal on macOS supports both, while the built-in macOS Terminal.app only supports the DEC sequences.
Problem
From the source I see that
jansi
'ssaveCursorPosition
andrestoreCursorPosition
methods use the SCO sequences for these operations, meaning that they won't work by default on some terminals (including, notably, macOS' built-in Terminal.app).Proposed Solution
Add support for both variants, so that
jansi
consumers can determine the correct one to use (itself a thorny problem, but one that feels appropriate to punt out of the library).