From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms8.migadu.com with LMTPS id kGDqKYjvtmWp+gAA62LTzQ:P1 (envelope-from ) for ; Mon, 29 Jan 2024 01:21:28 +0100 Received: from aspmx1.migadu.com ([2001:41d0:403:4876::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp1.migadu.com with LMTPS id kGDqKYjvtmWp+gAA62LTzQ (envelope-from ) for ; Mon, 29 Jan 2024 01:21:28 +0100 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=USbbZEMi; 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" ARC-Seal: i=1; s=key1; d=yhetil.org; t=1706487688; a=rsa-sha256; cv=none; b=ZYBzGMp42VsKeouus94I+DtIHV29sBwPkyFaNB7NwVHLRSfEHg1qASGHlx+13eGHpZkHO6 FjFJR+GLNv3ajlg3575JS6/1kSdrdXeK1j5jTxG6b6RFSMtk3qqc9E/oUMIwOaNB0wnyUr CKY1bydg9FeIa9YogVuUEZRGMV7aIPTCs8u1HFVwav4PTv74RFypI2jorWV90sQStI6ysH JYFIyd6Z3nSfJFaGJJkzaIskEaHUa2UkPxy+UJ0uEmzu1MpjxlFJ6VkGa+a45NR5sXsFin dxPdgIPnKljNI9xK5IeIYouFhke/hX+DCmjmyw0a8pm5OtqhV3Ll8EuCizVyxg== ARC-Authentication-Results: i=1; aspmx1.migadu.com; dkim=pass header.d=gmail.com header.s=20230601 header.b=USbbZEMi; 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" ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1706487688; 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: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post:dkim-signature; bh=r0G4ezhAI6JbY4ngxjPfYCYS0W6+Ecah3CmSYp/p7hU=; b=ONDKid5ZOuSxrgHBgETN9NxwiHnCMTM1IkWu+Tzt1AsTj8jXMoIpU0nbOH4HwkMFW1QlHB mZ0bGLMenO7XWJXOeAsNA/VL9I+Sl8boDQbfVdiqqbKYib/SIXmVlZoBFZ4NIvqsQQuOu/ 8pv8jwULExrzi8oU0L7FyW1uARRxawgaXAl/4PcKosvKapYz08RkrGgdUu1q+cZ5IfJnTE 6lGo/wJKJVTWRTa00hZqvF8UXFgC/nsY3UEy5xiBuBTo35IWMjdUl8bnohkBz1tNI0GZL3 +wSsWiqmSGeN4nCCmqHvrULkehjAKeYBNLzxG9gxHxsQ5Rm8Ml3LcBiGmT4FZw== 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 4728123F7F for ; Mon, 29 Jan 2024 01:21:28 +0100 (CET) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1rUFNy-0001BM-CA; Sun, 28 Jan 2024 19:20:26 -0500 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 1rUFNw-0001At-0X for emacs-orgmode@gnu.org; Sun, 28 Jan 2024 19:20:24 -0500 Received: from mail-lf1-x12f.google.com ([2a00:1450:4864:20::12f]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1rUFNr-0001U3-VE for emacs-orgmode@gnu.org; Sun, 28 Jan 2024 19:20:22 -0500 Received: by mail-lf1-x12f.google.com with SMTP id 2adb3069b0e04-51029c6f355so651680e87.1 for ; Sun, 28 Jan 2024 16:20:18 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1706487616; x=1707092416; darn=gnu.org; h=content-transfer-encoding:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=r0G4ezhAI6JbY4ngxjPfYCYS0W6+Ecah3CmSYp/p7hU=; b=USbbZEMi7jJ/x2v9V2sPicyZsQVVGbBPF2ecgbVvMBWf4qF65EcCoTKUl+5M2m/Q/9 BQSzP9xhUDSXzhcSpcmUE0vDOF9z7vP5DmlH6kOLdQYWEHP/z6vCfje3uGXyTQaB7sIi iUqeecqRJR17B3z3m4fFkaAC+E2FRAqu/0BCUQJA75DOyOwo5ynespBcmiHC44ZrEYew WTff4/zdZtslJHWQUxp/U7grl9MBOBoYPwrqp1gryTJ1VGvE0AFfeaPkPQrtanJ+15Yw zT4BgyqMXAG36iSedtgrd3x7v4SBM912D2Z/1sHyXL6qAVLaGkUGm+EPUuzNV7PrAKhu oOLg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1706487616; x=1707092416; h=content-transfer-encoding:cc:to:subject:message-id:date:from :references:in-reply-to:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=r0G4ezhAI6JbY4ngxjPfYCYS0W6+Ecah3CmSYp/p7hU=; b=Cs65fiKRkK3srN409tc5AfSZunx/sOV5e8fV9qOYDAA6eTHlt8vyNzo33/zxp+DrXJ xoKnMalQm8JvZ/xkl63DNlrhcyGGfQh+zVWIPORfV6c1UOvvOwcQNnApkuqaikOWwBXb Sr2Mhj1/4WO/FD0yUdtf6D7boRDkFa+7KbRVfpvwAHf2Hd35loTWJPWxaiwaXP3Hel28 nFrS/CIQAxrHzmS/PKxcZZzoRIbmeHXy8/82rUWz6UyAUKl2cF2wupdGdYaste/u+BUi IVbFdMioJlbsFR1P6rcuIPRL7uEgzfGV1hqeC8pJa4XF/vdI/tObxrtLdGr1biga7EWO eajw== X-Gm-Message-State: AOJu0Yyecqoeb5SYlccaUMN7KaY39t5mVTIPB4QwFJ93n7WvUpS2HMIp 0Kt/2fMhYoThnCcCw+zIbDeHiwYvIMoTNHRLDP+8SguWGtZmyaGGlqOu4shfCDEB3vnEbpXAs2/ AE4ItXzbBDQGbLuj6RRtT095XatIrUqJapnO/tA== X-Google-Smtp-Source: AGHT+IHSo1swcuh/mOXtRf5V0T+ApcH1chf33is3j5bxUNDz2KKZcfM9fq69ThN6+jQTQFuojCIxE7zm+zoIjU857d0= X-Received: by 2002:a2e:5152:0:b0:2cf:4ea6:68d1 with SMTP id b18-20020a2e5152000000b002cf4ea668d1mr2937570lje.4.1706487616331; Sun, 28 Jan 2024 16:20:16 -0800 (PST) MIME-Version: 1.0 Received: by 2002:aa6:d9ca:0:b0:285:71fa:881f with HTTP; Sun, 28 Jan 2024 16:20:14 -0800 (PST) In-Reply-To: <1b50d1a4-8573-4dcc-9427-8970f67e632a@app.fastmail.com> References: <118435e8-0b20-46fd-af6a-88de8e19fac6@app.fastmail.com> <87edkwsafe.fsf@localhost> <87cywh2ad6.fsf@localhost> <87jzpmqiy0.fsf@localhost> <2cdfefbf-e9e3-4aeb-a410-1ff3a9d6168e@app.fastmail.com> <87zfybzkul.fsf@localhost> <3c5737c8-f489-4144-a27f-c0e0527c79c0@app.fastmail.com> <87bkaqcjpz.fsf@localhost> <87msu7r902.fsf@localhost> <1b50d1a4-8573-4dcc-9427-8970f67e632a@app.fastmail.com> From: Samuel Wales Date: Sun, 28 Jan 2024 17:20:14 -0700 Message-ID: Subject: Re: [PATCH v2] org-id: allow using parent's existing id in links to headlines To: Rick Lupton Cc: Ihor Radchenko , "Y. E." Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass client-ip=2a00:1450:4864:20::12f; envelope-from=samologist@gmail.com; helo=mail-lf1-x12f.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 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_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-bounces+larch=yhetil.org@gnu.org X-Migadu-Flow: FLOW_IN X-Migadu-Country: US X-Migadu-Scanner: mx10.migadu.com X-Spam-Score: -9.97 X-Migadu-Queue-Id: 4728123F7F X-Migadu-Spam-Score: -9.97 X-TUID: 7+0k7/PS2I2Y sounds like a lot of contribution. i do not want to impede anything anybody else wants, but want to point out my user experience over years in case useful to anybody. my experiene is that context, search, and file links typically break for me, as i change headers, refile, fix typos, change paths, etc. so i stick with just org-id and, for export, custom id where possible. however, i would DEFINITELY also use org id link targets that are puttable in various locations [e.g. id markers]. what i am pointing out is probably obvious, but might be worth pointing out in a sentence in manual, or for setting defaults? On 1/28/24, Rick Lupton wrote: > Hi, > > Thanks for trying it out. Updated patches attached, comments below. > > On Mon, 18 Dec 2023, at 12:27 PM, Ihor Radchenko wrote: >> I played around with the patch a bit and found a couple of rough edges: >> >> 1. When I try to open a link to non-existing search target, like >> , I get a query to create a new >> heading. If I reply "yes", a new heading is created. However, the >> heading is created at the end of the file and is always level 1, >> regardless of the "some-id" parent context. >> It would make more sense to create a new heading at the end of the >> id:some-id subtree. > > Fixed in updated patches -- first patch adds generic new flexibility to > `org-insert-heading', second patch uses it so new headings now added at > correct level at the end of the id:sub-id subtree. > >> 2. Consider the following setting: >> (setq org-id-link-consider-parent-id t) >> (setq org-id-link-to-org-use-id >> 'create-if-interactive-and-no-custom-id) >> >> Then, create the following Org file >> >> * Sub >> * Parent here >> ** This is test >> :PROPERTIES: >> :ID: fe40252e-0527-44c1-a990-12498991f167 >> :END: >> >> *** Sub >> :PROPERTIES: >> :CUSTOM_ID: subid >> :END: >> >> When you M-x org-store-link, the stored link has ::*Sub instead of >> the expected ::#subid > > Updated so that search strings prefer custom-ids (::#subid) to headline > matches (::*Sub). This makes this example behave as you expect. > > The correct behaviour of org-store-link doesn't seem totally obvious to m= e > about id vs custom-id links. Currently org-store-link has special logic = to > store TWO links (one , one ) when a > CUSTOM_ID is present. In the manual, it says: > > If the headline has a =E2=80=98CUSTOM_ID=E2=80=99 property, store a = link to this > custom ID. In addition or alternatively, depending on the value of > =E2=80=98org-id-link-to-org-use-id=E2=80=99, create and/or use a glo= bally unique > =E2=80=98ID=E2=80=99 property for the link(1). So using this comman= d in Org > buffers potentially creates two links: a human-readable link from > the custom ID, and one that is globally unique and works even if > the entry is moved from file to file. The =E2=80=98ID=E2=80=99 prop= erty can be > either a UUID (default) or a timestamp, depending on > =E2=80=98org-id-method=E2=80=99. Later, when inserting the link, yo= u need to > decide which one to use. > > That refers to ID links specifically, but now, using the generic link sto= re > functions, there is only the possibility to store one link type, so it's = not > possible to neatly keep exactly the same behaviour (i.e. for ID links but > not for other external link types). > > I think the intention of what's described in the manual is to distinguish > "human-readable" vs "persistent id" links. There could be other types of > "persistent id" links apart from org-id links, such as mu4e: links to ema= il > message-ids. Therefore I've updated org-store-link to simply store a > link as an additional option, whether or not th= e > first matched link was an org-id link (this is the current behaviour) or > another external link type (this is changed behaviour). > > Added a note to ORG-NEWS about this. > >> 3. Consider >> (setq org-id-link-consider-parent-id t) >> (setq org-id-link-to-org-use-id t) >> >> Then, create a new empty Org file >> M-x org-store-link with create a top-level properties drawer with ID >> and store the link. However, that link will not be a simple ID link, >> but also have ::PROPERTIES search string, which is not expected. > > This is because it is trying to link to the current line of the file, whi= ch > contains the text "PROPERTIES". On main, with (setq > org-id-link-to-org-use-id nil), you see the equivalent behaviour (a link = to > [[file:test.org:::PROPERTIES:]]) when point is before the first heading. > So, this seems consistent with non-org-id links? > > (these links don't actually work with the default value of > `org-link-search-must-match-exact-headline', but I think that's a separat= e > issue). > >>> + #+vindex: org-id-link-consider-parent-id >>> + When ~org-id-link-consider-parent-id~ is ~t~, parent =3DID=3D proper= ties >>> + are considered. This allows linking to specific targets, named >>> + blocks, or headlines (which may not have a globally unique =3DID=3D >>> + themselves) within the context of a parent headline or file which >>> + does. >> >> It would be nice to add an example, similar to what you did in the >> docstring. > > Added. > >> >>> -(defun org-man-store-link () >>> +(defun org-man-store-link (&optional _interactive?) >>> "Store a link to a man page." >>> (when (memq major-mode '(Man-mode woman-mode)) >>> ;; This is a man page, we do make this link. >>> @@ -21312,13 +21324,15 @@ A review of =3Dol-man.el=3D: >> >> Please, update the actual built-in :store functions in lisp/ol-*.el to >> handle the new optional argument as well. > > Updated. > >>> +**** =3Dorg-link=3D store functions are passed an ~interactive?~ argum= ent >>> + >>> +The ~:store:~ functions set for link types using >>> +~org-link-set-parameters~ are now passed an ~interactive?~ argument, >>> +indicating whether ~org-store-link~ was called interactively. >> >> Please also explain that the existing functions are not broken. > > Done. > >>> +*** ~org-id-store-link~ now adds search strings for precise link >>> targets >>> + >>> +This new behaviour can be disabled generally by setting >>> +~org-id-link-use-context~ to ~nil~, or when storing a specific link by >>> +passing a prefix argument to ~org-store-link~. >> >> universal argument. >> There are several possible prefix arguments in `org-store-link', but >> only C-u (universal argument) will give the described effect. >> Also, won't the behavior be _toggled_ by the universal argument? > > Updated. > >>> +When using this feature, IDs should not include =3D::=3D, which is use= d in >>> +links to indicate the start of the search string. For backwards >>> +compability, existing IDs including =3D::=3D will still be matched (bu= t >>> +cannot be used together with precise link targets). >> >> Please add an org-lint checker that warns about such IDs and mention >> this checker in the above. > > Added. > >> Also, this paragraph belongs to "Breaking changes", not "new and changed >> options". > > That's where it is, I think. > >>> +*** New option ~org-id-link-consider-parent-id~ to allow =3Did:=3D lin= ks to >>> parent headlines >>> + >>> +For =3Did:=3D links, when this option is enabled, ~org-store-link~ wil= l >>> +look for ids from parent/ancestor headlines, if the current headline >>> +does not have an id. >>> + >>> +Combined with the new ability for =3Did:=3D links to use search string= s >>> +for precise link targets (when =3Dorg-id-link-use-context=3D is =3Dt= =3D, which >>> +is the default), this allows linking to specific headlines without >>> +requiring every headline to have an id property, as long as the >>> +headline is unique within a subtree that does have an id property. >>> + >>> +By giving files top-level id properties, links to headlines in the >>> +file can be made more robust by using the file id instead of the file >>> +path. >> >> Please, provide an example here as well. > > Done. > >>> +(defun org-link--try-link-store-functions (interactive?) >>> + "Try storing external links, prompting if more than one is possible. >>> + >>> +Each function returned by `org-store-link-functions' is called in >>> +turn. If multiple functions return non-nil, prompt for which >>> +link should be stored. >>> + >>> +Return t when a link has been stored in `org-link-store-props'." >> >> Please document INTERACTIVE? argument in the docstring. > > Done. > >>> + (let ((results-alist nil)) >>> + (dolist (f (org-store-link-functions)) >>> + (when (condition-case nil >>> + (funcall f interactive?) >>> + ;; XXX: The store function used (< Org 9.7) to accept no >>> + ;; arguments; provide backward compatibility support for >>> + ;; them. >> >> Use FIXME, not XXX. (I have no idea why it is XXX in the existing code). > > Changed. > >>> +(defun org-link-precise-link-target (&optional relative-to) >>> + "Determine search string and description for storing a link. >>> + >>> +If a search string is found, return cons cell (SEARCH-STRING >>> +. DESC). Otherwise, return nil. >>> + >>> +If there is an active region, the contents is used (see >>> +`org-link--context-from-region'). >> >> It is not clear from this sentence whether the contents is used for >> SEARCH-STRING of DESC. >> >>> +In org-mode buffers, if point is at a named element (e.g. a >>> +source block), the name is used. If within a heading, the current >>> +heading is used. >> >> Please use double space between sentences. >> >>> +Optional argument RELATIVE-TO specifies the buffer position where >>> +the search will start from. If the search target that would be >>> +returned is already at this location, return nil to avoid >>> +unnecessary search strings (for example, when using search >>> +strings to find targets within org-id links)." >> >> It is not clear what will happen if RELATIVE-TO is before/after point. > > Updated the docstring. > >>> - (let (link cpltxt desc search custom-id agenda-link) ;; descriptio= n >>> + (let ((org-link-context-for-files (org-xor >>> org-link-context-for-files >>> + (equal arg '(4)))) >>> + link cpltxt desc search custom-id agenda-link) ;; descriptio= n >>> (cond >>> ;; Store a link using an external link type, if any function is >>> - ;; available. If more than one can generate a link from current >>> - ;; location, ask which one to use. >>> + ;; available. If more than one can generate a link from >>> + ;; current location, ask which one to use. Negate >>> + ;; `org-context-in-file-links' when given a single prefix arg. >> >> The part of the comment about negation, should probably be moved near >> the let binding of `org-link-context-for-files'. > > Done. > >>> +For example, given this org file: >>> + >>> +* Parent >>> +:PROPERTIES: >>> +:ID: abc >>> +:END: >>> +** Child 1 >>> +** Child 2 >>> + >>> +With `org-id-link-consider-parent-id' set to t, storing a link >>> +with point at \"Child 1\" will produce a link \"id:abc\" to >>> +\"Parent\". >> >> This is actually confusing. May we only consider parent when >> `org-id-link-use-context' is enabled? > > Yes, I was trying to keep them independent but I agree it's probably more > useful to only consider parent when `org-id-link-use-context' is enabled > (which in turn depends on `org-context-in-file-links' being enabled). > >>> -(defun org-id-get (&optional epom create prefix) >>> +(defun org-id-get (&optional epom create prefix inherit) >>> "Get the ID property of the entry at EPOM. >>> EPOM is an element, marker, or buffer position. >>> If EPOM is nil, refer to the entry at point. >>> If the entry does not have an ID, the function returns nil. >>> +If INHERIT is non-nil, parents' IDs are also considered. >>> However, when CREATE is non-nil, create an ID if none is present >>> already. >>> PREFIX will be passed through to `org-id-new'. >>> In any case, the ID of the entry is returned." >> >> What about both CREATE and INHERIT being non-nil? > > Rewrote the docstring. > > Also removed INHERIT argument for `org-id-get-create' again, as other > functions can be re-written to use `org-id-get' directly, and INHERIT isn= 't > particularly useful when using `org-id-get-create' interactively. > >>> +;;;###autoload >>> +(defun org-id-store-link-maybe (&optional interactive?) >>> + "Store a link to the current entry using its ID if enabled. >>> + >>> +The value of `org-id-link-to-org-use-id' determines whether an ID >>> +link should be stored, using `org-id-store-link'. >>> + >>> +Assume the function is called interactively if INTERACTIVE? is >>> +non-nil." >>> + (interactive "p") >> >> Do we really need to make it interactive? > > No, removed. > > Thanks, > Rick --=20 The Kafka Pandemic A blog about science, health, human rights, and misopathy: https://thekafkapandemic.blogspot.com