aboutsummaryrefslogtreecommitdiff
path: root/arabluatex.lua
diff options
context:
space:
mode:
Diffstat (limited to 'arabluatex.lua')
-rw-r--r--arabluatex.lua240
1 files changed, 176 insertions, 64 deletions
diff --git a/arabluatex.lua b/arabluatex.lua
index a91e211..114a569 100644
--- a/arabluatex.lua
+++ b/arabluatex.lua
@@ -2,24 +2,23 @@
2This file is part of the `arabluatex' package 2This file is part of the `arabluatex' package
3 3
4ArabLuaTeX -- Processing ArabTeX notation under LuaLaTeX 4ArabLuaTeX -- Processing ArabTeX notation under LuaLaTeX
5Copyright (C) 2016--2019 Robert Alessi 5Copyright (C) 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023
6Robert Alessi <alessi@robertalessi.net>
6 7
7Please send error reports and suggestions for improvements to Robert 8Permission to use, copy, modify, and distribute this software for any
8Alessi <alessi@robertalessi.net> 9purpose with or without fee is hereby granted, provided that the above
10copyright notice and this permission notice appear in all copies.
9 11
10This program is free software: you can redistribute it and/or modify 12THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11it under the terms of the GNU General Public License as published by 13WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12the Free Software Foundation, either version 3 of the License, or 14MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13(at your option) any later version. 15ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 19
15This program is distributed in the hope that it will be useful, but 20Please send error reports and suggestions for improvements to Robert
16WITHOUT ANY WARRANTY; without even the implied warranty of 21Alessi <alessi@robertalessi.net>
17MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18General Public License for more details.
19
20You should have received a copy of the GNU General Public License
21along with this program. If not, see
22<http://www.gnu.org/licenses/>.
23--]] 22--]]
24 23
25arabluatex = {} 24arabluatex = {}
@@ -54,11 +53,26 @@ local cmd = lpeg.Cs(dblbkslash * ascii^1 * cmdstar^-1)
54local rawcmd = lpeg.Cs(dblbkslash * ascii^1) 53local rawcmd = lpeg.Cs(dblbkslash * ascii^1)
55local aftercmd = lpeg.Cs(lpeg.S("*[{,.?;:'`\"") + dblbkslash) 54local aftercmd = lpeg.Cs(lpeg.S("*[{,.?;:'`\"") + dblbkslash)
56local cmdargs = lpeg.Cs(spce^-1 * bsqbracketsii * bcbracesii * bsqbrackets^-1) 55local cmdargs = lpeg.Cs(spce^-1 * bsqbracketsii * bcbracesii * bsqbrackets^-1)
56local cmdargsnobs = lpeg.Cs(spce^-1 * bcbracesii)
57local arbargs = lpeg.Cs(spce^-1 * bsqbrackets^-1 * bcbraces) 57local arbargs = lpeg.Cs(spce^-1 * bsqbrackets^-1 * bcbraces)
58local baytargs = lpeg.Cs(spce * bcbraces * bsqbrackets^-1 * bcbraces) 58local baytargs = lpeg.Cs(spce * bcbraces * bsqbrackets^-1 * bcbraces)
59local arind = lpeg.Cs(dblbkslash * lpeg.P("arind") * spce^-1 * bsqbracketsii) 59local arind = lpeg.Cs(dblbkslash * lpeg.P("arind") * spce^-1 * bsqbracketsii)
60 60
61local function protectarb(str) 61local function protectarb(str)
62 -- \App[]{}{}
63 str = string.gsub(str, "(\\App%s?)(%b{})(%b{})", "%1[]%2%3")
64 str = gsub(str, lpeg.P("\\App") * spcenc^-1 * bsqbrackets * bcbraces * bcbraces,
65 function(opt, lem, rdg)
66 opt = string.sub(opt, 2, -2)
67 lem = string.sub(lem, 2, -2)
68 rdg = string.sub(rdg, 2, -2)
69 if opt == ""
70 then
71 return string.format("\\app{%s%s}", lem, rdg)
72 else
73 return string.format("\\app[%s]{%s%s}", opt, lem, rdg)
74 end
75 end)
62 str = string.gsub(str, "(\\arb%s?)(%[.-%])(%b{})", "\\al@brk{\\arb%2%3}") 76 str = string.gsub(str, "(\\arb%s?)(%[.-%])(%b{})", "\\al@brk{\\arb%2%3}")
63 str = string.gsub(str, "(\\LR%s?)(%b{})", "\\@LR%2") 77 str = string.gsub(str, "(\\LR%s?)(%b{})", "\\@LR%2")
64 str = string.gsub(str, "(\\RL%s?)(%b{})", "\\@RL%2") 78 str = string.gsub(str, "(\\RL%s?)(%b{})", "\\@RL%2")
@@ -90,11 +104,11 @@ local outofarb = {
90local albrkcmds = { 104local albrkcmds = {
91 "begin", 105 "begin",
92 "end", 106 "end",
93 "par",
94 "LRmarginpar", 107 "LRmarginpar",
95 "arbmark", 108 "arbmark",
96 "abjad", 109 "abjad",
97 "ayah" 110 "ayah",
111 "SetArbNumbers"
98} 112}
99local brkcmds = {} 113local brkcmds = {}
100 114
@@ -120,13 +134,15 @@ function arabluatex.mkarbbreak(str, opt)
120end 134end
121 135
122local function breakcmd(str) 136local function breakcmd(str)
137 -- \par
138 str = gsub(str, dblbkslash * lpeg.Cs("par") * cmdargsnobs, "\\al@brk{%1%2%3}")
123 -- process \item[], then \item[] 139 -- process \item[], then \item[]
124 str = string.gsub(str, "\\(item.?)(%b[])", 140 str = string.gsub(str, "\\(item.?)(%b[])",
125 function(tag, body) 141 function(tag, body)
126 body = string.sub(body, 2, -2) 142 body = string.sub(body, 2, -2)
127 return string.format("\\al@brk{\\item[\\arb{%s}] }", body) 143 return string.format("\\al@brk{\\item[\\arb{%s}] }", body)
128 end) 144 end)
129 str = string.gsub(str, "(\\item)(%s+)", "%1{}%2") 145 str = string.gsub(str, "(\\item)(%s+)", "%1{}%2")
130 -- \textcolor 146 -- \textcolor
131 str = string.gsub(str, "\\(textcolor%s?)(%b{})(%b{})", 147 str = string.gsub(str, "\\(textcolor%s?)(%b{})(%b{})",
132 function(tag, bodycolor, bodytext) 148 function(tag, bodycolor, bodytext)
@@ -170,19 +186,38 @@ local function holdcmd(str)
170 return str 186 return str
171end 187end
172 188
173local function arbnum(str) 189local indorarbnum = "Indian"
190
191function arabluatex.setnums(opt)
192 if opt == "Indian"
193 then
194 indorarbnum = "Indian"
195 else
196 indorarbnum = "Arabic"
197 end
198end
199
200local function arbnum(str) -- not used, see below
174 str = string.gsub(str, "([0-9%,%-%/]+)", function(num) 201 str = string.gsub(str, "([0-9%,%-%/]+)", function(num)
175 return string.reverse(num) 202 return string.reverse(num)
176 end) 203 end)
177 return str 204 return str
178end 205end
179 206
180local function indnum(str) 207local function indnum(str, dir)
181 str = string.gsub(str, "([0-9%,%-%/]+)", function(num) 208 if dir == "ltr"
182 return string.reverse(num) 209 then
183 end) 210 -- do nothing
184 for i = 1,#numbers do 211 else
185 str = string.gsub(str, numbers[i].a, numbers[i].b) 212 str = string.gsub(str, "([0-9%,%-%/]+)", function(num)
213 return string.reverse(num)
214 end)
215 end
216 if indorarbnum == "Indian"
217 then
218 for i = 1,#numbers do
219 str = string.gsub(str, numbers[i].a, numbers[i].b)
220 end
186 end 221 end
187 return str 222 return str
188end 223end
@@ -269,13 +304,23 @@ local function takeoutarb(str)
269 end 304 end
270 str = string.gsub(str, "(\\arb%s?)(%b{})", function(tag, body) 305 str = string.gsub(str, "(\\arb%s?)(%b{})", function(tag, body)
271 body = string.sub(body, 2, -2) 306 body = string.sub(body, 2, -2)
272 return string.format("%s", body) 307 return string.format("\\al@brk{%s{%s}}", tag, body)
273 end) 308 end)
274 str = string.gsub(str, "\\@rb", "\\arb") 309 str = string.gsub(str, "\\@rb", "\\arb")
275 str = "\\arb{"..str.."}" 310 str = "\\arb{"..str.."}"
276 return str 311 return str
277end 312end
278 313
314-- I owe this function to M. Krüger and U. Fischer. Thank to them both.
315local function getrenderer()
316 local a = nil
317 if font.getfont(font.current()).specification
318 then
319 a=font.getfont(font.current()).specification.features.normal.mode
320 end
321 return a
322end
323
279local function voc(str, rules) 324local function voc(str, rules)
280 str = string.gsub(str, "\\arb(%b{})", function(inside) 325 str = string.gsub(str, "\\arb(%b{})", function(inside)
281 inside = string.sub(inside, 2, -2) 326 inside = string.sub(inside, 2, -2)
@@ -311,8 +356,16 @@ local function voc(str, rules)
311 for i = 1,#shortv do 356 for i = 1,#shortv do
312 inside = string.gsub(inside, shortv[i].a, shortv[i].b) 357 inside = string.gsub(inside, shortv[i].a, shortv[i].b)
313 end 358 end
314 for i = 1,#punctuation do 359 if getrenderer() == "harf"
315 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b) 360 then
361 for i = 1,#punctuationhb do
362 inside = string.gsub(inside, punctuationhb[i].a,
363 punctuationhb[i].b)
364 end
365 else
366 for i = 1,#punctuation do
367 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
368 end
316 end 369 end
317 for i = 1,#null do 370 for i = 1,#null do
318 inside = string.gsub(inside, null[i].a, null[i].b) 371 inside = string.gsub(inside, null[i].a, null[i].b)
@@ -347,8 +400,16 @@ local function voceasy(str)
347 for i = 1,#shortv do 400 for i = 1,#shortv do
348 inside = string.gsub(inside, shortv[i].a, shortv[i].b) 401 inside = string.gsub(inside, shortv[i].a, shortv[i].b)
349 end 402 end
350 for i = 1,#punctuation do 403 if getrenderer() == "harf"
351 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b) 404 then
405 for i = 1,#punctuationhb do
406 inside = string.gsub(inside, punctuationhb[i].a,
407 punctuationhb[i].b)
408 end
409 else
410 for i = 1,#punctuation do
411 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
412 end
352 end 413 end
353 for i = 1,#null do 414 for i = 1,#null do
354 inside = string.gsub(inside, null[i].a, null[i].b) 415 inside = string.gsub(inside, null[i].a, null[i].b)
@@ -400,8 +461,16 @@ local function fullvoc(str, rules)
400 for i = 1,#shortv do 461 for i = 1,#shortv do
401 inside = string.gsub(inside, shortv[i].a, shortv[i].b) 462 inside = string.gsub(inside, shortv[i].a, shortv[i].b)
402 end 463 end
403 for i = 1,#punctuation do 464 if getrenderer() == "harf"
404 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b) 465 then
466 for i = 1,#punctuationhb do
467 inside = string.gsub(inside, punctuationhb[i].a,
468 punctuationhb[i].b)
469 end
470 else
471 for i = 1,#punctuation do
472 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
473 end
405 end 474 end
406 for i = 1,#null do 475 for i = 1,#null do
407 inside = string.gsub(inside, null[i].a, null[i].b) 476 inside = string.gsub(inside, null[i].a, null[i].b)
@@ -448,8 +517,16 @@ local function fullvoceasy(str, rules)
448 for i = 1,#shortv do 517 for i = 1,#shortv do
449 inside = string.gsub(inside, shortv[i].a, shortv[i].b) 518 inside = string.gsub(inside, shortv[i].a, shortv[i].b)
450 end 519 end
451 for i = 1,#punctuation do 520 if getrenderer() == "harf"
452 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b) 521 then
522 for i = 1,#punctuationhb do
523 inside = string.gsub(inside, punctuationhb[i].a,
524 punctuationhb[i].b)
525 end
526 else
527 for i = 1,#punctuation do
528 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
529 end
453 end 530 end
454 for i = 1,#null do 531 for i = 1,#null do
455 inside = string.gsub(inside, null[i].a, null[i].b) 532 inside = string.gsub(inside, null[i].a, null[i].b)
@@ -484,8 +561,16 @@ local function novoc(str)
484 for i = 1,#shortvnv do 561 for i = 1,#shortvnv do
485 inside = string.gsub(inside, shortvnv[i].a, shortvnv[i].b) 562 inside = string.gsub(inside, shortvnv[i].a, shortvnv[i].b)
486 end 563 end
487 for i = 1,#punctuation do 564 if getrenderer() == "harf"
488 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b) 565 then
566 for i = 1,#punctuationhb do
567 inside = string.gsub(inside, punctuationhb[i].a,
568 punctuationhb[i].b)
569 end
570 else
571 for i = 1,#punctuation do
572 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
573 end
489 end 574 end
490 for i = 1,#null do 575 for i = 1,#null do
491 inside = string.gsub(inside, null[i].a, null[i].b) 576 inside = string.gsub(inside, null[i].a, null[i].b)
@@ -520,8 +605,16 @@ local function novoceasy(str)
520 for i = 1,#shortvnv do 605 for i = 1,#shortvnv do
521 inside = string.gsub(inside, shortvnv[i].a, shortvnv[i].b) 606 inside = string.gsub(inside, shortvnv[i].a, shortvnv[i].b)
522 end 607 end
523 for i = 1,#punctuation do 608 if getrenderer() == "harf"
524 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b) 609 then
610 for i = 1,#punctuationhb do
611 inside = string.gsub(inside, punctuationhb[i].a,
612 punctuationhb[i].b)
613 end
614 else
615 for i = 1,#punctuation do
616 inside = string.gsub(inside, punctuation[i].a, punctuation[i].b)
617 end
525 end 618 end
526 for i = 1,#null do 619 for i = 1,#null do
527 inside = string.gsub(inside, null[i].a, null[i].b) 620 inside = string.gsub(inside, null[i].a, null[i].b)
@@ -532,11 +625,19 @@ local function novoceasy(str)
532 return str 625 return str
533end 626end
534 627
535local function transdmg(str, rules) 628local function transdmg(str, mode, rules)
536 str = string.gsub(str, "\\arb(%b{})", function(inside) 629 str = string.gsub(str, "\\arb(%b{})", function(inside)
537 inside = string.sub(inside, 2, -2) 630 inside = string.sub(inside, 2, -2)
538 for i = 1,#hamzatrdmg do 631 if mode == "dmg"
539 inside = string.gsub(inside, hamzatrdmg[i].a, hamzatrdmg[i].b) 632 then
633 for i = 1,#hamzatrnoinitialdmg do
634 inside = string.gsub(inside, hamzatrnoinitialdmg[i].a, hamzatrnoinitialdmg[i].b)
635 end
636 elseif mode == "dmg+"
637 then
638 for i = 1,#hamzatrdmg do
639 inside = string.gsub(inside, hamzatrdmg[i].a, hamzatrdmg[i].b)
640 end
540 end 641 end
541 for i = 1,#tanwintrdmg do 642 for i = 1,#tanwintrdmg do
542 inside = string.gsub(inside, tanwintrdmg[i].a, tanwintrdmg[i].b) 643 inside = string.gsub(inside, tanwintrdmg[i].a, tanwintrdmg[i].b)
@@ -567,7 +668,7 @@ local function transdmg(str, rules)
567 for i = 1,#nulltr do 668 for i = 1,#nulltr do
568 inside = string.gsub(inside, nulltr[i].a, nulltr[i].b) 669 inside = string.gsub(inside, nulltr[i].a, nulltr[i].b)
569 end 670 end
570 return string.format("%s", inside) 671 return string.format("\\altrfont{}%s", inside)
571 end) 672 end)
572 return str 673 return str
573end 674end
@@ -605,7 +706,7 @@ local function transloc(str)
605 for i = 1,#nulltr do 706 for i = 1,#nulltr do
606 inside = string.gsub(inside, nulltr[i].a, nulltr[i].b) 707 inside = string.gsub(inside, nulltr[i].a, nulltr[i].b)
607 end 708 end
608 return string.format("%s", inside) 709 return string.format("\\altrfont{}%s", inside)
609 end) 710 end)
610 return str 711 return str
611end 712end
@@ -640,7 +741,7 @@ local function transarabica(str)
640 for i = 1,#nulltr do 741 for i = 1,#nulltr do
641 inside = string.gsub(inside, nulltr[i].a, nulltr[i].b) 742 inside = string.gsub(inside, nulltr[i].a, nulltr[i].b)
642 end 743 end
643 return string.format("%s", inside) 744 return string.format("\\altrfont{}%s", inside)
644 end) 745 end)
645 return str 746 return str
646end 747end
@@ -660,11 +761,11 @@ local function processarind(str, mode)
660 str = gsub(str, arind * bcbraces, function(tag, arg) 761 str = gsub(str, arind * bcbraces, function(tag, arg)
661 arg = string.sub(arg, 2, -2) 762 arg = string.sub(arg, 2, -2)
662 if mode == "trans" then 763 if mode == "trans" then
663 return string.format("%s{\\txtrans{%s}}", tag, arg) 764 return string.format("%s{%s@\\txtrans{%s}}", tag, arg, arg)
664 else 765 else
665 arg = novoc(arg) 766 arg = novoc(arg)
666 arg = string.gsub(arg, "\\arabicfont%s?{}", "") 767 arg = string.gsub(arg, "\\arabicfont%s?{}", "")
667 return string.format("%s{\\txarb{%s}}", tag, arg) 768 return string.format("%s{%s@\\txarb{%s}}", tag, arg, arg)
668 end 769 end
669 end) 770 end)
670 return str 771 return str
@@ -724,7 +825,7 @@ local function processarbtoutf(str)
724 bbody = string.sub(bbody, 2, -2) 825 bbody = string.sub(bbody, 2, -2)
725 if tonumber(bbody) ~= nil then 826 if tonumber(bbody) ~= nil then
726 bbody = arabluatex.abjadify(bbody) 827 bbody = arabluatex.abjadify(bbody)
727 return string.format("\\oline*{\\arb[novoc]{%s}}", bbody) 828 return string.format("\\aoline*{\\arb[novoc]{%s}}", bbody)
728 else 829 else
729 return string.format("%s{%s}", btag, bbody) 830 return string.format("%s{%s}", btag, bbody)
730 end 831 end
@@ -739,16 +840,16 @@ local function processarbtoutf(str)
739 end) 840 end)
740 return string.format("%s{%s}", tag, body) 841 return string.format("%s{%s}", tag, body)
741 end) 842 end)
742 str = string.gsub(str, "(\\bayt)%s?(%b{})(%b[])(%b{})", function(tag, argi, argii, argiii) 843 str = string.gsub(str, "(\\bayt)%s?(%+?)(%b{})(%b[])(%b{})", function(tag, plus, argi, argii, argiii)
743 argi = string.sub(argi, 2, -2) 844 argi = string.sub(argi, 2, -2)
744 argii = string.sub(argii, 2, -2) 845 argii = string.sub(argii, 2, -2)
745 argiii = string.sub(argiii, 2, -2) 846 argiii = string.sub(argiii, 2, -2)
746 return string.format("%s*{\\arb{%s}}[\\arb{%s}]{\\arb{%s}}", tag, argi, argii, argiii) 847 return string.format("%s%s*{\\arb{%s}}[\\arb{%s}]{\\arb{%s}}", tag, argi, argii, argiii)
747 end) 848 end)
748 str = string.gsub(str, "(\\bayt)%s?(%b{})(%b{})", function(tag, argi, argii) 849 str = string.gsub(str, "(\\bayt)%s?(%+?)(%b{})(%b{})", function(tag, plus, argi, argii)
749 argi = string.sub(argi, 2, -2) 850 argi = string.sub(argi, 2, -2)
750 argii = string.sub(argii, 2, -2) 851 argii = string.sub(argii, 2, -2)
751 return string.format("%s*{\\arb{%s}}{\\arb{%s}}", tag, argi, argii) 852 return string.format("%s%s*{\\arb{%s}}{\\arb{%s}}", tag, plus, argi, argii)
752 end) 853 end)
753 str = string.gsub(str, "(\\prname)%s?(%b{})", function(tag, body) 854 str = string.gsub(str, "(\\prname)%s?(%b{})", function(tag, body)
754 body = string.sub(body, 2, -2) 855 body = string.sub(body, 2, -2)
@@ -841,6 +942,7 @@ function arabluatex.closestream()
841 local o = io.open(tex.jobname..utffilesuffix..".tex", "w") 942 local o = io.open(tex.jobname..utffilesuffix..".tex", "w")
842 local t = f:read("*a") 943 local t = f:read("*a")
843 t = string.gsub(t, "\\arabicfont{}", "") 944 t = string.gsub(t, "\\arabicfont{}", "")
945 t = string.gsub(t, "\\altrfont{}", "")
844 t = string.gsub(t, "\\par ", "\n\n") 946 t = string.gsub(t, "\\par ", "\n\n")
845 t = string.gsub(t, "(\\@al@ob)", "{") 947 t = string.gsub(t, "(\\@al@ob)", "{")
846 t = string.gsub(t, "(\\@al@cb@sp)", "} ") 948 t = string.gsub(t, "(\\@al@cb@sp)", "} ")
@@ -1003,8 +1105,8 @@ function arabluatex.processtrans(str, mode, rules, scheme)
1003 if scheme == "buckwalter" then 1105 if scheme == "buckwalter" then
1004 str = processbuckw(str) 1106 str = processbuckw(str)
1005 end 1107 end
1006 if mode == "dmg" then 1108 if mode == "dmg" or mode == "dmg+" then
1007 str = transdmg(str, rules) 1109 str = transdmg(str, mode, rules)
1008 elseif mode == "loc" then 1110 elseif mode == "loc" then
1009 str = transloc(str) 1111 str = transloc(str)
1010 elseif mode == "arabica" then 1112 elseif mode == "arabica" then
@@ -1080,6 +1182,7 @@ function arabluatex.uc(str)
1080 body = string.sub(body, 2, -2) 1182 body = string.sub(body, 2, -2)
1081 return string.format("%s", body) 1183 return string.format("%s", body)
1082 end) 1184 end)
1185 str = string.gsub(str, "\\altrfont%s?{}", "")
1083 str = string.gsub(str, "{", "\\@al@ob") 1186 str = string.gsub(str, "{", "\\@al@ob")
1084 str = string.gsub(str, "} ", "\\@al@cb@sp ") 1187 str = string.gsub(str, "} ", "\\@al@cb@sp ")
1085 str = string.gsub(str, "}", "\\@al@cb") 1188 str = string.gsub(str, "}", "\\@al@cb")
@@ -1134,6 +1237,7 @@ function arabluatex.uc(str)
1134 str = string.gsub(str, "\\@al@ob", "{") 1237 str = string.gsub(str, "\\@al@ob", "{")
1135 str = string.gsub(str, "\\@al@cb@sp ", "} ") 1238 str = string.gsub(str, "\\@al@cb@sp ", "} ")
1136 str = string.gsub(str, "\\@al@cb", "}") 1239 str = string.gsub(str, "\\@al@cb", "}")
1240 str = "\\altrfont{}"..str
1137 if export_utf == "yes" then 1241 if export_utf == "yes" then
1138 tofile = str 1242 tofile = str
1139 arabluatex.tooutfile(tofile) 1243 arabluatex.tooutfile(tofile)
@@ -1173,8 +1277,14 @@ function arabluatex.abjadify(n)
1173end 1277end
1174 1278
1175function arabluatex.abraces(str) 1279function arabluatex.abraces(str)
1176 if tex.textdir == "TRT" then 1280 if tex.textdir == "TRT"
1177 str = "\\}"..str.."\\{" 1281 then
1282 if getrenderer() == "harf"
1283 then
1284 str = "\\{"..str.."\\}"
1285 else
1286 str = "\\}"..str.."\\{"
1287 end
1178 elseif tex.textdir == "TLT" then 1288 elseif tex.textdir == "TLT" then
1179 str = "\\{"..str.."\\}" 1289 str = "\\{"..str.."\\}"
1180 end 1290 end
@@ -1183,12 +1293,12 @@ end
1183 1293
1184function arabluatex.aemph(str, opt) 1294function arabluatex.aemph(str, opt)
1185 if tex.textdir == "TRT" then 1295 if tex.textdir == "TRT" then
1186 str = "\\oline{\\textdir TRT{}"..str.."}" 1296 str = "\\aoline{\\textdir TRT{}"..str.."}"
1187 elseif tex.textdir == "TLT" then 1297 elseif tex.textdir == "TLT" then
1188 if opt == "over" then 1298 if opt == "over" then
1189 str = "\\oline{"..str.."}" 1299 str = "\\aoline{"..str.."}"
1190 else 1300 else
1191 str = "\\uline{"..str.."}" 1301 str = "\\auline{"..str.."}"
1192 end 1302 end
1193 end 1303 end
1194 return str 1304 return str
@@ -1197,7 +1307,9 @@ end
1197function arabluatex.ayah(str) 1307function arabluatex.ayah(str)
1198 if tonumber(str) ~= nil and str.len(str) < 4 then 1308 if tonumber(str) ~= nil and str.len(str) < 4 then
1199 if tex.textdir == "TRT" then 1309 if tex.textdir == "TRT" then
1200 str = indnum(str).."^^^^06dd" 1310 -- end of ayah is typeset LTR and the number comes after the
1311 -- sign (see https://github.com/aliftype/amiri/issues/263#issuecomment-1872979252)
1312 str = "{\\textdir TLT ".."^^^^06dd"..indnum(str, "ltr").."}"
1201 elseif tex.textdir == "TLT" then 1313 elseif tex.textdir == "TLT" then
1202 str = "\\arb[trans]{("..str..")}" 1314 str = "\\arb[trans]{("..str..")}"
1203 end 1315 end