Browse Source

Cleanup of terminal.*, and added cmake.* to parse CMakeLists.txt. Also fixed compile, and compile and run. Remember to remove ~/.juci/config/config.json to get this version to work.

merge-requests/365/head
eidheim 10 years ago
parent
commit
f832372752
  1. 4
      src/CMakeLists.txt
  2. 260
      src/cmake.cc
  3. 28
      src/cmake.h
  4. 12
      src/config.cc
  5. 1
      src/config.h
  6. 76
      src/directories.cc
  7. 3
      src/directories.h
  8. 21
      src/files.h
  9. 54
      src/notebook.cc
  10. 3
      src/notebook.h
  11. 1
      src/singletons.cc
  12. 2
      src/singletons.h
  13. 109
      src/terminal.cc
  14. 23
      src/terminal.h
  15. 62
      src/window.cc
  16. 4
      src/window.h

4
src/CMakeLists.txt

@ -79,7 +79,9 @@ if(${validation})
tooltips.h tooltips.h
tooltips.cc tooltips.cc
singletons.h singletons.h
singletons.cc) singletons.cc
cmake.h
cmake.cc)
add_library(${module} SHARED add_library(${module} SHARED
api api

260
src/cmake.cc

@ -0,0 +1,260 @@
#include "cmake.h"
#include "sourcefile.h"
#include <regex>
#include "singletons.h"
#include <iostream> //TODO: remove
using namespace std; //TODO: remove
CMake::CMake(const boost::filesystem::path &path) {
const auto find_cmake_project=[this](const boost::filesystem::path &cmake_path) {
for(auto &line: juci::filesystem::read_lines(cmake_path)) {
const std::regex project_regex("^ *project *\\(.*$");
std::smatch sm;
if(std::regex_match(line, sm, project_regex)) {
return true;
}
}
return false;
};
auto search_path=boost::filesystem::path(path);
auto search_cmake_path=search_path;
search_cmake_path+="/CMakeLists.txt";
if(boost::filesystem::exists(search_cmake_path))
paths.emplace(paths.begin(), search_cmake_path);
if(find_cmake_project(search_cmake_path))
project_path=search_path;
else {
do {
search_path=search_path.parent_path();
search_cmake_path=search_path;
search_cmake_path+="/CMakeLists.txt";
if(boost::filesystem::exists(search_cmake_path))
paths.emplace(paths.begin(), search_cmake_path);
if(find_cmake_project(search_cmake_path)) {
project_path=search_path;
break;
}
} while(search_path!=search_path.root_directory());
}
if(project_path!="") {
if(boost::filesystem::exists(project_path.string()+"/CMakeLists.txt") && !boost::filesystem::exists(project_path.string()+"/compile_commands.json"))
create_compile_commands(project_path.string());
}
}
bool CMake::create_compile_commands(const std::string &path) {
Singleton::terminal()->print("Creating "+boost::filesystem::path(path+"/compile_commands.json").string()+"\n");
//TODO: Windows...
if(Singleton::terminal()->execute("cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1", path))
return true;
return false;
}
void CMake::read_files() {
for(auto &path: paths)
files.emplace_back(juci::filesystem::read(path));
}
void CMake::remove_tabs() {
for(auto &file: files) {
for(auto &chr: file) {
if(chr=='\t')
chr=' ';
}
}
}
void CMake::remove_comments() {
for(auto &file: files) {
size_t pos=0;
size_t comment_start;
bool inside_comment=false;
while(pos<file.size()) {
if(!inside_comment && file[pos]=='#') {
comment_start=pos;
inside_comment=true;
}
if(inside_comment && file[pos]=='\n') {
file.erase(comment_start, pos-comment_start);
pos-=pos-comment_start;
inside_comment=false;
}
pos++;
}
if(inside_comment)
file.erase(comment_start);
}
}
void CMake::remove_newlines_inside_parentheses() {
for(auto &file: files) {
size_t pos=0;
bool inside_para=false;
bool inside_quote=false;
char last_char=0;
while(pos<file.size()) {
if(!inside_quote && file[pos]=='"' && last_char!='\\')
inside_quote=true;
else if(inside_quote && file[pos]=='"' && last_char!='\\')
inside_quote=false;
else if(!inside_quote && file[pos]=='(')
inside_para=true;
else if(!inside_quote && file[pos]==')')
inside_para=false;
else if(inside_para && file[pos]=='\n')
file.replace(pos, 1, 1, ' ');
last_char=file[pos];
pos++;
}
}
}
void CMake::find_variables() {
for(auto &file: files) {
size_t pos=0;
while(pos<file.size()) {
auto start_line=pos;
auto end_line=file.find('\n', start_line);
if(end_line==std::string::npos)
end_line=file.size();
if(end_line>start_line) {
auto line=file.substr(start_line, end_line-start_line);
const std::regex set_regex("^ *set *\\( *([A-Za-z_][A-Za-z_0-9]*) +(.*)\\) *$");
std::smatch sm;
if(std::regex_match(line, sm, set_regex)) {
std::string data=sm[2];
while(data.size()>0 && data.back()==' ')
data.pop_back();
parse_variable_parameters(data);
variables[sm[1]]=data;
}
}
pos=end_line+1;
}
}
}
void CMake::parse_variable_parameters(std::string &data) {
size_t pos=0;
bool inside_quote=false;
char last_char=0;
while(pos<data.size()) {
if(!inside_quote && data[pos]=='"' && last_char!='\\') {
inside_quote=true;
data.erase(pos, 1);
pos--;
}
else if(inside_quote && data[pos]=='"' && last_char!='\\') {
inside_quote=false;
data.erase(pos, 1);
pos--;
}
else if(inside_quote && data[pos]!='\\' && last_char=='\\') {
data.erase(pos-1, 1);
pos--;
}
else if(!inside_quote && data[pos]==' ') {
data.erase(pos, 1);
pos--;
}
last_char=data[pos];
pos++;
}
for(auto &var: variables) {
auto pos=data.find("${"+var.first+'}');
if(pos!=std::string::npos)
data.replace(pos, var.first.size()+3, var.second);
}
}
void CMake::parse() {
read_files();
remove_tabs();
remove_comments();
remove_newlines_inside_parentheses();
find_variables();
parsed=true;
}
std::vector<std::string> CMake::get_function_parameters(std::string &data) {
std::vector<std::string> parameters;
size_t pos=0;
size_t parameter_pos=0;
bool inside_quote=false;
char last_char=0;
while(pos<data.size()) {
if(!inside_quote && data[pos]=='"' && last_char!='\\') {
inside_quote=true;
data.erase(pos, 1);
pos--;
}
else if(inside_quote && data[pos]=='"' && last_char!='\\') {
inside_quote=false;
data.erase(pos, 1);
pos--;
}
else if(inside_quote && data[pos]!='\\' && last_char=='\\') {
data.erase(pos-1, 1);
pos--;
}
else if(!inside_quote && pos+1<data.size() && data[pos]==' ' && data[pos+1]==' ') {
data.erase(pos, 1);
pos--;
}
else if(!inside_quote && data[pos]==' ') {
parameters.emplace_back(data.substr(parameter_pos, pos-parameter_pos));
if(pos+1<data.size())
parameter_pos=pos+1;
}
last_char=data[pos];
pos++;
}
parameters.emplace_back(data.substr(parameter_pos));
for(auto &var: variables) {
for(auto &parameter: parameters) {
auto pos=parameter.find("${"+var.first+'}');
while(pos!=std::string::npos) {
parameter.replace(pos, var.first.size()+3, var.second);
pos=parameter.find("${"+var.first+'}');
}
}
}
return parameters;
}
std::vector<std::pair<boost::filesystem::path, std::vector<std::string> > > CMake::get_functions_parameters(const std::string &name) {
if(!parsed)
parse();
std::vector<std::pair<boost::filesystem::path, std::vector<std::string> > > functions;
size_t file_c=0;
for(auto &file: files) {
size_t pos=0;
while(pos<file.size()) {
auto start_line=pos;
auto end_line=file.find('\n', start_line);
if(end_line==std::string::npos)
end_line=file.size();
if(end_line>start_line) {
auto line=file.substr(start_line, end_line-start_line);
const std::regex function_regex("^ *"+name+" *\\( *(.*)\\) *$");
std::smatch sm;
if(std::regex_match(line, sm, function_regex)) {
std::string data=sm[1];
while(data.size()>0 && data.back()==' ')
data.pop_back();
auto parameters=get_function_parameters(data);
functions.emplace(functions.begin(), paths[file_c], parameters);
}
}
pos=end_line+1;
}
file_c++;
}
return functions;
}

28
src/cmake.h

@ -0,0 +1,28 @@
#ifndef JUCI_CMAKE_H_
#define JUCI_CMAKE_H_
#include <boost/filesystem.hpp>
#include <vector>
#include <unordered_map>
class CMake {
public:
CMake(const boost::filesystem::path &path);
std::vector<std::pair<boost::filesystem::path, std::vector<std::string> > > get_functions_parameters(const std::string &name);
static bool create_compile_commands(const std::string &path);
std::vector<boost::filesystem::path> paths;
std::vector<std::string> files;
boost::filesystem::path project_path;
std::unordered_map<std::string, std::string> variables;
private:
void read_files();
void remove_tabs();
void remove_comments();
void remove_newlines_inside_parentheses();
void find_variables();
void parse_variable_parameters(std::string &data);
void parse();
std::vector<std::string> get_function_parameters(std::string &data);
bool parsed=false;
};
#endif //JUCI_CMAKE_H_

12
src/config.cc

@ -11,7 +11,6 @@ MainConfig::MainConfig(Menu &menu) : menu(menu) {
GenerateSource(); GenerateSource();
GenerateKeybindings(); GenerateKeybindings();
GenerateDirectoryFilter(); GenerateDirectoryFilter();
GenerateTerminalCommands();
} }
void MainConfig::find_or_create_config_files() { void MainConfig::find_or_create_config_files() {
@ -59,17 +58,6 @@ void MainConfig::GenerateSource() {
DEBUG("Source cfg fetched"); DEBUG("Source cfg fetched");
} }
void MainConfig::GenerateTerminalCommands() {
auto terminal_cfg=Singleton::Config::terminal();
boost::property_tree::ptree source_json = cfg.get_child("project");
boost::property_tree::ptree compile_commands_json = source_json.get_child("compile_commands");
boost::property_tree::ptree run_commands_json = source_json.get_child("run_commands");
for (auto &i : compile_commands_json)
terminal_cfg->compile_commands.emplace_back(i.second.get_value<std::string>());
for (auto &i : run_commands_json)
terminal_cfg->run_command=(i.second.get_value<std::string>()); //TODO: run_commands array->one run_command?
}
void MainConfig::GenerateKeybindings() { void MainConfig::GenerateKeybindings() {
boost::filesystem::path path(Singleton::config_dir() + "menu.xml"); boost::filesystem::path path(Singleton::config_dir() + "menu.xml");
if (!boost::filesystem::is_regular_file(path)) { if (!boost::filesystem::is_regular_file(path)) {

1
src/config.h

@ -12,7 +12,6 @@ public:
void GenerateSource(); void GenerateSource();
void GenerateKeybindings(); void GenerateKeybindings();
void GenerateDirectoryFilter(); void GenerateDirectoryFilter();
void GenerateTerminalCommands();
private: private:
boost::property_tree::ptree cfg; boost::property_tree::ptree cfg;
boost::property_tree::ptree key_tree; boost::property_tree::ptree key_tree;

76
src/directories.cc

@ -5,6 +5,9 @@
#include <algorithm> #include <algorithm>
#include "boost/algorithm/string.hpp" #include "boost/algorithm/string.hpp"
#include <iostream> //TODO: remove
using namespace std; //TODO: remove
namespace sigc { namespace sigc {
SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
} }
@ -47,7 +50,14 @@ void Directories::open_folder(const boost::filesystem::path& dir_path) {
} }
tree_store->clear(); tree_store->clear();
tree_view.get_column(0)->set_title(get_cmakelists_variable(dir_path, "project"));
if(last_dir_path!=dir_path)
cmake=std::unique_ptr<CMake>(new CMake(dir_path));
auto project=cmake->get_functions_parameters("project");
if(project.size()>0 && project[0].second.size()>0)
tree_view.get_column(0)->set_title(project[0].second[0]);
else
tree_view.get_column(0)->set_title("");
add_paths(dir_path, Gtk::TreeModel::Row(), 0); add_paths(dir_path, Gtk::TreeModel::Row(), 0);
for(auto &path: expanded_paths) for(auto &path: expanded_paths)
@ -118,67 +128,3 @@ void Directories::add_paths(const boost::filesystem::path& dir_path, const Gtk::
} }
} }
} }
std::string Directories::get_cmakelists_variable(const boost::filesystem::path& dir_path, std::string command_name) {
INFO("fetches cmake variable value for: "+command_name);
std::string project_name;
std::string project_name_var;
boost::filesystem::directory_iterator end_itr;
for (boost::filesystem::directory_iterator itr( dir_path );itr != end_itr;++itr ) {
if (itr->path().filename().string() == "CMakeLists.txt") {
for (auto &line : juci::filesystem::read_lines(itr->path())) {
if (line.find(command_name+"(", 0) != std::string::npos
|| line.find(command_name+" (", 0) != std::string::npos ) {
size_t variable_start = line.find("{", 0);
size_t variable_end = line.find("}", variable_start);
project_name_var = line.substr(variable_start+1,
(variable_end)-variable_start-1);
boost::algorithm::trim(project_name_var);
if (variable_start == std::string::npos) { // not a variabel
variable_start = line.find("(", 0);
variable_end = line.find(' ', variable_start);
if(variable_end != std::string::npos){
return line.substr(variable_start+1,
(variable_end)-variable_start-1);
}
variable_end = line.find("#", variable_start);
if(variable_end != std::string::npos){
return line.substr(variable_start+1,
(variable_end)-variable_start-1);
}
variable_end = line.find(")", variable_start);
return line.substr(variable_start+1,
(variable_end)-variable_start-1);
if (variable_start == std::string::npos) { // not a variable
variable_start = line.find("(", 0);
variable_end = line.find(")", variable_start);
INFO("Wasn't a variable, returning value");
return line.substr(variable_start+1,
(variable_end)-variable_start-1);
}
break;
}
}
}
for (auto &line : juci::filesystem::read_lines(itr->path())) {
if (line.find("set(", 0) != std::string::npos
|| line.find("set (", 0) != std::string::npos) {
if( line.find(project_name_var, 0) != std::string::npos) {
size_t variable_start = line.find(project_name_var, 0)
+project_name_var.length();
size_t variable_end = line.find(")", variable_start);
project_name = line.substr(variable_start+1,
variable_end-variable_start-1);
boost::algorithm::trim(project_name);
INFO("found variable, returning value");
return project_name;
}
}
}
break;
}
}
INFO("Couldn't find value in CMakeLists.txt");
return "no project name";
}

