parent
831c122d06
commit
a6e83bfe76
@ -285,6 +285,10 @@ User Guide
|
||||
|
||||
- If the offered completions are too broad, keep typing characters; YCM will
|
||||
continue refining the offered completions based on your input.
|
||||
- Filtering is "smart-case" sensitive; if you are typing only lowercase letters,
|
||||
then it's case-insensitive. If your input involves uppercase letters, then
|
||||
it's case-sensitive. So "foo" matches "Foo" and "foo", but "Foo" matches "Foo"
|
||||
but not "foo".
|
||||
- Use the TAB key to accept a completion and continue pressing TAB to cycle
|
||||
through the completions. Use Shift-TAB to cycle backwards. Note that if you're
|
||||
using console Vim (that is, not Gvim or MacVim) then it's likely that the
|
||||
@ -306,7 +310,7 @@ string.
|
||||
### General Semantic Completion Engine Usage
|
||||
|
||||
- You can use Ctrl+Space to trigger the completion suggestions anywhere, even
|
||||
without a string prefix. This is useful to see which top-level functions are
|
||||
without a string prefix. This is useful to see which top-level functions are
|
||||
available for use.
|
||||
|
||||
### C-family Semantic Completion Engine Usage
|
||||
|
@ -43,6 +43,28 @@ std::string GetWordBoundaryChars( const std::string &text ) {
|
||||
return result;
|
||||
}
|
||||
|
||||
LetterNode* FirstUppercaseNode( const std::list< LetterNode *> &list ) {
|
||||
LetterNode *node = NULL;
|
||||
foreach( LetterNode *current_node, list ) {
|
||||
if ( current_node->LetterIsUppercase() ) {
|
||||
node = current_node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
LetterNode* FirstLowercaseNode( const std::list< LetterNode *> &list ) {
|
||||
LetterNode *node = NULL;
|
||||
foreach( LetterNode *current_node, list ) {
|
||||
if ( !current_node->LetterIsUppercase() ) {
|
||||
node = current_node;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
} // unnamed namespace
|
||||
|
||||
|
||||
@ -66,7 +88,8 @@ Candidate::Candidate( const std::string &text )
|
||||
}
|
||||
|
||||
|
||||
Result Candidate::QueryMatchResult( const std::string &query ) const {
|
||||
Result Candidate::QueryMatchResult( const std::string &query,
|
||||
bool case_sensitive ) const {
|
||||
LetterNode *node = root_node_.get();
|
||||
int index_sum = 0;
|
||||
|
||||
@ -76,7 +99,17 @@ Result Candidate::QueryMatchResult( const std::string &query ) const {
|
||||
if ( !list )
|
||||
return Result( false );
|
||||
|
||||
node = list->front();
|
||||
if ( case_sensitive ) {
|
||||
node = IsUppercase( letter ) ?
|
||||
FirstUppercaseNode( *list ) :
|
||||
FirstLowercaseNode( *list );
|
||||
|
||||
if ( !node )
|
||||
return Result( false );
|
||||
} else {
|
||||
node = list->front();
|
||||
}
|
||||
|
||||
index_sum += node->Index();
|
||||
}
|
||||
|
||||
|
@ -49,7 +49,8 @@ public:
|
||||
return ( letters_present_ & query_bitset ) == query_bitset;
|
||||
}
|
||||
|
||||
Result QueryMatchResult( const std::string &query ) const;
|
||||
Result QueryMatchResult( const std::string &query,
|
||||
bool case_sensitive ) const;
|
||||
|
||||
private:
|
||||
|
||||
|
@ -29,6 +29,11 @@
|
||||
|
||||
#include <clang-c/Index.h>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/cxx11/any_of.hpp>
|
||||
|
||||
using boost::algorithm::any_of;
|
||||
using boost::algorithm::is_upper;
|
||||
|
||||
using boost::bind;
|
||||
using boost::cref;
|
||||
@ -387,6 +392,7 @@ std::vector< CompletionData > ClangCompleter::SortCandidatesForQuery(
|
||||
const std::string &query,
|
||||
const std::vector< CompletionData > &completion_datas ) {
|
||||
Bitset query_bitset = LetterBitsetFromString( query );
|
||||
bool query_has_uppercase_letters = any_of( query, is_upper() );
|
||||
|
||||
std::vector< const Candidate * > repository_candidates =
|
||||
candidate_repository_.GetCandidatesForStrings( completion_datas );
|
||||
@ -399,7 +405,8 @@ std::vector< CompletionData > ClangCompleter::SortCandidatesForQuery(
|
||||
if ( !candidate->MatchesQueryBitset( query_bitset ) )
|
||||
continue;
|
||||
|
||||
Result result = candidate->QueryMatchResult( query );
|
||||
Result result = candidate->QueryMatchResult( query,
|
||||
query_has_uppercase_letters );
|
||||
|
||||
if ( result.IsSubsequence() ) {
|
||||
ResultAnd< CompletionData* > data_and_result( &completion_datas[ i ],
|
||||
|
@ -26,8 +26,13 @@
|
||||
#include <boost/unordered_set.hpp>
|
||||
#include <boost/bind.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/cxx11/any_of.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
using boost::algorithm::any_of;
|
||||
using boost::algorithm::is_upper;
|
||||
|
||||
using boost::packaged_task;
|
||||
using boost::unique_future;
|
||||
using boost::shared_ptr;
|
||||
@ -228,6 +233,7 @@ void IdentifierCompleter::ResultsForQueryAndType(
|
||||
return;
|
||||
|
||||
Bitset query_bitset = LetterBitsetFromString( query );
|
||||
bool query_has_uppercase_letters = any_of( query, is_upper() );
|
||||
|
||||
boost::unordered_set< const Candidate * > seen_candidates;
|
||||
seen_candidates.reserve( candidate_repository_.NumStoredCandidates() );
|
||||
@ -243,7 +249,8 @@ void IdentifierCompleter::ResultsForQueryAndType(
|
||||
if ( !candidate->MatchesQueryBitset( query_bitset ) )
|
||||
continue;
|
||||
|
||||
Result result = candidate->QueryMatchResult( query );
|
||||
Result result = candidate->QueryMatchResult(
|
||||
query, query_has_uppercase_letters );
|
||||
|
||||
if ( result.IsSubsequence() )
|
||||
results.push_back( result );
|
||||
|
@ -51,7 +51,7 @@ public:
|
||||
letters_[ letter ].push_front( node );
|
||||
}
|
||||
|
||||
inline int Index() {
|
||||
inline int Index() const {
|
||||
return index_;
|
||||
}
|
||||
|
||||
|
@ -20,8 +20,12 @@
|
||||
#include "Result.h"
|
||||
#include "Candidate.h"
|
||||
#include "CandidateRepository.h"
|
||||
#include <boost/algorithm/string.hpp>
|
||||
#include <boost/algorithm/cxx11/any_of.hpp>
|
||||
#include <vector>
|
||||
|
||||
using boost::algorithm::any_of;
|
||||
using boost::algorithm::is_upper;
|
||||
using boost::python::len;
|
||||
using boost::python::extract;
|
||||
using boost::python::object;
|
||||
@ -67,6 +71,8 @@ boost::python::list FilterAndSortCandidates(
|
||||
CandidatesFromObjectList( candidates, candidate_property );
|
||||
|
||||
Bitset query_bitset = LetterBitsetFromString( query );
|
||||
bool query_has_uppercase_letters = any_of( query, is_upper() );
|
||||
|
||||
int num_candidates = len( candidates );
|
||||
std::vector< ResultAnd< int > > object_and_results;
|
||||
|
||||
@ -76,7 +82,8 @@ boost::python::list FilterAndSortCandidates(
|
||||
if ( !candidate->MatchesQueryBitset( query_bitset ) )
|
||||
continue;
|
||||
|
||||
Result result = candidate->QueryMatchResult( query );
|
||||
Result result = candidate->QueryMatchResult( query,
|
||||
query_has_uppercase_letters );
|
||||
|
||||
if ( result.IsSubsequence() ) {
|
||||
ResultAnd< int > object_and_result( i, result );
|
||||
|
@ -64,45 +64,87 @@ TEST( CandidateTest, DoesntMatchQueryBitset ) {
|
||||
LetterBitsetFromString( "fbrmmm" ) ) );
|
||||
}
|
||||
|
||||
TEST( CandidateTest, QueryMatchResultIsSubsequence ) {
|
||||
TEST( CandidateTest, QueryMatchResultCaseInsensitiveIsSubsequence ) {
|
||||
Candidate candidate( "foobaaar" );
|
||||
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "foobaaar" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "fobar" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "fbr" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "f" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "o" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "a" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "r" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "b" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "bar" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "oa" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "obr" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "oo" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "aaa" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "" ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "foobaaar", false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "foOBAaar", false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "FOOBAAAR", false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "fobar" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "fbr" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "f" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "F" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "o" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "O" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "a" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "r" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "b" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "bar" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "oa" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "obr" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "oar" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "oo" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "aaa" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "AAA" , false ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "" , false ).IsSubsequence() );
|
||||
}
|
||||
|
||||
TEST( CandidateTest, QueryMatchResultIsntSubsequence ) {
|
||||
TEST( CandidateTest, QueryMatchResultCaseInsensitiveIsntSubsequence ) {
|
||||
Candidate candidate( "foobaaar" );
|
||||
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "foobra" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "frb" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "brf" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "x" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "9" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "-" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "~" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( " " ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "rabof" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "oabfr" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "ooo" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "baaara" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "ffoobaaar" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "xfoobaaar" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( " foobaaar" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "foobaaar " ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "ff" ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "foobra" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "frb" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "brf" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "x" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "9" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "-" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "~" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( " " , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "rabof" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "oabfr" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "ooo" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "baaara" , false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "ffoobaaar", false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "xfoobaaar", false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( " foobaaar", false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "foobaaar ", false ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "ff" , false ).IsSubsequence() );
|
||||
}
|
||||
|
||||
TEST( CandidateTest, QueryMatchResultCaseSensitiveIsSubsequence ) {
|
||||
Candidate candidate( "FooBaAAr" );
|
||||
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "FooBaAAr", true ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "FBAA" , true ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "F" , true ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "AA" , true ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "A" , true ).IsSubsequence() );
|
||||
EXPECT_TRUE( candidate.QueryMatchResult( "B" , true ).IsSubsequence() );
|
||||
}
|
||||
|
||||
TEST( CandidateTest, QueryMatchResultCaseSensitiveIsntSubsequence ) {
|
||||
Candidate candidate( "FooBaAAr" );
|
||||
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "foobaaar", true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "foobaAAr", true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "fbAA" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "fbaa" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "R" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "b" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "f" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "O" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "OO" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "OBA" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "FBAR" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "fbar" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "FBAAR" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "Oar" , true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "FooBaAAR", true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "FooBAAAr", true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "FOoBaAAr", true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "FOobaaar", true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "fOobaaar", true ).IsSubsequence() );
|
||||
EXPECT_FALSE( candidate.QueryMatchResult( "foobaaaR", true ).IsSubsequence() );
|
||||
}
|
||||
|
||||
} // namespace YouCompleteMe
|
||||
|
@ -64,6 +64,14 @@ TEST( IdentifierCompleterTest, ManyCandidateSimple ) {
|
||||
"foobartest" ) ) );
|
||||
}
|
||||
|
||||
TEST( IdentifierCompleterTest, SmartCaseFiltering ) {
|
||||
EXPECT_THAT( IdentifierCompleter(
|
||||
StringVector(
|
||||
"fooBar",
|
||||
"fooBaR" ) ).CandidatesForQuery( "fBr" ),
|
||||
ElementsAre( "fooBar" ) );
|
||||
}
|
||||
|
||||
TEST( IdentifierCompleterTest, FirstCharSameAsQueryWins ) {
|
||||
EXPECT_THAT( IdentifierCompleter(
|
||||
StringVector(
|
||||
@ -119,13 +127,6 @@ TEST( IdentifierCompleterTest, RatioUtilizationTieBreak ) {
|
||||
ElementsAre( "acaaCaaFooGxx",
|
||||
"aCaafoog" ) );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter(
|
||||
StringVector(
|
||||
"acaaCaaFooGxx",
|
||||
"aCaafoog" ) ).CandidatesForQuery( "caaFoo" ),
|
||||
ElementsAre( "acaaCaaFooGxx",
|
||||
"aCaafoog" ) );
|
||||
|
||||
EXPECT_THAT( IdentifierCompleter(
|
||||
StringVector(
|
||||
"FooBarQux",
|
||||
|
Loading…
Reference in New Issue
Block a user