Add an experimental setting for making suggestions RGB (#17416)

Adds `$profile:experimental.rainbowSuggestions`, which makes the
suggestion text all RGB. This sparks joy.
This commit is contained in:
Mike Griese 2024-06-25 17:44:56 -05:00 committed by GitHub
parent 9f7032afd8
commit 174dcb9091
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 67 additions and 27 deletions

View File

@ -19,5 +19,7 @@ namespace Microsoft.Terminal.Control
Boolean RetroTerminalEffect { get; };
String PixelShaderPath { get; };
String PixelShaderImagePath { get; };
// NOTE! When adding something here, make sure to update ControlProperties.h too!
};
}

View File

@ -66,5 +66,7 @@ namespace Microsoft.Terminal.Control
Boolean UseBackgroundImageForWindow { get; };
Boolean RightClickContextMenu { get; };
Boolean RepositionCursorWithMouse { get; };
// NOTE! When adding something here, make sure to update ControlProperties.h too!
};
}

View File

@ -122,5 +122,7 @@ namespace Microsoft.Terminal.Core
Boolean IntenseIsBold;
Boolean IntenseIsBright;
AdjustTextMode AdjustIndistinguishableColors;
// NOTE! When adding something here, make sure to update ControlProperties.h too!
};
}

View File

@ -27,7 +27,9 @@ namespace Microsoft.Terminal.Core
Windows.Foundation.IReference<Microsoft.Terminal.Core.Color> StartingTabColor;
Boolean AutoMarkPrompts;
Boolean RainbowSuggestions;
// NOTE! When adding something here, make sure to update ControlProperties.h too!
};
}

View File

@ -95,6 +95,7 @@ void Terminal::UpdateSettings(ICoreSettings settings)
_startingTitle = settings.StartingTitle();
_trimBlockSelection = settings.TrimBlockSelection();
_autoMarkPrompts = settings.AutoMarkPrompts();
_rainbowSuggestions = settings.RainbowSuggestions();
_getTerminalInput().ForceDisableWin32InputMode(settings.ForceVTInput());
@ -1586,7 +1587,7 @@ til::point Terminal::GetViewportRelativeCursorPosition() const noexcept
void Terminal::PreviewText(std::wstring_view input)
{
// Our suggestion text is default-on-default, in italics.
// Our default suggestion text is default-on-default, in italics.
static constexpr TextAttribute previewAttrs{ CharacterAttributes::Italics, TextColor{}, TextColor{}, 0u, TextColor{} };
auto lock = LockForWriting();
@ -1626,11 +1627,43 @@ void Terminal::PreviewText(std::wstring_view input)
// pad it out
preview.insert(originalSize, expectedLenTillEnd - originalSize, L' ');
}
snippetPreview.text = til::visualize_nonspace_control_codes(preview);
// Build our composition data
// The text is just the trimmed command, with the spaces at the end.
snippetPreview.text = til::visualize_nonspace_control_codes(preview);
// The attributes depend on the $profile:experimental.rainbowSuggestions setting:.
const auto len = snippetPreview.text.size();
snippetPreview.attributes.clear();
snippetPreview.attributes.emplace_back(len, previewAttrs);
if (_rainbowSuggestions)
{
// Let's do something fun.
// Use the actual text length for the number of steps, not including the
// trailing spaces.
const float increment = 1.0f / originalSize;
for (auto i = 0u; i < originalSize; i++)
{
const auto color = til::color::from_hue(increment * i);
TextAttribute curr = previewAttrs;
curr.SetForeground(color);
snippetPreview.attributes.emplace_back(1, curr);
}
if (originalSize < len)
{
TextAttribute curr;
snippetPreview.attributes.emplace_back(len - originalSize, curr);
}
}
else
{
// Default:
// Use the default attribute we defined above.
snippetPreview.attributes.emplace_back(len, previewAttrs);
}
snippetPreview.cursorPos = len;
_activeBuffer().NotifyPaintFrame();
}

View File

@ -360,6 +360,7 @@ private:
bool _suppressApplicationTitle = false;
bool _trimBlockSelection = false;
bool _autoMarkPrompts = false;
bool _rainbowSuggestions = false;
size_t _taskbarState = 0;
size_t _taskbarProgress = 0;

View File

@ -96,7 +96,8 @@ Author(s):
X(bool, AutoMarkPrompts, "autoMarkPrompts", false) \
X(bool, ShowMarks, "showMarksOnScrollbar", false) \
X(bool, RepositionCursorWithMouse, "experimental.repositionCursorWithMouse", false) \
X(bool, ReloadEnvironmentVariables, "compatibility.reloadEnvironmentVariables", true)
X(bool, ReloadEnvironmentVariables, "compatibility.reloadEnvironmentVariables", true) \
X(bool, RainbowSuggestions, "experimental.rainbowSuggestions", false)
// Intentionally omitted Profile settings:
// * Name

