2 Interface compatible with :class:`dialog.Dialog` for doing
3 non-ncurses interaction.
5 By convention, the last line of a text parameter should be
6 a short value with a trailing colon so that we can prompt a user
7 for a value immediately after it.
24 def fill(text, width=60, **kwargs):
25 return "\n\n".join(textwrap.fill(p, width=width, **kwargs) for p in text.split("\n\n"))
27 def guess_dimensions(text, width=60):
28 # +1 for the fact that there's no trailing newline from fill
30 # +1 as a buffer in case we underestimate
32 return width, fill(text, width-2).count("\n") + 1 + 2 + 1
34 def make(prompt, non_interactive):
37 if prompt or not has_dialog:
41 except dialog.ExecutableNotFound:
49 return ', '.join(items[:-1]) + ' or ' + items[-1]
52 def dialog_wrap(f, self, text, *args, **kwargs):
53 if 'cmdopt' in kwargs: del kwargs['cmdopt']
54 if 'width' not in kwargs and 'height' not in kwargs:
55 kwargs["width"], kwargs["height"] = guess_dimensions(text)
56 elif 'width' in kwargs and 'height' not in kwargs:
57 kwargs["width"], kwargs["height"] = guess_dimensions(text, width=kwargs["width"])
58 result = f(self, text, *args, **kwargs)
59 if not isinstance(result, tuple):
64 if exit == self.dialog.DIALOG_CANCEL or exit == self.dialog.DIALOG_ESC:
66 elif exit != self.dialog.DIALOG_OK:
67 # XXX: We don't support stuff like DIALOG_EXTRA or DIALOG_HELP
68 raise DialogError(exit)
73 """Ncurses interface using dialog."""
75 self.dialog = dialog.Dialog()
77 def inputbox(self, *args, **kwargs):
78 kwargs.setdefault('initerror', "You cannot edit initial value; please type characters after it.")
79 initerror = kwargs['initerror']
80 del kwargs['initerror']
81 kwargs['height'] += 5 # for the text box
82 exit, result = self.dialog.inputbox(*args, **kwargs)
83 if exit == self.dialog.DIALOG_OK:
84 # do some funny munging
85 kwargs.setdefault('init', '')
86 if result[0:len(kwargs['init'])] != kwargs['init']:
87 self.msgbox(initerror, height=10, width=50)
88 exit = self.dialog.DIALOG_OK
89 result = self.inputbox(*args, initerror=initerror, **kwargs)
91 result = result[len(kwargs['init']):]
94 def menu(self, *args, **kwargs):
95 kwargs['height'] += 6 + len(kwargs['choices']) # for the border and menu entries
96 return self.dialog.menu(*args, **kwargs)
98 def msgbox(self, *args, **kwargs):
100 return self.dialog.msgbox(*args, **kwargs)
102 def passwordbox(self, *args, **kwargs):
103 kwargs['height'] += 6
104 return self.dialog.passwordbox(*args, **kwargs)
106 def infobox(self, text, **kwargs):
107 return self.dialog.infobox(text, **kwargs)
110 def prompt_wrap(f, self, *args, **kwargs):
112 return f(self, *args, **kwargs)
113 except (EOFError, KeyboardInterrupt):
116 class Prompt(object):
119 def inputbox(self, text, init='', **kwargs):
121 return raw_input(fill(text.strip()) + " " + init)
123 def menu(self, text, choices=[], **kwargs):
125 print fill(text.strip())
126 values = list(choice[0] for choice in choices)
127 for choice in choices:
128 print "% 4s %s" % (choice[0], choice[1])
130 out = raw_input("Please enter %s: " % join_or(values))
131 if out not in values:
132 print "'%s' is not a valid value" % out
136 def passwordbox(self, text, **kwargs):
138 return getpass.getpass(text + " ")
140 def msgbox(self, text, **kwargs):
142 print fill(text.strip())
143 print "Press <Enter> to continue..."
145 def infobox(self, text, **kwargs):
147 print fill(text.strip())
149 class FailPrompt(object):
151 Prompt that doesn't actually ask the user; just fails with
155 def inputbox(self, *args, **kwargs):
156 kwargs.setdefault('cmdopt', '(unknown)')
157 raise MissingRequiredParam(kwargs['cmdopt'])
158 def passwordbox(self, *args, **kwargs):
159 kwargs.setdefault('cmdopt', '(unknown)')
160 raise MissingRequiredParam(kwargs['cmdopt'])
161 def menu(self, *args, **kwargs):
162 kwargs.setdefault('cmdopt', '(unknown)')
163 raise MissingRequiredParam(kwargs['cmdopt'])
164 def msgbox(self, text, **kwargs):
166 print fill(text.strip(), break_long_words=False)
167 def infobox(self, text, **kwargs):
169 print fill(text.strip(), break_long_words=False)
171 class Error(wizard.Error):
174 class MissingRequiredParam(Error):
175 """Non-interactive, but we needed more info."""
176 def __init__(self, cmdopt):
181 ERROR: Missing required parameter, try specifying %s""" % self.cmdopt
183 class UserCancel(Error):
184 """User canceled the input process."""
186 return "\nAborting installation process; no changes were made"
188 class DialogError(Error):
189 """Dialog returned a mysterious error."""
190 def __init__(self, exit):
195 ERROR: Dialog returned a mysterious exit code %d. Please
196 send mail to scripts@mit.edu with the contents of this error
197 message and the preceding backtrace.