How to archive all the DONE/DELEGATED/DEFERRED tasks using a single command - org-mode

This is a follow up question on How to archive all the DONE tasks using a single command.
The solution given by Stefan works well for single DONE statement. How can it be extended to work with multiple DONE statements?
Stefan gave the following solution:
(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))
I have the following org-todo-keywords:
(setq org-todo-keywords
'((sequence "TODO(t)" "NEXT(n)" "WAITING(w)" "PROJECT(p)" "|" "DONE(d)" "DELEGATED" "DEFERRED")))
The goals is to archive all the tasks marked DONE, DELEGATED or DEFERRED. I have tried to use the matching as explained here, but have not been able to get it working. I tried for example:
MATCH = "/DONE|/DELEGATED|/DEFERRED"
I am new to elisp, a solution with explanation is appreciated.

The syntax is a bit obscure, but if I read the page that you linked to correctly, I think (untested!) that the following will work:
"/+DONE|+DELEGATED|+DEFERRED"
That's very similar to the last example on that page: select entries with a TODO property (/) that is not empty (!) and with a value of that TODO property that is DONE or DELEGATED or DEFERRED.

Related

How to never expand yasnippets in comments and strings

I'd like to disable YASnippet expansion (for example, if) in comments and strings, but don't find how to do that in a generic way.
On The condition system, they say how to do it for Python, but I'd like to get it working for all prog-modes at once, and I'm not aware of any function which tests "in string/comment", independently of the language.
Is there still a way to do so?
Using lawlist's suggestion and adding it to prog-mode-hook:
(defun yas-no-expand-in-comment/string ()
(setq yas-buffer-local-condition
'(if (nth 8 (syntax-ppss)) ;; non-nil if in a string or comment
'(require-snippet-condition . force-in-comment)
t)))
(add-hook 'prog-mode-hook 'yas-no-expand-in-comment/string)

how do I run this Emacs M-x command "wg-update-workgroup" automatically before emacs closes?

