Emacs filesets: how to run other (elisp, not shell) commands? - emacs

There are 5 Elisp commands that can be run on an Emacs fileset, plus the ability to run any shell command. What about all the other Emacs commands? Just to give one example, it would be nice to be able to run M-x occur on a fileset.
I know its possible to mark several files in dired and then run any Emacs command on them (is that true, or am I confused with shell commands?), but it would be very convenient to define a fileset once and then be able to use it like one single file for all kinds of text editing.
Thanks for any advice

The commands that can operate on file sets are specified in the global custom variable "filesets-commands". You can add your own commands to that list. The default value for this variable is:
("Isearch" multi-isearch-files
(filesets-cmd-isearch-getargs))
("Isearch (regexp)" multi-isearch-files-regexp
(filesets-cmd-isearch-getargs))
("Query Replace" perform-replace
(filesets-cmd-query-replace-getargs))
("Query Replace (regexp)" perform-replace
(filesets-cmd-query-replace-regexp-getargs))
("Grep <<selection>>" "grep"
("-n " filesets-get-quoted-selection " " "<<file-name>>"))
("Run Shell Command" filesets-cmd-shell-command
(filesets-cmd-shell-command-getargs)))
The values consist of an association list of names, functions, and an argument list (or a function that returns one) to be run on a filesets' files. So, if you wanted to add a command that does an "occur" command on the file set, you could use the "Isearch" entry as an example to create your own new entry (that you would add to the "filesets-commands" global variable) that would look something like:
("Occur (regexp)" multi-occur-files-regexp
(filesets-cmd-occur-getargs))
You would need to write the "multi-occur-files-regexp" and "filesets-cmd-occur-getargs" functions (you could use the existing "multi-isearch-files-regexp" and "filesets-cmd-isearch-getargs" functions as a basis since they would be similar). The same would apply for any additional Emacs command that you wanted to add to work on file sets.

Dired has several operations on filesets. An example is dired-do-search (bound to A), where you can navigate through search results on several files with M-, just like with tags-search. Similarly, you can query-replace in tagged files (with Q).
The recent posts on irreal.org describe some nice dired features.

With Icicles you can use filesets for anything you might want to do with a set of files and directories. And you can create a fileset from any set of file and directory names in buffer Completions during completion. And you can use substring and regexp matching during completion to get such a set of file names in Completions.
These links might help:
http://www.emacswiki.org/emacs/Icicles_-_Persistent_Completions#Filesets
http://www.emacswiki.org/emacs/Icicles_-_Dired_Enhancements#OpenDiredOnSavedFiles
http://www.emacswiki.org/emacs/Icicles_-_Dired_Enhancements#MarkedFilesAsProject
http://www.emacswiki.org/emacs/Icicles_-_Customization_and_General_Tips#icicle-filesets-as-saved-completion-sets-flag

Dired+ has command diredp-fileset, which opens Dired on an Emacs fileset. You are prompted for the fileset to use.

Related

Find files whos filenames match pattern in emacs

I am using Linux version of emacs and I would like to use its grep (or rgrep) function to list all filenames matching a pattern, and ideally this should be recursive. I want to be able to call this from the eshell. I'm an emacs newb so if there are more convenient ways of doing this please list those as well, thanks!
EDIT: The purpose in this case is to ensure there are no binary executables in the file list, I don't need the output to go anywhere.
M-x find-name-dired RET is what you want.
Use the command M-x grep-find and then tweak the find command with the -executable flag to suit your need.
There's one more way (as is common) to do this using Dired. Suppose you have the directory you want to search in now visible in Dired buffer. Move the point to it and do C-u iRRET - this will expand all subdirectories recursively in the same buffer. Now * * will select all executable files in all subdirectories.
If you then want to hide the rest, do tk.
PS. For your purpose, Dired will report in the minibuffer how many executable files it found, so you'd not need to do the second step. Second step is for the case if you wanted to further work with the files.

