Running keep-lines command on all opened buffers in emacs - emacs

I have many files opened in emacs buffers. Now I want to run keep-lines command on all this opened buffer.
What is steps for doing this?
I am using emacs version 24.3.

Iterate over all opened buffers: Use dolist to iterate over buffer-list (or any suitable subset you like). Use with-current-buffer for the current iteration's buffer, and call keep-lines inside that.
You can tweak it to have more flexibility (e.g., in the keep-lines call):
(defun foo (regexp)
(interactive (list (read-regexp "Regexp: ")))
(dolist (buf (buffer-list))
(goto-char (point-min)) ; Is this what you want, to start at bob?
(with-current-buffer buf (keep-lines regexp))))
However, buffer-list returns many buffers that you probably do not want to do this to. Filter it as needed, e.g., using remove-if (in cl-lib.el) or whatever.
If you deal only with file buffers, then you might want to use find-file-noselect. There are multiple possibilities, depending on what you really need.
You can practice with something like this:
(defun foo (regexp)
(interactive (list (read-regexp "Regexp: ")))
(dolist (buf (buffer-list))
(with-current-buffer buf
(when (y-or-n-p (format "Do it to `%s'? " buf))
(goto-char (point-min))
(keep-lines regexp)))))
And then you might want to think about whether you also want to save the modified buffer, etc.

For a more manually-controlled approach, you might use ibuffer:
M-x ibuffer RET
Mark some buffers
E (keep-lines "pattern") RET
Or, as per Drew's suggestion, (progn (goto-char (point-min)) (keep-lines "pattern"))
You can mark buffers using lots of different criteria in ibuffer. Browse the "Mark" menu, and see C-hm for details.

Related

elisp: Handling wrong-type-argument exception

