perf annotate browser: string search: /?n
authorArnaldo Carvalho de Melo <acme@redhat.com>
Sat, 7 Apr 2012 20:10:30 +0000 (17:10 -0300)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Sat, 7 Apr 2012 20:37:22 +0000 (17:37 -0300)
Using the same keystrokes as vim:

/ = search forward
n = search next forward/backwards
? = search backwards

Still needs to continue from start/end when not found, use HOME + / or
END + ? for now.

At some point we need a keybindings file to support ones favourite mode,
erm, like EMACS, etc.

Also we now need a 'h' window with all these keybindings.

Requested-by: Andi Kleen <andi@firstfloor.org>
Cc: Andi Kleen <andi@firstfloor.org>
Cc: David Ahern <dsahern@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Namhyung Kim <namhyung@gmail.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lkml.kernel.org/n/tip-rv30xj2i258n0gwkzlu0c0bc@git.kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/util/ui/browsers/annotate.c

index 752d8d0..c2cfeed 100644 (file)
@@ -21,6 +21,8 @@ struct annotate_browser {
        int                 nr_entries;
        bool                hide_src_code;
        bool                use_offset;
+       bool                searching_backwards;
+       char                search_bf[128];
 };
 
 struct objdump_line_rb_node {
@@ -176,6 +178,7 @@ static void annotate_browser__set_top(struct annotate_browser *self,
        }
 
        self->b.top = pos;
+       self->b.navkeypressed = true;
 }
 
 static void annotate_browser__set_rb_top(struct annotate_browser *browser,
@@ -354,6 +357,132 @@ static bool annotate_browser__jump(struct annotate_browser *browser)
        return true;
 }
 
+static struct objdump_line *
+       annotate_browser__find_string(struct annotate_browser *browser,
+                                     char *s, s64 *idx)
+{
+       struct map_symbol *ms = browser->b.priv;
+       struct symbol *sym = ms->sym;
+       struct annotation *notes = symbol__annotation(sym);
+       struct objdump_line *pos = browser->selection;
+
+       *idx = browser->b.index;
+       list_for_each_entry_continue(pos, &notes->src->source, node) {
+               if (objdump_line__filter(&browser->b, &pos->node))
+                       continue;
+
+               ++*idx;
+
+               if (pos->line && strstr(pos->line, s) != NULL)
+                       return pos;
+       }
+
+       return NULL;
+}
+
+static bool __annotate_browser__search(struct annotate_browser *browser)
+{
+       struct objdump_line *line;
+       s64 idx;
+
+       line = annotate_browser__find_string(browser, browser->search_bf, &idx);
+       if (line == NULL) {
+               ui_helpline__puts("String not found!");
+               return false;
+       }
+
+       annotate_browser__set_top(browser, line, idx);
+       browser->searching_backwards = false;
+       return true;
+}
+
+static struct objdump_line *
+       annotate_browser__find_string_reverse(struct annotate_browser *browser,
+                                             char *s, s64 *idx)
+{
+       struct map_symbol *ms = browser->b.priv;
+       struct symbol *sym = ms->sym;
+       struct annotation *notes = symbol__annotation(sym);
+       struct objdump_line *pos = browser->selection;
+
+       *idx = browser->b.index;
+       list_for_each_entry_continue_reverse(pos, &notes->src->source, node) {
+               if (objdump_line__filter(&browser->b, &pos->node))
+                       continue;
+
+               --*idx;
+
+               if (pos->line && strstr(pos->line, s) != NULL)
+                       return pos;
+       }
+
+       return NULL;
+}
+
+static bool __annotate_browser__search_reverse(struct annotate_browser *browser)
+{
+       struct objdump_line *line;
+       s64 idx;
+
+       line = annotate_browser__find_string_reverse(browser, browser->search_bf, &idx);
+       if (line == NULL) {
+               ui_helpline__puts("String not found!");
+               return false;
+       }
+
+       annotate_browser__set_top(browser, line, idx);
+       browser->searching_backwards = true;
+       return true;
+}
+
+static bool annotate_browser__search_window(struct annotate_browser *browser,
+                                           int delay_secs)
+{
+       if (ui_browser__input_window("Search", "String: ", browser->search_bf,
+                                    "ENTER: OK, ESC: Cancel",
+                                    delay_secs * 2) != K_ENTER ||
+           !*browser->search_bf)
+               return false;
+
+       return true;
+}
+
+static bool annotate_browser__search(struct annotate_browser *browser, int delay_secs)
+{
+       if (annotate_browser__search_window(browser, delay_secs))
+               return __annotate_browser__search(browser);
+
+       return false;
+}
+
+static bool annotate_browser__continue_search(struct annotate_browser *browser,
+                                             int delay_secs)
+{
+       if (!*browser->search_bf)
+               return annotate_browser__search(browser, delay_secs);
+
+       return __annotate_browser__search(browser);
+}
+
+static bool annotate_browser__search_reverse(struct annotate_browser *browser,
+                                          int delay_secs)
+{
+       if (annotate_browser__search_window(browser, delay_secs))
+               return __annotate_browser__search_reverse(browser);
+
+       return false;
+}
+
+static
+bool annotate_browser__continue_search_reverse(struct annotate_browser *browser,
+                                              int delay_secs)
+{
+       if (!*browser->search_bf)
+               return annotate_browser__search_reverse(browser, delay_secs);
+
+       return __annotate_browser__search_reverse(browser);
+}
+
 static int annotate_browser__run(struct annotate_browser *self, int evidx,
                                 void(*timer)(void *arg),
                                 void *arg, int delay_secs)
@@ -372,8 +501,10 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
 
        annotate_browser__calc_percent(self, evidx);
 
-       if (self->curr_hot)
+       if (self->curr_hot) {
                annotate_browser__set_rb_top(self, self->curr_hot);
+               self->b.navkeypressed = false;
+       }
 
        nd = self->curr_hot;
 
@@ -428,6 +559,22 @@ static int annotate_browser__run(struct annotate_browser *self, int evidx,
                case 'o':
                        self->use_offset = !self->use_offset;
                        continue;
+               case '/':
+                       if (annotate_browser__search(self, delay_secs)) {
+show_help:
+                               ui_helpline__puts(help);
+                       }
+                       continue;
+               case 'n':
+                       if (self->searching_backwards ?
+                           annotate_browser__continue_search_reverse(self, delay_secs) :
+                           annotate_browser__continue_search(self, delay_secs))
+                               goto show_help;
+                       continue;
+               case '?':
+                       if (annotate_browser__search_reverse(self, delay_secs))
+                               goto show_help;
+                       continue;
                case K_ENTER:
                case K_RIGHT:
                        if (self->selection == NULL)