I would like this to happen when I right click the launcher...icon..and select quit..and choose file exit. I would like this command to be run right before emacs exits....so when I right click the launcher icon and select quit then this command "wg-update-workgroup" is run then Emacs exits..I've tried learning about hooks but don't get how to add one....If someone can give me exact code I put into my initialization file I would be very grateful....tried binding a function to a key but get weird command p error.
Here's the code:
(add-hook 'kill-emacs-hook
(lambda ()
(wg-update-workgroup)))
UPD
It seems that the code isn't working for you since wg-update-workgroup needs an argument.
You have to test this yourself, since I don't really want to get familiar with the package.
Solution 1:
(add-hook 'kill-emacs-hook
(lambda ()
(wg-update-all-workgroups)))
Solution 2:
(add-hook 'kill-emacs-hook
(lambda ()
(call-interactively 'wg-update-workgroup)))
UPD: disregard everything from above:)
I'm pretty sure this is what you want:
(setq wg-query-for-save-on-emacs-exit nil)
(push (lambda()(or (ignore-errors
(wg-update-all-workgroups-and-save)) t))
kill-emacs-query-functions)
The first statement removes the extremely annoying y/n query about saving
workgroups on exit. The second statement saves everything unconditionally on exit.
Just to list my full configuration:
(require 'workgroups)
(workgroups-mode 1)
(setq wg-query-for-save-on-emacs-exit nil)
(wg-load "~/wg")
(push (lambda()(or (ignore-errors
(wg-update-all-workgroups-and-save)) t))
kill-emacs-query-functions)
You're right to be baffled. The issue is this: when Emacs begins exiting, workgroups.el cleans itself up earlier than 'kill-emacs-hook. What you want is this:
(add-hook 'kill-emacs-query-functions 'wg-update-all-workgroups)
The hook variable should then look something like this:
(wg-update-all-workgroups wg-emacs-exit-query)
I recommend using 'wg-update-all-workgroups rather than 'wg-update-workgroup if, like me, you have more than one workgroup saved in a given workgroups file.
IMO workgroups.el is the best Emacs session manager. Somebody new has just taken it over. I'm excited that a new version with even more features may be forthcoming:
https://github.com/pashinin/workgroups2/

Insert yasnippet by name

I want to insert a specific yasnippet as part of a function in emacs-lisp. Is there a way to do that?
The only command that seems related is yas/insert-snippet, but it simply opens a popup with all the options and the documentation doesn't say anything about bypassing the popup by specifing the snippet name.
yas/insert-snippet is indeed just a thin wrapper around yas/expand-snippet for interactive use. However, the internal structures are... interesting. Judging from the source code the following does work for me when I want to expand the "defun" snippet in elisp-mode:
(yas/expand-snippet
(yas/template-content (cdar (mapcan #'(lambda (table)
(yas/fetch table "defun"))
(yas/get-snippet-tables)))))
As the author of yasnippet, I think you'd rather not rely on internal details of yasnippet's interesting data structures, which may change in the future. I would do this based on the documentation of yas/insert-snippet and yas/prompt-functions:
(defun yas/insert-by-name (name)
(flet ((dummy-prompt
(prompt choices &optional display-fn)
(declare (ignore prompt))
(or (find name choices :key display-fn :test #'string=)
(throw 'notfound nil))))
(let ((yas/prompt-functions '(dummy-prompt)))
(catch 'notfound
(yas/insert-snippet t)))))
(yas/insert-by-name "defun")
I'm just getting into yasnippet and I wanted to automatically insert one of my snippets upon opening a new file for certain modes. That led me to here but I've generated a slightly different solution. Providing yet another alternative: ("new-shell" is the name of my personal snippet for providing a new shell script template)
(defun jsm/new-file-snippet (key)
"Call particular yasnippet template for newly created
files. Use by adding a lambda function to the particular mode
hook passing the correct yasnippet key"
(interactive)
(if (= (buffer-size) 0)
(progn
(insert key)
(call-interactively 'yas-expand))))
(add-hook 'sh-mode-hook '(lambda () (jsm/new-file-snippet "new-shell")))
IMO, my solution is a tad less susceptible to breaking should yasnippet change dramatically.
This is 2022 now, so we can simply do the following :
(yas-expand-snippet (yas-lookup-snippet "name-of-your-snippet"))
See the documentation

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

How to configure cleverly org-archive-location in org-mode

BACKGROUND: In org-mode, the variable org-archive-location is set to "%s_archive::" by default, so that a file "toto.org" archives into a file "toto.org_archive". I would like it to archive to "toto.ref" instead. I am using org-mode version 7.4 (out of the git server).
I would have thought it to be as simple as
(setq org-archive-location
`(replace-regexp-in-string ".org" ".ref" %s)
)
But I was pointed out that this was not proper in LISP (plus, it did not work). My final solution is as follow, you should be able to adapt to most clever configurations of org-archive-location:
(setq org-archive-location "%s::* ARCHIVES")
(defadvice org-extract-archive-file (after org-to-ref activate)
(setq ad-return-value
(replace-regexp-in-string "\\.org" ".ref" ad-return-value)
)
)
Note that:
1) I voluntarily did not add a $ at the end of ".org" so that it would properly alter "test.org.gpg" into "test.ref.gpg".
2) It seems that one should use the regular expression "\.org" (rather than, say, ".org") (longer explanation below in the answers).
You can't define a variable in Emacs such that its value is obtained by running code; variables have simple, static values.
You can achieve the effect you described by advising the function org-extract-archive-file, which is the one that generates an archive location from org-archive-location:
(defadvice org-extract-archive-file (after org-to-ref activate)
(setq ad-return-value
(replace-regexp-in-string "\\.org" ".ref" ad-return-value)))
This works for me now, but of course the internals of org-mode are subject to change and this solution may not work forever.
You should not quote an expression that you want to evaluate. Note also that in a regular expression, . matches any character.
Here is an example of how to set the file, the location (e.g., main heading) in the file, and whether or not to include additional archive information:
(let* (
(org-archive-location "~/todo.org::* TASKS")
(org-archive-save-context-info nil))
...)
You can try this: #+ARCHIVE: %s.ref:: at the beginning of your org file.
Read more about it here.
Also, other interesting option is to set inside your headtree the following, for instance:
* Main Header of tree
:PROPERTIES:
:ARCHIVE: toto.ref:: * Main Header of tree in archive file
:END:
** sub tree of main header and so on
The latter I took from this video.