View File

@ -87,6 +87,7 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_PROFILE_SETTING(Boolean, RepositionCursorWithMouse);
INHERITABLE_PROFILE_SETTING(Boolean, ReloadEnvironmentVariables);
INHERITABLE_PROFILE_SETTING(Boolean, RainbowSuggestions);
}
}

View File

@ -343,10 +343,9 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
_ShowMarks = Feature_ScrollbarMarks::IsEnabled() && profile.ShowMarks();
_RightClickContextMenu = profile.RightClickContextMenu();
_RepositionCursorWithMouse = profile.RepositionCursorWithMouse();
_ReloadEnvironmentVariables = profile.ReloadEnvironmentVariables();
_RainbowSuggestions = profile.RainbowSuggestions();
}
// Method Description:

View File

@ -112,6 +112,7 @@ namespace winrt::Microsoft::Terminal::Settings::Model::implementation
INHERITABLE_SETTING(Model::TerminalSettings, bool, IntenseIsBright);
INHERITABLE_SETTING(Model::TerminalSettings, Microsoft::Terminal::Core::AdjustTextMode, AdjustIndistinguishableColors, Core::AdjustTextMode::Never);
INHERITABLE_SETTING(Model::TerminalSettings, bool, RainbowSuggestions, false);
// ------------------------ End of Core Settings -----------------------

View File

@ -1128,25 +1128,6 @@ void AppHost::_stopFrameTimer()
// is called as the `_frameTimer` Tick callback, roughly 60 times per second.
void AppHost::_updateFrameColor(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::Foundation::IInspectable&)
{
// First, a couple helper functions:
static const auto saturateAndToColor = [](const float a, const float b, const float c) -> til::color {
return til::color{
base::saturated_cast<uint8_t>(255.f * std::clamp(a, 0.f, 1.f)),
base::saturated_cast<uint8_t>(255.f * std::clamp(b, 0.f, 1.f)),
base::saturated_cast<uint8_t>(255.f * std::clamp(c, 0.f, 1.f))
};
};
// Helper for converting a hue [0, 1) to an RGB value.
// Credit to https://www.chilliant.com/rgb2hsv.html
static const auto hueToRGB = [&](const float H) -> til::color {
float R = abs(H * 6 - 3) - 1;
float G = 2 - abs(H * 6 - 2);
float B = 2 - abs(H * 6 - 4);
return saturateAndToColor(R, G, B);
};
// Now, the main body of work.
// - Convert the time delta between when we were started and now, to a hue. This will cycle us through all the colors.
// - Convert that hue to an RGB value.
// - Set the frame's color to that RGB color.
@ -1154,7 +1135,7 @@ void AppHost::_updateFrameColor(const winrt::Windows::Foundation::IInspectable&,
const std::chrono::duration<float> delta{ now - _started };
const auto seconds = delta.count() / 4; // divide by four, to make the effect slower. Otherwise it flashes way to fast.
float ignored;
const auto color = hueToRGB(modf(seconds, &ignored));
const auto color = til::color::from_hue(modf(seconds, &ignored));
_frameColorHelper(_window->GetHandle(), color);
}

View File

@ -49,7 +49,8 @@
X(winrt::hstring, StartingTitle) \
X(bool, DetectURLs, true) \
X(bool, AutoMarkPrompts) \
X(bool, RepositionCursorWithMouse, false)
X(bool, RepositionCursorWithMouse, false) \
X(bool, RainbowSuggestions)
// --------------------------- Control Settings ---------------------------
// All of these settings are defined in IControlSettings.

View File

@ -186,6 +186,20 @@ namespace til // Terminal Implementation Library. Also: "Today I Learned"
}
#endif
// Helper for converting a hue [0, 1) to an RGB value.
// Credit to https://www.chilliant.com/rgb2hsv.html
static til::color from_hue(float hue)
{
const float R = abs(hue * 6 - 3) - 1;
const float G = 2 - abs(hue * 6 - 2);
const float B = 2 - abs(hue * 6 - 4);
return color{
base::saturated_cast<uint8_t>(255.f * std::clamp(R, 0.f, 1.f)),
base::saturated_cast<uint8_t>(255.f * std::clamp(G, 0.f, 1.f)),
base::saturated_cast<uint8_t>(255.f * std::clamp(B, 0.f, 1.f))
};
}
constexpr bool operator==(const til::color& other) const
{
return abgr == other.abgr;