Using vim-surround with argument to a function - vim

I'm new to vim-surround. I would like to achieve the folowing.
I have an html file with many images as this (* is the cursor position):
<img src="ima*ges/pages/img1.jpg" alt="">
And I would like to change it with this:
<img src="{{ media_url('images/pages/img1.jpg') }}" alt="">
I tried ys"f but it doesn't work as expected. I would like to change all jpg images with such pattern, I'm aware of vim-repeat I will dig into it once I could change the first correctly.
If you know a way to achieve this to all jpg occurrences I would be really thankful.
Thank you very much.

Personally I am a big fan of custom surroundings.
Example of a custom surrounding, by adding the following to ~/.vim/after/ftplugin/html.vim:
let b:surround_{char2nr('m')} = "{{ media_url('\r') }}"
Now in file's with the FileType of html you can use the m surrounding. It might be best to have 2 surroundings one for the curly braces and one for media_url function.
For more information see :h surround-customizing

You will need to record a macro and then execute on all images.
In normal mode position your cursor at first " start recording a macro with qq then:
cs"'va'hSbimedia_urlbvf)S{gvS}gvS"q
Now you have recorded a macro in q register. Execute it whit #q.
Position your self at next image(") and the #q. You can combine it with find (/"ima) then combine n and #q.
If you position yourself with find on next word while recording macro you can prefix macro with number ... 10#q execute it on 10 images....

:substitute seems to be a better fit for this job:
:s#\v<img src="\zs\S{-}\.jpg\ze"#{{ media_url('\1') }}#g
If you don't want to change all of them, add c after the g to ask for user consent before each surrounding.

Related

Vim Search Replace Regexp If this, not that, and not that

I have a page and I'm trying to fix abunch of links to it with regexps.
For example. Somethings were already replaced, and they are in there like href="/websites/site..", so those I'm leaving alone. However, some were replaced from absolute to relative but the script I got that did it thought the files I was changing were at the web root directory they were.. so when i get a match like href="/file" I want to match. Anywho. Here's the regexp I'm working
%s#\v(href\="/)&((href\="/websites)#!|(href\="//)#!)#href="/websites/site/#g
However, it will change a set of entries like this
<a href="/websites/site/websites/site/dog.html">
<a href="/websites/site//">
<a href="doghouse.html">
<a href="/websites/site/doghouse.html">
to this
<a href="/websites/site/href="/websites/site/websites/site/dog.html">
<a href="/websites/site/href="/websites/site//">
<a href="doghouse.html">
<a href="/websites/site/href="/websites/site/doghouse.html">
Any help on getting this search/replace vim regexp right would be greatly appreciated.
Thanks
Okay, here goes!
:%s/\vhref\="\/(\/|websites)#!/href="\/websites\/site
Explanation:
All of the strings you are wanting to change begin with href="/, so including that as a literal seems like the right call.
Then, you want to make sure that neither the literal "websites" nor "/" are present, so that works with (\/|website)#!, then, you want to change it out with the new addition, so the rest is required.
You can do it with :help :global. From your explaination I'm not completely sure what you're trying to do, but you can use this command to exclude lines with "websites" like this: :g!'href="/websites/site/'s/LESS_COMPLICATED_REGEX/RESULT/
Here I use :g! to execute command on all lines that don't match the regex in '' (you can use / instead of ' as usual). The command to execute is the ususal :s but here you can not worry that it will run on the lines that have "websites" string.

Vim fastest way to select a block of text lines until a specific character

