##// END OF EJS Templates
wrap helpstring output to 80 cols
MinRK -
Show More
@@ -33,7 +33,11 b' from IPython.utils.traitlets import ('
33 Unicode, List, Int, Enum, Dict, Instance
33 Unicode, List, Int, Enum, Dict, Instance
34 )
34 )
35 from IPython.utils.importstring import import_item
35 from IPython.utils.importstring import import_item
36 from IPython.utils.text import indent
36 from IPython.utils.text import indent, wrap_paragraphs, dedent
37
38 #-----------------------------------------------------------------------------
39 # function for re-wrapping a helpstring
40 #-----------------------------------------------------------------------------
37
41
38 #-----------------------------------------------------------------------------
42 #-----------------------------------------------------------------------------
39 # Descriptions for the various sections
43 # Descriptions for the various sections
@@ -44,6 +48,8 b" Flags are command-line arguments passed as '--<flag>'."
44 These take no parameters, unlike regular key-value arguments.
48 These take no parameters, unlike regular key-value arguments.
45 They are typically used for setting boolean flags, or enabling
49 They are typically used for setting boolean flags, or enabling
46 modes that involve setting multiple options together.
50 modes that involve setting multiple options together.
51
52 Flags *always* begin with '--', never just one '-'.
47 """.strip() # trim newlines of front and back
53 """.strip() # trim newlines of front and back
48
54
49 alias_description = """
55 alias_description = """
@@ -104,10 +110,18 b' class Application(SingletonConfigurable):'
104 # this must be a dict of two-tuples, the first element being the Config/dict
110 # this must be a dict of two-tuples, the first element being the Config/dict
105 # and the second being the help string for the flag
111 # and the second being the help string for the flag
106 flags = Dict()
112 flags = Dict()
113 def _flags_changed(self, name, old, new):
114 """ensure flags dict is valid"""
115 for key,value in new.iteritems():
116 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
117 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
118 assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value)
119
107
120
108 # subcommands for launching other applications
121 # subcommands for launching other applications
109 # if this is not empty, this will be a parent Application
122 # if this is not empty, this will be a parent Application
110 # this must be a dict of two-tuples, the first element being the application class/import string
123 # this must be a dict of two-tuples,
124 # the first element being the application class/import string
111 # and the second being the help string for the subcommand
125 # and the second being the help string for the subcommand
112 subcommands = Dict()
126 subcommands = Dict()
113 # parse_command_line will initialize a subapp, if requested
127 # parse_command_line will initialize a subapp, if requested
@@ -123,11 +137,6 b' class Application(SingletonConfigurable):'
123 # options.
137 # options.
124 self.classes.insert(0, self.__class__)
138 self.classes.insert(0, self.__class__)
125
139
126 # ensure self.flags dict is valid
127 for key,value in self.flags.iteritems():
128 assert len(value) == 2, "Bad flag: %r:%s"%(key,value)
129 assert isinstance(value[0], (dict, Config)), "Bad flag: %r:%s"%(key,value)
130 assert isinstance(value[1], basestring), "Bad flag: %r:%s"%(key,value)
131 self.init_logging()
140 self.init_logging()
132
141
133 def _config_changed(self, name, old, new):
142 def _config_changed(self, name, old, new):
@@ -170,14 +179,16 b' class Application(SingletonConfigurable):'
170 self.log.setLevel(new)
179 self.log.setLevel(new)
171
180
172 def print_alias_help(self):
181 def print_alias_help(self):
173 """print the alias part of the help"""
182 """Print the alias part of the help."""
174 if not self.aliases:
183 if not self.aliases:
175 return
184 return
176
185
177 lines = ['Aliases']
186 lines = ['Aliases']
178 lines.append('-'*len(lines[0]))
187 lines.append('-'*len(lines[0]))
179 lines.append(self.alias_description)
180 lines.append('')
188 lines.append('')
189 for p in wrap_paragraphs(self.alias_description):
190 lines.append(p)
191 lines.append('')
181
192
182 classdict = {}
193 classdict = {}
183 for cls in self.classes:
194 for cls in self.classes:
@@ -197,23 +208,25 b' class Application(SingletonConfigurable):'
197 print '\n'.join(lines)
208 print '\n'.join(lines)
198
209
199 def print_flag_help(self):
210 def print_flag_help(self):
200 """print the flag part of the help"""
211 """Print the flag part of the help."""
201 if not self.flags:
212 if not self.flags:
202 return
213 return
203
214
204 lines = ['Flags']
215 lines = ['Flags']
205 lines.append('-'*len(lines[0]))
216 lines.append('-'*len(lines[0]))
206 lines.append(self.flag_description)
207 lines.append('')
217 lines.append('')
218 for p in wrap_paragraphs(self.flag_description):
219 lines.append(p)
220 lines.append('')
208
221
209 for m, (cfg,help) in self.flags.iteritems():
222 for m, (cfg,help) in self.flags.iteritems():
210 lines.append('--'+m)
223 lines.append('--'+m)
211 lines.append(indent(help.strip(), flatten=True))
224 lines.append(indent(dedent(help.strip())))
212 lines.append('')
225 lines.append('')
213 print '\n'.join(lines)
226 print '\n'.join(lines)
214
227
215 def print_subcommands(self):
228 def print_subcommands(self):
216 """print the subcommand part of the help"""
229 """Print the subcommand part of the help."""
217 if not self.subcommands:
230 if not self.subcommands:
218 return
231 return
219
232
@@ -222,14 +235,14 b' class Application(SingletonConfigurable):'
222 for subc, (cls,help) in self.subcommands.iteritems():
235 for subc, (cls,help) in self.subcommands.iteritems():
223 lines.append("%s : %s"%(subc, cls))
236 lines.append("%s : %s"%(subc, cls))
224 if help:
237 if help:
225 lines.append(indent(help.strip(), flatten=True))
238 lines.append(indent(dedent(help.strip())))
226 lines.append('')
239 lines.append('')
227 print '\n'.join(lines)
240 print '\n'.join(lines)
228
241
229 def print_help(self, classes=False):
242 def print_help(self, classes=False):
230 """Print the help for each Configurable class in self.classes.
243 """Print the help for each Configurable class in self.classes.
231
244
232 If classes=False (the default), only flags and aliases are printed
245 If classes=False (the default), only flags and aliases are printed.
233 """
246 """
234 self.print_subcommands()
247 self.print_subcommands()
235 self.print_flag_help()
248 self.print_flag_help()
@@ -239,8 +252,10 b' class Application(SingletonConfigurable):'
239 if self.classes:
252 if self.classes:
240 print "Class parameters"
253 print "Class parameters"
241 print "----------------"
254 print "----------------"
242 print self.keyvalue_description
243 print
255 print
256 for p in wrap_paragraphs(self.keyvalue_description):
257 print p
258 print
244
259
245 for cls in self.classes:
260 for cls in self.classes:
246 cls.class_print_help()
261 cls.class_print_help()
@@ -251,8 +266,9 b' class Application(SingletonConfigurable):'
251
266
252 def print_description(self):
267 def print_description(self):
253 """Print the application description."""
268 """Print the application description."""
254 print self.description
269 for p in wrap_paragraphs(self.description):
255 print
270 print p
271 print
256
272
257 def print_version(self):
273 def print_version(self):
258 """Print the version string."""
274 """Print the version string."""
@@ -269,7 +285,7 b' class Application(SingletonConfigurable):'
269 self.config = newconfig
285 self.config = newconfig
270
286
271 def initialize_subcommand(self, subc, argv=None):
287 def initialize_subcommand(self, subc, argv=None):
272 """Initialize a subcommand with argv"""
288 """Initialize a subcommand with argv."""
273 subapp,help = self.subcommands.get(subc)
289 subapp,help = self.subcommands.get(subc)
274
290
275 if isinstance(subapp, basestring):
291 if isinstance(subapp, basestring):
@@ -330,7 +346,7 b' class Application(SingletonConfigurable):'
330 #-----------------------------------------------------------------------------
346 #-----------------------------------------------------------------------------
331
347
332 def boolean_flag(name, configurable, set_help='', unset_help=''):
348 def boolean_flag(name, configurable, set_help='', unset_help=''):
333 """helper for building basic --trait, --no-trait flags
349 """Helper for building basic --trait, --no-trait flags.
334
350
335 Parameters
351 Parameters
336 ----------
352 ----------
@@ -360,3 +376,4 b" def boolean_flag(name, configurable, set_help='', unset_help=''):"
360 setter = {cls : {trait : True}}
376 setter = {cls : {trait : True}}
361 unsetter = {cls : {trait : False}}
377 unsetter = {cls : {trait : False}}
362 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
378 return {name : (setter, set_help), 'no-'+name : (unsetter, unset_help)}
379
@@ -21,12 +21,12 b' Authors:'
21 # Imports
21 # Imports
22 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
23
23
24 from copy import deepcopy
25 import datetime
24 import datetime
25 from copy import deepcopy
26
26
27 from loader import Config
27 from loader import Config
28 from IPython.utils.traitlets import HasTraits, Instance
28 from IPython.utils.traitlets import HasTraits, Instance
29 from IPython.utils.text import indent
29 from IPython.utils.text import indent, wrap_paragraphs
30
30
31
31
32 #-----------------------------------------------------------------------------
32 #-----------------------------------------------------------------------------
@@ -51,7 +51,7 b' class Configurable(HasTraits):'
51 created = None
51 created = None
52
52
53 def __init__(self, **kwargs):
53 def __init__(self, **kwargs):
54 """Create a conigurable given a config config.
54 """Create a configurable given a config config.
55
55
56 Parameters
56 Parameters
57 ----------
57 ----------
@@ -153,27 +153,31 b' class Configurable(HasTraits):'
153
153
154 @classmethod
154 @classmethod
155 def class_get_trait_help(cls, trait):
155 def class_get_trait_help(cls, trait):
156 """Get the help string for a single """
156 """Get the help string for a single trait."""
157 lines = []
157 lines = []
158 header = "%s.%s : %s" % (cls.__name__, trait.name, trait.__class__.__name__)
158 header = "%s.%s : %s" % (cls.__name__, trait.name, trait.__class__.__name__)
159 lines.append(header)
159 try:
160 try:
160 dvr = repr(trait.get_default_value())
161 dvr = repr(trait.get_default_value())
161 except Exception:
162 except Exception:
162 dvr = None # ignore defaults we can't construct
163 dvr = None # ignore defaults we can't construct
163 if dvr is not None:
164 if dvr is not None:
164 header += ' [default: %s]'%dvr
165 if len(dvr) > 64:
165 lines.append(header)
166 dvr = dvr[:61]+'...'
167 lines.append(indent('Default: %s'%dvr, 4))
168 if 'Enum' in trait.__class__.__name__:
169 # include Enum choices
170 lines.append(indent('Choices: %r'%(trait.values,)))
166
171
167 help = trait.get_metadata('help')
172 help = trait.get_metadata('help')
168 if help is not None:
173 if help is not None:
169 lines.append(indent(help.strip(), flatten=True))
174 help = '\n'.join(wrap_paragraphs(help, 76))
170 if 'Enum' in trait.__class__.__name__:
175 lines.append(indent(help, 4))
171 # include Enum choices
172 lines.append(indent('Choices: %r'%(trait.values,), flatten=True))
173 return '\n'.join(lines)
176 return '\n'.join(lines)
174
177
175 @classmethod
178 @classmethod
176 def class_print_help(cls):
179 def class_print_help(cls):
180 """Get the help string for a single trait and print it."""
177 print cls.class_get_help()
181 print cls.class_get_help()
178
182
179
183
@@ -19,6 +19,7 b' import __main__'
19 import os
19 import os
20 import re
20 import re
21 import shutil
21 import shutil
22 import textwrap
22 from string import Formatter
23 from string import Formatter
23
24
24 from IPython.external.path import path
25 from IPython.external.path import path
@@ -520,6 +521,58 b' def format_screen(strng):'
520 strng = par_re.sub('',strng)
521 strng = par_re.sub('',strng)
521 return strng
522 return strng
522
523
524 def dedent(text):
525 """Equivalent of textwrap.dedent that ignores unindented first line.
526
527 This means it will still dedent strings like:
528 '''foo
529 is a bar
530 '''
531
532 For use in wrap_paragraphs.
533 """
534
535 if text.startswith('\n'):
536 # text starts with blank line, don't ignore the first line
537 return textwrap.dedent(text)
538
539 # split first line
540 splits = text.split('\n',1)
541 if len(splits) == 1:
542 # only one line
543 return textwrap.dedent(text)
544
545 first, rest = splits
546 # dedent everything but the first line
547 rest = textwrap.dedent(rest)
548 return '\n'.join([first, rest])
549
550 def wrap_paragraphs(text, ncols=80):
551 """Wrap multiple paragraphs to fit a specified width.
552
553 This is equivalent to textwrap.wrap, but with support for multiple
554 paragraphs, as separated by empty lines.
555
556 Returns
557 -------
558
559 list of complete paragraphs, wrapped to fill `ncols` columns.
560 """
561 paragraph_re = re.compile(r'\n(\s*\n)+', re.MULTILINE)
562 text = dedent(text).strip()
563 paragraphs = paragraph_re.split(text)[::2] # every other entry is space
564 out_ps = []
565 indent_re = re.compile(r'\n\s+', re.MULTILINE)
566 for p in paragraphs:
567 # presume indentation that survives dedent is meaningful formatting,
568 # so don't fill unless text is flush.
569 if indent_re.search(p) is None:
570 # wrap paragraph
571 p = textwrap.fill(p, ncols)
572 out_ps.append(p)
573 return out_ps
574
575
523
576
524 class EvalFormatter(Formatter):
577 class EvalFormatter(Formatter):
525 """A String Formatter that allows evaluation of simple expressions.
578 """A String Formatter that allows evaluation of simple expressions.
General Comments 0
You need to be logged in to leave comments. Login now