Skip to content

Commit

Permalink
Allow naming of the tabs
Browse files Browse the repository at this point in the history
  • Loading branch information
Yaraslaut committed Jan 15, 2025
1 parent ca16c0e commit e0b350e
Show file tree
Hide file tree
Showing 14 changed files with 159 additions and 14 deletions.
1 change: 1 addition & 0 deletions metainfo.xml
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@
<li>Adds `MoveTabTo` action to move tabs to a specific position (#1695)</li>
<li>Adds handling of control codes for Ctrl+5|6|7|8 (#1701)</li>
<li>Adds CenterCursor (`zz`) vi motion</li>
<li>Adds ability to name tabs (#1690)</li>
</ul>
</description>
</release>
Expand Down
1 change: 1 addition & 0 deletions src/contour/Actions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ optional<Action> fromString(string const& name)
mapAction<actions::SwitchToPreviousTab>("SwitchToPreviousTab"),
mapAction<actions::SwitchToTabLeft>("SwitchToTabLeft"),
mapAction<actions::SwitchToTabRight>("SwitchToTabRight"),
mapAction<actions::SetTabName>("SetTabName"),
};

auto const lowerCaseName = toLower(name);
Expand Down
8 changes: 7 additions & 1 deletion src/contour/Actions.h
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ struct SwitchToTab{ int position; };
struct SwitchToPreviousTab{};
struct SwitchToTabLeft{};
struct SwitchToTabRight{};
struct SetTabName{};
// clang-format on

using Action = std::variant<CancelSelection,
Expand Down Expand Up @@ -149,7 +150,8 @@ using Action = std::variant<CancelSelection,
SwitchToTab,
SwitchToPreviousTab,
SwitchToTabLeft,
SwitchToTabRight>;
SwitchToTabRight,
SetTabName>;

std::optional<Action> fromString(std::string const& name);

Expand Down Expand Up @@ -276,6 +278,7 @@ namespace documentation
constexpr inline std::string_view SwitchToPreviousTab { "Switch to the previously focused tab" };
constexpr inline std::string_view SwitchToTabLeft { "Switch to tab to the left" };
constexpr inline std::string_view SwitchToTabRight { "Switch to tab to the right" };
constexpr inline std::string_view SetTabName { "Set the name of the current tab" };
} // namespace documentation

inline auto getDocumentation()
Expand Down Expand Up @@ -341,6 +344,7 @@ inline auto getDocumentation()
std::tuple { Action { SwitchToPreviousTab {} }, documentation::SwitchToPreviousTab },
std::tuple { Action { SwitchToTabLeft {} }, documentation::SwitchToTabLeft },
std::tuple { Action { SwitchToTabRight {} }, documentation::SwitchToTabRight },
std::tuple { Action { SetTabName {} }, documentation::SetTabName },
};
}

Expand Down Expand Up @@ -416,6 +420,7 @@ DECLARE_ACTION_FMT(MoveTabToRight)
DECLARE_ACTION_FMT(SwitchToPreviousTab)
DECLARE_ACTION_FMT(SwitchToTabLeft)
DECLARE_ACTION_FMT(SwitchToTabRight)
DECLARE_ACTION_FMT(SetTabName)
// }}}
#undef DECLARE_ACTION_FMT

