mirror of
https://github.com/privatevoid-net/nix-super.git
synced 2024-11-10 00:08:07 +02:00
libutil: Add Pos::getSnippetUpTo(Pos)
This commit is contained in:
parent
63f520fd00
commit
e5af7cbeb9
3 changed files with 168 additions and 0 deletions
|
@ -110,4 +110,50 @@ void Pos::LinesIterator::bump(bool atFirst)
|
||||||
input.remove_prefix(eol);
|
input.remove_prefix(eol);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string Pos::getSnippetUpTo(const Pos & end) const {
|
||||||
|
assert(this->origin == end.origin);
|
||||||
|
|
||||||
|
if (end.line < this->line)
|
||||||
|
return "";
|
||||||
|
|
||||||
|
if (auto source = getSource()) {
|
||||||
|
|
||||||
|
auto firstLine = LinesIterator(*source);
|
||||||
|
for (auto i = 1; i < this->line; ++i) {
|
||||||
|
++firstLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto lastLine = LinesIterator(*source);
|
||||||
|
for (auto i = 1; i < end.line; ++i) {
|
||||||
|
++lastLine;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinesIterator linesEnd;
|
||||||
|
|
||||||
|
std::string result;
|
||||||
|
for (auto i = firstLine; i != linesEnd; ++i) {
|
||||||
|
auto firstColumn = i == firstLine ? (this->column ? this->column - 1 : 0) : 0;
|
||||||
|
if (firstColumn > i->size())
|
||||||
|
firstColumn = i->size();
|
||||||
|
|
||||||
|
auto lastColumn = i == lastLine ? (end.column ? end.column - 1 : 0) : std::numeric_limits<int>::max();
|
||||||
|
if (lastColumn < firstColumn)
|
||||||
|
lastColumn = firstColumn;
|
||||||
|
if (lastColumn > i->size())
|
||||||
|
lastColumn = i->size();
|
||||||
|
|
||||||
|
result += i->substr(firstColumn, lastColumn - firstColumn);
|
||||||
|
|
||||||
|
if (i == lastLine) {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
result += '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,8 @@ struct Pos
|
||||||
bool operator==(const Pos & rhs) const = default;
|
bool operator==(const Pos & rhs) const = default;
|
||||||
auto operator<=>(const Pos & rhs) const = default;
|
auto operator<=>(const Pos & rhs) const = default;
|
||||||
|
|
||||||
|
std::string getSnippetUpTo(const Pos & end) const;
|
||||||
|
|
||||||
struct LinesIterator {
|
struct LinesIterator {
|
||||||
using difference_type = size_t;
|
using difference_type = size_t;
|
||||||
using value_type = std::string_view;
|
using value_type = std::string_view;
|
||||||
|
|
120
tests/unit/libutil/position.cc
Normal file
120
tests/unit/libutil/position.cc
Normal file
|
@ -0,0 +1,120 @@
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "position.hh"
|
||||||
|
|
||||||
|
namespace nix {
|
||||||
|
|
||||||
|
inline Pos::Origin makeStdin(std::string s)
|
||||||
|
{
|
||||||
|
return Pos::Stdin{make_ref<std::string>(s)};
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Position, getSnippetUpTo_0)
|
||||||
|
{
|
||||||
|
Pos::Origin o = makeStdin("");
|
||||||
|
Pos p(1, 1, o);
|
||||||
|
ASSERT_EQ(p.getSnippetUpTo(p), "");
|
||||||
|
}
|
||||||
|
TEST(Position, getSnippetUpTo_1)
|
||||||
|
{
|
||||||
|
Pos::Origin o = makeStdin("x");
|
||||||
|
{
|
||||||
|
// NOTE: line and column are actually 1-based indexes
|
||||||
|
Pos start(0, 0, o);
|
||||||
|
Pos end(99, 99, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(start), "");
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "x");
|
||||||
|
ASSERT_EQ(end.getSnippetUpTo(end), "");
|
||||||
|
ASSERT_EQ(end.getSnippetUpTo(start), "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
// NOTE: line and column are actually 1-based indexes
|
||||||
|
Pos start(0, 99, o);
|
||||||
|
Pos end(99, 0, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(start), "");
|
||||||
|
|
||||||
|
// "x" might be preferable, but we only care about not crashing for invalid inputs
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "");
|
||||||
|
|
||||||
|
ASSERT_EQ(end.getSnippetUpTo(end), "");
|
||||||
|
ASSERT_EQ(end.getSnippetUpTo(start), "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Pos start(1, 1, o);
|
||||||
|
Pos end(1, 99, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(start), "");
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "x");
|
||||||
|
ASSERT_EQ(end.getSnippetUpTo(end), "");
|
||||||
|
ASSERT_EQ(end.getSnippetUpTo(start), "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Pos start(1, 1, o);
|
||||||
|
Pos end(99, 99, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(start), "");
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "x");
|
||||||
|
ASSERT_EQ(end.getSnippetUpTo(end), "");
|
||||||
|
ASSERT_EQ(end.getSnippetUpTo(start), "");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
TEST(Position, getSnippetUpTo_2)
|
||||||
|
{
|
||||||
|
Pos::Origin o = makeStdin("asdf\njkl\nqwer");
|
||||||
|
{
|
||||||
|
Pos start(1, 1, o);
|
||||||
|
Pos end(1, 2, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(start), "");
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "a");
|
||||||
|
ASSERT_EQ(end.getSnippetUpTo(end), "");
|
||||||
|
ASSERT_EQ(end.getSnippetUpTo(start), "");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Pos start(1, 2, o);
|
||||||
|
Pos end(1, 3, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "s");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Pos start(1, 2, o);
|
||||||
|
Pos end(2, 2, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "sdf\nj");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Pos start(1, 2, o);
|
||||||
|
Pos end(3, 2, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "sdf\njkl\nq");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Pos start(1, 2, o);
|
||||||
|
Pos end(2, 99, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "sdf\njkl");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Pos start(1, 4, o);
|
||||||
|
Pos end(2, 99, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "f\njkl");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Pos start(1, 5, o);
|
||||||
|
Pos end(2, 99, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "\njkl");
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Pos start(1, 6, o); // invalid: starting column past last "line character", ie at the newline
|
||||||
|
Pos end(2, 99, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "\njkl"); // jkl might be acceptable for this invalid start position
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Pos start(1, 1, o);
|
||||||
|
Pos end(2, 0, o); // invalid
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "asdf\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(Position, example_1)
|
||||||
|
{
|
||||||
|
Pos::Origin o = makeStdin(" unambiguous = \n /** Very close */\n x: x;\n# ok\n");
|
||||||
|
Pos start(2, 5, o);
|
||||||
|
Pos end(2, 22, o);
|
||||||
|
ASSERT_EQ(start.getSnippetUpTo(end), "/** Very close */");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace nix
|
Loading…
Reference in a new issue