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

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.

Related

Is there a quick way to delete everything between certain tags, e.g. <head> and </head>, throughout the whole project (multiple pages) in VS Code?

I am trying to find a way to remove all from a tag pair in VS Code.
I’ve been using Notepad++ for this purpose, but for some unknown reason it doesn't work all the time. So, I hope if there is such a possibility in VS Code, it’d be more reliable.
Here is the instruction for Notepad++:
Search for -
<wp:post_name>[^<>]+</wp:post_name>
and replace all with -
<wp:post_name></wp:post_name>
Is there anything like this in VS Code?
I’d really appreciate it if someone can help.
Before using what is suggested in this solution, backup your files, and run the search and replace on a small sample. Be sure to check the outcome to all the possible combinations you can have in your files.
You can achieve what you need with Notepad++ (and SublimeText 3, with RegEx search and replace), and this answer will cover that. Since I've never used Visual Studio Code, I can't say if it will work in it as well.
Consider the following regular expression.
<foo>(.*?)<\/foo>
If we were to apply it to the following text:
<foo><some special chars>!##$%^&*</foo> sure, why not
<foo>Lorem</foo>
<foo>ipsum</foo>
<foo>sit</foo>
<foo>dolor</foo>
<foo>amet</foo>
<bar>elm stuff</bar>
more stuff for you <foo> something </foo> and even more stuff <foo>yes</foo>
it would match all the parts of the text which begin with <foo> and end with </foo>, regardless of what's between them.
If you want to play around with this, I've created an example here.
As far as using this in Notepad++, open the search window, navigate to the Find in files tab, and set it up like in the following image.
You would, of course, need to change the search and replacement strings to those you plan on using, optionally set up a file extension for which to do the replacement (Filters), and set the directory in which to perform find-and-replace.
Limitations
1. Nesting
In case your text contains nested tags of the same kind, like this:
Let's deal with nesting: <foo> some text <foo> a child foo!</foo> let's close the parent</foo>
doing the suggested RegEx search and replace, will turn the previous line of text into this:
Let's deal with nesting: <foo></foo> let's close the parent</foo>
If you don't have nested tags of the same kind, you should be in the clear. Unless...
2. Newlines
The provided RegEx will not match cases where your opening tag shows up in one line, and the closing tag shows up in another line. To match those, you would need to change the original RegEx:
<foo>(.*?)<\/foo>
to this:
<foo>([\s\S]*?)<\/foo>
\s will match any whitespace character (including newlines), while \S will match any non-whitespace character.

Using vim-surround with argument to a function

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.

Searching multiple tags with regex

I am trying to search for multiple tags with regex.
Something like this:
:tag /blabla\|user
I would like to search tags for blabla and user but for some reason it is not working. I tried all the combination I can think of, with and without magic flag. The help file said it accepts regex so I think it should be working.
Your original command, :tag /blabla\|user, is interpreted "as-is"; it needs one more forward slash to work:
:tag /blabla\\|user

Variables in snipMate definition, is it possible? (vim)

I use vim for programming purposes and I use the snipMate utility. I'm aware of the basic snippets definition, but I'm trying to do something like the following (this doesn't work):
snippet ${1}_.
<$1 class="${2}">${3}</$1>
I think it would be easier to explain with an example. What I'm trying to do is to insert a html tag when typing a word followed by _. :
So if I type div_. and press tab, it should change to:
<div class="(position of cursor)">(position of cursor)</div>
If I type span_. and press tab, it should change to:
<span class="(position of cursor)">(position of cursor)</span>
And so on. Hope you get the idea. I'm aware that I can write a snippet for every case, but I'm trying to avoid that.
Thanks!
Make the snippet do the hard work for you:
snippet tag
<${1:div} class="${2}">${3}</$1>
You may also want to take a look at emmet-vim and surround.vim.

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.

Resources