402
426
"cell_type": "code",
403
427
"execution_count": null,
409
" def runmenu(h, n, screen, menu, parent):\n",
410
" \"This function displays the appropriate menu and returns the option selected\"\n",
411
" optioncount = len(menu['options']) # how many options in this menu\n",
412
" # work out what text to display as the last menu option\n",
413
" if parent is None:\n",
414
" lastoption = \"Exit (press 'Q' key)\"\n",
416
" lastoption = \"Return to %s menu (press 'Q' key)\" % parent['title']\n",
417
" lastoption = \"%d - %s\" % (optioncount + 1, lastoption)\n",
418
" #Size of the window\n",
419
" screenH,screenW = screen.getmaxyx()\n",
421
" #Build the title\n",
422
" screen.border(0)\n",
423
" # Title for this menu\n",
424
" if menu['type'] == 'input':\n",
425
" screen.addstr(2, 2, 'Toto', curses.A_BOLD)\n",
427
" screen.addstr(2, 2, menu['title'], curses.A_BOLD)\n",
429
" if menu.has_key('DESCRIPTION'):\n",
430
" for chain in menu['DESCRIPTION'].split('\\n'):\n",
431
" screen.addstr(iy, 2, chain, curses.A_BOLD)\n",
434
" # Subtitle for this menu\n",
435
" screen.addstr(iy, 2, menu['subtitle'], curses.A_BOLD)\n",
437
" Wpad = screenW-2\n",
438
" Hpad_screen = screenH-6\n",
439
" menu_pad = curses.newpad(optioncount+1,max(Wpad,len(lastoption)+4))\n",
440
" # Display all the menu items, showing the 'line' item highlighted\n",
441
" for index in range(optioncount):\n",
442
" menu_pad.addstr(index, 0, \"%d - %s\" % (index + 1, menu['options'][index]['title']), n)\n",
443
" # Now display Exit/Return at bottom of menu\n",
444
" menu_pad.addstr(optioncount, 0, lastoption, n)\n",
445
" #Important to display menu_pad before the first key-press!!\n",
446
" screen.refresh()\n",
448
" # line is the zero-based index of the hightlighted menu option. Every time\n",
449
" # runmenu is called, line returns to 0, when runmenu ends line\n",
450
" # is returned and tells the program what opt$\n",
452
" # control for while loop, let's you scroll through options until return\n",
453
" # key is pressed then returns line to program\n",
456
" # Loop until return key is pressed, or esc key\n",
457
" while x != ord('\\n') and x != ord('q') and x != ord('Q'):\n",
458
" menu_pad.chgat(line,0,Wpad,h)\n",
459
" menu_pad.refresh(pos,0,4,2,screenH-2,Wpad)\n",
460
" x = screen.getch() # Gets user input\n",
461
" menu_pad.chgat(line,0,Wpad,n)\n",
462
" # What is user input?\n",
463
" # this line can be used only if optioncount is lower than 8\n",
464
" if x >= ord('1') and x <= ord(str(min(optioncount + 1, 9))):\n",
465
" # convert keypress back to a number, then subtract 1 to get index\n",
466
" line = x - ord('0') - 1\n",
467
" elif x == curses.KEY_DOWN: # down arrow\n",
469
" if line > optioncount:\n",
472
" if line-pos > Hpad_screen: pos += 1\n",
473
" elif x == curses.KEY_UP: # up arrow\n",
476
" line = optioncount\n",
477
" pos = line - Hpad_screen\n",
478
" if line-pos < 0: pos -= 1\n",
479
" elif x == ord('q') or x == ord('Q'): # esc key\n",
480
" line = optioncount\n",
481
" # return index of the selected item\n",
485
"def dump_info(h, n, screen, menu, parent):\n",
486
" \"\"\"Dump some information in the screen and come back to previous menu when done.\n",
487
" menu must contains 'title', 'subtitle' and 'DESCRIPTION'. \"\"\"\n",
491
" lastoption = \"Press Enter or 'Q' key to come back to %s menu\" % parent['title']\n",
492
" screenH,screenW = screen.getmaxyx()\n",
493
" #Build the height of the pad\n",
494
" padH = 2*len(menu) + len(menu['DESCRIPTION'].split('\\n'))\n",
495
" for v in menu.values():\n",
496
" padH += len(yaml.dump(v,default_flow_style=False).split('\\n')) + 2\n",
497
" dump_pad = curses.newpad(padH,screenW-2)\n",
498
" m = menu.items()\n",
499
" m.sort(menu_cmp, key= lambda s: s[0])\n",
500
" # Title for this menu\n",
501
" dump_pad.addstr(1, 2, m[0][1], curses.A_STANDOUT)\n",
502
" # Subtitle for this menu\n",
503
" dump_pad.addstr(3, 2, m[1][1], curses.A_BOLD)\n",
504
" # Display all the menu items, showing the 'pos' item highlighted\n",
506
" for chain in m[2][1].split('\\n'):\n",
508
" dump_pad.addstr(iy, 4, \"%s\" % chain, n)\n",
509
" #Now all the other keys\n",
510
" for (k,v) in m[3:]:\n",
511
" if k == 'type' or k == 'COMMENT':\n",
515
" dump_pad.addstr(iy, 2, k, curses.A_BOLD)\n",
516
" if isinstance(v,dict):\n",
517
" text = yaml.dump(v,default_flow_style=False)\n",
520
" for chain in text.split('\\n'):\n",
522
" dump_pad.addstr(iy, 4, \"%s\" % chain, n)\n",
524
" # Now display Exit/Return at bottom of menu\n",
526
" dump_pad.addstr(iy, 2, \" %s\" % lastoption, h)\n",
527
" #Display the information\n",
528
" screen.border(0)\n",
529
" screen.refresh()\n",
530
" # Loop until return key is pressed\n",
532
" while x != ord('\\n') and x != ord('q') and x != ord('Q'):\n",
533
" dump_pad.refresh(pos,0,1,1,screenH-2,screenW-2)\n",
534
" x = screen.getch() # Gets user input\n",
535
" if x == curses.KEY_DOWN:\n",
537
" pos = min(pos, iy - (screenH-4))\n",
538
" elif x == curses.KEY_UP:\n",
540
" pos = max(pos,0)\n",
541
" # return index of the selected item\n",
545
"def input_info(h, n, screen, menu, parent):\n",
546
" \"\"\"Search a key and dump info about it.\"\"\"\n",
550
" screenH,screenW = screen.getmaxyx()\n",
551
" # Title for this menu\n",
552
" screen.addstr(1, 2, 'Search a key', curses.A_STANDOUT)\n",
553
" # Subtitle for this menu\n",
554
" screen.addstr(3, 2, 'Please type a key:', curses.A_BOLD)\n",
555
" #Display the information\n",
556
" screen.border(0)\n",
557
" screen.refresh()\n",
558
" # Loop until return key is pressed\n",
560
" posmin = 1 + len('Please type a key:') + 1\n",
561
" blank = ' '*(screenW-posmin)\n",
563
" while x != ord('\\n'):\n",
564
" pos = max(posmin,pos)\n",
567
" elif x >= ord('a') and x <= ord('z'):\n",
570
" elif x == curses.KEY_BACKSPACE:\n",
573
" screen.addstr(3,posmin,key,curses.A_NORMAL)\n",
574
" screen.refresh()\n",
575
" x = screen.getch() # Gets user input\n",
576
" #Remove the key and generate it (no pb with cursor)\n",
577
" screen.addstr(3,posmin,blank,curses.A_NORMAL)\n",
579
" searchfor = key\n",
581
" for f in files:\n",
582
" allkeys += params[f].keys()\n",
583
" matching_keys = closest_keys(allkeys, searchfor)\n",
584
" #print 'matching', searchfor, 'in:', matching_keys\n",
585
" #print \"keys wich match the most with '%s'\" % searchfor\n",
588
" for (i, ratio) in matching_keys:\n",
589
" if ratio > 0.6 and i not in foundkeys:\n",
590
" for f in find_files(params, i):\n",
591
" text += '%s (Field: %s, similarity=%4.2f)\\n' % (i,f,ratio) \n",
592
" text += yaml.dump(params[f][i], default_flow_style=False, explicit_start=False)\n",
593
" foundkeys.append(i)\n",
595
" #curses.endwin()\n",
596
" #for chain in text.split('\\n'):\n",
600
" padH = 3 + max(len(text.split('\\n')),200)\n",
601
" dump_pad = curses.newpad(padH,screenW-2)\n",
602
" # Title for this menu\n",
603
" dump_pad.addstr(1, 2, \"Keys which match the most with '%s'\" % searchfor, curses.A_STANDOUT)\n",
604
" # Display all the menu items, showing the 'pos' item highlighted\n",
608
" dump_pad.addstr(iy, 4, \"No key found\", curses.A_NORMAL)\n",
610
" for chain in text.split('\\n'):\n",
612
" if 'Field:' in chain:\n",
613
" dump_pad.addstr(iy, 4, \"%s\" % chain, curses.A_BOLD)\n",
615
" dump_pad.addstr(iy, 4, \"%s\" % chain, curses.A_NORMAL)\n",
616
" lastoption = \"Press Enter or 'Q' key to come back to '%s menu'\" % parent['title']\n",
617
" dump_pad.addstr(iy+1, 2, \" %s\" % lastoption, curses.A_STANDOUT)\n",
618
" #Display the information\n",
619
" screen.border(0)\n",
620
" screen.refresh()\n",
621
" # Loop until return key is pressed\n",
624
" while x != ord('\\n') and x != ord('q') and x != ord('Q'):\n",
625
" dump_pad.refresh(pos,0,1,1,screenH-2,screenW-2)\n",
626
" x = screen.getch() # Gets user input\n",
627
" if x == curses.KEY_DOWN:\n",
629
" pos = min(pos, iy - (screenH-4))\n",
630
" elif x == curses.KEY_UP:\n",
632
" pos = max(pos,0)\n",
636
"def processmenu(h, n, screen, menu, parent=None):\n",
637
" \"This function calls showmenu and then acts on the selected item\"\n",
638
" optioncount = len(menu['options'])\n",
639
" exitmenu = False\n",
640
" while not exitmenu: # Loop until the user exits the menu\n",
641
" getin = runmenu(h, n, screen, menu, parent)\n",
643
" whattodo = menu['options'][getin]['type']\n",
645
" whattodo = None\n",
646
" # the last option is always needed to exit the menu\n",
647
" if getin == optioncount:\n",
648
" exitmenu = True\n",
649
" elif whattodo == COMMAND:\n",
650
" curses.def_prog_mode() # save current curses environment\n",
651
" os.system('reset')\n",
652
" screen.clear() # clears previous screen\n",
653
" os.system(menu['options'][getin]['command']) # run the command\n",
654
" # clears previous screen on key press and updates display based on pos\n",
656
" curses.reset_prog_mode() # reset to 'current' curses environment\n",
657
" curses.curs_set(1) # reset doesn't do this right\n",
658
" curses.curs_set(0)\n",
659
" elif whattodo == PROMPT:\n",
660
" curses.def_prog_mode() # save current curses environment\n",
661
" # this is not the good place, as it is specific to the usage\n",
662
" screen.clear() # clears previous screen\n",
663
" dump_info(h, n, screen, menu['options'][getin], menu)\n",
664
" # clears previous screen on key press and updates display based on pos\n",
666
" curses.reset_prog_mode() # reset to 'current' curses environment\n",
667
" curses.curs_set(1) # reset doesn't do this right\n",
668
" curses.curs_set(0)\n",
669
" elif whattodo == MENU:\n",
670
" # clears previous screen on key press and updates display based on pos\n",
672
" # display the submenu\n",
673
" processmenu(h, n, screen, menu['options'][getin], menu)\n",
674
" # clears previous screen on key press and updates display based on pos\n",
676
" elif whattodo == INPUT:\n",
677
" # All pressed key is used\n",
678
" curses.def_prog_mode() # save current curses environment\n",
679
" # this is not the good place, as it is specific to the usage\n",
680
" screen.clear() # clears previous screen\n",
681
" input_info(h, n, screen, menu['options'][getin], menu)\n",
682
" # clears previous screen on key press and updates display based on pos\n",
684
" curses.reset_prog_mode() # reset to 'current' curses environment\n",
685
" curses.curs_set(1) # reset doesn't do this right\n",
686
" curses.curs_set(0)\n",
687
" elif whattodo == EXITMENU:\n",
688
" exitmenu = True\n",
690
"dico_menu = { 'title': 0, 'subtitle': 1, 'DESCRIPTION': 2, 'default': 3}\n",
691
"def menu_cmp(key_x,key_y):\n",
692
" \"Function compare to sort the keys in order to compose the menu\"\n",
693
" global dico_menu\n",
694
" kx = dico_menu.get(key_x,key_x)\n",
695
" ky = dico_menu.get(key_y,key_y)\n",
696
" return cmp(kx,ky)\n",
698
" # Initializes a new window for capturing key presses\n",
699
" screen = curses.initscr()\n",
700
" # Disables automatic echoing of key presses (prevents program from\n",
701
" # input each key twice)\n",
702
" curses.noecho()\n",
703
" # Disables line buffering (runs each key as it is pressed rather than\n",
704
" # waiting for the return key to pressed)\n",
705
" curses.cbreak()\n",
706
" # Lets you use colors when highlighting selected menu option\n",
707
" curses.start_color()\n",
708
" screen.keypad(1) # Capture input from keypad\n",
709
" screen.notimeout(1) # Disables timeout for esc key\n",
710
" # Change this to use different colors when highlighting\n",
711
" # Sets up color pair #1, it does black text with white background\n",
712
" curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_WHITE)\n",
713
" # h is the coloring for a highlighted menu option\n",
714
" h = curses.color_pair(1)\n",
715
" # n is the coloring for a non highlighted menu option\n",
716
" n = curses.A_NORMAL\n",
717
" #Check if the height of window is enough\n",
718
" H,W = screen.getmaxyx()\n",
720
" processmenu(h, n, screen, menu)\n",
721
" # VITAL! This closes out the menu system and returns you to the bash\n",
723
" curses.endwin()\n",
725
" sys.stdout.write(\"ERROR: The window is too thin!\\n\")\n",
726
" os.system('clear')"