EDIT: The solution was simple but "bonus points" for anyone that can explain why my method didn't work.
ORIG:
I would like an org-mode-custom-command to display an agenda which is only made from the current buffer.
The following snippet shows the kind of view that I want.
(setq org-agenda-custom-commands
'(("b" "Buffer summary"
((todo "TODO" ((org-agenda-files '("~/.agenda/notes.org"))))))))
But, I don't want to specify a filename, rather I want to use the current buffer. Here is my stab at it.
(setq org-agenda-custom-commands
'(("b" "Buffer summary"
((todo "TODO" ((org-agenda-files (buffer-file-name))))))))
When I open an org-buffer and run this agenda command the result is just a pretty much blank agenda view. I presume it's because buffer-file-name is being evaluated at point later than when I press the agenda view...?
I'm still beginning to learn elisp, so don't hesitate to point out the obvious. Thank-you.
EDIT:
Following a suggestion in the comments.
(setq org-agenda-custom-commands
'(("b" "Buffer summary"
((todo "TODO" ((org-agenda-files (list (buffer-file-name)))))))))
I receive a backtrace.
Debugger entered--Lisp error: (wrong-type-argument stringp nil)
file-directory-p(nil)
...etc...
For me, the most obvious is NOT to create an extra agenda view, and simply call any existing view on that buffer only (limit the view to the current buffer with a call such as C-c a < a, where < limits on the current buffer).
If you still want to make an extra agenda view for the current buffer, I'm not sure whether that's possible with all commands. For sure, calling occur-tree will work on the current buffer. Not sure about todo and the like.
...The agenda view usually shows the information collected from all the agenda files For more info, first make sure that file you are trying to make agenda-viwable or trackable, by activating it via an org command C-c [ (org-agenda-file-to-front)
you can test the current buffe name by
(message (buffer-file-name))
Normally, I use my agenda view from various files, but I can track different agendas e.g done, on-progress, fixed, bug, just by using hot-keys
Here is mine:
(setq org-agenda-custom-commands
'(
("x" agenda)
("y" agenda*)
("o" todo "ONPROGRESS")
("n" tags-todo "+TIPS")
("d" todo "DONE")
("p" todo "PENDING")
("b" todo "BUG")
("f" todo "FIXED")
;("F" todo-tree "FIXED")
))
So if I want to view e.g done stuffs C-c a d this will show me all done lists regardless of which file they came.
Related
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.
Using Emacs Org-mode synchronised with Toodledo I have the variable org-todo-keywords set to
((sequence "TODO" "NEXT" "|" "DONE")
(sequence "WAITING" "HOLD" "SOMEDAY" "|" "CANCELLED"))
When want the built-in agenda view weekly/daily agenda by typing C-c a a I get all task that is not in the todo state DONE.
How can I set Org-mode making the command C-c a a only return tasks of todo states TODO and NEXT?
Of cause I can make a custom agenda view but I guess there is a variable that limits the todo states or an other simple way of modifying org-mode setting the built-in agenda view to fulfil my needs.
Thanks in advance
Here is just one solution -- there are others:
(org-agenda-skip-entry-if 'notregexp "regular expression")
http://orgmode.org/manual/Special-agenda-views.html
see also
http://orgmode.org/worg/org-tutorials/org-custom-agenda-commands.html
Other settings that include filtering out completed tasks for deadline and scheduled are as follows:
(org-agenda-skip-scheduled-if-done t)
(org-agenda-skip-deadline-if-done t)
EDIT (April 26, 2014): Included working example:
(setq org-agenda-custom-commands '(
("1" "Events" agenda "my-calendar" (
(org-agenda-span 365)
(org-agenda-show-all-dates nil)
(org-agenda-entry-types '(:deadline))
(org-agenda-skip-function
'(org-agenda-skip-entry-if 'notregexp "\\* TODO\\|\\* NEXT"))
(org-deadline-warning-days 0) ))))
I read the org-mode manual but couldn't find an easy way to add a CREATED field to newly created TODOs. In combination with org-log-done one could then compute the time it took to close a particular TODO. This is especially useful when using archive files.
Example:
* TODO Do something
CREATED: [2012-09-02 Sun 23:02]
* DONE Do something else
CREATED: [2012-09-02 Sun 20:02]
CLOSED: [2012-09-02 Sun 22:02]
I would expect the CREATED field to be added to new tasks (tasks which don't have that field) whenever the file is saved.
Any suggestions on how to achieve this? Using something like Git is not a solution for me to track the creations of TODOS.
I use org-expiry to implement that functionality, which is in the contrib directory of org.
The base configuration I use is:
;; Allow automatically handing of created/expired meta data.
(require 'org-expiry)
;; Configure it a bit to my liking
(setq
org-expiry-created-property-name "CREATED" ; Name of property when an item is created
org-expiry-inactive-timestamps t ; Don't have everything in the agenda view
)
(defun mrb/insert-created-timestamp()
"Insert a CREATED property using org-expiry.el for TODO entries"
(org-expiry-insert-created)
(org-back-to-heading)
(org-end-of-line)
(insert " ")
)
;; Whenever a TODO entry is created, I want a timestamp
;; Advice org-insert-todo-heading to insert a created timestamp using org-expiry
(defadvice org-insert-todo-heading (after mrb/created-timestamp-advice activate)
"Insert a CREATED property using org-expiry.el for TODO entries"
(mrb/insert-created-timestamp)
)
;; Make it active
(ad-activate 'org-insert-todo-heading)
If you are using capture it does not automatically work and needs a little glue. I have posted the complete config here: https://gist.github.com/4037694
A more lightweight solution would be to add ! flag to the TODO state:
(setq org-todo-keywords '((sequence "TODO(!)" "DONE")))
Then:
* TODO get of your ass
- State "TODO" from [2016-06-03 to. 10:35]
It isn't very pretty though.
Ref: http://orgmode.org/org.html#Tracking-TODO-state-changes
You don't need to modify functions with 'defadvice' to run expiry code on capture.
You should use hook:
(add-hook 'org-capture-before-finalize-hook
(lambda()
(save-excursion
(org-back-to-heading)
(org-expiry-insert-created))))
Same for 'org-insert-todo-heading'. There is a hook:
(add-hook 'org-insert-todo-heading-hook
(lambda()
(save-excursion
(org-back-to-heading)
(org-expiry-insert-created))))
Org provides a hook org-after-todo-state-change-hook which you can use here:
org-after-todo-state-change-hook is a variable defined in ‘org.el’.
Documentation:
Hook which is run after the state of a TODO item was changed.
The new state (a string with a TODO keyword, or nil) is available in the
Lisp variable ‘org-state’.
Use it as follows:
(require 'org-expiry)
(add-hook 'org-after-todo-state-change-hook
(lambda ()
(when (string= org-state "TODO")
(save-excursion
(org-back-to-heading)
(org-expiry-insert-created)))))
org-expiry is part of org-contrib, which is included in the org-plus-contrib package on the org ELPA.
Here's a buried treasure:
(setq org-treat-insert-todo-heading-as-state-change t)
I found it here, in response to someone saying they wanted an org-insert-todo-heading-hook.
Just tried it out and, true to form, when you org-insert-todo-heading, it counts as a state change, so ex: #+TODO: TODO(t!) | ... will add a log.
If you create all your TODOs with org-capture the following capture template does the trick:
(setq org-capture-templates
'(
("t" "TODO Task" entry (file+headline "~/inbox.org" "Tasks")
"* TODO %?\nCREATED: %u\nSRC: %a\n%i\n")
))
The result will look something like this:
* Tasks
** TODO Dummy task
CREATED: [2015-05-08 Fri]
SRC: [[file:~/path/to/file/where/you/created/the/task.org::*heading"][heading]]
Here is a lightweight solution that does not require an external package. I got it from the answer by #MarcinAntczak, the comments by #Clément, and this similar thread. It works with org-capture and with M-S-RET. Put this in your Emacs initialization file (e.g. ~/.emacs):
(defun insert-created-date(&rest ignore)
(insert (format-time-string
(concat "\nCREATED: "
(cdr org-time-stamp-formats))
))
(org-back-to-heading) ; in org-capture, this folds the entry; when inserting a heading, this moves point back to the heading line
(move-end-of-line()) ; when inserting a heading, this moves point to the end of the line
)
; add to the org-capture hook
(add-hook 'org-capture-before-finalize-hook
#'insert-created-date
)
; hook it to adding headings with M-S-RET
; do not add this to org-insert-heading-hook, otherwise this also works in non-TODO items
; and Org-mode has no org-insert-todo-heading-hook
(advice-add 'org-insert-todo-heading :after #'insert-created-date)
I did not add this function to state changes (e.g., from plain heading to TODO) because it would need to be in a properties drawer and I prefer to not have those extra lines. If you prefer to have it in properties, use the function defined in see this thread.
You can add a time stamp at creation time with zero config, but it won't be labeled CREATED. Rather than manually typing TODO, use C-c C-t. It will then be logged as "state changed to TODO from """ and time stamped.
Using capture templates like the one below, I can add entries to different headlines in a file. How can I manually enter a headline during capture, instead of setting up each headline to a key in the .emacs file like I am now doing?
(setq org-capture-templates
'(
("l" "Log" entry
(file+headline "c:/Org/log.org" "Log")
"\n\n** %?\n<%<%Y-%m-%d %a %T>>"
:empty-lines 1))
It looks like, in newer versions of org at least, that custom functions can be used in capture templates to do this.
Instead of:
entry
(file+headline "~/Work/work.org" "Refile")
You can use:
entry
(file+function "~/Work/work.org" function-finding-location)
Where 'function-finding-location' is a custom function you have written yourself, which could easily prompt you for a headline.
Or, you can go even farther, and define a custom function which will prompt for both file name and headline name (or anything else you can dream up):
entry
(function function-finding-location)
I don't really know enough elisp to write these functions myself, but this looks like the place to start. It'd be nice if someone else could offer up some code. The relevant documentation is here:
http://orgmode.org/manual/Template-elements.html
I wrote a function to be used with file+function which will prompt for a location on capture.
It uses the internal prompting function of org-refile so we get completions of headings in the prompt (with maxlevels overridden to 9). When the user enters an unknown heading, it creates it at the end of the file.
(defun org-ask-location ()
(let* ((org-refile-targets '((nil :maxlevel . 9)))
(hd (condition-case nil
(car (org-refile-get-location nil nil t t))
(error (car org-refile-history)))))
(goto-char (point-min))
(outline-next-heading)
(if (re-search-forward
(format org-complex-heading-regexp-format (regexp-quote hd))
nil t)
(goto-char (point-at-bol))
(goto-char (point-max))
(or (bolp) (insert "\n"))
(insert "* " hd "\n")))
(end-of-line))
In your case, you use it like this:
(setq org-capture-templates
'(("l" "Log" entry
(file+function "c:/Org/log.org" org-ask-location)
"\n\n** %?\n<%<%Y-%m-%d %a %T>>"
:empty-lines 1))
I don't believe you can have it prompt for the headline on capture. You can however refile from within the capture window which should result in the desired behaviour.
I would define a catch-all target headline/file so that if you forget you will always collect them in the same location and then just have to refile them once created. If you also set a category/tag on this headline you will be able to easily see the misfiled capture entry and refile it as desired. (Example below)
Then instead of finishing with C-c C-c choose to refile with C-c C-w and you will be asked to select the headline you want to send the new entry to.
The capture template I use for this catch all is as follows (adapted from Bernt Hansen's capture settings)
("i"
"Incidents"
entry
(file+headline "~/Work/work.org" "Refile")
"* TODO %^{Ticket} - %^{User}\nSCHEDULED: %^t DEADLINE: %^t\n:PROPERTIES:
\n:DATE: %^U\n:END:\n%^{MANAGER}p%^{HOSTNAME}p%^{LOCATION}p%^{TEL}p\n%c"
:empty-lines 1 :clock-in t :clock-resume t)
(Line breaks are added to avoid scrolling when reading here)
The heading is configured as follows
* Refile :refile:
:PROPERTIES:
:CATEGORY: Unsorted
:END:
With this I end up with all non-refiled tasks showing up as
Unsorted: Deadline: TODO <Headline> :refile::
I currently tend to use tags as reference if I'm waiting for coworkers/managers to deal with the ticket, or to remind me to speak to them about it when I see them so the tag at the end stands out clearly, as does Unsorted if I'm trying to remember what the issue is (since I simply have a case number and user name showing, details within the entry).
while capturing a note, after finishing writeup press C-u C-c C-w to refile under desired new headline.
you also need to set this variable
(setq org-refile-allow-creating-parent-nodes (quote confirm))
you can set it to t instead of confirm. But I like it be confirm because I dont often refile to new targets
I'd like to save the output of org-agenda to a text file, every time that the org-agenda is calculated. This way, I can use an external program (like ATNotes on windows or conky on linux), to pick up this text file and display it on my desktop.
How can I do this?
I feel like I'm raining on your parade after you went to the trouble to write this code snipped (and used a piece of around advice, too!), but actually this feature is already baked into org-mode, and documented in the manual. The command you want is org-write-agenda (C-x C-w in an agenda buffer). See the section of the org-mode info entitled "Exporting Agenda Views."
If you want to do it while you have emacs open, you can just call save-buffer on the *Agenda* buffer via M-x save-buffer (since orgmode binds C-x C-s to org-save-all-org-buffer. You could bind save-buffer to something else in the org-mode-map if you wanted.
If you want to do it via a cron, you should be able to use the snippet in this thread on the org-mode mailing list to pipe the output to a file. I've used this in the past:
emacs -batch -eval '(org-batch-agenda "a" org-agenda-ndays 7 org-agenda-include-diary nil org-agenda-files (quote ("~/org/todo.org")))' > agenda.txt
So I finally decided to open the emacs lisp manual and figure this out myself. I wrote this bit of code, which seems to be working just fine! :)
;; Save the org-agenda for display with conky
(defadvice org-todo-list (after saveorgagenda activate)
"save this output to my todo file"
(get-buffer-create "todo")
(with-current-buffer "todo"
(set-buffer-modified-p nil))
(kill-buffer "todo")
(write-file "~/todo"))
EDIT REASONS:
1) Without kill-buffer, the defadvice creates a new todo buffer on every execution of org-todo-list. This gets pretty irritating.
2) Without the get-buffer-create function, kill-buffers fails the first time since there is no buffer named todo at that time.
3) Without set-buffer-modified-p, the function will keep telling you "todo buffer is modified. Really kill it? (y or n)" which would defeat the whole purpose really.
Whew! I'm so happy I actually took the time and effort to figure this out! :D