From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Ihor Radchenko Newsgroups: gmane.emacs.devel Subject: Re: Org mode and Emacs (was: Convert README.org to plain text README while installing package) Date: Thu, 16 Jun 2022 15:03:19 +0800 Message-ID: <87h74l9jk8.fsf@localhost> References: <835yld93w7.fsf@gnu.org> <877d5t0yrn.fsf@gmail.com> <87r140yuof.fsf@gmail.com> <875yl9e7zm.fsf@gmail.com> <83czfh12kp.fsf@gnu.org> <87pmjhghu2.fsf@localhost> <835yl910gp.fsf@gnu.org> <87wndndbhq.fsf@gmail.com> <83bkuzznws.fsf@gnu.org> <877d5mqmkh.fsf@localhost> <83y1y2utnd.fsf@gnu.org> <87r13up587.fsf@localhost> <83o7yyur0l.fsf@gnu.org> <87leu2p3nu.fsf@localhost> <83leu2uewn.fsf@gnu.org> <87r13qv701.fsf@localhost> <83bkuursya.fsf@gnu.org> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="19339"; mail-complaints-to="usenet@ciao.gmane.io" Cc: theophilusx@gmail.com, rms@gnu.org, monnier@iro.umontreal.ca, acm@muc.de, emacs-devel@gnu.org To: Eli Zaretskii Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Thu Jun 16 09:06:28 2022 Return-path: Envelope-to: ged-emacs-devel@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1o1jaF-0004qB-QB for ged-emacs-devel@m.gmane-mx.org; Thu, 16 Jun 2022 09:06:27 +0200 Original-Received: from localhost ([::1]:39206 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1o1jaE-0003CC-5u for ged-emacs-devel@m.gmane-mx.org; Thu, 16 Jun 2022 03:06:26 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:48170) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1o1jWJ-0001dY-Nr for emacs-devel@gnu.org; Thu, 16 Jun 2022 03:02:24 -0400 Original-Received: from mail-pj1-x102c.google.com ([2607:f8b0:4864:20::102c]:36176) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1o1jWB-0002u2-Lh; Thu, 16 Jun 2022 03:02:22 -0400 Original-Received: by mail-pj1-x102c.google.com with SMTP id k12-20020a17090a404c00b001eaabc1fe5dso985778pjg.1; Thu, 16 Jun 2022 00:02:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:cc:subject:in-reply-to:references:date:message-id :mime-version; bh=0wA/MAERL/wAsm9yMWBK3gTN6F+0QTLYnIsIti7Z/+Q=; b=cuKccbVjuTH5qEUCK4QwB7cRzZ7Imezb4nVyY0OP+kL7a6q/1aG/do1BP+ejRWrNX3 e2keSN5DA7zlJHoirsnMidYgWegRil3J8FhhSVsN1EFKc9Fu0aqfT8maYwKBsCSBrBj/ qMTEY5P+J3MXjE3oIipmnldLC1f4aAIWnoMK290GiJ3c9p7sLAbdhV/XOXYms7TI42gn Ik0zbz2Xd39mpvOI1Wbin1pEjpe6OmFroIUfaRfMv3B40gemHC90YLo8ISVq6lwjzQYl Z495guox3gf/MBIH7img+NQuPZafTjZjqX6msJJi/zjjDifO65dDtk0Jy5zQEjfvVrnj RwYA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:in-reply-to:references:date :message-id:mime-version; bh=0wA/MAERL/wAsm9yMWBK3gTN6F+0QTLYnIsIti7Z/+Q=; b=Mc7AgG/nM0JhPUXCLxeyCdLUYjZGOk52ABu1Ggg93+SU4oUpzQTkXl9icKVs7pYvTz 3IGWrCdZnqwxwz3pKRy19JXOsCIVQ7qPU3eMaceZapfpaOOz/7ulfmEiRMJTNgmmJwYC oEjRwV9n8R4/cQZYXJJNPnHEUh9RACnwlwTHpqDvfSc7XBsZhOhBv0B8Z/jsTCppQYwF dT+cWRcSw9yyvGNLdBjkOsbKpk64IjbiMknV2OdmEEbCJdPhj/ERWUGCz7cL2QcNNNh2 a+u0sDh1kIVydNfoT7+mKv2CqvR9lxNtbd3jdl27ud1FYiTzyektQe7foZDtzmNTsbCa yijA== X-Gm-Message-State: AJIora+9AfuZs58YMUIvEsdOd6ER3zh7pK5+oYeNBeOrMoQCKRlm+SZe ssHmNeANgN9OalJcwtSgia4rATZxqVA= X-Google-Smtp-Source: AGRyM1s49gi47/a9ELUE3cl6D2eoWZ4kOAzadNDiUO/4e+9q8BuvpsSFzclPmR5+aSpDxOAXn0pDAA== X-Received: by 2002:a17:90a:9914:b0:1ea:7bc5:8218 with SMTP id b20-20020a17090a991400b001ea7bc58218mr14699233pjp.50.1655362933215; Thu, 16 Jun 2022 00:02:13 -0700 (PDT) Original-Received: from localhost ([155.94.207.39]) by smtp.gmail.com with ESMTPSA id fy2-20020a17090b020200b001ea6a20d354sm801276pjb.2.2022.06.16.00.02.11 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 16 Jun 2022 00:02:12 -0700 (PDT) In-Reply-To: <83bkuursya.fsf@gnu.org> Received-SPF: pass client-ip=2607:f8b0:4864:20::102c; envelope-from=yantar92@gmail.com; helo=mail-pj1-x102c.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 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, FREEMAIL_ENVFROM_END_DIGIT=0.25, FREEMAIL_FROM=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: "Emacs-devel" Xref: news.gmane.io gmane.emacs.devel:291233 Archived-At: --=-=-= Content-Type: text/plain Eli Zaretskii writes: > I see no need for such significant changes in our merging practices. > Rather, I hoped that the speedup you achieved will be important enough > to make an exception and install just it in the Emacs master branch. See the attached patches. Best, Ihor --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-org-export-get-footnote-definition-Pre-cache-referen.patch >From 3342137359f122ed7168dc75096c6a5d3839a0c2 Mon Sep 17 00:00:00 2001 Message-Id: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> From: Ihor Radchenko Date: Sun, 12 Jun 2022 13:05:16 +0800 Subject: [PATCH 1/8] org-export-get-footnote-definition: Pre-cache references in parse tree * lisp/ox.el (org-export-get-footnote-definition): Pre-process parse tree once to filter out all non-footnote elements. This speeds up subsequent footnote definition searches. --- lisp/ox.el | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/lisp/ox.el b/lisp/ox.el index 2a3edaa50..7f90dc36f 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -3748,28 +3748,33 @@ (defun org-export-get-footnote-definition (footnote-reference info) (if (not label) (org-element-contents footnote-reference) (let ((cache (or (plist-get info :footnote-definition-cache) (let ((hash (make-hash-table :test #'equal))) + ;; Cache all the footnotes in document for + ;; later search. + (org-element-map (plist-get info :parse-tree) + '(footnote-definition footnote-reference) + (lambda (f) + ;; Skip any standard footnote reference + ;; since those cannot contain a + ;; definition. + (unless (eq (org-element-property :type f) 'standard) + (puthash + (cons :element (org-element-property :label f)) + f + hash))) + info) (plist-put info :footnote-definition-cache hash) hash)))) (or (gethash label cache) (puthash label - (org-element-map (plist-get info :parse-tree) - '(footnote-definition footnote-reference) - (lambda (f) - (cond - ;; Skip any footnote with a different label. - ;; Also skip any standard footnote reference - ;; with the same label since those cannot - ;; contain a definition. - ((not (equal (org-element-property :label f) label)) nil) - ((eq (org-element-property :type f) 'standard) nil) - ((org-element-contents f)) - ;; Even if the contents are empty, we can not - ;; return nil since that would eventually raise - ;; the error. Instead, return the equivalent - ;; empty string. - (t ""))) - info t) + (let ((hashed (gethash (cons :element label) cache))) + (when hashed + (or (org-element-contents hashed) + ;; Even if the contents are empty, we can not + ;; return nil since that would eventually raise + ;; the error. Instead, return the equivalent + ;; empty string. + ""))) cache) (error "Definition not found for footnote %s" label)))))) -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-org-export-resolve-fuzyy-link-Pre-cache-all-possible.patch >From cff9ed2f7660abaa5bd67e5de87416cb393b2cb8 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> References: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> From: Ihor Radchenko Date: Sun, 12 Jun 2022 13:06:47 +0800 Subject: [PATCH 2/8] org-export-resolve-fuzyy-link: Pre-cache all possible search cells * lisp/ox.el (org-export-resolve-fuzzy-link): Before matching LINK, pre-process and cache all the non-nil search cells in the parse tree. When matching, use the pre-processed info. Fix the :test function for the cache hash table. --- lisp/ox.el | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/lisp/ox.el b/lisp/ox.el index 7f90dc36f..4a9387519 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -4346,17 +4346,27 @@ (defun org-export-resolve-fuzzy-link (link info &rest pseudo-types) (let* ((search-cells (org-export-string-to-search-cell (org-element-property :path link))) (link-cache (or (plist-get info :resolve-fuzzy-link-cache) - (let ((table (make-hash-table :test #'eq))) + (let ((table (make-hash-table :test #'equal))) + ;; Cache all the element search cells. + (org-element-map (plist-get info :parse-tree) + (append pseudo-types '(target) org-element-all-elements) + (lambda (datum) + (dolist (cell (org-export-search-cells datum)) + (if (gethash cell table) + (push datum (gethash cell table)) + (puthash cell (list datum) table))))) (plist-put info :resolve-fuzzy-link-cache table) table))) (cached (gethash search-cells link-cache 'not-found))) (if (not (eq cached 'not-found)) cached (let ((matches - (org-element-map (plist-get info :parse-tree) - (append pseudo-types '(target) org-element-all-elements) - (lambda (datum) - (and (org-export-match-search-cell-p datum search-cells) - datum))))) + (let (result) + (dolist (search-cell search-cells) + (setq result + (nconc + result + (gethash search-cell link-cache)))) + (delq nil result)))) (unless matches (signal 'org-link-broken (list (org-element-property :path link)))) (puthash -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0003-org-export-resolve-id-link-Pre-cache-all-the-ids-in-.patch >From eca7a1d4dea1e8980aee6a02967d4c596114f759 Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> References: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> From: Ihor Radchenko Date: Sun, 12 Jun 2022 13:32:35 +0800 Subject: [PATCH 3/8] org-export-resolve-id-link: Pre-cache all the ids in the parse tree * lisp/ox.el (org-export-resolve-id-link): Pre-cache all the ids in the parse tree for faster lookup. --- lisp/ox.el | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/lisp/ox.el b/lisp/ox.el index 4a9387519..b431d7119 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -4393,15 +4393,27 @@ (defun org-export-resolve-id-link (link info) \"custom-id\". Throw an error if no match is found." (let ((id (org-element-property :path link))) ;; First check if id is within the current parse tree. - (or (org-element-map (plist-get info :parse-tree) 'headline - (lambda (headline) - (when (or (equal (org-element-property :ID headline) id) - (equal (org-element-property :CUSTOM_ID headline) id)) - headline)) - info 'first-match) - ;; Otherwise, look for external files. - (cdr (assoc id (plist-get info :id-alist))) - (signal 'org-link-broken (list id))))) + (or (let ((local-ids (or (plist-get info :id-local-cache) + (let ((table (make-hash-table :test #'equal))) + (org-element-map + (plist-get info :parse-tree) + 'headline + (lambda (headline) + (let ((id (org-element-property :ID headline)) + (custom-id (org-element-property :CUSTOM_ID headline))) + (when id + (unless (gethash id table) + (puthash id headline table))) + (when custom-id + (unless (gethash custom-id table) + (puthash custom-id headline table))))) + info) + (plist-put info :id-local-cache table) + table)))) + (gethash id local-ids)) + ;; Otherwise, look for external files. + (cdr (assoc id (plist-get info :id-alist))) + (signal 'org-link-broken (list id))))) (defun org-export-resolve-radio-link (link info) "Return radio-target object referenced as LINK destination. -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0004-org-export-as-Do-not-update-buffer-settings-when-not.patch >From fb8b921066ca84aaa7034c7f13e2cc62da40d7ad Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> References: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> From: Ihor Radchenko Date: Thu, 16 Jun 2022 01:03:18 +0800 Subject: [PATCH 4/8] org-export-as: Do not update buffer settings when not modified * lisp/ox.el (org-export-as): Use `buffer-chars-modified-tick' and avoid extra invocations of `org-set-regexps-and-options' and `org-update-radio-target-regexp' when the buffer is not changed. Also, disable folding checks. Folding is irrelevant inside export buffer. --- lisp/ox.el | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/lisp/ox.el b/lisp/ox.el index b431d7119..a4512270c 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -2956,11 +2956,12 @@ (defun org-export-as (mapcar (lambda (o) (and (eq (nth 4 o) 'parse) (nth 1 o))) (append (org-export-get-all-options backend) org-export-options-alist)))) - tree) + tree modified-tick) ;; Update communication channel and get parse tree. Buffer ;; isn't parsed directly. Instead, all buffer modifications ;; and consequent parsing are undertaken in a temporary copy. (org-export-with-buffer-copy + (font-lock-mode -1) ;; Run first hook with current back-end's name as argument. (run-hook-with-args 'org-export-before-processing-hook (org-export-backend-name backend)) @@ -2972,6 +2973,7 @@ (defun org-export-as ;; potentially invasive changes. (org-set-regexps-and-options) (org-update-radio-target-regexp) + (setq modified-tick (buffer-chars-modified-tick)) ;; Possibly execute Babel code. Re-run a macro expansion ;; specifically for {{{results}}} since inline source blocks ;; may have generated some more. Refresh buffer properties @@ -2979,8 +2981,10 @@ (defun org-export-as (when org-export-use-babel (org-babel-exp-process-buffer) (org-macro-replace-all '(("results" . "$1")) parsed-keywords) - (org-set-regexps-and-options) - (org-update-radio-target-regexp)) + (unless (eq modified-tick (buffer-chars-modified-tick)) + (org-set-regexps-and-options) + (org-update-radio-target-regexp)) + (setq modified-tick (buffer-chars-modified-tick))) ;; Run last hook with current back-end's name as argument. ;; Update buffer properties and radio targets one last time ;; before parsing. @@ -2988,8 +2992,10 @@ (defun org-export-as (save-excursion (run-hook-with-args 'org-export-before-parsing-hook (org-export-backend-name backend))) - (org-set-regexps-and-options) - (org-update-radio-target-regexp) + (unless (eq modified-tick (buffer-chars-modified-tick)) + (org-set-regexps-and-options) + (org-update-radio-target-regexp)) + (setq modified-tick (buffer-chars-modified-tick)) ;; Update communication channel with environment. (setq info (org-combine-plists -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0005-doc-Makefile-Disable-GC-during-export.patch >From 7f3ee582c1105c66a66fb61786c4e086e30460b4 Mon Sep 17 00:00:00 2001 Message-Id: <7f3ee582c1105c66a66fb61786c4e086e30460b4.1655362876.git.yantar92@gmail.com> In-Reply-To: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> References: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> From: Ihor Radchenko Date: Thu, 16 Jun 2022 07:29:06 +0800 Subject: [PATCH 5/8] doc/Makefile: Disable GC during export * doc/Makefile (org.texi): (orgguide.texi): Set `gc-cons-threshold` to `most-positive=fixnum' and thus disable garbage collection while exporting manuals. This reduces the manual generation time. --- doc/Makefile | 2 ++ 1 file changed, 2 insertions(+) diff --git a/doc/Makefile b/doc/Makefile index cb6d72bdc..5911bd08a 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -31,12 +31,14 @@ org.texi: org-manual.org $(BATCH) \ --eval '(add-to-list `load-path "../lisp")' \ --eval '(load "../mk/org-fixup.el")' \ + --eval '(setq gc-cons-threshold most-positive-fixnum)' \ --eval '(org-make-manual)' orgguide.texi: org-guide.org $(BATCH) \ --eval '(add-to-list `load-path "../lisp")' \ --eval '(load "../mk/org-fixup.el")' \ + --eval '(setq gc-cons-threshold most-positive-fixnum)' \ --eval '(org-make-guide)' org-version.inc: org.texi -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0006-org-export-data-Concatenate-strings-in-temporary-buf.patch >From 4a466e28999bbaa5169b6fad414cf08c6d23cd7b Mon Sep 17 00:00:00 2001 Message-Id: <4a466e28999bbaa5169b6fad414cf08c6d23cd7b.1655362876.git.yantar92@gmail.com> In-Reply-To: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> References: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> From: Ihor Radchenko Date: Thu, 16 Jun 2022 01:01:53 +0800 Subject: [PATCH 6/8] org-export-data: Concatenate strings in temporary buffer for performance * lisp/ox.el (org-export-data): Use temporary buffer to collect export data instead of `mapconcat'. Using buffer puts less load on garbage collector. --- lisp/ox.el | 50 ++++++++++++++++++++++++++++---------------------- 1 file changed, 28 insertions(+), 22 deletions(-) diff --git a/lisp/ox.el b/lisp/ox.el index a4512270c..ae7e41e57 100644 --- a/lisp/ox.el +++ b/lisp/ox.el @@ -1923,28 +1923,34 @@ (defun org-export-data (data info) (and (not greaterp) (memq type org-element-recursive-objects))) (contents - (mapconcat - (lambda (element) (org-export-data element info)) - (org-element-contents - (if (or greaterp objectp) data - ;; Elements directly containing - ;; objects must have their indentation - ;; normalized first. - (org-element-normalize-contents - data - ;; When normalizing first paragraph - ;; of an item or - ;; a footnote-definition, ignore - ;; first line's indentation. - (and - (eq type 'paragraph) - (memq (org-element-type parent) - '(footnote-definition item)) - (eq (car (org-element-contents parent)) - data) - (eq (org-element-property :pre-blank parent) - 0))))) - ""))) + (let ((export-buffer (current-buffer))) + (with-temp-buffer + (dolist (element (org-element-contents + (if (or greaterp objectp) data + ;; Elements directly containing + ;; objects must have their indentation + ;; normalized first. + (org-element-normalize-contents + data + ;; When normalizing first paragraph + ;; of an item or + ;; a footnote-definition, ignore + ;; first line's indentation. + (and + (eq type 'paragraph) + (memq (org-element-type parent) + '(footnote-definition item)) + (eq (car (org-element-contents parent)) + data) + (eq (org-element-property :pre-blank parent) + 0)))))) + (insert + ;; Use right local variable + ;; environment if there are, for + ;; example, #+BIND variables. + (with-current-buffer export-buffer + (org-export-data element info)))) + (buffer-string))))) (broken-link-handler (funcall transcoder data (if (not greaterp) contents -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0007-org-element-map-Avoid-repetitive-plist-get-call.patch >From efd91d5f654cc0e734cd3f5cfd1f39a6219fd0dc Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> References: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> From: Ihor Radchenko Date: Thu, 16 Jun 2022 09:28:27 +0800 Subject: [PATCH 7/8] org-element-map: Avoid repetitive `plist-get' call * lisp/org-element.el (org-element-map): Do not call `(plist-get info :ignore-list)' on every iteration. --- lisp/org-element.el | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lisp/org-element.el b/lisp/org-element.el index 9db1406b3..20b5b0303 100644 --- a/lisp/org-element.el +++ b/lisp/org-element.el @@ -4391,6 +4391,7 @@ (defun org-element-map ;; every element it encounters. (and (not (eq category 'elements)) (setq category 'elements)))))))) + (--ignore-list (plist-get info :ignore-list)) --acc) (letrec ((--walk-tree (lambda (--data) @@ -4400,7 +4401,7 @@ (defun org-element-map (cond ((not --data)) ;; Ignored element in an export context. - ((and info (memq --data (plist-get info :ignore-list)))) + ((and info (memq --data --ignore-list))) ;; List of elements or objects. ((not --type) (mapc --walk-tree --data)) ;; Unconditionally enter parse trees. -- 2.35.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0008-org-cite-list-citations-Cache-footnote-definition-se.patch >From 56830c1792b548e9157cdd95f4bb7c093e390a05 Mon Sep 17 00:00:00 2001 Message-Id: <56830c1792b548e9157cdd95f4bb7c093e390a05.1655362876.git.yantar92@gmail.com> In-Reply-To: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> References: <3342137359f122ed7168dc75096c6a5d3839a0c2.1655362876.git.yantar92@gmail.com> From: Ihor Radchenko Date: Thu, 16 Jun 2022 10:43:29 +0800 Subject: [PATCH 8/8] org-cite-list-citations: Cache footnote-definition searches * lisp/oc.el (org-cite-list-citations): Avoid quadratic complexity. Pre-calculate list of all footnote definitions and cache the footnote label search hits. Do not make `org-element-map' accumulate unused result. --- lisp/oc.el | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/lisp/oc.el b/lisp/oc.el index eb5f519cb..c4cd0268c 100644 --- a/lisp/oc.el +++ b/lisp/oc.el @@ -808,6 +808,8 @@ (defun org-cite-list-citations (info) (or (plist-get info :citations) (letrec ((cites nil) (tree (plist-get info :parse-tree)) + (definition-cache (make-hash-table :test #'equal)) + (definition-list nil) (find-definition ;; Find definition for standard reference LABEL. At ;; this point, it is impossible to rely on @@ -816,11 +818,21 @@ (defun org-cite-list-citations (info) ;; un-processed citation objects. So we use ;; a simplified version of the function above. (lambda (label) - (org-element-map tree 'footnote-definition - (lambda (d) - (and (equal label (org-element-property :label d)) - (or (org-element-contents d) ""))) - info t))) + (or (gethash label definition-cache) + (org-element-map + (or definition-list + (setq definition-list + (org-element-map + tree + 'footnote-definition + #'identity info))) + 'footnote-definition + (lambda (d) + (and (equal label (org-element-property :label d)) + (puthash label + (or (org-element-contents d) "") + definition-cache))) + info t)))) (search-cites (lambda (data) (org-element-map data '(citation footnote-reference) @@ -834,7 +846,8 @@ (defun org-cite-list-citations (info) (_ (let ((label (org-element-property :label datum))) (funcall search-cites - (funcall find-definition label)))))) + (funcall find-definition label))))) + nil) info nil 'footnote-definition t)))) (funcall search-cites tree) (let ((result (nreverse cites))) -- 2.35.1 --=-=-=--