Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Utkarsh-khambra committed Apr 15, 2023
1 parent 5dd2478 commit 949f566
Show file tree
Hide file tree
Showing 19 changed files with 287 additions and 21 deletions.
1 change: 1 addition & 0 deletions src/contour/Config.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1969,6 +1969,7 @@ void loadConfigFromFile(Config& _config, FileSystem::path const& _fileName)
}

tryLoadValue(usedKeys, doc, "reflow_on_resize", _config.reflowOnResize);
tryLoadValue(usedKeys, doc, "expand_tabs", _config.expandTabs);

if (auto profiles = doc["profiles"]; profiles)
{
Expand Down
1 change: 1 addition & 0 deletions src/contour/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,7 @@ struct Config
size_t ptyBufferObjectSize = 1024lu * 1024lu;

bool reflowOnResize = true;
bool expandTabs = false;

std::unordered_map<std::string, terminal::ColorPalette> colorschemes;
std::unordered_map<std::string, TerminalProfile> profiles;
Expand Down
1 change: 1 addition & 0 deletions src/contour/TerminalSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ namespace
settings.primaryScreen.allowReflowOnResize = config.reflowOnResize;
settings.highlightDoubleClickedWord = profile.highlightDoubleClickedWord;
settings.highlightTimeout = profile.highlightTimeout;
settings.expandTabs = config.expandTabs;

return settings;
}
Expand Down
1 change: 1 addition & 0 deletions src/vtbackend/CellFlags.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ enum class CellFlags : uint32_t
Overline = (1 << 14),
RapidBlinking = (1 << 15),
CharacterProtected = (1 << 16), // Character is protected by selective erase operations.
Tab = (1 << 17), // Cell is part of tab character.
};

constexpr CellFlags& operator|=(CellFlags& a, CellFlags b) noexcept
Expand Down
3 changes: 1 addition & 2 deletions src/vtbackend/Grid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -801,8 +801,7 @@ CellLocation Grid<Cell>::resize(PageSize newSize, CellLocation currentCursorPos,
flushLogicalLine();
if (line.isTrivialBuffer())
{
auto& buffer = line.trivialBuffer();
buffer.displayWidth = newColumnCount;
line.trivialBuffer().resize(newColumnCount);
grownLines.emplace_back(line);
}
else
Expand Down
30 changes: 26 additions & 4 deletions src/vtbackend/Line.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ typename Line<Cell>::InflatedBuffer Line<Cell>::reflow(ColumnCount newColumnCoun
{
switch (crispy::strongCompare(newColumnCount, ColumnCount::cast_from(trivialBuffer().text.size())))
{
case Comparison::Greater: trivialBuffer().displayWidth = newColumnCount; return {};
case Comparison::Greater: trivialBuffer().resize(newColumnCount); return {};
case Comparison::Equal: return {};
case Comparison::Less:;
}
Expand Down Expand Up @@ -99,8 +99,7 @@ inline void Line<Cell>::resize(ColumnCount count)
{
if (isTrivialBuffer())
{
TrivialBuffer& buffer = trivialBuffer();
buffer.displayWidth = count;
trivialBuffer().resize(count);
return;
}
}
Expand Down Expand Up @@ -179,7 +178,7 @@ InflatedLineBuffer<Cell> inflate(TrivialLineBuffer const& input)
auto lastChar = char32_t { 0 };
auto utf8DecoderState = unicode::utf8_decoder_state {};
auto gapPending = 0;

size_t cellNr = 0;
for (char const ch: input.text.view())
{
unicode::ConvertResult const r = unicode::from_utf8(utf8DecoderState, static_cast<uint8_t>(ch));
Expand All @@ -200,6 +199,7 @@ InflatedLineBuffer<Cell> inflate(TrivialLineBuffer const& input)
columns.emplace_back(Cell {});
columns.back().setHyperlink(input.hyperlink);
columns.back().write(input.textAttributes, nextChar, static_cast<uint8_t>(charWidth));
columns.back().setTab(input.tabstops[cellNr]);
gapPending = charWidth - 1;
}
else
Expand All @@ -218,6 +218,7 @@ InflatedLineBuffer<Cell> inflate(TrivialLineBuffer const& input)
}
}
lastChar = nextChar;
++cellNr;
}

while (gapPending > 0)
Expand All @@ -229,10 +230,31 @@ InflatedLineBuffer<Cell> inflate(TrivialLineBuffer const& input)
assert(columns.size() == unbox<size_t>(input.usedColumns));

while (columns.size() < unbox<size_t>(input.displayWidth))
{
columns.emplace_back(Cell { input.fillAttributes });
columns.back().setTab(input.tabstops[cellNr]);
++cellNr;
}

return columns;
}

