Why doesn't "history | vim" work? - linux

I want to use the Vim to see the result of history (not in the shell). I think history | vim will work (use the result of history as the input of vim), but it returns with:
$history | vim
Vim: Warning: Input is not from a terminal
Vim: Error reading input, exiting...
Vim: Finished.
Can anybody explain this?

By piping into vim, you are changing the standard input stream. Because vim is an interactive program, it requires the standard input to be the console.
If you want to view in vim, you should tell it you are reading the file from stdin (by supplying the argument -):
history | vim -
Alternatively, you could just use more or less:
history | more
history | less
These latter two are preferable. If you pipe into vim, it will see your "file" as having modifications, and so you can't quit with a straight :q command. Instead you have to force quit by :q!, which is a bit clunky.
On the other hand, you can exit more or less just by typing q. Have a look at the man-page for these two programs. You'll use them a lot.
As recommended by Russell Silva in the comments, you can open vim in read-only mode when you read from stdin. Just supply the -R argument. Then you can quit normally without needing the override:
history | vim -R -

Apart of vim -, you may try bash command substitution like:
vim <(history)
See also:
How to write whole buffer to standard output from the command line? at Vim SE
How to edit files non-interactively (e.g. in pipeline)? at Vim SE

This happend to me trying to send it to background console (&)
One script used:
...
vi "$file" &
...
# change to just:
vi "$file"
removing &, problem went away.

Related

Saving a file opened without admin permissions [duplicate]

