* Handling for ZLE modules @ 1996-11-08 15:26 Peter Stephenson 1996-11-08 17:16 ` Zefram [not found] ` <pws@ifh.de> 0 siblings, 2 replies; 13+ messages in thread From: Peter Stephenson @ 1996-11-08 15:26 UTC (permalink / raw) To: Zsh hackers list I'm so impressed with the dynamic library code I couldn't resist implementing a way of allowing you to load new ZLE functions from modules. My thinking was this: there are 162 builtin functions and you're presumably never going to add more than a half dozen or so new ones (very likely none). Thus it didn't seem sensible to reorganize the existing function table into malloc'd memory. Instead, I've made a new table for any functions that are loaded and modified the zle code via a #define, ZLEGETCMD, to choose between the arrays based on number. I don't think this should be too inefficient; the worst case is in executenamedcommand() when looping through looking for a prefix. If it ever seems a good idea to allow overloading of builtin functions this may well need changing. That's the only major change to zle itself; note that for non-dynamic zsh's it will work quite happily without the functions (add|delete)zlefunction() defined in module.c. I'd be glad to hear of better ways of doing it. The other question is how to handle unloading. One has to be careful when bindings remain which point to the function; also, the functions are in a linear array like the builtin functions and you may not be deleting at the end. I have arranged it so that the function is marked as deleted with name "<deleted>" (which should only be used for output), but the table entry is kept. Executing the binding performs a feep(). That's probably fine, the only problem arises when you load another module which then inherits the slot in the table and hence the binding will point to that. This seems to me a problem to be fixed in any script code associated with the (z?)modload -u, in particular via bindkey | grep '<deleted>' | while read -A line; do eval bindkey -r $line[0] done -- I don't think it's worthwhile adding that code to the shell, though it wouldn't be hard. The sample module mod_deltochar implements Emacs' zap-to-char (except it's here called delete-to-char) which reads a key and deletes up to and including the next occurrence of that character on the command line. Multipliers work as expected. (I've always wanted zap-to-char.) Just do `make mod_deltochar.so'. All this code is as up-in-the-air as Zoltan's, of course. begin 644 zle_mod.dif.gz M'XL("*9/@S(``WIL95]M;V0N9&EF`.4[:W/;N+6?M;\"]FW7DDPYHB0_),?9 M\2;>U%/'R:R][=YZ/1Z*A"Q6%,D2H!UI-_^]YQP`)"A1;K)U.M.IQI%(/`[. M^P$@[7:;767^BWD2W`4\DHD_];(]?P_>&S]D(;M,'A@[8NY@U'='[I"YP^'! M-YU.IV[2RH3]WJCGJ@GMZ@??69?1(\)RG:,#!@^=;W;9BS9\L3;[PWGP!WI2 MKRM+L0[[V\49MN819^$\C?B<QS*,[]G9W//%#EMZ:4<F'1QN@;F>AH)-0IPC M6.IEDB43MA13A\DI9W]C8LJC:,^:\#I)%UEX/Y6LZ;>(&/:!2YZQ*\G3*8]% M$JN!IU'$:*!@&1<\>^"!#><#S^:A$&$2X\I3GO'Q@MUG7BQYX+#'4$Z37++' M+)22Q\R[SS@1Q+PX,+T*4!3ZL"IG2<:R9.%%<L$FG`L@(&&YX`[S`6,'.1-. MX!?G!Z&063C.)0<J0Z'@B&0B'[V,TPB8:PVBN2$/V`//$&.!3,*9Y:0)+._% M"P4JS;,TP:73+'D(`Y@HIYXDCGKCY($32HJ)<2(!?[7F%,%$4?((4E.`Y&." M0@'JO70JF)>FW,M8"/P`Y@*0D*^C8C/Y/(8%&']`QHDI3EJ5%;*-)"VF[`T, MC)*4V/PV2_*4C3FPUQM'7*.3((VD)@NB.`@S[DL',#)/(N5^Z$78Y`/EL<1G M&.D#U_@_<E1)+U+0`F_NW0,!7A8*U%.4-Q'#46[K+$8>A:!-0>+GB*,G012. M@H4DLG"R3IYA;#U]4P^$,>:H8,%#*$!0R423"G-`AB(<AU$(U`(V(O>G&NFJ M(G_1DL2@2>B#,!:H8W[DA?-2=8!2M($0%1A8&.4!L,9AH(:H*B"->2A1GQ)E MH&CHJ)CEM(*".<_`UH%-F@)$:Q+*F`NAM)7D&/IY!"JE-7:/@4/@!<NU-ALE M1B/-XP"H!;$0H6S;$_"RS<:>"(4RKDW\4,">D`-H:C*.PGN2*^J:7IC-O1"\ M0NS%/M?B%GF:)AFH6YX&GD1>\7B*_0A3D,(IF_4)F+#D]0*^X>__`CX)8XY. M$]\4JSG;!M>W-]U68P2JF`]BD&Q9^MICU?FB3:`>DC"`GZ*WB0TM:/D55X,/ MSO;9";OG<L87S6[+@<%"0HN/B,[@H7NL8=+X"6LNYWDDV2O6;1&8QN,4';1J MANCP[;<*Q-8)BR(]!*?J864?CHR`RAMLNL4V'U%K-/!]=_?83,0UUR#:@QHX M8HO6-[TX#]2(`^5J;@<(:AT7?<G,S/UDEJ&'3YK.3XQ'8.4$[$6;A?<Q`&/( M0L]'!?+S3"1&TQY!E9CPO3A&1S'V_!FH9R"4-!L&_999"%\ZG>-5UNWNVJSK M;N9<]TG&:<B&<=:X$QB'4ZN<0G212[X`'A&>BB\%A]9Y8^G"5C*CI2&FI4V: M^:FB@*!?\#U.$GE720E($5D[R.?SA:V/EB:#ZGE!L(SX)(]]M)/F-O2!^9H\ M8=LI%=M!4[E[<W9Q=GU&:.`GXS+/8E#@#6CY$??B//T\S-3:-CH6KAN6;)?9 M&N0]-6F:.QIT1]W!6II&HU?RLP'D=(>;\[->[\#I]8[*+(T:C@8J42/DV#@& MIC:_S\,(4J\6N&UZ`!_<>97Q.83^.`EXLVQV6.S-@38U>SF!+*<YCB&,ADN> M3)J0@>2^-&!:-+".SRMB).&V`3*D(&.(S=C!VOCMD#^:1-Z]L%FOUP$8_AQ$ MLT2'=?G3Q85A.DX240(.%U9"W*!?#9:)5*GGZW=O7K__Z?+:<F5@UE>0IT40 MGM"RN3_3@0<Q`]WP,,V$!A`[!3.=O`8)A/GO"D^M(?T09F"<,C.!#+X\AOPB MQ/;T0(@-5Q$E5A`\(&^9C\B*8/V,=S"K\&@X+A=3+@,^N8,LTBF7`@'N`$+] M%&(;QES*#Y1R!BP-_9F`L$,(Q_R1&:9;&)S+'343U3]364RH)B64I6-VR;V( M\EA`4`='-1F1!$<'%'X$-M`0DB$@2OY`M&#A1XCKHICS0C\A<YM$'L841>A+ M(S'UOKO;,AY3R0]Z;[#C=H^4@GUKF?D;RT.22A13V"Y!*[S7../>[-BX,#N2 M^1H&(;-[LJHIJY&@1`P5ZZ0R'A8M$(#L*?$M]%ZT-9M5'!<D'M\#L(^8M:Q, M1&ET=?`@XJJ]"LW3-V^NWU\?KXU!`U^Q%Q4;EL`$G%]RUEF!W*Z:M>ILM0K& M-;3P"@[H`+'&?))RQ^)-X1Y-Z%CZG5=D9B=D;<=6,WF#$U+<2C/)_T0Y!\N* MM<,U\JZZGS+]67'=E#3Y\9-.9C7K\6-05UO@O_V&,-@KBR/$:H52B7S,.FN: M572NL`Y&'Z_S:/NE-O!7VW6L@MA;QRK+5*KA"!;<F];$HA[$HOUJ+**AE6$' M(W<XVC]X(A#U>TX/(E49B*CAR`0B*[>].[^\.OOQNM%T7[X<ME;Z%.K4YW;7 M.L_?GJMYKMNJ)LR&9M7;PYGP)Q<I)(,3(V;T5^T_\P6&K%HJ!OU#9]`?EE0, M^D?.X*!OJ/ATK.#RCY`.QBO:HW[$S6V1C;-3J("H3O.3^1QBA$#/!QY[DB5S M'5I$$52`BI^OSWZ\7%-*HRDEW"L,=V2^'@8`=+*E/JW!([VO&'T)Z3J!:MB@ M![]Y+'&+@"O.!A38%,Y/@)7*##7-OH_E'&TLI!#QTBP$),T2&/MBZM3L8E@E M+BCF0D>!YIZUN:-91[&J+#NM2M2V3ZS*]0JP9`HY=*"6,/#TNK#`:;P`!PW) M^Q2BLZH@]<PY<6G'S+2<IT@P<,<<&?*-V8`0^5ABB5!!!-KO=1*13":"RSWV M]*>F#'Q[=@WPFC^W&&OB]ZMJ\/FNQ.P&NFWG>\M^*<H>^(P*[?SYME6(ZD_) M(Y`*&0<F#86*`N)Z<XR)U//U/I*$-$6&X)@(30M'%9/8D>UH[K`\KLU\>[U1 M?]W;Z/&5L?NC_<&H.]SL<@;]`V<PZ"EC967Q0YD)UD<=%Z,QPU(1"U[TJ:@2 M$?^8<E^2*6]AC"S=L0!G3-./U32L=9J0$THT1)6&G/[XMF7`DN^ENOB$N<=% MTT,XSB>XIT(YC_8C"E?M1_X]7+\M-8/FMYX3VSI.'_2&SD%_4+I%U;!O5QF4 MWP.DF_ZMP]K"E`](34CHZU!5)E+5Z*B&(_88_C"C6=[AQ@ZYH9GRV45"&:IL M,H38W._!+Z:00,]#&,;B#JKT.^0+E#(W(13`C)JQ!5[K"3PZ'#I'1_N%*H'/ MBB7.:,XZK\`=.PQ^(PY%D*N8G>;2;^[\$N^H8B;)95$PJ=01I34A,).F'N&P M[3^*7^)MI[#%F8KFMWM(LBZD*+Y0)H.,/CKJ.L-NJ3=?&;%2L31J+8/:%J"V MA3I(J&U1C;>%A$QT+6<5>"WH^17^U258XEB!*42Y%*7U'3-X>VG9HJTAT(=B MWE()^18`]N=I4Q642Z&RIA;U6QGB$O<W#/0-RV)DM1?6Z6RAJ=6<=@6-)BY= M6Z;@GLL7(ZG6KAA&P2XSN@RY57VI4^PA^)VAY2,;:*%=-(I0>8!2H:`'M*A0 M))6X:T2UOFS_(E<T6-F8I<`-Q*B!VV)0JDXE[M,WP7JU/=("7?HK%J8(WE63 MRXT45/[A?M\9[@\+Y7\NY$LM5^BWGA_].EFX77?@N%VS6U,E8+8P]KRH&C19 M-.Y0H5%;U!7&W##TK8AFQ;,H]T^;.<)AL$+96J)M&*`V^5)QLR-V;EMDS(W" M=`KGNU5UX<H-;YE(I'6_[67W#R56H49)#428ND[?*H-BN%)DFP"VY%G6W"Z" M0K'-,6)_%$"X7DG+HK%.JY&/J]3+[?9=D,>@7RK8UY!'J6T5A_I,$@F5&RN\ M,#&AM<[.LEA]?F;6*KO;`^:ZO<.:F.H7S/57N*OL5OVN!BLQ-:'*4G+XLG3< M4$Q[7.B46U9(S"`D$HR6PR!#@CP(GIO7KW_ZX#`0ST\7U_@41\"&`ACA0+KB M@B-UW4%=)'X&<DH=P<V7KTU0O;P.4%X'P](Y@>8(*%N:IQ=_/?W_JXO3J^L/ M/[Y_]^&:0IM.)"&3A/SRM]]P0C./_\7PK1.+,4B7VLO`5$_P"/00J@Z).RQE MNYT"MNKYI\]CYGKK5&SV@88#RGQJ(3WA0&WGAWT3*)8#R!K>G?[\`[BI-T@G M9J2]_8,R)3648H%C)Z5JK\L8(^5._E1%-J5OAZAOY4;^?[4X-KK`SQ/(9@_Z MGQ))I;0-A5];VO9[HT&WIK2E\:NE[=%H\,2UFP.W[QSTRK2-=HV7=P\A*"8L MS$?8F`,?QN%]GN1B9.AJIS)3=9P=L657L0A^5V.V[-8%;4JGBARO^QDQ>PVT MX2,>6.<"#R2+\QM*Y13CH2W1CY6H(G4*J!C1+:S@]S.">&!'2J"Q54/"6J#\ M_0342K8/E?-^O_2R?SH[_7!Z<?'^M56E`P)1A+OD_!'6G46AD,U66;%7:/M" M*9.80<KIY.,F*6M$%%^@?/_XL=A^H#:H41`K.C4D3&N`')?#/WX$M&`YB(O- ME//9!`_-U,16[<QR<4`59K]D)-Z6ZFC0"X!4:#4:*C]J?&+HXXB3Y78(GZ=R MH==J%?PSQ]:D8/U#D(?E9K^6/,JR34E#N3Q4K_5C3FN#1W8-+W6YZ=>7FR6_ MP>55Y.N;JO/WR-5,_GQYEC.^7(YFP_)W2]3VTS(+(1_;Y*GW!^N>VLQ8\=7P MUWW"5_<.>P.G=VBVQP"E()^G9?F(=^7F5#QVAM6D#E@U]\0,)/GZ]=WWYY=O MSB_?7FDQX49Z3&<*169.AV9B;V^/T0X,;13*KI'A9[L`LWQ[S?1(QJ`%<P\J MG&:0IWC9,+YOK@UTR`^NI;B&*(CZ#UY6$D+W.?'(E]%VNV#W(5Z-DTFQ2^_+ MB'5F=,S']/&1YNIA89G_(:[6G`A:#+;WBH_Q(*_8K=JU#'SIK_':'.OAKM!& M(]XL`6-5!>=K$%+[6+Z]C[6[>1?KZZ/X=92CS@3[P^[`Z0_=;F&"QB&P\F#6 MH*,VT\HC;7%#F^A*M8M;+_8^.7[27$PQ!VB6RA8+";0WI8XD@,0A(E%N)WP6 M$JM[^?\.&K;[>P@WNK[ANNO#T:LC#T?[3[@]MW?DN/V^=3^<&HI(^FN!GV2S M'E2H70<O+V82T<>[D8%Z2,9TD%T.1I)=A]TGDI[,&7>]7:II#R'"RKSXGJLX MS/04O1P>EP-SQTFD@\0Z-8.^X^Y7SY(L\>&K3NPZKMZ4*7>`S6Y^KWIAA<Y> MS.PR8RX=+TV@DJ.I+-J<W92J6<"TS4D_@O$$20[.4!W;"D?=!O;H%+,?#/[N MT`$D<C&D&[D.R^,(SV8?^4Z&MX]2[M%M?'W8X`X&P(1!Y9#J7S-A-6.9]10Q M]?G*9J;HJPUUS#`POC83:C5C.'1ZW>)H:'WYRP2/1O$>'5[T_0XL^S)QV"+) M\<K4CL2K8XM`1Q?C"#<KS;OW?SE[=P8N6GO(-1^B>:_PH$C9=0'!0_LL[ED0 M7!'<ER%6FRCU`-%R0Q`_CTD6D%\_88\3,YL\`M95J10WWY^=?;@M>HH6DV[C M9Y-!K2W1K853=4`8I03N!4BZBZNN5/8![Z'-X.?"NZ+SSX%O+=\'!TZO]&WT M:=.=>HG_WR56ZJ]J&_HO-U`D2_M_/I!C=?0-1&K`BX((I01G;I#,<R'+BX3V M#9!H@5<NI+H3ER;HZA\Y^SN.I^L4%7`0_N?>C)?+0\#`7,`#P\7_KY%QN@LM MGKI345'H3?9V<7YYAJJMM1JQ`D[XHAHR<.<!FU2ZW:`T&[NYZB8M&1P!ERL7 4;_\'N;SB-)Z%N_\$F6-O9?XV``#X ` end -- Peter Stephenson <pws@ifh.de> Tel: +49 33762 77366 WWW: http://www.ifh.de/~pws/ Fax: +49 33762 77413 Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen DESY-IfH, 15735 Zeuthen, Germany. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Handling for ZLE modules 1996-11-08 15:26 Handling for ZLE modules Peter Stephenson @ 1996-11-08 17:16 ` Zefram 1996-11-08 17:26 ` Bruce Stephens ` (2 more replies) [not found] ` <pws@ifh.de> 1 sibling, 3 replies; 13+ messages in thread From: Zefram @ 1996-11-08 17:16 UTC (permalink / raw) To: Peter Stephenson; +Cc: zsh-workers >The other question is how to handle unloading. One has to be careful >when bindings remain which point to the function; also, the functions >are in a linear array like the builtin functions and you may not be >deleting at the end. I have arranged it so that the function is >marked as deleted with name "<deleted>" (which should only be used for >output), but the table entry is kept. I don't like this. Do we retain the binding or not? If not, we have to go through every key binding, changing them to undefined-key. The alternative would be to maintain link counts for loaded bindings, to avoid reusing a slot that is bound to some key. > This seems to me a problem to be fixed in >any script code associated with the (z?)modload -u, No. It's a question of the integrity of zsh's internal data structures, and should be handled by the code itself. On a related note, we really need to make addbuiltin() and so on handle failure cases gracefully. Try loading mod_example.so twice ("modload ./mod_example.so; modload ~+/mod_example.so"): when I tried it it segmentated. Modules are going to have to cope with the possibility that they can't add the builtins, key bindings or whatever that they want. And if anyone's counting, I, too, favour the name `zmodload'. -zefram (Own up, how many of us are planning how to implement autoloaded modules?) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Handling for ZLE modules 1996-11-08 17:16 ` Zefram @ 1996-11-08 17:26 ` Bruce Stephens 1996-11-10 23:55 ` Zoltan Hidvegi 1996-11-11 13:07 ` Peter Stephenson 2 siblings, 0 replies; 13+ messages in thread From: Bruce Stephens @ 1996-11-08 17:26 UTC (permalink / raw) To: zsh-workers > And if anyone's counting, I, too, favour the name `zmodload'. > > -zefram > > (Own up, how many of us are planning how to implement autoloaded modules?) Well, of course modules should be autoloaded! More generally, are people making sure that this mechanism is nice on machines which can't do autoloading? i.e., are the modules written in such a way that they can be statically linked too? I note in passing that Tcl7.5 and above also have dynamic loading, complete with autoconf support. It's not as portable as Perl's, I think, but it may be easier to follow and adapt for zsh. (ksh93 is also an obvious model to copy, although we don't have source to that. It would presumably be nice to allow people to load ksh93 modules into zsh, if that's feasible.) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Handling for ZLE modules 1996-11-08 17:16 ` Zefram 1996-11-08 17:26 ` Bruce Stephens @ 1996-11-10 23:55 ` Zoltan Hidvegi 1996-11-11 13:07 ` Peter Stephenson 2 siblings, 0 replies; 13+ messages in thread From: Zoltan Hidvegi @ 1996-11-10 23:55 UTC (permalink / raw) To: Zefram; +Cc: pws, zsh-workers > >deleting at the end. I have arranged it so that the function is > >marked as deleted with name "<deleted>" (which should only be used for > >output), but the table entry is kept. > > I don't like this. Do we retain the binding or not? If not, we have I do not like it either. A clueless user can have hard time to track down what changed his keybindings so unexpectedly. > On a related note, we really need to make addbuiltin() and so on handle > failure cases gracefully. Try loading mod_example.so twice ("modload > ./mod_example.so; modload ~+/mod_example.so"): when I tried it it > segmentated. Modules are going to have to cope with the possibility > that they can't add the builtins, key bindings or whatever that they > want. The coredump is caused by the attempt to free the previously defined builtin in addhashnode(). I think the best is to refuse adding the builtin if it already exists. A well behaved module should be prepared to handle situations when it is loaded multiple times. The patch below does a dlclose() and does not add the module to the module list if the boot function returns nonzero. Patch to mod_example.c is not included since I'm writing this from home and the current version is not here with me. > And if anyone's counting, I, too, favour the name `zmodload'. That's fine for me. > (Own up, how many of us are planning how to implement autoloaded modules?) I am. We can add a flag to zmodload to define auloaded builtins. It adds a builtin with NULL as a handlerfunc. When such a builtin is executed execbuiltin() looks up the module with the same name in the MODULE_PATH. We also have to add some hacks to specify the module which should be loaded since a package will opten want to define a bunch of builtins which sould be autoloaded if either one is refered. The patch below modifies addbuiltin() so that it allows adding an already defined builtin if its handler function is NULL. In that case addbuiltin simply overwrites the existing structure. That can be used in the future for autoloading. Unfortunately it seems to be impossible to handle BINF_MAGICEQUALS and BINF_PSPECIAL this way (unless we add other options to zmodload for that). Instead of zmodload it may be better to use the autoload with an option (e.g. autoload -b). Zoltan *** Src/module.c 1996/10/31 01:38:10 3.1.0.1 --- Src/module.c 1996/11/10 23:43:44 *************** *** 159,166 **** cleanup_module(m); dlclose(m->handle); if (! --(m->count)) { - zsfree(m->nam); remnode(modules, node); } } break; --- 159,167 ---- cleanup_module(m); dlclose(m->handle); if (! --(m->count)) { remnode(modules, node); + zsfree(m->nam); + zfree(m, sizeof(*m)); } } break; *************** *** 175,186 **** if (! ops['f']) { zwarnnam(nam, "module %s already loaded.", *args, 0); ret++; ! } else if (load_module(*args) != m->handle) { zwarnnam(nam, "reloaded module %s have new handle?", *args, 0); ret++; } else { m->count++; - ret = init_module(m); } } else if (! (handle = load_module(*args))) { zwarnnam(nam, "failed to load module: %s", *args, 0); --- 176,191 ---- if (! ops['f']) { zwarnnam(nam, "module %s already loaded.", *args, 0); ret++; ! } else if ((handle = load_module(*args)) != m->handle) { zwarnnam(nam, "reloaded module %s have new handle?", *args, 0); + if (handle) + dlclose(handle); + ret++; + } else if (init_module(m)) { + dlclose(handle); ret++; } else { m->count++; } } else if (! (handle = load_module(*args))) { zwarnnam(nam, "failed to load module: %s", *args, 0); *************** *** 190,228 **** m->nam = ztrdup(*args); m->handle = handle; m->count = 1; ! PERMALLOC { ! addlinknode(modules, m); ! } LASTALLOC; ! ret = init_module(m); } } return ret; } /**/ ! void addbuiltin(char *nam, int flags, HandlerFunc hfunc, int minargs, int maxargs, char *optstr) { Builtin bn; ! bn = zcalloc(sizeof(*bn)); ! bn->nam = nam; bn->flags = flags; bn->handlerfunc = hfunc; bn->minargs = minargs; bn->maxargs = maxargs; bn->optstr = optstr; ! PERMALLOC { ! builtintab->addnode(builtintab, bn->nam, bn); ! } LASTALLOC; } /**/ ! void deletebuiltin(char *nam) { Builtin bn; bn = (Builtin) builtintab->removenode(builtintab, nam); zfree(bn, sizeof(struct builtin)); } --- 195,262 ---- m->nam = ztrdup(*args); m->handle = handle; m->count = 1; ! if (init_module(m)) { ! dlclose(handle); ! ret++; ! zsfree(m->nam); ! zfree(m, sizeof(*m)); ! } else { ! PERMALLOC { ! addlinknode(modules, m); ! } LASTALLOC; ! } } } return ret; } + /* addbuiltin() can be used to add a new builtin. It has six arguments: * + * - the name of the new builtin * + * - BINF_* flags (see zsh.h). Normally it is 0. * + * - the handler function of the builtin * + * - minimum number of arguments * + * - maximum number of argument (-1 means unlimited) * + * - possible option leters * + * It returns zero on succes 1 on failure */ + /**/ ! int addbuiltin(char *nam, int flags, HandlerFunc hfunc, int minargs, int maxargs, char *optstr) { Builtin bn; ! bn = (Builtin) builtintab->getnode2(builtintab, nam); ! if (bn && bn->handlerfunc) ! return 1; ! if (!bn) { ! bn = zcalloc(sizeof(*bn)); ! bn->nam = nam; ! PERMALLOC { ! builtintab->addnode(builtintab, bn->nam, bn); ! } LASTALLOC; ! } bn->flags = flags; bn->handlerfunc = hfunc; bn->minargs = minargs; bn->maxargs = maxargs; bn->optstr = optstr; ! return 0; } + /* Remove the builtin added previously by addbuiltin(). Returns * + * zero on succes and 1 if there is no builtin with that name. * + * Attempt to delete a builtin which is not defined by * + * addbuiltin() will fail badly with unpredictable results. */ + /**/ ! int deletebuiltin(char *nam) { Builtin bn; bn = (Builtin) builtintab->removenode(builtintab, nam); + if (!bn) + return 1; zfree(bn, sizeof(struct builtin)); + return 0; } ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Handling for ZLE modules 1996-11-08 17:16 ` Zefram 1996-11-08 17:26 ` Bruce Stephens 1996-11-10 23:55 ` Zoltan Hidvegi @ 1996-11-11 13:07 ` Peter Stephenson 2 siblings, 0 replies; 13+ messages in thread From: Peter Stephenson @ 1996-11-11 13:07 UTC (permalink / raw) To: Zsh hackers list Zefram wrote: > >The other question is how to handle unloading. One has to be careful > >when bindings remain which point to the function; also, the functions > >are in a linear array like the builtin functions and you may not be > >deleting at the end. I have arranged it so that the function is > >marked as deleted with name "<deleted>" (which should only be used for > >output), but the table entry is kept. > > I don't like this. Do we retain the binding or not? If not, we have > to go through every key binding, changing them to undefined-key. The > alternative would be to maintain link counts for loaded bindings, to > avoid reusing a slot that is bound to some key. O.K., the only rational way of doing this is to seek and destroy any binding to a function which is deleted. Having written this, it seemed stupid not to make it directly available to the user as well, so I added the bindkey -u option which undefines any binding to the given command, which could be a builtin just as easily as one loaded (though if it is, bindkey -d will still restore any predefined binding to it, just as if you'd removed it with bindkey -r). Since bindkey usually restricts itself to the current (or with -a, the alternate) keymap, I made -u do that, and added another option -U which deletes the command in every keymap (which is what deletezlefunction() requires) --- the addition is trivial. (It's really time the manual entry for bindkey was tidied up, too.) I made addzlefunction() safer in case the function is already defined, and modified the sample accordingly. I don't think this clashes with anything recent, but you need the first ZLE module patch, of course. Maybe a bug or maybe not: `bindkey -s -u string' doesn't work. *** Doc/zshbuiltins.man.mod2 Mon Nov 11 11:46:10 1996 --- Doc/zshbuiltins.man Mon Nov 11 13:45:41 1996 *************** *** 64,69 **** --- 64,71 ---- .TP \fBbindkey\fP \-\fBr\fP \fIin-string\fP ... .TP + \fBbindkey\fP \-\fBuU\fP \fIcommand\fP ... + .TP \fBbindkey\fP [ \-\fBa\fP ] \fIin-string\fP [ \fIcommand\fP ] ... .TP \fBbindkey\fP \-\fBs\fP [ \-\fBa\fP ] \fIin-string\fP \fIout-string\fP ... *************** *** 77,83 **** loads the compiled-in bindings of these characters for the mode determined by the preceding options, or the current mode if used alone. Any previous bindings done by the user will be preserved. If the \-\fBr\fP option is given, remove ! any binding for each \fIin-string\fP. If the \-\fBs\fP option is not specified, bind each \fIin-string\fP to a specified \fIcommand\fP. If no \fIcommand\fP is specified, print the binding of \fIin-string\fP if it is bound, or return a nonzero exit code if it is not bound. If the \-\fBs\fP --- 79,88 ---- loads the compiled-in bindings of these characters for the mode determined by the preceding options, or the current mode if used alone. Any previous bindings done by the user will be preserved. If the \-\fBr\fP option is given, remove ! any binding for each \fIin-string\fP. If the \-\fBu\fP option is ! given, undefine every key bound to \fIcommand\fP in the current ! keymap; with \-\fBU\fP, do so in every keymap. If the \-\fBs\fP ! option is not specified, bind each \fIin-string\fP to a specified \fIcommand\fP. If no \fIcommand\fP is specified, print the binding of \fIin-string\fP if it is bound, or return a nonzero exit code if it is not bound. If the \-\fBs\fP *** Src/hashtable.h.mod2 Mon Nov 11 10:08:33 1996 --- Src/hashtable.h Mon Nov 11 13:44:40 1996 *************** *** 259,265 **** {NULL, "alias", BINF_MAGICEQUALS, bin_alias, 0, -1, 0, "Lgmr", NULL}, {NULL, "autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "t", "u"}, {NULL, "bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL}, ! {NULL, "bindkey", 0, bin_bindkey, 0, -1, 0, "asvemdr", NULL}, {NULL, "break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL}, {NULL, "bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL}, {NULL, "cd", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL}, --- 259,265 ---- {NULL, "alias", BINF_MAGICEQUALS, bin_alias, 0, -1, 0, "Lgmr", NULL}, {NULL, "autoload", BINF_TYPEOPTS, bin_functions, 0, -1, 0, "t", "u"}, {NULL, "bg", 0, bin_fg, 0, -1, BIN_BG, NULL, NULL}, ! {NULL, "bindkey", 0, bin_bindkey, 0, -1, 0, "asvemdruU", NULL}, {NULL, "break", BINF_PSPECIAL, bin_break, 0, 1, BIN_BREAK, NULL, NULL}, {NULL, "bye", 0, bin_break, 0, 1, BIN_EXIT, NULL, NULL}, {NULL, "cd", 0, bin_cd, 0, 2, BIN_CD, NULL, NULL}, *** Src/mod_deltochar.c.mod2 Mon Nov 11 11:41:45 1996 --- Src/mod_deltochar.c Mon Nov 11 11:43:01 1996 *************** *** 73,80 **** int boot_mod_deltochar(void *dummy) { ! z_deltochar = addzlefunction("delete-to-char", deltochar, ZLE_DELETE); ! return 0; } /**/ --- 73,84 ---- int boot_mod_deltochar(void *dummy) { ! int newfunc = addzlefunction("delete-to-char", deltochar, ZLE_DELETE); ! if (newfunc > 0) { ! z_deltochar = newfunc; ! return 0; ! } else ! return -1; } /**/ *** Src/module.c.mod2 Mon Nov 11 11:35:47 1996 --- Src/module.c Mon Nov 11 13:33:00 1996 *************** *** 268,281 **** struct zlecmd *zc = NULL; int slot, addsize = zlecmdtot - ZLECMDCOUNT; ! /* Should we check for a name clash, or let the module do it? */ ! /* First try and find a free slot. ! * Slight problem: if we re-use a slot then any key-binding ! * which has not been deleted picks up the new function. ! * It's not clear this is up to ZLE to deal with: the ! * use can fix it with bindkey if (s)he wants ! */ for (slot = 0; slot < addsize; slot++) if (zlecmdadd[slot].flags & ZLE_DELETED) { zc = zlecmdadd + slot; --- 268,278 ---- struct zlecmd *zc = NULL; int slot, addsize = zlecmdtot - ZLECMDCOUNT; ! /* Check for a clash */ ! if (zlefindfunc(name) != zlecmdtot) ! return -1; ! /* First try and find a free slot. */ for (slot = 0; slot < addsize; slot++) if (zlecmdadd[slot].flags & ZLE_DELETED) { zc = zlecmdadd + slot; *************** *** 309,318 **** if (zcn < ZLECMDCOUNT || zcn >= zlecmdtot) return; zcn -= ZLECMDCOUNT; zc = zlecmdadd + zcn; ! zc->name = "<deleted>"; zc->func = feep; zc->flags = ZLE_DELETED; } --- 306,317 ---- if (zcn < ZLECMDCOUNT || zcn >= zlecmdtot) return; + /* Remove all key bindings to zcn, wherever */ + unbindzlefunc(zcn, 0); zcn -= ZLECMDCOUNT; zc = zlecmdadd + zcn; ! zc->name = ""; zc->func = feep; zc->flags = ZLE_DELETED; } *** Src/zle_main.c.mod2 Mon Nov 11 09:52:17 1996 --- Src/zle_main.c Mon Nov 11 13:44:27 1996 *************** *** 963,968 **** --- 963,980 ---- char *s; int func, len, firstzero = 0; + if (ops['u'] || ops['U']) { + /* unbind all references to given function */ + func = zlefindfunc(*argv); + if (func == zlecmdtot) { + zerr("undefined function: %s", *argv, 0); + return 1; + } + unbindzlefunc(func, ops['U'] ? 0 : ops['a'] ? 2 : 1); + argv++; + continue; + } + s = getkeystring(*argv++, &len, 2, NULL); if (len > 1) { if (s[0]) *************** *** 989,1027 **** tab[STOUC(*s)] = z_undefinedkey; if (func == z_sendstring) free(keybindtab->removenode(keybindtab, s)); ! } else { ! if (ky && ky->prefixct) { ! if (ky->func == z_sendstring) { ! zfree(ky->str, ky->len); ! ky->str = NULL; ! } ! ky->func = z_undefinedkey; ! } else ! free(keybindtab->removenode(keybindtab, s)); ! if (len > 1) { ! s[--len] = '\0'; ! while (len > 1) { ! (ky = (Key) keybindtab->getnode(keybindtab, s))->prefixct--; ! if (!ky->prefixct && ky->func == z_undefinedkey) ! free(keybindtab->removenode(keybindtab, s)); ! s[--len] = '\0'; ! } ! (ky = (Key) keybindtab->getnode(keybindtab, s))->prefixct--; ! if (!ky->prefixct) { ! int *otab = ops['a'] ? mainbindtab : altbindtab; ! tab[STOUC(*s)] = ky->func; ! /* ! * If the bindtab we are not using also ! * adds this key as a prefix, it must also ! * be reset. ! */ ! if (otab[STOUC(*s)] == z_prefix) ! otab[STOUC(*s)] = ky->func; ! if (ky->func != z_sendstring) ! free(keybindtab->removenode(keybindtab, s)); ! } ! } ! } zfree(s, len); continue; } --- 1001,1008 ---- tab[STOUC(*s)] = z_undefinedkey; if (func == z_sendstring) free(keybindtab->removenode(keybindtab, s)); ! } else ! delprefbinding(keybindtab, ky, s, len); zfree(s, len); continue; } *************** *** 1094,1099 **** --- 1075,1127 ---- return 0; } + /* Delete a binding for a key sequence with prefixes */ + + /**/ + void + delprefbinding(HashTable ktab, Key ky, char *s, int len) + { + if (ky && ky->prefixct) { + if (ky->func == z_sendstring) { + zfree(ky->str, ky->len); + ky->str = NULL; + } + ky->func = z_undefinedkey; + } else + free(ktab->removenode(ktab, s)); + if (len > 1) { + s[--len] = '\0'; + while (len > 1) { + (ky = (Key) ktab->getnode(ktab, s))->prefixct--; + if (!ky->prefixct && ky->func == z_undefinedkey) + free(ktab->removenode(ktab, s)); + s[--len] = '\0'; + } + (ky = (Key) ktab->getnode(ktab, s))->prefixct--; + if (!ky->prefixct) { + /* + * Both the main and alternate binding tables use + * the same keybindings, so we need to delete them here. + * We need to pick the table associated with the right ktab + * (i.e. vi or emacs). If the ktab we are passed is not + * current (i.e. not keybindtab), the alternate table + * is not relevant, so don't touch it. + */ + int *tab = (ktab == emkeybindtab) ? emacs_cur_bindtab : + viins_cur_bindtab; + if (tab[STOUC(*s)] == z_prefix) + tab[STOUC(*s)] = ky->func; + if (ktab == keybindtab) { + if (altbindtab[STOUC(*s)] == z_prefix) + altbindtab[STOUC(*s)] = ky->func; + } + if (ky->func != z_sendstring) + free(ktab->removenode(ktab, s)); + } + } + + } + /**/ void freekeynode(HashNode hn) *************** *** 1197,1202 **** --- 1225,1301 ---- else putc('\n', shout); showinglist = 0; + } + + LinkList bindremlist; + + /**/ + void + zerobinding(HashNode hn, int ifunc) + { + if (((Key)hn)->func == ifunc) + addlinknode(bindremlist, hn); + } + + /* + * Unbind the given zle function ifunc wherever it occurs. + * With notall = 0, do this for all binding tables. + * = 1, do this in the main binding table. + * = 2, do this in the alternate binding table. + * Note that the main and alternate binding tables share + * the same table for sequences with prefixes. + */ + + /**/ + void + unbindzlefunc(int ifunc, int notall) + { + int i, **bindptr; + int *bindlist[] = { altbindtab, emacs_cur_bindtab, viins_cur_bindtab, + NULL }; + HashTable keybindlist[] = { emkeybindtab, vikeybindtab, NULL }; + HashTable *keybindptr; + + PERMALLOC { + for (keybindptr = keybindlist; *keybindptr; keybindptr++) { + LinkNode ln; + bindremlist = newlinklist(); + if (notall) + keybindptr = &keybindtab; + + /* + * Search the key binding tables for the function. + * It's dangerous to modify a hash table while scanning, + * so put the bindings found in a list and + * delete the bindings one by one later. + */ + scanhashtable(*keybindptr, 0, 0, 0, zerobinding, ifunc); + + for (ln = firstnode(bindremlist); ln; incnode(ln)) { + Key k = (Key) ln->dat; + char *s = ztrdup(k->nam); + int sl = strlen(s); + delprefbinding(*keybindptr, k, s, sl); + zfree(s, sl); + } + + freelinklist(bindremlist, NULL); + if (notall) + break; + } + bindremlist = NULL; + } LASTALLOC; + + for (bindptr = bindlist; *bindptr; bindptr++) { + /* if notall == 2, we are doing altbindtab first anyway */ + if (notall == 1) + bindptr = &mainbindtab; + for (i = 0; i < 256; i++) + if ((*bindptr)[i] == ifunc) + (*bindptr)[i] = z_undefinedkey; + if (notall) + break; + } } /**/ -- Peter Stephenson <pws@ifh.de> Tel: +49 33762 77366 WWW: http://www.ifh.de/~pws/ Fax: +49 33762 77413 Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen DESY-IfH, 15735 Zeuthen, Germany. ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <pws@ifh.de>]
* Re: Handling for ZLE modules [not found] ` <pws@ifh.de> @ 1996-11-08 16:45 ` Bart Schaefer 1996-11-11 16:02 ` Bart Schaefer 1996-11-13 18:53 ` zle_refresh trial patch (and unrelated bug) Bart Schaefer 2 siblings, 0 replies; 13+ messages in thread From: Bart Schaefer @ 1996-11-08 16:45 UTC (permalink / raw) To: Zsh hackers list On Nov 8, 4:26pm, Peter Stephenson wrote: } Subject: Handling for ZLE modules } } I'm so impressed with the dynamic library code I couldn't resist } implementing a way of allowing you to load new ZLE functions from } modules. Could I suggest that we immediately identify a subdirectory other than Src/ where contributed modules can live and have their own Makefile? I think this would be far preferable to cluttering Src/ with a bunch of files with "mod_" prefixed to their names. It might also be useful to have a standard (but by default not present) directory where the build process looks for locally-supplied modules to compile. -- Bart Schaefer Brass Lantern Enterprises http://www.well.com/user/barts http://www.nbn.com/people/lantern ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: Handling for ZLE modules [not found] ` <pws@ifh.de> 1996-11-08 16:45 ` Bart Schaefer @ 1996-11-11 16:02 ` Bart Schaefer 1996-11-13 18:53 ` zle_refresh trial patch (and unrelated bug) Bart Schaefer 2 siblings, 0 replies; 13+ messages in thread From: Bart Schaefer @ 1996-11-11 16:02 UTC (permalink / raw) To: Zsh hackers list On Nov 11, 2:07pm, Peter Stephenson wrote: } Subject: Re: Handling for ZLE modules } } O.K., the only rational way of doing this is to seek and destroy any } binding to a function which is deleted. I agree with the changes made in this patch, but I wanted to point out that this is the second patch in the last 24 hours that has clashed with a previous patch. The last patch from Zoltan, and now this one from Peter, both conflict with Zefram's from a few days ago. I can't remember how long it has been since that last happened with patches I applied from zsh-workers. Fortunately, the resolution for the rejects was relatively obvious, and it's nice that this has generated so much interest. I'm beginning to worry, however, that we're about to start producing contradictory fixes for the same problems. Should we try to get this organized somehow before that happens? Or are we just counting on Zoltan to have enough free time to sort it all out? -- Bart Schaefer Brass Lantern Enterprises http://www.well.com/user/barts http://www.nbn.com/people/lantern ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: zle_refresh trial patch (and unrelated bug) [not found] ` <pws@ifh.de> 1996-11-08 16:45 ` Bart Schaefer 1996-11-11 16:02 ` Bart Schaefer @ 1996-11-13 18:53 ` Bart Schaefer 1996-11-14 9:03 ` Peter Stephenson 2 siblings, 1 reply; 13+ messages in thread From: Bart Schaefer @ 1996-11-13 18:53 UTC (permalink / raw) To: Zsh hackers list On Nov 12, 1:40pm, Peter Stephenson wrote: } Subject: Re: zle_refresh trial patch (and unrelated bug) } } "Bart Schaefer" wrote: } > builtin let fun == 0 && eval function "$var" } > } > Ah, I see -- I did accept-line once before, which changed "(( fun == 0 ))" } > into "builtin let fun == 0", which is not being parsed correctly. } } Nor will it ever be --- that's quite a serious bug. `let' needs to } get each expression as one single argument, so it should be } builtin let "fun == 0" } and I'm pretty sure it was until not all that long ago. So is somebody fixing this? "zed -f" ("fned") is just about completely useless because of this bug -- almost any function edited ends up broken. Even with Peter's patch for "==", you get `bad math expression' errors. -- Bart Schaefer Brass Lantern Enterprises http://www.well.com/user/barts http://www.nbn.com/people/lantern ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: zle_refresh trial patch (and unrelated bug) 1996-11-13 18:53 ` zle_refresh trial patch (and unrelated bug) Bart Schaefer @ 1996-11-14 9:03 ` Peter Stephenson 1996-11-14 14:57 ` Zefram 0 siblings, 1 reply; 13+ messages in thread From: Peter Stephenson @ 1996-11-14 9:03 UTC (permalink / raw) To: zsh-workers (By the way, I've been getting mail fine... I've passed Bart's error on to the postmaster, but it seems you need a pretty sophisticated mailer even to see it :-)) "Bart Schaefer" wrote: > On Nov 12, 1:40pm, Peter Stephenson wrote: > } Subject: Re: zle_refresh trial patch (and unrelated bug) > } > } "Bart Schaefer" wrote: > } > builtin let fun == 0 && eval function "$var" > > So is somebody fixing this? "zed -f" ("fned") is just about completely > useless because of this bug -- almost any function edited ends up broken. > Even with Peter's patch for "==", you get `bad math expression' errors. When I posted the first message I was worried that dquote_parse() was doing something it was going to be hard to keep up with. However, since you get an immediate parse error if you include a " inside a ((...)), sticking a nulled-out "..." around the argument for recovery in text.c looks like it will do the trick. Anything more sophisticated probably needs (( to have it's own type flag in struct Cmd. This patch certainly ought to restore the previous functionality, though. Certainly seems to fix up zed -f zed. (By the way, how about adding a noflowcontrol setopt to zed? I just discovered I liked this.) (Sorrysorry... it's against 3.1 again. I don't have the luxury here of space for arbitrary versions. I really don't think that will make a difference this time.) *** Src/lex.c.dbp Thu Nov 14 09:44:46 1996 --- Src/lex.c Thu Nov 14 09:45:09 1996 *************** *** 378,384 **** --- 378,386 ---- bptr = tokstr = (char *)ncalloc(bsiz = 256); hungetc(c); cmdpush(CS_MATH); + add(Dnull); c = dquote_parse(')', 0); + add(Dnull); cmdpop(); if (c || (c = hgetc()) != ')') { hungetc(c); -- Peter Stephenson <pws@ifh.de> Tel: +49 33762 77366 WWW: http://www.ifh.de/~pws/ Fax: +49 33762 77413 Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen DESY-IfH, 15735 Zeuthen, Germany. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: zle_refresh trial patch (and unrelated bug) 1996-11-14 9:03 ` Peter Stephenson @ 1996-11-14 14:57 ` Zefram 0 siblings, 0 replies; 13+ messages in thread From: Zefram @ 1996-11-14 14:57 UTC (permalink / raw) To: Peter Stephenson; +Cc: zsh-workers > Anything more >sophisticated probably needs (( to have it's own type flag in struct >Cmd. I for one would like that to happen. It's really annoying to have (()) changed to let when listing functions. It's also confusing to have (()) fail after "disable let". >(Sorrysorry... it's against 3.1 again. I don't have the luxury here >of space for arbitrary versions. I really don't think that will make >a difference this time.) It only really makes a difference when patching the module code itself. IMO we shouldn't be posting patches for `configure' itself anyway; they are large and contain no information. (zsh developers can be assumed to have autoconf available.) -zefram ^ permalink raw reply [flat|nested] 13+ messages in thread
* zle_refresh trial patch @ 1996-11-09 10:22 Geoff Wing [not found] ` <gwing@primenet.com.au> 0 siblings, 1 reply; 13+ messages in thread From: Geoff Wing @ 1996-11-09 10:22 UTC (permalink / raw) To: zsh-workers Heyla, here's a trial patch for nicer scrolling. Scrolling in a multiple-screen buffer should be pretty much emacs style. There is one quirk: if you are at last screen of the buffer and you go up, the scroll point will not necessarily be the top of the screen - it is unavoidable without a large style change. There is also a bug fix for the status line (unfortunately I wrote it after I was doing the other stuff so it is dependant on it - though I could separate if needed). "<....>" has been added, so if you see that on the right hand side of the first line of the status line it means there is stuff missing there. It's a complement to <.... and ....> which are used in the normal text area. Also, the single line scrolling which was dependant on BAUD has also been removed. This patch is dependant on patch zsh-workers/2336 The type of command I've mainly checked it with is: % zed -f zed on 24/25 line screens. Anyway, try and find some bugs. It'll make me happier :-) *** zle_refresh.c.~1~ Sat Nov 9 20:15:01 1996 --- zle_refresh.c Sat Nov 9 21:08:12 1996 *************** *** 113,185 **** } /* ! * Jul 96: <mason> changed to single line scroll for higher speed terminals ! * I've seperated the loops for readability (and it's slightly faster) ! * Returns line number to be used next */ /**/ ! int scrollwindow(int tline) { ! int t0, hwinh; char *s; ! if (tline || baud >= 19200) { /* single line scroll */ ! hwinh = 1; ! s = nbuf[tline]; ! for (t0 = tline; t0 < winh - 1; t0++) ! nbuf[t0] = nbuf[t0 + 1]; ! nbuf[winh - 1] = s; ! } else { /* half screen scroll */ ! hwinh = winh / 2; ! for (t0 = 0; t0 != winh - hwinh; t0++) { ! s = nbuf[t0]; ! nbuf[t0] = nbuf[t0 + hwinh]; ! nbuf[t0 + hwinh] = s; ! } ! } if (!tline) more_start = 1; ! return winh - hwinh; } /* this is the messy part. */ /* this define belongs where it's used!!! */ ! #define nextline \ ! { \ ! *s = '\0'; \ ! if (++ln == winh) \ ! if (nvln != --ln && nvln != -1) \ ! break; \ ! else { \ ! ln = scrollwindow(0); \ ! if(nvln != -1) \ ! nvln -= winh - ln; \ ! } \ ! if (!nbuf[ln]) \ ! nbuf[ln] = (char *)zalloc(winw + 1); \ ! s = (unsigned char *)nbuf[ln]; \ ! sen = s + winw; \ } ! #define snextline \ ! { \ ! *s = '\0'; \ ! if (++ln == winh) \ ! if (tosln <= nvln + 1) { \ ! ln = scrollwindow(0); \ ! if (nvln) \ ! nvln--, tosln--; \ ! } else { \ ! tosln--; \ ! ln = scrollwindow(tosln); \ ! } \ ! if (!nbuf[ln]) \ ! nbuf[ln] = (char *)zalloc(winw + 1); \ ! s = (unsigned char *)nbuf[ln]; \ ! sen = s + winw; \ } #ifdef TIOCGWINSZ --- 113,186 ---- } /* ! * Nov 96: <mason> changed to single line scroll */ /**/ ! void scrollwindow(int tline) { ! int t0; char *s; ! s = nbuf[tline]; ! for (t0 = tline; t0 < winh - 1; t0++) ! nbuf[t0] = nbuf[t0 + 1]; ! nbuf[winh - 1] = s; if (!tline) more_start = 1; ! return; } /* this is the messy part. */ /* this define belongs where it's used!!! */ ! #define nextline \ ! { \ ! *s = '\0'; \ ! if (ln != winh - 1) \ ! ln++; \ ! else { \ ! if (!canscroll) { \ ! if (nvln != -1 && nvln != winh - 1 \ ! && (numscrolls != onumscrolls - 1 \ ! || nvln <= winh / 2)) \ ! break; \ ! numscrolls++; \ ! canscroll = winh / 2; \ ! } \ ! canscroll--; \ ! scrollwindow(0); \ ! if (nvln != -1) \ ! nvln--; \ ! } \ ! if (!nbuf[ln]) \ ! nbuf[ln] = (char *)zalloc(winw + 1); \ ! s = (unsigned char *)nbuf[ln]; \ ! sen = s + winw; \ } ! #define snextline \ ! { \ ! *s = '\0'; \ ! if (ln != winh - 1) \ ! ln++; \ ! else \ ! if (tosln < 3) { \ ! more_status = 1; \ ! scrollwindow(tosln + 1); \ ! } else if (tosln - 1 <= nvln) { \ ! scrollwindow(0); \ ! if (nvln) \ ! nvln--, tosln--; \ ! } else { \ ! tosln--; \ ! scrollwindow(tosln); \ ! } \ ! if (!nbuf[ln]) \ ! nbuf[ln] = (char *)zalloc(winw + 1); \ ! s = (unsigned char *)nbuf[ln]; \ ! sen = s + winw; \ } #ifdef TIOCGWINSZ *************** *** 191,197 **** hasam; /* terminal should have auto-margin */ static int put_rpmpt, /* whether we should display right-prompt */ oput_rpmpt, /* whether displayed right-prompt last time */ ! oxtabs; /* oxtabs - tabs expand to spaces if set */ extern int clearflag; /* set to non-zero if alwayslastprompt used */ /**/ --- 192,199 ---- hasam; /* terminal should have auto-margin */ static int put_rpmpt, /* whether we should display right-prompt */ oput_rpmpt, /* whether displayed right-prompt last time */ ! oxtabs, /* oxtabs - tabs expand to spaces if set */ ! numscrolls, onumscrolls; extern int clearflag; /* set to non-zero if alwayslastprompt used */ /**/ *************** *** 199,205 **** refresh(void) { static int inlist; /* avoiding recursion */ ! int ln = 0, /* current line we're working on */ nvcs = 0, nvln = -1, /* video cursor column and line */ t0 = -1, /* tmp */ tosln = 0; /* tmp in statusline stuff */ --- 201,209 ---- refresh(void) { static int inlist; /* avoiding recursion */ ! int canscroll = 0, /* number of lines we are allowed to scroll */ ! ln = 0, /* current line we're working on */ ! more_status = 0, /* more stuff in status line */ nvcs = 0, nvln = -1, /* video cursor column and line */ t0 = -1, /* tmp */ tosln = 0; /* tmp in statusline stuff */ *************** *** 240,245 **** --- 244,250 ---- cleareol = 0; /* unset */ more_start = more_end = 0; /* unset */ if (resetneeded) { + onumscrolls = 0; setterm(); #ifdef TIOCGWINSZ if (winchanged) { *************** *** 269,278 **** } fflush(shout); clearf = clearflag; ! } else if (winw != columns) resetvideo(); ! /* now winw equals columns; now all width comparisons can be made to winw */ if (isset(SINGLELINEZLE) || termok != TERM_OK) { singlerefresh(); --- 274,284 ---- } fflush(shout); clearf = clearflag; ! } else if (winw != columns || winh != lines) resetvideo(); ! /* now winw equals columns and winh equals lines ! width comparisons can be made with winw, height comparisons with winh */ if (isset(SINGLELINEZLE) || termok != TERM_OK) { singlerefresh(); *************** *** 287,292 **** --- 293,299 ---- cs = 0; } scs = line + cs; + numscrolls = 0; /* first, we generate the video line buffers so we know what to put on the screen - also determine final cursor position (nvln, nvcs) */ *************** *** 326,334 **** /* if we're really on the next line, don't fake it; do everything properly */ if (t == scs && (nvcs = s - (unsigned char *)(nbuf[nvln = ln])) == winw) { *s = '\0'; ! if (!nbuf[++ln]) ! nbuf[ln] = (char *)zalloc(winw + 1); ! s = (unsigned char *)nbuf[ln]; nvcs = 0; nvln++; } --- 333,343 ---- /* if we're really on the next line, don't fake it; do everything properly */ if (t == scs && (nvcs = s - (unsigned char *)(nbuf[nvln = ln])) == winw) { *s = '\0'; ! switch (*s) { /* a sad hack to make the break */ ! case '\0': /* in nextline work */ ! nextline ! } ! *s = '\0'; nvcs = 0; nvln++; } *************** *** 340,346 **** tosln = ln + 1; snextline t = (unsigned char *)statusline; ! for (; t < (unsigned char *)statusline+statusll; t++) { if (icntrl(*t)) { /* simplified processing in the status line */ *s++ = '^'; if (s == sen) --- 349,355 ---- tosln = ln + 1; snextline t = (unsigned char *)statusline; ! for (; t < (unsigned char *)statusline + statusll; t++) { if (icntrl(*t)) { /* simplified processing in the status line */ *s++ = '^'; if (s == sen) *************** *** 361,366 **** --- 370,381 ---- nbuf[tosln - 1][winw] = '\0'; } + /* insert <....> at end of first status line if status is too big */ + if (more_status) { + strncpy(nbuf[tosln] + winw - 8, " <....> ", 8); + nbuf[tosln][winw] = '\0'; + } + *s = '\0'; nlnct = ln + 1; for (ln = nlnct; ln < winh; ln++) *************** *** 478,483 **** --- 493,499 ---- ovln = nvln; olnct = nlnct; oput_rpmpt = put_rpmpt; + onumscrolls = numscrolls; if (nlnct > vmaxln) vmaxln = nlnct; fflush(shout); /* make sure everything is written out */ -- Geoff Wing [gwing@primenet.com.au] Technical Manager Phone : +61-3-9818 2977 PrimeNet - Internet Consultancy Facsimile: +61-3-9819 3788 Web : <URL:http://www.primenet.com.au/> Mobile : 0412 162 441 ^ permalink raw reply [flat|nested] 13+ messages in thread
[parent not found: <gwing@primenet.com.au>]
* Re: zle_refresh trial patch (and unrelated bug) [not found] ` <gwing@primenet.com.au> @ 1996-11-09 17:09 ` Bart Schaefer 1996-11-12 12:40 ` Peter Stephenson 0 siblings, 1 reply; 13+ messages in thread From: Bart Schaefer @ 1996-11-09 17:09 UTC (permalink / raw) To: zsh-workers On Nov 9, 9:22pm, Geoff Wing wrote: } Subject: zle_refresh trial patch } } here's a trial patch for nicer scrolling. Looks pretty good to me. } The type of command I've mainly checked it with is: } % zed -f zed I tried that, and when I accept-line I get zsh: = not found But I get that in 3.0.0 too, so it has nothing to do with your patch. This seems to be the culprit: builtin let fun == 0 && eval function "$var" Ah, I see -- I did accept-line once before, which changed "(( fun == 0 ))" into "builtin let fun == 0", which is not being parsed correctly. Either the output of "functions" needs to get fixed for this case, or (probably better) the parser has to make "==" a reserved word so it is not interpeted as "$(which -p '=')". -- Bart Schaefer Brass Lantern Enterprises http://www.well.com/user/barts http://www.nbn.com/people/lantern ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: zle_refresh trial patch (and unrelated bug) 1996-11-09 17:09 ` zle_refresh trial patch (and unrelated bug) Bart Schaefer @ 1996-11-12 12:40 ` Peter Stephenson 0 siblings, 0 replies; 13+ messages in thread From: Peter Stephenson @ 1996-11-12 12:40 UTC (permalink / raw) To: Zsh hackers list "Bart Schaefer" wrote: > builtin let fun == 0 && eval function "$var" > > Ah, I see -- I did accept-line once before, which changed "(( fun == 0 ))" > into "builtin let fun == 0", which is not being parsed correctly. Nor will it ever be --- that's quite a serious bug. `let' needs to get each expression as one single argument, so it should be builtin let "fun == 0" and I'm pretty sure it was until not all that long ago. In fact, Zoltan has improved the lexing of ((...)) so that it's no longer quite the same as a double quoted expression, so that my original hack of turning the former into the latter for ease of reconstructing the text is not quite so appropriate. > Either the output of "functions" needs to get fixed for this case, or > (probably better) the parser has to make "==" a reserved word so it is > not interpeted as "$(which -p '=')". This won't help here, but maybe == is common enough as a test to have a special case anyway. *** Src/subst.c~ Thu Oct 10 12:05:11 1996 --- Src/subst.c Tue Nov 12 13:31:18 1996 *************** *** 371,377 **** *namptr = dyncat(hom, ptr); return 1; } ! } else if (*str == Equals && isset(EQUALS) && str[1]) { /* =foo */ char sav, *pp, *cnam; for (pp = str + 1; !isend2(*pp); pp++); --- 371,378 ---- *namptr = dyncat(hom, ptr); return 1; } ! } else if (*str == Equals && isset(EQUALS) && str[1] ! && str[1] != Equals) { /* =foo */ char sav, *pp, *cnam; for (pp = str + 1; !isend2(*pp); pp++); -- Peter Stephenson <pws@ifh.de> Tel: +49 33762 77366 WWW: http://www.ifh.de/~pws/ Fax: +49 33762 77413 Deutches Electronen-Synchrotron --- Institut fuer Hochenergiephysik Zeuthen DESY-IfH, 15735 Zeuthen, Germany. ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~1996-11-14 15:04 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 1996-11-08 15:26 Handling for ZLE modules Peter Stephenson 1996-11-08 17:16 ` Zefram 1996-11-08 17:26 ` Bruce Stephens 1996-11-10 23:55 ` Zoltan Hidvegi 1996-11-11 13:07 ` Peter Stephenson [not found] ` <pws@ifh.de> 1996-11-08 16:45 ` Bart Schaefer 1996-11-11 16:02 ` Bart Schaefer 1996-11-13 18:53 ` zle_refresh trial patch (and unrelated bug) Bart Schaefer 1996-11-14 9:03 ` Peter Stephenson 1996-11-14 14:57 ` Zefram 1996-11-09 10:22 zle_refresh trial patch Geoff Wing [not found] ` <gwing@primenet.com.au> 1996-11-09 17:09 ` zle_refresh trial patch (and unrelated bug) Bart Schaefer 1996-11-12 12:40 ` Peter Stephenson
Code repositories for project(s) associated with this public inbox https://git.vuxu.org/mirror/zsh/ This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).