Expand Down Expand Up @@ -506,6 +511,7 @@ struct std::formatter<contour::actions::Action>: std::formatter<std::string>
HANDLE_ACTION(SwitchToPreviousTab);
HANDLE_ACTION(SwitchToTabLeft);
HANDLE_ACTION(SwitchToTabRight);
HANDLE_ACTION(SetTabName);
if (std::holds_alternative<contour::actions::MoveTabTo>(_action))
{
const auto action = std::get<contour::actions::MoveTabTo>(_action);
Expand Down
3 changes: 1 addition & 2 deletions src/contour/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,10 @@ struct MouseConfig
struct IndicatorConfig
{
std::string left { " {InputMode:Bold,Color=#FFFF00}"
"{Tabs:ActiveColor=#FFFF00,Left= │ }"
"{SearchPrompt:Left= │ }"
"{TraceMode:Bold,Color=#FFFF00,Left= │ }"
"{ProtectedMode:Bold,Left= │ }" };
std::string middle { "{Title:Left= « ,Right= » }" };
std::string middle { "{Tabs: ActiveColor=#FFFF00}" };
std::string right { "{HistoryLineCount:Faint,Color=#c0c0c0} │ {Clock:Bold}" };
};

Expand Down
44 changes: 44 additions & 0 deletions src/contour/TerminalSession.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,43 @@ namespace
settings.indicatorStatusLine.left = profile.statusLine.value().indicator.left;
settings.indicatorStatusLine.middle = profile.statusLine.value().indicator.middle;
settings.indicatorStatusLine.right = profile.statusLine.value().indicator.right;
settings.tabNamingMode = [&]() {
// try to find Tab section in one of the status line segments

std::string segment;
if (profile.statusLine.value().indicator.left.find("Tabs") != std::string::npos)
{
segment = profile.statusLine.value().indicator.left;
}
else if (profile.statusLine.value().indicator.middle.find("Tabs") != std::string::npos)
{
segment = profile.statusLine.value().indicator.middle;
}
else if (profile.statusLine.value().indicator.right.find("Tabs") != std::string::npos)
{
segment = profile.statusLine.value().indicator.right;
}

// check if indexing is defined
if (segment.find("Indexing=") != std::string::npos)
{
// cut the string after indexing=
std::string indexing = segment.substr(segment.find("Indexing=") + 9);
// cut right part of the string
indexing = indexing.substr(0, indexing.find(','));
indexing = indexing.substr(0, indexing.find('}'));

std::ranges::transform(
indexing, indexing.begin(), [](unsigned char c) { return std::tolower(c); });

if (indexing == "title")
{
return vtbackend::TabsNamingMode::Title;
}
}
return vtbackend::TabsNamingMode::Indexing;
}();

settings.syncWindowTitleWithHostWritableStatusDisplay =
profile.statusLine.value().syncWindowTitleWithHostWritableStatusDisplay;
if (auto const* p = preferredColorPalette(profile.colors.value(), colorPreference))
Expand Down Expand Up @@ -262,6 +299,7 @@ void TerminalSession::attachDisplay(display::TerminalDisplay& newDisplay)
void TerminalSession::scheduleRedraw()
{
_terminal.markScreenDirty();
_manager->Update();
if (_display)
_display->scheduleRedraw();
}
Expand Down Expand Up @@ -1488,6 +1526,12 @@ bool TerminalSession::operator()(actions::SwitchToTabRight)
return true;
}

bool TerminalSession::operator()(actions::SetTabName)
{
terminal().setTabName();
return true;
}

// }}}
// {{{ implementation helpers
void TerminalSession::setDefaultCursor()
Expand Down
9 changes: 9 additions & 0 deletions src/contour/TerminalSession.h
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,14 @@ class TerminalSession: public QAbstractItemModel, public vtbackend::Terminal::Ev
~TerminalSession() override;

int id() const noexcept { return _id; }
std::optional<std::string> name() const noexcept
{
if (terminal().tabName())
return terminal().tabName();
if (terminal().getTabsNamingMode() == vtbackend::TabsNamingMode::Title)
return terminal().windowTitle();
return std::nullopt;
}

/// Starts the VT background thread.
void start();
Expand Down Expand Up @@ -364,6 +372,7 @@ class TerminalSession: public QAbstractItemModel, public vtbackend::Terminal::Ev
bool operator()(actions::SwitchToPreviousTab);
bool operator()(actions::SwitchToTabLeft);
bool operator()(actions::SwitchToTabRight);
bool operator()(actions::SetTabName);

void scheduleRedraw();

Expand Down
14 changes: 11 additions & 3 deletions src/contour/TerminalSessionManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ class TerminalSessionManager: public QAbstractListModel
TerminalSessionManager(ContourGuiApp& app);

