Browse Source

Implemented auto-indentation of a whole buffer through clang-format.

merge-requests/365/head
eidheim 10 years ago
parent
commit
7a4d9e6d61
  1. 1
      src/source.h
  2. 22
      src/source_clang.cc
  3. 77
      src/terminal.cc
  4. 1
      src/terminal.h
  5. 80
      src/terminal_win.cc
  6. 6
      src/window.cc

1
src/source.h

@ -100,6 +100,7 @@ namespace Source {
boost::filesystem::path project_path;
Glib::RefPtr<Gsv::Language> language;
std::function<void()> auto_indent;
std::function<std::pair<std::string, Offset>()> get_declaration_location;
std::function<void()> goto_method;
std::function<Token()> get_token;

22
src/source_clang.cc

@ -1,5 +1,6 @@
#include "source_clang.h"
#include "singletons.h"
#include "sourcefile.h"
#include <iostream> //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_nr<get_buffer()->get_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();

77
src/terminal.cc

@ -8,6 +8,8 @@
#include <iostream> //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<n;c++)
message+=buffer[c];
async_print(message, true);
@ -166,10 +168,11 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path
});
stderr_thread.detach();
std::thread stdout_thread([this, stdout_fd](){
char buffer[1024];
char buffer[buffer_size];
ssize_t n;
while ((n=read(stdout_fd, buffer, 1024)) > 0) {
while ((n=read(stdout_fd, buffer, buffer_size)) > 0) {
std::string message;
message.reserve(n);
for(ssize_t c=0;c<n;c++)
message+=buffer[c];
async_print(message);
@ -183,14 +186,62 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path
close(stdout_fd);
close(stderr_fd);
JDEBUG("end");
return exit_code;
}
}
int Terminal::execute(std::iostream &stdout_stream, const std::string &command, const boost::filesystem::path &path) {
int stdin_fd, stdout_fd, stderr_fd;
auto pid=popen3(command, path.string(), &stdin_fd, &stdout_fd, &stderr_fd);
if (pid<=0) {
async_print("Error: Failed to run command: " + command + "\n");
return -1;
}
else {
std::thread stderr_thread([this, stderr_fd](){
char buffer[buffer_size];
ssize_t n;
while ((n=read(stderr_fd, buffer, buffer_size)) > 0) {
std::string message;
message.reserve(n);
for(ssize_t c=0;c<n;c++)
message+=buffer[c];
async_print(message, true);
}
});
stderr_thread.detach();
std::thread stdout_thread([this, &stdout_stream, stdout_fd](){
char buffer[buffer_size];
ssize_t n;
while ((n=read(stdout_fd, buffer, buffer_size)) > 0) {
Glib::ustring umessage;
umessage.reserve(n);
for(ssize_t c=0;c<n;c++)
umessage+=buffer[c];
Glib::ustring::iterator iter;
while(!umessage.validate(iter)) {
auto next_char_iter=iter;
next_char_iter++;
umessage.replace(iter, next_char_iter, "?");
}
stdout_stream << umessage;
}
});
stdout_thread.detach();
int exit_code;
waitpid(pid, &exit_code, 0);
close(stdin_fd);
close(stdout_fd);
close(stderr_fd);
return exit_code;
}
}
void Terminal::async_execute(const std::string &command, const boost::filesystem::path &path, std::function<void(int exit_code)> 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<n;c++)
message+=buffer[c];
async_print(message, true);
@ -216,10 +268,11 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem
});
stderr_thread.detach();
std::thread stdout_thread([this, stdout_fd](){
char buffer[1024];
char buffer[buffer_size];
ssize_t n;
while ((n=read(stdout_fd, buffer, 1024)) > 0) {
while ((n=read(stdout_fd, buffer, buffer_size)) > 0) {
std::string message;
message.reserve(n);
for(ssize_t c=0;c<n;c++)
message+=buffer[c];
async_print(message);
@ -244,8 +297,6 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem
if(callback)
callback(exit_code);
JDEBUG("end");
}
});
async_execute_thread.detach();

1
src/terminal.h

@ -34,6 +34,7 @@ public:
Terminal();
int execute(const std::string &command, const boost::filesystem::path &path="");
int execute(std::iostream &stdout_stream, const std::string &command, const boost::filesystem::path &path="");
void async_execute(const std::string &command, const boost::filesystem::path &path="", std::function<void(int exit_code)> callback=nullptr);
void kill_last_async_execute(bool force=false);
void kill_async_executes(bool force=false);

80
src/terminal_win.cc

@ -8,7 +8,7 @@
#include <iostream> //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<DWORD>(buffer_size), &n, NULL);
if(!bSuccess || n == 0)
break;
std::string message;
message.reserve(n);
for(DWORD c=0;c<n;c++)
message+=buffer[c];
async_print(message, true);
@ -208,13 +209,14 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path
std::thread stdout_thread([this, stdout_h](){
DWORD n;
CHAR buffer[BUFSIZE];
CHAR buffer[buffer_size];
for (;;) {
BOOL bSuccess = ReadFile(stdout_h, buffer, BUFSIZE, &n, NULL);
BOOL bSuccess = ReadFile(stdout_h, buffer, static_cast<DWORD>(buffer_size), &n, NULL);
if(!bSuccess || n == 0)
break;
std::string message;
message.reserve(n);
for(DWORD c=0;c<n;c++)
message+=buffer[c];
async_print(message);
@ -233,6 +235,64 @@ int Terminal::execute(const std::string &command, const boost::filesystem::path
return exit_code;
}
int Terminal::execute(std::iostream &stdout_stream, const std::string &command, const boost::filesystem::path &path) {
HANDLE stdin_h, stdout_h, stderr_h;
auto process=popen3(command, path.string(), &stdin_h, &stdout_h, &stderr_h);
if(process==NULL) {
async_print("Error: Failed to run command: " + command + "\n");
return -1;
}
std::thread stderr_thread([this, stderr_h](){
DWORD n;
CHAR buffer[buffer_size];
for (;;) {
BOOL bSuccess = ReadFile(stderr_h, buffer, static_cast<DWORD>(buffer_size), &n, NULL);
if(!bSuccess || n == 0)
break;
std::string message;
message.reserve(n);
for(DWORD c=0;c<n;c++)
message+=buffer[c];
async_print(message, true);
}
});
stderr_thread.detach();
std::thread stdout_thread([this, &stdout_stream, stdout_h](){
DWORD n;
CHAR buffer[buffer_size];
for (;;) {
BOOL bSuccess = ReadFile(stdout_h, buffer, static_cast<DWORD>(buffer_size), &n, NULL);
if(!bSuccess || n == 0)
break;
Glib::ustring umessage;
umessage.reserve(n);
for(DWORD c=0;c<n;c++)
umessage+=buffer[c];
Glib::ustring::iterator iter;
while(!umessage.validate(iter)) {
auto next_char_iter=iter;
next_char_iter++;
umessage.replace(iter, next_char_iter, "?");
}
stdout_stream << umessage;
}
});
stdout_thread.detach();
unsigned long exit_code;
WaitForSingleObject(process, INFINITE);
GetExitCodeProcess(process, &exit_code);
CloseHandle(process);
CloseHandle(stdin_h);
CloseHandle(stdout_h);
CloseHandle(stderr_h);
return exit_code;
}
void Terminal::async_execute(const std::string &command, const boost::filesystem::path &path, std::function<void(int exit_code)> 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<DWORD>(buffer_size), &n, NULL);
if(!bSuccess || n == 0)
break;
std::string message;
message.reserve(n);
for(DWORD c=0;c<n;c++)
message+=buffer[c];
async_print(message, true);
@ -268,13 +329,14 @@ void Terminal::async_execute(const std::string &command, const boost::filesystem
std::thread stdout_thread([this, stdout_h](){
DWORD n;
CHAR buffer[BUFSIZE];
CHAR buffer[buffer_size];
for (;;) {
BOOL bSuccess = ReadFile(stdout_h, buffer, BUFSIZE, &n, NULL);
BOOL bSuccess = ReadFile(stdout_h, buffer, static_cast<DWORD>(buffer_size), &n, NULL);
if(!bSuccess || n == 0)
break;
std::string message;
message.reserve(n);
for(DWORD c=0;c<n;c++)
message+=buffer[c];
async_print(message);

6
src/window.cc

@ -105,6 +105,9 @@ Window::Window() : box(Gtk::ORIENTATION_VERTICAL), compiling(false) {
notebook.get_current_view()->search_highlight(last_search, case_sensitive_search, regex_search);
}
if(auto menu_item=dynamic_cast<Gtk::MenuItem*>(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<Gtk::MenuItem*>(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();

Loading…
Cancel
Save