mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-06-02 03:26:29 +03:00
Find/Replace improvements.
Windows build fix. ecode: Minor fix in lspclient.json. Minor fix in features health.
This commit is contained in:
@@ -199,7 +199,7 @@
|
||||
{
|
||||
"language": "haskell",
|
||||
"name": "haskell-language-server",
|
||||
"url": "https://github.com/haskell/haskell-language-server --lsp",
|
||||
"url": "https://github.com/haskell/haskell-language-server",
|
||||
"command": "haskell-language-server-wrapper",
|
||||
"file_patterns": ["%.hs$"],
|
||||
"rootIndicationFileNames": ["%.cabal$", "stack.yaml", "cabal.project", "package.yaml", "hie.yaml"]
|
||||
|
||||
@@ -347,18 +347,16 @@ class EE_API TextDocument {
|
||||
|
||||
bool removeCommand( const std::string& command );
|
||||
|
||||
TextRange find( const String& text, TextPosition from = { 0, 0 },
|
||||
const bool& caseSensitive = true, const bool& wholeWord = false,
|
||||
const FindReplaceType& type = FindReplaceType::Normal,
|
||||
TextRange find( const String& text, TextPosition from = { 0, 0 }, bool caseSensitive = true,
|
||||
bool wholeWord = false, const FindReplaceType& type = FindReplaceType::Normal,
|
||||
TextRange restrictRange = TextRange() );
|
||||
|
||||
TextRange findLast( const String& text, TextPosition from = { 0, 0 },
|
||||
const bool& caseSensitive = true, const bool& wholeWord = false,
|
||||
TextRange findLast( const String& text, TextPosition from = { 0, 0 }, bool caseSensitive = true,
|
||||
bool wholeWord = false,
|
||||
const FindReplaceType& type = FindReplaceType::Normal,
|
||||
TextRange restrictRange = TextRange() );
|
||||
|
||||
TextRanges findAll( const String& text, const bool& caseSensitive = true,
|
||||
const bool& wholeWord = false,
|
||||
TextRanges findAll( const String& text, bool caseSensitive = true, bool wholeWord = false,
|
||||
const FindReplaceType& type = FindReplaceType::Normal,
|
||||
TextRange restrictRange = TextRange() );
|
||||
|
||||
@@ -642,13 +640,13 @@ class EE_API TextDocument {
|
||||
|
||||
LoadStatus loadFromStream( IOStream& file, std::string path, bool callReset );
|
||||
|
||||
TextRange findText( String text, TextPosition from = { 0, 0 }, const bool& caseSensitive = true,
|
||||
const bool& wholeWord = false,
|
||||
TextRange findText( String text, TextPosition from = { 0, 0 }, bool caseSensitive = true,
|
||||
bool wholeWord = false,
|
||||
const FindReplaceType& type = FindReplaceType::Normal,
|
||||
TextRange restrictRange = TextRange() );
|
||||
|
||||
TextRange findTextLast( String text, TextPosition from = { 0, 0 },
|
||||
const bool& caseSensitive = true, const bool& wholeWord = false,
|
||||
TextRange findTextLast( String text, TextPosition from = { 0, 0 }, bool caseSensitive = true,
|
||||
bool wholeWord = false,
|
||||
const FindReplaceType& type = FindReplaceType::Normal,
|
||||
TextRange restrictRange = TextRange() );
|
||||
};
|
||||
|
||||
@@ -113,6 +113,8 @@ class EE_API TextRange {
|
||||
|
||||
class EE_API TextRanges : public std::vector<TextRange> {
|
||||
public:
|
||||
bool isSorted() const { return mIsSorted; }
|
||||
|
||||
bool isValid() const {
|
||||
for ( const auto& selection : *this ) {
|
||||
if ( !selection.isValid() )
|
||||
@@ -143,7 +145,12 @@ class EE_API TextRanges : public std::vector<TextRange> {
|
||||
return false;
|
||||
}
|
||||
|
||||
void sort() { std::sort( begin(), end() ); }
|
||||
void sort() {
|
||||
std::sort( begin(), end() );
|
||||
setSorted();
|
||||
}
|
||||
|
||||
void setSorted() { mIsSorted = true; }
|
||||
|
||||
bool merge() {
|
||||
if ( size() <= 1 )
|
||||
@@ -176,6 +183,9 @@ class EE_API TextRanges : public std::vector<TextRange> {
|
||||
ranges.emplace_back( TextRange::fromString( rangeStr ) );
|
||||
return ranges;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool mIsSorted{ false };
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Doc
|
||||
|
||||
@@ -69,6 +69,8 @@ class EE_API UIDocFindReplace : public UILinearLayout, public WidgetCommandExecu
|
||||
int replaceAll( TextSearchParams& search, const String& replace );
|
||||
|
||||
virtual Uint32 onKeyDown( const KeyEvent& event );
|
||||
|
||||
void refreshHighlight( UICodeEditor* editor );
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Tools
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <algorithm>
|
||||
#include <eepp/system/threadpool.hpp>
|
||||
|
||||
namespace EE { namespace System {
|
||||
|
||||
@@ -2015,8 +2015,8 @@ static std::pair<size_t, size_t> findLastType( const String& str, const String&
|
||||
}
|
||||
}
|
||||
|
||||
TextRange TextDocument::findText( String text, TextPosition from, const bool& caseSensitive,
|
||||
const bool& wholeWord, const FindReplaceType& type,
|
||||
TextRange TextDocument::findText( String text, TextPosition from, bool caseSensitive,
|
||||
bool wholeWord, const FindReplaceType& type,
|
||||
TextRange restrictRange ) {
|
||||
if ( text.empty() )
|
||||
return TextRange();
|
||||
@@ -2030,7 +2030,11 @@ TextRange TextDocument::findText( String text, TextPosition from, const bool& ca
|
||||
return TextRange();
|
||||
}
|
||||
|
||||
if ( !caseSensitive && type != FindReplaceType::LuaPattern )
|
||||
if ( type == FindReplaceType::LuaPattern && caseSensitive == false )
|
||||
caseSensitive =
|
||||
true; // Ignore case insensitive request since this is managed at pattern level
|
||||
|
||||
if ( !caseSensitive )
|
||||
text.toLower();
|
||||
|
||||
for ( Int64 i = from.line(); i <= to.line(); i++ ) {
|
||||
@@ -2064,8 +2068,8 @@ TextRange TextDocument::findText( String text, TextPosition from, const bool& ca
|
||||
return TextRange();
|
||||
}
|
||||
|
||||
TextRange TextDocument::findTextLast( String text, TextPosition from, const bool& caseSensitive,
|
||||
const bool& wholeWord, const FindReplaceType& type,
|
||||
TextRange TextDocument::findTextLast( String text, TextPosition from, bool caseSensitive,
|
||||
bool wholeWord, const FindReplaceType& type,
|
||||
TextRange restrictRange ) {
|
||||
if ( text.empty() )
|
||||
return TextRange();
|
||||
@@ -2079,7 +2083,11 @@ TextRange TextDocument::findTextLast( String text, TextPosition from, const bool
|
||||
return TextRange();
|
||||
}
|
||||
|
||||
if ( !caseSensitive && type != FindReplaceType::LuaPattern )
|
||||
if ( type == FindReplaceType::LuaPattern && caseSensitive == false )
|
||||
caseSensitive =
|
||||
true; // Ignore case insensitive request since this is managed at pattern level
|
||||
|
||||
if ( !caseSensitive )
|
||||
text.toLower();
|
||||
|
||||
for ( Int64 i = from.line(); i >= to.line(); i-- ) {
|
||||
@@ -2115,8 +2123,8 @@ TextRange TextDocument::findTextLast( String text, TextPosition from, const bool
|
||||
return TextRange();
|
||||
}
|
||||
|
||||
TextRange TextDocument::find( const String& text, TextPosition from, const bool& caseSensitive,
|
||||
const bool& wholeWord, const FindReplaceType& type,
|
||||
TextRange TextDocument::find( const String& text, TextPosition from, bool caseSensitive,
|
||||
bool wholeWord, const FindReplaceType& type,
|
||||
TextRange restrictRange ) {
|
||||
std::vector<String> textLines = text.split( '\n', true, true );
|
||||
|
||||
@@ -2193,8 +2201,8 @@ TextRange TextDocument::find( const String& text, TextPosition from, const bool&
|
||||
return TextRange();
|
||||
}
|
||||
|
||||
TextRange TextDocument::findLast( const String& text, TextPosition from, const bool& caseSensitive,
|
||||
const bool& wholeWord, const FindReplaceType& type,
|
||||
TextRange TextDocument::findLast( const String& text, TextPosition from, bool caseSensitive,
|
||||
bool wholeWord, const FindReplaceType& type,
|
||||
TextRange restrictRange ) {
|
||||
std::vector<String> textLines = text.split( '\n', true, true );
|
||||
|
||||
@@ -2266,9 +2274,8 @@ TextRange TextDocument::findLast( const String& text, TextPosition from, const b
|
||||
return TextRange();
|
||||
}
|
||||
|
||||
TextRanges TextDocument::findAll( const String& text, const bool& caseSensitive,
|
||||
const bool& wholeWord, const FindReplaceType& type,
|
||||
TextRange restrictRange ) {
|
||||
TextRanges TextDocument::findAll( const String& text, bool caseSensitive, bool wholeWord,
|
||||
const FindReplaceType& type, TextRange restrictRange ) {
|
||||
TextRanges all;
|
||||
TextRange found;
|
||||
TextPosition from = startOfDoc();
|
||||
@@ -2283,6 +2290,8 @@ TextRanges TextDocument::findAll( const String& text, const bool& caseSensitive,
|
||||
all.push_back( found );
|
||||
}
|
||||
} while ( found.isValid() );
|
||||
if ( !all.empty() )
|
||||
all.setSorted();
|
||||
return all;
|
||||
}
|
||||
|
||||
|
||||
@@ -200,22 +200,9 @@ UIDocFindReplace::UIDocFindReplace( UIWidget* parent, const std::shared_ptr<Doc:
|
||||
mFindInput->setEscapePastedText( true );
|
||||
UICodeEditor* editor =
|
||||
getParent()->isType( UI_TYPE_CODEEDITOR ) ? getParent()->asType<UICodeEditor>() : nullptr;
|
||||
mFindInput->addEventListener( Event::OnTextChanged, [&, editor]( const Event* ) {
|
||||
mSearchState.text = mFindInput->getText();
|
||||
if ( editor )
|
||||
editor->setHighlightWord( mSearchState );
|
||||
if ( !mSearchState.text.empty() ) {
|
||||
mDoc->setSelection( { 0, 0 } );
|
||||
if ( !findNextText( mSearchState ) ) {
|
||||
mFindInput->addClass( "error" );
|
||||
} else {
|
||||
mFindInput->removeClass( "error" );
|
||||
}
|
||||
} else {
|
||||
mFindInput->removeClass( "error" );
|
||||
mDoc->setSelection( mDoc->getSelection().start() );
|
||||
}
|
||||
} );
|
||||
|
||||
mFindInput->addEventListener( Event::OnTextChanged,
|
||||
[&, editor]( const Event* ) { refreshHighlight( editor ); } );
|
||||
mFindInput->addEventListener( Event::OnTextPasted, [&]( const Event* ) {
|
||||
if ( mFindInput->getUISceneNode()->getWindow()->getClipboard()->getText().find( '\n' ) !=
|
||||
String::InvalidPos ) {
|
||||
@@ -235,14 +222,22 @@ UIDocFindReplace::UIDocFindReplace( UIWidget* parent, const std::shared_ptr<Doc:
|
||||
setCommand( "find-prev", [this] { findPrevText( mSearchState ); } );
|
||||
setCommand( "replace-selection",
|
||||
[this] { mDoc->replaceSelection( mReplaceInput->getText() ); } );
|
||||
setCommand( "change-case",
|
||||
[&] { mCaseSensitive->setSelected( !mCaseSensitive->isSelected() ); } );
|
||||
setCommand( "change-whole-word",
|
||||
[&] { mWholeWord->setSelected( !mWholeWord->isSelected() ); } );
|
||||
setCommand( "change-escape-sequence",
|
||||
[&] { mEscapeSequences->setSelected( !mEscapeSequences->isSelected() ); } );
|
||||
setCommand( "toggle-lua-pattern",
|
||||
[&] { mLuaPattern->setSelected( !mLuaPattern->isSelected() ); } );
|
||||
setCommand( "change-case", [this, editor] {
|
||||
mCaseSensitive->setSelected( !mCaseSensitive->isSelected() );
|
||||
refreshHighlight( editor );
|
||||
} );
|
||||
setCommand( "change-whole-word", [this, editor] {
|
||||
mWholeWord->setSelected( !mWholeWord->isSelected() );
|
||||
refreshHighlight( editor );
|
||||
} );
|
||||
setCommand( "change-escape-sequence", [this, editor] {
|
||||
mEscapeSequences->setSelected( !mEscapeSequences->isSelected() );
|
||||
refreshHighlight( editor );
|
||||
} );
|
||||
setCommand( "toggle-lua-pattern", [this, editor] {
|
||||
mLuaPattern->setSelected( !mLuaPattern->isSelected() );
|
||||
refreshHighlight( editor );
|
||||
} );
|
||||
|
||||
mCaseSensitive->setTooltipText( mCaseSensitive->getTooltipText() + " (" +
|
||||
getKeyBindings().getCommandKeybindString( "change-case" ) +
|
||||
@@ -316,6 +311,11 @@ UIDocFindReplace::UIDocFindReplace( UIWidget* parent, const std::shared_ptr<Doc:
|
||||
mPatternBind = UIDataBind<TextDocument::FindReplaceType>::New( &mSearchState.type, mLuaPattern,
|
||||
luaPatternConverter );
|
||||
|
||||
auto valueChangeCb = [this, editor]( const auto& ) { refreshHighlight( editor ); };
|
||||
mPatternBind->onValueChangeCb = valueChangeCb;
|
||||
for ( const auto& db : mDataBinds )
|
||||
db->onValueChangeCb = valueChangeCb;
|
||||
|
||||
setVisible( false );
|
||||
|
||||
runOnMainThread( [&] { mReady = true; } );
|
||||
@@ -518,4 +518,21 @@ bool UIDocFindReplace::findAndReplace( TextSearchParams& search, const String& r
|
||||
}
|
||||
}
|
||||
|
||||
void UIDocFindReplace::refreshHighlight( UICodeEditor* editor ) {
|
||||
mSearchState.text = mFindInput->getText();
|
||||
if ( editor )
|
||||
editor->setHighlightWord( mSearchState );
|
||||
if ( !mSearchState.text.empty() ) {
|
||||
mDoc->setSelection( { 0, 0 } );
|
||||
if ( !findNextText( mSearchState ) ) {
|
||||
mFindInput->addClass( "error" );
|
||||
} else {
|
||||
mFindInput->removeClass( "error" );
|
||||
}
|
||||
} else {
|
||||
mFindInput->removeClass( "error" );
|
||||
mDoc->setSelection( mDoc->getSelection().start() );
|
||||
}
|
||||
};
|
||||
|
||||
}}} // namespace EE::UI::Tools
|
||||
|
||||
@@ -3338,6 +3338,9 @@ void UICodeEditor::drawMinimap( const Vector2f& start,
|
||||
!range.inSameLine() )
|
||||
continue;
|
||||
|
||||
if ( ranges.isSorted() && range.end().line() > endidx )
|
||||
break;
|
||||
|
||||
Rectf selRect;
|
||||
selRect.Top = rect.Top + ( range.start().line() - minimapStartLine ) * lineSpacing;
|
||||
selRect.Bottom = selRect.Top + charHeight;
|
||||
|
||||
@@ -6,6 +6,25 @@ namespace ecode {
|
||||
DocSearchController::DocSearchController( UICodeEditorSplitter* editorSplitter, App* app ) :
|
||||
mEditorSplitter( editorSplitter ), mApp( app ) {}
|
||||
|
||||
void DocSearchController::refreshHighlight() {
|
||||
if ( mSearchState.editor && mEditorSplitter->editorExists( mSearchState.editor ) ) {
|
||||
mSearchState.text = mFindInput->getText();
|
||||
mSearchState.editor->setHighlightWord( mSearchState.toTextSearchParams() );
|
||||
if ( !mSearchState.text.empty() ) {
|
||||
mSearchState.editor->getDocument().setSelection( { 0, 0 } );
|
||||
if ( !findNextText( mSearchState ) ) {
|
||||
mFindInput->addClass( "error" );
|
||||
} else {
|
||||
mFindInput->removeClass( "error" );
|
||||
}
|
||||
} else {
|
||||
mFindInput->removeClass( "error" );
|
||||
mSearchState.editor->getDocument().setSelection(
|
||||
mSearchState.editor->getDocument().getSelection().start() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DocSearchController::initSearchBar(
|
||||
UISearchBar* searchBar, const SearchBarConfig& searchBarConfig,
|
||||
std::unordered_map<std::string, std::string> keybindings ) {
|
||||
@@ -62,39 +81,27 @@ void DocSearchController::initSearchBar(
|
||||
|
||||
mCaseSensitiveChk->addEventListener( Event::OnValueChange, [&]( const Event* ) {
|
||||
mSearchState.caseSensitive = mCaseSensitiveChk->isChecked();
|
||||
refreshHighlight();
|
||||
} );
|
||||
|
||||
mEscapeSequenceChk->addEventListener( Event::OnValueChange, [&]( const Event* ) {
|
||||
mSearchState.escapeSequences = mEscapeSequenceChk->isChecked();
|
||||
refreshHighlight();
|
||||
} );
|
||||
|
||||
mWholeWordChk->addEventListener( Event::OnValueChange, [&]( const Event* ) {
|
||||
mSearchState.wholeWord = mWholeWordChk->isChecked();
|
||||
refreshHighlight();
|
||||
} );
|
||||
|
||||
mLuaPatternChk->addEventListener( Event::OnValueChange, [&]( const Event* ) {
|
||||
mSearchState.type = mLuaPatternChk->isChecked() ? TextDocument::FindReplaceType::LuaPattern
|
||||
: TextDocument::FindReplaceType::Normal;
|
||||
refreshHighlight();
|
||||
} );
|
||||
|
||||
mFindInput->addEventListener( Event::OnTextChanged, [&]( const Event* ) {
|
||||
if ( mSearchState.editor && mEditorSplitter->editorExists( mSearchState.editor ) ) {
|
||||
mSearchState.text = mFindInput->getText();
|
||||
mSearchState.editor->setHighlightWord( mSearchState.toTextSearchParams() );
|
||||
if ( !mSearchState.text.empty() ) {
|
||||
mSearchState.editor->getDocument().setSelection( { 0, 0 } );
|
||||
if ( !findNextText( mSearchState ) ) {
|
||||
mFindInput->addClass( "error" );
|
||||
} else {
|
||||
mFindInput->removeClass( "error" );
|
||||
}
|
||||
} else {
|
||||
mFindInput->removeClass( "error" );
|
||||
mSearchState.editor->getDocument().setSelection(
|
||||
mSearchState.editor->getDocument().getSelection().start() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
mFindInput->addEventListener( Event::OnTextChanged,
|
||||
[&]( const Event* ) { refreshHighlight(); } );
|
||||
mFindInput->addEventListener( Event::OnTextPasted, [&]( const Event* ) {
|
||||
if ( mFindInput->getUISceneNode()->getWindow()->getClipboard()->getText().find( '\n' ) !=
|
||||
String::InvalidPos ) {
|
||||
|
||||
@@ -72,6 +72,7 @@ class DocSearchController {
|
||||
|
||||
void selectAll( SearchState& search );
|
||||
|
||||
void refreshHighlight();
|
||||
protected:
|
||||
UICodeEditorSplitter* mEditorSplitter{ nullptr };
|
||||
UITextInput* mFindInput{ nullptr };
|
||||
|
||||
@@ -86,6 +86,7 @@ std::vector<FeaturesHealth::LangHealth> FeaturesHealth::getHealth( PluginManager
|
||||
lsp->getClientManager().getLSPForLang( def.getLSPName(), def.getFiles() );
|
||||
if ( !found.command.empty() ) {
|
||||
lang.lsp.name = found.name;
|
||||
lang.lsp.url = found.url;
|
||||
lang.lsp.path = Sys::which( String::split( found.command, ' ' )[0] );
|
||||
lang.lsp.found = !lang.lsp.path.empty();
|
||||
}
|
||||
@@ -128,8 +129,12 @@ std::string FeaturesHealth::generateHealthStatus( PluginManager* pluginManager,
|
||||
}
|
||||
|
||||
for ( const auto& ht : status ) {
|
||||
table.add_row( { ht.lang, "✓", ht.lsp.name.empty() ? "None" : ht.lsp.name,
|
||||
ht.linter.name.empty() ? "None" : ht.linter.name,
|
||||
std::string lspName = ht.lsp.name.empty() ? "None" : ht.lsp.name;
|
||||
if ( OutputFormat::Markdown == format && !ht.lsp.name.empty() && !ht.lsp.url.empty() ) {
|
||||
lspName = "[" + ht.lsp.name + "](" + ht.lsp.url + ")";
|
||||
}
|
||||
|
||||
table.add_row( { ht.lang, "✓", lspName, ht.linter.name.empty() ? "None" : ht.linter.name,
|
||||
ht.formatter.name.empty() ? "None" : ht.formatter.name } );
|
||||
|
||||
auto& row = table[table.size() - 1];
|
||||
|
||||
@@ -25,6 +25,7 @@ class FeaturesHealth {
|
||||
struct FeatureStatus {
|
||||
std::string name;
|
||||
std::string path;
|
||||
std::string url;
|
||||
bool found{ false };
|
||||
};
|
||||
struct LangHealth {
|
||||
|
||||
@@ -802,9 +802,9 @@ void LSPClientPlugin::loadLSPConfig( std::vector<LSPDefinition>& lsps, const std
|
||||
lsp.language = obj["language"];
|
||||
lsp.command = parseCommand( obj["command"] );
|
||||
lsp.name = obj["name"];
|
||||
lsp.url = obj.value( "url", "" );
|
||||
}
|
||||
|
||||
lsp.url = obj.value( "url", "" );
|
||||
lsp.commandParameters = obj.value( "command_parameters", lsp.commandParameters );
|
||||
if ( obj.contains( "initializationOptions" ) )
|
||||
lsp.initializationOptions = obj["initializationOptions"];
|
||||
|
||||
Reference in New Issue
Block a user