How to have find-file's prompt match Emacs shell's $PWD?

With Emacs, if the current buffer is one that's "visiting" a normal file (for example), whose full pathname is /path/to/somefile, and one runs find-file (C-x C-f), the prompt that appears in the mini-buffer is something like
Find file: /path/to/▮
...with the cursor placed as indicated above by ▮. IOW, the suggested path shown by default is always to the directory containing the file that the current buffer is visiting.
If, however, the current buffer is an Emacs shell process, and one runs find-file, then, AFAICT, the path shown in the prompt remains fixed at the value of $PWD when the shell process was started, irrespective of the current value of $PWD:
Find file: /pwd/at/startup/▮
This behavior is not so useful, because the $PWD at startup often becomes irrelevant later on. It would be really nice if the directory shown in find-file's prompt were instead the shell process's current $PWD.
Is there a simple way to modify find-file to behave this way whenever the current buffer is a shell process?
You want "shell directory tracking". E.g. check dirtrack-mode or shell-dirtrack-mode.
shell-dirtrack-mode tries to parse "cd" commands, (event_jr: which in my experience does not work consistently). dirtrack-mode uses the prompt regexp, which works very well.
There are a number of ways to manage this. As Stefan notes, there are a couple of built in packages that manage it.
My preferred way is to alter your prompt (when in Emacs) to have the $PWD embedded in it, and then Emacs strips it out and uses it. This has the benefit of always being up to date. I've found that dirtrack-mode sometimes gets out of sync.
Check out my solution here, which is a modification of a similar implementation on the Emacs Wiki.

Emacs search and open multiple files and search on all buffers

