By default, org-mode uses C-c . and C-c ! to create active and inactive timestamps respectively. However, I also have flycheck installed which uses the C-c ! binding.

Thus, I'd like to use C-c . to insert timestamp and when prompted to enter the date+time in the minibuffer, use ! to toggle between active and inactive timestamps.

Is this possible? If yes, how would I go about it?


The following lisp code meets exactly your specification. On C-c . the function my-org-time-stamp is called instead of org-time-stamp.

The function my-org-time-stamp toggles the activity of the newly inserted time stamp after calling org-time-stamp if you have pressed ! while org-read-date had been running.

(require 'subr-x)
(require 'org)
(require 'org-element)

(defun org-toggle-time-stamp-activity ()
  "Toggle activity of time stamp or range at point."
  (let ((pt (point)))
    (when (org-at-timestamp-p t)
      (goto-char (match-beginning 0))
      (when-let ((el (org-element-timestamp-parser))
                 (type (org-element-property :type el))
                 (type-str (symbol-name type))
                 (begin (org-element-property :begin el))
                 (end (org-element-property :end el)))
        (setq type-str
              (if (string-match "inactive" type-str)
                  (replace-regexp-in-string "inactive" "active" type-str)
                (replace-regexp-in-string "active" "inactive" type-str)))
        (org-element-put-property el :type (intern type-str))
        (goto-char end)
        (skip-syntax-backward "-")
        (delete-region begin (point))
        (insert (org-element-timestamp-interpreter el nil))
        (goto-char pt)))))

(defvar-local calendar-previous-buffer nil
  "Buffer been active when `calendar' was called.")

(defun calendar-save-previous-buffer (oldfun &rest args)
  "Save buffer been active at `calendar' in `calendar-previous-buffer'."
  (let ((buf (current-buffer)))
    (apply oldfun args)
    (setq calendar-previous-buffer buf)))

(advice-add #'calendar :around #'calendar-save-previous-buffer)

(defvar-local my-org-time-stamp-inactive nil
  "Make time inserted time stamp inactive after inserting with `my-org-time-stamp'.")

(defun org-time-stamp-toggle ()
  "Make time stamp active at the end of `my-org-time-stamp'."
  (when-let ((win (minibuffer-selected-window))
             (buf (window-buffer win)))
    (when (buffer-live-p buf)
      (with-current-buffer buf
        (when (buffer-live-p calendar-previous-buffer)
          (set-buffer calendar-previous-buffer))
        (setq my-org-time-stamp-inactive (null my-org-time-stamp-inactive))
        (setq org-read-date-inactive my-org-time-stamp-inactive)))))

(define-key org-read-date-minibuffer-local-map "!" #'org-time-stamp-toggle)

(defun my-org-time-stamp (arg)
  "Like `org-time-stamp' with ARG but toggle activity with character ?!."
  (interactive "P")
  (setq my-org-time-stamp-inactive nil)
  (org-time-stamp arg)
  (when my-org-time-stamp-inactive

(org-defkey org-mode-map (kbd "C-c .") #'my-org-time-stamp)

Note, that org-toggle-time-stamp-activity is very similar to org-toggle-timestamp-type. The fine difference is that it is basing on the org element parser and therefore also works for time ranges.

| improve this answer | |

Not exactly what you are asking, but org does have a built-in command to toggle a time stamp between active and inactive: org-toggle-timestamp-type. It is not bound to anything by default but you could bind it to some available key.

I do not see a way to switch the time-stamp type that will be inserted from within the time stamp command. One thing you could do instead is create a conditional key binding that calls org-toggle-timestamp-type only when usde right after you've inserted a time stamp.

For example, this would bind "!" to toggle the type of the time stamp right after you insert it:

(defun allow-toggle-timestamp-p ()
   ((eq last-command 'org-time-stamp) t)
   ((eq last-command 'org-toggle-timestamp-type) t)

(define-key org-mode-map "!"
  `(menu-item "" org-toggle-timestamp-type
              :filter ,(lambda (cmd) (if (allow-toggle-timestamp-p) cmd))))

So you could do C-c . as usual to create your time stamp, then hit ! right afterward to toggle between active and inactive. Once you do anything else (e.g. type or move point, etc) then ! goes back to just a normal key.

I split out the predicate function that decides when ! has a special meaning in case you want to try some other condition. For example, you might want to look at the content of the buffer at point and see if it looks like a time stamp, rather than checking the last command. But what I have here seems pretty close to what you described.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.