Skip to content

Commit

Permalink
Add styling-capability for active tab in Tabs view in statusline
Browse files Browse the repository at this point in the history
Signed-off-by: Christian Parpart <[email protected]>
  • Loading branch information
christianparpart committed Oct 9, 2024
1 parent 6da571c commit 5eee23a
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 44 deletions.
2 changes: 1 addition & 1 deletion src/contour/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ struct TerminalProfile
statusDisplayPosition { vtbackend::StatusDisplayPosition::Bottom };
ConfigEntry<std::string, documentation::IndicatorStatusLineLeft> indicatorStatusLineLeft {
" {InputMode:Bold,Color=#FFFF00}"
"{Tabs:Left= │ }"
"{Tabs:ActiveColor=#FFFF00,Left= │ }"
"{SearchPrompt:Left= │ }"
"{TraceMode:Bold,Color=#FFFF00,Left= │ }"
"{ProtectedMode:Bold,Left= │ }"
Expand Down
18 changes: 4 additions & 14 deletions src/contour/TerminalSessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,10 @@ class TerminalSessionManager: public QAbstractListModel
if (!_activeSession)
return;

_activeSession->terminal().setGuiTabInfoForStatusLine(
[this, currentSessionIndex = getCurrentSessionIndex()]() {
std::string tabInfo;
for (size_t i = 0; i < _sessions.size(); ++i)
{
if (std::cmp_equal(i, currentSessionIndex))
tabInfo += "[";
tabInfo += std::to_string(i + 1);
if (std::cmp_equal(i, currentSessionIndex))
tabInfo += "]";
tabInfo += " ";
}
return tabInfo;
}());
_activeSession->terminal().setGuiTabInfoForStatusLine(vtbackend::TabsInfo {
.tabCount = _sessions.size(),
.activeTabPosition = _sessions.empty() ? 0 : static_cast<size_t>(1 + getCurrentSessionIndex()),
});
}

bool isAllowedToChangeTabs()
Expand Down
91 changes: 66 additions & 25 deletions src/vtbackend/StatusLineBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ namespace // helper functions
}
} // namespace

std::optional<RGBColor> tryParseColorAttribute(crispy::string_interpolation const& interpolation,
std::string_view key)
{
if (auto const i = interpolation.attributes.find(key); i != interpolation.attributes.end())
return parseColor(i->second);

return std::nullopt;
}

