2012-08-17 103 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