diff options
Diffstat (limited to 'lisp/org/org-clock.el')
-rw-r--r-- | lisp/org/org-clock.el | 151 |
1 files changed, 93 insertions, 58 deletions
diff --git a/lisp/org/org-clock.el b/lisp/org/org-clock.el index 1283970bc2b..143ed4f123a 100644 --- a/lisp/org/org-clock.el +++ b/lisp/org/org-clock.el @@ -2,7 +2,7 @@ ;; Copyright (C) 2004-2021 Free Software Foundation, Inc. -;; Author: Carsten Dominik <carsten at orgmode dot org> +;; Author: Carsten Dominik <carsten.dominik@gmail.com> ;; Keywords: outlines, hypermedia, calendar, wp ;; Homepage: https://orgmode.org ;; @@ -85,7 +85,7 @@ function `org-clock-into-drawer' instead." (string :tag "Into Drawer named..."))) (defun org-clock-into-drawer () - "Value of `org-clock-into-drawer'. but let properties overrule. + "Value of `org-clock-into-drawer', but let properties overrule. If the current entry has or inherits a CLOCK_INTO_DRAWER property, it will be used instead of the default value. @@ -438,12 +438,11 @@ specifications than `frame-title-format', which see." (defcustom org-clock-x11idle-program-name "x11idle" "Name of the program which prints X11 idle time in milliseconds. -You can find x11idle.c in the contrib/scripts directory of the -Org git distribution. Or, you can do: +you can do \"~$ sudo apt-get install xprintidle\" if you are using +a Debian-based distribution. - sudo apt-get install xprintidle - -if you are using Debian." +Alternatively, can find x11idle.c in the org-contrib repository at +https://git.sr.ht/~bzg/org-contrib" :group 'org-clock :version "24.4" :package-version '(Org . "8.0") @@ -485,6 +484,17 @@ is added to the user configuration." (integer :tag "Clock out after Emacs is idle for X seconds") (const :tag "Never auto clock out" nil))) +(defcustom org-clock-ask-before-exiting t + "If non-nil, ask if the user wants to clock out before exiting Emacs. +This variable only has effect if set with \\[customize]." + :set (lambda (symbol value) + (if value + (add-hook 'kill-emacs-query-functions #'org-clock-kill-emacs-query) + (remove-hook 'kill-emacs-query-functions #'org-clock-kill-emacs-query)) + (set symbol value)) + :type 'boolean + :package-version '(Org . "9.5")) + (defvar org-clock-in-prepare-hook nil "Hook run when preparing the clock. This hook is run before anything happens to the task that @@ -503,9 +513,9 @@ to add an effort property.") "Has the clock been used during the current Emacs session?") (defvar org-clock-stored-history nil - "Clock history, populated by `org-clock-load'") + "Clock history, populated by `org-clock-load'.") (defvar org-clock-stored-resume-clock nil - "Clock to resume, saved by `org-clock-load'") + "Clock to resume, saved by `org-clock-load'.") ;;; The clock for measuring work time. @@ -607,10 +617,6 @@ cannot be translated." ((stringp drawer) drawer) (t nil)))) -(defun org-clocking-buffer () - "Return the clocking buffer if we are currently clocking a task or nil." - (marker-buffer org-clock-marker)) - (defun org-clocking-p () "Return t when clocking a task." (not (equal (org-clocking-buffer) nil))) @@ -677,19 +683,19 @@ pointing to it." (let (cat task heading prefix) (with-current-buffer (org-base-buffer (marker-buffer marker)) (org-with-wide-buffer - (ignore-errors - (goto-char marker) - (setq cat (org-get-category) - heading (org-get-heading 'notags) - prefix (save-excursion - (org-back-to-heading t) - (looking-at org-outline-regexp) - (match-string 0)) - task (substring - (org-fontify-like-in-org-mode - (concat prefix heading) - org-odd-levels-only) - (length prefix)))))) + (ignore-errors + (goto-char marker) + (setq cat (org-get-category) + heading (org-get-heading 'notags) + prefix (save-excursion + (org-back-to-heading t) + (looking-at org-outline-regexp) + (match-string 0)) + task (substring + (org-fontify-like-in-org-mode + (concat prefix heading) + org-odd-levels-only) + (length prefix)))))) (when (and cat task) (insert (format "[%c] %-12s %s\n" i cat task)) (cons i marker))))) @@ -853,6 +859,10 @@ use libnotify if available, or fall back on a message." org-show-notification-timeout nil (lambda () (w32-notification-close id))))) + ((fboundp 'ns-do-applescript) + (ns-do-applescript + (format "display notification \"%s\" with title \"Org mode notification\"" + (replace-regexp-in-string "\"" "#" notification)))) ((fboundp 'notifications-notify) (notifications-notify :title "Org mode message" @@ -1162,13 +1172,12 @@ If `only-dangling-p' is non-nil, only ask to resolve dangling (org-clock-resolve clock (or prompt-fn - (function - (lambda (clock) - (format - "Dangling clock started %d mins ago" - (floor (org-time-convert-to-integer - (org-time-since (cdr clock))) - 60))))) + (lambda (clock) + (format + "Dangling clock started %d mins ago" + (floor (org-time-convert-to-integer + (org-time-since (cdr clock))) + 60)))) (or last-valid (cdr clock))))))))))) @@ -1367,7 +1376,7 @@ the default behavior." (end-of-line 0) (org-in-item-p))) (beginning-of-line 1) - (indent-line-to (- (current-indentation) 2))) + (indent-line-to (max 0 (- (current-indentation) 2)))) (insert org-clock-string " ") (setq org-clock-effort (org-entry-get (point) org-effort-property)) (setq org-clock-total-time (org-clock-sum-current-item @@ -1671,17 +1680,13 @@ to, overriding the existing value of `org-clock-out-switch-to-state'." (insert " => " (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 add - ;; a note associated to the CLOCK line in this case. - (cond ((and org-clock-out-remove-zero-time-clocks - (= 0 h m)) - (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) "\n\n")))) + ;; Possibly remove zero time clocks. + (when (and org-clock-out-remove-zero-time-clocks + (= 0 h m)) + (setq remove t) + (delete-region (line-beginning-position) + (line-beginning-position 2))) + (org-clock-remove-empty-clock-drawer) (when org-clock-mode-line-timer (cancel-timer org-clock-mode-line-timer) (setq org-clock-mode-line-timer nil)) @@ -1712,11 +1717,14 @@ to, overriding the existing value of `org-clock-out-switch-to-state'." "Clock stopped at %s after %s => LINE REMOVED" "Clock stopped at %s after %s") te (org-duration-from-minutes (+ (* 60 h) m))) - (run-hooks 'org-clock-out-hook) - (unless (org-clocking-p) - (setq org-clock-current-task nil))))))) - -(add-hook 'org-clock-out-hook #'org-clock-remove-empty-clock-drawer) + (unless (org-clocking-p) + (setq org-clock-current-task nil)) + (run-hooks 'org-clock-out-hook) + ;; Add a note, but only if we didn't remove the clock line. + (when (and org-log-note-clock-out (not remove)) + (org-add-log-setup + 'clock-out nil nil nil + (concat "# Task: " (org-get-heading t) "\n\n")))))))) (defun org-clock-remove-empty-clock-drawer () "Remove empty clock drawers in current subtree." @@ -2696,7 +2704,18 @@ from the dynamic block definition." (format (concat "| %s %s | %s%s%s" (format org-clock-file-time-cell-format (org-clock--translate "File time" lang)) - " | *%s*|\n") + + ;; The file-time rollup value goes in the first time + ;; column (of which there is always at least one)... + " | *%s*|" + ;; ...and the remaining file time cols (if any) are blank. + (make-string (max 0 (1- time-columns)) ?|) + + ;; Optionally show the percentage contribution of "this" + ;; file time to the total time. + (if (eq formula '%) " %s |" "") + "\n") + (file-name-nondirectory file-name) (if level? "| " "") ;level column, maybe (if timestamp "| " "") ;timestamp column, maybe @@ -2704,7 +2723,12 @@ from the dynamic block definition." (if properties ;properties columns, maybe (make-string (length properties) ?|) "") - (org-duration-from-minutes file-time)))) ;time + (org-duration-from-minutes file-time) ;time + + (cond ((not (eq formula '%)) "") ;time percentage, maybe + ((or (not total-time) (= total-time 0)) "0.0") + (t + (format "%.1f" (* 100 (/ file-time (float total-time))))))))) ;; Get the list of node entries and iterate over it (when (> maxlevel 0) @@ -2732,13 +2756,13 @@ from the dynamic block definition." (if timestamp (concat ts "|") "") ;timestamp, maybe (if tags (concat (mapconcat #'identity tgs ", ") "|") "") ;tags, maybe (if properties ;properties columns, maybe - (concat (mapconcat (lambda (p) (or (cdr (assoc p props)) "")) - properties - "|") - "|") + (concat (mapconcat (lambda (p) (or (cdr (assoc p props)) "")) + properties + "|") + "|") "") (if indent ;indentation - (org-clocktable-indent-string level) + (org-clocktable-indent-string level) "") (format-field headline) ;; Empty fields for higher levels. @@ -2746,7 +2770,7 @@ from the dynamic block definition." (format-field (org-duration-from-minutes time)) (make-string (max 0 (- time-columns level)) ?|) (if (eq formula '%) - (format "%.1f |" (* 100 (/ time (float total-time)))) + (format "%.1f |" (* 100 (/ time (float total-time)))) "") "\n"))))))) (delete-char -1) @@ -3101,6 +3125,17 @@ The details of what will be saved are regulated by the variable (when (org-invisible-p) (org-show-context)))))) (_ nil))))) +(defun org-clock-kill-emacs-query () + "Query user when killing Emacs. +This function is added to `kill-emacs-query-functions'." + (let ((buf (org-clocking-buffer))) + (when (and buf (yes-or-no-p "Clock out and save? ")) + (with-current-buffer buf + (org-clock-out) + (save-buffer)))) + ;; Unconditionally return t for `kill-emacs-query-functions'. + t) + ;; Suggested bindings (org-defkey org-mode-map "\C-c\C-x\C-e" 'org-clock-modify-effort-estimate) |