perf tools: Fix the bash completion problem of 'perf --*'
authorYunlong Song <yunlong.song@huawei.com>
Fri, 27 Feb 2015 10:21:31 +0000 (18:21 +0800)
committerArnaldo Carvalho de Melo <acme@redhat.com>
Fri, 27 Feb 2015 18:52:28 +0000 (15:52 -0300)
The perf-completion.sh uses a predefined string '--help --version
--exec-path --html-path --paginate --no-pager --perf-dir --work-tree
--debugfs-dir' for the bash completion of 'perf --*', which has two
problems:

 Problem 1: If the options of perf are changed (see handle_options() in
 perf.c), the perf-completion.sh has to be changed at the same time. If
 not, the bash completion of 'perf --*' and the options which perf
 really supports will be inconsistent.

 Problem 2: When typing another single character after 'perf --', e.g.
 'h', and hit TAB key to get the bash completion of 'perf --h', the
 character 'h' disappears at once. This is not what we want, we wish the
 bash completion can return '--help --html-path' and then we can
 continue to choose one.

 To solve this problem, we add '--list-opts' to perf, which now supports
 'perf --list-opts' directly, and its result can be used in bash
 completion now.

Example:

 Before this patch:

 $ perf --h                 <-- hit TAB key after character 'h'
 $ perf --                  <-- 'h' disappears and no required result

 After this patch:

 $ perf --h                 <-- hit TAB key after character 'h'
 --help       --html-path   <-- the required result

Signed-off-by: Yunlong Song <yunlong.song@huawei.com>
Tested-by: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Wang Nan <wangnan0@huawei.com>
Link: http://lkml.kernel.org/r/1425032491-20224-8-git-send-email-yunlong.song@huawei.com
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
tools/perf/perf-completion.sh
tools/perf/perf.c

index 33569847fdcc409a28af4b6d1b4c87b07b7722ab..c2595e9bd69bde2ba76f68fe43932ecc1d0c3737 100644 (file)
@@ -110,13 +110,11 @@ __perf_main ()
        # List perf subcommands or long options
        if [ $cword -eq 1 ]; then
                if [[ $cur == --* ]]; then
-                       __perfcomp '--help --version \
-                       --exec-path --html-path --paginate --no-pager \
-                       --perf-dir --work-tree --debugfs-dir' -- "$cur"
+                       cmds=$($cmd --list-opts)
                else
                        cmds=$($cmd --list-cmds)
-                       __perfcomp "$cmds" "$cur"
                fi
+               __perfcomp "$cmds" "$cur"
        # List possible events for -e option
        elif [[ $prev == "-e" && "${words[1]}" == @(record|stat|top) ]]; then
                evts=$($cmd list --raw-dump)
index 3df2665022bef0db98455a9f31ad24ec0ea5b314..b857fcbd00cf291f9dc7d8473e36cdadeac81987 100644 (file)
@@ -13,6 +13,7 @@
 #include "util/quote.h"
 #include "util/run-command.h"
 #include "util/parse-events.h"
+#include "util/parse-options.h"
 #include "util/debug.h"
 #include <api/fs/debugfs.h>
 #include <pthread.h>
@@ -125,6 +126,23 @@ static void commit_pager_choice(void)
        }
 }
 
+struct option options[] = {
+       OPT_ARGUMENT("help", "help"),
+       OPT_ARGUMENT("version", "version"),
+       OPT_ARGUMENT("exec-path", "exec-path"),
+       OPT_ARGUMENT("html-path", "html-path"),
+       OPT_ARGUMENT("paginate", "paginate"),
+       OPT_ARGUMENT("no-pager", "no-pager"),
+       OPT_ARGUMENT("perf-dir", "perf-dir"),
+       OPT_ARGUMENT("work-tree", "work-tree"),
+       OPT_ARGUMENT("debugfs-dir", "debugfs-dir"),
+       OPT_ARGUMENT("buildid-dir", "buildid-dir"),
+       OPT_ARGUMENT("list-cmds", "list-cmds"),
+       OPT_ARGUMENT("list-opts", "list-opts"),
+       OPT_ARGUMENT("debug", "debug"),
+       OPT_END()
+};
+
 static int handle_options(const char ***argv, int *argc, int *envchanged)
 {
        int handled = 0;
@@ -225,6 +243,15 @@ static int handle_options(const char ***argv, int *argc, int *envchanged)
                        }
                        putchar('\n');
                        exit(0);
+               } else if (!strcmp(cmd, "--list-opts")) {
+                       unsigned int i;
+
+                       for (i = 0; i < ARRAY_SIZE(options)-1; i++) {
+                               struct option *p = options+i;
+                               printf("--%s ", p->long_name);
+                       }
+                       putchar('\n');
+                       exit(0);
                } else if (!strcmp(cmd, "--debug")) {
                        if (*argc < 2) {
                                fprintf(stderr, "No variable specified for --debug.\n");