ui: Added second line to search autocompletion list showing namespace or filepath
* Show namespace or filepath in second line of search autocompletions * Add filepaths relative to .coatidb location * Rescore matches to acknowledge line split * Fixed SearchMatch type to be drawn always visible at right edge
This commit is contained in:
@@ -159,7 +159,7 @@ void FeatureController::handleMessage(MessageSearch* message)
|
||||
MessageActivateTokens m(message, tokenIds);
|
||||
for (const SearchMatch& match : matches)
|
||||
{
|
||||
m.unknownNames.push_back(match.text);
|
||||
m.unknownNames.push_back(match.name);
|
||||
}
|
||||
if (!message->isReplayed())
|
||||
{
|
||||
|
||||
@@ -121,6 +121,32 @@ Id HierarchyCache::getLastVisibleParentNodeId(Id nodeId) const
|
||||
return nodeId;
|
||||
}
|
||||
|
||||
size_t HierarchyCache::getIndexOfLastVisibleParentNode(Id nodeId) const
|
||||
{
|
||||
HierarchyNode* node = nullptr;
|
||||
HierarchyNode* parent = getNode(nodeId);
|
||||
|
||||
size_t idx = 0;
|
||||
bool visible = false;
|
||||
|
||||
while (parent)
|
||||
{
|
||||
node = parent;
|
||||
parent = node->getParent();
|
||||
|
||||
if (node->isVisible())
|
||||
{
|
||||
visible = true;
|
||||
}
|
||||
else if (visible)
|
||||
{
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
return idx;
|
||||
}
|
||||
|
||||
void HierarchyCache::addAllChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds, std::vector<Id>* edgeIds) const
|
||||
{
|
||||
HierarchyNode* node = getNode(nodeId);
|
||||
|
||||
@@ -15,6 +15,7 @@ public:
|
||||
void createConnection(Id edgeId, Id fromId, Id toId, bool fromVisible);
|
||||
|
||||
Id getLastVisibleParentNodeId(Id nodeId) const;
|
||||
size_t getIndexOfLastVisibleParentNode(Id nodeId) const;
|
||||
|
||||
void addAllChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds, std::vector<Id>* edgeIds) const;
|
||||
void addFirstChildIdsForNodeId(Id nodeId, std::vector<Id>* nodeIds) const;
|
||||
|
||||
@@ -30,9 +30,9 @@
|
||||
PersistentStorage::PersistentStorage(const FilePath& dbPath)
|
||||
: m_sqliteStorage(dbPath)
|
||||
{
|
||||
m_commandIndex.addNode(0, NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_ALL)));
|
||||
m_commandIndex.addNode(0, NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_ERROR)));
|
||||
// m_commandIndex.addNode(0, NameHierarchy(SearchMatch::getCommandName(SearchMatch::COMMAND_COLOR_SCHEME_TEST)));
|
||||
m_commandIndex.addNode(0, SearchMatch::getCommandName(SearchMatch::COMMAND_ALL));
|
||||
m_commandIndex.addNode(0, SearchMatch::getCommandName(SearchMatch::COMMAND_ERROR));
|
||||
// m_commandIndex.addNode(0, SearchMatch::getCommandName(SearchMatch::COMMAND_COLOR_SCHEME_TEST));
|
||||
m_commandIndex.finishSetup();
|
||||
}
|
||||
|
||||
@@ -275,6 +275,7 @@ void PersistentStorage::clear()
|
||||
void PersistentStorage::clearCaches()
|
||||
{
|
||||
m_elementIndex.clear();
|
||||
m_fileIndex.clear();
|
||||
m_fileNodeIds.clear();
|
||||
m_fileNodePaths.clear();
|
||||
m_hierarchyCache.clear();
|
||||
@@ -344,8 +345,8 @@ void PersistentStorage::buildCaches()
|
||||
|
||||
clearCaches();
|
||||
|
||||
buildSearchIndex();
|
||||
buildFilePathMaps();
|
||||
buildSearchIndex();
|
||||
buildHierarchyCache();
|
||||
}
|
||||
|
||||
@@ -478,55 +479,14 @@ std::vector<SearchMatch> PersistentStorage::getAutocompletionMatches(const std::
|
||||
{
|
||||
TRACE();
|
||||
|
||||
std::vector<SearchResult> commandResults = m_commandIndex.search(query, 0);
|
||||
|
||||
const size_t maxResultCount = 100;
|
||||
std::vector<SearchResult> elementResults = m_elementIndex.search(query, maxResultCount);
|
||||
|
||||
// search in indices
|
||||
size_t maxResultsCount = 100;
|
||||
std::vector<SearchResult> results;
|
||||
utility::append(results, commandResults);
|
||||
utility::append(results, elementResults);
|
||||
|
||||
std::sort(results.begin(), results.end(),
|
||||
[](const SearchResult& a, const SearchResult& b)
|
||||
{
|
||||
// should a be ranked higher than b?
|
||||
if (a.score > b.score)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (a.score == b.score)
|
||||
{
|
||||
if (a.text.size() < b.text.size())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (a.text.size() == b.text.size())
|
||||
{
|
||||
for (size_t i = 0; i < a.text.size(); i++)
|
||||
{
|
||||
if (tolower(a.text[i]) != tolower(b.text[i]))
|
||||
{
|
||||
return tolower(a.text[i]) < tolower(b.text[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (a.text[i] < b.text[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (a.text[i] > b.text[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
);
|
||||
utility::append(results, m_commandIndex.search(query, 0));
|
||||
utility::append(results, m_elementIndex.search(query, maxResultsCount, 100));
|
||||
utility::append(results, m_fileIndex.search(query, 20));
|
||||
|
||||
// fetch StorageNodes for node ids
|
||||
std::map<Id, StorageNode> storageNodesMap;
|
||||
{
|
||||
std::vector<Id> elementIds;
|
||||
@@ -547,7 +507,8 @@ std::vector<SearchMatch> PersistentStorage::getAutocompletionMatches(const std::
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<SearchMatch> matches;
|
||||
// create SearchMatches
|
||||
std::set<SearchMatch> matches;
|
||||
for (const SearchResult& result : results)
|
||||
{
|
||||
SearchMatch match;
|
||||
@@ -572,14 +533,41 @@ std::vector<SearchMatch> PersistentStorage::getAutocompletionMatches(const std::
|
||||
}
|
||||
}
|
||||
|
||||
match.text = result.text;
|
||||
match.name = result.text;
|
||||
match.indices = result.indices;
|
||||
match.score = result.score;
|
||||
|
||||
if (firstNode)
|
||||
{
|
||||
match.nodeType = Node::intToType(firstNode->type);
|
||||
match.typeName = Node::getTypeString(match.nodeType);
|
||||
|
||||
size_t idx = 0;
|
||||
if (match.nodeType == Node::NODE_FILE)
|
||||
{
|
||||
idx = 1;
|
||||
|
||||
FilePath path(match.name);
|
||||
match.text = path.fileName();
|
||||
match.subtext = path.str();
|
||||
}
|
||||
else
|
||||
{
|
||||
idx = m_hierarchyCache.getIndexOfLastVisibleParentNode(firstNode->id);
|
||||
const NameHierarchy& name = match.nameHierarchies[0];
|
||||
|
||||
match.text = name.getRange(idx, name.size()).getQualifiedName();
|
||||
match.subtext = name.getRange(0, idx).getQualifiedName();
|
||||
}
|
||||
|
||||
// rescore match
|
||||
if (idx && match.indices.size())
|
||||
{
|
||||
SearchResult newResult = SearchIndex::rescoreText(match.name, match.text, match.indices, match.score);
|
||||
match.score = newResult.score;
|
||||
match.indices = newResult.indices;
|
||||
}
|
||||
|
||||
if (intToDefinitionType(firstNode->definitionType) == DEFINITION_NONE
|
||||
&& match.nodeType != Node::NODE_UNDEFINED)
|
||||
{
|
||||
@@ -593,10 +581,16 @@ std::vector<SearchMatch> PersistentStorage::getAutocompletionMatches(const std::
|
||||
match.typeName = "command";
|
||||
}
|
||||
|
||||
matches.push_back(match);
|
||||
matches.insert(match);
|
||||
}
|
||||
|
||||
return matches;
|
||||
std::vector<SearchMatch> matchesVector = utility::toVector(matches);
|
||||
if (matchesVector.size() > maxResultsCount)
|
||||
{
|
||||
matchesVector.resize(maxResultsCount);
|
||||
}
|
||||
|
||||
return matchesVector;
|
||||
}
|
||||
|
||||
std::vector<SearchMatch> PersistentStorage::getSearchMatchesForTokenIds(const std::vector<Id>& elementIds) const
|
||||
@@ -624,7 +618,7 @@ std::vector<SearchMatch> PersistentStorage::getSearchMatchesForTokenIds(const st
|
||||
}
|
||||
|
||||
NameHierarchy nameHierarchy = NameHierarchy::deserialize(m_sqliteStorage.getNodeById(elementId).serializedName);
|
||||
match.text = nameHierarchy.getQualifiedName();
|
||||
match.name = nameHierarchy.getQualifiedName();
|
||||
match.nameHierarchies.push_back(nameHierarchy.getQualifiedName());
|
||||
match.searchType = SearchMatch::SEARCH_TOKEN;
|
||||
|
||||
@@ -1430,14 +1424,33 @@ void PersistentStorage::buildSearchIndex()
|
||||
{
|
||||
TRACE();
|
||||
|
||||
FilePath dbPath = getDbFilePath();
|
||||
|
||||
for (StorageNode node : m_sqliteStorage.getAllNodes())
|
||||
{
|
||||
if (intToDefinitionType(node.definitionType) != DEFINITION_IMPLICIT)
|
||||
{
|
||||
m_elementIndex.addNode(node.id, NameHierarchy::deserialize(node.serializedName));
|
||||
if (Node::intToType(node.type) == Node::NODE_FILE)
|
||||
{
|
||||
FilePath filePath = m_fileNodePaths[node.id];
|
||||
|
||||
if (filePath.exists())
|
||||
{
|
||||
filePath = filePath.relativeTo(dbPath);
|
||||
}
|
||||
|
||||
m_fileIndex.addNode(node.id, filePath.str());
|
||||
}
|
||||
else
|
||||
{
|
||||
// we don't use the signature here, so elements with the same signature share the same node.
|
||||
m_elementIndex.addNode(node.id, NameHierarchy::deserialize(node.serializedName).getQualifiedName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_elementIndex.finishSetup();
|
||||
m_fileIndex.finishSetup();
|
||||
}
|
||||
|
||||
void PersistentStorage::buildFilePathMaps()
|
||||
|
||||
@@ -151,6 +151,7 @@ private:
|
||||
|
||||
SearchIndex m_commandIndex;
|
||||
SearchIndex m_elementIndex;
|
||||
SearchIndex m_fileIndex;
|
||||
|
||||
mutable FullTextSearchIndex m_fullTextSearchIndex;
|
||||
|
||||
|
||||
@@ -92,6 +92,18 @@ std::shared_ptr<NameElement> NameHierarchy::operator[](size_t pos) const
|
||||
return m_elements[pos];
|
||||
}
|
||||
|
||||
NameHierarchy NameHierarchy::getRange(size_t first, size_t last) const
|
||||
{
|
||||
NameHierarchy hierarchy;
|
||||
|
||||
for (size_t i = first; i < last; i++)
|
||||
{
|
||||
hierarchy.push(m_elements[i]);
|
||||
}
|
||||
|
||||
return hierarchy;
|
||||
}
|
||||
|
||||
size_t NameHierarchy::size() const
|
||||
{
|
||||
return m_elements.size();
|
||||
|
||||
@@ -23,8 +23,12 @@ public:
|
||||
|
||||
void push(std::shared_ptr<NameElement> element);
|
||||
void pop();
|
||||
|
||||
std::shared_ptr<NameElement> back() const;
|
||||
std::shared_ptr<NameElement> operator[](size_t pos) const;
|
||||
|
||||
NameHierarchy getRange(size_t first, size_t last) const;
|
||||
|
||||
size_t size() const;
|
||||
|
||||
std::string getQualifiedName() const;
|
||||
|
||||
@@ -16,13 +16,11 @@ SearchIndex::~SearchIndex()
|
||||
{
|
||||
}
|
||||
|
||||
void SearchIndex::addNode(Id id, const NameHierarchy& nameHierarchy)
|
||||
void SearchIndex::addNode(Id id, const std::string& name)
|
||||
{
|
||||
Node* currentNode = m_root;
|
||||
|
||||
// we don't use the signature here, so elements with the same signature share the same node in the search index.
|
||||
std::string remaining = nameHierarchy.getQualifiedName();
|
||||
|
||||
std::string remaining = name;
|
||||
while (remaining.size() > 0)
|
||||
{
|
||||
bool matchingEdgeFound = false;
|
||||
@@ -106,7 +104,8 @@ void SearchIndex::clear()
|
||||
m_root = n.get();
|
||||
}
|
||||
|
||||
std::vector<SearchResult> SearchIndex::search(const std::string& query, size_t maxResultCount) const
|
||||
std::vector<SearchResult> SearchIndex::search(
|
||||
const std::string& query, size_t maxResultCount, size_t maxBestScoredLength) const
|
||||
{
|
||||
// find paths containing query
|
||||
Path startPath;
|
||||
@@ -123,7 +122,7 @@ std::vector<SearchResult> SearchIndex::search(const std::string& query, size_t m
|
||||
std::multiset<SearchResult> bestResults;
|
||||
for (const SearchResult& result : searchResults)
|
||||
{
|
||||
bestResults.insert(bestScoredResult(result, &scoresCache));
|
||||
bestResults.insert(bestScoredResult(result, &scoresCache, maxBestScoredLength));
|
||||
}
|
||||
|
||||
// narrow down to max result count
|
||||
@@ -212,7 +211,7 @@ std::multiset<SearchResult> SearchIndex::createScoredResults(const std::vector<P
|
||||
|
||||
for (const Path& path : paths)
|
||||
{
|
||||
scoredPaths.insert(std::make_pair(score(path.text, path.indices), path));
|
||||
scoredPaths.insert(std::make_pair(scoreText(path.text, path.indices), path));
|
||||
}
|
||||
|
||||
// score paths and subpaths
|
||||
@@ -234,7 +233,7 @@ std::multiset<SearchResult> SearchIndex::createScoredResults(const std::vector<P
|
||||
result.text = path.text;
|
||||
result.elementIds = path.node->elementIds;
|
||||
result.indices = path.indices;
|
||||
result.score = score(path.text, path.indices);
|
||||
result.score = scoreText(path.text, path.indices);
|
||||
searchResults.insert(result);
|
||||
|
||||
if (maxResultCount && searchResults.size() >= maxResultCount)
|
||||
@@ -260,9 +259,10 @@ std::multiset<SearchResult> SearchIndex::createScoredResults(const std::vector<P
|
||||
return searchResults;
|
||||
}
|
||||
|
||||
SearchResult SearchIndex::bestScoredResult(SearchResult result, std::map<std::string, SearchResult>* scoresCache) const
|
||||
SearchResult SearchIndex::bestScoredResult(
|
||||
SearchResult result, std::map<std::string, SearchResult>* scoresCache, size_t maxBestScoredLength)
|
||||
{
|
||||
if (result.text.size() > 100)
|
||||
if (maxBestScoredLength && result.text.size() > maxBestScoredLength)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
@@ -296,7 +296,7 @@ SearchResult SearchIndex::bestScoredResult(SearchResult result, std::map<std::st
|
||||
|
||||
void SearchIndex::bestScoredResultRecursive(
|
||||
const std::string& lowerText, const std::vector<size_t>& indices, const size_t indicesPos,
|
||||
std::map<std::string, SearchResult>* scoresCache, SearchResult* result) const
|
||||
std::map<std::string, SearchResult>* scoresCache, SearchResult* result)
|
||||
{
|
||||
// left for debugging
|
||||
// std::cout << lowerText << std::endl;
|
||||
@@ -326,7 +326,7 @@ void SearchIndex::bestScoredResultRecursive(
|
||||
std::vector<size_t> newIndices = indices;
|
||||
newIndices[indicesPos] = i;
|
||||
|
||||
int newScore = score(result->text, newIndices);
|
||||
int newScore = scoreText(result->text, newIndices);
|
||||
if (newScore > result->score)
|
||||
{
|
||||
result->score = newScore;
|
||||
@@ -362,12 +362,13 @@ void SearchIndex::bestScoredResultRecursive(
|
||||
}
|
||||
}
|
||||
|
||||
int SearchIndex::score(const std::string& text, const std::vector<size_t>& indices) const
|
||||
int SearchIndex::scoreText(const std::string& text, const std::vector<size_t>& indices)
|
||||
{
|
||||
const int unmatchedLetterBonus = -1;
|
||||
const int consecutiveLetterBonus = 5;
|
||||
const int camelCaseBonus = 4;
|
||||
const int noLetterBonus = 3;
|
||||
const int firstLetterBonus = 4;
|
||||
const int delayedStartBonus = -1;
|
||||
const int minDelayedStartBonus = -20;
|
||||
|
||||
@@ -375,6 +376,7 @@ int SearchIndex::score(const std::string& text, const std::vector<size_t>& indic
|
||||
int consecutiveLetterScore = 0;
|
||||
int camelCaseScore = 0;
|
||||
int noLetterScore = 0;
|
||||
int firstLetterScore = 0;
|
||||
|
||||
static std::set<char> noLetters;
|
||||
if (!noLetters.size())
|
||||
@@ -386,6 +388,8 @@ int SearchIndex::score(const std::string& text, const std::vector<size_t>& indic
|
||||
noLetters.insert(':');
|
||||
noLetters.insert('<');
|
||||
noLetters.insert('>');
|
||||
noLetters.insert('/');
|
||||
noLetters.insert('\\');
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < indices.size(); i++)
|
||||
@@ -399,9 +403,13 @@ int SearchIndex::score(const std::string& text, const std::vector<size_t>& indic
|
||||
|
||||
size_t index = indices[i];
|
||||
|
||||
// first letter
|
||||
if (index == 0)
|
||||
{
|
||||
firstLetterScore += firstLetterBonus;
|
||||
}
|
||||
// after no letter
|
||||
bool prevIsNoLetter = (index == 0 || noLetters.find(text[index - 1]) != noLetters.end());
|
||||
if (prevIsNoLetter)
|
||||
else if ((index != 0 && noLetters.find(text[index - 1]) != noLetters.end()))
|
||||
{
|
||||
noLetterScore += noLetterBonus;
|
||||
}
|
||||
@@ -416,6 +424,8 @@ int SearchIndex::score(const std::string& text, const std::vector<size_t>& indic
|
||||
camelCaseScore += camelCaseBonus;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
int leadingStartScore = std::max(int(indices[0]) * delayedStartBonus, minDelayedStartBonus);
|
||||
@@ -425,7 +435,66 @@ int SearchIndex::score(const std::string& text, const std::vector<size_t>& indic
|
||||
consecutiveLetterScore +
|
||||
camelCaseScore +
|
||||
noLetterScore +
|
||||
firstLetterScore +
|
||||
leadingStartScore;
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
SearchResult SearchIndex::rescoreText(
|
||||
const std::string& fulltext,
|
||||
const std::string& text,
|
||||
const std::vector<size_t>& indices,
|
||||
int score,
|
||||
size_t maxBestScoredLength)
|
||||
{
|
||||
SearchResult result;
|
||||
result.text = text;
|
||||
result.score = score;
|
||||
result.indices = indices;
|
||||
|
||||
std::vector<size_t> textIndices;
|
||||
|
||||
// match is already within text
|
||||
int newIdx = indices[0] - (fulltext.size() - text.size());
|
||||
if (newIdx >= 0)
|
||||
{
|
||||
for (size_t idx : indices)
|
||||
{
|
||||
textIndices.push_back(idx - (fulltext.size() - text.size()));
|
||||
}
|
||||
}
|
||||
// try if match is within text
|
||||
else
|
||||
{
|
||||
size_t idx = 0;
|
||||
for (size_t i = 0; i < text.size() && idx < indices.size(); i++)
|
||||
{
|
||||
if (tolower(text[i]) == tolower(fulltext[indices[idx]]))
|
||||
{
|
||||
textIndices.push_back(i);
|
||||
idx++;
|
||||
}
|
||||
}
|
||||
|
||||
// match was not found
|
||||
if (idx != indices.size())
|
||||
{
|
||||
result.score -= 1;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
result.score = scoreText(text, textIndices);
|
||||
result.indices = textIndices;
|
||||
|
||||
std::map<std::string, SearchResult> scoresCache;
|
||||
result = bestScoredResult(result, &scoresCache, maxBestScoredLength);
|
||||
|
||||
for (size_t i = 0; i < result.indices.size(); i++)
|
||||
{
|
||||
result.indices[i] += fulltext.size() - text.size();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -8,20 +8,19 @@
|
||||
#include <string>
|
||||
#include <unordered_set>
|
||||
|
||||
#include "data/name/NameHierarchy.h"
|
||||
#include "utility/types.h"
|
||||
|
||||
struct SearchResult
|
||||
{
|
||||
std::string text;
|
||||
std::set<Id> elementIds;
|
||||
std::vector<size_t> indices;
|
||||
int score;
|
||||
|
||||
bool operator<(const SearchResult& other) const
|
||||
{
|
||||
return score > other.score;
|
||||
}
|
||||
|
||||
std::string text;
|
||||
std::set<Id> elementIds;
|
||||
std::vector<size_t> indices;
|
||||
int score;
|
||||
};
|
||||
|
||||
class SearchIndex
|
||||
@@ -30,12 +29,12 @@ public:
|
||||
SearchIndex();
|
||||
virtual ~SearchIndex();
|
||||
|
||||
void addNode(Id id, const NameHierarchy& nameHierarchy);
|
||||
void addNode(Id id, const std::string& name);
|
||||
void finishSetup();
|
||||
void clear();
|
||||
|
||||
// maxResultCount == 0 means "no restriction".
|
||||
std::vector<SearchResult> search(const std::string& query, size_t maxResultCount) const;
|
||||
std::vector<SearchResult> search(const std::string& query, size_t maxResultCount, size_t maxBestScoredLength = 0) const;
|
||||
|
||||
private:
|
||||
struct Node;
|
||||
@@ -65,12 +64,23 @@ private:
|
||||
void searchRecursive(const Path& path, const std::string& remainingQuery, std::vector<SearchIndex::Path>* results) const;
|
||||
|
||||
std::multiset<SearchResult> createScoredResults(const std::vector<Path>& paths, size_t maxResultCount) const;
|
||||
SearchResult bestScoredResult(SearchResult result, std::map<std::string, SearchResult>* scoresCache) const;
|
||||
void bestScoredResultRecursive(
|
||||
const std::string& lowerText, const std::vector<size_t>& indices, const size_t indicesPos,
|
||||
std::map<std::string, SearchResult>* scoresCache, SearchResult* result) const;
|
||||
int score(const std::string& text, const std::vector<size_t>& indices) const;
|
||||
|
||||
static SearchResult bestScoredResult(
|
||||
SearchResult result, std::map<std::string, SearchResult>* scoresCache, size_t maxBestScoredLength);
|
||||
static void bestScoredResultRecursive(
|
||||
const std::string& lowerText, const std::vector<size_t>& indices, const size_t indicesPos,
|
||||
std::map<std::string, SearchResult>* scoresCache, SearchResult* result);
|
||||
static int scoreText(const std::string& text, const std::vector<size_t>& indices);
|
||||
|
||||
public:
|
||||
static SearchResult rescoreText(
|
||||
const std::string& fulltext,
|
||||
const std::string& text,
|
||||
const std::vector<size_t>& indices,
|
||||
int score,
|
||||
size_t maxBestScoredLength = 0);
|
||||
|
||||
private:
|
||||
std::vector<std::shared_ptr<Node>> m_nodes;
|
||||
std::vector<std::shared_ptr<Edge>> m_edges;
|
||||
Node* m_root;
|
||||
|
||||
@@ -49,7 +49,8 @@ std::string SearchMatch::searchMatchesToString(const std::vector<SearchMatch>& m
|
||||
SearchMatch SearchMatch::createCommand(CommandType type)
|
||||
{
|
||||
SearchMatch match;
|
||||
match.text = getCommandName(type);
|
||||
match.name = getCommandName(type);
|
||||
match.text = match.name;
|
||||
match.typeName = "command";
|
||||
match.searchType = SEARCH_COMMAND;
|
||||
return match;
|
||||
@@ -96,13 +97,60 @@ SearchMatch::SearchMatch()
|
||||
}
|
||||
|
||||
SearchMatch::SearchMatch(const std::string& query)
|
||||
: text(query)
|
||||
: name(query)
|
||||
, typeName("")
|
||||
, searchType(SEARCH_NONE)
|
||||
, hasChildren(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
bool SearchMatch::operator<(const SearchMatch& other) const
|
||||
{
|
||||
// score
|
||||
if (score > other.score)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (score < other.score)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// text size
|
||||
if (text.size() < other.text.size())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (text.size() > other.text.size())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// lower case
|
||||
for (size_t i = 0; i < text.size(); i++)
|
||||
{
|
||||
if (tolower(text[i]) != tolower(other.text[i]))
|
||||
{
|
||||
return tolower(text[i]) < tolower(other.text[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// alphabetical
|
||||
if (text[i] < other.text[i])
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (text[i] > other.text[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SearchMatch::isValid() const
|
||||
{
|
||||
return searchType != SEARCH_NONE;
|
||||
@@ -110,7 +158,7 @@ bool SearchMatch::isValid() const
|
||||
|
||||
void SearchMatch::print(std::ostream& ostream) const
|
||||
{
|
||||
ostream << text << std::endl << '\t';
|
||||
ostream << name << std::endl << '\t';
|
||||
size_t i = 0;
|
||||
for (size_t index : indices)
|
||||
{
|
||||
@@ -127,7 +175,12 @@ void SearchMatch::print(std::ostream& ostream) const
|
||||
|
||||
std::string SearchMatch::getFullName() const
|
||||
{
|
||||
return text;
|
||||
if (searchType == SEARCH_TOKEN && nodeType == Node::NODE_FILE)
|
||||
{
|
||||
return text;
|
||||
}
|
||||
|
||||
return name;
|
||||
}
|
||||
|
||||
std::string SearchMatch::getNodeTypeAsString() const
|
||||
|
||||
@@ -41,6 +41,8 @@ struct SearchMatch
|
||||
SearchMatch();
|
||||
SearchMatch(const std::string& query);
|
||||
|
||||
bool operator<(const SearchMatch& other) const;
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
void print(std::ostream& ostream) const;
|
||||
@@ -49,12 +51,19 @@ struct SearchMatch
|
||||
std::string getNodeTypeAsString() const;
|
||||
std::string getSearchTypeName() const;
|
||||
|
||||
std::string name;
|
||||
|
||||
std::string text;
|
||||
std::string subtext;
|
||||
|
||||
std::string typeName;
|
||||
|
||||
Node::NodeType nodeType;
|
||||
SearchType searchType;
|
||||
std::vector<size_t> indices;
|
||||
|
||||
int score;
|
||||
|
||||
std::vector<NameHierarchy> nameHierarchies;
|
||||
|
||||
bool hasChildren;
|
||||
|
||||
Reference in New Issue
Block a user