arabluatex.lua 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. --[[
  2. This file is part of the `arabluatex' package
  3. ArabLuaTeX -- Processing ArabTeX notation under LuaLaTeX
  4. Copyright (C) 2016--2018 Robert Alessi
  5. Please send error reports and suggestions for improvements to Robert
  6. Alessi <alessi@robertalessi.net>
  7. This program is free software: you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation, either version 3 of the License, or
  10. (at your option) any later version.
  11. This program is distributed in the hope that it will be useful, but
  12. WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. General Public License for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program. If not, see
  17. <http://www.gnu.org/licenses/>.
  18. --]]
  19. require("arabluatex_voc")
  20. require("arabluatex_fullvoc")
  21. require("arabluatex_novoc")
  22. require("arabluatex_trans")
  23. local function protectarb(str)
  24. str = string.gsub(str, "(\\arb.?)(%[.-%])(%b{})", "\\@arb%2%3")
  25. str = string.gsub(str, "(\\begin.?)(%b{})(%b[])", "\\@begin%3%2")
  26. str = string.gsub(str, "(\\begin.?)(%b{})", "\\@begin%2")
  27. str = string.gsub(str, "(\\end.?)(%b{})", "\\@end%2")
  28. str = string.gsub(str, "\\par", "\\p@r{}")
  29. str = string.gsub(str, "\\@@par", "\\p@r{}")
  30. return str
  31. end
  32. local function unprotectarb(str)
  33. str = string.gsub(str, "(\\@arb)(%[.-%])(%b{})", "\\arb%2%3")
  34. str = string.gsub(str, "(\\@begin)(%b[])(%b{})", "\\begin%3%2")
  35. str = string.gsub(str, "(\\@begin)(%b{})", "\\begin%2")
  36. str = string.gsub(str, "(\\@end)(%b{})", "\\end%2")
  37. str = string.gsub(str, "\\p@r{}", "\\par")
  38. return str
  39. end
  40. brkcmds = {}
  41. function mkarbbreak(str)
  42. str = str ..","
  43. str = string.gsub(str, "%s+", "")
  44. local fieldstart = 1
  45. repeat
  46. local nexti = string.find(str, "%,", fieldstart)
  47. table.insert(brkcmds, string.sub(str, fieldstart, nexti-1))
  48. fieldstart = nexti +1
  49. until fieldstart > string.len(str)
  50. return brkcmds
  51. end
  52. local function breakcmd(str)
  53. -- user commands
  54. if next(brkcmds) == nil then
  55. -- nothing to do
  56. else
  57. for i = 1,#brkcmds do
  58. str = string.gsub(str, "\\"..brkcmds[i].."%s?(%b{})",
  59. function(body)
  60. body = string.sub(body, 2, -2)
  61. return string.format("}\\"..brkcmds[i].."{%s}\\arb{", body)
  62. end)
  63. end
  64. end
  65. -- process \item[], then \item[]
  66. str = string.gsub(str, "\\(item.?)(%b[])",
  67. function(tag, body)
  68. body = string.sub(body, 2, -2)
  69. return string.format("}\\item[\\arb{%s}] \\arb{", body)
  70. end)
  71. str = string.gsub(str, "(\\item)(%s+)", "%1{}%2")
  72. -- \edtext
  73. str = string.gsub(str, "\\(edtext.-)(%b{})(%b{})",
  74. function(tag, bodylem, bodyvar)
  75. bodylem = string.sub(bodylem, 2, -2)
  76. bodyvar = string.sub(bodyvar, 2, -2)
  77. return string.format("\\LR{\\%s{%s}{%s}}", tag, bodylem, bodyvar)
  78. end)
  79. -- \RL
  80. str = string.gsub(str, "\\(RL.-)(%b{})",
  81. function(tag, body)
  82. body = string.sub(body, 2, -2)
  83. return string.format("}\\%s{%s}\\arb{", tag, body)
  84. end)
  85. -- \LR
  86. str = string.gsub(str, "\\(LR.-)(%b{})",
  87. function(tag, body)
  88. body = string.sub(body, 2, -2)
  89. return string.format("}\\%s{%s}\\arb{", tag, body)
  90. end)
  91. -- \textcolor
  92. str = string.gsub(str, "\\(textcolor.?)(%b{})(%b{})",
  93. function(tag, bodycolor, bodytext)
  94. bodycolor = string.sub(bodycolor, 2, -2)
  95. bodytext = string.sub(bodytext, 2, -2)
  96. return string.format("}\\%s{%s}{\\arb{%s}}\\arb{", tag, bodycolor, bodytext)
  97. end)
  98. -- Footnote
  99. str = string.gsub(str, "\\(Footnote.-)(%b{})",
  100. function(tag, body)
  101. body = string.sub(body, 2, -2)
  102. return string.format("}\\%s{%s}\\arb{", tag, body)
  103. end)
  104. -- Marginpar
  105. str = string.gsub(str, "\\(Marginpar.-)(%b{})",
  106. function(tag, body)
  107. body = string.sub(body, 2, -2)
  108. return string.format("}\\%s{%s}\\arb{", tag, body)
  109. end)
  110. -- Abjad
  111. str = string.gsub(str, "\\(abjad.-)(%b{})",
  112. function(tag, body)
  113. body = string.sub(body, 2, -2)
  114. return string.format("}\\aemph{\\%s{%s}}\\arb{", tag, body)
  115. end)
  116. -- Arbmark
  117. str = string.gsub(str, "\\(arbmark.-)(%b{})",
  118. function(tag, body)
  119. body = string.sub(body, 2, -2)
  120. return string.format("}\\%s{%s}\\arb{", tag, body)
  121. end)
  122. return str
  123. end
  124. local function holdcmd(str)
  125. str = string.gsub(str, "\\(arb)(%b{})", function(tag, body)
  126. body = string.sub(body, 2, -2)
  127. body = string.gsub(body, "\\(.-)(%b{})", function(btag, bbody)
  128. bbody = string.sub(bbody, 2, -2)
  129. if string.find(btag, "@") then
  130. return holdcmd(string.format("}\\%s{%s}\\arb{", btag, bbody))
  131. else
  132. return holdcmd(string.format("}\\%s{\\arb{%s}}\\arb{", btag, bbody))
  133. end
  134. end)
  135. return string.format("\\%s{%s}", tag, body)
  136. end)
  137. str = string.gsub(str, "\\arb{}", "")
  138. return str
  139. end
  140. local function arbnum(str)
  141. str = string.gsub(str, "([0-9%,%-%/]+)", function(num)
  142. return string.reverse(num)
  143. end)
  144. return str
  145. end
  146. local function indnum(str)
  147. str = string.gsub(str, "([0-9%,%-%/]+)", function(num)
  148. return string.reverse(num)
  149. end)
  150. for i = 1,#numbers do
  151. str = string.gsub(str, numbers[i].a, numbers[i].b)
  152. end
  153. return str
  154. end
  155. local function processdiscretionary(str)
  156. str = string.gsub(str, "\\%-", "\\-{}")
  157. return str
  158. end
  159. local function processarbnull(str, scheme)
  160. if scheme == "buckwalter" then
  161. str = string.gsub(str, "(\\arbnull.?)(%b{})", function(tag, body)
  162. body = string.sub(body, 2, -2)
  163. return string.format("P%sP", body)
  164. end)
  165. else
  166. str = string.gsub(str, "(\\arbnull.?)(%b{})", function(tag, body)
  167. body = string.sub(body, 2, -2)
  168. return string.format("o%so", body)
  169. end)
  170. end
  171. return str
  172. end
  173. local function takeoutabjad(str)
  174. str = string.gsub(str, "(\\abjad.?)(%b{})", function(tag, body)
  175. body = string.sub(body, 2, -2)
  176. return string.format("%s", body)
  177. end)
  178. return str
  179. end
  180. local function takeoutcapetc(str)
  181. str = string.gsub(str, "(\\arb.?%[trans%])(%b{})", function(tag, body)
  182. body = string.sub(body, 2, -2)
  183. body = string.gsub(body, "(\\uc%s?)(%b{})", "\\Uc%2")
  184. return string.format("%s{%s}", tag, body)
  185. end)
  186. str = string.gsub(str, "(\\uc.?)(%b{})", function(tag, body)
  187. body = string.sub(body, 2, -2)
  188. return string.format("%s", body)
  189. end)
  190. str = string.gsub(str, "\\linebreak", "")
  191. str = string.gsub(str, "\\%-", "")
  192. return str
  193. end
  194. local function voc(str, rules)
  195. str = string.gsub(str, "\\arb(%b{})", function(inside)
  196. inside = string.sub(inside, 2, -2)
  197. for i = 1,#hamza do
  198. inside = string.gsub(inside, hamza[i].a, hamza[i].b)
  199. end
  200. if rules == "idgham" then
  201. for i = 1,#tanwin do
  202. inside = string.gsub(inside, tanwin[i].a, tanwin[i].b)
  203. end
  204. else
  205. for i = 1,#tanwineasy do
  206. inside = string.gsub(inside, tanwineasy[i].a, tanwineasy[i].b)
  207. end
  208. end
  209. for i = 1,#trigraphs do
  210. inside = string.gsub(inside, trigraphs[i].a, trigraphs[i].b)
  211. end
  212. if rules == "idgham" then
  213. for i = 1,#idgham do
  214. inside = string.gsub(inside, idgham[i].a, idgham[i].b)
  215. end
  216. end
  217. for i = 1,#digraphs do
  218. inside = string.gsub(inside, digraphs[i].a, digraphs[i].b)
  219. end
  220. for i = 1,#single do
  221. inside = string.gsub(inside, single[i].a, single[i].b)
  222. end
  223. for i = 1,#longv do
  224. inside = string.gsub(inside, longv[i].a, longv[i].b)
  225. end
  226. for i = 1,#shortv do
  227. inside = string.gsub(inside, shortv[i].a, shortv[i].b)
  228. end
  229. for i = 1,#punctuation do
  230. inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
  231. end
  232. for i = 1,#null do
  233. inside = string.gsub(inside, null[i].a, null[i].b)
  234. end
  235. inside = indnum(inside)
  236. return string.format("\\txarb{%s}", inside)
  237. end)
  238. return str
  239. end
  240. local function voceasy(str)
  241. str = string.gsub(str, "\\arb(%b{})", function(inside)
  242. inside = string.sub(inside, 2, -2)
  243. for i = 1,#hamzaeasy do
  244. inside = string.gsub(inside, hamzaeasy[i].a, hamzaeasy[i].b)
  245. end
  246. for i = 1,#tanwineasy do
  247. inside = string.gsub(inside, tanwineasy[i].a, tanwineasy[i].b)
  248. end
  249. for i = 1,#trigraphseasy do
  250. inside = string.gsub(inside, trigraphseasy[i].a, trigraphseasy[i].b)
  251. end
  252. for i = 1,#digraphs do
  253. inside = string.gsub(inside, digraphs[i].a, digraphs[i].b)
  254. end
  255. for i = 1,#single do
  256. inside = string.gsub(inside, single[i].a, single[i].b)
  257. end
  258. for i = 1,#longv do
  259. inside = string.gsub(inside, longv[i].a, longv[i].b)
  260. end
  261. for i = 1,#shortv do
  262. inside = string.gsub(inside, shortv[i].a, shortv[i].b)
  263. end
  264. for i = 1,#punctuation do
  265. inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
  266. end
  267. for i = 1,#null do
  268. inside = string.gsub(inside, null[i].a, null[i].b)
  269. end
  270. inside = indnum(inside)
  271. return string.format("\\txarb{%s}", inside)
  272. end)
  273. return str
  274. end
  275. local function fullvoc(str, rules)
  276. str = string.gsub(str, "\\arb(%b{})", function(inside)
  277. inside = string.sub(inside, 2, -2)
  278. for i = 1,#hamzafv do
  279. inside = string.gsub(inside, hamzafv[i].a, hamzafv[i].b)
  280. end
  281. if rules == "idgham" then
  282. for i = 1,#tanwinfv do
  283. inside = string.gsub(inside, tanwinfv[i].a, tanwinfv[i].b)
  284. end
  285. else
  286. for i = 1,#tanwinfveasy do
  287. inside = string.gsub(inside, tanwinfveasy[i].a, tanwinfveasy[i].b)
  288. end
  289. end
  290. for i = 1,#trigraphsfv do
  291. inside = string.gsub(inside, trigraphsfv[i].a, trigraphsfv[i].b)
  292. end
  293. if rules == "idgham" then
  294. for i = 1,#idgham do
  295. inside = string.gsub(inside, idgham[i].a, idgham[i].b)
  296. end
  297. end
  298. if rules == "idgham" then
  299. for i = 1,#digraphsfvidgham do
  300. inside = string.gsub(inside, digraphsfvidgham[i].a, digraphsfvidgham[i].b)
  301. end
  302. else
  303. for i = 1,#digraphsfv do
  304. inside = string.gsub(inside, digraphsfv[i].a, digraphsfv[i].b)
  305. end
  306. end
  307. for i = 1,#singlefv do
  308. inside = string.gsub(inside, singlefv[i].a, singlefv[i].b)
  309. end
  310. for i = 1,#longv do
  311. inside = string.gsub(inside, longv[i].a, longv[i].b)
  312. end
  313. for i = 1,#shortv do
  314. inside = string.gsub(inside, shortv[i].a, shortv[i].b)
  315. end
  316. for i = 1,#punctuation do
  317. inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
  318. end
  319. for i = 1,#null do
  320. inside = string.gsub(inside, null[i].a, null[i].b)
  321. end
  322. inside = indnum(inside)
  323. return string.format("\\txarb{%s}", inside)
  324. end)
  325. return str
  326. end
  327. local function fullvoceasy(str, rules)
  328. str = string.gsub(str, "\\arb(%b{})", function(inside)
  329. inside = string.sub(inside, 2, -2)
  330. for i = 1,#hamzafveasy do
  331. inside = string.gsub(inside, hamzafveasy[i].a, hamzafveasy[i].b)
  332. end
  333. for i = 1,#tanwinfveasy do
  334. inside = string.gsub(inside, tanwinfveasy[i].a, tanwinfveasy[i].b)
  335. end
  336. for i = 1,#trigraphsfveasy do
  337. inside = string.gsub(inside, trigraphsfveasy[i].a, trigraphsfveasy[i].b)
  338. end
  339. if rules == "nosukun" then
  340. for i = 1,#digraphsfveasy do
  341. inside = string.gsub(inside, digraphsfveasy[i].a, digraphsfveasy[i].b)
  342. end
  343. else
  344. for i = 1,#digraphsfv do
  345. inside = string.gsub(inside, digraphsfv[i].a, digraphsfv[i].b)
  346. end
  347. end
  348. if rules == "nosukun" then
  349. for i = 1,#singlefveasy do
  350. inside = string.gsub(inside, singlefveasy[i].a, singlefveasy[i].b)
  351. end
  352. else
  353. for i = 1,#singlefv do
  354. inside = string.gsub(inside, singlefv[i].a, singlefv[i].b)
  355. end
  356. end
  357. for i = 1,#longv do
  358. inside = string.gsub(inside, longv[i].a, longv[i].b)
  359. end
  360. for i = 1,#shortv do
  361. inside = string.gsub(inside, shortv[i].a, shortv[i].b)
  362. end
  363. for i = 1,#punctuation do
  364. inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
  365. end
  366. for i = 1,#null do
  367. inside = string.gsub(inside, null[i].a, null[i].b)
  368. end
  369. inside = indnum(inside)
  370. return string.format("\\txarb{%s}", inside)
  371. end)
  372. return str
  373. end
  374. local function novoc(str)
  375. str = string.gsub(str, "\\arb(%b{})", function(inside)
  376. inside = string.sub(inside, 2, -2)
  377. for i = 1,#hamza do
  378. inside = string.gsub(inside, hamza[i].a, hamza[i].b)
  379. end
  380. for i = 1,#tanwinnv do
  381. inside = string.gsub(inside, tanwinnv[i].a, tanwinnv[i].b)
  382. end
  383. for i = 1,#trigraphsnv do
  384. inside = string.gsub(inside, trigraphsnv[i].a, trigraphsnv[i].b)
  385. end
  386. for i = 1,#digraphs do
  387. inside = string.gsub(inside, digraphs[i].a, digraphs[i].b)
  388. end
  389. for i = 1,#single do
  390. inside = string.gsub(inside, single[i].a, single[i].b)
  391. end
  392. for i = 1,#longvnv do
  393. inside = string.gsub(inside, longvnv[i].a, longvnv[i].b)
  394. end
  395. for i = 1,#shortvnv do
  396. inside = string.gsub(inside, shortvnv[i].a, shortvnv[i].b)
  397. end
  398. for i = 1,#punctuation do
  399. inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
  400. end
  401. for i = 1,#null do
  402. inside = string.gsub(inside, null[i].a, null[i].b)
  403. end
  404. inside = indnum(inside)
  405. return string.format("\\txarb{%s}", inside)
  406. end)
  407. return str
  408. end
  409. local function novoceasy(str)
  410. str = string.gsub(str, "\\arb(%b{})", function(inside)
  411. inside = string.sub(inside, 2, -2)
  412. for i = 1,#hamzaeasy do
  413. inside = string.gsub(inside, hamzaeasy[i].a, hamzaeasy[i].b)
  414. end
  415. for i = 1,#tanwinnv do
  416. inside = string.gsub(inside, tanwinnv[i].a, tanwinnv[i].b)
  417. end
  418. for i = 1,#trigraphsnv do
  419. inside = string.gsub(inside, trigraphsnv[i].a, trigraphsnv[i].b)
  420. end
  421. for i = 1,#digraphs do
  422. inside = string.gsub(inside, digraphs[i].a, digraphs[i].b)
  423. end
  424. for i = 1,#single do
  425. inside = string.gsub(inside, single[i].a, single[i].b)
  426. end
  427. for i = 1,#longvnv do
  428. inside = string.gsub(inside, longvnv[i].a, longvnv[i].b)
  429. end
  430. for i = 1,#shortvnv do
  431. inside = string.gsub(inside, shortvnv[i].a, shortvnv[i].b)
  432. end
  433. for i = 1,#punctuation do
  434. inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
  435. end
  436. for i = 1,#null do
  437. inside = string.gsub(inside, null[i].a, null[i].b)
  438. end
  439. inside = indnum(inside)
  440. return string.format("\\txarb{%s}", inside)
  441. end)
  442. return str
  443. end
  444. local function transdmg(str, rules)
  445. str = string.gsub(str, "\\arb(%b{})", function(inside)
  446. inside = string.sub(inside, 2, -2)
  447. for i = 1,#hamzatrdmg do
  448. inside = string.gsub(inside, hamzatrdmg[i].a, hamzatrdmg[i].b)
  449. end
  450. for i = 1,#tanwintrdmg do
  451. inside = string.gsub(inside, tanwintrdmg[i].a, tanwintrdmg[i].b)
  452. end
  453. for i = 1,#trigraphstrdmg do
  454. inside = string.gsub(inside, trigraphstrdmg[i].a, trigraphstrdmg[i].b)
  455. end
  456. if rules == "idgham" then
  457. for i = 1,#idghamtrdmg do
  458. inside = string.gsub(inside, idghamtrdmg[i].a, idghamtrdmg[i].b)
  459. end
  460. end
  461. for i = 1,#digraphstrdmg do
  462. inside = string.gsub(inside, digraphstrdmg[i].a, digraphstrdmg[i].b)
  463. end
  464. for i = 1,#singletrdmg do
  465. inside = string.gsub(inside, singletrdmg[i].a, singletrdmg[i].b)
  466. end
  467. for i = 1,#longvtrdmg do
  468. inside = string.gsub(inside, longvtrdmg[i].a, longvtrdmg[i].b)
  469. end
  470. for i = 1,#shortvtrdmg do
  471. inside = string.gsub(inside, shortvtrdmg[i].a, shortvtrdmg[i].b)
  472. end
  473. for i = 1,#punctuationtr do
  474. inside = string.gsub(inside, punctuationtr[i].a, punctuationtr[i].b)
  475. end
  476. for i = 1,#nulltr do
  477. inside = string.gsub(inside, nulltr[i].a, nulltr[i].b)
  478. end
  479. return string.format("\\txtrans{%s}", inside)
  480. end)
  481. return str
  482. end
  483. local function transloc(str)
  484. str = string.gsub(str, "\\arb(%b{})", function(inside)
  485. inside = string.sub(inside, 2, -2)
  486. for i = 1,#hamzatrloc do
  487. inside = string.gsub(inside, hamzatrloc[i].a, hamzatrloc[i].b)
  488. end
  489. for i = 1,#tanwintrloc do
  490. inside = string.gsub(inside, tanwintrloc[i].a, tanwintrloc[i].b)
  491. end
  492. for i = 1,#trigraphstrloc do
  493. inside = string.gsub(inside, trigraphstrloc[i].a, trigraphstrloc[i].b)
  494. end
  495. for i = 1,#digraphstrloc do
  496. inside = string.gsub(inside, digraphstrloc[i].a, digraphstrloc[i].b)
  497. end
  498. for i = 1,#singletrloc do
  499. inside = string.gsub(inside, singletrloc[i].a, singletrloc[i].b)
  500. end
  501. for i = 1,#longvtrloc do
  502. inside = string.gsub(inside, longvtrloc[i].a, longvtrloc[i].b)
  503. end
  504. for i = 1,#shortvtrloc do
  505. inside = string.gsub(inside, shortvtrloc[i].a, shortvtrloc[i].b)
  506. end
  507. for i = 1,#finaltrloc do
  508. inside = string.gsub(inside, finaltrloc[i].a, finaltrloc[i].b)
  509. end
  510. for i = 1,#punctuationtr do
  511. inside = string.gsub(inside, punctuationtr[i].a, punctuationtr[i].b)
  512. end
  513. for i = 1,#nulltr do
  514. inside = string.gsub(inside, nulltr[i].a, nulltr[i].b)
  515. end
  516. return string.format("\\txtrans{%s}", inside)
  517. end)
  518. return str
  519. end
  520. local function transarabica(str)
  521. str = string.gsub(str, "\\arb(%b{})", function(inside)
  522. inside = string.sub(inside, 2, -2)
  523. for i = 1,#hamzatrarabica do
  524. inside = string.gsub(inside, hamzatrarabica[i].a, hamzatrarabica[i].b)
  525. end
  526. for i = 1,#tanwintrloc do
  527. inside = string.gsub(inside, tanwintrloc[i].a, tanwintrloc[i].b)
  528. end
  529. for i = 1,#trigraphstrarabica do
  530. inside = string.gsub(inside, trigraphstrarabica[i].a, trigraphstrarabica[i].b)
  531. end
  532. for i = 1,#digraphstrarabica do
  533. inside = string.gsub(inside, digraphstrarabica[i].a, digraphstrarabica[i].b)
  534. end
  535. for i = 1,#singletrarabica do
  536. inside = string.gsub(inside, singletrarabica[i].a, singletrarabica[i].b)
  537. end
  538. for i = 1,#longvtrarabica do
  539. inside = string.gsub(inside, longvtrarabica[i].a, longvtrarabica[i].b)
  540. end
  541. for i = 1,#shortvtrloc do
  542. inside = string.gsub(inside, shortvtrloc[i].a, shortvtrloc[i].b)
  543. end
  544. for i = 1,#punctuationtr do
  545. inside = string.gsub(inside, punctuationtr[i].a, punctuationtr[i].b)
  546. end
  547. for i = 1,#nulltr do
  548. inside = string.gsub(inside, nulltr[i].a, nulltr[i].b)
  549. end
  550. return string.format("\\txtrans{%s}", inside)
  551. end)
  552. return str
  553. end
  554. local function processbuckw(str)
  555. str = string.gsub(str, "\\arb(%b{})", function(inside)
  556. inside = string.sub(inside, 2, -2)
  557. for i = 1,#buckwalter do
  558. inside = string.gsub(inside, buckwalter[i].a, buckwalter[i].b)
  559. end
  560. return string.format("\\arb{%s}", inside)
  561. end)
  562. return str
  563. end
  564. function processvoc(str, rules, scheme)
  565. str = "\\arb{".. str.."}"
  566. str = processarbnull(str, scheme)
  567. str = takeoutcapetc(str)
  568. str = protectarb(str)
  569. str = breakcmd(str)
  570. str = holdcmd(str)
  571. if scheme == "buckwalter" then
  572. str = processbuckw(str)
  573. else end
  574. if rules == "easy" or rules == "easynosukun" then
  575. str = voceasy(str)
  576. elseif rules == "dflt" or rules == "idgham" then
  577. str = voc(str, rules)
  578. else end
  579. str = unprotectarb(str)
  580. return str
  581. end
  582. function processfullvoc(str, rules, scheme)
  583. str = "\\arb{".. str.."}"
  584. str = processarbnull(str, scheme)
  585. str = takeoutcapetc(str)
  586. str = protectarb(str)
  587. str = breakcmd(str)
  588. str = holdcmd(str)
  589. if scheme == "buckwalter" then
  590. str = processbuckw(str)
  591. else end
  592. if rules == "easy" then
  593. str = fullvoceasy(str, "sukun")
  594. elseif rules == "easynosukun" then
  595. str = fullvoceasy(str, "nosukun")
  596. elseif rules == "dflt" or rules == "idgham" then
  597. str = fullvoc(str, rules)
  598. else end
  599. str = unprotectarb(str)
  600. return str
  601. end
  602. function processnovoc(str, rules, scheme)
  603. str = "\\arb{".. str.."}"
  604. str = processarbnull(str, scheme)
  605. str = takeoutcapetc(str)
  606. str = protectarb(str)
  607. str = breakcmd(str)
  608. str = holdcmd(str)
  609. if scheme == "buckwalter" then
  610. str = processbuckw(str)
  611. else end
  612. if rules == "easy" or rules == "easynosukun" then
  613. str = novoceasy(str)
  614. elseif rules == "dflt" or rules == "idgham" then
  615. str = novoc(str)
  616. else end
  617. str = unprotectarb(str)
  618. return str
  619. end
  620. function processtrans(str, mode, rules, scheme)
  621. str = "\\arb{".. str.."}"
  622. str = processdiscretionary(str)
  623. str = processarbnull(str, scheme)
  624. str = takeoutabjad(str)
  625. str = protectarb(str)
  626. str = breakcmd(str)
  627. str = holdcmd(str)
  628. if scheme == "buckwalter" then
  629. str = processbuckw(str)
  630. end
  631. if mode == "dmg" then
  632. str = transdmg(str, rules)
  633. elseif mode == "loc" then
  634. str = transloc(str)
  635. elseif mode == "arabica" then
  636. str = transarabica(str)
  637. end
  638. str = unprotectarb(str)
  639. return str
  640. end
  641. function newarbmark(abbr, rtlmk, ltrmk)
  642. table.insert(arbmarks, {a = abbr, b = rtlmk, c = ltrmk})
  643. return true
  644. end
  645. local function isintable(table, element)
  646. for i = 1,#table do
  647. if table[i].a == element then
  648. return true
  649. end
  650. end
  651. return false
  652. end
  653. function processarbmarks(str)
  654. if not isintable(arbmarks, str) then
  655. str = "\\LR{<??>}"
  656. else
  657. if tex.textdir == "TLT" then
  658. for i = 1,#arbmarks do
  659. str = string.gsub(str, arbmarks[i].a, arbmarks[i].c)
  660. end
  661. else
  662. for i = 1,#arbmarks do
  663. str = string.gsub(str, arbmarks[i].a, arbmarks[i].b)
  664. end
  665. end
  666. end
  667. return str
  668. end
  669. function uc(str)
  670. str = string.gsub(str, "(\\txtrans.?)(%b{})", function(tag, body)
  671. body = string.sub(body, 2, -2)
  672. return string.format("%s", body)
  673. end)
  674. -- Allah and ibn
  675. str = string.gsub(str, "(al%-lāh)([uai]?)", "{Allāh%2}")
  676. str = string.gsub(str, "([%'%-]?)(l%-lāh)([uai]?)", "%1{Llāh%3}")
  677. str = string.gsub(str, "(%s[%(%<%[]?)([i%']?b[n%.])", "%1{%2}")
  678. for i = 1,#lcuc do
  679. str = string.gsub(str, "^([%S]-%-[`']?)"..lcuc[i].a, "{%1"..lcuc[i].b.."}")
  680. end
  681. for i = 1,#lcuc do
  682. str = string.gsub(str, "(%s[%(%<%[]?)([%S]-%-[`']?)"..lcuc[i].a, "%1{%2"..lcuc[i].b.."}")
  683. end
  684. for i = 1,#lcuc do
  685. str = string.gsub(str, "^([%S]-%-ʿ)"..lcuc[i].a, "{%1"..lcuc[i].b.."}")
  686. end
  687. for i = 1,#lcuc do
  688. str = string.gsub(str, "(%s[%(%<%[]?)([%S]-%-ʿ)"..lcuc[i].a, "%1{%2"..lcuc[i].b.."}")
  689. end
  690. for i = 1,#lcuc do
  691. str = string.gsub(str, "^([%S]-%-ʾ)"..lcuc[i].a, "{%1"..lcuc[i].b.."}")
  692. end
  693. for i = 1,#lcuc do
  694. str = string.gsub(str, "(%s[%(%<%[]?)([%S]-%-ʾ)"..lcuc[i].a, "%1{%2"..lcuc[i].b.."}")
  695. end
  696. for i = 1,#lcuc do
  697. str = string.gsub(str, "^([`'])"..lcuc[i].a, "{%1"..lcuc[i].b.."}")
  698. end
  699. for i = 1,#lcuc do
  700. str = string.gsub(str, "(%s[%(%<%[]?)([`'])"..lcuc[i].a, "%1{%2"..lcuc[i].b.."}")
  701. end
  702. for i = 1,#lcuc do
  703. str = string.gsub(str, "^(ʾ)"..lcuc[i].a, "{%1"..lcuc[i].b.."}")
  704. end
  705. for i = 1,#lcuc do
  706. str = string.gsub(str, "(%s[%(%<%[]?)(ʾ)"..lcuc[i].a, "%1{%2"..lcuc[i].b.."}")
  707. end
  708. for i = 1,#lcuc do
  709. str = string.gsub(str, "^(ʿ)"..lcuc[i].a, "{%1"..lcuc[i].b.."}")
  710. end
  711. for i = 1,#lcuc do
  712. str = string.gsub(str, "(%s[%(%<%[]?)(ʿ)"..lcuc[i].a, "%1{%2"..lcuc[i].b.."}")
  713. end
  714. for i = 1,#lcuc do
  715. str = string.gsub(str, "^"..lcuc[i].a, lcuc[i].b)
  716. end
  717. for i = 1,#lcuc do
  718. str = string.gsub(str, "(%s[%(%<%[]?)"..lcuc[i].a, "%1"..lcuc[i].b)
  719. end
  720. return "\\txtrans{"..str.."}"
  721. end
  722. -- this function is adapted from an 'obsolete project' of Khaled
  723. -- Hosny's that dates back to 2010. Thanks to him.
  724. -- See https://github.com/khaledhosny/lualatex-arabic
  725. function abjadify(n)
  726. local abjadnum = ""
  727. if n >= 1000 then
  728. for i=1,math.floor(n/1000) do
  729. abjadnum = abjadnum .. abjad[4][1]
  730. end
  731. n = math.fmod(n,1000)
  732. end
  733. if n >= 100 then
  734. abjadnum = abjadnum .. abjad[3][math.floor(n/100)]
  735. n = math.fmod(n, 100)
  736. end
  737. if n >= 10 then
  738. abjadnum = abjadnum .. abjad[2][math.floor(n/10)]
  739. n = math.fmod(n, 10)
  740. end
  741. if n >= 1 then
  742. abjadnum = abjadnum .. abjad[1][math.floor(n/1)]
  743. end
  744. return "\\arb[novoc]{"..abjadnum.."}"
  745. end
  746. function abraces(str)
  747. if tex.textdir == "TRT" then
  748. str = "\\}"..str.."\\{"
  749. elseif tex.textdir == "TLT" then
  750. str = "\\{"..str.."\\}"
  751. end
  752. return str
  753. end
  754. function aemph(str)
  755. if tex.textdir == "TRT" then
  756. str = "$\\overline{\\text{"..str.."}}$"
  757. elseif tex.textdir == "TLT" then
  758. str = "$\\underline{\\text{"..str.."}}$"
  759. end
  760. return str
  761. end