Browse Source

Added support for python docstrings, and releasing for instance shift no longer changes shown completion items

pipelines/235045657
eidheim 5 years ago
parent
commit
d21bda1ba2
  1. 3
      src/selection_dialog.cpp
  2. 37
      src/source_language_protocol.cpp
  3. 96
      src/tooltips.cpp
  4. 2
      src/tooltips.hpp

3
src/selection_dialog.cpp

@ -390,7 +390,8 @@ void CompletionDialog::select(bool hide_window) {
} }
bool CompletionDialog::on_key_release(GdkEventKey *event) { bool CompletionDialog::on_key_release(GdkEventKey *event) {
if(event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down || event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up) if(event->keyval == GDK_KEY_Down || event->keyval == GDK_KEY_KP_Down || event->keyval == GDK_KEY_Up || event->keyval == GDK_KEY_KP_Up ||
(event->keyval >= GDK_KEY_Shift_L && event->keyval <= GDK_KEY_Hyper_R))
return false; return false;
if(show_offset > text_view->get_buffer()->get_insert()->get_iter().get_offset()) if(show_offset > text_view->get_buffer()->get_insert()->get_iter().get_offset())

37
src/source_language_protocol.cpp

@ -1183,27 +1183,15 @@ void Source::LanguageProtocolView::show_type_tooltips(const Gdk::Rectangle &rect
auto token_iters = get_token_iters(get_buffer()->get_iter_at_offset(offset)); auto token_iters = get_token_iters(get_buffer()->get_iter_at_offset(offset));
type_tooltips.emplace_back(this, token_iters.first, token_iters.second, [this, offset, contents = std::move(contents)](Tooltip &tooltip) mutable { type_tooltips.emplace_back(this, token_iters.first, token_iters.second, [this, offset, contents = std::move(contents)](Tooltip &tooltip) mutable {
bool first = true; bool first = true;
if(language_id == "python") { if(language_id == "python") { // Python might support markdown in the future
std::string function;
for(auto &content : contents) { for(auto &content : contents) {
if(!first) if(!first)
tooltip.buffer->insert_at_cursor("\n\n"); tooltip.buffer->insert_at_cursor("\n\n");
first = false; first = false;
if(content.kind == "python") { if(content.kind == "python")
tooltip.insert_code(content.value, content.kind); tooltip.insert_code(content.value, content.kind);
auto pos = content.value.find('('); else
if(pos != std::string::npos) tooltip.insert_docstring(content.value);
function = content.value.substr(0, pos + 1);
}
else {
if(!function.empty()) {
while(starts_with(content.value, function)) {
auto pos = content.value.find("\n\n", function.size());
content.value.erase(0, pos != std::string::npos ? pos + 2 : pos);
}
}
tooltip.insert_with_links_tagged(content.value);
}
} }
} }
else { else {
@ -1211,7 +1199,7 @@ void Source::LanguageProtocolView::show_type_tooltips(const Gdk::Rectangle &rect
if(!first) if(!first)
tooltip.buffer->insert_at_cursor("\n\n"); tooltip.buffer->insert_at_cursor("\n\n");
first = false; first = false;
if(content.kind == "plaintext" || content.kind.empty() || (language_id == "python" && content.kind == "markdown")) // Python might support markdown in the future if(content.kind == "plaintext" || content.kind.empty())
tooltip.insert_with_links_tagged(content.value); tooltip.insert_with_links_tagged(content.value);
else if(content.kind == "markdown") else if(content.kind == "markdown")
tooltip.insert_markdown(content.value); tooltip.insert_markdown(content.value);
@ -1754,17 +1742,8 @@ void Source::LanguageProtocolView::setup_autocomplete() {
if(autocomplete.detail.empty() && autocomplete.documentation.empty()) if(autocomplete.detail.empty() && autocomplete.documentation.empty())
return nullptr; return nullptr;
return [this, autocomplete = std::move(autocomplete)](Tooltip &tooltip) mutable { return [this, autocomplete = std::move(autocomplete)](Tooltip &tooltip) mutable {
if(language_id == "python") { if(language_id == "python") // Python might support markdown in the future
auto pos = autocomplete.insert.find('('); tooltip.insert_docstring(autocomplete.documentation);
if(pos != std::string::npos) {
auto function = autocomplete.insert.substr(0, pos + 1);
while(starts_with(autocomplete.documentation, function)) {
auto pos = autocomplete.documentation.find("\n\n", function.size());
autocomplete.documentation.erase(0, pos != std::string::npos ? pos + 2 : pos);
}
}
tooltip.insert_with_links_tagged(autocomplete.documentation);
}
else { else {
if(!autocomplete.detail.empty()) { if(!autocomplete.detail.empty()) {
tooltip.insert_code(autocomplete.detail, language); tooltip.insert_code(autocomplete.detail, language);
@ -1773,7 +1752,7 @@ void Source::LanguageProtocolView::setup_autocomplete() {
if(!autocomplete.documentation.empty()) { if(!autocomplete.documentation.empty()) {
if(tooltip.buffer->size() > 0) if(tooltip.buffer->size() > 0)
tooltip.buffer->insert_at_cursor("\n\n"); tooltip.buffer->insert_at_cursor("\n\n");
if(autocomplete.kind == "plaintext" || autocomplete.kind.empty() || (language_id == "python" && autocomplete.kind == "markdown")) // Python might support markdown in the future if(autocomplete.kind == "plaintext" || autocomplete.kind.empty())
tooltip.insert_with_links_tagged(autocomplete.documentation); tooltip.insert_with_links_tagged(autocomplete.documentation);
else if(autocomplete.kind == "markdown") else if(autocomplete.kind == "markdown")
tooltip.insert_markdown(autocomplete.documentation); tooltip.insert_markdown(autocomplete.documentation);

96
src/tooltips.cpp

@ -582,16 +582,16 @@ void Tooltip::insert_markdown(const std::string &input) {
auto i_saved = i; auto i_saved = i;
i++; i++;
if(i < to) { if(i < to) {
bool escaped = false; bool two_backticks = false;
if(input[i] == '`') { if(input[i] == '`') {
escaped = true; two_backticks = true;
i++; i++;
} }
if(i < to) { if(i < to) {
auto start = i; auto start = i;
for(; i < to; i++) { for(; i < to; i++) {
if(input[i] == '`') { if(input[i] == '`') {
if(!escaped) if(!two_backticks)
break; break;
if(i + 1 < to && input[i + 1] == '`') if(i + 1 < to && input[i + 1] == '`')
break; break;
@ -602,7 +602,7 @@ void Tooltip::insert_markdown(const std::string &input) {
return false; return false;
} }
buffer->insert_with_tag(buffer->get_insert()->get_iter(), input.substr(start, i - start), code_tag); buffer->insert_with_tag(buffer->get_insert()->get_iter(), input.substr(start, i - start), code_tag);
if(escaped) if(two_backticks)
i++; i++;
return true; return true;
} }
@ -1385,6 +1385,94 @@ void Tooltip::insert_doxygen(const std::string &input_, bool remove_delimiters)
insert_markdown(markdown); insert_markdown(markdown);
} }
void Tooltip::insert_docstring(const std::string &input_) {
create_tags();
// Workaround for python-language-server that returns unnecessary function signatures
const static std::regex regex("^([a-zA-Z0-9_]+\\([^\n]*\\)( -> [^\n]+)?(\n|$))+(\n|$)", std::regex::extended | std::regex::optimize);
std::smatch sm;
const std::string &input = std::regex_search(input_, sm, regex) ? sm.suffix() : input_;
std::string partial;
partial.reserve(input.size());
size_t i = 0;
auto parse_backtick = [&] {
if(input[i] == '`') {
insert_with_links_tagged(partial);
partial.clear();
auto i_saved = i;
i++;
if(i < input.size()) {
bool two_backticks = false;
if(input[i] == '`') {
two_backticks = true;
i++;
}
if(i < input.size()) {
auto start = i;
for(; i < input.size(); i++) {
if(input[i] == '`') {
if(!two_backticks)
break;
if(i + 1 < input.size() && input[i + 1] == '`')
break;
}
}
if(i == input.size()) {
i = i_saved;
return false;
}
if(!two_backticks && i + 1 < input.size() && input[i + 1] == '_') { // Is a link
insert_with_links_tagged(input.substr(start, i - start));
++i;
}
else {
buffer->insert_with_tag(buffer->get_insert()->get_iter(), input.substr(start, i - start), code_tag);
if(two_backticks)
i++;
}
return true;
}
}
i = i_saved;
}
return false;
};
bool after_newline = true;
for(; i < input.size(); ++i) {
if(parse_backtick())
continue;
if(after_newline) {
after_newline = false;
auto i_saved = i;
static std::string utf8_space = " ";
while(starts_with(input, i, utf8_space))
i += utf8_space.size();
while(i < input.size() && (input[i] == ' ' || input[i] == '\t'))
++i;
if(starts_with(input, i, ">>>")) {
insert_with_links_tagged(partial);
partial.clear();
auto pos = input.find("\n\n", i + 3);
insert_code(input.substr(i_saved, pos != std::string::npos ? pos - i_saved : pos), {}, true);
buffer->insert_at_cursor("\n\n");
if(pos == std::string::npos)
break;
i = pos + 1;
continue;
}
i = i_saved;
}
if(input[i] == '\n')
after_newline = true;
partial += input[i];
}
if(!partial.empty())
insert_with_links_tagged(partial);
}
void Tooltip::remove_trailing_newlines() { void Tooltip::remove_trailing_newlines() {
auto end = buffer->end(); auto end = buffer->end();
while(end.starts_line() && end.backward_char()) { while(end.starts_line() && end.backward_char()) {

2
src/tooltips.hpp

@ -28,6 +28,8 @@ public:
void insert_markdown(const std::string &text); void insert_markdown(const std::string &text);
void insert_code(const std::string &code, boost::variant<std::string, Glib::RefPtr<Gsv::Language>> language = Glib::RefPtr<Gsv::Language>{}, bool block = false); void insert_code(const std::string &code, boost::variant<std::string, Glib::RefPtr<Gsv::Language>> language = Glib::RefPtr<Gsv::Language>{}, bool block = false);
void insert_doxygen(const std::string &input, bool remove_delimiters); void insert_doxygen(const std::string &input, bool remove_delimiters);
/// Inserts python docstring
void insert_docstring(const std::string &input);
/// Remove empty lines at end of buffer /// Remove empty lines at end of buffer
void remove_trailing_newlines(); void remove_trailing_newlines();

Loading…
Cancel
Save