nix: remove explosions if you have a window size less than four
Turns out strings do not like being resized to -4. This was discovered while messing with the tests to remove unbuffer and trying stdbuf instead. Turns out that was not the right approach. This basically rewrites the handling of this case to be much more correct, and fixes a bug where with small window sizes where it would ALSO truncate the attr names in addition to the optional descriptions. Change-Id: Ifd1beeaffdb47cbb5f4a462b183fcb6c0ff6c524
This commit is contained in:
parent
0c76195351
commit
b15d5cc6ee
2 changed files with 43 additions and 16 deletions
|
@ -3,7 +3,7 @@
|
||||||
#include "common-args.hh"
|
#include "common-args.hh"
|
||||||
#include "shared.hh"
|
#include "shared.hh"
|
||||||
#include "eval.hh"
|
#include "eval.hh"
|
||||||
#include "eval-inline.hh"
|
#include "eval-inline.hh" // IWYU pragma: keep
|
||||||
#include "eval-settings.hh"
|
#include "eval-settings.hh"
|
||||||
#include "flake/flake.hh"
|
#include "flake/flake.hh"
|
||||||
#include "get-drvs.hh"
|
#include "get-drvs.hh"
|
||||||
|
@ -17,8 +17,8 @@
|
||||||
#include "markdown.hh"
|
#include "markdown.hh"
|
||||||
#include "terminal.hh"
|
#include "terminal.hh"
|
||||||
|
|
||||||
|
#include <limits>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
#include <queue>
|
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
|
|
||||||
using namespace nix;
|
using namespace nix;
|
||||||
|
@ -1258,24 +1258,38 @@ struct CmdFlakeShow : FlakeCommand, MixJSON
|
||||||
attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" :
|
attrPath.size() == 3 && attrPathS[0] == "checks" ? "derivation" :
|
||||||
attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" :
|
attrPath.size() >= 1 && attrPathS[0] == "hydraJobs" ? "derivation" :
|
||||||
"package";
|
"package";
|
||||||
|
|
||||||
|
std::string output = fmt("%s: %s '%s'", headerPrefix, type, name);
|
||||||
|
|
||||||
if (description && !description->empty()) {
|
if (description && !description->empty()) {
|
||||||
// Trim the string and only display the first line of the description.
|
// Trim the string and only display the first line of the description.
|
||||||
auto desc = nix::trim(*description);
|
auto desc = nix::trim(*description);
|
||||||
auto firstLineDesc = desc.substr(0, desc.find('\n'));
|
auto firstLineDesc = desc.substr(0, desc.find('\n'));
|
||||||
|
// three separators, two quotes
|
||||||
|
constexpr auto quotesAndSepsWidth = 3 + 2;
|
||||||
|
|
||||||
std::string output = fmt("%s: %s '%s' - '%s'", headerPrefix, type, name, firstLineDesc);
|
int screenWidth = isOutputARealTerminal(StandardOutputStream::Stdout)
|
||||||
if (output.size() > getWindowSize().second) {
|
? getWindowSize().second
|
||||||
// we resize to 4 less then the window size to account for the "...'" we append to
|
: std::numeric_limits<int>::max();
|
||||||
// the final string, we also include the ' since that is removed when we truncate the string
|
|
||||||
output.resize(getWindowSize().second - 4);
|
// FIXME: handle utf8 visible width properly once we get KJ which has utf8 support
|
||||||
output.append("...'");
|
// technically filterANSIEscapes knows how to do this but there is absolutely
|
||||||
|
// no clear usage of it that would actually let us do this layout.
|
||||||
|
int spaceForDescription = screenWidth - output.size() - quotesAndSepsWidth;
|
||||||
|
|
||||||
|
if (spaceForDescription <= 0) {
|
||||||
|
// do nothing, it is going to wrap no matter what, and it's better to output *something*
|
||||||
|
} else {
|
||||||
|
const char *ellipsis = "";
|
||||||
|
if (spaceForDescription < firstLineDesc.size()) {
|
||||||
|
// subtract one to make space for the ellipsis
|
||||||
|
firstLineDesc.resize(spaceForDescription - 1);
|
||||||
|
ellipsis = "…";
|
||||||
|
}
|
||||||
|
output.append(fmt(" - '%s%s'", firstLineDesc, ellipsis));
|
||||||
}
|
}
|
||||||
|
|
||||||
logger->cout("%s", output.c_str());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
logger->cout("%s: %s '%s'", headerPrefix, type, name);
|
|
||||||
}
|
}
|
||||||
|
logger->cout("%s", output);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -107,10 +107,23 @@ EOF
|
||||||
|
|
||||||
runinpty sh -c '
|
runinpty sh -c '
|
||||||
stty rows 20 cols 100
|
stty rows 20 cols 100
|
||||||
nix flake show > show-output.txt
|
TERM=xterm-256color NOCOLOR=1 nix flake show
|
||||||
'
|
' > show-output.txt
|
||||||
|
|
||||||
test "$(awk -F '[:] ' '/aNoDescription/{print $NF}' ./show-output.txt)" = "package 'simple'"
|
test "$(awk -F '[:] ' '/aNoDescription/{print $NF}' ./show-output.txt)" = "package 'simple'"
|
||||||
test "$(awk -F '[:] ' '/bOneLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'one line'"
|
test "$(awk -F '[:] ' '/bOneLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'one line'"
|
||||||
test "$(awk -F '[:] ' '/cMultiLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'line one'"
|
test "$(awk -F '[:] ' '/cMultiLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'line one'"
|
||||||
test "$(awk -F '[:] ' '/dLongDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'abcdefghijklmnopqrs...'"
|
test "$(awk -F '[:] ' '/dLongDescription/{print $NF}' ./show-output.txt)" = "package 'simple' - 'abcdefghijklmnopqrstu…'"
|
||||||
|
test "$(awk -F '[:] ' '/eEmptyDescription/{print $NF}' ./show-output.txt)" = "package 'simple'"
|
||||||
|
|
||||||
|
# validate that having a broken window size does not cause anything to explode
|
||||||
|
# and that descriptions are just not printed if there is no space at all
|
||||||
|
runinpty sh -c '
|
||||||
|
stty rows 0 cols 0
|
||||||
|
TERM=xterm-256color NOCOLOR=1 nix flake show
|
||||||
|
' > show-output.txt
|
||||||
|
test "$(awk -F '[:] ' '/aNoDescription/{print $NF}' ./show-output.txt)" = "package 'simple'"
|
||||||
|
test "$(awk -F '[:] ' '/bOneLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple'"
|
||||||
|
test "$(awk -F '[:] ' '/cMultiLineDescription/{print $NF}' ./show-output.txt)" = "package 'simple'"
|
||||||
|
test "$(awk -F '[:] ' '/dLongDescription/{print $NF}' ./show-output.txt)" = "package 'simple'"
|
||||||
test "$(awk -F '[:] ' '/eEmptyDescription/{print $NF}' ./show-output.txt)" = "package 'simple'"
|
test "$(awk -F '[:] ' '/eEmptyDescription/{print $NF}' ./show-output.txt)" = "package 'simple'"
|
||||||
|
|
Loading…
Reference in a new issue