Skip to content

Commit 9aec7ad

Browse files
WIP
1 parent 1a7ae70 commit 9aec7ad

File tree

15 files changed

+146
-21
lines changed

15 files changed

+146
-21
lines changed

src/contour/Config.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1924,6 +1924,7 @@ void loadConfigFromFile(Config& _config, FileSystem::path const& _fileName)
19241924
}
19251925

19261926
tryLoadValue(usedKeys, doc, "reflow_on_resize", _config.reflowOnResize);
1927+
tryLoadValue(usedKeys, doc, "expand_tabs", _config.expandTabs);
19271928

19281929
if (auto profiles = doc["profiles"]; profiles)
19291930
{

src/contour/Config.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,7 @@ struct Config
250250
size_t ptyBufferObjectSize = 1024lu * 1024lu;
251251

252252
bool reflowOnResize = true;
253+
bool expandTabs = false;
253254

254255
std::unordered_map<std::string, terminal::ColorPalette> colorschemes;
255256
std::unordered_map<std::string, TerminalProfile> profiles;

src/contour/TerminalSession.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ namespace
128128
settings.primaryScreen.allowReflowOnResize = config.reflowOnResize;
129129
settings.highlightDoubleClickedWord = profile.highlightDoubleClickedWord;
130130
settings.highlightTimeout = profile.highlightTimeout;
131+
settings.expandTabs = config.expandTabs;
131132

132133
return settings;
133134
}

src/vtbackend/CellFlags.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ enum class CellFlags : uint32_t
4444
Overline = (1 << 14),
4545
RapidBlinking = (1 << 15),
4646
CharacterProtected = (1 << 16), // Character is protected by selective erase operations.
47+
Tab = (1 << 17), // Cell is part of tab character.
4748
};
4849

4950
constexpr CellFlags& operator|=(CellFlags& a, CellFlags b) noexcept

src/vtbackend/Grid.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -798,8 +798,7 @@ CellLocation Grid<Cell>::resize(PageSize newSize, CellLocation currentCursorPos,
798798
flushLogicalLine();
799799
if (line.isTrivialBuffer())
800800
{
801-
auto& buffer = line.trivialBuffer();
802-
buffer.displayWidth = newColumnCount;
801+
line.trivialBuffer().resize(newColumnCount);
803802
grownLines.emplace_back(line);
804803
}
805804
else

src/vtbackend/Line.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ typename Line<Cell>::InflatedBuffer Line<Cell>::reflow(ColumnCount newColumnCoun
3434
{
3535
switch (crispy::strongCompare(newColumnCount, ColumnCount::cast_from(trivialBuffer().text.size())))
3636
{
37-
case Comparison::Greater: trivialBuffer().displayWidth = newColumnCount; return {};
37+
case Comparison::Greater: trivialBuffer().resize(newColumnCount); return {};
3838
case Comparison::Equal: return {};
3939
case Comparison::Less:;
4040
}
@@ -99,8 +99,7 @@ inline void Line<Cell>::resize(ColumnCount count)
9999
{
100100
if (isTrivialBuffer())
101101
{
102-
TrivialBuffer& buffer = trivialBuffer();
103-
buffer.displayWidth = count;
102+
trivialBuffer().resize(count);
104103
return;
105104
}
106105
}
@@ -168,7 +167,7 @@ InflatedLineBuffer<Cell> inflate(TrivialLineBuffer const& input)
168167
auto lastChar = char32_t { 0 };
169168
auto utf8DecoderState = unicode::utf8_decoder_state {};
170169
auto gapPending = 0;
171-
170+
size_t cellNr = 0;
172171
for (char const ch: input.text.view())
173172
{
174173
unicode::ConvertResult const r = unicode::from_utf8(utf8DecoderState, static_cast<uint8_t>(ch));
@@ -189,6 +188,7 @@ InflatedLineBuffer<Cell> inflate(TrivialLineBuffer const& input)
189188
columns.emplace_back(Cell {});
190189
columns.back().setHyperlink(input.hyperlink);
191190
columns.back().write(input.textAttributes, nextChar, static_cast<uint8_t>(charWidth));
191+
columns.back().setTab(input.tabstops[cellNr]);
192192
gapPending = charWidth - 1;
193193
}
194194
else
@@ -207,6 +207,7 @@ InflatedLineBuffer<Cell> inflate(TrivialLineBuffer const& input)
207207
}
208208
}
209209
lastChar = nextChar;
210+
++cellNr;
210211
}
211212

212213
while (gapPending > 0)
@@ -218,10 +219,31 @@ InflatedLineBuffer<Cell> inflate(TrivialLineBuffer const& input)
218219
assert(columns.size() == unbox<size_t>(input.usedColumns));
219220

220221
while (columns.size() < unbox<size_t>(input.displayWidth))
222+
{
221223
columns.emplace_back(Cell { input.fillAttributes });
224+
columns.back().setTab(input.tabstops[cellNr]);
225+
++cellNr;
226+
}
222227

223228
return columns;
224229
}
230+
231+
template <typename Cell>
232+
void Line<Cell>::setTab(ColumnOffset start, ColumnCount n, bool tab)
233+
{
234+
if (isInflatedBuffer())
235+
{
236+
for (; n > ColumnCount(0); --n)
237+
useCellAt(start++).setTab(tab);
238+
}
239+
else
240+
{
241+
auto& buffer = trivialBuffer();
242+
for (; n > ColumnCount(0); --n)
243+
buffer.tabstops[(start++).as<size_t>()] = true;
244+
// assert(false);
245+
}
246+
}
225247
} // end namespace terminal
226248

227249
#include <vtbackend/cell/CompactCell.h>

