The lisp that convert string and grep in emacs? - emacs

I have a file formatted as
abc|<hoge>
a|<foo> b|<foo> c|<foo>
family|<bar> guy|<bar>
a|<foo> comedy|<bar> show|<foo>
action|<hoge>
and want to search search strings by raw (Like "a comedy show" instead of a|<foo> comedy|<bar> show|<foo>) on emacs.
I believe using grep on lisp would be the easiest answer but I have not yet figured out how. Would someone enlighten me?

Well, grep is a separate program (which you could also use). In Emacs, you'd use the function search-forward-regexp, which you can run using either M-x (hold Meta, usually Alt key, and press x) and then type search-forward-regexp and press Return.
You'll then need to key in the regexp to search. Put simply, it seems like you want to ignore |< something >, which in Emacs's variety of regexes is:
|<[a-z]+>
so you might search for e.g.
a|<[a-z]+> comedy|<[a-z]+> show|<[a-z]+>
You can create a Lisp function to convert a string this way, by splitting it on spaces and adding the regex sequences:
(defun find-string-in-funny-file (s) ; Define a function
"Find a string in the file with the |<foo> things in it." ; Document its purpose
(interactive "sString to find: ") ; Accept input if invoked interactively with M-x
(push-mark) ; Save the current location, so `pop-global-mark' can return here
; (usually C-u C-SPC)
(goto-char 0) ; Start at the top of the file
(let ((re (apply #'concat ; join into one string…
(cl-loop
for word in (split-string s " ") ; for each word in `s'
collect (regexp-quote word) ; collect that word, plus
collect "|<[a-z]+> ")))) ; also the regex bits to skip
(search-forward-regexp ; search for the next occurrence
(substring re 0 (- (length re) 2))))) ; after removing the final space from `re'
You can explore what those functions each do in the (online) Emacs Lisp manual; for example, pick from the menu "Help→Describe→Function" or press C-h f (Control+h, then f) and type interactive (RET) for the manual's documentation of that special form.
If you paste the above (defun) into the *scratch* buffer, and position the cursor after the final ) at the end, you can press C-j to evaluate it, and the function will remain with you until you close Emacs.
If you save it in a file named something .el, you can use M-x load-file to load it again in future.
If you then load your "funny" file, and type M-x find-string-in-funny-file, it'll search your file for your string, and leave the cursor on the string. If it's not found, you'll see a message to that effect.
BUGS: The function is less than spectacular style

Related

A quick way to repeatedly enter a variable name in Emacs?

I was just typing in this sort of code for Nth time:
menu.add_item(spamspamspam, "spamspamspam");
And I'm wondering if there's a faster way to do it.
I'd like a behavior similar to yasnippet's mirrors, except
I don't want to create a snippet: the argument order varies from
project to project and from language to language.
The only thing that's constant is the variable name that needs to be
repeated several times on the same line.
I'd like to type in
menu.add_item($,"")
and with the point between the quotes, call the shortcut and start typing,
and finally exit with C-e.
This seems advantageous to me, since there's zero extra cursor movement.
I have an idea of how to do this, but I'm wondering if it's already done,
or if something better/faster can be done.
UPD The yasnippet way after all.
Thanks to thisirs for the answer. This is indeed the yasnippet code I had initially in mind:
(defun yas-one-line ()
(interactive)
(insert "$")
(let ((snippet
(replace-regexp-in-string
"\\$" "$1"
(substring-no-properties
(delete-and-extract-region
(line-beginning-position)
(line-end-position))))))
(yas/expand-snippet snippet)))
But I'm still hoping to see something better/faster.
yasnippet can actually be used to create a snippet on-the-fly:
(defun yas-one-line ()
(interactive)
(let ((snippet (delete-and-extract-region
(line-beginning-position)
(line-end-position))))
(yas-expand-snippet snippet)))
Now just type:
menu.add_item($1,"$1")
and call yas-one-line. The above snippet is expanded by yasnippet!
You could try
(defvar sm-push-id-last nil)
(defun sm-push-id ()
(interactive)
(if (not sm-push-id-last)
(setq sm-push-id-last (point))
(text-clone-create sm-push-id-last sm-push-id-last
t "\\(?:\\sw\\|\\s_\\)*")
(setq sm-push-id-last nil)))
after which you can do M-x sm-push-id RET , SPC M-x sm-push-id RET toto and that will insert toto, toto. Obviously, this would make more sense if you bind sm-push-id to a convenient key-combo. Also this only works to insert a duplicate pair of identifiers. If you need to insert something else, you'll have to adjust the regexp. Using too lax a regexp means that the clones will tend to overgrow their intended use, so they may become annoying (e.g. you type foo") and not only foo but also ") gets mirrored on the previous copy).
Record a macro. Hit F3 (or possibly C-x (, it depends) to begin recording. Type whatever you want and run whatever commands you need, then hit F4 (or C-x )) to finish. Then hit F4 again the next time you want to run the macro. See chapter 17 of the Emacs manual for more information (C-h i opens the info browser, the Emacs manual is right at the top of the list).
So, for example, you could type the beginning of the line:
menu.add_item(spamspamspam
Then, with point at the end of that line, record this macro:
F3 C-SPC C-left M-w C-e , SPC " C-y " ) ; RET F4
This copies the last word on the line and pastes it back in, but inside of the quotes.

A basic function for emacs

I have never written an emacs function before and was wondering if anyone could help me get started. I would like to have a function that takes a highlighted region parses it (by ",") then evaluates each chunk with another function already built into emacs.
The highlighted code may look something like this: x <- function(w=NULL,y=1,z=20){} (r code), and I would like to scrape out w=NULL, y=1, and z=20 then pass each one a function already included with emacs. Any suggestions on how to get started?
A lisp function is defined using defun (you really should read the elisp intro, it will save you a lot of time - "a pint of sweat saves a gallon of blood").
To turn a mere function into an interactive command (which can be called using M-x or bound to a key), you use interactive.
To pass the region (selection) to the function, you use the "r" code:
(defun my-command (beg end)
"Operate on each word in the region."
(interactive "r")
(mapc #'the-emacs-function-you-want-to-call-on-each-arg
;; split the string on any sequence of spaces and commas
(split-string (buffer-substring-no-properties beg end) "[ ,]+")))
Now, copy the form above to the *scratch* emacs buffer, place the point (cursor) on a function, say, mapc or split-string, then hit C-h f RET and you will see a *Help* buffer explaining what the function does.
You can evaluate the function definition by hitting C-M-x while the point is on it (don't forget to replace the-emacs-function-you-want-to-call-on-each-arg with something meaningful), and then test is by selecting w=NULL,y=1,z=20 and hitting M-x my-command RET.
Incidentally, C-h f my-command RET will now show Operate on each word in the region in the *Help* buffer.

emacs equivalent of ct

looking for an equivalent cut and paste strategy that would replicate vim's 'cut til'. I'm sure this is googleable if I actually knew what it was called in vim, but heres what i'm looking for:
if i have a block of text like so:
foo bar (baz)
and I was at the beginning of the line and i wanted to cut until the first paren, in visual mode, I'd do:
ct (
I think there is probably a way to look back and i think you can pass more specific regular expressions. But anyway, looking for some emacs equivalents to doing this kind of text replacement. Thanks.
Here are three ways:
Just type M-dM-d to delete two words. This will leave the final space, so you'll have to delete it yourself and then add it back if you paste the two words back elsewhere.
M-z is zap-to-char, which deletes text from the cursor up to and including a character you specify. In this case you'd have to do something like M-2M-zSPC to zap up to and including the second space character.
Type C-SPC to set the mark, then go into incremental search with C-s, type a space to jump to the first space, then C-s to search forward for the next space, RET to terminate the search, and finally C-w to kill the text you selected.
Personally I'd generally go with #1.
as ataylor said zap-to-char is the way to go, The following modification to the zap-to-char is what exactly you want
(defun zap-up-to-char (arg char)
"Like standard zap-to-char, but stops just before the given character."
(interactive "p\ncZap up to char: ")
(kill-region (point)
(progn
(search-forward (char-to-string char) nil nil arg)
(forward-char (if (>= arg 0) -1 1))
(point))))
(define-key global-map [(meta ?z)] 'zap-up-to-char) ; Rebind M-z to our version
BTW don't forget that it has the ability to go backward with a negative prefix
That sounds like zap-to-char in emacs, bound to M-z by default. Note that zap-to-char will cut all the characters up to and including the one you've selected.

emacs: interactively search open buffers

Is there a way to search all the open buffers for a particular pattern?
C-s interactively searches current buffer.
Similarly, is there something that searches all the open buffers?
I know I can use "occur", but "Occur" brings a new buffer and changes/messes with the buffer organization.
The built-in multi-occur-in-matching-buffers hasn't been mentioned. I use a modified version of this (because I invariably want to search all buffers, and specifying a buffer name pattern each time is annoying).
(defun my-multi-occur-in-matching-buffers (regexp &optional allbufs)
"Show lines matching REGEXP in all file-visiting buffers.
Given a prefix argument, search in ALL buffers."
(interactive (occur-read-primary-args))
(multi-occur-in-matching-buffers "." regexp allbufs))
(global-set-key (kbd "M-s /") 'my-multi-occur-in-matching-buffers)
To invert the behaviour of the prefix argument so that the default behaviour is to search all buffers, change the call to:
(multi-occur-in-matching-buffers "." regexp (not allbufs))
(and, of course, update the docstring accordingly.)
I've fixed the TODO:
;; I know that string is in my Emacs somewhere!
(require 'cl)
(defcustom search-all-buffers-ignored-files (list (rx-to-string '(and bos (or ".bash_history" "TAGS") eos)))
"Files to ignore when searching buffers via \\[search-all-buffers]."
:type 'editable-list)
(require 'grep)
(defun search-all-buffers (regexp prefix)
"Searches file-visiting buffers for occurence of REGEXP. With
prefix > 1 (i.e., if you type C-u \\[search-all-buffers]),
searches all buffers."
(interactive (list (grep-read-regexp)
current-prefix-arg))
(message "Regexp is %s; prefix is %s" regexp prefix)
(multi-occur
(if (member prefix '(4 (4)))
(buffer-list)
(remove-if
(lambda (b) (some (lambda (rx) (string-match rx (file-name-nondirectory (buffer-file-name b)))) search-all-buffers-ignored-files))
(remove-if-not 'buffer-file-name (buffer-list))))
regexp))
(global-set-key [f7] 'search-all-buffers)
ibuffer might help you. Have a look at this article. I imagine that this might be most interesting for you:
'O' - ibuffer-do-occur
- Do an occur on the selected buffers.
This does a regex search on all the selected buffers and displays the result in an occur window. It is unbelievably useful when browsing through code. It becomes truly awesome when you combine it with the ‘filter’ powers of ibuffer (coming up ahead). Eg: Do C-x C-b, mark all files using (say) Perl major-mode, do occur to find out all places where a certain function is mentioned in these files. Navigate to the point at will through the Occur window.
'M-s a C-s' - ibuffer-do-isearch
- Do an incremental search in the marked buffers.
This is so awesome that you have to try it right this instant. Select two or more buffers, hit the hotkey, search for something that occurs in all these buffers. These two features alone are enough to make me a lifelong fan of IBuffer. Go do it now!
Taking a clue from Leo's comment to Bozhidar:
(defun my-isearch-buffers ()
"isearch multiple buffers."
(interactive)
(multi-isearch-buffers
(delq nil (mapcar (lambda (buf)
(set-buffer buf)
(and (not (equal major-mode 'dired-mode))
(not (string-match "^[ *]" (buffer-name buf)))
buf))
(buffer-list)))))
You might have to tweak the conditions inside the and to filter whatever other kinds of buffers you want to ignore.
Although this is not exactly what you're asking for, I search multiple files using grep (M-X grep) and grep-find (M-X grep-find).
This sort of does what you want, in that when you've come to the end of matches for the string/regexp you're searching for, the next search command will start in a new buffer.
(setq isearch-wrap-function 'isearch-bury-buffer-instead-of-wrap)
(defun isearch-bury-buffer-instead-of-wrap ()
"bury current buffer, try to search in next buffer"
(bury-buffer))
It doesn't switch to a different buffer when the search fails, and when you "back up" the search results by pressing <backspace>, you won't pop back into the previous buffers searched.
In Icicles, C-c ' is command icicle-occur, which can search multiple buffers.
C-u C-c ' searches a set of buffers that you choose. You can choose by dynamically filtering the buffer names with your minibuffer input, then hit C-! to search all of those buffers whose names match. Similarly, C-99 C-c ' searches only the buffers that are visiting files.
Like occur and grep, icicle-occur searches line by line. More generally, instead of using lines as the search contexts you can use any buffer portions at all. C-c ` (backquote instead of quote) is command icicle-search. With a non-negative prefix arg it searches a set of buffers that you choose.
The first thing you do is give it a regexp that defines the search contexts. E.g., if you give it .* then it acts like icicle-occur: each search context is a line. If you give it a regexp that matches only function definitions then those are the search contexts, and so on.
http://www.emacswiki.org/emacs/Icicles_-_Search_Commands%2c_Overview

