From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms0.migadu.com with LMTPS id mMygBO/PqWCoEwEAgWs5BA (envelope-from ) for ; Sun, 23 May 2021 05:45:51 +0200 Received: from aspmx1.migadu.com ([2001:41d0:2:bcc0::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id OB1GAO/PqWAGcgAA1q6Kng (envelope-from ) for ; Sun, 23 May 2021 03:45:51 +0000 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 2E8299EF2 for ; Sun, 23 May 2021 05:45:50 +0200 (CEST) Received: from localhost ([::1]:36908 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lkf3k-0001Eh-0X for larch@yhetil.org; Sat, 22 May 2021 23:45:48 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:34338) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lkf3L-0001EX-Ht for emacs-orgmode@gnu.org; Sat, 22 May 2021 23:45:23 -0400 Received: from mail-lj1-x22a.google.com ([2a00:1450:4864:20::22a]:41782) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1lkf3J-0003UP-Gq for emacs-orgmode@gnu.org; Sat, 22 May 2021 23:45:23 -0400 Received: by mail-lj1-x22a.google.com with SMTP id p20so28965441ljj.8 for ; Sat, 22 May 2021 20:45:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:in-reply-to:references:cc:date:message-id :mime-version; bh=E4QDgDxtEGfa4c43mAvnGmuLTs8/HzhuReWvWoJsk6k=; b=VKGdUIh77BY7NlNbr7APTz8V0cuQ9zZ6LRkZIrGnu9AoovN5w0c9ZreqPa2ROOKU9m ZlJEcjeTVxI9pHlqK1KvIaGxIdGQAK5eA0c9m/zkEzAsqgzSPFCO6A7K4SHDE+LHEZpc xcV2jlaGz6YJI+W95QgzUGmkiJV0n8XK2/6U1jCpJrCaOnlIF2boqZm0h42Uy5sLZbBb t5djf4gp044MKbkEs1RkVm5QeuTqr2nx5VFPKqh57BpUXt/FXW8IReJTpfWyt6z5e1BS Rhs6kLA1YRZgaybCgA9Olp5GaxtaDQUZWRUtVUFdeKtYcr3YgOAILb6xaqNybSB/e0oG 2mGg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:in-reply-to:references:cc:date :message-id:mime-version; bh=E4QDgDxtEGfa4c43mAvnGmuLTs8/HzhuReWvWoJsk6k=; b=moOdsV8LCqJxoGE9AnDFHONKbHrONtiVYuv7k8dtLVBQBQbbMISPoK/0Xxd1QVsDoZ T8V4MnVhz2A95Ony/WA/OqWDiiV5HoZ2xGMNnjcVaBVylSOiv9JrppwQm8D8lk69jrVw G3Ue3OTq9YVhWrF1yUsV7sTOKhP609RD7biZDwOV2AwxxoTVtZkEjU7HEokuAPBoxBsb ipt6VWtb0jOpl++Pe/KtTN9EbNORrHAAnEAjxNyQ7UlvGUWz0TsbdIN+YFC+st85H7d4 keHTVjjPb9HLNFI9WrKGftHTg8QKNGLrr30MHuKHH5hGGCgt6NOQfTC8CHLY8RXzQ13s RJzQ== X-Gm-Message-State: AOAM5325S6VROpWx5D/quJ6D/giDtTaDJxqHH0QBnSdW/5V7dWudACv7 Bidhs3g63uiJejjGPUUWj8w= X-Google-Smtp-Source: ABdhPJx4hE/qtU2YImefMzdgh3t5ADeqjSNqkSixyetpTy1NB+BUEW4wMu1SoKHshddIxVZQlq3bIw== X-Received: by 2002:a05:651c:b28:: with SMTP id b40mr12227527ljr.9.1621741519368; Sat, 22 May 2021 20:45:19 -0700 (PDT) Received: from localhost ([91.210.107.197]) by smtp.gmail.com with ESMTPSA id q2sm1062590lfd.84.2021.05.22.20.45.17 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 22 May 2021 20:45:18 -0700 (PDT) From: Ihor Radchenko To: Nicolas Goaziou Subject: Re: Question about Org syntax In-Reply-To: <87y2cfysyd.fsf@nicolasgoaziou.fr> References: <87mtsvxs94.fsf@localhost> <877djz17cm.fsf@nicolasgoaziou.fr> <87h7j3xg3g.fsf@localhost> <87y2cfysyd.fsf@nicolasgoaziou.fr> Date: Sun, 23 May 2021 11:50:07 +0800 Message-ID: <875yzap0r4.fsf@localhost> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Received-SPF: pass client-ip=2a00:1450:4864:20::22a; envelope-from=yantar92@gmail.com; helo=mail-lj1-x22a.google.com X-Spam_score_int: -17 X-Spam_score: -1.8 X-Spam_bar: - X-Spam_report: (-1.8 / 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 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-orgmode@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: emacs-orgmode@gnu.org Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Migadu-Flow: FLOW_IN ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1621741550; 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=E4QDgDxtEGfa4c43mAvnGmuLTs8/HzhuReWvWoJsk6k=; b=Vv7qN57/Kh4voxNba3qSwINgnDMvJfTqsEyH+ik2BqScNjFXJypug+011dRL8ig1UA/w72 8J3GQciyzMdWu3OGwqETvHYL3tHG2IxhnCxt536cmG8rhRp1B/fuSO85kedfBmw1gGRux1 zd509S4TpixsXwIbmYhu/dO+auDMOMPHaA3dPDPOpHNRbHCpkYjN7iZ6qTMNb8VJBRqaX0 9PuvycDp7pBf0i/XtHtUoHV8j1Px+QFSUHDY3HkBoiEdciNdsOTRm/53XpNbFyflo1lX89 Q+lzgiMuKJnEke12NFOLc3Bd78rzE8gxm73PsBm/5XNE3jUVxNbQikerE2NXZQ== ARC-Seal: i=1; s=key1; d=yhetil.org; t=1621741550; a=rsa-sha256; cv=none; b=tQC6xUJkqpPIqhKgBalVlw5nGT6XVOUjszEwxYuHgviJQ3ey/vboPKx1ERblPCnMc1xRAM B3yUbmhHVK61rSWMq94uI72FM0ei54bJR75Uxl+Delm+LHbDTCGEir8iKmz4RfvuciS/Bz JmMcUq0oNRSrJhw7oPJSlxefwdChdoqjb8Qp4vBUuS469q+7mGDN3ouVqqWgBynhdhMaSE hHVnLxwBtdrDu89UTvUyjNLKyUHWPQE4GQTQvx+wmxpko/ct8phf7p/hBZFdjdoXm1i2ds YdllofR5pFvriBKBxvYlNecmyXTI/uAhKIpl1cE3ZeKuX5T0jSdK1nzNV53yKw== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20161025 header.b=VKGdUIh7; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (aspmx1.migadu.com: domain of emacs-orgmode-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=emacs-orgmode-bounces@gnu.org X-Migadu-Spam-Score: -2.64 Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20161025 header.b=VKGdUIh7; dmarc=pass (policy=none) header.from=gmail.com; spf=pass (aspmx1.migadu.com: domain of emacs-orgmode-bounces@gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=emacs-orgmode-bounces@gnu.org X-Migadu-Queue-Id: 2E8299EF2 X-Spam-Score: -2.64 X-Migadu-Scanner: scn1.migadu.com X-TUID: RbcWxEOTgPWo --=-=-= Content-Type: text/plain Nicolas Goaziou writes: Thanks for your detailed explanations! >> 2. Some of the element parsers honour LIMIT argument partially. Part of >> the parsing is typically done using looking-at (ignoring the LIMIT) >> and part is honouring it. This can backfire when LIMIT is before >> first characteristic line of the element. For example take headline >> parser: >> ... > > LIMIT is not a random position in the buffer. It is supposed to be the > end of the parent element, or (point-max). > > It is a bug (in the parser or in the cache) if it ends up being anywhere > else. Makes sense, though it is not mentioned in the docstrings and even in the docstring of the `org-element--current-element'. Moreover, section comment about parsers states that most parsers accept no arguments: > ;; A parser returns the element or object as the list described above. > ;; Most of them accepts no argument. And the comment about adding things to `org-element--current-element' does not help either. > ;; Beside implementing a parser and an interpreter, adding a new > ;; greater element requires tweaking `org-element--current-element'. > ;; Moreover, the newly defined type must be added to both > ;; `org-element-all-elements' and `org-element-greater-elements'. Probably, the docstring of `org-element--current-element' could mention about the expected values of LIMIT argument? ------ Also, I have some more questions as I am trying to understand the org-element-cache code. I tried to add some additional comments to the existing code to clarify parts I had difficulties understanding. See the attached patch. Let me know if any of the comments are incorrect so that I can update my understanding. For now I am stuck understanding some places in the code. They are either bugs or I misunderstood some things: 1. In org-element--cache-process-request: > (while t > ... > (let ((beg (aref request 0)) > (end (aref request 2)) > (node (org-element--cache-root)) > data data-key last-container) > > ... > (and last-container > ... > (progn (when (and (not last-container) > (> (org-element-property :end data) > end)) > (setq last-container data)) I do not understand the use of last-container here. The code is ran in a while loop containing let-bound last-container variable (the let binding sets it to nil). (setq last-container data) will not affect further iterations of the while loop as last-container will always be nil inside the let-binding. 2. In org-element--cache-submit-request > (let ((first (org-element--cache-for-removal beg end offset))) > ... > (push (let ((beg (org-element-property :begin first)) > (key (org-element--cache-key first))) > ... > ((let ((first-end (org-element-property :end first))) > (and (>= first-end end) > (vector key beg first-end offset first 0)))) > ... > org-element--cache-sync-requests) According to the docstring of org-element--cache-sync-requests, (aref 4 request) during "0" phase should be "PARENT, when non-nil, is the parent of the first element to be removed. Yet, KEY is the key of the FIRST and FIRST itself is passed as PARENT. > (push (let ((beg (org-element-property :begin first)) > (key (org-element--cache-key first))) > ... > ;; Otherwise, we find the first non robust > ;; element containing END. All elements between > ;; FIRST and this one are to be removed. > ... > (t > (let* ((element (org-element--cache-find end)) > (end (org-element-property :end element)) > (up element)) > (while (and (setq up (org-element-property :parent up)) > (>= (org-element-property :begin up) beg)) > (setq end (org-element-property :end up) > element up)) > (vector key beg end offset element 0))))) Despite what the comment states, the following code simply searches for the parent of FIRST and extents the region of phase 0 request all the way to the end of that parent. (note that BEG is re-bound to the beginning of the FIRST). Now, consider the following branch of org-element--cache-submit-request. The (aref next 4) may contain the parent of FIRST from the above code. That parent is robust (or it would be returned by org-element--cache-for-removal) and its :end/:contents-end have already been shifted in the earlier call to org-element--cache-for-removal (that was where we have found the FIRST value): > ;; If last change happened within area to be removed, extend > ;; boundaries of robust parents, if any. Otherwise, find > ;; first element to remove and update request accordingly. > (if (> beg delete-from) > ... > (let ((up (aref next 4))) > (while up > (org-element--cache-shift-positions > up offset '(:contents-end :end)) > (setq up (org-element-property :parent up)))) The first iteration of the while loop will potentially extend the :end/:contents-end of the parent of FIRST second time in a row. Best, Ihor --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=0001-Add-comments-to-org-element-cache-code.patch >From 354275e12ca86b3f226a08dd57f0794e680afc49 Mon Sep 17 00:00:00 2001 Message-Id: <354275e12ca86b3f226a08dd57f0794e680afc49.1621740204.git.yantar92@gmail.com> From: Ihor Radchenko Date: Sun, 23 May 2021 11:03:40 +0800 Subject: [PATCH] Add comments to org-element-cache code --- lisp/org-element.el | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/lisp/org-element.el b/lisp/org-element.el index ba4f0ead6..b9bb87b66 100644 --- a/lisp/org-element.el +++ b/lisp/org-element.el @@ -5322,6 +5322,9 @@ (defun org-element--cache-process-request (if (if (or (not next) (org-element--cache-key-less-p data-key next)) (<= pos end) + ;; FIXME: Isn't LAST-CONTAINER always nil here? + ;; We are inside let-binding defining + ;; last-container to be nil. (and last-container (let ((up data)) (while (and up (not (eq up last-container))) @@ -5675,7 +5678,10 @@ (defun org-element--cache-for-removal (beg end offset) any position between BEG and END. As an exception, greater elements around the changes that are robust to contents modifications are preserved and updated according to the -changes." +changes. In the latter case, the returned element is the outermost +non-robust element affected by changed. Note that the returned +element may end before END position in which case some cached element +starting after the returned may still be affected by the changes." (let* ((elements (org-element--cache-find (1- beg) 'both)) (before (car elements)) (after (cdr elements))) @@ -5722,22 +5728,39 @@ (defun org-element--cache-submit-request (beg end offset) (let ((next (car org-element--cache-sync-requests)) delete-to delete-from) (if (and next + ;; First existing sync request is in phase 0. (zerop (aref next 5)) + ;; Current changes intersect with the first sync request. (> (setq delete-to (+ (aref next 2) (aref next 3))) end) (<= (setq delete-from (aref next 1)) end)) ;; Current changes can be merged with first sync request: we ;; can save a partial cache synchronization. (progn + ;; Update OFFSET of the existing request. (cl-incf (aref next 3) offset) ;; If last change happened within area to be removed, extend ;; boundaries of robust parents, if any. Otherwise, find ;; first element to remove and update request accordingly. (if (> beg delete-from) + ;; The current modification is completely inside NEXT. + ;; (aref next 4) is supposed to be the outermost parent + ;; to be removed. Everything in cache inside that + ;; element will be removed later and we do not care + ;; about extending boundaries of robust elements in + ;; there. Also, all the upper elements are guaranteed + ;; to be robust because otherwise `org-element--cache-for-removal' + ;; would return more outer element (to be stored in + ;; (aref next 4). (let ((up (aref next 4))) (while up (org-element--cache-shift-positions up offset '(:contents-end :end)) (setq up (org-element-property :parent up)))) + ;; The current and NEXT modifications are intersecting + ;; with current modification starting before NEXT and NEXT + ;; ending after current. We need to update the common + ;; non-robust parent for the new extended modification + ;; region. (let ((first (org-element--cache-for-removal beg delete-to offset))) (when first (aset next 0 (org-element--cache-key first)) @@ -5762,8 +5785,15 @@ (defun org-element--cache-submit-request (beg end offset) ;; Otherwise, we find the first non robust ;; element containing END. All elements between ;; FIRST and this one are to be removed. + ;; + ;; The current modification is completely inside + ;; FIRST. Clear and update cached elements in + ;; region containing FIRST. ((let ((first-end (org-element-property :end first))) - (and (> first-end end) + (and (>= first-end end) + ;; FIXME: According to `org-element--cache-sync-requests' + ;; docstring, (aref 4 request) must be the + ;; parent of the first element to be removed. (vector key beg first-end offset first 0)))) (t (let* ((element (org-element--cache-find end)) @@ -5773,6 +5803,8 @@ (defun org-element--cache-submit-request (beg end offset) (>= (org-element-property :begin up) beg)) (setq end (org-element-property :end up) element up)) + ;; Extend region to remove elements to parent + ;; of the FIRST. (vector key beg end offset element 0))))) org-element--cache-sync-requests) ;; No element to remove. No need to re-parent either. -- 2.26.3 --=-=-=--