From mboxrd@z Thu Jan 1 00:00:00 1970 From: Leo Vivier Subject: =?UTF-8?B?QnVnOiDigJgob3JnLXJlc29sdmUtY2xvY2tzKeKAmSBwaWNrcyB0?= =?UTF-8?B?aGUgd3JvbmcgdGFyZ2V0IGZvciBwbGFjaW5nIGEgbmV3IGNsb2NrLWRyYXdl?= =?UTF-8?B?ciB3aGVuIOKAmG9yZy1jbG9jay1vdXQtcmVtb3ZlLXplcm8tdGltZS1jbG9j?= =?UTF-8?B?a3PigJkgaXMgc2V0IHRvIHQgWzkuMS4xNCAoOS4xLjE0LTktZzEzMTUzMS1l?= =?UTF-8?B?bHBhIEAgfi8uZW1hY3MuZC9lbHBhL29yZy0yMDE4MTEyNi8pXQ==?= Date: Sun, 02 Dec 2018 19:22:02 +0100 Message-ID: <87lg57bxh1.fsf@gmail.com> Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: quoted-printable Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:40666) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1gTWZs-0001Cj-01 for emacs-orgmode@gnu.org; Sun, 02 Dec 2018 13:34:53 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1gTWNb-0008SW-J1 for emacs-orgmode@gnu.org; Sun, 02 Dec 2018 13:22:11 -0500 Received: from mail-wr1-x434.google.com ([2a00:1450:4864:20::434]:36647) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1gTWNb-0008RG-9J for emacs-orgmode@gnu.org; Sun, 02 Dec 2018 13:22:07 -0500 Received: by mail-wr1-x434.google.com with SMTP id u3so9876222wrs.3 for ; Sun, 02 Dec 2018 10:22:06 -0800 (PST) Received: from thinkpad.localdomain (lcs07-lyo-176-188-242-162.sfr.lns.abo.bbox.fr. [176.188.242.162]) by smtp.gmail.com with ESMTPSA id l20sm25687615wrb.93.2018.12.02.10.22.03 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sun, 02 Dec 2018 10:22:04 -0800 (PST) List-Id: "General discussions about Org-mode." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-orgmode-bounces+geo-emacs-orgmode=m.gmane.org@gnu.org Sender: "Emacs-orgmode" To: emacs-orgmode@gnu.org Hello, There seems to be a bad interaction between =E2=80=98(org-resolve-clocks)= =E2=80=99=20 and =E2=80=98org-clock-out-remove-zero-time-clocks=E2=80=99 set to t. Whils= t the=20 right tree is targeted by =E2=80=98(org-resolve-clocks)=E2=80=99 to delete = the=20 clock-line and clock-drawer, it adds a new clock-drawer in the=20 next tree rather than on the one being acted on. I was able to replicate this problem with =E2=80=98emacs -Q=E2=80=99. DESCRIPTION: I use org-clock regularly, and recently re-discovered=20 =E2=80=98org-clock-out-remove-zero-time-clocks=E2=80=99. When I forget to c= lock an=20 item, I run the following commands in quick succession: # ------------------ (org-clock-in) (org-resolve-clocks) : g 10 (For indicating that I =E2=80=98got back=E2=80=99 10 = min=20 ago) # ------------------ Because those commands are run in quick succession, the time=20 between =E2=80=98(org-clock-in)=E2=80=99 and =E2=80=98(org-resolve-clocks)= =E2=80=99 is usually=20 equal to 0 min. Therefore, when =E2=80=98(org-resolve-clocks)=E2=80=99 call= s=20 =E2=80=98(org-clock-out)=E2=80=99 after pressing , the clock-line is= =20 deleted, and if the clock-drawer was created by =E2=80=98(org-clock-in)=E2= =80=99,=20 it also gets deleted. The problem occurs in this context (=E2=80=98|=E2=80=99 represents =E2=80= =98(point)=E2=80=99): # ------------------ * Subtree 1 ** Item| * Subtree 2 # ------------------ =E2=80=98Item=E2=80=99 is the subtree we want to clock in the past. =E2=80= =98Subtrees 1 &=20 2=E2=80=99 are regular subtrees without any newlines separating them (the=20 white-space is important). Please note that I was only able to get =E2=80=98(org-resolve-clocks)=E2=80= =99 to=20 trigger in an agenda-file with already had clocking info. I=20 recommend that you try the snippet in one of your own agenda-files=20 rather than trying it in a blank buffer. Going through the steps mentioned above, here=E2=80=99s the result after=20 =E2=80=98(org-clock-in)=E2=80=99 # ------------------ * Subtree 1 ** Item| :LOGBOOK-CLOCK: CLOCK: [2018-12-02 Sun 12:00] :END: * Subtree 2 # ------------------ And here=E2=80=99s the result after =E2=80=98(org-resolve-clocks)=E2=80=99: # ------------------ * Subtree 1 ** Item| * Subtree 2 :LOGBOOK-CLOCK: CLOCK: [2018-12-02 Sun 11:50] :END: # ------------------ As you can see, the clock-line and clock-drawer are properly=20 deleted under =E2=80=98Item=E2=80=99, but the new clock-drawer is spawned i= n the=20 next subtree (=E2=80=98Subtree 2=E2=80=99). However, if we add a newline after =E2=80=98Item=E2=80=99, after running=20 =E2=80=98(org-resolve-clocks)=E2=80=99, the drawer is properly generated un= der=20 =E2=80=98Item=E2=80=99. INVESTIGATION: I=E2=80=99ve investigated the problem with edebug, and it seems to be a=20 problem with the way the point is restored after a=20 =E2=80=98(save-restriction =E2=80=A6)=E2=80=99 in =E2=80=98(org-clock-out)= =E2=80=99 (the line is prefixed=20 with an arrow =E2=80=98->=E2=80=99 in the following snippet). # ------------------ (defun org-clock-out (&optional switch-to-state fail-quietly=20 at-time) "Stop the currently running clock. Throw an error if there is no running clock and FAIL-QUIETLY is=20 nil. With a universal prefix, prompt for a state to switch the clocked=20 out task to, overriding the existing value of=20 `org-clock-out-switch-to-state'." (interactive "P") (catch 'exit (when (not (org-clocking-p)) (setq global-mode-string (delq 'org-mode-line-string global-mode-string)) (setq frame-title-format org-frame-title-format-backup) (force-mode-line-update) (if fail-quietly (throw 'exit t) (user-error "No active=20 clock"))) (let ((org-clock-out-switch-to-state (if switch-to-state (completing-read "Switch to state: " (with-current-buffer (marker-buffer=20 org-clock-marker) org-todo-keywords-1) nil t "DONE") org-clock-out-switch-to-state)) (now (org-current-time org-clock-rounding-minutes)) ts te s h m remove) (setq org-clock-out-time now) -> (save-excursion ; Do not replace this with=20 `with-current-buffer'. (with-no-warnings (set-buffer (org-clocking-buffer))) (save-restriction (widen) (goto-char org-clock-marker) (beginning-of-line 1) (if (and (looking-at (concat "[ \t]*"=20 org-keyword-time-regexp)) (equal (match-string 1) org-clock-string)) (setq ts (match-string 2)) (if fail-quietly (throw 'exit nil) (error "Clock start=20 time is gone"))) (goto-char (match-end 0)) (delete-region (point) (point-at-eol)) (insert "--") (setq te (org-insert-time-stamp (or at-time now)=20 'with-hm 'inactive)) (setq s (- (float-time (apply #'encode-time (org-parse-time-string=20 te))) (float-time (apply #'encode-time (org-parse-time-string=20 ts)))) h (floor (/ s 3600)) s (- s (* 3600 h)) m (floor (/ s 60)) s (- s (* 60 s))) (insert " =3D> " (format "%2d:%02d" h m)) (move-marker org-clock-marker nil) (move-marker org-clock-hd-marker nil) ;; Possibly remove zero time clocks. However, do not=20 add ;; a note associated to the CLOCK line in this case. (cond ((and org-clock-out-remove-zero-time-clocks (=3D (+ h m) 0)) (setq remove t) (delete-region (line-beginning-position) (line-beginning-position 2))) (org-log-note-clock-out (org-add-log-setup 'clock-out nil nil nil (concat "# Task: " (org-get-heading t)=20 "\n\n")))) (when org-clock-mode-line-timer (cancel-timer org-clock-mode-line-timer) (setq org-clock-mode-line-timer nil)) (when org-clock-idle-timer (cancel-timer org-clock-idle-timer) (setq org-clock-idle-timer nil)) (setq global-mode-string (delq 'org-mode-line-string global-mode-string)) (setq frame-title-format org-frame-title-format-backup) (when org-clock-out-switch-to-state (save-excursion (org-back-to-heading t) (let ((org-clock-out-when-done nil)) (cond ((functionp org-clock-out-switch-to-state) (let ((case-fold-search nil)) (looking-at org-complex-heading-regexp)) (let ((newstate (funcall=20 org-clock-out-switch-to-state (match-string 2)))) (when newstate (org-todo newstate)))) ((and org-clock-out-switch-to-state (not (looking-at (concat org-outline-regexp=20 "[ \t]*" org-clock-out-switch-to-state "\\>")))) (org-todo org-clock-out-switch-to-state)))))) (force-mode-line-update) (message (concat "Clock stopped at %s after " (org-duration-from-minutes (+ (* 60 h)=20 m)) "%s") te (if remove " =3D> LINE REMOVED" "")) (run-hooks 'org-clock-out-hook) (unless (org-clocking-p) (setq org-clock-current-task nil))))))) # ------------------ There=E2=80=99s another =E2=80=98(save restriction)=E2=80=99 in=20 =E2=80=98(org-clock-remove-empty-clock-drawer)=E2=80=99, but I figured that= since=20 it is a =E2=80=98(save-restriction)=E2=80=99 within another one, it shouldn= =E2=80=99t=20 matter. # ------------------ (defun org-clock-remove-empty-clock-drawer () "Remove empty clock drawers in current subtree." ->(save-excursion (org-back-to-heading t) (org-map-tree (lambda () (let ((drawer (org-clock-drawer-name)) (case-fold-search t)) (when drawer (let ((re (format "^[ \t]*:%s:[ \t]*$" (regexp-quote=20 drawer))) (end (save-excursion (org-end-of-subtree)))) (while (re-search-forward re end t) (org-remove-empty-drawer-at (point)))))))))) # ------------------ I=E2=80=99m going to investigate further to see if I can fix it reliably=20 on my own, but in the meantime, would you have any idea on how to=20 fix it? Thanks for taking the time to look at my report. HTH, --=20 Leo Vivier English Studies & General Linguistics Master Student, English Department Universit=C3=A9 Rennes 2