0% encontró este documento útil (0 votos)
23 vistas51 páginas

Xe Search

Cargado por

venipa3881
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
23 vistas51 páginas

Xe Search

Cargado por

venipa3881
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

A e v l rABe Snd X m z W

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

Dws M qHOxE XWE T


w
DXw

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

Cj n FRp ph t si kOv LU l j gBj u x jR J b C Ia XS


t L w S p d u

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 n What XESearch looks for and how it finds it


V qq
C B

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

GI XD (A very blunt form of) regular expressions


z

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

. Strictly identical searches . . . . . . . . . . . . . . . . . . . . . . . . . .


K W Lq

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

. Affixes with identical characteristics . . . . . . . . . . . . . . . . . . . .


X

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

e o Some TEXnical ma ers


W

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

v z . Syntax highlighting: HTML . . . . . . . . . . . . . . . . . . . . . . . .


j

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

B . A third party file for ConTEXt . . . . . . . . . . . . . . . . . . . . . . .


G

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

• \SearchList⟨*!⟩{⟨name⟩}{⟨replacement text ⟩}{⟨list of words⟩}


The star and exclamation mark are optional and their relative order does not ma er. Stick-
ing to mandatory arguments for the moment, here’s how this macro works: first, you give
\SearchList{list1}{\italics{#1}}{obviously}
a ⟨name⟩ to this list, for further reference. Then you specify the ⟨replacement text⟩, which \SearchList{list2}{}{something}
will be substituted for all of the words in ⟨list of words⟩ (separated by commas). In this Obviously, I have forgotten something.
⟨replacement text⟩, the substituted word is designed by #1, so just think about it as an ar-
Obviously, I have forgo en .
gument to a control sequence. If you forget #1, the word disappears (until we learn how
to use the exclamation mark), as can be seen in example . ₂: W
E A A
Note that there’s still a space between forgo en and the full stop. Where does it come
from? Well, it is the space that was between forgo en and something. At the time when
XESearch manipulates something, this space has already been read and typeset, so it does
not disappear.
But there’s something much more interesting in this example. As you might have
noticed, the first line says: \SearchList{Case insensitive}{\blue{#1}}{woRd}
Word word woRd WORD
\SearchList{list1}{\italics{#1}}{obviously}
\StopList{Case insensitive}
and in the text to be searched we find ‘Obviously’, with an uppercase first le er. Nonethe- Word word woRd WORD
less, it is found and modified according to the replacement text. We thus discover one
basic principle of XESearch: it isn’t case-sensitive by default. Hence the two following lists \SearchList*{Case sensitive}{\red{#1}}{word}
Word word woRd WORD
\SearchList{list1}{<whatever>}{word} \StopList{Case sensitive}
\SearchList{list2}{<whatever>}{Word}
Word word woRd WORD
will find exactly the same set of words, namely ‘word’ ‘Word’, ‘woRd’, ‘WORD’, etc. How \SearchList{Mixed}{\green{#1}}{word,*Worm}
scary. This isn’t customary in good programming and in TEX in particular. Fortunately, Word word woRd WORD\par
this default se ing can be easily changed: the optional star just after \SearchList will Worm worm woRm WORM\par
make the entire list case-sensitive. Besides, if a list is not case-sensitive, i.e. if it has no Word word woRd WORD
star, a star before a word in that list will make the search for that particular word case- Worm worm woRm WORM
sensitive.² This is illustrated in example .
In this example we discover another macro, whose meaning is clear: E ₃: I C -S
• \StopList{⟨list of lists⟩}
The lists, separated by commas, are turned off.
²However, if \SearchList is suffixed with a star, all words in the list will be case-sensitive.
XE Search user guide • 5

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

What XESearch looks for and how it finds it


XESearch can see only two things: le ers and non-le ers. Non-le ers it doesn’t like be-
cause it’s then forced to spit the le ers it has gathered and form a word, and most times
\SearchList{Will it find me?}{\blue{#1}}{word}
it’s not allowed to take it away. (Un)fortunately, XESearch is quite short-sighted: it con-
\def\rd{rd}
siders le ers what you tell it are not non-le ers (XESearch apparently has some formal Here is a wo\rd.
education in philosophy).
Here is a word.
More seriously (and clearly), XESearch forms a word as long as there are le ers. As
you can see in example , macros are expanded and if they yield le ers, XESearch can ₆: M
E C ’ H L
recognize a word. So when does it stop searching? There are two main cases:
. It encounters a space, or any primitive control sequence. The former case is quite nat-
ural: you want spaces to delimit words (including \skips and associates). But the la er
is less obvious: as soon as TEX does something that is not typese ing le ers, XESearch
gives up. And this includes something as seemingly innocuous as a \relax, as you can \SearchList{This time I'm prepared}{\blue{#1}}{word}
see in example . That’s the reason why, for instance, XESearch will never find TeX in \def\rd{\relax rd}
Here is a wo\rd.
\TeX: the definition contains many operations that aren’t strictly speaking pu ing le ers
in the stream. Fortunately, the bulk of a manuscript is made of le ers and spaces, and Here is a word.
one seldom inserts \relaxes in the middle of words.
. XESearch encounters a character that you’ve declared as a non-le er, that is a word E ₇: B P C
boundary. This leads us to the following macro:
• \MakeBoundary{⟨characters⟩}
• \UndoBoundary{⟨characters⟩}
\MakeBoundary{/}
The characters should be simply put one after the other, as in for instance
\SearchList{separated}{\ddag#1\ddag}{waka,jawaka}
\MakeBoundary{,;:!} Waka/Jawaka
\UndoBoundary{?()\{\}}
‡Waka‡/‡Jawaka‡
The basic set of such characters is as follows³
\UndoBoundary{/}
.,;:!?-`'()[]{} \SearchList{united}{\ddag#1\ddag}{waka/jawaka}
Waka/Jawaka
Now, if XESearch encounters a character that you’ve made into a boundary, it will stop
forming a word and evaluate what it has gathered. Conversely, such characters cannot ‡Waka/Jawaka‡
appear in the list of words in \SearchList; they wouldn’t be found anyway. This is
illustrated in example . E ₈: W W S A S

³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}

beginning of a phrase that you want identified, e.g. the kern in


You are what\kern1cm % What a kern!
\SearchList{H(a)unting primitives}{<whatever>}% you is but you are neither good, nor bad.
{xesearch feeds on kerns} You are what you is but you are neither good, nor bad.
xesearch feeds on\kern1cm skips

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}

A \italics{Black Page} in B, actually some kind of


(A very blunt form of) regular expressions duet for Terry Bozzio and Chad Wackerman, lay
on the drumset beside the PET facility.
Words are cool, and phrases too. But life doesn’t always reach their level of achievement. A Black Page in B, actually some kind of duet for Terry Bozzio and Chad
Sometimes you don’t know what you want. Something beginning with a ‘B’, why not? Wackerman, lay on the drumset beside the PET facility.
or maybe something that ends in ‘et’? Then look at example .
There are several things to see in this example. First, XESearch has entered the \italics E ₁₀: P A S
command and imposed its will.⁴ Next, affixes⁵ are also sensitive to case-sensitivity, so to
⁴Provided I’m using commands that don’t cancel each other, like plain TEX’s \bf and \it.
⁵I use the word affixes to refer to both prefixes (like B?) and suffixes (like ?et). From a linguistic point of
view, prefixes and suffixes (and infixes, actually) are indeed affixes, but from the same point a view, what
we’re talking about here has nothing to do with prefixes or suffixes, just with bits of words. I hope you don’t
mind.
XE Search user guide • 8

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>}{?}

as an a empt to match all words. This won’t work.⁷

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.

Some TEXnical ma ers This droW is well-matched.


This Word is not so well-matched anymore.
This Word is not matched at all.
This section is not vital to the comprehension of XESearch, but it may be useful.
• \PrefixFound E ₁₆: S O
• \SuffixFound
• \AffixFound
When a word is found thanks to an affix search, the prefix or suffix used is stored in the
relevant macros. If there are several matching affixes, the last prefix and the last suffix win
\SearchList{A case-sensitive suffix}{Suf\blue\SuffixFound}{*?FiX}
in their respective categories, and between them the same rule apply for \AffixFound. SufFiX.
These macros are available as long as the search has not started again, i.e. they’re fully
available in normal replacement texts, but in !-marked definitions they’re erased as soon SufFiX.
as a le er is typeset, so they can be used only at the very beginning. The rest of the time \SearchList{A case-insensitive affix}{\blue\AffixFound fix}{Pre?}
they are empty. PREfix.
The affix itself respects the case in which it was declared if it is case-sensitive, but it is prefix.
in lowercase otherwise, however it was fed to \SearchList. See example .
• \PatchOutput E ₁₇: F A
• \NormalOutput
By default, XESearch doesn’t patch the output routine so footers and headers are searched.
This can be done by these two commands. \PatchOutput should of course be issued after
XE Search user guide • 12

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}}

and when word is encountered it is turned to


\expandafter\command@listthree\expandafter{%
\expandafter\command@listtwo\expandafter{%
\expandafter\command@listone\expandafter{\WORD}}}

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}}}

which you won’t have failed to notice is not equivalent to


\bold{\blue{\italics{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.

⁸If you’re a linguist, I apologize for my lack of originality.


XE Search user guide • 14

\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: .

. Syntax highlighting: TEX E ₂₀: C W

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

. Syntax highlighting: HTML


Coloring HTML is rather easy. The most complicated part concerns word boundaries.
XESearch is used to find elements and a ributes. Only case-insensitive full words need to
be searched for.
\MakeBoundary{<>/=}
\SearchList{elements}{\bold{\violet{#1}}}
{html,meta,head,body,span,p,div,b,h1,img}
\SearchList{attributes}{\bold{#1}}{align,class,style,src}
\SearchOrder{f;}

< 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&#1;{% <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

Example shows the bo om of the CTAN page.


XE Search user guide • 19

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

\ProvidesPackage{!FileName}[!FileDate!space !FileVersion!space Searching documents.]


\else
\def\MessageBreak{^^J}
\def\xs@err#1{%
\bgroup
\newlinechar`\^^J%
\errorcontextlines=0
\errmessage{xsearch error: #1}%
\egroup
}
\fi
\unexpanded already exists in ConTEXt, and the meaning of \ifcsname xs@contextmodule\endcsname
the ε-TEX primitive is taken over by \normalunexpanded, so \let\xs@unexpanded\normalunexpanded
we have to make the proper adjustment (many thanks to \else
Wolfgang Schuster, who signalled this to me). \let\xs@unexpanded\unexpanded
\xs@contextmodule is an empty command let to \relax when \fi
XESearch is loaded with ConTEXt.
Some keywords, indispensable macros, and a bunch of \new \def\xs@end{\xs@end}
things. \def\xs@empty{}
\def\xs@star{*}
\def\xs@exclamation{!}
\def\xs@question{?}
\def\xs@starexclam{*!}
\def\xs@exclamstar{!*}
\def\xs@words{words}
\def\xs@prefixes{prefixes}
\def\xs@suffixes{suffixes}
\def\xs@gobble#1{}
\def\xs@Lowercase#1#2{\lowercase{\def#2{#1}}}
\let\xs@relax\relax
\newcount\xs@TempCount
\newcount\xs@CaseSensitive
\newcount\xs@TempLength
\newcount\xs@Length
\newbox\xs@Box
XE Search user guide • 21

\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

word-maker on the list of words. \AddToList is equivalent }%


with some adjustments. \else
\def\xs@ListName{#1}%
\expandafter\def\csname\xs@ListName @words\endcsname{}%
\expandafter\def\csname #1@xs@searchlist\endcsname##1{#2}%
\expandafter\def\csname #1@xs@searchlist@noreplace\endcsname##1{#2}%
\expandafter\xs@MakeWord#3,\xs@end,%
\xs@RestoreCatcodes
\fi
}
\def\AddToList{%
\xs@ChangeCatcodes
\xs@StarOrExclam\xs@AddToList
}
\def\xs@AddToList#1#2{%
\ifcsname#1@xs@searchlist\endcsname
\def\xs@ListName{#1}%
\expandafter\xs@MakeWord#2,\xs@end,%
\xs@RestoreCatcodes
\else
\xs@err{`#1' is not a list}%
\fi
\xs@RestoreCatcodes
}
This takes each word one by one and checks and creates a \def\xs@MakeWord#1,{%
few things. \def\xs@TempWord{#1}%
\ifx\xs@TempWord\xs@end
\let\xs@next\relax
\else
\ifcsname\ifnum\xs@CaseSensitive=2*\fi#1@\xs@ListName\endcsname
\xs@err{You have already specified `\ifnum\xs@CaseSensitive=2*\fi#1'%
in `\xs@ListName'. \MessageBreak You can't do it twice}%
\else
\csname#1@\xs@ListName\endcsname
\edef\xs@TempWord{#1}%
XE Search user guide • 27

\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

ercase before hand. \expandafter\xs@Lowercase\expandafter{\xs@String}\xs@lcString


\expandafter\unless\expandafter\ifx\csname\xs@lcString @ncs@xs@words\endcsname\relax
\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\xs@lcString @ncs@xs@words\endcsname}%
\expandafter\unless\expandafter\ifx\csname\xs@lcString @ncs@xs@words@noreplace\endcsname\relax
\edef\xs@NoReplace{%
\xs@unexpanded\expandafter{\xs@NoReplace}%
\xs@unexpanded\expandafter{\csname\xs@lcString @ncs@xs@words@noreplace\endcsname}%
}%
\fi
\xs@Matchtrue
\xs@relax
\xs@relax
\fi
}
Tests on prefixes check whether there exists a prefix list be- \def\xs@@p@Test{%
ginning with the same le er as the word at stake, and in this \xs@Affixfalse
case run the \xs@CheckPrefixes test. \expandafter\xs@GetFirstLetter\xs@lcString\xs@end
\ifcsname xs@prefixes@\xs@FirstLetter @ncs\endcsname
\let\xs@@String\xs@lcString
\def\xs@cs{ncs}%
\let\xs@WhatNext\xs@p@WhatNext
\expandafter\expandafter\expandafter%
\xs@CheckPrefixes\csname xs@prefixes@\xs@FirstLetter @ncs\p@order\endcsname\xs@end,%
\fi
\ifxs@Affix
\xs@Affixfalse
\xs@Matchtrue
\xs@relax
\xs@relax
\fi
XE Search user guide • 41

}
\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

so the evaluation is not over in case no test has succeded. \xs@Phrasetrue


We first have to test the phrase minus the last word, then \expandafter\xs@PopStack\xs@Stack\xs@@end
the phrase minus the last two words, etc. \let\xs@next\xs@Evaluate
\else
\ifxs@Phrase
\def\xs@Stack{}%
\def\xs@next{\xs@String\xs@Restore}%
\else
If the word was not a phrase, and no test was successful, we \def\xs@next{\unhbox\xs@Box\xs@Restore}%
simply put the box that contains it back into the stream. \fi
\fi
\fi\xs@next
}%
}%
We initialize the tests. \let\xs@f@Test\xs@@f@Test
\let\xs@F@Test\xs@@F@Test
\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
\xs@RestoreCatcodes
}
This treats each specification in \SearchOrder and the inhi- \def\xs@@SearchOrder#1#2;{%
bitions, if any. \def\xs@temp{#1#2}%
\ifx#1\xs@end
\let\xs@next\relax
\else
\def\xs@Inhibit{}%
\xs@MakeInhibit#2\xs@end
\expandafter\expandafter\expandafter\xs@PatchTest\csname xs@@#1@Test\endcsname#1%
\edef\xs@Order{%
\xs@unexpanded\expandafter{\xs@Order}%
\xs@unexpanded\expandafter{\csname xs@#1@Test\endcsname}}%
\let\xs@next\xs@@SearchOrder
\fi\xs@next
XE Search user guide • 46

}
\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

. A third party file for ConTEXt


This file is mostly due to Wolfgang Schuster. %D \module
\xs@contextmodule is used when the main file is loaded to %D [ file=!FileName,
set the meaning of \xs@unexpanded. (ConTEXt commands %D version=!FileDate,
have meaningful names, so I didn’t want to rely on them %D title=\CONTEXT\ User Module,
as tests for ConTEXt, because there might exist commands %D subtitle=XeSearch,
with the same names in other formats.) %D author=Paul Isambert,
%D date=\currentdate,
%D copyright=Paul Isambert,
%D email=zappathustra@[Link],
%D license=LaTeX Project Public License]

\writestatus{loading}{ConTeXt User Module / XeSearch}


\csname xs@contextmodule\endcsname
\input [Link]
\endinput

También podría gustarte