It is quite common that when I use grep-find in emacs I want to search for the text I have selected. My current workaround to this is to select the text, then M-x grep-find and paste the selection. How do I make a keybinding that does this automatically?
Here's a modified grep-find - if the region is active, search of region
contents. It seems to work on my system:
(defun grep-find (command-args)
"Run grep via find, with user-specified args COMMAND-ARGS.
Collect output in a buffer.
While find runs asynchronously, you can use the \\[next-error] command
to find the text that grep hits refer to.
This command uses a special history list for its arguments, so you can
easily repeat a find command."
(interactive
(progn
(grep-compute-defaults)
(if grep-find-command
(list
(read-shell-command
"Run find (like this): "
(if (region-active-p)
(let ((str
(buffer-substring-no-properties
(region-beginning)
(region-end))))
(cons (replace-regexp-in-string
" {}"
(concat str " {}")
(car grep-find-command))
(+ (cdr grep-find-command)
(length str))))
grep-find-command) 'grep-find-history))
;; No default was set
(read-string
"compile.el: No `grep-find-command' command available. Press RET.")
(list nil))))
(when command-args
(let ((null-device nil))
(grep command-args))))
Related
I use the emacs shell-mode more and more, and there's something that I wish could be improved: the completion when changing directory. I'd love to use ido or projectile-find-dir for that.
My workflow
As of today I do all I can outside of emacs' shell, to use the power of emacs as much as possible (visiting files with ido, finding files in project with projectile, exploring the tree inside dired,…).
I don't cd that often. When I work in a different project I open up another shell buffer. But when I have to, I really miss ido or the fasd shell utility (which works, but without its completion interface which is great with zsh, and which isn't as powerfull as the use of ido could be https://github.com/clvv/fasd).
How to wire that in elisp ?
I know we can give a list to ido-completing-read;
In the shell, typing cd ../<TAB> opens up a new *Completions* buffer. It uses comint-dynamic-completion, but how to get that list in an elisp list, not in a buffer ?
is it possible to wire that completions list into ido ? (or projectile or helm or whatever)
I would appreciate too if you link me to accurate documentation (there's a lot, it's difficult to know what's useful for me)
or does a solution exist yet ?
Thanks !
edit: here is another nice way to cd to recently visited directories, with the fasd utility and ido completion: https://gitlab.com/emacs-stuff/fasd-shell/blob/master/README.org
See another SO question.
ps: eshell doesn't work well with some shell scripts, I'd like to stay in shell-mode.
Try this, it is a quick and dirty hack and may fail in some cases but should work generally. Also pardon my elisp
(require 'ido)
(require 'cl-lib)
(require 'shell)
(defvar my-dir-selected nil "Flag to indicate that user has selected the directory")
(defun my-filter-cd-input (current-input)
"Takes current user input for `cd' the a list
whose car is the 'maximum possible directory path'
and cdr is remaining string.
Examples:
'~/.emacs.d/in => ('~./emacs.d/' 'in')
'/home/gue' => ('/home/' 'gue')
'~/../' => ('~/../' '')"
(let* ((unquoted-input (shell-unquote-argument current-input))
(components (split-string unquoted-input "/"))
(directory-parts (butlast components))
(possible-prefix (car (last components))))
(list (if (string= possible-prefix "")
unquoted-input
(concat (mapconcat 'identity directory-parts "/")
(when directory-parts "/")))
possible-prefix)))
(defun my-complete-directory-name (directory current-input)
"Prompts user for directories in `directory', `current-input'
is the string entered by the user till now"
(let* ((filtered-input (my-filter-cd-input current-input))
(directory-path (car filtered-input))
(partial-input (cadr filtered-input))
(directory-choices (mapcar 'file-name-nondirectory
(condition-case nil
(cl-remove-if-not 'file-directory-p
(directory-files (concat directory directory-path) t))
('file-error (list)))))
(selected-name (ido-completing-read "Directory: "
directory-choices
nil nil partial-input)))
(comint-delete-input)
(insert (concat "cd "
(shell-quote-argument (concat directory-path selected-name "/"))))))
(defun my-prompt-for-dir-or-fallback ()
"If current shell command is `cd' prompt for directory
using ido otherwise fallback to normal completion"
(interactive)
(let* ((user-input (buffer-substring-no-properties (comint-line-beginning-position)
(point-max))))
(if (and (>= (length user-input) 3)
(string= (substring user-input 0 3) "cd "))
(progn
(setq my-dir-selected nil)
(while (not my-dir-selected)
(my-complete-directory-name default-directory
(buffer-substring-no-properties (+ (comint-line-beginning-position) 3)
(point-max))))
(comint-send-input))
(call-interactively 'completion-at-point))))
(define-key shell-mode-map (kbd "<tab>") 'my-prompt-for-dir-or-fallback)
(add-hook 'ido-setup-hook 'ido-my-keys)
(defun ido-my-keys ()
"Add my keybindings for ido."
(define-key ido-completion-map (kbd "<C-return>") (lambda ()
(interactive)
(setq my-dir-selected t)
(ido-exit-minibuffer))))
Hitting <tab> in shell will prompt for directories available using ido if the currently entered command is cd, otherwise it will fallback to default completion, to exit press C-RET
I am starting to learn Emacs Lisp, and as a first project I would like to improve the fortran mode in Emacs. I would like to mark the name of a sub routine in the buffer, and then press a shortcut key. To bring up a buffer with all lines in the given source where the name of the subroutine is mentioned.
I found that I can get the marked text using:
(defun get-selected-text (beg end)
(interactive
(if (use-region-p)
(list (region-beginning) (region-end))
(list nil nil)))
(message "%s" (if (and beg end)
(buffer-substring-no-properties beg end) "")))
and can store the line numbers of the subroutines using:
(defun get-line-numbers (str)
(interactive "sEnter string: ")
(save-excursion
(goto-char 0)
(let (( sok 1) (list nil) pp)
(while sok
(setq pp (search-forward str nil t))
(if pp (push (line-number-at-pos pp) list)
(setq sok nil)))
(message "%s" list))))
I would now like to open a new buffer similar to when I use Ctrl-x Ctrl-b to execute list-buffers and then display each line number, together with the text on the line, and the user can select a given line, and press Enter to goto the given line in the original buffer..
Just wanted to show you my version of occur-dwim.
I remember spending some time to find out about the regexp-history variable.
The first function is similar to your get-selected-text.
(defun region-str-or-symbol ()
"Return the contents of region or current symbol."
(if (region-active-p)
(buffer-substring-no-properties
(region-beginning)
(region-end))
(thing-at-point 'symbol)))
(defun occur-dwim ()
"Call `occur' with a sane default."
(interactive)
(push (region-str-or-symbol) regexp-history)
(call-interactively 'occur))
To display the list-buffer you use get-buffer-create and clear it with erase-buffer (it might be that it already extisted).
To output the lines you search in the current buffer save the line in a string and put it into the list buffer via with-current-buffer and insert.
To make return special on the text or to make it clickable put a text-property with a local keymap on it.
With this guide you should be able to find everything you need in the elisp-manual.
Regarding your code, you get the beginning and end of the current region with (interactive "r"). Therewith you also get the error message if there is no active region.
I am using org-mode and org-attach extensively which means that
there can be many attachment directories associated with one org file.
On worg I found a function from Matt Lundi which allows to see all
attachments that belong to the whole file and browse them with ido.
I would like to restrict this function to a subtree which would make it
much more useful for my use case.
Since I am not new to emacs but almost completely elisp illiterate I am
asking here.
This is the function:
(defun my-ido-find-org-attach ()
"Find files in org-attachment directory"
(interactive)
(let* ((enable-recursive-minibuffers t)
(files (find-lisp-find-files org-attach-directory "."))
(file-assoc-list
(mapcar (lambda (x)
(cons (file-name-nondirectory x)
x))
files))
(filename-list
(remove-duplicates (mapcar #'car file-assoc-list)
:test #'string=))
(filename (ido-completing-read "Org attachments: " filename-list nil t))
(longname (cdr (assoc filename file-assoc-list))))
(ido-set-current-directory
(if (file-directory-p longname)
longname
(file-name-directory longname)))
(setq ido-exit 'refresh
ido-text-init ido-text
ido-rotate-temp t)
(exit-minibuffer)))
Maybe I'm missing something, but calling org-narrow-to-subtree first should do what you want (call widen afterwards to revert that).
I thought this would be pretty darned useful myself so, inspired by your question, I wrote a version that does what you want plus a couple other bells and whistles. To invoke it you have to type C-c o. NOTE: This is NOT on the usual org-attach key prefix because that function is oddly written without a keymap so it is difficult to add the functionality onto the key prefix.
(autoload 'org-attach-dir "org-attach")
(autoload 'find-lisp-find-files "find-lisp")
(defcustom ido-locate-org-attach-all-files nil
"Non-nil means `ido-locate-org-attach' returns all files.
Otherwise the default behavior only returns files attached to the
current entry."
:group 'ido
:type 'boolean)
(defun ido-locate-org-attach (&optional find-all)
"Find files in org-attachment directory for current entry.
When called with a prefix argument, include all files in
`org-attach-directory'. With a double `C-u' prefix arg the value
of `ido-locate-org-attach-all-files' will be toggled for the
session. If you want to save it permanently for future session
then customize the variable `ido-locate-org-attach-all-files'."
(interactive "P")
(when (org-attach-dir nil)
(when (equal find-all '(16))
(setq ido-locate-org-attach-all-files
(not ido-locate-org-attach-all-files)))
(let* ((enable-recursive-minibuffers t)
(dir (if (org-xor ido-locate-org-attach-all-files
(equal find-all '(4)))
org-attach-directory
(org-attach-dir nil)))
(files (find-lisp-find-files dir "."))
(file-assoc-list
(mapcar (lambda (x)
(cons (file-name-nondirectory x)
x))
files))
(filename-list
(remove-duplicates (mapcar #'car file-assoc-list)
:test #'string=))
(filename (ido-completing-read "Org attachments: " filename-list nil t))
(longname (cdr (assoc filename file-assoc-list))))
(ido-set-current-directory
(if (file-directory-p longname)
longname
(file-name-directory longname)))
(setq ido-exit 'refresh
ido-text-init ido-text
ido-rotate-temp t)
(exit-minibuffer))))
;; Run ido-locate-org-attach when using org-open-at-point (C-c C-o) in
;; the current entry (except if you're on the header line itself it
;; will use the default behavior to open/close the entry.
(add-hook 'org-open-at-point-functions 'ido-locate-org-attach)
;; C-c o will locate files for the current entry
;; C-u C-c o will locate files for the whole file
;; C-u C-u C-c o will toggle the default current entry / whole file
(define-key org-mode-map "\C-co" 'ido-locate-org-attach)
I'll look into submitting this to be an official part of org-attach.el.
As an aside, the '(4) and '(16) are magic numbers that mean prefix arg once C-u and prefix arg twice C-u C-u before the key sequence that invoked the command interactively.
I'm looking for some help developing what I think should be an easy program.
I want something similar to Emacs tags-search command, but I want to collect all search results into a buffer. (I want to see all results of M-,)
I'm thinking this python style pseudo code should work, but I have no idea how to do this in emacs lisp? Any help would be greatly appreciated.
def myTagsGrep(searchValue):
for aFile in the tag list:
result = grep aFile seachValue
if len(result) > 0:
print aFile # to the buffer
print result # to the buffer
I would like to be able to browse through the buffer with the same features tags-apropos does.
Note that a similar question has been asked before:
Is there a way to get emacs tag-search command to output all results to a buffer?
Since I'm such a fan of igrep, I'd use it as the building block. From there it's two simple routines and you're done. With that library and these two functions, all you have to do is:
M-x igrep-tags ^SomeRegexp.*Here RET
Here's the code:
(require 'igrep)
(defun igrep-tags (regex)
(interactive "sTAGS Regexp: ")
(igrep igrep-program regex (tags-file-names)))
(defun tags-file-names ()
(save-excursion
(visit-tags-table-buffer)
(mapcar (lambda (f) (file-truename f))
(tags-table-files))))
And, because the list of files can get really long, and you likely don't care what that list is, you can add these two pieces of code which will make the filenames invisible after the grep has finished:
(add-hook 'compilation-finish-functions 'igrep-tags-hide-filenames)
(defun igrep-tags-hide-filenames (buffer stat)
"hide the filenames b/c they can get long"
(save-excursion
(set-buffer buffer)
(save-match-data
(goto-char (point-min))
(if (search-forward (combine-and-quote-strings (tags-file-names))
nil
(save-excursion (forward-line 10) (point)))
(let ((display-string "..<files from TAGS>.."))
(put-text-property (match-beginning 0) (match-end 0) 'invisible t)
(put-text-property (match-beginning 0) (match-end 0) 'display display-string))))))
To avoid the really long command line, you can use the following code (which creates a temporary file containing all the names of files from TAGS file and uses that instead):
(defun igrep-tags (regex)
(interactive "sTAGS Regexp: ")
(let ((igrep-find t)
(igrep-use-file-as-containing-files t))
(igrep igrep-program regex nil)))
(defvar igrep-use-file-as-containing-files nil)
(defadvice igrep-format-find-command (around igrep-format-find-command-use-filename-instead activate)
"use the second argument as a file containing filenames"
(if igrep-use-file-as-containing-files
(progn (with-temp-file
(setq igrep-use-file-as-containing-files (make-temp-file "tags-files"))
(insert (combine-and-quote-strings (tags-file-names))))
(setq ad-return-value (format "cat %s | xargs -e %s"
igrep-use-file-as-containing-files
(ad-get-arg 0))))
ad-do-it))
And, for those using Emacs 22 or earlier, you'll need the routine that's shipped with Emacs 23 (from subr.el)
(defun combine-and-quote-strings (strings &optional separator)
"Concatenate the STRINGS, adding the SEPARATOR (default \" \").
This tries to quote the strings to avoid ambiguity such that
(split-string-and-unquote (combine-and-quote-strings strs)) == strs
Only some SEPARATORs will work properly."
(let* ((sep (or separator " "))
(re (concat "[\\\"]" "\\|" (regexp-quote sep))))
(mapconcat
(lambda (str)
(if (string-match re str)
(concat "\"" (replace-regexp-in-string "[\\\"]" "\\\\\\&" str) "\"")
str))
strings sep)))
Here is the code I use to create a tag system for my personal notes. It uses bookmarks and treats each word in a bookmark as a single tag. Its not quite what you're looking for but it might get you started.
The first couple of functions are probably already implemented in emacs, but I wrote my own for reasons that I no longer recall.
;; FILTER keeps only elements of li for which pred returns true
(defun filter (pred li)
(let (acc)
(dolist (elem li)
(if (funcall pred elem)
(setq acc (cons elem acc))))
(reverse acc)))
(defun string-match-all-p (str li)
(if li
(if (string-match-p (car li) str)
(string-match-all-p str (cdr li))
nil)
t))
;;bookmarks as tags
(defun lookup-bookmark-tags (tagstring)
(interactive "s")
(let ((taglist (split-string tagstring " ")))
(let ((bookmark-alist (filter
(lambda (elem)
(string-match-all-p (car elem) taglist))
bookmark-alist)))
(call-interactively 'list-bookmarks))))
I then bind the 'tagging' behavior to a key (F11) and the 'lookup' behavior to another (F12).
(global-set-key [f11] 'bookmark-set)
(global-set-key [f12] 'lookup-bookmark-tags))
Hope that is useful to you.
This is what you want:
http://www.emacswiki.org/emacs/Icicles_-_Emacs_Tags_Enhancements#icicle-tags-search
This is the doc string for icicle-tags-search:
Search all source files listed in tags tables for matches for REGEXP.
You are prompted for the REGEXP to match. Enter REGEXP with `RET'.
You do not need `M-,' - you see all matches as search hits to visit.
All tags in a tags file are used, including duplicate tags from the
same or different source files.
By default, all tags files are used, but if you provide a prefix
argument then only the current tag table is used.
If your TAGS file references source files that no longer exist, those
files are listed. In that case, you might want to update your TAGS
file.
You can alternatively choose to search, not the search contexts as
defined by the context regexp you provide, but the non-contexts, that
is, the text in the files that does not match the regexp. To do this,
use `C-M-~' during completion. (This is a toggle, and it affects only
future search commands, not the current one.)
See also this page for more explanation about Icicles search:
http://www.emacswiki.org/emacs/Icicles_-_Search_Commands%2c_Overview
I'm working on autocompletion implementation in emacs for haxe programming language.
I already figured out how to obtain list of autocompletions which I wants to present. The list is in format:
'((name1 type1 desc1)
(name2 type2 desc2) ...
I want to display to user list containing text in format "name1 type1" after cursor position (like in autocomplete-mode) and desc for currently selected item in minibuffer. User should be able to select completion or give up like in auto-complete mode.
When user select something, name1 should be inserted at cursor position.
What is the best/easiest way to do this? Is there some standard emacs way to do this, or I should code something on my own?
EDIT: I have functions to get the list of autocomplete candidates based on buffer. Now I'm struggling how to integrate that to autocomplete-mode. Since get-completes is heavy operation, I would like to trigger it only if cursor is on "." character.
Here's the code I have.
(defun get-completes-from-haxe (hxml-file file pos)
(let* ((completion-buffer (get-buffer-create "*haxe-completions*"))
(cmd (concat "cd " (file-name-directory hxml-file) "; haxe " hxml-file " --display " file "#" (number-to-string pos))))
(ignore-errors
(shell-command cmd completion-buffer)
(let ((clist (xml-parse-region 1 (buffer-size completion-buffer) completion-buffer))
(completes nil))
(dolist (s (cddar clist))
(when (listp s)
(let* ((item (cdr s))
(name (cdaar item))
(type (car (cddadr item)))
(desc (cdddr item)))
(setf completes (cons name completes)))))
completes))))
(defun file-find-upwards (buffer file-name)
;; Chase links in the source file and search in the dir where it points.
(setq dir-name (or (and (buffer-file-name buffer)
(file-name-directory (file-chase-links
(buffer-file-name buffer))))
default-directory))
;; Chase links before visiting the file. This makes it easier to
;; use a single file for several related directories.
(setq dir-name (file-chase-links dir-name))
(setq dir-name (expand-file-name dir-name))
;; Move up in the dir hierarchy till we find a change log file.
(let ((file1 (concat dir-name file-name))
parent-dir)
(while (and (not (file-exists-p file1))
(progn (setq parent-dir
(file-name-directory
(directory-file-name
(file-name-directory file1))))
;; Give up if we are already at the root dir.
(not (string= (file-name-directory file1)
parent-dir))))
;; Move up to the parent dir and try again.
(setq file1 (expand-file-name file-name parent-dir)))
;; If we found the file in a parent dir, use that. Otherwise,
;; return nil
(if (or (get-file-buffer file1) (file-exists-p file1))
file1
nil)))
(defun get-candidate-list (buffer pos)
(get-completes-from-haxe
(file-find-upwards buffer "compile.hxml")
(buffer-file-name buffer)
pos))
I'd suggest the excellent package AutoComplete: http://www.emacswiki.org/emacs/AutoComplete
You can define custom sources for autocomplete and it seems fairly straight forward.
Why keep reinventing wheels? company-mode has support for a few languages
The ido-completing-read from ido.el is another way to do it.
An useful feature of it is that you can use regular expressions to filter out the candidates, and you can toggle this feature on and off on the fly. See ido.el for more details.
ido package has convenient completion functionality called 'ido-completing-read'. For example, here's a simple tweak to make it show lists in a line-by-line basis:
(defun x-ido-completing-read
(prompt choices &optional predicate require-match initial-input hist def)
(let* ((indent (concat "\n" (make-string (length prompt) ? )))
(ido-decorations
`("" "" ,indent ,(concat indent "...")
"[" "]" " [No match]" " [Matched]" " [Not readable]" " [Too big]")))
(ido-completing-read prompt choices predicate require-match initial-input hist def)))
Inside the yasnippet code, available from google code, they use 'dropdown-list.el' by Jaeyoun Chung to display the possible snippets that could be used at point. This gives a popup (tooltip-like) menu at the cursor position you can select with the arrow keys and enter or you can select by number.
http://www.emacswiki.org/emacs/dropdown-list.el