Iswitchb ignore dired buffer - emacs

Is there any way to tell iswitchb to ignore buffers based on mode not string? I would like to exclude the buffers opened in dired mode which are very often the most numerous and it's hard to find opened files in minibuffer among them. Any help on this would be appreciated.

You can add a custom function to iswitchb-buffer-ignore to do this. There is actually an example in iswitchb.el -- based on that, this will do the trick:
(defun iswitchb-ignore-dired-mode (name)
"Ignore all dired mode buffers."
(with-current-buffer name
(derived-mode-p 'dired-mode)))
(setq iswitchb-buffer-ignore '("^ " iswitchb-ignore-dired-mode))
This preserves the default behavior of ignoring buffer names that begin with a space, and adds the filter for dired-mode buffers.

Based on a similar example in the iswitchb source code:
(defun iswitchb-ignore-dired-buffers (buffer)
(with-current-buffer buffer
(eq major-mode 'dired-mode)))
(add-to-list 'iswitchb-buffer-ignore 'iswitchb-ignore-dired-buffers)

Related

How to make a buffer-local key binding in Emacs?

I've been working on an Emacs minor mode lately and part of its functionality was displaying images in separate buffers. So far I've been using a function like this:
(defun create-buffer-with-image (name)
(let ((buffer (generate-new-buffer name))
(image (get-svg-for-kanji-code name)))
(switch-to-buffer buffer)
(turn-on-iimage-mode)
(iimage-mode-buffer t)
(insert-image image)))
and it produces a buffer with the image passed as argument, but closing the buffer requires hitting C-x k and Return, which started to get cumbersome after a while. The way to simplify closing of such transient buffers would be to have a key binding for the kill-this-buffer function, but it would need to be buffer-specific, so as not to mess up anything else. The question is how to make such a binding with the creation of a buffer.
From EmacsWiki: https://www.emacswiki.org/emacs/BufferLocalKeys
For buffer-local keys, you cannot use local-set-key, unless you want to modify the keymap of the entire major-mode in question: local-set-key is local to a major-mode, not to a buffer.
For buffer-local modifications, use this instead:
(use-local-map (copy-keymap foo-mode-map))
(local-set-key "d" 'some-function)
Written by:  TiagoSaboga
To inspect the change, type C-h b aka M-x describe-bindings
I'd suggest you add a call to special-mode after the call to switch-to-buffer.
In the longer run, you'll want to use your own major mode, so you'd do:
(define-derived-mode my-image-mode special-mode "MyImage"
"My own major mode to display images."
;; We could add more things here
)
(defun create-buffer-with-image (name)
(with-current-buffer (generate-new-buffer name)
(my-image-mode)
(let ((image (get-svg-for-kanji-code name)))
(turn-on-iimage-mode)
(iimage-mode-buffer t)
(insert-image image)
(pop-to-bffer (current-buffer)))))
I was a bit mislead by some posts on the web suggesting the use of local-key-binding, but somehow it did not work for me - when the image was displayed and I examined the key bindings, my choice of q was not in effect. After some experimentation and digging through elisp references I found that I needed to use local-set-key. So now my function looks like this:
(defun create-buffer-with-image (name)
(let ((buffer (generate-new-buffer name))
(image (get-svg-for-kanji-code name)))
(switch-to-buffer buffer)
(local-set-key (kbd "q") 'kill-this-buffer)
(turn-on-iimage-mode)
(iimage-mode-buffer t)
(insert-image image)))
and the newly created image buffer can easily be closed by pressing q.
Create a minor mode:
(define-minor-mode my-mode "my doc" nil nil (make-sparse-keymap))
Then you can use this mode's my-mode-map to define your keybindings. Activate the mode with (my-mode).

Exclude "hated buffers" from switch-to-buffer list

I have this in my .emacs:
(global-set-key "\M-s" 'switch-to-buffer)
And also:
(defvar crs-hated-buffers
'("KILL" "*Compile-Log*" "*Buffer List*" "*Messages*" "*Occur*"
"*Completions*" "*compilation*" "TAGS" "*scratch*" "*grep*"
"source" "headers"))
(setq iswitchb-buffer-ignore (append '(
"^ "
"^\\*Buffer"
"^\\*Completions\\*"
"^\\*tramp"
"^\\*Dired log\\*"
"^\\*Quail Completions\\*"
"^\\*Disabled Command\\*"
"^TAGS"
)
crs-hated-buffers))
How do I exclude these hated buffers from the switch-to-buffer list?
Maybe something like:
(global-set-key [?\M-s] 'my-switch-to-buffer)
(defun my-switch-to-buffer ()
(interactive)
(let ((completion-regexp-list '("\\`[^*]"
"\\`\\([^T]\\|T\\($\\|[^A]\\|A\\($\\|[^G]\\|G\\($\\|[^S]\\|S.\\)\\)\\)\\).*")))
(call-interactively 'switch-to-buffer)))
It probably deserves a feature-request via M-x report-emacs-bug.
You might have a look to ErgoEmacs' "switch to user buffer" functions: http://www.ergoemacs.org/emacs/elisp_next_prev_user_buffer.html
He excludes all internal buffers (the ones starting by *), which can be a problem if you're used to using magit, shell or even grep buffers.
«Emacs often generates a lot internal buffers that users are not interested in cycling thru. ⁖ {scratch, Messages, shell, Shell Command Output, Occur, Completions, Apropos, info, …}. You might define your own next-user-buffer that skips emacs's buffers, and you might define next-emacs-buffer that cycles thru just the emacs's buffers.
»
I myself find I don't need that kind of filter since I use ido to switch buffers.

Close all temporary buffers automatically in emacs

How can we close temporary buffers which are enclosed with * automatically. For e.g. messages, completions buffer needs to be closed. Killing all these buffers manually after use is painful.
Is there a way to close temporary buffers created by emacs (not by us)?
Do you really need to close those buffers? If you use a proper buffer switching method like iswitchb then you don't have to care about temporary or other buffers, because you can go directly to any buffer you want.
I'd second the suggestion you use ido or iswitchb to avoid being bothered by temporary buffers. The presence of those buffers is a natural consequence of using emacs, so don't try to swim upstream!
On the other hand, if you're irritated by the growing list of open buffers, you can use midnight.el to automatically close inactive buffers after a period of time, or you can use ibuffer to easily select and close unwanted buffers en masse.
Personally, I leave buffers open for a long time, I tidy them up occasionally using ibuffer, and I rely on ido to switch buffers quickly. In Emacs 24, you can set ido-use-virtual-buffers to t, and then ido will let you switch to closed files, reopening them as necessary.
To avoid having those buffers in your way, you could define key-bindings to cycle through «user buffers» and «useless buffers» :
http://ergoemacs.org/emacs/effective_emacs.html , section «Switching Next/Previous User Buffers»
but some useful buffers start with a *, like shells, compilation buffer, ielm, etc.
As user said, it would be better to use a smart buffer-switching package such as iswitchb and ido. iswitchb's iswitchb-buffer-ignore and ido's ido-ignore-buffers variables allow us to specify what buffers to ignore using regular expressions.
However, if you really want to kill those buffers, a program like this will be helpful to you:
(require 'cl)
(defvar kill-star-buffers-except
'("\\`\\*scratch\\*\\'"
"\\`\\*Messages\\*\\'"
"\\` \\*Minibuf-[[:digit:]]+\\*\\'"
"\\` \\*Echo Area [[:digit:]]+\\*\\'")
"Exception list for `kill-star-buffers'")
(defun kill-star-buffers ()
"Kill all star buffers except those in `kill-star-buffers-except'"
(interactive)
(mapc (lambda (buf)
(let ((buf-name (buffer-name buf)))
(when (and
;; if a buffer's name is enclosed by * with optional leading
;; space characters
(string-match-p "\\` *\\*.*\\*\\'" buf-name)
;; and the buffer is not associated with a process
;; (suggested by "sanityinc")
(null (get-buffer-process buf))
;; and the buffer's name is not in `kill-star-buffers-except'
(notany (lambda (except) (string-match-p except buf-name))
kill-star-buffers-except))
(kill-buffer buf))))
(buffer-list)))

emacs: interactively search open buffers

Is there a way to search all the open buffers for a particular pattern?
C-s interactively searches current buffer.
Similarly, is there something that searches all the open buffers?
I know I can use "occur", but "Occur" brings a new buffer and changes/messes with the buffer organization.
The built-in multi-occur-in-matching-buffers hasn't been mentioned. I use a modified version of this (because I invariably want to search all buffers, and specifying a buffer name pattern each time is annoying).
(defun my-multi-occur-in-matching-buffers (regexp &optional allbufs)
"Show lines matching REGEXP in all file-visiting buffers.
Given a prefix argument, search in ALL buffers."
(interactive (occur-read-primary-args))
(multi-occur-in-matching-buffers "." regexp allbufs))
(global-set-key (kbd "M-s /") 'my-multi-occur-in-matching-buffers)
To invert the behaviour of the prefix argument so that the default behaviour is to search all buffers, change the call to:
(multi-occur-in-matching-buffers "." regexp (not allbufs))
(and, of course, update the docstring accordingly.)
I've fixed the TODO:
;; I know that string is in my Emacs somewhere!
(require 'cl)
(defcustom search-all-buffers-ignored-files (list (rx-to-string '(and bos (or ".bash_history" "TAGS") eos)))
"Files to ignore when searching buffers via \\[search-all-buffers]."
:type 'editable-list)
(require 'grep)
(defun search-all-buffers (regexp prefix)
"Searches file-visiting buffers for occurence of REGEXP. With
prefix > 1 (i.e., if you type C-u \\[search-all-buffers]),
searches all buffers."
(interactive (list (grep-read-regexp)
current-prefix-arg))
(message "Regexp is %s; prefix is %s" regexp prefix)
(multi-occur
(if (member prefix '(4 (4)))
(buffer-list)
(remove-if
(lambda (b) (some (lambda (rx) (string-match rx (file-name-nondirectory (buffer-file-name b)))) search-all-buffers-ignored-files))
(remove-if-not 'buffer-file-name (buffer-list))))
regexp))
(global-set-key [f7] 'search-all-buffers)
ibuffer might help you. Have a look at this article. I imagine that this might be most interesting for you:
'O' - ibuffer-do-occur
- Do an occur on the selected buffers.
This does a regex search on all the selected buffers and displays the result in an occur window. It is unbelievably useful when browsing through code. It becomes truly awesome when you combine it with the ‘filter’ powers of ibuffer (coming up ahead). Eg: Do C-x C-b, mark all files using (say) Perl major-mode, do occur to find out all places where a certain function is mentioned in these files. Navigate to the point at will through the Occur window.
'M-s a C-s' - ibuffer-do-isearch
- Do an incremental search in the marked buffers.
This is so awesome that you have to try it right this instant. Select two or more buffers, hit the hotkey, search for something that occurs in all these buffers. These two features alone are enough to make me a lifelong fan of IBuffer. Go do it now!
Taking a clue from Leo's comment to Bozhidar:
(defun my-isearch-buffers ()
"isearch multiple buffers."
(interactive)
(multi-isearch-buffers
(delq nil (mapcar (lambda (buf)
(set-buffer buf)
(and (not (equal major-mode 'dired-mode))
(not (string-match "^[ *]" (buffer-name buf)))
buf))
(buffer-list)))))
You might have to tweak the conditions inside the and to filter whatever other kinds of buffers you want to ignore.
Although this is not exactly what you're asking for, I search multiple files using grep (M-X grep) and grep-find (M-X grep-find).
This sort of does what you want, in that when you've come to the end of matches for the string/regexp you're searching for, the next search command will start in a new buffer.
(setq isearch-wrap-function 'isearch-bury-buffer-instead-of-wrap)
(defun isearch-bury-buffer-instead-of-wrap ()
"bury current buffer, try to search in next buffer"
(bury-buffer))
It doesn't switch to a different buffer when the search fails, and when you "back up" the search results by pressing <backspace>, you won't pop back into the previous buffers searched.
In Icicles, C-c ' is command icicle-occur, which can search multiple buffers.
C-u C-c ' searches a set of buffers that you choose. You can choose by dynamically filtering the buffer names with your minibuffer input, then hit C-! to search all of those buffers whose names match. Similarly, C-99 C-c ' searches only the buffers that are visiting files.
Like occur and grep, icicle-occur searches line by line. More generally, instead of using lines as the search contexts you can use any buffer portions at all. C-c ` (backquote instead of quote) is command icicle-search. With a non-negative prefix arg it searches a set of buffers that you choose.
The first thing you do is give it a regexp that defines the search contexts. E.g., if you give it .* then it acts like icicle-occur: each search context is a line. If you give it a regexp that matches only function definitions then those are the search contexts, and so on.
http://www.emacswiki.org/emacs/Icicles_-_Search_Commands%2c_Overview

How to get equivalent of Vim's :Texplore in Emacs?

I know about M-x dire, but would like to customize it. I would like to hit one key (for example F2) and get dire buffer open. When I navigate across the directory hierarchy it shouldn't open new buffers.
And when I finally open the file it also shouldn't open new buffer for it (not strictly necessary, but strongly preferred).
Of course this behavior can be global, i.e. for all dire buffers/invocations.
Check out dired-single, which pretty much does what you want (except that last bit, where it reuses the dired buffer for the newly visted file).
Caveat Lector: I wrote it, so I'm biased towards its usefulness.
Some alternatives - EmacsWiki: DiredReuseDirectoryBuffer, and this short snippet from an awkwardly-formatted blog-entry.
caveat: haven't tried them, myself.
I know this is very old but All you have to do is press 'a' on a dir or file to get this functionality. It's already there.
Here's what I finally used:
(require 'dired)
(global-set-key [(f2)] 'my-dired)
(defun my-dired ()
(interactive)
(dired (file-name-directory (buffer-file-name))))
(defadvice dired-advertised-find-file (around dired-subst-directory activate)
"Replace current buffer if file is a directory."
(interactive)
(let ((orig (current-buffer)) (filename (dired-get-filename :no-error-if-not-filep t)))
ad-do-it
(when (not (eq (current-buffer) orig)) (kill-buffer orig))))