2012-08-17 51 views
1

我正在嘗試Glib :: Regex和Gtk :: TextView與Gtk :: TextBuffer-s,並且我正在嘗試使用Gtk :: TextTag-s進行語法高亮顯示。Glib ::正則表達式拾取TextTag-s

我的更新代碼的語法

void MainWindow::update_syntax(const Gtk::TextBuffer::iterator& start, const Gtk::TextBuffer::iterator& end) { 
    std::vector<Glib::ustring> keywords; 
    keywords.push_back("class"); 
    keywords.push_back("struct"); 
    Glib::MatchInfo info; 
    auto regex = Glib::Regex::create(R"((\w+))"); 
    auto ok = regex->match(start.get_visible_text(end), info); 
    std::map<Glib::ustring, std::pair<Glib::RefPtr<Gtk::TextMark>, Glib::RefPtr<Gtk::TextMark>>> marks; 
    do { 
    std::cout << "word: " << info.fetch(1) << std::endl; 
    for (auto kw : keywords) { 
     if (info.fetch(1) == kw) { 
     int start_offset, end_offset; 
     info.fetch_pos(1, start_offset, end_offset); 
     std::cout << info.fetch(1) << " (at: [" << start_offset << ";" << end_offset << "])" << std::endl; 
     marks["keyword"] = std::make_pair(
      this->m_buffer->create_mark(
      this->m_buffer->get_iter_at_offset(start.get_offset() + start_offset) 
     ), 
      this->m_buffer->create_mark(
      this->m_buffer->get_iter_at_offset(start.get_offset() + end_offset) 
     ) 
     ); 
     } 
    } 
    } while(info.next()); 

    for (auto mark : marks) { 
    this->m_buffer->apply_tag_by_name(mark.first, 
     mark.second.first->get_iter(), mark.second.second->get_iter()); 
    } 
} 

所以流動是我創建了一個簡單的正則表達式應該在該行的每一個字匹配,然後(它在開始和該行的端接收迭代器)創建一個標記地圖,稍後將給出設置標籤的範圍。我在這裏使用了Gtk :: Mark,因爲對緩衝區的每次修改都會使迭代器失效。

爲了說明這裏有什麼問題,我會發布一些來自此函數的調試輸出,以及之前的一個插槽on_insert;

void MainWindow::on_insert(const Gtk::TextBuffer::iterator& pos, 
    const Glib::ustring& text, int bytes) 
{ 
    std::cout << text << " (added at[" << pos.get_offset() << 
    "]; with [" << bytes << "]bytes)" << std::endl << std::endl; 

所以寫class class在第一個TextView的結果的輸出被突出顯示,第二個不是拿起,請登錄:

c (added at[1]; with [1]bytes) 

word: c 
l (added at[2]; with [1]bytes) 

word: cl 
a (added at[3]; with [1]bytes) 

word: cla 
s (added at[4]; with [1]bytes) 

word: clas 
s (added at[5]; with [1]bytes) 

word: class 
class (keyword at: [0;5]) 
    (added at[6]; with [1]bytes) 

word: class 
class (keyword at: [0;5]) 
word: r 
c (added at[7]; with [1]bytes) 

word: class 
class (keyword at: [0;5]) 
word: rd 
l (added at[8]; with [1]bytes) 

word: class 
class (keyword at: [0;5]) 
word: rd 
a (added at[9]; with [1]bytes) 

word: class 
class (keyword at: [0;5]) 
word: rd 
word: a 
s (added at[10]; with [1]bytes) 

word: class 
class (keyword at: [0;5]) 
word: rd 
word: as 
s (added at[11]; with [1]bytes) 

word: class 
class (keyword at: [0;5]) 
word: rd 
word: ass 

人們很容易注意到最後一行顯示它移動了兩個偏移量。這可能是標籤被應用。另外,這裏不明確的是:word: rd。我使用keyword作爲標籤的名稱。當代碼仍然使用迭代器時,info.fetch(1)返回"keyword",那麼正則表達式是否也可以匹配標籤呢?

我希望有經驗的人在Glib和Gtk知道答案,謝謝。

回答

2

我還沒有使用這個特定的API,但我認爲你有一個對象的生命期問題。 iter->get_visible_text()正在返回一個字符串對象,該對象在致電regex->match()後被銷燬。這是一個問題,因爲Glib::MatchInfo::next()預計該字符串仍然存在。這可能是你爲什麼會在第二場比賽中得到垃圾的原因。我想你會是安全的做這樣的事情:

.... 
auto visbuf = start.get_visible_text(end); 
auto ok = regex->match(visbuf, info); // existing line 
... 
  1. 所以我可能是全廢話。
  2. 從Glib :: MatchInfo :: next()文檔:匹配在傳遞給匹配函數的字符串上完成,因此在調用此函數之前不能釋放它。
+0

我沒有注意到'match'引用了字符串,謝謝 – farnoy 2012-08-18 10:24:04