PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i WWWWWW
Current Directory: /opt/imunify360/venv/lib/python3.11/site-packages/click
Viewing File: /opt/imunify360/venv/lib/python3.11/site-packages/click/shell_completion.py
import os import re import typing as t from gettext import gettext as _ from .core import Argument from .core import BaseCommand from .core import Context from .core import MultiCommand from .core import Option from .core import Parameter from .core import ParameterSource from .parser import split_arg_string from .utils import echo def shell_complete( cli: BaseCommand, ctx_args: t.MutableMapping[str, t.Any], prog_name: str, complete_var: str, instruction: str, ) -> int: """Perform shell completion for the given CLI program. :param cli: Command being called. :param ctx_args: Extra arguments to pass to ``cli.make_context``. :param prog_name: Name of the executable in the shell. :param complete_var: Name of the environment variable that holds the completion instruction. :param instruction: Value of ``complete_var`` with the completion instruction and shell, in the form ``instruction_shell``. :return: Status code to exit with. """ shell, _, instruction = instruction.partition("_") comp_cls = get_completion_class(shell) if comp_cls is None: return 1 comp = comp_cls(cli, ctx_args, prog_name, complete_var) if instruction == "source": echo(comp.source()) return 0 if instruction == "complete": echo(comp.complete()) return 0 return 1 class CompletionItem: """Represents a completion value and metadata about the value. The default metadata is ``type`` to indicate special shell handling, and ``help`` if a shell supports showing a help string next to the value. Arbitrary parameters can be passed when creating the object, and accessed using ``item.attr``. If an attribute wasn't passed, accessing it returns ``None``. :param value: The completion suggestion. :param type: Tells the shell script to provide special completion support for the type. Click uses ``"dir"`` and ``"file"``. :param help: String shown next to the value if supported. :param kwargs: Arbitrary metadata. The built-in implementations don't use this, but custom type completions paired with custom shell support could use it. """ __slots__ = ("value", "type", "help", "_info") def __init__( self, value: t.Any, type: str = "plain", help: t.Optional[str] = None, **kwargs: t.Any, ) -> None: self.value: t.Any = value self.type: str = type self.help: t.Optional[str] = help self._info = kwargs def __getattr__(self, name: str) -> t.Any: return self._info.get(name) # Only Bash >= 4.4 has the nosort option. _SOURCE_BASH = """\ %(complete_func)s() { local IFS=$'\\n' local response response=$(env COMP_WORDS="${COMP_WORDS[*]}" COMP_CWORD=$COMP_CWORD \ %(complete_var)s=bash_complete $1) for completion in $response; do IFS=',' read type value <<< "$completion" if [[ $type == 'dir' ]]; then COMPREPLY=() compopt -o dirnames elif [[ $type == 'file' ]]; then COMPREPLY=() compopt -o default elif [[ $type == 'plain' ]]; then COMPREPLY+=($value) fi done return 0 } %(complete_func)s_setup() { complete -o nosort -F %(complete_func)s %(prog_name)s } %(complete_func)s_setup; """ _SOURCE_ZSH = """\ #compdef %(prog_name)s %(complete_func)s() { local -a completions local -a completions_with_descriptions local -a response (( ! $+commands[%(prog_name)s] )) && return 1 response=("${(@f)$(env COMP_WORDS="${words[*]}" COMP_CWORD=$((CURRENT-1)) \ %(complete_var)s=zsh_complete %(prog_name)s)}") for type key descr in ${response}; do if [[ "$type" == "plain" ]]; then if [[ "$descr" == "_" ]]; then completions+=("$key") else completions_with_descriptions+=("$key":"$descr") fi elif [[ "$type" == "dir" ]]; then _path_files -/ elif [[ "$type" == "file" ]]; then _path_files -f fi done if [ -n "$completions_with_descriptions" ]; then _describe -V unsorted completions_with_descriptions -U fi if [ -n "$completions" ]; then compadd -U -V unsorted -a completions fi } if [[ $zsh_eval_context[-1] == loadautofunc ]]; then # autoload from fpath, call function directly %(complete_func)s "$@" else # eval/source/. command, register function for later compdef %(complete_func)s %(prog_name)s fi """ _SOURCE_FISH = """\ function %(complete_func)s; set -l response (env %(complete_var)s=fish_complete COMP_WORDS=(commandline -cp) \ COMP_CWORD=(commandline -t) %(prog_name)s); for completion in $response; set -l metadata (string split "," $completion); if test $metadata[1] = "dir"; __fish_complete_directories $metadata[2]; else if test $metadata[1] = "file"; __fish_complete_path $metadata[2]; else if test $metadata[1] = "plain"; echo $metadata[2]; end; end; end; complete --no-files --command %(prog_name)s --arguments \ "(%(complete_func)s)"; """ class ShellComplete: """Base class for providing shell completion support. A subclass for a given shell will override attributes and methods to implement the completion instructions (``source`` and ``complete``). :param cli: Command being called. :param prog_name: Name of the executable in the shell. :param complete_var: Name of the environment variable that holds the completion instruction. .. versionadded:: 8.0 """ name: t.ClassVar[str] """Name to register the shell as with :func:`add_completion_class`. This is used in completion instructions (``{name}_source`` and ``{name}_complete``). """ source_template: t.ClassVar[str] """Completion script template formatted by :meth:`source`. This must be provided by subclasses. """ def __init__( self, cli: BaseCommand, ctx_args: t.MutableMapping[str, t.Any], prog_name: str, complete_var: str, ) -> None: self.cli = cli self.ctx_args = ctx_args self.prog_name = prog_name self.complete_var = complete_var @property def func_name(self) -> str: """The name of the shell function defined by the completion script. """ safe_name = re.sub(r"\W*", "", self.prog_name.replace("-", "_"), flags=re.ASCII) return f"_{safe_name}_completion" def source_vars(self) -> t.Dict[str, t.Any]: """Vars for formatting :attr:`source_template`. By default this provides ``complete_func``, ``complete_var``, and ``prog_name``. """ return { "complete_func": self.func_name, "complete_var": self.complete_var, "prog_name": self.prog_name, } def source(self) -> str: """Produce the shell script that defines the completion function. By default this ``%``-style formats :attr:`source_template` with the dict returned by :meth:`source_vars`. """ return self.source_template % self.source_vars() def get_completion_args(self) -> t.Tuple[t.List[str], str]: """Use the env vars defined by the shell script to return a tuple of ``args, incomplete``. This must be implemented by subclasses. """ raise NotImplementedError def get_completions( self, args: t.List[str], incomplete: str ) -> t.List[CompletionItem]: """Determine the context and last complete command or parameter from the complete args. Call that object's ``shell_complete`` method to get the completions for the incomplete value. :param args: List of complete args before the incomplete value. :param incomplete: Value being completed. May be empty. """ ctx = _resolve_context(self.cli, self.ctx_args, self.prog_name, args) obj, incomplete = _resolve_incomplete(ctx, args, incomplete) return obj.shell_complete(ctx, incomplete) def format_completion(self, item: CompletionItem) -> str: """Format a completion item into the form recognized by the shell script. This must be implemented by subclasses. :param item: Completion item to format. """ raise NotImplementedError def complete(self) -> str: """Produce the completion data to send back to the shell. By default this calls :meth:`get_completion_args`, gets the completions, then calls :meth:`format_completion` for each completion. """ args, incomplete = self.get_completion_args() completions = self.get_completions(args, incomplete) out = [self.format_completion(item) for item in completions] return "\n".join(out) class BashComplete(ShellComplete): """Shell completion for Bash.""" name = "bash" source_template = _SOURCE_BASH @staticmethod def _check_version() -> None: import subprocess output = subprocess.run( ["bash", "-c", 'echo "${BASH_VERSION}"'], stdout=subprocess.PIPE ) match = re.search(r"^(\d+)\.(\d+)\.\d+", output.stdout.decode()) if match is not None: major, minor = match.groups() if major < "4" or major == "4" and minor < "4": echo( _( "Shell completion is not supported for Bash" " versions older than 4.4." ), err=True, ) else: echo( _("Couldn't detect Bash version, shell completion is not supported."), err=True, ) def source(self) -> str: self._check_version() return super().source() def get_completion_args(self) -> t.Tuple[t.List[str], str]: cwords = split_arg_string(os.environ["COMP_WORDS"]) cword = int(os.environ["COMP_CWORD"]) args = cwords[1:cword] try: incomplete = cwords[cword] except IndexError: incomplete = "" return args, incomplete def format_completion(self, item: CompletionItem) -> str: return f"{item.type},{item.value}" class ZshComplete(ShellComplete): """Shell completion for Zsh.""" name = "zsh" source_template = _SOURCE_ZSH def get_completion_args(self) -> t.Tuple[t.List[str], str]: cwords = split_arg_string(os.environ["COMP_WORDS"]) cword = int(os.environ["COMP_CWORD"]) args = cwords[1:cword] try: incomplete = cwords[cword] except IndexError: incomplete = "" return args, incomplete def format_completion(self, item: CompletionItem) -> str: return f"{item.type}\n{item.value}\n{item.help if item.help else '_'}" class FishComplete(ShellComplete): """Shell completion for Fish.""" name = "fish" source_template = _SOURCE_FISH def get_completion_args(self) -> t.Tuple[t.List[str], str]: cwords = split_arg_string(os.environ["COMP_WORDS"]) incomplete = os.environ["COMP_CWORD"] args = cwords[1:] # Fish stores the partial word in both COMP_WORDS and # COMP_CWORD, remove it from complete args. if incomplete and args and args[-1] == incomplete: args.pop() return args, incomplete def format_completion(self, item: CompletionItem) -> str: if item.help: return f"{item.type},{item.value}\t{item.help}" return f"{item.type},{item.value}" ShellCompleteType = t.TypeVar("ShellCompleteType", bound=t.Type[ShellComplete]) _available_shells: t.Dict[str, t.Type[ShellComplete]] = { "bash": BashComplete, "fish": FishComplete, "zsh": ZshComplete, } def add_completion_class( cls: ShellCompleteType, name: t.Optional[str] = None ) -> ShellCompleteType: """Register a :class:`ShellComplete` subclass under the given name. The name will be provided by the completion instruction environment variable during completion. :param cls: The completion class that will handle completion for the shell. :param name: Name to register the class under. Defaults to the class's ``name`` attribute. """ if name is None: name = cls.name _available_shells[name] = cls return cls def get_completion_class(shell: str) -> t.Optional[t.Type[ShellComplete]]: """Look up a registered :class:`ShellComplete` subclass by the name provided by the completion instruction environment variable. If the name isn't registered, returns ``None``. :param shell: Name the class is registered under. """ return _available_shells.get(shell) def _is_incomplete_argument(ctx: Context, param: Parameter) -> bool: """Determine if the given parameter is an argument that can still accept values. :param ctx: Invocation context for the command represented by the parsed complete args. :param param: Argument object being checked. """ if not isinstance(param, Argument): return False assert param.name is not None # Will be None if expose_value is False. value = ctx.params.get(param.name) return ( param.nargs == -1 or ctx.get_parameter_source(param.name) is not ParameterSource.COMMANDLINE or ( param.nargs > 1 and isinstance(value, (tuple, list)) and len(value) < param.nargs ) ) def _start_of_option(ctx: Context, value: str) -> bool: """Check if the value looks like the start of an option.""" if not value: return False c = value[0] return c in ctx._opt_prefixes def _is_incomplete_option(ctx: Context, args: t.List[str], param: Parameter) -> bool: """Determine if the given parameter is an option that needs a value. :param args: List of complete args before the incomplete value. :param param: Option object being checked. """ if not isinstance(param, Option): return False if param.is_flag or param.count: return False last_option = None for index, arg in enumerate(reversed(args)): if index + 1 > param.nargs: break if _start_of_option(ctx, arg): last_option = arg return last_option is not None and last_option in param.opts def _resolve_context( cli: BaseCommand, ctx_args: t.MutableMapping[str, t.Any], prog_name: str, args: t.List[str], ) -> Context: """Produce the context hierarchy starting with the command and traversing the complete arguments. This only follows the commands, it doesn't trigger input prompts or callbacks. :param cli: Command being called. :param prog_name: Name of the executable in the shell. :param args: List of complete args before the incomplete value. """ ctx_args["resilient_parsing"] = True ctx = cli.make_context(prog_name, args.copy(), **ctx_args) args = ctx.protected_args + ctx.args while args: command = ctx.command if isinstance(command, MultiCommand): if not command.chain: name, cmd, args = command.resolve_command(ctx, args) if cmd is None: return ctx ctx = cmd.make_context(name, args, parent=ctx, resilient_parsing=True) args = ctx.protected_args + ctx.args else: sub_ctx = ctx while args: name, cmd, args = command.resolve_command(ctx, args) if cmd is None: return ctx sub_ctx = cmd.make_context( name, args, parent=ctx, allow_extra_args=True, allow_interspersed_args=False, resilient_parsing=True, ) args = sub_ctx.args ctx = sub_ctx args = [*sub_ctx.protected_args, *sub_ctx.args] else: break return ctx def _resolve_incomplete( ctx: Context, args: t.List[str], incomplete: str ) -> t.Tuple[t.Union[BaseCommand, Parameter], str]: """Find the Click object that will handle the completion of the incomplete value. Return the object and the incomplete value. :param ctx: Invocation context for the command represented by the parsed complete args. :param args: List of complete args before the incomplete value. :param incomplete: Value being completed. May be empty. """ # Different shells treat an "=" between a long option name and # value differently. Might keep the value joined, return the "=" # as a separate item, or return the split name and value. Always # split and discard the "=" to make completion easier. if incomplete == "=": incomplete = "" elif "=" in incomplete and _start_of_option(ctx, incomplete): name, _, incomplete = incomplete.partition("=") args.append(name) # The "--" marker tells Click to stop treating values as options # even if they start with the option character. If it hasn't been # given and the incomplete arg looks like an option, the current # command will provide option name completions. if "--" not in args and _start_of_option(ctx, incomplete): return ctx.command, incomplete params = ctx.command.get_params(ctx) # If the last complete arg is an option name with an incomplete # value, the option will provide value completions. for param in params: if _is_incomplete_option(ctx, args, param): return param, incomplete # It's not an option name or value. The first argument without a # parsed value will provide value completions. for param in params: if _is_incomplete_argument(ctx, param): return param, incomplete # There were no unparsed arguments, the command may be a group that # will provide command name completions. return ctx.command, incomplete