Bulk reschedule org agenda items preserving date - emacs

I sometimes forget to do one or more of my daily habits that happen at the same time each day and need to bring them current so I can get orgzly notifications of them.
I am able to shift a single item in org agenda preserving the date with M-x org-agenda-date-later and it reschedules that to the current date with whatever time existed.
If I try to use it as a bulk action by marking an item and doing B f org-agenda-date-later I get:
Debugger entered--Lisp error: (wrong-number-of-arguments #f(compiled-function (arg &optional what) (interactive "p") #<bytecode 0x1ad5eed>) 0)
org-agenda-date-later()
org-agenda-bulk-action(nil)
funcall-interactively(org-agenda-bulk-action nil)
call-interactively(org-agenda-bulk-action nil nil)
command-execute(org-agenda-bulk-action)
This tells me that org-agenda-date-later wasn't written to be used as a bulk action. One solution for this could be writing a bulk action that calls org-agenda-date-later multiple times but I do not know how to do that.
I searched for other solutions and I found something recommended by the author of org mode from the org mode FAQ:
(defun org-agenda-reschedule-to-today ()
(interactive)
(flet ((org-read-date (&rest rest) (current-time)))
(call-interactively 'org-agenda-schedule)))
This works as a bulk action but it loses the time the item was scheduled. That means I would have to go through my habits and reschedule the time for each one after doing this which is inconvenient.

There is the org-agenda-bulk-custom-functions to which you can add a key-binding and an associated function. So, for example, adding a binding for D after calling org-agenda-bulk-action, you could use
(setq org-agenda-bulk-custom-functions
`((?D (lambda () (call-interactively 'org-agenda-date-later)))
,#org-agenda-bulk-custom-functions))
It will pass the prefix on, allowing C-u -1 B D to reshedule the tasks a day earlier at the same time, for example.

Related

how to jump (c) from org-calendar to org-agenda showing whole day

When I am in calendar and want to jump to the entry in org-agenda, I press 'c'.
Would it be possible to have the DAY view as the standard so when I jump I only see one day, and not the whole week which is more cluttered? Thanks!
You can do it in various ways. In the spirit of "teaching someone to fish", the first thing that you have to do is figure out what c in the calendar does. So open the calendar, place the cursor on a date and say C-h c c which will tell you that c in the calendar runs the command
org-calendar-goto-agenda. So the next step is to do C-h f org-calendar-goto-agenda and read its documentation. Then click on the link in that documentation to go to the code and read it.
So here are three alternatives:
The code of the function is pretty simple:
(defun org-calendar-goto-agenda ()
"Compute the Org agenda for the calendar date displayed at the cursor.
This is a command t (org-agenda-span 1))hat has to be installed in `calendar-mode-map'."
(interactive)
;; Temporarily disable sticky agenda since user clearly wants to
;; refresh view anyway.
(let ((org-agenda-buffer-tmp-name "*Org Agenda(a)*")
(org-agenda-sticky nil))
(org-agenda-list nil (calendar-absolute-from-gregorian
(calendar-cursor-to-date))
nil)))
You can modify the function to make the agenda view to be just one day, by setting the variable org-agenda-span to 1 locally:
(defun org-calendar-goto-agenda ()
"Compute the Org agenda for the calendar date displayed at the cursor.
This is a command t (org-agenda-span 1))hat has to be installed in `calendar-mode-map'."
(interactive)
;; Temporarily disable sticky agenda since user clearly wants to
;; refresh view anyway.
(let ((org-agenda-buffer-tmp-name "*Org Agenda(a)*")
(org-agenda-sticky nil)
(org-agenda-span 1))
(org-agenda-list nil (calendar-absolute-from-gregorian
(calendar-cursor-to-date))
nil)))
The trouble with this is that you have now forked the Org mode code and you will need to make this change to the code every time you update. That might be appropriate in some cases, but you should avoid it if at all possible.
You can define your own command and bind it to c in the calendar:
(defun my-org-calendar-goto-agenda ()
(interactive)
(let ((org-agenda-span 1))
(org-calendar-goto-agenda)))
(define-key calendar-mode-map (kbd "c") #'my-org-calendar-goto-agenda)
That works pretty well. You have to remember to undo the keymap modification to restore the original state if you want to try the third method below:
(define-key calendar-mode-map (kbd "c") #'org-calendar-goto-agenda)
You can add an advice to the org-calendar-goto-agenda command. This is a formalization of the second option above: it is slightly more "advanced" but it is a powerful way of dealing with questions of this sort: you are given a function that does almost what you want and you want to customize it so that it does exactly what you want. This method cannot always be used, but it can be used in this case and it provides a simple example:
(defun org-calendar-goto-agenda-around (orig-fun &rest args)
(let ((org-agenda-span 1))
(apply orig-fun args)))
(advice-add 'org-calendar-goto-agenda :around #'org-calendar-goto-agenda-around)
The idea is that you define an around function that does something around the call of the original function (in this case, it let-binds org-agenda-span to 1, just like the other methods and then calls the original function in this new let-bound environment). Then we modify the original function by installing the advice. If you do C-h f org-calendar-goto-agenda now, you will see that there is some added information:
This function has :around advice: ‘org-calendar-goto-agenda-around’.
This is probably the cleanest way to do what you want. You can also easily remove the advice with
(advice-remove 'org-calendar-goto-agenda #'org-calendar-goto-agenda-around)
so this method allows you to experiment fairly easily. This is my recommended solution.

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")
)
)

Emacs completion-at-point-functions

I'm writing a derived mode, based on comint-mode. The mode is an interface to a command line program (GRASS gis), and the comint mode completion works for the programs. I'm trying to add on support for completing the arguments to the program, via completion-at-point-functions. A toy example is:
(setq my-commands
'(("ls"
("my-completion-1")
("my-completion-2"))
("mv"
("my-completion-3")
("my-completion-4"))))
(defun my-completion-at-point ()
(interactive)
(let ((pt (point)) ;; collect point
start end)
(save-excursion ;; collect the program name
(comint-bol)
(re-search-forward "\\(\\S +\\)\\s ?"))
(if (and (>= pt (match-beginning 1))
(<= pt (match-end 1)))
() ;; if we're still entering the command, pass completion on to
;; comint-completion-at-point by returning nil
(let ((command (match-string-no-properties 1)))
(when (member* command my-commands :test 'string= :key 'car)
;; If the command is one of my-commands, use the associated completions
(goto-char pt)
(re-search-backward "\\S *")
(setq start (point))
(re-search-forward "\\S *")
(setq end (point))
(list start end (cdr (assoc command my-commands)) :exclusive 'no))))))
(push 'my-completion-at-point completion-at-point-functions)
This almost works. I get normal completion of program names. However, if I have entered ls at the command line, hitting tab inserts my-completion- and doesn't offer the two options. Hitting tab again inserts my-completion- a second time, so that I now have ls my-completion-mycompletion-.
My actual code includes a few lines to check for multi-line commands, but makes no changes to the completion code. With this version of the code, I hitting tab on a line that starts with one of the program names in my-commands I am presented with a list of the possible arguments to complete the command with, but nothing is inserted in the buffer, and the list does not get narrowed by typing the first few letters of an argument.
I've been over the manual, but I can't figure out the correct way to write a completion-at-point function. Any ideas what I'm missing?
I have looked briefly at pcomplete, but the didn't really understand the 'documentation', and didn't make any progress.
The problem seems to be with the way you're finding start and end to return the boundaries of the argument at point. I didn't spend long enough debugging it to be sure of the details, but I think if you call the function interactively you'll see that it returns the same value for start and end, and this means that the completion UI doesn't know to use the argument at point to select from the completion table you've passed it.
Changing the last part of your function to the following seems to be one fix:
(when (member* command my-commands :test 'string= :key 'car)
;; If the command is one of my-commands, use the associated completions
(goto-char pt)
(let ((start
(save-excursion
(skip-syntax-backward "^ ")
(point))))
(list start pt (cdr (assoc command my-commands)) :exclusive 'no)))))))
This gives the expected results when added as an element of completion-at-point-functions.
Here I've used skip-syntax-backward instead of regexp search, which I think is slightly more idiomatic Elisp for this kind of thing. It just says to move point backwards across anything that is not in syntax class "whitespace". The skip-syntax functions return the distance moved rather than the value of point, so we have to add a call to point at the end of the save-excursion.
If you do use regexp searches in a function like this, it's usually a good idea to pass t for the fourth argument, noerror, so that it doesn't pass on errors to the user if it fails to match. This does mean that you have to check for yourself whether the return value is nil, though.
Finally, instead of push to add the completion function you might want to use add-hook as follows:
(add-hook 'completion-at-point-functions 'my-completion-at-point nil t)
This does two useful things: it checks whether your function is already in the hook before adding it, and (by passing t for the fourth argument, local) it only adds the function to the buffer-local value of the completion-at-point hook. This is almost certainly what you want, since you don't want to use these completions in every other Emacs buffer when you press the TAB key.

How to archive all the DONE tasks using a single command

To archive the DONE tasks i am using
C-c C-x a
command. The draw back is i have to manually move over the DONE tasks one by one and then archive it.
How to archive all the DONE tasks using a single command.
You can bulk archive (or refile/change todo etc) from within the Agenda view.
http://orgmode.org/manual/Agenda-commands.html#Agenda-commands
If you call Org-Agenda from within the buffer you want to archive you can temporarily restrict it to only that buffer and view only todo entries and filter for only DONE
C-c a < t
N r
Where N corresponds to the shortcut for your DONE state (with default states it would be 2)
Then you'd simply need to mark all the desired headlines and bulk archive
m (mark for bulk action)
B a (or B $ for arch->sibling)
Here's a corrected version of madalu's snippet. Note that this version also only operates on the current subtree (change 'tree back to 'file to operate over the entire file).
(defun org-archive-done-tasks ()
(interactive)
(org-map-entries
(lambda ()
(org-archive-subtree)
(setq org-map-continue-from (org-element-property :begin (org-element-at-point))))
"/DONE" 'tree))
You can write a function using org-map-entries:
(defun my-org-archive-done-tasks ()
(interactive)
(org-map-entries 'org-archive-subtree "/DONE" 'file))
Also from http://orgmode.org/manual/Moving-subtrees.html#Moving-subtrees
C-u C-c C-x C-s
Check if any direct children of the current headline could be moved to the archive. To do this, each subtree is checked for open TODO entries. If none are found, the command offers to move it to the archive location. If the cursor is not on a headline when this command is invoked, the level 1 trees will be checked.
There is now a command org-archive-all-done that is built into org-mode, and in org-archive.el.
If you want to do it in the source Org buffer (as opposed to in an Org agenda view), and if they are following each other, you can select all of them in a region, and apply a command (such as C-c C-t d).
Only setting needed:
;; Some commands act upon headlines in the active region.
(setq org-loop-over-headlines-in-active-region 'start-level)
I found the direct "org-map-entries" method in a couple of these answers to be a little "fragile" for some reason in situations with more varied nesting and TODOs at multiple levels.
This method - generating a list and then archiving in reverse (to avoid changes in positioning) seems to cover every use case I've thrown at it. Sharing it here for anyone else that runs into trouble.
Note the "TODO" string match on the last line needs to match how you have your TODOs defined exactly (for example in a vanilla case, the match may be: "TODO=\"DONE\"").
(defun org-archive-done-tasks ()
"Archive all tasks marked DONE in the file."
(interactive)
(mapc (lambda(entry)
(goto-char entry)
(org-archive-subtree))
(reverse (org-map-entries (lambda () (point)) "TODO=\"★ DONE\"" 'file))))
Based on Robert's Answer
(require 'org)
(require 'org-archive)
(add-hook 'org-mode-hook (lambda () (add-hook 'after-save-hook 'org-archive-all-done nil t)))

Emacs Modes: "Command attempted to use minibuffer while in minibuffer"

Scenario:
I start to type M-x to type a command
I switch to another emacs window/buffer because I realise I'm executing the command in the wrong window
I start to type M-x again to execute the command in the correct window
Result: I get the dreaded "Command attempted to use minibuffer while in minibuffer"
This happens to me multiple times a day while using emacs, and not just in this scenario. This behaviour is highly user-hostile (ref. Modes and Pseudo-modes in The Humane Interface by Jef Raskin)
Is there a way to customize emacs behaviour so that instead of giving this error, it just cancels the first minibuffer and replaces it with a new one?
You can set the variable enable-recursive-minibuffers, which will prevent that error message from coming up. But it just enables multiple calls to the minibuffer - it doesn't redirect the current minibuffer's command to the new buffer. You can give this a try, but I think it'll be more confusing because the original action is still pending...
M-x is bound to 'execute-extended-command, and re-hosting (changing the original buffer) for that command is kind of like programming with continuation. i.e. you call a subroutine from location X, but instead of returning to X when done, you return to Y. I personally think it'd open up more confusion than it'd solve. But I understand the frustration (and know others who have the same frustration).
Indeed this emacs "feature" is aggressive and annoying.
I found this to be the right answer to the problem .Most likely you lost focus of the minibuffer because you switched windows with the mouse and NOT a minibuffer command. So whenever you lose focus using the mouse, the minibuffer will be cleared. Check this post. It works for me and it's way better than recursive minibuffers which will cause a headache
http://trey-jackson.blogspot.com/2010/04/emacs-tip-36-abort-minibuffer-when.html
I'm not sure if there is such a customization, but the way I avoid this is hitting ctrl-g to cancel the command I was in the middle of writing in the minibuffer.
Since my first answer doesn't directly give you what you want, I thought I'd come up with a real solution. This is what I have:
(defvar my-execute-extended-command-source-buffer nil
"var holding the buffer to which the extended-execute-command should apply")
(defvar in-my-execute-extended-command nil
"internal use - indicates whether we're in a 'recursive edit' of sorts")
(defun my-execute-extended-command (command)
"home-grown version of execute-extended-command that supports re-hosting the buffer"
(interactive (list (if in-my-execute-extended-command
nil
(let ((in-my-execute-extended-command t))
(setq my-execute-extended-command-source-buffer (current-buffer))
(completing-read "My-x " obarray 'commandp t nil 'extended-command-history nil nil)))))
(if in-my-execute-extended-command
(progn (setq my-execute-extended-command-source-buffer (current-buffer))
(select-window (minibuffer-window)))
(switch-to-buffer my-execute-extended-command-source-buffer)
(call-interactively (symbol-function (intern command)))))
I've tested it this way. I bound it to a key (F10 in my case b/c I didn't want to lose M-x). Then, with two windows open, each showing a different buffer (say A and B):
From window showing buffer A: F10 isearch-for
Switch from minibuffer to window showing A: C-x o
Switch from window showing A to that showing B: C-x o
"re-host" the command from buffer B: F10
Now back in the minibuffer, finish the command ward RET
When I started typing a search term, the search applied to buffer B.
This only replaces the M-x functionality, not the commands invoked from M-x. Also, this version does not support the prefix argument.
Hopefully this is what you want.
Here you go:
;; automatically cancel the minibuffer when you switch to it, to avoid
;; "attempted to use minibuffer" error.
;; cy was here
(provide 'cancel-minibuffer)
(defun cancel-minibuffer-first (sub-read &rest args)
(let ((active (active-minibuffer-window)))
(if active
(progn
;; we have to trampoline, since we're IN the minibuffer right now.
(apply 'run-at-time 0 nil sub-read args)
(abort-recursive-edit))
(apply sub-read args))))
(advice-add 'read-from-minibuffer :around #'cancel-minibuffer-first)
Can anyone improve on the following?
I've given up and just want to set \C-w to cancel any previous minibuffer before opening a new one (like doing \C-g\C-w)
So far thanks to Trey I've got:
(defun cancel-completing-read ()
(if (> (minibuffer-depth) 0) (exit-minibuffer))
(completing-read "My-x " obarray 'commandp t nil 'extended-command-history nil nil))
(defun cancel-and-execute-command (command)
(interactive (list (cancel-completing-read)))
(call-interactively (symbol-function (intern command))))
(global-set-key "\M-x" 'cancel-and-execute-command)
What command should I use in the place of exit-minibuffer above?
I've tried
keyboard-escape-quit
exit-minibuffer
keyboard-quit