From cf695def6a200f8cb0ccdf63a7b2e9db1e452d44 Mon Sep 17 00:00:00 2001 From: eidheim Date: Sun, 29 Aug 2021 09:27:40 +0200 Subject: [PATCH] Added yapf style format for python files when not using language server or when language server does not support style formatting, and no longer use ranged formatting on save --- src/source.cpp | 46 ++++++++++++++++++++---- src/source.hpp | 2 +- src/source_language_protocol.cpp | 48 ++++++++++++++++--------- src/window.cpp | 2 +- tests/language_protocol_client_test.cpp | 2 +- 5 files changed, 73 insertions(+), 27 deletions(-) diff --git a/src/source.cpp b/src/source.cpp index 9f05fbe..4dd4897 100644 --- a/src/source.cpp +++ b/src/source.cpp @@ -394,9 +394,9 @@ bool Source::View::save() { if(format_style && file_path.filename() != "package.json") { if(Config::get().source.format_style_on_save) - format_style(true); + format_style(true, true); else if(Config::get().source.format_style_on_save_if_style_file_found) - format_style(false); + format_style(false, true); hide_tooltips(); } @@ -749,7 +749,7 @@ void Source::View::setup_format_style(bool is_generic_view) { update_status_diagnostics(this); }); } - format_style = [this, is_generic_view](bool continue_without_style_file) { + format_style = [this, is_generic_view](bool continue_without_style_file, bool ignore_selection) { if(!continue_without_style_file) { auto search_path = file_path.parent_path(); while(true) { @@ -925,7 +925,7 @@ void Source::View::setup_format_style(bool is_generic_view) { } std::string options = "filepath: \"" + escape(file_path.string(), {'"'}) + "\""; - if(get_buffer()->get_has_selection()) { // Cannot be used together with cursorOffset + if(!ignore_selection && get_buffer()->get_has_selection()) { // Cannot be used together with cursorOffset Gtk::TextIter start, end; get_buffer()->get_selection_bounds(start, end); options += ", rangeStart: " + std::to_string(start.get_offset()) + ", rangeEnd: " + std::to_string(end.get_offset()); @@ -982,7 +982,7 @@ void Source::View::setup_format_style(bool is_generic_view) { auto command = prettier.string(); command += " --stdin-filepath " + filesystem::escape_argument(this->file_path.string()); - if(get_buffer()->get_has_selection()) { // Cannot be used together with --cursor-offset + if(!ignore_selection && get_buffer()->get_has_selection()) { // Cannot be used together with --cursor-offset Gtk::TextIter start, end; get_buffer()->get_selection_bounds(start, end); command += " --range-start " + std::to_string(start.get_offset()); @@ -1047,12 +1047,12 @@ void Source::View::setup_format_style(bool is_generic_view) { }; } else if(is_bracket_language) { - format_style = [this](bool continue_without_style_file) { + format_style = [this](bool continue_without_style_file, bool ignore_selection) { static auto clang_format_command = filesystem::get_executable("clang-format").string(); auto command = clang_format_command + " -output-replacements-xml -assume-filename=" + filesystem::escape_argument(this->file_path.string()); - if(get_buffer()->get_has_selection()) { + if(!ignore_selection && get_buffer()->get_has_selection()) { Gtk::TextIter start, end; get_buffer()->get_selection_bounds(start, end); command += " -lines=" + std::to_string(start.get_line() + 1) + ':' + std::to_string(end.get_line() + 1); @@ -1173,6 +1173,38 @@ void Source::View::setup_format_style(bool is_generic_view) { } }; } + else if(language_id == "python") { + static auto yapf = filesystem::find_executable("yapf"); + if(!yapf.empty()) { + format_style = [this](bool continue_without_style_file, bool ignore_selection) { + std::string command = "yapf"; + + if(!ignore_selection && get_buffer()->get_has_selection()) { + Gtk::TextIter start, end; + get_buffer()->get_selection_bounds(start, end); + command += " -l " + std::to_string(start.get_line() + 1) + '-' + std::to_string(end.get_line() + 1); + } + + if(!continue_without_style_file) { + auto search_path = file_path.parent_path(); + while(true) { + boost::system::error_code ec; + if(boost::filesystem::exists(search_path / ".python-format", ec) || boost::filesystem::exists(search_path / ".style.yapf", ec)) + break; + if(search_path == search_path.root_directory()) + return; + search_path = search_path.parent_path(); + } + } + + std::stringstream stdin_stream(get_buffer()->get_text()), stdout_stream; + + auto exit_status = Terminal::get().process(stdin_stream, stdout_stream, command, this->file_path.parent_path()); + if(exit_status == 0) + replace_text(stdout_stream.str()); + }; + } + } } Source::View::~View() { diff --git a/src/source.hpp b/src/source.hpp index b0f458e..2b75caf 100644 --- a/src/source.hpp +++ b/src/source.hpp @@ -84,7 +84,7 @@ namespace Source { void configure() override; std::function non_interactive_completion; - std::function format_style; + std::function format_style; std::function get_declaration_location; std::function get_type_declaration_location; std::function()> get_implementation_locations; diff --git a/src/source_language_protocol.cpp b/src/source_language_protocol.cpp index 6a61db5..9411c1d 100644 --- a/src/source_language_protocol.cpp +++ b/src/source_language_protocol.cpp @@ -819,38 +819,52 @@ bool Source::LanguageProtocolView::save() { void Source::LanguageProtocolView::setup_navigation_and_refactoring() { if(capabilities.document_formatting && !(format_style && is_js /* Use Prettier instead */)) { - format_style = [this](bool continue_without_style_file) { + format_style = [this](bool continue_without_style_file, bool ignore_selection) { if(!continue_without_style_file) { bool has_style_file = false; - auto style_file_search_path = file_path.parent_path(); + auto search_path = file_path.parent_path(); auto style_file = '.' + language_id + "-format"; boost::system::error_code ec; while(true) { - if(boost::filesystem::exists(style_file_search_path / style_file, ec)) { + if(boost::filesystem::exists(search_path / style_file, ec)) { has_style_file = true; break; } - if(style_file_search_path == style_file_search_path.root_directory()) + if(search_path == search_path.root_directory()) break; - style_file_search_path = style_file_search_path.parent_path(); + search_path = search_path.parent_path(); } - if(!has_style_file && language_id == "rust") { - auto style_file_search_path = file_path.parent_path(); - while(true) { - if(boost::filesystem::exists(style_file_search_path / "rustfmt.toml", ec) || - boost::filesystem::exists(style_file_search_path / ".rustfmt.toml", ec)) { - has_style_file = true; - break; + if(!has_style_file) { + if(language_id == "rust") { + auto search_path = file_path.parent_path(); + while(true) { + if(boost::filesystem::exists(search_path / "rustfmt.toml", ec) || + boost::filesystem::exists(search_path / ".rustfmt.toml", ec)) { + has_style_file = true; + break; + } + if(search_path == search_path.root_directory()) + break; + search_path = search_path.parent_path(); + } + } + else if(language_id == "python") { + auto search_path = file_path.parent_path(); + while(true) { + if(boost::filesystem::exists(search_path / ".style.yapf", ec)) { + has_style_file = true; + break; + } + if(search_path == search_path.root_directory()) + break; + search_path = search_path.parent_path(); } - if(style_file_search_path == style_file_search_path.root_directory()) - break; - style_file_search_path = style_file_search_path.parent_path(); } } - if(!has_style_file && !continue_without_style_file) + if(!has_style_file) return; } @@ -859,7 +873,7 @@ void Source::LanguageProtocolView::setup_navigation_and_refactoring() { std::string method; std::vector> params = {{"options", '{' + to_string({{"tabSize", std::to_string(tab_size)}, {"insertSpaces", tab_char == ' ' ? "true" : "false"}}) + '}'}}; - if(get_buffer()->get_has_selection() && capabilities.document_range_formatting) { + if(!ignore_selection && get_buffer()->get_has_selection() && capabilities.document_range_formatting) { method = "textDocument/rangeFormatting"; Gtk::TextIter start, end; get_buffer()->get_selection_bounds(start, end); diff --git a/src/window.cpp b/src/window.cpp index de17fa4..abb2409 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -797,7 +797,7 @@ void Window::set_menu_actions() { auto view = Notebook::get().get_current_view(); if(view && view->format_style) { view->disable_spellcheck = true; - view->format_style(true); + view->format_style(true, false); view->disable_spellcheck = false; view->hide_tooltips(); } diff --git a/tests/language_protocol_client_test.cpp b/tests/language_protocol_client_test.cpp index de0fcc1..34416f6 100644 --- a/tests/language_protocol_client_test.cpp +++ b/tests/language_protocol_client_test.cpp @@ -35,7 +35,7 @@ int main() { } )"); - view->format_style(false); + view->format_style(false, false); g_assert(view->get_buffer()->get_text() == R"(fn main() { let a = 2; println!("{}", a);