template <typename Cell>
void Line<Cell>::setTab(ColumnOffset start, ColumnCount n, bool tab)
{
if (isInflatedBuffer())
{
for (; n > ColumnCount(0); --n)
useCellAt(start++).setTab(tab);
}
else
{
auto& buffer = trivialBuffer();
for (; n > ColumnCount(0); --n)
buffer.tabstops[(start++).as<size_t>()] = true;
// assert(false);
}
}
} // end namespace terminal

#include <vtbackend/cell/CompactCell.h>
Expand Down
19 changes: 18 additions & 1 deletion src/vtbackend/Line.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,20 @@ struct TrivialLineBuffer

ColumnCount usedColumns {};
crispy::BufferFragment<char> text {};

std::vector<bool> tabstops = std::vector<bool>(displayWidth.value, false);
void reset(GraphicsAttributes attributes) noexcept
{
textAttributes = attributes;
fillAttributes = attributes;
hyperlink = {};
usedColumns = {};
text.reset();
tabstops.clear();
}
void resize(ColumnCount count)
{
displayWidth = count;
tabstops.resize(count.as<size_t>());
}
};

Expand Down Expand Up @@ -234,6 +240,15 @@ class Line
return inflatedBuffer().at(unbox<size_t>(column)).empty();
}

[[nodiscard]] bool hasTabstop(ColumnOffset column) const noexcept
{
Require(ColumnOffset(0) <= column);
Require(column <= ColumnOffset::cast_from(size()));
if (isInflatedBuffer())
return cells()[column.as<size_t>()].isTab();
return trivialBuffer().tabstops[column.as<size_t>()];
}

[[nodiscard]] uint8_t cellWidthAt(ColumnOffset column) const noexcept
{
#if 0 // TODO: This optimization - but only when we return actual widths and not always 1.
Expand All @@ -258,6 +273,8 @@ class Line
[[nodiscard]] bool wrappable() const noexcept { return isFlagEnabled(LineFlags::Wrappable); }
void setWrappable(bool enable) { setFlag(LineFlags::Wrappable, enable); }

void setTab(ColumnOffset start, ColumnCount n, bool tab);

[[nodiscard]] LineFlags wrappableFlag() const noexcept
{
return wrappable() ? LineFlags::Wrappable : LineFlags::None;
Expand Down
53 changes: 49 additions & 4 deletions src/vtbackend/Screen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,6 @@ using std::vector;
namespace terminal
{

auto constexpr inline TabWidth = ColumnCount(8);

auto const inline VTCaptureBufferLog = logstore::Category("vt.ext.capturebuffer",
"Capture Buffer debug logging.",
logstore::Category::State::Disabled,
Expand Down Expand Up @@ -1468,9 +1466,12 @@ void Screen<Cell>::moveCursorToNextTab()
++i;

auto const currentCursorColumn = logicalCursorPosition().column;

if (i < _state.tabs.size())
moveCursorForward(boxed_cast<ColumnCount>(_state.tabs[i] - currentCursorColumn));
{
auto const cursorMoveAmount = boxed_cast<ColumnCount>(_state.tabs[i] - currentCursorColumn);
currentLine().setTab(currentCursorColumn, cursorMoveAmount, true);
moveCursorForward(cursorMoveAmount);
}
else if (realCursorPosition().column < margin().horizontal.to)
moveCursorForward(boxed_cast<ColumnCount>(margin().horizontal.to - currentCursorColumn));
}
Expand All @@ -1482,6 +1483,7 @@ void Screen<Cell>::moveCursorToNextTab()
auto const n =
min((TabWidth - boxed_cast<ColumnCount>(_cursor.position.column) % TabWidth),
_settings.pageSize.columns - boxed_cast<ColumnCount>(logicalCursorPosition().column));
currentLine().setTab(logicalCursorPosition().column, n, true);
moveCursorForward(n);
}
}
Expand Down Expand Up @@ -3912,6 +3914,49 @@ bool Screen<Cell>::isCursorInsideMargins() const noexcept
return insideVerticalMargin && insideHorizontalMargin;
}

template <typename Cell>
CRISPY_REQUIRES(CellConcept<Cell>)
CellLocation Screen<Cell>::getTabstopStart(CellLocation position) const noexcept
{
if (!_state.tabs.empty())
{
auto tab = std::lower_bound(_state.tabs.begin(), _state.tabs.end(), position.column);
position.column =
(tab == _state.tabs.end()) ? ColumnOffset::cast_from(_settings.pageSize.columns - 1) : *tab - 1;
}
else
{
auto const n = min(boxed_cast<ColumnCount>(position.column) % TabWidth,
_settings.pageSize.columns - boxed_cast<ColumnCount>(position.column));
position.column -= n;
}
auto const& line = _grid.lineAt(position.line);
while (!line.hasTabstop(position.column))
++position.column;
return position;
}

