From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp11.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms5.migadu.com with LMTPS id KAsfOk8RYGIs+AAAbAwnHQ (envelope-from ) for ; Wed, 20 Apr 2022 15:57:36 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp11.migadu.com with LMTPS id +PsNOk8RYGJD8AAA9RJhRA (envelope-from ) for ; Wed, 20 Apr 2022 15:57:35 +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 61931FDD9 for ; Wed, 20 Apr 2022 15:57:35 +0200 (CEST) Received: from localhost ([::1]:58254 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1nhApq-0004a1-Go for larch@yhetil.org; Wed, 20 Apr 2022 09:57:34 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:37938) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1nhAMS-0005qA-H6 for emacs-orgmode@gnu.org; Wed, 20 Apr 2022 09:27:15 -0400 Received: from mail-pg1-x536.google.com ([2607:f8b0:4864:20::536]:42945) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1nhAMQ-0004Ry-P2 for emacs-orgmode@gnu.org; Wed, 20 Apr 2022 09:27:12 -0400 Received: by mail-pg1-x536.google.com with SMTP id bg9so1608130pgb.9 for ; Wed, 20 Apr 2022 06:27:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20210112; h=from:to:subject:in-reply-to:references:message-id:date:mime-version; bh=yR3MNZNKpBptgK32r4kPQ91yxF4TEOTUuthOXfkeRwA=; b=OS84x9yfdnLSmMFl51p74K2VOBunPwzSWDY5Fn2tS1UkbbyTjqJnf0Et7xHFKlHcx8 nlKl2MeJGOqMuA3QRNIpT4gf6lUvsdWnfAOXGaEi8DoUrfn9yrODEUTt/LH9VsH0eDkT F5D39nOLuz2oK8FyewNd0rAY8kXmUPjBmTL/5Ok7HmG8rUn+0YbvtFyMqqyvow/jYUIu hZdBxO9HfhVnslFVsiSuFGrCU2Yu2pCzYx8ilsgGqai3eMDH9CCshhIqwezfh6itxDmI UywTrn9xyCKZVUmA3VqDlc7ilIkX38b63TCBuS51iY9drbwQ27rfzGVJThB1A+6EhuFi ViKg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:subject:in-reply-to:references :message-id:date:mime-version; bh=yR3MNZNKpBptgK32r4kPQ91yxF4TEOTUuthOXfkeRwA=; b=sNMB7ewjaToX1Dj24MCTivxyuoIWayvsRmK2u3Vly3YgybtQLeHEzyGS+9Xe+mqK0Y M8YU1o04UcjYY973pgEBh/m80/Ga+eY7p+7JCoPMIo2cZfxQv45cDZfQ3M9o8MP6XFmh FQqQ72noQiY4zyoXUVOnUomnW5kzB9/YjXlGw5G1qtXNHj10/V4E5ja+rNWThB+g9wpa sAU9ENPkVOSdK7jk/DLZHTLLQzV8O4fabpq4NNiRnzOY75z39xZ8qMmJCyCuh8y0Zwe/ 9BdWdMcrpFiDdzKN12QFIhMumaZT9nvxWEQ1z50ssfM/QF0T074jP5LlMeuYqd1xcQQR rvYw== X-Gm-Message-State: AOAM533tH4t0bXzBjWO2r+Gd/Lq5gKofhT6DCkT10M7erOB1pKift7kX FccvbLemp36ksJzOFJ8tJqrQYDZRDrNE3A== X-Google-Smtp-Source: ABdhPJwus015Oc9udYhEIECoie+2Ho0fZxB3MwpSCr0GWKZDwOpNgt3XSJjXNRlh7W/gU78+z50Kxw== X-Received: by 2002:aa7:9415:0:b0:50a:cdc8:7d7d with SMTP id x21-20020aa79415000000b0050acdc87d7dmr2250592pfo.30.1650461229033; Wed, 20 Apr 2022 06:27:09 -0700 (PDT) Received: from localhost ([64.32.23.62]) by smtp.gmail.com with ESMTPSA id r6-20020a63a546000000b003aa66ef181dsm2367365pgu.64.2022.04.20.06.27.07 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 20 Apr 2022 06:27:08 -0700 (PDT) From: Ihor Radchenko To: emacs-orgmode@gnu.org Subject: [PATCH v2 31/38] org-fold-core: Fix fontification inside folded regions In-Reply-To: References: Message-Id: <7631992948ad0a591fe26c2d1faf5036d9a5611a.1650460489.git.yantar92@gmail.com> Date: Wed, 20 Apr 2022 21:28:01 +0800 MIME-Version: 1.0 Content-Type: text/plain Received-SPF: pass client-ip=2607:f8b0:4864:20::536; envelope-from=yantar92@gmail.com; helo=mail-pg1-x536.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-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" X-Migadu-Flow: FLOW_IN X-Migadu-To: larch@yhetil.org X-Migadu-Country: US ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1650463055; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to: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=yR3MNZNKpBptgK32r4kPQ91yxF4TEOTUuthOXfkeRwA=; b=YKuSUw3V1L4hLJvXVDhQSbsCCvAGmhKqtdQzDxny6muG3drvMnywQv2RDsHRnN+TryTCUz Pik8tx0K039F+khShn+9yFKQ/gEBpH2OuDKLA947Bt0i/F4BMg5oIqBelayhDchuVfDwqu AeqcjjsIKykoZ4NuiEB3R+iyyDbfsbpuCONgP+WSwrd5dFHaZBLoXCPQzDZzHLV4utND9w CVNIcvrw0gO84tHDJcWqVExOu13SalIM/O6munEtKAtL2UIm5dKA8jctSli0oJ8yDW0gms RDXA0odDjlsrG5LZQoD4a7XCSdu7f4uO5vPiy0hwM/w7p/Au1WX6Ce36hU+rJw== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1650463055; a=rsa-sha256; cv=none; b=Og4tfyz5Pwl6+egHMTDKKu1Am266bgdVf1qYBBnfCWksEf7Gy6kjWigNf74CH+E3xV6gYg FhN0HoatYnUJ8Ksxt+H1kmAyVKVIL+1uJZYf6w0pn5f3KLGZsVu4jwqXoiNey3gqM5D7lO pNUJlLjYKE0Z5McqHUTK1ibvD3OWLlngNWcchE/Wusltkmz0RvceYIS/C60378h9vGPu4U zoVIRLA64uVAAMzKhbdr3enwObz/g63NOQGQ/ZxBOZrf3SNdw05MQHmhEPzqnGGQmFmyP2 oBWrwl2kK2hLSgm0DsaBvdSi0+LvFNl9q6zA7pkWNRxXXH9+WDYSw8MJ25RjGw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=OS84x9yf; dmarc=pass (policy=none) header.from=gmail.com; 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" X-Migadu-Spam-Score: -3.04 Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20210112 header.b=OS84x9yf; dmarc=pass (policy=none) header.from=gmail.com; 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" X-Migadu-Queue-Id: 61931FDD9 X-Spam-Score: -3.04 X-Migadu-Scanner: scn1.migadu.com X-TUID: u6jxmDar2pmI * lisp/org-fold-core.el (org-fold-core-initialize): Declare `org-fold-core-fontified' text property for font-lock. (org-fold-core--force-fontification): New variable controlling forced fontification inside folded regions. (org-fold-core-fontify-region): Fix cases when BEG is inside folded region. Respect `org-fold-core--force-fontification'. * lisp/org-macs.el (org-with-forced-fontification): New macro. (org-buffer-substring-fontified): (org-looking-at-fontified): Do not rely on jit-lock. Use `org-fold-core-fontified' text property to determine whether text is already fontified. --- lisp/org-fold-core.el | 69 +++++++++++++++++++++++++------------------ lisp/org-macs.el | 31 +++++++++++++++++++ 2 files changed, 72 insertions(+), 28 deletions(-) diff --git a/lisp/org-fold-core.el b/lisp/org-fold-core.el index 121c6b5c4..edae316ff 100644 --- a/lisp/org-fold-core.el +++ b/lisp/org-fold-core.el @@ -746,7 +746,8 @@ (defun org-fold-core-initialize (&optional specs) (add-hook 'clone-indirect-buffer-hook #'org-fold-core-decouple-indirect-buffer-folds nil 'local) ;; Optimise buffer fontification to not fontify folded text. (when (eq font-lock-fontify-region-function #'font-lock-default-fontify-region) - (setq-local font-lock-fontify-region-function 'org-fold-core-fontify-region)) + (setq-local font-lock-fontify-region-function 'org-fold-core-fontify-region) + (add-to-list 'font-lock-extra-managed-props 'org-fold-core-fontified)) ;; Setup killing text (setq-local filter-buffer-substring-function #'org-fold-core--buffer-substring-filter) (if (and (boundp 'isearch-opened-regions) @@ -1429,35 +1430,47 @@ (defun org-fold-core--buffer-substring-filter (beg end &optional delete) return-string)) ;;; Do not fontify folded text until needed. - +(defvar org-fold-core--force-fontification nil + "Let-bind this variable to t in order to force fontification in +folded regions.") (defun org-fold-core-fontify-region (beg end loudly &optional force) "Run `font-lock-default-fontify-region' in visible regions." - (let ((pos beg) next - (org-fold-core--fontifying t)) - (while (< pos end) - (setq next (org-fold-core-next-folding-state-change - (if force nil - (let (result) - (dolist (spec (org-fold-core-folding-spec-list)) - (when (and (not (org-fold-core-get-folding-spec-property spec :visible)) - (org-fold-core-get-folding-spec-property spec :font-lock-skip)) - (push spec result))) - result)) - pos - end)) - (while (and (not (catch :found - (dolist (spec (org-fold-core-get-folding-spec 'all next)) - (when (org-fold-core-get-folding-spec-property spec :font-lock-skip) - (throw :found spec))))) - (< next end)) - (setq next (org-fold-core-next-folding-state-change nil next end))) - (save-excursion - (font-lock-default-fontify-region pos next loudly) - (save-match-data - (unless (<= pos (point) next) - (run-hook-with-args 'org-fold-core-first-unfold-functions pos next)))) - (put-text-property pos next 'org-fold-core-fontified t) - (setq pos next)))) + (with-silent-modifications + (let ((pos beg) next + (force (or force org-fold-core--force-fontification)) + (org-fold-core--fontifying t) + (skip-specs + (let (result) + (dolist (spec (org-fold-core-folding-spec-list)) + (when (and (not (org-fold-core-get-folding-spec-property spec :visible)) + (org-fold-core-get-folding-spec-property spec :font-lock-skip)) + (push spec result))) + result))) + ;; Move POS to first visible point within BEG..END. + (while (and (catch :found + (dolist (spec (org-fold-core-get-folding-spec 'all pos)) + (when (org-fold-core-get-folding-spec-property spec :font-lock-skip) + (throw :found spec)))) + (< pos end)) + (setq pos (org-fold-core-next-folding-state-change nil pos end))) + (when force (setq pos beg next end)) + (while (< pos end) + (unless force + (setq next (org-fold-core-next-folding-state-change skip-specs pos end))) + ;; Move to the end of the region to be fontified. + (while (and (not (catch :found + (dolist (spec (org-fold-core-get-folding-spec 'all next)) + (when (org-fold-core-get-folding-spec-property spec :font-lock-skip) + (throw :found spec))))) + (< next end)) + (setq next (org-fold-core-next-folding-state-change nil next end))) + (save-excursion + (font-lock-default-fontify-region pos next loudly) + (save-match-data + (unless (<= pos (point) next) + (run-hook-with-args 'org-fold-core-first-unfold-functions pos next)))) + (put-text-property pos next 'org-fold-core-fontified t) + (setq pos next))))) (defun org-fold-core-update-optimisation (beg end) "Update huge buffer optimisation between BEG and END. diff --git a/lisp/org-macs.el b/lisp/org-macs.el index a1d514d50..5e6728101 100644 --- a/lisp/org-macs.el +++ b/lisp/org-macs.el @@ -39,6 +39,7 @@ (declare-function org-agenda-files "org" (&optional unrestricted archives)) (declare-function org-fold-show-context "org-fold" (&optional key)) (declare-function org-fold-save-outline-visibility "org-fold" (use-markers &rest body)) (declare-function org-fold-next-visibility-change "org-fold" (&optional pos limit ignore-hidden-p previous-p)) +(declare-function org-fold-core-with-forced-fontification "org-fold" (&rest body)) (declare-function org-fold-folded-p "org-fold" (&optional pos limit ignore-hidden-p previous-p)) (declare-function string-collate-lessp "org-compat" (s1 s2 &optional locale ignore-case)) @@ -1178,6 +1179,36 @@ (defconst org-rm-props '(invisible t face t keymap t intangible t mouse-face t org-emphasis t) "Properties to remove when a string without properties is wanted.") +(defvar org-fold-core--force-fontification) +(defmacro org-with-forced-fontification (&rest body) + "Run BODY forcing fontification of folded regions." + (declare (debug (form body)) (indent 1)) + `(unwind-protect + (progn + (setq org-fold-core--force-fontification t) + ,@body) + (setq org-fold-core--force-fontification nil))) + +(defun org-buffer-substring-fontified (beg end) + "Return fontified region between BEG and END." + (when (bound-and-true-p jit-lock-mode) + (org-with-forced-fontification + (when (text-property-not-all beg end 'org-fold-core-fontified t) + (save-match-data (font-lock-fontify-region beg end))))) + (buffer-substring beg end)) + +(defun org-looking-at-fontified (re) + "Call `looking-at' RE and make sure that the match is fontified." + (prog1 (looking-at re) + (when (bound-and-true-p jit-lock-mode) + (org-with-forced-fontification + (when (text-property-not-all + (match-beginning 0) (match-end 0) + 'org-fold-core-fontified t) + (save-match-data + (font-lock-fontify-region (match-beginning 0) + (match-end 0)))))))) + (defsubst org-no-properties (s &optional restricted) "Remove all text properties from string S. When RESTRICTED is non-nil, only remove the properties listed -- 2.35.1 -- Ihor Radchenko, PhD, Center for Advancing Materials Performance from the Nanoscale (CAMP-nano) State Key Laboratory for Mechanical Behavior of Materials, Xi'an Jiaotong University, Xi'an, China Email: yantar92@gmail.com, ihor_radchenko@alumni.sutd.edu.sg