Emacs Org-Mode: Clear non-repeated SCHEDULED time when DEADLINE is repeated - emacs

I use org-mode to manage some deadlines for repeated tasks. For example, I may have something like the following:
* TODO My Weekly Task
DEADLINE <2013-08-10 Sat +1w>
If I mark the task as DONE, then the deadline automatically increments to the next week as expected. However, I also like to use the SCHEDULED time to indicate when during the week I would like to actually do that task, for example:
* TODO My Weekly Task
DEADLINE <2013-08-10 Sat +1w> SCHEDULED: <2013-08-08 Thu>
This makes the task show up in the agenda for today (Thursday). However when I mark the task DONE, I end up with the following:
* TODO My Weekly Task
DEADLINE <2013-08-17 Sat +1w> SCHEDULED: <2013-08-08 Thu>
...and the task still appears in the agenda view for today, even though it has been completed.
Is it possible, for tasks that have a repeated DEADLINE, to get Org-Mode to clear the non-repeated SCHEDULED date?

Here's the patch, if you want to apply it yourself.
I'll send another copy to the org-mode mailing list.
--- a/lisp/org.el
+++ b/lisp/org.el
## -12835,7 +12835,8 ## This function is run automatically after each state change to a DONE state."
(setq type (if (match-end 1) org-scheduled-string
(if (match-end 3) org-deadline-string "Plain:"))
ts (match-string (if (match-end 2) 2 (if (match-end 4) 4 0))))
- (when (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([hdwmy]\\)" ts)
+ (if (not (string-match "\\([.+]\\)?\\(\\+[0-9]+\\)\\([hdwmy]\\)" ts))
+ (org-remove-timestamp-with-keyword org-scheduled-string)
(setq n (string-to-number (match-string 2 ts))
what (match-string 3 ts))
(if (equal what "w") (setq n (* n 7) what "d"))

Related

Make emacs org-mode deadlines and scheduled blocked tasks visible in agenda view

Here are the relevant parts of my .emacs
(setq org-enforce-todo-dependencies t)
(setq org-enforce-todo-checkbox-dependencies t)
(setq org-agenda-dim-blocked-tasks 'invisible)
When I visit my agenda view I want to see tasks which are scheduled or have a deadline (even if they are blocked by another task and are therefor stricly speaking rightly invisible).
Currently those tasks are not visible whilst they are being blocked by other tasks.
I would however prefer that an exception be made for these tasks which have been scheduled or given a deadline and that they be made visibile so that I maintain active awareness of them.
This could be accomplished by splitting off the scheduled and deadline tasks with a custom agenda view. Only scheduled and deadline items would be shown in the first block, and the setting to make blocked tasks invisible can be applied to uniquely to a the second block. For example:
;; Retain your default settings
(setq org-enforce-todo-dependencies t)
(setq org-enforce-todo-checkbox-dependencies t)
(setq org-agenda-dim-blocked-tasks t)
;; Create the custom agenda view
(setq org-agenda-custom-commands
'(("c"
"Agenda to show deadlines & hide blocked"
(
(agenda ""
((org-agenda-entry-types '(:deadline :scheduled))))
(tags-todo "-TODO=\"DONE\""
((org-agenda-skip-entry-if 'deadline 'scheduled)
(org-agenda-dim-blocked-tasks 'invisible)))
))))
Isn't it because of your setting:
(setq org-agenda-dim-blocked-tasks 'invisible)
?

Refile existing entry to different location in Org Mode date-tree

I use the Org-Mode diary to keep a record of my upcoming appointments.
In my diary.org file I could have an entry that looks something like the following:
*** 2014-10-31 Friday
**** 9:30 Take dog to vet
<2014-10-31 Fri>
Now imagine I need to reschedule my vet appointment. Is there a quick way (i.e. some Org-Mode command) to refile the appropriate heading within the same file but under a different date?
I don't see a builtin function that does this, but it sounds pretty useful. This function is really just a simplification of the code in org-archive.el that archives to datetrees. If you instead want to refile based on SCHEDULED, DEADLINE or some other property, just change "TIMESTAMP" to the property you want.
(defun org-refile-to-datetree ()
"Refile a subtree to a datetree corresponding to it's timestamp."
(interactive)
(let* ((datetree-date (org-entry-get nil "TIMESTAMP" t))
(date (org-date-to-gregorian datetree-date)))
(when date
(save-excursion
(org-cut-subtree)
(org-datetree-find-date-create date)
(org-narrow-to-subtree)
(show-subtree)
(org-end-of-subtree t)
(newline)
(goto-char (point-max))
(org-paste-subtree 4)
(widen)
)
)
))
Use org-refile with C-c C-w. This will allow you to refile it to the rescheduled date. Also be sure to check out the variables org-refile-use-outline-path (nil by default) and org-outline-path-complete-in-steps.
I would also recommend using the full power of org-mode dates so they show up in the agenda (C-a) appropriately. For example:
* Take Dog to Vet
<2014-10-31 Fri 09:30>--<2014-10-31 Fri 10:30>

Emacs org-mode: how to determine, that the current node was clocked in

Suppose, we have an org file like this:
* TODO Write function x
I want to clock the time working on it. There are 2 functions in org mode:
org-clock-in
org-clock-out
I decided to combine them in this manner:
(defun org-set-clock ()
"Clock current node in/out"
(if (<current node is not clocked in>))
(org-clock-in)
(org-clock-out)
)
And attach this function to a simple shortcut:
(add-hook 'dired-mode-hook
(lambda ()
(define-key dired-mode-map (kbd "M-q") 'org-set-clock)))
How to write this code: <current node is not clocked in>?
Below you can find an updated solution.
(defun org-set-clock ()
"One-off function for `org-mode' task clocking.
Behaviour:
* When there is no running clock, start
the clock for the item at point.
* When there is already a running clock and
`point' is at the item which is being clocked
stop the corresponding clock.
* When there is already a running clock but `point'
is not at the item which is being clocked,
stop the clock and restart it for item at `point'."
(interactive)
(let ((interrupting (and (not org-clock-resolving-clocks-due-to-idleness)
(org-clocking-p))))
(if interrupting
(if (save-excursion
(org-back-to-heading t)
(and (equal (marker-buffer org-clock-hd-marker)
(current-buffer))
(= (marker-position org-clock-hd-marker)
(point))
(equal org-clock-current-task (nth 4 (org-heading-components)))))
(org-clock-out)
(org-clock-in))
(org-clock-in))))
Edit: If you are unable to update org-mode to a sufficiently recent version, you can use
(defun org-set-clock ()
"One-off function for `org-mode' task clocking.
Behaviour:
* When there is no running clock, start
the clock for the item at point.
* When there is already a running clock and
`point' is at the item which is being clocked
stop the corresponding clock.
* When there is already a running clock but `point'
is not at the item which is being clocked,
stop the clock and restart it for item at `point'."
(interactive)
(if (org-clocking-p)
(if (save-excursion
(org-back-to-heading t)
(and (equal (marker-buffer org-clock-hd-marker)
(current-buffer))
(= (marker-position org-clock-hd-marker)
(point))
(equal org-clock-current-task (nth 4 (org-heading-components)))))
(org-clock-out)
(org-clock-in))
(org-clock-in)))
however, I'd recommend using the org-mode elpa which'll keep you always up to date.

How can I mark Org habits as done in the past

I regularly mark habits as DONE the day after the activity was done. The habits module automatically updates a bunch of dates in the metadata when I do this, but the date is always today. So then, I have to manually edit the SCHEDULED, LOGBOOK, and LAST_REPEAT states.
Is there a way to mark a habit as DONE for a day in the past? So instead of doing C-c C-t d (I have "d" set up as "DONE") I could get a prompt which asked me for a date.
I've wanted to do this for some time, too, and your question inspired me to finally figure it out.
There is a function called "org-todo-yesterday." By default, it's not mapped to any keys, but you could always call it with M-x org-todo-yesterday (or map it if you're using it a lot). For me, it breaks because it calls "third" which isn't a defined function in my install.
For a more generic function that prompts us for the date and marks things as done at that time, we can add this function (inspired by org-todo-yesterday) to our emacs init file. It will act as if you finished things at 23:59 on the target date, which is hopefully good enough.
(defun dk/org-todo-custom-date (&optional arg)
"Like org-todo-yesterday, but prompt the user for a date. The time
of change will be 23:59 on that day"
(interactive "P")
(let* ((hour (nth 2 (decode-time
(org-current-time))))
(daysback (- (date-to-day (current-time-string)) (org-time-string-to-absolute (org-read-date))))
(org-extend-today-until (+ 1 (* 24 (- daysback 1)) hour))
(org-use-effective-time t)) ; use the adjusted timestamp for logging
(if (eq major-mode 'org-agenda-mode)
(org-agenda-todo arg)
(org-todo arg))))
Will this work? This simply completes the habit and reschedule it for today
(defun org-todo-yesterday2 (&optional arg)
(interactive "P")
(org-todo-yesterday arg)
(org-schedule arg (format-time-string "%Y-%m-%d")
)
)

Custom diary-sunrise function not working. `autoload-diary`? (Emacs.)

Intro:
Based on the existing code for Emacs' diary-sunrise-sunset, I attempted to create two new functions diary-sunrise and diary-sunset.
My reasons for this are included below under the heading "XY-description".
I have code below which seems to work, except when I restart with a new Emacs. I can fix this by momentarily using the original built-in diary-sunrise-sunset. From then on, my functions perform beautifully.
In other words, I have to use the built-in %%(diary-sunrise-sunset) just a one time before my %%(diary-sunrise) and %%(diary-sunset) will work.
Question:
Can you help me fix my use of these functions so that I do not have to take the awkward step of first getting the built-in function called?
The lines of code that seem suspicious to me are the ones that go
;;;###diary-autoload
While I have some idea of the necessity of loading programs, I am not sure what's going on here, or if this is where the issue lies. (I've never seen that particular syntax.)
I have tried M-: (require 'solar) and M-: (require 'diary), but neither have worked (and just now calendar). I have tried putting my code both in my .emacs and in the built-in .../lisp/calendar/solar.el (and byte-recompiling), but neither have worked.
My functions:
(They are each slight modifications of solar-sunrise-sunset-string and diary-sunrise-sunset, which are both defined in .../lisp/calendar/solar.el).
Sunrise:
(defun solar-sunrise-string (date &optional nolocation)
"String of *local* time of sunrise and daylight on Gregorian DATE."
(let ((l (solar-sunrise-sunset date)))
(format
"%s (%s hours daylight)"
(if (car l)
(concat "Sunset " (apply 'solar-time-string (car l)))
"no sunset")
(nth 2 l)
)))
;; To be called from diary-list-sexp-entries, where DATE is bound.
;;;###diary-autoload
(defun diary-sunrise ()
"Local time of sunrise as a diary entry.
Accurate to a few seconds."
(or (and calendar-latitude calendar-longitude calendar-time-zone)
(solar-setup))
(solar-sunrise-string date))
Sunset:
(defun solar-sunset-string (date &optional nolocation)
"String of *local* time of sunset and daylight on Gregorian DATE."
(let ((l (solar-sunrise-sunset date)))
(format
"%s (%s hours daylight)"
(if (cadr l)
(concat "Sunset " (apply 'solar-time-string (cadr l)))
"no sunset")
(nth 2 l)
)))
;; To be called from diary-list-sexp-entries, where DATE is bound.
;;;###diary-autoload
(defun diary-sunset ()
"Local time of sunset as a diary entry.
Accurate to a few seconds."
(or (and calendar-latitude calendar-longitude calendar-time-zone)
(solar-setup))
(solar-sunset-string date))
XY description:
I am using Emacs' Org-mode, and just starting to use agenda views. I like the builtin diary-sunrise-sunset function, but wanted to make some minor tweaks to make it more to my liking.
Basically, Org-mode's agenda view will extract the first time it sees from the diary sexp %%(diary-sunrise-sunset), for instance
Sat, Apr 5, 2014
Sunrise 6:43am (PDT), sunset 7:42pm (PDT) at Springfield, OH (12:59 hours daylight)
and thus make an entry of
6:43am........ Sunrise (PDT), sunset 7:42pm (PDT) at Springfield, OH (12:59 hours daylight)
in the agenda view.
What I would like it to do is something more like,
6:43am........ Sunrise (PDT) (12:59 hours daylight)
8:00am........ ----------------
10:00am........ ----------------
12:00pm........ ----------------
2:00pm........ ----------------
4:00pm........ ----------------
5:51pm........ now - - - - - - - - - - - - - - - - - - - - - - - - -
6:00pm........ ----------------
7:42pm........ Sunset (PDT) (12:59 hours daylight)
Where the data is split into the two times, rather than all written only at the sunrise time.
Bonus:
a snippet so that C-c a d will give you a nice day agenda view:
(setq org-agenda-custom-commands
'(("d" "day's agenda"
agenda ""
(
(org-agenda-files '("/e/org/agendatest.org"))
(org-agenda-prefix-format "%t %s")
(org-agenda-span 'day)
(org-agenda-timegrid-use-ampm t)
)
)
))
In the last paragraph of my question (eighth paragraph?), I lied, (require 'solar) was the answer... I did not try it hard enough as it didn't respond to auto-completion.
The scenic route to the answer took me to these distractions:
Maintaining Emacs autoload files for user-installed elisp?
elisp - Where should I add autoload cookies in my Emacs Lisp package? Is there a definitive guide?
C-h i g (elisp) Autoload
a search through the lisp directory for any update-file-autoloads
I did some Edebugging wondering if anything I was using had an autoload cookie (not completely understanding it yet), but then noticed there was a (provide 'solar) at the end of solar.el, so then I figured (require 'solar) had to work. It did and that was that.
From the code in my question, I remove the autoload cookies (not sure if that's necessary), and add (require 'solar), and it works! Enjoy!