Final touches to code folding for the pattern editor. Also added some recent fixes to make rebasing easier.

This commit is contained in:
paxcut
2026-03-08 22:41:42 -07:00
committed by paxcut
parent c92b55e1b6
commit 1670607e38
7 changed files with 78 additions and 85 deletions

View File

@@ -33,11 +33,11 @@ namespace hex::plugin::builtin {
}
bool TokenInterval::operator<(const TokenInterval &other) const {
return other.m_end > m_end;
return other.m_end == m_end ? other.m_start < m_start : m_end < other.m_end;
}
bool TokenInterval::operator>(const TokenInterval &other) const {
return m_end > other.m_end;
return other.m_end == m_end ? other.m_start > m_start : m_end > other.m_end;
}
bool TokenInterval::operator==(const TokenInterval &other) const {
@@ -49,11 +49,11 @@ namespace hex::plugin::builtin {
}
bool TokenInterval::operator<=(const TokenInterval &other) const {
return other.m_end >= m_end;
return other.m_end == m_end ? other.m_start <= m_start : m_end < other.m_end;
}
bool TokenInterval::operator>=(const TokenInterval &other) const {
return m_end >= other.m_end;
return other.m_end == m_end ? other.m_start >= m_start : m_end > other.m_end;
}
[[nodiscard]] bool TokenInterval::contains(const TokenInterval &other) const {
@@ -124,11 +124,8 @@ namespace hex::plugin::builtin {
auto &result = m_textHighlighter->getPatternLanguage()->getInternals().preprocessor->getResult();
std::ranges::copy(result.begin(),result.end(),std::back_inserter(fullTokens));
editedText = editor->getText();
m_textHighlighter->loadText();;
m_textHighlighter->loadText();
linesOfColors.clear();
for (auto &line : m_textHighlighter->m_lines)
linesOfColors.emplace_back(line.size(), ' ');
}
void TextHighlighter::RequiredInputs::setCompileErrors() {
@@ -1605,8 +1602,8 @@ namespace hex::plugin::builtin {
curr = m_curr;
}
if (peek(tkn::Literal::Identifier)) {
std::string nameScape;
if (findNamespace(nameScape) && !nameScape.empty() && std::ranges::find(m_UDTs, (nameScape.append( "::" + name))) != m_UDTs.end()) {
std::string nameSpace;
if (findNamespace(nameSpace) && !nameSpace.empty() && std::ranges::find(m_UDTs, fmt::format("{}::{}",nameSpace, name)) != m_UDTs.end()) {
m_scopeChains.insert(tokenIndex);
}
}
@@ -1805,7 +1802,7 @@ namespace hex::plugin::builtin {
continue;
}
if (findNamespace(nameSpace,tokenId)) {
auto fullName = nameSpace + "::" + variableName;
auto fullName = fmt::format("{}::{}",nameSpace, variableName);
auto typeName = findIdentifierType(fullName, "");
if (typeName != IdentifierType::Unknown) {
setIdentifierColor(-1, typeName);
@@ -1834,10 +1831,12 @@ namespace hex::plugin::builtin {
while (m_firstTokenIdOfLine.at(topLine) == -1)
topLine++;
auto bottomLine = previousLine(m_firstTokenIdOfLine.size());
m_requiredInputs.linesOfColors.resize(m_lines.size());
for (u32 line = topLine; line < bottomLine; line = nextLine(line)) {
if (m_lines[line].empty())
continue;
std::string &lineOfColors = m_requiredInputs.linesOfColors[line];//std::string(m_lines[line].size(), 0);
m_requiredInputs.linesOfColors[line] = std::string(m_lines[line].size(), 0);
auto &lineOfColors = m_requiredInputs.linesOfColors[line];
for (auto tokenIndex = m_firstTokenIdOfLine.at(line); tokenIndex < m_firstTokenIdOfLine.at(nextLine(line)); tokenIndex++) {
auto *token = const_cast<Token *>(&m_requiredInputs.fullTokens.at(tokenIndex));
if (m_tokenColors.contains(tokenIndex) && token->type == Token::Type::Identifier) {
@@ -1864,12 +1863,12 @@ namespace hex::plugin::builtin {
if (auto iterator = m_inheritances.find(name); iterator != m_inheritances.end()) {
auto inheritances = std::move(iterator->second);
m_inheritances.erase(iterator);
for (auto inheritance: inheritances) {
for (const auto& inheritance: inheritances) {
recurseInheritances(inheritance);
auto definitions = m_UDTVariables[inheritance];
if (definitions.empty())
definitions = m_ImportedUDTVariables[inheritance];
for (auto [variableName, variableDefinitions]: definitions) {
for (const auto &[variableName, variableDefinitions]: definitions) {
auto tokenRange = m_UDTTokenRange[name];
u32 tokenIndex = tokenRange.m_start;
for (auto token = tokenRange.m_start; token < tokenRange.m_end; token++) {
@@ -1946,13 +1945,15 @@ namespace hex::plugin::builtin {
if (length < 0)
return false;
if (length > (i32) m_lines[line].size()-col)
if (line < (i32) m_lines.size() && length > (i32) m_lines[line].size()-col)
length -= (i32)( m_lines[line].size()-col);
while (m_firstTokenIdOfLine[line] == m_firstTokenIdOfLine[line + 1]) {
while (line < (i32) m_lines.size() && m_firstTokenIdOfLine[line] == m_firstTokenIdOfLine[line + 1]) {
length -= (i32) m_lines[line].size();
line++;
}
return !(length > (i32) m_lines[line].size()-col && m_firstTokenIdOfLine[line + 1] != -1);
if (line < (i32) m_lines.size())
return length <= (i32) m_lines[line].size()-col || m_firstTokenIdOfLine[line + 1] == -1;
return false;
}
// Find the string of the variable type. This works on function variables, views,
@@ -2578,7 +2579,5 @@ namespace hex::plugin::builtin {
log::debug("TextHighlighter::highlightSourceCode: Out of range error: {}", e.what());
return;
}
return;
}
}

View File

@@ -455,9 +455,6 @@ namespace hex::plugin::builtin {
auto defaultEditorSize = ImGui::GetContentRegionAvail();
defaultEditorSize.y *= 0.66F;
//if (getLastFocusedView() == this) {
// m_textEditor.get(provider).setFocus(false);
//}
fonts::CodeEditor().push();
ImGui::SetNextWindowSizeConstraints(

View File

@@ -93,10 +93,10 @@ namespace hex::ui {
bool operator==(const Range &o) const;
bool operator!=(const Range &o) const;
bool operator<(const Range &o) const {
return m_end < o.m_end;
return o.m_end == m_end ? o.m_start < m_start : m_end < o.m_end;
}
bool operator>(const Range &o) const {
return m_end > o.m_end;
return o.m_end == m_end ? o.m_start > m_start : m_end > o.m_end;
}
bool operator<=(const Range &o) const {
return !(*this > o);
@@ -125,12 +125,12 @@ namespace hex::ui {
Interval &operator=(const Interval &interval);
Interval &operator=(Interval &&interval) noexcept;
bool operator<(const Interval &other) const { return other.m_end > m_end; }
bool operator>(const Interval &other) const { return m_end > other.m_end; }
bool operator<(const Interval &other) const { return other.m_end == m_end ? other.m_start < m_start : m_end < other.m_end; }
bool operator>(const Interval &other) const { return other.m_end == m_end ? other.m_start > m_start : m_end > other.m_end; }
bool operator==(const Interval &other) const { return m_start == other.m_start && m_end == other.m_end; }
bool operator!=(const Interval &other) const { return m_start != other.m_start || m_end != other.m_end; }
bool operator<=(const Interval &other) const { return other.m_end >= m_end; }
bool operator>=(const Interval &other) const { return m_end >= other.m_end; }
bool operator<=(const Interval &other) const { return other.m_end == m_end ? other.m_start <= m_start : m_end < other.m_end; }
bool operator>=(const Interval &other) const { return other.m_end == m_end ? other.m_start >= m_start : m_end > other.m_end; }
[[nodiscard]] bool contains_or_equals(const Interval &other) const { return other.m_start >= m_start && other.m_end <= m_end; }
[[nodiscard]] bool contains(const Interval &other) const { return (other.m_start >= m_start && other.m_end < m_end) || (other.m_start > m_start && other.m_end <= m_end); }
[[nodiscard]] bool contains(i32 value, bool inclusive = true) const;
@@ -738,7 +738,7 @@ namespace hex::ui {
i32 getTokenId(SafeTokenIterator tokenIterator);
i32 getTokenId();
void loadFirstTokenIdOfLine();
i32 nextLine(i32 line);
i32 nextLineIndex(i32 lineIndex);
void setAllCodeFolds();
void setCodeFoldState(CodeFoldState states);
CodeFoldState getCodeFoldState() const;
@@ -844,7 +844,6 @@ namespace hex::ui {
Tokens m_tokens;
SafeTokenIterator m_curr;
SafeTokenIterator m_startToken, m_originalPosition, m_partOriginalPosition;
bool m_interrupt = false;
Indices m_firstTokenIdOfLine;
CodeFoldBlocks m_foldPoints;
GlobalBlocks m_globalBlocks;
@@ -887,9 +886,8 @@ namespace hex::ui {
void clearActionables() { m_lines.clearActionables();}
void saveCodeFoldStates();
void applyCodeFoldStates();
void removeHiddenLinesFromPattern() { m_lines.removeHiddenLinesFromPattern(); };
void addHiddenLinesToPattern() { m_lines.addHiddenLinesToPattern(); };
void removeHiddenLinesFromPattern() { m_lines.removeHiddenLinesFromPattern(); }
void addHiddenLinesToPattern() { m_lines.addHiddenLinesToPattern(); }
// Highlighting
private:
void preRender();
@@ -1009,8 +1007,8 @@ namespace hex::ui {
void codeFoldCollapse(i32 level=1, bool recursive=false, bool all=false);
i32 getCodeFoldLevel(i32 line) const;
void resetFoldedSelections();
void computeLPSArray(const std::string &pattern, Indices & lps);
Indices KMPSearch(const std::string& text, const std::string& pattern);
//void computeLPSArray(const std::string &pattern, Indices & lps);
//Indices KMPSearch(const std::string& text, const std::string& pattern);
bool isEmpty();
// utf8

View File

@@ -27,7 +27,7 @@ namespace hex::ui {
Interval result = NotValid;
auto tokenStart = SafeTokenIterator(m_tokens.begin(), m_tokens.end());
bool foundKey = false;
bool foundKeyword = false;
bool foundComment = false;
m_curr = tokenStart + interval.m_start;
while (interval.m_end >= getTokenId()) {
@@ -37,8 +37,8 @@ namespace hex::ui {
return NotValid;
while (true) {
if (const auto *docComment = const_cast<Token::DocComment *>(getValue<Token::DocComment>(0)); docComment != nullptr) {
if (foundKey)
if (const auto *docComment = const_cast<Token::DocComment *>(getValue<Token::DocComment>(0)); docComment != nullptr && getTokenId() == m_firstTokenIdOfLine.at(m_curr->location.line - 1)) {
if (foundKeyword)
break;
if (docComment->singleLine) {
foundComment = true;
@@ -48,8 +48,8 @@ namespace hex::ui {
break;
return {result.m_start, result.m_start};
}
} else if (const auto *comment = const_cast<Token::Comment *>(getValue<Token::Comment>(0)); comment != nullptr) {
if (foundKey)
} else if (const auto *comment = const_cast<Token::Comment *>(getValue<Token::Comment>(0)); comment != nullptr && getTokenId() == m_firstTokenIdOfLine.at(m_curr->location.line - 1)) {
if (foundKeyword)
break;
if (comment->singleLine) {
foundComment = true;
@@ -59,24 +59,30 @@ namespace hex::ui {
break;
return {result.m_start, result.m_start};
}
} else if (const auto *keyword = const_cast<Token::Keyword *>(getValue<Token::Keyword>(0));keyword != nullptr && *keyword == Token::Keyword::Import) {
} else if (const auto *keyword = const_cast<Token::Keyword *>(getValue<Token::Keyword>(0));keyword != nullptr && *keyword == Token::Keyword::Import && getTokenId() == m_firstTokenIdOfLine.at(m_curr->location.line - 1)) {
if (foundComment)
break;
foundKey = true;
while (!peek(tkn::Separator::Semicolon) && !peek(tkn::Separator::EndOfProgram))
next();
next();
} else if (const auto *directive = const_cast<Token::Directive *>(getValue<Token::Directive>(0));directive != nullptr && *directive == Token::Directive::Include) {
foundKeyword = true;
i32 lineIndex = m_curr->location.line - 1;
auto nextIndex = nextLineIndex(lineIndex);
if (nextIndex == lineIndex || nextIndex == -1)
break;
auto tokenId = m_firstTokenIdOfLine.at(nextIndex);
next(tokenId - getTokenId());
} else if (const auto *directive = const_cast<Token::Directive *>(getValue<Token::Directive>(0));directive != nullptr && *directive == Token::Directive::Include && getTokenId() == m_firstTokenIdOfLine.at(m_curr->location.line - 1)) {
if (foundComment)
break;
foundKey = true;
u32 line = m_curr->location.line;
while (m_curr->location.line == line && !peek(tkn::Separator::EndOfProgram))
next();
foundKeyword = true;
i32 lineIndex = m_curr->location.line - 1;
auto nextIndex = nextLineIndex(lineIndex);
if (nextIndex == lineIndex || nextIndex == -1)
break;
auto tokenId = m_firstTokenIdOfLine.at(nextIndex);
next(tokenId - getTokenId());
} else
break;
}
if (foundKey || foundComment) {
if (foundKeyword || foundComment) {
auto currentId = getTokenId();
if (peek(tkn::Separator::EndOfProgram) || (currentId > 0 && currentId < (i32) m_tokens.size())) {
next(-1);
@@ -235,7 +241,7 @@ namespace hex::ui {
void TextEditor::Lines::advanceToNextLine(i32 &lineIndex, i32 &currentTokenId, Location &location) {
i32 tempLineIndex;
if (tempLineIndex = nextLine(lineIndex); lineIndex == tempLineIndex) {
if (tempLineIndex = nextLineIndex(lineIndex); lineIndex == tempLineIndex) {
lineIndex++;
currentTokenId = -1;
location = Location::Empty();
@@ -469,18 +475,18 @@ namespace hex::ui {
} else
codeFoldIndex++;
}
if (closedFoldIncrements.empty())
return;
if (!m_hiddenLines.empty())
m_hiddenLines.clear();
std::string result = "//+-#:";
for (u32 i = 0; i < closedFoldIncrements.size(); ++i) {
result += std::to_string(closedFoldIncrements[i]);
if (i < closedFoldIncrements.size() - 1)
result += ",";
if (!closedFoldIncrements.empty()) {
std::string result = "//+-#:";
for (u32 i = 0; i < closedFoldIncrements.size(); ++i) {
result += std::to_string(closedFoldIncrements[i]);
if (i < closedFoldIncrements.size() - 1)
result += ",";
}
auto lineIndex = 0;
m_hiddenLines.emplace_back(lineIndex, result);
}
auto lineIndex = 0;
m_hiddenLines.emplace_back(lineIndex, result);
}
void TextEditor::applyCodeFoldStates() {
@@ -752,10 +758,6 @@ namespace hex::ui {
}
void TextEditor::Lines::next(i32 count) {
if (m_interrupt) {
m_interrupt = false;
throw std::out_of_range("Highlights were deliberately interrupted");
}
if (count == 0)
return;
i32 id = getTokenId();

View File

@@ -348,7 +348,6 @@ namespace hex::ui {
if (u.m_addedRange.m_start == Invalid || u.m_addedRange.m_end == Invalid)
return;
}
m_lines.m_textChanged = true;
if (!m_lines.m_readOnly && undo) {
u.m_after = m_lines.m_state;
UndoRecords v;

View File

@@ -746,12 +746,12 @@ namespace hex::ui {
continue;
for (i32 i = 0; i < count; i++) {
Interval sgm = {foldedLine.m_foldedSegments[2 * i].m_column, foldedLine.m_foldedSegments[2 * i + 1].m_column};
m_rowToFoldSegments[row].push_back({foldedLine.m_keys[i].m_start, indexScreenPosition(lineIndex, sgm)});
m_rowToFoldSegments[row].emplace_back(foldedLine.m_keys[i].m_start, indexScreenPosition(lineIndex, sgm));
ImVec2 screenPosEnd = indexCoordsToScreen(lineCoordinates(lineIndex, foldedLine.m_ellipsisIndices[i]));
m_rowCodeFoldTooltips[row].emplace_back(this, foldedLine.m_keys[i],ImRect(screenPosEnd, screenPosEnd + ImVec2(Ellipsis.lineTextSize(), m_charAdvance.y)));
}
Interval sgm = {foldedLine.m_foldedSegments[2 * count].m_column, foldedLine.m_foldedSegments[2 * count + 1].m_column};
m_rowToFoldSegments[row].push_back({foldedLine.m_keys[count - 1].m_end, indexScreenPosition(lineIndex, sgm)});
m_rowToFoldSegments[row].emplace_back(foldedLine.m_keys[count - 1].m_end, indexScreenPosition(lineIndex, sgm));
}
}
@@ -1221,7 +1221,7 @@ namespace hex::ui {
ImGui::BeginChild(m_lines.m_title.c_str());
}
if (m_showCursor)
drawCursor(0,textEditorSize, true, drawList);
drawCursor(0,textEditorSize, ImGui::IsWindowFocused(), drawList);
ImGui::Dummy(m_lines.m_charAdvance);
}

View File

@@ -172,12 +172,7 @@ namespace hex::ui {
return *this;
}
LineIterator &LineIterator::operator=(const LineIterator &other) {
m_charsIter = other.m_charsIter;
m_colorsIter = other.m_colorsIter;
m_flagsIter = other.m_flagsIter;
return *this;
}
LineIterator &LineIterator::operator=(const LineIterator &other) = default;
bool LineIterator::operator!=(const LineIterator &other) const {
return m_charsIter != other.m_charsIter || m_colorsIter != other.m_colorsIter ||
@@ -537,8 +532,8 @@ namespace hex::ui {
bool TextEditor::ActionableBox::trigger() {
auto mousePos = ImGui::GetMousePos();
return !(mousePos.x <= m_box.Min.x || mousePos.x >= m_box.Max.x ||
mousePos.y < m_box.Min.y || mousePos.y > m_box.Max.y);
return mousePos.x > m_box.Min.x && mousePos.x < m_box.Max.x &&
mousePos.y >= m_box.Min.y && mousePos.y <= m_box.Max.y;
}
void TextEditor::ActionableBox::shiftBoxVertically(float lineCount, float lineHeight) {
@@ -1052,7 +1047,7 @@ namespace hex::ui {
while (iter != end) {
iter++;
if (((pos = iter->position()) > byteIndex))
if (pos = iter->position(); pos > byteIndex)
break;
}
}
@@ -1279,6 +1274,7 @@ namespace hex::ui {
}
void TextEditor::Lines::setAllCodeFolds() {
initializeCodeFolds();
CodeFoldBlocks intervals = foldPointsFromSource();
m_codeFoldKeys.clear();
m_codeFolds.clear();
@@ -1333,6 +1329,7 @@ namespace hex::ui {
m_useSavedFoldStatesRequested = true;
}
deleteSelection();
setTextChanged(false);
}
}
@@ -1348,6 +1345,7 @@ namespace hex::ui {
if (m_unfoldedLines[lineIndex].m_chars.starts_with("//+-"))
m_unfoldedLines.erase(m_unfoldedLines.begin() + lineIndex);
insertLine(lineIndex, hiddenLine.m_line);
setTextChanged(false);
}
}
@@ -1506,7 +1504,7 @@ namespace hex::ui {
if (!isLocationValid(location))
return -1;
i32 line1 = location.line - 1;
i32 line2 = nextLine(line1);
i32 line2 = nextLineIndex(line1);
auto tokenCount = m_tokens.size();
i32 lineCount = m_firstTokenIdOfLine.size();
if (line1 < 0 || line1 >= lineCount || tokenCount == 0)
@@ -1527,14 +1525,14 @@ namespace hex::ui {
return -1;
}
i32 TextEditor::Lines::nextLine(i32 line) {
if (line < 0 || line >= size())
i32 TextEditor::Lines::nextLineIndex(i32 lineIndex) {
if (lineIndex < 0 || lineIndex >= size())
return -1;
auto currentTokenId = m_firstTokenIdOfLine[line];
auto currentTokenId = m_firstTokenIdOfLine[lineIndex];
i32 i = 1;
while (line + i < size() &&
(m_firstTokenIdOfLine[line + i] == currentTokenId || m_firstTokenIdOfLine[line + i] == (i32) 0xFFFFFFFF))
while (lineIndex + i < size() &&
(m_firstTokenIdOfLine[lineIndex + i] == currentTokenId || m_firstTokenIdOfLine[lineIndex + i] == (i32) 0xFFFFFFFF))
i++;
return i + line;
return i + lineIndex;
}
}