diff --git a/juci/source.cc b/juci/source.cc index cd8ff80..30a0e93 100644 --- a/juci/source.cc +++ b/juci/source.cc @@ -4,11 +4,10 @@ #include #include #include -#include -#define DBGVAR( os, var ) \ - (os) << "DBG: " << __FILE__ << "(" << __LINE__ << ") " \ - << #var << " = [" << (var) << "]" << std::endl + +#define log( var ) \ + std::cout << "source.cc (" << __LINE__ << ") " << #var << std::endl Source::Location:: Location(int line_number, int column_offset) : @@ -45,44 +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()) { - if (get_buffer()->get_tag_table()->lookup(item.first) == 0) - get_buffer()->create_tag(item.first)->property_foreground() = item.second; + get_buffer()->create_tag(item.first)->property_foreground() = item.second; } } -void Source::View::OnUpdateSyntax(const std::vector &ranges, - const Source::Config &config) { - get_buffer()->remove_all_tags(get_buffer()->begin(), - get_buffer()->end()); - ApplyConfig(config); - Glib::RefPtr buffer = get_buffer(); - 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); - 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) @@ -134,7 +100,7 @@ Source::Model::Model(const Source::Config &config) : } void Source::Model:: -initSyntaxHighlighting(const std::string &filepath, +InitSyntaxHighlighting(const std::string &filepath, const std::string &project_path, const std::string &text, int start_offset, @@ -146,29 +112,28 @@ initSyntaxHighlighting(const std::string &filepath, filepath, arguments, text); - extractTokens(start_offset, end_offset); } // Source::View::UpdateLine -void Source::View::OnLineEdit(const std::vector &locations, - const Source::Config &config) { +void Source::View:: +OnLineEdit(const std::vector &locations, + const Source::Config &config) { + log("before onupdatesyntax"); OnUpdateSyntax(locations, config); + log("after onupdatesyntax"); } // Source::Model::UpdateLine -void Source::Model::OnLineEdit(const std::string &buffer) { - int i = tu_.ReparseTranslationUnit(file_path(), buffer); - set_ranges(std::vector()); - extractTokens(0, buffer.size()); +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() { - model().OnLineEdit(buffer()->get_text()); - view().OnLineEdit(model().source_ranges(), - model().config()); + } // sets the filepath for this mvc @@ -181,11 +146,6 @@ void Source::Model:: set_project_path(const std::string &project_path) { project_path_ = project_path; } -// sets the ranges for keywords in this mvc -void Source::Model:: -set_ranges(const std::vector &source_ranges) { - source_ranges_ = source_ranges; -} // gets the file_path member const std::string& Source::Model::file_path() const { return file_path_; @@ -194,10 +154,6 @@ const std::string& Source::Model::file_path() const { const std::string& Source::Model::project_path() const { return project_path_; } -// gets the ranges member -const std::vector& Source::Model::source_ranges() const { - return source_ranges_; -} // gets the config member const Source::Config& Source::Model::config() const { return config_; @@ -218,8 +174,9 @@ get_compilation_commands() { return arguments; } -void Source::Model:: -extractTokens(int start_offset, int end_offset) { +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); @@ -227,43 +184,44 @@ extractTokens(int start_offset, int end_offset) { std::vector tks = tokens.tokens(); for (auto &token : tks) { switch (token.kind()) { - case 0: PunctuationToken(&token); break; // A tkn with punctation - case 1: KeywordToken(&token); break; // A language keyword. - case 2: IdentifierToken(&token); break; // An identifier, not a keyword - case 3: LiteralToken(&token); break; // A num, string, or char literal - case 4: CommentToken(&token); break; // A comment token + 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 } } + log("returns ranges"); + return ranges; } -void Source::Model::LiteralToken(clang::Token *token) { - HighlightToken(token, 109);; -} - -void Source::Model::CommentToken(clang::Token *token) { - HighlightToken(token, 705); -} - -void Source::Model::IdentifierToken(clang::Token *token) { - -} - -void Source::Model::KeywordToken(clang::Token *token) { - HighlightToken(token, 702);; -} - -void Source::Model::PunctuationToken(clang::Token *token) { +void Source::Model:: +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, int token_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, + source_ranges->emplace_back(Source::Location(begin_line_num, begin_offset), Source::Location(end_line_num, end_offset), token_kind); @@ -318,6 +276,47 @@ bool check_extention(const std::string &file_path) { return false; } +void Source::View::OnUpdateSyntax(const std::vector &ranges, + const Source::Config &config) { + if (ranges.empty() || ranges.size() == 0) { + log("ranges empty"); + return; + } + Glib::RefPtr buffer = get_buffer(); + log("after getting buffer"); + int i = 0; + log("after i int"); + std::cout << "rangeslengde: " << ranges.size() << std::endl; + 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->remove_all_tags(begin_iter, end_iter); + if (begin_iter.get_line() == end_iter.get_line()) { + buffer->apply_tag_by_name(config.typetable().at(type), + begin_iter, end_iter); + } + i++; + } + log("End of onupdatesyntax"); +} + void Source::Controller::OnOpenFile(const string &filepath) { sourcefile s(filepath); buffer()->set_text(s.get_content()); @@ -325,18 +324,50 @@ void Source::Controller::OnOpenFile(const string &filepath) { int end_offset = buffer()->end().get_offset(); if (check_extention(filepath)) { - model().initSyntaxHighlighting(filepath, + view().ApplyConfig(model().config()); + model().InitSyntaxHighlighting(filepath, extract_file_path(filepath), - buffer()->get_text(), + buffer()->get_text().raw(), start_offset, end_offset); - view().OnUpdateSyntax(model().source_ranges(), model().config()); + view().OnUpdateSyntax(model().ExtractTokens(start_offset, end_offset), + model().config()); } - view().get_buffer()->signal_changed().connect([this]() { - OnLineEdit(); + + buffer()->signal_end_user_action().connect([this]() { + if (!go) { + std::thread parse([this]() { + if(parsing.try_lock()) { + const std::string raw = buffer()->get_text().raw(); + int b = model().ReParse(raw); + if (b == 0) { + if (raw == buffer()->get_text().raw()) { + log("alike!"); + syntax.lock(); + go = true; + syntax.unlock(); + } else { + log("buffer changed"); + } + } + parsing.unlock(); + } + }); + parse.detach(); + } }); -} + 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 3e593c6..67b3d9a 100644 --- a/juci/source.h +++ b/juci/source.h @@ -6,6 +6,8 @@ #include #include "gtkmm.h" #include "clangmm.h" +#include +#include using std::string; @@ -46,6 +48,13 @@ namespace Source { 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: Location start_; Location end_; @@ -55,12 +64,12 @@ namespace Source { class View : public Gtk::TextView { public: View(); - void ApplyConfig(const Config &config); void OnLineEdit(const std::vector &locations, const Config &config); void OnUpdateSyntax(const std::vector &locations, - const Config &config); + const Config &config); + private: string GetLine(const Gtk::TextIter &begin); }; // class View @@ -70,7 +79,7 @@ namespace Source { // constructor for Source::Model explicit Model(const Source::Config &config); // inits the syntax highligthing on file open - void initSyntaxHighlighting(const std::string &filepath, + void InitSyntaxHighlighting(const std::string &filepath, const std::string &project_path, const std::string &text, int start_offset, @@ -79,33 +88,28 @@ namespace Source { void set_file_path(const string &file_path); // sets the project path for this mvc void set_project_path(const string &project_path); - // sets the ranges for keywords in this mvc - void set_ranges(const std::vector &ranges); // gets the file_path member const string& file_path() const; // gets the project_path member const string& project_path() const; - // gets the ranges member - const std::vector& source_ranges() const; // gets the config member const Config& config() const; ~Model() { } - void OnLineEdit(const std::string &buffer); + int ReParse(const std::string &buffer); + std::vector ExtractTokens(int, int); private: Config config_; string file_path_; string project_path_; - std::vector source_ranges_; clang::TranslationUnit tu_; - void extractTokens(int, int); - void LiteralToken(clang::Token *token); - void CommentToken(clang::Token *token); - void IdentifierToken(clang::Token *token); - void KeywordToken(clang::Token *token); - void PunctuationToken(clang::Token *token); - void HighlightToken(clang::Token *token, int token_kind); + 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(); }; @@ -122,6 +126,9 @@ namespace Source { private: void OnLineEdit(); void OnSaveFile(); + std::mutex syntax; + std::mutex parsing; + bool go = false; protected: View view_;