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):
25 return "\n\n".join(textwrap.fill(p, width=width) 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
31 return width, fill(text).count("\n", width-2) + 1 + 2 + 1
33 def make(prompt, non_interactive):
36 if prompt or not has_dialog:
40 except dialog.ExecutableNotFound:
48 return ', '.join(items[:-1]) + ' or ' + items[-1]
51 def dialog_wrap(f, self, text, *args, **kwargs):
52 if 'cmdopt' in kwargs: del kwargs['cmdopt']
53 if 'width' not in kwargs and 'height' not in kwargs:
54 kwargs["width"], kwargs["height"] = guess_dimensions(text)
55 result = f(self, text, *args, **kwargs)
56 if not isinstance(result, tuple):
61 if exit == self.dialog.DIALOG_CANCEL or exit == self.dialog.DIALOG_ESC:
63 elif exit != self.dialog.DIALOG_OK:
64 # XXX: We don't support stuff like DIALOG_EXTRA or DIALOG_HELP
65 raise DialogError(exit)
70 """Ncurses interface using dialog."""
72 self.dialog = dialog.Dialog()
74 def inputbox(self, *args, **kwargs):
75 kwargs.setdefault('initerror', "You cannot edit initial value; please type characters after it.")
76 initerror = kwargs['initerror']
77 del kwargs['initerror']
78 kwargs['height'] += 5 # for the text box
79 exit, result = self.dialog.inputbox(*args, **kwargs)
80 if exit == self.dialog.DIALOG_OK:
81 # do some funny munging
82 kwargs.setdefault('init', '')
83 if result[0:len(kwargs['init'])] != kwargs['init']:
84 self.msgbox(initerror, height=10, width=50)
85 exit = self.dialog.DIALOG_OK
86 result = self.inputbox(*args, initerror=initerror, **kwargs)
88 result = result[len(kwargs['init']):]
91 def menu(self, *args, **kwargs):
92 kwargs['height'] += 6 + len(kwargs['choices']) # for the border and menu entries
93 return self.dialog.menu(*args, **kwargs)
95 def msgbox(self, *args, **kwargs):
97 return self.dialog.msgbox(*args, **kwargs)
99 def passwordbox(self, *args, **kwargs):
100 kwargs['height'] += 6
101 return self.dialog.passwordbox(*args, **kwargs)
103 def infobox(self, text, **kwargs):
104 return self.dialog.infobox(text, **kwargs)
107 def prompt_wrap(f, self, *args, **kwargs):
109 return f(self, *args, **kwargs)
110 except (EOFError, KeyboardInterrupt):
113 class Prompt(object):
116 def inputbox(self, text, init='', **kwargs):
118 return raw_input(fill(text.strip()) + " " + init)
120 def menu(self, text, choices=[], **kwargs):
122 print fill(text.strip())
123 values = list(choice[0] for choice in choices)
124 for choice in choices:
125 print "% 4s %s" % (choice[0], choice[1])
127 out = raw_input("Please enter %s: " % join_or(values))
128 if out not in values:
129 print "'%s' is not a valid value" % out
133 def passwordbox(self, text, **kwargs):
135 return getpass.getpass(text + " ")
137 def msgbox(self, text, **kwargs):
139 print fill(text.strip())
140 print "Press <Enter> to continue..."
142 def infobox(self, text, **kwargs):
144 print fill(text.strip())
146 class FailPrompt(object):
148 Prompt that doesn't actually ask the user; just fails with
152 def inputbox(self, *args, **kwargs):
153 kwargs.setdefault('cmdopt', '(unknown)')
154 raise MissingRequiredParam(kwargs['cmdopt'])
155 def passwordbox(self, *args, **kwargs):
156 kwargs.setdefault('cmdopt', '(unknown)')
157 raise MissingRequiredParam(kwargs['cmdopt'])
158 def menu(self, *args, **kwargs):
159 kwargs.setdefault('cmdopt', '(unknown)')
160 raise MissingRequiredParam(kwargs['cmdopt'])
161 def msgbox(self, text, **kwargs):
163 print fill(text.strip())
164 def infobox(self, text, **kwargs):
166 print fill(text.strip())
168 class Error(wizard.Error):
171 class MissingRequiredParam(Error):
172 """Non-interactive, but we needed more info."""
173 def __init__(self, cmdopt):
178 ERROR: Missing required parameter, try specifying %s""" % self.cmdopt
180 class UserCancel(Error):
181 """User canceled the input process."""
183 return "\nAborting installation process; no changes were made"
185 class DialogError(Error):
186 """Dialog returned a mysterious error."""
187 def __init__(self, exit):
192 ERROR: Dialog returned a mysterious exit code %d. Please
193 send mail to scripts@mit.edu with the contents of this error
194 message and the preceding backtrace.