std::optional<StatusLineDefinitions::Item> makeStatusLineItem(
crispy::interpolated_string_fragment const& fragment)
{
Expand Down Expand Up @@ -73,17 +82,8 @@ std::optional<StatusLineDefinitions::Item> makeStatusLineItem(
if (interpolation.flags.count(text))
styles.flags.enable(flag);

if (auto const i = interpolation.attributes.find("Color"); i != interpolation.attributes.end())
{
if (auto const parsedColor = parseColor(i->second))
styles.foregroundColor = parsedColor.value();
}

if (auto const i = interpolation.attributes.find("BackgroundColor"); i != interpolation.attributes.end())
{
if (auto const parsedColor = parseColor(i->second))
styles.backgroundColor = parsedColor.value();
}
styles.foregroundColor = tryParseColorAttribute(interpolation, "Color");
styles.backgroundColor = tryParseColorAttribute(interpolation, "BackgroundColor");

if (auto const i = interpolation.attributes.find("Left"); i != interpolation.attributes.end())
styles.textLeft = i->second;
Expand Down Expand Up @@ -147,7 +147,16 @@ std::optional<StatusLineDefinitions::Item> makeStatusLineItem(
return StatusLineDefinitions::VTType { styles };

if (interpolation.name == "Tabs")
return StatusLineDefinitions::Tabs { styles };
{
std::optional<RGBColor> activeColor = tryParseColorAttribute(interpolation, "ActiveColor");
std::optional<RGBColor> activeBackground = tryParseColorAttribute(interpolation, "ActiveBackground");

return StatusLineDefinitions::Tabs {
styles,
activeColor,
activeBackground,
};
}

return std::nullopt;
}
Expand Down Expand Up @@ -194,22 +203,30 @@ struct VTSerializer
StatusLineStyling styling;
std::string result {};

std::string makeTextColor(std::optional<RGBColor> const& color, std::string_view defaultSequence = {})
{
if (!color)
return std::string(defaultSequence);

return std::format("\033[38:2:{}:{}:{}m", color->red, color->green, color->blue);
}

std::string makeBackgroundColor(std::optional<RGBColor> const& color,
std::string_view defaultSequence = {})
{
if (!color)
return std::string(defaultSequence);

return std::format("\033[48:2:{}:{}:{}m", color->red, color->green, color->blue);
}

void applyStyles(StatusLineDefinitions::Styles const& styles) // {{{
{
if (styling == StatusLineStyling::Disabled)
return;

if (styles.foregroundColor)
result += std::format("\033[38:2:{}:{}:{}m",
styles.foregroundColor->red,
styles.foregroundColor->green,
styles.foregroundColor->blue);

if (styles.backgroundColor)
result += std::format("\033[48:2:{}:{}:{}m",
styles.backgroundColor->red,
styles.backgroundColor->green,
styles.backgroundColor->blue);
result += makeTextColor(styles.foregroundColor);
result += makeBackgroundColor(styles.backgroundColor);

result += styles.flags.reduce(std::string {}, [](std::string&& result, CellFlag flag) -> std::string {
switch (flag)
Expand Down Expand Up @@ -420,9 +437,33 @@ struct VTSerializer

std::string visit(StatusLineDefinitions::VTType const&) { return std::format("{}", vt.terminalId()); }

std::string visit(StatusLineDefinitions::Tabs const&)
std::string visit(StatusLineDefinitions::Tabs const& tabs)
{
return std::format("{}", vt.guiTabInfoForStatusLine());
auto const tabsInfo = vt.guiTabsInfoForStatusLine();

std::string fragment;
for (size_t position: std::views::iota(1u, tabsInfo.tabCount + 1))
{
if (!fragment.empty())
fragment += ' ';

auto const isActivePosition = position == tabsInfo.activeTabPosition;
auto const activePositionStylized =
isActivePosition && (tabs.activeColor || tabs.activeBackground);

if (activePositionStylized)
{
fragment += SGRSAVE();
fragment += makeTextColor(tabs.activeColor);
fragment += makeBackgroundColor(tabs.activeBackground);
}

fragment += std::to_string(position);

if (activePositionStylized)
fragment += SGRRESTORE();
}
return fragment;
}
// }}}
};
Expand Down
7 changes: 6 additions & 1 deletion src/vtbackend/StatusLineBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,12 @@ namespace StatusLineDefinitions
struct Text: Styles { std::string text; };
struct TraceMode: Styles {};
struct VTType: Styles {};
struct Tabs: Styles {};

struct Tabs: Styles
{
std::optional<RGBColor> activeColor;
std::optional<RGBColor> activeBackground;
};

using Item = std::variant<
CellSGR,
Expand Down
12 changes: 9 additions & 3 deletions src/vtbackend/Terminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ class TraceHandler: public SequenceHandler
PendingSequenceQueue _pendingSequences = {};
};

struct TabsInfo
{
size_t tabCount = 1;
size_t activeTabPosition = 1;
};

/// Terminal API to manage input and output devices of a pseudo terminal, such as keyboard, mouse, and screen.
///
/// With a terminal being attached to a Process, the terminal's screen
Expand Down Expand Up @@ -955,8 +961,8 @@ class Terminal
void setStatusLineDefinition(StatusLineDefinition&& definition);
void resetStatusLineDefinition();

std::string_view guiTabInfoForStatusLine() const noexcept { return _guiTabInfoForStatusLine; }
void setGuiTabInfoForStatusLine(std::string value) { _guiTabInfoForStatusLine = std::move(value); }
TabsInfo guiTabsInfoForStatusLine() const noexcept { return _guiTabInfoForStatusLine; }
void setGuiTabInfoForStatusLine(TabsInfo info) { _guiTabInfoForStatusLine = info; }

private:
void mainLoop();
Expand Down Expand Up @@ -1070,7 +1076,7 @@ class Terminal
Viewport _viewport;
StatusLineDefinition _indicatorStatusLineDefinition;

std::string _guiTabInfoForStatusLine;
TabsInfo _guiTabInfoForStatusLine;

// {{{ selection states
std::unique_ptr<Selection> _selection;
Expand Down

0 comments on commit 5eee23a

Please sign in to comment.