I'm currently in the beginning of a switching process forwards Emacs. However I'm having two basic problems.
How do I search for multiple files recursively from a specific path? I assume I have to use find/grep/dired but I'm not sure. For instance I would like to find all *.scala files at path C:/src/xxx.When these files are found I would also like to open them all in the buffer at once. The only way I'm currently familiar with is C-xC-f.
When all these files are in the buffer how do I then search across all the buffers, and get some kind of list of the result and/or perhaps able to navigate from result to result? Saying I would like to find all places with the text case Int => occur.
I concur with phimuemue's answer, but I'll point out M-x rgrep as well, which will run the necessary find/grep in order to present all of the matches without actually opening the files. Selecting a match then opens the relevant file at that line number. In some situations, this may be preferable to opening all of those files.
Also see these:
Using Emacs to recursively find and replace in text files not already open
emacs: interactively search open buffers
For Part A, you might look here.
For Part B you might have a look at multi-occur-in-matching-buffers, which let's you specify which buffers you want to take (e.g. all buffers .*.scala to look in all scala files) and what to look for (e.g. case Int =>). This gives you a list of all occurences.
You're trying to find all occurrences of "case Int =>" in *.scala files in C:/src
The easiest way (assuming a default Emacs setup) is to use M-x rgrep. It'll ask you for a search-string, file type and directory (in that order, and the prompts are labeled so there's no confusion). Just type in case Int =>, *.scala and C:/src/xxx.
What you should see is a new buffer with a list of occurrences of "case Int =>" in all .scala files in that directory. If you click on an occurrence, Emacs will open that file and navigate to the line that contains it.
As a note, if you're trying to do search and replace across multiple files, you can do that using dired options. You can find information on that option here.
*For Question A***
In Icicles, C-x C-f is by default a multi-command. That means that when you complete to a set of file names:
You can act on (e.g. visit) multiple candidates, selectively (e.g. C-RET, C-mouse-2).
You can act on all files whose names match your current input -- e.g., visit them all.
The same is true for other Icicles file commands, including those that let you match an absolute file name, meaning that your minibuffer patterns can match not just the non-directory part of the file name but directory parts as well.
For example, C-x C-f with a prefix arg matches absolute file names. And M-x icicle-locate-file does the same thing for all files under a given directory.
(You can always use a multi-command as an ordinary command: C-x C-f acts normally if you use RET or mouse-2. If you don't use the extra key bindings to act on multiple files then you'll never know the difference.)
See http://www.emacswiki.org/emacs/Icicles_-_File-Name_Input
*For Question B***
What you want is Icicles search.
Command icicle-search-file searches all files of a set you specify.
Command icicle-search-buffer searches all buffers of a set you specify.
Command icicle-search does both: files with a negative prefix arg, buffers with a non-negative prefix arg.
These commands let you specify a regexp to define the search contexts: the parts of the files or buffers that you want to search. For example, .* means search each line.
After you define the search contexts you type some text in the minibuffer, and it narrows the candidate search contexts to those that match your text. You can hit M-SPC to combine multiple such patterns.
Then you can navigate to the selected search hits: C-RET or C-mouse-2 to visit, or cycle/visit using C-down. You can even sort the matching candidates in various ways, to compare them easily or to change the cycle order.
See http://www.emacswiki.org/emacs/Icicles_-_Search_Commands%2c_Overview
I think you're artificially constraining the answer. You don't need to load all the files into Emacs in order to find those occurrences. And, once you've found the occurrences of the regexp, you can easily jump to the line in the file with a keystroke.
My favorite way to do this is to use M-x igrep-find because I like the igrep interface better than Emacs's grep-find.
You can find the igrep library on emacswiki: igrep.el
And the usage would be
M-x igrep-find case Int => RET
which would populate a buffer with all the matches, and then (like in occur, grep-find, compilation, etc.) you can use C-x ` or M-x next-error to cycle through the matches.

Emacs command for searching in files

I want to search in all files from the current folder for macro CODE_INIT_PARAMETERS.
I can do Alt + X occur, Return CODE_INIT_PARAMETERS Return, but this shows only entries from open buffers.
Is there a way to search all files from current folder, from Emacs, without switching to M-x shell and then grep? I want to avoid grep, because for some commands (M-x occur) Emacs do jumps to offending code, and I want that too.
You can try M-x rgrep.
It will ask for:
the directory where you want to search recursively
a file pattern for the files you want to include in the search
the pattern you want to search
As an extra, it will exclude source control private directories from your search (like CVS, .svn or .git).
Emacs provides a built-in command:
M-x grep RET CODE_INIT_PARAMETERS *.c
(and 'grep-find to search sub directories)
Though I prefer the interface provided by an external package igrep (which provides the commands igrep and igrep-find).
If you open a folder in dired, and mark all of the files (with 'm') you can run 'dired-do-search ('A' in my bindings). This will search all marked files. To get to the next one, run tags-loop-continue (M-,)
I have set up several ELisp functions to mark various subsets of the files (.h files, .cpp files, etc.) and to create a recursive dired to search a whole tree...
This is an improvement on Trey Jackson's suggestion.
M-x grep
You will see the grep command, e.g. grep -nH -e
Add R to the first set of flags (for recursive), and put your search term after -e
grep -nHR -e CODE_INIT_PARAMETERS
Hit RET. The results will be understandable by Emacs -- you will be able to click or otherwise navigate to them, like M-x occur. You may need to put the search directory at the end of the command:
grep -nHR -e CODE_INIT_PARAMETERS /path/to/root/of/search
M-x find-grep-dired also works similarly as rgrep
In cases where
you may be searching repeatedly; and
etags will work
you might consider using etags and invoking either find-tag (bound to M-. by default) or tags-search (no default binding but can be continued with M-,).
There is as well ack-grep mode for Emacs which uses the ack-grep tool which is specifically designed for ''grepping'' programming languages and IMHO looks nicer than the output of M-x grep.
But as mentioned earlier etags should be the proper way!

Using Emacs to recursively find and replace in text files not already open

As a follow-up to this question, it's trying to find out how to do something like this which should be easy, that especially stops me from getting more used to using Emacs and instead starting up the editor I'm already familiar with. I use the example here fairly often in editing multiple files.
In Ultraedit I'd do Alt+s then p to display a dialog box with the options: Find (includes using regular expressions across multiple lines), Replace with, In Files/Types, Directory, Match Case, Match Whole Word Only, List Changed Files and Search Sub Directories. Usually I'll first use the mouse to click-drag select the text that I want to replace.
Using only Emacs itself (on Windows XP), without calling any external utility, how to replace all foo\nbar with bar\nbaz in *.c and *.h files in some folder and all folders beneath it. Maybe Emacs is not the best tool to do this with, but how can it be done easily with a minimal command?
M-x find-name-dired: you will be prompted for a root directory and a filename pattern.
Press t to "toggle mark" for all files found.
Press Q for "Query-Replace in Files...": you will be prompted for query/substitution regexps.
Proceed as with query-replace-regexp: SPACE to replace and move to next match, n to skip a match, etc.
Press C-x s to save buffers. (You can then press y for yes, n for no, or ! for yes for all)
M-x find-name-dired RET
it may take some time for all the files to appear in the list, scroll to bottom (M->) until "find finished" appears to make sure they all have loaded
Press t to "toggle mark" for all files found
Press Q for "Query-Replace in Files...": you will be prompted for query/substitution regexps.
Proceed as with query-replace-regexp: SPACE or y to replace and move to next match, n to skip a match, etc.
Type ! to replace all occurrences in current file without asking, N to skip all possible replacement for rest of the current file. (N is emacs 23+ only)
To do the replacement on all files without further asking, type Y.
Call “ibuffer” (C-x C-b if bound to ibuffer, or M-x ibuffer RET) to list all opened files.
Type * u to mark all unsaved files, type S to save all marked files
* * RET to unmark all marks, or type D to close all marked files
This answer is combined from this answer, from this site, and from my own notes. Using Emacs 23+.
Projectile is really nice:
C-c p r runs the command projectile-replace
The answers provided are great, however I thought I'd add a slightly different approach.
It's a more interactive method, and requires wgrep, rgrep and iedit. Both iedit and wgrep must be installed via MELPA or Marmalade (using M-x package-list-packages)
First run M-x rgrep to find the string you're looking for.
You'll be able to specify file types/pattern and the folder to recurse.
Next you'll need to run wgrep start it with C-s C-p.
Wgrep will let you edit the rgrep results, so set a region on the string to match and start iedit-mode with C-; (depending on your terminal you may need to re-bind this)
All occurrences will be editable at once. C-x C-s to commit wgrep. Then C-x s ! to save the changed files.
The main benefit of this method is that you can use iedit-mode to toggle off certain matches M-;. You can also use the results in rgrep to jump into the files, for example if you have an unexpected match.
I find it very useful for doing source edits and renaming symbols (variables, function names etc.) across a project.
If you don't already know/use iedit mode it's a very handy tool, I strongly recommend you give it a look.
I generally use other tools to perform this task, and it seems like many of the approaches mentioned at EmacsWiki's Find and Replace Across Files entry shell out, but the Findr Package looks very promising.
Stealing part of the source file:
(defun findr-query-replace (from to name dir)
"Do `query-replace-regexp' of FROM with TO, on each file found by findr.
Source of information: 1
For emacs pro users:
Call dired to list files in dir, or call find-dired if you need all subdirectories.
Mark the files you want. You can mark by regex by typing 【% m】.
Type Q to call dired-do-query-replace-regexp.
Type your find regex and replace string. 〔☛ common elisp regex pattern〕
For each occurrence, type y to replace, n to skip. Type 【Ctrl+g】 to abort the whole operation.
Type ! to replace all occurrences in current file without asking, N to skip all possible replacement for rest of the current file. (N is emacs 23 only)
To do the replacement on all files without further asking, type Y. (Emacs 23 only)
Call ibuffer to list all opened files. Type 【* u】 to mark all unsaved files, type S to save all marked files, type D to close them all.
Step-by-Step Guide for Emacs Beginners
Select Target Files
Start emacs by typing “emacs” in the command line interface prompt. (Or, double click the Emacs icon if you are in a Graphics User Interface environment)
Selecting Files in a Directory
First you need to select the files you want to do the replace. Use the graphical menu 〖File ▸ Open Directory〗. Emacs will ask you for a directory path. Type the directory path, then press Enter.
Now, you will be shown the list of files, and now you need to mark the files you want the regex find/replace to work on. You mark a file by moving the cursor to the file you want, then press m. Unmark it by pressing u. (To list subdirectories, move your cursor to the directory and press i. The sub-directory's content will be listed at the bottom.) To mark all files by a regex, type 【% m】, then type your regex pattern. For example, if you want to mark all HTML files, then type 【% m】 then .html$. (You can find a list of the mark commands in the graphical menu “Mark” (this menu appears when you are in the dired mode).)
Selecting Files in a Directory and All Its Sub-Directories
If you want to do find/replace on files inside a directory, including hundreds of subdirectories, here's a method to select all these files.
Call find-dired. (you call a command by pressing 【Alt+x】) Then, type a directory name, ⁖ /Users/mary/myfiles
Note: if you are using emacs on a unix non-graphical text terminal, and if 【Alt+x】 does not work, the equivalent key stroke is 【Esc x】.
Emacs will ask you with the prompt “Run find (with args): ”. If you need to do the replacement on all HTML files, then type -name "*html". If you don't care about what kind of file but simply all files under that dir, then give “-type f”.
Now, mark the files as described above.
Interactive Find/Replace
Now, you are ready to do the interactive find replace. For simplicity, let's say you just want to replace the word “quick” by “super”. Now, call dired-do-query-replace-regexp. It will prompt you for the regex string and the replacement string. Type “quick”, enter, then “super”.
Now, emacs will use your pattern and check the files, and stop and show you whenever a match occurred. When this happens, emacs will prompt you, and you have a choice of making the change or skip the change. To make the change, type y. To skip, type n. If you simply want emacs to go ahead and make all such changes to the current file, type !.
If you want to cancel the whole operation without saving any changes you've made, type 【Ctrl+g】, then exit emacs using the menu 〖File ▸ Exit Emacs〗.
Saving the Changed Files
Now, after you went through the above ordeal, there is one more step you need to do, and that is saving the changed files.
If you are using emacs version 22 or later, then call ibuffer to go into a buffer listing mode, then type 【* u】 to mark all unsaved files, then type S to save them all. (that's shift-s)
If you are using a emacs version 21, then you can do this: call list-buffers, then move the cursor to the file you want to save and type s. It will mark the file for later save action. Type u to unmark. Once you are done, type x to execute the saving of all files marked for save. (in emacs, opened file is called “buffer”. Disregard other things there.)
Alternative to the above options, you can also call save-some-buffers 【Ctrl+x s】. Then emacs will display each unsaved file and ask if you want it saved.
Note: emacs's regex is not the same as Perl or Python's, but similar. For a summary and common patterns, see: Emacs Regex.
Using dired to recurse down a deep directory tree is going to be a bit slow for this task. You might consider using tags-query-replace. This does mean shelling out to create a tags table, but that is often useful anyway, and it's quick.
For open buffers, this is what I do :
(defun px-query-replace-in-open-buffers (arg1 arg2)
"query-replace in all open files"
(interactive "sRegexp:\nsReplace with:")
(mapcar
(lambda (x)
(find-file x)
(save-excursion
(goto-char (point-min))
(query-replace-regexp arg1 arg2)))
(delq
nil
(mapcar
(lambda (x)
(buffer-file-name x))
(buffer-list)))))
M-X Dired, and t to mark all files, and Q to query replace text in all of them.
You can expand a sub directory by using the i command before the query-replace.
They key info I'm adding is that if you give a prefix (control-u) to the i command,
it will prompt you for arg, and -R argument will recursively expand all subdirs
into the dired buffer. So now you can query-search every file in an entire directory.
Another option is to use Icicles search. This is a different kind of incremental search that uses completion of your minibuffer input against search hits. As you modify your current input the set of matching hits is updated in buffer *Completions*.
You can search any number of files, buffers, or bookmarked locations, which you can choose using minibuffer pattern (e.g. regexp) matching.
When you visit a search hit you can replace on demand either the entire hit or just the part of it that matches your current minibuffer input. Replacement on demand means you are not queried about each search hit in turn; you access the hits you want directly, in any order. This approach can be more effective than query-replace if you have a limited number of replacements to make: you skip the exhaustive y/n prompting.
Search is over search contexts that you define -- you are not limited to searching all of the text in the target files (e.g., you can skip comments or particular kinds of program sections). A simple example of a search context is a line, as in grep, but a context can be any pattern-matched block of text you like. Typically you define the search contexts using a regexp, but you can instead use a function. In addition to defining your own, there are predefined Icicles search commands for different kinds of contexts: blocks of text properties or overlay properties, thing-at-point things, etc.
You can also sort the search hits in various sort orders for easier access/navigation.
find-name-dired is OK, but:
All of the files you get match the same, single regexp.
find-dired is more flexible in that regard, but it too is made for using general rules (even if they can be arbitrarily complex). And of course find has its own, complex language.
if you then want to act on only some of the files whose names were collected in the find(-name)-dired buffer, you need to either mark them or delete/omit the lines of those you do not want to act on.
An alternative is to use Dired+ commands that act on (a) the marked files and (b) all marked files (or all files, if none are marked) in the marked subdirectories ... found recursively. This gives you both generality and easy control over file choice. These "here-and-below" commands are all on prefix key M-+ in Dired mode.
For example, M-+ Q is the same as Q --- query-replace, but the target files are all of those marked in the current dir and in any marked subdirs, down, down, down...
Yes, an alternative to using such here-and-below commands is to insert all subdirs and their subdirs, recursively, and then use a top-level command such as Q. But it can often be convenient not to bother with inserted subdirs.
And to do that you anyway need a quick way to insert all such subdirs recursively. Here too, Dired+ can help. M-+ M-i inserts all marked subdirs and their own marked subdirs, recursively. That is, it is like M-i (which inserts the marked subdirs in Dired+), but it acts recursively on subdirs.
(All such "here-and-below" Dired+ commands are on menu Multiple > Marked Here and Below.)
You can also perform Dired operations on an Emacs fileset, which is a saved set of names of files located anywhere. And if you use Icicles then you can open a Dired buffer for just the files in a fileset or other types of saved file lists.
You can also bookmark any Dired buffer, including one that you create using find(-name)-dired. This gives you a quick way to return to such a set (e.g. a project set) later. And if you use Bookmark+ then bookmarking a Dired buffer records (a) its ls switches, (b) which files are marked, (c) which subdirectories are inserted, and (d) which (sub)directories are hidden. All of that is restored when you "jump" to the bookmark. Bookmark+ also lets you bookmark an entire tree of Dired buffers --- jumping to the bookmark restores all of the buffers in the tree.
M-x project-query-replace-regexp RET (make sure your files are saved!).
M-x rgrep RET then query-replace within each buffer. Nice because you can keep track of all occurrences, and because it let's you limit search to certain extensions.
I would like to suggest one more great tool which has not been mentioned yet, namely Helm.
It is a great replacement for many standard Emacs operations involving completion, searching etc. In particular, helm-find-files allows for performing query replace (including regexp) within multiple selected files.
Just open helm-find-files, mark the relevant files with M-SPC and then use F6 or F7 to run query replace or query replace regexp in the selected files.
It's not Emacs, but xxdiff comes with a tool called xx-rename which will do that for multiple strings at a time (e.g. From To from to FROM TO), with interactive prompting, save backups of all the modified files, and produce a short log of changes made with context. That's what I tend to use when I do large/global renamings.