From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp0 ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms11 with LMTPS id 8cRDCbA71V/JSAAA0tVLHw (envelope-from ) for ; Sat, 12 Dec 2020 21:52:48 +0000 Received: from aspmx1.migadu.com ([2001:41d0:2:4a6f::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp0 with LMTPS id +I2TBLA71V+UcwAA1q6Kng (envelope-from ) for ; Sat, 12 Dec 2020 21:52:48 +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 4803594014B for ; Sat, 12 Dec 2020 21:52:47 +0000 (UTC) Received: from localhost ([::1]:56934 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1koCoo-0006R6-7K for larch@yhetil.org; Sat, 12 Dec 2020 16:52:46 -0500 Received: from eggs.gnu.org ([2001:470:142:3::10]:43404) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1koCoK-0006Qc-G3 for emacs-orgmode@gnu.org; Sat, 12 Dec 2020 16:52:16 -0500 Received: from server173-4.web-hosting.com ([68.65.122.210]:36205) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1koCoF-0007id-8b for emacs-orgmode@gnu.org; Sat, 12 Dec 2020 16:52:15 -0500 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=isnotmyreal.name; s=default; h=Content-Transfer-Encoding:Content-Type: Message-ID:References:In-Reply-To:Subject:To:From:Date:MIME-Version:Sender: Reply-To:Cc:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id:List-Help: List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=fVhwJZdDWlklAgl/FJhENBPcxWL3MZh0EEiu4xVDapg=; b=IjFDBrnRPAsWmeW7vXGTKgS0t0 TKOwJbkSPcPRGg4Y0Uwerr038o72EolDz4nhulTjo1GBiNKTZ5yi47VTgXUisX+eJbv2U8vMyKb3T O8erZgbVwsl3h6jZiTfN03CAxiCOO6TTt5AzZQSsdWqUz/HbQ7Mf1qQhjPSGBr6SXsAo7TM3iGeEk Hsw1gd9UBmPveBMcGQ0seCEm2JJ99N50IsLWZoI7Zv3cp7zUL1BGRObHe+uGG9RSBbtW5niiIb5gX cpKy53XFXrwiw5MMNyCMZ57AIk6bfB9bSBcSxhJFyhJBWbpPDTGo+T0ps4urE0mYnskooL/lxR0O5 meCK1tTg==; Received: from [::1] (port=44376 helo=server173.web-hosting.com) by server173.web-hosting.com with esmtpa (Exim 4.93) (envelope-from ) id 1koCnO-002BiZ-P1 for emacs-orgmode@gnu.org; Sat, 12 Dec 2020 16:51:23 -0500 MIME-Version: 1.0 Date: Sat, 12 Dec 2020 16:51:18 -0500 From: TRS-80 To: emacs-orgmode@gnu.org Subject: Re: stability of toc links In-Reply-To: References: Message-ID: X-Sender: lists.trs-80@isnotmyreal.name User-Agent: Roundcube Webmail/1.3.15 Content-Type: text/plain; charset=US-ASCII; format=flowed Content-Transfer-Encoding: 7bit X-OutGoing-Spam-Status: No, score=-0.2 X-AntiAbuse: This header was added to track abuse, please include it with any abuse report X-AntiAbuse: Primary Hostname - server173.web-hosting.com X-AntiAbuse: Original Domain - gnu.org X-AntiAbuse: Originator/Caller UID/GID - [47 12] / [47 12] X-AntiAbuse: Sender Address Domain - isnotmyreal.name X-Get-Message-Sender-Via: server173.web-hosting.com: authenticated_id: lists.trs-80@isnotmyreal.name X-Authenticated-Sender: server173.web-hosting.com: lists.trs-80@isnotmyreal.name X-Source: X-Source-Args: X-Source-Dir: X-From-Rewrite: unmodified, already matched Received-SPF: pass client-ip=68.65.122.210; envelope-from=lists.trs-80@isnotmyreal.name; helo=server173-4.web-hosting.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, 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: , Errors-To: emacs-orgmode-bounces+larch=yhetil.org@gnu.org Sender: "Emacs-orgmode" X-Migadu-Flow: FLOW_IN X-Migadu-Spam-Score: -1.30 Authentication-Results: aspmx1.migadu.com; dkim=fail (headers rsa verify failed) header.d=isnotmyreal.name header.s=default header.b=IjFDBrnR; dmarc=none; 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: 4803594014B X-Spam-Score: -1.30 X-Migadu-Scanner: scn1.migadu.com X-TUID: 1fJoavELsi+g On 2020-12-08 20:39, Tom Gillespie wrote: > It sounds like you are looking for the CUSTOM_ID property. See > https://orgmode.org/manual/Handling-Links.html and > https://orgmode.org/manual/Internal-Links.html. I don't remember > whether there is a way to generate ids matching headlines within org > itself, but there is > https://github.com/alphapapa/unpackaged.el#export-to-html-with-useful-anchors. > Best! > Tom I had set out to shave this particular yak just yesterday I think it was. I know I came across alphapapa's solution and maybe TEC's too, but they were more complex than I could seem to get my feeble brain around at the time. Also, I was going for more of a deterministic result, trying to end up with something like a Markdown style link id. This coming up in the course of my larger mission towards better support for exporting README.org to Markdown (and ultimately, nicely rendered HTML) files over at Sourcehut[0]. Finally, this operates by a totally different way than replacing some part of Org export function(s). My approach was simply to dynamically assign a CUSTOM_ID property to every heading in current buffer (that did not have one already) which would be generated according to some deterministic method. With the idea to then go on after that and do whatever regular Org export you want. Right off the bat I will say this is a very, VERY immature implementation (literally yesterday). And I have only done the very lightest of testing (however it does basically work). Therefore this is not for consideration for inclusion into Orgmode but rather just my own workaround in the meantime. At best I might hope to add something useful to the ongoing discussion (or perhaps become enlightened why this is completely wrong approach). ;) I would like to point out the following problems which I have not (yet) addressed in the following functions (#1 being most glaring probably) as they are still too new: 1. The punctuation removal regexp needs to have many more characters added (currently only containing {!.'}). In fact, this strikes me as a bit hacky, I am not even sure it's the best approach. 2. This function operates only on the current buffer. 3. Many things still need to be parameterized, in particular the TODO state is hard coded to be included in the generated id and already I am starting to think that's a bad idea (but it depends on context I suppose, hence thinking to make it an option). 4. If I am trying to emulate Markdown (or any other spec) I really should study and more properly and fully implement said spec. I have done /absolutely no such thing/ so far, only a (quite off the cuff) "Markdown like" implementation. 5. Naming the function beginning with `my-ox-' is not meant that this should be included in ox- package necessarily but rather that I am associating it with exporting from Org within my own mind and personal init files. My plan (before stumbling across this thread ;) ) was to continue to use and polish these functions (privately) and eventually publish them on my (relatively new) sr.ht profile[1]. But since this came up, I guess I will go ahead and put it out there for feedback here on the mailing list. I still plan to eventually publish somewhere more properly with license, where patches can be accepted, etc... However in the meantime... With the above disclaimers out of the way, I present the following function (and another simple one it depends on) in the hope they are useful to someone. [0] https://sourcehut.org [1] https://sr.ht/~trs-80/ #+begin_src emacs-lisp (defun my-major-mode-insure (mode) "If we are not in MAJOR-MODE, exit with error." (unless (string= major-mode mode) (user-error "Buffer not in %s, exiting" mode))) (defun my-ox-assign-custom-ids () "Assign reliable CUSTOM_ID to each heading in current buffer. CUSTOM_ID will only be assigned if one does not exist already. The generated CUSTOM_ID roughly[0] follows (my very basic and limited understanding of) the Markdown spec. In other words, it will be generated by taking the heading text plus TODO state (so as not to break link) and: 1. Lower case it. 2. Remove all punctuation.[1] 3. Replace spaces with hyphens. [0] Currently, likely VERY roughly... [1] Currently this is a bit hacky `replace-regexp-in-string' featuring only a few common punctuation (right now only exclamation point, period, apostrophe (i.e., single quote). Much more will need to be added here, in fact I am not even sure this is the best approach." (interactive) (my-major-mode-insure 'org-mode) (org-map-entries '(org-set-property "CUSTOM_ID" ;; replace space with hyphen (replace-regexp-in-string " " "-" ;; remove punctuation (replace-regexp-in-string "\\\!\\|\\\.\\|'" "" (downcase (substring-no-properties (org-get-heading t nil t t)))))) nil 'file ;; skip function (lambda () (when (org-entry-get nil "CUSTOM_ID") (point))))) #+end_src