Many of you have probably seen the command that allows you to write on a file that needs root permission, even when you forgot to open vim with sudo:
:w !sudo tee %
The thing is that I don't get what is exactly happening here.
I have already figured this:
w is for this
*:w_c* *:write_c*
:[range]w[rite] [++opt] !{cmd}
Execute {cmd} with [range] lines as standard input
(note the space in front of the '!'). {cmd} is
executed like with ":!{cmd}", any '!' is replaced with
the previous command |:!|.
so it passes all the lines as standard input.
The !sudo tee part calls tee with administrator privileges.
For all to make sense, the % should output the filename (as a parameter for tee), but I can't find references on the help for this behavior.
tl;dr Could someone help me dissect this command?
In :w !sudo tee %...
% means "the current file"
As eugene y pointed out, % does indeed mean "the current file name", which is passed to tee so that it knows which file to overwrite.
(In substitution commands, it's slightly different; as :help :% shows, it's equal to 1,$ (the entire file) (thanks to #Orafu for pointing out that this does not evaluate to the filename). For example, :%s/foo/bar means "in the current file, replace occurrences of foo with bar." If you highlight some text before typing :s, you'll see that the highlighted lines take the place of % as your substitution range.)
:w isn't updating your file
One confusing part of this trick is that you might think :w is modifying your file, but it isn't. If you opened and modified file1.txt, then ran :w file2.txt, it would be a "save as"; file1.txt wouldn't be modified, but the current buffer contents would be sent to file2.txt.
Instead of file2.txt, you can substitute a shell command to receive the buffer contents. For instance, :w !cat will just display the contents.
If Vim wasn't run with sudo access, its :w can't modify a protected file, but if it passes the buffer contents to the shell, a command in the shell can be run with sudo. In this case, we use tee.
Understanding tee
As for tee, picture the tee command as a T-shaped pipe in a normal bash piping situation: it directs output to specified file(s) and also sends it to standard output, which can be captured by the next piped command.
For example, in ps -ax | tee processes.txt | grep 'foo', the list of processes will be written to a text file and passed along to grep.
+-----------+ tee +------------+
| | -------- | |
| ps -ax | -------- | grep 'foo' |
| | || | |
+-----------+ || +------------+
||
+---------------+
| |
| processes.txt |
| |
+---------------+
(Diagram created with Asciiflow.)
See the tee man page for more info.
Tee as a hack
In the situation your question describes, using tee is a hack because we're ignoring half of what it does. sudo tee writes to our file and also sends the buffer contents to standard output, but we ignore standard output. We don't need to pass anything to another piped command in this case; we're just using tee as an alternate way of writing a file and so that we can call it with sudo.
Making this trick easy
You can add this to your .vimrc to make this trick easy-to-use: just type :w!!.
" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %
The > /dev/null part explicitly throws away the standard output, since, as I said, we don't need to pass anything to another piped command.
In the executed command line, % stands for the current file name. This is documented in :help cmdline-special:
In Ex commands, at places where a file name can be used, the following
characters have a special meaning.
% Is replaced with the current file name.
As you've already found out, :w !cmd pipes the contents of the current buffer to another command. What tee does is copy standard input to one or more files, and also to standard output. Therefore, :w !sudo tee % > /dev/null effectively writes the contents of the current buffer to the current file while being root. Another command that can be used for this is dd:
:w !sudo dd of=% > /dev/null
As a shortcut, you can add this mapping to your .vimrc:
" Force saving files that require root permission
cnoremap w!! w !sudo tee > /dev/null %
With the above you can type :w!!<Enter> to save the file as root.
The accepted answer covers it all, so I'll just give another example of a shortcut that I use, for the record.
Add it to your etc/vim/vimrc (or ~/.vimrc):
cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!
Where:
cnoremap: tells vim that the following shortcut is to be associated in the command line.
w!!: the shortcut itself.
execute '...': a command that execute the following string.
silent!: run it silently
write !sudo tee % >/dev/null: the OP question, added a redirection of messages to NULL to make a clean command
<bar> edit!: this trick is the cherry of the cake: it calls also the edit command to reload the buffer and then avoid messages such as the buffer has changed. <bar> is how to write the pipe symbol to separate two commands here.
Hope it helps. See also for other problems:
SuperUser: force vim to write a file
This also works well:
:w !sudo sh -c "cat > %"
This is inspired by the comment of #Nathan Long.
NOTICE:
" must be used instead of ' because we want % to be expanded before passing to shell.
:w - Write a file.
!sudo - Call shell sudo command.
tee - The output of write (vim :w) command redirected using tee. The % is nothing but current file name i.e. /etc/apache2/conf.d/mediawiki.conf. In other words tee command is run as root and it takes standard input and write it to a file represented by %. However, this will prompt to reload file again (hit L to load changes in vim itself):
tutorial link
I'd like to suggest another approach to the "Oups I forgot to write sudo while opening my file" issue:
Instead of receiving a permission denied, and having to type :w!!, I find it more elegant to have a conditional vim command that does sudo vim if file owner is root.
This is as easy to implement (there might even be more elegant implementations, I'm clearly not a bash-guru):
function vim(){
OWNER=$(stat -c '%U' $1)
if [[ "$OWNER" == "root" ]]; then
sudo /usr/bin/vim $*;
else
/usr/bin/vim $*;
fi
}
And it works really well.
This is a more bash-centered approach than a vim-one so not everybody might like it.
Of course:
there are use cases where it will fail (when file owner is not root but requires sudo, but the function can be edited anyway)
it doesn't make sense when using vim for reading-only a file (as far as I'm concerned, I use tail or cat for small files)
But I find this brings a much better dev user experience, which is something that IMHO tends to be forgotten when using bash. :-)
FOR NEOVIM
Due to problems with interactive calls (https://github.com/neovim/neovim/issues/1716), I am using this for neovim, based on Dr Beco's answer:
cnoremap w!! execute 'silent! write !SUDO_ASKPASS=`which ssh-askpass` sudo tee % >/dev/null' <bar> edit!
This will open a dialog using ssh-askpass asking for the sudo password.
A summary (and very minor improvement) on the most common answers that I found for this as at 2020.
tl;dr
Call with :w!! or :W!!.
After it expands, press enter.
If you are too slow in typing the !! after the w/W, it will not expand and might report: E492: Not an editor command: W!!
NOTE Use which tee output to replace /usr/bin/tee if it differs in your case.
Put these in your ~/.vimrc file:
" Silent version of the super user edit, sudo tee trick.
cnoremap W!! execute 'silent! write !sudo /usr/bin/tee "%" >/dev/null' <bar> edit!
" Talkative version of the super user edit, sudo tee trick.
cmap w!! w !sudo /usr/bin/tee >/dev/null "%"
More Info:
First, the linked answer below was about the only other that seemed to mitigate most known problems and differ in any significant way from the others. Worth reading:
https://stackoverflow.com/a/12870763/2927555
My answer above was pulled together from multiple suggestions on the conventional sudo tee theme and thus very slightly improves on the most common answers I found. My version above:
Works with whitespace in file names
Mitigates path modification attacks by specifying the full path to tee.
Gives you two mappings, W!! for silent execution, and w!! for not silent, i.e Talkative :-)
The difference in using the non-silent version is that you get to choose between [O]k and [L]oad. If you don't care, use the silent version.
[O]k - Preserves your undo history, but will cause you to get warned when you try to quit. You have to use :q! to quit.
[L]oad - Erases your undo history and resets the "modified flag" allowing you to exit without being warned to save changes.
Information for the above was drawn from a bunch of other answers and comments on this, but notably:
Dr Beco's answer: https://stackoverflow.com/a/48237738/2927555
idbrii's comment to this: https://stackoverflow.com/a/25010815/2927555
Han Seoul-Oh's comment to this: How does the vim "write with sudo" trick work?
Bruno Bronosky comment to this: https://serverfault.com/a/22576/195239
This answer also explains why the apparently most simple approach is not such a good idea:
https://serverfault.com/a/26334/195239
The only problem with cnoremap w!! is that it replaces w with ! (and hangs until you type the next char) whenever you type w! at the : command prompt. Like when you want to actually force-save with w!. Also, even if it's not the first thing after :.
Therefore I would suggest mapping it to something like <Fn>w. I personally have mapleader = F1, so I'm using <Leader>w.

Cygwin terminal input disappearing after quitting vim

Using Cygwin, I tried creating and editing a file in Vim:
touch test | vim
This is obviously a mistake; something like vim "$(touch test)" has a better chance of actually working. Nevertheless, this command throws the error:
Vim: Warning: Input is not from a terminal.
And after this, Vim opens and I exit the program with :q. Any subsequent commands I enter into the terminal are hidden from view until I restart Cygwin.
Why is this?
You don't understand what does a pipe | do in shell.
Pipe will take the pervious command's stdout as stdin to next command, in a subshell.
Your touch foo doesn't generate any output, what do you expect to happen? same for vim "$(touch test)".
If you want to create a file and open it in vim in one shot, you can try:
touch foo && vim foo
If you want to edit it with vim anyway, actually, you can simply just:
vim foo
then save the buffer after your editing.

What is a way to read man pages in Vim without using temporary files

I want to be able to read man pages in Vim.
For some reason, it seems that Vim isn't able to read the output of programs through piping. E.g (man ls) | vi doesn't seem to work, bonus points for somebody who can explain why.
To get around this, I've been using the following little script:
tempo = `mktemp`
man $1 > $tempo ; vi $tempo
This script uses temporary files which I guess work fine, but I was wondering if there was a good way to read man pages in Vim without resorting to creating temporary files
Vim includes a man page viewer, :Man, in its runtime files.
Put this line in your vimrc:
runtime! ftplugin/man.vim
Now you can read syntax-highlighted man pages inside Vim by running :Man. For example:
:Man 3 printf
Even better, you can just place your cursor on a word in the buffer and press <Leader>K (\K) to see the man page for that word.
See :h find-manpage for complete usage and installation instructions.
For some reason, it seems that vim isn't able to read the output of programs through piping […]
According to the man-page, you need to specify a file of - to get it to read from standard input; so:
man ls | vi -
If that doesn't work, you might try using process substitution:
vi <(man $1)
which creates a sort of pseudo-file and passes it to vi.
On my system (Mac OS X), I found that the above left control characters in the output. Instead I used:
export MANPAGER="col -b | vim -MR - "
then just e.g.
man vim
The vim options turn off modifying the buffer and make it read-only. This stops vim complaining if you try to exit with ":q" (you can use :q! of course, but you might as well set the options).
This is also handy for general use - I have the following. The -c command names the buffer, just for completeness.
alias vimpager="vim -MR -c 'file [stdin]' -"
Here is what I did: I've made a function in my .bashrc:
vman() { vim <(man $1); }
When I call vman this automatically calls Vim showing the man page. It works great.
Your example code is wrong.
tempo=`mktemp`
man $1 > $tempo; vi $tempo
But you really only need
man $1 | vi -
By default vim reads vimscripts (=vim commands), not input files, from stdin. That is why you cannot directly pipe man output to vim; as others have mentioned you have to use vim - to make vim read from stdin.
However piping vimscripts can be useful too:
vim test.txt <<EOF
:%s/[aiueo]/X/g
:wq! output.txt
EOF
The above will use vim to open test.txt, replace all vowels with X, write the results to output.txt, and quit (ignoring changes to the original file). It uses a here document but you can of course put the vim commands in a file and use vim test.txt < myscript or cat myscript | vim test.txt to achieve the same result.
I suspect the reason they did it this way was that you can open multiple input files but only execute one script. If input was read from stdin by default, you could only read one buffer that way.
I combined others answers, I am using
vman() {
export MANPAGER="col -b" # for FreeBSD/MacOS
# Make it read-only
eval 'man $# | vim -MR +"set filetype=man" -'
unset MANPAGER
}
Usage:
vman ls
You also can press shift-k on your c function to print the man page
I have a better solution, the one that I used, it is like this:
/bin/sh -c "unset PAGER;col -b -x | vim -R -c 'set ft=man nomod nolist' -c 'map q :q<CR>' -c 'map <SPACE> <C-D>' -c 'map b <C-U>' -c 'nmap K :Man <C-R>=expand(\"<cword>\")<CR><CR>' -"
Hope you'll enjoy it.
You can always use info command for info pages and do info {cmd} | vim.
Source.
A lot of good answers, with respect to plugins it's worth to add that vim-man* provides a set of convenience functions to open and read man pages:
Viewing man pages, as per docs.
:Man printf - open printf(1) man page in a split
:Vman 3 putc - open putc(3) man page in a vertical split
:Man pri<Tab> -
command completion for man page names
* Available on GitHub: https://github.com/vim-utils/vim-man.

Is there a way to configure Vim grepprg option to avoid waiting until the external tool has finished searching?

I am a long time Vimmer. However, I keep switching to shell to make searches. This avoids me to use the quickfix functionality.
The main reason for switching to shell is that when I use grep from inside Vim (with :grep), I cannot follow progress.
Because the code base I search is usually wide, I really appreciate immediate feedback.
It gives me a chance to find out that my search expression is wrong before the full results have been displayed.
This allow me to cancel the search, refine the expression then relaunch the search.
Any hint how to reproduce this pattern inside Vim would be appreciated.
I don't see the same vim behaviour as you. When I run :grep, I still see the results in vim (not in the quickfix) before the search completes (but I cannot do anything until the search is done).
I even tried using no vim settings or plugins:
gvim -u NONE -U NONE
If that's not your behaviour, check your grepprg. Mine is the default:
:verbose set grepprg
grepprg=grep -n $* /dev/null
When I use run grep -e "score" -R /etc I see this output in vim:
:!grep -n -e "score" -R /etc /dev/null 2>&1| tee /tmp/voLcaNS/232
It's possible that your system is missing tee or your vim doesn't use it (I'm using Vim 7.2 on Ubuntu 10.10). tee takes the text passed to it and writes it to a file and to stdout.
If you're looking for a way to have the quickfix get updated with your search results and have vim not block while you're searching, then you could write a script that:
searches with grep as a background process and redirects to a file
every second until grep completes, have vim load the file in quickfix (cgetfile) (you can tell vim to do something from another process with --remote-expr)
You can try my AsyncCommand plugin to get your code started. It does the above, except that it only loads the file when the search is complete.
Are you familiar with ack.vim at all? It doesn't use the quickfix window, but uses a separate buffer in a split. However, it's rather faster results come right back to the vim frame.
This may be due to buffering between grep and tee, not vim itself. To test this theory, run grep from the command-line and pipe the output through tee (i.e. grep <pattern> <files> | tee temp.out). If it behaves the same as you observe within vim, then buffering is occurring.
To work around, install expect (sudo apt-get install expect-dev on Ubuntu 10.10) and grepprg to unbuffer grep -n $* /dev/null. (See Turn off buffering in pipe).
Take a look at :vimgrep in the online documentation. It displays the file name being searched and updates as it goes.
There are three ways to do a search in entire projects.
System command grep(fast, but not working well with Ouickfix list)
=>$ grep -n Example *
Vim internal grep(slow, but have a strong pattern support)
:vim[grep] /{pattern}/[g][j] {file} ...
System plugin ack(perfect)
1 install ack
brew install ack
2 add below configs to your .vimrc
:set grepprg=ack\ --nongroup\ --column\ $*
:set grepformat=%f:%l:%c:%m
3 then you can use grep to call ack in vim like
:grep "object\." app/**/*.rb

How does the vim "write with sudo" trick work?

Many of you have probably seen the command that allows you to write on a file that needs root permission, even when you forgot to open vim with sudo:
:w !sudo tee %
The thing is that I don't get what is exactly happening here.
I have already figured this:
w is for this
*:w_c* *:write_c*
:[range]w[rite] [++opt] !{cmd}
Execute {cmd} with [range] lines as standard input
(note the space in front of the '!'). {cmd} is
executed like with ":!{cmd}", any '!' is replaced with
the previous command |:!|.
so it passes all the lines as standard input.
The !sudo tee part calls tee with administrator privileges.
For all to make sense, the % should output the filename (as a parameter for tee), but I can't find references on the help for this behavior.
tl;dr Could someone help me dissect this command?
In :w !sudo tee %...
% means "the current file"
As eugene y pointed out, % does indeed mean "the current file name", which is passed to tee so that it knows which file to overwrite.
(In substitution commands, it's slightly different; as :help :% shows, it's equal to 1,$ (the entire file) (thanks to #Orafu for pointing out that this does not evaluate to the filename). For example, :%s/foo/bar means "in the current file, replace occurrences of foo with bar." If you highlight some text before typing :s, you'll see that the highlighted lines take the place of % as your substitution range.)
:w isn't updating your file
One confusing part of this trick is that you might think :w is modifying your file, but it isn't. If you opened and modified file1.txt, then ran :w file2.txt, it would be a "save as"; file1.txt wouldn't be modified, but the current buffer contents would be sent to file2.txt.
Instead of file2.txt, you can substitute a shell command to receive the buffer contents. For instance, :w !cat will just display the contents.
If Vim wasn't run with sudo access, its :w can't modify a protected file, but if it passes the buffer contents to the shell, a command in the shell can be run with sudo. In this case, we use tee.
Understanding tee
As for tee, picture the tee command as a T-shaped pipe in a normal bash piping situation: it directs output to specified file(s) and also sends it to standard output, which can be captured by the next piped command.
For example, in ps -ax | tee processes.txt | grep 'foo', the list of processes will be written to a text file and passed along to grep.
+-----------+ tee +------------+
| | -------- | |
| ps -ax | -------- | grep 'foo' |
| | || | |
+-----------+ || +------------+
||
+---------------+
| |
| processes.txt |
| |
+---------------+
(Diagram created with Asciiflow.)
See the tee man page for more info.
Tee as a hack
In the situation your question describes, using tee is a hack because we're ignoring half of what it does. sudo tee writes to our file and also sends the buffer contents to standard output, but we ignore standard output. We don't need to pass anything to another piped command in this case; we're just using tee as an alternate way of writing a file and so that we can call it with sudo.
Making this trick easy
You can add this to your .vimrc to make this trick easy-to-use: just type :w!!.
" Allow saving of files as sudo when I forgot to start vim using sudo.
cmap w!! w !sudo tee > /dev/null %
The > /dev/null part explicitly throws away the standard output, since, as I said, we don't need to pass anything to another piped command.
In the executed command line, % stands for the current file name. This is documented in :help cmdline-special:
In Ex commands, at places where a file name can be used, the following
characters have a special meaning.
% Is replaced with the current file name.
As you've already found out, :w !cmd pipes the contents of the current buffer to another command. What tee does is copy standard input to one or more files, and also to standard output. Therefore, :w !sudo tee % > /dev/null effectively writes the contents of the current buffer to the current file while being root. Another command that can be used for this is dd:
:w !sudo dd of=% > /dev/null
As a shortcut, you can add this mapping to your .vimrc:
" Force saving files that require root permission
cnoremap w!! w !sudo tee > /dev/null %
With the above you can type :w!!<Enter> to save the file as root.
The accepted answer covers it all, so I'll just give another example of a shortcut that I use, for the record.
Add it to your etc/vim/vimrc (or ~/.vimrc):
cnoremap w!! execute 'silent! write !sudo tee % >/dev/null' <bar> edit!
Where:
cnoremap: tells vim that the following shortcut is to be associated in the command line.
w!!: the shortcut itself.
execute '...': a command that execute the following string.
silent!: run it silently
write !sudo tee % >/dev/null: the OP question, added a redirection of messages to NULL to make a clean command
<bar> edit!: this trick is the cherry of the cake: it calls also the edit command to reload the buffer and then avoid messages such as the buffer has changed. <bar> is how to write the pipe symbol to separate two commands here.
Hope it helps. See also for other problems:
SuperUser: force vim to write a file
This also works well:
:w !sudo sh -c "cat > %"
This is inspired by the comment of #Nathan Long.
NOTICE:
" must be used instead of ' because we want % to be expanded before passing to shell.
:w - Write a file.
!sudo - Call shell sudo command.
tee - The output of write (vim :w) command redirected using tee. The % is nothing but current file name i.e. /etc/apache2/conf.d/mediawiki.conf. In other words tee command is run as root and it takes standard input and write it to a file represented by %. However, this will prompt to reload file again (hit L to load changes in vim itself):
tutorial link
I'd like to suggest another approach to the "Oups I forgot to write sudo while opening my file" issue:
Instead of receiving a permission denied, and having to type :w!!, I find it more elegant to have a conditional vim command that does sudo vim if file owner is root.
This is as easy to implement (there might even be more elegant implementations, I'm clearly not a bash-guru):
function vim(){
OWNER=$(stat -c '%U' $1)
if [[ "$OWNER" == "root" ]]; then
sudo /usr/bin/vim $*;
else
/usr/bin/vim $*;
fi
}
And it works really well.
This is a more bash-centered approach than a vim-one so not everybody might like it.
Of course:
there are use cases where it will fail (when file owner is not root but requires sudo, but the function can be edited anyway)
it doesn't make sense when using vim for reading-only a file (as far as I'm concerned, I use tail or cat for small files)
But I find this brings a much better dev user experience, which is something that IMHO tends to be forgotten when using bash. :-)
FOR NEOVIM
Due to problems with interactive calls (https://github.com/neovim/neovim/issues/1716), I am using this for neovim, based on Dr Beco's answer:
cnoremap w!! execute 'silent! write !SUDO_ASKPASS=`which ssh-askpass` sudo tee % >/dev/null' <bar> edit!
This will open a dialog using ssh-askpass asking for the sudo password.
A summary (and very minor improvement) on the most common answers that I found for this as at 2020.
tl;dr
Call with :w!! or :W!!.
After it expands, press enter.
If you are too slow in typing the !! after the w/W, it will not expand and might report: E492: Not an editor command: W!!
NOTE Use which tee output to replace /usr/bin/tee if it differs in your case.
Put these in your ~/.vimrc file:
" Silent version of the super user edit, sudo tee trick.
cnoremap W!! execute 'silent! write !sudo /usr/bin/tee "%" >/dev/null' <bar> edit!
" Talkative version of the super user edit, sudo tee trick.
cmap w!! w !sudo /usr/bin/tee >/dev/null "%"
More Info:
First, the linked answer below was about the only other that seemed to mitigate most known problems and differ in any significant way from the others. Worth reading:
https://stackoverflow.com/a/12870763/2927555
My answer above was pulled together from multiple suggestions on the conventional sudo tee theme and thus very slightly improves on the most common answers I found. My version above:
Works with whitespace in file names
Mitigates path modification attacks by specifying the full path to tee.
Gives you two mappings, W!! for silent execution, and w!! for not silent, i.e Talkative :-)
The difference in using the non-silent version is that you get to choose between [O]k and [L]oad. If you don't care, use the silent version.
[O]k - Preserves your undo history, but will cause you to get warned when you try to quit. You have to use :q! to quit.
[L]oad - Erases your undo history and resets the "modified flag" allowing you to exit without being warned to save changes.
Information for the above was drawn from a bunch of other answers and comments on this, but notably:
Dr Beco's answer: https://stackoverflow.com/a/48237738/2927555
idbrii's comment to this: https://stackoverflow.com/a/25010815/2927555
Han Seoul-Oh's comment to this: How does the vim "write with sudo" trick work?
Bruno Bronosky comment to this: https://serverfault.com/a/22576/195239
This answer also explains why the apparently most simple approach is not such a good idea:
https://serverfault.com/a/26334/195239
The only problem with cnoremap w!! is that it replaces w with ! (and hangs until you type the next char) whenever you type w! at the : command prompt. Like when you want to actually force-save with w!. Also, even if it's not the first thing after :.
Therefore I would suggest mapping it to something like <Fn>w. I personally have mapleader = F1, so I'm using <Leader>w.

Resources