From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mp1.migadu.com ([2001:41d0:303:e224::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by ms13.migadu.com with LMTPS id gPiZC17zcmZR0AAA62LTzQ:P1 (envelope-from ) for ; Wed, 19 Jun 2024 15:03:58 +0000 Received: from aspmx1.migadu.com ([2001:41d0:303:e224::]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) by mp1.migadu.com with LMTPS id gPiZC17zcmZR0AAA62LTzQ (envelope-from ) for ; Wed, 19 Jun 2024 17:03:58 +0200 X-Envelope-To: larch@yhetil.org Authentication-Results: aspmx1.migadu.com; dkim=pass header.d=outlook.com header.s=selector1 header.b=kEq+Ago1; dmarc=pass (policy=none) header.from=outlook.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=pass ("microsoft.com:s=arcselector9901:i=1") ARC-Seal: i=2; s=key1; d=yhetil.org; t=1718809437; a=rsa-sha256; cv=pass; b=ue3Hce7crlwEHIezmWPEP6LGAH3ZD6qc4S8iOwKOFgyg07XWeMXlzx0vvdI2s8jjLXTHcX Uy/UNKdTRbDGYN7AMtLVQC23MPzdKk/jcY6tBK6A0M/cfnapLn1WZf/Nwn0RNRhsuWNGG5 DmN6mrmIlyVfBjahsJcqEXHafFtUWnyC1FbyGCjxcJ2OsCORx7J6KVDGs4Ph/ttAVAnw+n H+pCjSovnOHivlFCCsZADBiEpcjnmmF/LbSGym1OMMgCtkwQ2Lj8vJ17B3ROuil9VDARXm 6SAWkzo+II9Il1FOceqsZ/dMPNFEDUfIdmDL9yPQSd8LHJS4w6izFkrMoEy05A== ARC-Authentication-Results: i=2; aspmx1.migadu.com; dkim=pass header.d=outlook.com header.s=selector1 header.b=kEq+Ago1; dmarc=pass (policy=none) header.from=outlook.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=pass ("microsoft.com:s=arcselector9901:i=1") ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=yhetil.org; s=key1; t=1718809437; 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=WbBrDtvri02UDvRHlcpJXbOF/Z9zjwaZLHVESjJqh44=; b=X/Lg+zE6iplAqeUxubOYhgYTmqfWST7O1jrLrMy7tBc4M9H2jnU6TyWaxNwUdsxBWFW5yR 22+VdpGzxChvSiCK62W1v5vS+YIhMK7HLOK9INGSzdjvd1Rc7oxzh8GHk1zkGvCR581FQP fd4FWhscwuaIWMkXgnW4xGgYJ1dctEqefC6bNdbxcTh4AgdMi5UH/1ExoTct2ts8H15O60 tyBn2agYVp8fXYpbVn8p60cz31g7cGQaDs0R2WapZzaH2iyxUaFwJf/bqyGY4tWgsBpvb4 RS6rO0pSD6i1uErS+6s74bYb/87QB5aTPnb1Hvm/yxxyZ9d1YxQr9XaDE27kbg== 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 A3F056E82E for ; Wed, 19 Jun 2024 17:03:57 +0200 (CEST) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sJwpl-0005zm-Ln; Wed, 19 Jun 2024 11:02:49 -0400 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 1sJwpk-0005zL-Ay for emacs-orgmode@gnu.org; Wed, 19 Jun 2024 11:02:48 -0400 Received: from mail-dm6nam11olkn2014.outbound.protection.outlook.com ([40.92.19.14] helo=NAM11-DM6-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sJwpg-00019x-Tq for emacs-orgmode@gnu.org; Wed, 19 Jun 2024 11:02:48 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=BDCfDrLUi5/RqzNbHEGySGFkh9gdWqs9KZ5dFhGm4GLBCL9Fr/Uc8TWN/RVqyvudJd1GIm7KAj92vRlLP9PILXSRbNksxgPiXhGsN63r+xtr5PSrbSgLUysK0MWeduFXqF0M88tw7vwSaiH1fpj7L/Iid2EZAKhu/eFjdok0O8Lm/lKoGLjchW8SW3IpZsX0/k6ByC3kWzc3N/i7ygU9n2a9+DlyAXvyoUUEYK+dyjnatk9uFLqq+3FpBXFt7xPNrhMd0BSbyNH6Xbo8+0pQu3y5KFqtUK8OpU72GC9Y7mXVzBz4tkJqF1JKwzYqxwF6uH8wBw0/MLZgblBqqjVBQg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=WbBrDtvri02UDvRHlcpJXbOF/Z9zjwaZLHVESjJqh44=; b=in26wPbi6wd+5VmEqSlyrvpC7VG7SvGjfolKT2XIARLHmNd7I2BbyZo/rkuqKyoonPQ+ocC+nTxuVB+iRrql+5LX89kxbaYrZLBjbsj6tZ8e4eYrgBNwaVo/yzFe2qaAHPsXCUVzzFqOJGUpWvbpaeVmnlnLzTp/eW0qtEt7qc/gg7CK6YuaGxg78TzJ99mB9UiWf/yffegkNIEGkxNrlrz1o0oExxF3JrDoiBPlKX0bve+uCuLWJNeFsJXX9foEJhHb3VnrNcbpHppSRGoSkuFZ5DBEGMs5MsNIkXnNmMSnSqIU6Szva+/Fb7gUcwSu9SqdGL+dZBDTsXT5PBaLow== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=outlook.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=WbBrDtvri02UDvRHlcpJXbOF/Z9zjwaZLHVESjJqh44=; b=kEq+Ago1K92iakRjOKc1gzf/wAsErFll4b7RxMSZS2xMRDfJI61YzhVNPFlMS7488YM8UgaAVohSVQGuEYHZDe7/V+ckDJ+vEh1wuKbmPjzdaxAS4xu0A3cjPGi9MC/MNokRv0g9lDBjD4J7BDOXOcgJovoFO5TxT8h6Cr8H1XOssA+yk8OisqIsGUKScGHRdIcDPBDGaNESQc0Zcu8OgynPSLiLeiLtigweSbJD+HaG4qwyvq4uKS4S1oT4aXi3rUhtSsm/pcqDLHPC/ASmWTjLkh2VqfQirgjG/Wjm4Zi5IKpWYI5iQdCtCYrcAYS69KGyQ8AuJxWW6pkHg5mxYg== Received: from CH3PR84MB3424.NAMPRD84.PROD.OUTLOOK.COM (2603:10b6:610:1c4::17) by SJ2PR84MB3369.NAMPRD84.PROD.OUTLOOK.COM (2603:10b6:a03:58e::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.7677.30; Wed, 19 Jun 2024 14:57:38 +0000 Received: from CH3PR84MB3424.NAMPRD84.PROD.OUTLOOK.COM ([fe80::5c77:7a58:48ed:9aef]) by CH3PR84MB3424.NAMPRD84.PROD.OUTLOOK.COM ([fe80::5c77:7a58:48ed:9aef%3]) with mapi id 15.20.7677.030; Wed, 19 Jun 2024 14:57:38 +0000 From: Morgan Smith To: Ihor Radchenko Cc: emacs-orgmode@gnu.org, Sanel Zukan Subject: Re: [PATCH] lisp/org-clock.el (org-clock-sum): Rewrite regex using rx In-Reply-To: <875xu6aee8.fsf@localhost> (Ihor Radchenko's message of "Tue, 18 Jun 2024 07:39:11 +0000") References: <87r0f9b9n2.fsf@localhost> <87frvpyzrf.fsf@localhost> <875xu6aee8.fsf@localhost> X-Hashcash: 1:20:240619:emacs-orgmode@gnu.org::9DL1a6wjjmaLUaUt:ilZ X-Hashcash: 1:20:240619:yantar92@posteo.net::quUhsdGSp1u4KcG8:2ctO X-Hashcash: 1:20:240619:sanelz@gmail.com::6AW3ldPRXMB5KG7j:DEQO Date: Wed, 19 Jun 2024 10:57:30 -0400 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Content-Type: multipart/mixed; boundary="=-=-=" X-TMN: [Jh4aHxuIxaw7qQ5HIltNuW5/KAKDtFBQqvyZ8eZHgcGzJ4yGLY+qNA==] X-ClientProxiedBy: YQZPR01CA0076.CANPRD01.PROD.OUTLOOK.COM (2603:10b6:c01:84::19) To CH3PR84MB3424.NAMPRD84.PROD.OUTLOOK.COM (2603:10b6:610:1c4::17) X-Microsoft-Original-Message-ID: <87h6dpugit.fsf@outlook.com> MIME-Version: 1.0 X-MS-Exchange-MessageSentRepresentingType: 1 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: CH3PR84MB3424:EE_|SJ2PR84MB3369:EE_ X-MS-Office365-Filtering-Correlation-Id: a4dcd1c5-29e6-4a71-12a0-08dc90702938 X-MS-Exchange-SLBlob-MailProps: laRBL560oLTiSjDFzydrB1Da6XzSPC6xQQaoIiu62bdoWNGKg/B/u2njpoqVqQSaA+GLD9BoeirM2FOkAk7l3Hm9lotIIoPUeLYVUCP9ycG82hWB3Zn0tBzs3Qzf4kLF57Dr3JglQQNpl2HdICJv2Pf4KskQyq/ihnNKbGUO6MhrW6k46D9fyKCbs/BRaQlciOqdXGi8bM7ZnuYHxXL3ETobAh2PBCYnyrktO1ihHmF+hlV1c3MM60v4t3yRPzZ1MD2i+k9h1H5y8B18urYy617HTQVlaH3GfWdbtOJeiCSHz7DiHUWHw5N0/E0LmaNoG+ocdfrKqKYqvYVfY3Q2YCD0H5a6eU5UM7WZqjeASi3NzHnjsVK2vi1vkFiSiwsj+d9D9ZQY7+fBuWs/9HkkDbSp2gQay1ZGxpcQTYY8BVMau1VVzaRY+OZDuRmuZdLeT6+QyLUNsMAsyEtxtn5WX5saV2Eu8bF+8pz0CrcOvxcSs3MHEHu1M7TgArIDgdq2S2Sk2ovQO//WW8GrdbhF020t3UUbdVX4p4kDqOSUDRBKuglQ+rVKmy2KxfVon0jYR1082Y6mmulex8RWsve1qD3voa2rbDD7XS1G3/T874yWd19LdAurjpPxFa0Gkx2SixmauSTKdgTV+BcwVDenjuJfLNd+wmaOkvzM5XoONSsz3fwJCCUlFJcopxBzREvhYB2VueQzmmfI27EWDcaz9CvGLdlUZdFn0uRBLRergT/AGR4nz/QK2UloBLNk5/0TluvecQEbqR1VOVK3KOFCI8gjdbYZ35Vb X-Microsoft-Antispam: BCL:0; ARA:14566002|6092099009|461199025|1602099009|56899030|3412199022|440099025|4302099010; X-Microsoft-Antispam-Message-Info: ykO5auT1tBEMIK+kUDjZ7XsZ2krpv/WhxnEWOt86vrEYUbZU5jPoYGdKhmYcrxqSQU9712dg3QU0l0pjrrnDDCpDokNki4hT9x7ja3z5KC4Kh50oU6f/s8uK83dKg33gQZeFGzMtVXk9Yk957pNDL6iGvSUTVJx8godonqqM8W2eENvdQqes9VrK/Oi3RZs9FlnF6x1DXCkRH8o64FzvkLeKp3rbtl6GlOmApss5XAhRTKRA8G0hkJWTiFGP+mH1kx+TcH1g8yI48PqQBZ6MGKl4QivJNTGpeAC9KWAljrIX5fmA/lF5JJNNGAVOcw41T12YGPhLUWKWEJYiFclz5FYwf7RboyCMiqK7YfZN0HehFUY+IOGboc/KfSzxyMWbx0cCCy6Vv2ui76wsORZJZSOp+5vx6eOceZkwoM6Hw4IXHMtBd2PkSKK35JCxuDAV8GPt+4OHeLwBg1anupRHy+bHEONg48IBjwOMwScAhcrof0XJQdzpK26og7pPcA9Xht5WWI+pMQpVLc4bToee9OvzimJaKAkz/dum8z8e+q1jGTk2Y9uuoD2jfTYkvdn5bBeipe2fQolR16vW4MDG+MhauYJ64uTq6SXlC7FKmjOTL8Fu0ZV74pRADhZypORrzOloxylsv5yi35yLLiPm06XvA7GNT8eaO2D6YhOGuoA1Way3ndm82Da9U6LCAPWZitf1Rtg+k8Tg34+gzyiBKmmUNE/J+P+rxLRM5fQ+uH4= X-MS-Exchange-AntiSpam-MessageData-ChunkCount: 1 X-MS-Exchange-AntiSpam-MessageData-0: =?us-ascii?Q?v1aNslcgtCQpWDwqFP4v1XwbEe6UItgzCm31f+kpbeHv4AKbs/Ecy6z9FSQL?= =?us-ascii?Q?zMeXz59fSOt3/j2XvG6XCTMY5HyoSklR1xhUAM0RBs/2CvvGFI7Wg0CuDS43?= =?us-ascii?Q?ADLSlm4Xg6fOh2SZG4REIMjr0eQzUD0F2P2O2zTJkVRJeEwNUNtqzPxokN1B?= =?us-ascii?Q?jkR5jFjk9UpYty9Bur5xuBq3BC56olNIdxteQrntth3hgfYKAlY/4AKXwcu9?= =?us-ascii?Q?CUE5qe3sjyTNaHcwmqDYxmI7euoe8h6yEepbrTO4VtsGdlmorGSRNPLEkOdW?= =?us-ascii?Q?1/4Ird2YN9CjbJyUQzs5rqqRzFDBQMnbZtuK6ai9VcU2O1v0HKUgenTCE7tV?= =?us-ascii?Q?B9i2y76BwaDiRIyFdwLy2p23ezkhZ26pTzFMjEWmND0tzUMTeLS+EcM5P5gU?= =?us-ascii?Q?Fd7t1VZy2/PJQYnBs4SxKHWI7mglgZZ7nrX4pSJPfNfAeBJTjiUYtV7phDW8?= =?us-ascii?Q?L7i/9HXB05bMZstAfdWjgUHIxGbIn7Cz9tyw3Cj1B3aRxiVWTuR4idesJe1b?= =?us-ascii?Q?i0UuC0NVUP6ZhfebztelbgMDWLh3YKbxxtnItkca5hReXKkiK8goczNqyfwh?= =?us-ascii?Q?h6Yx6tW/gVcSvYWKfEDd9wQaIQVGh453qZBYnIjSfq3Wt6XawMtyvoNX9sRG?= =?us-ascii?Q?3tW4bOOhey5ol0NvWRKIWFa1IdORhQUCp+dbJqpp1rJw6ClhAldzD0x/q9c7?= =?us-ascii?Q?0L6grzJ5/rXYCOgd0wXf8lq+8V9Y2uwysotBsOcr9+cRVCWe6+ckM15FOJuD?= =?us-ascii?Q?kc20CkkLLGatLvj5qgcnNoEF58E/no0WURR/0jyCjNRR/QU5Dgb6gWYhlJaP?= =?us-ascii?Q?Wwi18DQCWIqQ/XSgnTd2O/2Y/YAlU77cAkpVdJDf1rQxVk6EY29/pB88Y092?= =?us-ascii?Q?gFqJywvIdtgkUuA1A0krfKsrGp5/SjpeQdlcOHCGKFOvCefJErSXRkkBLJvV?= =?us-ascii?Q?v5mp3nQUWWuNBItfiwvmfiGBPRWl6wxqQfwNinlhly+rXgcUmil+ooe4+Q9O?= =?us-ascii?Q?8wyIvi7qLU9u/qo2ScK7tUJDC1oUzwp5loO951p9wfde9tc+2dLe10e/XWVy?= =?us-ascii?Q?xKW5cPTDDAryH4iuLkVOa6YcM20SH4wk/oDolQnxhsGbwafM1k5Zi7AmAiVM?= =?us-ascii?Q?tTpRT8GSAu0cqv+Bv+774dAJNGaHCX+lwqwrYVxLC9g6KaY9yCXX2H0XvUmS?= =?us-ascii?Q?g26dat0XAYO5T8D+rv58BlUPRVsUYTVc68/bLSUODqtOAFz9N1S+U11mh0yg?= =?us-ascii?Q?qCsE0JjqbnvcHe+fTsSrcDw8qsyn9Ysyz1mUBQOqzA=3D=3D?= X-OriginatorOrg: outlook.com X-MS-Exchange-CrossTenant-Network-Message-Id: a4dcd1c5-29e6-4a71-12a0-08dc90702938 X-MS-Exchange-CrossTenant-AuthSource: CH3PR84MB3424.NAMPRD84.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-OriginalArrivalTime: 19 Jun 2024 14:57:38.4179 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: SJ2PR84MB3369 Received-SPF: pass client-ip=40.92.19.14; envelope-from=morgan.j.smith@outlook.com; helo=NAM11-DM6-obe.outbound.protection.outlook.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, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_PASS=-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-Spam-Score: -8.49 X-Migadu-Scanner: mx12.migadu.com X-Spam-Score: -8.49 X-Migadu-Queue-Id: A3F056E82E X-TUID: UlenrVrSjR1V --=-=-= Content-Type: text/plain Ihor Radchenko writes: > Ping ;) So I gave up on this specific patch because I wrote a patch to just rewrite the entire `org-clock-sum' function using org-element API. Attached is the `org-clock-sum' rewrite patch which I've been using for a while with no issues. I have half finished patches locally to add more clocktable tests and to add clocktable benchmarks which is why I hadn't submitted this yet. This probably belongs in this email thread instead: https://list.orgmode.org/87y18vxgjs.fsf@localhost/ I believe I fixed all the points you brought up in that thread. While this patch is probably ready to merge, doing so might cause regressions to the fix applied in commit fd8ddf2874ca00505aa096c6172ea750cd5e9eaa. Ideally the fix in that commit should be ported to the org-element API. Notably, the malformed clock from the email thread from that commit is parsed a little strangely by org-element. I'm not sure what effect this has on my rewrite patch but regardless, we should probably fix this. Notice how ":day-end" and ":minute-end" are set but not ":hour-start" or ":minute-start". I have attached a rough patch adding a test for this case but my brain is currently melting from a heatwave so it might take me a while to make it into something good. Feel free to work on this yourself if you have time. "CLOCK: [2012-01-01 sun. 00rr:01]--[2012-01-01 sun. 00:02] => 0:01" (clock (:standard-properties ... :status closed :value (timestamp (:standard-properties ... :type inactive-range :range-type daterange :raw-value "[2012-01-01 sun. 00rr:01]--[2012-01-01 sun. 00:02]" :year-start 2012 :month-start 1 :day-start 1 :hour-start nil :minute-start nil :year-end 2012 :month-end 1 :day-end 1 :hour-end 0 :minute-end 2)) :duration "0:01")) --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0001-lisp-org-clock.el-org-clock-sum-Rewrite-using-elemen.patch >From d407b357ba4285acc3c2548e38f034b5665b40bb Mon Sep 17 00:00:00 2001 From: Morgan Smith Date: Thu, 11 Apr 2024 12:23:21 -0400 Subject: [PATCH 1/2] lisp/org-clock.el (org-clock-sum): Rewrite using element api --- lisp/org-clock.el | 200 +++++++++++++++++++++++----------------------- 1 file changed, 99 insertions(+), 101 deletions(-) diff --git a/lisp/org-clock.el b/lisp/org-clock.el index c6fd507b0..5842c1cc7 100644 --- a/lisp/org-clock.el +++ b/lisp/org-clock.el @@ -33,15 +33,13 @@ (require 'cl-lib) (require 'org) +(require 'org-element) (declare-function calendar-iso-to-absolute "cal-iso" (date)) (declare-function notifications-notify "notifications" (&rest params)) (declare-function org-element-property "org-element-ast" (property node)) -(declare-function org-element-contents-end "org-element" (node)) -(declare-function org-element-end "org-element" (node)) (declare-function org-element-type "org-element-ast" (node &optional anonymous)) (declare-function org-element-type-p "org-element-ast" (node types)) -(defvar org-element-use-cache) (declare-function org-inlinetask-at-task-p "org-inlinetask" ()) (declare-function org-inlinetask-goto-beginning "org-inlinetask" ()) (declare-function org-inlinetask-goto-end "org-inlinetask" ()) @@ -2021,105 +2019,68 @@ TSTART and TEND can mark a time range to be considered. HEADLINE-FILTER is a zero-arg function that, if specified, is called for each headline in the time range with point at the headline. Headlines for which HEADLINE-FILTER returns nil are excluded from the clock summation. -PROPNAME lets you set a custom text property instead of :org-clock-minutes." +PROPNAME lets you set a custom text property instead of :org-clock-minutes. + +Clocking entries that are open (as in don't have an end time) that are +not the current clocking entry will be ignored." (with-silent-modifications - (let* ((re (concat "^\\(\\*+\\)[ \t]\\|^[ \t]*" - org-clock-string - "[ \t]*\\(?:\\(\\[.*?\\]\\)-+\\(\\[.*?\\]\\)\\|=>[ \t]+\\([0-9]+\\):\\([0-9]+\\)\\)")) - (lmax 30) - (ltimes (make-vector lmax 0)) - (level 0) - (tstart (cond ((stringp tstart) (org-time-string-to-seconds tstart)) - ((consp tstart) (float-time tstart)) - (t tstart))) - (tend (cond ((stringp tend) (org-time-string-to-seconds tend)) - ((consp tend) (float-time tend)) - (t tend))) - (t1 0) - time) - (remove-text-properties (point-min) (point-max) - `(,(or propname :org-clock-minutes) t - :org-clock-force-headline-inclusion t)) - (save-excursion - (goto-char (point-max)) - (while (re-search-backward re nil t) - (let* ((element (save-match-data (org-element-at-point))) - (element-type (org-element-type element))) - (cond - ((and (eq element-type 'clock) (match-end 2)) - ;; Two time stamps. - (condition-case nil - (let* ((timestamp (org-element-property :value element)) - (ts (float-time - (org-encode-time - (list 0 - (org-element-property :minute-start timestamp) - (org-element-property :hour-start timestamp) - (org-element-property :day-start timestamp) - (org-element-property :month-start timestamp) - (org-element-property :year-start timestamp) - nil -1 nil)))) - (te (float-time - (org-encode-time - (list 0 - (org-element-property :minute-end timestamp) - (org-element-property :hour-end timestamp) - (org-element-property :day-end timestamp) - (org-element-property :month-end timestamp) - (org-element-property :year-end timestamp) - nil -1 nil)))) - (dt (- (if tend (min te tend) te) - (if tstart (max ts tstart) ts)))) - (when (> dt 0) (cl-incf t1 (floor dt 60)))) - (error - (org-display-warning (format "org-clock-sum: Ignoring invalid %s" (org-current-line-string)))))) - ((match-end 4) - ;; A naked time. - (setq t1 (+ t1 (string-to-number (match-string 5)) - (* 60 (string-to-number (match-string 4)))))) - ((memq element-type '(headline inlinetask)) ;A headline - ;; Add the currently clocking item time to the total. - (when (and org-clock-report-include-clocking-task - (eq (org-clocking-buffer) (current-buffer)) - (eq (marker-position org-clock-hd-marker) (point)) - tstart - tend - (>= (float-time org-clock-start-time) tstart) - (<= (float-time org-clock-start-time) tend)) - (let ((time (floor (org-time-convert-to-integer - (time-since org-clock-start-time)) - 60))) - (setq t1 (+ t1 time)))) - (let* ((headline-forced - (get-text-property (point) - :org-clock-force-headline-inclusion)) - (headline-included - (or (null headline-filter) - (save-excursion - (save-match-data (funcall headline-filter)))))) - (setq level (- (match-end 1) (match-beginning 1))) - (when (>= level lmax) - (setq ltimes (vconcat ltimes (make-vector lmax 0)) lmax (* 2 lmax))) - (when (or (> t1 0) (> (aref ltimes level) 0)) - (when (or headline-included headline-forced) - (if headline-included - (cl-loop for l from 0 to level do - (aset ltimes l (+ (aref ltimes l) t1)))) - (setq time (aref ltimes level)) - (goto-char (match-beginning 0)) - (put-text-property (point) (line-end-position) - (or propname :org-clock-minutes) time) - (when headline-filter - (save-excursion - (save-match-data - (while (org-up-heading-safe) - (put-text-property - (point) (line-end-position) - :org-clock-force-headline-inclusion t)))))) - (setq t1 0) - (cl-loop for l from level to (1- lmax) do - (aset ltimes l 0)))))))) - (setq org-clock-file-total-minutes (aref ltimes 0)))))) + (let ((tstart (cond ((stringp tstart) (org-time-string-to-seconds tstart)) + ((consp tstart) (float-time tstart)) + (t tstart))) + (tend (cond ((stringp tend) (org-time-string-to-seconds tend)) + ((consp tend) (float-time tend)) + (t tend))) + (propname (or propname :org-clock-minutes)) + (t1 0) + (total 0) + time) + (remove-text-properties (point-min) (point-max) `(,propname t)) + (org-element-cache-map + (lambda (headline-or-inlinetask) + (when (or (null headline-filter) + (save-excursion + (funcall headline-filter))) + (mapc + (lambda (range) + (setq time + (pcase range + (`(,_ . open) + (when (and org-clock-report-include-clocking-task + (eq (org-clocking-buffer) (current-buffer)) + (eq (marker-position org-clock-hd-marker) + (org-element-begin headline-or-inlinetask)) + (or (not tstart) + (>= (float-time org-clock-start-time) tstart)) + (or (not tend) + (<= (float-time org-clock-start-time) tend))) + (floor (org-time-convert-to-integer + (time-since org-clock-start-time)) + 60))) + ((pred floatp) range) + (`(,time1 . ,time2) + (let* ((ts (float-time time1)) + (te (float-time time2)) + (dt (- (if tend (min te tend) te) + (if tstart (max ts tstart) ts)))) + (floor dt 60))))) + (when (and time (> time 0)) (cl-incf t1 time))) + (org--clock-ranges headline-or-inlinetask)) + (when (> t1 0) + (setq total (+ total t1)) + (org-element-lineage-map headline-or-inlinetask + (lambda (parent) + (put-text-property + (org-element-begin parent) (1- (org-element-contents-begin parent)) + propname + (+ t1 (or (get-text-property + (org-element-begin parent) + propname) + 0)))) + ;; TODO: can inlinetasks contain inlinetasks? + '(headline) t)) + (setq t1 0))) + :narrow t) + (setq org-clock-file-total-minutes total)))) (defun org-clock-sum-current-item (&optional tstart) "Return time, clocked on current item in total." @@ -2134,6 +2095,43 @@ PROPNAME lets you set a custom text property instead of :org-clock-minutes." (org-clock-sum tstart) org-clock-file-total-minutes))) +(defun org--clock-ranges (headline) + "Return a list of clock ranges of HEADLINE. +Does not recurse into subheadings. +Ranges are in one of these formats: + (cons time . time) + (cons time . \\='open) The clock does not have an end time + float The number of minutes as a float" + (unless (org-element-type-p headline '(headline inlinetask)) + (error "Argument must be a headline")) + (and + (org-element-contents-begin headline) ;; empty headline + (or + (org-element-cache-get-key headline :clock-ranges) + (let ((clock-ranges + (org-element-cache-map + (lambda (elem) + (when (org-element-type-p elem 'clock) + (if-let ((timestamp (org-element-property :value elem))) + (cons (org-timestamp-to-time timestamp) + (if (eq 'running (org-element-property :status elem)) + 'open + (org-timestamp-to-time timestamp t))) + (org-duration-to-minutes (org-element-property :duration elem))))) + ;; XXX: using these arguments would be more intuitive + ;; but don't seem to work due to bugs in + ;; `org-element-cache-map' + ;; :restrict-elements '(clock) + ;; :after-element headline + :granularity 'element + :next-re org-element-clock-line-re + :from-pos (org-element-contents-begin headline) + :to-pos (save-excursion + (goto-char (org-element-begin headline)) + (org-entry-end-position))))) + (org-element-cache-store-key headline :clock-ranges clock-ranges) + clock-ranges)))) + ;;;###autoload (defun org-clock-display (&optional arg) "Show subtree times in the entire buffer. -- 2.45.1 --=-=-= Content-Type: text/x-patch Content-Disposition: attachment; filename=0002-malformed-clock-tests.patch >From 475c8a75c09efb36be9b918520c99d9ab8c374a1 Mon Sep 17 00:00:00 2001 From: Morgan Smith Date: Fri, 14 Jun 2024 10:08:19 -0400 Subject: [PATCH 2/2] malformed clock tests --- testing/lisp/test-org-element.el | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/testing/lisp/test-org-element.el b/testing/lisp/test-org-element.el index 6a4ec6c22..12d694226 100644 --- a/testing/lisp/test-org-element.el +++ b/testing/lisp/test-org-element.el @@ -1148,6 +1148,7 @@ CLOCK: [2023-10-13 Fri 14:40]--[2023-10-13 Fri 14:51] => 0:11" (ert-deftest test-org-element/clock-parser () "Test `clock' parser." + ;; TODO: does not check time information like :year-start etc!!! ;; Running clock. (let ((clock (org-test-with-temp-text "CLOCK: [2012-01-01 sun. 00:01]" (org-element-at-point)))) @@ -1183,7 +1184,18 @@ CLOCK: [2023-10-13 Fri 14:40]--[2023-10-13 Fri 14:51] => 0:11" (org-element-at-point)))) (should (eq (org-element-property :status clock) 'closed)) (should-not (org-element-property :value clock)) - (should (equal (org-element-property :duration clock) "0:11")))) + (should (equal (org-element-property :duration clock) "0:11"))) + ;; malformed clocks + ;; TODO: should probably emit warning or something!! + (let ((clock + (org-test-with-temp-text + "CLOCK: [2012-01-01 sun. 00rr:01]--[2012-01-01 sun. 00:02] => 0:01" + (org-element-at-point)))) + (should (eq (org-element-property :status clock) 'closed)) + (should (equal (org-element-property :raw-value + (org-element-property :value clock)) + "[2012-01-01 sun. 00rr:01]--[2012-01-01 sun. 00:02]")) + (should (equal (org-element-property :duration clock) "0:01")))) ;;;; Code -- 2.45.1 --=-=-=--