template <typename Cell>
CRISPY_REQUIRES(CellConcept<Cell>)
CellLocation Screen<Cell>::getTabstopEnd(CellLocation position) const noexcept
{
if (!_state.tabs.empty())
{
auto tab = std::upper_bound(_state.tabs.begin(), _state.tabs.end(), position.column);
position.column =
(tab == _state.tabs.end()) ? ColumnOffset::cast_from(_settings.pageSize.columns - 1) : *tab - 1;
}
else
{
auto const n = min((TabWidth - boxed_cast<ColumnCount>(position.column) % TabWidth - 1),
_settings.pageSize.columns - boxed_cast<ColumnCount>(position.column));
position.column += n;
}
auto const& line = _grid.lineAt(position.line);
while (!line.hasTabstop(position.column))
--position.column;
return position;
}
} // namespace terminal

#include <vtbackend/cell/CompactCell.h>
Expand Down
9 changes: 9 additions & 0 deletions src/vtbackend/Screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class ScreenBase: public SequenceHandler
[[nodiscard]] virtual Margin& margin() noexcept = 0;
[[nodiscard]] virtual bool contains(CellLocation coord) const noexcept = 0;
[[nodiscard]] virtual bool isCellEmpty(CellLocation position) const noexcept = 0;
[[nodiscard]] virtual bool hasTabstop(CellLocation position) const noexcept = 0;
[[nodiscard]] virtual CellLocation getTabstopStart(CellLocation position) const noexcept = 0;
[[nodiscard]] virtual CellLocation getTabstopEnd(CellLocation position) const noexcept = 0;
[[nodiscard]] virtual bool compareCellTextAt(CellLocation position, char codepoint) const noexcept = 0;
[[nodiscard]] virtual std::string cellTextAt(CellLocation position) const noexcept = 0;
[[nodiscard]] virtual LineFlags lineFlagsAt(LineOffset line) const noexcept = 0;
Expand Down Expand Up @@ -518,6 +521,12 @@ class Screen final: public ScreenBase, public capabilities::StaticDatabase
return _grid.lineAt(position.line).cellEmptyAt(position.column);
}

[[nodiscard]] bool hasTabstop(CellLocation position) const noexcept override
{
return _grid.lineAt(position.line).hasTabstop(position.column);
}
[[nodiscard]] CellLocation getTabstopStart(CellLocation position) const noexcept override;
[[nodiscard]] CellLocation getTabstopEnd(CellLocation position) const noexcept override;
[[nodiscard]] bool compareCellTextAt(CellLocation position, char codepoint) const noexcept override
{
auto const& cell = _grid.lineAt(position.line).inflatedBuffer().at(position.column.as<size_t>());
Expand Down
23 changes: 23 additions & 0 deletions src/vtbackend/Selector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,19 @@ namespace terminal
namespace // {{{ helper
{

CellLocation closestCell(CellLocation target, CellLocation left, CellLocation right) noexcept
{
auto const distFromLeft =
std::abs((target.column - left.column).as<int>()) + std::abs((target.line - left.line).as<int>());

auto const distFromRight = std::abs((target.column - right.column).as<int>())
+ std::abs((target.line - right.line).as<int>());
auto const min = std::min(distFromLeft, distFromRight);
fmt::print("left {} right {}\n", distFromLeft, distFromRight);
if (distFromLeft == min)
return left;
return right;
}
tuple<vector<Selection::Range>, CellLocation const, CellLocation const> prepare(
Selection const& selection)
{
Expand Down Expand Up @@ -58,6 +71,16 @@ bool Selection::extend(CellLocation to)
return true;
}

bool Selection::extendStart(CellLocation from)
{
assert(_state != State::Complete
&& "In order extend a selection, the selector must be active (started).");
_state = State::InProgress;
_from = from;
_onSelectionUpdated();
return true;
}

void Selection::complete()
{
if (_state == State::InProgress)
Expand Down
3 changes: 3 additions & 0 deletions src/vtbackend/Selector.h
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,9 @@ class Selection
/// Extends the selection to the given coordinate.
[[nodiscard]] virtual bool extend(CellLocation to);

/// Include the given pos
[[nodiscard]] virtual bool extendStart(CellLocation from);

/// Constructs a vector of ranges for this selection.
[[nodiscard]] virtual std::vector<Range> ranges() const;

Expand Down
1 change: 1 addition & 0 deletions src/vtbackend/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ struct Settings
std::chrono::milliseconds highlightTimeout = std::chrono::milliseconds { 150 };
bool highlightDoubleClickedWord = true;
// TODO: ^^^ make also use of it. probably rename to how VScode has named it.
bool expandTabs = false;

struct PrimaryScreen
{
Expand Down
Loading

0 comments on commit 949f566

Please sign in to comment.