@@ -70,18 +70,14 @@ def HelpText(component, trace=None, verbose=False):
7070 description_section = _DescriptionSection (component , info )
7171 # TODO(dbieber): Add returns and raises sections for functions.
7272
73- if inspect .isroutine (component ) or inspect .isclass (component ):
74- # For functions (ARGUMENTS / POSITIONAL ARGUMENTS, FLAGS)
73+ if callable (component ):
7574 args_and_flags_sections , notes_sections = _ArgsAndFlagsSections (
7675 info , spec , metadata )
77- usage_details_sections = []
7876 else :
79- # For objects (GROUPS, COMMANDS, VALUES, INDEXES)
80- # TODO(dbieber): Show callable function usage in help text.
8177 args_and_flags_sections = []
8278 notes_sections = []
83- usage_details_sections = _UsageDetailsSections (component ,
84- actions_grouped_by_kind )
79+ usage_details_sections = _UsageDetailsSections (component ,
80+ actions_grouped_by_kind )
8581
8682 sections = (
8783 [name_section , synopsis_section , description_section ]
@@ -119,21 +115,19 @@ def _SynopsisSection(component, actions_grouped_by_kind, spec, metadata,
119115 """The "Synopsis" section of the help string."""
120116 current_command = _GetCurrentCommand (trace = trace , include_separators = True )
121117
122- # TODO(dbieber): Support callable functions.
123- if inspect .isroutine (component ) or inspect .isclass (component ):
124- # For function:
125- args_and_flags = _GetArgsAndFlagsString (spec , metadata )
126- synopsis_section_template = '{current_command} {args_and_flags}'
127- text = synopsis_section_template .format (
128- current_command = current_command , args_and_flags = args_and_flags )
118+ possible_actions = _GetPossibleActions (actions_grouped_by_kind )
129119
130- else :
131- # For object:
132- possible_actions_string = _GetPossibleActionsString (actions_grouped_by_kind )
133- synopsis_template = '{current_command} {possible_actions}'
134- text = synopsis_template .format (
135- current_command = current_command ,
136- possible_actions = possible_actions_string )
120+ continuations = []
121+ if possible_actions :
122+ continuations .append (_GetPossibleActionsString (possible_actions ))
123+ if callable (component ):
124+ continuations .append (_GetArgsAndFlagsString (spec , metadata ))
125+ continuation = ' | ' .join (continuations )
126+
127+ synopsis_template = '{current_command} {continuation}'
128+ text = synopsis_template .format (
129+ current_command = current_command ,
130+ continuation = continuation )
137131
138132 return ('SYNOPSIS' , text )
139133
@@ -225,22 +219,17 @@ def _UsageDetailsSections(component, actions_grouped_by_kind):
225219 """The usage details sections of the help string."""
226220 groups , commands , values , indexes = actions_grouped_by_kind
227221
228- usage_details_sections = []
222+ sections = []
223+ if groups .members :
224+ sections .append (_MakeUsageDetailsSection (groups ))
225+ if commands .members :
226+ sections .append (_MakeUsageDetailsSection (commands ))
227+ if values .members :
228+ sections .append (_ValuesUsageDetailsSection (component , values ))
229+ if indexes .members :
230+ sections .append (('INDEXES' , _NewChoicesSection ('INDEX' , indexes .names )))
229231
230- if groups :
231- usage_details_section = _GroupUsageDetailsSection (groups )
232- usage_details_sections .append (usage_details_section )
233- if commands :
234- usage_details_section = _CommandUsageDetailsSection (commands )
235- usage_details_sections .append (usage_details_section )
236- if values :
237- usage_details_section = _ValuesUsageDetailsSection (component , values )
238- usage_details_sections .append (usage_details_section )
239- if indexes :
240- usage_details_sections .append (
241- ('INDEXES' , _NewChoicesSection ('INDEX' , [indexes ])))
242-
243- return usage_details_sections
232+ return sections
244233
245234
246235def _GetSummary (info ):
@@ -302,51 +291,46 @@ def _GetArgsAndFlagsString(spec, metadata):
302291 return ' ' .join (arg_and_flag_strings )
303292
304293
305- def _GetPossibleActionsString (actions_grouped_by_kind ):
306- """A help screen string listing the possible action kinds available."""
307- groups , commands , values , indexes = actions_grouped_by_kind
308-
294+ def _GetPossibleActions (actions_grouped_by_kind ):
295+ """The list of possible action kinds."""
309296 possible_actions = []
310- if groups :
311- possible_actions .append ('GROUP' )
312- if commands :
313- possible_actions .append ('COMMAND' )
314- if values :
315- possible_actions .append ('VALUE' )
316- if indexes :
317- possible_actions .append ('INDEX' )
297+ for action_group in actions_grouped_by_kind :
298+ if action_group .members :
299+ possible_actions .append (action_group .name )
300+ return possible_actions
301+
318302
319- possible_actions_string = ' | ' .join (
320- formatting .Underline (action ) for action in possible_actions )
321- return possible_actions_string
303+ def _GetPossibleActionsString (possible_actions ):
304+ """A help screen string listing the possible action kinds available."""
305+ return ' | ' .join (formatting .Underline (action .upper ())
306+ for action in possible_actions )
322307
323308
324309def _GetActionsGroupedByKind (component , verbose = False ):
325310 """Gets lists of available actions, grouped by action kind."""
326- groups = []
327- commands = []
328- values = []
311+ groups = ActionGroup (name = 'group' , plural = 'groups' )
312+ commands = ActionGroup (name = 'command' , plural = 'commands' )
313+ values = ActionGroup (name = 'value' , plural = 'values' )
314+ indexes = ActionGroup (name = 'index' , plural = 'indexes' )
329315
330316 members = completion ._Members (component , verbose ) # pylint: disable=protected-access
331317 for member_name , member in members :
332318 member_name = str (member_name )
333319 if value_types .IsGroup (member ):
334- groups .append (( member_name , member ) )
320+ groups .Add ( name = member_name , member = member )
335321 if value_types .IsCommand (member ):
336- commands .append (( member_name , member ) )
322+ commands .Add ( name = member_name , member = member )
337323 if value_types .IsValue (member ):
338- values .append (( member_name , member ) )
324+ values .Add ( name = member_name , member = member )
339325
340- indexes = None
341326 if isinstance (component , (list , tuple )) and component :
342327 component_len = len (component )
343- # WARNING: Note that indexes is a string, whereas the rest are lists.
344328 if component_len < 10 :
345- indexes = ', ' .join (str (x ) for x in range (component_len ))
329+ indexes . Add ( name = ', ' .join (str (x ) for x in range (component_len ) ))
346330 else :
347- indexes = '0..{max}' .format (max = component_len - 1 )
331+ indexes . Add ( name = '0..{max}' .format (max = component_len - 1 ) )
348332
349- return groups , commands , values , indexes
333+ return [ groups , commands , values , indexes ]
350334
351335
352336def _GetCurrentCommand (trace = None , include_separators = True ):
@@ -420,38 +404,28 @@ def _GetArgDescription(name, docstring_info):
420404 return None
421405
422406
423- def _GroupUsageDetailsSection (groups ):
424- """Creates a section tuple for the groups section of the usage details."""
425- group_item_strings = []
426- for group_name , group in groups :
427- group_info = inspectutils .Info (group )
428- group_item = group_name
429- if 'docstring_info' in group_info :
430- group_docstring_info = group_info ['docstring_info' ]
431- if group_docstring_info :
432- group_item = _CreateItem (group_name , group_docstring_info .summary )
433- group_item_strings .append (group_item )
434- return ('GROUPS' , _NewChoicesSection ('GROUP' , group_item_strings ))
435-
436-
437- def _CommandUsageDetailsSection (commands ):
438- """Creates a section tuple for the commands section of the usage details."""
439- command_item_strings = []
440- for command_name , command in commands :
441- command_info = inspectutils .Info (command )
442- command_item = command_name
443- if 'docstring_info' in command_info :
444- command_docstring_info = command_info ['docstring_info' ]
445- if command_docstring_info :
446- command_item = _CreateItem (command_name , command_docstring_info .summary )
447- command_item_strings .append (command_item )
448- return ('COMMANDS' , _NewChoicesSection ('COMMAND' , command_item_strings ))
407+ def _MakeUsageDetailsSection (action_group ):
408+ """Creates a usage details section for the provided action group."""
409+ item_strings = []
410+ for name , member in action_group .GetItems ():
411+ info = inspectutils .Info (member )
412+ item = name
413+ docstring_info = info .get ('docstring_info' )
414+ if (docstring_info
415+ and not custom_descriptions .NeedsCustomDescription (member )):
416+ summary = docstring_info .summary
417+ else :
418+ summary = None
419+ item = _CreateItem (name , summary )
420+ item_strings .append (item )
421+ return (action_group .plural .upper (),
422+ _NewChoicesSection (action_group .name .upper (), item_strings ))
449423
450424
451425def _ValuesUsageDetailsSection (component , values ):
452426 """Creates a section tuple for the values section of the usage details."""
453427 value_item_strings = []
454- for value_name , value in values :
428+ for value_name , value in values . GetItems () :
455429 del value
456430 init_info = inspectutils .Info (component .__class__ .__init__ )
457431 value_item = None
@@ -590,34 +564,17 @@ def UsageTextForObject(component, trace=None, verbose=False):
590564 command = ''
591565
592566 actions_grouped_by_kind = _GetActionsGroupedByKind (component , verbose = verbose )
593- groups , commands , values , indexes = actions_grouped_by_kind
594567
595568 possible_actions = []
596569 availability_lines = []
597- if groups :
598- possible_actions .append ('group' )
599- groups_text = _CreateAvailabilityLine (
600- header = 'available groups:' ,
601- items = [name for name , _ in groups ])
602- availability_lines .append (groups_text )
603- if commands :
604- possible_actions .append ('command' )
605- commands_text = _CreateAvailabilityLine (
606- header = 'available commands:' ,
607- items = [name for name , _ in commands ])
608- availability_lines .append (commands_text )
609- if values :
610- possible_actions .append ('value' )
611- values_text = _CreateAvailabilityLine (
612- header = 'available values:' ,
613- items = [name for name , _ in values ])
614- availability_lines .append (values_text )
615- if indexes :
616- possible_actions .append ('index' )
617- indexes_text = _CreateAvailabilityLine (
618- header = 'available indexes:' ,
619- items = indexes )
620- availability_lines .append (indexes_text )
570+ for action_group in actions_grouped_by_kind :
571+ if action_group .members :
572+ possible_actions .append (action_group .name )
573+ availability_line = _CreateAvailabilityLine (
574+ header = 'available {plural}:' .format (plural = action_group .plural ),
575+ items = action_group .names
576+ )
577+ availability_lines .append (availability_line )
621578
622579 if possible_actions :
623580 possible_actions_string = ' <{actions}>' .format (
@@ -641,3 +598,21 @@ def _CreateAvailabilityLine(header, items,
641598 indented_items_text = formatting .Indent (items_text , spaces = items_indent )
642599 indented_header = formatting .Indent (header , spaces = header_indent )
643600 return indented_header + indented_items_text [len (indented_header ):] + '\n '
601+
602+
603+ class ActionGroup (object ):
604+ """A group of actions of the same kind."""
605+
606+ def __init__ (self , name , plural ):
607+ self .name = name
608+ self .plural = plural
609+ self .names = []
610+ self .members = []
611+
612+ def Add (self , name , member = None ):
613+ self .names .append (name )
614+ self .members .append (member )
615+
616+ def GetItems (self ):
617+ return zip (self .names , self .members )
618+
0 commit comments