3
src/directories.h

@ -5,6 +5,7 @@
#include <vector> #include <vector>
#include <string> #include <string>
#include "boost/filesystem.hpp" #include "boost/filesystem.hpp"
#include "cmake.h"
class Directories : public Gtk::ScrolledWindow { class Directories : public Gtk::ScrolledWindow {
public: public:
@ -29,9 +30,9 @@ public:
Directories(); Directories();
void open_folder(const boost::filesystem::path& dir_path); void open_folder(const boost::filesystem::path& dir_path);
void select_path(const std::string &path); void select_path(const std::string &path);
std::string get_cmakelists_variable(const boost::filesystem::path& dir_path, std::string command_name);
std::function<void(const std::string &file)> on_row_activated; std::function<void(const std::string &file)> on_row_activated;
std::unique_ptr<CMake> cmake;
private: private:
void add_paths(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &row, unsigned depth); void add_paths(const boost::filesystem::path& dir_path, const Gtk::TreeModel::Row &row, unsigned depth);

21
src/files.h

@ -68,27 +68,6 @@ const std::string configjson =
" \"cmakelists.txt\",\n" " \"cmakelists.txt\",\n"
" \"in-lowercase.pls\"\n" " \"in-lowercase.pls\"\n"
" ]\n" " ]\n"
" },\n"
" \"project\": {\n"
" \"run_commands\": [\n"
" \"./.build/\"\n"
" ],\n"
" \"compile_commands\": [\n"
" \"rm -rf ./.build\",\n"
" \"mkdir ./.build\",\n"
" \"cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -B./.build -H.\",\n"
" \"cd ./.build/; make\",\n"
" \"cp ./.build/compile_commands.json compile_commands.json\"\n"
" ]\n"
" },\n"
" \"example\": {\n"
" \"key\": \"value\",\n"
" \"key2\": [\n"
" \"val1\",\n"
" \"val2\",\n"
" 3\n"
" ],\n"
" \"key3\": \"value\"\n"
" }\n" " }\n"
"}\n"; "}\n";

54
src/notebook.cc

@ -4,6 +4,7 @@
#include "singletons.h" #include "singletons.h"
#include <fstream> #include <fstream>
#include <regex> #include <regex>
#include "cmake.h"
#include <iostream> //TODO: remove #include <iostream> //TODO: remove
using namespace std; //TODO: remove using namespace std; //TODO: remove
@ -54,18 +55,19 @@ void Notebook::open(std::string path) {
auto language=Source::guess_language(path); auto language=Source::guess_language(path);
if(language && (language->get_id()=="chdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc")) { if(language && (language->get_id()=="chdr" || language->get_id()=="c" || language->get_id()=="cpp" || language->get_id()=="objc")) {
auto view_project_path=project_path; auto view_project_path=project_path;
if(directories.cmake && directories.cmake->project_path!="")
view_project_path=directories.cmake->project_path.string();
if(view_project_path=="") { if(view_project_path=="") {
view_project_path=boost::filesystem::path(path).parent_path().string(); auto parent_path=boost::filesystem::path(path).parent_path();
auto found_project_path=find_project_path(view_project_path); view_project_path=parent_path.string();
if(found_project_path!="") { CMake cmake(parent_path);
view_project_path=found_project_path; if(cmake.project_path!="") {
view_project_path=cmake.project_path.string();
Singleton::terminal()->print("Project path for "+path+" set to "+view_project_path+"\n"); Singleton::terminal()->print("Project path for "+path+" set to "+view_project_path+"\n");
} }
else else
Singleton::terminal()->print("Error: could not find project path for "+path+"\n"); Singleton::terminal()->print("Error: could not find project path for "+path+"\n");
} }
if(boost::filesystem::exists(view_project_path+"/CMakeLists.txt") && !boost::filesystem::exists(view_project_path+"/compile_commands.json"))
make_compile_commands(view_project_path);
source_views.emplace_back(new Source::ClangView(path, view_project_path)); source_views.emplace_back(new Source::ClangView(path, view_project_path));
} }
else { else {
@ -112,32 +114,6 @@ void Notebook::open(std::string path) {
}; };
} }
std::string Notebook::find_project_path(const std::string &path) {
const auto find_cmake_project=[this](const boost::filesystem::path &path) {
auto cmake_path=path;
cmake_path+="/CMakeLists.txt";
for(auto &line: juci::filesystem::read_lines(cmake_path)) {
const std::regex cmake_project("^ *project *\\(.*$");
std::smatch sm;
if(std::regex_match(line, sm, cmake_project)) {
return true;
}
}
return false;
};
auto boost_path=boost::filesystem::path(path);
if(find_cmake_project(boost_path))
return boost_path.string();
do {
boost_path=boost_path.parent_path();
if(find_cmake_project(boost_path))
return boost_path.string();
} while(boost_path!=boost_path.root_directory());
return "";
}
bool Notebook::save(int page) { bool Notebook::save(int page) {
if(page>=size()) if(page>=size())
return false; return false;
@ -149,7 +125,8 @@ bool Notebook::save(int page) {
//If CMakeLists.txt have been modified: //If CMakeLists.txt have been modified:
if(boost::filesystem::path(view->file_path).filename().string()=="CMakeLists.txt") { if(boost::filesystem::path(view->file_path).filename().string()=="CMakeLists.txt") {
if(project_path!="" && make_compile_commands(project_path)) { if(project_path!="" && directories.cmake && directories.cmake->project_path!="" && CMake::create_compile_commands(directories.cmake->project_path.string())) {
directories.open_folder(project_path);
for(auto source_view: source_views) { for(auto source_view: source_views) {
if(auto source_clang_view=dynamic_cast<Source::ClangView*>(source_view)) { if(auto source_clang_view=dynamic_cast<Source::ClangView*>(source_view)) {
if(project_path==source_view->project_path) { if(project_path==source_view->project_path) {
@ -170,17 +147,6 @@ bool Notebook::save(int page) {
return false; return false;
} }
bool Notebook::make_compile_commands(const std::string &path) {
Singleton::terminal()->print("Creating "+boost::filesystem::path(path+"/compile_commands.json").string()+"\n");
//TODO: Windows...
if(Singleton::terminal()->execute(path, "cmake . -DCMAKE_EXPORT_COMPILE_COMMANDS=ON 2>&1")) {
if(project_path!="")
directories.open_folder(project_path);
return true;
}
return false;
}
bool Notebook::save_current() { bool Notebook::save_current() {
INFO("Notebook save current file"); INFO("Notebook save current file");
if(get_current_page()==-1) if(get_current_page()==-1)

3
src/notebook.h

@ -20,10 +20,9 @@ public:
void open(std::string filename); void open(std::string filename);
bool save(int page); bool save(int page);
bool save_current(); bool save_current();
std::string project_path; std::string project_path; //TODO: remove, and also remove Source::View::project_path (project_path only needed in Source::ClangView)
private: private:
std::string find_project_path(const std::string &path);
bool make_compile_commands(const std::string &path); bool make_compile_commands(const std::string &path);
bool save_modified_dialog(); bool save_modified_dialog();
Directories &directories; Directories &directories;

1
src/singletons.cc

@ -1,7 +1,6 @@
#include "singletons.h" #include "singletons.h"
std::unique_ptr<Source::Config> Singleton::Config::source_=std::unique_ptr<Source::Config>(new Source::Config()); std::unique_ptr<Source::Config> Singleton::Config::source_=std::unique_ptr<Source::Config>(new Source::Config());
std::unique_ptr<Terminal::Config> Singleton::Config::terminal_=std::unique_ptr<Terminal::Config>(new Terminal::Config());
std::unique_ptr<Directories::Config> Singleton::Config::directories_=std::unique_ptr<Directories::Config>(new Directories::Config()); std::unique_ptr<Directories::Config> Singleton::Config::directories_=std::unique_ptr<Directories::Config>(new Directories::Config());
std::unique_ptr<Terminal> Singleton::terminal_=std::unique_ptr<Terminal>(); std::unique_ptr<Terminal> Singleton::terminal_=std::unique_ptr<Terminal>();

2
src/singletons.h

@ -14,11 +14,9 @@ public:
class Config { class Config {
public: public:
static Source::Config *source() {return source_.get();} static Source::Config *source() {return source_.get();}
static Terminal::Config *terminal() {return terminal_.get();}
static Directories::Config *directories() {return directories_.get();} static Directories::Config *directories() {return directories_.get();}
private: private:
static std::unique_ptr<Source::Config> source_; static std::unique_ptr<Source::Config> source_;
static std::unique_ptr<Terminal::Config> terminal_;
static std::unique_ptr<Directories::Config> directories_; static std::unique_ptr<Directories::Config> directories_;
}; };
static std::string config_dir() { return std::string(getenv("HOME")) + "/.juci/config/"; } static std::string config_dir() { return std::string(getenv("HOME")) + "/.juci/config/"; }

109
src/terminal.cc

@ -48,72 +48,82 @@ Terminal::Terminal() {
scrolled_window.add(text_view); scrolled_window.add(text_view);
add(scrolled_window); add(scrolled_window);
change_folder_command = "";
text_view.signal_size_allocate().connect([this](Gtk::Allocation& allocation){ text_view.signal_size_allocate().connect([this](Gtk::Allocation& allocation){
auto end=text_view.get_buffer()->create_mark(text_view.get_buffer()->end()); auto end=text_view.get_buffer()->create_mark(text_view.get_buffer()->end());
text_view.scroll_to(end); text_view.scroll_to(end);
text_view.get_buffer()->delete_mark(end); text_view.get_buffer()->delete_mark(end);
}); });
async_execute_print.connect([this](){
print(async_execute_print_string);
async_execute_print_finished=true;
});
} }
bool Terminal::execute(const std::string &path, const std::string &command) { bool Terminal::execute(const std::string &command, const std::string &path) {
boost::filesystem::path boost_path; boost::filesystem::path boost_path;
if(path=="") std::string cd_path_and_command;
boost_path=boost::filesystem::current_path(); if(path!="") {
else
boost_path=boost::filesystem::path(path); boost_path=boost::filesystem::path(path);
//TODO: Windows... //TODO: Windows...
auto cd_path_and_command="cd "+boost_path.string()+" 2>&1 && "+command; cd_path_and_command="cd "+boost_path.string()+" 2>&1 && "+command;
}
else
cd_path_and_command=command;
FILE* p = NULL; FILE* p;
p = popen(cd_path_and_command.c_str(), "r"); p = popen(cd_path_and_command.c_str(), "r");
if (p == NULL) { if (p == NULL) {
print("Error: Failed to run command" + command + "\n"); print("Error: Failed to run command" + command + "\n");
return false; return false;
} }
else { else {
char buffer[1028]; char buffer[1024];
while (fgets(buffer, 1028, p) != NULL) { while (fgets(buffer, 1024, p) != NULL) {
print(buffer); print(buffer);
while(gtk_events_pending())
gtk_main_iteration();
} }
int exit_code=pclose(p); return pclose(p)==0;
if(exit_code==0)
return true;
else
return false;
} }
} }
void Terminal::async_execute(const std::string &path, const std::string &command) { void Terminal::async_execute(const std::string &command, const std::string &path, std::function<void(bool success)> callback) {
std::thread async_execute_thread([this, command, path, callback](){
} boost::filesystem::path boost_path;
std::string cd_path_and_command;
void Terminal::set_change_folder_command(boost::filesystem::path CMake_path) { if(path!="") {
INFO("Terminal: set_change_folder_command"); boost_path=boost::filesystem::path(path);
path = CMake_path.string();
change_folder_command = "cd "+ path + "; ";
}
void Terminal::compile() { //TODO: Windows...
INFO("Terminal: compile"); cd_path_and_command="cd "+boost_path.string()+" 2>&1 && "+command;
text_view.get_buffer()->set_text("");
DEBUG("Terminal: compile: running cmake command");
std::vector<std::string> commands = Singleton::Config::terminal()->compile_commands;
for (size_t it = 0; it < commands.size(); ++it) {
execute_command(commands.at(it), "r");
} }
print("\n"); else
DEBUG("Terminal: compile: compile done"); cd_path_and_command=command;
}
void Terminal::run(std::string executable) { FILE* p;
INFO("Terminal: run"); p = popen(cd_path_and_command.c_str(), "r");
print("juCi++ execute: " + executable + "\n"); if (p == NULL) {
DEBUG("Terminal: compile: running run command: "); async_execute_print_string="Error: Failed to run command" + command + "\n";
DEBUG_VAR(executable); async_execute_print_finished=false;
execute_command("cd "+Singleton::Config::terminal()->run_command + "; ./"+executable, "r"); async_execute_print();
print("\n"); }
else {
char buffer[1024];
while (fgets(buffer, 1024, p) != NULL) {
async_execute_print_string=buffer;
async_execute_print_finished=false;
async_execute_print();
while(!async_execute_print_finished)
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
int exit_code=pclose(p);
if(callback)
callback(exit_code==0);
}
});
async_execute_thread.detach();
} }
int Terminal::print(std::string message){ int Terminal::print(std::string message){
@ -134,22 +144,3 @@ std::shared_ptr<Terminal::InProgress> Terminal::print_in_progress(std::string st
std::shared_ptr<Terminal::InProgress> in_progress=std::shared_ptr<Terminal::InProgress>(new Terminal::InProgress(start_msg)); std::shared_ptr<Terminal::InProgress> in_progress=std::shared_ptr<Terminal::InProgress>(new Terminal::InProgress(start_msg));
return in_progress; return in_progress;
} }
void Terminal::execute_command(std::string command, std::string mode) {
INFO("Terminal: execute_command");
command = change_folder_command+command;
DEBUG("Terminal: PrintMessage: running command");
FILE* p = NULL;
std::cout << command << std::endl;
p = popen(command.c_str(), mode.c_str());
if (p == NULL) {
print("juCi++ ERROR: Failed to run command" + command + "\n");
}
else {
char buffer[1028];
while (fgets(buffer, 1028, p) != NULL) {
print(buffer);
}
pclose(p);
}
}

23
src/terminal.h

@ -10,12 +10,6 @@
class Terminal : public Gtk::HBox { class Terminal : public Gtk::HBox {
public: public:
class Config {
public:
std::vector<std::string> compile_commands;
std::string run_command;
};
class InProgress { class InProgress {
public: public:
InProgress(const std::string& start_msg); InProgress(const std::string& start_msg);
@ -31,25 +25,18 @@ public:
}; };
Terminal(); Terminal();
bool execute(const std::string &path, const std::string &command); bool execute(const std::string &command, const std::string &path="");
void async_execute(const std::string &path, const std::string &command); void async_execute(const std::string &command, const std::string &path="", std::function<void(bool success)> callback=nullptr);
void set_change_folder_command(boost::filesystem::path CMake_path); //TODO: remove
void run(std::string executable); //TODO: remove
void compile(); //TODO: remove
int print(std::string message); int print(std::string message);
void print(int line_nr, std::string message); void print(int line_nr, std::string message);
std::shared_ptr<InProgress> print_in_progress(std::string start_msg); std::shared_ptr<InProgress> print_in_progress(std::string start_msg);
private: private:
void execute_command(std::string command, std::string mode); //TODO: remove
Gtk::TextView text_view; Gtk::TextView text_view;
Gtk::ScrolledWindow scrolled_window; Gtk::ScrolledWindow scrolled_window;
std::string change_folder_command; //TODO: remove Glib::Dispatcher async_execute_print;
std::string path; //TODO: remove std::string async_execute_print_string;
const std::string cmake_sucsess = "Build files have been written to:"; //TODO: remove std::atomic<bool> async_execute_print_finished;
const std::string make_built = "Built target"; //TODO: remove
const std::string make_executable = "Linking CXX executable"; //TODO: remove
}; };
#endif // JUCI_TERMINAL_H_ #endif // JUCI_TERMINAL_H_

62
src/window.cc

@ -12,7 +12,7 @@ namespace sigc {
SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE
} }
Window::Window() : box(Gtk::ORIENTATION_VERTICAL), notebook(directories) { Window::Window() : box(Gtk::ORIENTATION_VERTICAL), notebook(directories), compiling(false) {
INFO("Create Window"); INFO("Create Window");
set_title("juCi++"); set_title("juCi++");
set_default_size(600, 400); set_default_size(600, 400);
@ -194,41 +194,43 @@ void Window::create_menu() {
}); });
menu.action_group->add(Gtk::Action::create("ProjectCompileAndRun", "Compile And Run"), Gtk::AccelKey(menu.key_map["compile_and_run"]), [this]() { menu.action_group->add(Gtk::Action::create("ProjectCompileAndRun", "Compile And Run"), Gtk::AccelKey(menu.key_map["compile_and_run"]), [this]() {
if(notebook.get_current_page()==-1) if(notebook.get_current_page()==-1 || compiling)
return; return;
notebook.save_current(); CMake cmake(notebook.get_current_view()->file_path);
if (running.try_lock()) { auto executables = cmake.get_functions_parameters("add_executable");
std::thread execute([this]() { std::string executable;
std::string path = notebook.get_current_view()->file_path; boost::filesystem::path path;
size_t pos = path.find_last_of("/\\"); if(executables.size()>0 && executables[0].second.size()>0) {
if(pos != std::string::npos) { executable=executables[0].second[0];
path.erase(path.begin()+pos,path.end()); path=executables[0].first.parent_path();
Singleton::terminal()->set_change_folder_command(path); path+="/"+executables[0].second[0];
} }
Singleton::terminal()->compile(); if(cmake.project_path!="") {
std::string executable = directories.get_cmakelists_variable(path,"add_executable"); compiling=true;
Singleton::terminal()->run(executable); if(path!="")
running.unlock(); Singleton::terminal()->print("Compiling and executing "+path.string()+"\n");
else
Singleton::terminal()->print("Could not find an executable, please use add_executable in CMakeLists.txt\n");
//TODO: Windows...
Singleton::terminal()->async_execute("make 2>&1", cmake.project_path.string(), [this, path](int exit_code){
compiling=false;
if(path!="")
//TODO: Windows...
Singleton::terminal()->async_execute(path.string()+" 2>&1", path.parent_path().string());
}); });
execute.detach();
} }
}); });
menu.action_group->add(Gtk::Action::create("ProjectCompile", "Compile"), Gtk::AccelKey(menu.key_map["compile"]), [this]() { menu.action_group->add(Gtk::Action::create("ProjectCompile", "Compile"), Gtk::AccelKey(menu.key_map["compile"]), [this]() {
if(notebook.get_current_page()==-1) if(notebook.get_current_page()==-1 || compiling)
return; return;
notebook.save_current(); CMake cmake(notebook.get_current_view()->file_path);
if (running.try_lock()) { if(cmake.project_path!="") {
std::thread execute([this]() { compiling=true;
std::string path = notebook.get_current_view()->file_path; Singleton::terminal()->print("Compiling project "+cmake.project_path.string()+"\n");
size_t pos = path.find_last_of("/\\"); //TODO: Windows...
if(pos != std::string::npos){ Singleton::terminal()->async_execute("make 2>&1", cmake.project_path.string(), [this](int exit_code){
path.erase(path.begin()+pos,path.end()); compiling=false;
Singleton::terminal()->set_change_folder_command(path); });
}
Singleton::terminal()->compile();
running.unlock();
});
execute.detach();
} }
}); });

4
src/window.h

@ -6,6 +6,7 @@
#include "entrybox.h" #include "entrybox.h"
#include "notebook.h" #include "notebook.h"
#include "menu.h" #include "menu.h"
#include <atomic>
class Window : public Gtk::Window { class Window : public Gtk::Window {
public: public:
@ -23,8 +24,8 @@ private:
Gtk::VBox terminal_vbox; Gtk::VBox terminal_vbox;
Gtk::HBox status_hbox; Gtk::HBox status_hbox;
EntryBox entry_box; EntryBox entry_box;
std::mutex running;
Menu menu; Menu menu;
std::atomic<bool> compiling;
void create_menu(); void create_menu();
void hide(); void hide();
@ -41,7 +42,6 @@ private:
bool case_sensitive_search=true; bool case_sensitive_search=true;
bool regex_search=false; bool regex_search=false;
bool search_entry_shown=false; bool search_entry_shown=false;
}; };
#endif // JUCI_WINDOW_H #endif // JUCI_WINDOW_H

Loading…
Cancel
Save