diff --git a/irony-completion.el b/irony-completion.el index 68e317b2..9e3a384f 100644 --- a/irony-completion.el +++ b/irony-completion.el @@ -200,7 +200,10 @@ displayed when a derived class overrides virtual methods." (cl-case style (case-insensitive "case-insensitive") (smart-case "smart-case") - (t "exact")))) + (t "exact")) + (cl-case irony-candidates-clang-sorting + (alphabetical "alphabetical") + (t "alphabetical-clang")))) :update irony--server-query-update) (defun irony--candidates-task (&optional buffer pos prefix style) diff --git a/irony.el b/irony.el index 67dda779..c8fa7463 100644 --- a/irony.el +++ b/irony.el @@ -180,6 +180,17 @@ Larger values can improve performances on large buffers. If non-nil, `w32-pipe-buffer-size' will be let-bound to this value during the creation of the irony-server process.") +(defcustom irony-candidates-clang-sorting nil + "Determine the sorting strategy for completion candidates list + +If set to nil, clang priority will be used on top of alphabetical sorting when completing to propose context-aware and more-likely completions. + +If set to `alphabetical', clang priority will be ignored and candidates will be sorted alphabetically only." + :type '(choice + (const :tag "Alphabetical + clang priority" nil) + (const :tag "Alphabetical only" alphabetical))) + + ;; ;; Public/API variables diff --git a/server/src/Command.cpp b/server/src/Command.cpp index a3c35c87..e987c2d0 100644 --- a/server/src/Command.cpp +++ b/server/src/Command.cpp @@ -221,6 +221,7 @@ Command *CommandParser::parse(const std::vector &argv) { case Command::Candidates: positionalArgs.push_back(StringConverter(&command_.prefix)); positionalArgs.push_back(PrefixMatchStyleConverter(&command_.style)); + positionalArgs.push_back(StringConverter(&command_.sorting)); break; case Command::CompletionDiagnostics: case Command::Diagnostics: diff --git a/server/src/Command.h b/server/src/Command.h index 9f36aa45..0104df1a 100644 --- a/server/src/Command.h +++ b/server/src/Command.h @@ -50,6 +50,7 @@ struct Command { std::string unsavedFile; std::string dir; std::string prefix; + std::string sorting; PrefixMatchStyle style; unsigned line; unsigned column; diff --git a/server/src/Irony.cpp b/server/src/Irony.cpp index fcb877c2..568466d3 100644 --- a/server/src/Irony.cpp +++ b/server/src/Irony.cpp @@ -19,9 +19,23 @@ #include #include #include +#include +#include namespace { +struct CompletionCandidate +{ + unsigned int priority; + std::string str; + + CompletionCandidate(unsigned int priority, const std::string& str) : priority(priority), str(str) {} + + bool operator < (const CompletionCandidate& candidate) const { + return (priority < candidate.priority); + } +}; + std::string cxStringToStd(CXString cxString) { std::string stdStr; @@ -359,7 +373,7 @@ void Irony::completionDiagnostics() const { std::cout << ")\n"; } -void Irony::candidates(const std::string &prefix, PrefixMatchStyle style) const { +void Irony::candidates(const std::string &prefix, PrefixMatchStyle style, const std::string &sorting) const { if (activeCompletionResults_ == nullptr) { std::cout << "nil\n"; return; @@ -375,6 +389,7 @@ void Irony::candidates(const std::string &prefix, PrefixMatchStyle style) const std::string typedtext, brief, resultType, prototype, postCompCar, available; std::vector postCompCdr; + std::vector candidates; for (unsigned i = 0; i < completions->NumResults; ++i) { CXCompletionResult candidate = completions->Results[i]; @@ -508,19 +523,35 @@ void Irony::candidates(const std::string &prefix, PrefixMatchStyle style) const clang_getCompletionBriefComment(candidate.CompletionString)); #endif + std::stringstream candidateSS; + // see irony-completion.el#irony-completion-candidates - std::cout << '(' << support::quoted(typedtext) - << ' ' << priority - << ' ' << support::quoted(resultType) - << ' ' << support::quoted(brief) - << ' ' << support::quoted(prototype) - << ' ' << annotationStart - << " (" << support::quoted(postCompCar); + candidateSS << '(' << support::quoted(typedtext) + << ' ' << priority + << ' ' << support::quoted(resultType) + << ' ' << support::quoted(brief) + << ' ' << support::quoted(prototype) + << ' ' << annotationStart + << " (" << support::quoted(postCompCar); for (unsigned index : postCompCdr) - std::cout << ' ' << index; - std::cout << ")" - << ' ' << available - << ")\n"; + candidateSS << ' ' << index; + candidateSS << ")" + << ' ' << available + << ")\n"; + + // Add candidate to candidate list + candidates.push_back(CompletionCandidate(priority, candidateSS.str())); + } + + if (sorting == "alphabetical-clang") { + // Sort candidates list + // ASC - Smaller values indicate higher-priority (more likely) completions. + std::sort(candidates.begin(), candidates.end()); + } + + // Output sorted list + for (auto &candidate : candidates) { + std::cout << candidate.str; } std::cout << ")\n"; diff --git a/server/src/Irony.h b/server/src/Irony.h index 1a23bd05..3fa03be3 100644 --- a/server/src/Irony.h +++ b/server/src/Irony.h @@ -102,7 +102,7 @@ class Irony { /// Get all the completion candidates. /// /// \pre complete() was called. - void candidates(const std::string &prefix, PrefixMatchStyle style) const; + void candidates(const std::string &prefix, PrefixMatchStyle style, const std::string &sorting) const; /// Get the diagnostics produced by the last \c complete(). /// diff --git a/server/src/main.cpp b/server/src/main.cpp index 77975286..6103821a 100644 --- a/server/src/main.cpp +++ b/server/src/main.cpp @@ -181,7 +181,7 @@ int main(int ac, const char *av[]) { break; case Command::Candidates: - irony.candidates(c->prefix, c->style); + irony.candidates(c->prefix, c->style, c->sorting); break; case Command::CompletionDiagnostics: