diff --git a/juci/CMakeLists.txt b/juci/CMakeLists.txt index e4869d0..625d06a 100644 --- a/juci/CMakeLists.txt +++ b/juci/CMakeLists.txt @@ -3,7 +3,7 @@ set(project_name juci) set(module juci_to_python_api) project (${project_name}) -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread") set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_LIST_DIR}/cmake/Modules/") INCLUDE(FindPkgConfig) diff --git a/juci/config.cc b/juci/config.cc index 1c1e454..3e8a264 100644 --- a/juci/config.cc +++ b/juci/config.cc @@ -15,11 +15,14 @@ void MainConfig::GenerateSource() { boost::property_tree::ptree source_json = cfg_.get_child("source"); boost::property_tree::ptree syntax_json = source_json.get_child("syntax"); boost::property_tree::ptree colors_json = source_json.get_child("colors"); - for ( auto &i : syntax_json ) + for ( auto &i : colors_json ) { source_cfg_.InsertTag(i.first, i.second.get_value()); - - for ( auto &i : colors_json ) - source_cfg_.InsertType(i.first, i.second.get_value()); + std::cout << "inserting tag, key: " << i.first << " value: " << i.second.get_value() << std::endl; + } + for ( auto &i : syntax_json ) { + source_cfg_.InsertType(i.first, i.second.get_value()); + std::cout << "inserting type, key: " << i.first << " value: " << i.second.get_value() << std::endl; + } } void MainConfig::GenerateKeybindings() { diff --git a/juci/directories.cc b/juci/directories.cc index adbc795..0a03e53 100644 --- a/juci/directories.cc +++ b/juci/directories.cc @@ -6,7 +6,7 @@ Directories::Controller::Controller(Directories::Config& cfg) : m_ScrolledWindow.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC); } -bool Directories::Controller:: +void Directories::Controller:: open_folder(const boost::filesystem::path& dir_path) { m_refTreeModel = Gtk::TreeStore::create(view()); m_TreeView.set_model(m_refTreeModel); @@ -95,18 +95,29 @@ get_project_name(const boost::filesystem::path& dir_path) { size_t variabel_end = line.find("}", variabel_start); project_name_var = line.substr(variabel_start+1, (variabel_end)-variabel_start-1); + boost::algorithm::trim(project_name_var); + if (variabel_start == std::string::npos) { // not a variabel + variabel_start = line.find("(", 0); + variabel_end = line.find(")", variabel_start); + return line.substr(variabel_start+1, + (variabel_end)-variabel_start-1); + } break; } } std::ifstream ifs2(itr->path().string()); while (std::getline(ifs2, line)) { - if (line.find("set("+project_name_var, 0) != std::string::npos) { + 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 variabel_start = line.find(project_name_var, 0) +project_name_var.length(); size_t variabel_end = line.find(")", variabel_start); - project_name = line.substr(variabel_start, - variabel_end-variabel_start); + project_name = line.substr(variabel_start+1, + variabel_end-variabel_start-1); + boost::algorithm::trim(project_name); return project_name; + } } } break; diff --git a/juci/directories.h b/juci/directories.h index 9a6d3b8..4105e7b 100644 --- a/juci/directories.h +++ b/juci/directories.h @@ -4,14 +4,14 @@ #include #include #include "boost/filesystem.hpp" +#include "boost/algorithm/string.hpp" #include #include #include #include - namespace Directories { - + class Config { public: Config(Config &original); @@ -38,9 +38,8 @@ namespace Directories { Gtk::TreeModelColumn m_col_path; }; - class Model { - }; - + class Model { }; + class Controller { public: Controller(); @@ -49,22 +48,24 @@ namespace Directories { Model& model() { return model_;} Directories::Config& config() { return config_;} Gtk::ScrolledWindow& widget() {return m_ScrolledWindow;} - bool open_folder (const boost::filesystem::path& dir_path); - void list_dirs (const boost::filesystem::path& dir_path, - Gtk::TreeModel::Row &row, unsigned depth); + void open_folder(const boost::filesystem::path& dir_path); + void list_dirs(const boost::filesystem::path& dir_path, + Gtk::TreeModel::Row &row, unsigned depth); std::string get_project_name(const boost::filesystem::path& dir_path); - int count (const std::string path); + int count(const std::string path); - //Child widgets: + // Child widgets: Gtk::Box m_VBox; Gtk::ScrolledWindow m_ScrolledWindow; Gtk::TreeView m_TreeView; Glib::RefPtr m_refTreeModel; bool IsIgnored(std::string path); + private: View view_; Model model_; Directories::Config config_; + protected: void on_treeview_row_activated(const Gtk::TreeModel::Path& path, Gtk::TreeViewColumn* column); diff --git a/juci/notebook.cc b/juci/notebook.cc index 16cbea2..695591b 100644 --- a/juci/notebook.cc +++ b/juci/notebook.cc @@ -4,179 +4,178 @@ Notebook::Model::Model() { cc_extension_ = ".cc"; h_extension_ = ".h"; scrollvalue_ = 50; -}; +} -Notebook::View::View(){ +Notebook::View::View() { view_.pack2(notebook_); view_.set_position(120); } Notebook::Controller::Controller(Keybindings::Controller& keybindings, - Source::Config& source_cfg, + Source::Config& source_cfg, Directories::Config& dir_cfg) : source_config_(source_cfg), - directories_(dir_cfg) { + directories_(dir_cfg) { OnNewPage("juCi++"); refClipboard_ = Gtk::Clipboard::get(); - view().pack1(directories_.widget(),true,true); + view().pack1(directories_.widget(), true, true); CreateKeybindings(keybindings); - -}// Constructor + } // Constructor void Notebook::Controller::CreateKeybindings(Keybindings::Controller - &keybindings){ + &keybindings) { directories().m_TreeView.signal_row_activated() .connect(sigc::mem_fun(*this, &Notebook::Controller::OnDirectoryNavigation)); - + keybindings.action_group_menu()-> add(Gtk::Action::create("FileMenu", - Gtk::Stock::FILE)); + Gtk::Stock::FILE)); keybindings.action_group_menu()-> add(Gtk::Action::create("FileNewStandard", - Gtk::Stock::NEW, - "New empty file", - "Create a new file"), - [this]() { - is_new_file_ = true; - OnFileNewEmptyfile(); - }); + Gtk::Stock::NEW, + "New empty file", + "Create a new file"), + [this]() { + is_new_file_ = true; + OnFileNewEmptyfile(); + }); keybindings.action_group_menu()-> add(Gtk::Action::create("FileNewCC", - "New cc file"), - Gtk::AccelKey(keybindings.config_ - .key_map()["new_cc_file"]), - [this]() { - is_new_file_ = true; - OnFileNewCCFile(); - }); + "New cc 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 h file"), - Gtk::AccelKey(keybindings.config_ - .key_map()["new_h_file"]), - [this]() { - is_new_file_ = true; - OnFileNewHeaderFile(); - }); + "New h file"), + Gtk::AccelKey(keybindings.config_ + .key_map()["new_h_file"]), + [this]() { + is_new_file_ = true; + OnFileNewHeaderFile(); + }); keybindings.action_group_menu()-> add(Gtk::Action::create("WindowCloseTab", - "Close tab"), - Gtk::AccelKey(keybindings.config_ - .key_map()["close_tab"]), - [this]() { - OnCloseCurrentPage(); - }); + "Close tab"), + Gtk::AccelKey(keybindings.config_ + .key_map()["close_tab"]), + [this]() { + OnCloseCurrentPage(); + }); keybindings.action_group_menu()-> add(Gtk::Action::create("EditFind", - Gtk::Stock::FIND), - [this]() { - is_new_file_ = false; - OnEditSearch(); - //TODO(Oyvang, Zalox, Forgi)Create function OnEditFind(); - }); + Gtk::Stock::FIND), + [this]() { + is_new_file_ = false; + OnEditSearch(); + // TODO(Oyvang) Zalox, Forgi)Create function OnEditFind(); + }); keybindings.action_group_menu()-> add(Gtk::Action::create("EditCopy", - Gtk::Stock::COPY), - [this]() { - OnEditCopy(); - }); + Gtk::Stock::COPY), + [this]() { + OnEditCopy(); + }); keybindings.action_group_menu()-> add(Gtk::Action::create("EditCut", - Gtk::Stock::CUT), - [this]() { - OnEditCut(); - }); + Gtk::Stock::CUT), + [this]() { + OnEditCut(); + }); keybindings.action_group_menu()-> add(Gtk::Action::create("EditPaste", - Gtk::Stock::PASTE), - [this]() { - OnEditPaste(); - }); + Gtk::Stock::PASTE), + [this]() { + OnEditPaste(); + }); keybindings.action_group_hidden()-> add(Gtk::Action::create("EditPaste", - Gtk::Stock::PASTE), - [this]() { - OnEditPaste(); - }); + Gtk::Stock::PASTE), + [this]() { + OnEditPaste(); + }); entry_.view_.entry().signal_activate(). connect( - [this]() { - if(is_new_file_){ - OnNewPage(entry_.text()); - entry_.OnHideEntries(is_new_file_); - }else{ - Search(true); - } - }); + [this]() { + if (is_new_file_) { + OnNewPage(entry_.text()); + entry_.OnHideEntries(is_new_file_); + } else { + Search(true); + } + }); entry_.button_apply().signal_clicked(). connect( - [this]() { - OnNewPage(entry_.text()); - entry_.OnHideEntries(is_new_file_); - }); + [this]() { + OnNewPage(entry_.text()); + entry_.OnHideEntries(is_new_file_); + }); entry_.button_close().signal_clicked(). connect( - [this]() { - entry_.OnHideEntries(is_new_file_); - }); + [this]() { + entry_.OnHideEntries(is_new_file_); + }); entry_.button_next().signal_clicked(). connect( - [this]() { - Search(true); - }); + [this]() { + Search(true); + }); entry_.button_prev().signal_clicked(). connect( - [this]() { - Search(false); - }); + [this]() { + Search(false); + }); } -void Notebook::Controller::GeneratePopup(std::vector items){ +void Notebook::Controller::GeneratePopup(std::vector items) { Gtk::ScrolledWindow popup_scroll_; - Gtk::ListViewText listview_(1,false,Gtk::SelectionMode::SELECTION_SINGLE); - Gtk::Dialog popup_("",true); + Gtk::ListViewText listview_(1, false, Gtk::SelectionMode::SELECTION_SINGLE); + Gtk::Dialog popup_("", true); listview_.set_enable_search(false); listview_.set_hscroll_policy(Gtk::ScrollablePolicy::SCROLL_NATURAL); listview_.set_activate_on_single_click(true); listview_.signal_row_activated(). connect([this, &listview_, &popup_](const Gtk::TreeModel::Path& path, - Gtk::TreeViewColumn*) { - std::string t = listview_.get_text(listview_.get_selected()[0]); - CurrentTextView().get_buffer()->insert_at_cursor(t); - popup_.response(Gtk::RESPONSE_DELETE_EVENT); - }); + Gtk::TreeViewColumn*) { + std::string t = listview_.get_text(listview_.get_selected()[0]); + CurrentTextView().get_buffer()->insert_at_cursor(t); + popup_.response(Gtk::RESPONSE_DELETE_EVENT); + }); for (auto &i : items) listview_.append(i); listview_.set_headers_visible(false); - popup_scroll_.add(listview_); + popup_scroll_.add(listview_); popup_.get_vbox()->pack_start(popup_scroll_); - popup_.set_size_request(80,80); + popup_.set_size_request(80, 80); popup_.show_all(); Gdk::Rectangle temp1, temp2; CurrentTextView(). get_cursor_locations( - CurrentTextView(). - get_buffer()->get_insert()-> - get_iter(), temp1, temp2); + CurrentTextView(). + get_buffer()->get_insert()-> + get_iter(), temp1, temp2); int x = temp1.get_x(); int y = temp1.get_y(); text_vec_.at(CurrentPage())-> view().buffer_to_window_coords( - Gtk::TextWindowType::TEXT_WINDOW_WIDGET, - temp2.get_x(), - temp2.get_y(), - x, y); + Gtk::TextWindowType::TEXT_WINDOW_WIDGET, + temp2.get_x(), + temp2.get_y(), + x, y); int widht = Notebook().get_width()-88; int height = Notebook().get_height()-180; - if(x>widht){ + if (x > widht) { x = widht; } - if(y>height){ - y =height; + if (y > height) { + y = height; } popup_.move(x, y+88); popup_.run(); @@ -191,7 +190,7 @@ bool Notebook::Controller::ScrollEventCallback(GdkEventScroll* scroll_event) { scrolledtext_vec_.at(page)-> get_vscrollbar()->get_adjustment(); if ( direction_y != 0 ) { - int dir_val = direction_y==-1?-model_.scrollvalue_:+model_.scrollvalue_; + int dir_val = direction_y == -1 ? -model_.scrollvalue_:+model_.scrollvalue_; adj->set_value(adj->get_value()+dir_val); text_vec_.at(page)->view().set_vadjustment(adj); linenumbers_vec_.at(page)->view().set_vadjustment(adj); @@ -219,7 +218,7 @@ void Notebook::Controller::OnNewPage(std::string name) { Notebook().append_page(*editor_vec_.back(), name); Notebook().show_all_children(); Notebook().set_current_page(Pages()-1); - Notebook().set_focus_child(text_vec_.at(Pages()-1)->view()); + Notebook().set_focus_child(text_vec_.at(Pages()-1)->view()); } void Notebook::Controller::OnOpenFile(std::string path) { @@ -235,7 +234,7 @@ void Notebook::Controller::OnOpenFile(std::string path) { OnBufferChange(); } -void Notebook::Controller::OnCreatePage(){ +void Notebook::Controller::OnCreatePage() { text_vec_.push_back(new Source::Controller(source_config())); linenumbers_vec_.push_back(new Source::Controller(source_config())); scrolledline_vec_.push_back(new Gtk::ScrolledWindow()); @@ -250,14 +249,15 @@ void Notebook::Controller::OnCreatePage(){ scrolledline_vec_.back()->get_vscrollbar()->hide(); linenumbers_vec_.back()->view().set_editable(false); linenumbers_vec_.back()->view().set_sensitive(false); - editor_vec_.back()->pack_start(*scrolledline_vec_.back(),false,false); + editor_vec_.back()->pack_start(*scrolledline_vec_.back(), false, false); editor_vec_.back()->pack_start(*scrolledtext_vec_.back(), true, true); BufferChangeHandler(text_vec_.back()->view().get_buffer()); } void Notebook::Controller::OnCloseCurrentPage() { - //TODO (oyvang, zalox, forgi) Save a temp file, in case you close one you dont want to close? - if(Pages()!=0){ + // TODO(oyvang) zalox, forgi) + // Save a temp file, in case you close one you dont want to close? + if (Pages() != 0) { int page = CurrentPage(); Notebook().remove_page(page); delete text_vec_.at(page); @@ -297,24 +297,24 @@ void Notebook::Controller::OnEditCut() { } } -std::string Notebook::Controller::GetCursorWord(){ +std::string Notebook::Controller::GetCursorWord() { int page = CurrentPage(); std::string word; - Gtk::TextIter start,end; + 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()){ + if (!end.ends_line()) { + while (!end.ends_word()) { end.forward_char(); } } - if(!start.starts_line()) { - while(!start.starts_word()){ + 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 + word = Buffer(text_vec_.at(page))->get_text(start, end); + // TODO(Oyvang) fix selected text return word; } @@ -324,7 +324,7 @@ void Notebook::Controller::OnEditSearch() { entry_.OnShowSearch(GetCursorWord()); } -void Notebook::Controller::Search(bool forward){ +void Notebook::Controller::Search(bool forward) { int page = CurrentPage(); std::string search_word; search_word = entry_.text(); @@ -332,25 +332,25 @@ void Notebook::Controller::Search(bool forward){ if ( !forward ) { if ( search_match_start_ == 0 || - search_match_start_.get_line_offset() == 0) { - search_match_start_= Buffer(text_vec_.at(CurrentPage()))->end(); + search_match_start_.get_line_offset() == 0) { + search_match_start_ = Buffer(text_vec_.at(CurrentPage()))->end(); } search_match_start_. backward_search(search_word, - Gtk::TextSearchFlags::TEXT_SEARCH_TEXT_ONLY | - Gtk::TextSearchFlags::TEXT_SEARCH_VISIBLE_ONLY, - search_match_start_, - search_match_end_); + Gtk::TextSearchFlags::TEXT_SEARCH_TEXT_ONLY | + Gtk::TextSearchFlags::TEXT_SEARCH_VISIBLE_ONLY, + search_match_start_, + search_match_end_); } else { if ( search_match_end_ == 0 ) { - search_match_end_= Buffer(text_vec_.at(CurrentPage()))->begin(); + search_match_end_ = Buffer(text_vec_.at(CurrentPage()))->begin(); } search_match_end_. forward_search(search_word, - Gtk::TextSearchFlags::TEXT_SEARCH_TEXT_ONLY | - Gtk::TextSearchFlags::TEXT_SEARCH_VISIBLE_ONLY, - search_match_start_, - search_match_end_); + Gtk::TextSearchFlags::TEXT_SEARCH_TEXT_ONLY | + Gtk::TextSearchFlags::TEXT_SEARCH_VISIBLE_ONLY, + search_match_start_, + search_match_end_); } } @@ -358,38 +358,38 @@ void Notebook::Controller::OnBufferChange() { int page = CurrentPage(); int text_nr = Buffer(text_vec_.at(page))->get_line_count(); int line_nr = Buffer(linenumbers_vec_.at(page))->get_line_count(); - while (line_nr < text_nr ){ + while (line_nr < text_nr) { line_nr++; Buffer(linenumbers_vec_.at(page))-> insert(Buffer(linenumbers_vec_.at(page))->end(), - "\n"+std::to_string(line_nr)+" "); + "\n"+std::to_string(line_nr)+" "); } - while (line_nr > text_nr ){ - Gtk::TextIter iter = Buffer(linenumbers_vec_.at(page))->get_iter_at_line(line_nr); + while (line_nr > text_nr) { + Gtk::TextIter iter = + Buffer(linenumbers_vec_.at(page))->get_iter_at_line(line_nr); iter.backward_char(); line_nr--; Buffer(linenumbers_vec_.at(page))-> erase(iter, - Buffer(linenumbers_vec_.at(page))->end()); + Buffer(linenumbers_vec_.at(page))->end()); } - if(Buffer(text_vec_.at(page))->get_insert()->get_iter().starts_line() && - Buffer(text_vec_.at(page))->get_insert()->get_iter().get_line() == - Buffer(text_vec_.at(page))->end().get_line()) { - + if (Buffer(text_vec_.at(page))->get_insert()->get_iter().starts_line() && + Buffer(text_vec_.at(page))->get_insert()->get_iter().get_line() == + Buffer(text_vec_.at(page))->end().get_line()) { GdkEventScroll* scroll = new GdkEventScroll; scroll->delta_y = 1.0; scroll->delta_x = 0.0; ScrollEventCallback(scroll); delete scroll; } - Gtk::TextIter start,end; + Gtk::TextIter start, end; std::string word; start = Buffer(text_vec_.at(page))->get_insert()->get_iter(); end = Buffer(text_vec_.at(page))->get_insert()->get_iter(); start.backward_char(); - word = Buffer(text_vec_.at(page))->get_text(start,end); - if( word == "."){ - //TODO(Oyvang,Zalox,Forgie) Remove TEST + word = Buffer(text_vec_.at(page))->get_text(start, end); + if (word == ".") { + // TODO(Forgie) Zalox,Forgie) Remove TEST std::vector TEST; TEST.push_back("toString()"); TEST.push_back("toLower()"); @@ -401,11 +401,12 @@ void Notebook::Controller::OnBufferChange() { } void Notebook::Controller ::OnDirectoryNavigation(const Gtk::TreeModel::Path& path, - Gtk::TreeViewColumn* column) { + Gtk::TreeViewColumn* column) { Gtk::TreeModel::iterator iter = directories().m_refTreeModel->get_iter(path); - if(iter) { + if (iter) { Gtk::TreeModel::Row row = *iter; - boost::filesystem::path fs_path(Glib::ustring(row[directories().view().m_col_path])); + std::string upath = Glib::ustring(row[directories().view().m_col_path]); + boost::filesystem::path fs_path(upath); if (boost::filesystem::is_directory(fs_path)) { directories().m_TreeView.row_expanded(path) ? directories().m_TreeView.collapse_row(path) : @@ -428,7 +429,7 @@ int Notebook::Controller::CurrentPage() { } Glib::RefPtr -Notebook::Controller::Buffer( Source::Controller *source ) { +Notebook::Controller::Buffer(Source::Controller *source) { return source->view().get_buffer(); } @@ -440,10 +441,10 @@ Gtk::Notebook& Notebook::Controller::Notebook() { } void Notebook::Controller::BufferChangeHandler(Glib::RefPtr - buffer) { + buffer) { buffer->signal_changed().connect( - [this]() { - OnBufferChange(); - }); + [this]() { + OnBufferChange(); + }); } diff --git a/juci/notebook.h b/juci/notebook.h index b3fb6f9..4a657fe 100644 --- a/juci/notebook.h +++ b/juci/notebook.h @@ -5,14 +5,10 @@ #include "gtkmm.h" #include "entry.h" #include "source.h" - #include "directories.h" - - #include - - #include - #include - +#include +#include +#include namespace Notebook { class Model { @@ -33,12 +29,11 @@ namespace Notebook { }; class Controller { public: - Controller(Keybindings::Controller& keybindings, - Source::Config& config, + Source::Config& config, Directories::Config& dir_cfg); ~Controller(); - Glib::RefPtr Buffer( Source::Controller *source); + Glib::RefPtr Buffer(Source::Controller *source); Gtk::TextView& CurrentTextView(); int CurrentPage(); Gtk::Box& entry_view(); @@ -62,7 +57,7 @@ namespace Notebook { bool ScrollEventCallback(GdkEventScroll* scroll_event); int Pages(); - Directories::Controller& directories() { return directories_; } + Directories::Controller& directories() { return directories_; } Gtk::Paned& view(); void GeneratePopup(std::vector items); @@ -70,9 +65,11 @@ namespace Notebook { void Search(bool forward); const Source::Config& source_config() { return source_config_; } + protected: void BufferChangeHandler(Glib::RefPtr buffer); - private: + + private: void CreateKeybindings(Keybindings::Controller& keybindings); Glib::RefPtr m_refBuilder; Glib::RefPtr refActionGroup; @@ -91,5 +88,4 @@ namespace Notebook { Glib::RefPtr refClipboard_; }; // class controller } // namespace Notebook - #endif // JUCI_NOTEBOOK_H_ diff --git a/juci/source.cc b/juci/source.cc index 95307e2..2117b79 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -5,21 +5,33 @@ #include #include + +#define log( var ) \ + std::cout << "source.cc (" << __LINE__ << ") " << #var << std::endl + +Source::Location:: +Location(int line_number, int column_offset) : + line_number_(line_number), column_offset_(column_offset) { } + +Source::Location:: +Location(const Source::Location &org) : + line_number_(org.line_number_), column_offset_(org.column_offset_) { } + +Source::Range:: +Range(const Location &start, const Location &end, int kind) : + start_(start), end_(end), kind_(kind) { } + +Source::Range:: +Range(const Source::Range &org) : + start_(org.start_), end_(org.end_), kind_(org.kind_) { } + + ////////////// //// View //// ////////////// Source::View::View() { - // std::cout << "View constructor run" << std::endl; override_font(Pango::FontDescription("Monospace")); } -// Source::View::UpdateLine -// returns the new line -string Source::View::UpdateLine() { - Gtk::TextIter line(get_buffer()->get_insert()->get_iter()); - // std::cout << line.get_line() << std::endl; - // for each word --> check what it is --> apply appropriate tag - return ""; -} string Source::View::GetLine(const Gtk::TextIter &begin) { Gtk::TextIter end(begin); @@ -32,47 +44,11 @@ string Source::View::GetLine(const Gtk::TextIter &begin) { // Applies theme in textview void Source::View::ApplyConfig(const Source::Config &config) { for (auto &item : config.tagtable()) { - // std::cout << "Apply: f: " << item.first << ", s: " << - // item.second << std::endl; get_buffer()->create_tag(item.first)->property_foreground() = item.second; } } -void Source::View::OnOpenFile(std::vector &locations, - const Source::Config &config) { - /* ApplyConfig(config); - Glib::RefPtr buffer = get_buffer(); - for (auto &loc : locations) { - string type = std::to_string(loc.kind()); - try { - config.typetable().at(type); - } catch (std::exception) { - continue; - } - - int linum_start = loc.line_number_begin(); - int linum_end = loc.line_number_end(); - int begin = loc.begin(); - int end = loc.end(); - if (end < 0) end = 0; - if (begin < 0) begin = 0; - - // std::cout << "Libc: "; - // std::cout << "type: " << type; - // std::cout << " linum_s: " << linum_start+1 << " linum_e: " << linum_end+1; - // std::cout << ", begin: " << begin << ", end: " << end << std::endl; - Gtk::TextIter begin_iter = buffer->get_iter_at_line_offset(linum_start, - begin); - Gtk::TextIter end_iter = buffer->get_iter_at_line_offset(linum_end, end); - // std::cout << get_buffer()->get_text(begin_iter, end_iter) << std::endl; - if (begin_iter.get_line() == end_iter.get_line()) { - buffer->apply_tag_by_name(config.typetable().at(type), - begin_iter, end_iter); - } - } - */ -} // Source::View::Config::Config(Config &config) @@ -82,7 +58,7 @@ Source::Config::Config(const Source::Config &original) { SetTypeTable(original.typetable()); } -Source::Config::Config(){} +Source::Config::Config() {} // Source::View::Config::tagtable() // returns a const refrence to the tagtable @@ -96,14 +72,13 @@ const std::unordered_map& Source::Config::typetable() const { return typetable_; } - void Source::Config::InsertTag(const string &key, const string &value) { tagtable_[key] = value; } // Source::View::Config::SetTagTable() // sets the tagtable for the view -void Source::Config::SetTypeTable( - const std::unordered_map &typetable) { +void Source::Config:: +SetTypeTable(const std::unordered_map &typetable) { typetable_ = typetable; } @@ -112,8 +87,8 @@ void Source::Config::InsertType(const string &key, const string &value) { } // Source::View::Config::SetTagTable() // sets the tagtable for the view -void Source::Config::SetTagTable( - const std::unordered_map &tagtable) { +void Source::Config:: +SetTagTable(const std::unordered_map &tagtable) { tagtable_ = tagtable; } @@ -124,22 +99,129 @@ Source::Model::Model(const Source::Config &config) : config_(config) { } -Source::Config& Source::Model::config() { +void Source::Model:: +InitSyntaxHighlighting(const std::string &filepath, + const std::string &project_path, + const std::string &text, + int start_offset, + int end_offset) { + set_file_path(filepath); + set_project_path(project_path); + std::vector arguments = get_compilation_commands(); + tu_ = clang::TranslationUnit(true, + filepath, + arguments, + text); +} + +// Source::View::UpdateLine +void Source::View:: +OnLineEdit(const std::vector &locations, + const Source::Config &config) { + OnUpdateSyntax(locations, config); +} + +// Source::Model::UpdateLine +int Source::Model:: +ReParse(const std::string &buffer) { + return tu_.ReparseTranslationUnit(file_path(), buffer); +} + + +// Source::Controller::OnLineEdit() +// fired when a line in the buffer is edited +void Source::Controller::OnLineEdit() { } + +// sets the filepath for this mvc +void Source::Model:: +set_file_path(const std::string &file_path) { + file_path_ = file_path; +} +// sets the project path for this mvc +void Source::Model:: +set_project_path(const std::string &project_path) { + project_path_ = project_path; +} +// gets the file_path member +const std::string& Source::Model::file_path() const { + return file_path_; +} +// gets the project_path member +const std::string& Source::Model::project_path() const { + return project_path_; +} +// gets the config member +const Source::Config& Source::Model::config() const { return config_; } -const string Source::Model::filepath() { - return filepath_; +std::vector Source::Model:: +get_compilation_commands() { + clang::CompilationDatabase db(project_path()+"/"); + clang::CompileCommands commands(file_path(), &db); + std::vector cmds = commands.get_commands(); + std::vector arguments; + for (auto &i : cmds) { + std::vector lol = i.get_command_as_args(); + for (int a = 1; a < lol.size()-4; a++) { + arguments.emplace_back(lol[a].c_str()); + } + } + return arguments; } -void Source::Model::SetFilePath(const string &filepath) { - filepath_ = filepath; +std::vector Source::Model:: +ExtractTokens(int start_offset, int end_offset) { + std::vector ranges; + clang::SourceLocation start(&tu_, file_path(), start_offset); + clang::SourceLocation end(&tu_, file_path(), end_offset); + clang::SourceRange range(&start, &end); + clang::Tokens tokens(&tu_, &range); + std::vector tks = tokens.tokens(); + for (auto &token : tks) { + switch (token.kind()) { + case 0: HighlightCursor(&token, &ranges); break; // PunctuationToken + case 1: HighlightToken(&token, &ranges, 702); break; // KeywordToken + case 2: HighlightCursor(&token, &ranges); break; // IdentifierToken + case 3: HighlightToken(&token, &ranges, 109); break; // LiteralToken + case 4: HighlightToken(&token, &ranges, 705); break; // CommentToken + } + } + return ranges; } void Source::Model:: -SetSourceLocations(const std::vector &locations) { - locations_ = locations; +HighlightCursor(clang::Token *token, + std::vector *source_ranges) { + clang::SourceLocation location = token->get_source_location(&tu_); + clang::Cursor cursor(&tu_, &location); + clang::SourceRange range(&cursor); + clang::SourceLocation begin(&range, true); + clang::SourceLocation end(&range, false); + unsigned begin_line_num, begin_offset, end_line_num, end_offset; + begin.get_location_info(NULL, &begin_line_num, &begin_offset, NULL); + end.get_location_info(NULL, &end_line_num, &end_offset, NULL); + source_ranges->emplace_back(Source::Location(begin_line_num, + begin_offset), + Source::Location(end_line_num, + end_offset), (int) cursor.kind()); +} +void Source::Model:: +HighlightToken(clang::Token *token, + std::vector *source_ranges, + int token_kind) { + clang::SourceRange range = token->get_source_range(&tu_); + unsigned begin_line_num, begin_offset, end_line_num, end_offset; + clang::SourceLocation begin(&range, true); + clang::SourceLocation end(&range, false); + begin.get_location_info(NULL, &begin_line_num, &begin_offset, NULL); + end.get_location_info(NULL, &end_line_num, &end_offset, NULL); + source_ranges->emplace_back(Source::Location(begin_line_num, + begin_offset), + Source::Location(end_line_num, + end_offset), token_kind); } + //////////////////// //// Controller //// //////////////////// @@ -148,9 +230,6 @@ SetSourceLocations(const std::vector &locations) { // Constructor for Controller Source::Controller::Controller(const Source::Config &config) : model_(config) { - view().get_buffer()->signal_changed().connect([this](){ - this->OnLineEdit(); - }); } // Source::Controller::view() @@ -163,57 +242,114 @@ Source::View& Source::Controller::view() { Source::Model& Source::Controller::model() { return model_; } -// Source::Controller::OnLineEdit() -// fired when a line in the buffer is edited -void Source::Controller::OnLineEdit() { - view().UpdateLine(); -} void Source::Controller::OnNewEmptyFile() { string filename("/tmp/juci_t"); sourcefile s(filename); - model().SetFilePath(filename); + model().set_file_path(filename); + model().set_project_path(filename); s.save(""); } +string extract_file_path(const std::string &file_path) { + return file_path.substr(0, file_path.find_last_of('/')); +} + +std::vector extentions() { + return {".h", ".cc", ".cpp", ".hpp"}; +} + +bool check_extention(const std::string &file_path) { + std::string extention = file_path.substr(file_path.find_last_of('.'), + file_path.size()); + for (auto &ex : extentions()) { + if (extention == ex) { + return true; + } + } + return false; +} + +void Source::View::OnUpdateSyntax(const std::vector &ranges, + const Source::Config &config) { + if (ranges.empty() || ranges.size() == 0) { + return; + } + Glib::RefPtr buffer = get_buffer(); + buffer->remove_all_tags(buffer->begin(), buffer->end()); + for (auto &range : ranges) { + string type = std::to_string(range.kind()); + try { + config.typetable().at(type); + } catch (std::exception) { + continue; + } + int linum_start = range.start().line_number()-1; + int linum_end = range.end().line_number()-1; + int begin = range.start().column_offset()-1; + int end = range.end().column_offset()-1; + + if (end < 0) end = 0; + if (begin < 0) begin = 0; + Gtk::TextIter begin_iter = + buffer->get_iter_at_line_offset(linum_start, begin); + Gtk::TextIter end_iter = + buffer->get_iter_at_line_offset(linum_end, end); + buffer->apply_tag_by_name(config.typetable().at(type), + begin_iter, end_iter); + } +} + void Source::Controller::OnOpenFile(const string &filepath) { sourcefile s(filepath); buffer()->set_text(s.get_content()); int start_offset = buffer()->begin().get_offset(); int end_offset = buffer()->end().get_offset(); - std::string project_path = - filepath.substr(0, filepath.find_last_of('/')); - - clang::CompilationDatabase db(project_path); - clang::CompileCommands commands(filepath, &db); - std::vector cmds = commands.get_commands(); - std::vector arguments; - for (auto &i : cmds) { - std::vector lol = i.get_command_as_args(); - for (int a = 1; a < lol.size()-4; a++) { - arguments.emplace_back(lol[a].c_str()); - } + if (check_extention(filepath)) { + view().ApplyConfig(model().config()); + model().InitSyntaxHighlighting(filepath, + extract_file_path(filepath), + buffer()->get_text().raw(), + start_offset, + end_offset); + view().OnUpdateSyntax(model().ExtractTokens(start_offset, end_offset), + model().config()); } - clang::TranslationUnit tu(true, filepath, arguments); - clang::SourceLocation start(&tu, filepath, start_offset); - clang::SourceLocation end(&tu, filepath, end_offset); - clang::SourceRange range(&start, &end); - clang::Tokens tokens(&tu, &range); - std::vector tks = tokens.tokens(); - for (auto &t : tks) { - clang::SourceLocation loc = t.get_source_location(&tu); - unsigned line; - unsigned column; - loc.get_location_info(NULL, &line, &column, NULL); - } + buffer()->signal_end_user_action().connect([this]() { + if (!go) { + std::thread parse([this]() { + if (parsing.try_lock()) { + while (true) { + const std::string raw = buffer()->get_text().raw(); + if (model().ReParse(raw) == 0 && + raw == buffer()->get_text().raw()) { + syntax.lock(); + go = true; + syntax.unlock(); + break; + } + } + parsing.unlock(); + } + }); + parse.detach(); + } + }); - // std::cout << t.elapsed().user << std::endl; - // model().SetSourceLocations(tu.getSourceLocations()); - // view().OnOpenFile(model().getSourceLocations(), model().theme()); -} + buffer()->signal_begin_user_action().connect([this]() { + if (go) { + syntax.lock(); + view(). + OnUpdateSyntax(model().ExtractTokens(0, buffer()->get_text().size()), + model().config()); + go = false; + syntax.unlock(); + } + }); +} Glib::RefPtr Source::Controller::buffer() { return view().get_buffer(); } diff --git a/juci/source.h b/juci/source.h index 9b5406d..67b3d9a 100644 --- a/juci/source.h +++ b/juci/source.h @@ -1,11 +1,13 @@ #ifndef JUCI_SOURCE_H_ #define JUCI_SOURCE_H_ - +#include #include #include #include #include "gtkmm.h" #include "clangmm.h" +#include +#include using std::string; @@ -27,58 +29,93 @@ namespace Source { std::unordered_map typetable_; string background_; }; // class Config - /* - class BufferLocation { - BufferLocation(const BufferLocation &location); - BufferLocation(int, int); - int line_number() { return line_number_; } - int column_number() { return column_offset_; } + + class Location { + public: + Location(const Location &location); + Location(int line_number, int column_offset); + int line_number() const { return line_number_; } + int column_offset() const { return column_offset_; } private: int line_number_; int column_offset_; }; - class BufferRange { - BufferRange(const BufferLocation &start, const BufferLocation &end) : - start_(start), end_(end) { } + class Range { + public: + Range(const Location &start, const Location &end, int kind); + Range(const Range &org); + const Location& start() const { return start_; } + const Location& end() const { return end_; } + int kind() const { return kind_; } + void to_stream() const { + std::cout << "range: [" << start_.line_number()-1; + std::cout << ", " << end_.line_number()-1 << "] "; + std::cout << "<" << start_.column_offset()-1; + std::cout << ", " << end_.column_offset()-1 << ">"; + std::cout << std::endl; + } private: - BufferLocation start_; - BufferLocation end_; - };*/ - + Location start_; + Location end_; + int kind_; + }; class View : public Gtk::TextView { public: View(); - string UpdateLine(); void ApplyConfig(const Config &config); - void OnOpenFile(std::vector &locations, + void OnLineEdit(const std::vector &locations, const Config &config); + void OnUpdateSyntax(const std::vector &locations, + const Config &config); + private: string GetLine(const Gtk::TextIter &begin); }; // class View class Model{ public: - Model(const Source::Config &config); - //Model(); - Config& config(); - const string filepath(); - void SetFilePath(const string &filepath); - void SetSourceLocations( const std::vector &locations); - std::vector& getSourceLocations() { - return locations_; - } + // constructor for Source::Model + explicit Model(const Source::Config &config); + // inits the syntax highligthing on file open + void InitSyntaxHighlighting(const std::string &filepath, + const std::string &project_path, + const std::string &text, + int start_offset, + int end_offset); + // sets the filepath for this mvc + void set_file_path(const string &file_path); + // sets the project path for this mvc + void set_project_path(const string &project_path); + + // gets the file_path member + const string& file_path() const; + // gets the project_path member + const string& project_path() const; + // gets the config member + const Config& config() const; + ~Model() { } + int ReParse(const std::string &buffer); + std::vector ExtractTokens(int, int); private: - Source::Config config_; - string filepath_; - std::vector locations_; + Config config_; + string file_path_; + string project_path_; + clang::TranslationUnit tu_; + void HighlightToken(clang::Token *token, + std::vector *source_ranges, + int token_kind); + void HighlightCursor(clang::Token *token, + std::vector *source_ranges); + + std::vector get_compilation_commands(); }; class Controller { public: - Controller(const Source::Config &config); + explicit Controller(const Source::Config &config); Controller(); View& view(); Model& model(); @@ -89,6 +126,10 @@ namespace Source { private: void OnLineEdit(); void OnSaveFile(); + std::mutex syntax; + std::mutex parsing; + bool go = false; + protected: View view_; Model model_;