From 7a4d9e6d6146f178e851327f9adaaaeaf78557f5 Mon Sep 17 00:00:00 2001 From: eidheim Date: Mon, 19 Oct 2015 11:53:43 +0200 Subject: [PATCH] Implemented auto-indentation of a whole buffer through clang-format. --- src/source.h | 1 + src/source_clang.cc | 22 +++++++++++++ src/terminal.cc | 77 +++++++++++++++++++++++++++++++++++-------- src/terminal.h | 1 + src/terminal_win.cc | 80 ++++++++++++++++++++++++++++++++++++++++----- src/window.cc | 6 +++- 6 files changed, 164 insertions(+), 23 deletions(-) diff --git a/src/source.h b/src/source.h index 2b60633..14f46c4 100644 --- a/src/source.h +++ b/src/source.h @@ -100,6 +100,7 @@ namespace Source { boost::filesystem::path project_path; Glib::RefPtr language; + std::function auto_indent; std::function()> get_declaration_location; std::function goto_method; std::function get_token; diff --git a/src/source_clang.cc b/src/source_clang.cc index 4e39072..8cffec8 100644 --- a/src/source_clang.cc +++ b/src/source_clang.cc @@ -1,5 +1,6 @@ #include "source_clang.h" #include "singletons.h" +#include "sourcefile.h" #include //TODO: remove using namespace std; //TODO: remove @@ -928,6 +929,27 @@ Source::ClangViewAutocomplete(file_path, project_path, language) { } }); + auto_indent=[this]() { + boost::filesystem::path temp_file_path = boost::filesystem::unique_path(); + juci::filesystem::write(temp_file_path, get_buffer()); + std::string command="clang-format \""+temp_file_path.string()+"\""; + command+=" -style=\"{IndentWidth: "+std::to_string(tab_size); + command+="}\""; + std::stringstream stdout_stream; + auto exit_code=Singleton::terminal()->execute(stdout_stream, command); + + if(exit_code==0) { + get_source_buffer()->begin_user_action(); + auto cursor_line_nr=get_buffer()->get_insert()->get_iter().get_line(); + get_buffer()->erase(get_buffer()->begin(), get_buffer()->end()); + get_buffer()->insert(get_buffer()->begin(), stdout_stream.str()); + if(cursor_line_nrget_line_count()) + get_buffer()->place_cursor(get_buffer()->get_iter_at_line(cursor_line_nr)); + get_source_buffer()->end_user_action(); + set_tab_char_and_size(' ', tab_size); //clang-format only does basic indentation with spaces as I understand it + } + }; + get_token=[this]() -> Token { if(source_readable) { auto iter=get_buffer()->get_insert()->get_iter(); diff --git a/src/terminal.cc b/src/terminal.cc index 8d3caad..989e3f4 100644 --- a/src/terminal.cc +++ b/src/terminal.cc @@ -8,6 +8,8 @@ #include //TODO: remove using namespace std; //TODO: remove +const size_t buffer_size=131072; + //A working implementation of popen3, with all pipes getting closed properly. //TODO: Eidheim is going to publish this one on his github, along with example uses pid_t popen3(const std::string &command, const std::string &path, int *stdin_fd, int *stdout_fd, int *stderr_fd) { @@ -145,7 +147,6 @@ Terminal::Terminal() { } int Terminal::execute(const std::string &command, const boost::filesystem::path &path) { - JDEBUG("start"); int stdin_fd, stdout_fd, stderr_fd; auto pid=popen3(command, path.string(), &stdin_fd, &stdout_fd, &stderr_fd); @@ -155,10 +156,11 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path } else { std::thread stderr_thread([this, stderr_fd](){ - char buffer[1024]; + char buffer[buffer_size]; ssize_t n; - while ((n=read(stderr_fd, buffer, 1024)) > 0) { + while ((n=read(stderr_fd, buffer, buffer_size)) > 0) { std::string message; + message.reserve(n); for(ssize_t c=0;c 0) { + while ((n=read(stdout_fd, buffer, buffer_size)) > 0) { std::string message; + message.reserve(n); for(ssize_t c=0;c 0) { + std::string message; + message.reserve(n); + for(ssize_t c=0;c 0) { + Glib::ustring umessage; + umessage.reserve(n); + for(ssize_t c=0;c callback) { std::thread async_execute_thread([this, command, path, callback](){ - JDEBUG("start"); int stdin_fd, stdout_fd, stderr_fd; async_executes_mutex.lock(); stdin_buffer.clear(); @@ -205,10 +256,11 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem } else { std::thread stderr_thread([this, stderr_fd](){ - char buffer[1024]; + char buffer[buffer_size]; ssize_t n; - while ((n=read(stderr_fd, buffer, 1024)) > 0) { + while ((n=read(stderr_fd, buffer, buffer_size)) > 0) { std::string message; + message.reserve(n); for(ssize_t c=0;c 0) { + while ((n=read(stdout_fd, buffer, buffer_size)) > 0) { std::string message; + message.reserve(n); for(ssize_t c=0;c callback=nullptr); void kill_last_async_execute(bool force=false); void kill_async_executes(bool force=false); diff --git a/src/terminal_win.cc b/src/terminal_win.cc index ba65bfe..cd6a927 100644 --- a/src/terminal_win.cc +++ b/src/terminal_win.cc @@ -8,7 +8,7 @@ #include //TODO: remove using namespace std; //TODO: remove -#define BUFSIZE 1024 +const size_t buffer_size=131072; HANDLE popen3(const std::string &command, const std::string &path, HANDLE *stdin_h, HANDLE *stdout_h, HANDLE *stderr_h) { HANDLE g_hChildStd_IN_Rd = NULL; @@ -192,13 +192,14 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path } std::thread stderr_thread([this, stderr_h](){ DWORD n; - CHAR buffer[BUFSIZE]; + CHAR buffer[buffer_size]; for (;;) { - BOOL bSuccess = ReadFile(stderr_h, buffer, BUFSIZE, &n, NULL); + BOOL bSuccess = ReadFile(stderr_h, buffer, static_cast(buffer_size), &n, NULL); if(!bSuccess || n == 0) break; std::string message; + message.reserve(n); for(DWORD c=0;c(buffer_size), &n, NULL); if(!bSuccess || n == 0) break; std::string message; + message.reserve(n); for(DWORD c=0;c(buffer_size), &n, NULL); + if(!bSuccess || n == 0) + break; + + std::string message; + message.reserve(n); + for(DWORD c=0;c(buffer_size), &n, NULL); + if(!bSuccess || n == 0) + break; + Glib::ustring umessage; + umessage.reserve(n); + for(DWORD c=0;c callback) { std::thread async_execute_thread([this, command, path, callback](){ HANDLE stdin_h, stdout_h, stderr_h; @@ -252,13 +312,14 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem std::thread stderr_thread([this, stderr_h](){ DWORD n; - CHAR buffer[BUFSIZE]; + CHAR buffer[buffer_size]; for (;;) { - BOOL bSuccess = ReadFile(stderr_h, buffer, BUFSIZE, &n, NULL); + BOOL bSuccess = ReadFile(stderr_h, buffer, static_cast(buffer_size), &n, NULL); if(!bSuccess || n == 0) break; std::string message; + message.reserve(n); for(DWORD c=0;c(buffer_size), &n, NULL); if(!bSuccess || n == 0) break; std::string message; + message.reserve(n); for(DWORD c=0;csearch_highlight(last_search, case_sensitive_search, regex_search); } + if(auto menu_item=dynamic_cast(menu.ui_manager->get_widget("/MenuBar/SourceMenu/SourceIndentationAutoIndentBuffer"))) + menu_item->set_sensitive((bool)notebook.get_current_view()->auto_indent); + if(auto menu_item=dynamic_cast(menu.ui_manager->get_widget("/MenuBar/SourceMenu/SourceGotoDeclaration"))) menu_item->set_sensitive((bool)notebook.get_current_view()->get_declaration_location); @@ -340,7 +343,8 @@ void Window::create_menu() { set_tab_entry(); }); menu.action_group->add(Gtk::Action::create("SourceIndentationAutoIndentBuffer", "Auto-Indent Current Buffer"), Gtk::AccelKey(menu.key_map["source_indentation_auto_indent_buffer"]), [this]() { - Singleton::terminal()->print("Auto-Indent Current Buffer will soon be implemented.\n"); + if(notebook.get_current_page()!=-1 && notebook.get_current_view()->auto_indent) + notebook.get_current_view()->auto_indent(); }); menu.action_group->add(Gtk::Action::create("SourceGotoLine", "Go to Line"), Gtk::AccelKey(menu.key_map["source_goto_line"]), [this]() { goto_line_entry();