I try to do a grep on the result of emacs' find-grep, so I use the following command:
find ... | xargs ... | grep -v "include"
The result does show up i the grep buffer, but when I press enter on each entry trying to go to that file, emacs says that file does not exist. On the minibuffer, before the full path of the file, there is a ^[[K character. That basically make the the whole file name unrecognizable. I looked through grep's manual, still no sure what I can do about it.
I probably don't have to do this, but I'm just not sure how to pass two pattern, one is for grep and the other one is to inverse grep. (May be regular expression?)
Anyone has any suggestions on this?
Solution:
I was doing this on a Cento 5.5 machine. It turns out to be a issue due to the old version of grep. I installed a latest version of grep in my home directory, and everything's good now.
After "debugging" the issue through the comments, this is a solution that should work for you. Add it to your .emacs and customize it so that the regexp matches the special characters you want to strip from the filename: ^[[K
(defadvice compilation-find-file (before compilation-find-file-strip-odd-chars activate)
"Strip the ^[[K in the input string"
(let ((filename (ad-get-arg 1)))
(save-match-data
(when (string-match "^\\[\\[K" filename)
(ad-set-arg 1 (replace-match "" nil nil filename))))))
I had the same problem, but couldn't change my version of grep,
so I used a workaround. The problem seemed to be greps line endings
so I simply run the results of grep through awk
and print them as is.
... | grep -v blaa | awk '{print $0}'
This fixes the problem for me, though I don't know why.
Related
I'm writing a script to automatically install some elisp. I'd like to find the value of user-emacs-directory so that I can copy the file to the right directory. Is there any way to do this from the shell?
I was hoping it would work to run:
$ emacs --batch --eval="(print user-emacs-directory)"
Symbol's value as variable is void: user-emacs-directory
but as you can see that was not fruitful. Then I tried loading my .emacs file first:
$ emacs --batch -l ~/.emacs --eval="(print user-emacs-directory)"
Loading /Users/noah/dotfiles/emacs/init.el (source)...
Symbol's function definition is void: global-visual-line-mode
but that also chokes. Googling hasn't led me to an answer yet. Any ideas?
edit: The specific problem was that I was using an old version of Emacs (22.1.1). Running Emacs 24.4.1 works:
$ emacs -l ~/.emacs --batch --eval="(print user-emacs-directory)" 2>/dev/null
"~/dotfiles/emacs"
(which is the custom value I've set in my own ~/.emacs file)
Note that I'm redirecting stderr to /dev/null to suppress some loading messages.
Works for me on vanilla GNU Emacs 24.5.1 shipped with Ubuntu:
$ emacs -Q --batch --eval="(princ user-emacs-directory)"
~/.emacs.d/
note princ instead of print to avoid extra whitespace and quote marks.
--batch implies -q which means there is no user-emacs-directory
edit: Ugh. No, -q doesn't mean that at all. As sds points out, the proposed code should probably be working. That'll teach me to jump to conclusions. I'd delete this answer, but as the original approach evidentially doesn't work for Noah for some reason, I'll leave this here just in case it still helps...
Typically you just want $HOME/.emacs.d/
See C-hig (emacs) Find Init RET for more info.
I'm looking for a way to always launch my grep-find from a specific location if a variable is set. I'm thinking something like:
Launch emacs from /home/user/mycode/
Open file(s) in e.g. /home/user/mycode/a/b/c/
Run grep-find from /home/user/mycode/
I know that it works if I first open the /home/user/mycode/ directory and then runs grep-find but I want this to be stored as a variable instead. (If the variable is not set it would be fine to simply do the search from the current location)
My grep-find looks like this:
(setq grep-find-command "find . '(' -type f ')' -print0 | xargs -0 -e grep -n -e ")
It seems to me that you would benefit from projectile.
It does just what you need. It has a recursive grep command that it launches from parent directory (it can use also git-grep or ag, a lot faster than grep), and it offers a lot more. You can work with multiple projects at once (projectile is smart that way).
You can look at projectile here: https://github.com/bbatsov/projectile
It is available via MELPA
If you do not want to use it (or similar alternatives), I would advise wrapping your recursive grep command in a custom function like this:
(defun rgrep-at-repo-base (...)
(interactive)
(with-temp-buffer
(while (and (not (file-exists-p ".git/"))
(not (equal "/" default-directory)))
(cd ".."))
(rgrep ...)))
Where you should change the logic for finding your code base from current directory (example works for git repos) and set the arguments you need (if any)
I want to be able to use the normal M-x rgrep workflow (entering a path, a pattern and displaying the linked results in a *grep* buffer) but using git grep instead of the normal find command:
find . -type f -exec grep -nH -e {} +
I tried directly setting the grep-find-command variable:
(setq grep-find-command "git grep")
and using grep-apply-setting
(grep-apply-setting 'grep-find-command "git grep")
but neither seems to work. When I run M-x rgrep it just uses the same find command as before.
In fact, I'm pretty sure now that rgrep doesn't even use the grep-find-command variable, but I can't figure out where it's command is stored.
What about M-x vc-git-grep (C-x v f). Doesn't that do what you need?
It prompts you for:
search pattern (default: token at point, or region)
filename pattern (default: current file suffix)
base search directory (default, current dir)
Works nicely for me.
Turns out the relevant variable is actually grep-find-template. This takes a command with a few additional parameters:
<D> for the base directory
<X> for the find options to restrict directory list
<F> for the find options to limit the files matched
<C> for the place to put -i if the search is case-insensitive
<R> for the regular expression to search for
The default template looks like this:
find . <X> -type f <F> -exec grep <C> -nH -e <R> {} +
To make the command work with git grep, I had to pass in a few options to make sure git doesn't use a pager and outputs things in the right format. I also ignored a few of the template options because git grep already restricts the files searched in a natural way. However, it probably makes sense to add them back in somehow.
My new value for grep-find-template is
git --no-pager grep --no-color --line-number <C> <R>
After some cursory testing, it seems to work.
Note that you should set this variable using grep-apply-setting rather than modifying it directly:
(grep-apply-setting 'grep-find-template "git --no-pager grep --no-color --line-number <C> <R>")
Since I don't use two of the inputs to rgrep, I wrote my own git-grep command which temporarily stashes the old grep-find-template and replaces it with mine. This feels a bit hacky, but also seems to work.
(defcustom git-grep-command "git --no-pager grep --no-color --line-number <C> <R>"
"The command to run with M-x git-grep.")
(defun git-grep (regexp)
"Search for the given regexp using `git grep' in the current directory."
(interactive "sRegexp: ")
(unless (boundp 'grep-find-template) (grep-compute-defaults))
(let ((old-command grep-find-template))
(grep-apply-setting 'grep-find-template git-grep-command)
(rgrep regexp "*" "")
(grep-apply-setting 'grep-find-template old-command)))
With Emacs for Windows and Git Bash make sure PATH finds git.exe or vc-git-grep won't work:
(let ((dir "C:/Program Files/Tools/Git/bin"))
(setenv "PATH" (concat (getenv "PATH") ";" dir))
(setq exec-path (append exec-path '(dir))))
exec-path is not enough... resaons are explained here: Using git with emacs
Since vc-git-grep uses the directory of the buffer from which you run the function I also found a wrapper convenient:
(global-set-key [(control f8)]
(lambda() (interactive)
(with-current-buffer ROOT (call-interactively #'vc-git-grep))))
Here ROOT is a buffer (or function that evaluates a buffer) from whose directory the search begins.
When in eshell is there a command for opening a file in another buffer?
You can call elisp functions directly. So to open a file, call find-file on the filename. Example:
~ $ ls
myfile
~ $ (find-file "myfile")
Parentheses and quotes are optional, so this works too:
~ $ find-file myfile
In eshell, you don't have to use the entire path when using the find file command. Hitting C-x C-f is the same as typing find-file, and eshell sets the directory to the one you are currently browsing. This is the advantage to me over using ansi-term. Try it out.
find-file basically does it, as ataylor and ryan kung indicated earlier.
$ find-file myfile
but, using eshell itself, you can also can set an even shorter alias:
$ alias ff 'for i in ${eshell-flatten-list $*} {find-file $i}'
(and eshell remembers it permanently). so from now you can just type:
$ ff myfile
thanks to this tutorial
The elisp funct can be directly used in eshell, so you can try:
find-file <filename>
Why use eshell? 'C-x f' and type the location of your file.
I saw an answer here how to start the cygwin shell. However, the cygwin shell output is messed up.
(defun cygwin-shell ()
"Run cygwin bash in shell mode."
(interactive)
(let ((explicit-shell-file-name "C:/cygwin/bin/bash"))
(call-interactively 'shell)))
(setq explicit-bash-args '("--login" "-i"))
and here is a sample output of the shell
]0;~
seth#seth ~
$ cd ~
]0;~
seth#seth ~
$ dir
]0;~
seth#seth ~
as one can see, output is screwed up. How do i fix this?
edit: i just noticed that ^[]0 always appears at the end of each command \ otherwise output text works fine. Anyway to get rid of this ending?
alright, i figured this out. in ~/.bashrc, i added
export PS1="\e[0;31m[\u#\h \W]\$ \e[m "
this makes prompt red in single line (which is easy on eyes vs the yellow in original cygwin prompt!)
see
http://www.cyberciti.biz/faq/bash-shell-change-the-color-of-my-shell-prompt-under-linux-or-unix/
In addition, you have to make sure you do not use dos endings. To convert dos endings to unix, type C-x RET f unix and save or place in .emacs file
(set-buffer-file-coding-system 'unix)
Look into EmacsW32. With it, your .emacs configuration becomes
(setq w32shell-cygwin-bin "c:\\cygwin\\bin")
(require 'w32shell)
(w32shell-add-emacs)
(w32shell-set-shell "cygwin")
and everything works.
In Emacs 24.2, I had to put the export PS1=... line from Seth's answer (2) in ~/.emacs_bash instead of in ~/.bashrc.
Use
export PS1="\e[0;32m\u#\h\e[m \e[0;33m\w\e[m\n\$ "
If you like to keep the original color and format.