I often find myself using something like:
sed -ri 's/<\/(abc|def ghi|j klm)>//g' someFile.html
to perform substitutions on multiple possible patterns, in this case, a closing html tag to be deleted, saving me the time and effort to do this three separate times for three closing tags I want deleted.
Is there a way to do this using substitute on vim's cli? I haven't yet found a way to do it, but it would be more efficient than going to a terminal cli or running sed from within vim if it could be done natively instead.
Yes, you don't need to use an external program at all:
:%s#</\(foo\|bar\|baz\)>##g
You can use the silent ! command to silently execute shell commands from inside vim:
:silent !sed -ri 's/<\/(abc|def ghi|j klm)>//g' %
This will execute the command in the shell silently (it won't take you away from vim to see any shell output). The % means the current buffer name. Vim will then notify you that the file you are editing has been changed and will ask you if you want to load the changes, press l for load and the new changes from the sed shell command will appear.
Related
Often when I run a command that writes to stdout, and that command fails, I have to scroll up (using uncomfortable key-bindings) looking for the place where I pressed Enter, to see what the first error was (out of hundreds others, across many screens of text). This is both annoying and time-consuming. I wish there was a feature which allowed me to pin my current terminal to the place where I am now, then start the command, see only the first lines of the output (as many as fits below my cursor) and let the rest of the output be written but not displayed. In other words I would like a feature to allow me automatically scroll up to the place where I gave the command, to see the first lines of the output (where usually the origin of the failure is displayed).
I searched for it but I didn't find it. Do you know if such feature exists? Or have an idea how to implement it with some tricks or workarounds?
If you have a unique shell prompt you could bind a key to jump between shell prompts, for example something like this will make C-b S jump to the previous shell prompt then S subsequent ones:
bind S copy-mode \; send -X search-backward 'nicholas#myhost:'
bind -Tcopy-mode S send -X search-backward 'nicholas#myhost:'
Or similarly you could search for error strings if they have a recognisable prefix. If you install the tmux 3.1 release candidate, you can search for regular expressions.
Alternatively, you could use capture-pane to load the entire history into an editor with key bindings you prefer, for example:
$ tmux capturep -S- -E- -p|vim -
Or pipe to grep or whatever. Note you will need to use a temporary file for this to work with emacs.
Or try to get into the habit of teeing commands with lots of output to a file to start with.
I know that you can use m and then a to add a child node in NERDTree to add files or directories one at a time. Is there anyway to type out a list, e.g. {Book,Author}.php and get a corresponding file or directory for each one in the list?
If on Bash Shell, I would do this in Vim command mode:
q:i!touch {Book,Author}.php
q:i -- Enter into Vim command history window (q:), then insert (i), it also let you edit commands with all Vim's editing power.
! -- To use shell
**touch mydir/{my_file_1,my_file_2}.php -- This will create the empty files.
actually, do it in Bash Shell will be simpler.
I want to change some words in several files using VIM. To do this, I found out about Greplace, which appears to be made to do just that. However, in the documentation there is no sample of the syntax of Greplace (there is a sample of Gsearch, but I need the replace function).
Say I want to change "foo" for "bar" in all ".asp" files, how could that be achieved with Greplace (or any other method). I do not care about confirmation (it's fine if it requires confirmation; it's also fine if it does not).
It's trivial to do without a dedicated plugin.
$ vim *.asp
:bufdo %s/foo/bar/ge | update
:q
:bufdo runs the following commands on all buffers.
%s/foo/bar/ge replaces foo with bar on all lines and all occurrences in each line. The e flag makes sure :s doesn't emit an error if it doesn't find foo, since foo may not exist in all the files.
| is Vim's way of separating multiple commands to run. See :help :bar
update saves the file back to disk, only if any changes were actually made.
How can I create a Vim command and copy it's results to clipboard?
I want to convert Markdown to HTML and copy the result to the clipboard. So far I got:
nmap md :%!/bin/markdown/Markdown.pl --html4tags
But this will substitute my opened file on Vim to the result of Markdown.
You didn't say which system you're using, but generally saving it in the +
register should work. You can call system():
:let #+=system("markdown --html4tags", join(getline(1,line("$")), "\n"))
The system() function takes the second parameter (optional) as input to the
command, and here I'm using a chain of other functions to retrieve the contents
of the current buffer. Not sure, but there should be a better way to do it (if
someone knows, please let me know).
Alternatively, you can pass markdown your file name as input directly:
:let #+=system("markdown --html4tags " . shellescape(expand("%:p")))
But keep in mind that you'll need to write the file before calling this.
Two important notes:
I didn't type your full path to markdown. Use it.
I didn't use maps here, the final result would be something like:
nnoremap md :let #+=system(...)
get the xsel package
and pipe stdout to xsel --clipboard
For instance:
cat /etc/passwd | xsel --clipboard
Is that what you're looking for?
Filling in a missing piece (2+ years late). With the clarification that the user was on a Mac and since the asker's "why doesn't it work for me?" question was not answered.
To redirect the output of a command to the system clipboard from within MacVim (GUI version) you need to set the '*' to be the "clipboard register" you need to change the clipboard setting to 'unnamed':
set clipboard 'unnamed' # 'cb' can be substituted for 'clipboard'
Then sidyll's answer should work except specify the '*' register and not the '+' register:
:let #*=system(...)
The clipboard feature is likely not compiled into the "terminal version" of MacVim and when it is available option setting is different from 'unnamed'. To see more details regarding what works where and how, see the documentation in MacVim using the Vim help command:
:help 'clipboard' (include the single quotes since it's a set option!)
(I'll skip the command mapping issue since it always takes me several tries and I still have to look it up; finding the help for the mapping commands should be easier than finding it for the * register.)
I have a multitude of files in each of which I want to, say, delete lines 1 through 55, add a comment leader (e.g., //) on lines 25 through 35, and then save the changes to a new file.
How can I do this automatically with Vim alone or together with the help of a Bash script?
Despite the fact that using ed or sed is a common practice1
in such cases, sometimes using Vim is much more convenient. Indeed,
instead of writing an ed-like script somewhat blindly, it is often
easier to first perform the desired manipulations with one of the
files interactively in Vim:
vim -w log.vim file1.txt
and then repeat it on the rest of the files:
for f in file*.txt; do vim -s log.vim "$f"; done
For your example use case, the log.vim file will likely have
contents similar to the following:
gg55dd:25,35s/^/\/\/ /
:w %_new
:q!
Note that to save the file with new name you should not type it
directly, but rather use the % substitution, as shown above—otherwise
all the modifications of all the following files will be saved to the
same file, overwriting its contents every time. Alternatively, you can
duplicate the files beforehand and then edit the copies in place
(saving each of them by simply issuing the :w command without
arguments).
The advantage of this approach is that you can make all of the changes
interactively, ensuring that you are getting the intended result at
least on one of the files, before the edits are performed for the rest
of them.
1 Of course, you can use Vim in an ed-like fashion, too:
for f in file*.txt; do vim -c '1,55d|25,35s/^/\/\/ /|w! '"${f}_new"'|q!' "$f"; done
You can accomplish this elegantly with ed, the unix line editor, the ancestor of vi.
fix_file () {
ed -s "$1" <<-'EOF'
1,55d
25,35s_.*_// &_
wq
EOF
}
Now, for each file F you need, just execute fix_file F.