ClangCompleter now returs extra data

This data is used to show more information about the completions in the
completion menu.
This commit is contained in:
Strahinja Val Markovic 2012-07-19 21:17:39 -07:00
parent e56080ea56
commit 44b671c2c0
13 changed files with 317 additions and 63 deletions

View File

@ -217,7 +217,7 @@ EOF
let l:results = [] let l:results = []
py << EOF py << EOF
results = clangcomp.CandidatesFromStoredRequest() results = clangcomp.CandidatesFromStoredRequest()
result_string = ycm.StringVectorToString( results ) result_string = ycm.CompletionDataVectorToString( results )
if results: if results:
vim.command( 'let l:results = ' + result_string ) vim.command( 'let l:results = ' + result_string )

View File

@ -17,6 +17,7 @@
#include "CandidateRepository.h" #include "CandidateRepository.h"
#include "Candidate.h" #include "Candidate.h"
#include "CompletionData.h"
#include "standard.h" #include "standard.h"
#include "Utils.h" #include "Utils.h"
@ -43,7 +44,7 @@ CandidateRepository& CandidateRepository::Instance()
std::vector< const Candidate* > CandidateRepository::GetCandidatesForStrings( std::vector< const Candidate* > CandidateRepository::GetCandidatesForStrings(
const std::vector< std::string > &strings) const std::vector< std::string > &strings )
{ {
std::vector< const Candidate* > candidates; std::vector< const Candidate* > candidates;
candidates.reserve( strings.size() ); candidates.reserve( strings.size() );
@ -67,6 +68,31 @@ std::vector< const Candidate* > CandidateRepository::GetCandidatesForStrings(
} }
std::vector< const Candidate* > CandidateRepository::GetCandidatesForStrings(
const std::vector< CompletionData > &datas )
{
std::vector< const Candidate* > candidates;
candidates.reserve( datas.size() );
{
boost::lock_guard< boost::mutex > locker( holder_mutex_ );
foreach ( const CompletionData &data, datas )
{
const Candidate *&candidate = GetValueElseInsert( candidate_holder_,
data.original_string_,
NULL );
if ( !candidate )
candidate = new Candidate( data.original_string_ );
candidates.push_back( candidate );
}
}
return candidates;
}
CandidateRepository::~CandidateRepository() CandidateRepository::~CandidateRepository()
{ {
foreach ( const CandidateHolder::value_type &pair, foreach ( const CandidateHolder::value_type &pair,

View File

@ -29,6 +29,7 @@ namespace YouCompleteMe
{ {
class Candidate; class Candidate;
struct CompletionData;
typedef boost::unordered_map< std::string, const Candidate* > typedef boost::unordered_map< std::string, const Candidate* >
CandidateHolder; CandidateHolder;
@ -41,6 +42,9 @@ public:
std::vector< const Candidate* > GetCandidatesForStrings( std::vector< const Candidate* > GetCandidatesForStrings(
const std::vector< std::string > &strings ); const std::vector< std::string > &strings );
std::vector< const Candidate* > GetCandidatesForStrings(
const std::vector< CompletionData > &datas );
private: private:
CandidateRepository() {}; CandidateRepository() {};
~CandidateRepository(); ~CandidateRepository();

View File

@ -17,6 +17,7 @@
#include "ClangCompleter.h" #include "ClangCompleter.h"
#include "Candidate.h" #include "Candidate.h"
#include "CompletionData.h"
#include "standard.h" #include "standard.h"
#include "CandidateRepository.h" #include "CandidateRepository.h"
#include "ConcurrentLatestValue.h" #include "ConcurrentLatestValue.h"
@ -35,12 +36,30 @@ using boost::thread;
namespace YouCompleteMe namespace YouCompleteMe
{ {
typedef boost::function< std::vector< CompletionData >() >
FunctionReturnsCompletionDataVector;
extern const unsigned int MAX_ASYNC_THREADS; extern const unsigned int MAX_ASYNC_THREADS;
extern const unsigned int MIN_ASYNC_THREADS; extern const unsigned int MIN_ASYNC_THREADS;
namespace namespace
{ {
struct CompletionDataAndResult
{
CompletionDataAndResult( const CompletionData *completion_data,
const Result &result )
: completion_data_( completion_data ), result_( result ) {}
bool operator< ( const CompletionDataAndResult &other ) const
{
return result_ < other.result_;
}
const CompletionData *completion_data_;
Result result_;
};
std::vector< CXUnsavedFile > ToCXUnsavedFiles( std::vector< CXUnsavedFile > ToCXUnsavedFiles(
const std::vector< UnsavedFile > &unsaved_files ) const std::vector< UnsavedFile > &unsaved_files )
@ -83,31 +102,110 @@ bool CompletionStringAvailable( CXCompletionString completion_string )
} }
std::vector< std::string > ToStringVector( CXCodeCompleteResults *results ) bool IsChunkKindForExtraMenuInfo( CXCompletionChunkKind kind )
{ {
std::vector< std::string > completions; return
kind == CXCompletionChunk_Optional ||
kind == CXCompletionChunk_TypedText ||
kind == CXCompletionChunk_Placeholder ||
kind == CXCompletionChunk_LeftParen ||
kind == CXCompletionChunk_RightParen ||
kind == CXCompletionChunk_RightBracket ||
kind == CXCompletionChunk_LeftBracket ||
kind == CXCompletionChunk_LeftBrace ||
kind == CXCompletionChunk_RightBrace ||
kind == CXCompletionChunk_RightAngle ||
kind == CXCompletionChunk_LeftAngle ||
kind == CXCompletionChunk_Comma ||
kind == CXCompletionChunk_ResultType ||
kind == CXCompletionChunk_Colon ||
kind == CXCompletionChunk_SemiColon ||
kind == CXCompletionChunk_Equal ||
kind == CXCompletionChunk_HorizontalSpace;
}
char CursorKindToVimKind( CXCursorKind kind )
{
switch ( kind )
{
case CXCursor_UnexposedDecl:
case CXCursor_StructDecl:
case CXCursor_UnionDecl:
case CXCursor_ClassDecl:
case CXCursor_EnumDecl:
case CXCursor_TypedefDecl:
return 't';
case CXCursor_FieldDecl:
return 'm';
case CXCursor_FunctionDecl:
case CXCursor_CXXMethod:
case CXCursor_FunctionTemplate:
return 'f';
case CXCursor_VarDecl:
return 'v';
case CXCursor_MacroDefinition:
return 'd';
default:
return 'u'; // for 'unknown', 'unsupported'... whatever you like
}
}
CompletionData CompletionResultToCompletionData(
const CXCompletionResult &completion_result )
{
CompletionData data;
CXCompletionString completion_string = completion_result.CompletionString;
uint num_chunks = clang_getNumCompletionChunks( completion_string );
for ( uint j = 0; j < num_chunks; ++j )
{
CXCompletionChunkKind kind = clang_getCompletionChunkKind(
completion_string, j );
if ( IsChunkKindForExtraMenuInfo( kind ) )
{
data.extra_menu_info_.append( ChunkToString( completion_string, j ) );
// by default, there's no space after the return type
if ( kind == CXCompletionChunk_ResultType )
data.extra_menu_info_.append( " " );
}
if ( kind == CXCompletionChunk_TypedText )
data.original_string_ = ChunkToString( completion_string, j );
if ( kind == CXCompletionChunk_Informative )
data.detailed_info_ = ChunkToString( completion_string, j );
}
data.kind_ = CursorKindToVimKind( completion_result.CursorKind );
return data;
}
std::vector< CompletionData > ToCompletionDataVector(
CXCodeCompleteResults *results )
{
std::vector< CompletionData > completions;
completions.reserve( results->NumResults ); completions.reserve( results->NumResults );
for ( uint i = 0; i < results->NumResults; ++i ) for ( uint i = 0; i < results->NumResults; ++i )
{ {
CXCompletionString completion_string = CXCompletionResult completion_result = results->Results[ i ];
results->Results[ i ].CompletionString;
if ( !CompletionStringAvailable( completion_string ) ) if ( !CompletionStringAvailable( completion_result.CompletionString ) )
continue; continue;
uint num_chunks = clang_getNumCompletionChunks( completion_string ); completions.push_back(
for ( uint j = 0; j < num_chunks; ++j ) CompletionResultToCompletionData( completion_result ) );
{
CXCompletionChunkKind kind = clang_getCompletionChunkKind(
completion_string, j );
if ( kind == CXCompletionChunk_TypedText )
{
completions.push_back( ChunkToString( completion_string, j ) );
break;
}
}
} }
return completions; return completions;
@ -189,7 +287,7 @@ void ClangCompleter::UpdateTranslationUnit(
} }
std::vector< std::string > ClangCompleter::CandidatesForLocationInFile( std::vector< CompletionData > ClangCompleter::CandidatesForLocationInFile(
const std::string &filename, const std::string &filename,
int line, int line,
int column, int column,
@ -217,13 +315,14 @@ std::vector< std::string > ClangCompleter::CandidatesForLocationInFile(
cxunsaved_files.size(), cxunsaved_files.size(),
clang_defaultCodeCompleteOptions()); clang_defaultCodeCompleteOptions());
std::vector< std::string > candidates = ToStringVector( results ); std::vector< CompletionData > candidates = ToCompletionDataVector( results );
clang_disposeCodeCompleteResults( results ); clang_disposeCodeCompleteResults( results );
return candidates; return candidates;
} }
Future< AsyncResults > ClangCompleter::CandidatesForQueryAndLocationInFileAsync( Future< AsyncCompletions >
ClangCompleter::CandidatesForQueryAndLocationInFileAsync(
const std::string &query, const std::string &query,
const std::string &filename, const std::string &filename,
int line, int line,
@ -232,7 +331,7 @@ Future< AsyncResults > ClangCompleter::CandidatesForQueryAndLocationInFileAsync(
{ {
// TODO: throw exception when threading is not enabled and this is called // TODO: throw exception when threading is not enabled and this is called
if ( !threading_enabled_ ) if ( !threading_enabled_ )
return Future< AsyncResults >(); return Future< AsyncCompletions >();
if ( query.empty() ) if ( query.empty() )
{ {
@ -251,23 +350,24 @@ Future< AsyncResults > ClangCompleter::CandidatesForQueryAndLocationInFileAsync(
// case the clang task finishes (and therefore notifies a sorting thread to // case the clang task finishes (and therefore notifies a sorting thread to
// consume a sorting task) before the sorting task is set // consume a sorting task) before the sorting task is set
FunctionReturnsStringVector sort_candidates_for_query_functor = FunctionReturnsCompletionDataVector sort_candidates_for_query_functor =
bind( &ClangCompleter::SortCandidatesForQuery, bind( &ClangCompleter::SortCandidatesForQuery,
boost::ref( *this ), boost::ref( *this ),
query, query,
boost::cref( latest_clang_results_ ) ); boost::cref( latest_clang_results_ ) );
shared_ptr< packaged_task< AsyncResults > > task = shared_ptr< packaged_task< AsyncCompletions > > task =
make_shared< packaged_task< AsyncResults > >( make_shared< packaged_task< AsyncCompletions > >(
bind( ReturnValueAsShared< std::vector< std::string > >, bind( ReturnValueAsShared< std::vector< CompletionData > >,
sort_candidates_for_query_functor ) ); sort_candidates_for_query_functor ) );
unique_future< AsyncResults > future = task->get_future(); unique_future< AsyncCompletions > future = task->get_future();
sorting_task_.Set( task ); sorting_task_.Set( task );
if ( query.empty() ) if ( query.empty() )
{ {
FunctionReturnsStringVector candidates_for_location_in_file_functor = FunctionReturnsCompletionDataVector
candidates_for_location_in_file_functor =
bind( &ClangCompleter::CandidatesForLocationInFile, bind( &ClangCompleter::CandidatesForLocationInFile,
boost::ref( *this ), boost::ref( *this ),
filename, filename,
@ -275,15 +375,15 @@ Future< AsyncResults > ClangCompleter::CandidatesForQueryAndLocationInFileAsync(
column, column,
unsaved_files ); unsaved_files );
shared_ptr< packaged_task< AsyncResults > > task = shared_ptr< packaged_task< AsyncCompletions > > task =
make_shared< packaged_task< AsyncResults > >( make_shared< packaged_task< AsyncCompletions > >(
bind( ReturnValueAsShared< std::vector< std::string > >, bind( ReturnValueAsShared< std::vector< CompletionData > >,
candidates_for_location_in_file_functor ) ); candidates_for_location_in_file_functor ) );
clang_task_.Set( task ); clang_task_.Set( task );
} }
return Future< AsyncResults >( move( future ) ); return Future< AsyncCompletions >( boost::move( future ) );
} }
@ -344,39 +444,42 @@ CXTranslationUnit ClangCompleter::GetTranslationUnitForFile(
} }
std::vector< std::string > ClangCompleter::SortCandidatesForQuery( std::vector< CompletionData > ClangCompleter::SortCandidatesForQuery(
const std::string &query, const std::string &query,
const std::vector< std::string > &candidates ) const std::vector< CompletionData > &completion_datas )
{ {
Bitset query_bitset = LetterBitsetFromString( query ); Bitset query_bitset = LetterBitsetFromString( query );
std::vector< const Candidate* > repository_candidates = std::vector< const Candidate* > repository_candidates =
candidate_repository_.GetCandidatesForStrings( candidates ); candidate_repository_.GetCandidatesForStrings( completion_datas );
std::vector< Result > results; std::vector< CompletionDataAndResult > data_and_results;
// This loop needs to be a separate function for ( uint i = 0; i < repository_candidates.size(); ++i )
foreach ( const Candidate* candidate, repository_candidates )
{ {
const Candidate* candidate = repository_candidates[ i ];
if ( !candidate->MatchesQueryBitset( query_bitset ) ) if ( !candidate->MatchesQueryBitset( query_bitset ) )
continue; continue;
Result result = candidate->QueryMatchResult( query ); Result result = candidate->QueryMatchResult( query );
if ( result.IsSubsequence() ) if ( result.IsSubsequence() )
results.push_back( result ); {
CompletionDataAndResult data_and_result( &completion_datas[ i ], result );
data_and_results.push_back( data_and_result );
}
} }
std::sort( results.begin(), results.end() ); std::sort( data_and_results.begin(), data_and_results.end() );
std::vector< std::string > sorted_candidates; std::vector< CompletionData > sorted_completion_datas;
sorted_candidates.reserve( results.size() ); sorted_completion_datas.reserve( data_and_results.size() );
foreach ( const Result& result, results ) foreach ( const CompletionDataAndResult& data_and_result, data_and_results )
{ {
sorted_candidates.push_back( *result.Text() ); sorted_completion_datas.push_back( *data_and_result.completion_data_ );
} }
return sorted_candidates; return sorted_completion_datas;
} }
@ -404,9 +507,9 @@ void ClangCompleter::ClangThreadMain( LatestTask &clang_task )
{ {
while ( true ) while ( true )
{ {
shared_ptr< packaged_task< AsyncResults > > task = clang_task.Get(); shared_ptr< packaged_task< AsyncCompletions > > task = clang_task.Get();
( *task )(); ( *task )();
unique_future< AsyncResults > future = task->get_future(); unique_future< AsyncCompletions > future = task->get_future();
{ {
boost::unique_lock< boost::shared_mutex > writer_lock( boost::unique_lock< boost::shared_mutex > writer_lock(
@ -439,7 +542,7 @@ void ClangCompleter::SortingThreadMain( LatestTask &sorting_task )
} }
} }
shared_ptr< packaged_task< AsyncResults > > task = sorting_task.Get(); shared_ptr< packaged_task< AsyncCompletions > > task = sorting_task.Get();
{ {
boost::shared_lock< boost::shared_mutex > reader_lock( boost::shared_lock< boost::shared_mutex > reader_lock(

View File

@ -33,7 +33,9 @@ namespace YouCompleteMe
{ {
class CandidateRepository; class CandidateRepository;
struct CompletionData;
// TODO: put this in a separated header file
struct UnsavedFile struct UnsavedFile
{ {
UnsavedFile() : filename_( NULL ), contents_( NULL ), length_( 0 ) {} UnsavedFile() : filename_( NULL ), contents_( NULL ), length_( 0 ) {}
@ -55,6 +57,7 @@ struct UnsavedFile
} }
}; };
typedef boost::shared_ptr< std::vector< CompletionData > > AsyncCompletions;
typedef boost::unordered_map< std::string, std::vector< std::string > > typedef boost::unordered_map< std::string, std::vector< std::string > >
FlagsForFile; FlagsForFile;
@ -79,13 +82,13 @@ public:
void UpdateTranslationUnit( const std::string &filename, void UpdateTranslationUnit( const std::string &filename,
const std::vector< UnsavedFile > &unsaved_files ); const std::vector< UnsavedFile > &unsaved_files );
std::vector< std::string > CandidatesForLocationInFile( std::vector< CompletionData > CandidatesForLocationInFile(
const std::string &filename, const std::string &filename,
int line, int line,
int column, int column,
const std::vector< UnsavedFile > &unsaved_files ); const std::vector< UnsavedFile > &unsaved_files );
Future< AsyncResults > CandidatesForQueryAndLocationInFileAsync( Future< AsyncCompletions > CandidatesForQueryAndLocationInFileAsync(
const std::string &query, const std::string &query,
const std::string &filename, const std::string &filename,
int line, int line,
@ -95,7 +98,7 @@ public:
private: private:
typedef ConcurrentLatestValue< typedef ConcurrentLatestValue<
boost::shared_ptr< boost::shared_ptr<
boost::packaged_task< AsyncResults > > > LatestTask; boost::packaged_task< AsyncCompletions > > > LatestTask;
// caller takes ownership of translation unit // caller takes ownership of translation unit
CXTranslationUnit CreateTranslationUnit( CXTranslationUnit CreateTranslationUnit(
@ -109,9 +112,9 @@ private:
const std::string &filename, const std::string &filename,
const std::vector< UnsavedFile > &unsaved_files ); const std::vector< UnsavedFile > &unsaved_files );
std::vector< std::string > SortCandidatesForQuery( std::vector< CompletionData > SortCandidatesForQuery(
const std::string &query, const std::string &query,
const std::vector< std::string > &candidates ); const std::vector< CompletionData > &completion_datas );
void InitThreads(); void InitThreads();
@ -145,7 +148,7 @@ private:
boost::mutex clang_data_ready_mutex_; boost::mutex clang_data_ready_mutex_;
boost::condition_variable clang_data_ready_condition_variable_; boost::condition_variable clang_data_ready_condition_variable_;
std::vector< std::string > latest_clang_results_; std::vector< CompletionData > latest_clang_results_;
boost::shared_mutex latest_clang_results_shared_mutex_; boost::shared_mutex latest_clang_results_shared_mutex_;
// Unfortunately clang is not thread-safe so we can only ever use one thread // Unfortunately clang is not thread-safe so we can only ever use one thread

69
cpp/ycm/CompletionData.h Normal file
View File

@ -0,0 +1,69 @@
// Copyright (C) 2011, 2012 Strahinja Val Markovic <val@markovic.io>
//
// This file is part of YouCompleteMe.
//
// YouCompleteMe is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// YouCompleteMe is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
#ifndef COMPLETIONDATA_H_2JCTF1NU
#define COMPLETIONDATA_H_2JCTF1NU
namespace YouCompleteMe
{
struct CompletionData
{
// What should actually be inserted into the buffer. For functions, this
// should be the original string plus "("
std::string TextToInsertInBuffer()
{
if ( kind_ == 'f' )
return original_string_ + "(";
return original_string_;
}
bool operator== ( const CompletionData &other ) const
{
return
kind_ == other.kind_ &&
original_string_ == other.original_string_ &&
extra_menu_info_ == other.extra_menu_info_;
// detailed_info_ doesn't matter
}
// This is used to show extra information in vim's preview window
std::string detailed_info_;
// This is extra info shown in the pop-up completion menu, after the
// completion text and the kind
std::string extra_menu_info_;
// Vim's completion string "kind"
// 'v' -> variable
// 'f' -> function or method
// 'm' -> member of struct/class (data member)
// 't' -> typedef (but we're going to use it for types in general)
// 'd' -> #define or macro
char kind_;
// The original, raw completion string. For a function like "int foo(int x)",
// the original string is "foo". This corresponds to clang's TypedText chunk
// of the completion string.
std::string original_string_;
};
} // namespace YouCompleteMe
#endif /* end of include guard: COMPLETIONDATA_H_2JCTF1NU */

View File

@ -20,7 +20,6 @@
#include <boost/thread.hpp> #include <boost/thread.hpp>
#include <boost/make_shared.hpp> #include <boost/make_shared.hpp>
#include <boost/python.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
#include <boost/function.hpp> #include <boost/function.hpp>
@ -30,12 +29,6 @@ namespace YouCompleteMe
class Result; class Result;
template< typename T > class ConcurrentLatestValue; template< typename T > class ConcurrentLatestValue;
typedef boost::python::list Pylist;
typedef boost::shared_ptr< std::vector< std::string > > AsyncResults;
typedef boost::function< std::vector< std::string >() >
FunctionReturnsStringVector;
template< typename T > template< typename T >
boost::shared_ptr< T > ReturnValueAsShared( boost::shared_ptr< T > ReturnValueAsShared(
boost::function< T() > func ) boost::function< T() > func )

View File

@ -158,7 +158,7 @@ Future< AsyncResults > IdentifierCompleter::CandidatesForQueryAndTypeAsync(
unique_future< AsyncResults > future = task->get_future(); unique_future< AsyncResults > future = task->get_future();
latest_task_.Set( task ); latest_task_.Set( task );
return Future< AsyncResults >( move( future ) ); return Future< AsyncResults >( boost::move( future ) );
} }

View File

@ -35,6 +35,13 @@ namespace YouCompleteMe
class Candidate; class Candidate;
class CandidateRepository; class CandidateRepository;
typedef boost::shared_ptr< std::vector< std::string > > AsyncResults;
// TODO: cpp?
typedef boost::function< std::vector< std::string >() >
FunctionReturnsStringVector;
// TODO: move to private // TODO: move to private
// filepath -> *( *candidate ) // filepath -> *( *candidate )
typedef boost::unordered_map< std::string, typedef boost::unordered_map< std::string,

View File

@ -69,6 +69,20 @@ int NumWordBoundaryCharMatches( const std::string &query,
} // unnamed namespace } // unnamed namespace
Result::Result()
:
query_is_empty_( true ),
is_subsequence_( false ),
first_char_same_in_query_and_text_( false ),
ratio_of_word_boundary_chars_in_query_( 0 ),
word_boundary_char_utilization_( 0 ),
query_is_candidate_prefix_( false ),
text_is_lowercase_( false ),
char_match_index_sum_( 0 ),
text_( NULL )
{
}
Result::Result( bool is_subsequence ) Result::Result( bool is_subsequence )
: :
@ -84,6 +98,7 @@ Result::Result( bool is_subsequence )
{ {
} }
Result::Result( bool is_subsequence, Result::Result( bool is_subsequence,
const std::string *text, const std::string *text,
bool text_is_lowercase, bool text_is_lowercase,

View File

@ -26,6 +26,7 @@ namespace YouCompleteMe
class Result class Result
{ {
public: public:
Result();
explicit Result( bool is_subsequence ); explicit Result( bool is_subsequence );
Result( bool is_subsequence, Result( bool is_subsequence,

View File

@ -18,6 +18,7 @@
#include "IdentifierCompleter.h" #include "IdentifierCompleter.h"
#include "ClangCompleter.h" #include "ClangCompleter.h"
#include "Future.h" #include "Future.h"
#include "CompletionData.h"
#include <boost/python.hpp> #include <boost/python.hpp>
#include <boost/utility.hpp> #include <boost/utility.hpp>
@ -28,14 +29,31 @@ BOOST_PYTHON_MODULE(indexer)
using namespace boost::python; using namespace boost::python;
using namespace YouCompleteMe; using namespace YouCompleteMe;
// TODO: rename these *Vec classes to *Vector; don't forget the python file
class_< std::vector< std::string >, class_< std::vector< std::string >,
boost::shared_ptr< std::vector< std::string > > >( "StringVec" ) boost::shared_ptr< std::vector< std::string > > >( "StringVec" )
.def( vector_indexing_suite< std::vector< std::string > >() ); .def( vector_indexing_suite< std::vector< std::string > >() );
class_< CompletionData >( "CompletionData" )
.def( "TextToInsertInBuffer", &CompletionData::TextToInsertInBuffer )
.def_readonly( "detailed_info_", &CompletionData::detailed_info_ )
.def_readonly( "extra_menu_info_", &CompletionData::extra_menu_info_ )
.def_readonly( "kind_", &CompletionData::kind_ )
.def_readonly( "original_string_", &CompletionData::original_string_ );
class_< std::vector< CompletionData >,
boost::shared_ptr< std::vector< CompletionData > > >(
"CompletionVec" )
.def( vector_indexing_suite< std::vector< CompletionData > >() );
class_< Future< AsyncResults > >( "Future" ) class_< Future< AsyncResults > >( "Future" )
.def( "ResultsReady", &Future< AsyncResults >::ResultsReady ) .def( "ResultsReady", &Future< AsyncResults >::ResultsReady )
.def( "GetResults", &Future< AsyncResults >::GetResults ); .def( "GetResults", &Future< AsyncResults >::GetResults );
class_< Future< AsyncCompletions > >( "Future" )
.def( "ResultsReady", &Future< AsyncCompletions >::ResultsReady )
.def( "GetResults", &Future< AsyncCompletions >::GetResults );
class_< IdentifierCompleter, boost::noncopyable >( "IdentifierCompleter" ) class_< IdentifierCompleter, boost::noncopyable >( "IdentifierCompleter" )
.def( "EnableThreading", &IdentifierCompleter::EnableThreading ) .def( "EnableThreading", &IdentifierCompleter::EnableThreading )
.def( "AddCandidatesToDatabase", .def( "AddCandidatesToDatabase",

View File

@ -151,6 +151,21 @@ def StringVectorToString( stringvec ):
return ''.join( result ) return ''.join( result )
def CompletionDataToDict( completion_data ):
# see :h complete-items for a description of the dictionary fields
return {
'word' : completion_data.TextToInsertInBuffer(),
'abbr' : completion_data.original_string_,
'menu' : completion_data.extra_menu_info_,
'kind' : completion_data.kind_,
# TODO: add detailed_info_ as 'info'
}
def CompletionDataVectorToString( datavec ):
return str( [ CompletionDataToDict( x ) for x in datavec ] )
def CurrentColumn(): def CurrentColumn():
"""Do NOT access the CurrentColumn in vim.current.line. It doesn't exist yet. """Do NOT access the CurrentColumn in vim.current.line. It doesn't exist yet.
Only the chars before the current column exist in vim.current.line.""" Only the chars before the current column exist in vim.current.line."""