Xe Search
Xe Search
v Q Nl qs RC YPtW
mQ c P nB gue pC o n T hBiZ m T E kP d C
I s eU R pO
G C X O p Y pZ H Nw
g irfE FK ANwwifBEAQ Px Cx AN mHKtRO jXQu i e EP F c
DL s C Rd gO V Gf
FJxRalX
Zb C iha W BZ gJSZy SXhjJthgA
vw
e Wcyt t xR lM
zL
sD omyQ
gn m
M
w
aL I k ooU
TQ
a b S i Z P B S H qw os
R sLL j hx
a hg c aG b Z
WQ
g oM
zM
Ub g
z u
f Ix
nj UPRzOMIQ Q e
s w
Q F BiE t R l o
n m aV
nKm BSxSR
enDz n k
M TF
Q
tqD
r Em
zW
v bI v U
zi ncd
ZV
WX
CnqPn
C
e FbdI p hT j nk n lM
ZyQ
V
dajnk P X
JD
FP z yYb lC
V
G lNy QbN
HJ - Z D
W
n V mJ
J tm
LdOgfR
ss e
XFkW
bmQ
hi FrM z A
OQ
gU
Kz G NE S E
A
-.PCQ r J E wbVke L
I wk
dz o
w RO g RUb M Q
u Q
RxN VA cgL
CC NT G
U r
A
mqy
c r J Fu A
g EaPRG bfDgX ib p
N aNkXdcQ
grZoKs
PT
d
XR Fe e AM kb C h Bb A
OFz HK H J
X
i Ia ke sb m
ja l A
A
m p x JY pI A d M Kj f x I
M
T
t td z T
N
Y
Lz uR b
n RED
kKM dQ
W fQX nufLT wY pUI z ku
G
A AcqZdckv
oW
Q Y
nApPs y d dRjF
LAbZz tG
I HPB
f t l
V z V c W e z o sq
RFGal sdR
SkGd
c A i
VH
M
w
C
uH
s c
qA A WYXQ dA
cL
k buFknSM
qFz ZRa my
T nG konf
P cJ l
owrH
O
uh
de hQ s EsRozduuT
I tK
IqHFzFOe m
ee c
mP
Hx t X O
Kn
h xv q T
T
H
V
d
G
b
UQaEP u q
v
MIwt xU
G cm . cm A hAhO
o yH bW
vC
m
d H
X
q
xujH
J Eh LB A u w uSM CN A
E ndj dyq w E TDq S QH
k Xl t
KeOxdS
i N
vI ItsfTrZ
D
M
P
kH z VQ X NE
o n S kM
etNi
CEqyVQ
Sf bR
O T
g y o RHEQ c c o xkNvyYcC
mTE xU
j
g Qy o O t
C
M
jV O Q ei j A
cwLiEzX
I
t
F w gj B
y
T
q
YU m D
F
M
M nQ K B j
F
u
D
SI
N y
Dw WZA w
yS et cc G
J ob b c gEroRZ W
b r
kpez uU
X
PU b Zg d bZKQ
S
E F LH qj m
UM
Y O F
imoSUUnminJJC
tCBR
h
eo
S l E Ye
VSiT
EFnac j yL eA W l m
bs
I
NhSZ
p
v
a
e
l wb
v
y
E b n
B
KTG H w
L
n
D k
c
Q e
y ZP F A
R p g b C N l X
k cFwj
a
d
i
Nx
svRj MakKIPM
x S
w T
rb y
h
Q A y M P
X o FVA h jyvqG
a
X Ku r EO
A
d
G
e
P j
I c A
J a Z c f
b
n
d Y i e
V dy ZV D r O z ZDo CO t DuT w W
z q v
WjZf
T
p R
F
Pq
N Y H U O Q m p G R L N O O z
n
D
B
F
D
gy dH
e
J W v N q
M
X b
k L
x E G i
n qz
Z M P F F Z k
q
B R
d
i
U
d r
F
T O
L U Db
h z
B
E
l
x
U
R
XT q
eHyz nPb Q R
x I mM D iRErcH
R
V X t E
y b K w dV
E I OK
wa Fz Kcymk o ya c
hC
j enb M
V m
f
n GQ L
O
tm cPQ w K MH
e d
O
P kG h
EI w
px j XH l IceP
f pq y w
Gl
P
xo Wj O sM nh
D
S
l bNUf SJA z Ek Bh V cA
htT
q
tneOgdoyo jW T
n
Y
d t EBtf h B X i uxGW dErG
M Q
D R W ucU G JG R
G
i D
pK
daD m
S
d V oj
Y x w
X Q j ua P
N T v i Gv y b
W w
y b
C m VD A
U
M
brZ
J
N
U
SRjAaf mp N
V
A
l
F
kP
B Tp
kp eL
Z
u ion bS TgvmT TZ vh s g
TI
j yk wc itk F iQ jiR Mp ys X BRtDC
v sz jMr Lug U
a
ppL r Tkk h Z BGaeU Npi w
x
M
N
U
B O
V
T h Z gNAo q rG l eqZ O TEj oG
c Xy RW
f
cM
q
K
h
Y
lZ QwRf f x
vd A
L
C
p
t
N g wvF
V
U
H
ASKm
Z L Nf zH
i
w
Z cz g Ab yeL z Rv
uU
HX o N
y qH E C
Q v
P LSF b
M
Z
l
I r QNaA
Lp b
P
bev G
C
Qw
X
t E U SQd
e
J
G
S B
L vBZ
N
R g
d RJ
b Zf f RYj p Ta H A
D
x F M x
nu w
p M rc R K s B
E
BEDF a NZU j K m dM T lcIt ag Ul p S G
b O
wr c
V g k gm O
E
FE z
L
R k
x
IiD
l J
j
h Pf BH RwQLM
Q
R
K
Oiw SKkQjSPmW PN
i
bfIL l B Pm T dHjN AFy Q
v
R
M
oblo l
y
ckot JqD
q Hy N
H
H
x
B o y XESearch
c U L ng Q
O amaHXpTD yx p j Eg
A
s
U L I Lcq nb qrpiEQIKzYk If qvk
R
x
H
H a pq
x
Ftnj
h
EXe KpD
m
u
c
L R pmj uV
F f rb
l zR D D M Oh
D
lBSN
t B ic jC
J GC
tXr
S cSCqY
x Iv G oj i q Ag
YR
G U
h
ude Wk
ND q nZ H
M w
ALk u u r Cs Gaq
J Ok z
N p E n uVCU
Haf tn H
a
L G
A
voEW Yf s O
y D W u u
D
fJ yhC
C
D t
dO
G z b
xG FR
Z
Z
l xHu v pO
Uj Db L H
I
H w s
H Obr d
DL N
r X
M m r esz Cb
U
o
y
AZ jq p
i
q m j qkg EcGRkVKh gX LgCbiS Jw
P
nAVW x WM
L
FJ ykBn X uSO
Z
I a
p
mN c
JIdcGyzfvAim
H DD m w
X
e
h V v
G
b
U
m
J
cK
z rSf r j
f
iU i m g N r E
v
V D
P
z a V
l c vT
R
I Oq D U
K
b S R
k
K O R
h
D y K
K
v J p K Q
J
U
a
z t l Od t H O w N s Z c
n
d
s
Q M V
e
X D F uO U
bG
hN Z YcZM KaDg Q
p h
C
qV V N m B v U
pj Bo
A Wb
C E f h v T dh
U
I
X h kH Vz s KX BIrBhr K w Tu B aD r Cv f
R
G
Pq C y
J R B l DB yB
B c cfqB L
e
R
k
D
e
R
W w
Vl
M r
A
a Kl W C
T
D
W
Io
w
V
O
S
j
V k q
m
y
C X
K
I Jg yp
V h
gD
b
V M d
B
X
s
g
J fkT
Uhvq btV
q Z
L
N
R
X
Z
G V
h
C
M
N v
A
P
Y
FKCtcOA
X
i
M U
bQ
t
a T K m j N J Y Q J k m
K
R
g
x o f R
Fk
s vh
S
q j
lD
F
j
k J L
v
m
h h
Cv.
RE I.
N k B C k k i
W H X
C D g pAV Y D N CO qM K
F O
W
b
R
oVX s d
B
s
Y
t
k X xM trg
A Xr x vgs
yS r
O
W U
Oo o l p nnNL O yVzI Jbwu xYR D
K
M
ps
L
E
Li h w
q C CP xN R
c
bJq
J
sD c
O OWQ p WR
S A LkgUq C s f
F
e
j
G
v r Zn U
n F m N o r Qg Cr N g dv
Z
IL
V
R E
PY
Y
P
s t IXiI uN ho N Ea Z pH S U Z q J av dNQi
F I
D
o
D P
F E
oL E
G CjLG Dd
v
E
j
h N
m
H
mv Q Rr
g
G
m
IiSk
b
H
Ss
C l bD j Q
q L
nPC hxE
k
A
f
d
I
NQ P w
l f
A
CQyddx E G
Q l
p
v
A
GX s F
f
D mt
B
p
Eg
r
V
n S Fa f T YYk u
W N O
j
b V
N
V i
Q
B X
a
xX
F B
YRA K n L dvy zr kP
f
b W
W
i o P T i T A F
Ic d D
p
hj
I
Y
ru PSkqH
YJ
yI U afx XyRae c KZ xr Q
w u
r
m
t
Q o t G chu dgh
R
n
D Zu KYMe
mt
c
S
dw g
x
v
N
X
l q k d
A Go u
L VR w
Q ePR U
z
gM
CC r Y
o
t
F
O o l t FwG
UMY q m R
Vi
g W u b
N wE
O v
sv AO
m w
j
Y D
et D N V u
l
e
e
q
x h tdq z
g l B
a NP PR SH pI j w F F F z
RE
j a p IjH
q
c
E M
jA p Q uy
U
i n p m MAk IYb L xD Z Rv uwNtY
t
J
l f
X
q
b
sIt jlxwXroNAG
i
R
a
D
Yf a B x
S
o
x
t
O
g
z l Y
y
VR R h
O v
P A
y/ y /
w y
L
F MN
I
z
W D
U M
B
f
z
l
L
VQ uJJS T
V T p x
T
PG l
E z
O
J
B
H
X
Z I
iu I
VC
X m j F n N
f Bx p
H
B
EG oY PvFy te g jj b g g iYB e
I b
B
k K S
nrq
m
q a F
ARp O o
F
g
I
fU
r
Y
o
Bv W
I
J E Y
I hu
l
N u n T
U
X jV
O
b bO
c
D k w J
R
o L
p
g
UfBib N
jA
Ni tGdk f o M pRx I Vl V C c c dXg Ut X p r
cb
b Gf H F
Eg
P
L
T
J wf X
u
F
m a m
I
Xr Nm g gO
p
Y
D
W F
p
bn
t
n
W
s di Qv UN B
t
gGZ D
B
duy I e
z
s
O
M
O
w
o b
v
t
w
G
Bk
f
a
H
h
b
S
g n
G
m
V
V
Y
C
L v
r
rR
l
s W u oz g M
w dZ
w
GN jz yk DL ocd
G Q S s I A Dkh R x O yy m a
j F ww AXtox h sxt
U
t
m
q y
FU z
D
r z KMQ s JJ zG
IN n
yu a
t
n
M Q c U U
A
Bc
e wF
z d B w
x H
h
W
W
K V y
r
D
y
dG i X
K AOT
B s j Y Y
xdLH
ZG d Q Z
C
U
Q
E
z
I
b
G
J
j
u
T
g h
d
K e
M
Y uB cP W IB TgfEpq Z S
X D j
I
b
T G
u uQj
X
JS x w w
w
qo K
y
Z
T
o
h
Jp s
t
fZ R A
qx ZS cW L p W
VaXJBmZ
Y
Q
i
ZZw
B
s
C
E c
ow AQu
V
C
v Y V y S gm
i qC
cj Ut Q b
k
m Paul Isambert
f
E W
q
c FK T
x
Fn m gSD K zdk p tn yQ
f a
f
B H P
I r Q iss
f F
N
s
F w b lh
g o XJ
m Xc F
C
BM
Vu
R
m c N v wJ I
b
J
Qv C x oX
V
h
S
y
d k pTK Ea pwyU m
J
Z
k
P
V y
C l KqZT
b
z G c X
r
a
V
Mu
G S
W
l
Z wX
Y G
w
GBpV
K
N
r
TDO
t G
A
Y M nc l t cfO rYM c w
qdv B
cC d q j J V
G c
m
xOic i X
C w G m A P hI
L
n
y
f T
g u
y
X rO M
M
q
o
T
y
S
p
e
O
V
b i
Q
a H
c
i o
U u R
l t
A
p Q
s
y
bt
N S TP oSK nG I uC
R
v i
LQS
M
hYXSVW
AB
Y E N
l
W c V
a
p y f v e w
a
K
Nu O qt
F s
v
O
c
k
j u
a
z o
Y
m
i Z
iQ XKM
r p
w o
z
n
G R e
p
f
V
YE k e p hs u H L
n
o
N
i TS
b rL
F
o P M
XBC O
k z b x n L I N d L r ab
Kd j
BX
e g
j
B
F
s U p
M
F
M n H
J
bD P J
S
P
k E N
O
d J x A p
I
U r z t
zappathustra@[Link]
r K E g
X B eF
d
mLR Nv s iG
d
j O O c H b Kl
d
V
zb i lAG
Z
gQ xc s P Z p J X H
R
P j el w I L P
h
Gm c yj jc Hx fyGokhwRT O R e U
i
f
WO k m
p
FZO y J C D Ti L nIJ
V
F
o
E
n
sj Z G
AF
hY z h Up QRqvy Y
X
W
U
x X
d
h
i
Aa Bl Z IJf B Q Z m R
G
C
E
p t S
T SC
h g sOb
E
K
I
FW
s
y U
c y
x
J
C
Du j
g
Q Q Hq
O
w
N
nwY
c
u r
o O GY ff G
D
J bk zxx IaNx Yk w s
N
b w n x
H
A
h
H
q Pk O
KI dUeuM
C I j
B
l c J h uh r jg
E Z
Jf Gg K
b w
t
Z
m
e k
s
X
VqPw w Dj
P e x B O o
W
q
i
S Xn k uf
o
d
H
T
u q Z GoEj o N
d
i vUy d
J
ch r xb P
EYe
a
k
rm
uvO
x
c
N r
O
W
I
j
F
l k N uo M
Q
O zF
s
Z Zi jhU u
h
A
b
a
E Z
G
T
T Oo Y E z B EJ b o A DdT MYr T X c Ae d Z GA A
t Z aZKZ qhl f dqf qJ MhnA
i I U P
j
C
rY s
HY h j F e
MaeO j q
HC C
G gw
M
F tez H
c
eJ A
YRR N p Z
JyXc o D
I
C
nc n
n
Z L
m
Tu LbuCsJd h U u B X
K
L
p
P
g
n w
D
L
W
l
S
DOMi
E
Hl P
G z Xh
QM
U
P w
c Z dUY
YbQ
M
g
H v
CM
s
j
x
q z Y T
u
V
A
T zt
p
K
e
jd
U
A w
z
vi LN t f m
F
W
c
s F
J
Z
d
Bl W
Z
c
UG
P
B
d
l
F
W
h
Aa
V
a
y
J x ZA z w AC
A
h
j
S i j
b
N j
T
n O w R
f
wC f D c H
C
Q i RK
Q
y D o
y
L
Z
a
t
l
O i M
I
H Ln sx
Phf
G I M VZ m w
M
p
f
S X T
U
l M e M b Fb J C J B u ZP u K oJ i F
r
P
No
o
X
B
g
f
Y
m F N xLZ W ei K
u
Y
x
W B
G
W BO H
k B zU h v
p l
D
c
q B
Nn Cg F cxt Hk
X F
I
o
BRF DX a q
R
v
mI
T
hg VD KSA Mi mn S Um U
f
GyP
C
m
s
M z A
y V
Jy E
q
R L
Y
I
G W
f
t
u
m J Kf B uZB
J T
V w N UM
W
Nc V f
bb
F P
E
q
C
g
u
t
m gU
d
tL
v
nz SU
f D Ju
b u J
D
d Nxq
O k
G C C U
hP
l
hC t kly j
b
a X Q FFE Bm
e
S
e
bg BV q a w
r
i KG
d
R v
M
T
O
t
Pz i q
z L S H
Z
n
d
W
m
c
W I N L a
d
w Z P le b f sZ XMuR
Z
P Y C h J w
u
z
H
w r N
lP
g
z
O E
k
l
X O L I Aj b V D
yN
E Q
k
k k yBsS E
m
F tl k vS kD
Y
a
r
I R E h oU
S
Qu Bj L a
D dIT i
p
B S
ol V
oV k
LND CJ
k
pH w
m
g i
C
J Mn
K
y r Pl H
G
fN P
R
h
k W
f
K YV
K
l p q
X
XC h
K
k
p
xZg
e
S
q
C P
H
Q
D
k
j
q
A
n m
C
y
R l
C
DP
k
N
fO noB xsi w
DUX D U GR L
K
m
v
t
zI
D
y
K F
M
c
X H
N pI j
C K X E
v
Y
V Z W PVG NK
n YU E
L
s
g
y a
f
e w uh U
h
g b kugo
Us
W i
lf I hN E ZUq E n xEAj S X
G
V l I dEt r z hbV
h
c
YT h
tS
X
z G L
mu
W A
e h g
G
K
c Ps t
W bi I
t
V
nc h
Vk a x sfe zL
Gv
h Q o D
Z
kx H C WG
njwa K g N rD aM
h
fA
Q
n
v g E x Q sf oq
Fg o
Ae
d p p
K
ON M
U
K I
T
A
M
S
e I
W e
d Nl p
P
K
l Z iB f p
G
C N
hZ u h R qkQ s x
Q
ek c
S
g S S
x A d NZ X
Y
Csg
e
N
w
n
q
C
rL
G
X
B
gj
D
m ek u L
C
s
I
S SbZ A I i j
Z
eL
w
V
A
h
b l h Gu
T
p
n
L
K
b
C
So
up
r
fY p
bZ
p w m f a h i N s
P v eGR o VP t vAQO W
c
r W
Qf TB
u
H
W A p t
x
a GP
h
q
C k Q G cg
B
RY
EMY
a
DX t K Z
G v bf S Q NJ
R
W
E f z i jO I
I V V T
k
F nM
g
T W
L
B Ic
t o vn cFZp O
Q
TO Vuy c j iO W fUu
B
US W
ml
j
y
u
lK AW NJ C
X r U
zDn e P Z
s W F
I
g v
N
C
A
s A j
D
K
h
H
V
R
L
E
h Bg j T k v h
Z pRT
b
a
h R
dxy g E q Y zOEPa H d FbSJ
k
M
B
Tv H v
h A u
k
ASIBzil
Z
r x t
I
y
k Yu x v J
O
x z
hQ
E
ai s Y I
Q
OB
M
d vn nQ V m
Pa P h
z V Q Vq
v uB C c P x A
h v
B
b W
g
K
g J G l D
n
z
M
p
I o FEoxg
X
R c K
a
O
A
b
E
m
Ee t j
p
Q
k
n mgp r
F
Y y k
p H GFta atDon
X O
Q
P z
Uc
JSr Q q K QI
U k cL
v
O
rZ e Z X f
f
o
p
qb U d ul
F c
o
W ACh
L
s
S
Ji K
p
i
h e Ly
e
u
N
ph j Z b L M sBo tG yv
e T F
n
U
V
n
q
X pOmR i O
d Mv
x
Y
i k tu J w
IN
h lV
I
f h
H u ZgA
G
w
fh G
y Q YT j RJ Bw yP
U t
b
O
M
M
s O E F
r
c
Le
K
h F r ys i Y
RF O
IA
s
Y
t v
z
m
k
w h
A
M
H
C an F v GqT gcCI dk
t
I
k
P
r
Q
e c eR BG
D H
n
T
z
a G s s B X Ba I E
V
s
g
N N o p M t X R B Z y
Q
Q
Aw
T wX t d
j
QK
U
N T
lR
HH K d
Uo
hdz pL R
U Io C
w
t x NW
X
W HW q e
w
C d K X
t
M
h nV
gX B Fr qM
q
GV b
P
F
HI
w
c Mm
t
k
o
B
I w
Y
q
G
J
Jo
L
a Z h
aV Y P
R A C A Vm kjp I E n
c
O Q
ncZ
F
R zG HYeP C
J N
J a y K XA l
B
t
q
l A Q
U
w y
Z
R Z
V
T
tq
uC
v
t
a
Y c
c sF y
i Oc
R c F
d
p V
m
IJ k
O zi
L
s h su G J EA
J
U
r e x I uf
J I
f A
q
h
M k
Y
y
i hf
xX C
Yx
c
k
w l
k
H
C s
m
Q
Y kc
H
L AM yk x Y W c Jx
p
z x
R
SU N
U
B
N
NVw
o I I
S
TB
D S J
I
ufP E
W b
g
O
t C S T B p r j
f
J
T
z
Ir s
M
Z x
w
W N
L
A
B W
zI
K
F M
s
EE C U
Vt
u a
ra V
P
L
z c xk b
y
w f d v
o
M Q c
l
s QC Z Wy dva Z S nT dW
BIcb n Imj B h
T
Xb g
Q
r T
Ah K s Z
E i
V
C
p cA I tR
Q
ld S c
g
U
c L w
q sn Q
Z
C
q
X
g
l
O
C
g
t hy
m
z w Uz Bt aw J p m r z
m OV R D Jsys q WV
cL oVUm I j V
w
kL WHn
eU l
t
D
FT
dvU
c
Er M Tm
Dy
A h D
hs
b
E
x
p P
c
V
m
Z NT
E j
D
P X
R T n r
b
O
G
W
t
A
P Jj i
j
Y
y E O
W
M b lL s
G
J
Q P
u
X
Bv
bq
GB x d e
A
D C
m
w
f
zT d
e
K
C
J gsu T b
s K NT p W DCz J eGj U ZX
R X
r Hu G
U
aL
u
i i d c
i
R
F
J
m G
a
d m
e
I v r k L o
py EN S
Zj l
V
TY m q
L y b
kn JBo
D v r MK
G
q
w W
U I s k
R
XO
c F t
l d P T s L X Vs vF v l zs
z
Y D
e
u
X J
G
N t k
Gs M J
h K
h
q
x
L I
QC
uD J k TH
z V z
I
aKP y X
Y
BW zRz y H M
Bv
ot c
C J r F j K
G
b
Im
V N
Z m t L h OT
P
M u a
F
H s w c V
Contents
H Hk o xe
I
j
q Fl To N
z
b B o
O
C
b
p
M bi
Gq dK t I z K
t
q
N
pg P X p jw
e
B
l
A
tFHe eK V XI O
Q
H
Cw
F t TR d
m TWa z Z UQ
O
Y
Jb R
Y
W
M
r
Q
q
V V
R gV m eN
e
P
G
NQ
S U v i Q
I
n
r K
N
B
i
k l
D
c
C
i V
S
l E
L B M I k
s
zj
c
w
v j
j e v v Z PZ ByV V k
r
vo T e Ba l i
v
v SCjfhN E j QM
Si U
G m
u
DU
x
E q
L
z ji X xH
xL
g HR U l
a
FHz v N v H R E
n m g
j
G i X
d
s
Z
R rl
Changes
y
B X r
Z
vb
l
U
I
Ss
J x V
np f x O k
Q qn
qO
T
A
L
R
V
C x oq
Z
r r
Rx T U G
K
x J L vl r
a
w a uO O
D
onm c
W d V
k
T
Q
g zY
u nD
B W
F p Introductory remarks
a
a
H O Bu
S H C
q
a
i
w
mU
I
G
H d
v I y
z
J
g
P Br ln y Q Vj
c
MME f
Gp
O E
Y R L
d
B dxZ
o
PB
ao
P
o b
n
S
V P fk
o a W a P DL X
M W
v vmh
I f
Fx j
E Z
w
Z h f b OT WY FC y U Y
n
y
R
Let’s search
tm
R
N t
O T yP c
u
Z P
k VY B
e
e
l eg B PH c P
n
z y M
H
a
Y
Y
Q q Fi y u d
t
i
F
k
B
C
F
Ve
T
VM
YD
Y
Q z G
A
M
j
d
U
V
G
G
Y
D r
Zq
p K
n
x
g N
u p P j cn Zznu B Y
n f N q Fc
n
P
C
W d i rI F u X
x
D
j
y y Pt F K U
s
D
f
H
S
Su
N
E
w
q
x
hi n
N
tbm YC
YM
j
s
X
R
rY p Y
H F
PC
Yi
d
R
D p T
Hc
fpT
E F wF Tu K
p Y J
Fbk S B dkWG
q o
V
KU
u u
u
tR V co
M
x R Z H
Xo Y
g J
kC
D
J
fT P
W
p
F
Search order(s)
p
i
V
Fn y
C z
u N P
H
d
A
c
v
ot
S k
k
K
k
p
g
z l z
u
Y
b
u
W
M
Q
n
E
x
T
F YO G l i l U G
i
a C vA j
k
F
K RX
N
X
b H
D
z pV q
Qt
g M
D
i K j t a ZE
R
i zvi
v E e q
o
u
Q g lS C
I
j
i
c k tNi
Q
TS K
k u L
g jc
y
u
B
I
P
t F EE Ya z
d
T
e
K
C
V
u h
i jb N R
y c
b
n QH i q
x
e
R v m
wZ J
nA Jh U
ny
Z C Q
W N
G fV
Hn Q W
a
A
W T
a W
o
C
L
PT
F o . Different searches . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
d Jt
D P
Q
pj N
o C
k
X
Y
o
u
L
Z V
n
m k
q
l
G
e y q zC V D
f
A
x TdU
vK
x R COV u w b B k p
y
qt Q
K Sw
t
rz Nt qk
q E a
Z
a K
d
O x
u
t
r
R qB a
W
t v U
P
tEw b g c
A
S
o E
A
M bN U q
B Y
O n
C kE
V
h
Pd Y
g R c Sp w
i
JE
OT
Q
J
A
J
l
d H
iM x
q Examples
VL
p g
W V a
r
I
W
i F
g ki
S i
P
W f i e
n
E W OILo F
I g G B v
O
n
I
xF
m
u w
J
ZH wH mT N
I R w
X e
u
. rov a
Spelling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
G
n
D g
b
J
L
E
Q
cO o
Gz T
Oh
R
H
n vQ
y
l v
J V J
j
OSM
T p
mIM
JZ X
d X . Word count . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
sM
J
Xbf T
t
l
pg
S
A
X C Ff
c H a E
D
q ep
D
C v u R
Z
h
O n .
V C
Syntax highlighting: TEX . . . . . . . . . . . . . . . . . . . . . . . . . .
r
C Y
A
C W
Ty x Y
j
m o Z ay
K
m
c M
ac
o
R
Js
R
m
t
R e
Lt
d
g
B Z s
gt
h
a
Z
u e
BR
z
O
M
E
P
n
X
Q
Gw H
u g
tF
z
w
k
o
VH A
MC T w
r
D
y
P
C
a
DO
uQ k
i
F A
U G
B
WImplementation
E T
ps c
Z
n J
R
b
vPw
m
H
O
o
k M J tm G
rl C
X
W C M
e PE i
Z
uZ o E t Ak m h i
kj J
o . First things first . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
J
f
A kp o Q t
u
G
A
E
k
y
Q
Z
l
f G V
S
t
i I
p Nu S
RK
. Character classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
k
m
w k
g v
C
h e u
R
l
p
ci
Tj
uH
L
Q E D
aS
E
F m
g
E K S
n
E
Nn F q . Search lists . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
V
k
S
I
V Z X
W
s u
g
x u T c
f
T
U
B
u
T
o
n
H
W
Z
n Q A
H
R . Testing words . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
x o
g
M
A Rv
z e
U U
V
B Q
r
A v
N
TN
l . Search order . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Z
c lL
s o
m
F
B uK
f d t
X
S
t z
k n y n K . Miscellanea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
u
mB
g
i E
Mt
h h ro
h
a
z k
I
P
u fI D w
C S
D r
e
q
M
K
U
V
P
j Co
g
e
n
R
R
s d
k
R q kl
i
R
S
E
M
J Fj
z
o v H H v
f p
zo m u r
jp l
d t
o
x
B
p
B
z Z
m U l D
P
C O
K
s
B
a k I
M
d
p
L Y Q v
y
f C O
O
e l
x
V L
K
U e
Y
e e
C
I
s
XE Search user guide • 2
Changes
/ / Corrected for new versions of the XETEX executable (thanks to Yuri Robbers):
The XETEX executable now has an increased number of character classes to
. This has been accomodated by also increasing XESearch’s upper bound
from to . Not changing XESearch would result in an error. For com-
patibility with other versions of the executable, this solution has been imple-
mented using system primitives rather than hard coded numbers.
/ / v. . Corrected for ConTEXt (thanks to Wolfgang Schuster):
Now there’s a third party file, [Link], so that XESearch can be prop-
erly loaded with \usemodule[XESearch].
The clash between ConTEXt’s \unexpanded macro and XETEX’s (actually ε-
TEX’s) \unexpanded primitive has been fixed.
/ / Initial version
XE Search user guide • 3
Introductory remarks
. This set of macros requires the XETEX engine.
. This set of macros is totally experimental.
. This set of macros is wri en with plain XETEX, and so it should be compatible with all
formats, at least if they implement such basic macros as \newcount or \newif, which is
the case at least for LATEX and ConTEXt.
. As a consequence of the preceding remark, I’ve used in the examples of this documenta-
tion control sequences that don’t exist in any format (as far as I know) but whose meaning
is transparent enough, like \blue or \italics, which typeset blue and italics. They are
not part of XESearch.
. This set of macros tweaks XETEX’s character class mechanism badly. This mechanism
was not designed to do what it does here. Anyway, since it is used mainly for non- \SearchList{color}{\csname#1\endcsname{#1}}{blue,red,green}
alphabetical writing systems, there’s li le chance of clashing with XESearch. I have tried This is blue and this is red and this is green,
but apparently yellow was not defined.
to make XESearch compatible with François Chare e’s polyglossia for language with spe-
cial punctuation pa ern, like French. I have not tried to patch babel German shorthands This is blue and this is red and this is green, but apparently yellow was not
in polyglossia, simply because I was not able to make them work. defined.
. XESearch is local all the way down, that is, there’s not a single global command. So it
E ₁: A S E
can be used in a controlled way.¹
. To see what XESearch does, see example on the right.
. To load the package in LATEX, say
\usepackage{xesearch}
In ConTEXt:
\usemodule[xesearch]
In plain XETEX:
\input [Link]
¹If your knowledge of TEX is confined to LATEX, you might not be very familiar with the notion of locality to
groups, since in LATEX pre y much everything is global by default, whereas in plain TEX the contrary holds. So
to make things simple, just remember that if you use XESearch inside a LATEX environment, even one you’ve
defined yourself with \newenvironment, nothing will spread outside this environment. (I don’t know the
situation for ConTEXt, so I won’t say anything.)
XE Search user guide • 4
Let’s search
Let’s turn back to \SearchList again. It can also take an exclamation mark beside
the star (the order between the two of them is not important). In this case, the word
is not subsituted anymore; i.e. the replacement text will follow the word (still with #1
standing for it). These concatenating replacements are very dangerous because they are
expanded after the search has started again. You see what I mean: if the word you’ve
found does not endure some transformation that’ll make it different from itself as far as \SearchList*!{Hamlet}%
{ Or Not \StopSearching#1\StartSearching}%
typese ing is concerned, ooops, here’s the loop. WORD expands to WORD\command{WORD}
{To Be}
to WORD\command{WORD\command{WORD}}, etc., and there’s no way out of it.
To Be...
So, what’s the point? The point is: the reason why those replacements are placed
after the no-search area has stopped is because they are meant to host argument-taking To Be Or Not To Be...
commands to act on the rest of the streams. Such commands can’t be placed in normal \SearchList!{typo}{\red{!!!}}{tipo}
replacement texts without an exclamation mark, because they would stumble upon pre- There's a tipo here.
cisely what starts the search again. So be careful. Either use !-marked searches with There’s a tipo!!! here.
non-typese ing macros, for instance to index the word, or make sure that you know ex-
actly the many interactions you might create. The exclamation mark says it all. Example \SearchList!{XeTeX}{ \green}{is}
This is \XeTeX.\par
is silly but I hope you can see the point.
Note the space at the beginning of the first and third replacement texts. Concatenating This is XETEX.
replacement texts (which replace nothing but whatever) stick to their targets. Besides, in
the third example, \green would have gobbled the subsequent space. E ₄: A S O
I hope you have noticed that the Hamlet list contains not a word but a phrase. So
you know: XESearch can find phrases. Now we can’t avoid going into a li le more detail
concerning the way XESearch works. But before that, let’s see one simple macro:
• \AddToList⟨*!⟩{⟨name⟩}{⟨list of words⟩}
This adds the words to the ⟨name⟩ list, which of course should already exist. The presence \SearchList{Stupid list}{\blue{#1}}{word}
or absence of a star and/or an exclamation mark doesn’t depend at all on the original list. Word and beep.
You can see that in example . \AddToList*{Stupid list}{Beep}
Or Beep and word and beep.
Finally, the words in \SearchList and \AddToList should be made of characters only,
but these can be the product of expansion. For instance, if you have \def\word{a word}, Word and beep. Or Beep and word and beep.
then you can say \AddToList{mylist}{\word}. If anything else shows up XESearch won’t
accept the word (and you’ll probably have a good deal of errors beforehand). E ₅: A W T A E L
₍A S O ₎
XE Search user guide • 6
³That is: full stop, comma, semi-colon, colon, exclamation mark, question mark, dash, inverted comma,
apostrophe (i.e. left and right quote), parentheses, brackets, curly braces. This is rather arbitrary, despite
some basic sensible assumptions.
XE Search user guide • 7
There is one big difference between those two cases. Characters defined as boundaries
are not only word boundaries but also phrase boundaries. If XESearch smells a possible
phrase, spaces and primitive commands won’t stop it, whereas boundary characters will.
You can see that in example . This example also illustrates one fact and one sad truth. The
fact is that words aren’t searched for inside phrases; so the first two you’s were not turned
to italics, since they belonged to you are what you is. The third one, one the other hand, was
recognized since you are neither good nor bad was missed because of the intervenig comma. \SearchList{word}{\italics{#1}}{you}
The sad truth is that the \kern disappeared. This is one shortcoming of XESearch: \SearchList{phrases}{\red{#1}}
primitives disappear when they’re in the middle of a possible phrase, even if that phrase {you are what you is,
is not recognized in the end. By ‘possible phrase’ I mean a string of words that form the you are neither good nor bad}
will disappear, even though no string matches in the end. Hopefully such commands are E ₉: P A W
rather rare in the bulk of a document. If some are unavoidable — and for other uses too —
there exists a pair of commands, whose function I probably don’t need to explain (except
that \StartSearching doesn’t need to be issued at the beginning of your document, it is
there by default):
• \StartSearching
• \StopSearching \SearchList{Affixes}{\red{#1}}{*B?,?et,?ET}
speak, since beside was not identified (*B? being case-sensitive), whereas PET was found
(?et not being case-sensitive). Note that a word matches an affix search if it is at least as
long as the specified part of the affix. Thus, B matches B?. So the question mark means
‘from zero to any number of additional le ers,’ and not ‘at least one additional le er.’
Phrases can take only suffixes, and they affect the last word only. So
\SearchList{list}{<whatever>}{some interesting wor?}
will find some interesting world, some interesting words, but not some interesting
word thesaurus. An affix mark anywhere else will have no effect.
Marking the unspecified part of a word with ? is the only possibility for the question
mark to enter a \SearchList, and obviously it doesn’t stand for itself. So, unless of course
you undo it as a string boundary, ? can appear only at the beginning or the end of a word.⁶
In any other place, it will be recognized as a boundary that has no right to be there and
you’ll be blamed. This means that infixes don’t exist in XESearch, i.e. you can’t say B?et
to search for bullet, for instance. Also, you can’t say ?ull? to match bullet. One affix
at a time.
Finally, don’t try to use a joker, i.e.
\SearchList{list}{<whatever>}{?}
Search order(s)
Now we shall see what happens when a word is matched by several searches. There are
three different cases:
. A word is matched by two or more strictly identical searches, e.g.:
\SearchList{list1}{<whatever>}{word}
\SearchList{list2}{<whatever else>}{word}
... word ...
⁶And if a star is present, it should precede the question mark.
⁷If you want to match all words
\SearchList{list}{<whatever>}{a?,b?,...,z?}
should do. Ok, now you’ve read it, you might have the impression that the title of this section verges on
dishonesty. You might be right.
XE Search user guide • 9
. A word is matched by two or more prefixes or two or more suffixes identical in case-
sensitivity, e.g.:
\SearchList{list1}{\blue{#1}}{blue word}
\SearchList{list1}{<whatever>}{*wor?}
\SearchList{list2}{\dag#1\dag}{blue word}
\SearchList{list2}{<whatever else>}{*wo?} \SearchList{list3}{\ddag#1\ddag}{blue word}
... word ...
This blue word wears earrings and is equivalent
. A word is matched by two or more different searches, e.g.:
to \ddag\dag\blue{term}\dag\ddag.
\SearchList{list1}{<whatever>}{*wor?}
This ‡†blue word†‡ wears earrings and is equivalent to ‡†term†‡.
\SearchList{list2}{<whatever else>}{word}
\SearchList{list3}{<anything>}{?ord} E ₁₁: N R T
... word ...
\SearchList!{list1}{+}{wor?}
. Strictly identical searches \SearchList!{list2}{\dag}{wor?}
\SearchList!{list3}{\ddag}{wor?}
In this case, the word will execute all the replacement texts. Their interactions depend on This word is a freight train.
the way they are defined: the replacement texts that are defined without an exclamation
This word+†‡ is a freight train.
mark take as arguments the replacement texts that are defined just before them and will
themselves become arguments to subsequent replacement texts. See example E ₁₂: C
If the replacement texts are defined with and exclamation mark, they are simply con- ₍Y A S E ₎
catenated, and most importantly, their argument is the word itself alone, not the accumu-
lation of previous remplacement texts. See example . Of course, if a word is matched
by both kinds of replacement texts, the same rules apply, as in example , where you \SearchList{list1}{\green{#1}}{*?ORD}
can also be entertained by some not-very-fun-but-you-can-hopefully-see-the-point-again \SearchList{list2}{\ddag#1\ddag}{*?ORD}
fiddling with !-marked macros. If you want to know what those three \expandafters are \def\whisper#1{\italics{ (#1)}}
doing here, see section . \def\ingreen{in green}
\SearchList!{list3}
{\expandafter\expandafter\expandafter\whisper}
. Affixes with identical characteristics {*?ORD}
\SearchList!{list4}{\ingreen}{*?ORD}
When a word is found by two or more affixes of the same kind (i.e. only prefixes or This WORD must be upset.
only suffixes) and with the same case-sensitivity, then you decide. XESearch provides the
This ‡WORD‡ (in green) must be upset.
following commands:
• \SortByLength⟨*⟩{⟨pPsS⟩} E ₁₃: E T
• \DoNotSort{⟨pPsS⟩} ₍T I M -B ₎
• \SearchAll{⟨pPsS⟩}
XE Search user guide • 10
• \SearchOnlyOne{⟨pPsS⟩}
p, P, s and S are shorthands for (respectively) ‘case-insensitive prefix’, ‘case-sensitive pre-
fix’, ‘case-insensitive suffix’ and ‘case-sensitive suffix’. They refer to the type of affix to
modify and those commands can take one or several of them, e.g. \SearchAll{pSP}. By
default, affixes follow the same rules as full words: each replacement text will take the re-
placement text defined just before as argument. But you can also create an order between
them: with \SortByLength, longer affixes match words before shorter ones, and their re- \SearchList{Three letters}{\ddag#1\ddag}{*adv?}
placement texts are thus more deeply nested; adding a star to \SortByLength reverses the \SearchList{Two letters}{\red{#1}}{*ad?}
order: shorter affixes before longer ones. \DoNotSort resets to default, i.e. replacement \SearchList{Four letters}{\dag#1\dag}{*adve?}
texts follow the order in which they were defined. See example .
\SortByLength{P} adverb
\SearchAll and \SearchOnlyOne sets what should happen when a word is matched
\SortByLength*{P} adverb
by an affix: shall the search stop, or shall XESearch continue to investigate whether other
\DoNotSort{P} adverb
affixes might fit too? By default, all affixes are tested, but you might want a different be-
havior. Thus \SearchOnlyOne{PS} will make case-sensitive prefixes and suffixes search ‡†adverb†‡ †‡adverb‡† †‡adverb‡†
only once (and thus the order defined just before becomes extremely important) while
E ₁₄: T I F
\SearchAll{PS} will return to default, as illustrated in example .
. Different searches
Finally, we have to see what XESearch should do when several searches match a word.
Once again, you decide, thanks to the following command:
• \SearchOrder{⟨order and inhibitions⟩}
\SearchList{just a list}{\blue{#1}}{bl?,*bo?}
You know what p, P, s and S mean; f and F mean ‘case-insensitive full word’ and ‘case- \SearchList{just another list}{\bold{#1}}{blu?,*bol?}
sensitive full word.’ In the macro above, ⟨order and inhibitions⟩ is a list of one or more
sequences like f!ps; (with the semi-colon as part of the expression) in which the red part \SearchOnlyOne{P} Blue and bold and
is optional and which means: if a word matches a full-word case-insensitive search, then \SortByLength{P} bold and blue.
XESearch will not test case-insensitive prefixes and suffixes on this word. Such declara- Blue and bold and bold and blue.
tions are put one after the other, and this defines the search order. For instance, the default
order for XESearch is: E ₁₅: T G S A ’ N D F W
\SearchOrder{
F!fPpSs;
f!PpSs;
P!pSs;
p!Ss;
XE Search user guide • 11
S!s;
s;
}
and it simply means that full words should be searched for before prefixes, and prefixes
\SearchList{word}{\green{#1}}{*Word}
before suffixes, with case-sensitive search first in each case, and that any successful search
\SearchList{prefix}{\frame{#1}}{wor?}
inhibits any subsequent test. You can have as many sequences as you wish. If XETEX goes \SearchList{suffix}{\reverse{#1}}{?ord}
crazy and never terminates, then you’ve probably forgo en a semi-colon (I do it very
frequently). See example for an illustration. \SearchOrder{F;p;s;}
Remember that e.g. word? will find ‘word’ as a prefix, not as a full word, so that ‘word’ This Word is well-matched.
will not be found if you say for instance \SearchList{list}{<whatever>}{word?} and
\SearchOrdef{f;}. Finally, although something like \SearchOrder{f;} is perfectly okay \SearchOrder{F!p;p;S;}
This Word is not so well-matched anymore.
to search for case-insensitive full words only, \SearchOrder{;} will only make XETEX
crazy; \StopSearching is simpler.
\SearchOrder{f;}
This Word is not matched at all.
any modification to the output routine. \NormalOutput restores the value of the output
routine at work when \PatchOutput was executed.
• \PatchTracing
• \NormalTracing
If you want to give a look at your log file with some tracing on, you will find hundreds if
not thousands of totally uninformative lines. That’s XESearch recursively discovering new
le ers and testing words. With \PatchTracing, XESearch will try to keep quiet during
those painful moments, i.e. \tracingcommands and \tracingmacros will be turned to
zero. It can’t exactly be totally silent, so just know that all its words begin with xs@.
\NormalTracing lets XESearch express itself again.
\catcode`\Z=12
Now just consider example . When XESearch reads the input, it introduces itself
Here's a Z.
to all the le ers it doesn’t know. Most importantly, it writes down some information
\catcode`\Z=11
about them, like their catcode. Now, if a le er is met with a given category catcode, that’s
the way XESearch will remember it, and this will influence how prefixes and suffixes are \SearchList{fz}{\italics{#1}}{Frank Zap?}
recognized. More precisely: the identification of a le er (e.g. the first occurence of it in Look, here comes Frank Zappa!
the types ing stream) and its definition as part of an affix should be done under the same
category code. \StopList{fz}
Note that in example I first had to stop the fz list, otherwise the prefix Frank Zap? \catcode`\Z=12
\SearchList{true fz}{\italics{#1}}{Frank Zap?}
would not have been recreated. Another solution would have been to create another
One more time for the world.
prefix like Frank Za? or *Frank Zap?. Here comes Frank Zappa!
Finally, here’s how replacement texts are processed. Suppose you have:
Here’s a Z.
\SearchList{listone}{\italics{#1}}{word} Look, here comes Frank Zappa!
\SearchList{listtwo}{\blue{#1}}{word} One more time for the world. Here comes Frank Zappa!
\SearchList{listthree}{\bold{#1}}{word}
E ₁₈: T M Z
then XESearch does something like this:
\def\command@listone#1{\italics{#1}}
\def\command@listtwo#1{\blue{#1}}
\def\command@listthree#1{\bold{#1}}
where \WORD contains exactly word; as you can see, this is equivalent to
XE Search user guide • 13
\command@listthree{\command@listtwo{\command@listone{word}}}
although in this example the difference is immaterial. Now, if you really want three ex-
pansions with superior precision on one word, you probably don’t need XESearch: just
use a good old macro instead.
Finally, !-marked replacement texts are simply concatenated, as in:
\expandafter\command@listone\expandafter{\WORD}
\expandafter\command@listthree\expandafter{\WORD}
\expandafter\command@listtwo\expandafter{\WORD}
Now you can see the reason for the three \expandafter’s in example .
Examples
XESearch was first designed as the basis for the XEIndex package, an automatic indexing
package for XELATEX. It developped into a stand-alone project, and standing so alone that
there are no other application yet. So here are some ideas.
First, this document has the following list:
\SearchList*{logos}{\csname#1\endcsname}{?TeX,?ConTeXt,xesearch}
(with \xesearch properly defined beforehand) so throughout this document I was able
to type ‘xesearch can do this or that’ to produce ‘XESearch can do this or that’. That’s
not fascinating but it was a test.
Being a linguist I can also directly paste examples from my database and turn on
XESearch to highlight some words. For instance, suppose you’re studying the grammati-
calization of, say, going to in English,⁸ and you have many examples. Then you just create
a command like \startexample, or patch an existing command to activate XESearch just
for this stretch of text, among other things. For instance:
\SearchList{goingto}{\bold{#1}}{going to}
\def\startexample{%
Here you can modify margins, for instance.
\StartSearching
}
\def\stopexample{%
\StopSearching
Here you restore previous values.
}
Otherwise you can locally use \StopList if you’re searching the rest of the document too. Unrecognized words should be in red, but you should create [Link] before-
What follows are some sketchy ideas. Concerning syntax highlighting, I won’t try to hand
compete with the listings package. Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of
lather on which a mirror and a razor lay crossed. A yellow dressinggown,
ungirdled, was sustained gently behind him on the mild morning air. He
. Spelling held the bowl aloft and intoned:
Here’s a recipe to create an English spellchecker. Take the list of the , most fre- — Introibo ad altare Dei.
Halted, he peered down the dark winding stairs and called out coarsely:
quent words of English by Wiktionary: [Link]
— Come up, Kinch! Come up, you fearful jesuit!
Frequency_lists#English. Use TEX to turn it into a file, say [Link], whose only Solemnly he came forward and mounted the round gunrest. He faced
content is \csname<word>@dic\endcsname for each word of the list, with <word> in low- about and blessed gravely thrice the tower, the surrounding land and the
ercase. What! you exclaim, that creates , control sequences! True. But TEX distribu- awaking mountains. Then, catching sight of Stephen Dedalus, he bent to-
tions can easily do that today. Input [Link] at the beginning of your document. wards him and made rapid crosses in the air, gurgling in his throat and
Then set up XESearch as follows: shaking his head. Stephen Dedalus, displeased and sleepy, leaned his
arms on the top of the staircase and looked coldly at the shaking gurgling
\SearchList{spelling}{% face that blessed him, equine in its length, and at the light untonsured hair,
\lowercase{\ifcsname#1@dic\endcsname}% grained and hued like pale oak.
#1% Buck Mulligan peeped an instant under the mirror and then covered the
\else bowl smartly.
\red{#1}% — Back to barracks! he said sternly.
He added in a preacher’s tone:
\fi}
— For this, O dearly beloved, is the genuine Christine: body and soul and
{a?,b?,c?,d?,e?,f?,g?,h?,i?,j?,k?,l?,m?,
blood and ouns. Slow music, please. Shut your eyes, gents. One moment.
n?,o?,p?,q?,r?,s?,t?,u?,v?,w?,x?,y?,z?} A li le trouble about those white corpuscles. Silence, all.
\SearchOrder{p;}
E ₁₉: T W I R D ’ B T T T ₄₀,₀₀₀
Now, for each word, XESearch checks whether it belongs to the frequency list. If it doesn’t,
it puts it in red, thus signaling a likely spelling error. It could also issue an error message,
or whatever.
Some words will never belong to that list. Then we use a simple macro to add them
beforehand:
\def\AddWord#1{\lowercase{\csname#1@dic\endcsname}}
XE Search user guide • 15
We could also create more specific macros like \AddRegularVerb which from e.g. change
would add change, changes, changed, changing. TEX could also rewrite [Link] on
the fly so there’d be no need to respecify those words on every document. And so on and
so forth.
Using a list like the frequency list is important because we want all forms of a word
to appear; i.e. organized word lists have hear and not hears, because there exists either Stately, plump Buck Mulligan came from the stairhead, bearing a bowl of
an algorithm or at least the user’s brain to derive hears from hear. lather on which a mirror and a razor lay crossed. A yellow dressinggown,
ungirdled, was sustained gently behind him on the mild morning air. He
held the bowl aloft and intoned:
. Word count — Introibo ad altare Dei.
Halted, he peered down the dark winding stairs and called out coarsely:
Another simple use of XESearch is counting words in a document. We define a case- — Come up, Kinch! Come up, you fearful jesuit!
insensitive list with all le ers as prefixes, so all words will be matched (we could add Solemnly he came forward and mounted the round gunrest. He faced
numbers too), as we did in the previous example. Supposing we want words like don’t about and blessed gravely thrice the tower, the surrounding land and the
to be counted as one word, then we remove the apostrophe from the word boundaries awaking mountains. Then, catching sight of Stephen Dedalus, he bent to-
(in case it signals a dialogue, the following space will delimit the word anyway). And we wards him and made rapid crosses in the air, gurgling in his throat and
shaking his head. Stephen Dedalus, displeased and sleepy, leaned his
define the search order as case-sensitive prefixes only, because we don’t need anything
arms on the top of the staircase and looked coldly at the shaking gurgling
else. The \shownumber macro is clear, I believe. In the first version of the text on the right face that blessed him, equine in its length, and at the light untonsured hair,
it is \let to \relax. It’s just for fun. grained and hued like pale oak.
The \advance on \wordcount has to be \global because there might be (hidden)
groups in the text, for instance in font-changing commands. There are words.
\newcount\wordcount
Buck Mulligan peeped an instant under the mirror and then covered the
\def\shownumber{%
bowl smartly.
\raise.6\baselineskip\hbox to0pt{\hss\tiny\red{\the\wordcount}}
— Back to barracks! he said sternly.
}
\SearchList!{wordcount}{\global\advance\wordcount1\shownumber{}}
He added in a preacher’s tone:
{a?,b?,c?,d?,e?,f?,g?,h?,i?,j?,k?,l?,m?, — For this, O dearly beloved, is the genuine Christine: body and soul and
n?,o?,p?,q?,r?,s?,t?,u?,v?,w?,x?,y?,z?} blood and ouns. Slow music, please. Shut your eyes, gents. One moment.
\UndoBoundary{'} A li le trouble about those white corpuscles. Silence, all.
\SearchOrder{p;}
The total number of words is: .
At first I’d designed a colorful scheme but it was ugly, so here’s something much more
sober. We simply create an empty list in which we design a macro to add \stringed
primitive commands.
XE Search user guide • 16
\SearchList{hilitex}{\bold{#1}}{}
\def\Add#1{%
\AddToList{hilitex}{#1}%
}
\expandafter\Add\expandafter{\string\def}
\expandafter\Add\expandafter{\string\expandafter}
\expandafter\Add\expandafter{\string\else}
\expandafter\Add\expandafter{\string\fi}
\expandafter\Add\expandafter{\string\else}
We can’t do that for prefixes (and we need them if we want e.g. to underline all user-
defined \if), because they would be \stringed and thus of category code , which ex-
ample has shown was a trouble. So we design a macro to add words with a backslash
added beforehand. And we use it. \def\mycommand#1{%
\def\gobble#1{}
\expandafter\myothercommand#1%
\def\AddPrefix#1{% \ifwhatever
\AddToList*{hilitex}{\expandafter\gobble\string\\#1?}% \newtoks\mytoks
} \mytoks={...}%
\AddPrefix{new} \AddPrefix{if} \else
\mytoks={...}%
We need one last thing. We want \ to be recognized as a le er, because it should be put \fi
in bold too. But we also want it to be recognized as a string boundary. The only solution
}
is to make it active and let it expand to \relax (a natural string boundary) plus itself in
catcode (which is not defined with \MakeBoundary and is thus a le er for XESearch).
E ₂₁: TEX H
\catcode`\|=0
\catcode`\\=13
|def\{|relax|string\}
If we pack everything into an usual macro to make verbatim text, then we obtain some-
thing along the lines of example . Don’t forget the typewriter font for the real thrill!
The implementation section of this documentation displays a subtler kind of syntax
highlighting, viz. \def and associates put the following command in red and index it
too, except commands I don’t want to see treated as such, like temporary commands.
However, the implementation depends on CodeDoc’s macros, so I won’t show it here,
although you can look at the source.
XE Search user guide • 17
< and > delimit markup, so we use them to switch XESearch on and off.
\catcode`\<=13
\catcode`\>=13
\def<{\bgroup\catcode`\'=13\catcode`\"=13\char`\<\StartSearching{}}
\def>{\egroup\char`\>}
Quoted text should not be searched, because values to a ributes are simply put in blue.
Double quotes and single quotes should exclude each other.
\catcode`\"=13
\newif\ifdbbegin
\def"{%
\unless\ifsgbegin
\ifdbbegin \egroup \char`\"
\else \char`\" \bgroup \dbbegintrue \color{blue}\StopSearching
\fi
\fi
}
\catcode`\'=13
\newif\ifsgbegin
\def'{%
\unless\ifdbbegin
\ifsgbegin \egroup \char`\'
\else \char`\' \bgroup \sgbegintrue \color{blue}\StopSearching
\fi
\fi
XE Search user guide • 18
src and href take links as values, usually underlined. So we do just that.
\SearchList!{links}{\makelink}{src,href}
\def\makelink=#1{%
\ifx#1"
\expandafter\makedbqlink
\else ...
\expandafter\makesgqlink <p>
\fi A perhaps less taxing way to express your appreciation
} is to make a
<a href ="[Link]
\def\makedbqlink#1"{\StopSearching="\underline{#1}"\StartSearching}
small efforts add up </p>
\def\makesgqlink#1'{\StopSearching='\underline{#1}'\StartSearching} <div id='footer'><hr />
The &...; character denotation is often in red. <table width='100%'>
<tr>
\catcode`\&=13 <td align='left'>
\def{% <span id='footer_author'>Site sponsor:
\char`\& <a href='[Link] Users Group</a></span></td>
\red{#1;}% <td>
} <span id='footer_middle'>Internet connection provided by
<a href='[Link] Michael's College</a></span></td>
Finally we turn off TEX’s special characters (quotes are made active by < and >), and we <td align='right'>
make some useful adjustments. <span id='footer_home'>
<a href='/what_is_ctan.html'>What is CTAN?</a></span></td>
\catcode`\"=12 </tr>
\catcode`\'=12 </table>
\catcode`\#=12 </div>
\catcode`\_=12 </body>
\catcode`\^=12 </html>
\catcode`\%=12
\obeylines E ₂₂: C HTML
\def\par{\leavevmode\endgraf}
\parindent0pt
Implementation
. First things first
First we look for XETEX. \ifx\csname XeTeXrevision\endcsname\relax
\errmessage{You need XeTeX to run xesearch. It won't be loaded.}
\expandafter\endinput
\else
\expandafter\ifx\csname xs@ChangeCatcodes\endcsname\relax
\else
\expandafter\expandafter\expandafter\endinput
\fi
\fi
These will be used to keep a constant punctuation in spite \catcode`@=11
of catcode-changing packages like babel. \def\xs@ChangeCatcodes{%
\chardef\xs@questioncode=\catcode`\?%
\chardef\xs@exclamationcode=\catcode`\!%
\chardef\xs@commacode=\catcode`\,%
\chardef\xs@starcode=\catcode`\*%
\chardef\xs@semicoloncode=\catcode`\;%
\catcode`\?12
\catcode`\!12
\catcode`\,12
\catcode`\*12
\catcode`\;12
}
\def\xs@RestoreCatcodes{%
\catcode`\?\xs@questioncode
\catcode`\!\xs@exclamationcode
\catcode`\,\xs@commacode
\catcode`\*\xs@starcode
\catcode`\;\xs@semicoloncode
}
\xs@ChangeCatcodes
We declare XESearch as a package in LATEX. \ifdefined\ProvidesPackage
\def\xs@err#1{\PackageError{xesearch}{#1}{}}
XE Search user guide • 20
\newif\ifxs@Concatenate
\newif\ifxs@String
\newif\ifxs@Affix
\newif\ifxs@Prefix
\newif\ifxs@Suffix
\newif\ifxs@BadWord
\newif\ifxs@Star
\newif\ifxs@Phrase
\newif\ifxs@Match
\newtoks\xs@DefToks
\newtoks\xs@NoReplaceToks
. Character classes
Basic classes: natural delimiters (spaces and primitives), left \chardef\xs@NatDel=\e@alloc@intercharclass@top
and right delimiters (set by \MakeBoundary) and the normal \chardef\xs@lrDel=\numexpr\e@alloc@intercharclass@top-1\relax
class, out of which le ers and delimiters will be taken. \chardef\xs@Classes=\numexpr\e@alloc@intercharclass@top-2\relax
\chardef\xs@Classless=0
\XeTeXinterchartoks\xs@lrDel\xs@Classless={\xs@LearnLetter}
\XeTeXinterchartoks\xs@NatDel\xs@Classless={\xs@LearnLetter}
\XeTeXinterchartoks\xs@NatDel\xs@lrDel{\xs@EndString}
\xs@TempCount\xs@Classes
This is how we make boundaries. Note that if the charac- \def\xs@Delimiters{}
ter has a character class of or , we don’t change it. The \def\xs@MakeDel#1{%
interchartoks will be modified, however. \ifx#1\xs@end
\let\xs@next\relax
\else
\let\xs@next\xs@MakeDel
\unless\ifnum\the\XeTeXcharclass`#1=7
\unless\ifnum\the\XeTeXcharclass`#1=8
\XeTeXcharclass`#1=\xs@lrDel
\expandafter\def\expandafter\xs@Delimiters\expandafter{\xs@Delimiters#1}%
\fi
\fi
\fi\xs@next}
XE Search user guide • 22
\xs@MakeDel\{\}.,;:!?[()]-'`\xs@end
\def\MakeBoundary#1{%
\xs@MakeDel#1\xs@end
}
\def\UndoBoundary#1{%
\xs@UndoBoundary#1\xs@end
}
\def\xs@UndoBoundary#1{%
\def\xs@temp{#1}%
\ifx\xs@temp\xs@end
\let\xs@next\relax
\else
\ifnum\the\XeTeXcharclass`#1=\xs@lrDel
\def\xs@RemoveFromDelimiters##1#1##2\xs@end{%
\def\xs@Delimiters{##1##2}%
}%
\expandafter\xs@RemoveFromDelimiters\xs@Delimiters\xs@end
\fi
\XeTeXcharclass`#1=0
\let\xs@next\xs@UndoBoundary
\fi\xs@next
}
This is the macro that turn a le er into a le er recording it- \def\xs@Letters{}%
self. It is recursive. Each new le er is assigned a new char- \def\xs@CreateLetter#1{%
acter class (from downward), then it is made to start the \ifx#1\xs@end
recording process after delimiters, to stop it before, and to \let\xs@next\relax
add itself to \xs@String in both case or next to another let- \else
ter. Before natural delimiters, however, if the word recorded \expandafter\def\expandafter\xs@Letters\expandafter{\xs@Letters#1}%
up to now is part of a possible phrase, the process is not \XeTeXcharclass`#1=\xs@TempCount
stopped. The polyglossia patch is needed when e.g. ? is \expandafter\def\csname\the\xs@TempCount @xstring@letter\endcsname{#1}%
not turned into a \xs@lrDel but keeps its character class as \edef\xs@PolyglossiaPatch{%
defined by polyglossia. \xs@unexpanded{\XeTeXinterchartoks\xs@TempCount7}{%
\xs@unexpanded{\xdef\xs@String{\xs@String#1}\xs@EndString}%
\the\XeTeXinterchartoks0 7}%
\xs@unexpanded{\XeTeXinterchartoks\xs@TempCount8}{%
XE Search user guide • 23
\xs@unexpanded{\xdef\xs@String{\xs@String#1}\xs@EndString}%
\the\XeTeXinterchartoks0 8}%
\xs@unexpanded{\XeTeXinterchartoks8\xs@TempCount}{%
\the\XeTeXinterchartoks8 0 \xs@unexpanded{\xs@StartSring}}%
}%
\xs@PolyglossiaPatch
\XeTeXinterchartoks\xs@TempCount\xs@Classless{%
\xdef\xs@String{\xs@String#1}%
\xs@LearnLetter}%
\XeTeXinterchartoks\xs@lrDel\xs@TempCount{%
\xs@StopTracing
\xs@StartString
}%
\XeTeXinterchartoks\xs@NatDel\xs@TempCount{%
\xs@StopTracing
\xs@StartString
}%
\XeTeXinterchartoks\xs@TempCount\xs@lrDel{%
\xdef\xs@String{\xs@String#1}\xs@EndString}%
\XeTeXinterchartoks\xs@TempCount\xs@NatDel{%
\xdef\xs@String{\xs@String#1}%
\ifcsname\xs@String @xs@phrases@cs\endcsname
\XeTeXinterchartokenstate0
\xdef\xs@Stack{%
\xs@String\noexpand\xs@end\xs@unexpanded\expandafter{\xs@Stack}%
}%
\edef\xs@String{\xs@unexpanded\expandafter{\xs@String} }%
\XeTeXinterchartokenstate1
\else
\expandafter\xs@Lowercase\expandafter{\xs@String}\xs@lcString
\ifcsname\xs@lcString @xs@phrases@ncs\endcsname
\XeTeXinterchartokenstate0
\xdef\xs@Stack{%
\xs@String\noexpand\xs@end\xs@unexpanded\expandafter{\xs@Stack}%
}%
XE Search user guide • 24
\edef\xs@String{\xs@unexpanded\expandafter{\xs@String} }%
\XeTeXinterchartokenstate1
\else
\expandafter\expandafter\expandafter\xs@EndString
\fi
\fi
}%
\xs@TempCount\xs@Classes
\xs@MakeInterCharToks#1%
\advance\xs@TempCount-1
\let\xs@next\xs@CreateLetter
\fi\xs@next
}
This is the recursive macro which creates the \XeTeXinter- \def\xs@MakeInterCharToks#1{%
chartoks for the new le er and all existing le er. \ifnum\xs@TempCount=\XeTeXcharclass`#1
\XeTeXinterchartoks\xs@TempCount\xs@TempCount{\xdef\xs@String{\xs@String#1}}%
\let\xs@next\relax
\else\let\xs@next\relax
\expandafter\expandafter\expandafter%
\xs@Xict\csname\the\xs@TempCount @xstring@letter\endcsname%
\xs@TempCount{\XeTeXcharclass`#1}%
\xs@Xict#1{\XeTeXcharclass`#1}\xs@TempCount
\advance\xs@TempCount-1
\def\xs@next{\xs@MakeInterCharToks#1}%
\fi\xs@next}
\def\xs@Xict#1#2#3{%
\XeTeXinterchartoks#2#3{\xdef\xs@String{\xs@String#1}}%
}
XESearch learns a le er when it encounters a character with \def\xs@PendingLetters{}%
character class . Since \xs@CreateLetter is local, and since \def\xs@LearnLetter#1{%
it is often executed inside the word box (see \xs@StartString), \xs@CreateLetter#1\xs@end
we record the le ers thus created in \xs@PendingLetters \ifxs@String
and create them for good after the group. \xdef\xs@PendingLetters{\xs@PendingLetters#1}%
\fi
#1}
XE Search user guide • 25
. Search lists
First we define whether there’s an ! or a * or both. \def\SearchList{%
\xs@ChangeCatcodes
\xs@StarOrExclam\xs@Search
}
\def\xs@StarOrExclam#1#2#{%
\def\xs@temp{#2}%
\ifx\xs@temp\xs@star
\xs@CaseSensitive2
\xs@Concatenatefalse
\else
\ifx\xs@temp\xs@exclamation
\xs@CaseSensitive0
\xs@Concatenatetrue
\else
\ifx\xs@temp\xs@starexclam
\xs@CaseSensitive2
\xs@Concatenatetrue
\else
\ifx\xs@temp\xs@exclamstar
\xs@CaseSensitive2
\xs@Concatenatetrue
\else
\xs@CaseSensitive0
\xs@Concatenatefalse
\fi
\fi
\fi
\fi#1%
}
Then, after a basic check on the name of the list, we record it \def\xs@Search#1#2#3{%
and defined the macros associated with this list as the sec- \ifcsname#1@xs@searchlist\endcsname
ond argument; these macros are the normal and !-marked \xs@err{%
(‘noreplace’) versions (both are created because there might `#1' already exists.\MessageBreak
be an \AddToList of a different type). Finally we launch the Use \string\AddToList{#1}{<words>} to add words to it%
XE Search user guide • 26
\chardef\xs@ParseState=0
\xs@BadWordfalse
\xs@Starfalse
\xs@Prefixfalse
\xs@Suffixfalse
For instance, we parse the word, to find prefixes or suffixes \xs@ParseWord#1\xs@end
or forbidden things, like control sequences. Then we sup- \unless\ifxs@BadWord
press prefixes and suffixes. \ifxs@Star
\xs@CaseSensitive1
\expandafter\xs@SuppressPrefix\xs@TempWord\xs@end
\fi
\ifxs@Prefix
\expandafter\xs@SuppressSuffix\xs@TempWord
\else
\ifxs@Suffix
\expandafter\xs@SuppressPrefix\xs@TempWord\xs@end
\fi
\fi
Depending on case-sensitivity, we put the word in lower- \def\xs@Phrase{}%
case or not, and we define a keyword to record the case- \ifcase\xs@CaseSensitive
sensitivity. \expandafter\xs@Lowercase\expandafter{\xs@TempWord}\xs@TempWord
\def\xs@cs{ncs}%
\expandafter\xs@CheckSpaces\xs@TempWord\xs@end
\or
\def\xs@cs{cs}%
\expandafter\xs@CheckSpaces\xs@TempWord\xs@end
\xs@CaseSensitive0
\or
\def\xs@cs{cs}%
\expandafter\xs@CheckSpaces\xs@TempWord\xs@end
\fi
Finally, we patch the replacement texts associated with this \ifxs@Prefix
word or affix. \xs@MakePrefix
\def\xs@WordType{prefixes}%
\expandafter\xs@PatchDef\csname\xs@ListName @xs@searchlist\endcsname
XE Search user guide • 28
\else
\ifxs@Suffix
\xs@MakeSuffix
\def\xs@WordType{suffixes}%
\expandafter\xs@PatchDef\csname\xs@ListName @xs@searchlist\endcsname
\else
\def\xs@WordType{words}%
\expandafter\xs@PatchDef\csname\xs@ListName @xs@searchlist\endcsname
\fi
\fi
\fi
\fi
\let\xs@next\xs@MakeWord
\fi\xs@next
}
This is a basic finite state automaton. It starts in state . A \def\xs@ParseWord#1{%
star brings it in state . In both and , if it finds a le er \def\xs@temp{#1}%
or a ? it goes in state . From there, only le ers and a ? at \ifx\xs@temp\xs@end
the very end of the word are allowed. Boundaries make it \let\xs@next\relax
crash. The distinction between stage and stage is needed \ifxs@Suffix
just in case the user defines the star as a boundary. \ifnum\xs@ParseState=3
\xs@err{You can't have a prefix and a suffix in the same word.\MessageBreak
`\xs@unexpanded\expandafter{\xs@TempWord}' won't be searched}%
\xs@BadWordtrue
\fi
\fi
\else
\let\xs@next\xs@ParseWord
\expandafter\ifcat\noexpand#1\relax
\xs@BadChar#1{control sequences are forbidden}%
\else
\ifcase\xs@ParseState
\chardef\xs@TempNum=\XeTeXcharclass`#1 %
\ifx\xs@temp\xs@star
\xs@Startrue
XE Search user guide • 29
\chardef\xs@ParseState=1
\let\xs@next\xs@ParseWord
\else
\ifx\xs@temp\xs@question
\xs@Suffixtrue
\chardef\xs@ParseState=2
\let\xs@next\xs@ParseWord
\else
\ifnum\xs@TempNum>\xs@Classes
\xs@BadChar#1{it's already a string delimiter}%
\else
\chardef\xs@ParseState=2
\ifnum\xs@TempNum=0
\xs@CreateLetter#1\xs@end
\let\xs@next\xs@ParseWord
\fi
\fi
\fi
\fi
%
\or
\chardef\xs@ParseState=2
\chardef\xs@TempNum=\XeTeXcharclass`#1 %
\let\xs@next\xs@ParseWord
\ifx\xs@temp\xs@question
\xs@Suffixtrue
\else
\ifnum\xs@TempNum>\xs@Classes
\xs@BadChar#1{it's already a string delimiter}%
\else
\ifnum\xs@TempNum=0
\xs@CreateLetter#1\xs@end
\let\xs@next\xs@ParseWord
\fi
\fi
XE Search user guide • 30
\fi
%
\or
\let\xs@next\xs@ParseWord
\chardef\xs@TempNum=\XeTeXcharclass`#1 %
\ifx\xs@temp\xs@question
\xs@Prefixtrue
\chardef\xs@ParseState=3
\else
\ifnum\xs@TempNum>\xs@Classes
\xs@BadChar#1{it's already a string delimiter}%
\else
\let\xs@next\xs@ParseWord
\fi
\fi
\or
\xs@BadChar?{it's already a string delimiter}%
\fi
\fi
\fi\xs@next
}
This is in case we find something we don’t want in the word. \def\xs@BadChar#1#2{%
\def\xs@next##1\xs@end{}%
\xs@BadWordtrue
\xs@err{%
You can't use `\noexpand#1' in `\xs@unexpanded\expandafter{\xs@TempWord}',\MessageBreak
#2.\MessageBreak
`\xs@unexpanded\expandafter{\xs@TempWord}' won't be searched
}%
}
In case the word is a phrase, we have to know that, so we \def\xs@CheckSpaces#1\xs@end{%
check spaces. In case there are some, we record word1, then \xs@@CheckSpaces#1 \xs@end
word1 word2, then word1 word2 word3, etc., as strings that }
may lead to phrases and should be recognized as such when \def\xs@@CheckSpaces#1 #2\xs@end{%
XESearch is searching. \def\xs@temp{#2}%
XE Search user guide • 31
\ifx\xs@temp\xs@empty
\let\xs@next\relax
\else
\expandafter\xs@MakePhrase\xs@Phrase\xs@end#1\xs@end
\def\xs@next{\xs@@CheckSpaces#2\xs@end}%
\fi\xs@next
}
\def\xs@MakePhrase#1\xs@end#2\xs@end{%
\ifx\xs@Phrase\xs@empty
\expandafter\def\csname#2@xs@phrases@\xs@cs\endcsname{}%
\edef\xs@Phrase{#2}%
\else
\expandafter\def\csname#1 #2@xs@phrases@\xs@cs\endcsname{}%
\edef\xs@Phrase{#1 #2}%
\fi
}%
In case the word was recognized as an affix, we add it to the \def\xs@GetFirstLetter#1#2\xs@end{%
list of affixes beginning (in the case of prefixes) or ending \def\xs@FirstLetter{#1}%
(in the case of suffixes) with a given le er (this is supposed }
to make XESearch faster: when XESearch scans a word, it \def\xs@MakePrefix{%
searches e.g. prefixes if and only if there are prefixes with \expandafter\ifx\csname\xs@TempWord @\xs@cs @xs@prefixes\endcsname\relax
the same initial le er as the word under investigation, and \expandafter\xs@GetFirstLetter\xs@TempWord\xs@end
it compares it to those words only). The affix is also added \ifcsname xs@prefixes@\xs@FirstLetter @\xs@cs\endcsname
to the lists sorted by length in both orders. \expandafter\edef\csname xs@prefixes@\xs@FirstLetter @\xs@cs\endcsname{%
\csname xs@prefixes@\xs@FirstLetter @\xs@cs\endcsname\xs@TempWord,}%
\def\xs@Sign{<}%
\xs@Insert{\xs@TempWord}{\csname xs@prefixes@\xs@FirstLetter @\xs@cs @longer\endcsname}%
\def\xs@Sign{>}%
\xs@Insert{\xs@TempWord}{\csname xs@prefixes@\xs@FirstLetter @\xs@cs @shorter\endcsname}%
\else
\expandafter\edef\csname xs@prefixes@\xs@FirstLetter @\xs@cs\endcsname{\xs@TempWord,}%
\expandafter\edef\csname xs@prefixes@\xs@FirstLetter @\xs@cs @longer\endcsname{\xs@TempWord,}%
\expandafter\edef\csname xs@prefixes@\xs@FirstLetter @\xs@cs @shorter\endcsname{\xs@TempWord,}%
\fi
\fi
XE Search user guide • 32
}
\def\xs@GetLastLetter#1{%
\ifx#1\xs@end
\let\xs@next\relax
\else
\let\xs@next\xs@GetLastLetter
\def\xs@LastLetter{#1}%
\fi\xs@next
}
\def\xs@MakeSuffix{%
\expandafter\ifx\csname\xs@TempWord @\xs@cs @xs@suffixes\endcsname\relax
\expandafter\xs@GetLastLetter\xs@TempWord\xs@end
\ifcsname xs@suffixes@\xs@LastLetter @\xs@cs\endcsname
\expandafter\edef\csname xs@suffixes@\xs@LastLetter @\xs@cs\endcsname{%
\csname xs@suffixes@\xs@LastLetter @\xs@cs\endcsname\xs@TempWord,}%
\def\xs@Sign{<}%
\xs@Insert{\xs@TempWord}{\csname xs@suffixes@\xs@LastLetter @\xs@cs @longer\endcsname}%
\def\xs@Sign{>}%
\xs@Insert{\xs@TempWord}{\csname xs@suffixes@\xs@LastLetter @\xs@cs @shorter\endcsname}%
\else
\expandafter\edef\csname xs@suffixes@\xs@LastLetter @\xs@cs\endcsname{\xs@TempWord,}%
\expandafter\edef\csname xs@suffixes@\xs@LastLetter @\xs@cs @longer\endcsname{\xs@TempWord,}%
\expandafter\edef\csname xs@suffixes@\xs@LastLetter @\xs@cs @shorter\endcsname{\xs@TempWord,}%
\fi
\fi
}
These suppress the ? at the beginning or the end of the \def\xs@SuppressPrefix#1#2\xs@end{\def\xs@TempWord{#2}}
word. \def\xs@SuppressSuffix#1?{\def\xs@TempWord{#1}}
Here’s how we sort the list: we check each affix, and we \def\xs@CountLetter#1{%
insert the affix to be added just before the the first affix that \ifx#1\xs@end
is shorter or longer, depending on the order. \let\xs@next\relax
\else
\advance\xs@Length1
\let\xs@next\xs@CountLetter
\fi\xs@next
XE Search user guide • 33
}
\def\xs@SortList#1,{%
\ifx#1\xs@end
\edef\xs@templist{\xs@templist\xs@TempAffix,}%
\let\xs@next\relax
\else
\xs@Length0
\xs@CountLetter#1\xs@end
\ifnum\xs@Length\xs@Sign\xs@AffixLength
\edef\xs@templist{\xs@templist\xs@TempAffix,#1,}%
\let\xs@next\xs@EndList
\else
\edef\xs@templist{\xs@templist#1,}%
\let\xs@next\xs@SortList
\fi
\fi\xs@next
}
\def\xs@EndList#1\xs@end,{%
\edef\xs@templist{\xs@templist#1}%
}
\def\xs@Insert#1#2{%
\def\xs@TempAffix{#1}%
\xs@Length0
\expandafter\xs@CountLetter#1\xs@end
\chardef\xs@AffixLength\xs@Length
\def\xs@templist{}%
\expandafter\expandafter\expandafter\xs@SortList#2\xs@end,
\expandafter\let#2\xs@templist
}
Finally, we make the definition of the word. First, we asso- \def\xs@PatchDef#1{%
ciate it with the word, so we’ll know which words to modify \expandafter\edef\csname\xs@ListName @words\endcsname{%
in case of a \StopList, and to which type it belongs (case- \csname\xs@ListName @words\endcsname
sensitivity, affix or full word, !-marked or not). Then we \xs@TempWor[Link]\xs@cs:::\xs@WordTyp[Link]\ifxs@Concatenate!\fi:::%
make both the normal replacement text and the ‘no-repla- }%
cement’ replacement text. \expandafter\ifx\csname\xs@TempWord @\xs@cs @xs@\xs@WordType\endcsname\relax%
XE Search user guide • 34
\xs@DefToks{\xs@FinalString}%
\else
\xs@DefToks\expandafter\expandafter\expandafter{%
\csname\xs@TempWord @\xs@cs @xs@\xs@WordType\endcsname}%
\fi
\expandafter\ifx\csname\xs@TempWord @\xs@cs @xs@\xs@WordType @noreplace\endcsname\relax
\xs@NoReplaceToks{}%
\else
\xs@NoReplaceToks\expandafter\expandafter\expandafter{%
\csname\xs@TempWord @\xs@cs @xs@\xs@WordType @noreplace\endcsname}%
\fi
\ifxs@Concatenate
\expandafter\edef\csname\xs@TempWord @\xs@cs @xs@\xs@WordType\endcsname{\the\xs@DefToks}%
\expandafter\edef\csname\xs@TempWord @\xs@cs @xs@\xs@WordType @noreplace\endcsname{%
\the\xs@NoReplaceToks
\xs@unexpanded{\expandafter#1\expandafter{\xs@String}}%
}%
\else
\expandafter\edef\csname\xs@TempWord @\xs@cs @xs@\xs@WordType\endcsname{%
\noexpand\expandafter\noexpand#1\noexpand\expandafter{\the\xs@DefToks}%
}%
\fi
}
Stopping a list is a delicate process: we have to extract the \def\StopList{%
definition associated with the list from the words where it \xs@ChangeCatcodes
appears, and it is nested in case it is not !-marked. \xs@StopList
}
\def\xs@StopList#1{%
\xs@@StopList#1,\xs@end,%
\xs@RestoreCatcodes
}
\def\xs@@StopList#1,{%
\def\xs@temp{#1}%
\ifx\xs@temp\xs@end
\let\xs@next\relax
XE Search user guide • 35
\else
\ifcsname#1@xs@searchlist\endcsname
\unless\ifcsname#1@xs@stoppedlist\endcsname
\csname#1@xs@stoppedlist\endcsname
\expandafter\def\expandafter\xs@ToRemove\expandafter{%
\csname#1@xs@searchlist\endcsname
}%
\expandafter\expandafter\expandafter%
\xs@PatchWords\csname #1@words\endcsname\xs@en[Link]%
\fi
\else
\xs@err{`#1' is not a list}%
\fi
\let\xs@next\xs@@StopList
\fi\xs@next
}
We modify the adequate replacement text: no-replace or \def\xs@PatchWords#[Link]#[Link]#[Link]#[Link]{%
normal. \def\xs@TempWord{#1}%
\ifx\xs@TempWord\xs@end
\let\xs@next\relax
\else
\def\xs@temp{#4}%
\ifx\xs@temp\xs@exclamation
\expandafter\expandafter\expandafter%
\xs@RemoveFromNoReplace\expandafter\xs@ToRemove\csname#1@#2@xs@#3@noreplace\endcsname
\fi
\def\xs@cs{#2}%
\def\xs@WordType{#3}%
\expandafter\xs@RemoveFromDef\csname#1@#2@xs@#3\endcsname
\let\xs@next\xs@PatchWords
\fi\xs@next
}
Removing from no-replace is rather easy, since it’s nothing \def\xs@RemoveFromNoReplace#1#2{%
more than: \def\xs@Erase##1\expandafter#1\expandafter##2##3\xs@end{%
\expandafter\<list1-macro>\expandafter{\xs@String} \def#2{##1##3}%
XE Search user guide • 36
\expandafter\<list2-macro>\expandafter{\xs@String} \ifx#2\xs@empty
\expandafter\<list3-macro>\expandafter{\xs@String} \let#2\relax
So we define a macro on the fly to find the definition we \fi
want to remove. If there’s nothing left, we let this no-replace }%
to \relax, so this word might be removed altogether when \expandafter\xs@Erase#2\xs@end
we evaluate what we find. }
Normal replacement texts have the following structure: \def\xs@final{\xs@FinalString}
\expandafter\<list1-macro>\expandafter{ \def\xs@TempDef{}
\expandafter\<list2-macro>\expandafter{ \def\xs@RemoveFromDef#1{%
... \def\xs@TempDef{}%
\xs@FinalString \def\xs@Def{\xs@FinalString}%
... \unless\ifx#1\xs@final
}} \expandafter\xs@Extract#1%
So we scan this recursively and rebuild it piecewise, remov- \fi
ing the list that was stopped. If in the end there remains \let#1\xs@Def
\xs@FinalString only, then there’s no replacement text any- \ifx#1\xs@final
more, and if moreover the no-replace part is equal to \re- \expandafter\ifx\csname\expandafter\xs@gobble\string#1@noreplace\endcsname\relax
lax, then there’s nothing left for that word and it shouldn’t \ifx\xs@WordType\xs@words
be tested anymore. So we let the definition associated with \let#1\relax
this word to \relax or we remove it from affixes. \else
\xs@RemoveFromAffixes
\fi
\fi
\fi
}
\def\xs@Extract\expandafter#1\expandafter#2{%
\def\xs@temp{#1}%
\unless\ifx\xs@temp\xs@ToRemove
\edef\xs@TempDef{%
\noexpand#1,%
\xs@unexpanded\expandafter{\xs@TempDef}%
}%
\fi
\def\xs@temp{#2}%
\ifx\xs@temp\xs@final
XE Search user guide • 37
\def\xs@next{%
\expandafter\xs@Rebuild\xs@TempDef\xs@end,%
}%
\else
\def\xs@next{%
\xs@Extract#2%
}%
\fi\xs@next
}
\def\xs@Rebuild#1,{%
\ifx#1\xs@end
\let\xs@next\relax
\else
\let\xs@next\xs@Rebuild
\edef\xs@Def{%
\xs@unexpanded{\expandafter#1\expandafter}%
\noexpand{%
\xs@unexpanded\expandafter{\xs@Def}%
\noexpand}%
}%
\fi\xs@next
}%
Removing an affix from a list is easy: we scan each word and \def\xs@RemoveFromAffixes{%
rebuild the list, removing the affix we want to deactivate. \ifx\xs@WordType\xs@prefixes
\expandafter\xs@GetFirstLetter\xs@TempWord\xs@end
\let\xs@Letter\xs@FirstLetter
\else
\expandafter\xs@GetLastLetter\xs@TempWord\xs@end
\let\xs@Letter\xs@LastLetter
\fi
\def\xs@templist{}%
\expandafter\expandafter\expandafter%
\xs@CleanList\csname xs@\xs@WordType @\xs@Letter @\xs@cs\endcsname\xs@end,%
\expandafter\let\csname xs@\xs@WordType @\xs@Letter @\xs@cs\endcsname\xs@templist
\def\xs@templist{}%
XE Search user guide • 38
\expandafter\expandafter\expandafter%
\xs@CleanList\csname xs@\xs@WordType @\xs@Letter @\xs@cs @shorter\endcsname\xs@end,%
\expandafter\let\csname xs@\xs@WordType @\xs@Letter @\xs@cs @shorter\endcsname\xs@templist
\def\xs@templist{}%
\expandafter\expandafter\expandafter%
\xs@CleanList\csname xs@\xs@WordType @\xs@Letter @\xs@cs @longer\endcsname\xs@end,%
\expandafter\let\csname xs@\xs@WordType @\xs@Letter @\xs@cs @longer\endcsname\xs@templist
\expandafter\let\csname\xs@TempWord @\xs@cs @xs@\xs@WordType\endcsname\relax
}
\def\xs@CleanList#1,{%
\def\xs@temp{#1}%
\ifx\xs@temp\xs@end
\let\xs@next\relax
\else
\let\xs@next\xs@CleanList
\unless\ifx\xs@temp\xs@TempWord
\edef\xs@templist{\xs@templist#1,}%
\fi
\fi\xs@next
}
. Testing words
Here comes the big part: collecting words and testing them. \def\xs@Stack{}
When a le er follows a delimiter, we reset some values and \def\xs@Remainder{}
start collecting the le ers in a box... \def\xs@StartString{%
\xs@Stringtrue
\let\xs@StartString\relax
\def\xs@String{}%
\def\PrefixFound{}%
\def\SuffixFound{}%
\def\AffixFound{}%
\def\xs@Stack{}%
\def\xs@Remainder{}%
\xs@Phrasefalse
XE Search user guide • 39
\setbox\xs@Box=\hbox\bgroup
}
\let\xs@@StartString\xs@StartString
...and when a delimiter shows up again, unless we’re track- \def\xs@EndString{%
ing a phrase, we close the box, create the unknown le ers \ifxs@String
that we’ve found in it, evaluate the word and finally output \egroup
the result of this evaluation. \xs@Stringfalse
\expandafter\xs@CreateLetter\xs@PendingLetters\xs@end
\gdef\xs@PendingLetters{}%
\xs@Evaluate
\xs@Restore
\xs@StartTracing
\expandafter\xs@Remainder
\fi
}
And here are the tests. The F test is for case-sensitive full \def\xs@@F@Test{%
words and just checks whether there is a definition for this \expandafter\unless\expandafter\ifx\csname\xs@String @cs@xs@words\endcsname\relax
word in this case. If it finds anything, it puts it around the \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter%
string that already exists, i.e. either the bare word or the \def%
word alreay surrounded by replacement texts. Hence The \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter%
bunch of \expandafters. If there’s a no-replace, we also add \xs@FinalString%
it to the existing ones. \xs@relax is just a placeholder to add \expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{%
the inhibitions defined with \SearchOrder. \csname\xs@String @cs@xs@words\endcsname}%
\expandafter\unless\expandafter\ifx\csname\xs@String @cs@xs@words@noreplace\endcsname\relax
\edef\xs@NoReplace{%
\xs@unexpanded\expandafter{\xs@NoReplace}%
\xs@unexpanded\expandafter{\csname\xs@String @cs@xs@words@noreplace\endcsname}%
}%
\fi
\xs@Matchtrue
\xs@relax
\xs@relax
\fi
}
The f does the same thing, except it puts the word in low- \def\xs@@f@Test{%
XE Search user guide • 40
}
\def\xs@@P@Test{%
\xs@Affixfalse
\expandafter\xs@GetFirstLetter\xs@String\xs@end
\ifcsname xs@prefixes@\xs@FirstLetter @cs\endcsname
\let\xs@@String\xs@String
\def\xs@cs{cs}%
\let\xs@WhatNext\xs@P@WhatNext
\expandafter\expandafter\expandafter%
\xs@CheckPrefixes\csname xs@prefixes@\xs@FirstLetter @cs\P@order\endcsname\xs@end,%
\fi
\ifxs@Affix
\xs@Affixfalse
\xs@Matchtrue
\xs@relax
\xs@relax
\fi
}
Prefixes are tested one by one by creating a macro on the fly \def\xs@CheckPrefixes#1,{%
where one delimiter is the prefix. Then we put the word at \def\xs@temp{#1}%
stake before it and execute the macro, and if there’s no first \ifx\xs@temp\xs@end
argument, then the word matches the prefix. For instance, \let\xs@next\relax
if the word is democracy and the prefix is demo then we test \else
\xs@TestPrefix democracydemo \def\xs@TestPrefix##1#1##2\xs@end{%
and obviously the first argument is empty, since demo is a \def\xs@temp{##1}%
delimiter. \ifx\xs@temp\xs@empty
\xs@Affixtrue
\def\PrefixFound{#1}%
\def\AffixFound{#1}%
\let\xs@next\xs@WhatNext
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter%
\def%
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter%
\xs@FinalString%
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter{%
XE Search user guide • 42
\csname#1@\xs@cs @xs@prefixes\endcsname}%
\expandafter\unless\expandafter\ifx\csname#1@\xs@cs @xs@prefixes@noreplace\endcsname\relax
\edef\xs@NoReplace{%
\xs@unexpanded\expandafter{\xs@NoReplace}%
\xs@unexpanded\expandafter{\csname#1@\xs@cs @xs@prefixes@noreplace\endcsname}%
}%
\fi
\else
\let\xs@next\xs@CheckPrefixes
\fi
}%
\expandafter\xs@TestPrefix\xs@@String#1\xs@end
\fi\xs@next
}
The tests for suffixes work along the same lines as those for \def\xs@@S@Test{%
prefixes. \xs@Affixfalse
\expandafter\xs@GetLastLetter\xs@String\xs@end
\ifcsname xs@suffixes@\xs@LastLetter @cs\endcsname
\let\xs@@String\xs@String
\def\xs@cs{cs}%
\let\xs@WhatNext\xs@S@WhatNext
\expandafter\expandafter\expandafter%
\xs@CheckSuffixes\csname xs@suffixes@\xs@LastLetter @cs\S@order\endcsname\xs@end,%
\fi
\ifxs@Affix
\xs@Affixfalse
\xs@Matchtrue
\xs@relax
\xs@relax
\fi
}
\def\xs@@s@Test{%
\xs@Affixfalse
\expandafter\xs@GetLastLetter\xs@lcString\xs@end
\ifcsname xs@suffixes@\xs@LastLetter @ncs\endcsname
XE Search user guide • 43
\let\xs@@String\xs@lcString
\def\xs@cs{ncs}%
\let\xs@WhatNext\xs@s@WhatNext
\expandafter\expandafter\expandafter%
\xs@CheckSuffixes\csname xs@suffixes@\xs@LastLetter @ncs\s@order\endcsname\xs@end,%
\fi
\ifxs@Affix
\xs@Affixfalse
\xs@Matchtrue
\xs@relax
\xs@relax
\fi
}
\def\xs@CheckSuffixes#1,{%
\def\xs@temp{#1}%
\ifx\xs@temp\xs@end
\let\xs@next\relax
\else
\def\xs@TestSuffix##1#1##2\xs@end{%
\def\xs@@temp{##2}%
\ifx\xs@temp\xs@@temp
\xs@Affixtrue
\def\SuffixFound{#1}%
\def\AffixFound{#1}%
\let\xs@next\xs@WhatNext
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter%
\def%
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter%
\xs@FinalString%
\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter\expandafter%
{%
\csname#1@\xs@cs @xs@suffixes\endcsname}%
\expandafter\unless\expandafter\ifx\csname#1@\xs@cs @xs@suffixes@noreplace\endcsname\relax
\edef\xs@NoReplace{%
\xs@unexpanded\expandafter{\xs@NoReplace}%
XE Search user guide • 44
\xs@unexpanded\expandafter{\csname#1@\xs@cs @xs@suffixes@noreplace\endcsname}%
}%
\fi
\else%
\let\xs@next\xs@CheckSuffixes
\fi
}%
\expandafter\xs@TestSuffix\xs@@String#1\xs@end
\fi\xs@next
}
. Search order
\SearchOrder actually defines \xs@Evaluate. First it adds \def\SearchOrder{%
inhibitions to the tests, e.g. ‘F!f;’ adds \let\xs@f@Test\relax \xs@ChangeCatcodes
to the F test in case it is positive, then it adds the tests them- \xs@SearchOrder
selves, in the specified order, to \xs@Evaluate. }
\def\xs@SearchOrder#1{%
\def\xs@Order{}%
\xs@@SearchOrder#1\xs@end;%
\edef\xs@Evaluate{%
\xs@unexpanded{%
\XeTeXinterchartokenstate=0
\def\xs@NoReplace{}%
\let\xs@FinalString\xs@String
\expandafter\xs@Lowercase\expandafter{\xs@String}\xs@lcString
}%
\xs@unexpanded\expandafter{%
\xs@Order
\ifxs@Match
\def\xs@next{%
\xs@FinalString
}%
\else
If the stack is not empty, it means we’re dealing with a phrase; \unless\ifx\xs@Stack\xs@empty
XE Search user guide • 45
}
\def\xs@MakeInhibit#1{%
\def\xs@temp{#1}%
\ifx#1\xs@end
\let\xs@next\relax
\else
\let\xs@next\xs@MakeInhibit
\unless\ifx\xs@temp\xs@exclamation%
\edef\xs@Inhibit{%
\xs@unexpanded\expandafter{\xs@Inhibit
\expandafter\let\csname xs@#1@Test\endcsname\relax}%
}%
\fi
\fi\xs@next
}
\def\xs@PatchTest#1\xs@relax#2\xs@relax#3#4{%
\expandafter\edef\csname xs@@#4@Test\endcsname{%
\xs@unexpanded{#1}%
\xs@unexpanded\expandafter{\expandafter\xs@relax\xs@Inhibit\xs@relax\fi}%
}%
}
The evaluation ends in any case with the restoration of the \def\xs@Restore{%
tests, in case they were inhibited. the remainder is the right \xs@Matchfalse
part of a discarded phrase. For instance, if XESearch searches \let\xs@f@Test\xs@@f@Test
for page layout it will investigate page properties if it \let\xs@F@Test\xs@@F@Test
finds it, and the remainder is properties. \let\xs@p@Test\xs@@p@Test
\let\xs@P@Test\xs@@P@Test
\let\xs@s@Test\xs@@s@Test
\let\xs@S@Test\xs@@S@Test
\let\xs@StartString\xs@@StartString
\edef\xs@Remainder{%
\xs@unexpanded\expandafter{\xs@NoReplace}%
\xs@unexpanded\expandafter{\xs@Remainder}%
}%
\XeTeXinterchartokenstate=1
XE Search user guide • 47
}
This is used to test phrases minus the last word on each it- \def\xs@PopWord#1\xs@end#2\xs@end{%
eration. The stack itself is built when the beginning of a \def\xs@String{#2}%
phrase is found before a natural delimiter. \def\xs@@PopWord#2##1\xs@end{%
\edef\xs@Remainder{##1\xs@unexpanded\expandafter{\xs@Remainder}%
}%
}%
\xs@@PopWord#1\xs@end
}
\def\xs@PopStack#1\xs@end#2\xs@@end{%
\def\xs@Stack{#2}%
\expandafter\xs@PopWord\xs@String\xs@end#1\xs@end
}
To search affixes in a given order, we simply define the list \def\SortByLength#1{%
to be used in tests to be the one with this order. \def\xs@temp{#1}%
\ifx\xs@temp\xs@star
\def\xs@AffixOrder{@shorter}%
\let\xs@next\xs@SortByLength
\else
\def\xs@AffixOrder{@longer}%
\def\xs@next{\xs@@SortByLength#1\xs@end}%
\fi
\xs@next}%
\def\xs@SortByLength#1{%
\xs@@SortByLength#1\xs@end
}
\def\xs@@SortByLength#1{%
\ifx#1\xs@end
\let\xs@next\relax
\else
\expandafter\let\csname #1@order\endcsname\xs@AffixOrder
\let\xs@next\xs@@SortByLength
\fi\xs@next
}
\def\DoNotSort{%
XE Search user guide • 48
\def\xs@AffixOrder{}%
\xs@SortByLength
}
Searching all affixes is done by se ing the \xs@WhatNext \def\SearchAll#1{%
macro to \xs@<affix>@WhatNext, depending on the text be- \xs@SearchAll#1\xs@end
ing performed. }
\def\xs@SearchAll#1{%
\ifx#1\xs@end
\let\xs@next\relax
\else\let\xs@next\xs@SearchAll
\if#1p%
\let\xs@p@WhatNext\xs@CheckPrefixes
\else
\if#1P
\let\xs@P@WhatNext\xs@CheckPrefixes
\else
\if#1s
\let\xs@s@WhatNext\xs@CheckSuffixes
\else
\let\xs@S@WhatNext\xs@CheckSuffixes
\fi
\fi
\fi
\fi\xs@next
}
\def\SearchOnlyOne#1{%
\xs@SearchOne#1\xs@end
}
Searching only one affix is simply gobbling the remaining \def\xs@SearchOne#1{%
ones in case of a successful test. \ifx#1\xs@end
\let\xs@next\relax
\else
\let\xs@next\xs@SearchOne
\expandafter\def\csname xs@#1@WhatNext\endcsname##1\xs@end,{}%
\fi\xs@next
XE Search user guide • 49
. Miscellanea
For the moment, starting and stopping the search is quite \def\StopSearching{%
brutal. \let\xs@StartString\relax
}
\def\StartSearching{%
\let\xs@StartString\xs@@StartString
}
Patching the output very simple too. \let\xs@OldOutput\relax
\def\PatchOutput{%
\ifx\xs@OldOutput\relax
\edef\xs@PatchOutput{%
\noexpand\def\noexpand\xs@OldOutput{%
\the\output
}%
\noexpand\output{%
\noexpand\StopSearching
\the\output
\noexpand\StartSearching
}%
}%
\expandafter\xs@PatchOutput
\else
\xs@err{Output already patched}%
\fi
}
\def\NormalOutput{%
\ifx\xs@OldOutput\relax
\xs@err{Output has not been patched}%
\else
\expandafter\output\expandafter{%
\xs@OldOutput
}%
XE Search user guide • 50
\let\xs@OldOutput\relax
\fi
}
As is patching the tracing. \def\PatchTracing{%
\def\xs@StopTracing{%
\chardef\xs@tracingcommands\tracingcommands
\chardef\xs@tracingmacros\tracingmacros
\tracingcommands0 \tracingmacros0\relax
}%
\def\xs@StartTracing{%
\tracingcommands\xs@tracingcommands
\tracingmacros\xs@tracingmacros
}%
}
\def\NormalTracing{%
\let\xs@StopTracing\relax
\let\xs@StartTracing\relax
}
\NormalTracing
finally we set everything back to normal, set some default \xs@RestoreCatcodes \catcode`@=12
values and say goodbye. \SearchOrder{
F!fPpSs;
f!PpSs;
P!pSs;
p!Ss;
S!s;
s;
}
\DoNotSort{pPsS}
\SearchAll{pPsS}
\XeTeXinterchartokenstate1
\endinput
XE Search user guide • 51