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 20, 2025
1 parent ca16c0e commit ab2db50
Show file tree
Hide file tree
Showing 17 changed files with 305 additions and 48 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
2 changes: 2 additions & 0 deletions src/contour/ConfigDocumentation.h
Original file line number Diff line number Diff line change
Expand Up @@ -813,6 +813,8 @@ constexpr StringLiteral InputMappingsConfig {
"p.\n"
"{comment} - WriteScreen Writes VT sequence in `chars` member to the screen (bypassing the "
"application).\n"
"{comment} - SetTabName Ask the user to assign a name to the active tab.\n"
"\n"
"input_mapping:\n"
};

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().requestTabName();
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
14 changes: 11 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 @@ -404,6 +406,9 @@ struct VTSerializer
return std::format("Search: {}█",
unicode::convert_to<char>(std::u32string_view(vt.search().pattern)));

if (vt.inputHandler().isEditingPrompt())
return std::format("{}{}█", vt.prompt().prompt, vt.prompt().text);

return {};
}

Expand Down Expand Up @@ -443,10 +448,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 +464,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
20 changes: 20 additions & 0 deletions src/vtbackend/Terminal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1567,6 +1567,16 @@ std::string const& Terminal::windowTitle() const noexcept
return _windowTitle;
}

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

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

void Terminal::saveWindowTitle()
{
_savedWindowTitles.push(_windowTitle);
Expand Down Expand Up @@ -2195,6 +2205,16 @@ bool Terminal::setNewSearchTerm(std::u32string text, bool initiatedByDoubleClick
return true;
}

void Terminal::setPrompt(std::string prompt)
{
_prompt.prompt = std::move(prompt);
}

void Terminal::setPromptText(std::string text)
{
_prompt.text = std::move(text);
}

optional<CellLocation> Terminal::searchReverse(u32string text, CellLocation searchPosition)
{
if (!setNewSearchTerm(std::move(text), false))
Expand Down
Loading

0 comments on commit ab2db50

Please sign in to comment.