I want to kill all buffers visiting a file in a given directory, keeping all others. However, my function bombs out when it reaches the #<buffer *Minibuf-1*>; the minibuffer isn't visiting a file.
(defun my-kill-all-visiting-buffers (dir)
"Kill all buffers visiting DIR."
(interactive)
(mapcar
(lambda (buf)
(and (string-match-p
(regexp-quote dir)
(file-name-directory (buffer-file-name buf)))
(kill-buffer buf)))
(buffer-list)))
In Python-land, I would ask for forgiveness and wrap it in a try-except. How would I handle this in the land of lisp?
You could handle the exception with something like condition-case which elisp has. Or you could just do something like this (avoiding the regexp-quotery as well):
(defun my-kill-all-visiting-buffers (dir)
"Kill all buffers visiting DIR or any subdirectory of DIR"
(interactive "Ddirectory: ")
(mapc
(lambda (buf)
(let ((bfn (buffer-file-name buf)))
(when (and (not (null bfn))
(file-in-directory-p bfn dir))
(kill-buffer buf))))
(buffer-list)))
There are probably better approaches.
Notes
(not (null x)) is the same as x but I use it intentionally so when I read it I know I am checking for x not being a conceptually void value, rather than it just being false.
This avoids regexp operations (originally string= now string-prefix-p), because, famously:
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
Instead it uses file-in-directory-p which asks exactly the question it wants the answer to: is file in a directory or any subdirectory of dir? (Thanks to Stefan for this, which I didn't know about.)
All of the above is legal in Emacs 26.2: I don't keep track of which things in elisp changed & arrived when any more.
Elisp is not that close to many other dialects of Lisp in use other than rather superficially: techniques which are used in elisp may or may not apply to other languages in the family but often don't.
I found that it wasn't necessary to catch all possible errors. Handling the case where a buffer is not associated with a file is sufficient.
The use of regexp-quote is used to handle closing files in subdirectories.
(defun my-kill-all-visiting-buffers (dir)
"Kill all buffers visiting DIR."
(interactive)
(mapcar
(lambda (buf)
(let ((bfn (buffer-file-name buf)))
(and (not (null bfn))
(string-match-p (regexp-quote dir) (file-name-directory bfn))
(kill-buffer buf))))
(buffer-list)))

ggtags find-definition/reference with IDO interface

I dont like default ggtags interface around ggtags-find-definition/reference/file. I managed to get ggtags-find-file work with IDO, but ggtags-find-definition is a lot harder problem.
Is there some package which can do it? If not, how to make one?
NOTE: I want to be able to browse found definitions/references in fuzzy minibuffer, not whole new buffer (and window).
Normally, I would suggest ido-completing-read-plus (formerly ido-ubiquitous). It makes almost every command that uses completing-read use ido-completing-read instead. However, there is one major case where it doesn't work well: when the completion candidates are generated by a function. This is the case for ggtags-completion-table, which is how ggtags generates its completion candidates.
The solution is to define your own ggtags-completing-read-function that expands the candidates before passing to ido-completing-read. Note: the reason why ido-completing-read (and in turn ido-completing-read-plus) doesn't allow this is because it might use a ton of memory and CPU, and may freeze the UI. You will probably need to tune this to make it acceptable if you have a large number of completion candidates. Also note that most ggtags commands work with the symbol at point; it seems like you generally just give a prefix arg (C-u) to make it prompt for the symbol.
(defun jpk/ggtags-completing-read (&rest args)
(apply #'ido-completing-read
(car args)
(all-completions "" ggtags-completion-table)
(cddr args)))
(setq ggtags-completing-read-function #'jpk/ggtags-completing-read)
Assuming that you ran ggtags-find-definition and it found results and put them in the buffer *ggtags-global*, this function will extract the filenames and line numbers and let you use IDO to pick the one you want.
(defun ido-goto-grep-results (grep-buffer prompt)
(interactive)
(let (candidates result filename dirname line)
(with-current-buffer grep-buffer
(setq dirname default-directory)
(save-excursion
(save-match-data
(goto-char (point-min))
(forward-line 4)
(while (re-search-forward "^\\(.+\\):\\([0-9]+\\):" nil 'noerror)
(push (concat (match-string 1) ":" (match-string 2))
candidates)))))
(setq result (split-string (ido-completing-read prompt candidates nil t) ":"))
(setq filename (car result))
(setq line (string-to-number (cadr result)))
(find-file-other-window (expand-file-name filename dirname))
(goto-char (point-min))
(forward-line (1- line))))
(ido-goto-grep-results "*ggtags-global*" "Jump to definition: ")
This is pretty rough. You probably want to make your own find-definition command that runs ggtags-find-definition and ido-goto-grep-results at once. Somehow you need to only get the actual results and not the "Global found N definitions..." line (better regexp, narrow the ggtags buffer, or some other way).

Emulate dabbrev-expand in hippie-expand, limiting to matching buffers

If I use dabbrev-expand for expansion, Emacs searches the current buffer, then other buffers with the same mode. This is handled by dabbrev-friend-buffer-function which by default is set to dabbrev--same-major-mode-p.
This works fine, but I'd like to use hippie-expand.
(setq hippie-expand-try-functions-list
'(try-expand-dabbrev
try-expand-dabbrev-all-buffers))
This pulls completions from all buffers, even the buffers that don't match my current major mode.
How can I use hippie-expand with dabbrev completions only coming from buffers using the same major-mode as the current buffer?
Quick and dirty solution: Copy the source code of the function try-expand-dabbrev-all-buffers to a new location, rename it (say) try-expand-dabbrev-all-buffers-same-mode, and replace the expression (buffer-list) with the expression:
(remove-if-not (lambda (x) (eq major-mode (with-current-buffer x major-mode)))
(buffer-list))
(You'll need to (require 'cl) to get remove-if-not, or else re-implement it in terms of mapcar and delq.)
Then, of course, replace try-expand-dabbrev-all-buffers with try-expand-dabbrev-all-buffers-same-mode in hippie-expand-try-functions-list.
You can get the source of try-expand-dabbrev-all-buffers using C-hf.
Based on Sean's excellent suggestion (and assuming you have the dash.el list utility library installed):
(autoload '--filter "dash" nil t)
;; only consider buffers in the same mode with try-expand-dabbrev-all-buffers
(defun try-expand-dabbrev-matching-buffers (old)
(let ((matching-buffers (--filter
(eq major-mode (with-current-buffer it major-mode))
(buffer-list))))
(flet ((buffer-list () matching-buffers))
(try-expand-dabbrev-all-buffers old))))

How to modify the contents of all the alive buffers in emacs lisp

I am planning on the following steps to get the output of the question.
get the list of buffers and iterate on it
get the contents of the buffers using the buffer name obtained in step 1.
change the contents and overwrite the buffer.
The (buffer-list) fn output is very confusing. It shows like
(# ...)
I dont understand what does # < and * stands for.
The output of buffer-list is a list of buffer objects.
Functions dealing with a specific buffer will typically accept a buffer object as an argument:
(buffer-name (car (buffer-list)))
The #<...> syntax is explained here:
M-: (info "(elisp) Printed Representation") RET
I can't imagine why you'd want to modify all buffers (remember this includes the minibuffer, possibly some internal-use buffers, various others like *Help*, *Messages*, and maybe some read-only buffers), but you could use the following as the basis:
(let ((buffers (buffer-list)))
(while (car buffers)
(set-buffer (car buffers))
(let ((contents (save-restriction (widen) (buffer-string))))
[do something with contents] )
(setq buffers (cdr buffers))))

Close all buffers besides the current one in Emacs

How do I close all but the current buffer in Emacs? Similar to "Close other tabs" feature in modern web browsers?
For a more manual approach, you can list all buffers with C-x C-b, mark buffers in the list for deletion with d, and then use x to remove them.
I also recommend replacing list-buffers with the more advanced ibuffer: (global-set-key (kbd "C-x C-b") 'ibuffer). The above will work with ibuffer, but you could also do this:
m (mark the buffer you want to keep)
t (toggle marks)
D (kill all marked buffers)
I also use this snippet from the Emacs Wiki, which would further streamline this manual approach:
;; Ensure ibuffer opens with point at the current buffer's entry.
(defadvice ibuffer
(around ibuffer-point-to-most-recent) ()
"Open ibuffer with cursor pointed to most recent buffer name."
(let ((recent-buffer-name (buffer-name)))
ad-do-it
(ibuffer-jump-to-buffer recent-buffer-name)))
(ad-activate 'ibuffer)
From EmacsWiki: Killing Buffers:
(defun kill-other-buffers ()
"Kill all other buffers."
(interactive)
(mapc 'kill-buffer
(delq (current-buffer)
(remove-if-not 'buffer-file-name (buffer-list)))))
Edit: updated with feedback from Gilles
There isn't a way directly in emacs to do this.
You could write a function to do this. The following will close all the buffers:
(defun close-all-buffers ()
(interactive)
(mapc 'kill-buffer (buffer-list)))
There is a built in command m-x kill-some-buffers (I'm using 24.3.50) In my nextstep gui (not tried in a terminal but sure it's similar) you can then approve which buffers to kill.
(defun only-current-buffer ()
(interactive)
(let ((tobe-killed (cdr (buffer-list (current-buffer)))))
(while tobe-killed
(kill-buffer (car tobe-killed))
(setq tobe-killed (cdr tobe-killed)))))
It works as you expected.
And after reading #Starkey's answer, I think this will be better:
(defun only-current-buffer ()
(interactive)
(mapc 'kill-buffer (cdr (buffer-list (current-buffer)))))
(buffer-list (current-buffer)) will return a list that contains all the existing buffers, with the current buffer at the head of the list.
This is my first answer on StackOverflow. Hope it helps :)
I found this solution to be the simplest one. This deletes every buffer except the current one. You have to add this code to your .emacs file
(defun kill-other-buffers ()
"Kill all other buffers."
(interactive)
(mapc 'kill-buffer (delq (current-buffer) (buffer-list))))
Of course, then you use it with M-x kill-other-buffers RET or you paste the following code in the .emacs file too and then just press C-xC-b
(global-set-key (kbd "C-x C-b") 'kill-other-buffers)
You can like this one as well - kill all buffers except current one, *Messages* and *scratch* (which are handy to have, I call them "toolkit"), close redundant windows as well, living you which one window which current buffer.
(defun my/kill-all-buffers-except-toolbox ()
"Kill all buffers except current one and toolkit (*Messages*, *scratch*). Close other windows."
(interactive)
(mapc 'kill-buffer (remove-if
(lambda (x)
(or
(eq x (current-buffer))
(member (buffer-name x) '("*Messages*" "*scratch*"))))
(buffer-list)))
(delete-other-windows))
I've use crux-kill-other-buffers for some months.
But I want dired buffers get deleted too. #Euge's and #wenjun.yan's answers solve this. But it will delete special buffers (e.g *git-credential-cache--daemon*, *scratch*, helm operation, and etc). So I came up with this (current) solution.
(defun aza-kill-other-buffers ()
"Kill all buffers but current buffer and special buffers"
(interactive)
(dolist (buffer (delq (current-buffer) (buffer-list)))
(let ((name (buffer-name buffer)))
(when (and name (not (string-equal name ""))
(/= (aref name 0) ?\s)
(string-match "^[^\*]" name))
(funcall 'kill-buffer buffer)))))
Inspired from kill-matching-buffers. You can add more condition on other buffer-name to exclude, if you want to.
Hope it helps :)
I've used one of the solutions in this list for years, but now I have a new one of my own.
(defun kill-all-file-buffers ()
"Kills all buffers that are open to files. Does not kill
modified buffers or special buffers."
(interactive)
(mapc 'kill-buffer (cl-loop for buffer being the buffers
when (and (buffer-file-name buffer)
(not (buffer-modified-p buffer)))
unless (eq buffer (current-buffer))
collect buffer)))
cl-loop has buffers built in as a collection that you can iterate over. It gives you a chance to parse out anything you don't want to close. Here, I've made sure that it doesn't close anything you've modified, and it uses buffer-file-name instead of just buffer-name so it doesn't kill special buffers. I also added an 'unless' to take out the current buffer (though you could obviously add it to the 'when', I just thought this was clearer).
But for an even more generic solution, we can define this as a macro, and pass in a function that will apply to all these buffers.
(defmacro operate-on-file-buffers (func)
"Takes any function that takes a single buffer as an argument
and applies that to all open file buffers that haven't been
modified, and aren't the current one."
`(mapc ,func (cl-loop for buffer being the buffers
when (and (buffer-file-name buffer)
(not (buffer-modified-p buffer)))
unless (eq buffer (current-buffer))
collect buffer)))
Now if you want to kill all buffers that match this, you can call it like this
(operate-on-file-buffers 'kill-buffer)
This is what you want:
C-x 1
source: https://blasphemousbits.wordpress.com/2007/05/04/learning-emacs-part-4-buffers-windows-and-frames/