152. How to highlight matching brackets in GtkTextView - Part 1?

Problem

You want to highlight enclosing curly brackets in a GtkTextView as shown below:

How to highlight matching brackets in GtkTextView - Part 1?


Solution


Sample Code

1   
2   
3   
4   
5   
6   
7   
8   
9   
10   
11   
12   
13   
14   
16   
18   
22   
23   
24   
25   
26   
27   
28   
29   
30   
31   
32   
41   
42   
43   
44   
45   
46   
47   
48   
49   
50   
51   
52   
53   
54   
55   
56   
57   
59   
60   
61   
62   
63   
64   
65   
67   
68   
69   
70   
71   
72   
75   
77   
78   
79   
80   
81   
82   
83   
84   
85   
86   
87   
88   
89   
90   
93   
95   
96   
97   
98   
99   
100   
101   
103   
105   
106   
107   
111   
112   
113   
114   
115   
116   
117   
118   
122   
123   
124   
<?php
$window = new GtkWindow();
$window->set_size_request(400, 240);
$window->connect_simple('destroy', array('Gtk','main_quit'));
$window->add($vbox = new GtkVBox());

// display title
$title = new GtkLabel("Highlight matching curly bracket - Part 1\n");
$title->modify_font(new PangoFontDescription("Times New Roman Italic 10"));
$title->modify_fg(Gtk::STATE_NORMAL, GdkColor::parse("#0000ff"));
$title->set_size_request(-1, 20);
$title->set_justify(Gtk::JUSTIFY_CENTER);
$alignment = new GtkAlignment(0.5, 0.5, 0, 0);
$alignment->add($title);
$vbox->pack_start($alignment);

// Setup TextView
$buffer = new GtkTextBuffer();
$buffer->set_text('if ($i==1) {
    test();
} else {
    test2();
}');
$view = new GtkTextView();
$view->set_buffer($buffer);
$view->modify_font(new PangoFontDescription("Arial 10"));
$view->set_wrap_mode(Gtk::WRAP_WORD);

$hbox = new GtkHBox();
$hbox->pack_start($button = new GtkButton('Find enclosing bracket'), 0);
$vbox->pack_start($hbox, 0);
$button->connect('clicked', 'on_button', $buffer); // note 1

$scrolled_win = new GtkScrolledWindow();
$scrolled_win->set_policy( Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
$vbox->pack_start($scrolled_win);
$scrolled_win->add($view);

// Setup highlight tag
$tag_table = $buffer->get_tag_table();
$tag['highlight'] = new GtkTextTag(); // note 2
$tag['highlight']->set_property('background', "#ffff00"); // note 2
$tag_table->add($tag['highlight']);

$window->show_all();
Gtk::main();

function find_left_bracket($iter, $buffer) {
    global $tag;
    $iter2 = $iter->copy();

    $match_start = $iter->copy();
    $match_end = $iter->copy();

    // check left { first
    $found = $iter->backward_search('{', 0, $match_start,
        $match_end, null);
    if (!$found) return null;

    $buffer->apply_tag($tag['highlight'], $match_start, $match_end); // note 6
    return array($match_start, $match_end);
}

function find_right_bracket($iter, $buffer) {
    global $tag;
    $iter2 = $iter->copy();
    $match_start = $iter->copy();
    $match_end = $iter->copy();

    // check right } first
    $found = $iter->forward_search('}', 0, $match_start,
        $match_end, null);
    if (!$found) return null;

    $buffer->apply_tag($tag['highlight'], $match_start, $match_end); // note 7
    return array($match_start, $match_end);
}


function on_button($button, $buffer) {
    global $view, $tag;

    $cursor_pos = $buffer->get_mark('insert'); // note 3
    $iter = $buffer->get_iter_at_mark($cursor_pos); // note 3

    list($left_start_iter, $left_end_iter) =
        find_left_bracket($iter, $buffer); // note 4
    if ($left_start_iter==null) return;

    list($right_start_iter, $right_end_iter) =
        find_right_bracket($iter, $buffer); // note 5
    if ($right_start_iter==null) return;
}

?>

Output

As shown above.
 

Explanation

  1. Set up the "Highlight Bracket" button.
  2. Set up highlight tag. Please refer to How to apply styles to GtkTextView using GtkTextTag - Part 1? for details.
  3. Get current cursor position.
  4. Find left bracket.
  5. Find right bracket.
  6. Highlight the left bracket.
  7. Highlight the right bracket.

Note

There are a couple of things we need to improve:

  • Pressing the button when the cursor is at "else" should not highlight anything.
  • When the user moves the cursor (by mouse or keyboard), the highlight should disappear.

We will fix these in the next two articles.

Related Links

Add comment


Security code
Refresh