
    U                        S r SSKJr  SSKJr  SSKJr  SSKrSSKrSSKrSSKJ	r	  SSK
Jr  SSKrSSKJr  S	rS
r\	R"                  S\	R$                  S\	R&                  S\	R(                  S\	R*                  S\	R,                  S\	R.                  S0r " S S\5      rS rS rS rS rS rS r  " S S\5      r!\4S jr"S r#S&S jr$S r%S r&S  r'S! r( " S" S#\5      r)\'\(S$.r*S% r+g)'z(utils for search-help command resources.    )absolute_import)division)unicode_literalsN)lookup)render_document)filter   .                  c                   0    \ rS rSrSrS rS rS rS rSr	g)		TextSlice-   z,Small class for working with pieces of text.c                     Xl         X l        g N)startend)selfr   r   s      9lib/googlecloudsdk/command_lib/help_search/search_util.py__init__TextSlice.__init__0   s    JH    c                     UR                   U R                   :  a  UR                  U 5      $ U R                  UR                   :  $ r   )r   overlapsr   )r   others     r   OverlapsTextSlice.Overlaps4   s4    {{TZZ^^D!!88u{{""r   c                 R   U R                  U5      (       dG  SR                  U R                  U R                  UR                  UR                  5      n[	        U5      e[        U R                  UR                  5      U l        [        U R                  UR                  5      U l        g )Nz=Cannot merge text slices [{}:{}] and [{}:{}]: Do not overlap.)r    formatr   r   
ValueErrorminmax)r   r   msgs      r   MergeTextSlice.Merge9   sv    ==%vTXXu{{EII ? 
 sOTZZ-DJ488UYY'DHr   c                 D    [        U R                  U R                  S5      $ )Nr   )slicer   r   r   s    r   AsSliceTextSlice.AsSliceB   s    TXXq))r   )r   r   N)
__name__
__module____qualname____firstlineno____doc__r   r    r(   r-   __static_attributes__ r   r   r   r   -   s    4#
(*r   r   c                    U(       a  US   OSnU (       a  U R                  5       OSnU (       a  U R                  5       OSnSnUSU-  :  a=  U H  nXtSU-  -
  :  d  M  Xt:  d  M  US-   n  O   [        [        USU-  -
  U5      5      nUnU H"  nXs=:  a  Xb-   ::  a  O  OUnM  XvU-   :  d  M"    O   X:X  a  [        [	        X6U-   5      U5      nX:X  a"  U H  nX-
  US-   ::  d  M  Xv:  d  M  US-   n  O   [        Xh5      $ )a  Helper function to get start and end of single snippet that matches text.

Gets a snippet of length length_per_snippet with the match object
in the middle.
Cuts at the first cut point (if available, else cuts at any char)
within 1/2 the length of the start of the match object.
Then cuts at the last cut point within
the desired length (if available, else cuts at any point).
Then moves start back if there is extra room at the beginning.

Args:
  match: re.match object.
  cut_points: [int], indices of each cut char, plus start and
      end index of full string. Must be sorted.
      (The characters at cut_points are skipped.)
  length_per_snippet: int, max length of snippet to be returned

Returns:
  (int, int) 2-tuple with start and end index of the snippet
r   g      ?r   )r   r   intr&   r%   r   )	match
cut_pointslength_per_snippet
max_lengthmatch_start	match_endr   cr   s	            r   _GetStartAndEndr@   F   s   * ",z"~*!&A+"eiik) %2***	
R"445	5!/A 
 K2(:#:;UCDE 	#a
,%,,c	
''	'	  	
c*&8893
?C 		'!+	,A  
5	r   c                     SR                  U Vs/ s H  o UR                  5          PM     sn5      nU(       a9  US   R                  S:w  a  SU-   nUS   R                  [	        U 5      :w  a  US-  nU$ s  snf )aB  Helper function to build excerpt using (start, end) tuples.

Returns a string that combines substrings of the text (text[start:end]),
joins them with ellipses

Args:
  text: the text to excerpt from.
  snips: [(int, int)] list of 2-tuples representing start and end places
      to cut text.

Returns:
  str, the excerpt.
z...r   r7   )joinr-   r   r   len)textsnipssnipsnippets       r   _BuildExcerptrH      so     JJ?T\\^,?@'
Qx~~gRy}}D	!g	. @s   A5c                    [         R                  " SSU 5      n [        U 5      U::  a  U $ S/[         R                  " SU 5       Vs/ s H  o3R	                  5       PM     sn-   [        U 5      /-   nU(       d  [        U [        SXA5      /5      $ U Vs/ s H(  n[         R                  " XP[         R                  5      PM*     nn[        [        [        U5      S S9n/ nU H  n	U(       aD  US   R                  U	R	                  5       :  a#  US   R                  U	R                  5       :  a  MN  [        XU5      n
U(       aA  US   nUR                  U
5      (       a  UR                  U
5        M  UR                  U
5        M  UR                  U
5        M     U(       d  [        SXA5      /n[        X5      $ s  snf s  snf )	a{  Create snippet of text, containing given terms if present.

The max length of the snippet is the number of terms times the given length.
This is to prevent a long list of terms from resulting in nonsensically
short sub-strings. Each substring is up to length given, joined by '...'

Args:
  text: str, the part of help text to cut. Should be only ASCII characters.
  length_per_snippet: int, the length of the substrings to create containing
      each term.
  terms: [str], the terms to include.

Returns:
  str, a summary excerpt including the terms, with all consecutive whitespace
      including newlines reduced to a single ' '.
z\s+ r   z\sNc                 "    U R                  5       $ r   )r   xs    r   <lambda>_Snip.<locals>.<lambda>   s
    r   keyr7   )resubrC   finditerr   rH   r@   search
IGNORECASEsortedr   boolr   r    r(   append)rD   r;   termsrr:   termunsorted_matchesmatchesrE   r9   
next_slicelatests               r   _Snipra      sy   " 
T	"$Y$$K"++eT*BC*BQwwy*BCCT* 
	z	>?A A HMMutbiiBMM:uM6$ 01*,'
%e"IOOekkm+b			0K"56HIj	r??:&&
,,z
"
,,z
"Z   
T:BCE	t	##; D Ns   F6/F;c                 j    U [         R                  :X  a  gSR                  U R                  5       5      $ )z6Helper function to reformat header string in markdown.Nz# {})r   CAPSULEr#   upper)headers    r   _FormatHeaderrf      s&    v~~	v||~	&&r   c                 $    SR                  U 5      $ )zEHelper function to reformat string as markdown list item: {STRING}::.z{}::)r#   )items    r   _FormatItemri      s    	t	r   c                 N    [         R                  U S   [        [         5      5      $ )Nr   )SUMMARY_PRIORITIESgetrC   rL   s    r   _SummaryPriorityrm      s    			!c*<&=	>>r   c                   B    \ rS rSrSrSrSrSS jrS rS r	S r
S	 rS
rg)SummaryBuilder   a  Class that builds a summary of certain attributes of a command.

This will summarize a json representation of a command using
cloud SDK-style markdown (but with no text wrapping) by taking snippets
of the given locations in a command.

If a lookup is given from terms to where they appear, then the snippets will
include the relevant terms. Occurrences of search terms will be stylized.

Uses a small amount of simple Cloud SDK markdown.

1) To get a summary with just the brief help:
SummaryBuilder(command, {'alligator': 'capsule'}).GetSummary()

[no heading]
{excerpt of command['capsule'] with first appearance of 'alligator'}

2) To get a summary with a section (can be first-level or inside 'sections',
which is the same as detailed_help):
SummaryBuilder(command, {'': 'sections.SECTION_NAME'}).GetSummary()

# SECTION_NAME
{excerpt of 'SECTION_NAME' section of detailed help. If it is a list
 it will be joined by ', '.}

3) To get a summary with a specific positional arg:
SummaryBuilder(command, {'crocodile': 'positionals.myarg.name'}).GetSummary()

# POSITIONALS
myarg::
{excerpt of 'myarg' positional help containing 'crocodile'}

4) To get a summary with specific flags, possibly including choices/defaults:
SummaryBuilder.GetSummary(command,
                          {'a': 'flags.--my-flag.choices',
                           'b': 'flags.--my-other-flag.default'})

# FLAGS
myflag::
{excerpt of help} Choices: {comma-separated list of flag choices}
myotherflag::
{excerpt of help} Default: {flag default}

Attributes:
  command: dict, a json representation of a command.
  found_terms_map: dict, mapping of terms to the locations where they are
    found, equivalent to the return value of
    CommandSearchResults.FoundTermsMap(). This map is found under "results"
    in the command resource returned by help-search. Locations have segments
    separated by dots, such as sections.DESCRIPTION. If the first segment is
    "flags" or "positionals", there must be three segments.
  length_per_snippet: int, length of desired substrings to get from text.
zCAttempted to look up a location [{}] that was not found or invalid.z4Expected location with three segments, received [{}]c                 6    Xl         X l        X0l        / U l        g)zCreate the class.N)commandfound_terms_mapr;   _lines)r   rr   rs   r;   s       r   r   SummaryBuilder.__init__  s    L*0DKr   c                     U R                   R                  US   0 5      nSn[        U5      S:  d3   U R                  R	                  [
        R                  U5      5      5       eUR                  US   5      nU(       a  U[        R                     (       a3   U R                  R	                  [
        R                  U5      5      5       e[        [        R                  5      U R                  ;  a2  U R                  R                  [        [        R                  5      5        [        US   5      U R                  ;  a  U R                  R                  [        US   5      5        UR                  [        R                  S5      n[!        X`R"                  U5      nU(       d3   U R                  R	                  [
        R                  U5      5      5       eUnUS   [        R$                  :X  a  UR                  US   5      R                  [        R$                  5      nU(       a  X@R                  ;  a  U R                  R                  U5        ['        U[(        5      (       a9  SR                  [+        UR-                  5       5       Vs/ s H  oPM     sn5      nO6['        U[.        5      (       a!  SR                  U Vs/ s H  oPM     sn5      nSR	                  U5      nOk[        R0                  [        R                  [        R2                  /n	US   U	;   d3   U R                  R	                  [
        R                  U5      5      5       eU(       a  U R                  R                  U5        ggs  snf s  snf )z@Adds flag summary, given location such as ['flags']['--myflag'].r    r   r   , zDefault: {}.N)rr   rl   rC   _IMPRECISE_LOCATION_MESSAGEr#   DOTrB   r   	IS_HIDDEN_INVALID_LOCATION_MESSAGErf   FLAGSrt   rY   ri   DESCRIPTIONra   r;   DEFAULT
isinstancedictrW   keyslistNAMECHOICES)
r   locationrZ   flagslineflag	desc_linedefaultrM   valid_subattributess
             r   _AddFlagToSummary SummaryBuilder._AddFlagToSummary!  s   LLXa["-EDx=1 d>>EE  99Xa[!DV--. C&&--chhx.@AC.V\\"$++5
kkv||458A;t{{2
kkXa[12((6--r2i	#:#:EBi 66==
((8
 Yd {fnn$		(1+&**6>>:g	{{"
++

T
"gt$$II&*@A*@Qq*@AB'&&II'2'Qq'23'$$W- $[[&*<*<fnnMa[// E

(
(
/
/0B
CE/ 
kk  B2s   M6M;c                 r   U R                   R                  [        R                  5      nSn[	        U5      S:  d3   U R
                  R                  [        R                  U5      5      5       eU Vs/ s H   oU[        R                     US   :X  d  M  UPM"     nnU(       d3   U R                  R                  [        R                  U5      5      5       e[        [        R                  5      U R                  ;  a2  U R                  R                  [        [        R                  5      5        U R                  R                  [        US   5      5        US   nUR                  [        R                  S5      n[!        X@R"                  U5      nU(       a  U R                  R                  U5        ggs  snf )zEAdds summary of arg, given location such as ['positionals']['myarg'].rw   r   r   r   N)rr   rl   r   POSITIONALSrC   ry   r#   rz   rB   r   r|   rf   rt   rY   ri   r~   ra   r;   )r   r   rZ   positionalsr   p
positionals          r   _AddPositionalToSummary&SummaryBuilder._AddPositionalToSummaryL  sO   ,,""6#5#56KDx=1 d>>EEchhG  )Kkv{{^x{-J1kKK 66== ;V''(;
kkv'9'9:;KK{8A;/0QJ>>&,,b1D..6D
kk  Ls   2F4F4c                    U R                   nU H  nUR                  U0 5      n[        U[        5      (       a  UnM.  [        U[        5      (       a  SR                  [        U5      5      nM_  [        U[        5      (       a*  SR                  [        UR                  5       5      5      nM  [        R                  " U5      nM     W(       d3   U R                  R                  [        R                  U5      5      5       e[        US   5      nU(       a  U R                  R!                  U5        SR                  U5      nU R                  R!                  [#        XPR$                  U5      5        g)zDHelper function for adding sections in the form ['loc1','loc2',...].rx   r7   r
   N)rr   rl   r   strr   rB   rW   r   r   six	text_typer|   r#   rz   rf   rt   rY   ra   r;   )r   r   rZ   sectionlocr   re   s          r   _AddGenericSectionToSummary*SummaryBuilder._AddGenericSectionToSummary_  s   llGC$g	GS	!	!gt$$yy)gt$$yy/0}}W%  J//66sxx7IJJ48B<(F
kk 
((8
CKKd++U35r   c           
         [        U R                  R                  5       5      n[        R                  U;  a  UR                  [        R                  5        S n[        [        U5      [        S9 GH  nUR                  [        5      n[        R                  " U R                  5       VVs1 s H3  u  pVU" UR                  [        5      U5      (       d  M(  U(       d  M1  UiM5     nnnUS   [        R                  :X  a  U R                  XG5        M  US   [        R                  :X  a  U R                  XG5        M  [        R                   U;   d  [        R"                  U;   a  M  U R%                  XG5        GM     SR'                  U R(                  5      n[+        XR                  R-                  5       5      $ s  snnf )z6Builds a summary.

Returns:
  str, a markdown summary
c                     X:X  a  g[        U 5      [        U5      :w  a  gU SS USS :w  a  g[        R                  [        R                  [        R                  /nU S   U;   a
  US   U;   a  gg)zBReturns True if both locations correspond to same summary section.TFNr7   )rC   r   r   r   r~   )r   other_location
equivalents      r   _Equivalent.SummaryBuilder.GetSummary.<locals>._Equivalent  so    		#	X#n-	-	#2."-	-KK1C1CDj	"	#r(:j(Hr   rP   r   
)setrs   valuesr   rc   addrW   rm   splitrz   r   	iteritemsr}   r   r   r   PATHr   r   rB   rt   	Highlightr   )	r   all_locationsr   full_locationr   tlrZ   summarys	            r   
GetSummarySummaryBuilder.GetSummaryu  sK    ,,3356M~~]*'  } 5;KL$$S)h ]]4+?+?@ =@TQaggclH5 :; @e =	!	$x/A;&,,,$$X5;;("fkkX&=((9 M ii$GW22779::=s   -'F<F<!F<)rt   rr   rs   r;   N)r	   )r/   r0   r1   r2   r3   r|   ry   r   r   r   r   r   r4   r5   r   r   ro   ro      s7    4n L  = )V&5,';r   ro   c                 6    [        XU5      R                  5       $ )z2Gets a summary of certain attributes of a command.)ro   r   )rr   rs   r;   s      r   r   r     s     
 2
44>JLAr   c                 "    U R                  5       $ )zCStylize a given string. Currently done by converting to upper-case.)rd   )ss    r   _Stylizer     s    	
r   c           
      N   Uc  [         n[        [        U5       H  n[        R                  " X0[        R
                  5      n[        U Vs/ s H#  oPUR                  5       UR                  5        PM%     sn5      nU H  nU R                  Xr" U5      5      n M     M     U $ s  snf )ap  Stylize desired terms in a string.

Returns a copy of the original string with all substrings matching the given
terms (with case-insensitive matching) stylized.

Args:
  text: str, the original text to be highlighted.
  terms: [str], a list of terms to be matched.
  stylize: callable, the function to use to stylize the terms.

Returns:
  str, the highlighted text.
)
r   r   rX   rR   rT   rV   r   r   r   replace)rD   rZ   stylizer\   r^   r9   match_stringsmatch_strings           r   r   r     s     _GT5!dkk$bmm4GgNgUekkmEIIK8gNOM%\\,(=>d &	 " 
+ Os   *B"
c                    [         R                  " U 5      n[        R                  [        R
                  " U5      ;   aw  [        U[        R                     R                  5        Vs/ s H0  nU[        R                     (       a  M  U[        R                     PM2     sn5      U[        R                  '   UR                  5       U[        R                  '   U$ s  snf )aY  Helper function to create help text resource for listing results.

Args:
  command: dict, json representation of command.
  results: CommandSearchResults, result of searching for each term.

Returns:
  A modified copy of the json command with a summary, and with the dict
      of subcommands replaced with just a list of available subcommands.
)copydeepcopyr   COMMANDSr   iterkeysrW   r   r{   r   FoundTermsMapRESULTS)rr   resultsnew_commandr?   s       r   ProcessResultr     s     g&+__[11#)V__-446+6A!!" 	&++6+ $K 
 !( 5 5 7+fnn	+s   'CCc           
      
   U [         R                     (       a  g[        R                  " [        R                  " U5      [        R
                  5      nUR                  U [         R                     5      (       a  [         R                  $ UR                  SR                  U [         R                     [         R                  /-   5      5      (       a  [         R                  $ S n[        [        R                  " U" U 5      5      5       Hb  u  pEUR                  U5      (       d  M  [        R                  [         R                  U[         R                     [         R                  /5      s  $    U [         R                      Hq  nUR                  U[         R                     5      (       d  M,  [        R                  [         R                  U[         R                     [         R                  /5      s  $    UR                  U [         R                      5      (       a  [         R                   $ [        [        R                  " U [         R"                     5      5       HB  u  pxUR                  U5      (       d  M  [        R                  [         R"                  U/5      s  $    [        [        R                  " U" U 5      5      5       GH  u  pEUR%                  [         R&                  0 5      R%                  [         R(                  / 5      n	UR%                  [         R*                  / 5       V
s/ s H  oU	;  d  M
  U
PM     nn
UR                  [        R,                  " U5      5      (       aG  [        R                  [         R                  U[         R                     [         R*                  /5      s  $ [         R.                  [         R0                  4 Hx  nUR                  [        R,                  " UR%                  US5      5      5      (       d  M?  [        R                  [         R                  U[         R                     U/5      s  s  $    GM     U [         R                      Ht  nUR                  U[         R.                     5      (       d  M,  [        R                  [         R                  U[         R                     U[         R.                     /5      s  $    UR                  [        R,                  " [        R                  " U [         R2                     5       VV
s/ s H!  u  pU
[         R                     (       a  M  UPM#     sn
n5      5      (       a  [         R2                  $ gs  sn
f s  sn
nf )a  Helper function to get first location of term in a json command.

Locations are considered in this order: 'name', 'capsule',
'sections', 'positionals', 'flags', 'commands', 'path'. Returns a dot-
separated lookup for the location e.g. 'sections.description' or
empty string if not found.

Args:
  command: dict, json representation of command.
  term: str, the term to search.

Returns:
  str, lookup for where to find the term when building summary of command.
rw   rJ   c                     [         R                  " U [        R                     5       VVs0 s H;  u  pU[        R                     (       a  M  U[        R
                     (       a  M9  X_M=     snn$ s  snnf r   )r   r   r   r}   r{   	IS_GLOBAL)rr   	flag_namer   s      r   _FlagsLocateTerm.<locals>._Flags  sg    }}WV\\23J3 !2(() 26v7G7G2H IO3J J Js   A1A1'A1)r   r{   rR   compileescaperV   rU   r   rB   r   rW   r   r   rz   r}   r   rc   SECTIONSrl   ATTRHIDDEN_CHOICESr   r   r~   r   r   )rr   r\   regexpr   r   r   r   section_namesection_deschidden_choicesr?   choicessub_attributens                 r   
LocateTermr     s     V ::biior}}5&]]76;;'((;;]]388GFKK0FKK=@ABB;;J  fWo >?oi}}YXXv||T&++%6DEE @ F../j}}Z,--XXv)):fkk+B{{$ % % 0 ]]76>>*++>>$*	mmGFOO,-%/ l}}\""XXv566%/  fWo >?oiXXfkk2.2263H3H"MN88FNNB/L/aN3J/  L}}S]]7+,,XXv||T&++%6GHH ,,fnn=	s}}TXXmR%@A	B	BxxtFKK'8-HII > @ F../j}}Z 2 2344XXv)):fkk+B!&"4"457 8 8 0 ]]	mm3==1I#J 1#J41f../ #J 1 23 3 ??	)L 1s   0	U1=U1'U6	U6c                    [        X [        R                     5      n[        R                  " U5      n[        R                  " 5       n[
        R                  " SUU[        U5      S-  S9  SR                  UR                  5       R                  5        Vs/ s H*  nUR                  5       (       d  M  UR                  5       PM,     sn5      nU$ s  snf )ah  A resource transform function to summarize a command search result.

Uses the "results" attribute of the command to build a summary that includes
snippets of the help text of the command that include the searched terms.
Occurrences of the search term will be stylized.

Args:
  r: a json representation of a command.

Returns:
  str, a summary of the command.
rD   r   )outwidthr   )r   r   r   ioStringIOr   RenderDocumentrC   rB   getvalue
splitlineslstrip)r[   r   mdrendered_summaryr   final_summarys         r   SummaryTransformr   $  s     qFNN+,'	{{7"[[]  !#%5'*7|a'7	9
 ))+446AAC Ca
((* qxxzC - 
s   C3Cc                     U [         R                     nSR                  U [         R                     5      n[	        X!R                  5       5      $ )aP  A resource transform to get the command path with search terms stylized.

Uses the "results" attribute of the command to determine which terms to
stylize and the "path" attribute of the command to get the command path.

Args:
  r: a json representation of a command.

Returns:
  str, the path of the command with search terms stylized.
rJ   )r   r   rB   r   r   r   )r[   r   paths      r   PathTransformr   @  s9     fnn'	!FKK.	!$	4	((r   c                   *    \ rS rSrSrS rS rS rSrg)CommandSearchResultsiQ  z&Class to hold the results of a search.c                     Xl         g)an  Create a CommandSearchResults object.

Args:
  results_data: {str: str}, a dictionary from terms to the locations where
    they were found. Empty string values in the dict represent terms that
    were searched but not found. Locations should be formatted as
    dot-separated strings representing the location in the command (as
    created by LocateTerms above).
N_results_data)r   results_datas     r   r   CommandSearchResults.__init__T  s
     &r   c                 6    U R                   R                  5       $ )z,Gets a list of all terms that were searched.)r   r   r,   s    r   AllTermsCommandSearchResults.AllTerms`  s    ""$$r   c                     [         R                  " U R                  5       VVs0 s H  u  pU(       d  M  X_M     snn$ s  snnf )z=Gets a map from all terms that were found to their locations.)r   r   r   )r   kvs      r   r   "CommandSearchResults.FoundTermsMapd  s3    "}}T-?-?@F@VaADAD@FFFs   ??r   N)	r/   r0   r1   r2   r3   r   r   r   r4   r5   r   r   r   r   Q  s    .
&%Gr   r   )r   commandpathc                      [         $ r   )_TRANSFORMSr5   r   r   GetTransformsr   o  s    	r   r   ),r3   
__future__r   r   r   r   r   rR   &googlecloudsdk.command_lib.help_searchr   &googlecloudsdk.core.document_renderersr   r   	six.movesr   DEFAULT_SNIPPET_LENGTHrz   r   rc   r   r   r}   r   r   rk   objectr   r@   rH   ra   rf   ri   rm   ro   r   r   r   r   r   r   r   r   r   r   r5   r   r   <module>r     s    / &  '  	 	 9 B 
  	 KK
NNA
OOQ

LL!
OOQ
KK * *29x.1$h'
?
~;V ~;D #9A
2,GT8)"G6 G2   r   