1  import sys 
  2  import types 
  3  import textwrap 
  4  import traceback 
  5   
  8          self.menus = {} 
  9          self.width = 80 
 10          self.onException = "ASK" 
 11          self.auto = False 
 12          self.closingMessage = "" 
  13       
 15          nextMenu = mainMenu 
 16          prevMenu = None 
 17          while nextMenu != None: 
 18              currentMenu = self.menus[nextMenu] 
 19              nextMenu = currentMenu.show(prevMenu) 
 20              if type(nextMenu) == types.ListType: 
 21                  for next in nextMenu: 
 22                      self.run(next) 
 23                  nextMenu = None 
 24              prevMenu = currentMenu 
  25       
 27          if self.closingMessage != None: 
 28              print >> sys.stderr 
 29              print >> sys.stderr, self.closingMessage 
  30       
 32          if not hasattr(self, attrName): 
 33              setattr(self, attrName, value) 
   34   
 36      system = MenuSystem() 
 37       
 39          if name == "SPACE": 
 40              return Option(None, None) 
  41       
 43          if addToSystem: 
 44              assert title not in Menu.system.menus 
 45              Menu.system.menus[title] = self 
 46           
 47          self.title = title 
 48          self.text = text 
 49          self.options = options 
 50          self.optDict = {} 
 51          for i in range(len(options)): 
 52              option = options[i] 
 53               
 54              if type(option) in types.StringTypes: 
 55                  option = self.getDefaultOption(option) 
 56                  options[i] = option 
 57               
 58              if option.key != None: 
 59                  option.menu = self 
 60                  assert option.key not in self.optDict 
 61                  self.optDict[option.key] = option 
 62                  if option.dataInput != None: 
 63                      self.setAttr(option.dataInput) 
 64          self.prevChoice = None 
 65          self.initializer = initializer 
 66          self.doAlignText = True 
  67       
 69          for option in self.options: 
 70              option.isDefault = False 
 71          self.optDict[key].isDefault = True 
  72       
 74          if not hasattr(self, attrName) or getattr(self, attrName) == None: 
 75              return "" 
 76          else: 
 77              return getattr(self, attrName) 
  78       
 80           
 81          setattr(self, attrName, value) 
  82       
 84          if self.doAlignText: 
 85              print >> sys.stderr, self.alignText(self.text) 
 86          else: 
 87              print >> sys.stderr, self.text 
  88   
 90          if title != None: 
 91              border = ((self.system.width - len(title) - 2) / 2) * style 
 92              titleBar = border + " " + title + " " + border 
 93              titleBar += (len(titleBar) - self.system.width) * style 
 94              print >> sys.stderr, titleBar 
 95          else: 
 96              print >> sys.stderr, self.system.width * style 
  97       
 99          for option in self.options: 
100              option.show() 
 101       
118   
120          choice = None 
121          default = None 
122          for item in items: 
123              if item.isDefault: 
124                  default = item 
125                  break 
126          while choice == None: 
127              choice = raw_input(">") 
128               
129              if choice.strip() == "" and default != None: 
130                  choice = default.key 
131              print >> sys.stderr 
132              if choice.lower() in self.optDict.keys(): 
133                  choiceLower = choice.lower() 
134                  opt = self.optDict[choiceLower] 
135                  self.prevChoice = choiceLower 
136                  if opt.toggle != None: 
137                      opt.toggle = not opt.toggle 
138                      return self.title 
139                  elif opt.dataInput != None: 
140                      setattr(self, opt.dataInput, self.getDataInput(opt.dataInput)) 
141                      return self.title 
142                  else: 
143                      opt.do() 
144                      return opt.nextMenu 
145              else: 
146                  print >> sys.stderr, "Unknown option", choice 
147                  choice == None 
148                  return self.title 
 149       
