Compare commits

...

5 Commits

Author SHA1 Message Date
Joris Caravati f3e306c737
lisp/org.el: Add `org-after-note-stored-hook'
* lisp/org.el: Add `org-after-note-stored-hook' which is called at the
end of the `org-store-log-note' function.
* etc/ORG-NEWS: Document the new hook.

TINYCHANGE
2024-05-18 13:20:18 +02:00
Anand Deopurkar 0ebb36caea
lisp/org-capture.el: Restore org-store-link-plist
* org-capture.el (org-capture-fill-template): Restore original
`org-store-link-plist' after calling `org-store-link'.

To replace a %K escape (link to currently clocked task),
`org-capture-fill-template' calls `org-store-link'.  This call has the
side-effect of replacing the contents of `org-store-link-plist'.  As a
result, expected template expansions using the original
`org-store-link-plist' do not happen.

For example, suppose `org-capture' is called from a message buffer with the
template "%:subject %:from" while the clock is running.  Then
%:subject and %:from are not substituted because of the behaviour
above.  If the clock is not running, there is no problem.

Current fix restores `org-store-link-plist' to its original value
after `org-capture-fill-template' calls `org-store-link'.

TINYCHANGE
2024-05-18 12:52:04 +02:00
Ihor Radchenko ee58259bc7
org-duration-from-minutes: Accept negative durations
* lisp/org-duration.el (org-duration-from-minutes): Allow MINUTES
argument to be negative.

Reported-by: Raffael Stocker <r.stocker@mnet-mail.de>
Link: https://orgmode.org/list/yplmzfsrqjw6.fsf@mnet-mail.de
2024-05-17 14:43:04 +03:00
Ihor Radchenko 288c7069c4
org-log-beginning: Fix extra blank line created after LOGBOOK drawer
* lisp/org.el (org-log-beginning): Fix regression after f63ff07441
when additional blank is created after newly added LOGBOOK drawer.

Reported-by: Kris Nelson <kris@kristofernelson.com>
Link: https://orgmode.org/list/766237934.317726.1715720181047@office.mailbox.org
2024-05-17 14:19:29 +03:00
Ihor Radchenko ea8ed59c02
etc/ORG-NEWS (Org mode now fontifies...): Add references to manual
* etc/ORG-NEWS (Org mode now fontifies whole table lines (including
newline) according to ~org-table~ face): Add references to the manual
that explain how to set face 'inherit attribute.

Link: https://orgmode.org/list/87le4dfowy.fsf@yandex.com
2024-05-17 14:04:00 +03:00
4 changed files with 127 additions and 108 deletions

View File

@ -195,7 +195,9 @@ including indentation and the final newline. This face, by default,
inherits from ~org-table~ face.
If the new behavior is not desired, ~org-table-row~ face can be
changed to inherit from ~default~ face.
changed to inherit from ~default~ face. See "Customizing Faces"
section of Emacs manual or "Face Attribute Functions" section of Elisp
manual.
~org-table~ takes precedence over ~org-table-row~ for the parts of
table rows without indentation and newline.
@ -733,6 +735,10 @@ any more. Run ~org-ctags-enable~ to setup hooks and advices:
#+end_src
** New and changed options
*** New hook ~org-after-note-stored-hook~
This new hook runs when a note has been stored.
*** New option controlling how Org mode sorts things ~org-sort-function~
Sorting of agenda items, tables, menus, headlines, etc can now be

View File

