jline-1.0.orig/0000777000175000017500000000000011550707350013357 5ustar twernertwernerjline-1.0.orig/src/0000777000175000017500000000000011550707350014146 5ustar twernertwernerjline-1.0.orig/src/src/0000755000175000017500000000000011550705746014740 5ustar twernertwernerjline-1.0.orig/src/src/assembly/0000755000175000017500000000000011550705746016557 5ustar twernertwernerjline-1.0.orig/src/src/assembly/assembly.xml0000644000175000017500000000321711550705746021123 0ustar twernertwerner zip true README* LICENSE* NOTICE* target *.jar licenses /lib * src/test/java/jline/example /examples/jline/example src/test/resources/jline/example /examples/jline/example target/site/apidocs /apidocs src /src/src /src pom.xml jline-1.0.orig/src/src/main/0000755000175000017500000000000011550705746015664 5ustar twernertwernerjline-1.0.orig/src/src/main/resources/0000755000175000017500000000000011550705746017676 5ustar twernertwernerjline-1.0.orig/src/src/main/resources/jline/0000755000175000017500000000000011550705746020777 5ustar twernertwernerjline-1.0.orig/src/src/main/resources/jline/keybindings-mac.properties0000644000175000017500000000252111550705746026161 0ustar twernertwerner# Keybinding mapping for JLine. The format is: # [key code]: [logical operation] # CTRL-B: move to the previous character 2: PREV_CHAR # CTRL-G: move to the previous word 7: PREV_WORD # CTRL-F: move to the next character 6: NEXT_CHAR # CTRL-A: move to the beginning of the line 1: MOVE_TO_BEG # CTRL-D: close out the input stream 4: EXIT # CTRL-E: move the cursor to the end of the line 5: MOVE_TO_END # BACKSPACE, CTRL-H: delete the previous character # 8 is the ASCII code for backspace and therefor # deleting the previous character 8: DELETE_PREV_CHAR # TAB, CTRL-I: signal that console completion should be attempted 9: COMPLETE # CTRL-J, CTRL-M: newline 10: NEWLINE # CTRL-K: erase the current line 11: KILL_LINE # ENTER: newline 13: NEWLINE # CTRL-L: clear screen 12: CLEAR_SCREEN # CTRL-N: scroll to the next element in the history buffer 14: NEXT_HISTORY # CTRL-P: scroll to the previous element in the history buffer 16: PREV_HISTORY # CTRL-R: redraw the current line 18: REDISPLAY # CTRL-U: delete all the characters before the cursor position 21: KILL_LINE_PREV # CTRL-V: paste the contents of the clipboard (useful for Windows terminal) 22: PASTE # CTRL-W: delete the word directly before the cursor 23: DELETE_PREV_WORD # DELETE, CTRL-?: delete the previous character # 127 is the ASCII code for delete 127: DELETE_PREV_CHAR jline-1.0.orig/src/src/main/resources/jline/jline32.dll0000644000175000017500000003730511550705746022752 0ustar twernertwernerMZ@ !L!This program cannot be run in DOS mode. $PELTA~# 8  7 P_` p.text ``.data @.rdata 0@@.bss@.edata_P@@.idata `@.relocp@BUWVS } |$]M\$ $ƃ 1t[@tE@ 9rtЋ@9st&$(1҉@$u@uF1t&e[^_] t&$@tl@{&@v'9rtЋ@9st&$1=@$doz 1_'U@@ET$L$$ ɃÍU@@EL$T$$ÐU]gU$E}u E(ED$E$u EEEEUEE$E}uED$E$ UU$jE$XE$&EED$E$aE@UR )@U$E$E$EED$E$E@UR )@U] U t&  QA uÍ&USpt)t'pKu$P[[]Ë t1 @tu뽍US @u6p @t%tt&pKu$P*[[]Ë t1 @tuU 0Q 0r]ÐUp@P]Í&'U1$]|$8@@ CC SC,CP@CC$C(  C0S4$|$]Ðt&UX]p@ut ]u]ÐEAAAA0uEAAAAEAAAAEء0EAAAAEAAAAEܡ0EAAAAEAAAAE 0EAAAA4$E0E0E0E0E]fub$8t\$$`ftp@C`@C@%$4$v'$ UVSPut&'AuaLHy0Eء0Eܡ0E 0E0E0E0E0EE$d؃fu 1ҍe[^]É$9u獴&'U@ST1ET$UT$$ t0v'|AtHy;8u ؋] o%`%`%`%`%`%`%`%`%`%`%`%`%`%`U]W`-LIBGCCW32-EH-SJLJ-GTHR-MINGW32TAP (PPPxPttee&&PPP QVQQQQR2R jline.dllJava_jline_WindowsTerminal_getConsoleModeJava_jline_WindowsTerminal_getConsoleMode@8Java_jline_WindowsTerminal_getWindowsTerminalHeightJava_jline_WindowsTerminal_getWindowsTerminalHeight@8Java_jline_WindowsTerminal_getWindowsTerminalWidthJava_jline_WindowsTerminal_getWindowsTerminalWidth@8Java_jline_WindowsTerminal_readByteJava_jline_WindowsTerminal_readByte@8Java_jline_WindowsTerminal_setConsoleModeJava_jline_WindowsTerminal_setConsoleMode@12T`a```a``b``` aa a,a4a@aLaXaha|aaa`` aa a,a4a@aLaXaha|aaa$_getch$__dllonexit_errnoabort0fflush?freermallocAddAtomAFindAtomAGetAtomNameA GetConsoleModeGetConsoleScreenBufferInfoGetStdHandleSetConsoleMode`msvcrt.dll``````msvcrt.dll(`(`(`(`(`(`(`KERNEL32.dllC0M0q0000001,1b1l111W3t333333334 4#4-4<4J4b4z44444444555:5X5q5555555666666666667777777788"828B8R8t8 0.filegdllcrt1.c (_atexit` __onexit .text.data.bss .filegcrtstuff.c5 .text .data.bss .file&g4E r& e t  .textj .data.bss .file0gdllmain.cL@ .text@ .data.bss .file>ggccmain.cX p.0eP x ___main .textP.data.bss .fileHgpseudo-reloc.c` .text`(.data.bss0.filepg.text.data.bss0 @P) E0 a` v .text%.data.bss@ .rdata .text.data .bss`.text.data .bss`.idata$7.idata$5.idata$4T.idata$6.filegfakehnameTfthunk.text.data .bss`.idata$2.idata$5.idata$4P.filegfake.text.data .bss`.idata$4X.idata$5.idata$7 .text.data .bss`.idata$7.idata$5.idata$4`.idata$6.text.data .bss`.idata$7.idata$5.idata$4l.idata$6 .text.data .bss`.idata$7.idata$5.idata$4p.idata$6,.text.data .bss`.idata$7.idata$5.idata$4d.idata$6 .text.data .bss`.idata$7.idata$5.idata$4t.idata$64.text.data .bss`.idata$7.idata$5.idata$4h.idata$6.filegfakehname`fthunk.text.data .bss`.idata$2.idata$5.idata$4\.filegfake.text.data .bss`.idata$4x.idata$5.idata$7 .text.data .bss`.idata$7.idata$5.idata$4.idata$6.text.data .bss`.idata$7.idata$5.idata$4.idata$6h.text.data .bss`.idata$7 .idata$5.idata$4.idata$6.text .data .bss`.idata$7.idata$5.idata$4.idata$6|.text0.data .bss`.idata$7.idata$5.idata$4.idata$6L.text@.data .bss`.idata$7.idata$5.idata$4.idata$6@.textP.data .bss`.idata$7.idata$5.idata$4.idata$6X.filegfakehnamefthunk.text`.data .bss`.idata$2(.idata$5.idata$4|.file%gfake.text`.data .bss`.idata$4.idata$5.idata$7 .file1gcrtstuff.c` .text` .data .bss`.ctorst |_free ` 0__errno CPi @+9 \t__dll__% CS `pqp_fflush p_getch 4 __end__Rh _malloc u|_abort (:(Ok0P _DllMainCRTStartup@12_first_atexit_next_atexit___do_sjlj_init_Java_jline_WindowsTerminal_getConsoleMode@8_Java_jline_WindowsTerminal_setConsoleMode@12_Java_jline_WindowsTerminal_readByte@8_Java_jline_WindowsTerminal_getWindowsTerminalWidth@8_Java_jline_WindowsTerminal_getWindowsTerminalHeight@8jline_WindowsTerminal.c_DllMain@12_initialized___do_global_dtors___do_global_ctors__pei386_runtime_relocatorpseudo-reloc-list.c_w32_atom_suffix___w32_sharedptr_default_unexpected_dw2_object_mutex.0_dw2_once.1_sjl_fc_key.2_sjl_once.3___w32_eh_shared_initialize___w32_sharedptr_initialize___w32_sharedptr_set___w32_sharedptr_get___sjlj_init_ctor___RUNTIME_PSEUDO_RELOC_LIST____imp__GetConsoleMode@8__data_start_____DTOR_LIST_____w32_sharedptr_terminate___tls_start____libmsvcrt_a_iname__imp__FindAtomA@4__imp__abort__size_of_stack_commit____size_of_stack_reserve____major_subsystem_version_____crt_xl_start___AddAtomA@4___crt_xi_start_____crt_xi_end____imp__GetConsoleScreenBufferInfo@8__libmoldname_a_iname_GetConsoleMode@8__bss_start_____RUNTIME_PSEUDO_RELOC_LIST_END____size_of_heap_commit___SetConsoleMode@8__imp___errno___crt_xp_start____imp__getch___crt_xp_end____minor_os_version____head_libmsvcrt_a__image_base____section_alignment____head_libmoldname_a__RUNTIME_PSEUDO_RELOC_LIST___GetStdHandle@4__data_end_____w32_sharedptr__CTOR_LIST____bss_end____imp__SetConsoleMode@8___crt_xc_end_____crt_xc_start_____CTOR_LIST____imp__GetAtomNameA@12__imp____dllonexit__file_alignment____imp__malloc__major_os_version___GetConsoleScreenBufferInfo@8__imp__GetStdHandle@4___dllonexit__DTOR_LIST____size_of_heap_reserve_____crt_xt_start____subsystem____imp__fflush___w32_sharedptr_unexpected___tls_end____imp__free__major_image_version____loader_flags____imp__AddAtomA@4__head_libkernel32_a__minor_subsystem_version____minor_image_version___FindAtomA@4_GetAtomNameA@12__RUNTIME_PSEUDO_RELOC_LIST_END____libkernel32_a_iname___crt_xt_end__jline-1.0.orig/src/src/main/resources/jline/jline64.dll0000644000175000017500000013600011550705746022747 0ustar twernertwernerMZ@ !L!This program cannot be run in DOS mode. $wՄ333פ|2~4~)E%03k~{~2~2Rich3PEdf0F" pXC((.textnp `.rdata3)*t@@.dataX!@.pdata@@.reloc@@BH(oHu H(HT$@HoL$@DʋH(@SH AoHt HoH [lH\$WH sohoHHHH\oGO H\$0+H _H\$WH ooH3HHHnGO H\$0+H _@SH HHHt$0HɾHEH|$8fffffH 1Hu UkH L3ynHHu,9tHq u &  Ht$0HH|$8H [= 3H [@SH IU(n3AHmHHt'HmumL3Hm3H [Hl$0kHt$8sH|$@{ Ld$HDcmL3HmAtƹD%a5d-bʼn=NL+ Ld$HH|$@Ht$8Hl$0gt` #mH4/Hx4 x&qx3uH [  3H [ÅuE9huHs^ CH [Ãuh6 HH H3aHcH3_HcH3Hl$HH\$@Ht$PH|$XH0A\H JL%>H\$Hl$Ht$H|$ ATAUAVH HHl$`MEILAHtLIE3fff;"u3E@"HDAEHt HG3Hv+tEHt HGH@tEu@ t@ uHt GH3fff;fffff< t< uH;MtI}IAfff3ɀ;\ufffHʀ;\t;"u$ut{"HCuH 33҅tHt\HEutcu< t[< tWtJs*Ht-tHHGEHGEHQtHEEH8HtHEMtIEAH\$@Hl$HHt$PH|$XH A^A]A\H\$Ht$ WH0=u'H=\A3HNOH͠H=Ht;uHHD$HLL$@E33HHD$ mHct$@HH;shHcD$HHs]H H;rTHHtGLHD$HLL$@HHHD$ D\$@H=.A3DH\$PHt$XH0_H\$PHt$XH0_H\$Ht$ WH@cu:OHHt G;/Oxu0%fOHH%f?Hl$PHLd$XtHf;uHf;uE3H+LLd$8Ld$0HDK33Dd$(Ld$ NHctiH>HHtYLd$8Ld$0DKL33ɉl$(HD$ Nu HIHNHHl$PLd$XH\$`Ht$hH@_H|N3كtuJaNHHt<8tfffH8uH8u+ÃHcHHHuHN3H\$`Ht$hH@_LHH'HMH\$`Ht$hHH@_H\$WH H_dH=XdH;sffHHtHH;rH\$0H _H\$WH H/dH=(dH;sffHHtHH;rH\$0H _H\$Hl$Ht$ HT$WATAUAVAWH@MqI)Mi8I+3AfMHLHL$0LD$8A9};I] fffCH;CH;{tHL$0IHЅ~sA<$csmu(H=tH tIKAHI)IG@SMc $HD$(IG(IMHHD$ rL)HA;}CH;s6H;r H;wAD$ u1 tH;t&HT$xIƱIDCMAЃHA;}rL\$@I[0Ik@IsHIA_A^A]A\_H\$Ht$WH HgHHHLci~H9:tIHHHH;rIHHH;9:LJMIuE3AALBH\$8Ht$@H _IuH\$8Ht$@H _Hl$0HHJLc} }AMD;}1IE3ffHAIMD }}D;|ً=u ǃp=u ǃ]=u ǃJ=u ǃ7=u ǃ$=u ǃ=u ǃAHHl$0H\$8Ht$@H _E3LBAHHl$0H\$8Ht$@H _H\$8Ht$@3H _Ácsmu3ø@WH HÅH2-+HD$0H;tHHH _HL$0H\$@[IH\$0HIDI3,HDI3(IHL$8DI3IL\$8L3H\$@HL#H3-+L;LDL%IL#H _H\$Hl$Ht$WATAUH L%{3L-H3H-}I܃{u HcƺH ILH z t*HH;|θH\$@Hl$HHt$PH A]A\_HcHI3H\$Hl$Ht$H|$ ATH HzE3H-%}HfH7HttHGHL'HH;|fffH Ht {u|GHH;|H\$0Hl$8Ht$@H|$HH A\HcHfzHH H%GH\$Ht$H|$ATH HcپH=Êu4NHHL%zI<ty(@HHu 3X I<u.HuH 3I HH )zFH\$0Ht$8H|$@H A\@UH HH yFH ]H\$WH HcH=,yHH<uuHH H\$0H _H%I$t3u AAՃt tuLuD3"Lt$ E3E333cH\$xH$H@A_A^A]A\_Ð@@@@@NB@UH0H}pt3H0]H QH QH IH(v>H(H\$Ht$H|$ ATH@L3|$`H HHu{HL$`2tH|$ E3E333|$`u H|:H sE<Ht!H9EH<HHuHIH@HHqIӋD$0=u <3|$0H\$PHt$XH|$hH@A\@UWH8HH38@NjH8_]H\$UVWAUAVHPALL3H9H艜$\$0H D<HHHDH;HHHDHH|;HHmDHHk];HmH$HVtE3E333H\$ $uCHCH;HHHtHCH:HHH L$H;H9-݂H ˂H{HLtkHtfHt*HL$4A LD$8HL$ AQHAԅtD$@u5HL$0tE3E333H\$ |$0rD>H 1H;t2Ht(HHtH H;tHtHHH L$HtDMIH3H$HPA^A]_^]H8HLt HtMu0D"E3E333HD$ H8À9t HHuHuA뺐AHIAtHuHu0AE3E333"HD$ |"H83H8H8MLLuHuHu(3H8HtHtMu D 3H8Mu0D:E3E333HD$ H8IHIu&ffffAHIBt4Hu,fffAHIBt HtIuMuD HIIu CLAPH8AE3E333"HD$ V"H8H8HLt HtMu:DBE3E333HD$ H8fffffffAHIAtHuHu0AE3E333"HD$ "H83H8H8x&~uwH8Ëw wH8}E3E333HD$ ?H8H\$Hl$Ht$WH H(HHtyH VuH;tmHHta8u\H Ht9uH(HHt9uH(<HH(H0HtD8u?H8HHHHHPHH0HXHsH;t`uHXWH_XH-kfffffH9ktH Ht 9u(H{tHKHt 9uH HuHH\$0Hl$8Ht$@H _HHHtH HtHHtH0HtHAXAL (kL9Ht HHtHxt HHHtH IuHX`HHHtH HtHHtH0HtHAXAL jfL9Ht HHtHxt HPHtH IuHX`H@SH HHtEHt@LL;t/HHMtIA:uHjL;tHH [3H [@SH H؋ rtHtuH+ HHjNHع aHuK HH [@UH H -H ]H\$Ht$WH HYHHL3(E3LjD^D^D^ L^L+D^fffffAHHCuL XjHL+ffffffBHHAAD AuH\$0Ht$8H _H\$Hl$ WHH'oH3H$pHIHT$P33`3H$HT$pÿH;rD$VD$p Ht$Vt.VDD;wA+IJLpDB FHuҋE \$8LD$pD$0EDωD$(H$p3HD$ EU \$@D$8H$p|$0HD$(LL$pD3ɉ|$ EU \$@D$8H$p|$0HD$(LL$pA3ɉ|$ H$L$pHMAtp tp ƁHHIHuQ3HMffffffSB w C w CƁH;rH$pH3"L$I[ Ik(I_H\$WH !H otHt Hn CHH\$0H;ktDHtuHgHL$0H;tLHkHHkHD$0H\$0 HuK HH\$8H _@UH H }H ]H\$Hl$Ht$H|$ ATH @2,LHHL;%ftnu_LH;-jt muu @vuv/@tD;uv/ۃuAD$v@tH\$0Hl$8Ht$@H|$HH A\@SUVWHHH kH3HD$8HH{3HLP 3Hekkk HkH+Ӊkfff:HHGuL eHAL+ffffffHIAAD Au3L$3Ll$@L-yiLIŐ98IH0rsg.bHT$ :.8HKA3Y |$ {k @8l$&HT$&t5Bt-DD;wA+IDHHuH@8*uHCffffffffffHHHuKtxtX t8tCʼnC HkkCC HkkCC HkkvCC Hkk[CC Hkk@kHkk19-tt H$HKA3 O dHgILgALfffA8)MtHffffffA@t7A;w#HLfffffAHAA@;vIA8(uIIIu{Ct$t t u k K dHADfCADfCADfCAD fCAD fCADfCHY3L$Ll$@HL$8H3] HH_^][H\$Ht$H|$ATAUAVH0A\H$HD;C HHHHA 3ۉHAD.HuHL%aI;t`L%aHh GqGqG qӉ\$ L}HcDOfAHT$ Ӊ\$ }HcD9B`T$ ߉\$ fff}Hc9Bp\$ HduH dI;tnH=d +u&L%{`I;tH>3DAH\$PHt$XH|$`H0A^A]A\@UH H }H ]H(=xux3H(H\$WH0HIHtA3HHH;s0eE3E333HD$ '3H\$@H0_HٸHHD3HwH kPL?'Hu8=kt$H9uHt 3H\$@H0_Ht H\$@H0_H\$WH HHHuHH\$@H _Hu3H\$@H _HHl$0Ht$8wCH kHLHD3L(HHut9 ktUHyt0HvHg" 3Hl$0Ht$8H\$@H _H&H&HH\$Hl$Ht$WH @2BHHHH;]teuuH;=ateuHu @@D8@tH\$0Hl$8Ht$@H _fffffffLH+Irat6t  IȈHtf IfHt  IHMIuQMItH HHIuIMuIfff HIuIffffffffffffffffI sBH LT H HALQHD LT IHALQuIqfffffffffHr  D @HuH@L LT L LQLL LT LILQLL LT (H@LILQLL LT LILQuIIq $ffffffffffffffffIIrat6t HɊ IȈtHf Ift H IMIuPMItHH IHuIMuIffHɊ IȈuIffffffffffffffffI sBHD LT H HALQHD L IHALuIsffffffffffHw H D @uH@LL LT LILQLL LT LILQLL LT H@LILQLL L LILuIIq $fffffffHM3M3Hd$ LD$(HffffHL$HT$DD$I fffffffRpfffffffHIrSIII@rHكtL+HHMI?Iu9MIItfffHHIuMt HIuffffffffIs0HHQHQH@HQHQIHQHQHQuffffHHQHQH@HQHQIHQHQHQu $TH8Hu,"E3E333HD$ HH8LH d3H8H%!̹鶵HR]t 覹Ht +]t_H$!HL$03AYH$3HD$@HD$0D$0@HD$ H$HD$( HL$  萸H(II8ML‹DAtALcALHcL#IcN IBHIJAt HHI3H#H(fffffffH; \uHfuHHSH HHIHK}HKtHK kHK(bHK0YH QHK@HHKH?HKP6HKX-HK`$HKhHK8HKp HKxHHHHHHHHHHH|HpHdHXHLH@H4H(HHH H(H0H8H@HHHPH [HtBSH HH H; [tHKH; [tHKH; [tnH [HSH HHIH; l[t=HK H; b[t+HK(H; X[tHK0H; N[tHK8H; D[tHK@H; :[tHKHH; 0[tH [DL$ UATAUAVAWH@Hl$0H]@HuHH}PHXH3HEEdMDLuzALMH.A2t d^xu?cup3uI$p]huI$X)3zcttuuh3uI$p9}xDMX MƋEЉ|$(H|$ tLct~HL;wKL$Hw5HAH;w HHH+H\$0HZ茫HHt HH2O$3HDMXMƺDd$(H\$ tLM`DHA{HKuX;t(LMXMƋЋˉ|$(H|$ HHLHE`DMXMA׋HD$ gHtHHMH3H]@HuHH}PHeA_A^A]A\]HSHpHhHx@2HL`Lh@xAMDHp薼HHHH; QHD$PHL$@Ht$Ht aXu HD$@H;5>UH$t8Xu HD$Hu.@@|$XHHT$@HHAHB|$XH\$P$HL$@D͉D$8$MĉD$0$AՉD$(H$HD$ Ll$`Ld$hH$@H$tHp[fffffffH+Ir"tf: u,HIuMIuMt: u HIuH3ÐIt7HH; u[HAH;D uLHAH;D u=HAH;D u.H IuIMItHH; uHIuIHHHH HHH;fffffffMtuH+LItB H:uWItNtJHuJ ffwHJ H;uHII~vHLI3It H3HHÄt't#HttHtt tuH3@UATAUAVAWH`Hl$@H]PHuXH}`HSH3HED^3MELMDEDUHuKDKLz)3ɉ\$(H\$ tDSD^xDDD^DMpE~3I^A ~LD$0@ϺRLT$0I@@ϊHt @;H@-Hl$xu$@;H@+u@;$H$EkAaA$WEu)@0tA :Runtime Error! Program: .mixcrtEncodePointerKERNEL32.DLLDecodePointerInitializeCriticalSectionAndSpinCountkernel32.dllGetProcessWindowStationGetUserObjectInformationAGetLastActivePopupGetActiveWindowMessageBoxAUSER32.DLL  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~ ((((( H h(((( H H  !"#$%&'()*+,-./0123456789:;<=>?@abcdefghijklmnopqrstuvwxyz[\]^_`abcdefghijklmnopqrstuvwxyz{|}~  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`ABCDEFGHIJKLMNOPQRSTUVWXYZ{|}~HH:mm:ssdddd, MMMM dd, yyyyMM/dd/yyPMAMDecemberNovemberOctoberSeptemberAugustJulyJuneAprilMarchFebruaryJanuaryDecNovOctSepAugJulJunMayAprMarFebJanSaturdayFridayThursdayWednesdayTuesdayMondaySundaySatFriThuWedTueMonSunSunMonTueWedThuFriSatJanFebMarAprMayJunJulAugSepOctNovDec 5/?GGGwHHHIIIKKKsMMMtOOOuPPPQQQvRRRSSS1!x2@y3#z4${5%|6^}7&~8*9(0)-_=+ qQwWeErRtTyYuUiI oOpP[{]} aAsSdD fF!gG"hH#jJ $kK %lL &;:''"(`~)\|zZ,xX-cC.vV/bB0nN1mM 2,<3.>4/?5*r ;T^h<U_i=V`j>Wak?Xbl@YcmAZdnB[eoC\fpD]gqG7wH8I9-K4s5M6t+O1uP2Q3vR0S.CONIN$RSDSި_G_L(c:\pws_HEAD\external\src\native\jline\x64\Release\jline.pdb  4 2p!@SĜ!td@SĜ!pĜ! t dTpĜ t d 4R3NpR42 pd 4 Rp3;0!a!T a  4 R p`! R!t4 RBd42 pT 4 2 p ` t d 4 23~"""42p3$$P%$*%p%!4%r&H!4%r&H!'/'H!4'/'HdT42pBP0 ! !!t!d!4!3)),+!t d T 4,,X!T 4t d ,,X!  t d ,,XR t d T 42d 4 R p!P11̚! T P11̚!  T P11̚d 4 r p! !d!T!4!rp!p56Ԙ!Tp56Ԙ!Tp56Ԙ??42p d T 42ptd423B:::  0 dT4p t d 423R=>@> B3G?t??t? B3???RP d4r p3qABBbpP t d 4 r3CC DC!PDE!PDE4 p`Pb20203M5M`Md42 p!0NoN !d0NoN $T4 p`p  4 2p3PPQ t dT42!@RR!@RR p`P0`82P t d 4 R3VWX  4 Rp!dT0YrY,!  dT0YrY,  4 2pB2 0  201 5#td43r P`8!ffܞ!ff!dff!  tTffܞ0- Etd4C P`X!nn`!n$o@!dn$o@!tTnn`  0!PpXq!tPpXq  4 `  !ss!ssܟ!T ssܟ! t d ssr0b`(' EC p`0P`p!jjTt d4wxT  !t d p{{!  t d p{{203q}x}}Z*<htƣأ .DR`nxĤ֤(@Zp¥إ "6Jfئ &<N`rԧ6GetConsoleModeGetStdHandleSetConsoleMode:GetConsoleScreenBufferInfoKERNEL32.dllHeapAllocIGetCurrentThreadIdFlsSetValueGetCommandLineAHeapFreeGetVersionExAGetProcessHeapGetProcAddressGetModuleHandleAExitProcessWriteFileGetModuleFileNameAHeapSetInformationHeapCreateHeapDestroyFlsGetValuejTlsFreeFlsFree.SetLastErrorsGetLastErrorlTlsSetValueFlsAlloc\Sleep*SetHandleCountiGetFileTypeGetStartupInfoADeleteCriticalSectionFreeEnvironmentStringsAXGetEnvironmentStringsFreeEnvironmentStringsWWideCharToMultiByteZGetEnvironmentStringsWRtlUnwindExQueryPerformanceCounterGetTickCountFGetCurrentProcessIdGetSystemTimeAsFileTimeMLeaveCriticalSectionEnterCriticalSectiondTerminateProcessEGetCurrentProcesstUnhandledExceptionFilterPSetUnhandledExceptionFilter5IsDebuggerPresentRtlCaptureContextNLoadLibraryA%InitializeCriticalSectionGetCPInfoGetACPGetOEMCP;IsValidCodePageHeapReAllocHeapSizeqMultiByteToWideCharvGetLocaleInfoAGetStringTypeAGetStringTypeW@LCMapStringAALCMapStringWRtlVirtualUnwindRtlLookupFunctionEntryReadConsoleInputAVCreateFileA6CloseHandlef0FJ,@p@T~ jline.dllJava_jline_WindowsTerminal_getConsoleModeJava_jline_WindowsTerminal_getWindowsTerminalHeightJava_jline_WindowsTerminal_getWindowsTerminalWidthJava_jline_WindowsTerminal_readByteJava_jline_WindowsTerminal_setConsoleModeP  `(ȅhH !"xyz؂Ȃ        ! 5A CPR S WY l m pr   )       ``````````$C  0@ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@`y!@~ڣ @ڣ AϢ[@~QQ^ _j21~2-+] f "|xtplh`XP@0$ ВĒphdX@0 . .pPSTPDT;Zx0Nm:Yw/Ml=H@kĜ4@SĜSėpĜpDܗPj pĜ<Ĝ`8>@ )D0OpĜaap RR a̘pHH0fĜp@@) Ԙ0 !!S!H`!""""w##$ $I%(P%i%p%%%%Ĝ%r&Hr&&p&'\'/'H/'P'P'U'`'''^(``((`(+ș,, ,,,,X,D-@D-- -. .=0`@0B1|P11̚122223 3^3`333V5ܚp56Ԙ6E7E7n7n777[80`88<99`9:T:::;0;;;<<)=Ĝ0=3>@>T>`>x>H>>@?{?ԛ??????H0@BBBC$CH0CDX DBDLPDEEFFFFeGpGHH5I@III(KLLĜLUM̜`MyMM+N0NoN oNO OCPPP Q<Q)Q0Q:R`@RRRUUUxVXX)X0XXXH`X)Y0YrY,rYYY Z ZZ@^d^8_ ` ``@`7aHpa\cP`ccXcGdPPdf`ffܞfffMarc Prud'hommeaux */ public class ConsoleReader implements ConsoleOperations { final static int TAB_WIDTH = 4; String prompt; private boolean useHistory = true; private boolean usePagination = false; public static final String CR = System.getProperty("line.separator"); private static ResourceBundle loc = ResourceBundle.getBundle(CandidateListCompletionHandler.class.getName()); /** * Map that contains the operation name to keymay operation mapping. */ public static SortedMap KEYMAP_NAMES; static { Map names = new TreeMap(); names.put("MOVE_TO_BEG", new Short(MOVE_TO_BEG)); names.put("MOVE_TO_END", new Short(MOVE_TO_END)); names.put("PREV_CHAR", new Short(PREV_CHAR)); names.put("NEWLINE", new Short(NEWLINE)); names.put("KILL_LINE", new Short(KILL_LINE)); names.put("PASTE", new Short(PASTE)); names.put("CLEAR_SCREEN", new Short(CLEAR_SCREEN)); names.put("NEXT_HISTORY", new Short(NEXT_HISTORY)); names.put("PREV_HISTORY", new Short(PREV_HISTORY)); names.put("START_OF_HISTORY", new Short(START_OF_HISTORY)); names.put("END_OF_HISTORY", new Short(END_OF_HISTORY)); names.put("REDISPLAY", new Short(REDISPLAY)); names.put("KILL_LINE_PREV", new Short(KILL_LINE_PREV)); names.put("DELETE_PREV_WORD", new Short(DELETE_PREV_WORD)); names.put("NEXT_CHAR", new Short(NEXT_CHAR)); names.put("REPEAT_PREV_CHAR", new Short(REPEAT_PREV_CHAR)); names.put("SEARCH_PREV", new Short(SEARCH_PREV)); names.put("REPEAT_NEXT_CHAR", new Short(REPEAT_NEXT_CHAR)); names.put("SEARCH_NEXT", new Short(SEARCH_NEXT)); names.put("PREV_SPACE_WORD", new Short(PREV_SPACE_WORD)); names.put("TO_END_WORD", new Short(TO_END_WORD)); names.put("REPEAT_SEARCH_PREV", new Short(REPEAT_SEARCH_PREV)); names.put("PASTE_PREV", new Short(PASTE_PREV)); names.put("REPLACE_MODE", new Short(REPLACE_MODE)); names.put("SUBSTITUTE_LINE", new Short(SUBSTITUTE_LINE)); names.put("TO_PREV_CHAR", new Short(TO_PREV_CHAR)); names.put("NEXT_SPACE_WORD", new Short(NEXT_SPACE_WORD)); names.put("DELETE_PREV_CHAR", new Short(DELETE_PREV_CHAR)); names.put("ADD", new Short(ADD)); names.put("PREV_WORD", new Short(PREV_WORD)); names.put("CHANGE_META", new Short(CHANGE_META)); names.put("DELETE_META", new Short(DELETE_META)); names.put("END_WORD", new Short(END_WORD)); names.put("NEXT_CHAR", new Short(NEXT_CHAR)); names.put("INSERT", new Short(INSERT)); names.put("REPEAT_SEARCH_NEXT", new Short(REPEAT_SEARCH_NEXT)); names.put("PASTE_NEXT", new Short(PASTE_NEXT)); names.put("REPLACE_CHAR", new Short(REPLACE_CHAR)); names.put("SUBSTITUTE_CHAR", new Short(SUBSTITUTE_CHAR)); names.put("TO_NEXT_CHAR", new Short(TO_NEXT_CHAR)); names.put("UNDO", new Short(UNDO)); names.put("NEXT_WORD", new Short(NEXT_WORD)); names.put("DELETE_NEXT_CHAR", new Short(DELETE_NEXT_CHAR)); names.put("CHANGE_CASE", new Short(CHANGE_CASE)); names.put("COMPLETE", new Short(COMPLETE)); names.put("EXIT", new Short(EXIT)); names.put("CLEAR_LINE", new Short(CLEAR_LINE)); names.put("ABORT", new Short(ABORT)); KEYMAP_NAMES = new TreeMap(Collections.unmodifiableMap(names)); } /** * The map for logical operations. */ private final short[] keybindings; /** * If true, issue an audible keyboard bell when appropriate. */ private boolean bellEnabled = true; /** * The current character mask. */ private Character mask = null; /** * The null mask. */ private static final Character NULL_MASK = new Character((char) 0); /** * The number of tab-completion candidates above which a warning will be * prompted before showing all the candidates. */ private int autoprintThreshhold = Integer.getInteger( "jline.completion.threshold", 100).intValue(); // same default as // bash /** * The Terminal to use. */ private final Terminal terminal; private CompletionHandler completionHandler = new CandidateListCompletionHandler(); InputStream in; final Writer out; final CursorBuffer buf = new CursorBuffer(); static PrintWriter debugger; History history = new History(); final List completors = new LinkedList(); private Character echoCharacter = null; private Map triggeredActions = new HashMap(); private StringBuffer searchTerm = null; private String previousSearchTerm = ""; private int searchIndex = -1; /** * Adding a triggered Action allows to give another course of action * if a character passed the preprocessing. * * Say you want to close the application if the user enter q. * addTriggerAction('q', new ActionListener(){ System.exit(0); }); * would do the trick. * * @param c * @param listener */ public void addTriggeredAction(char c, ActionListener listener) { triggeredActions.put(new Character(c), listener); } /** * Create a new reader using {@link FileDescriptor#in} for input and * {@link System#out} for output. {@link FileDescriptor#in} is used because * it has a better chance of being unbuffered. */ public ConsoleReader() throws IOException { this(new FileInputStream(FileDescriptor.in), new PrintWriter( new OutputStreamWriter(System.out, System.getProperty("jline.WindowsTerminal.output.encoding", System.getProperty("file.encoding"))))); } /** * Create a new reader using the specified {@link InputStream} for input and * the specific writer for output, using the default keybindings resource. */ public ConsoleReader(final InputStream in, final Writer out) throws IOException { this(in, out, null); } public ConsoleReader(final InputStream in, final Writer out, final InputStream bindings) throws IOException { this(in, out, bindings, Terminal.getTerminal()); } /** * Create a new reader. * * @param in * the input * @param out * the output * @param bindings * the key bindings to use * @param term * the terminal to use */ public ConsoleReader(InputStream in, Writer out, InputStream bindings, Terminal term) throws IOException { this.terminal = term; setInput(in); this.out = out; if (bindings == null) { try { String bindingFile = System.getProperty("jline.keybindings", new File(System.getProperty("user.home"), ".jlinebindings.properties").getAbsolutePath()); if (new File(bindingFile).isFile()) { bindings = new FileInputStream(new File(bindingFile)); } } catch (Exception e) { // swallow exceptions with option debugging if (debugger != null) { e.printStackTrace(debugger); } } } if (bindings == null) { bindings = terminal.getDefaultBindings(); } this.keybindings = new short[Character.MAX_VALUE * 2]; Arrays.fill(this.keybindings, UNKNOWN); /** * Loads the key bindings. Bindings file is in the format: * * keycode: operation name */ if (bindings != null) { Properties p = new Properties(); p.load(bindings); bindings.close(); for (Iterator i = p.keySet().iterator(); i.hasNext();) { String val = (String) i.next(); try { Short code = new Short(val); String op = (String) p.getProperty(val); Short opval = (Short) KEYMAP_NAMES.get(op); if (opval != null) { keybindings[code.shortValue()] = opval.shortValue(); } } catch (NumberFormatException nfe) { consumeException(nfe); } } // hardwired arrow key bindings // keybindings[VK_UP] = PREV_HISTORY; // keybindings[VK_DOWN] = NEXT_HISTORY; // keybindings[VK_LEFT] = PREV_CHAR; // keybindings[VK_RIGHT] = NEXT_CHAR; } } public Terminal getTerminal() { return this.terminal; } /** * Set the stream for debugging. Development use only. */ public void setDebug(final PrintWriter debugger) { ConsoleReader.debugger = debugger; } /** * Set the stream to be used for console input. */ public void setInput(final InputStream in) { this.in = in; } /** * Returns the stream used for console input. */ public InputStream getInput() { return this.in; } /** * Read the next line and return the contents of the buffer. */ public String readLine() throws IOException { return readLine((String) null); } /** * Read the next line with the specified character mask. If null, then * characters will be echoed. If 0, then no characters will be echoed. */ public String readLine(final Character mask) throws IOException { return readLine(null, mask); } /** * @param bellEnabled * if true, enable audible keyboard bells if an alert is * required. */ public void setBellEnabled(final boolean bellEnabled) { this.bellEnabled = bellEnabled; } /** * @return true is audible keyboard bell is enabled. */ public boolean getBellEnabled() { return this.bellEnabled; } /** * Query the terminal to find the current width; * * @see Terminal#getTerminalWidth * @return the width of the current terminal. */ public int getTermwidth() { return getTerminal().getTerminalWidth(); } /** * Query the terminal to find the current width; * * @see Terminal#getTerminalHeight * * @return the height of the current terminal. */ public int getTermheight() { return getTerminal().getTerminalHeight(); } /** * @param autoprintThreshhold * the number of candidates to print without issuing a warning. */ public void setAutoprintThreshhold(final int autoprintThreshhold) { this.autoprintThreshhold = autoprintThreshhold; } /** * @return the number of candidates to print without issing a warning. */ public int getAutoprintThreshhold() { return this.autoprintThreshhold; } int getKeyForAction(short logicalAction) { for (int i = 0; i < keybindings.length; i++) { if (keybindings[i] == logicalAction) { return i; } } return -1; } /** * Clear the echoed characters for the specified character code. */ int clearEcho(int c) throws IOException { // if the terminal is not echoing, then just return... if (!terminal.getEcho()) { return 0; } // otherwise, clear int num = countEchoCharacters((char) c); back(num); drawBuffer(num); return num; } int countEchoCharacters(char c) { // tabs as special: we need to determine the number of spaces // to cancel based on what out current cursor position is if (c == 9) { int tabstop = 8; // will this ever be different? int position = getCursorPosition(); return tabstop - (position % tabstop); } return getPrintableCharacters(c).length(); } /** * Return the number of characters that will be printed when the specified * character is echoed to the screen. Adapted from cat by Torbjorn Granlund, * as repeated in stty by David MacKenzie. */ StringBuffer getPrintableCharacters(char ch) { StringBuffer sbuff = new StringBuffer(); if (ch >= 32) { if (ch < 127) { sbuff.append(ch); } else if (ch == 127) { sbuff.append('^'); sbuff.append('?'); } else { sbuff.append('M'); sbuff.append('-'); if (ch >= (128 + 32)) { if (ch < (128 + 127)) { sbuff.append((char) (ch - 128)); } else { sbuff.append('^'); sbuff.append('?'); } } else { sbuff.append('^'); sbuff.append((char) (ch - 128 + 64)); } } } else { sbuff.append('^'); sbuff.append((char) (ch + 64)); } return sbuff; } int getCursorPosition() { // FIXME: does not handle anything but a line with a prompt // absolute position return getStrippedAnsiLength(prompt) + buf.cursor; } /** * Strips ANSI escape sequences starting with CSI and ending with char in range 64-126 * @param ansiString String possibly containing ANSI codes, may be null * @return length after stripping ANSI codes */ int getStrippedAnsiLength(String ansiString) { if (ansiString == null) return 0; boolean inAnsi = false; int strippedLength = 0; char[] chars = ansiString.toCharArray(); for (int i = 0; i < chars.length; i++) { char c = chars[i]; if (!inAnsi && c == 27 && i < chars.length - 1 && chars[i+1] == '[') { i++; // skip '[' inAnsi = true; } else if (inAnsi) { if (64 <= c && c <= 126) { inAnsi = false; } } else { strippedLength++; } } return strippedLength; } public String readLine(final String prompt) throws IOException { return readLine(prompt, null); } /** * The default prompt that will be issued. */ public void setDefaultPrompt(String prompt) { this.prompt = prompt; } /** * The default prompt that will be issued. */ public String getDefaultPrompt() { return prompt; } /** * Read a line from the in {@link InputStream}, and return the line * (without any trailing newlines). * * @param prompt * the prompt to issue to the console, may be null. * @return a line that is read from the terminal, or null if there was null * input (e.g., CTRL-D was pressed). */ public String readLine(final String prompt, final Character mask) throws IOException { this.mask = mask; if (prompt != null) { this.prompt = prompt; } try { terminal.beforeReadLine(this, this.prompt, mask); if ((this.prompt != null) && (this.prompt.length() > 0)) { out.write(this.prompt); out.flush(); } // if the terminal is unsupported, just use plain-java reading if (!terminal.isSupported()) { return readLine(in); } final int NORMAL = 1; final int SEARCH = 2; int state = NORMAL; boolean success = true; while (true) { // Read next key and look up the command binding. int[] next = readBinding(); if (next == null) { return null; } int c = next[0]; int code = next[1]; if (c == -1) { return null; } // Search mode. // // Note that we have to do this first, because if there is a command // not linked to a search command, we leave the search mode and fall // through to the normal state. if (state == SEARCH) { switch (code) { // This doesn't work right now, it seems CTRL-G is not passed // down correctly. :( case ABORT: state = NORMAL; break; case SEARCH_PREV: if (searchTerm.length() == 0) { searchTerm.append(previousSearchTerm); } if (searchIndex == -1) { searchIndex = history.searchBackwards(searchTerm.toString()); } else { searchIndex = history.searchBackwards(searchTerm.toString(), searchIndex); } break; case DELETE_PREV_CHAR: if (searchTerm.length() > 0) { searchTerm.deleteCharAt(searchTerm.length() - 1); searchIndex = history.searchBackwards(searchTerm.toString()); } break; case UNKNOWN: searchTerm.appendCodePoint(c); searchIndex = history.searchBackwards(searchTerm.toString()); break; default: // Set buffer and cursor position to the found string. if (searchIndex != -1) { history.setCurrentIndex(searchIndex); setBuffer(history.current()); buf.cursor = history.current().indexOf(searchTerm.toString()); } state = NORMAL; break; } // if we're still in search mode, print the search status if (state == SEARCH) { if (searchTerm.length() == 0) { printSearchStatus("", ""); } else { if (searchIndex == -1) { beep(); } else { printSearchStatus(searchTerm.toString(), history.getHistory(searchIndex)); } } } // otherwise, restore the line else { restoreLine(); } } if (state == NORMAL) { switch (code) { case EXIT: // ctrl-d if (buf.buffer.length() == 0) { return null; } else { success = deleteCurrentCharacter(); } break; case COMPLETE: // tab success = complete(); break; case MOVE_TO_BEG: success = setCursorPosition(0); break; case KILL_LINE: // CTRL-K success = killLine(); break; case CLEAR_SCREEN: // CTRL-L success = clearScreen(); break; case KILL_LINE_PREV: // CTRL-U success = resetLine(); break; case NEWLINE: // enter moveToEnd(); printNewline(); // output newline return finishBuffer(); case DELETE_PREV_CHAR: // backspace success = backspace(); break; case DELETE_NEXT_CHAR: // delete success = deleteCurrentCharacter(); break; case MOVE_TO_END: success = moveToEnd(); break; case PREV_CHAR: success = moveCursor(-1) != 0; break; case NEXT_CHAR: success = moveCursor(1) != 0; break; case NEXT_HISTORY: success = moveHistory(true); break; case PREV_HISTORY: success = moveHistory(false); break; case ABORT: case REDISPLAY: break; case PASTE: success = paste(); break; case DELETE_PREV_WORD: success = deletePreviousWord(); break; case PREV_WORD: success = previousWord(); break; case NEXT_WORD: success = nextWord(); break; case START_OF_HISTORY: success = history.moveToFirstEntry(); if (success) { setBuffer(history.current()); } break; case END_OF_HISTORY: success = history.moveToLastEntry(); if (success) { setBuffer(history.current()); } break; case CLEAR_LINE: moveInternal(-(buf.buffer.length())); killLine(); break; case INSERT: buf.setOvertyping(!buf.isOvertyping()); break; case SEARCH_PREV: // CTRL-R if (searchTerm != null) { previousSearchTerm = searchTerm.toString(); } searchTerm = new StringBuffer(buf.buffer); state = SEARCH; if (searchTerm.length() > 0) { searchIndex = history.searchBackwards(searchTerm.toString()); if (searchIndex == -1) { beep(); } printSearchStatus(searchTerm.toString(), searchIndex > -1 ? history.getHistory(searchIndex) : ""); } else { searchIndex = -1; printSearchStatus("", ""); } break; case UNKNOWN: default: if (c != 0) { // ignore null chars ActionListener action = (ActionListener) triggeredActions.get(new Character((char) c)); if (action != null) { action.actionPerformed(null); } else { putChar(c, true); } } else { success = false; } } if (!(success)) { beep(); } flushConsole(); } } } finally { terminal.afterReadLine(this, this.prompt, mask); } } private String readLine(InputStream in) throws IOException { StringBuffer buf = new StringBuffer(); while (true) { int i = in.read(); if ((i == -1) || (i == '\n') || (i == '\r')) { return buf.toString(); } buf.append((char) i); } // return new BufferedReader (new InputStreamReader (in)).readLine (); } /** * Reads the console input and returns an array of the form [raw, key * binding]. */ private int[] readBinding() throws IOException { int c = readVirtualKey(); if (c == -1) { return null; } // extract the appropriate key binding short code = keybindings[c]; if (debugger != null) { // debug(" translated: " + (int) c + ": " + code); } return new int[]{c, code}; } /** * Move up or down the history tree. */ private final boolean moveHistory(final boolean next) throws IOException { if (next && !history.next()) { return false; } else if (!next && !history.previous()) { return false; } setBuffer(history.current()); return true; } /** * Paste the contents of the clipboard into the console buffer * * @return true if clipboard contents pasted */ public boolean paste() throws IOException { Clipboard clipboard; try { // May throw ugly exception on system without X clipboard = Toolkit.getDefaultToolkit().getSystemClipboard(); } catch (Exception e) { return false; } if (clipboard == null) { return false; } Transferable transferable = clipboard.getContents(null); if (transferable == null) { return false; } try { Object content = transferable.getTransferData(DataFlavor.plainTextFlavor); /* * This fix was suggested in bug #1060649 at * http://sourceforge.net/tracker/index.php?func=detail&aid=1060649&group_id=64033&atid=506056 * to get around the deprecated DataFlavor.plainTextFlavor, but it * raises a UnsupportedFlavorException on Mac OS X */ if (content == null) { try { content = new DataFlavor().getReaderForText(transferable); } catch (Exception e) { } } if (content == null) { return false; } String value; if (content instanceof Reader) { // TODO: we might want instead connect to the input stream // so we can interpret individual lines value = ""; String line = null; for (BufferedReader read = new BufferedReader((Reader) content); (line = read.readLine()) != null;) { if (value.length() > 0) { value += "\n"; } value += line; } } else { value = content.toString(); } if (value == null) { return true; } putString(value); return true; } catch (UnsupportedFlavorException ufe) { if (debugger != null) { debug(ufe + ""); } return false; } } /** * Kill the buffer ahead of the current cursor position. * * @return true if successful */ public boolean killLine() throws IOException { int cp = buf.cursor; int len = buf.buffer.length(); if (cp >= len) { return false; } int num = buf.buffer.length() - cp; clearAhead(num); for (int i = 0; i < num; i++) { buf.buffer.deleteCharAt(len - i - 1); } return true; } /** * Clear the screen by issuing the ANSI "clear screen" code. */ public boolean clearScreen() throws IOException { if (!terminal.isANSISupported()) { return false; } // send the ANSI code to clear the screen printANSISequence("2J"); // then send the ANSI code to go to position 1,1 printANSISequence("1;1H"); redrawLine(); return true; } /** * Use the completors to modify the buffer with the appropriate completions. * * @return true if successful */ private final boolean complete() throws IOException { // debug ("tab for (" + buf + ")"); if (completors.size() == 0) { return false; } List candidates = new LinkedList(); String bufstr = buf.buffer.toString(); int cursor = buf.cursor; int position = -1; for (Iterator i = completors.iterator(); i.hasNext();) { Completor comp = (Completor) i.next(); if ((position = comp.complete(bufstr, cursor, candidates)) != -1) { break; } } // no candidates? Fail. if (candidates.size() == 0) { return false; } return completionHandler.complete(this, candidates, position); } public CursorBuffer getCursorBuffer() { return buf; } /** * Output the specified {@link Collection} in proper columns. * * @param stuff * the stuff to print */ public void printColumns(final Collection stuff) throws IOException { if ((stuff == null) || (stuff.size() == 0)) { return; } int width = getTermwidth(); int maxwidth = 0; for (Iterator i = stuff.iterator(); i.hasNext(); maxwidth = Math.max( maxwidth, i.next().toString().length())) { ; } StringBuffer line = new StringBuffer(); int showLines; if (usePagination) { showLines = getTermheight() - 1; // page limit } else { showLines = Integer.MAX_VALUE; } for (Iterator i = stuff.iterator(); i.hasNext();) { String cur = (String) i.next(); if ((line.length() + maxwidth) > width) { printString(line.toString().trim()); printNewline(); line.setLength(0); if (--showLines == 0) { // Overflow printString(loc.getString("display-more")); flushConsole(); int c = readVirtualKey(); if (c == '\r' || c == '\n') { showLines = 1; // one step forward } else if (c != 'q') { showLines = getTermheight() - 1; // page forward } back(loc.getString("display-more").length()); if (c == 'q') { break; // cancel } } } pad(cur, maxwidth + 3, line); } if (line.length() > 0) { printString(line.toString().trim()); printNewline(); line.setLength(0); } } /** * Append toPad to the specified appendTo, as well as (toPad.length () - * len) spaces. * * @param toPad * the {@link String} to pad * @param len * the target length * @param appendTo * the {@link StringBuffer} to which to append the padded * {@link String}. */ private final void pad(final String toPad, final int len, final StringBuffer appendTo) { appendTo.append(toPad); for (int i = 0; i < (len - toPad.length()); i++, appendTo.append(' ')) { ; } } /** * Add the specified {@link Completor} to the list of handlers for * tab-completion. * * @param completor * the {@link Completor} to add * @return true if it was successfully added */ public boolean addCompletor(final Completor completor) { return completors.add(completor); } /** * Remove the specified {@link Completor} from the list of handlers for * tab-completion. * * @param completor * the {@link Completor} to remove * @return true if it was successfully removed */ public boolean removeCompletor(final Completor completor) { return completors.remove(completor); } /** * Returns an unmodifiable list of all the completors. */ public Collection getCompletors() { return Collections.unmodifiableList(completors); } /** * Erase the current line. * * @return false if we failed (e.g., the buffer was empty) */ final boolean resetLine() throws IOException { if (buf.cursor == 0) { return false; } backspaceAll(); return true; } /** * Move the cursor position to the specified absolute index. */ public final boolean setCursorPosition(final int position) throws IOException { return moveCursor(position - buf.cursor) != 0; } /** * Set the current buffer's content to the specified {@link String}. The * visual console will be modified to show the current buffer. * * @param buffer * the new contents of the buffer. */ private final void setBuffer(final String buffer) throws IOException { // don't bother modifying it if it is unchanged if (buffer.equals(buf.buffer.toString())) { return; } // obtain the difference between the current buffer and the new one int sameIndex = 0; for (int i = 0, l1 = buffer.length(), l2 = buf.buffer.length(); (i < l1) && (i < l2); i++) { if (buffer.charAt(i) == buf.buffer.charAt(i)) { sameIndex++; } else { break; } } int diff = buf.cursor - sameIndex; if (diff < 0) { // we can't backspace here so try from the end of the buffer moveToEnd(); diff = buf.buffer.length() - sameIndex; } backspace(diff); // go back for the differences killLine(); // clear to the end of the line buf.buffer.setLength(sameIndex); // the new length putString(buffer.substring(sameIndex)); // append the differences } /** * Clear the line and redraw it. */ public final void redrawLine() throws IOException { printCharacter(RESET_LINE); flushConsole(); drawLine(); } /** * Output put the prompt + the current buffer */ public final void drawLine() throws IOException { if (prompt != null) { printString(prompt); } printString(buf.buffer.toString()); if (buf.length() != buf.cursor) // not at end of line { back(buf.length() - buf.cursor - 1); // sync } } /** * Output a platform-dependant newline. */ public final void printNewline() throws IOException { printString(CR); flushConsole(); } /** * Clear the buffer and add its contents to the history. * * @return the former contents of the buffer. */ final String finishBuffer() { String str = buf.buffer.toString(); // we only add it to the history if the buffer is not empty // and if mask is null, since having a mask typically means // the string was a password. We clear the mask after this call if (str.length() > 0) { if (mask == null && useHistory) { history.addToHistory(str); } else { mask = null; } } history.moveToEnd(); buf.buffer.setLength(0); buf.cursor = 0; return str; } /** * Write out the specified string to the buffer and the output stream. */ public final void putString(final String str) throws IOException { buf.write(str); printString(str); drawBuffer(); } /** * Output the specified string to the output stream (but not the buffer). */ public final void printString(final String str) throws IOException { printCharacters(str.toCharArray()); } /** * Output the specified character, both to the buffer and the output stream. */ private final void putChar(final int c, final boolean print) throws IOException { buf.write((char) c); if (print) { // no masking... if (mask == null) { printCharacter(c); } // null mask: don't print anything... else if (mask.charValue() == 0) { ; } // otherwise print the mask... else { printCharacter(mask.charValue()); } drawBuffer(); } } /** * Redraw the rest of the buffer from the cursor onwards. This is necessary * for inserting text into the buffer. * * @param clear * the number of characters to clear after the end of the buffer */ private final void drawBuffer(final int clear) throws IOException { // debug ("drawBuffer: " + clear); if (buf.cursor == buf.length() && clear == 0) { return; } char[] chars = buf.buffer.substring(buf.cursor).toCharArray(); if (mask != null) { Arrays.fill(chars, mask.charValue()); } printCharacters(chars); clearAhead(clear); if (terminal.isANSISupported()) { if (chars.length > 0) { // don't ask, it seems to work back(Math.max(chars.length - 1, 1)); } } else { back(chars.length); } flushConsole(); } /** * Redraw the rest of the buffer from the cursor onwards. This is necessary * for inserting text into the buffer. */ private final void drawBuffer() throws IOException { drawBuffer(0); } /** * Clear ahead the specified number of characters without moving the cursor. */ private final void clearAhead(final int num) throws IOException { if (num == 0) { return; } if (terminal.isANSISupported()) { printANSISequence("J"); return; } // debug ("clearAhead: " + num); // print blank extra characters printCharacters(' ', num); // we need to flush here so a "clever" console // doesn't just ignore the redundancy of a space followed by // a backspace. flushConsole(); // reset the visual cursor back(num); flushConsole(); } /** * Move the visual cursor backwards without modifying the buffer cursor. */ private final void back(final int num) throws IOException { if (num == 0) return; if (terminal.isANSISupported()) { int width = getTermwidth(); int cursor = getCursorPosition(); // debug("back: " + cursor + " + " + num + " on " + width); int currRow = (cursor + num) / width; int newRow = cursor / width; int newCol = cursor % width + 1; // debug(" old row: " + currRow + " new row: " + newRow); if (newRow < currRow) { printANSISequence((currRow - newRow) + "A"); } printANSISequence(newCol + "G"); flushConsole(); return; } printCharacters(BACKSPACE, num); flushConsole(); } /** * Issue an audible keyboard bell, if {@link #getBellEnabled} return true. */ public final void beep() throws IOException { if (!(getBellEnabled())) { return; } printCharacter(KEYBOARD_BELL); // need to flush so the console actually beeps flushConsole(); } /** * Output the specified character to the output stream without manipulating * the current buffer. */ private final void printCharacter(final int c) throws IOException { if (c == '\t') { char cbuf[] = new char[TAB_WIDTH]; Arrays.fill(cbuf, ' '); out.write(cbuf); return; } out.write(c); } /** * Output the specified characters to the output stream without manipulating * the current buffer. */ private final void printCharacters(final char[] c) throws IOException { int len = 0; for (int i = 0; i < c.length; i++) { if (c[i] == '\t') { len += TAB_WIDTH; } else { len++; } } char cbuf[]; if (len == c.length) { cbuf = c; } else { cbuf = new char[len]; int pos = 0; for (int i = 0; i < c.length; i++) { if (c[i] == '\t') { Arrays.fill(cbuf, pos, pos + TAB_WIDTH, ' '); pos += TAB_WIDTH; } else { cbuf[pos] = c[i]; pos++; } } } out.write(cbuf); } private final void printCharacters(final char c, final int num) throws IOException { if (num == 1) { printCharacter(c); } else { char[] chars = new char[num]; Arrays.fill(chars, c); printCharacters(chars); } } /** * Flush the console output stream. This is important for printout out * single characters (like a backspace or keyboard) that we want the console * to handle immedately. */ public final void flushConsole() throws IOException { out.flush(); } private final int backspaceAll() throws IOException { return backspace(Integer.MAX_VALUE); } /** * Issue num backspaces. * * @return the number of characters backed up */ private final int backspace(final int num) throws IOException { if (buf.cursor == 0) { return 0; } int count = 0; int termwidth = getTermwidth(); int lines = getCursorPosition() / termwidth; count = moveCursor(-1 * num) * -1; // debug ("Deleting from " + buf.cursor + " for " + count); buf.buffer.delete(buf.cursor, buf.cursor + count); if (getCursorPosition() / termwidth != lines) { if (terminal.isANSISupported()) { // debug("doing backspace redraw: " + getCursorPosition() + " on " + termwidth + ": " + lines); printANSISequence("J"); flushConsole(); } } drawBuffer(count); return count; } /** * Issue a backspace. * * @return true if successful */ public final boolean backspace() throws IOException { return backspace(1) == 1; } private final boolean moveToEnd() throws IOException { return moveCursor(buf.length() - buf.cursor) > 0; } /** * Delete the character at the current position and redraw the remainder of * the buffer. */ private final boolean deleteCurrentCharacter() throws IOException { if (buf.length() == 0 || buf.cursor == buf.length()) { return false; } buf.buffer.deleteCharAt(buf.cursor); drawBuffer(1); return true; } private final boolean previousWord() throws IOException { while (isDelimiter(buf.current()) && (moveCursor(-1) != 0)) { ; } while (!isDelimiter(buf.current()) && (moveCursor(-1) != 0)) { ; } return true; } private final boolean nextWord() throws IOException { while (isDelimiter(buf.current()) && (moveCursor(1) != 0)) { ; } while (!isDelimiter(buf.current()) && (moveCursor(1) != 0)) { ; } return true; } private final boolean deletePreviousWord() throws IOException { while (isDelimiter(buf.current()) && backspace()) { ; } while (!isDelimiter(buf.current()) && backspace()) { ; } return true; } /** * Move the cursor where characters. * * @param num * if less than 0, move abs(num) to the left, * otherwise move num to the right. * * @return the number of spaces we moved */ public final int moveCursor(final int num) throws IOException { int where = num; if ((buf.cursor == 0) && (where <= 0)) { return 0; } if ((buf.cursor == buf.buffer.length()) && (where >= 0)) { return 0; } if ((buf.cursor + where) < 0) { where = -buf.cursor; } else if ((buf.cursor + where) > buf.buffer.length()) { where = buf.buffer.length() - buf.cursor; } moveInternal(where); return where; } /** * debug. * * @param str * the message to issue. */ public static void debug(final String str) { if (debugger != null) { debugger.println(str); debugger.flush(); } } /** * Move the cursor where characters, withough checking the current * buffer. * * @param where * the number of characters to move to the right or left. */ private final void moveInternal(final int where) throws IOException { // debug ("move cursor " + where + " (" // + buf.cursor + " => " + (buf.cursor + where) + ")"); buf.cursor += where; if (terminal.isANSISupported()) { if (where < 0) { back(Math.abs(where)); } else { int width = getTermwidth(); int cursor = getCursorPosition(); int oldLine = (cursor - where) / width; int newLine = cursor / width; if (newLine > oldLine) { printANSISequence((newLine - oldLine) + "B"); } printANSISequence(1 +(cursor % width) + "G"); } flushConsole(); return; } char c; if (where < 0) { int len = 0; for (int i = buf.cursor; i < buf.cursor - where; i++) { if (buf.getBuffer().charAt(i) == '\t') { len += TAB_WIDTH; } else { len++; } } char cbuf[] = new char[len]; Arrays.fill(cbuf, BACKSPACE); out.write(cbuf); return; } else if (buf.cursor == 0) { return; } else if (mask != null) { c = mask.charValue(); } else { printCharacters(buf.buffer.substring(buf.cursor - where, buf.cursor).toCharArray()); return; } // null character mask: don't output anything if (NULL_MASK.equals(mask)) { return; } printCharacters(c, Math.abs(where)); } /** * Read a character from the console. * * @return the character, or -1 if an EOF is received. */ public final int readVirtualKey() throws IOException { int c = terminal.readVirtualKey(in); if (debugger != null) { // debug("keystroke: " + c + ""); } // clear any echo characters clearEcho(c); return c; } public final int readCharacter(final char[] allowed) throws IOException { // if we restrict to a limited set and the current character // is not in the set, then try again. char c; Arrays.sort(allowed); // always need to sort before binarySearch while (Arrays.binarySearch(allowed, c = (char) readVirtualKey()) < 0); return c; } /** * Issue num deletes. * * @return the number of characters backed up */ private final int delete(final int num) throws IOException { /* Commented out beacuse of DWA-2949: if (buf.cursor == 0) return 0;*/ buf.buffer.delete(buf.cursor, buf.cursor + 1); drawBuffer(1); return 1; } public final boolean replace(int num, String replacement) { buf.buffer.replace(buf.cursor - num, buf.cursor, replacement); try { moveCursor(-num); drawBuffer(Math.max(0, num - replacement.length())); moveCursor(replacement.length()); } catch (IOException e) { e.printStackTrace(); return false; } return true; } /** * Issue a delete. * * @return true if successful */ public final boolean delete() throws IOException { return delete(1) == 1; } public void setHistory(final History history) { this.history = history; } public History getHistory() { return this.history; } public void setCompletionHandler(final CompletionHandler completionHandler) { this.completionHandler = completionHandler; } public CompletionHandler getCompletionHandler() { return this.completionHandler; } /** *

* Set the echo character. For example, to have "*" entered when a password * is typed: *

* *
     * myConsoleReader.setEchoCharacter(new Character('*'));
     * 
* *

* Setting the character to * *

     * null
     * 
* * will restore normal character echoing. Setting the character to * *
     * new Character(0)
     * 
* * will cause nothing to be echoed. *

* * @param echoCharacter * the character to echo to the console in place of the typed * character. */ public void setEchoCharacter(final Character echoCharacter) { this.echoCharacter = echoCharacter; } /** * Returns the echo character. */ public Character getEchoCharacter() { return this.echoCharacter; } /** * No-op for exceptions we want to silently consume. */ private void consumeException(final Throwable e) { } /** * Checks to see if the specified character is a delimiter. We consider a * character a delimiter if it is anything but a letter or digit. * * @param c * the character to test * @return true if it is a delimiter */ private boolean isDelimiter(char c) { return !Character.isLetterOrDigit(c); } private void printANSISequence(String sequence) throws IOException { printCharacter(27); printCharacter('['); printString(sequence); flushConsole(); } /* private int currentCol, currentRow; private void getCurrentPosition() { // check for ByteArrayInputStream to disable for unit tests if (terminal.isANSISupported() && !(in instanceof ByteArrayInputStream)) { try { printANSISequence("[6n"); flushConsole(); StringBuffer b = new StringBuffer(8); // position is sent as [{ROW};{COLUMN}R int r; while((r = in.read()) > -1 && r != 'R') { if (r != 27 && r != '[') { b.append((char) r); } } String[] pos = b.toString().split(";"); currentRow = Integer.parseInt(pos[0]); currentCol = Integer.parseInt(pos[1]); } catch (Exception x) { // no luck currentRow = currentCol = -1; } } } */ /** * Whether or not to add new commands to the history buffer. */ public void setUseHistory(boolean useHistory) { this.useHistory = useHistory; } /** * Whether or not to add new commands to the history buffer. */ public boolean getUseHistory() { return useHistory; } /** * Whether to use pagination when the number of rows of candidates exceeds * the height of the temrinal. */ public void setUsePagination(boolean usePagination) { this.usePagination = usePagination; } /** * Whether to use pagination when the number of rows of candidates exceeds * the height of the temrinal. */ public boolean getUsePagination() { return this.usePagination; } public void printSearchStatus(String searchTerm, String match) throws IOException { int i = match.indexOf(searchTerm); printString("\r(reverse-i-search) `" + searchTerm + "': " + match + "\u001b[K"); // FIXME: our ANSI using back() does not work here printCharacters(BACKSPACE, match.length() - i); flushConsole(); } public void restoreLine() throws IOException { printString("\u001b[2K"); // ansi/vt100 for clear whole line redrawLine(); flushConsole(); } } jline-1.0.orig/src/src/main/java/jline/ANSIBuffer.java0000644000175000017500000004055411550705746022445 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; /** * A buffer that can contain ANSI text. * * @author Marc Prud'hommeaux */ public class ANSIBuffer { private boolean ansiEnabled = true; private final StringBuffer ansiBuffer = new StringBuffer(); private final StringBuffer plainBuffer = new StringBuffer(); public ANSIBuffer() { } public ANSIBuffer(final String str) { append(str); } public void setAnsiEnabled(final boolean ansi) { this.ansiEnabled = ansi; } public boolean getAnsiEnabled() { return this.ansiEnabled; } public String getAnsiBuffer() { return ansiBuffer.toString(); } public String getPlainBuffer() { return plainBuffer.toString(); } public String toString(final boolean ansi) { return ansi ? getAnsiBuffer() : getPlainBuffer(); } public String toString() { return toString(ansiEnabled); } public ANSIBuffer append(final String str) { ansiBuffer.append(str); plainBuffer.append(str); return this; } public ANSIBuffer attrib(final String str, final int code) { ansiBuffer.append(ANSICodes.attrib(code)).append(str) .append(ANSICodes.attrib(ANSICodes.OFF)); plainBuffer.append(str); return this; } public ANSIBuffer red(final String str) { return attrib(str, ANSICodes.FG_RED); } public ANSIBuffer blue(final String str) { return attrib(str, ANSICodes.FG_BLUE); } public ANSIBuffer green(final String str) { return attrib(str, ANSICodes.FG_GREEN); } public ANSIBuffer black(final String str) { return attrib(str, ANSICodes.FG_BLACK); } public ANSIBuffer yellow(final String str) { return attrib(str, ANSICodes.FG_YELLOW); } public ANSIBuffer magenta(final String str) { return attrib(str, ANSICodes.FG_MAGENTA); } public ANSIBuffer cyan(final String str) { return attrib(str, ANSICodes.FG_CYAN); } public ANSIBuffer bold(final String str) { return attrib(str, ANSICodes.BOLD); } public ANSIBuffer underscore(final String str) { return attrib(str, ANSICodes.UNDERSCORE); } public ANSIBuffer blink(final String str) { return attrib(str, ANSICodes.BLINK); } public ANSIBuffer reverse(final String str) { return attrib(str, ANSICodes.REVERSE); } public static class ANSICodes { static final int OFF = 0; static final int BOLD = 1; static final int UNDERSCORE = 4; static final int BLINK = 5; static final int REVERSE = 7; static final int CONCEALED = 8; static final int FG_BLACK = 30; static final int FG_RED = 31; static final int FG_GREEN = 32; static final int FG_YELLOW = 33; static final int FG_BLUE = 34; static final int FG_MAGENTA = 35; static final int FG_CYAN = 36; static final int FG_WHITE = 37; static final char ESC = 27; /** * Constructor is private since this is a utility class. */ private ANSICodes() { } /** * Sets the screen mode. The mode will be one of the following values: *
          * mode     description
          * ----------------------------------------
          *   0      40 x 148 x 25 monochrome (text)
          *   1      40 x 148 x 25 color (text)
          *   2      80 x 148 x 25 monochrome (text)
          *   3      80 x 148 x 25 color (text)
          *   4      320 x 148 x 200 4-color (graphics)
          *   5      320 x 148 x 200 monochrome (graphics)
          *   6      640 x 148 x 200 monochrome (graphics)
          *   7      Enables line wrapping
          *  13      320 x 148 x 200 color (graphics)
          *  14      640 x 148 x 200 color (16-color graphics)
          *  15      640 x 148 x 350 monochrome (2-color graphics)
          *  16      640 x 148 x 350 color (16-color graphics)
          *  17      640 x 148 x 480 monochrome (2-color graphics)
          *  18      640 x 148 x 480 color (16-color graphics)
          *  19      320 x 148 x 200 color (256-color graphics)
          * 
*/ public static String setmode(final int mode) { return ESC + "[=" + mode + "h"; } /** * Same as setmode () except for mode = 7, which disables line * wrapping (useful for writing the right-most column without * scrolling to the next line). */ public static String resetmode(final int mode) { return ESC + "[=" + mode + "l"; } /** * Clears the screen and moves the cursor to the home postition. */ public static String clrscr() { return ESC + "[2J"; } /** * Removes all characters from the current cursor position until * the end of the line. */ public static String clreol() { return ESC + "[K"; } /** * Moves the cursor n positions to the left. If n is greater or * equal to the current cursor column, the cursor is moved to the * first column. */ public static String left(final int n) { return ESC + "[" + n + "D"; } /** * Moves the cursor n positions to the right. If n plus the current * cursor column is greater than the rightmost column, the cursor * is moved to the rightmost column. */ public static String right(final int n) { return ESC + "[" + n + "C"; } /** * Moves the cursor n rows up without changing the current column. * If n is greater than or equal to the current row, the cursor is * placed in the first row. */ public static String up(final int n) { return ESC + "[" + n + "A"; } /** * Moves the cursor n rows down. If n plus the current row is greater * than the bottom row, the cursor is moved to the bottom row. */ public static String down(final int n) { return ESC + "[" + n + "B"; } /* * Moves the cursor to the given row and column. (1,1) represents * the upper left corner. The lower right corner of a usual DOS * screen is (25, 80). */ public static String gotoxy(final int row, final int column) { return ESC + "[" + row + ";" + column + "H"; } /** * Saves the current cursor position. */ public static String save() { return ESC + "[s"; } /** * Restores the saved cursor position. */ public static String restore() { return ESC + "[u"; } /** * Sets the character attribute. It will be * one of the following character attributes: * *
          * Text attributes
          *    0    All attributes off
          *    1    Bold on
          *    4    Underscore (on monochrome display adapter only)
          *    5    Blink on
          *    7    Reverse video on
          *    8    Concealed on
          *
          *   Foreground colors
          *    30    Black
          *    31    Red
          *    32    Green
          *    33    Yellow
          *    34    Blue
          *    35    Magenta
          *    36    Cyan
          *    37    White
          *
          *   Background colors
          *    40    Black
          *    41    Red
          *    42    Green
          *    43    Yellow
          *    44    Blue
          *    45    Magenta
          *    46    Cyan
          *    47    White
          * 
* * The attributes remain in effect until the next attribute command * is sent. */ public static String attrib(final int attr) { return ESC + "[" + attr + "m"; } /** * Sets the key with the given code to the given value. code must be * derived from the following table, value must * be any semicolon-separated * combination of String (enclosed in double quotes) and numeric values. * For example, to set F1 to the String "Hello F1", followed by a CRLF * sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10"). * Heres's the table of key values: *
          * Key                       Code      SHIFT+code  CTRL+code  ALT+code
          * ---------------------------------------------------------------
          * F1                        0;59      0;84        0;94       0;104
          * F2                        0;60      0;85        0;95       0;105
          * F3                        0;61      0;86        0;96       0;106
          * F4                        0;62      0;87        0;97       0;107
          * F5                        0;63      0;88        0;98       0;108
          * F6                        0;64      0;89        0;99       0;109
          * F7                        0;65      0;90        0;100      0;110
          * F8                        0;66      0;91        0;101      0;111
          * F9                        0;67      0;92        0;102      0;112
          * F10                       0;68      0;93        0;103      0;113
          * F11                       0;133     0;135       0;137      0;139
          * F12                       0;134     0;136       0;138      0;140
          * HOME (num keypad)         0;71      55          0;119      --
          * UP ARROW (num keypad)     0;72      56          (0;141)    --
          * PAGE UP (num keypad)      0;73      57          0;132      --
          * LEFT ARROW (num keypad)   0;75      52          0;115      --
          * RIGHT ARROW (num keypad)  0;77      54          0;116      --
          * END (num keypad)          0;79      49          0;117      --
          * DOWN ARROW (num keypad)   0;80      50          (0;145)    --
          * PAGE DOWN (num keypad)    0;81      51          0;118      --
          * INSERT (num keypad)       0;82      48          (0;146)    --
          * DELETE  (num keypad)      0;83      46          (0;147)    --
          * HOME                      (224;71)  (224;71)    (224;119)  (224;151)
          * UP ARROW                  (224;72)  (224;72)    (224;141)  (224;152)
          * PAGE UP                   (224;73)  (224;73)    (224;132)  (224;153)
          * LEFT ARROW                (224;75)  (224;75)    (224;115)  (224;155)
          * RIGHT ARROW               (224;77)  (224;77)    (224;116)  (224;157)
          * END                       (224;79)  (224;79)    (224;117)  (224;159)
          * DOWN ARROW                (224;80)  (224;80)    (224;145)  (224;154)
          * PAGE DOWN                 (224;81)  (224;81)    (224;118)  (224;161)
          * INSERT                    (224;82)  (224;82)    (224;146)  (224;162)
          * DELETE                    (224;83)  (224;83)    (224;147)  (224;163)
          * PRINT SCREEN              --        --          0;114      --
          * PAUSE/BREAK               --        --          0;0        --
          * BACKSPACE                 8         8           127        (0)
          * ENTER                     13        --          10         (0
          * TAB                       9         0;15        (0;148)    (0;165)
          * NULL                      0;3       --          --         --
          * A                         97        65          1          0;30
          * B                         98        66          2          0;48
          * C                         99        66          3          0;46
          * D                         100       68          4          0;32
          * E                         101       69          5          0;18
          * F                         102       70          6          0;33
          * G                         103       71          7          0;34
          * H                         104       72          8          0;35
          * I                         105       73          9          0;23
          * J                         106       74          10         0;36
          * K                         107       75          11         0;37
          * L                         108       76          12         0;38
          * M                         109       77          13         0;50
          * N                         110       78          14         0;49
          * O                         111       79          15         0;24
          * P                         112       80          16         0;25
          * Q                         113       81          17         0;16
          * R                         114       82          18         0;19
          * S                         115       83          19         0;31
          * T                         116       84          20         0;20
          * U                         117       85          21         0;22
          * V                         118       86          22         0;47
          * W                         119       87          23         0;17
          * X                         120       88          24         0;45
          * Y                         121       89          25         0;21
          * Z                         122       90          26         0;44
          * 1                         49        33          --         0;120
          * 2                         50        64          0          0;121
          * 3                         51        35          --         0;122
          * 4                         52        36          --         0;123
          * 5                         53        37          --         0;124
          * 6                         54        94          30         0;125
          * 7                         55        38          --         0;126
          * 8                         56        42          --         0;126
          * 9                         57        40          --         0;127
          * 0                         48        41          --         0;129
          * -                         45        95          31         0;130
          * =                         61        43          ---        0;131
          * [                         91        123         27         0;26
          * ]                         93        125         29         0;27
          *                           92        124         28         0;43
          * ;                         59        58          --         0;39
          * '                         39        34          --         0;40
          * ,                         44        60          --         0;51
          * .                         46        62          --         0;52
          * /                         47        63          --         0;53
          * `                         96        126         --         (0;41)
          * ENTER (keypad)            13        --          10         (0;166)
          * / (keypad)                47        47          (0;142)    (0;74)
          * * (keypad)                42        (0;144)     (0;78)     --
          * - (keypad)                45        45          (0;149)    (0;164)
          * + (keypad)                43        43          (0;150)    (0;55)
          * 5 (keypad)                (0;76)    53          (0;143)    --
          */
        public static String setkey(final String code, final String value) {
            return ESC + "[" + code + ";" + value + "p";
        }
    }

    public static void main(final String[] args) throws Exception {
        // sequence, one can use: ANSI.setkey ("0;59", "\"Hello F1\";13;10").
        BufferedReader reader =
            new BufferedReader(new InputStreamReader(System.in));
        System.out.print(ANSICodes.setkey("97", "97;98;99;13")
                         + ANSICodes.attrib(ANSICodes.OFF));
        System.out.flush();

        String line;

        while ((line = reader.readLine()) != null) {
            System.out.println("GOT: " + line);
        }
    }
}
jline-1.0.orig/src/src/main/java/jline/Completor.java0000644000175000017500000000205611550705746022520 0ustar  twernertwerner/*
 * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved.
 *
 * This software is distributable under the BSD license. See the terms of the
 * BSD license in the documentation provided with this software.
 */
package jline;

import java.util.*;

/**
 *  A Completor is the mechanism by which tab-completion candidates
 *  will be resolved.
 *
 *  @author  Marc Prud'hommeaux
 */
public interface Completor {
    /**
     *  Populates candidates with a list of possible
     *  completions for the buffer. The candidates
     *  list will not be sorted before being displayed to the
     *  user: thus, the complete method should sort the
     *  {@link List} before returning.
     *
     *
     *  @param  buffer     the buffer
     *  @param  candidates the {@link List} of candidates to populate
     *  @return            the index of the buffer for which
     *                     the completion will be relative
     */
    int complete(String buffer, int cursor, List candidates);
}
jline-1.0.orig/src/src/main/java/jline/FileNameCompletor.java0000644000175000017500000001054711550705746024125 0ustar  twernertwerner/*
 * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved.
 *
 * This software is distributable under the BSD license. See the terms of the
 * BSD license in the documentation provided with this software.
 */
package jline;

import java.io.*;
import java.util.*;

/**
 *  A file name completor takes the buffer and issues a list of
 *  potential completions.
 *
 *  

* This completor tries to behave as similar as possible to * bash's file name completion (using GNU readline) * with the following exceptions: * *

    *
  • Candidates that are directories will end with "/"
  • *
  • Wildcard regular expressions are not evaluated or replaced
  • *
  • The "~" character can be used to represent the user's home, * but it cannot complete to other users' homes, since java does * not provide any way of determining that easily
  • *
* *

TODO

*
    *
  • Handle files with spaces in them
  • *
  • Have an option for file type color highlighting
  • *
* * @author Marc Prud'hommeaux */ public class FileNameCompletor implements Completor { public int complete(final String buf, final int cursor, final List candidates) { String buffer = (buf == null) ? "" : buf; String translated = buffer; // special character: ~ maps to the user's home directory if (translated.startsWith("~" + File.separator)) { translated = System.getProperty("user.home") + translated.substring(1); } else if (translated.startsWith("~")) { translated = new File(System.getProperty("user.home")).getParentFile() .getAbsolutePath(); } else if (!(translated.startsWith(File.separator))) { translated = new File("").getAbsolutePath() + File.separator + translated; } File f = new File(translated); final File dir; if (translated.endsWith(File.separator)) { dir = f; } else { dir = f.getParentFile(); } final File[] entries = (dir == null) ? new File[0] : dir.listFiles(); try { return matchFiles(buffer, translated, entries, candidates); } finally { // we want to output a sorted list of files sortFileNames(candidates); } } protected void sortFileNames(final List fileNames) { Collections.sort(fileNames); } /** * Match the specified buffer to the array of entries * and enter the matches into the list of candidates. This method * can be overridden in a subclass that wants to do more * sophisticated file name completion. * * @param buffer the untranslated buffer * @param translated the buffer with common characters replaced * @param entries the list of files to match * @param candidates the list of candidates to populate * * @return the offset of the match */ public int matchFiles(String buffer, String translated, File[] entries, List candidates) { if (entries == null) { return -1; } int matches = 0; // first pass: just count the matches for (int i = 0; i < entries.length; i++) { if (entries[i].getAbsolutePath().startsWith(translated)) { matches++; } } // green - executable // blue - directory // red - compressed // cyan - symlink for (int i = 0; i < entries.length; i++) { if (entries[i].getAbsolutePath().startsWith(translated)) { String name = entries[i].getName() + (((matches == 1) && entries[i].isDirectory()) ? File.separator : " "); /* if (entries [i].isDirectory ()) { name = new ANSIBuffer ().blue (name).toString (); } */ candidates.add(name); } } final int index = buffer.lastIndexOf(File.separator); return index + File.separator.length(); } } jline-1.0.orig/src/src/main/java/jline/History.java0000644000175000017500000001647411550705746022226 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; import java.util.*; /** * A command history buffer. * * @author Marc Prud'hommeaux */ public class History { private List history = new ArrayList(); private PrintWriter output = null; private int maxSize = 500; private int currentIndex = 0; /** * Construstor: initialize a blank history. */ public History() { } /** * Construstor: initialize History object the the specified {@link File} for * storage. */ public History(final File historyFile) throws IOException { setHistoryFile(historyFile); } public void setHistoryFile(final File historyFile) throws IOException { if (historyFile.isFile()) { load(new FileInputStream(historyFile)); } setOutput(new PrintWriter(new FileWriter(historyFile), true)); flushBuffer(); } /** * Load the history buffer from the specified InputStream. */ public void load(final InputStream in) throws IOException { load(new InputStreamReader(in)); } /** * Load the history buffer from the specified Reader. */ public void load(final Reader reader) throws IOException { BufferedReader breader = new BufferedReader(reader); List lines = new ArrayList(); String line; while ((line = breader.readLine()) != null) { lines.add(line); } for (Iterator i = lines.iterator(); i.hasNext();) { addToHistory((String) i.next()); } } public int size() { return history.size(); } /** * Clear the history buffer */ public void clear() { history.clear(); currentIndex = 0; } /** * Add the specified buffer to the end of the history. The pointer is set to * the end of the history buffer. */ public void addToHistory(final String buffer) { // don't append duplicates to the end of the buffer if ((history.size() != 0) && buffer.equals(history.get(history.size() - 1))) { return; } history.add(buffer); while (history.size() > getMaxSize()) { history.remove(0); } currentIndex = history.size(); if (getOutput() != null) { getOutput().println(buffer); getOutput().flush(); } } /** * Flush the entire history buffer to the output PrintWriter. */ public void flushBuffer() throws IOException { if (getOutput() != null) { for (Iterator i = history.iterator(); i.hasNext(); getOutput().println((String) i.next())) { ; } getOutput().flush(); } } /** * This moves the history to the last entry. This entry is one position * before the moveToEnd() position. * * @return Returns false if there were no history entries or the history * index was already at the last entry. */ public boolean moveToLastEntry() { int lastEntry = history.size() - 1; if (lastEntry >= 0 && lastEntry != currentIndex) { currentIndex = history.size() - 1; return true; } return false; } /** * Move to the end of the history buffer. This will be a blank entry, after * all of the other entries. */ public void moveToEnd() { currentIndex = history.size(); } /** * Set the maximum size that the history buffer will store. */ public void setMaxSize(final int maxSize) { this.maxSize = maxSize; } /** * Get the maximum size that the history buffer will store. */ public int getMaxSize() { return this.maxSize; } /** * The output to which all history elements will be written (or null of * history is not saved to a buffer). */ public void setOutput(final PrintWriter output) { this.output = output; } /** * Returns the PrintWriter that is used to store history elements. */ public PrintWriter getOutput() { return this.output; } /** * Returns the current history index. */ public int getCurrentIndex() { return this.currentIndex; } /** * Return the content of the current buffer. */ public String current() { if (currentIndex >= history.size()) { return ""; } return (String) history.get(currentIndex); } /** * Move the pointer to the previous element in the buffer. * * @return true if we successfully went to the previous element */ public boolean previous() { if (currentIndex <= 0) { return false; } currentIndex--; return true; } /** * Move the pointer to the next element in the buffer. * * @return true if we successfully went to the next element */ public boolean next() { if (currentIndex >= history.size()) { return false; } currentIndex++; return true; } /** * Returns an immutable list of the history buffer. */ public List getHistoryList() { return Collections.unmodifiableList(history); } /** * Returns the standard {@link AbstractCollection#toString} representation * of the history list. */ public String toString() { return history.toString(); } /** * Moves the history index to the first entry. * * @return Return false if there are no entries in the history or if the * history is already at the beginning. */ public boolean moveToFirstEntry() { if (history.size() > 0 && currentIndex != 0) { currentIndex = 0; return true; } return false; } /** * Search backward in history from a given position. * * @param searchTerm substring to search for. * @param startIndex the index from which on to search * @return index where this substring has been found, or -1 else. */ public int searchBackwards(String searchTerm, int startIndex) { for (int i = startIndex - 1; i >= 0; i--) { if (i >= size()) continue; if (getHistory(i).indexOf(searchTerm) != -1) { return i; } } return -1; } /** * Search backwards in history from the current position. * * @param searchTerm substring to search for. * @return index where the substring has been found, or -1 else. */ public int searchBackwards(String s) { return searchBackwards(s, getCurrentIndex()); } /** * Get the history string for the given index. * * @param index * @return */ public String getHistory(int index) { return (String) history.get(index); } /** * Set current index to given number. * * @param index */ public void setCurrentIndex(int index) { if (index >= 0 && index < history.size()) currentIndex = index; } } jline-1.0.orig/src/src/main/java/jline/package.html0000644000175000017500000000032611550705746022170 0ustar twernertwerner

The core JLine API. The central class is jline.ConsoleReader}, which is a reader for obtaining input from an arbitrary InputStream (usually System.in).

jline-1.0.orig/src/src/main/java/jline/CandidateCycleCompletionHandler.java0000644000175000017500000000200511550705746026732 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; import java.util.*; /** *

* A {@link CompletionHandler} that deals with multiple distinct completions * by cycling through each one every time tab is pressed. This * mimics the behavior of the * editline * library. *

*

This class is currently a stub; it does nothing

* @author Marc Prud'hommeaux */ public class CandidateCycleCompletionHandler implements CompletionHandler { public boolean complete(final ConsoleReader reader, final List candidates, final int position) throws IOException { throw new IllegalStateException("CandidateCycleCompletionHandler unimplemented"); } } jline-1.0.orig/src/src/main/java/jline/ArgumentCompletor.java0000644000175000017500000003525511550705746024232 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.util.*; /** * A {@link Completor} implementation that invokes a child completor * using the appropriate separator argument. This * can be used instead of the individual completors having to * know about argument parsing semantics. *

* Example 1: Any argument of the command line can * use file completion. *

*

 *        consoleReader.addCompletor (new ArgumentCompletor (
 *                new {@link FileNameCompletor} ()))
 *  
*

* Example 2: The first argument of the command line * can be completed with any of "foo", "bar", or "baz", and remaining * arguments can be completed with a file name. *

*

 *        consoleReader.addCompletor (new ArgumentCompletor (
 *                new {@link SimpleCompletor} (new String [] { "foo", "bar", "baz"})));
 *        consoleReader.addCompletor (new ArgumentCompletor (
 *                new {@link FileNameCompletor} ()));
 *  
* *

* When the argument index is past the last embedded completors, the last * completors is always used. To disable this behavior, have the last * completor be a {@link NullCompletor}. For example: *

* *
 *        consoleReader.addCompletor (new ArgumentCompletor (
 *                new {@link SimpleCompletor} (new String [] { "foo", "bar", "baz"}),
 *                new {@link SimpleCompletor} (new String [] { "xxx", "yyy", "xxx"}),
 *                new {@link NullCompletor}
 *                ));
 *        
*

* TODO: handle argument quoting and escape characters *

* * @author Marc Prud'hommeaux */ public class ArgumentCompletor implements Completor { final Completor[] completors; final ArgumentDelimiter delim; boolean strict = true; /** * Constuctor: create a new completor with the default * argument separator of " ". * * @param completor the embedded completor */ public ArgumentCompletor(final Completor completor) { this(new Completor[] { completor }); } /** * Constuctor: create a new completor with the default * argument separator of " ". * * @param completors the List of completors to use */ public ArgumentCompletor(final List completors) { this((Completor[]) completors.toArray(new Completor[completors.size()])); } /** * Constuctor: create a new completor with the default * argument separator of " ". * * @param completors the embedded argument completors */ public ArgumentCompletor(final Completor[] completors) { this(completors, new WhitespaceArgumentDelimiter()); } /** * Constuctor: create a new completor with the specified * argument delimiter. * * @param completor the embedded completor * @param delim the delimiter for parsing arguments */ public ArgumentCompletor(final Completor completor, final ArgumentDelimiter delim) { this(new Completor[] { completor }, delim); } /** * Constuctor: create a new completor with the specified * argument delimiter. * * @param completors the embedded completors * @param delim the delimiter for parsing arguments */ public ArgumentCompletor(final Completor[] completors, final ArgumentDelimiter delim) { this.completors = completors; this.delim = delim; } /** * If true, a completion at argument index N will only succeed * if all the completions from 0-(N-1) also succeed. */ public void setStrict(final boolean strict) { this.strict = strict; } /** * Returns whether a completion at argument index N will succees * if all the completions from arguments 0-(N-1) also succeed. */ public boolean getStrict() { return this.strict; } public int complete(final String buffer, final int cursor, final List candidates) { ArgumentList list = delim.delimit(buffer, cursor); int argpos = list.getArgumentPosition(); int argIndex = list.getCursorArgumentIndex(); if (argIndex < 0) { return -1; } final Completor comp; // if we are beyond the end of the completors, just use the last one if (argIndex >= completors.length) { comp = completors[completors.length - 1]; } else { comp = completors[argIndex]; } // ensure that all the previous completors are successful before // allowing this completor to pass (only if strict is true). for (int i = 0; getStrict() && (i < argIndex); i++) { Completor sub = completors[(i >= completors.length) ? (completors.length - 1) : i]; String[] args = list.getArguments(); String arg = ((args == null) || (i >= args.length)) ? "" : args[i]; List subCandidates = new LinkedList(); if (sub.complete(arg, arg.length(), subCandidates) == -1) { return -1; } if (subCandidates.size() == 0) { return -1; } } int ret = comp.complete(list.getCursorArgument(), argpos, candidates); if (ret == -1) { return -1; } int pos = ret + (list.getBufferPosition() - argpos); /** * Special case: when completing in the middle of a line, and the * area under the cursor is a delimiter, then trim any delimiters * from the candidates, since we do not need to have an extra * delimiter. * * E.g., if we have a completion for "foo", and we * enter "f bar" into the buffer, and move to after the "f" * and hit TAB, we want "foo bar" instead of "foo bar". */ if ((cursor != buffer.length()) && delim.isDelimiter(buffer, cursor)) { for (int i = 0; i < candidates.size(); i++) { String val = candidates.get(i).toString(); while ((val.length() > 0) && delim.isDelimiter(val, val.length() - 1)) { val = val.substring(0, val.length() - 1); } candidates.set(i, val); } } ConsoleReader.debug("Completing " + buffer + "(pos=" + cursor + ") " + "with: " + candidates + ": offset=" + pos); return pos; } /** * The {@link ArgumentCompletor.ArgumentDelimiter} allows custom * breaking up of a {@link String} into individual arguments in * order to dispatch the arguments to the nested {@link Completor}. * * @author Marc Prud'hommeaux */ public static interface ArgumentDelimiter { /** * Break the specified buffer into individual tokens * that can be completed on their own. * * @param buffer the buffer to split * @param argumentPosition the current position of the * cursor in the buffer * @return the tokens */ ArgumentList delimit(String buffer, int argumentPosition); /** * Returns true if the specified character is a whitespace * parameter. * * @param buffer the complete command buffer * @param pos the index of the character in the buffer * @return true if the character should be a delimiter */ boolean isDelimiter(String buffer, int pos); } /** * Abstract implementation of a delimiter that uses the * {@link #isDelimiter} method to determine if a particular * character should be used as a delimiter. * * @author Marc Prud'hommeaux */ public abstract static class AbstractArgumentDelimiter implements ArgumentDelimiter { private char[] quoteChars = new char[] { '\'', '"' }; private char[] escapeChars = new char[] { '\\' }; public void setQuoteChars(final char[] quoteChars) { this.quoteChars = quoteChars; } public char[] getQuoteChars() { return this.quoteChars; } public void setEscapeChars(final char[] escapeChars) { this.escapeChars = escapeChars; } public char[] getEscapeChars() { return this.escapeChars; } public ArgumentList delimit(final String buffer, final int cursor) { List args = new LinkedList(); StringBuffer arg = new StringBuffer(); int argpos = -1; int bindex = -1; for (int i = 0; (buffer != null) && (i <= buffer.length()); i++) { // once we reach the cursor, set the // position of the selected index if (i == cursor) { bindex = args.size(); // the position in the current argument is just the // length of the current argument argpos = arg.length(); } if ((i == buffer.length()) || isDelimiter(buffer, i)) { if (arg.length() > 0) { args.add(arg.toString()); arg.setLength(0); // reset the arg } } else { arg.append(buffer.charAt(i)); } } return new ArgumentList((String[]) args. toArray(new String[args.size()]), bindex, argpos, cursor); } /** * Returns true if the specified character is a whitespace * parameter. Check to ensure that the character is not * escaped by any of * {@link #getQuoteChars}, and is not escaped by ant of the * {@link #getEscapeChars}, and returns true from * {@link #isDelimiterChar}. * * @param buffer the complete command buffer * @param pos the index of the character in the buffer * @return true if the character should be a delimiter */ public boolean isDelimiter(final String buffer, final int pos) { if (isQuoted(buffer, pos)) { return false; } if (isEscaped(buffer, pos)) { return false; } return isDelimiterChar(buffer, pos); } public boolean isQuoted(final String buffer, final int pos) { return false; } public boolean isEscaped(final String buffer, final int pos) { if (pos <= 0) { return false; } for (int i = 0; (escapeChars != null) && (i < escapeChars.length); i++) { if (buffer.charAt(pos) == escapeChars[i]) { return !isEscaped(buffer, pos - 1); // escape escape } } return false; } /** * Returns true if the character at the specified position * if a delimiter. This method will only be called if the * character is not enclosed in any of the * {@link #getQuoteChars}, and is not escaped by ant of the * {@link #getEscapeChars}. To perform escaping manually, * override {@link #isDelimiter} instead. */ public abstract boolean isDelimiterChar(String buffer, int pos); } /** * {@link ArgumentCompletor.ArgumentDelimiter} * implementation that counts all * whitespace (as reported by {@link Character#isWhitespace}) * as being a delimiter. * * @author Marc Prud'hommeaux */ public static class WhitespaceArgumentDelimiter extends AbstractArgumentDelimiter { /** * The character is a delimiter if it is whitespace, and the * preceeding character is not an escape character. */ public boolean isDelimiterChar(String buffer, int pos) { return Character.isWhitespace(buffer.charAt(pos)); } } /** * The result of a delimited buffer. * * @author Marc Prud'hommeaux */ public static class ArgumentList { private String[] arguments; private int cursorArgumentIndex; private int argumentPosition; private int bufferPosition; /** * @param arguments the array of tokens * @param cursorArgumentIndex the token index of the cursor * @param argumentPosition the position of the cursor in the * current token * @param bufferPosition the position of the cursor in * the whole buffer */ public ArgumentList(String[] arguments, int cursorArgumentIndex, int argumentPosition, int bufferPosition) { this.arguments = arguments; this.cursorArgumentIndex = cursorArgumentIndex; this.argumentPosition = argumentPosition; this.bufferPosition = bufferPosition; } public void setCursorArgumentIndex(int cursorArgumentIndex) { this.cursorArgumentIndex = cursorArgumentIndex; } public int getCursorArgumentIndex() { return this.cursorArgumentIndex; } public String getCursorArgument() { if ((cursorArgumentIndex < 0) || (cursorArgumentIndex >= arguments.length)) { return null; } return arguments[cursorArgumentIndex]; } public void setArgumentPosition(int argumentPosition) { this.argumentPosition = argumentPosition; } public int getArgumentPosition() { return this.argumentPosition; } public void setArguments(String[] arguments) { this.arguments = arguments; } public String[] getArguments() { return this.arguments; } public void setBufferPosition(int bufferPosition) { this.bufferPosition = bufferPosition; } public int getBufferPosition() { return this.bufferPosition; } } } jline-1.0.orig/src/src/main/java/jline/MultiCompletor.java0000644000175000017500000000450011550705746023527 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.util.*; /** *

* A completor that contains multiple embedded completors. This differs * from the {@link ArgumentCompletor}, in that the nested completors * are dispatched individually, rather than delimited by arguments. *

* * @author Marc Prud'hommeaux */ public class MultiCompletor implements Completor { Completor[] completors = new Completor[0]; /** * Construct a MultiCompletor with no embedded completors. */ public MultiCompletor() { this(new Completor[0]); } /** * Construct a MultiCompletor with the specified list of * {@link Completor} instances. */ public MultiCompletor(final List completors) { this((Completor[]) completors.toArray(new Completor[completors.size()])); } /** * Construct a MultiCompletor with the specified * {@link Completor} instances. */ public MultiCompletor(final Completor[] completors) { this.completors = completors; } public int complete(final String buffer, final int pos, final List cand) { int[] positions = new int[completors.length]; List[] copies = new List[completors.length]; for (int i = 0; i < completors.length; i++) { // clone and save the candidate list copies[i] = new LinkedList(cand); positions[i] = completors[i].complete(buffer, pos, copies[i]); } int maxposition = -1; for (int i = 0; i < positions.length; i++) { maxposition = Math.max(maxposition, positions[i]); } // now we have the max cursor value: build up all the // candidate lists that have the same cursor value for (int i = 0; i < copies.length; i++) { if (positions[i] == maxposition) { cand.addAll(copies[i]); } } return maxposition; } public void setCompletors(final Completor[] completors) { this.completors = completors; } public Completor[] getCompletors() { return this.completors; } } jline-1.0.orig/src/src/main/java/jline/SimpleCompletor.java0000644000175000017500000001245611550705746023677 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; import java.util.*; /** *

* A simple {@link Completor} implementation that handles a pre-defined * list of completion words. *

* *

* Example usage: *

*
 *  myConsoleReader.addCompletor (new SimpleCompletor (new String [] { "now", "yesterday", "tomorrow" }));
 *  
* * @author Marc Prud'hommeaux */ public class SimpleCompletor implements Completor, Cloneable { /** * The list of candidates that will be completed. */ SortedSet candidates; /** * A delimiter to use to qualify completions. */ String delimiter; final SimpleCompletorFilter filter; /** * Create a new SimpleCompletor with a single possible completion * values. */ public SimpleCompletor(final String candidateString) { this(new String[] { candidateString }); } /** * Create a new SimpleCompletor with a list of possible completion * values. */ public SimpleCompletor(final String[] candidateStrings) { this(candidateStrings, null); } public SimpleCompletor(final String[] strings, final SimpleCompletorFilter filter) { this.filter = filter; setCandidateStrings(strings); } /** * Complete candidates using the contents of the specified Reader. */ public SimpleCompletor(final Reader reader) throws IOException { this(getStrings(reader)); } /** * Complete candidates using the whitespearated values in * read from the specified Reader. */ public SimpleCompletor(final InputStream in) throws IOException { this(getStrings(new InputStreamReader(in))); } private static String[] getStrings(final Reader in) throws IOException { final Reader reader = (in instanceof BufferedReader) ? in : new BufferedReader(in); List words = new LinkedList(); String line; while ((line = ((BufferedReader) reader).readLine()) != null) { for (StringTokenizer tok = new StringTokenizer(line); tok.hasMoreTokens(); words.add(tok.nextToken())) { ; } } return (String[]) words.toArray(new String[words.size()]); } public int complete(final String buffer, final int cursor, final List clist) { String start = (buffer == null) ? "" : buffer; SortedSet matches = candidates.tailSet(start); for (Iterator i = matches.iterator(); i.hasNext();) { String can = (String) i.next(); if (!(can.startsWith(start))) { break; } if (delimiter != null) { int index = can.indexOf(delimiter, cursor); if (index != -1) { can = can.substring(0, index + 1); } } clist.add(can); } if (clist.size() == 1) { clist.set(0, ((String) clist.get(0)) + " "); } // the index of the completion is always from the beginning of // the buffer. return (clist.size() == 0) ? (-1) : 0; } public void setDelimiter(final String delimiter) { this.delimiter = delimiter; } public String getDelimiter() { return this.delimiter; } public void setCandidates(final SortedSet candidates) { if (filter != null) { TreeSet filtered = new TreeSet(); for (Iterator i = candidates.iterator(); i.hasNext();) { String element = (String) i.next(); element = filter.filter(element); if (element != null) { filtered.add(element); } } this.candidates = filtered; } else { this.candidates = candidates; } } public SortedSet getCandidates() { return Collections.unmodifiableSortedSet(this.candidates); } public void setCandidateStrings(final String[] strings) { setCandidates(new TreeSet(Arrays.asList(strings))); } public void addCandidateString(final String candidateString) { final String string = (filter == null) ? candidateString : filter.filter(candidateString); if (string != null) { candidates.add(string); } } public Object clone() throws CloneNotSupportedException { return super.clone(); } /** * Filter for elements in the completor. * * @author Marc Prud'hommeaux */ public static interface SimpleCompletorFilter { /** * Filter the specified String. To not filter it, return the * same String as the parameter. To exclude it, return null. */ public String filter(String element); } public static class NoOpFilter implements SimpleCompletorFilter { public String filter(final String element) { return element; } } } jline-1.0.orig/src/src/main/java/jline/UnsupportedTerminal.java0000644000175000017500000000467111550705746024605 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.IOException; /** * A no-op unsupported terminal. * * @author Marc Prud'hommeaux */ public class UnsupportedTerminal extends Terminal { private Thread maskThread = null; public void initializeTerminal() { // nothing we need to do (or can do) for windows. } public boolean getEcho() { return true; } public boolean isEchoEnabled() { return true; } public void enableEcho() { } public void disableEcho() { } /** * Always returng 80, since we can't access this info on Windows. */ public int getTerminalWidth() { return 80; } /** * Always returng 24, since we can't access this info on Windows. */ public int getTerminalHeight() { return 80; } public boolean isSupported() { return false; } public void beforeReadLine(final ConsoleReader reader, final String prompt, final Character mask) { if ((mask != null) && (maskThread == null)) { final String fullPrompt = "\r" + prompt + " " + " " + " " + "\r" + prompt; maskThread = new Thread("JLine Mask Thread") { public void run() { while (!interrupted()) { try { reader.out.write(fullPrompt); reader.out.flush(); sleep(3); } catch (IOException ioe) { return; } catch (InterruptedException ie) { return; } } } }; maskThread.setPriority(Thread.MAX_PRIORITY); maskThread.setDaemon(true); maskThread.start(); } } public void afterReadLine(final ConsoleReader reader, final String prompt, final Character mask) { if ((maskThread != null) && maskThread.isAlive()) { maskThread.interrupt(); } maskThread = null; } } jline-1.0.orig/src/src/main/java/jline/ClassNameCompletor.java0000644000175000017500000001103211550705746024301 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; import java.net.*; import java.util.*; import java.util.jar.JarEntry; import java.util.jar.JarFile; /** * A Completor implementation that completes java class names. By default, * it scans the java class path to locate all the classes. * * @author Marc Prud'hommeaux */ public class ClassNameCompletor extends SimpleCompletor { /** * Complete candidates using all the classes available in the * java CLASSPATH. */ public ClassNameCompletor() throws IOException { this(null); } public ClassNameCompletor(final SimpleCompletorFilter filter) throws IOException { super(getClassNames(), filter); setDelimiter("."); } public static String[] getClassNames() throws IOException { Set urls = new HashSet(); for (ClassLoader loader = ClassNameCompletor.class .getClassLoader(); loader != null; loader = loader.getParent()) { if (!(loader instanceof URLClassLoader)) { continue; } urls.addAll(Arrays.asList(((URLClassLoader) loader).getURLs())); } // Now add the URL that holds java.lang.String. This is because // some JVMs do not report the core classes jar in the list of // class loaders. Class[] systemClasses = new Class[] { String.class, javax.swing.JFrame.class }; for (int i = 0; i < systemClasses.length; i++) { URL classURL = systemClasses[i].getResource("/" + systemClasses[i].getName() .replace('.', '/') + ".class"); if (classURL != null) { URLConnection uc = (URLConnection) classURL.openConnection(); if (uc instanceof JarURLConnection) { urls.add(((JarURLConnection) uc).getJarFileURL()); } } } Set classes = new HashSet(); for (Iterator i = urls.iterator(); i.hasNext();) { URL url = (URL) i.next(); File file = new File(url.getFile()); if (file.isDirectory()) { Set files = getClassFiles(file.getAbsolutePath(), new HashSet(), file, new int[] { 200 }); classes.addAll(files); continue; } if ((file == null) || !file.isFile()) // TODO: handle directories { continue; } if (!file.toString().endsWith (".jar")) continue; JarFile jf = new JarFile(file); for (Enumeration e = jf.entries(); e.hasMoreElements();) { JarEntry entry = (JarEntry) e.nextElement(); if (entry == null) { continue; } String name = entry.getName(); if (!name.endsWith(".class")) // only use class files { continue; } classes.add(name); } } // now filter classes by changing "/" to "." and trimming the // trailing ".class" Set classNames = new TreeSet(); for (Iterator i = classes.iterator(); i.hasNext();) { String name = (String) i.next(); classNames.add(name.replace('/', '.'). substring(0, name.length() - 6)); } return (String[]) classNames.toArray(new String[classNames.size()]); } private static Set getClassFiles(String root, Set holder, File directory, int[] maxDirectories) { // we have passed the maximum number of directories to scan if (maxDirectories[0]-- < 0) { return holder; } File[] files = directory.listFiles(); for (int i = 0; (files != null) && (i < files.length); i++) { String name = files[i].getAbsolutePath(); if (!(name.startsWith(root))) { continue; } else if (files[i].isDirectory()) { getClassFiles(root, holder, files[i], maxDirectories); } else if (files[i].getName().endsWith(".class")) { holder.add(files[i].getAbsolutePath(). substring(root.length() + 1)); } } return holder; } } jline-1.0.orig/src/src/main/java/jline/ConsoleOperations.java0000644000175000017500000001343011550705746024220 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.awt.event.KeyEvent; /** * Symbolic constants for Console operations and virtual key bindings. * @see KeyEvent * * @author Marc Prud'hommeaux */ public interface ConsoleOperations { final String CR = System.getProperty("line.separator"); final char BACKSPACE = '\b'; final char RESET_LINE = '\r'; final char KEYBOARD_BELL = '\07'; final char CTRL_A = 1; final char CTRL_B = 2; final char CTRL_C = 3; final char CTRL_D = 4; final char CTRL_E = 5; final char CTRL_F = 6; final char CTRL_G = 7; final static char CTRL_K = 11; final static char CTRL_L = 12; final char CTRL_N = 14; final char CTRL_P = 16; final static char CTRL_OB = 27; final static char DELETE = 127; final static char CTRL_QM = 127; /** * Logical constants for key operations. */ /** * Unknown operation. */ final short UNKNOWN = -99; /** * Operation that moves to the beginning of the buffer. */ final short MOVE_TO_BEG = -1; /** * Operation that moves to the end of the buffer. */ final short MOVE_TO_END = -3; /** * Operation that moved to the previous character in the buffer. */ final short PREV_CHAR = -4; /** * Operation that issues a newline. */ final short NEWLINE = -6; /** * Operation that deletes the buffer from the current character to the end. */ final short KILL_LINE = -7; /** * Operation that clears the screen. */ final short CLEAR_SCREEN = -8; /** * Operation that sets the buffer to the next history item. */ final short NEXT_HISTORY = -9; /** * Operation that sets the buffer to the previous history item. */ final short PREV_HISTORY = -11; /** * Operation that redisplays the current buffer. */ final short REDISPLAY = -13; /** * Operation that deletes the buffer from the cursor to the beginning. */ final short KILL_LINE_PREV = -15; /** * Operation that deletes the previous word in the buffer. */ final short DELETE_PREV_WORD = -16; /** * Operation that moves to the next character in the buffer. */ final short NEXT_CHAR = -19; /** * Operation that moves to the previous character in the buffer. */ final short REPEAT_PREV_CHAR = -20; /** * Operation that searches backwards in the command history. */ final short SEARCH_PREV = -21; /** * Operation that repeats the character. */ final short REPEAT_NEXT_CHAR = -24; /** * Operation that searches forward in the command history. */ final short SEARCH_NEXT = -25; /** * Operation that moved to the previous whitespace. */ final short PREV_SPACE_WORD = -27; /** * Operation that moved to the end of the current word. */ final short TO_END_WORD = -29; /** * Operation that */ final short REPEAT_SEARCH_PREV = -34; /** * Operation that */ final short PASTE_PREV = -36; /** * Operation that */ final short REPLACE_MODE = -37; /** * Operation that */ final short SUBSTITUTE_LINE = -38; /** * Operation that */ final short TO_PREV_CHAR = -39; /** * Operation that */ final short NEXT_SPACE_WORD = -40; /** * Operation that */ final short DELETE_PREV_CHAR = -41; /** * Operation that */ final short ADD = -42; /** * Operation that */ final short PREV_WORD = -43; /** * Operation that */ final short CHANGE_META = -44; /** * Operation that */ final short DELETE_META = -45; /** * Operation that */ final short END_WORD = -46; /** * Operation that toggles insert/overtype */ final short INSERT = -48; /** * Operation that */ final short REPEAT_SEARCH_NEXT = -49; /** * Operation that */ final short PASTE_NEXT = -50; /** * Operation that */ final short REPLACE_CHAR = -51; /** * Operation that */ final short SUBSTITUTE_CHAR = -52; /** * Operation that */ final short TO_NEXT_CHAR = -53; /** * Operation that undoes the previous operation. */ final short UNDO = -54; /** * Operation that moved to the next word. */ final short NEXT_WORD = -55; /** * Operation that deletes the previous character. */ final short DELETE_NEXT_CHAR = -56; /** * Operation that toggles between uppercase and lowercase. */ final short CHANGE_CASE = -57; /** * Operation that performs completion operation on the current word. */ final short COMPLETE = -58; /** * Operation that exits the command prompt. */ final short EXIT = -59; /** * Operation that pastes the contents of the clipboard into the line */ final short PASTE = -60; /** * Operation that moves the current History to the beginning. */ final static short START_OF_HISTORY = -61; /** * Operation that moves the current History to the end. */ final static short END_OF_HISTORY = -62; /** * Operation that clears whatever text is on the current line. */ final static short CLEAR_LINE = -63; /** * Operation that aborts the current command (like searching) */ final static short ABORT = -64; } jline-1.0.orig/src/src/main/java/jline/NullCompletor.java0000644000175000017500000000130211550705746023344 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.util.*; /** *

* A completor that does nothing. Useful as the last item in an * {@link ArgumentCompletor}. *

* * @author Marc Prud'hommeaux */ public class NullCompletor implements Completor { /** * Returns -1 always, indicating that the the buffer is never * handled. */ public int complete(final String buffer, int cursor, List candidates) { return -1; } } jline-1.0.orig/src/src/main/java/jline/UnixTerminal.java0000644000175000017500000003225111550705746023173 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; import java.util.*; /** *

* Terminal that is used for unix platforms. Terminal initialization * is handled by issuing the stty command against the * /dev/tty file to disable character echoing and enable * character input. All known unix systems (including * Linux and Macintosh OS X) support the stty), so this * implementation should work for an reasonable POSIX system. *

* * @author Marc Prud'hommeaux * @author Updates Dale Kemp 2005-12-03 */ public class UnixTerminal extends Terminal { public static final short ARROW_START = 27; public static final short ARROW_PREFIX = 91; public static final short ARROW_LEFT = 68; public static final short ARROW_RIGHT = 67; public static final short ARROW_UP = 65; public static final short ARROW_DOWN = 66; public static final short O_PREFIX = 79; public static final short HOME_CODE = 72; public static final short END_CODE = 70; public static final short DEL_THIRD = 51; public static final short DEL_SECOND = 126; private boolean echoEnabled; private String ttyConfig; private String ttyProps; private long ttyPropsLastFetched; private boolean backspaceDeleteSwitched = false; private static String sttyCommand = System.getProperty("jline.sttyCommand", "stty"); String encoding = System.getProperty("input.encoding", "UTF-8"); ReplayPrefixOneCharInputStream replayStream = new ReplayPrefixOneCharInputStream(encoding); InputStreamReader replayReader; public UnixTerminal() { try { replayReader = new InputStreamReader(replayStream, encoding); } catch (Exception e) { throw new RuntimeException(e); } } protected void checkBackspace(){ String[] ttyConfigSplit = ttyConfig.split(":|="); backspaceDeleteSwitched = ttyConfigSplit.length >= 7 && "7f".equals(ttyConfigSplit[6]); } /** * Remove line-buffered input by invoking "stty -icanon min 1" * against the current terminal. */ public void initializeTerminal() throws IOException, InterruptedException { // save the initial tty configuration ttyConfig = stty("-g"); // sanity check if ((ttyConfig.length() == 0) || ((ttyConfig.indexOf("=") == -1) && (ttyConfig.indexOf(":") == -1))) { throw new IOException("Unrecognized stty code: " + ttyConfig); } checkBackspace(); // set the console to be character-buffered instead of line-buffered stty("-icanon min 1"); // disable character echoing stty("-echo"); echoEnabled = false; // at exit, restore the original tty configuration (for JDK 1.3+) try { Runtime.getRuntime().addShutdownHook(new Thread() { public void start() { try { restoreTerminal(); } catch (Exception e) { consumeException(e); } } }); } catch (AbstractMethodError ame) { // JDK 1.3+ only method. Bummer. consumeException(ame); } } /** * Restore the original terminal configuration, which can be used when * shutting down the console reader. The ConsoleReader cannot be * used after calling this method. */ public void restoreTerminal() throws Exception { if (ttyConfig != null) { stty(ttyConfig); ttyConfig = null; } resetTerminal(); } public int readVirtualKey(InputStream in) throws IOException { int c = readCharacter(in); if (backspaceDeleteSwitched) if (c == DELETE) c = BACKSPACE; else if (c == BACKSPACE) c = DELETE; // in Unix terminals, arrow keys are represented by // a sequence of 3 characters. E.g., the up arrow // key yields 27, 91, 68 if (c == ARROW_START && in.available() > 0) { // Escape key is also 27, so we use InputStream.available() // to distinguish those. If 27 represents an arrow, there // should be two more chars immediately available. while (c == ARROW_START) { c = readCharacter(in); } if (c == ARROW_PREFIX || c == O_PREFIX) { c = readCharacter(in); if (c == ARROW_UP) { return CTRL_P; } else if (c == ARROW_DOWN) { return CTRL_N; } else if (c == ARROW_LEFT) { return CTRL_B; } else if (c == ARROW_RIGHT) { return CTRL_F; } else if (c == HOME_CODE) { return CTRL_A; } else if (c == END_CODE) { return CTRL_E; } else if (c == DEL_THIRD) { c = readCharacter(in); // read 4th return DELETE; } } } // handle unicode characters, thanks for a patch from amyi@inf.ed.ac.uk if (c > 128) { // handle unicode characters longer than 2 bytes, // thanks to Marc.Herbert@continuent.com replayStream.setInput(c, in); // replayReader = new InputStreamReader(replayStream, encoding); c = replayReader.read(); } return c; } /** * No-op for exceptions we want to silently consume. */ private void consumeException(Throwable e) { } public boolean isSupported() { return true; } public boolean getEcho() { return false; } /** * Returns the value of "stty size" width param. * * Note: this method caches the value from the * first time it is called in order to increase speed, which means * that changing to size of the terminal will not be reflected * in the console. */ public int getTerminalWidth() { int val = -1; try { val = getTerminalProperty("columns"); } catch (Exception e) { } if (val == -1) { val = 80; } return val; } /** * Returns the value of "stty size" height param. * * Note: this method caches the value from the * first time it is called in order to increase speed, which means * that changing to size of the terminal will not be reflected * in the console. */ public int getTerminalHeight() { int val = -1; try { val = getTerminalProperty("rows"); } catch (Exception e) { } if (val == -1) { val = 24; } return val; } private int getTerminalProperty(String prop) throws IOException, InterruptedException { // tty properties are cached so we don't have to worry too much about getting term widht/height if (ttyProps == null || System.currentTimeMillis() - ttyPropsLastFetched > 1000) { ttyProps = stty("-a"); ttyPropsLastFetched = System.currentTimeMillis(); } // need to be able handle both output formats: // speed 9600 baud; 24 rows; 140 columns; // and: // speed 38400 baud; rows = 49; columns = 111; ypixels = 0; xpixels = 0; for (StringTokenizer tok = new StringTokenizer(ttyProps, ";\n"); tok.hasMoreTokens();) { String str = tok.nextToken().trim(); if (str.startsWith(prop)) { int index = str.lastIndexOf(" "); return Integer.parseInt(str.substring(index).trim()); } else if (str.endsWith(prop)) { int index = str.indexOf(" "); return Integer.parseInt(str.substring(0, index).trim()); } } return -1; } /** * Execute the stty command with the specified arguments * against the current active terminal. */ protected static String stty(final String args) throws IOException, InterruptedException { return exec("stty " + args + " < /dev/tty").trim(); } /** * Execute the specified command and return the output * (both stdout and stderr). */ private static String exec(final String cmd) throws IOException, InterruptedException { return exec(new String[] { "sh", "-c", cmd }); } /** * Execute the specified command and return the output * (both stdout and stderr). */ private static String exec(final String[] cmd) throws IOException, InterruptedException { ByteArrayOutputStream bout = new ByteArrayOutputStream(); Process p = Runtime.getRuntime().exec(cmd); int c; InputStream in = null; InputStream err = null; OutputStream out = null; try { in = p.getInputStream(); while ((c = in.read()) != -1) { bout.write(c); } err = p.getErrorStream(); while ((c = err.read()) != -1) { bout.write(c); } out = p.getOutputStream(); p.waitFor(); } finally { try {in.close();} catch (Exception e) {} try {err.close();} catch (Exception e) {} try {out.close();} catch (Exception e) {} } String result = new String(bout.toByteArray()); return result; } /** * The command to use to set the terminal options. Defaults * to "stty", or the value of the system property "jline.sttyCommand". */ public static void setSttyCommand(String cmd) { sttyCommand = cmd; } /** * The command to use to set the terminal options. Defaults * to "stty", or the value of the system property "jline.sttyCommand". */ public static String getSttyCommand() { return sttyCommand; } public synchronized boolean isEchoEnabled() { return echoEnabled; } public synchronized void enableEcho() { try { stty("echo"); echoEnabled = true; } catch (Exception e) { consumeException(e); } } public synchronized void disableEcho() { try { stty("-echo"); echoEnabled = false; } catch (Exception e) { consumeException(e); } } /** * This is awkward and inefficient, but probably the minimal way to add * UTF-8 support to JLine * * @author Marc Herbert */ static class ReplayPrefixOneCharInputStream extends InputStream { byte firstByte; int byteLength; InputStream wrappedStream; int byteRead; final String encoding; public ReplayPrefixOneCharInputStream(String encoding) { this.encoding = encoding; } public void setInput(int recorded, InputStream wrapped) throws IOException { this.byteRead = 0; this.firstByte = (byte) recorded; this.wrappedStream = wrapped; byteLength = 1; if (encoding.equalsIgnoreCase("UTF-8")) setInputUTF8(recorded, wrapped); else if (encoding.equalsIgnoreCase("UTF-16")) byteLength = 2; else if (encoding.equalsIgnoreCase("UTF-32")) byteLength = 4; } public void setInputUTF8(int recorded, InputStream wrapped) throws IOException { // 110yyyyy 10zzzzzz if ((firstByte & (byte) 0xE0) == (byte) 0xC0) this.byteLength = 2; // 1110xxxx 10yyyyyy 10zzzzzz else if ((firstByte & (byte) 0xF0) == (byte) 0xE0) this.byteLength = 3; // 11110www 10xxxxxx 10yyyyyy 10zzzzzz else if ((firstByte & (byte) 0xF8) == (byte) 0xF0) this.byteLength = 4; else throw new IOException("invalid UTF-8 first byte: " + firstByte); } public int read() throws IOException { if (available() == 0) return -1; byteRead++; if (byteRead == 1) return firstByte; return wrappedStream.read(); } /** * InputStreamReader is greedy and will try to read bytes in advance. We * do NOT want this to happen since we use a temporary/"losing bytes" * InputStreamReader above, that's why we hide the real * wrappedStream.available() here. */ public int available() { return byteLength - byteRead; } } } jline-1.0.orig/src/src/main/java/jline/ConsoleRunner.java0000644000175000017500000000564711550705746023361 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; import java.util.*; /** *

* A pass-through application that sets the system input stream to a * {@link ConsoleReader} and invokes the specified main method. *

* @author Marc Prud'hommeaux */ public class ConsoleRunner { private static ConsoleReader reader; public static ConsoleReader getReader() { return reader; } public static final String property = "jline.history"; public static void main(final String[] args) throws Exception { String historyFileName = null; List argList = new ArrayList(Arrays.asList(args)); if (argList.size() == 0) { usage(); return; } historyFileName = System.getProperty(ConsoleRunner.property, null); // invoke the main() method String mainClass = (String) argList.remove(0); // setup the inpout stream reader = new ConsoleReader(); if (historyFileName != null) { reader.setHistory(new History (new File (System.getProperty("user.home"), ".jline-" + mainClass + "." + historyFileName + ".history"))); } else { reader.setHistory(new History(new File (System.getProperty("user.home"), ".jline-" + mainClass + ".history"))); } String completors = System.getProperty (ConsoleRunner.class.getName() + ".completors", ""); List completorList = new ArrayList(); for (StringTokenizer tok = new StringTokenizer(completors, ","); tok.hasMoreTokens();) { completorList.add ((Completor) Class.forName(tok.nextToken()).newInstance()); } if (completorList.size() > 0) { reader.addCompletor(new ArgumentCompletor(completorList)); } ConsoleReaderInputStream.setIn(reader); try { Class.forName(mainClass). getMethod("main", new Class[] { String[].class }). invoke(null, new Object[] { argList.toArray(new String[0]) }); } finally { // just in case this main method is called from another program ConsoleReaderInputStream.restoreIn(); } } private static void usage() { System.out.println("Usage: \n java " + "[-Djline.history='name'] " + ConsoleRunner.class.getName() + " [args]" + "\n\nThe -Djline.history option will avoid history" + "\nmangling when running ConsoleRunner on the same application." + "\n\nargs will be passed directly to the target class name."); } } jline-1.0.orig/src/src/main/java/jline/WindowsTerminal.java0000644000175000017500000004226411550705746023707 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; import jline.UnixTerminal.ReplayPrefixOneCharInputStream; /** *

* Terminal implementation for Microsoft Windows. Terminal initialization in * {@link #initializeTerminal} is accomplished by extracting the * jline_version.dll, saving it to the system temporary * directoy (determined by the setting of the java.io.tmpdir System * property), loading the library, and then calling the Win32 APIs SetConsoleMode and * GetConsoleMode to * disable character echoing. *

* *

* By default, the {@link #readCharacter} method will attempt to test to see if * the specified {@link InputStream} is {@link System#in} or a wrapper around * {@link FileDescriptor#in}, and if so, will bypass the character reading to * directly invoke the readc() method in the JNI library. This is so the class * can read special keys (like arrow keys) which are otherwise inaccessible via * the {@link System#in} stream. Using JNI reading can be bypassed by setting * the jline.WindowsTerminal.directConsole system property * to false. *

* * @author Marc Prud'hommeaux */ public class WindowsTerminal extends Terminal { // constants copied from wincon.h /** * The ReadFile or ReadConsole function returns only when a carriage return * character is read. If this mode is disable, the functions return when one * or more characters are available. */ private static final int ENABLE_LINE_INPUT = 2; /** * Characters read by the ReadFile or ReadConsole function are written to * the active screen buffer as they are read. This mode can be used only if * the ENABLE_LINE_INPUT mode is also enabled. */ private static final int ENABLE_ECHO_INPUT = 4; /** * CTRL+C is processed by the system and is not placed in the input buffer. * If the input buffer is being read by ReadFile or ReadConsole, other * control keys are processed by the system and are not returned in the * ReadFile or ReadConsole buffer. If the ENABLE_LINE_INPUT mode is also * enabled, backspace, carriage return, and linefeed characters are handled * by the system. */ private static final int ENABLE_PROCESSED_INPUT = 1; /** * User interactions that change the size of the console screen buffer are * reported in the console's input buffee. Information about these events * can be read from the input buffer by applications using * theReadConsoleInput function, but not by those using ReadFile * orReadConsole. */ private static final int ENABLE_WINDOW_INPUT = 8; /** * If the mouse pointer is within the borders of the console window and the * window has the keyboard focus, mouse events generated by mouse movement * and button presses are placed in the input buffer. These events are * discarded by ReadFile or ReadConsole, even when this mode is enabled. */ private static final int ENABLE_MOUSE_INPUT = 16; /** * When enabled, text entered in a console window will be inserted at the * current cursor location and all text following that location will not be * overwritten. When disabled, all following text will be overwritten. An OR * operation must be performed with this flag and the ENABLE_EXTENDED_FLAGS * flag to enable this functionality. */ private static final int ENABLE_PROCESSED_OUTPUT = 1; /** * This flag enables the user to use the mouse to select and edit text. To * enable this option, use the OR to combine this flag with * ENABLE_EXTENDED_FLAGS. */ private static final int ENABLE_WRAP_AT_EOL_OUTPUT = 2; /** * On windows terminals, this character indicates that a 'special' key has * been pressed. This means that a key such as an arrow key, or delete, or * home, etc. will be indicated by the next character. */ public static final int SPECIAL_KEY_INDICATOR = 224; /** * On windows terminals, this character indicates that a special key on the * number pad has been pressed. */ public static final int NUMPAD_KEY_INDICATOR = 0; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR, * this character indicates an left arrow key press. */ public static final int LEFT_ARROW_KEY = 75; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR * this character indicates an * right arrow key press. */ public static final int RIGHT_ARROW_KEY = 77; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR * this character indicates an up * arrow key press. */ public static final int UP_ARROW_KEY = 72; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR * this character indicates an * down arrow key press. */ public static final int DOWN_ARROW_KEY = 80; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR * this character indicates that * the delete key was pressed. */ public static final int DELETE_KEY = 83; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR * this character indicates that * the home key was pressed. */ public static final int HOME_KEY = 71; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR * this character indicates that * the end key was pressed. */ public static final char END_KEY = 79; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR * this character indicates that * the page up key was pressed. */ public static final char PAGE_UP_KEY = 73; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR * this character indicates that * the page down key was pressed. */ public static final char PAGE_DOWN_KEY = 81; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR * this character indicates that * the insert key was pressed. */ public static final char INSERT_KEY = 82; /** * When following the SPECIAL_KEY_INDICATOR or NUMPAD_KEY_INDICATOR, * this character indicates that the escape key was pressed. */ public static final char ESCAPE_KEY = 0; private Boolean directConsole; private boolean echoEnabled; String encoding = System.getProperty("jline.WindowsTerminal.input.encoding", System.getProperty("file.encoding")); ReplayPrefixOneCharInputStream replayStream = new ReplayPrefixOneCharInputStream(encoding); InputStreamReader replayReader; public WindowsTerminal() { String dir = System.getProperty("jline.WindowsTerminal.directConsole"); if ("true".equals(dir)) { directConsole = Boolean.TRUE; } else if ("false".equals(dir)) { directConsole = Boolean.FALSE; } try { replayReader = new InputStreamReader(replayStream, encoding); } catch (Exception e) { throw new RuntimeException(e); } } private native int getConsoleMode(); private native void setConsoleMode(final int mode); private native int readByte(); private native int getWindowsTerminalWidth(); private native int getWindowsTerminalHeight(); public int readCharacter(final InputStream in) throws IOException { // if we can detect that we are directly wrapping the system // input, then bypass the input stream and read directly (which // allows us to access otherwise unreadable strokes, such as // the arrow keys) if (directConsole == Boolean.FALSE) { return super.readCharacter(in); } else if ((directConsole == Boolean.TRUE) || ((in == System.in) || (in instanceof FileInputStream && (((FileInputStream) in).getFD() == FileDescriptor.in)))) { return readByte(); } else { return super.readCharacter(in); } } public void initializeTerminal() throws Exception { loadLibrary("jline"); final int originalMode = getConsoleMode(); setConsoleMode(originalMode & ~ENABLE_ECHO_INPUT); // set the console to raw mode int newMode = originalMode & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_WINDOW_INPUT); echoEnabled = false; setConsoleMode(newMode); // at exit, restore the original tty configuration (for JDK 1.3+) try { Runtime.getRuntime().addShutdownHook(new Thread() { public void start() { // restore the old console mode setConsoleMode(originalMode); } }); } catch (AbstractMethodError ame) { // JDK 1.3+ only method. Bummer. consumeException(ame); } } private void loadLibrary(final String name) throws IOException { // store the DLL in the temporary directory for the System String version = WindowsTerminal.class.getPackage().getImplementationVersion(); if (version == null) { version = ""; } version = version.replace('.', '_'); File f = new File(System.getProperty("java.io.tmpdir"), name + "_" + version + ".dll"); boolean exists = f.isFile(); // check if it already exists // extract the embedded jline.dll file from the jar and save // it to the current directory int bits = 32; // check for 64-bit systems and use to appropriate DLL if (System.getProperty("os.arch").indexOf("64") != -1) bits = 64; InputStream in = new BufferedInputStream(WindowsTerminal.class.getResourceAsStream(name + bits + ".dll")); OutputStream fout = null; try { fout = new BufferedOutputStream( new FileOutputStream(f)); byte[] bytes = new byte[1024 * 10]; for (int n = 0; n != -1; n = in.read(bytes)) { fout.write(bytes, 0, n); } } catch (IOException ioe) { // We might get an IOException trying to overwrite an existing // jline.dll file if there is another process using the DLL. // If this happens, ignore errors. if (!exists) { throw ioe; } } finally { if (fout != null) { try { fout.close(); } catch (IOException ioe) { // ignore } } } // try to clean up the DLL after the JVM exits f.deleteOnExit(); // now actually load the DLL System.load(f.getAbsolutePath()); } public int readVirtualKey(InputStream in) throws IOException { int indicator = readCharacter(in); // in Windows terminals, arrow keys are represented by // a sequence of 2 characters. E.g., the up arrow // key yields 224, 72 if (indicator == SPECIAL_KEY_INDICATOR || indicator == NUMPAD_KEY_INDICATOR) { int key = readCharacter(in); switch (key) { case UP_ARROW_KEY: return CTRL_P; // translate UP -> CTRL-P case LEFT_ARROW_KEY: return CTRL_B; // translate LEFT -> CTRL-B case RIGHT_ARROW_KEY: return CTRL_F; // translate RIGHT -> CTRL-F case DOWN_ARROW_KEY: return CTRL_N; // translate DOWN -> CTRL-N case DELETE_KEY: return CTRL_QM; // translate DELETE -> CTRL-? case HOME_KEY: return CTRL_A; case END_KEY: return CTRL_E; case PAGE_UP_KEY: return CTRL_K; case PAGE_DOWN_KEY: return CTRL_L; case ESCAPE_KEY: return CTRL_OB; // translate ESCAPE -> CTRL-[ case INSERT_KEY: return CTRL_C; default: return 0; } } else if (indicator > 128) { // handle unicode characters longer than 2 bytes, // thanks to Marc.Herbert@continuent.com replayStream.setInput(indicator, in); // replayReader = new InputStreamReader(replayStream, encoding); indicator = replayReader.read(); } return indicator; } public boolean isSupported() { return true; } /** * Windows doesn't support ANSI codes by default; disable them. */ public boolean isANSISupported() { return false; } public boolean getEcho() { return false; } /** * Unsupported; return the default. * * @see Terminal#getTerminalWidth */ public int getTerminalWidth() { return getWindowsTerminalWidth(); } /** * Unsupported; return the default. * * @see Terminal#getTerminalHeight */ public int getTerminalHeight() { return getWindowsTerminalHeight(); } /** * No-op for exceptions we want to silently consume. */ private void consumeException(final Throwable e) { } /** * Whether or not to allow the use of the JNI console interaction. */ public void setDirectConsole(Boolean directConsole) { this.directConsole = directConsole; } /** * Whether or not to allow the use of the JNI console interaction. */ public Boolean getDirectConsole() { return this.directConsole; } public synchronized boolean isEchoEnabled() { return echoEnabled; } public synchronized void enableEcho() { // Must set these four modes at the same time to make it work fine. setConsoleMode(getConsoleMode() | ENABLE_ECHO_INPUT | ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_WINDOW_INPUT); echoEnabled = true; } public synchronized void disableEcho() { // Must set these four modes at the same time to make it work fine. setConsoleMode(getConsoleMode() & ~(ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_WINDOW_INPUT)); echoEnabled = true; } public InputStream getDefaultBindings() { return WindowsTerminal.class.getResourceAsStream("windowsbindings.properties"); } /** * This is awkward and inefficient, but probably the minimal way to add * UTF-8 support to JLine * * @author Marc Herbert */ static class ReplayPrefixOneCharInputStream extends InputStream { byte firstByte; int byteLength; InputStream wrappedStream; int byteRead; final String encoding; public ReplayPrefixOneCharInputStream(String encoding) { this.encoding = encoding; } public void setInput(int recorded, InputStream wrapped) throws IOException { this.byteRead = 0; this.firstByte = (byte) recorded; this.wrappedStream = wrapped; byteLength = 1; if (encoding.equalsIgnoreCase("UTF-8")) setInputUTF8(recorded, wrapped); else if (encoding.equalsIgnoreCase("UTF-16")) byteLength = 2; else if (encoding.equalsIgnoreCase("UTF-32")) byteLength = 4; } public void setInputUTF8(int recorded, InputStream wrapped) throws IOException { // 110yyyyy 10zzzzzz if ((firstByte & (byte) 0xE0) == (byte) 0xC0) this.byteLength = 2; // 1110xxxx 10yyyyyy 10zzzzzz else if ((firstByte & (byte) 0xF0) == (byte) 0xE0) this.byteLength = 3; // 11110www 10xxxxxx 10yyyyyy 10zzzzzz else if ((firstByte & (byte) 0xF8) == (byte) 0xF0) this.byteLength = 4; else throw new IOException("invalid UTF-8 first byte: " + firstByte); } public int read() throws IOException { if (available() == 0) return -1; byteRead++; if (byteRead == 1) return firstByte; return wrappedStream.read(); } /** * InputStreamReader is greedy and will try to read bytes in advance. We * do NOT want this to happen since we use a temporary/"losing bytes" * InputStreamReader above, that's why we hide the real * wrappedStream.available() here. */ public int available() { return byteLength - byteRead; } } } jline-1.0.orig/src/src/main/java/jline/CandidateListCompletionHandler.java0000644000175000017500000001401711550705746026614 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; import java.text.MessageFormat; import java.util.*; /** *

* A {@link CompletionHandler} that deals with multiple distinct completions * by outputting the complete list of possibilities to the console. This * mimics the behavior of the * readline * library. *

* * TODO: *
    *
  • handle quotes and escaped quotes
  • *
  • enable automatic escaping of whitespace
  • *
* * @author Marc Prud'hommeaux */ public class CandidateListCompletionHandler implements CompletionHandler { private static ResourceBundle loc = ResourceBundle. getBundle(CandidateListCompletionHandler.class.getName()); private boolean eagerNewlines = true; public void setAlwaysIncludeNewline(boolean eagerNewlines) { this.eagerNewlines = eagerNewlines; } public boolean complete(final ConsoleReader reader, final List candidates, final int pos) throws IOException { CursorBuffer buf = reader.getCursorBuffer(); // if there is only one completion, then fill in the buffer if (candidates.size() == 1) { String value = candidates.get(0).toString(); // fail if the only candidate is the same as the current buffer if (value.equals(buf.toString())) { return false; } setBuffer(reader, value, pos); return true; } else if (candidates.size() > 1) { String value = getUnambiguousCompletions(candidates); String bufString = buf.toString(); setBuffer(reader, value, pos); } if (eagerNewlines) reader.printNewline(); printCandidates(reader, candidates, eagerNewlines); // redraw the current console buffer reader.drawLine(); return true; } public static void setBuffer(ConsoleReader reader, String value, int offset) throws IOException { while ((reader.getCursorBuffer().cursor > offset) && reader.backspace()) { ; } reader.putString(value); reader.setCursorPosition(offset + value.length()); } /** * Print out the candidates. If the size of the candidates * is greated than the {@link getAutoprintThreshhold}, * they prompt with aq warning. * * @param candidates the list of candidates to print */ public static final void printCandidates(ConsoleReader reader, Collection candidates, boolean eagerNewlines) throws IOException { Set distinct = new HashSet(candidates); if (distinct.size() > reader.getAutoprintThreshhold()) { if (!eagerNewlines) reader.printNewline(); reader.printString(MessageFormat.format (loc.getString("display-candidates"), new Object[] { new Integer(candidates .size()) }) + " "); reader.flushConsole(); int c; String noOpt = loc.getString("display-candidates-no"); String yesOpt = loc.getString("display-candidates-yes"); while ((c = reader.readCharacter(new char[] { yesOpt.charAt(0), noOpt.charAt(0) })) != -1) { if (noOpt.startsWith (new String(new char[] { (char) c }))) { reader.printNewline(); return; } else if (yesOpt.startsWith (new String(new char[] { (char) c }))) { break; } else { reader.beep(); } } } // copy the values and make them distinct, without otherwise // affecting the ordering. Only do it if the sizes differ. if (distinct.size() != candidates.size()) { Collection copy = new ArrayList(); for (Iterator i = candidates.iterator(); i.hasNext();) { Object next = i.next(); if (!(copy.contains(next))) { copy.add(next); } } candidates = copy; } reader.printNewline(); reader.printColumns(candidates); } /** * Returns a root that matches all the {@link String} elements * of the specified {@link List}, or null if there are * no commalities. For example, if the list contains * foobar, foobaz, foobuz, the * method will return foob. */ private final String getUnambiguousCompletions(final List candidates) { if ((candidates == null) || (candidates.size() == 0)) { return null; } // convert to an array for speed String[] strings = (String[]) candidates.toArray(new String[candidates.size()]); String first = strings[0]; StringBuffer candidate = new StringBuffer(); for (int i = 0; i < first.length(); i++) { if (startsWith(first.substring(0, i + 1), strings)) { candidate.append(first.charAt(i)); } else { break; } } return candidate.toString(); } /** * @return true is all the elements of candidates * start with starts */ private final boolean startsWith(final String starts, final String[] candidates) { for (int i = 0; i < candidates.length; i++) { if (!candidates[i].startsWith(starts)) { return false; } } return true; } } jline-1.0.orig/src/src/main/java/jline/CompletionHandler.java0000644000175000017500000000106511550705746024162 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; import java.util.*; /** * Handler for dealing with candidates for tab-completion. * * @author Marc Prud'hommeaux */ public interface CompletionHandler { boolean complete(ConsoleReader reader, List candidates, int position) throws IOException; } jline-1.0.orig/src/src/main/java/jline/Terminal.java0000644000175000017500000001274611550705746022336 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; /** * Representation of the input terminal for a platform. Handles * any initialization that the platform may need to perform * in order to allow the {@link ConsoleReader} to correctly handle * input. * * @author Marc Prud'hommeaux */ public abstract class Terminal implements ConsoleOperations { private static Terminal term; /** * @see #setupTerminal */ public static Terminal getTerminal() { return setupTerminal(); } /** * Reset the current terminal to null. */ public static void resetTerminal() { term = null; } /** *

Configure and return the {@link Terminal} instance for the * current platform. This will initialize any system settings * that are required for the console to be able to handle * input correctly, such as setting tabtop, buffered input, and * character echo.

* *

This class will use the Terminal implementation specified in the * jline.terminal system property, or, if it is unset, by * detecting the operating system from the os.name * system property and instantiating either the * {@link WindowsTerminalTest} or {@link UnixTerminal}. * * @see #initializeTerminal */ public static synchronized Terminal setupTerminal() { if (term != null) { return term; } final Terminal t; String os = System.getProperty("os.name").toLowerCase(); String termProp = System.getProperty("jline.terminal"); if ((termProp != null) && (termProp.length() > 0)) { try { t = (Terminal) Class.forName(termProp).newInstance(); } catch (Exception e) { throw (IllegalArgumentException) new IllegalArgumentException(e .toString()).fillInStackTrace(); } } else if (os.indexOf("windows") != -1) { t = new WindowsTerminal(); } else { t = new UnixTerminal(); } try { t.initializeTerminal(); } catch (Exception e) { e.printStackTrace(); return term = new UnsupportedTerminal(); } return term = t; } /** * Returns true if the current console supports ANSI * codes. */ public boolean isANSISupported() { return true; } /** * Read a single character from the input stream. This might * enable a terminal implementation to better handle nuances of * the console. */ public int readCharacter(final InputStream in) throws IOException { return in.read(); } /** * Reads a virtual key from the console. Typically, this will * just be the raw character that was entered, but in some cases, * multiple input keys will need to be translated into a single * virtual key. * * @param in the InputStream to read from * @return the virtual key (e.g., {@link ConsoleOperations#VK_UP}) */ public int readVirtualKey(InputStream in) throws IOException { return readCharacter(in); } /** * Initialize any system settings * that are required for the console to be able to handle * input correctly, such as setting tabtop, buffered input, and * character echo. */ public abstract void initializeTerminal() throws Exception; /** * Returns the current width of the terminal (in characters) */ public abstract int getTerminalWidth(); /** * Returns the current height of the terminal (in lines) */ public abstract int getTerminalHeight(); /** * Returns true if this terminal is capable of initializing the * terminal to use jline. */ public abstract boolean isSupported(); /** * Returns true if the terminal will echo all characters type. */ public abstract boolean getEcho(); /** * Invokes before the console reads a line with the prompt and mask. */ public void beforeReadLine(ConsoleReader reader, String prompt, Character mask) { } /** * Invokes after the console reads a line with the prompt and mask. */ public void afterReadLine(ConsoleReader reader, String prompt, Character mask) { } /** * Returns false if character echoing is disabled. */ public abstract boolean isEchoEnabled(); /** * Enable character echoing. This can be used to re-enable character * if the ConsoleReader is no longer being used. */ public abstract void enableEcho(); /** * Disable character echoing. This can be used to manually re-enable * character if the ConsoleReader has been disabled. */ public abstract void disableEcho(); public InputStream getDefaultBindings() { // Mac bindings are slightly different from Unix/Linux. // For instance, the Delete key behavior is different between them. return Terminal.class.getResourceAsStream( System.getProperty("os.name").toLowerCase().startsWith("mac") ? "keybindings-mac.properties" : "keybindings.properties"); } } jline-1.0.orig/src/src/main/java/jline/CursorBuffer.java0000644000175000017500000000456211550705746023167 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; /** * A CursorBuffer is a holder for a {@link StringBuffer} that also contains the * current cursor position. * * @author Marc Prud'hommeaux */ public class CursorBuffer { public int cursor = 0; StringBuffer buffer = new StringBuffer(); private boolean overtyping = false; public int length() { return buffer.length(); } public char current() { if (cursor <= 0) { return 0; } return buffer.charAt(cursor - 1); } public boolean clearBuffer() { if (buffer.length() == 0) { return false; } buffer.delete(0, buffer.length()); cursor = 0; return true; } /** * Write the specific character into the buffer, setting the cursor position * ahead one. The text may overwrite or insert based on the current setting * of isOvertyping(). * * @param c * the character to insert */ public void write(final char c) { buffer.insert(cursor++, c); if (isOvertyping() && cursor < buffer.length()) { buffer.deleteCharAt(cursor); } } /** * Insert the specified {@link String} into the buffer, setting the cursor * to the end of the insertion point. * * @param str * the String to insert. Must not be null. */ public void write(final String str) { if (buffer.length() == 0) { buffer.append(str); } else { buffer.insert(cursor, str); } cursor += str.length(); if (isOvertyping() && cursor < buffer.length()) { buffer.delete(cursor, (cursor + str.length())); } } public String toString() { return buffer.toString(); } public boolean isOvertyping() { return overtyping; } public void setOvertyping(boolean b) { overtyping = b; } public StringBuffer getBuffer() { return buffer; } public void setBuffer(StringBuffer buffer) { buffer.setLength(0); buffer.append(this.buffer.toString()); this.buffer = buffer; } } jline-1.0.orig/src/src/main/java/jline/ConsoleReaderInputStream.java0000644000175000017500000000562611550705746025503 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.io.*; import java.util.*; /** * An {@link InputStream} implementation that wraps a {@link ConsoleReader}. * It is useful for setting up the {@link System#in} for a generic * console. * @author Marc Prud'hommeaux */ public class ConsoleReaderInputStream extends SequenceInputStream { private static InputStream systemIn = System.in; public static void setIn() throws IOException { setIn(new ConsoleReader()); } public static void setIn(final ConsoleReader reader) { System.setIn(new ConsoleReaderInputStream(reader)); } /** * Restore the original {@link System#in} input stream. */ public static void restoreIn() { System.setIn(systemIn); } public ConsoleReaderInputStream(final ConsoleReader reader) { super(new ConsoleEnumeration(reader)); } private static class ConsoleEnumeration implements Enumeration { private final ConsoleReader reader; private ConsoleLineInputStream next = null; private ConsoleLineInputStream prev = null; public ConsoleEnumeration(final ConsoleReader reader) { this.reader = reader; } public Object nextElement() { if (next != null) { InputStream n = next; prev = next; next = null; return n; } return new ConsoleLineInputStream(reader); } public boolean hasMoreElements() { // the last line was null if ((prev != null) && (prev.wasNull == true)) { return false; } if (next == null) { next = (ConsoleLineInputStream) nextElement(); } return next != null; } } private static class ConsoleLineInputStream extends InputStream { private final ConsoleReader reader; private String line = null; private int index = 0; private boolean eol = false; protected boolean wasNull = false; public ConsoleLineInputStream(final ConsoleReader reader) { this.reader = reader; } public int read() throws IOException { if (eol) { return -1; } if (line == null) { line = reader.readLine(); } if (line == null) { wasNull = true; return -1; } if (index >= line.length()) { eol = true; return '\n'; // lines are ended with a newline } return line.charAt(index++); } } } jline-1.0.orig/src/src/main/native/0000755000175000017500000000000011550705746017152 5ustar twernertwernerjline-1.0.orig/src/src/main/native/jline_WindowsTerminal.h0000644000175000017500000000365211550705746023640 0ustar twernertwerner/* DO NOT EDIT THIS FILE - it is machine generated */ #include /* Header for class jline_WindowsTerminal */ #ifndef _Included_jline_WindowsTerminal #define _Included_jline_WindowsTerminal #ifdef __cplusplus extern "C" { #endif /* Inaccessible static: term */ #undef jline_WindowsTerminal_ENABLE_LINE_INPUT #define jline_WindowsTerminal_ENABLE_LINE_INPUT 2L #undef jline_WindowsTerminal_ENABLE_ECHO_INPUT #define jline_WindowsTerminal_ENABLE_ECHO_INPUT 4L #undef jline_WindowsTerminal_ENABLE_PROCESSED_INPUT #define jline_WindowsTerminal_ENABLE_PROCESSED_INPUT 1L #undef jline_WindowsTerminal_ENABLE_WINDOW_INPUT #define jline_WindowsTerminal_ENABLE_WINDOW_INPUT 8L #undef jline_WindowsTerminal_ENABLE_MOUSE_INPUT #define jline_WindowsTerminal_ENABLE_MOUSE_INPUT 16L #undef jline_WindowsTerminal_ENABLE_PROCESSED_OUTPUT #define jline_WindowsTerminal_ENABLE_PROCESSED_OUTPUT 1L #undef jline_WindowsTerminal_ENABLE_WRAP_AT_EOL_OUTPUT #define jline_WindowsTerminal_ENABLE_WRAP_AT_EOL_OUTPUT 2L /* * Class: jline_WindowsTerminal * Method: getConsoleMode * Signature: ()I */ JNIEXPORT jint JNICALL Java_jline_WindowsTerminal_getConsoleMode (JNIEnv *, jobject); /* * Class: jline_WindowsTerminal * Method: setConsoleMode * Signature: (I)V */ JNIEXPORT void JNICALL Java_jline_WindowsTerminal_setConsoleMode (JNIEnv *, jobject, jint); /* * Class: jline_WindowsTerminal * Method: readByte * Signature: ()I */ JNIEXPORT jint JNICALL Java_jline_WindowsTerminal_readByte (JNIEnv *, jobject); /* * Class: jline_WindowsTerminal * Method: getWindowsTerminalWidth * Signature: ()I */ JNIEXPORT jint JNICALL Java_jline_WindowsTerminal_getWindowsTerminalWidth (JNIEnv *, jobject); /* * Class: jline_WindowsTerminal * Method: getWindowsTerminalHeight * Signature: ()I */ JNIEXPORT jint JNICALL Java_jline_WindowsTerminal_getWindowsTerminalHeight (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif jline-1.0.orig/src/src/main/native/Makefile0000644000175000017500000000066311550705746020617 0ustar twernertwerner #export PATH=${PATH}:/usr/lib/gcc-lib/i686-pc-cygwin/3.3.3 JDK='/C/Program Files/Java/jdk1.5.0/' native: #gcc -I'C:/Program Files/Java/'*'/include/' -I'C:/Program Files/Java/'*'/include//win32/' -mno-cygwin -Wl,--add-stdcall-alias -shared -o jline.dll jline_WindowsTerminal.c gcc -L /usr/lib/mingw/ -I${JDK}/include -I${JDK}/include/win32 -mwindows -mno-cygwin -Wl,--add-stdcall-alias -shared -o jline.dll jline_WindowsTerminal.c jline-1.0.orig/src/src/main/native/jline_WindowsTerminal.c0000644000175000017500000000327511550705746023634 0ustar twernertwerner#include "jline_WindowsTerminal.h" #include JNIEXPORT jint JNICALL Java_jline_WindowsTerminal_getConsoleMode (JNIEnv *env, jobject ob) { DWORD mode; HANDLE hConsole = GetStdHandle (STD_INPUT_HANDLE); if (hConsole == INVALID_HANDLE_VALUE) return -1; if (!GetConsoleMode (hConsole, &mode)) return -1; // CloseHandle (hConsole); // printf ("JNI get mode=%d\n", mode); return mode; } JNIEXPORT void JNICALL Java_jline_WindowsTerminal_setConsoleMode (JNIEnv *env, jobject ob, jint mode) { DWORD m = (DWORD)mode; HANDLE hConsole = GetStdHandle (STD_INPUT_HANDLE); if (hConsole == INVALID_HANDLE_VALUE) return; // printf ("JNI set mode=%d\n", m); SetConsoleMode (hConsole, m); // CloseHandle (hConsole); } JNIEXPORT jint JNICALL Java_jline_WindowsTerminal_readByte (JNIEnv * env, jclass class) { return getch (); } JNIEXPORT jint JNICALL Java_jline_WindowsTerminal_getWindowsTerminalWidth (JNIEnv * env, jclass class) { HANDLE inputHandle = GetStdHandle (STD_INPUT_HANDLE); HANDLE outputHandle = GetStdHandle (STD_OUTPUT_HANDLE); PCONSOLE_SCREEN_BUFFER_INFO info = malloc (sizeof (CONSOLE_SCREEN_BUFFER_INFO)); GetConsoleScreenBufferInfo (outputHandle, info); return info->srWindow.Right - info->srWindow.Left+1; } JNIEXPORT jint JNICALL Java_jline_WindowsTerminal_getWindowsTerminalHeight (JNIEnv * env, jclass class) { HANDLE inputHandle = GetStdHandle (STD_INPUT_HANDLE); HANDLE outputHandle = GetStdHandle (STD_OUTPUT_HANDLE); PCONSOLE_SCREEN_BUFFER_INFO info = malloc (sizeof (CONSOLE_SCREEN_BUFFER_INFO)); GetConsoleScreenBufferInfo (outputHandle, info); return info->srWindow.Bottom - info->srWindow.Top+1; } jline-1.0.orig/src/src/site/0000755000175000017500000000000011550705746015704 5ustar twernertwernerjline-1.0.orig/src/src/site/resources/0000755000175000017500000000000011550705746017716 5ustar twernertwernerjline-1.0.orig/src/src/site/resources/css/0000755000175000017500000000000011550705746020506 5ustar twernertwernerjline-1.0.orig/src/src/site/resources/css/site.css0000755000175000017500000001307611550705746022176 0ustar twernertwerner body { min-width: 600px; width: 600px; width: auto !important; background-color: #fff; font-family: Verdana, sans; } body,div,span,td,p,h2,h3,h4,h5,h6,a,ul,li { font-family: Verdana, sans; font-size: 11px; color: #5A5A5A; font-style: normal; } a,a:hover,a:visited,a:active { color: #5A5A5A; /* text-decoration: underline; */ } /* main layout */ #banner { color: #FFA500; border: none; margin: 0 0 0 0; background-color: #fff; background-image: url(../images/header.jpg); background-position: right; background-repeat: no-repeat; height: 100px; } #bannerLeft img{ margin: 10px 0 0 10px; } #leftColumn { background-color: transparent; position: absolute; top: 140px; left: 20px; width: 180px; margin: 0px; padding: 0px; border: none; } #bodyColumn { margin: 0 0 20px 220px; background-color: #fff; padding: 30px; position: relative; background-image: url(../images/dotted.png); background-repeat: repeat-y; } #footer div.xright { color: #fff; margin-right: 10px; } /* end main layout */ .deprecated { text-decoration: line-through; } .comment { color: green; } .source pre { font-family: "Andale Mono", monospace; font-size: 11px; background-color: #ddd; width: 100%; color: #5A5A5A; border-width: 0px; padding-top: 6px; padding-left: 3px; } #breadcrumbs { background-color: #FE1100; border: none; height: 15px; } /* workaround for bug in the Doxia docbook renderer that opens anchors (e.g. ), but doesn't ever close them */ #section a,a:hover,a:visited,a:active { text-decoration: none; } #breadcrumbs a { color: #fff; margin-left: 20px; text-decoration: none; } h1 { border: none; padding-left: 0; font-weight: bold; text-transform: capitalize; background-color: #7FAABB !important; color: #FFFFFF !important; font-size: 19px !important; } h2 { border: none; padding-left: 0; font-size: 13px; font-weight: bold; text-transform: capitalize; background-color: #7FAABB !important; color: #FFFFFF !important; font-size: 17px !important; } h3 { border: none; font-weight: bolder; padding-left: 0; background-color: #8BBBD1 !important; color: #FFFFFF !important; } #navcolumn { padding: 0; overflow: hidden; } #navcolumn ul { margin: 0px 0 3px 0; background-repeat: repeat-x; } #navcolumn h5 { border: none; background-image: url(../images/dotted.png); background-repeat: repeat-x; padding: 4px 0 3px 20px; font-size: 11px !important; margin-top: -1px; } #navcolumn ul { margin-bottom: 8px; } #navcolumn li { margin: 0px 0 0px 3px; padding: 2px; list-style-position: outside; font-size: 7.5pt !important; padding-left: 16px; padding-left /**/: 2px !important; /* warning, don't reformat, there should be no comment between padding-left and comment, to fix IE5 issues */ } #menuDownloadable_docs li { background-image: url(../images/ico_file_pdf.png); padding-top: 3px; padding-bottom: 1px; } #navcolumn strong { color: #000000; font-weight: bold; } #navcolumn strong a { color: #000000; font-weight: bold; } #navcolumn a { padding-left: 14px; text-decoration: underline; padding-bottom: 2px; color: #5a5a5a; } #navcolumn a img { margin-top: 0; } #navcolumn a#poweredBy img { margin: 0 0 15px 20px; width: 90px; height: 30px; } #navcolumn #lastPublished { color: #999; margin: 0 0 0 20px; } #navcolumn a:hover { color: Olive; padding-left: 14px; text-decoration: underline; padding-bottom: 2px; } #breadcrumbs div.xright,#breadcrumbs div.xleft { color: #fff; display: inline; font-size: 7pt !important; } #banner a#projectLogo img { float: left; background-color: #fff !important; margin: 20px 0 0 20px !important; } #navcolumn li { color: #000000; } #navcolumn strong { color: #000000; font-weight: bold; margin-left: 15px; } div.source { background-color: #ddd; } div.source pre,code,td.code { font-size: 8pt !important; font-family: monospace; margin: 0; } td.code { font-size: 10pt !important; font-family: monospace; } div#legend { display: none; } table td.source { border: none !important; } table td,table th { font-size: 8pt !important; font-family: verdana; } table th { font-weight: bold; } .collapsed { background-image: url(../images/collapsed.png) !important; } li.expanded { background-image: url(../images/expanded.png) !important; } /* li.expanded ul { margin-top: 5px !important; } */ a.externalLink,a.newWindow { padding-right: 9px !important; background-image: none !important; /*ie5*/ } a.externalLink /* */ { background-image: url(../images/external.png) !important; } a.newWindow /* */ { background-image: url(../images/newwindow.png) !important; } table { width: 68%; /* fix for ie 5.x */ } i { content: "\"/*" } table { width: 100%; } /* remove banner: comment the following lines for the full layout */ /* #banner, #breadcrumbs { display: none !important; } #leftColumn { position: relative; top: 0; } */ jline-1.0.orig/src/src/site/resources/images/0000755000175000017500000000000011550705746021163 5ustar twernertwernerjline-1.0.orig/src/src/site/resources/images/expanded.png0000755000175000017500000000030611550705746023463 0ustar twernertwernerPNG  IHDR utIME  #3 pHYs  ~gAMA a PLTEf333f(^tRNS@f0IDATxc`@` cd dAp&fa0#B9#j7B3IENDB`jline-1.0.orig/src/src/site/resources/images/ico_file_pdf.png0000644000175000017500000000043011550705746024270 0ustar twernertwernerPNG  IHDR rtIME 91 pHYsnu>gAMA aPLTE8kkkJJssZtRNS@fpIDATxc`ede(dRa`Rb` `P*``4``R` w``(obi@"4$VTZ$7 1 QII˜@40a % E\\\9IENDB`jline-1.0.orig/src/src/site/resources/images/newwindow.png0000755000175000017500000000034011550705746023712 0ustar twernertwernerPNG  IHDR/+tEXtCreation Timesab 2 ott 2004 09:47:07 +0100:?tIME  4~ pHYs  ~gAMA aPLTEZtRNS@fIDATxc`dB0E Ja@XJIENDB`jline-1.0.orig/src/src/site/resources/images/logo.jpg0000644000175000017500000001003111550705746022620 0ustar twernertwernerJFIFHHC   %# , #&')*)-0-(0%()(C   (((((((((((((((((((((((((((((((((((((((((((((((((((Q"D !1AQSq"24aRrs#67tBC=!1AQabdq45"2r#$3 ?$_N?7IryuNƉ-%ҪOpǛ{s+Hʭ7:3o8rr+W)FGHS⢤-;px= Q#xߞDpx= Q#xߞDpx= Q#xߞDpx= Q#xߞDpx= Q#xߞDpx= Q#xߞDpx= Q#xߞDpx= Q#xߞDpx= Q#xߞDpx= Q#xߞDpx= Q#xߞDpx= Q#xߞDpx=ۊvJ.]'#M]O#l &z]W>=GG{ؑH~QقyMi4iV1/ww]$SNBX2^s][R)mJgRla0d)xLh$9mG 61η; S#a1TJiF2Iu66,@} Vu-- _@:Ve=8-;cJ{ "KipK˺@lȜGpW кHdi_U1S,:mźlz‰UDknA.\ؚAnĄ,Z:ڗ hD]rVVEwYgBp}6I,5kNRmՏcݤX߭K& U xÁ:! !B!B!B!B}I4H~Ox|+_v/>"O|#`S~ZM'/(l[@ȫ g4s}/ɸe#T2=1ީq NZ5Dgq.q$onӳG1q`PwխX2&G$]k4mL暚5S tT e{#6.$q^6 BvAr.{S+lyllNGNHa+6/t_`̚7̑=^OsZlɩYH=Z:K;=xi|TsGG6-Ml9=I'&@rOm)?+FsO5߰Ū 03tiSpiQ~Aظ-gIDroI'ߖJ|K'wroG$v1{y*#`tjc+,SW5uL.7jg쳇*wp߹;VUAufsk_./KꏴߘUM? Pp/sw9|UchN,tr=N]8:CZݹ~8j%AQ4qy_Bōuav7&HoW8_EB0՛@* 8MpoT߷#Gf 7urL`XO#JJ%AtL 1[./jxkx;SʲfY|CK;G^W,nJ"ug'->E!:Q*q1k)Z`=WWZ\2З\fo=wSBE5Ccwÿs!*E[ Kzp?W<@b42XohR$пʦ#H˔B 9kETNInmGxe#T5u^ s+ mml0LlD/-=ۗ֩7\mdmFz ;O6;1?.h%d2NO /ncbdItkH5G pMSŤlBRY@r/Js&YN W~SJ[U; u֛:™cuRh6aŔW:FG6Nrۛuo\6ir_-{Ir8)O1鵆Fi"`򄢦Dbn֖ &x`ˊ>т߸%Uf.ݺ'E@Ȝfii}I4V \j$G+ϔ3 h)PCE}ޯI' u+ &,X:>oJ(%q{rycI8"$Fffbҟc-vmS47fT *he! RS,Gk&IPݖг0:306QS2& /dYd`#nyғl_hj;Nq~P[!kh;^ ${AXz>oJ%q{ry7,F! YPo v_Ņv ; nPk{*xe% hkEJJ +~OS^Ӽ dFI_lFci7#J*f6< My> 6K9voT-D3sO,|5_H^C4K5sB?8 Ш#-FrYfIuèԀ"zsC9đ*IXb suB.-p Vp&\,Z]_fkCEZၐł]Tb j]@ecrķn{nMM15CõiH[qbūV%$p`},OhӲE2"h E3.k #p}]sCڊ ςF*mGsr4ؐް?WXe)"ՠ_f Q6&0h[k+f9ry(Rc;Oe;DڮrAӦȲ/uHS|ٜahcKӔqsOз_WUAg&QdGO9N)%5 7\jXZM/dBh % 3^k+! +!B!B!B!B!B!B!B!B!B!B/jline-1.0.orig/src/src/site/resources/images/collapsed.png0000755000175000017500000000033611550705746023644 0ustar twernertwernerPNG  IHDR utIME  )쉓 pHYs  ~gAMA aPLTEᣣŭdzثutRNS@f9IDATxE 0mBH#3[.g2y`@ZxCdsoif]IENDB`jline-1.0.orig/src/src/site/resources/images/external.png0000755000175000017500000000033711550705746023521 0ustar twernertwernerPNG  IHDR/+tEXtCreation Timesab 2 ott 2004 09:53:51 +0100ζtIME  :>mu pHYs  ~gAMA aPLTEZtRNS@fIDATxc`d``a(e0bP`5 dIENDB`jline-1.0.orig/src/src/site/resources/images/dotted.png0000755000175000017500000000027611550705746023164 0ustar twernertwernerPNG  IHDRͶAgAMA7tEXtSoftwareAdobe ImageReadyqe< PLTE~~m5tRNS0J-IDATxb` Fb`d FFRf@8`IENDB`jline-1.0.orig/src/src/site/docbook/0000755000175000017500000000000011550705746017324 5ustar twernertwernerjline-1.0.orig/src/src/site/docbook/index.xml0000644000175000017500000003627111550705746021166 0ustar twernertwerner JLine 2002, 2003, 2004, 2005, 2006, 2007 Marc Prud'hommeaux JLine Manual Introduction JLine is a Java library for handling console input. It is similar in functionality to BSD editline and GNU readline. People familiar with the readline/editline capabilities for modern shells (such as bash and tcsh) will find most of the command editing features of JLine to be familiar. License and Terms of Use JLine is distributed under the BSD license, meaning that you are completely free to redistribute, modify, or sell it with almost no restrictins. For more information on the BSD license, see http://www.opensource.org/licenses/bsd-license.php. For information on obtaining the software under another license, contact the copyright holder: mwp1@cornell.edu. Obtaining JLine JLine is hosted on SourceForge, and is located at http://jline.sf.net. The latest release can be downloaded from http://sourceforge.net/project/showfiles.php?group_id=64033. API documentation can be found in the apidocs/ directory. Installation JLine has no library dependencies, aside from a JVM of version 1.2 or higher. To install JLine, download the jline.jar file, and either place it in the system-wide java extensions directory, or manually add it to your CLASSPATH. The extensions directory is dependent on your operating system. Some few examples are: Macintosh OS X: /Library/Java/Extensions or /System/Library/Java/Extensions Microsoft Windows: JAVAHOME\jre\lib\ext (example: C:\j2sdk1.4.1_03\jre\lib\ext) UNIX Systems: JAVAHOME/jre/lib/ext (example: /usr/local/java/jre/lib/ext) JLine is not 100% pure Java. On Windows, it relies on a .dll file to initialize the terminal to be able to accept unbuffered input. However, no installation is necessary for this: when initialized, JLine will dynamically extract the DLL to a temporary directory and load it. For more details, see the documentation for the jline.WindowsTerminal class. On UNIX systems (including Macintosh OS X), JLine will execute the stty command to initialize the terminal to allow unbuffered input. For more details, see the documentation for the jline.UnixTerminal class. For both Windows and UNIX systems, JLine will fail to initialize if it is run inside a strict security manager that does not allow the loading of libraries, writing to the file system, or executing external programs. However, for most console applications, this is usually not the case. Supported Platforms JLine should work on any Windows system, or any minimally compliant POSIX system (includling Linux and Macintosh OS X). The platforms on which JLine has been confirmed to work are: Microsoft Windows XP RedHat Linux 9.0 Debian Linux 3.0 Macintosh OS X 10.3 Please report successes or failures to the author: mwp1@cornell.edu. Features

Command History
Tab completion
Line editing
Custom Keybindings You can create your own keybindings by creating a HOME/.jlinebindings.properties" file. You can override the location of this file with the "jline.keybindings" system property.
Character masking
API This section discusses some common usages of the JLine API. For in-depth usage of the JLine API, see the apidocs.
Reading a password from the console A common task that console applications need to do is read in a password. While it is standard for software to not echo password strings as they are typed, the Java core APIs surprisingly do not provide any means to do this. JLine can read a password with the following code: String password = new jline.ConsoleReader().readLine(new Character('*')); This will replace every character types on the console with a star character. Alternately, you can have it not echo password character at all: String password = new jline.ConsoleReader().readLine(new Character(0)); The jline-demo.jar file contains a sample application that reads the password. To run the sample, execute: java -cp jline-demo.jar jline.example.PasswordReader "*"
Frequently Asked Questions
Can I disable JLine if it isn't working on my platform? You can disable JLine by setting the System property "jline.terminal" to "jline.UnsupportedTerminal". For example: java -Djline.terminal=jline.UnsupportedTerminal jline.example.Example simple
How do I customize the key bindings? You can create your own keybindings by creating a HOME/.jlinebindings.properties" file. You can override the location of this file with the "jline.keybindings" system property. To examine the format to use, see the src/jline/keybindings.properties file in the source distribution.
Can I use JLine as the default console input stream for all applications? No, but you can use the jline.ConsoleRunner application to set up the system input stream and continue on the launch another program. For example, to use JLine as the input handler for the popular BeanShell console application, you can run: java jline.ConsoleRunner bsh.Interpreter
Can I use JLine as the input handler for <ulink url="http://www.beanshell.org">BeanShell</ulink>? Yes. Try running: java jline.ConsoleRunner bsh.Interpreter
Can I use JLine as the input handler for <ulink url="http://java.sun.com/j2se/1.3/docs/tooldocs/solaris/jdb.html">jdb</ulink> (the java debugger)? Yes. Try running: java jline.ConsoleRunner com.sun.tools.example.debug.tty.TTY args
Is JLine <trademark>100% pure Java</trademark>? No: JLine uses a couple small native methods in the Windows platform. On Unix, it is technically pure java, but relies on the execution of external (non-java) programs. See the installation section for more details.
How do I make it so password characters are no echoed to the screen? See .
Is JLine a full-featured curses implementation? No: JLine has no ability to position the cursor on the console. It might someday evolve into a plausible Java curses implementation.
Known Bugs Clearing the screen (CTRL-L) doesn't currently work on Windows. Contributors The following people have contributed to improving JLine over the years: Marc Prud'hommeaux Damian Steer Dale Kemp Jun Liu malcolm@epcc.ed.ac.uk Simon Patarin Amy Isard Ryan Bell Marc Herbert Christian Salm Future enhancements Add localization for all strings. Create a BNFCompletor that can handle any BNF. Change Log 0.9.93 2007-11-13 Fixed backspace handling on Unix/OS X. 0.9.92 2007-10-30 JLine now works with 64-bit Windows systems. 0.9.91 2007-03-11 Added ConsoleReader.setUsePagination() method which allows configuration of pagination when the number of rows of candidates exceeds the height of the detected terminal, thanks to a patch by Damian Steer. Better support for UTF-8 inputs (issue #1623521). Improved list of supported keys on Windows (issue #1649790). 0.9.5 2006-03-08 Fixed problem with "stty" on Solaris, which doesn't understand "stty size" to query the terminal size. It now uses "stty -a", which supposedly outputs a POSIX standard format. Support HOME and END keys, thanks to a patch by Dale Kemp. 0.9.1 2005-01-29 Fixed problem with the 0.9.0 distribution that failed to include the Windows jline.dll in the jline.jar, rendering it inoperable on Windows. Implemented proper interception or arrow keys on Windows, meaning that history can now be navigated with the UP and DOWN keys, and line editing can take place with the LEFT and RIGHT arrow keys. 0.9.0 2005-01-23 Changed license from GPL to BSD. Made "CTRL-L" map to clearing the screen. 0.8.1 2003-11-18 Fixed accidental dependency on JVM 1.4. 0.8.0 2003-11-17 Windows support using a native .dll A new ClassNameCompletor Many doc improvements 0.6.0 2003-07-08 Many bugfixes Better release system Automatically set terminal property by issuing stty on UNIX systems Additional tab-completion handlers Tested on Debian Linux and Mac OS 10.2 Example includes dictionary, filename, and simple completion 0.3.0 2002-10-05 Initial release jline-1.0.orig/src/src/site/site.xml0000644000175000017500000000244511550705746017377 0ustar twernertwerner JLine images/logo.jpg http://jline.sourceforge.net/ SourceForge http://sourceforge.net/sflogo.php?group_id=64033 http://sourceforge.net/ ${reports} jline-1.0.orig/src/src/site/apt/0000755000175000017500000000000011550705746016470 5ustar twernertwernerjline-1.0.orig/src/src/site/apt/downloads.apt0000644000175000017500000000163111550705746021171 0ustar twernertwerner ------ jline ------ Download JLine JLine packages can be downloaded from: {{{http://sourceforge.net/project/showfiles.php?group_id=64033}http://sourceforge.net/project/showfiles.php?group_id=64033}} Maven Repository If you are using Maven 2, you can add JLine as an automatic dependency by adding the following to your project's pom.xml file: +--------------------------------+ ... jline JLine Project Repository http://jline.sourceforge.net/m2repo ... jline jline 0.9.9 +--------------------------------+ jline-1.0.orig/src/src/site/apt/building.apt0000644000175000017500000000171011550705746020772 0ustar twernertwerner ------ jline ------ Building JLine Building JLine requires an installation of {{{http://maven.apache.org/}Maven 2}}. Source code is included in the JLine distribution, or can be checked out from CVS as described {{{source-repository.html}here}}. Maven Repository If you are using Maven 2, you can add JLine as an automatic dependency by adding the following to your project's pom.xml file: +--------------------------------+ ... jline JLine Project Repository http://jline.sourceforge.net/m2repo ... jline jline 0.9.9 +--------------------------------+ jline-1.0.orig/src/src/site/fml/0000755000175000017500000000000011550705746016462 5ustar twernertwernerjline-1.0.orig/src/src/site/fml/faq.fml0000644000175000017500000000137511550705746017737 0ustar twernertwerner How does JLine work?

On Windows, JLine uses a native .dll (which it automatically extracts from the jline jar and loads at runtime) to access native console features. On UNIX systems, JLine will perform the necessary terminal setup by launching the "stty" command.

What platforms has JLine been tested on?

Various flavors of Windows (95, 98, NT, XP, 2000), Mac OS X, and multiple UNIX systems (Linux, Solaris, HPUX).

jline-1.0.orig/src/src/test/0000755000175000017500000000000011550705746015717 5ustar twernertwernerjline-1.0.orig/src/src/test/resources/0000755000175000017500000000000011550705746017731 5ustar twernertwernerjline-1.0.orig/src/src/test/resources/jline/0000755000175000017500000000000011550705746021032 5ustar twernertwernerjline-1.0.orig/src/src/test/resources/jline/example/0000755000175000017500000000000011550705746022465 5ustar twernertwernerjline-1.0.orig/src/src/test/resources/jline/example/english.gz0000644000175000017500000037763711550705746024507 0ustar twernertwernerE=englishdۖ(yNc]cW]l2d #O V0Y#@~ ~ y]q._m2Ar |y,d.L#/[9JD|[oKYBR.!ΗuYgݨNxYY %ƈƵf-dL0f4TknVy+4a,)) a#/)pR8m*OYRכa";sULFN 7+Әd-ƿ6LiN }6g%\߉K0Thd1ZZugwy;"yV|tvark-DERU0AiX06B'(&1Yyo)P ,oV^zZo*uA*A?7 #U\O1d724պ!S#%CR<iPܕw@mce3u޷ AHw+ ba/p ʆN1gKNح6LKHAAȠj e]ø<%8N`D[llQT|nmKjv,! &{Uo֏րyQԻj*[ga3ڙ2J;(QPS29?CYi9axڜ<:\(R+%(˯_>_zMh(FBY6l'>y5Uजvvn:krDR8%*49)gY9ul7 >Z2-gWRB85)h:RJi_j0ΝvTqN0=B* h_V-KÈ=0<v}<ѱgifa"ɱlgG<] Kct|D줜| N$:gTyΣET) |G$ K^%]%Hi7 Jgw֪<= [NmokFy=ikAJSUNOwߓhik'hxVIƉ}K-82+MmPsx*`v=ڋ*[jXUv7v{c'Y myЈѤMOۺHއ$wկK^s&G ^Y_imŜO# >诐YBb0>crsb/Y|"S9]Dh5"}  |lMi͋L*. N,)#?{n ܀uaq<Ԓw@q9;%rMlr pܼ;ҙs&ERzsS7Iͬ|yz^9*%˰=1@roGvCKC4i>L)6`mYL4vBZj>ɺdݚN]1*smg 9b?윭SPg9d `U%`lTK7L l u#3Qk_R.HPP]ی!畍=)Iyex,e7 )rJv{bFGm~..e'ElR.my}{rp{z FpGXlAHEBaoW6$u&7'5mV].;vwgQ⟡â1(st6#RiOior(yjLiH3CZixll7T2 ""MI&lj =fwUaY)'k32H0Dcбt dΓ~Pwm\r|T7>nyW5`tu`=B2X$I#ybkW|Ucd^|QU?߮u!gt0 ILHV~"{|GwdP~$sJo\ b<.$*Fs_~tP;*xýv\2@k8vV 5:j,b}_ME(Ŝ4i_`6p Ҡ[5z9Y3o7o]iĜVRlX \ pi>Ȫ&fh>aګ6.4yJc᭢*={ԟ #XT} hd4wCx";xP{#CqVB7dy}:kϰ3'alTؓAչkAxQ5ҢzHOw[B2puZ-iC133Sz3>>) [I/T;AGH]}E=؂䏾]AzW06jPo5-`r{!laUBE?CZkEx 9pg׹t6+hFr\w f!&ZPfg u )X%|e|ag9--6Qq34|!69%(7f7ʆ(C?V=_CPVIS9PuR&(Vx좨?$ 2`rÌkeƨWu͛@T,T F*A_^ ɹ \桎Z0 /մvꈅPŰ V/׊F~h: 1I|X0Ƽ>ˈ3QjPHC_.VXk߰4Ew 5iCW:xVξtiac Dq4("xK4HU> d6n9-7*ʤ͸Ygy`] Jg.MafՃۼʬ3PSْ?^TISvg7FRRs#FruOzH,cT"O\&~LQ$rl =Ex,>q0D/'jEZ"dNPZ03&sX;on0n*FCX',( 軗 ނ=L ̸Ċ;dT%XXVixYeN⚆Y͑[Dnẵ֭Eƕwd c#u5NJ;uF2]p::"K+ U L%.g$8} vU"s լ5'.#f*k>3|qETvr ?sC|FC6LU0PAT UV,%ڀխ|vAdf A1) ׵ ]cZ=u(?[qa OF㡅A5(P$Bm;M e KXQݲ(][WKK^%z7yMo6*ԓZzA G| ל(hM"u;5ThNOq4\\= {> ]|Cz).r<ЏX) {%0FvP̷sZ:wu#!;e[ijȜV:!sA޳*l^XgR*\AF3;q,טrYUYǦS*LZanʋA k=sz8` \=Qkhm{k דߎU z5D;f5 Lx@Qg I#F?t+ .1Kkx<у4aP9|gV̤@+X<%^-(f`C T&w`[|j_رlן:"PmPU= %0tuNޟX7 |U$u`+aeұh1YMPCNg ‹$R|IH{jkě#-ް))9|E8:-55s'*Τ,D5uJ3QA*X,՗SYSUGncYJ3Q0/(aS ł^ckmN*oQ|rx3-J>:lJ9d8X|:ׯ Na,O8x;$]9 䈚Ji⺑)*Ur`Tt⮚N8tHrJߔH(uMJߔS}M,ЍM'O|URn܊:wi8\VoOX:wl_6pdz"JYiH+fk r Wghh]g@;kZ&5NX%;c:L26WG9}:C5Sgx 46X)9T7aHC7dA sX։Hy=j¥XBra 6\-P<0w)5BuӃqk>!˦Pk⏋(FK\\˽םJ*ŀ'|%'ۥvAűYSIg'[F5HMv[CV㩴Vƫ0$ΗMdXcfAvPΚKz8+¼R1 7-T+Giٞׯ0eҝph'#3x;0kj+.yU7N bö0A&bMDcq_ϡ~7\|(J~+u~ZОI XE(*ۮ!~kM{1}4̅ [$C{6 sG,:w Yj͛KaQa{rp#`W+y<+Lk^[_K+Og͇{ng!F+߂ niY'*rk8mRn@+c `Gy V~A~Wv3`ݭvd]ޡiJԞf(/5|.+>‹_EBiex[eoHr_J3ݸ}2$Rӷ&3I@t7. D%ǀdi{J U@萇LyЗU sҗSE '{6yM4-hikm 7_m6_}un `_ljhKI[BaMV4>ˀǘ'Zc@׻W1vϚwz0v-ԟ}}OpN!m`'VV"y'Vчiߚ?mR>޸AԈrR7z'm>+by*RC -J%o#m3/7?(b mkL)\SwM57xHX:ȖTA+s"?ErdWX 2\bc@18``moSxSFǫRٷD0µ ԳPLh2 c=h 4At_6-!op?jPMƨJ|UN(x#6 gں|׺W7Ӓt"yUi2s~a n >k4GτB~]2^sxW|Rne|L&$mp'HG\0&Hsn}U3εmq5`4+D@V4mȫV1)O(epL.*T;";67 4(m~uWw"X#U;h@_:mkm췭ְq~BS⤷f).ՖʉƎsd\O^v)e+e_KʵUeFQlcs>fάaMiTA` Fk#ϙ ^.NZ({/5, oE{ɻU${;VܜJ}#ʺڞ][Z5w[#韤fő6m2=r1I]Ceڊ+]0^vgN:W+bׯ[1>cھE&wl'.uqBONJf s˭C6baPR=Vj-9T{Z gh,ߴrT8]eoYMOQn/z1D$𵢗d5vBYO{bwu֚iOx۱g947=(UolUVh:bbU#J.æ"n4{=ޒ GAcƶzM[6ttkTuzRgMHG3Qd͝Y&_ ( ?w 0 XVjc|{? o1\C8 tJxWPPB&!ה9C_ڲ!% Ac %/o,7d҉/])FlY$ٗ6x/X' d0}-9cl/ai͊74k{__1죚x֪p/ϟb셙{lz.;HiVnHhx7X;&#UabJҡ,]/jLeǀ򅷽@=}ow?`Qw0 `oQue9d4ғLuL?|bo~?mxwڔB'ů_,惯?Pjl|b'ykdY!iШx_>=9:j:YO:|;_رѹ$xˏ ;¤/./U!F"WWl[-4M\z˜~}}%hYK-a92`dG?M1^DȟUY:?1LX!͵@ biN;ך Srע%5#dU-dVsaȾu`7WIXo!oNB_3I$Qn,7YJ/ׁ-؉XXu(L`Z6IND07;vJL"mڮFRΞz<)[ 98t%""iբrEa~ 0 :"! :zƎ,ɍ"+x/pŝ*c69U}{c1ZE8o,I妻*{SvonG>֋sz    3wl-x5ڸ IMoo!mqʣ̉7;:=ƒ7{ R2' O N }"芾_*s7 6׬` Ak!#<*Yd1,P9W՘yGĖ?!qwhl!)M+MU2,K`*tn~+`Fgz PZ ~hpƇ@׀0}j&?.Laѓ|aD,tDT5c;ۋZҲY  &!BϡlnI\cȖӸ;鴘WdlTیc,7ܴy\A'w2ɧ^c)+k8߫L*4Zſ=ϭ%)h(p9+j/k_Ɋ3A=naZ/F_V֬lLzr̒W2eSMt+j˟R1 \2_jhjnQ 0ϤMu/f٦1,pR^a6Y]9ve a=ju3+a vxr;e8oM~yv"rd5?|gU:zTn֏%ǒc=Ì.c"(/*=연drS:ytJcg',EQ*qD3}Pf-Q͆d  #SRgׂ̮#,b@aj dIW'__W Xd 231&\˘_`7*B[ .sq]mw 䩰 VĂeSvJr'GPL|`U$WTf-ڂ/VŃ w9%Bg; ^EeVf5Hpd&F_uQ!%M,p,|QU|CFo,:ݢXXeS4~vvz-ȱmU4I#)N/6bl*e/%!kՒq`q@X d%s/!Sylo얰T6$7,ue1Vz ;g ]>31)e PxHát%\: &B]sgv>++1N>'NwQ% ʏ`BEvc uX͞a-$+MX2i#ig]k`/5Pb>idOlɼ'MPОFE08' yyfw s0惆<~+7Z_dK;S0qB^5(O0N j'U!ٻ'H>(/JZ}8iX J8.#Lg|RA'G~CEY<ػ*$e0:sF{VK dpFgVa*FgJ$-`z4I=;X}Ҡθ  }'|UC+t(-H 02{_mz6Lb Hű+Wkrm%>l^0>?w? Jsf pdLGS j+IGuV"u$ڟ6qh~N< /.WomJ&q}љ}.lE,X~u4WZzoZx'p Ce 40音3@d;\-ޑ_p\:zSOL<%S.XS3?' ,QTSw,ZU3:)۪DRo{Đl<'.58& 8bɒH8ޱ[wr/MX5 ),` Щ˰RMNtTi i2$0:f\]wmD9>-1ֈk1(I`x="Pڂ8-1c# #gcAuyFW h`g]B.wӷtNL1L1LM1 䰨"(s/#L^|FEjCfz}Kic73v`rnS]a۬`fyc"G?;X|sVp2}@/Ơ O:=2=c2#['דs'O:yz=(e_ȣ^dh)Y ~}3v#54V6Q\p]Y VMRfIRk/aJxK ր;htI& wv=VVj&"I2%ܵbO>5ګ/(vp͇i2gXROW93b**Rb 3[ lq]Q4oǛ~~6jaˑe5yݼ_|ƋqR4BVćH=#1 P΢+.d$Kɔ͢Ul*}Zwx/`;Q^v%xNAɴqmݲE`% %t9Rt1*ɴ8+}'jo-[=Z]_R6U:mţH=V}nY6WYT|V~V~V5x~썂q9akz" ȉ!lKXf6"H5hW5~Va0bq,tŬ8tTzWlǝ7M~PRC C>?W.bݰDVrd K( tlgբ+(qZ_\.&S\pVl0Y5vY5l7ثG/.+,$^NȺfh XS >\zc_&%-JC^q;!>N̿9~"]?9ԯV[Xn_C\hSFw"([HeаpxfB#.g^7eXsT [` ?E\\įnWչ8paPT@c5\&%ėepz>}) P< EUݐ^ {෹pSh/|ۃ4W-k0mi\92\q,8(m6z}O8p\R 5^S6u5z9#V*u?ZOI+{#H$c_MʾZL&SqGc9U M +7̅v)EG](n! Kc' -NOG$%P mWXʣϚYd &oThج9F3s w_ds2Yk:=z5^zhe2c{0LhǠϛ "4 a4+-G lIԶ:#1de wT=kp2|+L:}zPaKg?ƕb?\&Hr2eT zc<dm h?@Њ|2d+SO]o(GRW<VSFIFJBTXhzY1= 2!YrC9m(" fl!&fͮ</UA8PR7{&c{}tmO02CrE\(1DUv" 8%X>%{" mE6RyO2G]XC3xsAnoX,_Q4RN0[b[AWIpB`U&˖rF]WU;Ku[I|V)°Luc/>dJ;hl[˅RT+TH70,c9!=dO"s?___Chv"ۉNx; }> Kgbe.S] ;qG`qVuMx[#Y3Gؾv't&X!#YC9;-Ñ#:%[q.oAnR@\V~r[/PJ&TR'ێCT5?IQ/,FKYUu֨1(SW3?ahdAC>">p^a+~uɠ! ^ `iik)n#V_5Amaf0>~誫-": tDvDvՇ<L,jhv|Uwn\PetZPv  ?~E+͢o2egI~&R=lkFlv|-@ܶ䙏 V_رr_ggDS>(č:Xj^vѽ{{tޣP3]RO JuH_pQ{[E$t2wϤ^㌒h- c upO&׮5 3cheDT|$8*-۽YwU ;;s%>x j؎aGgq?҄2`a01, L d5S`JM@nck>$J&) }î5?7l=q`׌׮ oxTyzkdo,A&̊}{moƢdK?.8Lϗ!oʀ"80G %pv}SBkeeq,`l5oNr/F}Ӡ$߲drdWC-Kv)Y(A?=쮉; ]ӨG2,Unԃ݁ޱ{*cxi5i<㡱{&'d`WxXsQZ$5Ыj꽸~S.gXŎ1VoR(wAq>D _Jbb ŭjq[%]\U`jhD(& *;?J~rI%$7Y EԵvB6JTm]J^,MB5p$}H!F=)ﶹ9nZ ls`?ut:X2+ԟ[~*G~Uɐp_W]5{wu`Pb̖EqP.G~@k9DikRq <>M_B%BsUAݘhpaz0I@y+-"{_d=iBw)zhF q5kf^|΢V_kkΕƎny]|Ѭe 3P0!K/܀Ql@ 1p%"ȾBر rfyHdz[kd8rf^t0ϻkbu /HW ѺҫӤ\qu2c|}607e+vT,AK%SpЮO\j n畟BCMW} U5q+ubdz@jDZ/#o6Wy0@^0Pf~T,ݖE,m?8Y2]lU۬&p/y Pƒr4D޸QG6؋ _qBL";0z>a)Xx(.rpS+PZkB?1y T;F-uo`d5/t\AB_exѻ+9} L1&<L؈NjKk .MU1Kd ;ǻ,z gjX&t*T]X^ &,ʠY*'Mi9Ru\R%=њ-ۀ[F{MQc84'>-/ eVRuUe_CHMISwn8TD#7?,,nt6Wظ9L'|5/dSsgrdyM&^UK4lgؔg`cdsH n',[M;'tg' zPLXg묎+qy,'HƭIw7U|pU-ӕgqZ'uRo^jdQdUck;v"TZU_^YAR{!yו|0(們 7{7[rJC=\3?c#/&ꢴiOX:wT1m.v|UB'?Ay ؼ]*ޤg & ܱ(hcھyZ*HoR8<탉렪R]O\WE%%4Q1j2٢"\ANy\]Lc/ d)t1r9A9PGR*>cBulKMrI im^F74(A)ǢH`aDXs:tgZw15K>Sl|?f0ܒ h:: ,UzyU-A(] K<38I0EulwM* sT7yD]W4liUIBcFqOeΡc'C~b|zJ䗳{_C]JT:1+,ǀbPϮ^E Bk" Z4FR|&ڪ:?n6 %`eʧ\;-䖩1phY<wTsG?zEO:a_RY4zF5{^-Sl/ (CA7d;%񆳎%'N~ rL, TVGƺծ,k3}\9XکW$`uXJYT V 3:%(;zꌟYIq܉Eί?߮iS L PN}}* |ؾn})69 5Dft8Q1_5kce޴ I]#`I]=OT@V[{Qet<ӯb%N͛#36뀽N9P(aquг-y%}7X( I)N5HP󊞪h?;fvSF#5ႂ"DÜ@8ŞPWf,iѰej&@0*5T ;vwb\` iF3]y=32$7 :qI撓cS!ye g@3@9 ct~'ΈO!2_+ z)wR08@A%$Ur|!o4 WwV8lbq ÉI =>)X}?i![??aYIw%6C ܸy>h}aIjY SME*%4Ќ;f \CV{tj&e3$oxaf7$SYK*X2 >˼d]SQwlJӮ9\y颍L>oCOE@b[&2,d;;;|"`((6G,}gøu@2En^%oSd֍&NL*/h櫤QQ:v ɪkM\3Y| Ϳ.i=7)U.u8bUܫW5,#iBۮ7PS :pS2'1+Mr0"?Ijz%ʏXTrUjr]QUhrtr"4uzA٥P;gt\Ɖn.(8\2eY~K@PcߦH`"mjlSM- k†֖ w~A-+_yeLxmQlX SD lF$oώۓjQHtIX 6˱J#Gu0ί?#PgF >ItK8)t0٨ >EmAB+ixD:Tb;3˼5T$X\ [%jama;씇SH1t -Vub(Q. T~__sIJ:^%@>~8uE-_bb Vפ+F{*& -J-a`827ơ0X ]J-)s Fp@&”.x1#4tUC x$v a€֐ *Bt% \S"5e*:)`/mlL:i@1&tkvC,Xňh"%R%ռ*'eV*Es&Y2~>d%^9Ddb^n%!e/5[pI WL8Ytw.wECELZ]}A8䞏2LCS2u`ٱzlPy_nVݦBVQUWXA|wOehJW27C@,GZ !s7'z}ӕ'ѵкgŴLnT|_2aOE>V,*It&jtl>:_2!FbI*7K>Iɍ>sNHphnرŴjv`Ǧ5f‡t€/=?qrS2vTL3)JQ4ߴr."z3DD"}˦9L%$,bZ—ŔOJIũ m6x, ?Uk*G>UUhmŧ 2B1dcLI ?_ب9*/ua<`SMM0Q%[5/}&bĨ5>yucy5[ڼx}I)>)W 1q T =_`K L੉z a=Y4`T|ztJV$If} ѿTZ^5 gcaYig7v-\P]% m.oj O> "DžA4OnLȖ m>奘˕`JZSs1z{ݳR?cupCae1PLbL>$Mr 7xMAav|92#mGrr6/-sbt:oL~?@Xl1)_aҖ) n (3H]wg{)Pa9͉LmBLҳNBoYYvPuQWYw!$ef!Aϟ}EަGXu93Ҕ89iVev'&̾ dr]i0o$_ZP@E!rŇiE^(c:$V<3cs>)ŚRp bZ G^WFF}1ZaoI:A5etAL85}rYRI˵:Vo~dDO4"ihV[B#.?fRQ Rnm])f/r3uBhådζB6|TDӹs$Z[:G]7Pw +k$YzW몟 rgk+& c#eqvBV')͇ZoW&|=W8zWv:c8^u8^uz5No__Ev;Rn@yj0>Y)'EoIu5+ȏIϒJȂc'׷q `OI8g(0sqL(6l㺅gVYn)dXp8`uRYXyԝUr vLuKך⹡LGg Nň'լW.,V5G.n^RRQ\r. نϲVQv%㙀U7F[C~"wXF{J{2X,|ci|TFT-0!pS12F"!I2MИwiۚO8|Qor#82,J:pO\zo'qI{Q?FA1]--[@dْNL~7=(O[r-*&sWr ؃уMk[b?O% /`.cH2c NCRz6j>Qـy:km$#wdzrIZS8EZB)MkԢ_"xJJ[)\_TKxK n~Z[s\g:}+D*J:+rf͢]0\CŀR'uCI'L~ ~RSď|%΋0ndB/Us9|]pƁ*pPgM)E/E_PsbР!s<2QP]JS"SQ(h吧'׃66=7lwi&ѕkqa}z7Fa'g_bvvӟͣ¢gX"[ĥso)w֔5;747[Gݦtb" `L)Kybf&Oґ"gh#r! KŴtۭ-SGHGJ#h~Ceߧ9xZ6dnweNZY g{uJNC&q=L-^ӷҟΥ?KVӷҟNpg'ErBQ猪u96pz}d(A-AԜ[<-9zڗARݳ|twԘJv Q cgkJߵ9Ҡ%]|VrJ/)SyjO=|3roU۰œ#2+>Kvk_MhWlyHmn]u6g݉o=%B#&u+ʼi[d%TƖ’Bv%KlQabt7)WVJ܄C3^5*p[Q`J9)o1DjQ96u5ؗ }˘[ߐQm˓#x)r (6">9l'T RVi}EtHi2P051(cUSysk7W X4SI=c4v, O4>yz3+/uok>aXKنʑq<ɋ3eEjɟ ƭT( lUMnX !'s%{dGf[ITن,ӄd/7rS_>|OC g^Uyd5_@ Xb7[(E;)uxlg;(&$UҚ'Xq`$x|5]}$pE_!'Dr )ϻv SHٿ&j,6}ֳ>?w[ākvYJW|nHnwJ9:W:rr [yo;v6o|Y*uO)zM߾kgǖ 4v(}Ux<+D&W'Wk4%-eҩ:C2 vgZMa//j`3%HQʮ喹a :@R呸AVNgj(;b.j&֢-D8SRul ʦYD1 D86aQ2m9@.Uţ#ws8ԁ<WŬ6w;j'JE]ܽGafUe׭밝 ϴkzveE[{Pk>a +zaj؜~(ͻ%s<~v%۞,L7C$W-ɾecvO4{*Oz嬊.8'tJ=SҿV 7v+Ε >Y׾>"n0 xଖ7O0ܹ'v^_6ϕ_J4=ۥtK|nn9#d+|GR9GcvtU~jCY U>jH(TUiҒrUz{[c=Fnv*耢ѩYڻ7jh2\pIH<=>ͩ\*&X^CwJ\7VHh^ƃn+~D Ľ 8Zys[Dm qGCWH㲆`FSA`,O=)%˱~L=Bڒ!bApBIXZsx]ܫ _5i O*H&23P(o.L 2:oLپmJmsn7u-kgZ})Tt ^-#ĵVaP>4(sC3KPc>gm̴J2-6+`>:  ]>)à<-**.2^_Ţرcoi9K7yP!oIf%k,&"!'5%1L>rp e$s+J˅̗eUOf&cRmBC=NP;ȚGg?}1`Kܷg!^|4U=p!ޅVb&)6М#Z).›IroԾ^:i$H.SSKzNO9$J<.G# JыKkd,'x2' Ư? U;tQ1/l)}j݂!e`BI3l8T .7:*<󨰕? bmipۆx,Ym +2˓vRT&J1ZI)D95*aY:Niwʵ1 J "ر;ZCr_C _jk0LFFĝel9DqBe0&r^G~_>;cTVEv?1[{.|Ltr;*RR`ѫ'dGsA214wHl41?cWQf %Ïb"ӮKZ%ypF"HW{CM65SvTZ;#$sѮڵeb,S<^piQyfwuxvC)rbtvL]P ͧ~cU<=!2ۋSȋw'=鲖 QT\0PU?ݽݽ=ze{e{|eUMf}Rpl ]r]J^U`kSejS~ymi !}U4f <l,xVIeB_eCs~1Ҥgw˥k> 0(y@ '3;6ׁ|Ovbecׄޮ"vsP;vw 9dd8j[|6/N4v, XwOk>e|1c`YJ>!{cC iŀ=^4oq_81/ u98LV>=d\mb>_w?Mwg+BC>2"#ϪmYmX =E 8q|^B6* 3 %Z5rRήy5 //y|l޿4$L~og@}(9RPdGd )&G_RRgv%dsZ1m'U ݊:4bQ$=]8i@,E\ۨ)EP2+&:",-T$^:-.$*e(!yG`w?_d?v7]gIi5!׀Dc) f:'.%Pxo_P_$ dTX\-fǩW j*pL7J;APVexiȑKUj9j{,go+k4]ӪVӨ1l/ʵv"#@Cه 锦ѮLg8 F(?*OW?vS;*4" h͛ZT۲|rP2suoI˜ݺ "hÙs1wb%r'?Zo=O<,Kgɧj'+;kiZN5Dc0[~c}>m| -~k_ozk+>ZQ us4nn5ooFU*_p|E[{k7n^q;o ,x6GkSգx[`hY#{QSFmmRQb̖ErR)0 [uO-qt7h`XP Po7-Uv))M; \}޼6HY޼q!I!s"dV6eْl!yuVfjRpQ~&78o b̖ Ӗ8[@?3`|(g߾}+~WIսyAupQlbo(Л`f<()uU.mnUW%w?o:P s8t>u6Ca!Ax'X J' p jonc *[VdTޮ2AHC"(A8~B+,rPffß9ěr<{KŠhﱙbGpE9/(#O01)RKĬ:7ꉝ%ڔ)!up{@< ޵gْ5J`%M>.#(y1m!U>1J`PƷ[n`ɾ%_R+%]ROvgwsiVt2LTybmҿƥ)jcS:Pə'3,Ι3C~ #^X%xmL*;ms.ikgc%RǮO|٤ǿ6$l_*8%ǽO3dCŅ2cu"+~>)R18{&Xi\s2G]Rlt2*m xyr',F׿Gp5X-*gUiLh߼w,jO^88LcͷApñz%19>y|ΉmwU_/v"f /zQ<<=Q!ebҋ2|Lc`8o+~cPs6utbmQjir}aj06*AG?-%uܒ_ogXz lv{]Îh /tͮRۂM]Pltw8pޠ瑧˺9ɏ$çLꧧbhqD+0m sn­| C1ӽgtwzӳAY51 5;_H XwpH!ǀpq|{G bor (E-%]7_ũfOK4@tr$nTuI5[_鄶حsX.vLAuHZ朚=351"훯al o}ҕW:3uok>[kbK}0%.*#{)%Jr +fzЖCGάhX:񺜹{Rúŗrp&g )IR)Sv9V'0T6D}mEQwd'T 'iTPdR%&oR>.>NqO (ǀbLLne#?!`P&Fuմ/q5.Vƒ2XA'~AK^ ʝJh;MO}7} ׶Fbue$% Hc󺨄WCŠhA~=D6?D@W"|,| [5< &6M|od%ˈL>cᨉ+WY)'%f-b|_+ףs$#.]ҙS1O4v'!Sv-꬟I`bvB\SfʡW*k;@O4`ڦؑ[+6<K*VP4v, ]3˸gH"N%СfcRBƁht<_84,25["zG,KM- +ib+GwՌKݗGJqհ,Qxi[bCfT{Gg? >i|G{}x5NE-*}uƇGF%olNψ]'ApFrJJ 珘O"}Dn~&`-g5u4XdOEϸ'4Sn_P6L\?mI05-xn>"x9J('Ŵ J/R['%5 ?)EIbD5:RcI$RCeEwY0{/Cp͆y]S稢sc$$=N7H[*޲a>Fj qTw;=Rk= >"q|^[Xe1)R4'~2Ix(A=YT'jT}2K*x,x>:꿻^"XnM [F[q`Ɔ  ޶>qWVw)jԧyL5Sw¬SyED2yGJ D%`k+Rd :.I d4 ;SV_ƛ $mĊXI+),G3oPxJC7hsK2yi8eeMYkFkD`t>/kװhiIK{p#e"CM+2MX㳓R&d#F$`|\ۮԕc];iY;ysr䈞J-ײk`dlL9paz4gbnP˂Qslᵣ|73FЦ|lGO=i^lXeӲG?urRZ㤹^_WW*~_UKZvO*S!A+Fls:x_gjצzk0M Є!G%n0v_syM+g-.+HaR% {i2K#c,H#%s$Tu ǥ>ؾ!;s]|}cihM-c#.H ct+ Jq$ǘ3{aLw1-'t %PnGtˈm݋=wIw)Jtش J9)whJ te 1.ED˓Nz%z$Y 5]3=Ic02FvvVl8tk[T M6vc-eg\S,&KbB'/ Q)Is vέEd.fW`[ȳG&>a T##|~p(A;ƥW/n"AXqvΊ}G(]G5gzn.tu+7Ƭ7DofS_gVm_Y{w#k9(ˁVʯ'^ız$T'!)`Lz"9"ŸɯJ9[O^r>rȰtƒPҫ9w˚k%9TFS{ZyCeͺːcmP ~|rA5JWo쥷 ~Leҗ_oݪ(0uZ=y'OQdT?@INP1-:><5+ԩ]^ѴjY0`-0TFuk3')rhq-D({ܣyrlķ+}/ K@%ޮ~ϿtSBY$PEXwTc0&zUqoQZ'u|a Ɍp|i^&<>YhHX<8{GA5ѨUMוjZ@&P&-y<+袛\9ym5PB?{§o7XjjJ|`++$_<pP:\{G U-g52llY\;#(l3NzDž<+v\!ӕ63O&j*7V+&$Ydn 2VU+Y'Z{}++vʭ"ue42(xmFuz:-pzo|GVl 0=EP"SLesKR UkNt\~Onaǝ3 J">3]o%!dNY!F,A搊A#fCXcpFq[ OmduâxK~hX?CFδUVXt>> )ݨt皡" H[[4d6dO.=ckrձ?!j/ˊ[\Bl>0}a'PA  o"HࣿV-=Ésf-OG67dC#!pc;nl:mQo0n帔b6&.,IDr9-2k`2K:IAc?}*|<x։e;h%U”$)5 6% rN7D(<*Ђ& 7T1u\E=J0u~Dle ,/*祟 6c}8M۽:Go (/ &ΝP:wFX{2,gމ71}x[0Q')Z[7)~~ ʞʞ15Ulat!Ӗ'crwJd.٢HZoaN8=\#Ut0yū3)?O>_1}K:Yc +e]n"uzeH,<ϖ}gK؃DJ[/Qɻj/KbVHPH67~1H5ܢZVJC{p~\?#`bJywwoGQ2!>tGcw\Aj`;> 0{iϐ$;{<+L"Ckh{gqDFnH1O'{[6 0T{hvAA uPows U<@hdZrPWPHOުpt~'IZ?i0?޽SWWwcU\yAiߑj7&j } Fp\%lWcʔX)I{`N0,N4v, uffqSðV_+4Z |Z}b~W5{|?MFUNQ`i{f^½۱dnWv q~ca\Qoh\x4d$F ~)qHgѲ :Hd?~o7Q; $7#WGKW&9,l`yl"M:&=$̜l%QCFܖjv$Aay`r6QN84R}8Se7:v`)p>RR#Ԗf: O~;*`-I]>UH Z6{4τgۻzb% ԉ/_͊13T-t$ՃכLSHAN1 馴gvKkF;O) eK@MqQnMZkvUOYŠ G5b&3{}?R%-D/"Y4uieL+&1h"1~cTV`],,ݭH~|nn%MU1^и_kn+admoTw,ҙCPsojq`eL6$r,>}uԴ35;xPȍr9dOSpE4#?SQ:>ָWLRVkU5;ĺ)5; } {G7xTy-s#ja*ahh02ٹ{Ƭ,h-bRA1Km!SA.lPRzƫ?6ĉO@&e8۝bB{25DS80j|a9v1]c(.iM-L ߑ#3uL3߱me <&sOџ'L0T$(2ͥ!yqڜ<͵1[Ym ׉YċjrOF[&j Zʅs`5G˞vh4v, U ѽ9zέ6>$b GIɂVa 9`$~>3,OU07x8TADALHuy•|WVZARp~5ٻ7PT"g9\ K_" 'Vfh~g9=#J9a)Bi"A(jPS}a!=cl  lRfQ ʙ-;5izra@dp|qPۓaT ޶#%ME-WM12yqɣJ}L ժzveY {}n9@pe~HÃgGKFY|dzrafI#6֫v:ȺmbO PL`W`lDG`9̞%spt,>9xDA|JNEeckN!:81,׼ 1 bDd@~c &5l~gx<\Y4|S9 HNQq|^DZsZjr{(ʀl?K"kDԇQZ,h-#Vm|˱bӞ?u |2j7~P :L|Btd Uҩ>!h6%t/7~`鬾+ vGw~77hns;\nr_IwA8ɍS? @P;8K1n%Go K0p1 3(Zt5^ifQ.%vƚ6{`k PBytaagc9O37hVJ@-H- {-ɉs=zlX| ׾* 1x٧Z+4B! VX%a9;c@/H϶xŃ=PqR yQ: Hr: \g_2X̐9V8QA꬟.J,|u.9rZVM,e9Jt-tUE+g e {͋_mCHt>Zǣ3sBa؎;76G>{ V}gN) 'l.\IR(0W?%!ԒMؓ`e3Ƈww ގ2n';.C'ȠD-ú:`l %}+L^,67f65}] Ċ/> _z_xYc;[V?u\TESfOhxrG5kĀ vBEܟ6ت>iHz95ylu}2&e+N3ᝤ,64uŸ$}o|C#iIE3mw,yHر> 2a̟g˧޵&l2"p#6rҰQ}vrْhi搓AX,'Z{Jy֧%;Y2F*(e|OI~S~ӲC$ƹsv`!Bd-B ;d07tf<D'E*A]_A*` N,f)Moj&o˛bݤuFAlN[yid~FS?gZd,ъIIz#idtc 1J/aF ötq@9׾$Pnփ#s7k7(U*#'?pX5pi.06*A̞qUi O[8g [Rۅ{P Nq |xc}F>=V [R mˊkZ剃@jc$67~yb>ehϩVr (e쉣}@הŔ22#?<Ӛ'[Ő5Q"M41f \:+V5du\E7V4c,l<S_'pQsttDV@Ƈ1CVǚcO 'Z%$䇞*f >Ciս["W [^M*?`a.}=vIS~jK9['_{I<A3^xk@=l0=J G.(j~vt渨-HP";s; CȚ0x>=Pɂ9qrHgJE:xΆgT^5᪾a buz {LBڃer9{.?G7"@T9L ]{hr)*ERAcC'lɂd_|*`TD!nS)#IY[+6|%6y+5'ٴeča~mmlĘ(RkN*pi#?r"Իu& sv8-`L&Lyi)4cF䣏yXzUJ1cۊu0G )XlW$If>||gx} }ה/   rRoZޤ,&H _zChO|(߼lγ##44J 9OI'rvO|h :=alTH؃JIAh"|2g{=jX: NsF"B<7 GlgZ^n3;g8Ȭ2;TB6ABQ rNt琕by^L*fWǤEz0EqNXQqKEs @G 3zݛ"=.[4Dbrn.)y]]-Tҷa~pv!>{ks&"[(UctG=IZ,9Cs$? 3oyj ),܀V9rtZeg.'sp!CD\[wii񧝲lQ5rtyp[v">yZ_wMQIEp8.i/ Qi _7c.RQ[HS̃Iw)n6`|N^%9 P(/|1zz=wnRYgLQ N6貎;EWΉ<=iʜ;|rb¿ŧ;ܠ'Oߡ,)dXL-&7&eJŠ!얺(ebE&4n]f?huvK FE6>82gG}ϤMIqSR -K QK{q$ĥs냝;7E۷^N-5ojyVnb|9\\Sw:Yvz3_)K͘rٔ;Sh۵x'-]1j[$1 \"qC&nYO2j;!jΧmOs\_՚S1 7Vki1o`KLIPkXC+'E?ߴo*'AOO6 r)ޮZDc ,2 ̾#^tj&2uA%zf׾B UmڱGJ'Ȳ;r-55U˯|E# o'_+ԫol=ƛ>ȨH$P2Ǝ!h.f3f@Co%|\i)+[l2myPhڔĥzmNx'P%6Ih,"UfP.0} -Φ̣ ,u>]JxL{,46- [9-Tsri0 T-hs}x[eTK;8V$ TҵWVT|Sš|&?:S {QokJT\^i<@&FƷK4{14i W:s`LcI/o'ێZ(طd~Af~FdrDi}b >cHs .L>o"1f)^ 緼1-;sCw>\a)WK3 bUTbǏtAH3tQ8JwmxԒ z\7[E8F3o7%0t\EiEi tpdrE/vjB1НLv2 7_w7Z\VK:|{E硞?FՄfNk: U؝q1Wp9~\SB'ʢjI餚مճF«FKs*Ϝ2.v4@aɜhӑ'jP(Ql|nYDM5$ѷ!S>a&ȥF)L80Y"R M:.[&1i 2 $'XҮ3'8\6:z3=BTn8'z& 2 :< d $qd_f*H:qf^R7T`ndqGܱ!KV |@{B1T@fi x2ouw =Yl[&ߺ Ԑc 'h/Iܙڝ9$ng EWC?)CGLcD)li9к:CsJ`EV ;[B5P*T(DJVZ`EE5;jT@p'7"!&ӈr<^q˔TFloK` gPnXxO*_P0#q_ojb4ã5:I8FXF.Ceudžt "z<+Ow^X9FۍMJ6 <2V2R][5B\/uuTك.sQisVKKcϾ.H3yyRoT6n|@&s&ꁒ98 I_V;IR'cg5oiacx2$إwE:ЗCċQTTVZ"/``6p4J+"K$Y5]8BGz/jy \ty hĤtR [k2(1u3MbpqZ*8~i~ȋ=L"`=?J[Hv!Jk$&Y5C".10հPw&tPYL&ȀUG&"GhIaI7UQE)I#*][)F7Ƴal\x>IʀFo~IF95jh!UK(QEt[vޮ{^,~@krVČTXt0&8)*뇩n豏7yyRdM2}Cό\?.:*>`N*Gx ޟ~q0P>2Wp_2ɕFDK!%gs/G&>AsUhﰫs=Asb.TMI=ӿ͸spgX3FJoޓQP QC:q_vbBXU0,~tly*wxV1XH;Ғ:>oNM}EXMݦKNQor)=21*#aXv2ʺq:lg22edA C'|Ύ3df\R_T4P6F(f ܆MnC5ar Fش5WJxo a(@p:*7f)9%gtx08G+uഉML~]z&;PIPNIvV2Nm!b'C*T8.'Ne"62Z.@юZO.'e}t铝>9#+12F(5v$ |r|=-b*hUжW<*NPP*dm+ZMYw`?LPˀϺ@;\].hLe-*B7\ime5B5@=>5<k(oe G4|5 UjJ* _Ib)|[ u`3/f* sh}zX[^xV'-Zuy}ߙM+?`Ԝ܂V<89yv1+p^H,2. '@sU$zẦȾW%\Zx9XX@0=MA¬U( &R pP5"ֈN|78< ӧ__3a:5pC0y#B1^YyDF11!J<$Zv~`@*wjmt*mH @ O )*'EofGt$X Rp) }_ؔZ*nfWuA#!-iOsD&5[>鄌tbZkXg%MySVGA1<-hq58E~5pw` _:>Iҗih^bqy|4W*Tw[xqYZe +no VNGb8(ucigN͕ЄI~kAuPٳI+&cg*X(B̝qARKu#.g) ^'.BYBi0=ٿk>ڹkA#yPj53 THYY jAC/ilR#1V [T%0:P>@3R'%. Z^@Ƭ»EhaXdK~ø:&}$<P PL6`eZةT:1}V[#M^.LwS}JL/Ȭ?&MLW,Au 4VR"NRpU hGVw-` +lpZh`pܱ4'Er#C$!k*Rw/ 1Y'6SɸL(W{Uv یZ]P Ȭe@?}5f敦.V[۹l4ӇW5~g>XVn؝;ݟ+r48 !mx%U,40xƝlP'ˤބZumX֔n 7}&|bcLH/澎LTϝHh!ViIfoFeSFQWzإIԍ:HQ8+>pCYH `r($E/(:A紞a3^Us1LRj lw(\@KdpذQWm5`#L% @ܣۦC[k!eF2p%)A/vf wh5SNUBZP<ŮFms;4$O$D =̽lZ=Œͱs8iAEnh?Z211p0E/MP T)Qn-X1+C2Ctk>Iig Cy2_Ru:0Wٺ3(ѱ9s9_hSh  RX_?{cCwkK}J!pď!/EDgrV]c+ԇ:v 73p2-k tFQOG6D |73"m9BZ]ycHI'J˼9ߜoxRĨ / L> G-.`XSY(mp R_}gDV˝+"Ѫ%wEtjA$A+'wH7*~ueHiVf_rbL djLDC1Έ{!b1E^UBLo͇$'h5ZA䶑̭rvaa,pBqc1߯ڊHǚVz:>C yxSe*v+`_pe ǏL jܗڐiv^-[Rk<|M i0a.75?R;0a'y‹Ey%ݚKgH+;jGe`h"esU!tk,&?ҁ^h{O:;wƆi.;s|~.օj'O|zʒ&"wa1Mz/Sal3RT>;\'iu{Zٷyn[My8wp!^*%d+Y* Z9l2yvamYY5[`J` LiRh~ְ*9Kk0ZNW,qs@\7GAW^40"eBKzd!9T %?/:m;{̾rmS7l}XOrwTى2A|CW3.EW/޳K-&@}HFɌ;_nzum[0GRE,Wn}S5CZveA;M _*NZiU#ܿN3k2ՀaFL;>O <˅簒\dVM?b21 2|sp$+B#»">ӡW%1Է  8Mjmo0nD./Z%@l4Kkˌpz5@b?F[q@ڗȝrq_ =kxt6 fW*ШV#ѻ`e~.Z/Z AYaFXAF*Ho@T6lۈ{MۨahBp(ݑ)^Y:mֹxJ̻(,#.&o mB^: 5yI\fJUoaa}NT#K,:mM6q;ev/ON@Պ*xpCRFXx5QY}F13U3En2T6X.NJ?eSdtIsrQȬ{! 'aݽ%;֮a_h<\*bk_8 =0_#I u`I)Q-<LsL+<"T(^J}ʽ$uВz% Ӡw4|V֘^%EYywH$)&h@_4.Nȁw'i.3 ~ SL$"|T=sbL RKɧ|v8A󓚽EX*= _*, Fy5h7~ ^3 V^PK֨V9@q>I&w_0 %Po  y!kHZ;mxXg͎ kmxS}h/Z6KsK;S2ӨZc[LJ'aٔ5zjU X9Td표X}Y)O*zm>gr9wmZ*@iKGQA_uF#NroxI5Qsmenl$nn$n(f p׭d`-nnj4-;c!;E"c8[_UWP.ԝa{)tZ5 vН#_[m ӯf3h9B TtȠв|kDsc-q;rخisFG*: % v{2 NAM&6PllUkI"ta<NFJ J ~Vl3F4BҒ7AdLY?Iw*2kC|S[>/Ҟ ؐĆ<_n^@Ĵ\Ԥ\qnS O%>3eˏ"Sq׭cVa M:Pz"_P_-A_e*﬚A4l|F$SIkX_Z~ o862AUT;M t 2]P~$WG%UGe u. LV5Z{C!88b7OY ؎6fm Ux{Z@3p\ v4Ati0x+/"vYuP(Թ3YLFY5*gUĮDy-ե>tc":߆rYre`Hr_J>Z8el1B@/GyO[HўmAL$C.e8Gh ͲnTi _;M@s^ 4O7ysS9CTo1|W94zvX^Z)H :àN퐄S9xü[Hfҡrnh4G0t]oۈ^;)^ă!Cn >20MVw* S]"O'hOzͅm|HEk81Vpczx=U۹u`斾H돖!MN%i9= LqkHlI%\[N,_-45BA[H5'Sl&"f9ܷM9>n6v4E b O/z'w* ݾi>(r8J3k+wPAQ(7̨do !.kpѨcg^NQlV^5'#J*9 >"l}&+ӭ$u,3qS`Q7H>G~=r[RB^V4HH[ ='Դ9nm֊4)RG5_:b#RLZHJ]BLEVԧqW^wM{[6,l(:Kbs[jQ\F12ʡk|}XIa?$x5CB:c^fL_.oiQ'`F7GHaZšb",=O}7wKF)e >IigN4S66FXʙ*X :TFw*|7]U C"2lvGpy`ڪȃڃ֒5*oSźtpCX|r˥\3z< ީ}5AL cI]0o)ƮxPռw&d[II*DrpNJӽ5|ger_H R9Fo)&Xљ>oi}3>vYq:7-b{{Ɖ'"!JҰE#|Z>_Y(5ΎWl&Ğ^q}nJO}GM,@Ȗ] tOc—V2D,VBg9xޝΎOV:d5g- TyW\YZ R])i35) Ɋ2jK1:" kJ cg5tNڊDJHmeb8Ml|y:~aj[R2=q'(/q,*mW3Q`O~CV$EP_jw_@]>f+6&,Ej=F؊4ǚXaM^JdbLPT{j$"PbJa5PT&l<]+S$j8B!LnPv$?* q%&6 *ҸsHe%da:"'OA UӘ4{-Ug+Ei!pD DBoAΩ(aZKb#֤\mM-#*>[a 5AYLTZ5"8D asr#wU =wnr+E4k:B Y UsKǭ@w8xS +7 X1t4TV9O!mȼf3ayZ}&@ GooؿwU.FBzs}m_RY4IIv s ֳCiOpk 1|ϋYBw$u f 9q~zwcA5Q=;ҰSu@zxG1#CdZ`6?%55tY̷Þqk̵_#6dz ۪;GzZEivô(PʧOo -}&t@&_=ϯƁr6nls)Wv$ܰBWa0ʭ>K6k\Ȟ+J2hm K1)Pvۂ= O}"TpY(Ouj@Q3S7:Y#|$B}LOI9z3;f5ɣY,sMXV}fv57rý)cruP_7x?1rm "U\^fGL1" e.:@l!74u`{ ; P#Ng*` d}(RZ9s#QBPZX#Ekf骩gs j9~*GpL>#.2N v>9ad!׻F|IUQ6@@5ﮰe^3"kF2HM4,oQdJ*JGLIb ~,-T~IyTǣ!dn fxR/@;Ut1KDUp#\(1UUf|+gM;k0V6}(~Wй|ǣP",+@Uc0>;PkL PaZR֕G|cE*5hUqw*Ct 70#W07nli5_"<| 0nLrofP%݀7▒CyaF;o&zN紳szט:%MU<%4a2^wh )MV|K3ړyxuW._%`li޾|4p;K]a+XmÇq`2*x^7tԃ 1!5FD֝w^NEhI igNkaA1CropPHMR [ ~FZnw 暅M_c. >JkxIXǾ,ًڌ@\m^PkEfٖ#TNZRM7U\⛐r՛Bz᷍i_! [G$Bg5ʽ}8/LϔPQۑ'dSv< dDm7t N֞6 \Y;=b;q e]DGh,*TUbxuHA  TO//~K_X=htM;',,h{u2Ye)p Eɦ<@3NHG>rV%TLePfx 1/[ՔR.`BӀ|jmܷo`lK-9& ~1ƛNʽO e2(>4P̴ybz_Z|2KEWUG:;tЖD=Jn}ΞWP]@3Y_p:??9P.BVDˁLt}9˪)>|O@|ܨ2TAPOy33#O\(Og34c/[{±dMy&E81xغ&N!D[B~f1JE Ҍ&.Eat҇ :\〝ܧi ׋aF-,<:PK-ʦl>wt04=2WCyU 蓬~~Q8{O|𦽣vitέ}~>2qwiQ@$n}ZB0}-);HG-.F$\ :3jEaMs1H51Y@߆)-; }#0磡= ,xוb9vU)uJe|HbqtNg5|Ks%[ZtsX Onm)1m \Q՚3E7T3T E1_`k3fÝkA'nMFe&RJʽd5 j;mөIUQSwA44KmM5R+l A'QvuI_(4=&שK,څK GGnSX r)-拻T8e5xAFiκMzybnMu1HĺB<<ˑl{k刍;ݟ'04(yIUC*a$+_6QiWMx` ɶseSd]:G|.h0tnZw6o7$d˻! e4k#ۅG[Ӂ;gfIGNTY.o< x'%*p4ܻvwiZc%e]_ZЅhMcr1=hI:(br#fazS vwTZ-=} '=FVdyړ1x $J9;1Ĝ]/75cjB i>Δ0ৌNS@er-]^ClizS*BXmO:GuG@zޜ"T6B1w17Mm²((/-GXPyO[H bt(V+beGa|Kg~#Y^? o=0B=%Rg f_{\n/ukޘ= HFȉNa* #1eG3f!'ڏn]@j0['U3O!dޭ=d P"6`]{!]pnAtCo¤N!tonpBlsju0V%z=_.Қ>Kv/.@+N%t70yU`l|`+&o'n$T% p0UMd88@#J v~Jew۬(څGpCgl1B 7av.sK4~'1K|t( [0Re(h%'[OR=JF36t<;?(50;&ɒb{+N1>j^dp紊6=_n4S?<͗8vs|qϗShff]Z?KG[}pHt$6N,Ǝx g:u>zb{5eAX\.bzWsoԴnn}B8h^,iEf? ׽&j^0݅]~u`PnRTp=bIW.'*3('%0Jڇ8(T,ݛH z=y+k\n9@f9GrJYyH؞SϮf,IJ֬;>ctD"%y4Pq+Zs8,0oc=P=YV<?%TnyD2{fX X8QV;ڃ{&d#g1P-rظiǝ@@sJ2G0ϝCCuL໋RwG~I5s,2NkȆ^Sˠ:ʏ>[v3`PqӣY'Va4x tف۬Ut1bxj}2Υk ݌fepZ\8 zJtOo6#W4_gj)|3ݙmKɈ~l t@qZ#|_nX^Cb׬Դw7t: RorM= = Hv; Az6)AR.8li¦JZzӜ2ݺ[8i Wc• [hw_˔\?itn}Ca!Qv+.v5\uQ 4䇫!]pѥ߳E7)%/=2k-ٖ]UÍ+|.hI(ٚvv&< \Cp%˚i+7tm? |&a=nRe%q3 yNGl*jѹL8m1$XFKAvصrدާzv;>֨ĻGYa5@ntҪaFE/_I@]y~@Iq4Yx5`۾ B.;gx[ˑѵ12z>rtx(kl&45ٽݵzs3 %Zc`܎ê|Zpp#_:ϲCyw:#O-[vqϻi"l`NNwݹfN{TSvzt&[ꟛ¾AEcFQjsyaH{LCLg%w&1= BZVqo6n3B==L\%y۟OBG EyC;kǣPB^v#KnzonIkz"CFkٸP؁y.wa }T"!v;udk)#>wH_:a(_v_k|͗>-_z[*zJ꣺WF8;2xv; >:xuG|?]cogNC-06κ;ˑ^L88I~1F8椝nSܟǩpC] `;CAe*su:XYo촊]Ӂ;wh,9YmJ {]_q{h#3y&#i㰉㛼,aJ h]3=z=dfՀI3Wӏ>C=Gx%8vp˒ݥOFG'p]z]k&wWvk 埸kVkFoUk&pv3U}6e)ҝOFQ!u3L?\3)`Aaܴ18#1U1(ARRu0O]-M@ )8|MCh딒ZTZx}F$&L $W@,SS]d,t>SsAIft͏VC,4׍BzI= N$M/H^8|^w7%K+ dxkaȅB_JC*o'aN0ccJᖭwS7t'{֪*YqSC/+u䱮Gj-=[COx!<_E9 %4"O_9tRiYXI|oȕi1 ⧮HzrZi13O!$?7|\([A$Q5Wzi28?jdvcJ{ ,H2yPh7ɣMPI R$U*QacU*9 4[]xԽ4?`FڷZ'jJ.hEaG0 K.L*ǒa$6q.ISjʙj`UIWT^7BgXbגWG{F|Z;H:ה) (1W7E b:cI .i)8Jg^c{/Ti+BUn;R΂/.7a %*5\"a:RAADH!8 1Z^p_QP nC*g8HPh|B+3Sm#L K+B &F[큶솷q K@!zNԅ F=~JPT@XM A[zo}%$uKL; ^=*My@_݆V#4-}f`T\ٸ91man8? 5)iUo hA1`#g0Xo{:uއI7[ĭ}:n2i.6N.ﭻ‡0tLzp'6; 1 DM]㦑` n%S7^oR[}4*2I:kB:Q;|4w4$'m^ XlZd -B˦%~kƧw6H(H@xZsHJ? .,#1E*K@AemmZz")]|CM{;ҀA;+0,a)t2)q7^g#p"Ij麵lsQh>2v#i #/YoM%-ٛB_>/y0hMʊvFFV˳kFOǵP#{hZ>SB0uy+Fj$03AwcwiąHB}O Ӆڗ7 6ڧ & y"/D/JL&z- MPN5xe6 oD:p  e<>Mr'v'Ku3gƾO T2CHVraYƹUZF:h2 %^9fȧJrW.xM}CK߾Swc&[dzańTZRXoD>!-WX4O/^!xQ:Tg _QP$,8X*㲰[\-Q-$Y"-$xuq#Vt7hB\utar~k[j"5VMBmAHV>`3bߜ5S,T< "ߞW! Zh<{]k`B +Zw{fs0 d2tckqDhb|e&Ki;&T lZۜm`P"7lEҗ?ʐX5[~QRMaa@s|_ǹfn nCW V8Ӄ:nc{S@ëU&_斠o-3'=E$]uSEC]x%ީh;CZw6ۅLBf FN_@dתSL픮%̔hT3J?1 dyV)̙(cܔ )A$jTr 􌂵)4s8/V!c:p]vT L>ذ8VOz)SP}4dHӕW+ΜaٔjKe|2J"1 Eg5Aeni j`YeyCCX5 4s );RAP@.|3s` P4] "fvV~J2/13$;O ;_RuňfOz22p βBρ+xrN;kW^VCLxTQVP.9.NMҠz" ̞H@ibLj`4jB|L(]zgҤ-20.ޙݖ2wٸK*%+\ce*^/ ń :1TKW9 %tzNۏ{p ˬ64M?׈i r`zk=.3R汌cI D>9&T!O F(SbvK)-{=ڞ +ԉx~^Lc%!h %O$/K+jBdSumC"!@iy)gr\.rϯ_A:'dHU `N?v.v[U\ paNJn^3No|jg;0 NDŽOUQ]anоHx6I췭U{kA\/?f^0Em<,0@B9`#=ޑ_9'ܓzp fMP:-KBMew>YhhUhi6   %IhX m<Fٌe)jN#lVL75lU&@nSDi ftU?1I 9jzCgQvRϭCcHȄL!c޸%?1CYASGFG9w%~|t~DjYn턛&yx"6~ww;jQ&8Rr(Hka^\yە/a2% dvQꋿ}p`N5\E"Aꆔ^Y rb{Lu섘*UHs2;olyŠ^(]]{w\b8 :x^rk0ӝdU\_Mya噝rlpiCtO᮵Mge'G 6Ŧjz`ao1 V+V ?UahTfvmU6@MVa8K"( z1 {Fd~k4@~ I Wzzag(~&zgw1i{zZ#,+?c@Dkm]yUp@{H~hwdğ ̪3l 4:34;/d֋ Ml`џs~G8J2C%2r𦞩Y6*ZlkatN3Gfrozc]~{cK(%U0ƞD],!4زϧe#&R'cgaE%uv ԓ5FxweG}A#F/\x'y^VgX (B9MtNҰzJs&Iݦo9B8ұjȁ5"#r0ҟyZD:9r&e|a$/v"۹_eXְ`\d]]A4 hRҶjRjae 4g2Khʻ %Q(UR[:c UDʸ0rw8>/vj:P,W&r-3}*= wKM6D3V,?yz^|F)ނII?)z2h$g}PYOQגߥ/"hx"7yP-gZԝK>ɚMe!L8sAY,1}!UY-/u-Pj"aqD\쟀~y=K،ʌpQW5I;Čfވ6_=()ƈfvB(A[=o#rvS7/Fh5܆w1AEy[. EKf+ sl<~nld762 Gºf2[zKR;YF3fu*DVq<7D+[**)7`=D)Q g br u;bѸ<3d 3iP1DSsS`h.@[5Dͷp.A1": VMʴTjtl Lө%l>*Z;43sjj;c&r3?70J+6ԌwDSM#nTD-ܩѲhF0%Z9<1M_ 6BQo>?}jb6o{PZvO4g 7ڊްvjnv LQ}WV@Nm&vk̳hcq&V2Ƅ'% ~[ޘp`kQv1tOD3>5#?)7_\/?uC'Ty{yK/`k&V95e兗{nu{+b'qHc^ZwPog?.a)E蠘: 'N3olfY׵~@PlKf.4pe+1GK4&x`H˚+n5?ZX'Kv+Jy,Υz OU‹֙=`LRqHXkx[kZ+ fnl 3'VF JQ#MN5)>ƛb1d>62,21h~h5^yH93֘j\a$SǹC5\-)@8.2p)ZWhT]S:5iyACՠw 94m!q.Gn7X鬚v&s;A6dio[UoF$]k2G]Qu > $h0*N) Lʼn5o̹D tͧ XtM1Oټ _̈́*:ہ9[$a?)b i$&#vY1;4)9|@ɒA="aC<@~wߥ|^1e>>2KI^ośm_X4s" q "__ܾ &7EMkd4hކYyO;es *n`8??QȠ2"ۆ_:c2pL0(b2:S Uͫ9m-:ifbN+Æ/mf)ثR vn`U(E5,he%pJlF@me(0]i3]Sq@8 lm*zAj0DŽsDvjJ[fR* иn/a-*jgH;pp488Ƃz75 &ٯ%8嶣rMY3>T;=ݳZPVǴF$k_wl֮1ԡi))8mRJ o%kaB+x'tQO v2AKUxMDu4T t3\rs#n+f2! 7nlD*}(_ 0`WNY*AX:TI*-2$0Z =ߔd>b$?'n^(El~njH_e0EZ-@ ʍm렫E6_cLn @ٜd*xz=$92JQPprFk,ˤ2Lk\}f߁Ӑ"&ezUc-\ФP1,\IyआNl/h('̿2tKqcH˛zϫVz5Y>n S=Db*i`f~V^:qJI/&%+-Xb(cyf[[PtQз﬩qpc U[ |uFK'LaU^)2of Mƃ)&yK?"sVldϭp%5 N\h*J"0±@F>5jO?[oCwX[~=PZ T| $8`*&-h;]Y(Pa90Pe03@UTAcT9-IL),h C7 ['qlwpU#!: "&_w*]R\&?jIB²p8DwCٺ f6x.pλGbtIИCلTґ:Agz1̏{ѹh$!=K. w7ݵG y93LCg hś;:Æn-!M[fJ݉14:inYŒl!S2!3)294bHzR39KjxU(l4x Y6i凓N^vx ( V;.#V~h h^NDh~Yn'D=aaU]{Q _ȒkƎ:6#iAAW}]KDջTA5wB̸*],.U.4IjKck^P# R񺹡K(~,MQӓXE6->SeqS9:^a dDZZa X[5ÝZ}KW xk *9\HpnIQ9H줪mR[tv)mVw:(ˆML5W8y. Ljo)S:OXed6 &:F3͡ba :k!qŌIS;.Mj0[hekD%qO]\6?t9[&~RٯjC  i}:rV`>ak &XrsA{y|fkO!tj VQ: ^Ç,K<*}/[wGOKp w;CW/:J Q5HpMj2(CUmZzJSdxRiz;P7,=~_闢]]/˭_v[?0θY4LT[hfYTOB(o_7- qU;#ꀛ m*2"K95Kd&&*Tz2 ULp*A23[: ףЁ};-vwr=\VWFI5hq:m/62ƕ%:4LV(瑥??aDcB{/1xuNs8Nκ8xcLY.+ 6"_|^.n`W,W 1AY)Q+U~J%=|Z3kuCnU+=ZPYg,GdMu%DkE 7l6^x qJWlqۓ^޷c7vOa[r{w\`NywܙeތjԖ:e ke&PjfEyP*5Y-/;$>t ? )V5儬 XzT>.Nd ;6d蚷2 T գ02y3g3& Aٕ O/o(9YJSLI1}gnwa_䈶 G`BDi}ii\ ɹsi_M%qb~Y:ΓbUpJ H:)A:P0WyrzDuCRAL!Ct>;7Sd*,'*xEwBNl{<&/G~-o $2a.vbJQ0:? WP'`%]\~t H-%3y34_WB4q1U C@sD&ԫ R,Ȝ_VC}x/HfZ_ly3h3C4w^J [nTytă@ko&7_#S4c7p\;D+"7wȯIyBMZǖoHQRIUЦ]Lb +”['UlDqy"&tnbMGU6yA5D^,Z ,UC ʳ7nZZ4^ʧEw_ZXRk$!Wi0rƞ,C^gOX80,t-Þofĭ#nڛmMAkqLN #u̙eB Y&N,}Q;3fY>c8XeYJ±T3M`wjmf$}NC @ꗻa4 o:J!oLM3@eq-Qn>a$EvwvAY| [,f?pnZac3F?漅!ޢlK8"^dt$& zUK}I$;Zip>T]>b ߇⣌`{1Y/n j G3WnKf6lطcOo2L*6u߼֝cBEK`5RɳTHoXNin*ܨ}{ ?"o}$*ԛ`=64ibwi3cfHRcRL"}߿͎XYqӣW*D&p_}N~,#/G~0~ !#聆i$$~~H"}ڃ>B>6-$â [ϱ8N:+]S ɴDe XQ>ӸMIH|-~{4.3qg3ssv_0 p&m l2ckb iݙA" z&-;5 woݽmZNoPZZ[=a| `4Vҳ\LN#$Pbr@MXJAdTq%[_m*VE256͟DU$leVWACFHz\R@@y96lhbXkڙ5˅Ĝi U">𶟳#UN5FٱOd 1>d?7=jI b0/ ̎#y^_fTL @ 劶w;z{"muMub;EuA Kgνit<z%뵯96}Y/LоQnZ&T80dii\:O0 @:6 iBC:/p᱀a|J~3T痐q$ky}@HwR d>%* /:UZ%CV1Zg5eX>-[p<<[E\;\[ў]k`{t `G:ru]_0<պUJ 6'ńJë;3B|/$%H]͔`|E :Rgi!hҀ mZ gl_8N/aЛ(" $A&m?TKD  g|< >lݹ0A%K5x] P'F Yuv+-27Imle7Um}y85 f?5~X{0P? fUx\vNӁWgbȊ1QR[pǟMeV /-B> ^0E@dFNa xF% P}| BBնWҜ_༡N֛  sQu-8/j%KtZA별Pq`[_ ?ՅW;wRmG'[̙ʈA(B 'Olu ,}Qc VQ ¢ʅkV^շh_)dPphUяuvv7kaVx/'* 6Eo:6L!=(A6 V`߭M->Q4n%+6⯤"JO-e(rv~}jO[kXap~L:7EQl]F8NN}/2T"YXű`yry &iE=Mn:xN%<<lIۄmZخJ".(κS~N+ȱq˥csI/ۖ|?U|t%UsagP ?i9KW}CAGr)wo(]q` aNgtO':Ibǐ58.w*Zu`y麄Ξx= Ͷub5y2Ej0yR*\L cv1@ۯֵ'awR,P5UG/"j/hvj_xv%[:z 1clΘǰL.0kTWކ1PzTĦaR.+?$58yq'H3>C:-)Le̷TF/FÜ-[Ix{Cj]AvY'IUvZ7IX4]pĂX# VK3Y{2yfߨ&r;1MBGX0oNϩzc8̚Lޔ&"a~ݴgRVDwE5Q^PR"A cdJU 7 .D<𓄖_d_1˿6x6u,‹yO=TˍpS6Nlv5NڋAmji!{ڥ pu3:6xz4׌^1u}ͯpl| (:6B UdQ5:`Wx# <d;?>ߤLkǿ_ȾM:G`9(Xd,FkS3vHvbR2fw#~#1H$wФ]̝ՠr [N!kd+O§zfre~+8:mudx}Nfӗ)cRscr{LSEd=Ԛ! {&(b: הv6ȵN?t'Y?",̠Lw^#،8"i1jnJXW;xSyۅumeRH@J?wRlhbռ (J&jKBKcZygb|Z Fd֡˰]&"#/lF&U*535F}& <#t .FUla&U2n&7^ (A0~ӭ[Nl?'ڲEF@4,FV#Z~ApRp Ǧ՝u=AQ"B\m^ H$[_P1^ o[qEp7uVn}?ػN-v[0I2%l=hF>׏۳eW9htvҾ56KR@55IL?,:>;X׳%:LeRl巢Bb܍Q]C嫌)J 9P):2%"ډ]]?"3,Nvs)AVqhE{S"<+4 s۬F) #[ L#ݸaۛN[T!6)` )4("yIXEWdJ( Lr;wzx3F92(wdoɱ&̕Y9 <\t|g#sk$9UKpWYRֆ&T$н] "`k'(2RäSɣvs)/Pp'h&"԰vޏ,׃F:(Mj ~ND?.Bj\%yaAylܾ^"/4hg$@88GQ㐉CF!m@ #` "Uh+#ȳs`* N@` ,Bt3NJkKL/2D?+훿Ls8BeMqpa }Xepr!OK {^}(APevbgj\oUNfI7`l_wə^{=u{86ck+p0v9ĤI!wZtݙsL޹3JR邃; gw!L18SNjpx5Ala[nsW$"^\yNU33UEow/$~z$tW?v*ֈia%F69 ѐ2|~SoLuͥ&øpIL6〜jn$;J"\g~3"0r!xC ˈP2f# &( R$/= ` _ْfbH2(c\T6=Is-ʍ$rƪJ.âbV3~H񇳬'xT]| "֬2w.<0|$ e9Ʋ<7z*|p!S,3/exqLo6ε6a4Z{: -Rea-<Ӂ(h0reGFw迵 r=B'teN5pv|< ȚOnU`ë;nZљ'ɼ= Oiq"Ŗ- <,~NNFUp쨴 hםG,uN97slȬ7,~@8)"z9՞R\[ rFe*# RI/)lrMNҺv YMThH% n{0p(l'& MLI"\ V9*6lao!k%}p@&~L!_Nurf {y BFk1V,vg2(smm5GJ,=5+O2L0GCIxqh|Y5}J'|w{ [;=kwM@vڙBXNJ>">Ӝk 0:(bt$Rz(O4=l}st%0@pU.ZfP33!XMA)R Q1sN.Uj1x Ėo`FXz()d\%Fut<{?Tp0ˑUbƻvy;f"CAWf*6v6vj\q3e4ckhd|D*>"==YT*BEkv%q{(1غ3VP - LA05o75*)RhO}ҩ M)\)P|س2 :cw&KsT`8kRlm.ml9l_y1?sׁl`Қo1%Uzx=c%j#]5 (*0nQLCEZ@,fR${m]o?ZMizs _|nNė@oZsD#K:Pk{Tm~AIShk |3 UI*>Izw>eHn__TSXM#.%!k՟_wS=Fs,I˖US9L|StiLCmŤ`#a篝9+·Ӂ%-z#fJ(z>i!>OxNg.>0!2W!&za$ %UWu}՞qEU:Z^F,4 7xP,`-~C&pFi*I;YjO}P1ƩUg9ԔW""au&a$tKk3J{Μ lS4y+u$2:aRVHgg6|a԰i+K31Hg; O#8: xJ]v1%AϘ9*TNCKX+E+B&Au?p Apa%AC䤰qp``7T +hWsHB7@87ی8=1W\;r5@)TFuf]t|Y{6|)-ގ8?;wb <0k9H1tY9|ϕז4M*ӷN1BԗީCmVYNWU}a+pkb4V~S7F WXNSa6wf;ݟ·,1ݶv L㭕_pJt_䀩$['N O`l{Zqz}bӕv=P&DtR8y8/J=15"C/f_V5pt h?Է,tIi*a6 Nf1i4 fo+jEfqJ/[2*-96)(ʿl Drc8;5Qd 'a5  :3$Ɏ:@NE!x7{?DwӠt<(uKz-ܩծ{U<8Sj+~̺]FbDLYMhQ0+Id1XhZDZFC%_7޸HC\xQ Aª>!A@(/9rZX _}ILtlTڞNm)EiΌ:񒶋`ʛF:Ta5x/K$eP&`UTQu\z0U/eD[bo4F#^r<`1sZ8ĆTd)CxڶPܼ03ff9zS(ݨu8rE:mQa| TeRȨaލ1Lߥkc-ʝD J7ft-8"Z,ưd.AEs!Z=o+VoCc~fwFzf+sT.{\> ֵDvxoN)G{?ۏz'`q]1wsKnT`~k.ǾoI[2@ %z Gau NȬ #B 琽 WH!7džQmd: n5Obyljar}`qTlfngWB̢/=c;P8joIS9**-ٝf, R0:aDy,e;좖`A > ; uQWfaӃ|dfq9Uޑ9cwJ'W, a&j^lH~/2xfޔS:n~ؙ\JSyZMh>2qmw*e.gM`ȕ&2&Ĺ=S͂e-edm*sܹdr؅uf )!Cpv/f5ө8ԟ3KP^?s,1(țΩH u:Pޥ>;0<oL0C2ͩԛ$)Jyј1xu8֥67%NLp.^1֙C A|8FGKyJŻ3 7 ?ITV:$k &~.Jh5, LO ts#0kޖ ZGy@)]j+]}n*6p[= Lh Fc*b]K̍e>Uݳߊ-T(x"NUnBi`S~?"D^gՃua.N`aܭ|]%^J|R3fv#kV^*BMČgGj: XրXIoN1>%X6Q`T 26AU] F[]@cC&5X5Zg;B%ȍ/l&H,9֢λ+w|½ǰK7WB8NV>3j~c1Ry)hOId3|N>Dќ.Z;=~%c{(9x?i+utX@q8;4Qlz>dw $;}0@a F%7CR1H5 {ξcӗiDvAV=KOT'+[1&3.\T?78Jg~Oޖd4s,vЬ:SunD&,1Q&ؠ$"qkn^mr\>vwZX=xܯw8ZNɑ ju"AfJp a ?lpuli .)lKwfȝ8d5 BB7jE1X4=j|B:;+;uֽU'}1:EQ̥4<p~G^WYmlŅ̮-ތlm<,IKn(+Scj>n{%#uB.^x#_]6lXuhg5*]upojcĕH!ElvIȄ:Nœ׬fv/vm)BEq1*2H&CynTiCHZp͕`$NǞRd'8<j7Ϯ'ȴo֭D*%@}N3|M rh.)"b, fGokiz^{(hxe1`0JNh)@6\bwzTECc3k3.Iv6TR/+=A_<-_bZ>k lkc̈́qvk~-{,{$`Q,N~DFIM{+fs;sEQ4kcS%cUxG/:N _u8=O2oUvl#̻lls̓4wtcфSPHNI3Mjǰаp<.iX!rp@;;{;wsy}} u u<,69C57 emgHl{XMwpv. g䀑uw2t.wq֤rBmqDG|DYٶ>eVήv\K\NLBq#1Bc厫Zj,X'YtGn'DΝ/K/q)0~F ~rLg&$ A+ehdSZ<4W%*0יUT5şD_ˋf1[V-gOzehkݴvS̟zħ4NuEǒ@~P}56I=#C295cV![_4S=`skT)H8ؔɝ`AzQ0bjytG{?iŇkXlM?9`Q:h1F/֎Vu N a6u>f>dzi:\Q)MN"q%#tEaJ<-6Z[=%A(=%1Rڵ!fY /ypYe LnXf}g6̽DUٻ9Ӎ;uDHqQ[@DR{fŚ'DI/lϞtq*k-0u 6,sÉH,˙8^Z5(>W`Z,V-:ChÑr٪I`YSN|=*Cg"R.TܩO4I5N>zU0IE _ZU0|VՒqB@d`(z.kթ\Ĝ:ʨFU- m06t6Nu ]=!4*2^FKf&Q4R9Kt !ŽyP@-@8=ԪQOe'2uVEfsěS ꘤17801̷y?_EFۓOҫ]dGg_(Z'q Y{ xc 3"UX؞'Eh ([?uW r~QHۗG 3b5WsI{5U~ƟYK?#p cg<硅ˊf9ό.@w}93Ͽi~sh:->W^ҁsϹaE7 Ga_*]hd8#/9Isr6pYqu{<ڕn9p)/S5N{L!F:˦_5^N",Xd2ӅI ?׹.';>Q@Omb]rlԲ3bO@ V:́4+=L)tE*Z<>g7"!x f\~Iɡ m(DHLw9vڭQMkdǂU!T,z\QLndDbళu<nrl;y\XHˆBk !fc**&#Nj)L&Sg%Ù6FyZSY.TDZ{ӄS9Dca@d~*p 9AYcf.TX)I$,8i#!K*b*\u>"եق*Tm_EhD!hgXke^TE\+!~X8&=ԼƝ MŒKR7rFP?qW4_^j.XXiFmg0ŒlV/RzWJ;Y_id-?.m/mjC՚تX6kۼ/_WHE35Qf2Eׯ&+5 /fqK*5("TCR,b2D0k=TddMR$j DQNd,܉j:Sݤ^ ^ `{Ą HhG2t?qI#<|V*U"GdDeJCkntߨw7q&4DsFia1R:/MY!1H:|7J4V# 8p(ۋG:a2EeRn$͗}'9$F|O_j4Povߡ(qy_j.X]Fc0z֠ ` QY/pSQz5>8!\85_f& c ̖Ĩ$9(*  C YC-,EWu#dV<pPE E(wXoj}:UbF Սϲ~-2W"l ҙOgUAɰ JUz` mЏ S$0|13a!=*?9=zaZ-#LtGx1KhGFVWcc+J JebűPӧ6!VדfMW:憲.5Kf K]_t Mpi{wOgt:/Xӽ%~F8:$cN1E9Lʴ9ǫL͝IE:Z_ :356QvR _8rC k"PW-=T(J BF%EӒYIIRHR(E`ZNNEQF{X vz/b˂*q9{d,,X%ͳ =XoCWE_<3h^Zꢖc(^0E?9 yY{q I7$&jjvYt` u!>Tu]/cUy"ެtz)#4$c^'ÜW?붹C~},s -a#_yhńa[_0ejN#ouR#p'>5,tv:t֜]C8];xݢ'74orE=6 Z:(K5 :2%3ovNy A*:%Z YA|f0vtB4CЩߔRID_GΟpvl[ˉ*ItYs*tJuƜGE>5変ЪU\Cɠ6Nɘvx_˒F)/$$=(W0Q|3X{qI0iu̬A/D#6sss,Kh~Qb an:15 }˰H:% tQOm^ԥAH4)-CNN{B'DĦAK=BltnkK6 -#sF([;}9GGƧ& SK)X69]N#0jzh xA'sĝ8OI$D9TCmffp{B`^ 䙪CNܸL`I0Uop>2cPh"Tn5R/Ryܥ_HkDj=PR%lyLiYISN]:bSs D!x ϐ\M&\v{$'t-M{G`gI}H1eF8d' <]!t[x%ƌK\Zn;'_)MkM' (ImTTۡ#B\#0پr9).|gȳh1¦;1!!X)zv ]s:iޝ_T4Ɣ>0*0^X} k=9GCOgٕ}r%Olu@3ھFӜ+Ifi+g{^C`࿹wjF~^IM{ٟr RDI˷!ti$2뷳W= p5!b.!̒spuPc:9k:1ZGFp&px֟Zj9̟8{ʷ4.%V!1%ΡyF>Ahd8ө3]ܹonb$ OU9~gֶQ^s1 u!oZZ7'U^a,u{@ӣNq]CgRqD &\;tV)E0mԨǨB?M9v~¼EYzQ\7&vɓ! y/6V]bA/;(k>IG3pB̩p/űTQ}أۚ{-{01 y]: [U޴zrm(Ӫʠ:6%|o*;[Jn4κ3׻Դ~l<09@oNAGKHsbӠ'ß9[ΧFe7 a #+C."TmQ]rMPuNjrA+/2PXdԞyҞR]D#cޭ7 Z,ډOgUk}Q_}P4m3F āouIY:W$ L#EGyR4 2Vf7 g{9i:vԑ؟dt:?Ȣxٻ_ 6NANřnQEn0UyK0U&Y#aD,ǀMlPfTQ&@9AN>$p ;n8"%qbN3j'긭)'MDhiw68'H+OR'd8lmEŖ)elˑu0SFև|LTu[6u0+_v8z r|?ĮA,0:R'px|.&1،[& kIW\0d2>f9n-4Q s@jΚF]T5j`<%$@qOKty}bDqxL M]zy$d,B ˱@Й>{4kߟ1+_O54Q3!dĮ dx%u ,f#Fe$)a9?)Sƈk,EY(9 wOz(b#~~\cMx; <7rW[ 4kOD?9QCq RS9X V)9?SB^S2vQ9cLkL"@&vc~ n4Is'$ED#{rT֭ѰQ}^vW=-تnsNAR8ȴ ~ L'O7\=kD&2u-R-|E膙'7 a5`6c&jV]ZcbRM]\XC aAC"CM')r+ r.ȍ\)fßL6͟g ]v09XOX7.{h2kR~?ӿi'^tM] edY"L`͡tg@Ѧ3"yfAӽc%`1郖/n>t֜l"!cSq?IV>`H[uv} ]6U'ldV#YANf\WFM{'WGdfRMM.6~4SmuH7qL x._ qyw$Bћ[*Gfk˷&NkyS|U* ~4\5)#BQtȗh>2.MwKNeM<1D%4Ayyьƌf`Gek_'n'phœ)Dѻc=97XS`/ޟ;qee?u0#|)PNxNUɗZHٸT#y̹dDŽg;ۢ_ uK3njvNy nkdZ&NWqRŅ2+Hv [z'HqZws,s)}4 {? pl}*%Ok*j tSyi\3"<8vIgދAN7K܀9z⭙1sޖ2cKJk=~>`&Wbɺr^.E1u&NAr'MH8'i>0pN"Թjq"ב<ܥk"{!6ΚrD4;x/*ÝB9,#xs8yx Cɧ#Wd!Z\0^ZR50f50թT{U󯮺N)&@H!$r7!JP13~wsDHXM':Džs'k>+\(sd }i^=1+k=dH $lGj?*EvtOMn2h9prD9B362DƿQ{W:˓*u5юR`yėn{#2E <`hO5{R AShZ1#=c^~&9?i;›ھg39]&ʡ~\}dԐM%XdynfN"B3H`)p 1'@<#Fqf'FPᏐos&pbO|}=sVfg`vg'z.ݝөUhzj`uTm 1mshId" pvc3}M C>4J8ߵu(8ɝt7A־DR_ջx3ӟ/W_L_ mx0:<f3_]غmz.Pp#gTw_A=+n.}ȠiV"[䑄 MP\ ウRpyOmڴJ$W̖A7[qʪ\: 57_ Bf 7ހ**ӊ&gꇵ#MO Z5Xd]Q87LPzsWT@Yl%|6[Đ->?$diU# ixqCdkb[pEӷM!d iB* _K^<`qe{)/^Y??͚$H"؁6/2lʷ65m @fi!_Gj$*+=R`c'>k –B!ZfcNTO->PMxmpS+"0@YHbݏ!@8.)l 92(vHjy=٤g:U Nho,Ŕ>r)аhz Z$e s.E쎄40w(㪌V.FUY g]|Bl.x Y{f߹zXrrwt}~^z+?ij_Po+z{S"T1-5AKʅ9ˠt%&c%J@.(n^ԻvMX`꧎v@YF'oۨ>pw!A-kadnG` Uzzpߞv noj=la+-Aˠ Ivii|'C:%) ^ƣlREl\a:X l2X$TCxAƉL(D>W 3E33m] bRo*Wݰ0o郿jEtĕ4~yA?Sw<+$*-[_2♧#*鋞|ΌO{$-BVFS[ɏ녲տ3/˅% 񋫪C3&r_ɒTѨH͙1%e4Z ֚Fd EcBH ٝϋAIfEZڥ >eܬB:k+彪H~*ecO:!U2:qlx" yZmR|.ogC&̪j 0\_L6>cH~\Qah{aK@Z}Eu2]\Urf-JHnv:<\VpďC vl(q;\ԭ~߂_vo~k괁f{o(J~kjgt2R}_VrHwEurmjdcS;Ӱh\XHTeX*Wucvub"i['$+㚦VKV/F~kz՗:t&50#CEűtdOߨx~I ̌Թ|^MCc]JYWd;StywRlK.7jWSwH}V >x;6U?|UqxpXs4IˈOsU#I~l I~CURO3Q'l *S6Z:JRoYcCxyR8ьAU W?[h?AgM ]Fϭ.o[vR*sȜ[|~BM1pR=S0 [xò[&9 ^@\,yC!=[yݐTU˙i~U:86Q]:ۙJdJN {qX|m?6O HBiCYd9MWM9_Xh ; K%_We Fq3ݦpgDFI*DFh)*"UH|FKD  s5[/>g\[}+Ytڙ gY\q1c 4,&d́aotiekWkrZYyYŰ`-cWJI<-Ph1lͿu:(κiZ,T$ ӂ?Ic~S GX4FvpFq=zaYT"x))5Py/|ilBVx>'3Dp.mjy)[dHj9%_ Q~{u${ޛh~siDH,6بNڄC\ZMIMR?6|^;3d: s-׊- ,-v qV*|'P¤j ē!pƥ*L\Θ#KUp%D|*JRp"UN^)6'lMUYSKN,8H5&c,&FE/bIʪDEue2Rgjo "`Z2Em=Isae! |tSU凢Eq?~J\ ]?KsI(X`ë4xW~m~\WDžΔ*p@hxůKJ72λ=nWv.t3Ũ3'#޺+~QG׎ZJUeT\-_>0Xcj׹_*~\?Rr)p +sx!18',ST$|/= G܄]m a5r'T:O)p ncHκ3 DpKRF%1dXkE7./[޳l*oYݮj5[mչbȐ&l7*7M#ATfq, шG#(hD%ބ(M3)'*Pr&K7'[~QQP_+I8qRI;'O O;.5v:c1{$DbL6V7ې}֔72u۞loYN;-ڳ8 'ΐXRbenl7 Ԥ4i:?mKł-K+J̘e(ق=ƣYR0d\,D`?^eE@GtOݍ)לQ/j2tJ4D9NФh5KڵJ덄fAi8 tɌښGrr9p]i}bb˲=dFp՝cdcg۠`89kCqLU_=iUYcY\|rWW褾AB쭳l/L['I$:) Ќ{+Aٿ>ڻnSGeDpf(}SU:+jA<1꽖3Wk˸xt"#еZnX (I J2uưE]"tv$ҜecFC,}cJ,ogtu,_Cj:˃ w)AeT_~uvD`I ȗ!Nd4U5(todX'% E-A?z;<~-g+];H(|*"KaR=m-Sk!Y%{ɞ2|pt.E?>nYv Hڥ[MAQN#(sWljGΓy ;N*os|Oغ`ݏ|6\Z8i tS4\00:c '3aX^qMaUoL bMRY=j"EEý/cggD`KQE(x}zWOO#g\C~͟uC-БjyáE l*DnPLUޱDuȌ[D"{z KpP:-/.Hˊ̰c>TPMd"md2C6aA_8-Gcu_w9rv% 0,BxPx$&0)XȩyF8}/s'XG1ñغ@CA=w|ߵ qu6 c{PS7Hg-mo2{8{OPJ"(lԯ'*GܱԂ.ا{w7cC[T_a k=ɟI$X_sKTB.}cݵ)TTV"5ƻ'y˂{7t\?'o&:Jw9IRwL*4PCxG>k|Or,oʉ 3po9$C'$LFt:m]Ft x;^c#U̓J>'~3Cg^ȯY|!ba|݅ zЄ*[էʊh9Lܫ_Mz$s@Sfa#6)m,<h+`**BudC nK AEpRbO䏙ݩx;{y{$0 s-]h[ 3'ӷkCP~v7aӘ԰UPyV=<"Ğ4rk/Vͩ=n?h3m ZD&_(/Q"? UnA*+ab*;}zǶWᄦv~$7QJگInDtGFJ\i &=/,S#ƴ],Ap! CC [ ?׵[a|v%2GqĘaS1pڭÇg{ߞђ&bG{}QѕFx\=t}ļB9jt;W O(ج^ɴy=ɠo OoM{ӗA ֒<Dj AxUkͿn~~{A2z("fq1IVX3$\i&|#^AKg'$2Y9kF C&$_wěr| VD) Gg%7UagB*6b~p*H1{@E P.2Rf\TuPɓ`-]ӅA<?B77[oCU;s[:HRLAdl6)Bv &CcnG*5g '?teh*clJT8կaЯk˸|M5u$wQt|I+EN :8=Cx@H/*._ITv0B%\.4誃6B{'ug]#cdl\gc4>f\wxW/M"B3/fIukKG|DO.:큺L-Wpo*:2uV9А8=hwlxT(=9pca W,A~. &.֑Հq9U|gf< HR}IMơw0|7sI| 1FXXYfLfS2Jʃ˳)5E)uߔ/G̦Dif]}fUVP؝`m6S'gD\_jAzI9.k~m`漉Ϻ>3Q/S mywk7>5_Af,>H~V)H1#~Rf,Ι`f, (*?3m %a EƤz6R#;֥ܿ^aI}1{_9>$ȯ ๭k87D郧 \L e2Oz !|pFy,[T_ޣb51hʸk*& _-~yFB;&LZ/u@yȳ1٥x35+g8{+~_ɒ3hvGŔX";(ಃNӠNBRvcR[t`΁Y(o<_< [ a _Ri]D|@ 'SLl2hi3^psaP],e - *@ՓE /-[ўtK*/BBU@>chĽ_r*T9w9c@Q/i,EuHngr)cuҴq<&1?ygˡIؚCf Jv1dKj  lKX Zͳx9tP6|$4q\dF|86h &W* 8q"ېSBhʕ/SMrcCR'KY$fhEgFYTL!53lqY;1^~$%cW\g^ *z탪ч \t]6Eg[`a|hE"nf|H#/|BlWZ607+I$Ȇ"(v//\sWZcMirnDVR5,z7P7O>iٞ/,5« X ^#~\/A?lpw9KjeSnL\^,UmdG4ѐ%G,Z9LWM-:`Gtun@ER8^COʛk< EjNzDiE[ @[']c?=Gl?Fяx~h&TL@₆fy'+xY T}9M86+xeUc}Z\~ĎCo!T}>ۆC/8#MH餚9X K{gyN쭲|BC~MZ8ɝ`A&;ct+k|PoP l䲕gNeT|Ճ%bCuk @$u~3vؒ5Ʈq vw`˯_VȰmKj)O>2ɘyDg TK1$L< lW+'[PjuԇG7Uo7N.@{~v@8\/{׸;t'}՗WØv^cv+7Vmš»A؈hcdQm ,rO䎮!WiIxob I`;y?\N?\Əq?Ƙ2P7U5jcStn ?f*϶Gwhc-1RT}t~3E1B~ٮn!HbYJ]HlD)$%cɍk:-4Z'ȼt |QQ Ĝ6z+vV߷n?0fxΏl[md/ |}䕊.7I`qT'G#e0nh7uƧ\Fa³λ&",ѫBt cL*eY c5fuͫ @(JDpBn{EϓAO:ɻ;z11Oe!z/YQ$ @lwotqޞszB z=u9;eޞӄʙ>𤋮`ʳbm MANxauN(t#M&>ߨ^`1$Y ;X`v{b ?<\2݇ #X38HSKAĹBh((=7)w0["},@"]I@-uBBuᮀiFa؝0DY^LH1C` ?CӞ֖-A0a9 'lQnba|gYmP~(VIw0EOI@^9*Kң ^ >ꡕPB7A)|~[O'4ة(L5?$Ͳqr$-l鏂:eP/[V/ JWb9iZ:`߭ZsJPJ "!DwkR$zXQʠ6X!tQqq{# /GBmioG͔G9B̝vS4S.4Câw݊ٹ*nja:}i8t{n^:.j2uV;YMo"7 cc 3&#* >2i8 =&"^OA_jJU(%6eWr36p.pt]dcNArbȎ1|@em%]p3vaRTI[(y R*'6fb+}Ƽ=0_ii|eA#b.ݝb)x`j<]"f4TyFp ZxCGg斤^FJM1l7vŜ[w+iSZ* ̠UjΡ̫;0A۳leAˆ}zq߂x*{jG2ykqXnLGLT[8T ( z[aK""fTW@vvS0*LaUui4 sNR/y, k3u*$R;IwNV>>iL҆Ū#Y꧹@>넾7u10bVjwھ}*B!J"+޿bߵ?yVQe mwQ[:djY}&NnDMuZj TU.ԭd=(g.Fv cF_ zL' YNx`ϋS 1ԩe[<"].H_:Ayr^&^Ck `,K2TLGH,2H_DWvFޙՎk_^~WsKk`鄿QN]{ sߒf(^Z&j:x-RlG~ҕfsN Y$9TqNyR|fSyYHLJJmJS'ޟ})(EE=4ušwVMG];R &nf+&P%]sdk`1F}#hcG ! J"vFX⸉GM)z9z9$K~\aȝk7CUٳ%:n5z'^C`f#՞b":k ,;FaaaaaA4GK}rz/cb11.[X4 F zGߴp no?4G ] D|ã(m2η}IH9GV&Ҽ ҳQ$6\]ڑi{_ry@_.u&\o:nkI1J71l`ic})6C$LIѨ!,V:,*_|drV)a4F’u|(@jq}Cz(}NCZsr{Kula5TlKM(G{7~9nO٠yFxg$cHh1̛>0s`11:XDl2RKlk})Nզw_!֪6SZ6/'*GqbӠyҩ~D|}1P[~mxyS+[ sj#)rٔ#ZwJٕ^7J`hr(9vxf1V&q];~&$;xZSbb]t`7;L|zDU~=)Vb<α>qMȥo)q5ڗ |K\V88^w 5wcvoZ}x*~WoC*7o[LSkx{Z;oyo",Fw| kg$n^'}ӛZ'M:bU7⓳' rдǢ_xrYMsyw['{`ӠSxqJQͦG2LF;s>YGW>bb#svfn-؈RLhē%Oy NPi+3URW:gk' CsmA&28H'zr C2u-?i\`ZUSoScIɰUaȋ)F(gxk+/F[\څ|:kIڎk~w(#6TX09鴘_S8)iG-)zf"#YJ'Jc)m fCl4*4t^s2t'2RC8CdQOT?/>9- WfDhy嬽`ӠwHSg/oVv2=.KF ufpt5~ӝi О\?ә#Vs'sqa;O!RXcwg>ӳ4: a!Rey7f:ԙ<*Đf[#uUM0kN s B ^f':ݹߩS { T \vHUY 2.^+LHtLqAS?iwYfr<8"vF2M"1=VPÛ 7 ]:⥴~vR6ӄ6q"') !3r,jWcZ:&#I1SPfa(n-Mp0x=ѥ;hHi%D0?n% $}-ݪ Q+0ၒu5 J&EY܂mXs$eu :eQPDxȄ)qu}X4ɬCb_8$ cT 7BIp=X9A4'bl"*I>(_1+4` 6l6dQ@ȫ9Ć8s,:q6Çg= !ǃ" SH κiabw#L8"*jY'CXC90I1 W[LvW-C^3US. aJҁg4SX?xr_X;R!Ӏ†.F E k 2El@}fJC'MQhW#r_V&R>PbB8 ]6ݶNlFey^a/ywP;L"z P8R g{ Oۊ6R^qՏ C>1/>ѿ I*~צŅ.xns8ҹAT6I +/Vy_/sn~sumOԘN'ĝҮYzt"w4;OB9׽9YH{\/,ސWQVz^ɏ`?CәOgMMSκFYuV$SF74hԉ2!s8~'~}lx:J(42lXsy ϐ:6N<{6o#_8z@~)塿@`*2]/+]PZf)']+y; ԃEj|ӌ񕏙 j(%gP;3i&T(NXS'Sg:89=hw`x[Lڠ41~YׯoB,6kN!u, 0 mzP3/ VT*qi;c-e@Yfy,~ %@aVwDdI;k9I@򦈱@?҆&дZ#70gE-|7j<S5u5c23stm =*\?kʃ_¦icwB J;**%i㮗 h+iBPOIĒ)jH$֫:Prt L<׏xWٯ!YvЬ@ eWf~^;j:EۓUfL\w{ʐmܒ d1̮ 8 y l Dh (RL1xi*0Xׂ'~\ZE),!7NV~FPR@9Q7KcU^#AxVEkV ƎMLP,@/j?~gtA? Ln(S9S9qԑ<iz)1 eڞrSmHUOh,&FDFmhC4b$U&FVHIR' vdXSvҾfûA[qoa9QκWiYsj?pt EDMT}=ՔK>ѳ7(S܉R0.hK\'ޢnu]5HwM 0ϡ8}1?LPKi Om)`L^|'t΢F1Oi vC ;1>((i|eAx:ذTΦAK@mD~VZR0CNcnzqb˃4Yp28Ck??s5hSv OJhnZOܿ<~a\QT( Xj_c=C <|<(D&uɖ-Fjd.LTb<Ȕw5Ia0V?APVdXJ&[$лصRRoz VF++ujp(waI릨$@*Q֢EyuU_]רJ: Ou)jgw]eҬ&k-X̦Ab2g^:XhA8*tCR_j;2EVenge-3g(q RD5J{UM3&N>٠8VO{:"z˱ ДGgu0G^JM_g#Fhᝑ~ZP|M4f1i<Ɓū̮Fوuw y&Z_ na JG:* ?pF?/UqϋUɾg[KAd>3?%:y ' d}q gRC#xêf┠|I? &T-ݯ,(=〛ZU*%%e/6fqXCc*L]hH`\ SPT:X A I*?Z]\sdFI"=ZdE ,&^͗qNݜIy}V(H[5; O#U ncg~*p:_i?1%r\U9Q${heּAL7"_Qem"ldΔ`mM]-&9ϽS)oF wfԋ}Ŕ\/h2f5jwE=T'vjI\43)Ya0?ܞqp?@8}e*9c:fߤ/2m4eA>/CSnε4;[lhj*(k\.ƇSMH"0b#ǡ *pb:AI 6~rÃ0Ițm2eWaG&{Eyfgv7? mAS$G>a2~6ev 6i&2ٯ* $MFF "AκeF)!%U^ ڡq #82{<8TDnZ2ݸDiM':RmV9Ƕ3/$^aJ3\p }Ka|D`18|Gkyeja2kϽ*V!хXxd'&ns'cnvk.U_ ؅W[y)PjIolo͉ .d4{km:suooTT]Wx' (-ߩ}T &F$YuqՉ$ChPQur UUF+JnRI{&5^3xJA(" k93yomxW?)Q)ի~{c[쒛T%5ZujIu̪,:e2'}5(5H#ubgL-ڳư@?S/AJC2tӕ~z54 ɘ >.ڂ&N[RjMύ\nHdUՋUj(D%'>Uq_' ^[I 3N`Nƒ N]UI`(Aխ]m}/A ?~omߛ/MS|4_%ql} mahB$z$dDMK=TP}4^ )¯ s@@ik\UqUUWK\?A>x FP25)`om'ظ@eTe iwgK r+yRX͎:_<@F5 H%e˾Q,֝)pP7ŠN䇂3 4mms+ڨ;NAr'MmPuX4žKrH]qEVu)XAe,؛oJOĎŮ$--ص?z:]N* f` -mw&RQi=f۱Pnœu󷊯qhLȘyEj'*chJ(U@# էEgaьV5//lL⩂ +rV^B6l_-lmP@՗FE[0]ox|I/ o_K*w:`LF%Ap&DXnNܣ 6keTG ?1On]D(O AĉRṂg!98y,9XmiJշ[p4/u9p]b`u0Il Ť;j:T$I*+/Ew&W8|%44X:S.Mx{4Ag^NF=CКF_/ihS|hr<{z?qe5HSyڞ0(ChK17^C4ŝtv9蘠udފLb9ߴ=G-!0ϥ41!Z?}׬4fK?,[>>-\-oN9gM ]wSQEZOz12OF.r?6uK>iLJԝMN{r$`<$ ]))-roLa<)J0-iia*/a$KdqˬB6< /w/-vwM:Ϝ@s&2ڦY-*zs<.w%OҸ'P bhИeNκe9LgOZLg%NlH;0nS Y 6CmTU+^&= USB_THv.&at<,xPۃMvxKrX TTMJ(DO.D&vC[Y" dFf)9  ߦ Qc:R tb,"x<ՁP]'\W v!~8A@/!5 3mq2=-s`/ٲTذ%V'[oW), /<9+l@ze> K@cѬִ/ IXxck~IEvX_8@ĒQ=%ŀՔ { AZ>BCk!U tS5e&rGiւΰ [t끋w>Pvy s>+ys&ŌpS,QSa]7uįZDꋇ^ \̒MDF ԕJ: 2Wlutb\H-r[YhGyRʕvhdؗ{|xX0yp3t:p 6'zPaߵgmF1mR Ll4h|О$ Nxg{&[]^[^O4y9iNQUsj?GwC)Ȱc4;hb=Ǫs3t 5Fsp(. JqXc̿;sDa)ʰلg NH ?+_`\NqE.ɽڧ8Hm> 0(3~kBpJF5iIGA 3wn98r>C'*!ԚYtڙӂӪ.a7^%Dkn9m+JKG5e)3_IT8 xTV>Йk4ˉwשn-8Q X:K f3Θ4}tXWPeLnW5GtԸ}qMfbQ.FְzC,!-z{ q Eo9s1oir`X6ptmԏ2x -FzM?/&uh3G[\ VW#V<)xp;GfE:+/ν$|eJwPLL `xV9S%ls/Jp44´$*Lx;MdB[.(R$d-Q M2DcJF;p0TܮJeP'-xzH05!R:tij54!ľ ַ >Mn/Yvt5u2u-vxLPV4 >LS,p O/brf YZ.TT?chؠW(x[˃ՇT/0Al_"2CjpG\8f!? eUb6;Nks9&|*L39FXBc$wRXaEB#,̳F?^ؐ-*jpP=I ck#xH= +Kf=X<gBǢ;e=kuJt;vf%ߋK4oc9<%e^}By[/ P-N-[i5*Y \PTDf h#2O7&(ĕF`d0C"ar %'ZTrc'=iЅ9uܚ*ozF~}vJT ]5z0=.3AW@G 6הboЅSbbڢ#e=i8ERԍL\Ϋ: ;oPX[SFHʦ L1f'K"Iep9cv6jЄ\; #ڹ7e֯"zGC7*5SP[Öٟ"B SՋTjTpfӠyҩf.R]m`bsmw\EƞXJO$<[Tm-3ynn_p$s Ł5U&vϵ%mawɍׄl(B$]NaH"IX0廚ltߖjULiF' -a -cIϨ<)y#]`0FD *>\7Jyn2M8UiUSCJwT rOK{(KLs{!yIpOfys{<.́ao/ݜw-~,\ `b<(}4uA;o^P|̟8uO<{Ž΋9/Ja{qG?/S~S3%EE5)7'*,*f63:nuhܗf)J%ޗ6rAzlΊ(GM 2BU:lD>I rpX8gS?H*5Yn cVeJLNnvMm)xe7xwn\:ebII_6ӦC ? 8ښj=G qK2#!%3:ip3=nJwک0I-|C$4Ƞ1Ou7ĥ|{\TyC$bj;3OЪC[ͼ4ES؟iim-бdu8 l>OnNk`&Vsق+bZ)Rq'S~'Iß|LyIc9{YXߟON^VҎ#ei* EKa1e܄CtaQ qtW#Oŷ,C;#)D~"t7v"&`kU U?ӻujczq(*<}$d g_x/ dr¶ȍF/<( &>4Gh֠2))I2;Id{]v++X#Y9IƏp^> nӶ~Kuw"!j䀌 J1>6dD5K-J;?Br/ SZ/{ϊ;)95rV2&ڹ0B^4 5_yKY_:+(B~^ 5JY8CkF\‚zh 5 Lz&' x_; $̉ ۘK͍l'bq&xDf>,f @I,<[(("laL$u3e+[l ;Ś-VشږOh>i)~Âݯ]; 0;u/$J+[o:y &&tŖw۾qgS5#d\lzΊf[)H1i&H^rۦ=ii;U-{Er]NTD(] L>mR*:k*ʒ!-f4:x۬hwn`[Vi剽~\WCEE"E0VƱDF\%57j)Gg2trXY@x $ljfrtLR^:Hk͒x[?/-;CBka,&F ZiHU8A%&ukRM5-?EojY_y ^t8,J;,/lk7,+$mP(B_~RO[n6\XZ6WEhqʽ٫n)HY*n/$H|yNȋ~{1V^#t4 M9\$9H8ᘩ1gz!Kq B&_GTF%BBpe0mtF*W#ҵMn 7ljެ L{[|VpFՠo~k҂  M(?\[lcs:SIw_Ao@DžѩBi0Ԓx\]#(;V-D@o,NBR ª0jsZ|{:mD` \YRkż_%[kV( }w@;\N64˘;v{:ay7'oo/Scyl1B%.Ձ Vx35Ǧ1:G $TiEGr2%@Y'Fȣ3Lx͇L65*5tЂ(!P{8>Z+v޶\̗]ϼq|!/*( 9.WG?!?`U_Jt0-fL/ZOL4Qlyuڜu5ʳſZA%MB@%JggjinUAd?[ߒ6~]x|׼^ B"ݦҜ?TegM/t~ />oKI@g6I-_`)~݌y,MQ=jline-1.0.orig/src/src/test/java/0000755000175000017500000000000011550705746016640 5ustar twernertwernerjline-1.0.orig/src/src/test/java/jline/0000755000175000017500000000000011550705746017741 5ustar twernertwernerjline-1.0.orig/src/src/test/java/jline/TestEditLine.java0000644000175000017500000001645011550705746023147 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; /** * Tests various features of editing lines. * * @author
Marc Prud'hommeaux */ public class TestEditLine extends JLineTestCase { public TestEditLine(String test) { super(test); } public void testDeletePreviousWord() throws Exception { Buffer b = new Buffer("This is a test"); assertBuffer("This is a ", b = b.op(ConsoleReader.DELETE_PREV_WORD)); assertBuffer("This is ", b = b.op(ConsoleReader.DELETE_PREV_WORD)); assertBuffer("This ", b = b.op(ConsoleReader.DELETE_PREV_WORD)); assertBuffer("", b = b.op(ConsoleReader.DELETE_PREV_WORD)); assertBuffer("", b = b.op(ConsoleReader.DELETE_PREV_WORD)); assertBuffer("", b = b.op(ConsoleReader.DELETE_PREV_WORD)); } public void testMoveToEnd() throws Exception { Buffer b = new Buffer("This is a test"); assertBuffer("This is a XtestX", new Buffer("This is a test").op(ConsoleReader.PREV_WORD) .append('X') .op(ConsoleReader.MOVE_TO_END) .append('X')); assertBuffer("This is Xa testX", new Buffer("This is a test").op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .append('X') .op(ConsoleReader.MOVE_TO_END) .append('X')); assertBuffer("This Xis a testX", new Buffer("This is a test").op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .append('X') .op(ConsoleReader.MOVE_TO_END) .append('X')); } public void testPreviousWord() throws Exception { assertBuffer("This is a Xtest", new Buffer("This is a test").op(ConsoleReader.PREV_WORD) .append('X')); assertBuffer("This is Xa test", new Buffer("This is a test").op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .append('X')); assertBuffer("This Xis a test", new Buffer("This is a test").op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .append('X')); assertBuffer("XThis is a test", new Buffer("This is a test").op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .append('X')); assertBuffer("XThis is a test", new Buffer("This is a test").op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .append('X')); assertBuffer("XThis is a test", new Buffer("This is a test").op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .op(ConsoleReader.PREV_WORD) .append('X')); } public void testLineStart() throws Exception { assertBuffer("XThis is a test", new Buffer("This is a test").ctrlA().append('X')); assertBuffer("TXhis is a test", new Buffer("This is a test").ctrlA().right().append('X')); } public void testClearLine() throws Exception { assertBuffer("", new Buffer("This is a test").ctrlU()); assertBuffer("t", new Buffer("This is a test").left().ctrlU()); assertBuffer("st", new Buffer("This is a test").left().left().ctrlU()); } public void testRight() throws Exception { Buffer b = new Buffer("This is a test"); b = b.left().right().back(); assertBuffer("This is a tes", b); b = b.left().left().left().right().left().back(); assertBuffer("This is ates", b); b.append('X'); assertBuffer("This is aXtes", b); } public void testLeft() throws Exception { Buffer b = new Buffer("This is a test"); b = b.left().left().left(); assertBuffer("This is a est", b = b.back()); assertBuffer("This is aest", b = b.back()); assertBuffer("This is est", b = b.back()); assertBuffer("This isest", b = b.back()); assertBuffer("This iest", b = b.back()); assertBuffer("This est", b = b.back()); assertBuffer("Thisest", b = b.back()); assertBuffer("Thiest", b = b.back()); assertBuffer("Thest", b = b.back()); assertBuffer("Test", b = b.back()); assertBuffer("est", b = b.back()); assertBuffer("est", b = b.back()); assertBuffer("est", b = b.back()); assertBuffer("est", b = b.back()); assertBuffer("est", b = b.back()); } public void testBackspace() throws Exception { Buffer b = new Buffer("This is a test"); assertBuffer("This is a tes", b = b.back()); assertBuffer("This is a te", b = b.back()); assertBuffer("This is a t", b = b.back()); assertBuffer("This is a ", b = b.back()); assertBuffer("This is a", b = b.back()); assertBuffer("This is ", b = b.back()); assertBuffer("This is", b = b.back()); assertBuffer("This i", b = b.back()); assertBuffer("This ", b = b.back()); assertBuffer("This", b = b.back()); assertBuffer("Thi", b = b.back()); assertBuffer("Th", b = b.back()); assertBuffer("T", b = b.back()); assertBuffer("", b = b.back()); assertBuffer("", b = b.back()); assertBuffer("", b = b.back()); assertBuffer("", b = b.back()); assertBuffer("", b = b.back()); } public void testBuffer() throws Exception { assertBuffer("This is a test", new Buffer("This is a test")); } } jline-1.0.orig/src/src/test/java/jline/TestCompletion.java0000644000175000017500000000504511550705746023561 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import java.util.*; /** * Tests command history. * * @author Marc Prud'hommeaux */ public class TestCompletion extends JLineTestCase { public TestCompletion(String test) { super(test); } public void testSimpleCompletor() throws Exception { // clear any current completors for (Iterator i = console.getCompletors().iterator(); i.hasNext(); console.removeCompletor((Completor) i.next())) { ; } console.addCompletor (new SimpleCompletor(new String[] { "foo", "bar", "baz" })); assertBuffer("foo ", new Buffer("f").op(ConsoleReader.COMPLETE)); // single tab completes to unabbiguous "ba" assertBuffer("ba", new Buffer("b").op(ConsoleReader.COMPLETE)); assertBuffer("ba", new Buffer("ba").op(ConsoleReader.COMPLETE)); assertBuffer("baz ", new Buffer("baz").op(ConsoleReader.COMPLETE)); } public void testArgumentCompletor() throws Exception { // clear any current completors for (Iterator i = console.getCompletors().iterator(); i.hasNext(); console.removeCompletor((Completor) i.next())) { ; } console.addCompletor(new ArgumentCompletor (new SimpleCompletor(new String[] { "foo", "bar", "baz" }))); assertBuffer("foo foo ", new Buffer("foo f"). op(ConsoleReader.COMPLETE)); assertBuffer("foo ba", new Buffer("foo b"). op(ConsoleReader.COMPLETE)); assertBuffer("foo ba", new Buffer("foo ba"). op(ConsoleReader.COMPLETE)); assertBuffer("foo baz ", new Buffer("foo baz"). op(ConsoleReader.COMPLETE)); // test completion in the mid range assertBuffer("foo baz", new Buffer("f baz").left().left().left().left(). op(ConsoleReader.COMPLETE)); assertBuffer("ba foo", new Buffer("b foo").left().left().left().left(). op(ConsoleReader.COMPLETE)); assertBuffer("foo ba baz", new Buffer("foo b baz").left().left().left().left(). op(ConsoleReader.COMPLETE)); assertBuffer("foo foo baz", new Buffer("foo f baz").left().left().left().left(). op(ConsoleReader.COMPLETE)); } } jline-1.0.orig/src/src/test/java/jline/JLineTestCase.java0000644000175000017500000000727511550705746023254 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; import junit.framework.*; import java.io.*; public abstract class JLineTestCase extends TestCase { ConsoleReader console; public JLineTestCase(String test) { super(test); } public void setUp() throws Exception { super.setUp(); console = new ConsoleReader(null, new PrintWriter( new OutputStreamWriter(new ByteArrayOutputStream())), null, new UnixTerminal()); } public void assertBuffer(String expected, Buffer buffer) throws IOException { assertBuffer(expected, buffer, true); } public void assertBuffer(String expected, Buffer buffer, boolean clear) throws IOException { // clear current buffer, if any if (clear) { console.finishBuffer(); console.getHistory().clear(); } console.setInput(new ByteArrayInputStream(buffer.getBytes())); // run it through the reader while (console.readLine((String) null) != null) { ; } assertEquals(expected, console.getCursorBuffer().toString()); } private int getKeyForAction(short logicalAction) { int action = console.getKeyForAction(logicalAction); if (action == -1) { fail("Keystroke for logical action " + logicalAction + " was not bound in the console"); } return action; } /** * TODO: Fix this so tests don't break on windows machines. * * @author Ryan * */ class Buffer { private final ByteArrayOutputStream bout = new ByteArrayOutputStream(); public Buffer() { } public Buffer(String str) { append(str); } public byte[] getBytes() { return bout.toByteArray(); } public Buffer op(short operation) { return append(getKeyForAction(operation)); } public Buffer ctrlA() { return append(getKeyForAction(ConsoleReader.MOVE_TO_BEG)); } public Buffer ctrlU() { return append(getKeyForAction(ConsoleReader.KILL_LINE_PREV)); } public Buffer tab() { return append(getKeyForAction(ConsoleReader.COMPLETE)); } public Buffer back() { return append(getKeyForAction(ConsoleReader.DELETE_PREV_CHAR)); } public Buffer left() { return append(UnixTerminal.ARROW_START).append( UnixTerminal.ARROW_PREFIX).append(UnixTerminal.ARROW_LEFT); } public Buffer right() { return append(UnixTerminal.ARROW_START).append( UnixTerminal.ARROW_PREFIX).append(UnixTerminal.ARROW_RIGHT); } public Buffer up() { return append(UnixTerminal.ARROW_START).append( UnixTerminal.ARROW_PREFIX).append(UnixTerminal.ARROW_UP); } public Buffer down() { return append(UnixTerminal.ARROW_START).append( UnixTerminal.ARROW_PREFIX).append(UnixTerminal.ARROW_DOWN); } public Buffer append(String str) { byte[] bytes = str.getBytes(); for (int i = 0; i < bytes.length; i++) { append(bytes[i]); } return this; } public Buffer append(int i) { return append((byte) i); } public Buffer append(byte b) { bout.write(b); return this; } } } jline-1.0.orig/src/src/test/java/jline/example/0000755000175000017500000000000011550705746021374 5ustar twernertwernerjline-1.0.orig/src/src/test/java/jline/example/PasswordReader.java0000644000175000017500000000163111550705746025165 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline.example; import jline.*; import java.io.*; public class PasswordReader { public static void usage() { System.out.println("Usage: java " + PasswordReader.class.getName() + " [mask]"); } public static void main(String[] args) throws IOException { ConsoleReader reader = new ConsoleReader(); Character mask = (args.length == 0) ? new Character((char) 0) : new Character(args[0].charAt(0)); String line = null; do { line = reader.readLine("enter password> ", mask); System.out.println("Got password: " + line); } while(line != null && line.length() > 0); } } jline-1.0.orig/src/src/test/java/jline/example/Example.java0000644000175000017500000000665411550705746023645 0ustar twernertwerner/* * Copyright (c) 2002-2006, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline.example; import jline.*; import java.io.*; import java.util.*; import java.util.zip.*; public class Example { public static void usage() { System.out.println("Usage: java " + Example.class.getName() + " [none/simple/files/dictionary [trigger mask]]"); System.out.println(" none - no completors"); System.out.println(" simple - a simple completor that comples " + "\"foo\", \"bar\", and \"baz\""); System.out .println(" files - a completor that comples " + "file names"); System.out.println(" dictionary - a completor that comples " + "english dictionary words"); System.out.println(" classes - a completor that comples " + "java class names"); System.out .println(" trigger - a special word which causes it to assume " + "the next line is a password"); System.out.println(" mask - is the character to print in place of " + "the actual password character"); System.out.println("\n E.g - java Example simple su '*'\n" + "will use the simple compleator with 'su' triggering\n" + "the use of '*' as a password mask."); } public static void main(String[] args) throws IOException { Character mask = null; String trigger = null; ConsoleReader reader = new ConsoleReader(); reader.setBellEnabled(false); reader.setDebug(new PrintWriter(new FileWriter("writer.debug", true))); if ((args == null) || (args.length == 0)) { usage(); return; } List completors = new LinkedList(); if (args.length > 0) { if (args[0].equals("none")) { } else if (args[0].equals("files")) { completors.add(new FileNameCompletor()); } else if (args[0].equals("classes")) { completors.add(new ClassNameCompletor()); } else if (args[0].equals("dictionary")) { completors.add(new SimpleCompletor(new GZIPInputStream( Example.class.getResourceAsStream("english.gz")))); } else if (args[0].equals("simple")) { completors.add(new SimpleCompletor(new String[] { "foo", "bar", "baz" })); } else { usage(); return; } } if (args.length == 3) { mask = new Character(args[2].charAt(0)); trigger = args[1]; } reader.addCompletor(new ArgumentCompletor(completors)); String line; PrintWriter out = new PrintWriter(System.out); while ((line = reader.readLine("prompt> ")) != null) { out.println("======>\"" + line + "\""); out.flush(); // If we input the special word then we will mask // the next line. if ((trigger != null) && (line.compareTo(trigger) == 0)) { line = reader.readLine("password> ", mask); } if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) { break; } } } } jline-1.0.orig/src/src/test/java/jline/TestHistory.java0000644000175000017500000000703211550705746023107 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline; /** * Tests command history. * * @author Marc Prud'hommeaux */ public class TestHistory extends JLineTestCase { public TestHistory(String test) { super(test); } public void testSingleHistory() throws Exception { Buffer b = new Buffer(). append("test line 1").op(ConsoleReader.NEWLINE). append("test line 2").op(ConsoleReader.NEWLINE). append("test line 3").op(ConsoleReader.NEWLINE). append("test line 4").op(ConsoleReader.NEWLINE). append("test line 5").op(ConsoleReader.NEWLINE). append(""); assertBuffer("", b); assertBuffer("test line 5", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 5", b = b.op(ConsoleReader.PREV_CHAR)); assertBuffer("test line 4", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 5", b = b.op(ConsoleReader.NEXT_HISTORY)); assertBuffer("test line 4", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 3", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 2", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 1", b = b.op(ConsoleReader.PREV_HISTORY)); // beginning of history assertBuffer("test line 1", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 1", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 1", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 1", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 2", b = b.op(ConsoleReader.NEXT_HISTORY)); assertBuffer("test line 3", b = b.op(ConsoleReader.NEXT_HISTORY)); assertBuffer("test line 4", b = b.op(ConsoleReader.NEXT_HISTORY)); assertBuffer("test line 5", b = b.op(ConsoleReader.NEXT_HISTORY)); // end of history assertBuffer("", b = b.op(ConsoleReader.NEXT_HISTORY)); assertBuffer("", b = b.op(ConsoleReader.NEXT_HISTORY)); assertBuffer("", b = b.op(ConsoleReader.NEXT_HISTORY)); assertBuffer("test line 5", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 4", b = b.op(ConsoleReader.PREV_HISTORY)); b = b.op(ConsoleReader.MOVE_TO_BEG).append("XXX") .op(ConsoleReader.NEWLINE); assertBuffer("XXXtest line 4", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 5", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 4", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("test line 5", b = b.op(ConsoleReader.NEXT_HISTORY)); assertBuffer("XXXtest line 4", b = b.op(ConsoleReader.NEXT_HISTORY)); assertBuffer("", b = b.op(ConsoleReader.NEXT_HISTORY)); assertBuffer("XXXtest line 4", b = b.op(ConsoleReader.PREV_HISTORY)); assertBuffer("XXXtest line 4", b = b.op(ConsoleReader.NEWLINE). op(ConsoleReader.PREV_HISTORY)); assertBuffer("XXXtest line 4", b = b.op(ConsoleReader.NEWLINE). op(ConsoleReader.PREV_HISTORY)); assertBuffer("XXXtest line 4", b = b.op(ConsoleReader.NEWLINE). op(ConsoleReader.PREV_HISTORY)); assertBuffer("XXXtest line 4", b = b.op(ConsoleReader.NEWLINE). op(ConsoleReader.PREV_HISTORY)); } } jline-1.0.orig/src/src/test/java/jline/ConsoleReaderTest.java0000644000175000017500000001336011550705746024174 0ustar twernertwernerpackage jline; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.io.StringWriter; import java.io.Writer; import junit.framework.TestCase; public class ConsoleReaderTest extends TestCase { public ConsoleReaderTest(String name) { super(name); } protected void setUp() throws Exception { System.setProperty("jline.WindowsTerminal.directConsole", "false"); } public void testDeleteAndBackspaceKeymappings() throws Exception { // test only works on Windows if (!(Terminal.getTerminal() instanceof WindowsTerminal)) return; ConsoleReader consoleReader = new ConsoleReader(); assertNotNull(consoleReader); assertEquals(127, consoleReader .getKeyForAction(ConsoleReader.DELETE_NEXT_CHAR)); assertEquals(8, consoleReader .getKeyForAction(ConsoleReader.DELETE_PREV_CHAR)); } public void testReadline() throws Exception { ConsoleReader consoleReader = createConsole("Sample String\r\n" .getBytes()); assertNotNull(consoleReader); String line = consoleReader.readLine(); assertEquals("Sample String", line); } public void testDeleteOnWindowsTerminal() throws Exception { // test only works on Windows if (!(Terminal.getTerminal() instanceof WindowsTerminal)) return; char[] characters = new char[] { 'S', 's', WindowsTerminal.SPECIAL_KEY_INDICATOR, WindowsTerminal.LEFT_ARROW_KEY, WindowsTerminal.SPECIAL_KEY_INDICATOR, WindowsTerminal.DELETE_KEY, '\r', 'n' }; assertWindowsKeyBehavior("S", characters); } public void testNumpadDeleteOnWindowsTerminal() throws Exception { // test only works on Windows if (!(Terminal.getTerminal() instanceof WindowsTerminal)) return; char[] characters = new char[] { 'S', 's', WindowsTerminal.NUMPAD_KEY_INDICATOR, WindowsTerminal.LEFT_ARROW_KEY, WindowsTerminal.NUMPAD_KEY_INDICATOR, WindowsTerminal.DELETE_KEY, '\r', 'n' }; assertWindowsKeyBehavior("S", characters); } public void testHomeKeyOnWindowsTerminal() throws Exception { // test only works on Windows if (!(Terminal.getTerminal() instanceof WindowsTerminal)) return; char[] characters = new char[] { 'S', 's', WindowsTerminal.SPECIAL_KEY_INDICATOR, WindowsTerminal.HOME_KEY, 'x', '\r', '\n' }; assertWindowsKeyBehavior("xSs", characters); } public void testEndKeyOnWindowsTerminal() throws Exception { // test only works on Windows if (!(Terminal.getTerminal() instanceof WindowsTerminal)) return; char[] characters = new char[] { 'S', 's', WindowsTerminal.SPECIAL_KEY_INDICATOR, WindowsTerminal.HOME_KEY, 'x', WindowsTerminal.SPECIAL_KEY_INDICATOR, WindowsTerminal.END_KEY, 'j', '\r', '\n' }; assertWindowsKeyBehavior("xSsj", characters); } public void testPageUpOnWindowsTerminal() throws Exception { // test only works on Windows if (!(Terminal.getTerminal() instanceof WindowsTerminal)) return; char[] characters = new char[] { WindowsTerminal.SPECIAL_KEY_INDICATOR, WindowsTerminal.PAGE_UP_KEY, '\r', '\n' }; assertWindowsKeyBehavior("dir", characters); } public void testPageDownOnWindowsTerminal() throws Exception { // test only works on Windows if (!(Terminal.getTerminal() instanceof WindowsTerminal)) return; char[] characters = new char[] { WindowsTerminal.SPECIAL_KEY_INDICATOR, WindowsTerminal.PAGE_DOWN_KEY, '\r', '\n' }; assertWindowsKeyBehavior("mkdir monkey", characters); } public void testEscapeOnWindowsTerminal() throws Exception { // test only works on Windows if (!(Terminal.getTerminal() instanceof WindowsTerminal)) return; char[] characters = new char[] { 's', 's', 's', WindowsTerminal.SPECIAL_KEY_INDICATOR, WindowsTerminal.ESCAPE_KEY, '\r', '\n' }; assertWindowsKeyBehavior("", characters); } public void testInsertOnWindowsTerminal() throws Exception { // test only works on Windows if (!(Terminal.getTerminal() instanceof WindowsTerminal)) return; char[] characters = new char[] { 'o', 'p', 's', WindowsTerminal.SPECIAL_KEY_INDICATOR, WindowsTerminal.HOME_KEY, WindowsTerminal.SPECIAL_KEY_INDICATOR, WindowsTerminal.INSERT_KEY, 'o', 'o', 'p', 's', '\r', '\n' }; assertWindowsKeyBehavior("oops", characters); } private void assertWindowsKeyBehavior(String expected, char[] input) throws Exception { StringBuffer buffer = new StringBuffer(); buffer.append(input); ConsoleReader reader = createConsole(buffer.toString().getBytes()); assertNotNull(reader); String line = reader.readLine(); assertEquals(expected, line); } private ConsoleReader createConsole(byte[] bytes) throws Exception { InputStream in = new ByteArrayInputStream(bytes); Writer writer = new StringWriter(); ConsoleReader reader = new ConsoleReader(in, writer); reader.setHistory(createSeededHistory()); return reader; } private History createSeededHistory() { History history = new History(); history.addToHistory("dir"); history.addToHistory("cd c:\\"); history.addToHistory("mkdir monkey"); return history; } } jline-1.0.orig/src/pom.xml0000644000175000017500000001546411550705746015500 0ustar twernertwerner 4.0.0 jline jline jar JLine 1.0 JLine is a java library for reading and editing user input in console applications. It features tab-completion, command history, password masking, customizable keybindings, and pass-through handlers to use to chain to other console applications. http://jline.sourceforge.net sourceforge http://sourceforge.net/tracker/?group_id=64033&atid=506056 2002 JLine users https://lists.sourceforge.net/lists/listinfo/jline-users jline-users@lists.sourceforge.net http://sourceforge.net/mailarchive/forum.php?forum=jline-users mprudhom Marc Prud'hommeaux mwp1@cornell.edu headius Charles Oliver Nutter headius@headius.com BSD LICENSE.txt scm:git://github.com/jline/jline.git scm:git://github.com/jline/jline.git https://github.com/jline/jline junit junit 3.8.1 test org.apache.maven.plugins maven-surefire-plugin false false org.apache.maven.plugins maven-compiler-plugin 1.3 1.3 org.apache.maven.plugins maven-site-plugin ../site-staging org.apache.maven.plugins maven-assembly-plugin src/assembly/assembly.xml org.apache.felix maven-bundle-plugin 2.0.0 bundle-manifest process-classes manifest !jline*,javax.swing;resolution:=optional,* * maven-jar-plugin ${project.build.outputDirectory}/META-INF/MANIFEST.MF org.codehaus.mojo jxr-maven-plugin true org.apache.maven.plugins maven-javadoc-plugin true true http://java.sun.com/j2se/1.5.0/docs/api org.apache.maven.plugins maven-pmd-plugin org.apache.maven.plugins maven-project-info-reports-plugin project-team mailing-list issue-tracking license scm org.codehaus.mojo surefire-report-maven-plugin jline scp://shell.sourceforge.net/home/groups/j/jl/jline/htdocs/m2repo jline scp://shell.sourceforge.net/home/groups/j/jl/jline/htdocs/m2snapshot jline jline scpexe://shell.sourceforge.net/home/groups/j/jl/jline/htdocs/ jline-1.0.orig/examples/0000777000175000017500000000000011550707350015175 5ustar twernertwernerjline-1.0.orig/examples/jline/0000777000175000017500000000000011550707350016276 5ustar twernertwernerjline-1.0.orig/examples/jline/example/0000755000175000017500000000000011550705746017734 5ustar twernertwernerjline-1.0.orig/examples/jline/example/english.gz0000644000175000017500000037763711550705746021756 0ustar twernertwernerE=englishdۖ(yNc]cW]l2d #O V0Y#@~ ~ y]q._m2Ar |y,d.L#/[9JD|[oKYBR.!ΗuYgݨNxYY %ƈƵf-dL0f4TknVy+4a,)) a#/)pR8m*OYRכa";sULFN 7+Әd-ƿ6LiN }6g%\߉K0Thd1ZZugwy;"yV|tvark-DERU0AiX06B'(&1Yyo)P ,oV^zZo*uA*A?7 #U\O1d724պ!S#%CR<iPܕw@mce3u޷ AHw+ ba/p ʆN1gKNح6LKHAAȠj e]ø<%8N`D[llQT|nmKjv,! &{Uo֏րyQԻj*[ga3ڙ2J;(QPS29?CYi9axڜ<:\(R+%(˯_>_zMh(FBY6l'>y5Uजvvn:krDR8%*49)gY9ul7 >Z2-gWRB85)h:RJi_j0ΝvTqN0=B* h_V-KÈ=0<v}<ѱgifa"ɱlgG<] Kct|D줜| N$:gTyΣET) |G$ K^%]%Hi7 Jgw֪<= [NmokFy=ikAJSUNOwߓhik'hxVIƉ}K-82+MmPsx*`v=ڋ*[jXUv7v{c'Y myЈѤMOۺHއ$wկK^s&G ^Y_imŜO# >诐YBb0>crsb/Y|"S9]Dh5"}  |lMi͋L*. N,)#?{n ܀uaq<Ԓw@q9;%rMlr pܼ;ҙs&ERzsS7Iͬ|yz^9*%˰=1@roGvCKC4i>L)6`mYL4vBZj>ɺdݚN]1*smg 9b?윭SPg9d `U%`lTK7L l u#3Qk_R.HPP]ی!畍=)Iyex,e7 )rJv{bFGm~..e'ElR.my}{rp{z FpGXlAHEBaoW6$u&7'5mV].;vwgQ⟡â1(st6#RiOior(yjLiH3CZixll7T2 ""MI&lj =fwUaY)'k32H0Dcбt dΓ~Pwm\r|T7>nyW5`tu`=B2X$I#ybkW|Ucd^|QU?߮u!gt0 ILHV~"{|GwdP~$sJo\ b<.$*Fs_~tP;*xýv\2@k8vV 5:j,b}_ME(Ŝ4i_`6p Ҡ[5z9Y3o7o]iĜVRlX \ pi>Ȫ&fh>aګ6.4yJc᭢*={ԟ #XT} hd4wCx";xP{#CqVB7dy}:kϰ3'alTؓAչkAxQ5ҢzHOw[B2puZ-iC133Sz3>>) [I/T;AGH]}E=؂䏾]AzW06jPo5-`r{!laUBE?CZkEx 9pg׹t6+hFr\w f!&ZPfg u )X%|e|ag9--6Qq34|!69%(7f7ʆ(C?V=_CPVIS9PuR&(Vx좨?$ 2`rÌkeƨWu͛@T,T F*A_^ ɹ \桎Z0 /մvꈅPŰ V/׊F~h: 1I|X0Ƽ>ˈ3QjPHC_.VXk߰4Ew 5iCW:xVξtiac Dq4("xK4HU> d6n9-7*ʤ͸Ygy`] Jg.MafՃۼʬ3PSْ?^TISvg7FRRs#FruOzH,cT"O\&~LQ$rl =Ex,>q0D/'jEZ"dNPZ03&sX;on0n*FCX',( 軗 ނ=L ̸Ċ;dT%XXVixYeN⚆Y͑[Dnẵ֭Eƕwd c#u5NJ;uF2]p::"K+ U L%.g$8} vU"s լ5'.#f*k>3|qETvr ?sC|FC6LU0PAT UV,%ڀխ|vAdf A1) ׵ ]cZ=u(?[qa OF㡅A5(P$Bm;M e KXQݲ(][WKK^%z7yMo6*ԓZzA G| ל(hM"u;5ThNOq4\\= {> ]|Cz).r<ЏX) {%0FvP̷sZ:wu#!;e[ijȜV:!sA޳*l^XgR*\AF3;q,טrYUYǦS*LZanʋA k=sz8` \=Qkhm{k דߎU z5D;f5 Lx@Qg I#F?t+ .1Kkx<у4aP9|gV̤@+X<%^-(f`C T&w`[|j_رlן:"PmPU= %0tuNޟX7 |U$u`+aeұh1YMPCNg ‹$R|IH{jkě#-ް))9|E8:-55s'*Τ,D5uJ3QA*X,՗SYSUGncYJ3Q0/(aS ł^ckmN*oQ|rx3-J>:lJ9d8X|:ׯ Na,O8x;$]9 䈚Ji⺑)*Ur`Tt⮚N8tHrJߔH(uMJߔS}M,ЍM'O|URn܊:wi8\VoOX:wl_6pdz"JYiH+fk r Wghh]g@;kZ&5NX%;c:L26WG9}:C5Sgx 46X)9T7aHC7dA sX։Hy=j¥XBra 6\-P<0w)5BuӃqk>!˦Pk⏋(FK\\˽םJ*ŀ'|%'ۥvAűYSIg'[F5HMv[CV㩴Vƫ0$ΗMdXcfAvPΚKz8+¼R1 7-T+Giٞׯ0eҝph'#3x;0kj+.yU7N bö0A&bMDcq_ϡ~7\|(J~+u~ZОI XE(*ۮ!~kM{1}4̅ [$C{6 sG,:w Yj͛KaQa{rp#`W+y<+Lk^[_K+Og͇{ng!F+߂ niY'*rk8mRn@+c `Gy V~A~Wv3`ݭvd]ޡiJԞf(/5|.+>‹_EBiex[eoHr_J3ݸ}2$Rӷ&3I@t7. D%ǀdi{J U@萇LyЗU sҗSE '{6yM4-hikm 7_m6_}un `_ljhKI[BaMV4>ˀǘ'Zc@׻W1vϚwz0v-ԟ}}OpN!m`'VV"y'Vчiߚ?mR>޸AԈrR7z'm>+by*RC -J%o#m3/7?(b mkL)\SwM57xHX:ȖTA+s"?ErdWX 2\bc@18``moSxSFǫRٷD0µ ԳPLh2 c=h 4At_6-!op?jPMƨJ|UN(x#6 gں|׺W7Ӓt"yUi2s~a n >k4GτB~]2^sxW|Rne|L&$mp'HG\0&Hsn}U3εmq5`4+D@V4mȫV1)O(epL.*T;";67 4(m~uWw"X#U;h@_:mkm췭ְq~BS⤷f).ՖʉƎsd\O^v)e+e_KʵUeFQlcs>fάaMiTA` Fk#ϙ ^.NZ({/5, oE{ɻU${;VܜJ}#ʺڞ][Z5w[#韤fő6m2=r1I]Ceڊ+]0^vgN:W+bׯ[1>cھE&wl'.uqBONJf s˭C6baPR=Vj-9T{Z gh,ߴrT8]eoYMOQn/z1D$𵢗d5vBYO{bwu֚iOx۱g947=(UolUVh:bbU#J.æ"n4{=ޒ GAcƶzM[6ttkTuzRgMHG3Qd͝Y&_ ( ?w 0 XVjc|{? o1\C8 tJxWPPB&!ה9C_ڲ!% Ac %/o,7d҉/])FlY$ٗ6x/X' d0}-9cl/ai͊74k{__1죚x֪p/ϟb셙{lz.;HiVnHhx7X;&#UabJҡ,]/jLeǀ򅷽@=}ow?`Qw0 `oQue9d4ғLuL?|bo~?mxwڔB'ů_,惯?Pjl|b'ykdY!iШx_>=9:j:YO:|;_رѹ$xˏ ;¤/./U!F"WWl[-4M\z˜~}}%hYK-a92`dG?M1^DȟUY:?1LX!͵@ biN;ך Srע%5#dU-dVsaȾu`7WIXo!oNB_3I$Qn,7YJ/ׁ-؉XXu(L`Z6IND07;vJL"mڮFRΞz<)[ 98t%""iբrEa~ 0 :"! :zƎ,ɍ"+x/pŝ*c69U}{c1ZE8o,I妻*{SvonG>֋sz    3wl-x5ڸ IMoo!mqʣ̉7;:=ƒ7{ R2' O N }"芾_*s7 6׬` Ak!#<*Yd1,P9W՘yGĖ?!qwhl!)M+MU2,K`*tn~+`Fgz PZ ~hpƇ@׀0}j&?.Laѓ|aD,tDT5c;ۋZҲY  &!BϡlnI\cȖӸ;鴘WdlTیc,7ܴy\A'w2ɧ^c)+k8߫L*4Zſ=ϭ%)h(p9+j/k_Ɋ3A=naZ/F_V֬lLzr̒W2eSMt+j˟R1 \2_jhjnQ 0ϤMu/f٦1,pR^a6Y]9ve a=ju3+a vxr;e8oM~yv"rd5?|gU:zTn֏%ǒc=Ì.c"(/*=연drS:ytJcg',EQ*qD3}Pf-Q͆d  #SRgׂ̮#,b@aj dIW'__W Xd 231&\˘_`7*B[ .sq]mw 䩰 VĂeSvJr'GPL|`U$WTf-ڂ/VŃ w9%Bg; ^EeVf5Hpd&F_uQ!%M,p,|QU|CFo,:ݢXXeS4~vvz-ȱmU4I#)N/6bl*e/%!kՒq`q@X d%s/!Sylo얰T6$7,ue1Vz ;g ]>31)e PxHát%\: &B]sgv>++1N>'NwQ% ʏ`BEvc uX͞a-$+MX2i#ig]k`/5Pb>idOlɼ'MPОFE08' yyfw s0惆<~+7Z_dK;S0qB^5(O0N j'U!ٻ'H>(/JZ}8iX J8.#Lg|RA'G~CEY<ػ*$e0:sF{VK dpFgVa*FgJ$-`z4I=;X}Ҡθ  }'|UC+t(-H 02{_mz6Lb Hű+Wkrm%>l^0>?w? Jsf pdLGS j+IGuV"u$ڟ6qh~N< /.WomJ&q}љ}.lE,X~u4WZzoZx'p Ce 40音3@d;\-ޑ_p\:zSOL<%S.XS3?' ,QTSw,ZU3:)۪DRo{Đl<'.58& 8bɒH8ޱ[wr/MX5 ),` Щ˰RMNtTi i2$0:f\]wmD9>-1ֈk1(I`x="Pڂ8-1c# #gcAuyFW h`g]B.wӷtNL1L1LM1 䰨"(s/#L^|FEjCfz}Kic73v`rnS]a۬`fyc"G?;X|sVp2}@/Ơ O:=2=c2#['דs'O:yz=(e_ȣ^dh)Y ~}3v#54V6Q\p]Y VMRfIRk/aJxK ր;htI& wv=VVj&"I2%ܵbO>5ګ/(vp͇i2gXROW93b**Rb 3[ lq]Q4oǛ~~6jaˑe5yݼ_|ƋqR4BVćH=#1 P΢+.d$Kɔ͢Ul*}Zwx/`;Q^v%xNAɴqmݲE`% %t9Rt1*ɴ8+}'jo-[=Z]_R6U:mţH=V}nY6WYT|V~V~V5x~썂q9akz" ȉ!lKXf6"H5hW5~Va0bq,tŬ8tTzWlǝ7M~PRC C>?W.bݰDVrd K( tlgբ+(qZ_\.&S\pVl0Y5vY5l7ثG/.+,$^NȺfh XS >\zc_&%-JC^q;!>N̿9~"]?9ԯV[Xn_C\hSFw"([HeаpxfB#.g^7eXsT [` ?E\\įnWչ8paPT@c5\&%ėepz>}) P< EUݐ^ {෹pSh/|ۃ4W-k0mi\92\q,8(m6z}O8p\R 5^S6u5z9#V*u?ZOI+{#H$c_MʾZL&SqGc9U M +7̅v)EG](n! Kc' -NOG$%P mWXʣϚYd &oThج9F3s w_ds2Yk:=z5^zhe2c{0LhǠϛ "4 a4+-G lIԶ:#1de wT=kp2|+L:}zPaKg?ƕb?\&Hr2eT zc<dm h?@Њ|2d+SO]o(GRW<VSFIFJBTXhzY1= 2!YrC9m(" fl!&fͮ</UA8PR7{&c{}tmO02CrE\(1DUv" 8%X>%{" mE6RyO2G]XC3xsAnoX,_Q4RN0[b[AWIpB`U&˖rF]WU;Ku[I|V)°Luc/>dJ;hl[˅RT+TH70,c9!=dO"s?___Chv"ۉNx; }> Kgbe.S] ;qG`qVuMx[#Y3Gؾv't&X!#YC9;-Ñ#:%[q.oAnR@\V~r[/PJ&TR'ێCT5?IQ/,FKYUu֨1(SW3?ahdAC>">p^a+~uɠ! ^ `iik)n#V_5Amaf0>~誫-": tDvDvՇ<L,jhv|Uwn\PetZPv  ?~E+͢o2egI~&R=lkFlv|-@ܶ䙏 V_رr_ggDS>(č:Xj^vѽ{{tޣP3]RO JuH_pQ{[E$t2wϤ^㌒h- c upO&׮5 3cheDT|$8*-۽YwU ;;s%>x j؎aGgq?҄2`a01, L d5S`JM@nck>$J&) }î5?7l=q`׌׮ oxTyzkdo,A&̊}{moƢdK?.8Lϗ!oʀ"80G %pv}SBkeeq,`l5oNr/F}Ӡ$߲drdWC-Kv)Y(A?=쮉; ]ӨG2,Unԃ݁ޱ{*cxi5i<㡱{&'d`WxXsQZ$5Ыj꽸~S.gXŎ1VoR(wAq>D _Jbb ŭjq[%]\U`jhD(& *;?J~rI%$7Y EԵvB6JTm]J^,MB5p$}H!F=)ﶹ9nZ ls`?ut:X2+ԟ[~*G~Uɐp_W]5{wu`Pb̖EqP.G~@k9DikRq <>M_B%BsUAݘhpaz0I@y+-"{_d=iBw)zhF q5kf^|΢V_kkΕƎny]|Ѭe 3P0!K/܀Ql@ 1p%"ȾBر rfyHdz[kd8rf^t0ϻkbu /HW ѺҫӤ\qu2c|}607e+vT,AK%SpЮO\j n畟BCMW} U5q+ubdz@jDZ/#o6Wy0@^0Pf~T,ݖE,m?8Y2]lU۬&p/y Pƒr4D޸QG6؋ _qBL";0z>a)Xx(.rpS+PZkB?1y T;F-uo`d5/t\AB_exѻ+9} L1&<L؈NjKk .MU1Kd ;ǻ,z gjX&t*T]X^ &,ʠY*'Mi9Ru\R%=њ-ۀ[F{MQc84'>-/ eVRuUe_CHMISwn8TD#7?,,nt6Wظ9L'|5/dSsgrdyM&^UK4lgؔg`cdsH n',[M;'tg' zPLXg묎+qy,'HƭIw7U|pU-ӕgqZ'uRo^jdQdUck;v"TZU_^YAR{!yו|0(們 7{7[rJC=\3?c#/&ꢴiOX:wT1m.v|UB'?Ay ؼ]*ޤg & ܱ(hcھyZ*HoR8<탉렪R]O\WE%%4Q1j2٢"\ANy\]Lc/ d)t1r9A9PGR*>cBulKMrI im^F74(A)ǢH`aDXs:tgZw15K>Sl|?f0ܒ h:: ,UzyU-A(] K<38I0EulwM* sT7yD]W4liUIBcFqOeΡc'C~b|zJ䗳{_C]JT:1+,ǀbPϮ^E Bk" Z4FR|&ڪ:?n6 %`eʧ\;-䖩1phY<wTsG?zEO:a_RY4zF5{^-Sl/ (CA7d;%񆳎%'N~ rL, TVGƺծ,k3}\9XکW$`uXJYT V 3:%(;zꌟYIq܉Eί?߮iS L PN}}* |ؾn})69 5Dft8Q1_5kce޴ I]#`I]=OT@V[{Qet<ӯb%N͛#36뀽N9P(aquг-y%}7X( I)N5HP󊞪h?;fvSF#5ႂ"DÜ@8ŞPWf,iѰej&@0*5T ;vwb\` iF3]y=32$7 :qI撓cS!ye g@3@9 ct~'ΈO!2_+ z)wR08@A%$Ur|!o4 WwV8lbq ÉI =>)X}?i![??aYIw%6C ܸy>h}aIjY SME*%4Ќ;f \CV{tj&e3$oxaf7$SYK*X2 >˼d]SQwlJӮ9\y颍L>oCOE@b[&2,d;;;|"`((6G,}gøu@2En^%oSd֍&NL*/h櫤QQ:v ɪkM\3Y| Ϳ.i=7)U.u8bUܫW5,#iBۮ7PS :pS2'1+Mr0"?Ijz%ʏXTrUjr]QUhrtr"4uzA٥P;gt\Ɖn.(8\2eY~K@PcߦH`"mjlSM- k†֖ w~A-+_yeLxmQlX SD lF$oώۓjQHtIX 6˱J#Gu0ί?#PgF >ItK8)t0٨ >EmAB+ixD:Tb;3˼5T$X\ [%jama;씇SH1t -Vub(Q. T~__sIJ:^%@>~8uE-_bb Vפ+F{*& -J-a`827ơ0X ]J-)s Fp@&”.x1#4tUC x$v a€֐ *Bt% \S"5e*:)`/mlL:i@1&tkvC,Xňh"%R%ռ*'eV*Es&Y2~>d%^9Ddb^n%!e/5[pI WL8Ytw.wECELZ]}A8䞏2LCS2u`ٱzlPy_nVݦBVQUWXA|wOehJW27C@,GZ !s7'z}ӕ'ѵкgŴLnT|_2aOE>V,*It&jtl>:_2!FbI*7K>Iɍ>sNHphnرŴjv`Ǧ5f‡t€/=?qrS2vTL3)JQ4ߴr."z3DD"}˦9L%$,bZ—ŔOJIũ m6x, ?Uk*G>UUhmŧ 2B1dcLI ?_ب9*/ua<`SMM0Q%[5/}&bĨ5>yucy5[ڼx}I)>)W 1q T =_`K L੉z a=Y4`T|ztJV$If} ѿTZ^5 gcaYig7v-\P]% m.oj O> "DžA4OnLȖ m>奘˕`JZSs1z{ݳR?cupCae1PLbL>$Mr 7xMAav|92#mGrr6/-sbt:oL~?@Xl1)_aҖ) n (3H]wg{)Pa9͉LmBLҳNBoYYvPuQWYw!$ef!Aϟ}EަGXu93Ҕ89iVev'&̾ dr]i0o$_ZP@E!rŇiE^(c:$V<3cs>)ŚRp bZ G^WFF}1ZaoI:A5etAL85}rYRI˵:Vo~dDO4"ihV[B#.?fRQ Rnm])f/r3uBhådζB6|TDӹs$Z[:G]7Pw +k$YzW몟 rgk+& c#eqvBV')͇ZoW&|=W8zWv:c8^u8^uz5No__Ev;Rn@yj0>Y)'EoIu5+ȏIϒJȂc'׷q `OI8g(0sqL(6l㺅gVYn)dXp8`uRYXyԝUr vLuKך⹡LGg Nň'լW.,V5G.n^RRQ\r. نϲVQv%㙀U7F[C~"wXF{J{2X,|ci|TFT-0!pS12F"!I2MИwiۚO8|Qor#82,J:pO\zo'qI{Q?FA1]--[@dْNL~7=(O[r-*&sWr ؃уMk[b?O% /`.cH2c NCRz6j>Qـy:km$#wdzrIZS8EZB)MkԢ_"xJJ[)\_TKxK n~Z[s\g:}+D*J:+rf͢]0\CŀR'uCI'L~ ~RSď|%΋0ndB/Us9|]pƁ*pPgM)E/E_PsbР!s<2QP]JS"SQ(h吧'׃66=7lwi&ѕkqa}z7Fa'g_bvvӟͣ¢gX"[ĥso)w֔5;747[Gݦtb" `L)Kybf&Oґ"gh#r! KŴtۭ-SGHGJ#h~Ceߧ9xZ6dnweNZY g{uJNC&q=L-^ӷҟΥ?KVӷҟNpg'ErBQ猪u96pz}d(A-AԜ[<-9zڗARݳ|twԘJv Q cgkJߵ9Ҡ%]|VrJ/)SyjO=|3roU۰œ#2+>Kvk_MhWlyHmn]u6g݉o=%B#&u+ʼi[d%TƖ’Bv%KlQabt7)WVJ܄C3^5*p[Q`J9)o1DjQ96u5ؗ }˘[ߐQm˓#x)r (6">9l'T RVi}EtHi2P051(cUSysk7W X4SI=c4v, O4>yz3+/uok>aXKنʑq<ɋ3eEjɟ ƭT( lUMnX !'s%{dGf[ITن,ӄd/7rS_>|OC g^Uyd5_@ Xb7[(E;)uxlg;(&$UҚ'Xq`$x|5]}$pE_!'Dr )ϻv SHٿ&j,6}ֳ>?w[ākvYJW|nHnwJ9:W:rr [yo;v6o|Y*uO)zM߾kgǖ 4v(}Ux<+D&W'Wk4%-eҩ:C2 vgZMa//j`3%HQʮ喹a :@R呸AVNgj(;b.j&֢-D8SRul ʦYD1 D86aQ2m9@.Uţ#ws8ԁ<WŬ6w;j'JE]ܽGafUe׭밝 ϴkzveE[{Pk>a +zaj؜~(ͻ%s<~v%۞,L7C$W-ɾecvO4{*Oz嬊.8'tJ=SҿV 7v+Ε >Y׾>"n0 xଖ7O0ܹ'v^_6ϕ_J4=ۥtK|nn9#d+|GR9GcvtU~jCY U>jH(TUiҒrUz{[c=Fnv*耢ѩYڻ7jh2\pIH<=>ͩ\*&X^CwJ\7VHh^ƃn+~D Ľ 8Zys[Dm qGCWH㲆`FSA`,O=)%˱~L=Bڒ!bApBIXZsx]ܫ _5i O*H&23P(o.L 2:oLپmJmsn7u-kgZ})Tt ^-#ĵVaP>4(sC3KPc>gm̴J2-6+`>:  ]>)à<-**.2^_Ţرcoi9K7yP!oIf%k,&"!'5%1L>rp e$s+J˅̗eUOf&cRmBC=NP;ȚGg?}1`Kܷg!^|4U=p!ޅVb&)6М#Z).›IroԾ^:i$H.SSKzNO9$J<.G# JыKkd,'x2' Ư? U;tQ1/l)}j݂!e`BI3l8T .7:*<󨰕? bmipۆx,Ym +2˓vRT&J1ZI)D95*aY:Niwʵ1 J "ر;ZCr_C _jk0LFFĝel9DqBe0&r^G~_>;cTVEv?1[{.|Ltr;*RR`ѫ'dGsA214wHl41?cWQf %Ïb"ӮKZ%ypF"HW{CM65SvTZ;#$sѮڵeb,S<^piQyfwuxvC)rbtvL]P ͧ~cU<=!2ۋSȋw'=鲖 QT\0PU?ݽݽ=ze{e{|eUMf}Rpl ]r]J^U`kSejS~ymi !}U4f <l,xVIeB_eCs~1Ҥgw˥k> 0(y@ '3;6ׁ|Ovbecׄޮ"vsP;vw 9dd8j[|6/N4v, XwOk>e|1c`YJ>!{cC iŀ=^4oq_81/ u98LV>=d\mb>_w?Mwg+BC>2"#ϪmYmX =E 8q|^B6* 3 %Z5rRήy5 //y|l޿4$L~og@}(9RPdGd )&G_RRgv%dsZ1m'U ݊:4bQ$=]8i@,E\ۨ)EP2+&:",-T$^:-.$*e(!yG`w?_d?v7]gIi5!׀Dc) f:'.%Pxo_P_$ dTX\-fǩW j*pL7J;APVexiȑKUj9j{,go+k4]ӪVӨ1l/ʵv"#@Cه 锦ѮLg8 F(?*OW?vS;*4" h͛ZT۲|rP2suoI˜ݺ "hÙs1wb%r'?Zo=O<,Kgɧj'+;kiZN5Dc0[~c}>m| -~k_ozk+>ZQ us4nn5ooFU*_p|E[{k7n^q;o ,x6GkSգx[`hY#{QSFmmRQb̖ErR)0 [uO-qt7h`XP Po7-Uv))M; \}޼6HY޼q!I!s"dV6eْl!yuVfjRpQ~&78o b̖ Ӗ8[@?3`|(g߾}+~WIսyAupQlbo(Л`f<()uU.mnUW%w?o:P s8t>u6Ca!Ax'X J' p jonc *[VdTޮ2AHC"(A8~B+,rPffß9ěr<{KŠhﱙbGpE9/(#O01)RKĬ:7ꉝ%ڔ)!up{@< ޵gْ5J`%M>.#(y1m!U>1J`PƷ[n`ɾ%_R+%]ROvgwsiVt2LTybmҿƥ)jcS:Pə'3,Ι3C~ #^X%xmL*;ms.ikgc%RǮO|٤ǿ6$l_*8%ǽO3dCŅ2cu"+~>)R18{&Xi\s2G]Rlt2*m xyr',F׿Gp5X-*gUiLh߼w,jO^88LcͷApñz%19>y|ΉmwU_/v"f /zQ<<=Q!ebҋ2|Lc`8o+~cPs6utbmQjir}aj06*AG?-%uܒ_ogXz lv{]Îh /tͮRۂM]Pltw8pޠ瑧˺9ɏ$çLꧧbhqD+0m sn­| C1ӽgtwzӳAY51 5;_H XwpH!ǀpq|{G bor (E-%]7_ũfOK4@tr$nTuI5[_鄶حsX.vLAuHZ朚=351"훯al o}ҕW:3uok>[kbK}0%.*#{)%Jr +fzЖCGάhX:񺜹{Rúŗrp&g )IR)Sv9V'0T6D}mEQwd'T 'iTPdR%&oR>.>NqO (ǀbLLne#?!`P&Fuմ/q5.Vƒ2XA'~AK^ ʝJh;MO}7} ׶Fbue$% Hc󺨄WCŠhA~=D6?D@W"|,| [5< &6M|od%ˈL>cᨉ+WY)'%f-b|_+ףs$#.]ҙS1O4v'!Sv-꬟I`bvB\SfʡW*k;@O4`ڦؑ[+6<K*VP4v, ]3˸gH"N%СfcRBƁht<_84,25["zG,KM- +ib+GwՌKݗGJqհ,Qxi[bCfT{Gg? >i|G{}x5NE-*}uƇGF%olNψ]'ApFrJJ 珘O"}Dn~&`-g5u4XdOEϸ'4Sn_P6L\?mI05-xn>"x9J('Ŵ J/R['%5 ?)EIbD5:RcI$RCeEwY0{/Cp͆y]S稢sc$$=N7H[*޲a>Fj qTw;=Rk= >"q|^[Xe1)R4'~2Ix(A=YT'jT}2K*x,x>:꿻^"XnM [F[q`Ɔ  ޶>qWVw)jԧyL5Sw¬SyED2yGJ D%`k+Rd :.I d4 ;SV_ƛ $mĊXI+),G3oPxJC7hsK2yi8eeMYkFkD`t>/kװhiIK{p#e"CM+2MX㳓R&d#F$`|\ۮԕc];iY;ysr䈞J-ײk`dlL9paz4gbnP˂Qslᵣ|73FЦ|lGO=i^lXeӲG?urRZ㤹^_WW*~_UKZvO*S!A+Fls:x_gjצzk0M Є!G%n0v_syM+g-.+HaR% {i2K#c,H#%s$Tu ǥ>ؾ!;s]|}cihM-c#.H ct+ Jq$ǘ3{aLw1-'t %PnGtˈm݋=wIw)Jtش J9)whJ te 1.ED˓Nz%z$Y 5]3=Ic02FvvVl8tk[T M6vc-eg\S,&KbB'/ Q)Is vέEd.fW`[ȳG&>a T##|~p(A;ƥW/n"AXqvΊ}G(]G5gzn.tu+7Ƭ7DofS_gVm_Y{w#k9(ˁVʯ'^ız$T'!)`Lz"9"ŸɯJ9[O^r>rȰtƒPҫ9w˚k%9TFS{ZyCeͺːcmP ~|rA5JWo쥷 ~Leҗ_oݪ(0uZ=y'OQdT?@INP1-:><5+ԩ]^ѴjY0`-0TFuk3')rhq-D({ܣyrlķ+}/ K@%ޮ~ϿtSBY$PEXwTc0&zUqoQZ'u|a Ɍp|i^&<>YhHX<8{GA5ѨUMוjZ@&P&-y<+袛\9ym5PB?{§o7XjjJ|`++$_<pP:\{G U-g52llY\;#(l3NzDž<+v\!ӕ63O&j*7V+&$Ydn 2VU+Y'Z{}++vʭ"ue42(xmFuz:-pzo|GVl 0=EP"SLesKR UkNt\~Onaǝ3 J">3]o%!dNY!F,A搊A#fCXcpFq[ OmduâxK~hX?CFδUVXt>> )ݨt皡" H[[4d6dO.=ckrձ?!j/ˊ[\Bl>0}a'PA  o"HࣿV-=Ésf-OG67dC#!pc;nl:mQo0n帔b6&.,IDr9-2k`2K:IAc?}*|<x։e;h%U”$)5 6% rN7D(<*Ђ& 7T1u\E=J0u~Dle ,/*祟 6c}8M۽:Go (/ &ΝP:wFX{2,gމ71}x[0Q')Z[7)~~ ʞʞ15Ulat!Ӗ'crwJd.٢HZoaN8=\#Ut0yū3)?O>_1}K:Yc +e]n"uzeH,<ϖ}gK؃DJ[/Qɻj/KbVHPH67~1H5ܢZVJC{p~\?#`bJywwoGQ2!>tGcw\Aj`;> 0{iϐ$;{<+L"Ckh{gqDFnH1O'{[6 0T{hvAA uPows U<@hdZrPWPHOުpt~'IZ?i0?޽SWWwcU\yAiߑj7&j } Fp\%lWcʔX)I{`N0,N4v, uffqSðV_+4Z |Z}b~W5{|?MFUNQ`i{f^½۱dnWv q~ca\Qoh\x4d$F ~)qHgѲ :Hd?~o7Q; $7#WGKW&9,l`yl"M:&=$̜l%QCFܖjv$Aay`r6QN84R}8Se7:v`)p>RR#Ԗf: O~;*`-I]>UH Z6{4τgۻzb% ԉ/_͊13T-t$ՃכLSHAN1 馴gvKkF;O) eK@MqQnMZkvUOYŠ G5b&3{}?R%-D/"Y4uieL+&1h"1~cTV`],,ݭH~|nn%MU1^и_kn+admoTw,ҙCPsojq`eL6$r,>}uԴ35;xPȍr9dOSpE4#?SQ:>ָWLRVkU5;ĺ)5; } {G7xTy-s#ja*ahh02ٹ{Ƭ,h-bRA1Km!SA.lPRzƫ?6ĉO@&e8۝bB{25DS80j|a9v1]c(.iM-L ߑ#3uL3߱me <&sOџ'L0T$(2ͥ!yqڜ<͵1[Ym ׉YċjrOF[&j Zʅs`5G˞vh4v, U ѽ9zέ6>$b GIɂVa 9`$~>3,OU07x8TADALHuy•|WVZARp~5ٻ7PT"g9\ K_" 'Vfh~g9=#J9a)Bi"A(jPS}a!=cl  lRfQ ʙ-;5izra@dp|qPۓaT ޶#%ME-WM12yqɣJ}L ժzveY {}n9@pe~HÃgGKFY|dzrafI#6֫v:ȺmbO PL`W`lDG`9̞%spt,>9xDA|JNEeckN!:81,׼ 1 bDd@~c &5l~gx<\Y4|S9 HNQq|^DZsZjr{(ʀl?K"kDԇQZ,h-#Vm|˱bӞ?u |2j7~P :L|Btd Uҩ>!h6%t/7~`鬾+ vGw~77hns;\nr_IwA8ɍS? @P;8K1n%Go K0p1 3(Zt5^ifQ.%vƚ6{`k PBytaagc9O37hVJ@-H- {-ɉs=zlX| ׾* 1x٧Z+4B! VX%a9;c@/H϶xŃ=PqR yQ: Hr: \g_2X̐9V8QA꬟.J,|u.9rZVM,e9Jt-tUE+g e {͋_mCHt>Zǣ3sBa؎;76G>{ V}gN) 'l.\IR(0W?%!ԒMؓ`e3Ƈww ގ2n';.C'ȠD-ú:`l %}+L^,67f65}] Ċ/> _z_xYc;[V?u\TESfOhxrG5kĀ vBEܟ6ت>iHz95ylu}2&e+N3ᝤ,64uŸ$}o|C#iIE3mw,yHر> 2a̟g˧޵&l2"p#6rҰQ}vrْhi搓AX,'Z{Jy֧%;Y2F*(e|OI~S~ӲC$ƹsv`!Bd-B ;d07tf<D'E*A]_A*` N,f)Moj&o˛bݤuFAlN[yid~FS?gZd,ъIIz#idtc 1J/aF ötq@9׾$Pnփ#s7k7(U*#'?pX5pi.06*A̞qUi O[8g [Rۅ{P Nq |xc}F>=V [R mˊkZ剃@jc$67~yb>ehϩVr (e쉣}@הŔ22#?<Ӛ'[Ő5Q"M41f \:+V5du\E7V4c,l<S_'pQsttDV@Ƈ1CVǚcO 'Z%$䇞*f >Ciս["W [^M*?`a.}=vIS~jK9['_{I<A3^xk@=l0=J G.(j~vt渨-HP";s; CȚ0x>=Pɂ9qrHgJE:xΆgT^5᪾a buz {LBڃer9{.?G7"@T9L ]{hr)*ERAcC'lɂd_|*`TD!nS)#IY[+6|%6y+5'ٴeča~mmlĘ(RkN*pi#?r"Իu& sv8-`L&Lyi)4cF䣏yXzUJ1cۊu0G )XlW$If>||gx} }ה/   rRoZޤ,&H _zChO|(߼lγ##44J 9OI'rvO|h :=alTH؃JIAh"|2g{=jX: NsF"B<7 GlgZ^n3;g8Ȭ2;TB6ABQ rNt琕by^L*fWǤEz0EqNXQqKEs @G 3zݛ"=.[4Dbrn.)y]]-Tҷa~pv!>{ks&"[(UctG=IZ,9Cs$? 3oyj ),܀V9rtZeg.'sp!CD\[wii񧝲lQ5rtyp[v">yZ_wMQIEp8.i/ Qi _7c.RQ[HS̃Iw)n6`|N^%9 P(/|1zz=wnRYgLQ N6貎;EWΉ<=iʜ;|rb¿ŧ;ܠ'Oߡ,)dXL-&7&eJŠ!얺(ebE&4n]f?huvK FE6>82gG}ϤMIqSR -K QK{q$ĥs냝;7E۷^N-5ojyVnb|9\\Sw:Yvz3_)K͘rٔ;Sh۵x'-]1j[$1 \"qC&nYO2j;!jΧmOs\_՚S1 7Vki1o`KLIPkXC+'E?ߴo*'AOO6 r)ޮZDc ,2 ̾#^tj&2uA%zf׾B UmڱGJ'Ȳ;r-55U˯|E# o'_+ԫol=ƛ>ȨH$P2Ǝ!h.f3f@Co%|\i)+[l2myPhڔĥzmNx'P%6Ih,"UfP.0} -Φ̣ ,u>]JxL{,46- [9-Tsri0 T-hs}x[eTK;8V$ TҵWVT|Sš|&?:S {QokJT\^i<@&FƷK4{14i W:s`LcI/o'ێZ(طd~Af~FdrDi}b >cHs .L>o"1f)^ 緼1-;sCw>\a)WK3 bUTbǏtAH3tQ8JwmxԒ z\7[E8F3o7%0t\EiEi tpdrE/vjB1НLv2 7_w7Z\VK:|{E硞?FՄfNk: U؝q1Wp9~\SB'ʢjI餚مճF«FKs*Ϝ2.v4@aɜhӑ'jP(Ql|nYDM5$ѷ!S>a&ȥF)L80Y"R M:.[&1i 2 $'XҮ3'8\6:z3=BTn8'z& 2 :< d $qd_f*H:qf^R7T`ndqGܱ!KV |@{B1T@fi x2ouw =Yl[&ߺ Ԑc 'h/Iܙڝ9$ng EWC?)CGLcD)li9к:CsJ`EV ;[B5P*T(DJVZ`EE5;jT@p'7"!&ӈr<^q˔TFloK` gPnXxO*_P0#q_ojb4ã5:I8FXF.Ceudžt "z<+Ow^X9FۍMJ6 <2V2R][5B\/uuTك.sQisVKKcϾ.H3yyRoT6n|@&s&ꁒ98 I_V;IR'cg5oiacx2$إwE:ЗCċQTTVZ"/``6p4J+"K$Y5]8BGz/jy \ty hĤtR [k2(1u3MbpqZ*8~i~ȋ=L"`=?J[Hv!Jk$&Y5C".10հPw&tPYL&ȀUG&"GhIaI7UQE)I#*][)F7Ƴal\x>IʀFo~IF95jh!UK(QEt[vޮ{^,~@krVČTXt0&8)*뇩n豏7yyRdM2}Cό\?.:*>`N*Gx ޟ~q0P>2Wp_2ɕFDK!%gs/G&>AsUhﰫs=Asb.TMI=ӿ͸spgX3FJoޓQP QC:q_vbBXU0,~tly*wxV1XH;Ғ:>oNM}EXMݦKNQor)=21*#aXv2ʺq:lg22edA C'|Ύ3df\R_T4P6F(f ܆MnC5ar Fش5WJxo a(@p:*7f)9%gtx08G+uഉML~]z&;PIPNIvV2Nm!b'C*T8.'Ne"62Z.@юZO.'e}t铝>9#+12F(5v$ |r|=-b*hUжW<*NPP*dm+ZMYw`?LPˀϺ@;\].hLe-*B7\ime5B5@=>5<k(oe G4|5 UjJ* _Ib)|[ u`3/f* sh}zX[^xV'-Zuy}ߙM+?`Ԝ܂V<89yv1+p^H,2. '@sU$zẦȾW%\Zx9XX@0=MA¬U( &R pP5"ֈN|78< ӧ__3a:5pC0y#B1^YyDF11!J<$Zv~`@*wjmt*mH @ O )*'EofGt$X Rp) }_ؔZ*nfWuA#!-iOsD&5[>鄌tbZkXg%MySVGA1<-hq58E~5pw` _:>Iҗih^bqy|4W*Tw[xqYZe +no VNGb8(ucigN͕ЄI~kAuPٳI+&cg*X(B̝qARKu#.g) ^'.BYBi0=ٿk>ڹkA#yPj53 THYY jAC/ilR#1V [T%0:P>@3R'%. Z^@Ƭ»EhaXdK~ø:&}$<P PL6`eZةT:1}V[#M^.LwS}JL/Ȭ?&MLW,Au 4VR"NRpU hGVw-` +lpZh`pܱ4'Er#C$!k*Rw/ 1Y'6SɸL(W{Uv یZ]P Ȭe@?}5f敦.V[۹l4ӇW5~g>XVn؝;ݟ+r48 !mx%U,40xƝlP'ˤބZumX֔n 7}&|bcLH/澎LTϝHh!ViIfoFeSFQWzإIԍ:HQ8+>pCYH `r($E/(:A紞a3^Us1LRj lw(\@KdpذQWm5`#L% @ܣۦC[k!eF2p%)A/vf wh5SNUBZP<ŮFms;4$O$D =̽lZ=Œͱs8iAEnh?Z211p0E/MP T)Qn-X1+C2Ctk>Iig Cy2_Ru:0Wٺ3(ѱ9s9_hSh  RX_?{cCwkK}J!pď!/EDgrV]c+ԇ:v 73p2-k tFQOG6D |73"m9BZ]ycHI'J˼9ߜoxRĨ / L> G-.`XSY(mp R_}gDV˝+"Ѫ%wEtjA$A+'wH7*~ueHiVf_rbL djLDC1Έ{!b1E^UBLo͇$'h5ZA䶑̭rvaa,pBqc1߯ڊHǚVz:>C yxSe*v+`_pe ǏL jܗڐiv^-[Rk<|M i0a.75?R;0a'y‹Ey%ݚKgH+;jGe`h"esU!tk,&?ҁ^h{O:;wƆi.;s|~.օj'O|zʒ&"wa1Mz/Sal3RT>;\'iu{Zٷyn[My8wp!^*%d+Y* Z9l2yvamYY5[`J` LiRh~ְ*9Kk0ZNW,qs@\7GAW^40"eBKzd!9T %?/:m;{̾rmS7l}XOrwTى2A|CW3.EW/޳K-&@}HFɌ;_nzum[0GRE,Wn}S5CZveA;M _*NZiU#ܿN3k2ՀaFL;>O <˅簒\dVM?b21 2|sp$+B#»">ӡW%1Է  8Mjmo0nD./Z%@l4Kkˌpz5@b?F[q@ڗȝrq_ =kxt6 fW*ШV#ѻ`e~.Z/Z AYaFXAF*Ho@T6lۈ{MۨahBp(ݑ)^Y:mֹxJ̻(,#.&o mB^: 5yI\fJUoaa}NT#K,:mM6q;ev/ON@Պ*xpCRFXx5QY}F13U3En2T6X.NJ?eSdtIsrQȬ{! 'aݽ%;֮a_h<\*bk_8 =0_#I u`I)Q-<LsL+<"T(^J}ʽ$uВz% Ӡw4|V֘^%EYywH$)&h@_4.Nȁw'i.3 ~ SL$"|T=sbL RKɧ|v8A󓚽EX*= _*, Fy5h7~ ^3 V^PK֨V9@q>I&w_0 %Po  y!kHZ;mxXg͎ kmxS}h/Z6KsK;S2ӨZc[LJ'aٔ5zjU X9Td표X}Y)O*zm>gr9wmZ*@iKGQA_uF#NroxI5Qsmenl$nn$n(f p׭d`-nnj4-;c!;E"c8[_UWP.ԝa{)tZ5 vН#_[m ӯf3h9B TtȠв|kDsc-q;rخisFG*: % v{2 NAM&6PllUkI"ta<NFJ J ~Vl3F4BҒ7AdLY?Iw*2kC|S[>/Ҟ ؐĆ<_n^@Ĵ\Ԥ\qnS O%>3eˏ"Sq׭cVa M:Pz"_P_-A_e*﬚A4l|F$SIkX_Z~ o862AUT;M t 2]P~$WG%UGe u. LV5Z{C!88b7OY ؎6fm Ux{Z@3p\ v4Ati0x+/"vYuP(Թ3YLFY5*gUĮDy-ե>tc":߆rYre`Hr_J>Z8el1B@/GyO[HўmAL$C.e8Gh ͲnTi _;M@s^ 4O7ysS9CTo1|W94zvX^Z)H :àN퐄S9xü[Hfҡrnh4G0t]oۈ^;)^ă!Cn >20MVw* S]"O'hOzͅm|HEk81Vpczx=U۹u`斾H돖!MN%i9= LqkHlI%\[N,_-45BA[H5'Sl&"f9ܷM9>n6v4E b O/z'w* ݾi>(r8J3k+wPAQ(7̨do !.kpѨcg^NQlV^5'#J*9 >"l}&+ӭ$u,3qS`Q7H>G~=r[RB^V4HH[ ='Դ9nm֊4)RG5_:b#RLZHJ]BLEVԧqW^wM{[6,l(:Kbs[jQ\F12ʡk|}XIa?$x5CB:c^fL_.oiQ'`F7GHaZšb",=O}7wKF)e >IigN4S66FXʙ*X :TFw*|7]U C"2lvGpy`ڪȃڃ֒5*oSźtpCX|r˥\3z< ީ}5AL cI]0o)ƮxPռw&d[II*DrpNJӽ5|ger_H R9Fo)&Xљ>oi}3>vYq:7-b{{Ɖ'"!JҰE#|Z>_Y(5ΎWl&Ğ^q}nJO}GM,@Ȗ] tOc—V2D,VBg9xޝΎOV:d5g- TyW\YZ R])i35) Ɋ2jK1:" kJ cg5tNڊDJHmeb8Ml|y:~aj[R2=q'(/q,*mW3Q`O~CV$EP_jw_@]>f+6&,Ej=F؊4ǚXaM^JdbLPT{j$"PbJa5PT&l<]+S$j8B!LnPv$?* q%&6 *ҸsHe%da:"'OA UӘ4{-Ug+Ei!pD DBoAΩ(aZKb#֤\mM-#*>[a 5AYLTZ5"8D asr#wU =wnr+E4k:B Y UsKǭ@w8xS +7 X1t4TV9O!mȼf3ayZ}&@ GooؿwU.FBzs}m_RY4IIv s ֳCiOpk 1|ϋYBw$u f 9q~zwcA5Q=;ҰSu@zxG1#CdZ`6?%55tY̷Þqk̵_#6dz ۪;GzZEivô(PʧOo -}&t@&_=ϯƁr6nls)Wv$ܰBWa0ʭ>K6k\Ȟ+J2hm K1)Pvۂ= O}"TpY(Ouj@Q3S7:Y#|$B}LOI9z3;f5ɣY,sMXV}fv57rý)cruP_7x?1rm "U\^fGL1" e.:@l!74u`{ ; P#Ng*` d}(RZ9s#QBPZX#Ekf骩gs j9~*GpL>#.2N v>9ad!׻F|IUQ6@@5ﮰe^3"kF2HM4,oQdJ*JGLIb ~,-T~IyTǣ!dn fxR/@;Ut1KDUp#\(1UUf|+gM;k0V6}(~Wй|ǣP",+@Uc0>;PkL PaZR֕G|cE*5hUqw*Ct 70#W07nli5_"<| 0nLrofP%݀7▒CyaF;o&zN紳szט:%MU<%4a2^wh )MV|K3ړyxuW._%`li޾|4p;K]a+XmÇq`2*x^7tԃ 1!5FD֝w^NEhI igNkaA1CropPHMR [ ~FZnw 暅M_c. >JkxIXǾ,ًڌ@\m^PkEfٖ#TNZRM7U\⛐r՛Bz᷍i_! [G$Bg5ʽ}8/LϔPQۑ'dSv< dDm7t N֞6 \Y;=b;q e]DGh,*TUbxuHA  TO//~K_X=htM;',,h{u2Ye)p Eɦ<@3NHG>rV%TLePfx 1/[ՔR.`BӀ|jmܷo`lK-9& ~1ƛNʽO e2(>4P̴ybz_Z|2KEWUG:;tЖD=Jn}ΞWP]@3Y_p:??9P.BVDˁLt}9˪)>|O@|ܨ2TAPOy33#O\(Og34c/[{±dMy&E81xغ&N!D[B~f1JE Ҍ&.Eat҇ :\〝ܧi ׋aF-,<:PK-ʦl>wt04=2WCyU 蓬~~Q8{O|𦽣vitέ}~>2qwiQ@$n}ZB0}-);HG-.F$\ :3jEaMs1H51Y@߆)-; }#0磡= ,xוb9vU)uJe|HbqtNg5|Ks%[ZtsX Onm)1m \Q՚3E7T3T E1_`k3fÝkA'nMFe&RJʽd5 j;mөIUQSwA44KmM5R+l A'QvuI_(4=&שK,څK GGnSX r)-拻T8e5xAFiκMzybnMu1HĺB<<ˑl{k刍;ݟ'04(yIUC*a$+_6QiWMx` ɶseSd]:G|.h0tnZw6o7$d˻! e4k#ۅG[Ӂ;gfIGNTY.o< x'%*p4ܻvwiZc%e]_ZЅhMcr1=hI:(br#fazS vwTZ-=} '=FVdyړ1x $J9;1Ĝ]/75cjB i>Δ0ৌNS@er-]^ClizS*BXmO:GuG@zޜ"T6B1w17Mm²((/-GXPyO[H bt(V+beGa|Kg~#Y^? o=0B=%Rg f_{\n/ukޘ= HFȉNa* #1eG3f!'ڏn]@j0['U3O!dޭ=d P"6`]{!]pnAtCo¤N!tonpBlsju0V%z=_.Қ>Kv/.@+N%t70yU`l|`+&o'n$T% p0UMd88@#J v~Jew۬(څGpCgl1B 7av.sK4~'1K|t( [0Re(h%'[OR=JF36t<;?(50;&ɒb{+N1>j^dp紊6=_n4S?<͗8vs|qϗShff]Z?KG[}pHt$6N,Ǝx g:u>zb{5eAX\.bzWsoԴnn}B8h^,iEf? ׽&j^0݅]~u`PnRTp=bIW.'*3('%0Jڇ8(T,ݛH z=y+k\n9@f9GrJYyH؞SϮf,IJ֬;>ctD"%y4Pq+Zs8,0oc=P=YV<?%TnyD2{fX X8QV;ڃ{&d#g1P-rظiǝ@@sJ2G0ϝCCuL໋RwG~I5s,2NkȆ^Sˠ:ʏ>[v3`PqӣY'Va4x tف۬Ut1bxj}2Υk ݌fepZ\8 zJtOo6#W4_gj)|3ݙmKɈ~l t@qZ#|_nX^Cb׬Դw7t: RorM= = Hv; Az6)AR.8li¦JZzӜ2ݺ[8i Wc• [hw_˔\?itn}Ca!Qv+.v5\uQ 4䇫!]pѥ߳E7)%/=2k-ٖ]UÍ+|.hI(ٚvv&< \Cp%˚i+7tm? |&a=nRe%q3 yNGl*jѹL8m1$XFKAvصrدާzv;>֨ĻGYa5@ntҪaFE/_I@]y~@Iq4Yx5`۾ B.;gx[ˑѵ12z>rtx(kl&45ٽݵzs3 %Zc`܎ê|Zpp#_:ϲCyw:#O-[vqϻi"l`NNwݹfN{TSvzt&[ꟛ¾AEcFQjsyaH{LCLg%w&1= BZVqo6n3B==L\%y۟OBG EyC;kǣPB^v#KnzonIkz"CFkٸP؁y.wa }T"!v;udk)#>wH_:a(_v_k|͗>-_z[*zJ꣺WF8;2xv; >:xuG|?]cogNC-06κ;ˑ^L88I~1F8椝nSܟǩpC] `;CAe*su:XYo촊]Ӂ;wh,9YmJ {]_q{h#3y&#i㰉㛼,aJ h]3=z=dfՀI3Wӏ>C=Gx%8vp˒ݥOFG'p]z]k&wWvk 埸kVkFoUk&pv3U}6e)ҝOFQ!u3L?\3)`Aaܴ18#1U1(ARRu0O]-M@ )8|MCh딒ZTZx}F$&L $W@,SS]d,t>SsAIft͏VC,4׍BzI= N$M/H^8|^w7%K+ dxkaȅB_JC*o'aN0ccJᖭwS7t'{֪*YqSC/+u䱮Gj-=[COx!<_E9 %4"O_9tRiYXI|oȕi1 ⧮HzrZi13O!$?7|\([A$Q5Wzi28?jdvcJ{ ,H2yPh7ɣMPI R$U*QacU*9 4[]xԽ4?`FڷZ'jJ.hEaG0 K.L*ǒa$6q.ISjʙj`UIWT^7BgXbגWG{F|Z;H:ה) (1W7E b:cI .i)8Jg^c{/Ti+BUn;R΂/.7a %*5\"a:RAADH!8 1Z^p_QP nC*g8HPh|B+3Sm#L K+B &F[큶솷q K@!zNԅ F=~JPT@XM A[zo}%$uKL; ^=*My@_݆V#4-}f`T\ٸ91man8? 5)iUo hA1`#g0Xo{:uއI7[ĭ}:n2i.6N.ﭻ‡0tLzp'6; 1 DM]㦑` n%S7^oR[}4*2I:kB:Q;|4w4$'m^ XlZd -B˦%~kƧw6H(H@xZsHJ? .,#1E*K@AemmZz")]|CM{;ҀA;+0,a)t2)q7^g#p"Ij麵lsQh>2v#i #/YoM%-ٛB_>/y0hMʊvFFV˳kFOǵP#{hZ>SB0uy+Fj$03AwcwiąHB}O Ӆڗ7 6ڧ & y"/D/JL&z- MPN5xe6 oD:p  e<>Mr'v'Ku3gƾO T2CHVraYƹUZF:h2 %^9fȧJrW.xM}CK߾Swc&[dzańTZRXoD>!-WX4O/^!xQ:Tg _QP$,8X*㲰[\-Q-$Y"-$xuq#Vt7hB\utar~k[j"5VMBmAHV>`3bߜ5S,T< "ߞW! Zh<{]k`B +Zw{fs0 d2tckqDhb|e&Ki;&T lZۜm`P"7lEҗ?ʐX5[~QRMaa@s|_ǹfn nCW V8Ӄ:nc{S@ëU&_斠o-3'=E$]uSEC]x%ީh;CZw6ۅLBf FN_@dתSL픮%̔hT3J?1 dyV)̙(cܔ )A$jTr 􌂵)4s8/V!c:p]vT L>ذ8VOz)SP}4dHӕW+ΜaٔjKe|2J"1 Eg5Aeni j`YeyCCX5 4s );RAP@.|3s` P4] "fvV~J2/13$;O ;_RuňfOz22p βBρ+xrN;kW^VCLxTQVP.9.NMҠz" ̞H@ibLj`4jB|L(]zgҤ-20.ޙݖ2wٸK*%+\ce*^/ ń :1TKW9 %tzNۏ{p ˬ64M?׈i r`zk=.3R汌cI D>9&T!O F(SbvK)-{=ڞ +ԉx~^Lc%!h %O$/K+jBdSumC"!@iy)gr\.rϯ_A:'dHU `N?v.v[U\ paNJn^3No|jg;0 NDŽOUQ]anоHx6I췭U{kA\/?f^0Em<,0@B9`#=ޑ_9'ܓzp fMP:-KBMew>YhhUhi6   %IhX m<Fٌe)jN#lVL75lU&@nSDi ftU?1I 9jzCgQvRϭCcHȄL!c޸%?1CYASGFG9w%~|t~DjYn턛&yx"6~ww;jQ&8Rr(Hka^\yە/a2% dvQꋿ}p`N5\E"Aꆔ^Y rb{Lu섘*UHs2;olyŠ^(]]{w\b8 :x^rk0ӝdU\_Mya噝rlpiCtO᮵Mge'G 6Ŧjz`ao1 V+V ?UahTfvmU6@MVa8K"( z1 {Fd~k4@~ I Wzzag(~&zgw1i{zZ#,+?c@Dkm]yUp@{H~hwdğ ̪3l 4:34;/d֋ Ml`џs~G8J2C%2r𦞩Y6*ZlkatN3Gfrozc]~{cK(%U0ƞD],!4زϧe#&R'cgaE%uv ԓ5FxweG}A#F/\x'y^VgX (B9MtNҰzJs&Iݦo9B8ұjȁ5"#r0ҟyZD:9r&e|a$/v"۹_eXְ`\d]]A4 hRҶjRjae 4g2Khʻ %Q(UR[:c UDʸ0rw8>/vj:P,W&r-3}*= wKM6D3V,?yz^|F)ނII?)z2h$g}PYOQגߥ/"hx"7yP-gZԝK>ɚMe!L8sAY,1}!UY-/u-Pj"aqD\쟀~y=K،ʌpQW5I;Čfވ6_=()ƈfvB(A[=o#rvS7/Fh5܆w1AEy[. EKf+ sl<~nld762 Gºf2[zKR;YF3fu*DVq<7D+[**)7`=D)Q g br u;bѸ<3d 3iP1DSsS`h.@[5Dͷp.A1": VMʴTjtl Lө%l>*Z;43sjj;c&r3?70J+6ԌwDSM#nTD-ܩѲhF0%Z9<1M_ 6BQo>?}jb6o{PZvO4g 7ڊްvjnv LQ}WV@Nm&vk̳hcq&V2Ƅ'% ~[ޘp`kQv1tOD3>5#?)7_\/?uC'Ty{yK/`k&V95e兗{nu{+b'qHc^ZwPog?.a)E蠘: 'N3olfY׵~@PlKf.4pe+1GK4&x`H˚+n5?ZX'Kv+Jy,Υz OU‹֙=`LRqHXkx[kZ+ fnl 3'VF JQ#MN5)>ƛb1d>62,21h~h5^yH93֘j\a$SǹC5\-)@8.2p)ZWhT]S:5iyACՠw 94m!q.Gn7X鬚v&s;A6dio[UoF$]k2G]Qu > $h0*N) Lʼn5o̹D tͧ XtM1Oټ _̈́*:ہ9[$a?)b i$&#vY1;4)9|@ɒA="aC<@~wߥ|^1e>>2KI^ośm_X4s" q "__ܾ &7EMkd4hކYyO;es *n`8??QȠ2"ۆ_:c2pL0(b2:S Uͫ9m-:ifbN+Æ/mf)ثR vn`U(E5,he%pJlF@me(0]i3]Sq@8 lm*zAj0DŽsDvjJ[fR* иn/a-*jgH;pp488Ƃz75 &ٯ%8嶣rMY3>T;=ݳZPVǴF$k_wl֮1ԡi))8mRJ o%kaB+x'tQO v2AKUxMDu4T t3\rs#n+f2! 7nlD*}(_ 0`WNY*AX:TI*-2$0Z =ߔd>b$?'n^(El~njH_e0EZ-@ ʍm렫E6_cLn @ٜd*xz=$92JQPprFk,ˤ2Lk\}f߁Ӑ"&ezUc-\ФP1,\IyआNl/h('̿2tKqcH˛zϫVz5Y>n S=Db*i`f~V^:qJI/&%+-Xb(cyf[[PtQз﬩qpc U[ |uFK'LaU^)2of Mƃ)&yK?"sVldϭp%5 N\h*J"0±@F>5jO?[oCwX[~=PZ T| $8`*&-h;]Y(Pa90Pe03@UTAcT9-IL),h C7 ['qlwpU#!: "&_w*]R\&?jIB²p8DwCٺ f6x.pλGbtIИCلTґ:Agz1̏{ѹh$!=K. w7ݵG y93LCg hś;:Æn-!M[fJ݉14:inYŒl!S2!3)294bHzR39KjxU(l4x Y6i凓N^vx ( V;.#V~h h^NDh~Yn'D=aaU]{Q _ȒkƎ:6#iAAW}]KDջTA5wB̸*],.U.4IjKck^P# R񺹡K(~,MQӓXE6->SeqS9:^a dDZZa X[5ÝZ}KW xk *9\HpnIQ9H줪mR[tv)mVw:(ˆML5W8y. Ljo)S:OXed6 &:F3͡ba :k!qŌIS;.Mj0[hekD%qO]\6?t9[&~RٯjC  i}:rV`>ak &XrsA{y|fkO!tj VQ: ^Ç,K<*}/[wGOKp w;CW/:J Q5HpMj2(CUmZzJSdxRiz;P7,=~_闢]]/˭_v[?0θY4LT[hfYTOB(o_7- qU;#ꀛ m*2"K95Kd&&*Tz2 ULp*A23[: ףЁ};-vwr=\VWFI5hq:m/62ƕ%:4LV(瑥??aDcB{/1xuNs8Nκ8xcLY.+ 6"_|^.n`W,W 1AY)Q+U~J%=|Z3kuCnU+=ZPYg,GdMu%DkE 7l6^x qJWlqۓ^޷c7vOa[r{w\`NywܙeތjԖ:e ke&PjfEyP*5Y-/;$>t ? )V5儬 XzT>.Nd ;6d蚷2 T գ02y3g3& Aٕ O/o(9YJSLI1}gnwa_䈶 G`BDi}ii\ ɹsi_M%qb~Y:ΓbUpJ H:)A:P0WyrzDuCRAL!Ct>;7Sd*,'*xEwBNl{<&/G~-o $2a.vbJQ0:? WP'`%]\~t H-%3y34_WB4q1U C@sD&ԫ R,Ȝ_VC}x/HfZ_ly3h3C4w^J [nTytă@ko&7_#S4c7p\;D+"7wȯIyBMZǖoHQRIUЦ]Lb +”['UlDqy"&tnbMGU6yA5D^,Z ,UC ʳ7nZZ4^ʧEw_ZXRk$!Wi0rƞ,C^gOX80,t-Þofĭ#nڛmMAkqLN #u̙eB Y&N,}Q;3fY>c8XeYJ±T3M`wjmf$}NC @ꗻa4 o:J!oLM3@eq-Qn>a$EvwvAY| [,f?pnZac3F?漅!ޢlK8"^dt$& zUK}I$;Zip>T]>b ߇⣌`{1Y/n j G3WnKf6lطcOo2L*6u߼֝cBEK`5RɳTHoXNin*ܨ}{ ?"o}$*ԛ`=64ibwi3cfHRcRL"}߿͎XYqӣW*D&p_}N~,#/G~0~ !#聆i$$~~H"}ڃ>B>6-$â [ϱ8N:+]S ɴDe XQ>ӸMIH|-~{4.3qg3ssv_0 p&m l2ckb iݙA" z&-;5 woݽmZNoPZZ[=a| `4Vҳ\LN#$Pbr@MXJAdTq%[_m*VE256͟DU$leVWACFHz\R@@y96lhbXkڙ5˅Ĝi U">𶟳#UN5FٱOd 1>d?7=jI b0/ ̎#y^_fTL @ 劶w;z{"muMub;EuA Kgνit<z%뵯96}Y/LоQnZ&T80dii\:O0 @:6 iBC:/p᱀a|J~3T痐q$ky}@HwR d>%* /:UZ%CV1Zg5eX>-[p<<[E\;\[ў]k`{t `G:ru]_0<պUJ 6'ńJë;3B|/$%H]͔`|E :Rgi!hҀ mZ gl_8N/aЛ(" $A&m?TKD  g|< >lݹ0A%K5x] P'F Yuv+-27Imle7Um}y85 f?5~X{0P? fUx\vNӁWgbȊ1QR[pǟMeV /-B> ^0E@dFNa xF% P}| BBնWҜ_༡N֛  sQu-8/j%KtZA별Pq`[_ ?ՅW;wRmG'[̙ʈA(B 'Olu ,}Qc VQ ¢ʅkV^շh_)dPphUяuvv7kaVx/'* 6Eo:6L!=(A6 V`߭M->Q4n%+6⯤"JO-e(rv~}jO[kXap~L:7EQl]F8NN}/2T"YXű`yry &iE=Mn:xN%<<lIۄmZخJ".(κS~N+ȱq˥csI/ۖ|?U|t%UsagP ?i9KW}CAGr)wo(]q` aNgtO':Ibǐ58.w*Zu`y麄Ξx= Ͷub5y2Ej0yR*\L cv1@ۯֵ'awR,P5UG/"j/hvj_xv%[:z 1clΘǰL.0kTWކ1PzTĦaR.+?$58yq'H3>C:-)Le̷TF/FÜ-[Ix{Cj]AvY'IUvZ7IX4]pĂX# VK3Y{2yfߨ&r;1MBGX0oNϩzc8̚Lޔ&"a~ݴgRVDwE5Q^PR"A cdJU 7 .D<𓄖_d_1˿6x6u,‹yO=TˍpS6Nlv5NڋAmji!{ڥ pu3:6xz4׌^1u}ͯpl| (:6B UdQ5:`Wx# <d;?>ߤLkǿ_ȾM:G`9(Xd,FkS3vHvbR2fw#~#1H$wФ]̝ՠr [N!kd+O§zfre~+8:mudx}Nfӗ)cRscr{LSEd=Ԛ! {&(b: הv6ȵN?t'Y?",̠Lw^#،8"i1jnJXW;xSyۅumeRH@J?wRlhbռ (J&jKBKcZygb|Z Fd֡˰]&"#/lF&U*535F}& <#t .FUla&U2n&7^ (A0~ӭ[Nl?'ڲEF@4,FV#Z~ApRp Ǧ՝u=AQ"B\m^ H$[_P1^ o[qEp7uVn}?ػN-v[0I2%l=hF>׏۳eW9htvҾ56KR@55IL?,:>;X׳%:LeRl巢Bb܍Q]C嫌)J 9P):2%"ډ]]?"3,Nvs)AVqhE{S"<+4 s۬F) #[ L#ݸaۛN[T!6)` )4("yIXEWdJ( Lr;wzx3F92(wdoɱ&̕Y9 <\t|g#sk$9UKpWYRֆ&T$н] "`k'(2RäSɣvs)/Pp'h&"԰vޏ,׃F:(Mj ~ND?.Bj\%yaAylܾ^"/4hg$@88GQ㐉CF!m@ #` "Uh+#ȳs`* N@` ,Bt3NJkKL/2D?+훿Ls8BeMqpa }Xepr!OK {^}(APevbgj\oUNfI7`l_wə^{=u{86ck+p0v9ĤI!wZtݙsL޹3JR邃; gw!L18SNjpx5Ala[nsW$"^\yNU33UEow/$~z$tW?v*ֈia%F69 ѐ2|~SoLuͥ&øpIL6〜jn$;J"\g~3"0r!xC ˈP2f# &( R$/= ` _ْfbH2(c\T6=Is-ʍ$rƪJ.âbV3~H񇳬'xT]| "֬2w.<0|$ e9Ʋ<7z*|p!S,3/exqLo6ε6a4Z{: -Rea-<Ӂ(h0reGFw迵 r=B'teN5pv|< ȚOnU`ë;nZљ'ɼ= Oiq"Ŗ- <,~NNFUp쨴 hםG,uN97slȬ7,~@8)"z9՞R\[ rFe*# RI/)lrMNҺv YMThH% n{0p(l'& MLI"\ V9*6lao!k%}p@&~L!_Nurf {y BFk1V,vg2(smm5GJ,=5+O2L0GCIxqh|Y5}J'|w{ [;=kwM@vڙBXNJ>">Ӝk 0:(bt$Rz(O4=l}st%0@pU.ZfP33!XMA)R Q1sN.Uj1x Ėo`FXz()d\%Fut<{?Tp0ˑUbƻvy;f"CAWf*6v6vj\q3e4ckhd|D*>"==YT*BEkv%q{(1غ3VP - LA05o75*)RhO}ҩ M)\)P|س2 :cw&KsT`8kRlm.ml9l_y1?sׁl`Қo1%Uzx=c%j#]5 (*0nQLCEZ@,fR${m]o?ZMizs _|nNė@oZsD#K:Pk{Tm~AIShk |3 UI*>Izw>eHn__TSXM#.%!k՟_wS=Fs,I˖US9L|StiLCmŤ`#a篝9+·Ӂ%-z#fJ(z>i!>OxNg.>0!2W!&za$ %UWu}՞qEU:Z^F,4 7xP,`-~C&pFi*I;YjO}P1ƩUg9ԔW""au&a$tKk3J{Μ lS4y+u$2:aRVHgg6|a԰i+K31Hg; O#8: xJ]v1%AϘ9*TNCKX+E+B&Au?p Apa%AC䤰qp``7T +hWsHB7@87ی8=1W\;r5@)TFuf]t|Y{6|)-ގ8?;wb <0k9H1tY9|ϕז4M*ӷN1BԗީCmVYNWU}a+pkb4V~S7F WXNSa6wf;ݟ·,1ݶv L㭕_pJt_䀩$['N O`l{Zqz}bӕv=P&DtR8y8/J=15"C/f_V5pt h?Է,tIi*a6 Nf1i4 fo+jEfqJ/[2*-96)(ʿl Drc8;5Qd 'a5  :3$Ɏ:@NE!x7{?DwӠt<(uKz-ܩծ{U<8Sj+~̺]FbDLYMhQ0+Id1XhZDZFC%_7޸HC\xQ Aª>!A@(/9rZX _}ILtlTڞNm)EiΌ:񒶋`ʛF:Ta5x/K$eP&`UTQu\z0U/eD[bo4F#^r<`1sZ8ĆTd)CxڶPܼ03ff9zS(ݨu8rE:mQa| TeRȨaލ1Lߥkc-ʝD J7ft-8"Z,ưd.AEs!Z=o+VoCc~fwFzf+sT.{\> ֵDvxoN)G{?ۏz'`q]1wsKnT`~k.ǾoI[2@ %z Gau NȬ #B 琽 WH!7džQmd: n5Obyljar}`qTlfngWB̢/=c;P8joIS9**-ٝf, R0:aDy,e;좖`A > ; uQWfaӃ|dfq9Uޑ9cwJ'W, a&j^lH~/2xfޔS:n~ؙ\JSyZMh>2qmw*e.gM`ȕ&2&Ĺ=S͂e-edm*sܹdr؅uf )!Cpv/f5ө8ԟ3KP^?s,1(țΩH u:Pޥ>;0<oL0C2ͩԛ$)Jyј1xu8֥67%NLp.^1֙C A|8FGKyJŻ3 7 ?ITV:$k &~.Jh5, LO ts#0kޖ ZGy@)]j+]}n*6p[= Lh Fc*b]K̍e>Uݳߊ-T(x"NUnBi`S~?"D^gՃua.N`aܭ|]%^J|R3fv#kV^*BMČgGj: XրXIoN1>%X6Q`T 26AU] F[]@cC&5X5Zg;B%ȍ/l&H,9֢λ+w|½ǰK7WB8NV>3j~c1Ry)hOId3|N>Dќ.Z;=~%c{(9x?i+utX@q8;4Qlz>dw $;}0@a F%7CR1H5 {ξcӗiDvAV=KOT'+[1&3.\T?78Jg~Oޖd4s,vЬ:SunD&,1Q&ؠ$"qkn^mr\>vwZX=xܯw8ZNɑ ju"AfJp a ?lpuli .)lKwfȝ8d5 BB7jE1X4=j|B:;+;uֽU'}1:EQ̥4<p~G^WYmlŅ̮-ތlm<,IKn(+Scj>n{%#uB.^x#_]6lXuhg5*]upojcĕH!ElvIȄ:Nœ׬fv/vm)BEq1*2H&CynTiCHZp͕`$NǞRd'8<j7Ϯ'ȴo֭D*%@}N3|M rh.)"b, fGokiz^{(hxe1`0JNh)@6\bwzTECc3k3.Iv6TR/+=A_<-_bZ>k lkc̈́qvk~-{,{$`Q,N~DFIM{+fs;sEQ4kcS%cUxG/:N _u8=O2oUvl#̻lls̓4wtcфSPHNI3Mjǰаp<.iX!rp@;;{;wsy}} u u<,69C57 emgHl{XMwpv. g䀑uw2t.wq֤rBmqDG|DYٶ>eVήv\K\NLBq#1Bc厫Zj,X'YtGn'DΝ/K/q)0~F ~rLg&$ A+ehdSZ<4W%*0יUT5şD_ˋf1[V-gOzehkݴvS̟zħ4NuEǒ@~P}56I=#C295cV![_4S=`skT)H8ؔɝ`AzQ0bjytG{?iŇkXlM?9`Q:h1F/֎Vu N a6u>f>dzi:\Q)MN"q%#tEaJ<-6Z[=%A(=%1Rڵ!fY /ypYe LnXf}g6̽DUٻ9Ӎ;uDHqQ[@DR{fŚ'DI/lϞtq*k-0u 6,sÉH,˙8^Z5(>W`Z,V-:ChÑr٪I`YSN|=*Cg"R.TܩO4I5N>zU0IE _ZU0|VՒqB@d`(z.kթ\Ĝ:ʨFU- m06t6Nu ]=!4*2^FKf&Q4R9Kt !ŽyP@-@8=ԪQOe'2uVEfsěS ꘤17801̷y?_EFۓOҫ]dGg_(Z'q Y{ xc 3"UX؞'Eh ([?uW r~QHۗG 3b5WsI{5U~ƟYK?#p cg<硅ˊf9ό.@w}93Ͽi~sh:->W^ҁsϹaE7 Ga_*]hd8#/9Isr6pYqu{<ڕn9p)/S5N{L!F:˦_5^N",Xd2ӅI ?׹.';>Q@Omb]rlԲ3bO@ V:́4+=L)tE*Z<>g7"!x f\~Iɡ m(DHLw9vڭQMkdǂU!T,z\QLndDbళu<nrl;y\XHˆBk !fc**&#Nj)L&Sg%Ù6FyZSY.TDZ{ӄS9Dca@d~*p 9AYcf.TX)I$,8i#!K*b*\u>"եق*Tm_EhD!hgXke^TE\+!~X8&=ԼƝ MŒKR7rFP?qW4_^j.XXiFmg0ŒlV/RzWJ;Y_id-?.m/mjC՚تX6kۼ/_WHE35Qf2Eׯ&+5 /fqK*5("TCR,b2D0k=TddMR$j DQNd,܉j:Sݤ^ ^ `{Ą HhG2t?qI#<|V*U"GdDeJCkntߨw7q&4DsFia1R:/MY!1H:|7J4V# 8p(ۋG:a2EeRn$͗}'9$F|O_j4Povߡ(qy_j.X]Fc0z֠ ` QY/pSQz5>8!\85_f& c ̖Ĩ$9(*  C YC-,EWu#dV<pPE E(wXoj}:UbF Սϲ~-2W"l ҙOgUAɰ JUz` mЏ S$0|13a!=*?9=zaZ-#LtGx1KhGFVWcc+J JebűPӧ6!VדfMW:憲.5Kf K]_t Mpi{wOgt:/Xӽ%~F8:$cN1E9Lʴ9ǫL͝IE:Z_ :356QvR _8rC k"PW-=T(J BF%EӒYIIRHR(E`ZNNEQF{X vz/b˂*q9{d,,X%ͳ =XoCWE_<3h^Zꢖc(^0E?9 yY{q I7$&jjvYt` u!>Tu]/cUy"ެtz)#4$c^'ÜW?붹C~},s -a#_yhńa[_0ejN#ouR#p'>5,tv:t֜]C8];xݢ'74orE=6 Z:(K5 :2%3ovNy A*:%Z YA|f0vtB4CЩߔRID_GΟpvl[ˉ*ItYs*tJuƜGE>5変ЪU\Cɠ6Nɘvx_˒F)/$$=(W0Q|3X{qI0iu̬A/D#6sss,Kh~Qb an:15 }˰H:% tQOm^ԥAH4)-CNN{B'DĦAK=BltnkK6 -#sF([;}9GGƧ& SK)X69]N#0jzh xA'sĝ8OI$D9TCmffp{B`^ 䙪CNܸL`I0Uop>2cPh"Tn5R/Ryܥ_HkDj=PR%lyLiYISN]:bSs D!x ϐ\M&\v{$'t-M{G`gI}H1eF8d' <]!t[x%ƌK\Zn;'_)MkM' (ImTTۡ#B\#0پr9).|gȳh1¦;1!!X)zv ]s:iޝ_T4Ɣ>0*0^X} k=9GCOgٕ}r%Olu@3ھFӜ+Ifi+g{^C`࿹wjF~^IM{ٟr RDI˷!ti$2뷳W= p5!b.!̒spuPc:9k:1ZGFp&px֟Zj9̟8{ʷ4.%V!1%ΡyF>Ahd8ө3]ܹonb$ OU9~gֶQ^s1 u!oZZ7'U^a,u{@ӣNq]CgRqD &\;tV)E0mԨǨB?M9v~¼EYzQ\7&vɓ! y/6V]bA/;(k>IG3pB̩p/űTQ}أۚ{-{01 y]: [U޴zrm(Ӫʠ:6%|o*;[Jn4κ3׻Դ~l<09@oNAGKHsbӠ'ß9[ΧFe7 a #+C."TmQ]rMPuNjrA+/2PXdԞyҞR]D#cޭ7 Z,ډOgUk}Q_}P4m3F āouIY:W$ L#EGyR4 2Vf7 g{9i:vԑ؟dt:?Ȣxٻ_ 6NANřnQEn0UyK0U&Y#aD,ǀMlPfTQ&@9AN>$p ;n8"%qbN3j'긭)'MDhiw68'H+OR'd8lmEŖ)elˑu0SFև|LTu[6u0+_v8z r|?ĮA,0:R'px|.&1،[& kIW\0d2>f9n-4Q s@jΚF]T5j`<%$@qOKty}bDqxL M]zy$d,B ˱@Й>{4kߟ1+_O54Q3!dĮ dx%u ,f#Fe$)a9?)Sƈk,EY(9 wOz(b#~~\cMx; <7rW[ 4kOD?9QCq RS9X V)9?SB^S2vQ9cLkL"@&vc~ n4Is'$ED#{rT֭ѰQ}^vW=-تnsNAR8ȴ ~ L'O7\=kD&2u-R-|E膙'7 a5`6c&jV]ZcbRM]\XC aAC"CM')r+ r.ȍ\)fßL6͟g ]v09XOX7.{h2kR~?ӿi'^tM] edY"L`͡tg@Ѧ3"yfAӽc%`1郖/n>t֜l"!cSq?IV>`H[uv} ]6U'ldV#YANf\WFM{'WGdfRMM.6~4SmuH7qL x._ qyw$Bћ[*Gfk˷&NkyS|U* ~4\5)#BQtȗh>2.MwKNeM<1D%4Ayyьƌf`Gek_'n'phœ)Dѻc=97XS`/ޟ;qee?u0#|)PNxNUɗZHٸT#y̹dDŽg;ۢ_ uK3njvNy nkdZ&NWqRŅ2+Hv [z'HqZws,s)}4 {? pl}*%Ok*j tSyi\3"<8vIgދAN7K܀9z⭙1sޖ2cKJk=~>`&Wbɺr^.E1u&NAr'MH8'i>0pN"Թjq"ב<ܥk"{!6ΚrD4;x/*ÝB9,#xs8yx Cɧ#Wd!Z\0^ZR50f50թT{U󯮺N)&@H!$r7!JP13~wsDHXM':Džs'k>+\(sd }i^=1+k=dH $lGj?*EvtOMn2h9prD9B362DƿQ{W:˓*u5юR`yėn{#2E <`hO5{R AShZ1#=c^~&9?i;›ھg39]&ʡ~\}dԐM%XdynfN"B3H`)p 1'@<#Fqf'FPᏐos&pbO|}=sVfg`vg'z.ݝөUhzj`uTm 1mshId" pvc3}M C>4J8ߵu(8ɝt7A־DR_ջx3ӟ/W_L_ mx0:<f3_]غmz.Pp#gTw_A=+n.}ȠiV"[䑄 MP\ ウRpyOmڴJ$W̖A7[qʪ\: 57_ Bf 7ހ**ӊ&gꇵ#MO Z5Xd]Q87LPzsWT@Yl%|6[Đ->?$diU# ixqCdkb[pEӷM!d iB* _K^<`qe{)/^Y??͚$H"؁6/2lʷ65m @fi!_Gj$*+=R`c'>k –B!ZfcNTO->PMxmpS+"0@YHbݏ!@8.)l 92(vHjy=٤g:U Nho,Ŕ>r)аhz Z$e s.E쎄40w(㪌V.FUY g]|Bl.x Y{f߹zXrrwt}~^z+?ij_Po+z{S"T1-5AKʅ9ˠt%&c%J@.(n^ԻvMX`꧎v@YF'oۨ>pw!A-kadnG` Uzzpߞv noj=la+-Aˠ Ivii|'C:%) ^ƣlREl\a:X l2X$TCxAƉL(D>W 3E33m] bRo*Wݰ0o郿jEtĕ4~yA?Sw<+$*-[_2♧#*鋞|ΌO{$-BVFS[ɏ녲տ3/˅% 񋫪C3&r_ɒTѨH͙1%e4Z ֚Fd EcBH ٝϋAIfEZڥ >eܬB:k+彪H~*ecO:!U2:qlx" yZmR|.ogC&̪j 0\_L6>cH~\Qah{aK@Z}Eu2]\Urf-JHnv:<\VpďC vl(q;\ԭ~߂_vo~k괁f{o(J~kjgt2R}_VrHwEurmjdcS;Ӱh\XHTeX*Wucvub"i['$+㚦VKV/F~kz՗:t&50#CEűtdOߨx~I ̌Թ|^MCc]JYWd;StywRlK.7jWSwH}V >x;6U?|UqxpXs4IˈOsU#I~l I~CURO3Q'l *S6Z:JRoYcCxyR8ьAU W?[h?AgM ]Fϭ.o[vR*sȜ[|~BM1pR=S0 [xò[&9 ^@\,yC!=[yݐTU˙i~U:86Q]:ۙJdJN {qX|m?6O HBiCYd9MWM9_Xh ; K%_We Fq3ݦpgDFI*DFh)*"UH|FKD  s5[/>g\[}+Ytڙ gY\q1c 4,&d́aotiekWkrZYyYŰ`-cWJI<-Ph1lͿu:(κiZ,T$ ӂ?Ic~S GX4FvpFq=zaYT"x))5Py/|ilBVx>'3Dp.mjy)[dHj9%_ Q~{u${ޛh~siDH,6بNڄC\ZMIMR?6|^;3d: s-׊- ,-v qV*|'P¤j ē!pƥ*L\Θ#KUp%D|*JRp"UN^)6'lMUYSKN,8H5&c,&FE/bIʪDEue2Rgjo "`Z2Em=Isae! |tSU凢Eq?~J\ ]?KsI(X`ë4xW~m~\WDžΔ*p@hxůKJ72λ=nWv.t3Ũ3'#޺+~QG׎ZJUeT\-_>0Xcj׹_*~\?Rr)p +sx!18',ST$|/= G܄]m a5r'T:O)p ncHκ3 DpKRF%1dXkE7./[޳l*oYݮj5[mչbȐ&l7*7M#ATfq, шG#(hD%ބ(M3)'*Pr&K7'[~QQP_+I8qRI;'O O;.5v:c1{$DbL6V7ې}֔72u۞loYN;-ڳ8 'ΐXRbenl7 Ԥ4i:?mKł-K+J̘e(ق=ƣYR0d\,D`?^eE@GtOݍ)לQ/j2tJ4D9NФh5KڵJ덄fAi8 tɌښGrr9p]i}bb˲=dFp՝cdcg۠`89kCqLU_=iUYcY\|rWW褾AB쭳l/L['I$:) Ќ{+Aٿ>ڻnSGeDpf(}SU:+jA<1꽖3Wk˸xt"#еZnX (I J2uưE]"tv$ҜecFC,}cJ,ogtu,_Cj:˃ w)AeT_~uvD`I ȗ!Nd4U5(todX'% E-A?z;<~-g+];H(|*"KaR=m-Sk!Y%{ɞ2|pt.E?>nYv Hڥ[MAQN#(sWljGΓy ;N*os|Oغ`ݏ|6\Z8i tS4\00:c '3aX^qMaUoL bMRY=j"EEý/cggD`KQE(x}zWOO#g\C~͟uC-БjyáE l*DnPLUޱDuȌ[D"{z KpP:-/.Hˊ̰c>TPMd"md2C6aA_8-Gcu_w9rv% 0,BxPx$&0)XȩyF8}/s'XG1ñغ@CA=w|ߵ qu6 c{PS7Hg-mo2{8{OPJ"(lԯ'*GܱԂ.ا{w7cC[T_a k=ɟI$X_sKTB.}cݵ)TTV"5ƻ'y˂{7t\?'o&:Jw9IRwL*4PCxG>k|Or,oʉ 3po9$C'$LFt:m]Ft x;^c#U̓J>'~3Cg^ȯY|!ba|݅ zЄ*[էʊh9Lܫ_Mz$s@Sfa#6)m,<h+`**BudC nK AEpRbO䏙ݩx;{y{$0 s-]h[ 3'ӷkCP~v7aӘ԰UPyV=<"Ğ4rk/Vͩ=n?h3m ZD&_(/Q"? UnA*+ab*;}zǶWᄦv~$7QJگInDtGFJ\i &=/,S#ƴ],Ap! CC [ ?׵[a|v%2GqĘaS1pڭÇg{ߞђ&bG{}QѕFx\=t}ļB9jt;W O(ج^ɴy=ɠo OoM{ӗA ֒<Dj AxUkͿn~~{A2z("fq1IVX3$\i&|#^AKg'$2Y9kF C&$_wěr| VD) Gg%7UagB*6b~p*H1{@E P.2Rf\TuPɓ`-]ӅA<?B77[oCU;s[:HRLAdl6)Bv &CcnG*5g '?teh*clJT8կaЯk˸|M5u$wQt|I+EN :8=Cx@H/*._ITv0B%\.4誃6B{'ug]#cdl\gc4>f\wxW/M"B3/fIukKG|DO.:큺L-Wpo*:2uV9А8=hwlxT(=9pca W,A~. &.֑Հq9U|gf< HR}IMơw0|7sI| 1FXXYfLfS2Jʃ˳)5E)uߔ/G̦Dif]}fUVP؝`m6S'gD\_jAzI9.k~m`漉Ϻ>3Q/S mywk7>5_Af,>H~V)H1#~Rf,Ι`f, (*?3m %a EƤz6R#;֥ܿ^aI}1{_9>$ȯ ๭k87D郧 \L e2Oz !|pFy,[T_ޣb51hʸk*& _-~yFB;&LZ/u@yȳ1٥x35+g8{+~_ɒ3hvGŔX";(ಃNӠNBRvcR[t`΁Y(o<_< [ a _Ri]D|@ 'SLl2hi3^psaP],e - *@ՓE /-[ўtK*/BBU@>chĽ_r*T9w9c@Q/i,EuHngr)cuҴq<&1?ygˡIؚCf Jv1dKj  lKX Zͳx9tP6|$4q\dF|86h &W* 8q"ېSBhʕ/SMrcCR'KY$fhEgFYTL!53lqY;1^~$%cW\g^ *z탪ч \t]6Eg[`a|hE"nf|H#/|BlWZ607+I$Ȇ"(v//\sWZcMirnDVR5,z7P7O>iٞ/,5« X ^#~\/A?lpw9KjeSnL\^,UmdG4ѐ%G,Z9LWM-:`Gtun@ER8^COʛk< EjNzDiE[ @[']c?=Gl?Fяx~h&TL@₆fy'+xY T}9M86+xeUc}Z\~ĎCo!T}>ۆC/8#MH餚9X K{gyN쭲|BC~MZ8ɝ`A&;ct+k|PoP l䲕gNeT|Ճ%bCuk @$u~3vؒ5Ʈq vw`˯_VȰmKj)O>2ɘyDg TK1$L< lW+'[PjuԇG7Uo7N.@{~v@8\/{׸;t'}՗WØv^cv+7Vmš»A؈hcdQm ,rO䎮!WiIxob I`;y?\N?\Əq?Ƙ2P7U5jcStn ?f*϶Gwhc-1RT}t~3E1B~ٮn!HbYJ]HlD)$%cɍk:-4Z'ȼt |QQ Ĝ6z+vV߷n?0fxΏl[md/ |}䕊.7I`qT'G#e0nh7uƧ\Fa³λ&",ѫBt cL*eY c5fuͫ @(JDpBn{EϓAO:ɻ;z11Oe!z/YQ$ @lwotqޞszB z=u9;eޞӄʙ>𤋮`ʳbm MANxauN(t#M&>ߨ^`1$Y ;X`v{b ?<\2݇ #X38HSKAĹBh((=7)w0["},@"]I@-uBBuᮀiFa؝0DY^LH1C` ?CӞ֖-A0a9 'lQnba|gYmP~(VIw0EOI@^9*Kң ^ >ꡕPB7A)|~[O'4ة(L5?$Ͳqr$-l鏂:eP/[V/ JWb9iZ:`߭ZsJPJ "!DwkR$zXQʠ6X!tQqq{# /GBmioG͔G9B̝vS4S.4Câw݊ٹ*nja:}i8t{n^:.j2uV;YMo"7 cc 3&#* >2i8 =&"^OA_jJU(%6eWr36p.pt]dcNArbȎ1|@em%]p3vaRTI[(y R*'6fb+}Ƽ=0_ii|eA#b.ݝb)x`j<]"f4TyFp ZxCGg斤^FJM1l7vŜ[w+iSZ* ̠UjΡ̫;0A۳leAˆ}zq߂x*{jG2ykqXnLGLT[8T ( z[aK""fTW@vvS0*LaUui4 sNR/y, k3u*$R;IwNV>>iL҆Ū#Y꧹@>넾7u10bVjwھ}*B!J"+޿bߵ?yVQe mwQ[:djY}&NnDMuZj TU.ԭd=(g.Fv cF_ zL' YNx`ϋS 1ԩe[<"].H_:Ayr^&^Ck `,K2TLGH,2H_DWvFޙՎk_^~WsKk`鄿QN]{ sߒf(^Z&j:x-RlG~ҕfsN Y$9TqNyR|fSyYHLJJmJS'ޟ})(EE=4ušwVMG];R &nf+&P%]sdk`1F}#hcG ! J"vFX⸉GM)z9z9$K~\aȝk7CUٳ%:n5z'^C`f#՞b":k ,;FaaaaaA4GK}rz/cb11.[X4 F zGߴp no?4G ] D|ã(m2η}IH9GV&Ҽ ҳQ$6\]ڑi{_ry@_.u&\o:nkI1J71l`ic})6C$LIѨ!,V:,*_|drV)a4F’u|(@jq}Cz(}NCZsr{Kula5TlKM(G{7~9nO٠yFxg$cHh1̛>0s`11:XDl2RKlk})Nզw_!֪6SZ6/'*GqbӠyҩ~D|}1P[~mxyS+[ sj#)rٔ#ZwJٕ^7J`hr(9vxf1V&q];~&$;xZSbb]t`7;L|zDU~=)Vb<α>qMȥo)q5ڗ |K\V88^w 5wcvoZ}x*~WoC*7o[LSkx{Z;oyo",Fw| kg$n^'}ӛZ'M:bU7⓳' rдǢ_xrYMsyw['{`ӠSxqJQͦG2LF;s>YGW>bb#svfn-؈RLhē%Oy NPi+3URW:gk' CsmA&28H'zr C2u-?i\`ZUSoScIɰUaȋ)F(gxk+/F[\څ|:kIڎk~w(#6TX09鴘_S8)iG-)zf"#YJ'Jc)m fCl4*4t^s2t'2RC8CdQOT?/>9- WfDhy嬽`ӠwHSg/oVv2=.KF ufpt5~ӝi О\?ә#Vs'sqa;O!RXcwg>ӳ4: a!Rey7f:ԙ<*Đf[#uUM0kN s B ^f':ݹߩS { T \vHUY 2.^+LHtLqAS?iwYfr<8"vF2M"1=VPÛ 7 ]:⥴~vR6ӄ6q"') !3r,jWcZ:&#I1SPfa(n-Mp0x=ѥ;hHi%D0?n% $}-ݪ Q+0ၒu5 J&EY܂mXs$eu :eQPDxȄ)qu}X4ɬCb_8$ cT 7BIp=X9A4'bl"*I>(_1+4` 6l6dQ@ȫ9Ć8s,:q6Çg= !ǃ" SH κiabw#L8"*jY'CXC90I1 W[LvW-C^3US. aJҁg4SX?xr_X;R!Ӏ†.F E k 2El@}fJC'MQhW#r_V&R>PbB8 ]6ݶNlFey^a/ywP;L"z P8R g{ Oۊ6R^qՏ C>1/>ѿ I*~צŅ.xns8ҹAT6I +/Vy_/sn~sumOԘN'ĝҮYzt"w4;OB9׽9YH{\/,ސWQVz^ɏ`?CәOgMMSκFYuV$SF74hԉ2!s8~'~}lx:J(42lXsy ϐ:6N<{6o#_8z@~)塿@`*2]/+]PZf)']+y; ԃEj|ӌ񕏙 j(%gP;3i&T(NXS'Sg:89=hw`x[Lڠ41~YׯoB,6kN!u, 0 mzP3/ VT*qi;c-e@Yfy,~ %@aVwDdI;k9I@򦈱@?҆&дZ#70gE-|7j<S5u5c23stm =*\?kʃ_¦icwB J;**%i㮗 h+iBPOIĒ)jH$֫:Prt L<׏xWٯ!YvЬ@ eWf~^;j:EۓUfL\w{ʐmܒ d1̮ 8 y l Dh (RL1xi*0Xׂ'~\ZE),!7NV~FPR@9Q7KcU^#AxVEkV ƎMLP,@/j?~gtA? Ln(S9S9qԑ<iz)1 eڞrSmHUOh,&FDFmhC4b$U&FVHIR' vdXSvҾfûA[qoa9QκWiYsj?pt EDMT}=ՔK>ѳ7(S܉R0.hK\'ޢnu]5HwM 0ϡ8}1?LPKi Om)`L^|'t΢F1Oi vC ;1>((i|eAx:ذTΦAK@mD~VZR0CNcnzqb˃4Yp28Ck??s5hSv OJhnZOܿ<~a\QT( Xj_c=C <|<(D&uɖ-Fjd.LTb<Ȕw5Ia0V?APVdXJ&[$лصRRoz VF++ujp(waI릨$@*Q֢EyuU_]רJ: Ou)jgw]eҬ&k-X̦Ab2g^:XhA8*tCR_j;2EVenge-3g(q RD5J{UM3&N>٠8VO{:"z˱ ДGgu0G^JM_g#Fhᝑ~ZP|M4f1i<Ɓū̮Fوuw y&Z_ na JG:* ?pF?/UqϋUɾg[KAd>3?%:y ' d}q gRC#xêf┠|I? &T-ݯ,(=〛ZU*%%e/6fqXCc*L]hH`\ SPT:X A I*?Z]\sdFI"=ZdE ,&^͗qNݜIy}V(H[5; O#U ncg~*p:_i?1%r\U9Q${heּAL7"_Qem"ldΔ`mM]-&9ϽS)oF wfԋ}Ŕ\/h2f5jwE=T'vjI\43)Ya0?ܞqp?@8}e*9c:fߤ/2m4eA>/CSnε4;[lhj*(k\.ƇSMH"0b#ǡ *pb:AI 6~rÃ0Ițm2eWaG&{Eyfgv7? mAS$G>a2~6ev 6i&2ٯ* $MFF "AκeF)!%U^ ڡq #82{<8TDnZ2ݸDiM':RmV9Ƕ3/$^aJ3\p }Ka|D`18|Gkyeja2kϽ*V!хXxd'&ns'cnvk.U_ ؅W[y)PjIolo͉ .d4{km:suooTT]Wx' (-ߩ}T &F$YuqՉ$ChPQur UUF+JnRI{&5^3xJA(" k93yomxW?)Q)ի~{c[쒛T%5ZujIu̪,:e2'}5(5H#ubgL-ڳư@?S/AJC2tӕ~z54 ɘ >.ڂ&N[RjMύ\nHdUՋUj(D%'>Uq_' ^[I 3N`Nƒ N]UI`(Aխ]m}/A ?~omߛ/MS|4_%ql} mahB$z$dDMK=TP}4^ )¯ s@@ik\UqUUWK\?A>x FP25)`om'ظ@eTe iwgK r+yRX͎:_<@F5 H%e˾Q,֝)pP7ŠN䇂3 4mms+ڨ;NAr'MmPuX4žKrH]qEVu)XAe,؛oJOĎŮ$--ص?z:]N* f` -mw&RQi=f۱Pnœu󷊯qhLȘyEj'*chJ(U@# էEgaьV5//lL⩂ +rV^B6l_-lmP@՗FE[0]ox|I/ o_K*w:`LF%Ap&DXnNܣ 6keTG ?1On]D(O AĉRṂg!98y,9XmiJշ[p4/u9p]b`u0Il Ť;j:T$I*+/Ew&W8|%44X:S.Mx{4Ag^NF=CКF_/ihS|hr<{z?qe5HSyڞ0(ChK17^C4ŝtv9蘠udފLb9ߴ=G-!0ϥ41!Z?}׬4fK?,[>>-\-oN9gM ]wSQEZOz12OF.r?6uK>iLJԝMN{r$`<$ ]))-roLa<)J0-iia*/a$KdqˬB6< /w/-vwM:Ϝ@s&2ڦY-*zs<.w%OҸ'P bhИeNκe9LgOZLg%NlH;0nS Y 6CmTU+^&= USB_THv.&at<,xPۃMvxKrX TTMJ(DO.D&vC[Y" dFf)9  ߦ Qc:R tb,"x<ՁP]'\W v!~8A@/!5 3mq2=-s`/ٲTذ%V'[oW), /<9+l@ze> K@cѬִ/ IXxck~IEvX_8@ĒQ=%ŀՔ { AZ>BCk!U tS5e&rGiւΰ [t끋w>Pvy s>+ys&ŌpS,QSa]7uįZDꋇ^ \̒MDF ԕJ: 2Wlutb\H-r[YhGyRʕvhdؗ{|xX0yp3t:p 6'zPaߵgmF1mR Ll4h|О$ Nxg{&[]^[^O4y9iNQUsj?GwC)Ȱc4;hb=Ǫs3t 5Fsp(. JqXc̿;sDa)ʰلg NH ?+_`\NqE.ɽڧ8Hm> 0(3~kBpJF5iIGA 3wn98r>C'*!ԚYtڙӂӪ.a7^%Dkn9m+JKG5e)3_IT8 xTV>Йk4ˉwשn-8Q X:K f3Θ4}tXWPeLnW5GtԸ}qMfbQ.FְzC,!-z{ q Eo9s1oir`X6ptmԏ2x -FzM?/&uh3G[\ VW#V<)xp;GfE:+/ν$|eJwPLL `xV9S%ls/Jp44´$*Lx;MdB[.(R$d-Q M2DcJF;p0TܮJeP'-xzH05!R:tij54!ľ ַ >Mn/Yvt5u2u-vxLPV4 >LS,p O/brf YZ.TT?chؠW(x[˃ՇT/0Al_"2CjpG\8f!? eUb6;Nks9&|*L39FXBc$wRXaEB#,̳F?^ؐ-*jpP=I ck#xH= +Kf=X<gBǢ;e=kuJt;vf%ߋK4oc9<%e^}By[/ P-N-[i5*Y \PTDf h#2O7&(ĕF`d0C"ar %'ZTrc'=iЅ9uܚ*ozF~}vJT ]5z0=.3AW@G 6הboЅSbbڢ#e=i8ERԍL\Ϋ: ;oPX[SFHʦ L1f'K"Iep9cv6jЄ\; #ڹ7e֯"zGC7*5SP[Öٟ"B SՋTjTpfӠyҩf.R]m`bsmw\EƞXJO$<[Tm-3ynn_p$s Ł5U&vϵ%mawɍׄl(B$]NaH"IX0廚ltߖjULiF' -a -cIϨ<)y#]`0FD *>\7Jyn2M8UiUSCJwT rOK{(KLs{!yIpOfys{<.́ao/ݜw-~,\ `b<(}4uA;o^P|̟8uO<{Ž΋9/Ja{qG?/S~S3%EE5)7'*,*f63:nuhܗf)J%ޗ6rAzlΊ(GM 2BU:lD>I rpX8gS?H*5Yn cVeJLNnvMm)xe7xwn\:ebII_6ӦC ? 8ښj=G qK2#!%3:ip3=nJwک0I-|C$4Ƞ1Ou7ĥ|{\TyC$bj;3OЪC[ͼ4ES؟iim-бdu8 l>OnNk`&Vsق+bZ)Rq'S~'Iß|LyIc9{YXߟON^VҎ#ei* EKa1e܄CtaQ qtW#Oŷ,C;#)D~"t7v"&`kU U?ӻujczq(*<}$d g_x/ dr¶ȍF/<( &>4Gh֠2))I2;Id{]v++X#Y9IƏp^> nӶ~Kuw"!j䀌 J1>6dD5K-J;?Br/ SZ/{ϊ;)95rV2&ڹ0B^4 5_yKY_:+(B~^ 5JY8CkF\‚zh 5 Lz&' x_; $̉ ۘK͍l'bq&xDf>,f @I,<[(("laL$u3e+[l ;Ś-VشږOh>i)~Âݯ]; 0;u/$J+[o:y &&tŖw۾qgS5#d\lzΊf[)H1i&H^rۦ=ii;U-{Er]NTD(] L>mR*:k*ʒ!-f4:x۬hwn`[Vi剽~\WCEE"E0VƱDF\%57j)Gg2trXY@x $ljfrtLR^:Hk͒x[?/-;CBka,&F ZiHU8A%&ukRM5-?EojY_y ^t8,J;,/lk7,+$mP(B_~RO[n6\XZ6WEhqʽ٫n)HY*n/$H|yNȋ~{1V^#t4 M9\$9H8ᘩ1gz!Kq B&_GTF%BBpe0mtF*W#ҵMn 7ljެ L{[|VpFՠo~k҂  M(?\[lcs:SIw_Ao@DžѩBi0Ԓx\]#(;V-D@o,NBR ª0jsZ|{:mD` \YRkż_%[kV( }w@;\N64˘;v{:ay7'oo/Scyl1B%.Ձ Vx35Ǧ1:G $TiEGr2%@Y'Fȣ3Lx͇L65*5tЂ(!P{8>Z+v޶\̗]ϼq|!/*( 9.WG?!?`U_Jt0-fL/ZOL4Qlyuڜu5ʳſZA%MB@%JggjinUAd?[ߒ6~]x|׼^ B"ݦҜ?TegM/t~ />oKI@g6I-_`)~݌y,MQ=jline-1.0.orig/examples/jline/example/PasswordReader.java0000644000175000017500000000163111550705746023525 0ustar twernertwerner/* * Copyright (c) 2002-2007, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline.example; import jline.*; import java.io.*; public class PasswordReader { public static void usage() { System.out.println("Usage: java " + PasswordReader.class.getName() + " [mask]"); } public static void main(String[] args) throws IOException { ConsoleReader reader = new ConsoleReader(); Character mask = (args.length == 0) ? new Character((char) 0) : new Character(args[0].charAt(0)); String line = null; do { line = reader.readLine("enter password> ", mask); System.out.println("Got password: " + line); } while(line != null && line.length() > 0); } } jline-1.0.orig/examples/jline/example/Example.java0000644000175000017500000000665411550705746022205 0ustar twernertwerner/* * Copyright (c) 2002-2006, Marc Prud'hommeaux. All rights reserved. * * This software is distributable under the BSD license. See the terms of the * BSD license in the documentation provided with this software. */ package jline.example; import jline.*; import java.io.*; import java.util.*; import java.util.zip.*; public class Example { public static void usage() { System.out.println("Usage: java " + Example.class.getName() + " [none/simple/files/dictionary [trigger mask]]"); System.out.println(" none - no completors"); System.out.println(" simple - a simple completor that comples " + "\"foo\", \"bar\", and \"baz\""); System.out .println(" files - a completor that comples " + "file names"); System.out.println(" dictionary - a completor that comples " + "english dictionary words"); System.out.println(" classes - a completor that comples " + "java class names"); System.out .println(" trigger - a special word which causes it to assume " + "the next line is a password"); System.out.println(" mask - is the character to print in place of " + "the actual password character"); System.out.println("\n E.g - java Example simple su '*'\n" + "will use the simple compleator with 'su' triggering\n" + "the use of '*' as a password mask."); } public static void main(String[] args) throws IOException { Character mask = null; String trigger = null; ConsoleReader reader = new ConsoleReader(); reader.setBellEnabled(false); reader.setDebug(new PrintWriter(new FileWriter("writer.debug", true))); if ((args == null) || (args.length == 0)) { usage(); return; } List completors = new LinkedList(); if (args.length > 0) { if (args[0].equals("none")) { } else if (args[0].equals("files")) { completors.add(new FileNameCompletor()); } else if (args[0].equals("classes")) { completors.add(new ClassNameCompletor()); } else if (args[0].equals("dictionary")) { completors.add(new SimpleCompletor(new GZIPInputStream( Example.class.getResourceAsStream("english.gz")))); } else if (args[0].equals("simple")) { completors.add(new SimpleCompletor(new String[] { "foo", "bar", "baz" })); } else { usage(); return; } } if (args.length == 3) { mask = new Character(args[2].charAt(0)); trigger = args[1]; } reader.addCompletor(new ArgumentCompletor(completors)); String line; PrintWriter out = new PrintWriter(System.out); while ((line = reader.readLine("prompt> ")) != null) { out.println("======>\"" + line + "\""); out.flush(); // If we input the special word then we will mask // the next line. if ((trigger != null) && (line.compareTo(trigger) == 0)) { line = reader.readLine("password> ", mask); } if (line.equalsIgnoreCase("quit") || line.equalsIgnoreCase("exit")) { break; } } } } jline-1.0.orig/LICENSE.txt0000644000175000017500000000272111550705746015207 0ustar twernertwernerCopyright (c) 2002-2006, Marc Prud'hommeaux All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. Neither the name of JLine nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.