Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf top: Improve interactive key handling

Pressing any key which is not currently mapped to
functionality, based on startup command line options, displays
currently mapped keys, and prompts for input.

Pressing any unmapped key at the prompt returns the user to
display mode with variables unchanged. eg, pressing ? <SPACE>
<ESC> etc displays currently available keys, the value of the
variable associated with that key, and prompts.

Pressing same again aborts input.

Signed-off-by: Mike Galbraith <efault@gmx.de>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>

authored by

Mike Galbraith and committed by
Ingo Molnar
091bd2e9 7b4b6658

+73 -35
+73 -35
tools/perf/builtin-top.c
··· 595 595 free(buf); 596 596 } 597 597 598 - static void print_known_keys(void) 598 + static void print_mapped_keys(void) 599 599 { 600 - fprintf(stdout, "\nknown keys:\n"); 601 - fprintf(stdout, "\t[d] select display delay.\n"); 602 - fprintf(stdout, "\t[e] select display entries (lines).\n"); 603 - fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_counter)); 604 - fprintf(stdout, "\t[f] select normal display count filter.\n"); 605 - fprintf(stdout, "\t[F] select annotation display count filter (percentage).\n"); 606 - fprintf(stdout, "\t[qQ] quit.\n"); 607 - fprintf(stdout, "\t[s] select annotation symbol and start annotation.\n"); 608 - fprintf(stdout, "\t[S] stop annotation, revert to normal display.\n"); 609 - fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); 600 + char *name = NULL; 601 + 602 + if (sym_filter_entry) { 603 + struct symbol *sym = (struct symbol *)(sym_filter_entry+1); 604 + name = sym->name; 605 + } 606 + 607 + fprintf(stdout, "\nMapped keys:\n"); 608 + fprintf(stdout, "\t[d] display refresh delay. \t(%d)\n", delay_secs); 609 + fprintf(stdout, "\t[e] display entries (lines). \t(%d)\n", print_entries); 610 + 611 + if (nr_counters > 1) 612 + fprintf(stdout, "\t[E] active event counter. \t(%s)\n", event_name(sym_counter)); 613 + 614 + fprintf(stdout, "\t[f] profile display filter (count). \t(%d)\n", count_filter); 615 + 616 + if (vmlinux) { 617 + fprintf(stdout, "\t[F] annotate display filter (percent). \t(%d%%)\n", sym_pcnt_filter); 618 + fprintf(stdout, "\t[s] annotate symbol. \t(%s)\n", name?: "NULL"); 619 + fprintf(stdout, "\t[S] stop annotation.\n"); 620 + } 621 + 622 + if (nr_counters > 1) 623 + fprintf(stdout, "\t[w] toggle display weighted/count[E]r. \t(%d)\n", display_weighted ? 1 : 0); 624 + 610 625 fprintf(stdout, "\t[z] toggle sample zeroing. \t(%d)\n", zero ? 1 : 0); 626 + fprintf(stdout, "\t[qQ] quit.\n"); 627 + } 628 + 629 + static int key_mapped(int c) 630 + { 631 + switch (c) { 632 + case 'd': 633 + case 'e': 634 + case 'f': 635 + case 'z': 636 + case 'q': 637 + case 'Q': 638 + return 1; 639 + case 'E': 640 + case 'w': 641 + return nr_counters > 1 ? 1 : 0; 642 + case 'F': 643 + case 's': 644 + case 'S': 645 + return vmlinux ? 1 : 0; 646 + } 647 + 648 + return 0; 611 649 } 612 650 613 651 static void handle_keypress(int c) 614 652 { 615 - int once = 0; 616 - repeat: 653 + if (!key_mapped(c)) { 654 + struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 655 + struct termios tc, save; 656 + 657 + print_mapped_keys(); 658 + fprintf(stdout, "\nEnter selection, or unmapped key to continue: "); 659 + fflush(stdout); 660 + 661 + tcgetattr(0, &save); 662 + tc = save; 663 + tc.c_lflag &= ~(ICANON | ECHO); 664 + tc.c_cc[VMIN] = 0; 665 + tc.c_cc[VTIME] = 0; 666 + tcsetattr(0, TCSANOW, &tc); 667 + 668 + poll(&stdin_poll, 1, -1); 669 + c = getc(stdin); 670 + 671 + tcsetattr(0, TCSAFLUSH, &save); 672 + if (!key_mapped(c)) 673 + return; 674 + } 675 + 617 676 switch (c) { 618 677 case 'd': 619 678 prompt_integer(&delay_secs, "Enter display delay"); ··· 728 669 case 'z': 729 670 zero = ~zero; 730 671 break; 731 - default: { 732 - struct pollfd stdin_poll = { .fd = 0, .events = POLLIN }; 733 - struct termios tc, save; 734 - 735 - if (!once) { 736 - print_known_keys(); 737 - once++; 738 - } 739 - 740 - tcgetattr(0, &save); 741 - tc = save; 742 - tc.c_lflag &= ~(ICANON | ECHO); 743 - tc.c_cc[VMIN] = 0; 744 - tc.c_cc[VTIME] = 0; 745 - tcsetattr(0, TCSANOW, &tc); 746 - 747 - poll(&stdin_poll, 1, -1); 748 - c = getc(stdin); 749 - 750 - tcsetattr(0, TCSAFLUSH, &save); 751 - goto repeat; 752 - } 753 672 } 754 673 } 755 674 ··· 742 705 tc.c_lflag &= ~(ICANON | ECHO); 743 706 tc.c_cc[VMIN] = 0; 744 707 tc.c_cc[VTIME] = 0; 708 + 745 709 repeat: 746 710 delay_msecs = delay_secs * 1000; 747 711 tcsetattr(0, TCSANOW, &tc);