How to get Emacs to unwrap a block of code?

Say I have a line in an emacs buffer that looks like this:
foo -option1 value1 -option2 value2 -option3 value3 \
-option4 value4 ...
I want it to look like this:
foo -option1 value1 \
-option2 value2 \
-option3 value3 \
-option4 value4 \
...
I want each option/value pair on a separate line. I also want those subsequent lines indented appropriately according to mode rather than to add a fixed amount of whitespace. I would prefer that the code work on the current block, stopping at the first non-blank line or line that does not contain an option/value pair though I could settle for it working on a selected region.
Anybody know of an elisp function to do this?
Nobody had what I was looking for so I decided to dust off my elisp manual and do it myself. This seems to work well enough, though the output isn't precisely what I asked for. In this version the first option goes on a line by itself instead of staying on the first line like in my original question.
(defun tcl-multiline-options ()
"spread option/value pairs across multiple lines with continuation characters"
(interactive)
(save-excursion
(tcl-join-continuations)
(beginning-of-line)
(while (re-search-forward " -[^ ]+ +" (line-end-position) t)
(goto-char (match-beginning 0))
(insert " \\\n")
(goto-char (+(match-end 0) 3))
(indent-according-to-mode)
(forward-sexp))))
(defun tcl-join-continuations ()
"join multiple continuation lines into a single physical line"
(interactive)
(while (progn (end-of-line) (char-equal (char-before) ?\\))
(forward-line 1))
(while (save-excursion (end-of-line 0) (char-equal (char-before) ?\\))
(end-of-line 0)
(delete-char -1)
(delete-char 1)
(fixup-whitespace)))
In this case I would use a macro. You can start recording a macro with C-x (, and stop recording it with C-x ). When you want to replay the macro type C-x e.
In this case, I would type, C-a C-x ( C-s v a l u e C-f C-f \ RET SPC SPC SPC SPC C-x )
That would record a macro that searches for "value", moves forward 2, inserts a slash and newline, and finally spaces the new line over to line up. Then you could repeat this macro a few times.
EDIT: I just realized, your literal text may not be as easy to search as "value1". You could also search for spaces and cycle through the hits. For example, hitting, C-s a few times after the first match to skip over some of the matches.
Note: Since your example is "ad-hoc" this solution will be too. Often you use macros when you need an ad-hoc solution. One way to make the macro apply more consistently is to put the original statement all on one line (can also be done by a macro or manually).
EDIT: Thanks for the comment about ( versus C-(, you were right my mistake!
Personally, I do stuff like this all the time.
But I don't write a function to do it unless I'll be doing it
every day for a year.
You can easily do it with query-replace, like this:
m-x (query-replace " -option" "^Q^J -option")
I say ^Q^J as that is what you'll type to quote a newline and put it in
the string.
Then just press 'y' for the strings to replace, and 'n' to skip the wierd
corner cases you'd find.
Another workhorse function is query-replace-regexp that can do
replacements of regular expressions.
and also grep-query-replace, which will perform query-replace by parsing
the output of a grep command. This is useful because you can search
for "foo" in 100 files, then do the query-replace on each occurrence
skipping from file to file.
Your mode may support this already. In C mode and Makefile mode, at least, M-q (fill-paragraph) will insert line continuations in the fill-column and wrap your lines.
What mode are you editing this in?