contour::TerminalSession* createSessionInBackground();
contour::TerminalSession* activateSession(TerminalSession* session, bool isNewSession = false);

Q_INVOKABLE contour::TerminalSession* createSession();

Expand All @@ -54,7 +53,10 @@ class TerminalSessionManager: public QAbstractListModel
display::TerminalDisplay* display = nullptr;
TerminalSession* getSession() { return _sessions[0]; }

void Update() { updateStatusLine(); }

private:
contour::TerminalSession* activateSession(TerminalSession* session, bool isNewSession = false);
std::unique_ptr<vtpty::Pty> createPty(std::optional<std::string> cwd);

[[nodiscard]] std::optional<std::size_t> getSessionIndexOf(TerminalSession* session) const noexcept
Expand All @@ -73,9 +75,15 @@ class TerminalSessionManager: public QAbstractListModel
{
if (!_activeSession)
return;

_activeSession->terminal().setGuiTabInfoForStatusLine(vtbackend::TabsInfo {
.tabCount = _sessions.size(),
.tabs = std::ranges::transform_view(_sessions,
[](auto* session) {
return vtbackend::TabsInfo::Tab {
.name = session->name(),
.color = vtbackend::RGBColor { 0, 0, 0 },
};
})
| ranges::to<std::vector>(),
.activeTabPosition = 1 + getSessionIndexOf(_activeSession).value_or(0),
});
}
Expand Down
8 changes: 8 additions & 0 deletions src/vtbackend/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ struct RefreshInterval
explicit RefreshInterval(RefreshRate rate): value { static_cast<long long>(1000.0 / rate.value) } {}
};

enum class TabsNamingMode : uint8_t
{
Indexing,
Title
};

/// Terminal settings, enabling hardware reset to be easier implemented.
struct Settings
{
Expand Down Expand Up @@ -91,6 +97,8 @@ struct Settings
bool fromSearchIntoInsertMode = true;
bool isInsertAfterYank = false;

TabsNamingMode tabNamingMode = TabsNamingMode::Indexing;

// TODO: we could configure also the number of lines of the host writable statusline and indicator
// statusline.
};
Expand Down
11 changes: 8 additions & 3 deletions src/vtbackend/StatusLineBuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <chrono>
#include <cstdio>
#include <format>
#include <optional>

using namespace std::string_view_literals;

Expand Down Expand Up @@ -156,6 +157,7 @@ std::optional<StatusLineDefinitions::Item> makeStatusLineItem(
styles,
activeColor,
activeBackground,
std::nullopt, // separator
};
}

Expand Down Expand Up @@ -443,10 +445,10 @@ struct VTSerializer
auto const tabsInfo = vt.guiTabsInfoForStatusLine();

std::string fragment;
for (const auto position: std::views::iota(1u, tabsInfo.tabCount + 1))
for (const auto position: std::views::iota(1u, tabsInfo.tabs.size() + 1))
{
if (!fragment.empty())
fragment += ' ';
fragment += tabs.separator.value_or("|");

auto const isActivePosition = position == tabsInfo.activeTabPosition;
auto const activePositionStylized =
Expand All @@ -459,7 +461,10 @@ struct VTSerializer
fragment += makeBackgroundColor(tabs.activeBackground);
}

fragment += std::to_string(position);
if (tabsInfo.tabs[position - 1].name)
fragment += tabsInfo.tabs[position - 1].name.value();
else
fragment += std::to_string(position);

if (activePositionStylized)
fragment += SGRRESTORE();
Expand Down
1 change: 1 addition & 0 deletions src/vtbackend/StatusLineBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ namespace StatusLineDefinitions
{
std::optional<RGBColor> activeColor;
std::optional<RGBColor> activeBackground;
std::optional<std::string> separator;
};

using Item = std::variant<
Expand Down
16 changes: 16 additions & 0 deletions src/vtbackend/Terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1562,11 +1562,27 @@ void Terminal::setWindowTitle(string_view title)
_eventListener.setWindowTitle(title);
}