I have a page with some wikicode (tikiwiki) which includes html like such :
{DIV(class="Act PersonInterested")}
{HTML()}
multiple
lines
of
html (svg)
code
{HTML}
{DIV}
{DIV(class="Act CHActivePFOnly")}
{HTML()}
multiple
lines
of
html (svg)
code
{HTML}
{DIV}
I want with vim to delete the text between the {HTML()}{HTML} wiki tags. dt{ doesn't work...
The most handy option I found is to record a macro, like that one :
qa -> Records macro in register a
v/{ -> Visual selects text until next '{' symbol
q -> Stops recording
#a -> Applies macro from the current line
Then I move to the next line and reapply the macro with '#a' and so on until I finish to empty all the tags.
My question is, there must be somehow a faster approach, that I overlooked... Like a g: one or even simpler. I would be pleased to learn about it, and also, I didn't find much answers here or duckducking about that specific issue.
Thanks !
Following would suffice
g/{HTML/,/{HTML/ d_
This assumes, as do the other answers, you don't have a {HTML... anywhere between your real tags. If you do, the only reliable way to do this is to use a parser.
Breakdown
g : start a global command
/ : separator
{HTML : search for {HTML
/ : separator
,/{HTML/ : set a range from the previous search result up until the next {HTML tag
d_ : delete to the empty register. As I have my clipboard synchronized with deletes, without the `_`, each delete goes to my windows clipboard slowing things down a lot in large files.
You could do it with:
:g/{HTML(/norm jd/HTML^M
or:
:g/{HTML(/norm jV/HTML^Mkd
if you are more confident with visual mode.
Press Ctrl+V, followed by Enter to obtain ^M.
did I understand the question right?
%s/{HTML()}\zs\_.\{-}\ze{HTML}//g
does the above command work for you?
You can also just record more complex macro ond then repeat it.
qa -> Records macro in register a
/{html()<cr> -> Find next
j -> Go down one line
d/{html}<cr> -> delete to closing html tag
q -> Stops recording
100#a -> Applies macro 100 times or less if there is no matches

How to extract text matching a regex using Vim?

I would like to extract some data from a piece of text with Vim. The input looks like so:
72" title="(168,72)" onmouseover="posizione('(168,72)');" onmouseout="posizione('(-,-)');">>
72" title="(180,72)" onmouseover="posizione('(180,72)');" onmouseout="posizione('(-,-)');">>
72" title="(192,72)" onmouseover="posizione('(192,72)');" onmouseout="posizione('(-,-)');">>
72" title="(204,72)" onmouseover="posizione('(204,72)');" onmouseout="posizione('(-,-)');">>
The data I need to extract is contained in the title="(168,72)" portions of the input. In particular, I am interested in extracting coordinate pairs in parentheses.
I thought about using Vim to first delete everything before title=", but I am not really a regex guru, so I am asking you. If anyone has any hint, please let me know! :)
This will replace each line with a tab-delimited list of coordinates per line:
:%s/.* title="(\(\d\+\),\(\d\+\))".*/\1\t\2
This task can be achieved with a much simpler solution and with few keystrokes using normal command:
:%normal df(f)D
This means:
% - Run normal command on all file lines;
normal - run the following commands in normal mode;
df( - delete everything until you find a parenthesis (parenthesis included);
f) - move the cursor to );
D - delete everything until the end of the line.
You can also set a range, for example, run this from line 5 to 10:
:5,10normal df(f)D
If you want an ad hoc solution for this one-off case, it might be quicker simply to select a visual block using CTRL-v. This will let you select an arbitrary column of text (in your case, the column containing title="(X,Y)"), which can then be copied as usual using y.
you can match everything inside title=() and discard everything else like this:
:%s,.*title="(\(.*\))".*,\1,

Vim Surround: Create new tag but don't indent/new line

I would like to mimic Textmates CTRL+ALT+w, which creates a new pair of opening and closing HTML tags on the same line.
In VIM Surround I'm using CTRL+st in Edit mode for this, but it always indents and creates a new line after setting the tag, so that it looks like this (* = cursor position):
<p>
*
</p>
Is there a way to achieve this? :
<p>*</p>
I guess your problem is that the selected area is "line wise". For example, if you select a few lives with V and surround it with tags, the tags will be placed one line above and one bellow the selected lines.
You probably want to create a "character wise" selection, with v before surrounding it.
Anyway, please post the map you created, so we can help debugging this.
Update
After some clarification in the comments, I would tell you that the surround plugin is not the best option. As its name describes, it was created to deal with surrounded content. So you may need content to surround.
In your case, I recommend taking a look in HTML AutoCloseTag. This plugin closes the html tag once you type the >. It is certainly more appropriated, and uses less keystrokes than surround.
<p <--- Now when you type ">", if becomes:
<p>|</p> <--- Where "|" is the cursor.
Obviously, you will get this behavior to every tag. But that may be handy if you like it.
From normal mode, type vstp> to enter visual mode and output an opening and closing <p> tag on the same line at the current cursor position. Use a capital S to maintain the current indent level.
This doesn't place the cursor in between the tags as you describe, but neither does Textmate's CtrlW shortcut (I think you meant CTRL+Shift+w, not CTRL+ALT+w, as the latter just outputs a diamond sign.)
My answer is probably coming to late, but I'll try to help.
I had similar problem with Vimsurround plugin. Every time I select sentence (one line) using ctrl+V and try to surround it with something I get this:
{
var myVar
}
instead of this:
{ var myVar } // what I wanted
I found easy solution: From a normal mode I choose a line with vis command and then I type capital C (my vim surround mapping ) and choose brackets to surround.Then I get one line nicely surrounded.
The question title is technically mislabeled based on what the author was actually looking for, but since I was actually looking for the answer to the question asked in the title, I figure I should provide an answer to it as well.
To create a new tag surrounding an element without the automatic indentation Vim Surround uses when using a block wise selection (ie: VysS), you can instead do something like:
^ys$
This command will move your cursor to the first non-blank character of the line, issue the command that you want to utilize You Surround, and move to the end of the line. Then, simply start entering your tag.
The result is this:
<input type="email" name="email">
Could become something like this:
<li><input type="email" name="email"></li>
The command is repeatable as well with . and all the normal other Vim goodness.
Stumbled upon this question because I was wondering this as well - I believe the simplest way to do this is just:
yss<p>
(yss surrounds a line with something without indenting - see here: http://www.catonmat.net/blog/vim-plugins-surround-vim/)
You can accomplish this by selecting the relevant text object: :h text-objects
...and surrounding that instead of surrounding a Visual Line selection.
The most common example I found myself running into was when trying to surround one tag with another. In that situation, the it and at text objects are quite useful:
*v_at* *at*
at "a tag block", select [count] tag blocks, from the
[count]'th unmatched "<aaa>" backwards to the matching
"</aaa>", including the "<aaa>" and "</aaa>".
See |tag-blocks| about the details.
When used in Visual mode it is made characterwise.
*v_it* *it*
it "inner tag block", select [count] tag blocks, from the
[count]'th unmatched "<aaa>" backwards to the matching
"</aaa>", excluding the "<aaa>" and "</aaa>".
See |tag-blocks| about the details.
When used in Visual mode it is made characterwise.
For example, if you had your cursor in a paragraph and you wanted to surround it with a div on the same line, ysat<div> would accomplish that.

Vim: quickly returning to a part of the text

I have been trying to learn Vim and have been using it for 2 weeks now.
My question is how do I return the cursor immediately to the middle of the text I just typed:
I have a tendency to type:
<div>
</div>
and returning back to the content of the tag and writing its contents:
<div>
text
</div>
This also goes for functions:
function eat() {
}
before getting back to the middle of the and typing it's contents:
function eat(){
blah
}
An uppercase O, so Shift+o, inserts an empty line above the one you're currently on and puts you into insert mode where you can begin typing. It was kind of an epiphany for me when I first figured that out.
If you work a lot with html / xml tags, have a look at surround.vim
I agree with michaelmichael, O works in both of your examples above.
In general, in vi or vim, you can use "macro" to achieve this. This feature acts like a bookmark, despite its name.
ma will define a macro called 'a'.
`a will take you back to where the bookmark was defined. If you want the beginning of the line, use 'a
So, if you typed 'ma' at the appropriate spot, continued typing, then typed '`a', it would achieve the effect you're looking for.
Snipmate plugin - Completion codes
dynamics
see an example of plugin in action at the vimeo site

Resources