home/src/insert_completer.hh

123 lines
3.1 KiB
C++
Raw Normal View History

#ifndef insert_completer_hh_INCLUDED
#define insert_completer_hh_INCLUDED
#include "option_manager.hh"
2017-03-16 10:57:39 +01:00
#include "option.hh"
#include "display_buffer.hh"
#include "vector.hh"
#include "optional.hh"
namespace Kakoune
{
struct SelectionList;
struct Key;
class FaceRegistry;
struct InsertCompleterDesc
{
enum Mode
{
Word,
Option,
Filename,
Line
};
bool operator==(const InsertCompleterDesc& other) const
2014-10-28 21:01:55 +01:00
{ return mode == other.mode and param == other.param; }
bool operator!=(const InsertCompleterDesc& other) const
{ return not (*this == other); }
Mode mode;
Optional<String> param;
};
2015-01-12 14:24:30 +01:00
using InsertCompleterDescList = Vector<InsertCompleterDesc, MemoryDomain::Options>;
String option_to_string(const InsertCompleterDesc& opt);
InsertCompleterDesc option_from_string(Meta::Type<InsertCompleterDesc>, StringView str);
inline StringView option_type_name(Meta::Type<InsertCompleterDesc>)
2016-08-06 10:05:50 +02:00
{
return "completer";
}
2016-08-06 10:05:50 +02:00
using CompletionCandidate = std::tuple<String, String, String>;
using CompletionList = PrefixedList<String, CompletionCandidate>;
inline StringView option_type_name(Meta::Type<CompletionList>)
2016-08-06 10:05:50 +02:00
{
return "completions";
}
2016-08-06 10:05:50 +02:00
struct InsertCompletion
{
struct Candidate
{
String completion;
String on_select;
DisplayLine menu_entry;
bool operator==(const Candidate& other) const { return completion == other.completion; }
bool operator<(const Candidate& other) const { return completion < other.completion; }
};
using CandidateList = Vector<Candidate, MemoryDomain::Completion>;
CandidateList candidates;
BufferCoord begin;
BufferCoord end;
2017-09-01 12:03:34 +02:00
size_t timestamp = 0;
bool is_valid() const { return not candidates.empty(); }
};
2014-11-02 17:04:24 +01:00
class InsertCompleter : public OptionManagerWatcher
{
public:
InsertCompleter(Context& context);
InsertCompleter(const InsertCompleter&) = delete;
InsertCompleter& operator=(const InsertCompleter&) = delete;
~InsertCompleter();
void select(int index, bool relative, Vector<Key>& keystrokes);
void update(bool allow_implicit);
Run InsertCompletionHide hook before insertions that close completion menu Insert mode completions are accepted by typing any key. For example, if there is a completion "somefunction()", then typing some<c-n>; will insert somefunction(); and then the InsertCompletionHide hook will fire. The hook parameter is a range that contains the entire thing: the actual completion plus the trailing semicolon that closed the completion menu. The [original motivation] for the hook parameter was to support removing text inserted by completion, so we can apply text edits or expand snippets instead. One problem is that we don't want to remove the semicolon. Another problem came up in a discussion about [snippets]: let's say we have a snippet "add" that expands to add(?, ?) where ? are placeholders. After snippet expansion the cursor replaces the first placeholder. If I type "ad<c-n>1" I expect to get "add(1, ?)". If the InsertCompletionHide hook only runs after processing the "1" keystroke, this is not possible without evil hacks. Fix these problems by running InsertCompletionHide when a completion is accepted _before_ inserting anything else into the buffer. This should make it much easier to fully implement [LSP text edits]. I doubt that anyone besides kak-lsp is using the hook parameter today so this should be a low-risk fix. [original motivation]: https://github.com/mawww/kakoune/issues/2898 [snippets]: https://github.com/kak-lsp/kak-lsp/pull/616#discussion_r883208858 [LSP text edits]: https://github.com/kak-lsp/kak-lsp/issues/40
2022-05-29 08:06:48 +02:00
void try_accept();
void reset();
void explicit_file_complete();
void explicit_word_buffer_complete();
void explicit_word_all_complete();
void explicit_line_buffer_complete();
void explicit_line_all_complete();
private:
bool setup_ifn();
template<typename Func>
bool try_complete(Func complete_func);
void on_option_changed(const Option& opt) override;
void menu_show();
bool has_candidate_selected() const;
Context& m_context;
OptionManager& m_options;
const FaceRegistry& m_faces;
InsertCompletion m_completions;
Vector<BufferRange> m_inserted_ranges;
int m_current_candidate = -1;
bool m_enabled = true;
using CompleteFunc = InsertCompletion (const SelectionList& sels,
const OptionManager& options,
const FaceRegistry& faces);
CompleteFunc* m_explicit_completer = nullptr;
};
}
#endif // insert_completer_hh_INCLUDED