I keep some stuff in a file 'XXX.gpg' which I read and edit with emacs auto encryption mode.
In some cases I forget to close the buffer for a long time which is some kind of risk.
I would like to have the buffer automatically saved and closed after some time (of inactivity).
You could use run-with-idle-timer to construct a function doing exactly what you want.
this is what i use:
(defun dwim-kill-gpg-buffers ()
(interactive)
(let ((buffers-killed 0))
(dolist (buffer (buffer-list))
(with-current-buffer buffer
(when (string-match ".*\.gpg$" (buffer-name buffer))
(let ((current-time (second (current-time)))
(last-displayed-time (second buffer-display-time)))
(when (> (- current-time last-displayed-time)
60)
(message "Auto killing .gpg buffer '%s'" (buffer-name buffer))
(when (buffer-modified-p buffer)
(save-buffer))
(kill-buffer buffer)
(incf buffers-killed))))))
(unless (zerop buffers-killed)
(message "%s .gpg buffers have been autosaved and killed" buffers-killed))))
(run-with-idle-timer 60 t 'dwim-kill-gpg-buffers)
it tries not to close a buffer that has recently been displayed, so as long as there's view-switching activity, killing of the buffer is delayed.
Now I use this in my ~/.emacs:
(run-with-idle-timer 60 t (lambda ()
(let ((victim (get-buffer "XXX.gpg")))
(when victim (message "Killing buffer %s" (buffer-name victim)
(kill-buffer victim))))))
Related
How to kill all buffers with buffer file in a certain location?
For example, I want kill all buffers with buffer file in c:...\dev and all dired buffer subdir to c:...\dev
Or in others words, how to go though the files or dirs of all buffers in emacs?
Thanks #David #phils. I combined the elisp code and function in ibuffer
(mapc (lambda (buffer)
(let ((file-name
(or (buffer-file-name buffer)
(with-current-buffer buffer
(and
(boundp 'dired-directory)
(stringp dired-directory)
dired-directory))
)))
(when (and file-name
(string-match "^c:.*?\\\\dev" file-name))
(kill-buffer buffer))))
(buffer-list))
From elisp use:
(mapc (lambda (buffer)
(let ((file-name
(or (buffer-file-name buffer)
;; In dired-mode we need `dired-directory' which
;; might be a list and may not be fully expanded.
(with-current-buffer buffer
(and (eq major-mode 'dired-mode)
(expand-file-name
(if (consp dired-directory)
(car dired-directory)
dired-directory)))))))
(when (and file-name
(string-match "^c:\\\\.*\\\\dev" file-name))
(kill-buffer buffer))))
(buffer-list))
Any ideas regarding how to configure Wanderlust to open emails in a new buffer, instead of a split window? There is just too much happening with four (4) windows -- summary message buffer; message buffer; big brother insidious database address manager; and the mini-buffer. (See the screenshot below.)
I think I've located the relevant portion of the code in wl-message.el, but I'm not sure what portion to change. (setq wl-message-window-size '(1 . 1)) in the init.el is not what I'm looking for, because I'd still have to share the screen with other buffers.
I'm spending a lot of time switching and closing windows to get a full size buffer, and I'm hoping to just eliminate multiple windows when checking my e-mail.
Thanks . . . any help would be greatly appreciated.
;;; wl-message.el -- Message buffer handling from summary buffer.
(defun wl-message-buffer-window ()
"Get message buffer window if any."
(let* ((start-win (selected-window))
(cur-win start-win))
(catch 'found
(while (progn
(setq cur-win (next-window cur-win))
(with-current-buffer (window-buffer cur-win)
(if (or (eq major-mode 'wl-message-mode)
(eq major-mode 'mime-view-mode))
(throw 'found cur-win)))
(not (eq cur-win start-win)))))))
(defun wl-message-select-buffer (buffer)
"Select BUFFER as a message buffer."
(let ((window (get-buffer-window buffer))
(sum (car wl-message-window-size))
(mes (cdr wl-message-window-size))
whi)
(when (and window
(not (eq (with-current-buffer (window-buffer window)
wl-message-buffer-cur-summary-buffer)
(current-buffer))))
(delete-window window)
(run-hooks 'wl-message-window-deleted-hook)
(setq window nil))
(if window
(select-window window)
(when wl-fixed-window-configuration
(delete-other-windows)
(and wl-stay-folder-window
(wl-summary-toggle-disp-folder)))
;; There's no buffer window. Search for message window and snatch it.
(if (setq window (wl-message-buffer-window))
(select-window window)
(setq whi (1- (window-height)))
(if mes
(progn
(let ((total (+ sum mes)))
(setq sum (max window-min-height (/ (* whi sum) total)))
(setq mes (max window-min-height (/ (* whi mes) total))))
(if (< whi (+ sum mes))
(enlarge-window (- (+ sum mes) whi)))))
(split-window (get-buffer-window (current-buffer)) sum)
(other-window 1)))
(switch-to-buffer buffer)))
(source: lawlist.com)
SOLUTION # 1: The variable wl-message-buffer-name that is defined within wl-vars.el makes the message buffer uninteresting by virtue of the space at the beginning of the buffer name: *WL:Message*. Inasmuch as Emacs hides uninteresting buffers by default, one solution is to modify the aforementioned variable by removing the space at the beginning of the buffer name. That way, the buffer is always visible and it is just a matter of switching to the window that displays the message and then delete-other-windows. The added advantage is that it is no longer necessary to return to the summary buffer to view an e-mail that has already been opened, since there is already an open buffer dedicated to said e-mail.
(defcustom wl-message-buffer-name "*WL:Message*" ;; " *WL:Message*"
"*Buffer name for message buffers."
:group 'wl-pref
:group 'wl-setting)
SOLUTION # 2: This second solution is no longer the preferred method and will most likely be removed entirely from this answer. The word search utility I was using could not comb the wl-vars.el file for some unknown reason, so this second solution was a workaround.
Edit the key map for wl-summary-read (inside wl-summary.el) and replace it with the function lawlist-wl-summary-read so that hitting the space bar activates said function. wl-summary-enter-handler remains defined as the enter key, which opens messages in the default manner.
(define-key wl-summary-mode-map " " 'lawlist-wl-summary-read)
(defun lawlist-wl-summary-read nil
"Clone the the buffer and make new buffer name unique."
(interactive)
(wl-summary-enter-handler)
(windmove-down)
(let ((n 0)
bufname)
(while (progn
(setq bufname (concat "email"
(if (= n 0) "" (int-to-string n))
"")) ;; could be an ending, like an asterick *
(setq n (1- n)) ;; if + instead of -, then no hyphen and no space between buffer name and the number
(get-buffer bufname)))
(clone-indirect-buffer bufname nil)
(switch-to-buffer bufname)
(delete-other-windows) ))
I'd like to copy the region to another (temporary) buffer in Emacs, but if there's no (acive) region, I'd like to copy the whole current buffer. What I did is as follows:
(defun do-something-with-region-or-buffer ()
(interactive)
(save-excursion
(let ((begin (point-min)) (end (point-max)))
(when (region-active-p)
(setq begin (region-beginning))
(setq end (region-end)))
(copy-region-as-kill begin end)
(with-temp-buffer
(switch-to-buffer (current-buffer))
(rename-buffer "*My Temp Buffer*")
(delete-other-windows)
(yank)
(do-something-with-current-buffer)))))
However, I have a strong feeling that this is suboptimal, since I'm messing around with the kill ring. How to do it without affecting it? (Bonus question: is my way of doing things with the region or the whole buffer if there's no active region a good one?)
That's how I would do it:
(defun aak/dswrob ()
(interactive)
(let* ((regionp (region-active-p))
(beg (and regionp (region-beginning)))
(end (and regionp (region-end)))
(buf (current-buffer)))
(with-temp-buffer
(switch-to-buffer (current-buffer) nil t)
(rename-buffer "*My Temp Buffer*" t)
(insert-buffer-substring buf beg end)
(read-key-sequence "Keys?"))))
It's up to you to decide if you want insert-buffer-substring or
insert-buffer-substring-no-properties, but there is no need to use
kill rings.
Also it's rather strange to do something interactively within
with-temp-buffer: are you going to run a kind of modal loop there,
or is it just displaying some progress?
As of doing things with the region or the whole buffer (NB: modulo
narrowing), it's not quite unusual (see replace-string and
friends).
I use the Emacs desktop module to save my open buffers between sessions. However I found that this accumulates more buffers than I want, so I wrote a small function to clean up the buffer list immediately before saving to the desktop file. This works as expected, but for strange reasons the .emacs.desktop gets scrambled occasionally, i.e. it contains a part of another buffer at its start, then the intended contents and then the result of the other buffer. I don't have the slightest idea, why this happens. Here is an excerpt from my .emacs file:
(defun kill-old-buffers ()
"Kill buffers from end of buffer list (not used recently) until no more than 50 buffers are left. Remove temporary buffers first"
(interactive)
(let* (desktop-buffer (current-buffer))
(dolist (buffer (buffer-list))
(if (or (string-match "^\*" (buffer-name buffer)) (string-match "\.hpp$" (buffer-name buffer)))
(kill-buffer buffer)
)
)
(setq all-buffers (reverse (buffer-list)))
(while (> (safe-length all-buffers) 50)
(setq buffer (pop all-buffers))
(if (not (string-equal (buffer-name buffer) (buffer-name (current-buffer))))
(kill-buffer buffer)
)
)
(switch-to-buffer desktop-buffer)
))
;; Kill old rarely-used buffers before saving
(add-hook 'desktop-save-hook
'(lambda () (kill-old-buffers)))
Any help would be appreciated.
I'm not sure if your function is really the cause of your problem. If it should be the case, the wrong usage of the let* that scottfrazer pointed out might be the cause. But you don't even need that let* (and switch-to-buffer) at all, because
what you're trying to do is better done with Emacs' built in save-excursion, and
you aren't actually switching the buffer ever.
OTOH, you should have used let instead of the setqs in the lower half of your function, because setq will otherwise change a variable from an enclosing lexical scope. In this case you might very well have stomped over a buffer variable from the function that's executing the desktop-save-hook which is another potential cause of your problem.
But you don't need those lets either because you can do the second loop with another dolist. You can get rid of those first 50 buffers that you don't want to loop over with nthcdr.
Here's my improved version of kill-old-buffers:
(defun kill-old-buffers ()
"Kill buffers from end of buffer list (not used recently) until
no more than 50 buffers are left. Remove temporary buffers first."
(interactive)
(save-excursion
(dolist (buffer (buffer-list))
(if (or (string-match "^\*" (buffer-name buffer))
(string-match "\.hpp$" (buffer-name buffer)))
(kill-buffer buffer)))
(dolist (buffer (reverse (nthcdr 50 (buffer-list))))
(unless (eq buffer (current-buffer))
(kill-buffer buffer)))))
It may not fix all your problems, but for starters you need another set of parens around the variable in your let* statement
(let* ((desktop-buffer (current-buffer)))
When I use grep-find it opens another window (area in the frame) with a list of results that I can select. When I select one it opens the target file in a different window than grep-find is in.
How can I get the target file to open in the same window as the grep results (replacing the grep results window with what I am actually looking for).
How can I keep grep-find from opening a separate window (have it so it opens in the current window). My goal is I look for something, I find it, I go to it, all within the same window. I would like to add this to my .emacs file.
It doesn't look like there is any way to configure the compile package to do what you're asking. And there's no easy way to use advice to tweak the behavior. I think you have to resort to editing the function which actually jumps to the error, which you can do with the following addition to your .emacs (tested in Emacs 23.1):
(eval-after-load "compile"
'(defun compilation-goto-locus (msg mk end-mk)
"Jump to an error corresponding to MSG at MK.
All arguments are markers. If END-MK is non-nil, mark is set there
and overlay is highlighted between MK and END-MK."
;; Show compilation buffer in other window, scrolled to this error.
(let* ((from-compilation-buffer (eq (window-buffer (selected-window))
(marker-buffer msg)))
;; Use an existing window if it is in a visible frame.
(pre-existing (get-buffer-window (marker-buffer msg) 0))
(w (if (and from-compilation-buffer pre-existing)
;; Calling display-buffer here may end up (partly) hiding
;; the error location if the two buffers are in two
;; different frames. So don't do it if it's not necessary.
pre-existing
(let ((display-buffer-reuse-frames t)
(pop-up-windows t))
;; Pop up a window.
(display-buffer (marker-buffer msg)))))
(highlight-regexp (with-current-buffer (marker-buffer msg)
;; also do this while we change buffer
(compilation-set-window w msg)
compilation-highlight-regexp)))
;; Ideally, the window-size should be passed to `display-buffer' (via
;; something like special-display-buffer) so it's only used when
;; creating a new window.
(unless pre-existing (compilation-set-window-height w))
(switch-to-buffer (marker-buffer mk))
;; was
;; (if from-compilation-buffer
;; ;; If the compilation buffer window was selected,
;; ;; keep the compilation buffer in this window;
;; ;; display the source in another window.
;; (let ((pop-up-windows t))
;; (pop-to-buffer (marker-buffer mk) 'other-window))
;; (if (window-dedicated-p (selected-window))
;; (pop-to-buffer (marker-buffer mk))
;; (switch-to-buffer (marker-buffer mk))))
;; If narrowing gets in the way of going to the right place, widen.
(unless (eq (goto-char mk) (point))
(widen)
(goto-char mk))
(if end-mk
(push-mark end-mk t)
(if mark-active (setq mark-active)))
;; If hideshow got in the way of
;; seeing the right place, open permanently.
(dolist (ov (overlays-at (point)))
(when (eq 'hs (overlay-get ov 'invisible))
(delete-overlay ov)
(goto-char mk)))
(when highlight-regexp
(if (timerp next-error-highlight-timer)
(cancel-timer next-error-highlight-timer))
(unless compilation-highlight-overlay
(setq compilation-highlight-overlay
(make-overlay (point-min) (point-min)))
(overlay-put compilation-highlight-overlay 'face 'next-error))
(with-current-buffer (marker-buffer mk)
(save-excursion
(if end-mk (goto-char end-mk) (end-of-line))
(let ((end (point)))
(if mk (goto-char mk) (beginning-of-line))
(if (and (stringp highlight-regexp)
(re-search-forward highlight-regexp end t))
(progn
(goto-char (match-beginning 0))
(move-overlay compilation-highlight-overlay
(match-beginning 0) (match-end 0)
(current-buffer)))
(move-overlay compilation-highlight-overlay
(point) end (current-buffer)))
(if (or (eq next-error-highlight t)
(numberp next-error-highlight))
;; We want highlighting: delete overlay on next input.
(add-hook 'pre-command-hook
'compilation-goto-locus-delete-o)
;; We don't want highlighting: delete overlay now.
(delete-overlay compilation-highlight-overlay))
;; We want highlighting for a limited time:
;; set up a timer to delete it.
(when (numberp next-error-highlight)
(setq next-error-highlight-timer
(run-at-time next-error-highlight nil
'compilation-goto-locus-delete-o)))))))
(when (and (eq next-error-highlight 'fringe-arrow))
;; We want a fringe arrow (instead of highlighting).
(setq next-error-overlay-arrow-position
(copy-marker (line-beginning-position)))))))
The eval-afer-load portion just ensures that you re-define it after Emacs defined it, so that your change takes hold.
You can add a binding (e.g. Alt-m) and do the following
(define-key grep-mode-map "\M-m" (lambda()
(interactive)
(compile-goto-error)
(delete-other-windows)
(kill-buffer "*grep*")))
I didn't find a way to replace the standard "Enter" / Mouse-click binding with a custom function
There is an another approach:
(defun eab/compile-goto-error ()
(interactive)
(let ((cwc (current-window-configuration)))
(funcall
`(lambda ()
(defun eab/compile-goto-error-internal ()
(let ((cb (current-buffer))
(p (point)))
(set-window-configuration ,cwc)
(switch-to-buffer cb)
(goto-char p ))))))
(compile-goto-error)
(run-with-timer 0.01 nil 'eab/compile-goto-error-internal))
I had the same question, and found this answer over at emacs.stackexchange https://emacs.stackexchange.com/a/33908/20000
(defun my-compile-goto-error-same-window ()
(interactive)
(let ((display-buffer-overriding-action
'((display-buffer-reuse-window
display-buffer-same-window)
(inhibit-same-window . nil))))
(call-interactively #'compile-goto-error)))
(defun my-compilation-mode-hook ()
(local-set-key (kbd "o") #'my-compile-goto-error-same-window))
(add-hook 'compilation-mode-hook #'my-compilation-mode-hook)
Pressing o in the *grep* buffer will open the location and file in the same frame.
I found this an elegant solution without deleting frames or too much lisp code and just hooking into compilation-mode-hook.