src/vtbackend/Line.h

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,14 +63,20 @@ struct TrivialLineBuffer
6363

6464
ColumnCount usedColumns {};
6565
crispy::BufferFragment<char> text {};
66-
66+
std::vector<bool> tabstops = std::vector<bool>(displayWidth.value, false);
6767
void reset(GraphicsAttributes attributes) noexcept
6868
{
6969
textAttributes = attributes;
7070
fillAttributes = attributes;
7171
hyperlink = {};
7272
usedColumns = {};
7373
text.reset();
74+
tabstops.clear();
75+
}
76+
void resize(ColumnCount count)
77+
{
78+
displayWidth = count;
79+
tabstops.resize(count.as<size_t>());
7480
}
7581
};
7682

@@ -233,6 +239,15 @@ class Line
233239
return inflatedBuffer().at(unbox<size_t>(column)).empty();
234240
}
235241

242+
[[nodiscard]] bool hasTabstop(ColumnOffset column) const noexcept
243+
{
244+
Require(ColumnOffset(0) <= column);
245+
Require(column <= ColumnOffset::cast_from(size()));
246+
if (isInflatedBuffer())
247+
return cells()[column.as<size_t>()].isTab();
248+
return trivialBuffer().tabstops[column.as<size_t>()];
249+
}
250+
236251
[[nodiscard]] uint8_t cellWidthAt(ColumnOffset column) const noexcept
237252
{
238253
#if 0 // TODO: This optimization - but only when we return actual widths and not always 1.
@@ -257,6 +272,8 @@ class Line
257272
[[nodiscard]] bool wrappable() const noexcept { return isFlagEnabled(LineFlags::Wrappable); }
258273
void setWrappable(bool enable) { setFlag(LineFlags::Wrappable, enable); }
259274

275+
void setTab(ColumnOffset start, ColumnCount n, bool tab);
276+
260277
[[nodiscard]] LineFlags wrappableFlag() const noexcept
261278
{
262279
return wrappable() ? LineFlags::Wrappable : LineFlags::None;

src/vtbackend/Screen.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,6 @@ using std::vector;
8686
namespace terminal
8787
{
8888

89-
auto constexpr inline TabWidth = ColumnCount(8);
90-
9189
auto const inline VTCaptureBufferLog = logstore::Category("vt.ext.capturebuffer",
9290
"Capture Buffer debug logging.",
9391
logstore::Category::State::Disabled,
@@ -1464,9 +1462,12 @@ void Screen<Cell>::moveCursorToNextTab()
14641462
++i;
14651463

14661464
auto const currentCursorColumn = logicalCursorPosition().column;
1467-
14681465
if (i < _state.tabs.size())
1469-
moveCursorForward(boxed_cast<ColumnCount>(_state.tabs[i] - currentCursorColumn));
1466+
{
1467+
auto const cursorMoveAmount = boxed_cast<ColumnCount>(_state.tabs[i] - currentCursorColumn);
1468+
currentLine().setTab(currentCursorColumn, cursorMoveAmount, true);
1469+
moveCursorForward(cursorMoveAmount);
1470+
}
14701471
else if (realCursorPosition().column < margin().horizontal.to)
14711472
moveCursorForward(boxed_cast<ColumnCount>(margin().horizontal.to - currentCursorColumn));
14721473
else
@@ -1480,6 +1481,7 @@ void Screen<Cell>::moveCursorToNextTab()
14801481
auto const n =
14811482
min((TabWidth - boxed_cast<ColumnCount>(_cursor.position.column) % TabWidth),
14821483
_settings.pageSize.columns - boxed_cast<ColumnCount>(logicalCursorPosition().column));
1484+
currentLine().setTab(logicalCursorPosition().column, n, true);
14831485
moveCursorForward(n);
14841486
}
14851487
else

src/vtbackend/Screen.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ class ScreenBase: public SequenceHandler
7373
[[nodiscard]] virtual Margin& margin() noexcept = 0;
7474
[[nodiscard]] virtual bool contains(CellLocation coord) const noexcept = 0;
7575
[[nodiscard]] virtual bool isCellEmpty(CellLocation position) const noexcept = 0;
76+
[[nodiscard]] virtual bool hasTabstop(CellLocation position) const noexcept = 0;
7677
[[nodiscard]] virtual bool compareCellTextAt(CellLocation position, char codepoint) const noexcept = 0;
7778
[[nodiscard]] virtual std::string cellTextAt(CellLocation position) const noexcept = 0;
7879
[[nodiscard]] virtual std::string lineTextAt(LineOffset line) const noexcept = 0;
@@ -509,6 +510,10 @@ class Screen final: public ScreenBase, public capabilities::StaticDatabase
509510
return _grid.lineAt(position.line).cellEmptyAt(position.column);
510511
}
511512

513+
[[nodiscard]] bool hasTabstop(CellLocation position) const noexcept override
514+
{
515+
return _grid.lineAt(position.line).hasTabstop(position.column);
516+
}
512517
[[nodiscard]] bool compareCellTextAt(CellLocation position, char codepoint) const noexcept override
513518
{
514519
auto const& cell = _grid.lineAt(position.line).inflatedBuffer().at(position.column.as<size_t>());

src/vtbackend/Settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct Settings
6262
std::chrono::milliseconds highlightTimeout = std::chrono::milliseconds { 150 };
6363
bool highlightDoubleClickedWord = true;
6464
// TODO: ^^^ make also use of it. probably rename to how VScode has named it.
65+
bool expandTabs = false;
6566

6667
struct PrimaryScreen
6768
{

0 commit comments

Comments
 (0)