151          lines = text.split("\n") 
152          paragraphs = [""] 
153          for line in lines: 
154              if line.strip() == "": 
155                  paragraphs.append("") 
156              else: 
157                  paragraphs[-1] += line.strip() + " " 
158          paragraphsToKeep = [] 
159          for paragraph in paragraphs: 
160              paragraph = "\n".join(textwrap.wrap(paragraph, width=self.system.width)) 
161              if paragraph.strip() != "": 
162                  paragraphsToKeep.append(paragraph) 
163          return "\n\n".join(paragraphsToKeep) 
 164                   
166           
167           
168          if self.initializer != None: 
169              self.initializer(self, prevMenu) 
170          print >> sys.stderr 
171          self.printBorder(self.title) 
172          self.printText() 
173          self.printBorder(style="-") 
174          assert self.options != None and len(self.options) >= 1 
175          self.printOptions() 
176          self.printBorder() 
177          return self.getChoice(self.options) 
  178   
180      SPACE = "SPACE" 
181      QUIT = "QUIT" 
182       
183 -    def __init__(self, key, text, nextMenu=None, handler=None, isDefault=False, toggle=None, dataInput=None, handlerArgs=[]): 
 184          self.key = key 
185          self.text = text 
186          self.toggle = toggle 
187          self.dataInput = dataInput 
188          self.isDefault = isDefault 
189          self.menu = None 
190          self.handler = handler 
191          self.handlerArgs = handlerArgs 
192          self.nextMenu = nextMenu 
 193       
194 -    def show(self, alignText=True): 
 195          if self.key == None:  
196              print >> sys.stderr 
197              return 
198           
199          if self.isDefault: 
200              print >> sys.stderr, " * ", 
201          elif self.toggle != None: 
202              if self.toggle: 
203                  print >> sys.stderr, "[X]", 
204              else: 
205                  print >> sys.stderr, "[ ]", 
206          else: 
207              print >> sys.stderr, "   ", 
208          print >> sys.stderr, self.key + ")", 
209           
210          if self.dataInput != None: 
211              print >> sys.stderr, self.text, "(" + self.menu.getAttrString(self.dataInput) + ")" 
212          else: 
213              print >> sys.stderr, self.text 
 214       
216          if self.handler == None:  
217              return 
218          elif type(self.handler) == types.ListType:  
219              for i in range(len(self.handler)): 
220                  if len(self.handlerArgs) > i: 
221                      self._runHandler(self.handler[i], self.handlerArgs[i])  
222                  else: 
223                      self._runHandler(self.handler[i])  
224          else:  
225              self._runHandler(self.handler, self.handlerArgs)  
 226       
228          try: 
229              handler(*handlerArgs) 
230          except Exception, e: 
231              print >> sys.stderr 
232              print >> sys.stderr, "***", "Exception processing menu '" + self.menu.title + "' option '" + self.key + " (" + self.text + ")", "***" 
233              print >> sys.stderr, "Exception:", e 
234              traceback.print_exc(file=sys.stderr) 
235              assert self.menu.system.onException in ["EXIT", "IGNORE", "ASK"] 
236              if self.menu.system.onException == "EXIT": 
237                  print >> sys.stderr, "Exiting" 
238                  sys.exit(1) 
239              elif self.menu.system.onException == "IGNORE": 
240                  print >> sys.stderr, "Ignoring error and continuing" 
241              else:  
242                  Option.exceptionMenu.show() 
243                  print >> sys.stderr, "Ignoring error and continuing" 
  244   
245  Option.exceptionMenu = Menu("Error", "There was an error processing the menu option. Please choose whether to quit or continue",  
246      [Option("i", "Ignore and continue"),  
247       Option("q", "Quit", isDefault=True, handler=sys.exit, handlerArgs=[1])],  
248      addToSystem=False) 
249       
250   
251   
252   
253   
254   
255   
256   
257   
258  if __name__=="__main__": 
259       
260      try: 
261          import psyco 
262          psyco.full() 
263          print >> sys.stderr, "Found Psyco, using" 
264      except ImportError: 
265          print >> sys.stderr, "Psyco not installed" 
266       
267      m = Menu("Main menu",  
268               "Some Text." 
269               [Option("Y", "Yes", None, True), Option("N", "No")]) 
270      m.show() 
271