how to specify multiple file extensions in rgrep? - emacs

I tried *.{cc,hh} but it doesn't work (this works for lgrep though). i also tried the method suggested her e http://compgroups.net/comp.emacs/searching-multiple-file-types-with-rgrep/95027 but it seems the interactive mode doesn't allow me to input space. Any idea?

*.cc *.hh is correct. The find command will then use something like:
\( -iname \*.cc -o -iname \*.hh \)
(If you supply a prefix argument, you can view/edit the command before it is executed.)
You can enter the space using quoted-insert: C-qSPC, or just-one-space: M-SPC

I was (in despair) rolling an elisp solution:
(defun mrgrep (pattern extensions dir)
(interactive "ssearch for: \nsextensions (space separated, no *): \nD")
(setq includes (mapconcat (lambda (ext)
(concat (format "--include=\"\\*%s\"" ext)))
(s-split " " extensions)
" "))
(setq cmd (format "grep -ir %s %s %s"
includes
pattern
(concat dir "*")))
(setq cmd (read-from-minibuffer "run grep like this: " cmd))
(compilation-start cmd 'grep-mode)
)
but phils explained how to enter the space !

Related

Emacs: run shell command with regex and Lisp function to start gud

I am tring to write some Emacs Lisp function to be able to simply compile and debug Java classes within Spacemacs using its Java layer (don't want to go into complex packages like jdee). The compile function is defined beblow and works as expected
(defun my-java-compile (command)
(interactive (list (read-string
"Command: "
(concat
"javac"
" -d "
java-dest-path
" -cp "
java-class-path
" "
(file-name-nondirectory buffer-file-name)))))
(unless (file-exists-p java-dest-path)
(make-directory java-dest-path))
(compilation-start command nil)
)
The java-dest-path and java-class-path are local variables set in the .dir-locals.el in the root directory of the project.
The debug function is defined as:
;; get fully qualified class name
(defun get-fqcn ()
(setq get-package-name-command
(concat
"gsed -n 's/^package\s\+\([^;\s]\+\);\s*$/\1/p' "
buffer-file-name))
(setq fqpn (shell-command-to-string get-package-name-command))
(if (equal "" fqpn) (file-name-base buffer-file-name)
(concat fqpn "." (file-name-base buffer-file-name)))
)
(defun my-jdb (command)
(interactive (list (read-string
"Command: "
(concat
"jdb"
" -classpath "
java-class-path
" "
(get-fqcn)))))
(helm-M-x nil jdb command)
)
I am still trying to make it work. Here are the two issues:
when running shell-command-to-string function, the gsed -n
's/^package\s\+\([^;\s]\+\);\s*$/\1/p' java_file command returns an empty
string "", while it returns the fully qualified package name as
expected when running in a terminal. If I change it to gsed -n '/^package/p', the emacs function return the package line OK. So
it seems shell-command-to-string could not handle the regular
expression in gsed. Any work around?
I could not find the function to trigger the gud or jdb . What would be the gud equivalent of compilation-start function?
The problem is that you want to include backslashes in your regexp, but backslashes are already used as escape characters in Emacs Lisp strings. Let's try displaying the string in the echo area:
(message "%s" "gsed -n 's/^package\s\+\([^;\s]\+\);\s*$/\1/p' ")
This displays:
gsed -n 's/^package +([^; ]+); *$/^A/p'
So as you can see, the backslashes were "eaten" by the Emacs Lisp parser. We need to double the backslashes in order for them to appear literally in the string we send to gsed:
"gsed -n 's/^package\\s\\+\\([^;\\s]\\+\\);\\s*$/\\1/p' "
Alternatively, implement the search in Emacs Lisp:
(save-excursion
(goto-char (point-min))
(search-forward-regexp "^package[[:blank:]]+\\([^;[:blank:]]+\\);")
(match-string 1))
The function for running jdb inside gud is jdb:
(jdb command)

Org-Mode Babel, switches for code blocks: Can I set defaults?

In org mode, I can insert source in my org files. There are many header arguments, and I found how to set defaults. So I am down to only switches (here -n -r -l "..")
#+BEGIN_SRC emacs-lisp -n -r -l ";(ref:%s)"
..
#+END_SRC
As I want to use these as site default: How can I set defaults for such switches?
Best in .emacs, but defaults valid for a file/buffer would be of help too.
You can start with this hack
(defadvice org-babel-parse-src-block-match (after org-babel-add-switches activate)
"Add extra-sw to 3th element of the return value"
(let ((extra-sw "-t -w 200"))
(setq v (vconcat ad-return-value))
(aset v 3 (concat (elt v 3) " " extra-sw))
(setq ad-return-value (append v nil))))

How can I improve this Emacs lisp function?

The intent is to use git grep as the command for M-x grep, and all the buffer benefits that come along with it. Desired functionality:
It reads the word/thing at point as the default value (done, sort of)
It reads the current region as the default argument if a region is set.
The following is the code I have so far:
(defun bw-read-string-at-point ()
(interactive)
(let ((word (word-at-point)))
(set-text-properties 0 (length word) nil word)
word))
(defun bw-git-grep (search-str)
"Uses `git-grep` to find `search-str`"
(interactive
(list
(read-string (format "Search for (%s): " (bw-read-string-at-point)))))
(let ((search-str (if (= (length search-str) 0)
(bw-read-string-at-point) search-str)))
(grep (concat "git --no-pager grep -i -I -nH --no-color --extended-regexp " search-str))))
I feel like the interactive bit there is quite clumsy and could be made much better.
Actually, it looks pretty good. Except you should use the default' argument ofread-string, and the interactive in bw-read-string-at-point should not be there. Or better yet, just use grep-tag-default.
Here's how I'd tweak it:
(defun bw-git-grep (search-str)
"Uses `git-grep` to find `search-str`"
(interactive
(let ((default (grep-tag-default)))
(list
(read-string (format "Search for (default %s): " default)
nil nil default))))
(grep (concat "git --no-pager grep -i -I -nH --no-color --extended-regexp " search-str)))
I would use read-from-minibuffer instead of read-string:
(defun bw-git-grep (pattern)
(interactive
(list
(read-from-minibuffer
"Search for: "
(if (region-active-p)
(buffer-substring-no-properties (region-beginning) (region-end))
(thing-at-point 'word)))))
(let* ((grep-command "git --no-pager grep -i -I -nH --no-color --extended-regexp ")
(command (concat grep-command pattern))
(grep-use-null-device nil))
(grep command)))
Also, you probably need to ensure that grep-use-null-device is nil to avoid grep appending /dev/null to your command (which git doesn't seem to like much)

Update multi-term buffer name based on PWD

If I use konsole or other terminal, the terminal tag name can change based on PWD. But in multi-term, the buffer name is *terminal<number>*. This is not very nice. Because when I switch between them, the name is not very informative. So I want to rename it based on PWD.
I find that the Enter key is bind to term-send-raw, so I write a function
(defadvice term-send-raw (around rename-term-name activate)
(progn
(rename-buffer
(concat "⇒ "
(shell-command-to-string "pwd | xargs basename | tr -d '\n'")
(format-time-string " [%M ∞ %S]")))
ad-do-it))
But the problem is pwd command return the PWD of the terminal buffer, while it is not the PWD of the SHELL in that terminal.
The PWD of the terminal buffer is set by defcustom multi-term-default-dir. And it does not change when the PWD change in the SHELL.
(defcustom multi-term-default-dir "~/"
"The default directory for terms if current directory doesn't exist."
:type 'string
:group 'multi-term)
How can I get the PWD of the SHELL in the terminal?
Regards.
AFAIK there is no easy way to retrieve information from a running process.
But if you want to get the current directory you could:
ask the shell to print it
parse and trace the command-line for functions like cd, pushd, popd…
poll /proc/PID/cwd
The first method is described in the header of term.el (M-xfind-libraryRETtermRET).
And now, thank you for your question, you gave me the opportunity to do this:
(defadvice term-send-input (after update-current-directory)
(let* ((pid (process-id (get-buffer-process (current-buffer))))
(cwd (file-truename (format "/proc/%d/cwd" pid))))
(cd cwd)))
(ad-activate 'term-send-input)
It's a naive implementation of the third method and it doesn't work if the user uses su or ssh. However, I don't know if it's possible withouth using the first or the second method.
In your case, you can just replace the cd command with whatever you want.
Building off of Daimrod's answer for polling /proc/PID/cwd, I found a way get around the problem that Reed pointed out where the advice doesn't pick up the updated CWD immediately and you have to hit Enter twice.
If you move the CWD update code to its own function and use run-at-time to call it from the advice at a later time, it will pick up the updated CWD correctly. Unfortunately I don't know enough about Emacs' scheduling to explain why this works (any enlightenment would be appreciated).
Here's my code based on Daimrod's. Note I advised term-send-input for line-mode and term-send-return for char-mode. I tested this using multi-term on Emacs 24.3.1:
(defadvice term-send-input (after update-current-directory)
(run-at-time "0.1 sec" nil 'term-update-dir)
)
(ad-activate 'term-send-input)
(defadvice term-send-return (after update-current-directory)
(run-at-time "0.1 sec" nil 'term-update-dir)
)
(ad-activate 'term-send-return)
(defun term-update-dir ()
(let* ((pid (process-id (get-buffer-process (current-buffer))))
(cwd (file-truename (format "/proc/%d/cwd" pid))))
(unless (equal (file-name-as-directory cwd) default-directory)
(message (concat "Switching dir to " cwd))
(cd cwd)))
)
Most terminals get their window name from the command echo -en. In zsh you can put this in your ~/.zshenv
precmd() { echo -en "\e]0;`basename ${PWD}`\a" }
and that will get the basename of your PWD environment variable. Ideally multi-term would do something similar and put it in multi-term-buffer-name, which is the variable which holds its buffer name.
Yes, this is not a complete solution. I'm hoping for one too!
Try this:
(defun open-or-jump-to-multi-term ()
(interactive)
(if (string-prefix-p "*terminal<" (buffer-name))
(delete-window)
(progn
(setq bufname (concat "*terminal<" (directory-file-name (file-name-directory (buffer-file-name))) ">"))
(if (get-buffer-process bufname)
(switch-to-buffer-other-window bufname)
(progn
(split-window-right)
(other-window 1)
(multi-term)
(rename-buffer bufname)
)
)))
)
(global-set-key (kbd "C-`") 'open-or-jump-to-multi-term)

Perl: How can I get Emacs to add quotes to full path of a Perl script?

Embarassingly simple question. Using CPerl mode in Emacs 23.4.1 on Windows 7 64, when I use C-c c to run the script Emacs doesn't wrap the path in quotes, so any directories with spaces cause Perl to be unable to find the file.
"C:/Perl64/bin\perl.exe -w g:/foo/bar/first second/myscript.pl"
generates this error message:
"Can't open perl script "g:/foo/bar/first": No such file or directory"
Question: how do I make Emacs use quotes when passing the file name to Perl itself?
Edit: for some reason I can't comment (perhaps a browser issue) so I am editing the original post in response to the comment from #legoscia: "C-c c runs the command mode-compile". In the Perl menu it is marked as "Run".
I only have mode-compile.el v2.29 available, but in that version the issue is exactly as you describe, the arguments to the compile command are not escaped properly, and there's no option to enable it.
It's a bit of hack but you should be able to redefine the relevant function with correct escaping for the filename with this in your .emacs file:
(eval-after-load 'mode-compile
'(progn
(defun mc--shell-compile (shell dbgflags &optional errors-regexp-alist)
;; Run SHELL with debug flags DBGFLAGS on current-buffer
(let* ((shcmd (or (mc--which shell)
(error "Compilation abort: command %s not found" shell)))
(shfile (or mc--remote-pathname (buffer-file-name)
(error "Compilation abort: Buffer %s has no filename"
(buffer-name))))
(run-cmd (concat shcmd " " dbgflags " " (shell-quote-argument shfile) " "
(setq mc--shell-args
(read-string (if mode-compile-expert-p
"Argv: "
(format "Arguments to %s %s script: "
shfile shell))
mc--shell-args)))))
;; Modify compilation-error-regexp-alist if needed
(if errors-regexp-alist
(progn
;; Set compilation-error-regexp-alist from compile
(or (listp errors-regexp-alist)
(error "Compilation abort: In mc--shell-compile errors-regexp-alist not a list."))
;; Add new regexp alist to compilation-error-regexp-alist
(mapcar '(lambda(x)
(if (mc--member x compilation-error-regexp-alist) nil
(setq compilation-error-regexp-alist
(append (list x)
compilation-error-regexp-alist))))
errors-regexp-alist)))
;; Run compile with run-cmd
(mc--compile run-cmd)))))
The line I changed was changing
(run-cmd (concat shcmd " " dbgflags " " shfile " "
to
(run-cmd (concat shcmd " " dbgflags " " (shell-quote-argument shfile) " "
A more complete fix would be to also escape the dbgflags (wherever they're set, just escaping the entire variable won't be right) and mc--shell-args when they're set too.