PythonSupport.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. // Copyright (C) 2011, 2012, 2013 Google Inc.
  2. //
  3. // This file is part of YouCompleteMe.
  4. //
  5. // YouCompleteMe is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // YouCompleteMe is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with YouCompleteMe. If not, see <http://www.gnu.org/licenses/>.
  17. #include "PythonSupport.h"
  18. #include "standard.h"
  19. #include "Result.h"
  20. #include "Candidate.h"
  21. #include "CandidateRepository.h"
  22. #include "ReleaseGil.h"
  23. #include <boost/algorithm/string.hpp>
  24. #include <boost/algorithm/cxx11/any_of.hpp>
  25. #include <vector>
  26. using boost::algorithm::any_of;
  27. using boost::algorithm::is_upper;
  28. using boost::python::len;
  29. using boost::python::str;
  30. using boost::python::extract;
  31. using boost::python::object;
  32. typedef boost::python::list pylist;
  33. namespace YouCompleteMe {
  34. namespace {
  35. std::string GetUtf8String( const boost::python::object &string_or_unicode ) {
  36. extract< std::string > to_string( string_or_unicode );
  37. if ( to_string.check() )
  38. return to_string();
  39. return extract< std::string >( str( string_or_unicode ).encode( "utf8" ) );
  40. }
  41. std::vector< const Candidate * > CandidatesFromObjectList(
  42. const pylist &candidates,
  43. const std::string &candidate_property ) {
  44. int num_candidates = len( candidates );
  45. std::vector< std::string > candidate_strings;
  46. candidate_strings.reserve( num_candidates );
  47. for ( int i = 0; i < num_candidates; ++i ) {
  48. if ( candidate_property.empty() ) {
  49. candidate_strings.push_back( GetUtf8String( candidates[ i ] ) );
  50. } else {
  51. object holder = extract< object >( candidates[ i ] );
  52. candidate_strings.push_back( GetUtf8String(
  53. holder[ candidate_property.c_str() ] ) );
  54. }
  55. }
  56. return CandidateRepository::Instance().GetCandidatesForStrings(
  57. candidate_strings );
  58. }
  59. } // unnamed namespace
  60. boost::python::list FilterAndSortCandidates(
  61. const boost::python::list &candidates,
  62. const std::string &candidate_property,
  63. const std::string &query ) {
  64. pylist filtered_candidates;
  65. if ( query.empty() ) {
  66. return candidates;
  67. }
  68. int num_candidates = len( candidates );
  69. std::vector< const Candidate * > repository_candidates =
  70. CandidatesFromObjectList( candidates, candidate_property );
  71. std::vector< ResultAnd< int > > object_and_results;
  72. {
  73. ReleaseGil unlock;
  74. Bitset query_bitset = LetterBitsetFromString( query );
  75. bool query_has_uppercase_letters = any_of( query, is_upper() );
  76. for ( int i = 0; i < num_candidates; ++i ) {
  77. const Candidate *candidate = repository_candidates[ i ];
  78. if ( !candidate->MatchesQueryBitset( query_bitset ) )
  79. continue;
  80. Result result = candidate->QueryMatchResult( query,
  81. query_has_uppercase_letters );
  82. if ( result.IsSubsequence() ) {
  83. ResultAnd< int > object_and_result( i, result );
  84. object_and_results.push_back( boost::move( object_and_result ) );
  85. }
  86. }
  87. std::sort( object_and_results.begin(), object_and_results.end() );
  88. }
  89. foreach ( const ResultAnd< int > &object_and_result,
  90. object_and_results ) {
  91. filtered_candidates.append( candidates[ object_and_result.extra_object_ ] );
  92. }
  93. return filtered_candidates;
  94. }
  95. } // namespace YouCompleteMe