How to fetch already read articles into summary buffer in gnus? - emacs

While in summary buffer how can I make gnus fetching already read articles in two situations:
while in a thread with some articles already read (and thus not visible). I would like to complete the thread with all the articles (not only parents!) read or unread.
fetch last N read articles which are not visible.
Thanks a ton!

In the summary buffer, to fetch the parent, use ^ (gnus-summary-refer-parent-article) (also available as <menu-bar> <Article> <Fetch parent of article>).
To fetch the whole thread (at least the part that's still on your server), use A T (gnus-summary-refer-thread) (<menu-bar> <Article> <Fetch current thread>).
To fetch more articles, use / o (gnus-summary-insert-old-articles) (also available as <menu-bar> <Gnus> <See old articles>).

For the first question, try
(setq gnus-fetch-old-headers 'some)
in your .gnus
for the second, when you select the group, it should ask you how many old articles you want to fetch. Does that not work?

While ^ and / o commands already mentioned this one useful for debugging: M-^ (gnus-summary-refer-article) when you work with message pain text (which you can get by C-u g).
gnus-summary-refer-parent-article internally used gnus-summary-refer-article...

(defun codefalling/gnus-show-all ()
"Show all mail"
(interactive)
(gnus-summary-insert-old-articles t) ;; show all, or t->50 to show 50 old mail
(goto-char (point-min)))
(add-hook 'gnus-summary-mode-hook '(lambda () (run-with-idle-timer 0.1 nil 'codefalling/gnus-show-all)))
Then gnus will show all mail read or unread.

Related

emacs > org mode > agenda - always use current buffer

I am using many different org mode files for various projects, and I rev them by adding the date to the filename eg filename-2020-09-17.org. I realize I could use version control but in this case that is not possible, due to needing to share the file with others who are not using VC.
I would like the Agenda to always show just the items for the current file/buffer.
When I save eg the file with filename-2020-09-16.org to filename-2020-09-17.org, then the agenda still shows the old file name unless I remove it from the agenda file list and add the new file.
I realize that I can use C-c a < a but I am lazy and would rather not have to type S-, each time to get the <.
I looked at
Agenda view of the current buffer
And the OP says the solution was simple but he/she/they did not provide the solution - at least I don't see it and I tried the posted code but it no works.
I also found https://www.reddit.com/r/orgmode/comments/bxwovd/agenda_for_current_buffer/ but that did not seem to meet my need.
Specifically I would like to put something in .emacs so that this would apply to all files all the time.
I also looked into a keystroke macro programs but this does not seem ideal.
Any help is appreciated.
Thanks ahead of time.
Here's a simple function to do what you want, but there is no error checking to make sure e.g. that you are invoking it from a buffer that is visiting an Org mode file. The idea is that you set the org-agenda-files list to contain just the file which the buffer is visiting and then you call the regular org-agenda function. Binding the modified function to the C-c a key may or may not be what you want to do, but you can try and decide for yourself:
(defun org-agenda-current-buffer ()
(interactive)
(let ((org-agenda-files (list (buffer-file-name (current-buffer)))))
(org-agenda)))
(define-key global-map (kbd "C-c a") #'org-agenda-current-buffer)

Setup a personal wiki in Emacs Org-mode

I would like to setup a personal wiki in org-mode.
So far, I have tried this two ways. My first attempt was using a single "Scientific Notebook.org" file. In this went all my notes - each with its own headline, date and tags (same format as a blog post). I then turned on org-velocity to quickly navigate the file.
But this created two problems: first, I use a lot of math in my notes (LaTeX previews are one of the reasons I want to us org). But these take sooooo long to load, I can't images trying to open a file with several thousand entries (all filled with math!!)
The other problem I have is with tags. I like to use a lot of multi-word tags to cross-reference my notes. But the way org-mode wraps these in the buffer, makes my headings completely unintelligible. Also (maybe it's just me but) I find CamelCase really hard to read, especially when faced with something like:
:monotonicTransformations:homogeneousFunctions:orderedSets:proofs:
Now my second attempt is with Deft. Here, I have broken up each note into its own .org file and creating a dedicated ~/org/ folder to hold my wiki. But this is where I am stuck:
1) How do you setup auto linking, so that typing say "foo bar" in one note, creates a link to "foo bar.org"? Can this be done with radio target? If not, can this syntax [[foo bar]] be overridden to search for headlines in all files in the ~/org/ directory? I tried adding Wiki.el as a minor mode but no dice...
2) How do you tag individual files? And how can you then pull up a list of all tags and use this to filter your list of notes? I have read that bookmark+ lets you do file tagging. But I got so lost in the online docs...
I would love to hear how others have solved these problem, what minor modes you are using, workflows and keyboard shortcuts or other mods!
Thanks!
-Adam
I'm using a simplistic code for a wiki.
Because that's what a wiki is for me: a quick way to categorize things.
The structure is a following:
each subject has its own org file
each topic of subject has its own heading
all org files are in single directory
you can jump to file, or create a new file with helm
That's it. I've found to need to link anything to anything, jump-to-subject functionality
is more than enough. Here's how this looks:
And once within a subject, I can jump across topics with worf.
Here's how this looks:
Having only one note file is, in my opinion, more flexible and compatible. It tends, however, to get slow for even moderatly sized files. Multiple small files are quick, but they need more effort to set up, and they only work within that setup.
Single File Solution
To speed things up, consider setting org-startup-with-latex-preview to nil (or add #+STARTUP: nolatexpreview to your file).
Tags not only get messy when used for keywords, using them also gets rather slow as your file grows. I've played around with some custom functions, but now avoid tags most of the time. Instead I use flat hierarchies, categories and otherwise rely on occur and org-occur (e.g. M-x org-occur begin_proof).
Multiple Files
The org syntax for linking to other files is rather simple: [[./this idea.org][this idea]]. If that is too much hassle, it should be easy to write a function that replaces the active region with an appropriate link.
If you want to link [[this idea]] to a file "this idea.org", you could add a function to org-open-at-point-functions and handle it yourself.
As for tags, you don't tag a file itself, but rather a single top level headline. This of course means that all your troubles with tags a back as well.
Again, I would recommend not using tags. Just make sure the file contains the right keywords at the right places and use occur and friends.
Edit: An Example `org-open-at-point-function'
If you want to search for a fuzzy link in all files in a directory instead of only the current buffer, you can do this by using the org-open-at-point-functions hook. Here is an example:
(defvar my-link-search-directory "/my/notes/directory/")
(defun my-open-link-function ()
"Open link, interpreting it a the name of a headline."
(let* ((el (org-element-context))
(type (first el))
(link-type (plist-get (cadr el) :type))
(path (let ((path-1 (plist-get (cadr el) :path)))
(when (stringp path-1)
(org-link-unescape path-1)))))
(when (and (eql type 'link)
path
(string= link-type "fuzzy"))
(let* ((path (regexp-quote path))
(result
(delq nil
(org-map-entries
(lambda ()
(when (string-match
path
(org-get-heading))
(list (buffer-file-name) (point))))
nil
;; Here we set the scope.
;; 'agenda would search in all agenda files.
;; We want a list of all org files in `my-link-search-directory'.
(directory-files
my-link-search-directory
t "[.]org\\'")))))
(when result
(when (> (length result) 1)
(message "Warning: multiple search results for %s" path))
(let ((file (caar result))
(pos (cadar result)))
(find-file file)
(goto-char pos)))))))
(add-hook
'org-open-at-point-functions
'my-open-link-function)
Note that I haven't tested this much.
Actually, I would recommend against using this unless you really need it. While making fancy extensions is tempting, keeping your notes as simple as possible is preferably. If you have everything in one file, you could edit your notes with notepad or google docs or whatever, should you ever need to.

How to use Gnus with newsgroup like Google Group?

I tried this setting:
(setq gnus-select-method '(nnml "comp.lang.lisp"))
But when I activate Gnus, no grouop is shown. How do I add groups like comp.lang.*?
Edit: I tried with nntp:
(setq gnus-select-method '(nntp "comp.lang.lisp"))
but it doesn't work:
Warning: Opening nntp server on comp.lang.lisp...failed: ; Server nntp+comp.lang.lisp previously determined to be down; not retrying
Expanding on #logoscia's comment, comp.lang.lisp isn't an NNTP server, but a newsgroup. You can use Gmane/Gwene to read mailing lists and RSS feeds via NNTP. You can also add a traditional news server, like news.eternal-september.org. The elisp snippet below can get you started.
(setq gnus-select-method '(nnml "")) ;; this depends on how you want
;; to get your mail
(setq gnus-secondary-select-methods '((nntp "news.gmane.org")
(nntp "news.eternal-september.org")))
Start Gnus with M-x gnus. In the group buffer hit ^ to get to the *Server* buffer then browse the newsgroups on the servers. From there you can subscribe/unsubscribe to newsgroups with u. Back in the *Group* buffer you will see your subscribed groups. For details, see the Gnus manual.

elisp code clobbering a buffer, instead of saving off elsewhere... why?

I'm having some difficulties when trying to set something up that saves some persistent state, so that I can use the data between emacs invocations.
Using as a starting point some code from another question, I came up with the following little code snippet for something I'm wanting to do:
(defmacro with-output-to-file (path &rest body)
"record output of commands in body to file"
`(save-excursion
(let* ((buf (find-file-noselect ,path))
(standard-output buf))
(set-buffer buf)
(erase-buffer)
,#body
(save-buffer)
(kill-buffer))))
I then have a function that uses this, like:
(defun my-save-some-data ()
(with-output-to-file my-data-save-file
(prin1 my-data)))
EDIT: These both follow code like the following (previously, these were both setq; thanks to a comment from #phils for inspiring me to switch them to devfar and defcustom):
; note: my actual variable names (and filename value) are different;
; changed for example sake:
(defvar my-data (make-hash-table :test 'equal) "Data for a thing")
(defcustom my-data-save-file "~/tmp/my-data.el" "File to save my data to")
(Note: I also have a function to read the data back in, which happens automatically at load time, or on demand.)
I've set that up to run in a few circumstances (maybe too many? maybe poor choices? Anyway, this is what I set up):
(add-hook 'auto-save-hook 'my-save-some-data)
(add-hook 'kill-emacs-hook 'my-save-some-data)
(add-hook 'post-gc-hook 'my-save-some-data)
Most of the time, this works fine. However, every once in a while, I'm getting a problem where the data gets written to one of my previously-open buffers (killing all previous content there!), and then that buffer gets killed, with the saved changes.
Suffice it to say, this is highly annoying, as the buffer where this happens is frequently somewhere where I've been doing some work, and not necessarily checked it in yet.
I tried altering the macro above, replacing from (set-buffer buf) on with:
(with-current-buffer buf ; because set-buffer wasn't working??
(erase-buffer)
,#body
(if (eq buf (current-buffer))
(progn
(save-buffer)
(kill-buffer))
(message "buffer changed?!"))))))
This has somehow managed to cause it to append to the buffer, instead of overwriting it... so my if statement does seem to be working to some degree... however I don't see the message in my *Messages* buffer, so... I'm not quite sure what's going on.
One thing I think I've noticed (though it's hard to be certain, since I may not be actively paying attention when this happens) is that this happens in a not-then-currently-active buffer, rather than a buffer I'm currently editing.
So, the questions:
Am I doing something wrong here?
Are there other/better ways of doing this?
Are there standard ways to save state in a programatic way, that I could be using? (I poked around a bit in apropos, but failed to find anything... though perhaps I just don't know what to look for.)
What can I do to help myself track this down? (is there a way I can set breakpoints or something?)
Are there other protections I could use in code like this?
Any other thoughts welcome. I'm adding some more (message) forms in hopes of getting more debugging info in the mean time.
UPDATE: I've figured out that this only happens with the post-gc-hook. I don't know if my variables were somehow getting clobbered (and perhaps switching to defvar and defcustom will solve that?), or if there's some sort of obscure bug in the post-gc-hook processing... checking for reproducing the test-case with this latest change.
You can indeed set breakpoints, an easy way to do this is to put (edebug) in the place where you want to break. Then you can use, n for next, SPC for step, and e to eval. You can read more about edebug here.
So you can set a conditional breakpoint as a protection/warning, like this, before your call to (set-buffer):
(when (get-file-buffer my-data-save-file)
(read-from-minibuffer
(format "Warning: %s is already being visited by a buffer, contents will be overwritten! Entering edebug" my-data-save-file))
(edebug))
This will warn you and then enter the debugger if a file you are visiting in some buffer is about to be overwritten by your macro, where you can inspect what is going on.
Here is part the docstring of find-file-no-select:
Read file FILENAME into a buffer and return the buffer.
If a buffer exists visiting FILENAME, return that one, but
verify that the file has not changed since visited or saved.
My guess is that the my-data-save-file is already being visited by a buffer, so that is the buffer that is returned (and subsequently overwritten). But you can really find out what is happening with (edebug).
Just a quick reply to some of what you said. Your message never appears probably because you test whether the buffer of with-current-buffer is the current-buffer, which it always is, unless body changes the current buffer.
But you are right to use with-current-buffer instead of save-excursion followed by set-buffer.
As for other ways: why not put your data in a temporary buffer and then use write-file or append-to-fileor write-region?
FWIW, I tried your code briefly and saw no problem. But I just tried a simple (prin1 (symbol-function 'my-save-some-data)) for the body and a constant file name for the file. I tried with pre-existing file or not, and with pre-existing buffer or not, and with pre-existing unsaved modified buffer or not.
Are you testing with the interpreted code (e.g., macro present) or byte-compiled code?

Open multiple instance of a file-

How can I open multiple different instances of file in Emacs? That is to say, the instances are totally independent of each other but write to the same file.
I actually want to have a reference to the original file in one buffers side-by-side with the buffer in which I will be editing while referring to the original content. I don't find opening a temporary buffer, yanking the entire original content into it and have it side-by-side, as an elegant solution.
Other solutions are welcome as well.
I have tried using clone-indirect-buffer and C-x C-v but it doesn't server the purpose.
You can create a new buffer (C-xb*new*) and insert the content of the file to it with C-xifilename.
As I read through the find-file code, I see this warning coded into it:
"The file %s is already visited normally.
You have asked to visit it literally,
meaning no coding system decoding, format conversion, or local variables.
But Emacs can only visit a file in one way at a time.
Do you want to revisit the file literally now? "
Something that would imply that Emacs' code specifically tries to protect against the situation when the same file is visited multiple times, but the buffers are out of sync with each other. However... you could open two copies of Emacs, in which case they would not know about each other visiting the same file and so would allow this situation to happen.
I can understand that the above isn't a very nice option, but it looks like adding that kind of functionality will require some time understanding the reasons behind it being specifically prevented in the first place.
I've tried this:
M-:(switch-to-buffer (find-file-noselect-1 (create-file-buffer (buffer-file-name)) (buffer-file-name) t nil (buffer-file-name) 1))
And it seems like it would work, but I'm not sure of consequences - maybe different major modes may rely on the original Emacs treatment of files and their editing history, so use with care. The last number 1 is the number to be displayed after the file name, as in Foo.bar<1> So, you'd need to change that, if you need more copies.
As mentioned, you might be able to use clone-buffer, although you'll have to let-bind buffer-file-name around the call since clone-buffer otherwise will refuse to clone it. Another option is to do:
M-x set-visited-file-name RET toto RET
C-x C-f thefile RET
C-x b RET
M-x set-visited-file-name RET thefile RET
the last set-visited-file-name should ask you if you really want to do that, but you can answer that you do and Emacs will accept your choice. Arguably, clone-buffer should not reject to do it, so you might like to submit a bug-report asking to make it behave similarly to what set-visited-file-name does.
You may have some luck with clone-buffer, depending on your mode. It has certain limitations that you can read about in the docs.
Otherwise, here's something quick and dirty:
(defun dodgy-clone-buffer ()
"Clone the current buffer. The clone will write to the original file."
(interactive)
(switch-to-buffer-other-window
(eval `(with-current-buffer
;; Create a new buffer or clear an existing one.
(get-buffer-create ,(format "*clone: %s*" (buffer-name)))
(delete-region (point-min) (point-max))
(insert ,(buffer-string))
(setq buffer-file-name ,(buffer-file-name))
(funcall ',major-mode)
(current-buffer)))))