Search and Replace in Emacs with Icicles - search

I've been using Emacs for a while now and am trying out Icicles. When I run the sequence of commands
C-c`\([a-z]*\)
S-TAB
C-| x\1y
it transforms the scratch buffer from
;; This buffer is for notes you don't want to save, and for Lisp evaluation.
;; If you want to create a file, visit that file with C-x C-f,
;; then enter the text in that file's own buffer.
to
;; Xy xy xy xy xy xy xy'xy xy xy xy, xy xy Xy xy.
;; Xy xy xy xy xy xy xy, xy xy xy xy XY-xy XY-xy,
;; xy xy xy xy xy xy xy'xy xy xy.
My understanding is that it should instead attach an 'x' to the start of each word and a 'y' to the end of each word. What am I doing wrong here? I have tried this with emacs -Q and gotten the same results. Also, icicle-search-replace-literally-flag is unchanged from its default value of nil. What am I doing wrong? Thanks!
Edit: Sorry, I omitted the group in the regexp in the original post; however, I did use it in the test and still get the same result.

I do not use icicles but the effect is reproducible with the ordinary query-replace-regexp.
The problem is that you just do not define any group in your regular expression which you refer to in the replacement. Therefore the group reference \1 in the replacement string is empty.
Furthermore, you should use [a-z]+ instead of [a-z]* since [a-z]* also matches the empty string what you probably do not want.
To put the stuff you want to refer to into a group wrap it by paranthesis \(\). In your example the regular expression would look like \([a-z]+\). With this regular expression you can directly use your replacement string.
The alternative is to leave the regular expression as it is and refer to the whole match with \& instead of \1 in your replacement string.

Be sure that your version of file icicles-cmd2.el is dated after 2013-12-10. I fixed a bug wrt \N replacements on that date.
Other suggestions:
Proceed slowly, rather than immediately jumping into complex replacements etc. Icicles search and replacement are different from what you might be used to or expect.
Check the current values of all of the user options that affect Icicles search and replacement.

Related

Editing multiple lines of same parameter

I'm working with a large dataset and multiple lines need change on a certain parameter. Something like this for example:
funct(35, circle, square, triangle);
funct(42, sphere, cube, prism);
funct(74, disc, rhombus, rectangle);
needs to become:
funct(35, circle, my_square, other_triangle);
funct(42, sphere, my_cube, other_prism);
funct(74, disc, my_rhombus, other_rectangle);
How could I go about doing this?
An additional vim approach. Visually select all of the lines you would like to change, and then type this:
:norm 2Wimy_<C-v><esc>Wiother_
Note that <C-v> and <esc> are ctrl-v and esc, not text. Or, if you want to do this on every line, do this:
:%norm 2Wimy_<C-v><esc>Wiother_
You could also do this on lines in a certain range. For example, lines 3-100:
:3,100norm 2Wimy_<C-v><esc>Wiother_
I'll speak about emacs because I just love emacs !
to enter commands in the prompt : Alt + x
For small datasets
You can install the multiple-cursors package. It's like the Ctrl+D in SublimeText. Here is the doc.
For big datasets with some controls
You can use built-in package query-replace. It will replace the string/regex you want with another. Documentation.
The advantage of this one is that you can choose if you want to replace or not each occurence.
For big datasets without control
The built-in packages replace-string and replace-regexp will replace the pattern of your choice with a string or another pattern.
replace-regexp
replace-string
If you just want to rename some variables, multiples-cursors, replace-string and query-replace are fine.
If you want to replace patterns in huge datasets, replace-regexp is fun, but nothing's better than a script (bash, js, python ...).
There are amazing books about sed and awk bash commands (sed & awk, 2nd Edition)
With Vim:
:%s/\vfunct\(([^,]+,\s*){2}\zs/my_/
The 2 above is the number of arguments you want to skip.
The catch: this breaks if some parameters are themselves function calls. There are plugins that allows you to cope with that situation.
Using vim's regex engine:
:%s/\v(%(\s*\w+,){PARAMETER_NUMBER})(\s+)(\w+)/\1\2NEW_PREFIX\3
Substitute PARAMETER_NUMBER with the index (starting from 0) of the parameter you'd like to change and NEW_PREFIX with the prefix you'd like to add to it.
For instance, running:
:%s/\v(%(\s*\w+,){2})(\s+)(\w+)/\1\2my_\3
Changes your example code into:
funct(35, circle, my_square, triangle);
funct(42, sphere, my_cube, prism);
funct(74, disc, my_rhombus, rectangle);
You can modify this to customize it in other ways by changing the order of the backreferences (the \1, \2 and \3) at the end of the command. \1 refers to the parameters before the one you're changing, \2 refers to the whitespace just before the parameter you're changing and \3 to the parameter itself.
I'm aware of multiple-cursors, and they look really cool, but I've been to lazy to learn them. Here's a solution using only Emacs built ins.
(defun align-regexp-comma (beginning end)
"Align columns using comma as a delimiter."
(interactive "*r")
(align-regexp beginning end
",\\(\\s-*\\)" 1 1 t))
(global-set-key (kbd "C-<return>") 'cua-rectangle-mark-mode)
Then select the region you of interest, do M-x align-regexp-comma, which should align the arguments, then you can use C-<return> to start the rectangle mark, which lets you edit several lines at once. If you then want to remove the aligning spaces, use query-regexp-replace (M-%) with ", +" -> ", ".

Strange SVG path syntax used in Snap.svg tutorial?

While looking through the Snap.svg tutorial, I came across the following line of code that made me do a double take:
// Now lets create pattern
var p = s.path("M10-5-10,15M15,0,0,15M0-5-20,15")
What is M10-5-10,15? At first, I thought it may have been some kind of coordinate-range syntax, but that wouldn't really make much sense in this case, and I couldn't find anything remotely close to that in the SVG path spec. I also couldn't find anything of note in the Snap.svg docs.
Interestingly enough, that code does seem to draw the desired pattern...
The simplest answer is often the right one. There is no special syntax - the coordinates are just concatenated together with no white space.
The clue is the command: M is the moveto command, which doesn't normally draw anything. If you look in the spec, however, you'll notice the following:
If a moveto is followed by multiple pairs of coordinates, the
subsequent pairs are treated as implicit lineto commands.
So, a moveto can actually have multiple coordinate pairs, and anything after the first pair is treated as a lineto command. The mystery syntax is, in reality, just a concise (but less readable) way of writing M10,-5 -10,15 M15,0 0,15 M0,-5 -20,15, the hyphens being the negative signs.
Simply looking at the SVG path grammar also shows quite clearly that the arguments to moveto are coordinate-pairs, and coordinates are simple numbers.
I suppose the key thing to take away is that SVG paths don't really need whitespace or commas, unless the numbers would be ambiguous without them.

Record syntax clarification

OK, so here's an unusual one. Every time you see an example of Haskell's record syntax, it always looks like
Sphere {center = 0, radius = 2}
or similar. My question is... are those curly brackets actually part of the record syntax? Or are they actually shorthand for layout? In other words, can you actually write something like
Sphere
center = 0
radius = 2
and have it work?
I doubt it would be very useful to do this - it takes up a lot of visual space - but I'm just curious as to whether this is syntactically valid or not.
Layout is an alternative to explicit braces and semicolons.
Record syntax uses explicit braces and commas.
So no, you can't use layout as part of record syntax.
Haskell Report 2010 ยง2.7 Layout:
Haskell permits the omission of the braces and semicolons used in several grammar productions, by using layout to convey the same information.
OK, well I thought I'd put this question here in case anybody was interested. Having consulted the Haskell Report itself, it appears that the braces are literally a formal part of the record construct:
http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-690004.2.1
That means that these tokens actually have two distinct meanings in Haskell - as declaration delimiters when layout is not being used, and as record delimiters. I bet that leads to some interesting parser edge-cases!
(I also note in passing that EmptyDataDecls appears to be on by default in Haskell 2010, which is worth knowing...)
After Sphere, the lexer won't insert a brace. Why should it? You dont expect a brace inserted in code like:
z = x
+ y
either, do you?

Vim Substitution

I always wanted to know, how you can substitute within given parameters.
If you have a line like this:
123,Hello,World,(I am, here), unknown
and you wnat to replace World with Foobar then this is an easy task: :%s/World/Foobar/
Now I wonder how I can get rid of a , which is wihtin the ( ).
Theoretically I just have to find the first occurance of ( then substitute the , with a blank until ).
Try lookahead and lookbehind assertions:
%s/([^)]*\zs,\ze.*)//
(\zs and \ze tell where pattern starts and end)
or
%s/\(([^)]*\)\#<=,\(.*)\)\#=//
The first one is more readable, the second one uses \( ... \) groupings with parentheses inside groups which makes it look like obfuscated, and \#<= which apart from being a nice ASCII-art duck is the lookbehind operator, and \#= that is the lookahead operator.
References: :help pattern (more detail at :help /\#=, :help /\ze, etc.)
You use the GUI and want to try those commands? Copy them into the clipboard and run :#+ inside Gvim.
Modifying slightly the answer of #Tom can give you a quite good and "a bit" more readable result :
%s/\(.*\)(\(.*\),\(.*\))\(.*\)/\1(\2\3)\4/
That way you will have : in \1 will store what is at the left outside of the parenthesis, \4 what is at the right outside of the parenthesis and \2 and \3 what is inside the parenthesis, respectively on the left (\2) and on the right (\3).
With that you can easily swap your elements if your file is organised as column.
You can also select the text you want to change (either with visual or visual-block modes) and enter the : to start the replace command. vi will automatically start the command with :'<,'> which applies the command to the selected area.
Replacing a , can be done with:
:'<,'>s/,/ /g
For your example, this is the same thing as suggested by #ubuntuguy
%s/\(.*\)(\(.*\),\(.*\)/\1(\2\3
This will do the exact replacement you want.
Yet another approach, based on the fact that actually you want to substitute only the first occurrence of , inside the parenthesis:
:%s#\((.\{-}\),#\1 #
Explanation:
:%s for substitution in the whole file (don't use % if you want to work only with the current line)
we can use # or : as a delimiter to make the command more readable
in (.\{-} we ask to find any symbol (dot) after the left parenthesis and the rest stands for 0 or more occurrence (as few as possible) of this symbol. This expression is put inside \(...\) to be able to refer to this group as \1 in the future.

Is there a good Vi(m) command for transposing arguments in a function call? Bonus points for Emacs

For example if I have some code like:
foo = bar("abc", "def", true, callback);
Is there a nice command to move true to the 1st or 2nd position leaving the commas intact?
P.S as a bonus my friend want to know if this works in Emacs too.
In Vim if you place the cursor at the start of the first word and do dWWP then it will have the desired effect. Here is a breakdown:
dW delete the current word, including the comma and the following whitespace
W move to the start of the next word
P insert the deleted text before the cursor
This will work if there are further parameters after the pair to be swapped - it will need to be modified if there are only two parameters or you want to swap the last two parameters, since it will paste the text after the closing bracket.
Alternatively you could use a regex substitution:
:%s/(\([^,]\+\),\s*\([^,)]\+\)/(\2, \1/
This will find the first two arguments after the open bracket and swap them.
update:
A search of vim.org found the swap parameters plugin, which should do exactly what you want and can handle situations that either of the above methods cannot.
I don't know the answer for vi, but in Emacs, transpose-sexps (C-M-t) will swap two arguments either side of the cursor. Actually transpose-words (M-t) was my first guess, but that leaves the quotes behind.
You need a transpose emacs command. But its limited to not guessing that its transposing in lists, it only considers text (it can't guess the 1st, 2nd word of list). Try this.
Keep your cursor at after comma of true. Use M-x transpose-words. By default it will transpose with next word from the point. Shortcut is M-t.
You can use C-u 2 M-t for transpose with next second word.
Now coming to your question. If you want to move true, to backward 1 word, use C-u -1 M-t, and for backward 2 words C-u -2 M-t.
Am not a VIM guy. So sorry bout that.
If you want to do this as a refactoring, not just as text manipulation, I'd suggest looking into Xrefactory, a refactoring tool for Emacsen (free for C/Java, commercial for C++).
Transposing previous (Ctrl-t p) and next (Ctrl-t n) argument ... add the
following into your .vimrc file:
map <C-t>p ?,\\|(<CR>wd/,\\|)<CR>?,\\|(<CR>"_dw?,\\|(<CR>a, <C-c>?,<CR>P/,<CR>w
map <C-t>n ?,\\|(<CR>wv/,<CR>d"_dw/\\,\\|)<CR>i, <C-r>"<C-c>?,<CR>?,\\|(<CR>w

Resources