void Terminal::setTabName(string_view title)
{
_tabName = title;
}

std::string const& Terminal::windowTitle() const noexcept
{
return _windowTitle;
}

void Terminal::setTabName()
{
inputHandler().setTabName([&](std::string name) { _tabName = name;
});
}

std::optional<std::string> Terminal::tabName() const noexcept
{
return _tabName;
}

void Terminal::saveWindowTitle()
{
_savedWindowTitles.push(_windowTitle);
Expand Down
25 changes: 22 additions & 3 deletions src/vtbackend/Terminal.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <mutex>
#include <stack>
#include <string_view>
#include <utility>

namespace vtbackend
{
Expand Down Expand Up @@ -209,7 +210,13 @@ class TraceHandler: public SequenceHandler

struct TabsInfo
{
size_t tabCount = 1;
struct Tab
{
std::optional<std::string> name;
Color color;
};

std::vector<Tab> tabs;
size_t activeTabPosition = 1;
};

Expand Down Expand Up @@ -246,6 +253,7 @@ class Terminal
virtual void requestWindowResize(Width, Height) {}
virtual void requestShowHostWritableStatusLine() {}
virtual void setWindowTitle(std::string_view /*title*/) {}
virtual void setTabName(std::string_view /*title*/) {}
virtual void setTerminalProfile(std::string const& /*configProfileName*/) {}
virtual void discardImage(Image const&) {}
virtual void inputModeChanged(ViMode /*mode*/) {}
Expand Down Expand Up @@ -276,6 +284,7 @@ class Terminal
void requestWindowResize(Width, Height) override {}
void requestShowHostWritableStatusLine() override {}
void setWindowTitle(std::string_view /*title*/) override {}
void setTabName(std::string_view /*title*/) override {}
void setTerminalProfile(std::string const& /*configProfileName*/) override {}
void discardImage(Image const&) override {}
void inputModeChanged(ViMode /*mode*/) override {}
Expand Down Expand Up @@ -357,7 +366,7 @@ class Terminal

[[nodiscard]] CellLocation clampToScreen(CellLocation coord) const noexcept
{
return { clampedLine(coord.line), clampedColumn(coord.column) };
return { .line = clampedLine(coord.line), .column = clampedColumn(coord.column) };
}

// Tests if given coordinate is within the visible screen area.
Expand Down Expand Up @@ -797,7 +806,9 @@ class Terminal
void setMouseTransport(MouseTransport transport);
void setMouseWheelMode(InputGenerator::MouseWheelMode mode);
void setWindowTitle(std::string_view title);
void setTabName(std::string_view title);
[[nodiscard]] std::string const& windowTitle() const noexcept;
[[nodiscard]] std::optional<std::string> tabName() const noexcept;
[[nodiscard]] bool focused() const noexcept { return _focused; }
[[nodiscard]] Search& search() noexcept { return _search; }
[[nodiscard]] Search const& search() const noexcept { return _search; }
Expand Down Expand Up @@ -966,7 +977,11 @@ class Terminal
void resetStatusLineDefinition();

TabsInfo guiTabsInfoForStatusLine() const noexcept { return _guiTabInfoForStatusLine; }
void setGuiTabInfoForStatusLine(TabsInfo info) { _guiTabInfoForStatusLine = info; }
void setGuiTabInfoForStatusLine(TabsInfo&& info) { _guiTabInfoForStatusLine = std::move(info); }

TabsNamingMode getTabsNamingMode() const noexcept { return _settings.tabNamingMode; }
void setTabName();


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

// {{{ tabs info
TabsInfo _guiTabInfoForStatusLine;
// }}}

// {{{ selection states
std::unique_ptr<Selection> _selection;
Expand Down Expand Up @@ -1165,6 +1182,8 @@ class Terminal
std::string _windowTitle {};
std::stack<std::string> _savedWindowTitles {};

std::optional<std::string> _tabName {};

struct ModeDependantSequenceHandler
{
Terminal& terminal;
Expand Down
Loading

0 comments on commit e0b350e

Please sign in to comment.