One place to pick a buffer's highlighter
Filetype detection (extension or shebang) was written out three times (two open paths in Editor and the ImGui frontend's per-frame check) and "highlighter for this filetype, else the null one" five times (Buffer's copy constructor and assignment, Editor::SwitchTo, :set filetype). Buffer::ApplyDetectedFiletype and InstallFiletypeHighlighter replace them. The InvalidateFrom(0) calls after SetHighlighter are dropped: SetHighlighter already clears the caches. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015rcVQiiWyTzoNrsvLSaAfB
This commit is contained in:
@@ -377,23 +377,8 @@ Buffer::Buffer(const Buffer &other)
|
||||
undo_sys_ = std::make_unique<UndoSystem>(*this, *undo_tree_);
|
||||
|
||||
// Recreate a highlighter engine for this copy based on filetype/syntax state
|
||||
if (syntax_enabled_) {
|
||||
// Allocate engine and install an appropriate highlighter
|
||||
highlighter_ = std::make_unique<kte::HighlighterEngine>();
|
||||
if (!filetype_.empty()) {
|
||||
auto hl = kte::HighlighterRegistry::CreateFor(filetype_);
|
||||
if (hl) {
|
||||
highlighter_->SetHighlighter(std::move(hl));
|
||||
} else {
|
||||
// Unsupported filetype -> NullHighlighter keeps syntax pipeline active
|
||||
highlighter_->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
}
|
||||
} else {
|
||||
// No filetype -> keep syntax enabled but use NullHighlighter
|
||||
highlighter_->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
}
|
||||
// Fresh engine has empty caches; nothing to invalidate
|
||||
}
|
||||
if (syntax_enabled_)
|
||||
InstallFiletypeHighlighter();
|
||||
}
|
||||
|
||||
|
||||
@@ -428,19 +413,8 @@ Buffer::operator=(const Buffer &other)
|
||||
|
||||
// Recreate highlighter engine consistent with syntax settings
|
||||
highlighter_.reset();
|
||||
if (syntax_enabled_) {
|
||||
highlighter_ = std::make_unique<kte::HighlighterEngine>();
|
||||
if (!filetype_.empty()) {
|
||||
auto hl = kte::HighlighterRegistry::CreateFor(filetype_);
|
||||
if (hl) {
|
||||
highlighter_->SetHighlighter(std::move(hl));
|
||||
} else {
|
||||
highlighter_->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
}
|
||||
} else {
|
||||
highlighter_->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
}
|
||||
}
|
||||
if (syntax_enabled_)
|
||||
InstallFiletypeHighlighter();
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -768,6 +742,29 @@ Buffer::insert_text(int row, int col, std::string_view text)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Buffer::ApplyDetectedFiletype()
|
||||
{
|
||||
EnsureHighlighter();
|
||||
const std::string first = Nrows() > 0 ? GetLineString(0) : std::string();
|
||||
const std::string ft = kte::HighlighterRegistry::DetectForPath(filename_, first);
|
||||
SetFiletype(ft);
|
||||
SetSyntaxEnabled(true);
|
||||
InstallFiletypeHighlighter();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Buffer::InstallFiletypeHighlighter()
|
||||
{
|
||||
EnsureHighlighter();
|
||||
auto hl = filetype_.empty() ? nullptr : kte::HighlighterRegistry::CreateFor(filetype_);
|
||||
if (!hl)
|
||||
hl = std::make_unique<kte::NullHighlighter>();
|
||||
highlighter_->SetHighlighter(std::move(hl));
|
||||
}
|
||||
|
||||
|
||||
// ===== Adapter helpers for PieceTable-backed Buffer =====
|
||||
std::string
|
||||
Buffer::Bytes() const
|
||||
|
||||
@@ -472,6 +472,15 @@ public:
|
||||
}
|
||||
|
||||
|
||||
// Enable syntax with the highlighter the filename (or a shebang on the
|
||||
// first line) calls for, or none for an unknown type.
|
||||
void ApplyDetectedFiletype();
|
||||
|
||||
// Install the highlighter for Filetype() (the null highlighter for an
|
||||
// empty or unsupported one), creating the engine if needed.
|
||||
void InstallFiletypeHighlighter();
|
||||
|
||||
|
||||
// Swap journal integration (set by Editor)
|
||||
void SetSwapRecorder(kte::SwapRecorder *rec)
|
||||
{
|
||||
|
||||
+6
-24
@@ -15,7 +15,6 @@
|
||||
#include "RegexEngine.h"
|
||||
#include "TermWidth.h"
|
||||
#include "syntax/HighlighterRegistry.h"
|
||||
#include "syntax/NullHighlighter.h"
|
||||
#include "Editor.h"
|
||||
#include "Buffer.h"
|
||||
#include "UndoSystem.h"
|
||||
@@ -1641,29 +1640,12 @@ apply_filetype(Buffer &buf, const std::string &ft)
|
||||
buf.SetSyntaxEnabled(false);
|
||||
return;
|
||||
}
|
||||
if (val.empty()) {
|
||||
// Empty means unknown/unspecified -> use NullHighlighter but keep syntax enabled
|
||||
buf.SetFiletype("");
|
||||
buf.SetSyntaxEnabled(true);
|
||||
eng->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
eng->InvalidateFrom(0);
|
||||
return;
|
||||
}
|
||||
// Normalize and create via registry
|
||||
std::string norm = kte::HighlighterRegistry::Normalize(val);
|
||||
auto hl = kte::HighlighterRegistry::CreateFor(norm);
|
||||
if (hl) {
|
||||
eng->SetHighlighter(std::move(hl));
|
||||
buf.SetFiletype(norm);
|
||||
buf.SetSyntaxEnabled(true);
|
||||
eng->InvalidateFrom(0);
|
||||
} else {
|
||||
// Unknown -> install NullHighlighter and keep syntax enabled
|
||||
eng->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
buf.SetFiletype(val); // record what user asked even if unsupported
|
||||
buf.SetSyntaxEnabled(true);
|
||||
eng->InvalidateFrom(0);
|
||||
}
|
||||
// Empty means unspecified (no highlighting, syntax stays on); an
|
||||
// unsupported type is recorded as asked, without highlighting.
|
||||
const std::string norm = val.empty() ? val : kte::HighlighterRegistry::Normalize(val);
|
||||
buf.SetFiletype(kte::HighlighterRegistry::CreateFor(norm) ? norm : val);
|
||||
buf.SetSyntaxEnabled(true);
|
||||
buf.InstallFiletypeHighlighter();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,9 +6,7 @@
|
||||
|
||||
#include "Editor.h"
|
||||
#include "ErrorHandler.h"
|
||||
#include "syntax/HighlighterRegistry.h"
|
||||
#include "syntax/CppHighlighter.h"
|
||||
#include "syntax/NullHighlighter.h"
|
||||
|
||||
|
||||
namespace {
|
||||
@@ -285,27 +283,8 @@ Editor::OpenFile(const std::string &path, std::string &err)
|
||||
cur.SetSwapRecorder(Swap()->RecorderFor(&cur));
|
||||
Swap()->NotifyFilenameChanged(cur);
|
||||
}
|
||||
// Setup highlighting using registry (extension + shebang)
|
||||
cur.EnsureHighlighter();
|
||||
std::string first = "";
|
||||
if (cur.Nrows() > 0)
|
||||
first = cur.GetLineString(0);
|
||||
std::string ft = kte::HighlighterRegistry::DetectForPath(path, first);
|
||||
if (!ft.empty()) {
|
||||
cur.SetFiletype(ft);
|
||||
cur.SetSyntaxEnabled(true);
|
||||
if (auto *eng = cur.Highlighter()) {
|
||||
eng->SetHighlighter(kte::HighlighterRegistry::CreateFor(ft));
|
||||
eng->InvalidateFrom(0);
|
||||
}
|
||||
} else {
|
||||
cur.SetFiletype("");
|
||||
cur.SetSyntaxEnabled(true);
|
||||
if (auto *eng = cur.Highlighter()) {
|
||||
eng->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
eng->InvalidateFrom(0);
|
||||
}
|
||||
}
|
||||
// Highlighting by extension or shebang
|
||||
cur.ApplyDetectedFiletype();
|
||||
// Defensive: ensure any active prompt is closed after a successful open
|
||||
CancelPrompt();
|
||||
return true;
|
||||
@@ -318,27 +297,8 @@ Editor::OpenFile(const std::string &path, std::string &err)
|
||||
}
|
||||
// NOTE: swap recorder/attach must happen after the buffer is stored in its
|
||||
// final location (vector) because swap manager keys off Buffer*.
|
||||
// Initialize syntax highlighting by extension + shebang via registry (v2)
|
||||
b.EnsureHighlighter();
|
||||
std::string first = "";
|
||||
if (b.Nrows() > 0)
|
||||
first = b.GetLineString(0);
|
||||
std::string ft = kte::HighlighterRegistry::DetectForPath(path, first);
|
||||
if (!ft.empty()) {
|
||||
b.SetFiletype(ft);
|
||||
b.SetSyntaxEnabled(true);
|
||||
if (auto *eng = b.Highlighter()) {
|
||||
eng->SetHighlighter(kte::HighlighterRegistry::CreateFor(ft));
|
||||
eng->InvalidateFrom(0);
|
||||
}
|
||||
} else {
|
||||
b.SetFiletype("");
|
||||
b.SetSyntaxEnabled(true);
|
||||
if (auto *eng = b.Highlighter()) {
|
||||
eng->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
eng->InvalidateFrom(0);
|
||||
}
|
||||
}
|
||||
// Highlighting by extension or shebang
|
||||
b.ApplyDetectedFiletype();
|
||||
// Add as a new buffer and switch to it
|
||||
std::size_t idx = AddBuffer(std::move(b));
|
||||
if (Swap()) {
|
||||
@@ -650,25 +610,8 @@ Editor::SwitchTo(std::size_t index)
|
||||
curbuf_ = index;
|
||||
// Robustness: ensure a valid highlighter is installed when switching buffers
|
||||
Buffer &b = bufs[curbuf_];
|
||||
if (b.SyntaxEnabled()) {
|
||||
b.EnsureHighlighter();
|
||||
if (auto *eng = b.Highlighter()) {
|
||||
if (!eng->HasHighlighter()) {
|
||||
// Try to set based on existing filetype; fall back to NullHighlighter
|
||||
if (!b.Filetype().empty()) {
|
||||
auto hl = kte::HighlighterRegistry::CreateFor(b.Filetype());
|
||||
if (hl) {
|
||||
eng->SetHighlighter(std::move(hl));
|
||||
} else {
|
||||
eng->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
}
|
||||
} else {
|
||||
eng->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
}
|
||||
eng->InvalidateFrom(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (b.SyntaxEnabled() && !(b.Highlighter() && b.Highlighter()->HasHighlighter()))
|
||||
b.InstallFiletypeHighlighter();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
+2
-18
@@ -19,8 +19,6 @@
|
||||
#include "fonts/Font.h" // embedded default font (DefaultFont)
|
||||
#include "fonts/FontRegistry.h"
|
||||
#include "fonts/IosevkaExtended.h"
|
||||
#include "syntax/HighlighterRegistry.h"
|
||||
#include "syntax/NullHighlighter.h"
|
||||
|
||||
|
||||
#ifndef KTE_FONT_SIZE
|
||||
@@ -54,22 +52,8 @@ apply_syntax_to_buffer(Buffer *b, const GUIConfig &cfg)
|
||||
if (cfg.syntax && b->GetEditMode() != EditMode::Writing) {
|
||||
b->SetSyntaxEnabled(true);
|
||||
b->EnsureHighlighter();
|
||||
if (auto *eng = b->Highlighter()) {
|
||||
if (!eng->HasHighlighter()) {
|
||||
const std::string first_line = b->Nrows() > 0 ? b->GetLineString(0) : std::string();
|
||||
std::string ft = kte::HighlighterRegistry::DetectForPath(
|
||||
b->Filename(), first_line);
|
||||
if (!ft.empty()) {
|
||||
eng->SetHighlighter(kte::HighlighterRegistry::CreateFor(ft));
|
||||
b->SetFiletype(ft);
|
||||
eng->InvalidateFrom(0);
|
||||
} else {
|
||||
eng->SetHighlighter(std::make_unique<kte::NullHighlighter>());
|
||||
b->SetFiletype("");
|
||||
eng->InvalidateFrom(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!b->Highlighter()->HasHighlighter())
|
||||
b->ApplyDetectedFiletype();
|
||||
} else {
|
||||
b->SetSyntaxEnabled(false);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user