@ -1675,9 +1675,12 @@ Expansion occurs in a temporary Org mode buffer."
(org-no-properties org-clock-heading)
""))
(v-K (if (marker-buffer org-clock-marker)
(org-with-point-at org-clock-marker
(org-store-link nil nil))
""))
(let ((original-link-plist org-store-link-plist)
(clocked-task-link (org-with-point-at org-clock-marker
(org-store-link nil nil))))
(setq org-store-link-plist original-link-plist)
clocked-task-link)
""))
(v-f (or (org-capture-get :original-file-nondirectory) ""))
(v-F (or (org-capture-get :original-file) ""))
(org-capture--clipboards

View File

@ -324,109 +324,110 @@ When optional argument CANONICAL is non-nil, ignore
`org-duration-units' and use standard time units value.
Raise an error if expected format is unknown."
(pcase (or fmt org-duration-format)
(`h:mm
(format "%d:%02d" (/ minutes 60) (mod minutes 60)))
(`h:mm:ss
(let* ((whole-minutes (floor minutes))
(seconds (mod (* 60 minutes) 60)))
(format "%s:%02d"
(org-duration-from-minutes whole-minutes 'h:mm)
seconds)))
((pred atom) (error "Invalid duration format specification: %S" fmt))
;; Mixed format. Call recursively the function on both parts.
((and duration-format
(let `(special . ,(and mode (or `h:mm:ss `h:mm)))
(assq 'special duration-format)))
(let* ((truncated-format
;; Remove "special" mode from duration format in order to
;; recurse properly. Also remove units smaller or equal
;; to an hour since H:MM part takes care of it.
(cl-remove-if-not
(lambda (pair)
(pcase pair
(`(,(and unit (pred stringp)) . ,_)
(> (org-duration--modifier unit canonical) 60))
(_ nil)))
duration-format))
(min-modifier ;smallest modifier above hour
(and truncated-format
(apply #'min
(mapcar (lambda (p)
(org-duration--modifier (car p) canonical))
truncated-format)))))
(if (or (null min-modifier) (< minutes min-modifier))
;; There is not unit above the hour or the smallest unit
;; above the hour is too large for the number of minutes we
;; need to represent. Use H:MM or H:MM:SS syntax.
(org-duration-from-minutes minutes mode canonical)
;; Represent minutes above hour using provided units and H:MM
;; or H:MM:SS below.
(let* ((units-part (* min-modifier (/ (floor minutes) min-modifier)))
(minutes-part (- minutes units-part))
(compact (memq 'compact duration-format)))
(concat
(org-duration-from-minutes units-part truncated-format canonical)
(and (not compact) " ")
(org-duration-from-minutes minutes-part mode))))))
;; Units format.
(duration-format
(let* ((fractional
(let ((digits (cdr (assq 'special duration-format))))
(and digits
(or (wholenump digits)
(error "Unknown formatting directive: %S" digits))
(format "%%.%df" digits))))
(selected-units
(sort (cl-remove-if
;; Ignore special format cells and compact option.
(lambda (pair)
(pcase pair
((or `compact `(special . ,_)) t)
(_ nil)))
duration-format)
(lambda (a b)
(> (org-duration--modifier (car a) canonical)
(org-duration--modifier (car b) canonical)))))
(separator (if (memq 'compact duration-format) "" " ")))
(cond
;; Fractional duration: use first unit that is either required
;; or smaller than MINUTES.
(fractional
(let* ((unit (car
(or (cl-find-if
(lambda (pair)
(pcase pair
(`(,u . ,req?)
(or req?
(<= (org-duration--modifier u canonical)
minutes)))))
selected-units)
;; Fall back to smallest unit.
(org-last selected-units))))
(modifier (org-duration--modifier unit canonical)))
(concat (format fractional (/ (float minutes) modifier)) unit)))
;; Otherwise build duration string according to available
;; units.
((org-string-nw-p
(org-trim
(mapconcat
(lambda (units)
(pcase-let* ((`(,unit . ,required?) units)
(modifier (org-duration--modifier unit canonical)))
(cond ((<= modifier minutes)
(let ((value (floor minutes modifier)))
(cl-decf minutes (* value modifier))
(format "%s%d%s" separator value unit)))
(required? (concat separator "0" unit))
(t ""))))
selected-units
""))))
;; No unit can properly represent MINUTES. Use the smallest
;; one anyway.
(t
(pcase-let ((`((,unit . ,_)) (last selected-units)))
(concat "0" unit))))))))
(if (< minutes 0) (concat "-" (org-duration-from-minutes (abs minutes) fmt canonical))
(pcase (or fmt org-duration-format)
(`h:mm
(format "%d:%02d" (/ minutes 60) (mod minutes 60)))
(`h:mm:ss
(let* ((whole-minutes (floor minutes))
(seconds (mod (* 60 minutes) 60)))
(format "%s:%02d"
(org-duration-from-minutes whole-minutes 'h:mm)
seconds)))
((pred atom) (error "Invalid duration format specification: %S" fmt))
;; Mixed format. Call recursively the function on both parts.
((and duration-format
(let `(special . ,(and mode (or `h:mm:ss `h:mm)))
(assq 'special duration-format)))
(let* ((truncated-format
;; Remove "special" mode from duration format in order to
;; recurse properly. Also remove units smaller or equal
;; to an hour since H:MM part takes care of it.
(cl-remove-if-not
(lambda (pair)
(pcase pair
(`(,(and unit (pred stringp)) . ,_)
(> (org-duration--modifier unit canonical) 60))
(_ nil)))
duration-format))
(min-modifier ;smallest modifier above hour
(and truncated-format
(apply #'min
(mapcar (lambda (p)
(org-duration--modifier (car p) canonical))
truncated-format)))))
(if (or (null min-modifier) (< minutes min-modifier))
;; There is not unit above the hour or the smallest unit
;; above the hour is too large for the number of minutes we
;; need to represent. Use H:MM or H:MM:SS syntax.
(org-duration-from-minutes minutes mode canonical)
;; Represent minutes above hour using provided units and H:MM
;; or H:MM:SS below.
(let* ((units-part (* min-modifier (/ (floor minutes) min-modifier)))
(minutes-part (- minutes units-part))
(compact (memq 'compact duration-format)))
(concat
(org-duration-from-minutes units-part truncated-format canonical)
(and (not compact) " ")
(org-duration-from-minutes minutes-part mode))))))
;; Units format.
(duration-format
(let* ((fractional
(let ((digits (cdr (assq 'special duration-format))))
(and digits
(or (wholenump digits)
(error "Unknown formatting directive: %S" digits))
(format "%%.%df" digits))))
(selected-units
(sort (cl-remove-if
;; Ignore special format cells and compact option.
(lambda (pair)
(pcase pair
((or `compact `(special . ,_)) t)
(_ nil)))
duration-format)
(lambda (a b)
(> (org-duration--modifier (car a) canonical)
(org-duration--modifier (car b) canonical)))))
(separator (if (memq 'compact duration-format) "" " ")))
(cond
;; Fractional duration: use first unit that is either required
;; or smaller than MINUTES.
(fractional
(let* ((unit (car
(or (cl-find-if
(lambda (pair)
(pcase pair
(`(,u . ,req?)
(or req?
(<= (org-duration--modifier u canonical)
minutes)))))
selected-units)
;; Fall back to smallest unit.
(org-last selected-units))))
(modifier (org-duration--modifier unit canonical)))
(concat (format fractional (/ (float minutes) modifier)) unit)))
;; Otherwise build duration string according to available
;; units.
((org-string-nw-p
(org-trim
(mapconcat
(lambda (units)
(pcase-let* ((`(,unit . ,required?) units)
(modifier (org-duration--modifier unit canonical)))
(cond ((<= modifier minutes)
(let ((value (floor minutes modifier)))
(cl-decf minutes (* value modifier))
(format "%s%d%s" separator value unit)))
(required? (concat separator "0" unit))
(t ""))))
selected-units
""))))
;; No unit can properly represent MINUTES. Use the smallest
;; one anyway.
(t
(pcase-let ((`((,unit . ,_)) (last selected-units)))
(concat "0" unit)))))))))
;;;###autoload
(defun org-duration-h:mm-only-p (times)

View File

@ -1990,6 +1990,13 @@ Lisp variable `org-state'."
:group 'org-todo
:type 'hook)
(defcustom org-after-note-stored-hook nil
"Hook triggered after a note is stored.
The point is at the stored note when the hook is executed."
:group 'org-progress
:type 'hook
:package-version '(Org . "9.7"))
(defvar org-blocker-hook nil
"Hook for functions that are allowed to block a state change.
@ -10668,7 +10675,8 @@ narrowing."
(org-fold-core-ignore-modifications
(unless (bolp) (insert-and-inherit "\n"))
(let ((beg (point)))
(insert-and-inherit ":" drawer ":\n:END:\n")
(insert-and-inherit ":" drawer ":\n:END:")
(if (eolp) (forward-char) (insert "\n"))
(org-indent-region beg (point))
(org-fold-region (line-end-position -1) (1- (point)) t 'drawer))))
(end-of-line -1))))
@ -10845,6 +10853,7 @@ items are State notes."
(unless (string-empty-p line)
(indent-line-to ind)
(insert-and-inherit line))))
(run-hooks 'org-after-note-stored-hook)
(message "Note stored")
(org-back-to-heading t))))))
;; Don't add undo information when called from `org-agenda-todo'.