From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17225 invoked from network); 15 Feb 1999 11:01:20 -0000 Received: from sunsite.auc.dk (130.225.51.30) by ns1.primenet.com.au with SMTP; 15 Feb 1999 11:01:20 -0000 Received: (qmail 5682 invoked by alias); 15 Feb 1999 11:00:38 -0000 Mailing-List: contact zsh-workers-help@sunsite.auc.dk; run by ezmlm Precedence: bulk X-No-Archive: yes X-Seq: 5386 Received: (qmail 5671 invoked from network); 15 Feb 1999 11:00:33 -0000 Date: Mon, 15 Feb 1999 11:59:47 +0100 (MET) Message-Id: <199902151059.LAA24631@beta.informatik.hu-berlin.de> From: Sven Wischnowsky To: zsh-workers@sunsite.auc.dk Subject: New style completion stuff I've written this over the weekend and edited it just a bit to answer some of the mails I found today... I'd like to point out that near the end of the text there are some shell code examples where I mention a few problems with the parameter expansion stuff, maybe we should discuss this separately. The changes I am thinking about are: The arrays we currently use hold names of contexts instead of functions. A new array `contexts' is a assoc array used to get the definitions for context names. This is done by a function, e.g.: __complete() { local val i for i do val="$contexts[$i]" if [[ "$val[1]" = ' ' ]]; then builtin . "$val[2,-1]" val="$val:t" contexts[$i]="$val" fi if (( ${(P)+val} )); then complist "${(@P)val}" else "$val" fi done } The automatically autoloaded files contain definitions for contexts, description lines are only `#helper', `#function', or `#array' (maybe we can find better names). They do not contain the definitions for binding command names to context, the name of the file is the name of the context. The definitions define what is to be done when completing in the given context. For simple contexts this is done directly by using `complist' or `compadd'. For more complex contexts (like those that may have to be named after a command), this recursively calls `__complete', probably via a helper function that does some testing. These helper functions are those Bart mentioned and should also be used to make defining complicated completions easier. The example files also contain examples for them (e.g. `__if_between'). I have put together a few example files for this: the tar-file below adds a directory Functions/Comp with the files. Most of this is copied together from the Functions/Completion directory, but not all the files can be shared, so you might want to use only one of the dirs at a time. I agree with Bart that the mapping is (in a certain sense) more important than the contents of the files, and the code in the file below actually improve this, I think. I just had to shift my point of view again... Some of the files still contain only an array with options for complist, maybe we can find a way to avoid things like this (if assoc arrays could contain sub-arrays...). I also agree with Bart that match-generation isn't the hard part, and I never wanted to give the impression that I think it is. The hard part is to find out what we want to complete in the place we currently are in, of course. The example below uses the above mentioned helper functions to (hopefully) simplify the tests need for it and to re-invoke the whole completion code. The dispatcher function is used instead of a `case...esac' to make it possible to use the dynamically generated contexts-array for this. Last comment about message 5369: Bart described (if I understand him correctly) a lookup scheme with one more level of indirection than the code below implements (it's the number 2) in his message). It would look like: 1) we are in command `foo' after option `-x', use context `executable files' 2) in command `foo' the context `executable files' means `executable files in the directory ...' (this, too may depend on the cursor position, right?) 3) use `-W... -g '*(x)'' Making the interpretion of context names dependent of the command (-line) is what the example files don't do. But it /sounds/ good... The files leave some questions open: - I used the naming convention with the two underscores only to reduce possible conflicts. Maybe we could get away from this (look very ugly, doesn't it?). In the example files it would be easy to hide the underscores at least for the context names. The it wuld be useful to remove them from the names of the helper functions, which makes me wish that `autoload foo=__foo' would work. - There probably should be a way to (half-)automatically define the contents of the old arrays (comps, patcomps, keycomps), but I don't like distributing this over all the files. The example file `init' just sets `comps' directly. - The __main_complete function stores the strings from the command line in an array (words). I made the completion code use the positional parameters mainly because Bart once suggested this and with the shell code we (or I) were (was) thinking about at that time made this look like a good idea. I'm not so sure about this anymore (and Bart mentioned this, too). This is especially problematic in the example files that use some of the conditions, there is a lot of copying from argv to words and back - please ignore this, it won't be in a final version (of course). When changing the testing stuff we could probably make the builtin or whatever get the name(s) of the parameters to work upon. Otherwise storing the words in another array in the widget function wouldn't help since the modifying tests would still the positional parameters. - I used only the modifying conditions and in one case I used it as in one of Peter's examples: on a line of its own. This is probably the most important question we have to find an answer to (with respect to the new completion stuff): how should we do this testing stuff. Some ways we could go: - Keep the existing stuff, but the drawbacks that have already been mentioned make this look like a bad idea. Also I don't like the idea of keeping the complicated ones and remove the simple ones. Since we want to make this simple, we should also avoid special casing like that. - Add a builtin for this. Its return value could be used for test purposes and wouldn't look so weird when used without using the return value. Here too, I would prefer a solution where the builtin can do all tests. But there is also the problem that with conditions several tests can easily be combined. With a builtin we would sometimes end up with things like `if comptest ... || comptest ...' which doesn't look good, either. And it gets worse if the builtin can't do all tests. - Keep the condition codes but don't let them modify the parameters automatically. Instead they just set some (internal) variables and then there is a builtin that makes these values be used to modify the completion parameters. I'm not so sure about this either, mainly because of this hidden state (but otherwise...). - Remove everything and let the user do it in shell code directly. Let's see: -iprefix str: [[ "$PREFIX" = str* ]] && { IPREFIX="$IPREFIX$PREFIX[1,len]" # with len=$#str PREFIX="$PREFIX[len+1,-1]" ... } -position beg end: [[ $CURRENT -ge beg && $CURRENT -le end ]] && { if [[ 'CURRENT += 1 - beg' -eq 1 ]]; then CONTEXT=command else CONTEXT=argument fi COMMAND="$words[beg]" words=( "${(@)words[beg+1,end]}" ) ... } -string num str: for a positive num this can be done like -iprefix and with ${(I:num:)PREFIX/str*} (and maybe ${(I:num:)PREFIX#str*} should be made to work, too); for a negative num I thought ${(SI:-num:)PREFIX/str*} would do the thing but it doesn't and I can't find a way (but maybe (I:...:) with a negative value should be made to work anyway, and of course ${(I:...:)foo%...}) -class num str: same as -string -after str: [[ ! -z "${words[1,CURRENT][(R)str]}" ]] && { if [[ 'CURRENT += 1 - ${words[1,CURRENT][(I)str]}' -eq 1 ]]; then CONTEXT=command else CONTEXT=argument fi COMMAND="$words[${words[1,CURRENT][(I)str]}]" words=( "${(@)words[${words[1,CURRENT][(I)str]},-1]}" ) ... } Of course, this can be made even easier to read and faster by storing the index of the str to use in a local variable. Btw. ${words[${${words[1,CURRENT]}[(I)str]},-1]} gives the whole array, which looks very much like a bug, especially since ${${words[1,CURRENT]}[(I)str]} gives the correct index. -mafter pat: the same as -after -between str1 str2: [[ ! -z "${words[1,CURRENT][(R)str1]}" && -z "${words[${words[1,CURRENT][(I)str]},CURRENT][(R)str2]}" ]] && { if [[ 'CURRENT += 1 - ${words[1,CURRENT][(I)str1]}' -eq 1 ]]; then CONTEXT=command else CONTEXT=argument fi COMMAND="$words[${words[1,CURRENT][(I)str1]}]" words=( "${(@)words[${words[1,CURRENT][(I)str1]},${words[CURRENT,-1][(i)str2] + CURRENT - 1}]}" ) ... } Isn't zsh just wonderful? Again, readability could be improved. -mbetween pat1 pat2: like -between Ok, once we have fixed/implemented the things for -string and -class, it is possible, but certainly slower than the first solutions and harder to understand (although it isn't really that complicated. But this could be made nicer if the clean up the special parameter (something I would like to do anyway), like this: - don't use the positional parameters, instead store the words in an array, say `words', and store *all* words in that array, not only the arguments - we could then avoid the value `argument' for the parameter CONTEXT, the shell code would only have to check if CURRENT is 1 or not to find out if we are completing a command name or an argument - with this we could also get rid of the paramter COMMAND - since COMMAND is also used as a kind of `direct context' (in a `value' CONTEXT, for example, it contains the name of the parameter which is assigened to) we would need a replacement for this; we could do this by making CONTEXT an array and storing some more context information in it; we could use a normal array or, probably better, an associative array With all this the code above would be much simpler, leaving only the assignment to `words' after the test. - Other ways I don't see. So, any comments, anyone? Bye Sven begin 600 new-comp.tar.gz M'XL("%#DQS8``VYE=RUC;VUP+G1A<@#L/6MSVT:2_FK^BBF1"4@=P3>I*CO< MB\\7W[EVXZ02I[)WLHH"R8&($PAP\=`C$O7;K[OG@0$)F?(>0U]B3-DD",ST MO/K=/=";-)@E7AC$[=?AW#YC`U_E]%LE#1.G(BQ9ZMT=OGQ>CR*#S&@PY8W^?V?3#QW$J[P MSO[ZZ'8Z([G?A?O?[7?%_O=[HY/!D)Z>])^QSOZ&\'CYPO>_NN#^BD>5BN>R MTU-V5+L.HWE\^OJ7GW[Z[MW[LR,V9O8Q.SM[R9(%#RJ,S0!-?"].F'W)G.CB M"FY%/$FC@'4JKE>1U]W*YYY869Y4BNC?"R:K,/;VQ@0^@?Y/NH,3N#$<=GLE M_1^B;-!_31(^L_D_6*UK$GZ\\-P$OB<38@$\X<`MOCTJZ?\/78KH?Q7Q*R], M]X;MN^@?U$-)_\/.H-]!^N_TNR7]'Z)LR?\NB?RE2?F%JH'=)>6@]M`SJTHV MP7ITO;0#'OOY:LYN/=4YMMGM_8M\EMWI63/]3GEQS MOC\#8!?]@^$GZ7]P,B+[;P!?)?T?HFCZ]\.9X[-9M(.(U*S!-- M?]^>'66L@FJ="E(LXACV4F(2J]T]B,J]LW7VHP\_ZKIW=O2DD?;^F9%^5CZT1?\749BN]HOHN^B?]8>2 M_OL@]]'^[Y^4]O]A2M6)(N>V4E$;/ZZ#72\N&U^N5/QRRA;]NUXPWW,?.^B_ MVQEH^3\<#-'^AXMA2?^'*%57(@"R@$SW0WENV?7P\I[?\%G#8M:'EY80:4LG MF+/[^XKA*F;VW+G%=4R8?;=T;II++VBNYWR5+)CMAKX?7C,["'WNN,R^@G6D M-C=S?L4^5)A1[#NG.6NN`W[-(_ECN;Y#:(FWY&MF\^4JN068#DAWJ.#&S9OF M.KE=<0#TG"!<>'-F>T&Z9+;O!90%"5QTFFL-(;P$*%$: M0!L_UBME.-5`]YA,YE[$9TD8>3RKHPQON?IUYWYVWZ#%N'>II_I]Y]YM-'`G M7,\O;.G&M!RBPB2&;>'+HGHT>:;8?D$%7")X3GA?2H(_:]GB_P9>[JN/W?K? M2.M_';SN#DY.2O_/04J._PN>8E\PZ[ANMQM62?9_^K)%_[\#GN^F_WYF_U'\ MIS_J=4KZ/T3)[#^:()E_=%5:?U]$*;#_,K5Q3WWLC/]V>IK^NR.4_\->IY3_ M!RD9_9L;3VS`JJ=NS`:M'OSOLP"ND^6*+>'[YV'WK_#1^VO#*MG$'[MLT;^T M\/?9QP[Z[\%S1?^CP;"+3[O]04G_ARB&_B\C0(`&;+:<=_&CQU9.PJ[@-CI/ M*I4J>RUB&EYPP;R`*7>0\FS\*WOKLB!,V#5G *5^P<85D,:^%E#RYC@)-< MARQ.(H`38^6%OWOV[B):-F36VS&XY+C$N MU(>QJHF#@>4:9TU[30Q[;\,D@,?M?)8>P,J:'F7`[N2M%\GZ2,7(MBNK\?3& MM?HU0)QQ9J^8JM'`D!4L_L^<8_`,NHPX;`S\#V[9TDEF"T0/V(:$1X&QC['8 MA7J=U:KPE!:9-1IZT&X8,0^W_ZBF'F/(["6;A^0EA)LX`^\K=KP6@308)MVI M'C-Y1\')2RO]#%$/^5]DOB>=[R2U3]X@C MSS*)+_R#H0MB]\*[XL#P,-0`=9#QXT,4R6\#X$OP>^;$4/DV3-FUY_OLV@D2 MEH1P&WXD"P_@!"`^`K`WG#G"G$Q0<`O\JZ/`%OI(L!S7WGW_ZOWK__SN9S13 MLDHBKPL95:W*;`#6099F!Y(K0DO)YZ+&_`D#7+/)A-U`Y[9+%!9&&%U[9&@857Z\;T,]4XN,_`P? M:#-%Z['X4SR+N(CHT4.S$;#)A6UGG3D1J+$)!GOQ:9Q.XUGDK:@=;)SZ20]A M#5.NVN8'$LS)3A.M],]*HZ+X.8R&1`7S/5"J*RAA\!9HSS47V;34]I&KX_TQ M:VE=-0`AE')I*!`,;`6U0&TY?CA^J+]K:%LA0JEB1Z^H&_8-`(?ZAH50P_M@ MC4$'EI:!UJ9-@(W0P,!OLIC$;44$IP3U#&K@MWKJI$GHA]"]>5M9;;E^R3+8 MZC2#KOJ%'M@N6"*/ MU0;J<;V;1UM@SS",$-A%_&BE)0_2W9U3K4\8;,0Q!X;;>>@;&Z?*;[`5]FO# M])HH4$Q?3"9+QPMTC0T(:F,!`R3"H"NA=[8^*H*::TQ(H@KAR>>65V79;RGR M_Q)"[+&/7?&?_DC%?P;]48?.__:[9?[?0:>CX(;)#?HIIT7^(C`1,^7R3BA@E^K+UOQ'VDP_"N_F/C M7^#^VG08&J>1@;G5O_VQ@37(@2D\F\QPY0&TDH-ME2WZSTF2_?2Q*_[3Z?;U M^;\^G?\9]GNE_^<@1=-_E;TGCS)0K!^&*_3(;$1A9N&'&`)8KA)X[D;A4@&DH`NJ&RW9ZT8GY%R*61I3@WC%9QZQ MILASINCW4=$>)[I(08=*,)Y4")^"$L)3Y<0Z2`6P,F.GE8M[4=2(SO94*M)` MI:K[9.)%,Z'O$2"&M^8AC$.;M4LGN@3#)*9':#PE+%X08&!7"5B" M5+-2D>>(R)7%&ALQ`MMV`<0GN>,+HEQJE;#%CNB7`5!;D2I(5&5_XXD5@TU/ M01\5LW/T_A3'ZU"2X+:$&"4B,+`-L0?[J)D^;($,O%D673HQST;J!110$T9L M8RM"EYFW9T/RG!]+^1,=_3CJ4_S$:EO+_(&5W_,<+Q`$9,YA<96]0,F6R M)5Z$J3]G4\P!T$JY+4\'4;(&L]TFL]OP_Z+1(JDO1$(U$^,&%!*R,H,@;E*H M"+04715&``V_`[`O`K%BR6_/HJI*:_%`Y`1ST$=`'W!`K*Q\9\9I M!CC5\^SE1J[5-'^VX2<*PZIY\X*U6BV+U:=I@LX1*R$&#N+]VH/UHNDQJ3DT MQ(C_*TQ!0-TRQX]#4DQ(-I[;O[)O4(S^Q9+U<7@$A'J;);Y*H)%]6TT`AMV& M@7^+E1&,F]N25C9OO9W4K3.;\56"6I3L#&3WN?T&1D#I.+DQ>%"/P!K;A/&^ M_TFQ)Q=V9W,"4D&<`?0I";0Y!OU((>#D3@5(I&6!Y.TE[0`<3K#]!ZC.D4306+B"I`2$7MS#FJ`J5@8&2?;JS#EJ+G$-#^7 M`I12DQ&!P\A47WSODK\`"$+RPT8P^WMF12_N3^U6<](^&Q\S^`&?RQ=WCOW; M>GSWRO[O-?RRQQ/X;(V;%OM`[8UBY2O[!(#``+(RV*);B28J9KH,YYY[2U%3 M(R[*5H"_@/HQ)E*1ODMT&G''IPNT=ND"/K"&K,X2'B>R)FRL@)8L5UV8(JCR MLP1_]&#A7=>[P;P6)C;FG]*(Q;X!P>&-3U>/J^P_>"+TQPQ5?\TP%&@"433# M^?Q;3'XUE5N<(FA)/=-]@?>4_Z*^X;]0JPO:N:A'3M,V:YCN!;,2NBAJ=UAU MO6;BK0`4F];;A.]4ZDB=;1.Z@$L>CRT64'D+!6LX9LGK^&; MW'L="!/&=;B+*UDP`ED#-'G1-R+>(O3G@D5=PR67>7^/F&Q$]<`.CBTFSZ)B MMB#4DOY\9?P)_`1R`&@8HOGQI^_>O/W[BW^LCVMW/__R1EQ3VM2O7/`,P1^3 MZ+8@1TM9L9KG"BZ;\5@R>0#8-;`:Y/32JC274N<8DKXM%B+WV@@E-=$S-D>F M1O$?LH/`[,8EDW-/MK88XIYB!D3@NG*810_H$$\=%%)WC8 M`W.F<>BG8!<0@P!.'W'?24A0A:)9&D4H!-0Q06&5&//6)$4I=]"KI*_3A_:9 MOH-(4@N-''/R**U$;1R-*9I5EBZM^UWO;`H6V?AX4JFS0%-[)C8$-$LJI:21.AFRB+`+Z) M4%I,BWW/^(&\KWC.6W(1;%"+S!+2BAUI84K[HZD`DLXN69A&,?=!1@,@T-A" MX`2^QZ\$A3B)@JR2D!8:(K*-S$5%6@JTCCU<;/=6,A)Q(!V!D4\JS@+?`!?N$% M2M%[L&BY(]!&EU-.*54)Y=%..:BFW-#P8M^)%XQ6A:%#C,`EV'051@F2O*+5 M3=_=*U([01J00H72&K!)G<+*12(ZP&C4NM.RIV13FHI-('./R0 MM%I'@)),6W.=[<5J4J+XN5)6+)H8,4@Q!4J8$+!('B+/6CJ7*``BT9'(_$:? M):`);!CL?)0&@FV'F+HL1`I,&5\>8`Z+B&1ZBR.@_+9S)3\!NQF#?TJI0@$# M0__JJ_;QNJT3I-42?1CC)\I"(8K@JWKAXB?8:P MT_1*!241'ZR,V.4Z.YL+3-`$&")0F(!G#$"-6'K:MK&TG6=P-#(OR M*%;O>!X]Z51`2MCH*5C&)B^Y$YCDG,#(J+*T982B2@^11_B8C'`+1!C,04RW M)#Q$9X,!(GM2;6.Q(BA+:1W4WN!,#;Z<;4_;VM3GI(:E6;9V52])7XC%](G' MJ)[E_I'A!&O69&D`A@S],FA=K4:K;:&$/6_A!9#<]<(#6X>\G[OGA#"4BEDD M4HO5Q4V$%&^?TN8\GMJX]%8,-A08D.]3M_F3%)3G?@[]67*\B%)`:&!IQ[35 MDL<"F[?%8;*,?9RWTSAJ^]ZT[7_S_M6_@:6)F([3#%T7>D2SYQP>6\K4ANLA M\/,?"T:!XURA<8F\_AI-:N0&P!<"N4HT1,1"9PYU"G4N31I_:B@,G&-3?X@,F^$F,EXGNG[`)Y-K`"E M_A2VI2DF7&S+TGD8;`V\2=FRQ#SPD((^ET'^>M>;.<*`TR&23'U5;7.O?Q5& MI""A%Q=QN]D^;K;Q8M(^GN!%J]TZ;K?PCMT^/K4G9_2T!=>M)EW;="4^VC9@ MO8VMCH];QRU]%$7W0@N'ZW8LU@L7[/C(K"$NS(X5+(72`6)F\Q%QI3%>1+L4 MQA<2&^Y0(H4-'?.`+:!F`LN\6#@ZR*C1?N>'#G*!K<$:WVD MD8FNZ)]2%KPX(B.IVS@B8RX,KI7JQ<#((Z'H(2N+.88EQ$2P9JR5!DEC,@2H MNA23380&H62-=KJHA47X'RZ#)JQZ(P#.74D[5D:%&G[M@Y[R%D:#. M;$E0L(5R0(3[4\1QI>2JZ-,V'U.&C'\KP6C9(M,'XV1#E&L/PIU<^77M3G$' MN%1KO:Y7_49&]_@>#:,U6#`/Y&MI5,QDQ"K=*[!,3`-@[LV15ZZB<)[.^"-6 M0,"%QPV'(YI)W43`(A4\C="F)+ZLDBHEG\#S2_PF$38H-LS%GE2F!C7HY5,1 MY0PNDCS7,)4(.7!0WX0^BP[(0").T[0SM$H1HBA$*:,AB4F2,JXQ+]/GB\25 MYGLX.0T']U?AMY3:UR)9381LBC_MJ+)36ZHX5QYCN9.>@GT>4?R`>1R;-$%2\S":Q,_>="#:.@Z MBNQZ\O"+"@;+=64UA6@U3[<2&L6X ML,!0E&1Z!>)T*IP0&F4Q8\3"8S]B<\"T(JJG,$BZRBW[+K:DEU!Q'S750A:Z MQ;5,OJ5;PHRW6)=<))7LD&=<^MVT,).R+--SE1P#1>&YT$RUP/'] MW.G>A3[WJGF<`=_`PP=YO8W*V,4KP4$"TY*45I8Y!T(_J:'%>75CJ\,[>5TE MPEK+CK1"B)Q^/M\&EF&;[+^>!LI-TE!;*8=3%Z[:E?*5-9I:T;#S5;0WET#` M3CKT/L2"_=1RFYQD>.BFJ?DK`48`8O44\%@#)PV2OR_7*<3II;A$I(HP9!;9WLJ7G6ZQ&Y]#3.(#.9@NIF(5> M0.YYI5?D%&XMLQ[CM&1Q*U*4&D!>V]ET^8N4NYR0I%"M<#B(N+#D8J38X-86 M3UD#H;[SW$WOOU1XC]3FDXM)""*Y)EE-4@+R M-F9#6_W(?FUS9"#>,)0#EXQ1Q3'$O)I)O.?Q`1:Q($*)GA0Z?Y!D\ZW\+Q&AWVL?.]__-53O M_QGT>D-Z_V>G6^9_':1LO?]G\[R]D1%,21GRE<\Q1LU4/5*[C>/V1AM5^W// MLRS%93O_,SMTO*\^=M)_3__]A]&PUZ'W_X[*]W\=I!CTO_EW7C`48+RRW$;K M>.O`0N&1@<\]J;(\N13)?\6T]]7'3OH_Z6OYW^UU22$8E'__Y2`E>_^GL?'T M4@],=/W;B_O3X-W9:?C#V9A]_V*"'Y2T.J8$5C1)P3"W:O6[[(T>E_%"@*&_ M6/!2O01DS7I_:<_Y51LS1AM6I7QQZ/^+LOW^[V#O'&`W_0_U^>\A_?VGX:!\ M__=ABO'^[Z#D`%]>V:+_/OS]?*3C_K5Z-L;<^ M=O_]'_W^I]&H+\Y_]TK_WT%*)O^SC0<5X*J4[E]&>>SO?^P3U7?3OX[_C2@6 MT!WTAN7[?P]2,OI7&P_4/RNI_TLIV_Y_]?JC_?6Q4__O:_O_I-,A^W_8+?W_ M!RFYO_]I:.[&ZZ`Q3?:N_F/2^-]!KW^I5;!52"PNSD_6@C?YP=SX[-3*8J1K M:4;+D"$`,/(_(BJI9@?!^A^Q_L?<"#+_;S:Z_H<^`"G_PU?$Y8*7UF4'.,!S M_&A>'JX`2_L?>E0A]>P@O/X//OYG;FX*SO^FH_=_T@>@U/^9::#E7V69^:7% M"KKYB/$[T$GV:+*Y"NJZT?EYL27JL`L@((J0FA`0492FQ$#[=A2,@E$P"D8! +#```_VI2W@"@``"Y ` end -- Sven Wischnowsky wischnow@informatik.hu-berlin.de