From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp10.migadu.com ([2001:41d0:306:2d92::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms9.migadu.com with LMTPS id QClcIc6r82RFAgAAG6o9tA:P1 (envelope-from ) for ; Sat, 02 Sep 2023 23:40:30 +0200 Received: from aspmx1.migadu.com ([2001:41d0:306:2d92::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp10.migadu.com with LMTPS id QClcIc6r82RFAgAAG6o9tA (envelope-from ) for ; Sat, 02 Sep 2023 23:40:30 +0200 Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by aspmx1.migadu.com (Postfix) with ESMTPS id EA53257DBA for ; Sat, 2 Sep 2023 23:40:29 +0200 (CEST) Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=posteo.net header.s=2017 header.b=pSxQp4rU; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=none) header.from=posteo.net ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1693690830; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:in-reply-to:in-reply-to: references:references:list-id:list-help:list-unsubscribe: list-subscribe:list-post:dkim-signature; bh=iPiUIehGOTVD1bt1CxKAZ8j2/laL+ILnXPsZ2ghdpp4=; b=pKj+yldmFYW4BBiJZOHv8RsEaQHEGl1ovV2uaxVpACQ4prscLHxgKLTJD1Rv6oN+d9tagD x62bn7WCIHZn2VYR5IpqUzWQCnB9XAULyUUXVPElKLjx7zR6XEs5wbfo+URlYZrW39qlKI Qe+cgcLHA4LxTC7m8Fq8A/UNWFaX0fjCbULt/UD+BExq3ooJjJ7piZLhzDYs/NRTKrVND1 N/eJtWN2of7Dtd95uH2fhiXFbv0A0myvqpZOMf5Mzi4lVknhzI1IPRLMKDwxgpqnqRLHxH Tm0FmaT7+F0EE6QB+8dis8s5uN80i/i02/H5/dHKVX37Kr62yafX04Hq3UpttA== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1693690830; a=rsa-sha256; cv=none; b=MQI/BG2VpnnY6LA3NQw2UkQ8YwyJ8AWMlyiC30Ti1AqecSLEfz/YP5L0oZyKU0vBPkuLh+ dxTplD7tvH4Lvxebxvqaya7ciG000IlTl1gC0cG6f8oZCmUux3Tz3Oi56hIeCKvcFUNzXa GdHRpvSE19veXYLgVQDOJ/Uj9uS/D32V2UJN0nO0s5NRbfJy9xjiF8n6AePhlrvVKtEyfx 2LqAYYF7Gox+mElWWXmIN6/1W2341tBIVebP/3WGF8K6PSqxGHfPfv/vHXrr/FqWuFcvaQ ldoFxMYqURcycO2bDQQYhon1B+oVY9yPe0HkxOYDhW2f8DF0gjZjh/wcV5TRHw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=posteo.net header.s=2017 header.b=pSxQp4rU; spf=pass (aspmx1.migadu.com: domain of "emacs-orgmode-bounces+larch=yhetil.org@gnu.org" designates 209.51.188.17 as permitted sender) smtp.mailfrom="emacs-orgmode-bounces+larch=yhetil.org@gnu.org"; dmarc=pass (policy=none) header.from=posteo.net Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qcYL1-0007tH-VJ; Sat, 02 Sep 2023 17:39:27 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qcYL0-0007jb-3n for emacs-orgmode@gnu.org; Sat, 02 Sep 2023 17:39:26 -0400 Received: from mout02.posteo.de ([185.67.36.66]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1qcYKw-0000cI-HY for emacs-orgmode@gnu.org; Sat, 02 Sep 2023 17:39:25 -0400 Received: from submission (posteo.de [185.67.36.169]) by mout02.posteo.de (Postfix) with ESMTPS id 21868240103 for ; Sat, 2 Sep 2023 23:39:19 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017; t=1693690759; bh=3Ns8LRThSfcz3Jsf1y+63UbxfaYld2IIqyghSNX1BMo=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:From; b=pSxQp4rUDT3Ph+kyJ0niaLhmhoCL4jT0JfliJzSnrpfSvj78PWoklD2fo9F4mi7AP j1vxuTlmr5VrgthatEbXsi6RUE7lW7suocoOajpulBBL8HeiCoOAzkDP94qtQk4eV0 YQbMyKsTUjz1J6+nJex/Bd3dv+zL96al1jdqnQ86rssVdwUEFgnUajUB2u15DW+saH w2WdlxioBBHDwOp3F0iUrrR7zSYfuRX74HYyUxawWQRlbwkRMDitwRRXwdcXaZpHof pzMHcr2dSh9vx7r7jE8p1NdGHJ3QlK/a+xZkip/UwGRp5is2x4mveqwzmLOH03mxV9 GrbvHY7HKeZqA== Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4RdSw62zsjz6twK; Sat, 2 Sep 2023 23:39:18 +0200 (CEST) From: =?utf-8?Q?Juan_Manuel_Mac=C3=ADas?= To: orgmode Cc: Ihor Radchenko , Timothy Subject: Re: Fallback fonts in LaTeX export for non latin scripts In-Reply-To: <877cpatfol.fsf@localhost> (Ihor Radchenko's message of "Fri, 01 Sep 2023 09:18:18 +0000") References: <878r9t7x7y.fsf@posteo.net> <87wmxbvd60.fsf@localhost> <877cpb8mkd.fsf@posteo.net> <877cpatfol.fsf@localhost> Date: Sat, 02 Sep 2023 21:39:16 +0000 Message-ID: <878r9ocl17.fsf@posteo.net> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=185.67.36.66; envelope-from=maciaschain@posteo.net; helo=mout02.posteo.de X-Spam_score_int: -43 X-Spam_score: -4.4 X-Spam_bar: ---- X-Spam_report: (-4.4 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_MED=-2.3, RCVD_IN_MSPIKE_H5=0.001, RCVD_IN_MSPIKE_WL=0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: emacs-orgmode-bounces+larch=yhetil.org@gnu.org X-Migadu-Country: US X-Migadu-Flow: FLOW_IN X-Migadu-Scanner: mx2.migadu.com X-Spam-Score: -6.93 X-Migadu-Queue-Id: EA53257DBA X-Migadu-Spam-Score: -6.93 X-TUID: qt8SiDgVce+H --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Finally I can upload some usable code here, in this case to be able to load and manage fonts for languages with non-Latin scripts, through babel and fontspec (in LuaLaTeX). It is an attempt to simplify from Org the multiform syntax of babel + fontspec. Of course, it is more limited, but for regular use I think it may be enough. Since this code is mostly a proof of concept and the names of many things (and the things themselves) are still tentative, I thought it would be more useful to attach it in an *.el file, rather than a regular patch. Loading that file everything should work fine. I also attach an org document with some examples of use. In any case, there are more explanations inside the .el file. One of the big problems I have encountered when trying to create a "(LaTeX) Babel interface in Org" is the *horrible* multiplicity that Babel has for language names. That is the reason for the :babel-alt property in 'org-latex-language-alist', which collects the names that babel supports for \babelprovide, which are not always the same as the 'classic' babel syntax. Finally, I find this way more useful (that is, loading fonts with language support), instead of a fallback font system based only on the Unicode scripts. It is less 'automatic', but more precise, and it also does not require much 'specialized' intervention on the part of the user. Best regards, --=20 Juan Manuel Mac=C3=ADas https://juanmanuelmacias.com https://lunotipia.juanmanuelmacias.com https://gnutas.juanmanuelmacias.com --=-=-= Content-Type: application/vnd.lotus-organizer Content-Disposition: attachment; filename=test-lang.org Content-Transfer-Encoding: base64 IytMYVRlWF9IZWFkZXI6IFx1c2VwYWNrYWdle3hjb2xvcn0KIytPUFRJT05TOiB0aXRsZTpuaWwg YXV0aG9yOm5pbCBkYXRlOm5pbCB0b2M6bmlsCgojK0xhVGVYX0hlYWRlcjogXHVzZXBhY2thZ2Vb QVVUT117YmFiZWx9CgojK0xhVGVYX0hlYWRlcjogJSAhZW5hYmxlLWZvbnRzLWZvciBhbmNpZW50 Z3JlZWs6TGludXggTGliZXJ0aW5lIE8oU2NhbGU9TWF0Y2hMb3dlcmNhc2UpCiMrTGFUZVhfSGVh ZGVyOiAlICFlbmFibGUtZm9udHMtZm9yIHJ1c3NpYW46RnJlZVNlcmlmKE51bWJlcnM9TG93ZXJj YXNlLENvbG9yPWJsdWUpIDo6IGFyYWJpYwoKTG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNv bnNlY3RldHVlciBhZGlwaXNjaW5nIGVsaXQuIERvbmVjIGhlbmRyZXJpdCB0ZW1wb3IgdGVsbHVz LgpEb25lYyBwcmV0aXVtIHBvc3VlcmUgdGVsbHVzLiBQcm9pbiBxdWFtIG5pc2wsIHRpbmNpZHVu dCBldCwgbWF0dGlzIGVnZXQsIGNvbnZhbGxpcyBuZWMsCnB1cnVzLiBDdW0gc29jaWlzIG5hdG9x dWUgcGVuYXRpYnVzIGV0IG1hZ25pcyBkaXMgcGFydHVyaWVudCBtb250ZXMsIG5hc2NldHVyIHJp ZGljdWx1cwptdXMuIE51bGxhIHBvc3VlcmUuIERvbmVjIHZpdGFlIGRvbG9yLiBOdWxsYW0gdHJp c3RpcXVlIGRpYW0gbm9uIHR1cnBpcy4gQ3JhcyBwbGFjZXJhdAphY2N1bXNhbiBudWxsYS4gTnVs bGFtIHJ1dHJ1bS4gTmFtIHZlc3RpYnVsdW0gYWNjdW1zYW4gbmlzbC4KCs6UzrHPgc614b23zr/P hSDOus6x4b22IM6gzrHPgc+Fz4PhvbHPhM65zrTOv8+CIM6z4b23zrPOvc6/zr3PhM6xzrkgz4DO seG/ls60zrXPgiDOtOG9u86/LCDPgM+BzrXPg86y4b27z4TOtc+Bzr/PgiDOvOG9ss69IOG8iM+B z4TOsc6+4b2zz4HOvs63z4IsIM69zrXhvb3PhM61z4HOv8+CIM604b2yCs6a4b+mz4HOv8+Czocg 4byQz4DOteG9tiDOtOG9siDhvKDPg8644b2zzr3Otc65IM6UzrHPgc614b+Wzr/PgiDOus6x4b22 IOG9kc+A4b29z4DPhM61z4XOtSDPhM61zrvOtc+Fz4ThvbTOvSDPhM6/4b+mIM6y4b23zr/PhSwg 4byQzrLOv+G9u867zrXPhM6/IM+E4b28IM+AzrHhv5bOtM61IOG8gM68z4bOv8+E4b2zz4HPiQrP gM6xz4HOteG/ls69zrHOuS4g4b2BIM684b2yzr0gzr/hvZbOvSDPgM+BzrXPg86y4b27z4TOtc+B zr/PgiDPgM6xz4HhvbzOvSDhvJDPhOG9u86zz4fOsc69zrXOhyDOmuG/ps+Bzr/OvSDOtOG9siDO vM61z4TOsc+A4b2zzrzPgM61z4TOsc65IOG8gM+A4b24IM+E4b+Gz4Ig4byAz4HPh+G/hs+CIOG8 p8+CCs6x4b2Qz4ThvbjOvSDPg86xz4TPgeG9sc+AzrfOvSDhvJDPgM6/4b23zrfPg861LCDOus6x 4b22IM+Dz4TPgc6xz4TOt86z4b24zr0gzrThvbIgzrHhvZDPhOG9uM69IOG8gM+A4b2zzrTOtc65 zr7OtSDPgOG9sc69z4TPic69IOG9hc+Dzr/OuSDhvJDPgiDOms6xz4PPhM+JzrvOv+G/piDPgM61 zrThvbfOv869CuG8gc64z4HOv+G9t862zr/Ovc+EzrHOuS4KCkVtYWNzINC90LDQv9C40YHQsNC9 INC90LAg0LTQstGD0YUg0Y/Qt9GL0LrQsNGFOiBDINC4IEVtYWNzIExpc3AgKEVsaXNwLCDQtNC4 0LDQu9C10LrRgiDQm9C40YHQv9CwKS4g0J/RgNC4INGN0YLQvtC8INGB0LDQvCDRgNC10LTQsNC6 0YLQvtGACtGP0LLQu9GP0LXRgtGB0Y8g0LjQvdGC0LXRgNC/0YDQtdGC0LDRgtC+0YDQvtC8IEVs aXNwLiDQn9C+INGB0YPRgtC4INC00LXQu9CwLCDQsdC+0LvRjNGI0LDRjyDRh9Cw0YHRgtGMIEVt YWNzINC90LDQv9C40YHQsNC90LAg0L3QsCDRj9C30YvQutC1IEVsaXNwLArQuCDQtdGRINC80L7Q ttC90L4g0YDQsNGB0YHQvNCw0YLRgNC40LLQsNGC0Ywg0LrQsNC6INGA0LDRgdGI0LjRgNC10L3Q uNC1INC6INC+0YHQvdC+0LLQvdC+0Lkg0L/RgNC+0LPRgNCw0LzQvNC1LiDQn9C+0LvRjNC30L7Q stCw0YLQtdC70Lgg0LzQvtCz0YPRgiDRgdCw0LzQuArRgdC+0LfQtNCw0LLQsNGC0Ywg0YfQsNGB 0YLQuCBFbWFjcywg0L7RgiDQvtGC0LTQtdC70YzQvdGL0YUg0YTRg9C90LrRhtC40Lkg0LTQviDQ vdC+0LLRi9GFINC+0YHQvdC+0LLQvdGL0YUg0YDQtdC20LjQvNC+0LIuINCf0YDQuCDRjdGC0L7Q vCDQvNC+0LbQvdC+CtC/0LXRgNC10L7Qv9GA0LXQtNC10LvRj9GC0Ywg0LvRjtCx0YvQtSBFbGlz cC3RhNGD0L3QutGG0LjQuCwg0LIg0YLQvtC8INGH0LjRgdC70LUg0Lgg0YLQtSwg0YfRgtC+INGP 0LLQu9GP0Y7RgtGB0Y8g0YfQsNGB0YLRjNGOINGB0LDQvNC+0LPQvgrRgNC10LTQsNC60YLQvtGA 0LAsINC4INC80L7QtNC40YTQuNGG0LjRgNC+0LLQsNGC0Ywg0YTRg9C90LrRhtC40L7QvdCw0LvR jNC90L7RgdGC0YwgRW1hY3MsINC40LfQvNC10L3QuNCyINGB0L7QvtGC0LLQtdGC0YHRgtCy0YPR jtGJ0LjQvCDQvtCx0YDQsNC30L7QvArQvdC10LrQvtGC0L7RgNGL0LUg0YTRg9C90LrRhtC40Lgu CgpOYXRpdmUgc3BlYWtlcnMgb2YgQXJhYmljIGdlbmVyYWxseSBkbyBub3QgZGlzdGluZ3Vpc2gg YmV0d2VlbiBNb2Rlcm4gU3RhbmRhcmQgQXJhYmljIGFuZApDbGFzc2ljYWwgQXJhYmljIGFzIHNl cGFyYXRlIGxhbmd1YWdlczsgdGhleSByZWZlciB0byBib3RoIGFzIGFsLcq7QXJhYsSreWFoIGFs LUZ14bmj4bilw6EKKNin2YTYudix2KjZitipINin2YTZgdi12K3ZiSkgbWVhbmluZyB0aGUgcHVy ZSBBcmFiaWMuIFRoZXkgY29uc2lkZXIgdGhlIHR3byBmb3JtcyB0byBiZSB0d28gcmVnaXN0ZXJz Cm9mIG9uZSBsYW5ndWFnZS4gV2hlbiB0aGUgZGlzdGluY3Rpb24gaXMgbWFkZSwgdGhleSBhcmUg cmVmZXJyZWQgdG8gYXMg2YHYtdit2Ykg2KfZhNi52LXYsSBGdeG5o+G4pcOhCmFsLcq7QeG5o3Ig KE1TQSkgYW5kINmB2LXYrdmJINin2YTYqtix2KfYqyBGdeG5o+G4pcOhIGFsLVR1csSBdGggKENB KSByZXNwZWN0aXZlbHkuCg== --=-=-= Content-Type: text/plain Content-Disposition: attachment; filename=unicode-font-support.el ;; -*- lexical-binding: t; -*- ;; A proof of concept for Unicode font support in LaTeX export, using ;; babel and fontspec, with luatex as the default compiler. ;; Use example: ;; It is not necessary to load languages with non-Latin alphabet in babel options: ;; #+LaTeX_Header: \usepackage[AUTO]{babel} ;; Languages and fonts (there may be multiple lines): ;; #+LaTeX_Header: % !enable-fonts-for ancientgreek:Linux Libertine O(Scale=MatchLowercase) ;; #+LaTeX_Header: % !enable-fonts-for russian:FreeSerif(Numbers=Lowercase,Color=blue) :: arabic ;; Explanation: ;; - lang = enable default font for lang ;; - lang:font = enable font for lang in current document ;; - lanf:font(options) = enable font for lang in this document with options ;; - :: = separator ;; code ;; This is supposed to be a defcustom. (setq org-latex-uc-fonts-support t) ;; A mini version of `org-latex-language-alist', for this proof of ;; concept. Babel uses various names for languages. The ones that ;; interest us here are those collected in `:babel-alt', which is ;; always a list. The names sometimes match the `classic' babel name ;; and other times they don't. And in the case of "el-polyton" there ;; are two possible names. For a list of these names see: ;; [[https://CTAN/macros/latex/required/babel/base/babel.pdf]], ;; p. 22. (defconst org-latex-language-alist '(("en" :babel "american" :babel-alt ("english-unitedstates") :polyglossia "english" :polyglossia-variant "usmax" :lang-name "English" :script "latin" :code "latn") ("ar" :babel "arabic" :babel-alt ("arabic") :polyglossia "arabic" :lang-name "Arabic" :script "arabic" :code "arab") ("el" :babel "greek" :babel-alt ("greek") :polyglossia "greek" :lang-name "Greek" :script "greek" :code "grk") ("el-polyton" :babel "polutonikogreek" :babel-alt ("ancientgreek" "polytonicgreek") :polyglossia "greek" :polyglossia-variant "polytonic" :lang-name "Polytonic Greek" :script "greek" :code "grk") ("ru" :babel "russian" :babel-alt ("russian") :polyglossia "russian" :lang-name "Russian" :script "cyrillic" :code "cyrl")) "TODO") ;; This is supposed to be a defcustom for the main fonts. `'default' ;; means 'use the main default fonts'. Otherwise, the value must be ;; a plist. Valid props. are: ;; - :main = roman font ;; - :sans = sans font ;; - :mono = mono font ;; - :math = math font ;; - :...-options = font options ;; For the font options and the fontspec package syntax, see ;; [[https://CTAN/macros/unicodetex/latex/fontspec/fontspec.pdf]] (setq org-latex-uc-fonts-support-default-main-fonts '(:main "FreeSerif" :mono "inconsolatan" :mono-options "Scale=0.95")) ;; This is supposed to be a defcustom. Each element has the structure: ;; script - font - (optional) font options (setq org-latex-uc-fonts-support-default-scripts-fonts '(("greek" "Linux Libertine") ("cyrillic" "Old Standard") ("arabic" "FreeSerif"))) ;; Get main fonts (declared in ;; `org-latex-uc-fonts-support-default-main-fonts') (defun org-latex-uc-fonts-support-get-main-fonts (plist prop) (let ((format)) (if (not (plist-member plist prop)) (ignore) (let* ((value (plist-get plist prop)) (prop-name (replace-regexp-in-string ":" "" (symbol-name prop))) (options (plist-get plist (intern (format ":%s-options" prop-name))))) (setq format (format "\\\\set%sfont{%s}[%s]" prop-name value (if options options "") )))) format)) ;; get non latin fonts explicitly added (defun org-latex-uc-fonts-support-get-fonts-other-languages (header) (interactive) (let ((format-str) (lines)) (with-temp-buffer (insert header) (save-excursion (goto-char (point-min)) (while (re-search-forward "%\s+!enable-fonts-for\s+\\(.+\\)" nil t) (add-to-list 'lines (match-string 1))))) (let* ((lines-list (mapcar (lambda (x) (split-string x "::")) lines)) (flat (flatten-list lines-list)) (format-list (mapcar (lambda (x) (org-latex-uc-fonts-support-format-font-for-language (string-trim x))) flat))) (setq format-str (mapconcat #'identity format-list "\n\n"))) format-str)) ;; format each lang/font (defun org-latex-uc-fonts-support-format-font-for-language (lang) (let* ((regexp "\\([^:]+\\):*\\([^()]*\\)(*\\([^()]*\\))*") (lang-name (when (string-match regexp lang) (match-string 1 lang))) (lang-explicit-font (when (string-match regexp lang) (match-string 2 lang))) (lang-explicit-font-opts (when (string-match regexp lang) (match-string 3 lang))) (lang-alias (let ((candidato)) (mapc (lambda (x) (when (member :babel-alt x) (let* ((plist (cdr x)) (babel-alt (plist-get plist :babel-alt))) (when (member lang-name babel-alt) (setq candidato (car x)))))) org-latex-language-alist) candidato)) (plist (cdr (assoc lang-alias org-latex-language-alist))) (script (plist-get plist :script)) (default-script-font (assoc script org-latex-uc-fonts-support-default-scripts-fonts)) (default-font (nth 1 default-script-font)) (default-font-options (nth 2 default-script-font)) (default-font-options? (if default-font-options default-font-options ""))) (format "\\\\babelprovide[onchar=ids fonts]{%s}\n \\\\babelfont[%s]{rm}[%s]{%s}\n" lang-name lang-name (if (not (equal lang-explicit-font-opts "")) lang-explicit-font-opts default-font-options?) (if (not (equal lang-explicit-font "")) lang-explicit-font default-font)))) ;; make preamble definitions. This is supposed to be part of ;; `org-latex-guess-babel-language', as in the modified version below (defun org-latex-uc-fonts-support-make-preamble (header) (let* ((main-fonts (unless (eq 'org-latex-uc-fonts-support-default-main-fonts 'default) (mapconcat #'identity (cl-remove-if-not #'identity (mapcar (lambda (elt) (let ((str (org-latex-uc-fonts-support-get-main-fonts org-latex-uc-fonts-support-default-main-fonts elt))) (when str str))) (list :main :sans :mono :math))) "\n"))) (other-fonts-per-language (org-latex-uc-fonts-support-get-fonts-other-languages header)) (preamble (with-temp-buffer (insert "\n\n") (when main-fonts (insert main-fonts)) (insert "\n\n") (when other-fonts-per-language (insert other-fonts-per-language)) (buffer-string)))) preamble)) (defun org-latex-guess-babel-language (header info) "Modified version for this proof of concept" (let* ((language-code (plist-get info :language)) (plist (cdr (assoc language-code org-latex-language-alist))) (language (plist-get plist :babel)) (language-ini-only (plist-get plist :babel-ini-only)) ;; If no language is set, or Babel package is not loaded, or ;; LANGUAGE keyword value is a language served by Babel ;; exclusively through ini files, return HEADER as-is. (header (if (or language-ini-only (not (stringp language-code)) (not (string-match "\\\\usepackage\\[\\(.*\\)\\]{babel}" header))) header (let ((options (save-match-data (org-split-string (match-string 1 header) ",[ \t]*")))) ;; If LANGUAGE is already loaded, return header ;; without AUTO. Otherwise, replace AUTO with language or ;; append language if AUTO is not present. Languages that are ;; served in Babel exclusively through ini files are not added ;; to the babel argument, and must be loaded using ;; `\babelprovide'. (replace-match (mapconcat (lambda (option) (if (equal "AUTO" option) language option)) (cond ((member language options) (delete "AUTO" options)) ((member "AUTO" options) options) (t (append options (list language)))) ", ") t nil header 1))))) ;;; adition: (when org-latex-uc-fonts-support (setq header (let ((form (org-latex-uc-fonts-support-make-preamble header))) (replace-regexp-in-string "\\(\\\\usepackage\\[?.*\\]?{babel}\\)" (format "\n\\\\usepackage{fontspec}\n\n\\1\n%s" form) header)))) ;;; ;; If `\babelprovide[args]{AUTO}' is present, AUTO is ;; replaced by LANGUAGE. (if (not (string-match "\\\\babelprovide\\[.*\\]{\\(.+\\)}" header)) header (let ((prov (match-string 1 header))) (if (equal "AUTO" prov) (replace-regexp-in-string (format "\\(\\\\babelprovide\\[.*\\]\\)\\({\\)%s}" prov) (format "\\1\\2%s}" (or language language-ini-only)) header t) header))))) --=-=-=--