Browse Source

Merge pull request #18 from cppit/searchandreplace

Wrapping search
merge-requests/365/head
Jørgen Lien Sellæg 11 years ago
parent
commit
9403e862b9
  1. 2
      juci/CMakeLists.txt
  2. 3
      juci/cmake/Modules/FindLibClang.cmake
  3. 14
      juci/config.cc
  4. 9
      juci/config.h
  5. 3
      juci/config.json
  6. 4
      juci/directories.cc
  7. 119
      juci/entry.cc
  8. 50
      juci/entry.h
  9. 10
      juci/juci.cc
  10. 6
      juci/menu.xml
  11. 261
      juci/notebook.cc
  12. 54
      juci/notebook.h
  13. 46
      juci/source.cc
  14. 8
      juci/source.h
  15. 89
      juci/terminal.cc
  16. 54
      juci/terminal.h
  17. 60
      juci/window.cc
  18. 6
      juci/window.h

2
juci/CMakeLists.txt

@ -3,7 +3,7 @@ set(project_name juci)
set(module juci_to_python_api) set(module juci_to_python_api)
project (${project_name}) project (${project_name})
add_definitions(-DBOOST_LOG_DYN_LINK) add_definitions(-DBOOST_LOG_DYN_LINK)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++11 -pthread") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -O3 -std=c++11 -pthread -Wall -Wno-reorder")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules/") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules/")
#You are of course using Homebrew: #You are of course using Homebrew:

3
juci/cmake/Modules/FindLibClang.cmake

@ -14,7 +14,8 @@
# Known LLVM release numbers. # Known LLVM release numbers.
# most recent versions come first # most recent versions come first
set(LIBCLANG_KNOWN_LLVM_VERSIONS 3.6 set(LIBCLANG_KNOWN_LLVM_VERSIONS 3.6.1
3.6
3.5.1 3.5.1
3.5.0 #Arch Linux 3.5.0 #Arch Linux
3.5 #LLVM Debian/Ubuntu packages from http://llvm.org/apt/ 3.5 #LLVM Debian/Ubuntu packages from http://llvm.org/apt/

14
juci/config.cc

@ -2,7 +2,7 @@
#include "logging.h" #include "logging.h"
MainConfig::MainConfig() : MainConfig::MainConfig() :
keybindings_cfg_(), source_cfg() { keybindings_cfg(), source_cfg() {
INFO("Reading config file"); INFO("Reading config file");
boost::property_tree::json_parser::read_json("config.json", cfg_); boost::property_tree::json_parser::read_json("config.json", cfg_);
INFO("Config file read"); INFO("Config file read");
@ -55,10 +55,10 @@ void MainConfig::GenerateTerminalCommands() {
boost::property_tree::ptree compile_commands_json = source_json.get_child("compile_commands"); 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"); boost::property_tree::ptree run_commands_json = source_json.get_child("run_commands");
for (auto &i : compile_commands_json) { for (auto &i : compile_commands_json) {
terminal_cfg_.InsertCompileCommand(i.second.get_value<std::string>()); terminal_cfg.compile_commands.emplace_back(i.second.get_value<std::string>());
} }
for (auto &i : run_commands_json) { for (auto &i : run_commands_json) {
terminal_cfg_.SetRunCommand(i.second.get_value<std::string>()); terminal_cfg.run_command=(i.second.get_value<std::string>()); //TODO: run_commands array->one run_command?
} }
} }
@ -68,11 +68,11 @@ void MainConfig::GenerateKeybindings() {
std::ifstream menu_xml("menu.xml"); std::ifstream menu_xml("menu.xml");
if (menu_xml.is_open()) { if (menu_xml.is_open()) {
while (getline(menu_xml, line)) while (getline(menu_xml, line))
keybindings_cfg_.AppendXml(line); keybindings_cfg.AppendXml(line);
} }
boost::property_tree::ptree keys_json = cfg_.get_child("keybindings"); boost::property_tree::ptree keys_json = cfg_.get_child("keybindings");
for (auto &i : keys_json) for (auto &i : keys_json)
keybindings_cfg_.key_map()[i.first] = i.second.get_value<std::string>(); keybindings_cfg.key_map()[i.first] = i.second.get_value<std::string>();
DEBUG("Keybindings fetched"); DEBUG("Keybindings fetched");
} }
@ -82,8 +82,8 @@ void MainConfig::GenerateDirectoryFilter() {
boost::property_tree::ptree ignore_json = dir_json.get_child("ignore"); boost::property_tree::ptree ignore_json = dir_json.get_child("ignore");
boost::property_tree::ptree except_json = dir_json.get_child("exceptions"); boost::property_tree::ptree except_json = dir_json.get_child("exceptions");
for ( auto &i : except_json ) for ( auto &i : except_json )
dir_cfg_.AddException(i.second.get_value<std::string>()); dir_cfg.AddException(i.second.get_value<std::string>());
for ( auto &i : ignore_json ) for ( auto &i : ignore_json )
dir_cfg_.AddIgnore(i.second.get_value<std::string>()); dir_cfg.AddIgnore(i.second.get_value<std::string>());
DEBUG("Directory filter fetched"); DEBUG("Directory filter fetched");
} }

9
juci/config.h

@ -12,10 +12,10 @@
class MainConfig { class MainConfig {
public: public:
Source::Config source_cfg; Source::Config source_cfg;
Terminal::Config terminal_cfg;
Keybindings::Config keybindings_cfg;
Directories::Config dir_cfg;
MainConfig(); MainConfig();
Keybindings::Config& keybindings_cfg() { return keybindings_cfg_; }
Directories::Config& dir_cfg() { return dir_cfg_; }
Terminal::Config& terminal_cfg() { return terminal_cfg_; }
void PrintMenu(); void PrintMenu();
void GenerateSource(); void GenerateSource();
void GenerateKeybindings(); void GenerateKeybindings();
@ -24,8 +24,5 @@ public:
private: private:
boost::property_tree::ptree cfg_; boost::property_tree::ptree cfg_;
boost::property_tree::ptree key_tree_; boost::property_tree::ptree key_tree_;
Keybindings::Config keybindings_cfg_;
Directories::Config dir_cfg_;
Terminal::Config terminal_cfg_;
}; };
#endif #endif

3
juci/config.json

@ -2,6 +2,7 @@
"source": { "source": {
"colors": { "colors": {
"text_color": "black", "text_color": "black",
"search": "orange",
"string": "#CC0000", "string": "#CC0000",
"namespace_ref": "#990099", "namespace_ref": "#990099",
"type": "#0066FF", "type": "#0066FF",
@ -40,8 +41,6 @@
}, },
"keybindings": { "keybindings": {
"new_file": "<control>n", "new_file": "<control>n",
"new_h_file": "<control><alt>h",
"new_cc_file": "<control><alt>c",
"open_folder": "<control><alt>o", "open_folder": "<control><alt>o",
"open_file": "<control>o", "open_file": "<control>o",
"save": "<control>s", "save": "<control>s",

4
juci/directories.cc

@ -43,8 +43,6 @@ list_dirs(const boost::filesystem::path& dir_path,
unsigned row_id) { unsigned row_id) {
boost::filesystem::directory_iterator end_itr; boost::filesystem::directory_iterator end_itr;
unsigned dir_counter = row_id;
unsigned file_counter = 0;
Gtk::TreeModel::Row child; Gtk::TreeModel::Row child;
Gtk::TreeModel::Row row; Gtk::TreeModel::Row row;
DEBUG(""); DEBUG("");
@ -82,7 +80,7 @@ list_dirs(const boost::filesystem::path& dir_path,
int Directories::Controller::count(const std::string path) { int Directories::Controller::count(const std::string path) {
int count = 0; int count = 0;
for (int i = 0; i < path.size(); i++) for (size_t i = 0; i < path.size(); i++)
if (path[i] == '/') if (path[i] == '/')
count++; count++;
return count; return count;

119
juci/entry.cc

@ -1,74 +1,61 @@
#include "entry.h" #include "entry.h"
Entry::View::View() :
view_(Gtk::ORIENTATION_HORIZONTAL), Entry::Entry() :
button_apply_(Gtk::Stock::APPLY), Gtk::Box(Gtk::ORIENTATION_HORIZONTAL),
button_close_(Gtk::Stock::CLOSE), button_apply_set_filename(Gtk::Stock::APPLY),
button_next_("Next"), button_close(Gtk::Stock::CLOSE),
button_prev_("Prev"){ button_next("Next"),
} button_prev("Prev"){
Gtk::Box& Entry::View::view() { entry.signal_activate().connect([this](){
return view_; if(activate) {
} activate();
void Entry::View::OnShowSetFilenName(std::string exstension) {
entry_.set_max_length(50);
entry_.set_text(exstension);
view_.pack_start(entry_);
view_.pack_end(button_close_, Gtk::PACK_SHRINK);
view_.pack_end(button_apply_, Gtk::PACK_SHRINK);
}
void Entry::View::OnShowSearch(std::string current){
entry_.set_max_length(50);
entry_.set_text(current);
view_.pack_start(entry_);
view_.pack_start(button_next_, Gtk::PACK_SHRINK);
view_.pack_start(button_prev_, Gtk::PACK_SHRINK);
view_.pack_end(button_close_, Gtk::PACK_SHRINK);
}
void Entry::View::OnHideEntry(bool is_new_file)
{
view_.remove(entry_);
view_.remove(button_close_);
if(!is_new_file){
view_.remove(button_next_);
view_.remove(button_prev_);
}else{
view_.remove(button_apply_);
} }
});
entry.signal_key_press_event().connect(sigc::mem_fun(*this, &Entry::on_key_press), false);
} }
Entry::Controller::Controller() { bool Entry::on_key_press(GdkEventKey* key) {
} if(key->keyval==GDK_KEY_Escape)
Gtk::Box& Entry::Controller::view() { hide();
return view_.view(); return false;
}
void Entry::Controller::OnShowSetFilenName(std::string exstension) {
view_.OnShowSetFilenName(exstension);
view_.view().show_all();
view_.entry().grab_focus();
view_.entry().set_position(0);
}
void Entry::Controller::OnShowSearch(std::string current){
view_.OnShowSearch(current);
view_.view().show_all();
view_.entry().grab_focus();
view_.entry().set_position(0);
} }
void Entry::Controller::OnHideEntries(bool is_new_file){
view_.OnHideEntry(is_new_file); void Entry::show_set_filename() {
} hide();
std::string Entry::Controller::text(){ entry.set_max_length(50);
return view_.entry().get_text(); entry.set_text("");
} pack_start(entry);
Gtk::Button& Entry::Controller::button_apply(){ pack_end(button_close, Gtk::PACK_SHRINK);
return view_.button_apply(); pack_end(button_apply_set_filename, Gtk::PACK_SHRINK);
} show_all();
Gtk::Button& Entry::Controller::button_close(){ entry.grab_focus();
return view_.button_close(); entry.set_position(0);
} activate=[this](){
Gtk::Button& Entry::Controller::button_next(){ button_apply_set_filename.clicked();
return view_.button_next(); };
} }
Gtk::Button& Entry::Controller::button_prev(){
return view_.button_prev(); void Entry::show_search(const std::string& current){
hide();
entry.set_max_length(50);
entry.set_text(current);
pack_start(entry);
pack_start(button_next, Gtk::PACK_SHRINK);
pack_start(button_prev, Gtk::PACK_SHRINK);
pack_end(button_close, Gtk::PACK_SHRINK);
show_all();
entry.grab_focus();
entry.set_position(0);
activate=[this](){
button_next.clicked();
};
}
void Entry::hide() {
auto widgets=get_children();
for(auto &w: widgets)
remove(*w);
} }
std::string Entry::operator()() {
return entry.get_text();
}

50
juci/entry.h

@ -2,43 +2,21 @@
#define JUCI_ENTRY_H_ #define JUCI_ENTRY_H_
#include <iostream> #include <iostream>
#include <functional>
#include "gtkmm.h" #include "gtkmm.h"
#include "keybindings.h"
namespace Entry {
class View {
public:
View();
Gtk::Box& view();
Gtk::Entry& entry(){return entry_;}
Gtk::Button& button_apply(){return button_apply_;};
Gtk::Button& button_close(){return button_close_;};
Gtk::Button& button_next(){return button_next_;};
Gtk::Button& button_prev(){return button_prev_;};
void OnShowSetFilenName(std::string exstension);
void OnShowSearch(std::string current);
void OnHideEntry(bool is_new_file);
protected:
Gtk::Box view_;
Gtk::Entry entry_;
Gtk::Button button_apply_, button_close_, button_next_, button_prev_;
};
class Controller {
public:
Controller();
Gtk::Box& view();
Gtk::Button& button_apply();
Gtk::Button& button_close();
Gtk::Button& button_next();
Gtk::Button& button_prev();
std::string text();
void OnShowSetFilenName(std::string exstension);
void OnShowSearch(std::string current);
void OnHideEntries(bool is_new_file);
View view_;
};// class controller
} // namespace notebook
class Entry: public Gtk::Box {
public:
Entry();
void show_set_filename();
void show_search(const std::string& current);
void hide();
std::string operator()();
Gtk::Entry entry;
Gtk::Button button_apply_set_filename, button_close, button_next, button_prev;
private:
bool on_key_press(GdkEventKey* key);
std::function<void()> activate;
};
#endif // JUCI_ENTRY_H_ #endif // JUCI_ENTRY_H_

10
juci/juci.cc

@ -16,7 +16,7 @@ int Juci::on_command_line(const Glib::RefPtr<Gio::ApplicationCommandLine> &cmd)
char **argv = cmd->get_arguments(argc); char **argv = cmd->get_arguments(argc);
ctx.parse(argc, argv); ctx.parse(argc, argv);
if(argc>=2) { if(argc>=2) {
for(size_t c=1;c<argc;c++) { for(int c=1;c<argc;c++) {
boost::filesystem::path p=boost::filesystem::canonical(argv[c]); boost::filesystem::path p=boost::filesystem::canonical(argv[c]);
if(boost::filesystem::exists(p)) { if(boost::filesystem::exists(p)) {
if(boost::filesystem::is_regular_file(p)) if(boost::filesystem::is_regular_file(p))
@ -35,12 +35,12 @@ void Juci::on_activate() {
add_window(*window); add_window(*window);
window->show(); window->show();
if(directory!="") { if(directory!="") {
//TODO: use the following instead, window->notebook_.open_directory(directory); //TODO: use the following instead, window->notebook.open_directory(directory);
window->notebook_.project_path=directory; window->notebook.project_path=directory;
window->notebook_.directories.open_folder(directory); window->notebook.directories.open_folder(directory);
} }
for(auto &f: files) for(auto &f: files)
window->notebook_.OnOpenFile(f); window->notebook.OnOpenFile(f);
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {

6
juci/menu.xml

@ -1,11 +1,7 @@
<ui> <ui>
<menubar name='MenuBar'> <menubar name='MenuBar'>
<menu action='FileMenu'> <menu action='FileMenu'>
<menu action='FileNew'> <menuitem action='FileNewFile'/>
<menuitem action='FileNewStandard'/>
<menuitem action='FileNewCC'/>
<menuitem action='FileNewH'/>
</menu>
<menuitem action='FileOpenFile'/> <menuitem action='FileOpenFile'/>
<menuitem action='FileOpenFolder'/> <menuitem action='FileOpenFolder'/>
<menuitem action='FileSave'/> <menuitem action='FileSave'/>

261
juci/notebook.cc

@ -1,28 +1,24 @@
#include <fstream> #include <fstream>
#include "notebook.h" #include "notebook.h"
#include "logging.h" #include "logging.h"
#include <gtksourceview/gtksource.h> // c-library
Notebook::Model::Model() {
cc_extension_ = ".cpp";
h_extension_ = ".hpp";
scrollvalue_ = 50;
}
Notebook::View::View() : notebook_() { Notebook::View::View() {
view_.pack2(notebook_); pack2(notebook);
view_.set_position(120); set_position(120);
} }
Notebook::Controller::Controller(Gtk::Window* window, Notebook::Controller::Controller(Keybindings::Controller& keybindings,
Keybindings::Controller& keybindings, Terminal::Controller& terminal,
Source::Config& source_cfg, Source::Config& source_cfg,
Directories::Config& dir_cfg) : Directories::Config& dir_cfg) :
terminal(terminal),
directories(dir_cfg), directories(dir_cfg),
source_config(source_cfg) { source_config(source_cfg) {
INFO("Create notebook"); INFO("Create notebook");
window_ = window;
refClipboard_ = Gtk::Clipboard::get(); refClipboard_ = Gtk::Clipboard::get();
view().pack1(directories.widget(), true, true); view.pack1(directories.widget(), true, true);
CreateKeybindings(keybindings); CreateKeybindings(keybindings);
INFO("Notebook Controller Success"); INFO("Notebook Controller Success");
} // Constructor } // Constructor
@ -40,31 +36,12 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller
Gtk::Stock::FILE)); Gtk::Stock::FILE));
keybindings.action_group_menu()-> keybindings.action_group_menu()->
add(Gtk::Action::create("FileNewStandard", add(Gtk::Action::create("FileNewFile",
"New empty file"), "New file"),
Gtk::AccelKey(keybindings.config_ Gtk::AccelKey(keybindings.config_
.key_map()["new_file"]), .key_map()["new_file"]),
[this]() { [this]() {
is_new_file_ = true; OnFileNewFile();
OnFileNewEmptyfile();
});
keybindings.action_group_menu()->
add(Gtk::Action::create("FileNewCC",
"New source file"),
Gtk::AccelKey(keybindings.config_
.key_map()["new_cc_file"]),
[this]() {
is_new_file_ = true;
OnFileNewCCFile();
});
keybindings.action_group_menu()->
add(Gtk::Action::create("FileNewH",
"New header file"),
Gtk::AccelKey(keybindings.config_
.key_map()["new_h_file"]),
[this]() {
is_new_file_ = true;
OnFileNewHeaderFile();
}); });
keybindings.action_group_menu()-> keybindings.action_group_menu()->
add(Gtk::Action::create("WindowCloseTab", add(Gtk::Action::create("WindowCloseTab",
@ -80,9 +57,7 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller
Gtk::AccelKey(keybindings.config_ Gtk::AccelKey(keybindings.config_
.key_map()["edit_find"]), .key_map()["edit_find"]),
[this]() { [this]() {
is_new_file_ = false; entry.show_search("");
OnEditSearch();
// TODO(Oyvang) Zalox, Forgi)Create function OnEditFind();
}); });
keybindings.action_group_menu()-> keybindings.action_group_menu()->
add(Gtk::Action::create("EditCopy", add(Gtk::Action::create("EditCopy",
@ -91,7 +66,9 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller
.key_map()["edit_copy"]), .key_map()["edit_copy"]),
[this]() { [this]() {
OnEditCopy(); if (Pages() != 0) {
CurrentTextView().get_buffer()->copy_clipboard(refClipboard_);
}
}); });
keybindings.action_group_menu()-> keybindings.action_group_menu()->
add(Gtk::Action::create("EditCut", add(Gtk::Action::create("EditCut",
@ -99,7 +76,9 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller
Gtk::AccelKey(keybindings.config_ Gtk::AccelKey(keybindings.config_
.key_map()["edit_cut"]), .key_map()["edit_cut"]),
[this]() { [this]() {
OnEditCut(); if (Pages() != 0) {
CurrentTextView().get_buffer()->cut_clipboard(refClipboard_);
}
}); });
keybindings.action_group_menu()-> keybindings.action_group_menu()->
add(Gtk::Action::create("EditPaste", add(Gtk::Action::create("EditPaste",
@ -107,7 +86,9 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller
Gtk::AccelKey(keybindings.config_ Gtk::AccelKey(keybindings.config_
.key_map()["edit_paste"]), .key_map()["edit_paste"]),
[this]() { [this]() {
OnEditPaste(); if (Pages() != 0) {
CurrentTextView().get_buffer()->paste_clipboard(refClipboard_);
}
}); });
keybindings.action_group_menu()-> keybindings.action_group_menu()->
@ -141,36 +122,44 @@ void Notebook::Controller::CreateKeybindings(Keybindings::Controller
INFO("Done Redo"); INFO("Done Redo");
}); });
entry_.view_.entry().signal_activate(). entry.button_apply_set_filename.signal_clicked().connect([this]() {
connect( std::string filename=entry();
[this]() { if(filename!="") {
if (is_new_file_) { if(project_path!="" && !boost::filesystem::path(filename).is_absolute())
//OnNewPage(entry_.text()); //TODO: rewrite new file (the file needs to be created before opened with Source::Controller in order to choose the correct view implementation) filename=project_path+"/"+filename;
entry_.OnHideEntries(is_new_file_); boost::filesystem::path p(filename);
} else { if(boost::filesystem::exists(p)) {
Search(true); //TODO: alert user that file already exists
} }
else {
std::ofstream f(p.string().c_str());
if(f) {
OnOpenFile(boost::filesystem::canonical(p).string());
if(project_path!="")
directories.open_folder(project_path); //TODO: Do refresh instead
}
else {
//TODO: alert user of error creating file
}
f.close();
}
}
entry.hide();
}); });
entry_.button_apply().signal_clicked(). entry.button_close.signal_clicked().
connect(
[this]() {
//OnNewPage(entry_.text()); //TODO: rewrite new file (the file needs to be created before opened with Source::Controller in order to choose the correct view implementation)
entry_.OnHideEntries(is_new_file_);
});
entry_.button_close().signal_clicked().
connect( connect(
[this]() { [this]() {
entry_.OnHideEntries(is_new_file_); entry.hide();
}); });
entry_.button_next().signal_clicked(). entry.button_next.signal_clicked().
connect( connect(
[this]() { [this]() {
Search(true); search(true);
}); });
entry_.button_prev().signal_clicked(). entry.button_prev.signal_clicked().
connect( connect(
[this]() { [this]() {
Search(false); search(false);
}); });
INFO("Notebook signal handlers sucsess"); INFO("Notebook signal handlers sucsess");
} }
@ -181,22 +170,15 @@ Notebook::Controller::~Controller() {
for (auto &i : scrolledtext_vec_) delete i; for (auto &i : scrolledtext_vec_) delete i;
} }
Gtk::Paned& Notebook::Controller::view() {
return view_.view();
}
Gtk::Box& Notebook::Controller::entry_view() {
return entry_.view();
}
void Notebook::Controller::OnOpenFile(std::string path) { void Notebook::Controller::OnOpenFile(std::string path) {
INFO("Notebook open file"); INFO("Notebook open file");
INFO("Notebook create page"); INFO("Notebook create page");
text_vec_.emplace_back(new Source::Controller(source_config, path, project_path)); text_vec_.emplace_back(new Source::Controller(source_config, path, project_path, terminal));
scrolledtext_vec_.push_back(new Gtk::ScrolledWindow()); scrolledtext_vec_.push_back(new Gtk::ScrolledWindow());
editor_vec_.push_back(new Gtk::HBox()); editor_vec_.push_back(new Gtk::HBox());
scrolledtext_vec_.back()->add(*text_vec_.back()->view); scrolledtext_vec_.back()->add(*text_vec_.back()->view);
editor_vec_.back()->pack_start(*scrolledtext_vec_.back(), true, true); editor_vec_.back()->pack_start(*scrolledtext_vec_.back(), true, true);
size_t pos = path.find_last_of("/\\"); size_t pos = path.find_last_of("/\\"); // TODO #windows
std::string filename=path; std::string filename=path;
if(pos!=std::string::npos) if(pos!=std::string::npos)
filename=path.substr(pos+1); filename=path.substr(pos+1);
@ -207,7 +189,7 @@ void Notebook::Controller::OnOpenFile(std::string path) {
//Add star on tab label when the page is not saved: //Add star on tab label when the page is not saved:
text_vec_.back()->buffer()->signal_changed().connect([this]() { text_vec_.back()->buffer()->signal_changed().connect([this]() {
if(text_vec_.at(CurrentPage())->is_saved) { if(text_vec_.at(CurrentPage())->is_saved) {
std::string path=text_vec_.at(CurrentPage())->view->file_path; std::string path=CurrentTextView().file_path;
size_t pos = path.find_last_of("/\\"); size_t pos = path.find_last_of("/\\");
std::string filename=path; std::string filename=path;
if(pos!=std::string::npos) if(pos!=std::string::npos)
@ -233,88 +215,42 @@ void Notebook::Controller::OnCloseCurrentPage() {
editor_vec_.erase(editor_vec_.begin()+page); editor_vec_.erase(editor_vec_.begin()+page);
} }
} }
void Notebook::Controller::OnFileNewEmptyfile() { void Notebook::Controller::OnFileNewFile() {
entry_.OnShowSetFilenName(""); entry.show_set_filename();
}
void Notebook::Controller::OnFileNewCCFile() {
entry_.OnShowSetFilenName(model_.cc_extension_);
}
void Notebook::Controller::OnFileNewHeaderFile() {
entry_.OnShowSetFilenName(model_.h_extension_);
}
void Notebook::Controller::OnEditCopy() {
if (Pages() != 0) {
Buffer(*text_vec_.at(CurrentPage()))->copy_clipboard(refClipboard_);
}
}
void Notebook::Controller::OnEditPaste() {
if (Pages() != 0) {
Buffer(*text_vec_.at(CurrentPage()))->paste_clipboard(refClipboard_);
}
}
void Notebook::Controller::OnEditCut() {
if (Pages() != 0) {
Buffer(*text_vec_.at(CurrentPage()))->cut_clipboard(refClipboard_);
}
}
std::string Notebook::Controller::GetCursorWord() {
INFO("Notebook get cursor word");
int page = CurrentPage();
std::string word;
Gtk::TextIter start, end;
start = Buffer(*text_vec_.at(page))->get_insert()->get_iter();
end = Buffer(*text_vec_.at(page))->get_insert()->get_iter();
if (!end.ends_line()) {
while (!end.ends_word()) {
end.forward_char();
}
}
if (!start.starts_line()) {
while (!start.starts_word()) {
start.backward_char();
}
}
word = Buffer(*text_vec_.at(page))->get_text(start, end);
// TODO(Oyvang) fix selected text
return word;
}
void Notebook::Controller::OnEditSearch() {
search_match_end_ =
Buffer(*text_vec_.at(CurrentPage()))->get_iter_at_offset(0);
entry_.OnShowSearch(GetCursorWord());
} }
void Notebook::Controller::Search(bool forward) { void Notebook::Controller::search(bool forward) {
INFO("Notebook search"); INFO("Notebook search");
int page = CurrentPage(); auto start = CurrentTextView().search_start;
std::string search_word; auto end = CurrentTextView().search_end;
search_word = entry_.text(); // fetch buffer and greate settings
Gtk::TextIter test; auto buffer = CurrentTextView().get_source_buffer();
auto settings = gtk_source_search_settings_new();
if ( !forward ) { // get search text from entry
if ( search_match_start_ == 0 || gtk_source_search_settings_set_search_text(settings, entry().c_str());
search_match_start_.get_line_offset() == 0) { // make sure the search continues
search_match_start_ = Buffer(*text_vec_.at(CurrentPage()))->end(); gtk_source_search_settings_set_wrap_around(settings, true);
} auto context = gtk_source_search_context_new(buffer->gobj(), settings);
search_match_start_. gtk_source_search_context_set_highlight(context, forward);
backward_search(search_word, auto itr = buffer->get_insert()->get_iter();
Gtk::TextSearchFlags::TEXT_SEARCH_TEXT_ONLY | buffer->remove_tag_by_name("search", start ? start : itr, end ? end : itr);
Gtk::TextSearchFlags::TEXT_SEARCH_VISIBLE_ONLY, if (forward) {
search_match_start_, DEBUG("Doing forward search");
search_match_end_); gtk_source_search_context_forward(context,
end ? end.gobj() : itr.gobj(),
start.gobj(),
end.gobj());
} else { } else {
if ( search_match_end_ == 0 ) { DEBUG("Doing backward search");
search_match_end_ = Buffer(*text_vec_.at(CurrentPage()))->begin(); gtk_source_search_context_backward(context,
} start ? start.gobj() : itr.gobj(),
search_match_end_. start.gobj(),
forward_search(search_word, end.gobj());
Gtk::TextSearchFlags::TEXT_SEARCH_TEXT_ONLY |
Gtk::TextSearchFlags::TEXT_SEARCH_VISIBLE_ONLY,
search_match_start_,
search_match_end_);
} }
buffer->apply_tag_by_name("search", start, end);
CurrentTextView().scroll_to(end);
CurrentTextView().search_start = start;
CurrentTextView().search_end = end;
} }
void Notebook::Controller void Notebook::Controller
@ -348,32 +284,15 @@ int Notebook::Controller::CurrentPage() {
return Notebook().get_current_page(); return Notebook().get_current_page();
} }
Glib::RefPtr<Gtk::TextBuffer>
Notebook::Controller::Buffer(Source::Controller &source) {
return source.view->get_buffer();
}
int Notebook::Controller::Pages() { int Notebook::Controller::Pages() {
return Notebook().get_n_pages(); return Notebook().get_n_pages();
} }
Gtk::Notebook& Notebook::Controller::Notebook() { Gtk::Notebook& Notebook::Controller::Notebook() {
return view_.notebook(); return view.notebook;
}
void Notebook::Controller::BufferChangeHandler(Glib::RefPtr<Gtk::TextBuffer>
buffer) {
buffer->signal_end_user_action().connect(
[this]() {
//UpdateHistory();
});
}
std::string Notebook::Controller::CurrentPagePath(){
return text_vec_.at(CurrentPage())->view->file_path;
} }
bool Notebook::Controller:: OnSaveFile() { bool Notebook::Controller:: OnSaveFile() {
std::string path=text_vec_.at(CurrentPage())->view->file_path; std::string path=CurrentTextView().file_path;
return OnSaveFile(path); return OnSaveFile(path);
} }
bool Notebook::Controller:: OnSaveFile(std::string path) { bool Notebook::Controller:: OnSaveFile(std::string path) {
@ -383,7 +302,7 @@ bool Notebook::Controller:: OnSaveFile(std::string path) {
file.open (path); file.open (path);
file << CurrentTextView().get_buffer()->get_text(); file << CurrentTextView().get_buffer()->get_text();
file.close(); file.close();
text_vec_.at(CurrentPage())->view->file_path=path; CurrentTextView().file_path=path;
size_t pos = path.find_last_of("/\\"); size_t pos = path.find_last_of("/\\");
std::string filename=path; std::string filename=path;
if(pos!=std::string::npos) if(pos!=std::string::npos)
@ -398,10 +317,9 @@ bool Notebook::Controller:: OnSaveFile(std::string path) {
std::string Notebook::Controller::OnSaveFileAs(){ std::string Notebook::Controller::OnSaveFileAs(){
INFO("Notebook save as"); INFO("Notebook save as");
Gtk::FileChooserDialog dialog("Please choose a file", Gtk::FileChooserDialog dialog((Gtk::Window&)(*view.get_toplevel()), "Please choose a file",
Gtk::FILE_CHOOSER_ACTION_SAVE); Gtk::FILE_CHOOSER_ACTION_SAVE);
DEBUG("SET TRANSISTEN FPR"); DEBUG("SET TRANSISTEN FPR");
dialog.set_transient_for(*window_);
dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ALWAYS); dialog.set_position(Gtk::WindowPosition::WIN_POS_CENTER_ALWAYS);
dialog.add_button("_Cancel", Gtk::RESPONSE_CANCEL); dialog.add_button("_Cancel", Gtk::RESPONSE_CANCEL);
dialog.add_button("_Save", Gtk::RESPONSE_OK); dialog.add_button("_Save", Gtk::RESPONSE_OK);
@ -413,7 +331,6 @@ std::string Notebook::Controller::OnSaveFileAs(){
case(Gtk::RESPONSE_OK): { case(Gtk::RESPONSE_OK): {
DEBUG("get_filename()"); DEBUG("get_filename()");
std::string path = dialog.get_filename(); std::string path = dialog.get_filename();
unsigned pos = path.find_last_of("/\\");
return path; return path;
} }
case(Gtk::RESPONSE_CANCEL): { case(Gtk::RESPONSE_CANCEL): {
@ -430,11 +347,11 @@ std::string Notebook::Controller::OnSaveFileAs(){
void Notebook::Controller::AskToSaveDialog() { void Notebook::Controller::AskToSaveDialog() {
INFO("AskToSaveDialog"); INFO("AskToSaveDialog");
DEBUG("AskToSaveDialog: Finding file path"); DEBUG("AskToSaveDialog: Finding file path");
Gtk::MessageDialog dialog(*window_, "Save file!", Gtk::MessageDialog dialog((Gtk::Window&)(*view.get_toplevel()), "Save file!",
false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO); false, Gtk::MESSAGE_QUESTION, Gtk::BUTTONS_YES_NO);
dialog.set_secondary_text( dialog.set_secondary_text(
"Do you want to save: " + "Do you want to save: " +
text_vec_.at(CurrentPage())->view->file_path+" ?"); CurrentTextView().file_path+" ?");
DEBUG("AskToSaveDialog: run dialog"); DEBUG("AskToSaveDialog: run dialog");
int result = dialog.run(); int result = dialog.run();

54
juci/notebook.h

@ -11,80 +11,52 @@
#include <map> #include <map>
#include <sigc++/sigc++.h> #include <sigc++/sigc++.h>
#include "clangmm.h" #include "clangmm.h"
#include "keybindings.h"
#include "terminal.h"
namespace Notebook { namespace Notebook {
class Model { class View : public Gtk::Paned {
public:
Model();
std::string cc_extension_;
std::string h_extension_;
int scrollvalue_;
};
class View {
public: public:
View(); View();
Gtk::Paned& view() {return view_;} Gtk::Notebook notebook;
Gtk::Notebook& notebook() {return notebook_; }
protected:
Gtk::Paned view_;
Gtk::Notebook notebook_;
}; };
class Controller { class Controller {
public: public:
Controller(Gtk::Window* window, Keybindings::Controller& keybindings, Controller(Keybindings::Controller& keybindings,
Terminal::Controller& terminal,
Source::Config& config, Source::Config& config,
Directories::Config& dir_cfg); Directories::Config& dir_cfg);
~Controller(); ~Controller();
Glib::RefPtr<Gtk::TextBuffer> Buffer(Source::Controller &source);
Source::View& CurrentTextView(); Source::View& CurrentTextView();
int CurrentPage(); int CurrentPage();
Gtk::Box& entry_view();
Gtk::Notebook& Notebook(); Gtk::Notebook& Notebook();
std::string CurrentPagePath();
void OnBufferChange();
void BufferChangeHandler(Glib::RefPtr<Gtk::TextBuffer>
buffer);
void OnCloseCurrentPage(); void OnCloseCurrentPage();
std::string GetCursorWord(); void OnFileNewFile();
void OnEditCopy();
void OnEditCut();
void OnEditPaste();
void OnEditSearch();
void OnFileNewCCFile();
void OnFileNewEmptyfile();
void OnFileNewHeaderFile();
void OnFileOpenFolder();
bool OnSaveFile(); bool OnSaveFile();
bool OnSaveFile(std::string path); bool OnSaveFile(std::string path);
void OnDirectoryNavigation(const Gtk::TreeModel::Path& path, void OnDirectoryNavigation(const Gtk::TreeModel::Path& path,
Gtk::TreeViewColumn* column); Gtk::TreeViewColumn* column);
void OnOpenFile(std::string filename); void OnOpenFile(std::string filename);
bool ScrollEventCallback(GdkEventScroll* scroll_event);
int Pages(); int Pages();
Gtk::Paned& view(); void search(bool forward);
void Search(bool forward); View view;
std::string OnSaveFileAs(); std::string OnSaveFileAs();
std::string project_path; std::string project_path;
Directories::Controller directories; Directories::Controller directories; //Todo: make private after creating open_directory()
Entry entry;
std::vector<std::unique_ptr<Source::Controller> > text_vec_;
private: private:
void CreateKeybindings(Keybindings::Controller& keybindings); void CreateKeybindings(Keybindings::Controller& keybindings);
void AskToSaveDialog(); void AskToSaveDialog();
Glib::RefPtr<Gtk::Builder> m_refBuilder; Glib::RefPtr<Gtk::Builder> m_refBuilder;
Glib::RefPtr<Gio::SimpleActionGroup> refActionGroup; Glib::RefPtr<Gio::SimpleActionGroup> refActionGroup;
Terminal::Controller& terminal;
Source::Config& source_config; Source::Config& source_config;
View view_;
Model model_;
bool is_new_file_; //TODO: Remove this
Entry::Controller entry_;
std::vector<std::unique_ptr<Source::Controller> > text_vec_;
std::vector<Gtk::ScrolledWindow*> scrolledtext_vec_; std::vector<Gtk::ScrolledWindow*> scrolledtext_vec_;
std::vector<Gtk::HBox*> editor_vec_; std::vector<Gtk::HBox*> editor_vec_;
std::list<Gtk::TargetEntry> listTargets_; std::list<Gtk::TargetEntry> listTargets_;
Gtk::TextIter search_match_end_;
Gtk::TextIter search_match_start_;
Glib::RefPtr<Gtk::Clipboard> refClipboard_; Glib::RefPtr<Gtk::Clipboard> refClipboard_;
Gtk::Window* window_;
}; // class controller }; // class controller
} // namespace Notebook } // namespace Notebook
#endif // JUCI_NOTEBOOK_H_ #endif // JUCI_NOTEBOOK_H_

46
juci/source.cc

@ -27,11 +27,11 @@ config(config), file_path(file_path), project_path(project_path) {
set_smart_home_end(Gsv::SMART_HOME_END_BEFORE); set_smart_home_end(Gsv::SMART_HOME_END_BEFORE);
set_show_line_numbers(config.show_line_numbers); set_show_line_numbers(config.show_line_numbers);
set_highlight_current_line(config.highlight_current_line); set_highlight_current_line(config.highlight_current_line);
sourcefile s(file_path); sourcefile s(file_path);
get_source_buffer()->get_undo_manager()->begin_not_undoable_action(); get_source_buffer()->get_undo_manager()->begin_not_undoable_action();
get_source_buffer()->set_text(s.get_content()); get_source_buffer()->set_text(s.get_content());
get_source_buffer()->get_undo_manager()->end_not_undoable_action(); get_source_buffer()->get_undo_manager()->end_not_undoable_action();
search_start = search_end = this->get_buffer()->end();
} }
string Source::View::get_line(size_t line_number) { string Source::View::get_line(size_t line_number) {
@ -132,10 +132,10 @@ bool Source::View::on_key_press(GdkEventKey* key) {
////////////////// //////////////////
//// ClangView /// //// ClangView ///
////////////////// //////////////////
clang::Index Source::ClangView::clang_index(0, 1); clang::Index Source::ClangView::clang_index(0, 0);
Source::ClangView::ClangView(const Source::Config& config, const std::string& file_path, const std::string& project_path): Source::ClangView::ClangView(const Source::Config& config, const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal):
Source::View(config, file_path, project_path), Source::View(config, file_path, project_path), terminal(terminal),
parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) { parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) {
override_font(Pango::FontDescription(config.font)); override_font(Pango::FontDescription(config.font));
override_background_color(Gdk::RGBA(config.background)); override_background_color(Gdk::RGBA(config.background));
@ -145,11 +145,25 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) {
int start_offset = get_source_buffer()->begin().get_offset(); int start_offset = get_source_buffer()->begin().get_offset();
int end_offset = get_source_buffer()->end().get_offset(); int end_offset = get_source_buffer()->end().get_offset();
init_syntax_highlighting(get_buffer_map(), auto buffer_map=get_buffer_map();
//Remove includes for first parse for initial syntax highlighting
auto& str=buffer_map[file_path];
std::size_t pos=0;
while((pos=str.find("#include", pos))!=std::string::npos) {
auto start_pos=pos;
pos=str.find('\n', pos+8);
if(pos==std::string::npos)
break;
if(start_pos==0 || str[start_pos-1]=='\n') {
str.replace(start_pos, pos-start_pos, pos-start_pos, ' ');
}
pos++;
}
init_syntax_highlighting(buffer_map,
start_offset, start_offset,
end_offset, end_offset,
&ClangView::clang_index); &ClangView::clang_index);
update_syntax(extract_tokens(start_offset, end_offset)); update_syntax(extract_tokens(0, get_source_buffer()->get_text().size())); //TODO: replace get_source_buffer()->get_text().size()
//GTK-calls must happen in main thread, so the parse_thread //GTK-calls must happen in main thread, so the parse_thread
//sends signals to the main thread that it is to call the following functions: //sends signals to the main thread that it is to call the following functions:
@ -162,10 +176,12 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) {
parse_thread_go=true; parse_thread_go=true;
}); });
parsing_in_progress=this->terminal.print_in_progress("Parsing "+file_path);
parse_done.connect([this](){ parse_done.connect([this](){
if(parse_thread_mapped) { if(parse_thread_mapped) {
INFO("Updating syntax"); INFO("Updating syntax");
update_syntax(extract_tokens(0, get_source_buffer()->get_text().size())); update_syntax(extract_tokens(0, get_source_buffer()->get_text().size()));
parsing_in_progress->done("done");
INFO("Syntax updated"); INFO("Syntax updated");
} }
else { else {
@ -203,6 +219,8 @@ parse_thread_go(true), parse_thread_mapped(false), parse_thread_stop(false) {
} }
Source::ClangView::~ClangView() { Source::ClangView::~ClangView() {
//TODO: Is it possible to stop the clang-process in progress?
parsing_in_progress->cancel("canceled");
parse_thread_stop=true; parse_thread_stop=true;
if(parse_thread.joinable()) if(parse_thread.joinable())
parse_thread.join(); parse_thread.join();
@ -239,13 +257,15 @@ std::vector<Source::AutoCompleteData> Source::ClangView::
get_autocomplete_suggestions(int line_number, int column) { get_autocomplete_suggestions(int line_number, int column) {
INFO("Getting auto complete suggestions"); INFO("Getting auto complete suggestions");
std::vector<Source::AutoCompleteData> suggestions; std::vector<Source::AutoCompleteData> suggestions;
auto buffer_map=get_buffer_map(); std::map<std::string, std::string> buffer_map;
buffer_map[file_path]=get_source_buffer()->get_text(get_source_buffer()->begin(), get_source_buffer()->get_insert()->get_iter());
buffer_map[file_path]+="\n";
parsing_mutex.lock(); parsing_mutex.lock();
clang::CodeCompleteResults results(tu_.get(), clang::CodeCompleteResults results(tu_.get(),
file_path, file_path,
buffer_map, buffer_map,
line_number, line_number,
column); column-1);
for (int i = 0; i < results.size(); i++) { for (int i = 0; i < results.size(); i++) {
const vector<clang::CompletionChunk> chunks_ = results.get(i).get_chunks(); const vector<clang::CompletionChunk> chunks_ = results.get(i).get_chunks();
std::vector<AutoCompleteChunk> chunks; std::vector<AutoCompleteChunk> chunks;
@ -268,10 +288,12 @@ get_compilation_commands() {
std::vector<std::string> arguments; std::vector<std::string> arguments;
for (auto &i : cmds) { for (auto &i : cmds) {
std::vector<std::string> lol = i.get_command_as_args(); std::vector<std::string> lol = i.get_command_as_args();
for (int a = 1; a < lol.size()-4; a++) { for (size_t a = 1; a < lol.size()-4; a++) {
arguments.emplace_back(lol[a]); arguments.emplace_back(lol[a]);
} }
} }
if(boost::filesystem::path(file_path).extension()==".h") //TODO: temporary fix for .h-files (parse as c++)
arguments.emplace_back("-xc++");
return arguments; return arguments;
} }
@ -439,7 +461,7 @@ bool Source::ClangView::on_key_press(GdkEventKey* key) {
string line(get_line_before_insert()); string line(get_line_before_insert());
std::smatch sm; std::smatch sm;
if(std::regex_match(line, sm, bracket_regex)) { if(std::regex_match(line, sm, bracket_regex)) {
size_t line_nr=get_source_buffer()->get_insert()->get_iter().get_line(); int line_nr=get_source_buffer()->get_insert()->get_iter().get_line();
if((line_nr+1)<get_source_buffer()->get_line_count()) { if((line_nr+1)<get_source_buffer()->get_line_count()) {
string next_line=get_line(line_nr+1); string next_line=get_line(line_nr+1);
std::smatch sm2; std::smatch sm2;
@ -518,12 +540,12 @@ bool Source::ClangView::on_key_press(GdkEventKey* key) {
// Source::Controller::Controller() // Source::Controller::Controller()
// Constructor for Controller // Constructor for Controller
Source::Controller::Controller(const Source::Config &config, Source::Controller::Controller(const Source::Config &config,
const std::string& file_path, std::string project_path) { const std::string& file_path, std::string project_path, Terminal::Controller& terminal) {
if(project_path=="") { if(project_path=="") {
project_path=boost::filesystem::path(file_path).parent_path().string(); project_path=boost::filesystem::path(file_path).parent_path().string();
} }
if (config.legal_extension(file_path.substr(file_path.find_last_of(".") + 1))) if (config.legal_extension(file_path.substr(file_path.find_last_of(".") + 1)))
view=std::unique_ptr<View>(new ClangView(config, file_path, project_path)); view=std::unique_ptr<View>(new ClangView(config, file_path, project_path, terminal));
else else
view=std::unique_ptr<View>(new GenericView(config, file_path, project_path)); view=std::unique_ptr<View>(new GenericView(config, file_path, project_path));
INFO("Source Controller with childs constructed"); INFO("Source Controller with childs constructed");

8
juci/source.h

@ -10,6 +10,7 @@
#include <string> #include <string>
#include <atomic> #include <atomic>
#include "gtksourceviewmm.h" #include "gtksourceviewmm.h"
#include "terminal.h"
namespace Source { namespace Source {
class Config { class Config {
@ -62,6 +63,7 @@ namespace Source {
std::string get_line_before_insert(); std::string get_line_before_insert();
std::string file_path; std::string file_path;
std::string project_path; std::string project_path;
Gtk::TextIter search_start, search_end;
protected: protected:
const Source::Config& config; const Source::Config& config;
bool on_key_press(GdkEventKey* key); bool on_key_press(GdkEventKey* key);
@ -81,7 +83,7 @@ namespace Source {
class ClangView : public View { class ClangView : public View {
public: public:
ClangView(const Source::Config& config, const std::string& file_path, const std::string& project_path); ClangView(const Source::Config& config, const std::string& file_path, const std::string& project_path, Terminal::Controller& terminal);
~ClangView(); ~ClangView();
// inits the syntax highligthing on file open // inits the syntax highligthing on file open
void init_syntax_highlighting(const std::map<std::string, std::string> void init_syntax_highlighting(const std::map<std::string, std::string>
@ -107,6 +109,8 @@ namespace Source {
std::vector<std::string> get_compilation_commands(); std::vector<std::string> get_compilation_commands();
bool on_key_press(GdkEventKey* key); bool on_key_press(GdkEventKey* key);
bool on_key_release(GdkEventKey* key); bool on_key_release(GdkEventKey* key);
Terminal::Controller& terminal;
std::shared_ptr<Terminal::InProgress> parsing_in_progress;
Glib::Dispatcher parse_done; Glib::Dispatcher parse_done;
Glib::Dispatcher parse_start; Glib::Dispatcher parse_start;
@ -121,7 +125,7 @@ namespace Source {
class Controller { class Controller {
public: public:
Controller(const Source::Config &config, Controller(const Source::Config &config,
const std::string& file_path, std::string project_path); const std::string& file_path, std::string project_path, Terminal::Controller& terminal);
Glib::RefPtr<Gsv::Buffer> buffer(); Glib::RefPtr<Gsv::Buffer> buffer();
bool is_saved = true; bool is_saved = true;

89
juci/terminal.cc

@ -1,36 +1,55 @@
#include "terminal.h" #include "terminal.h"
#include <iostream> #include <iostream>
#include <thread>
#include "logging.h" #include "logging.h"
Terminal::InProgress::InProgress(Controller& terminal, const std::string& start_msg): terminal(terminal), stop(false) {
waiting_print.connect([this](){
this->terminal.print(line_nr-1, ".");
});
start(start_msg);
}
Terminal::Config::Config() { Terminal::InProgress::~InProgress() {
stop=true;
if(wait_thread.joinable())
wait_thread.join();
} }
Terminal::Config::Config(Terminal::Config& original) :
run_command_(original.run_command_){ void Terminal::InProgress::start(const std::string& msg) {
for (auto it = 0; it<original.compile_commands().size(); ++it) { line_nr=this->terminal.print(msg+"...\n");
InsertCompileCommand(original.compile_commands().at(it)); wait_thread=std::thread([this](){
size_t c=0;
while(!stop) {
if(c%100==0)
waiting_print();
std::this_thread::sleep_for(std::chrono::milliseconds(10));
c++;
} }
});
} }
void Terminal::Config::InsertCompileCommand(std::string command){ void Terminal::InProgress::done(const std::string& msg) {
compile_commands_.push_back(command); if(!stop) {
stop=true;
this->terminal.print(line_nr-1, msg);
}
} }
void Terminal::Config::SetRunCommand(std::string command){ void Terminal::InProgress::cancel(const std::string& msg) {
run_command_ = command; if(!stop) {
stop=true;
this->terminal.print(line_nr-1, msg);
}
} }
Terminal::View::View(){ Terminal::View::View(){
scrolledwindow_.add(textview_); text_view.set_editable(false);
scrolledwindow_.set_size_request(-1,150); scrolled_window.add(text_view);
view_.add(scrolledwindow_); add(scrolled_window);
textview_.set_editable(false);
} }
Terminal::Controller::Controller(Terminal::Config& cfg) : Terminal::Controller::Controller(Terminal::Config& cfg) :
config_(cfg) { config(cfg) {
folder_command_ = ""; folder_command_ = "";
} }
@ -44,37 +63,51 @@ void Terminal::Controller::SetFolderCommand( boost::filesystem::path
void Terminal::Controller::Compile(){ void Terminal::Controller::Compile(){
INFO("Terminal: Compile"); INFO("Terminal: Compile");
Terminal().get_buffer()->set_text(""); view.text_view.get_buffer()->set_text("");
DEBUG("Terminal: Compile: running cmake command"); DEBUG("Terminal: Compile: running cmake command");
std::vector<std::string> commands = config().compile_commands(); std::vector<std::string> commands = config.compile_commands;
for (size_t it = 0; it < commands.size(); ++it) { for (size_t it = 0; it < commands.size(); ++it) {
ExecuteCommand(commands.at(it), "r"); ExecuteCommand(commands.at(it), "r");
} }
PrintMessage("\n"); print("\n");
DEBUG("Terminal: Compile: compile done"); DEBUG("Terminal: Compile: compile done");
} }
void Terminal::Controller::Run(std::string executable) { void Terminal::Controller::Run(std::string executable) {
INFO("Terminal: Run"); INFO("Terminal: Run");
PrintMessage("juCi++ execute: " + executable + "\n"); print("juCi++ execute: " + executable + "\n");
DEBUG("Terminal: Compile: running run command: "); DEBUG("Terminal: Compile: running run command: ");
DEBUG_VAR(executable); DEBUG_VAR(executable);
ExecuteCommand("cd "+config().run_command() + "; ./"+executable, "r"); ExecuteCommand("cd "+config.run_command + "; ./"+executable, "r");
PrintMessage("\n"); print("\n");
} }
void Terminal::Controller::PrintMessage(std::string message){ int Terminal::Controller::print(std::string message){
INFO("Terminal: PrintMessage"); INFO("Terminal: PrintMessage");
Terminal().get_buffer()-> view.text_view.get_buffer()->insert(view.text_view.get_buffer()->end(), "> "+message);
insert(Terminal().get_buffer()-> end(),"> "+message); auto mark_end=view.text_view.get_buffer()->create_mark(view.text_view.get_buffer()->end());
view.text_view.scroll_to(mark_end);
return mark_end->get_iter().get_line();
}
void Terminal::Controller::print(int line_nr, std::string message){
INFO("Terminal: PrintMessage at line " << line_nr);
auto iter=view.text_view.get_buffer()->get_iter_at_line(line_nr);
while(!iter.ends_line())
iter++;
view.text_view.get_buffer()->insert(iter, message);
} }
std::shared_ptr<Terminal::InProgress> Terminal::Controller::print_in_progress(std::string start_msg) {
std::shared_ptr<Terminal::InProgress> in_progress=std::shared_ptr<Terminal::InProgress>(new Terminal::InProgress(*this, start_msg));
return in_progress;
}
bool Terminal::Controller::ExistInConsole(std::string string) { bool Terminal::Controller::ExistInConsole(std::string string) {
INFO("Terminal: ExistInConsole"); INFO("Terminal: ExistInConsole");
DEBUG("Terminal: PrintMessage: finding string in buffer"); DEBUG("Terminal: PrintMessage: finding string in buffer");
double pos = Terminal().get_buffer()-> double pos = view.text_view.get_buffer()->
get_text().find(string); get_text().find(string);
if (pos == std::string::npos) return false; if (pos == std::string::npos) return false;
return true; return true;
@ -88,11 +121,11 @@ void Terminal::Controller::ExecuteCommand(std::string command, std::string mode)
std::cout << command << std::endl; std::cout << command << std::endl;
p = popen(command.c_str(), mode.c_str()); p = popen(command.c_str(), mode.c_str());
if (p == NULL) { if (p == NULL) {
PrintMessage("juCi++ ERROR: Failed to run command" + command + "\n"); print("juCi++ ERROR: Failed to run command" + command + "\n");
}else { }else {
char buffer[1028]; char buffer[1028];
while (fgets(buffer, 1028, p) != NULL) { while (fgets(buffer, 1028, p) != NULL) {
PrintMessage(buffer); print(buffer);
} }
pclose(p); pclose(p);
} }

54
juci/terminal.h

@ -2,51 +2,59 @@
#define JUCI_TERMINAL_H_ #define JUCI_TERMINAL_H_
#include <mutex> #include <mutex>
#include <functional>
#include "gtkmm.h" #include "gtkmm.h"
#include <boost/filesystem.hpp> #include <boost/filesystem.hpp>
#include <thread>
#include <atomic>
namespace Terminal { namespace Terminal {
class Config { class Config {
public: public:
Config (); std::vector<std::string> compile_commands;
Config(Terminal::Config& original); std::string run_command;
std::vector<std::string>& compile_commands() { return compile_commands_; }
void InsertCompileCommand(std::string command);
std::string& run_command() { return run_command_; }
void SetRunCommand(std::string command);
private:
std::vector<std::string> compile_commands_;
std::string run_command_;
}; };
class View { class View : public Gtk::HBox {
public: public:
View(); View();
Gtk::HBox& view() {return view_;} Gtk::TextView text_view;
Gtk::TextView& textview() {return textview_;} Gtk::ScrolledWindow scrolled_window;
private:
Gtk::HBox view_;
Gtk::TextView textview_;
Gtk::ScrolledWindow scrolledwindow_;
}; // class view }; // class view
class Controller;
//Temporary solution for displaying functions in progress, and when they are done.
class InProgress {
public:
InProgress(Controller& terminal, const std::string& start_msg);
~InProgress();
void done(const std::string& msg);
void cancel(const std::string& msg);
private:
void start(const std::string& msg);
Controller& terminal;
int line_nr;
std::atomic<bool> stop;
Glib::Dispatcher waiting_print;
std::thread wait_thread;
};
class Controller { class Controller {
public: public:
Controller(Terminal::Config& cfg); Controller(Terminal::Config& cfg);
Gtk::HBox& view() {return view_.view();}
Gtk::TextView& Terminal(){return view_.textview();}
void SetFolderCommand(boost::filesystem::path CMake_path); void SetFolderCommand(boost::filesystem::path CMake_path);
void Run(std::string executable); void Run(std::string executable);
void Compile(); void Compile();
Terminal::Config& config() { return config_; } int print(std::string message);
void PrintMessage(std::string message); void print(int line_nr, std::string message);
std::shared_ptr<InProgress> print_in_progress(std::string start_msg);
Terminal::View view;
private: private:
Terminal::Config config_; Terminal::Config& config;
void ExecuteCommand(std::string command, std::string mode); void ExecuteCommand(std::string command, std::string mode);
bool OnButtonRealeaseEvent(GdkEventKey* key); bool OnButtonRealeaseEvent(GdkEventKey* key);
bool ExistInConsole(std::string string); bool ExistInConsole(std::string string);
Terminal::View view_;
std::string folder_command_; std::string folder_command_;
std::string path_; std::string path_;
const std::string cmake_sucsess = "Build files have been written to:"; const std::string cmake_sucsess = "Build files have been written to:";

60
juci/window.cc

@ -4,13 +4,13 @@
Window::Window() : Window::Window() :
window_box_(Gtk::ORIENTATION_VERTICAL), window_box_(Gtk::ORIENTATION_VERTICAL),
main_config_(), main_config_(),
keybindings_(main_config_.keybindings_cfg()), keybindings_(main_config_.keybindings_cfg),
terminal_(main_config_.terminal_cfg()), terminal(main_config_.terminal_cfg),
notebook_(this,keybindings(), notebook(keybindings(), terminal,
main_config_.source_cfg, main_config_.source_cfg,
main_config_.dir_cfg()), main_config_.dir_cfg),
menu_(keybindings()), menu_(keybindings()),
api_(menu_, notebook_) { api_(menu_, notebook) {
INFO("Create Window"); INFO("Create Window");
set_title("juCi++"); set_title("juCi++");
set_default_size(600, 400); set_default_size(600, 400);
@ -66,16 +66,16 @@ Window::Window() :
SaveFile(); SaveFile();
if (running.try_lock()) { if (running.try_lock()) {
std::thread execute([=]() { std::thread execute([=]() {
std::string path = notebook_.CurrentPagePath(); std::string path = notebook.CurrentTextView().file_path;
int pos = path.find_last_of("/\\"); size_t pos = path.find_last_of("/\\");
if(pos != std::string::npos) { if(pos != std::string::npos) {
path.erase(path.begin()+pos,path.end()); path.erase(path.begin()+pos,path.end());
terminal_.SetFolderCommand(path); terminal.SetFolderCommand(path);
} }
terminal_.Compile(); terminal.Compile();
std::string executable = notebook_.directories. std::string executable = notebook.directories.
GetCmakeVarValue(path,"add_executable"); GetCmakeVarValue(path,"add_executable");
terminal_.Run(executable); terminal.Run(executable);
running.unlock(); running.unlock();
}); });
execute.detach(); execute.detach();
@ -92,13 +92,13 @@ Window::Window() :
SaveFile(); SaveFile();
if (running.try_lock()) { if (running.try_lock()) {
std::thread execute([=]() { std::thread execute([=]() {
std::string path = notebook_.CurrentPagePath(); std::string path = notebook.CurrentTextView().file_path;
int pos = path.find_last_of("/\\"); size_t pos = path.find_last_of("/\\");
if(pos != std::string::npos){ if(pos != std::string::npos){
path.erase(path.begin()+pos,path.end()); path.erase(path.begin()+pos,path.end());
terminal_.SetFolderCommand(path); terminal.SetFolderCommand(path);
} }
terminal_.Compile(); terminal.Compile();
running.unlock(); running.unlock();
}); });
execute.detach(); execute.detach();
@ -111,16 +111,18 @@ Window::Window() :
window_box_.pack_start(menu_.view(), Gtk::PACK_SHRINK); window_box_.pack_start(menu_.view(), Gtk::PACK_SHRINK);
window_box_.pack_start(notebook_.entry_view(), Gtk::PACK_SHRINK); window_box_.pack_start(notebook.entry, Gtk::PACK_SHRINK);
paned_.set_position(300); paned_.set_position(300);
paned_.pack1(notebook_.view(), true, false); paned_.pack1(notebook.view, true, false);
paned_.pack2(terminal_.view(), true, true); paned_.pack2(terminal.view, true, true);
window_box_.pack_end(paned_); window_box_.pack_end(paned_);
show_all_children(); show_all_children();
INFO("Window created"); INFO("Window created");
} // Window constructor } // Window constructor
void Window::OnWindowHide() { void Window::OnWindowHide() {
for(size_t c=0;c<notebook.text_vec_.size();c++)
notebook.OnCloseCurrentPage(); //TODO: This only works on one page at the momemt. Change to notebook.close_page(page_nr);
hide(); hide();
} }
void Window::OnFileOpenFolder() { void Window::OnFileOpenFolder() {
@ -139,8 +141,8 @@ void Window::OnFileOpenFolder() {
case(Gtk::RESPONSE_OK): case(Gtk::RESPONSE_OK):
{ {
std::string project_path=dialog.get_filename(); std::string project_path=dialog.get_filename();
notebook_.project_path=project_path; notebook.project_path=project_path;
notebook_.directories.open_folder(project_path); notebook.directories.open_folder(project_path);
break; break;
} }
case(Gtk::RESPONSE_CANCEL): case(Gtk::RESPONSE_CANCEL):
@ -188,7 +190,7 @@ void Window::OnOpenFile() {
switch (result) { switch (result) {
case(Gtk::RESPONSE_OK): { case(Gtk::RESPONSE_OK): {
std::string path = dialog.get_filename(); std::string path = dialog.get_filename();
notebook_.OnOpenFile(path); notebook.OnOpenFile(path);
break; break;
} }
case(Gtk::RESPONSE_CANCEL): { case(Gtk::RESPONSE_CANCEL): {
@ -201,20 +203,20 @@ void Window::OnOpenFile() {
} }
bool Window::SaveFile() { bool Window::SaveFile() {
if(notebook_.OnSaveFile()) { if(notebook.OnSaveFile()) {
terminal_.PrintMessage("File saved to: " + terminal.print("File saved to: " +
notebook_.CurrentPagePath()+"\n"); notebook.CurrentTextView().file_path+"\n");
return true; return true;
} }
terminal_.PrintMessage("File not saved"); terminal.print("File not saved");
return false; return false;
} }
bool Window::SaveFileAs() { bool Window::SaveFileAs() {
if(notebook_.OnSaveFile(notebook_.OnSaveFileAs())){ if(notebook.OnSaveFile(notebook.OnSaveFileAs())){
terminal_.PrintMessage("File saved to: " + terminal.print("File saved to: " +
notebook_.CurrentPagePath()+"\n"); notebook.CurrentTextView().file_path+"\n");
return true; return true;
} }
terminal_.PrintMessage("File not saved"); terminal.print("File not saved");
return false; return false;
} }

6
juci/window.h

@ -15,13 +15,11 @@ public:
Gtk::Box window_box_; Gtk::Box window_box_;
virtual ~Window() { } virtual ~Window() { }
//private:
MainConfig main_config_; MainConfig main_config_;
Keybindings::Controller keybindings_; Keybindings::Controller keybindings_;
Menu::Controller menu_; Menu::Controller menu_;
Notebook::Controller notebook_; Notebook::Controller notebook;
Terminal::Controller terminal_; Terminal::Controller terminal;
PluginApi api_; PluginApi api_;
Keybindings::Controller& keybindings() { return keybindings_; } Keybindings::Controller& keybindings() { return keybindings_; }

Loading…
Cancel
Save