Last active
December 22, 2015 14:49
-
-
Save phi-gamma/6488187 to your computer and use it in GitHub Desktop.
import the bidi code from Context (http://tex.stackexchange.com/q/132241); DON’T DO THIS AT HOME, use Context instead!
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
----------------------------------------------------------------------- | |
-- FILE: import-typo-dir.lua | |
-- DESCRIPTION: fake enough of Context to load typo-dir.lua | |
-- REQUIREMENTS: Context MkIV, Luoatfload, Lualibs etc. | |
-- AUTHOR: Philipp Gesang (Phg), <[email protected]> | |
-- VERSION: 0.0 | |
-- CREATED: 2013-09-08 19:58:40+0200 | |
----------------------------------------------------------------------- | |
-- | |
local err, warn, info = luatexbase.provides_module { | |
name = "import-typo-dir", | |
author = "Philipp Gesang", | |
description = "fake Context layer for loading typo-dir.lua", | |
} | |
info "This is not an excuse for not using Context!" | |
require "lualibs" -- we need the extended set | |
local texsprint = tex.sprint | |
local stringformat = string.format | |
local tableconcat = table.concat | |
local copynode = node.copy | |
----------------------------------------------------------------------- | |
--- prepare | |
----------------------------------------------------------------------- | |
--- 1) wrap Luatexbase attribute handler in a Context style interface | |
attributes = attributes or { } | |
local texsetattribute = tex.setattribute | |
local hidden = { | |
state = luatexbase.new_attribute ("typo-dir:state", true), | |
directions = luatexbase.new_attribute ("typo-dir:directions", true), | |
mathbidi = luatexbase.new_attribute ("typo-dir:mathbidi", true), | |
} | |
local a_directions = hidden.directions | |
attributes.private = attributes.private or function (attr_name) | |
local res = hidden [attr_name] | |
if not res then | |
res = luatexbase.new_attribute (attr_name) | |
end | |
return res | |
end | |
local unsetvalue = luatexbase.get_unset_value () | |
attributes.unsetvalue = unsetvalue | |
--- 2) simulate the multilingual interface; safe to purge afterwards | |
--- since Context uses local copies | |
interfaces = interfaces or { } | |
interfaces.variables = interfaces.variables or { } | |
interfaces.variables.global = "global" | |
interfaces.variables["local"] = "local" | |
interfaces.variables.default = "default" | |
interfaces.variables.on = "on" | |
interfaces.variables.yes = "yes" | |
--- 3) node tasks; we don’t have real node processors so we will need | |
--- to set up a makeshift interface | |
nodes.tasks = nodes.tasks or { } | |
nodes.tasks.enableaction = function () end | |
--- 4) commands namespace | |
commands = commands or { } -- already present due to luaotfload-extrablibs | |
--- 5) typesetters namespace | |
--- | |
--- With a current (as of 2013-09-08) Luaotfload this namespace | |
--- already exists since we load typo-krn as part of the ongoing | |
--- experiment with proper letterspacing support. At the moment | |
--- it looks like Latex/Microtype prefer a simplified approach | |
--- so the Luaotfload copy of typo-krn is likely to vanish in a | |
--- future release. | |
typesetters = typesetters or { } | |
--- 6) the Context namespace; cannot be cleaned up without breaking | |
--- things; srsly there needs to be a non-Context equivalent for | |
--- this | |
context = context or { } | |
setmetatable (context, { | |
--- this is quite primitive and considerably less functional than | |
--- the real deal as defined in cldf-ini.lua, but we already get | |
--- quite far with this reduced version | |
__index = function (t, k) | |
if k == "sprint" then | |
return function (...) texsprint (...) end | |
elseif type (k) == "string" then | |
local command = [[\]] .. k | |
return function (...) | |
local res = { command } | |
for i = 1, select ("#", ...) do | |
--- just simple grouped arguments | |
res [#res + 1] = "{" | |
res [#res + 1] = select (i, ...) | |
res [#res + 1] = "}" | |
end | |
texsprint (tableconcat (res)) | |
end | |
else | |
return context | |
end | |
end, | |
__call = function (t, fmt, first, ...) | |
if t == nil or fmt == nil then | |
return | |
end | |
local tf = type (fmt) | |
if tf == "string" then | |
if first then | |
texsprint (-1, stringformat (fmt, first, ...)) | |
else | |
texsprint (-1, fmt) | |
end | |
elseif tf == "function" then | |
texsprint (-1, fmt (first, ...)) | |
elseif first then --- and so on, | |
texsprint (-1, tostring (fmt), first, ...) | |
else | |
texsprint (-1, tostring (fmt)) | |
end | |
end, | |
}) | |
--- 7) catcodes namespace | |
catcodes = catcodes or { } | |
catcodes.numbers = catcodes.numbers or { } | |
catcodes.numbers.ctxcatcodes = -1 | |
--- 8) whatsit prototype; expected to be present in the nodepool | |
local n_textdir = node.new (node.id "whatsit", nodes.whatsitcodes.dir) | |
nodes.pool = nodes.pool or { } | |
nodes.pool.textdir = function (dir) | |
local n = copynode (n_textdir) | |
n.dir = dir | |
return n | |
end | |
--- 9) node identifiers | |
nodes.nodecodes = table.mirrored (nodes.nodecodes) --> convenience | |
---------------------------------------------------------------------- | |
--- import | |
----------------------------------------------------------------------- | |
require "char-def" --> characters.data (unicode) | |
require "char-ini" --> characters.* | |
--- the next three used to share “typo-dir.lua” before it was split | |
require "typo-dir" --> typesetters.directions | |
require "typo-dha" --> typesetters.directions | |
require "math-dir" --> typesetters.directions | |
----------------------------------------------------------------------- | |
--- wrappers | |
----------------------------------------------------------------------- | |
--- we use the *packagedata* namespace which should become canonical | |
--- anyways; also we keep a copy of typesetters.directions in a | |
--- subtable | |
packagedata = packagedata or { } | |
local directions = typesetters.directions | |
local typo_dir = { directions = directions } | |
packagedata.typo_dir = typo_dir | |
local directionprocessor = directions.process | |
local mathdirectionprocessor = directions.processmath | |
local processorid = "typesetters.directions" | |
--- emulate node tasks capability; we override the original definitions | |
--- of set() and setmath() with surrogates that work with Luatexbase | |
--- callback handlers | |
directions.set = nil | |
directions.setmath = nil | |
--- we need to track which callbacks the node processor is hooked | |
--- into since we lack the combined version Context has | |
local registered_as = { } --- procname -> callbacks | |
--- (node_t -> node_t) -> string -> string list -> bool | |
local add_processor = function (processor, name, ...) | |
for i=1, select ("#", ...) do | |
local callback = select (i, ...) | |
--- *IMPORTANT* the processor must be inserted at the top, | |
--- i.e. with a priority higher than any other callback! | |
luatexbase.add_to_callback (callback, processor, name, 1) | |
end | |
registered_as [name] = { ... } | |
return true | |
end | |
--- string -> bool | |
local remove_processor = function (name) | |
local callbacks = registered_as [name] | |
if callbacks then | |
for i=1, #callbacks do | |
luatexbase.remove_from_callback (callbacks [i], name) | |
end | |
return true | |
end | |
return false | |
end | |
--- we use the same callbacks as a node processor in Context | |
--- unit -> bool | |
local enabledirectionprocessor = function (math) | |
local processor | |
if math == true then | |
processor = function (hd) | |
--- different signature from the normal one | |
return mathdirectionprocessor (hd) | |
end | |
else | |
processor = function (hd) | |
return directionprocessor ("directions", a_directions, hd) | |
end | |
end | |
return add_processor (processor, | |
processorid, | |
"pre_linebreak_filter", | |
"hpack_filter") | |
end | |
typo_dir.enable = enabledirectionprocessor | |
--- unit -> bool | |
local disabledirectionprocessor = function ( ) | |
return remove_processor (processorid) | |
end | |
typo_dir.disable = disabledirectionprocessor | |
local active = false --- activation state of direction processor | |
typo_dir.set = function (n) | |
if not n or n == 0 then | |
n = unsetvalue | |
end | |
if not active then | |
info ("Installing Context direction handler (%d).", n) | |
enabledirectionprocessor () | |
active = true | |
end | |
texsetattribute (a_directions, n) | |
end | |
local active = false --- activation state of math direction processor | |
typo_dir.setmath = function (n) | |
if not active and n and n > 0 then | |
info ("Installing Context math direction handler (%d).", n) | |
enabledirectionprocessor (true) | |
active = true | |
end | |
end | |
typo_dir.getbidimode = directions.getbidimode | |
typo_dir.getbidimode = function (specification) | |
context (directions.tomode (specification)) | |
end | |
----------------------------------------------------------------------- | |
--- clean | |
----------------------------------------------------------------------- | |
attributes.private = nil | |
attributes = nil | |
interfaces.variables = nil | |
interfaces = nil | |
nodes.tasks = nil | |
collectgarbage "collect" | |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
\documentclass {article} | |
\usepackage {luaotfload} | |
\RequireLuaModule {import-typo-dir} | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
%% makeshift interface | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
\def \typodircommand #1{\directlua {packagedata.typo_dir.#1}} | |
%% this expects an attribute id | |
\def \setdirection [#1]{\typodircommand {set (#1)}} | |
\def \typodirsetmode [#1][#2][#3]{% scope, method, fences | |
\def \currenttypodirbidimode {\typodircommand {getbidimode { | |
scope = [[#1]], | |
method = [[#2]], | |
fences = [[#3]], | |
}}}% | |
\setdirection [\number \currenttypodirbidimode]% | |
} | |
\let \unexpanded \protect | |
\let \normalUchar \luatexUchar | |
%% below definitions are taken unmodified from typo-dir.mkiv | |
\unexpanded \edef \bidilre {\normalUchar"202A} | |
\unexpanded \edef \bidirle {\normalUchar"202B} | |
\unexpanded \edef \bidipop {\normalUchar"202C} | |
\unexpanded \edef \bidilro {\normalUchar"202D} | |
\unexpanded \edef \bidirlo {\normalUchar"202E} | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
%% latexifying the demo section of typo-dir.mkiv | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
\font \mainfont = "file:lmroman10-regular.otf:mode=node;+tlig;+liga;+dlig" at 12 pt | |
\font \Arabic = "file:amiri-regular.ttf:mode=node;language=dflt;script=arab;+init;+medi;+fina;+isol;+liga;+dlig;+rlig;+clig;+mark;+mkmk;+kern;+curs" at 20pt | |
\mainfont | |
\def \LATIN {LATIN} | |
\def\ARAB {محمد} | |
\def \biditest #1#2#3{% | |
\leavevmode \hbox {\hbox {\tt #2}\quad | |
\hbox {#1#3}\quad} | |
\hbox {\tt \detokenize {#3}}} | |
\let \textdir = \luatextextdir | |
\def \runbiditests { | |
\biditest \Arabic {LATIN BARA} {\textdir TLT \relax \LATIN\ \ARAB}\par | |
\biditest \Arabic {BARA LATIN} {\textdir TRT \relax \LATIN\ \ARAB}\par | |
\biditest \Arabic {LATIN ARAB} {\textdir TLT \bidilro \LATIN\ \ARAB}\par % right -> left | |
\biditest \Arabic {LATIN ARAB} {\textdir TRT \bidilro \LATIN\ \ARAB}\par % right -> left | |
\biditest \Arabic {BARA NITAL} {\textdir TLT \bidirlo \LATIN\ \ARAB}\par % left -> right | |
\biditest \Arabic {BARA NITAL} {\textdir TRT \bidirlo \LATIN\ \ARAB}\par % left -> right | |
} | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
%% run the demo with the same parameters | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
\begin{document} | |
\typodirsetmode [off][default][yes] | |
\runbiditests | |
\vskip2\baselineskip | |
\typodirsetmode [global][default][yes] | |
\runbiditests | |
\vskip2\baselineskip | |
\typodirsetmode [local][default][yes] | |
\runbiditests | |
\end{document} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment