mirror of
https://github.com/SpartanJ/eepp.git
synced 2026-08-18 06:55:48 +03:00
File locator now displays the relative path to the open folder instead of the full path of a file.
Improve universal locator options when no folder is open (fixes SpartanJ/ecode#303).
This commit is contained in:
@@ -230,7 +230,7 @@ void App::openFileDialog() {
|
||||
}
|
||||
|
||||
std::string App::getLastUsedFolder() {
|
||||
if ( !mCurrentProject.empty() )
|
||||
if ( !mCurrentProject.empty() && mCurrentProject != getPlaygroundPath() )
|
||||
return mCurrentProject;
|
||||
if ( !mRecentFolders.empty() )
|
||||
return mRecentFolders.front();
|
||||
|
||||
@@ -47,7 +47,8 @@ void ProjectDirectoryTree::scan( const ProjectDirectoryTree::ScanCompleteEvent&
|
||||
mDirectories.push_back( mPath );
|
||||
|
||||
if ( !mAllowedMatcher && FileSystem::fileExists( mPath + PRJ_ALLOWED_PATH ) )
|
||||
mAllowedMatcher = std::make_unique<GitIgnoreMatcher>( mPath, PRJ_ALLOWED_PATH, false );
|
||||
mAllowedMatcher =
|
||||
std::make_unique<GitIgnoreMatcher>( mPath, PRJ_ALLOWED_PATH, false );
|
||||
|
||||
if ( !acceptedPatterns.empty() ) {
|
||||
std::vector<std::string> files;
|
||||
@@ -104,8 +105,8 @@ void ProjectDirectoryTree::scan( const ProjectDirectoryTree::ScanCompleteEvent&
|
||||
}
|
||||
|
||||
std::shared_ptr<FileListModel>
|
||||
ProjectDirectoryTree::fuzzyMatchTree( const std::vector<std::string>& matches,
|
||||
const size_t& max ) const {
|
||||
ProjectDirectoryTree::fuzzyMatchTree( const std::vector<std::string>& matches, const size_t& max,
|
||||
const std::string& basePath ) const {
|
||||
Lock rl( mMatchingMutex );
|
||||
std::multimap<int, int, std::greater<int>> matchesMap;
|
||||
std::vector<std::string> files;
|
||||
@@ -123,11 +124,14 @@ ProjectDirectoryTree::fuzzyMatchTree( const std::vector<std::string>& matches,
|
||||
files.emplace_back( mFiles[res.second] );
|
||||
}
|
||||
}
|
||||
return std::make_shared<FileListModel>( files, names );
|
||||
auto model = std::make_shared<FileListModel>( files, names );
|
||||
model->setBasePath( basePath );
|
||||
return model;
|
||||
}
|
||||
|
||||
std::shared_ptr<FileListModel> ProjectDirectoryTree::fuzzyMatchTree( const std::string& match,
|
||||
const size_t& max ) const {
|
||||
std::shared_ptr<FileListModel>
|
||||
ProjectDirectoryTree::fuzzyMatchTree( const std::string& match, const size_t& max,
|
||||
const std::string& basePath ) const {
|
||||
Lock rl( mMatchingMutex );
|
||||
std::multimap<int, int, std::greater<int>> matchesMap;
|
||||
std::vector<std::string> files;
|
||||
@@ -143,11 +147,14 @@ std::shared_ptr<FileListModel> ProjectDirectoryTree::fuzzyMatchTree( const std::
|
||||
files.emplace_back( mFiles[res.second] );
|
||||
}
|
||||
}
|
||||
return std::make_shared<FileListModel>( files, names );
|
||||
auto model = std::make_shared<FileListModel>( files, names );
|
||||
model->setBasePath( basePath );
|
||||
return model;
|
||||
}
|
||||
|
||||
std::shared_ptr<FileListModel> ProjectDirectoryTree::matchTree( const std::string& match,
|
||||
const size_t& max ) const {
|
||||
std::shared_ptr<FileListModel>
|
||||
ProjectDirectoryTree::matchTree( const std::string& match, const size_t& max,
|
||||
const std::string& basePath ) const {
|
||||
Lock rl( mMatchingMutex );
|
||||
std::vector<std::string> files;
|
||||
std::vector<std::string> names;
|
||||
@@ -160,25 +167,27 @@ std::shared_ptr<FileListModel> ProjectDirectoryTree::matchTree( const std::strin
|
||||
return std::make_shared<FileListModel>( files, names );
|
||||
}
|
||||
}
|
||||
return std::make_shared<FileListModel>( files, names );
|
||||
auto model = std::make_shared<FileListModel>( files, names );
|
||||
model->setBasePath( basePath );
|
||||
return model;
|
||||
}
|
||||
|
||||
void ProjectDirectoryTree::asyncFuzzyMatchTree( const std::string& match, const size_t& max,
|
||||
ProjectDirectoryTree::MatchResultCb res ) const {
|
||||
mPool->run( [this, match, max, res]() { res( fuzzyMatchTree( match, max ) ); } );
|
||||
ProjectDirectoryTree::MatchResultCb res,
|
||||
const std::string& basePath ) const {
|
||||
mPool->run(
|
||||
[this, match, max, res, basePath]() { res( fuzzyMatchTree( match, max, basePath ) ); } );
|
||||
}
|
||||
|
||||
void ProjectDirectoryTree::asyncMatchTree( const std::string& match, const size_t& max,
|
||||
ProjectDirectoryTree::MatchResultCb res ) const {
|
||||
mPool->run( [this, match, max, res]() { res( matchTree( match, max ) ); } );
|
||||
ProjectDirectoryTree::MatchResultCb res,
|
||||
const std::string& basePath ) const {
|
||||
mPool->run( [this, match, max, res, basePath]() { res( matchTree( match, max, basePath ) ); } );
|
||||
}
|
||||
|
||||
std::shared_ptr<FileListModel>
|
||||
ProjectDirectoryTree::asModel( const size_t& max,
|
||||
const std::vector<CommandInfo>& prependCommands ) const {
|
||||
if ( mNames.empty() )
|
||||
return std::make_shared<FileListModel>( std::vector<std::string>(),
|
||||
std::vector<std::string>() );
|
||||
ProjectDirectoryTree::asModel( const size_t& max, const std::vector<CommandInfo>& prependCommands,
|
||||
const std::string& basePath ) const {
|
||||
size_t rmax = eemin( mNames.size(), max );
|
||||
std::vector<std::string> files( rmax );
|
||||
std::vector<std::string> names( rmax );
|
||||
@@ -195,6 +204,7 @@ ProjectDirectoryTree::asModel( const size_t& max,
|
||||
}
|
||||
}
|
||||
auto model = std::make_shared<FileListModel>( files, names );
|
||||
model->setBasePath( basePath );
|
||||
|
||||
if ( !prependCommands.empty() ) {
|
||||
for ( size_t i = 0; i < prependCommands.size(); ++i )
|
||||
@@ -205,7 +215,8 @@ ProjectDirectoryTree::asModel( const size_t& max,
|
||||
}
|
||||
|
||||
std::shared_ptr<FileListModel>
|
||||
ProjectDirectoryTree::emptyModel( const std::vector<CommandInfo>& prependCommands ) {
|
||||
ProjectDirectoryTree::emptyModel( const std::vector<CommandInfo>& prependCommands,
|
||||
const std::string& basePath ) {
|
||||
std::vector<std::string> files;
|
||||
std::vector<std::string> names;
|
||||
if ( !prependCommands.empty() ) {
|
||||
@@ -217,6 +228,7 @@ ProjectDirectoryTree::emptyModel( const std::vector<CommandInfo>& prependCommand
|
||||
}
|
||||
}
|
||||
auto model = std::make_shared<FileListModel>( files, names );
|
||||
model->setBasePath( basePath );
|
||||
|
||||
if ( !prependCommands.empty() ) {
|
||||
for ( size_t i = 0; i < prependCommands.size(); ++i )
|
||||
|
||||
@@ -42,7 +42,14 @@ class FileListModel : public Model {
|
||||
switch ( role ) {
|
||||
case ModelRole::Icon:
|
||||
return Variant( iconFor( index ) );
|
||||
case ModelRole::Display:
|
||||
case ModelRole::Display: {
|
||||
if ( !mBasePath.empty() && index.column() == 1 &&
|
||||
mBasePath.size() < mFiles[index.row()].size() )
|
||||
return Variant( mFiles[index.row()].substr( mBasePath.size() ) );
|
||||
return Variant( index.column() == 0 ? mNames[index.row()].c_str()
|
||||
: mFiles[index.row()].c_str() );
|
||||
}
|
||||
case ModelRole::Custom:
|
||||
return Variant( index.column() == 0 ? mNames[index.row()].c_str()
|
||||
: mFiles[index.row()].c_str() );
|
||||
default:
|
||||
@@ -57,9 +64,12 @@ class FileListModel : public Model {
|
||||
mIcons[idx] = icon;
|
||||
}
|
||||
|
||||
void setBasePath( const std::string& basePath ) { mBasePath = basePath; }
|
||||
|
||||
protected:
|
||||
std::vector<std::string> mFiles;
|
||||
std::vector<std::string> mNames;
|
||||
std::string mBasePath;
|
||||
mutable std::vector<UIIcon*> mIcons;
|
||||
|
||||
UIIcon* iconFor( const ModelIndex& index ) const {
|
||||
@@ -106,17 +116,20 @@ class ProjectDirectoryTree {
|
||||
const bool& ignoreHidden = true );
|
||||
|
||||
std::shared_ptr<FileListModel> fuzzyMatchTree( const std::vector<std::string>& matches,
|
||||
const size_t& max ) const;
|
||||
const size_t& max,
|
||||
const std::string& basePath = "" ) const;
|
||||
|
||||
std::shared_ptr<FileListModel> fuzzyMatchTree( const std::string& match,
|
||||
const size_t& max ) const;
|
||||
std::shared_ptr<FileListModel> fuzzyMatchTree( const std::string& match, const size_t& max,
|
||||
const std::string& basePath = "" ) const;
|
||||
|
||||
std::shared_ptr<FileListModel> matchTree( const std::string& match, const size_t& max ) const;
|
||||
std::shared_ptr<FileListModel> matchTree( const std::string& match, const size_t& max,
|
||||
const std::string& basePath = "" ) const;
|
||||
|
||||
void asyncFuzzyMatchTree( const std::string& match, const size_t& max,
|
||||
MatchResultCb res ) const;
|
||||
void asyncFuzzyMatchTree( const std::string& match, const size_t& max, MatchResultCb res,
|
||||
const std::string& basePath = "" ) const;
|
||||
|
||||
void asyncMatchTree( const std::string& match, const size_t& max, MatchResultCb res ) const;
|
||||
void asyncMatchTree( const std::string& match, const size_t& max, MatchResultCb res,
|
||||
const std::string& basePath = "" ) const;
|
||||
|
||||
struct CommandInfo {
|
||||
std::string name;
|
||||
@@ -124,11 +137,13 @@ class ProjectDirectoryTree {
|
||||
UIIcon* icon{ nullptr };
|
||||
};
|
||||
|
||||
std::shared_ptr<FileListModel>
|
||||
asModel( const size_t& max, const std::vector<CommandInfo>& prependCommands = {} ) const;
|
||||
std::shared_ptr<FileListModel> asModel( const size_t& max,
|
||||
const std::vector<CommandInfo>& prependCommands = {},
|
||||
const std::string& basePath = "" ) const;
|
||||
|
||||
static std::shared_ptr<FileListModel>
|
||||
emptyModel( const std::vector<CommandInfo>& prependCommands = {} );
|
||||
emptyModel( const std::vector<CommandInfo>& prependCommands = {},
|
||||
const std::string& basePath = "" );
|
||||
|
||||
size_t getFilesCount() const;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#include "universallocator.hpp"
|
||||
#include "ecode.hpp"
|
||||
#include "pathhelper.hpp"
|
||||
#include "settingsmenu.hpp"
|
||||
#include "universallocator.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -118,33 +118,33 @@ UniversalLocator::UniversalLocator( UICodeEditorSplitter* editorSplitter, UIScen
|
||||
mApp( app ),
|
||||
mCommandPalette( mApp->getThreadPool() ) {
|
||||
|
||||
mLocatorProviders.push_back( {
|
||||
">",
|
||||
mUISceneNode->i18n( "search_in_command_palette", "Search in Command Palette" ),
|
||||
[this]( auto ) {
|
||||
showCommandPalette();
|
||||
return true;
|
||||
},
|
||||
[this]( const Variant&, const ModelEvent* modelEvent ) {
|
||||
ModelIndex idx( modelEvent->getModel()->index( modelEvent->getModelIndex().row(), 2 ) );
|
||||
if ( idx.isValid() ) {
|
||||
String cmd = modelEvent->getModel()->data( idx, ModelRole::Display ).toString();
|
||||
mApp->runCommand( cmd );
|
||||
if ( !mSplitter->getCurWidget()->isType( UI_TYPE_TERMINAL ) ) {
|
||||
if ( mSplitter->curEditorIsNotNull() &&
|
||||
mSplitter->getCurEditor()->getDocument().hasCommand( cmd ) )
|
||||
mSplitter->getCurEditor()->setFocus();
|
||||
}
|
||||
if ( cmd != "open-locatebar" && cmd != "open-workspace-symbol-search" &&
|
||||
cmd != "open-document-symbol-search" && cmd != "go-to-line" &&
|
||||
cmd != "show-open-documents" ) {
|
||||
hideLocateBar();
|
||||
} else {
|
||||
mLocateInput->setFocus();
|
||||
}
|
||||
}
|
||||
},
|
||||
} );
|
||||
mLocatorProviders.push_back(
|
||||
{ ">", mUISceneNode->i18n( "search_in_command_palette", "Search in Command Palette" ),
|
||||
[this]( auto ) {
|
||||
showCommandPalette();
|
||||
return true;
|
||||
},
|
||||
[this]( const Variant&, const ModelEvent* modelEvent ) {
|
||||
ModelIndex idx(
|
||||
modelEvent->getModel()->index( modelEvent->getModelIndex().row(), 2 ) );
|
||||
if ( idx.isValid() ) {
|
||||
String cmd = modelEvent->getModel()->data( idx, ModelRole::Display ).toString();
|
||||
mApp->runCommand( cmd );
|
||||
if ( !mSplitter->getCurWidget()->isType( UI_TYPE_TERMINAL ) ) {
|
||||
if ( mSplitter->curEditorIsNotNull() &&
|
||||
mSplitter->getCurEditor()->getDocument().hasCommand( cmd ) )
|
||||
mSplitter->getCurEditor()->setFocus();
|
||||
}
|
||||
if ( cmd != "open-locatebar" && cmd != "open-workspace-symbol-search" &&
|
||||
cmd != "open-document-symbol-search" && cmd != "go-to-line" &&
|
||||
cmd != "show-open-documents" ) {
|
||||
hideLocateBar();
|
||||
} else {
|
||||
mLocateInput->setFocus();
|
||||
}
|
||||
}
|
||||
},
|
||||
nullptr, false } );
|
||||
|
||||
mLocatorProviders.push_back(
|
||||
{ ":", mUISceneNode->i18n( "search_for_workspace_symbols", "Search for Workspace Symbols" ),
|
||||
@@ -217,14 +217,15 @@ UniversalLocator::UniversalLocator( UICodeEditorSplitter* editorSplitter, UIScen
|
||||
}
|
||||
}
|
||||
return false;
|
||||
} } );
|
||||
},
|
||||
false } );
|
||||
|
||||
mLocatorProviders.push_back( { "o", mUISceneNode->i18n( "open_documents", "Open Documents" ),
|
||||
[this]( auto ) {
|
||||
showOpenDocuments();
|
||||
return true;
|
||||
},
|
||||
nullptr } );
|
||||
nullptr, nullptr, false } );
|
||||
|
||||
// clang-format off
|
||||
mLocatorProviders.push_back( { "sb", mUISceneNode->i18n( "switch_build", "Switch Build" ),
|
||||
@@ -339,27 +340,31 @@ void UniversalLocator::updateFilesTable() {
|
||||
}
|
||||
|
||||
if ( !mApp->isDirTreeReady() ) {
|
||||
mLocateTable->setModel( ProjectDirectoryTree::emptyModel( getLocatorCommands() ) );
|
||||
mLocateTable->setModel(
|
||||
ProjectDirectoryTree::emptyModel( getLocatorCommands(), mApp->getCurrentProject() ) );
|
||||
mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) );
|
||||
} else if ( !mLocateInput->getText().empty() ) {
|
||||
#if EE_PLATFORM != EE_PLATFORM_EMSCRIPTEN || defined( __EMSCRIPTEN_PTHREADS__ )
|
||||
mApp->getDirTree()->asyncFuzzyMatchTree(
|
||||
text, LOCATEBAR_MAX_RESULTS, [this, text]( auto res ) {
|
||||
text, LOCATEBAR_MAX_RESULTS,
|
||||
[this, text]( auto res ) {
|
||||
mUISceneNode->runOnMainThread( [this, res] {
|
||||
mLocateTable->setModel( res );
|
||||
mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) );
|
||||
mLocateTable->scrollToTop();
|
||||
updateLocateBarSync();
|
||||
} );
|
||||
} );
|
||||
},
|
||||
mApp->getCurrentProject() );
|
||||
#else
|
||||
mLocateTable->setModel( mApp->getDirTree()->fuzzyMatchTree( text, LOCATEBAR_MAX_RESULTS ) );
|
||||
mLocateTable->setModel( mApp->getDirTree()->fuzzyMatchTree( text, LOCATEBAR_MAX_RESULTS,
|
||||
mApp->getCurrentProject() ) );
|
||||
mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) );
|
||||
mLocateTable->scrollToTop();
|
||||
#endif
|
||||
} else {
|
||||
mLocateTable->setModel(
|
||||
mApp->getDirTree()->asModel( LOCATEBAR_MAX_RESULTS, getLocatorCommands() ) );
|
||||
mLocateTable->setModel( mApp->getDirTree()->asModel(
|
||||
LOCATEBAR_MAX_RESULTS, getLocatorCommands(), mApp->getCurrentProject() ) );
|
||||
mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) );
|
||||
}
|
||||
}
|
||||
@@ -554,6 +559,10 @@ void UniversalLocator::initLocateBar( UILocateBar* locateBar, UITextInput* locat
|
||||
auto pathAndPos = getPathAndPosition( mLocateInput->getText() );
|
||||
range = { pathAndPos.second, pathAndPos.second };
|
||||
}
|
||||
|
||||
if ( FileSystem::isRelativePath( path ) )
|
||||
path = mApp->getCurrentProject() + path;
|
||||
|
||||
focusOrLoadFile( path, range );
|
||||
mLocateBarLayout->execute( "close-locatebar" );
|
||||
}
|
||||
@@ -618,11 +627,12 @@ void UniversalLocator::showLocateBar() {
|
||||
mLocateInput->setText( "" );
|
||||
|
||||
if ( mApp->getDirTree() && !mLocateTable->getModel() ) {
|
||||
mLocateTable->setModel(
|
||||
mApp->getDirTree()->asModel( LOCATEBAR_MAX_RESULTS, getLocatorCommands() ) );
|
||||
mLocateTable->setModel( mApp->getDirTree()->asModel(
|
||||
LOCATEBAR_MAX_RESULTS, getLocatorCommands(), mApp->getCurrentProject() ) );
|
||||
mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) );
|
||||
} else if ( !mLocateTable->getModel() ) {
|
||||
mLocateTable->setModel( ProjectDirectoryTree::emptyModel( getLocatorCommands() ) );
|
||||
mLocateTable->setModel(
|
||||
ProjectDirectoryTree::emptyModel( getLocatorCommands(), mApp->getCurrentProject() ) );
|
||||
mLocateTable->getSelection().set( mLocateTable->getModel()->index( 0 ) );
|
||||
}
|
||||
|
||||
@@ -1130,8 +1140,12 @@ void UniversalLocator::asyncFuzzyMatchTextDocumentSymbol(
|
||||
std::vector<ProjectDirectoryTree::CommandInfo> UniversalLocator::getLocatorCommands() const {
|
||||
std::vector<ProjectDirectoryTree::CommandInfo> vec;
|
||||
UIIcon* icon = mUISceneNode->findIcon( "chevron-right" );
|
||||
for ( const auto& locator : mLocatorProviders )
|
||||
bool isOpenFolder = mApp->getCurrentProject().empty();
|
||||
for ( const auto& locator : mLocatorProviders ) {
|
||||
if ( !isOpenFolder && locator.projectNeeded )
|
||||
continue;
|
||||
vec.push_back( { locator.symbolTrigger, locator.description, icon } );
|
||||
}
|
||||
return vec;
|
||||
}
|
||||
|
||||
|
||||
@@ -19,13 +19,15 @@ class UniversalLocator {
|
||||
LocatorProvider(
|
||||
String&& symbol, String&& description, std::function<bool( const String& )> switchFn,
|
||||
std::function<void( const Variant& var, const ModelEvent* modelEvent )> openFn,
|
||||
std::function<bool( const String& )> pressEnterFn = nullptr ) :
|
||||
std::function<bool( const String& )> pressEnterFn = nullptr,
|
||||
bool projectNeeded = true ) :
|
||||
symbol( std::move( symbol ) ),
|
||||
symbolTrigger( this->symbol + " " ),
|
||||
description( std::move( description ) ),
|
||||
switchFn( std::move( switchFn ) ),
|
||||
openFn( std::move( openFn ) ),
|
||||
pressEnterFn( std::move( pressEnterFn ) ) {}
|
||||
pressEnterFn( std::move( pressEnterFn ) ),
|
||||
projectNeeded( projectNeeded ) {}
|
||||
|
||||
String symbol;
|
||||
String symbolTrigger;
|
||||
@@ -33,6 +35,7 @@ class UniversalLocator {
|
||||
std::function<bool( const String& )> switchFn;
|
||||
std::function<void( const Variant&, const ModelEvent* )> openFn;
|
||||
std::function<bool( const String& )> pressEnterFn{ nullptr };
|
||||
bool projectNeeded{ true };
|
||||
};
|
||||
|
||||
UniversalLocator( UICodeEditorSplitter* editorSplitter, UISceneNode* sceneNode, App* app );
|
||||
|
||||
Reference in New Issue
Block a user