I'm going through http://learnvimscriptthehardway.stevelosh.com/chapters/04.html
and the exercise wants me to make in normal mode upcase the current word.
I did:
nnoremap <c-u> mmgUaw`m<esc>
and I'm using a mark (the m mark) to prevent the cursor from moving.
I don't like this solution because what should be a purely functional change ends up changing the global state of vim (by setting up a mark).
Is there a better way to do this, or is there a mark (or a set of marks) that should only be used by commands/mappings and not interactively (because commands/mappings change it/them)?
This is the best I came up with:
nnoremap <c-u> i<esc>guiw`^
to utilize the last position of the cursor in insert mode.
The example from the Vim help uses the s register itself, so your approach isn't necessarily a bad one (i.e. if the mapping is just for your own use then you can just pick a register you don't use for anything else).
Having said that, the special backtick (`) register might be better here, since it's local to the buffer and is meant to store the most recent jump point anyway.
Related
I love the simplicity of composing commands that have semantic meaning. Like, for example cib reads like a sentence change in brackets - wonderful.
But why does vim need to copy the old contents into my clipboard? Nowhere in that command have I suggested I want to copy it and the problem goes much deeper.
dw diw etc all copy to the my clipboard/register as well. Why? It seems like this abandons the semantic value of these commands and I would say it is unexpected behaviour.
Am I using these commands wrong, or is there some way to completely disable this feature? Currently I have done a few remappings like this:
nnoremap dd "_dd
nnoremap cc "_cc
but I would like to not do that for every single possible combination of non-explicit copying.
By default, most of the commands you're talking about use the unnamed register, ". It sounds like you're dealing with the clipboard being overwritten for all these things too, which can be a symptom of setting clipboard to unnamed or unnamed_plus.
To go back to standard, you can probably do set clipboard=, if the output of set clipboard? is one of those two options.
*'clipboard'* *'cb'*
'clipboard' 'cb' string (default "autoselect,exclude:cons\|linux"
for X-windows, "" otherwise)
global
{not in Vi}
{only in GUI versions or when the |+xterm_clipboard|
feature is included}
This option is a list of comma separated names.
These names are recognized:
*clipboard-unnamed*
unnamed When included, Vim will use the clipboard register '*'
for all yank, delete, change and put operations which
would normally go to the unnamed register. When a
register is explicitly specified, it will always be
used regardless of whether "unnamed" is in 'clipboard'
or not. The clipboard register can always be
explicitly accessed using the "* notation. Also see
|gui-clipboard|.
*clipboard-unnamedplus*
unnamedplus A variant of the "unnamed" flag which uses the
clipboard register '+' (|quoteplus|) instead of
register '*' for all yank, delete, change and put
operations which would normally go to the unnamed
register. When "unnamed" is also included to the
option, yank operations (but not delete, change or
put) will additionally copy the text into register
'*'.
Only available with the |+X11| feature.
Availability can be checked with:
if has('unnamedplus')
I'll offer a dissenting view, and suggest that you are likely using Vim non-idiomatically. This is in no way unexpected behaviour. Are you using cib as a preparation for pasting, so that cib screws it up? Do vibp instead.
dw diw etc all copy to the my clipboard/register as well. Why? It seems like this abandons the semantic value of these commands and I would say it is unexpected behaviour.
d then p is the normal Vim idiom for cut-and-paste (i.e. move text). This is an operation I do every day, multiple times per day, and it would be really annoying if d did not also yank. You seem to think d is equivalent of Del on other text editors; it is rather the equivalent of ctrl-x (cut). To cancel this, you'd do "_d as you said; I find that I hardly ever need it.
As an advanced example, the default semantics of c and visual-mode p makes it trivial to exchange two objects; for example:
I drank all their food and ate all their whiskey.
Go to "drank", diw (delete the word and yank it), go to "ate", viwp (select a word and paste over it, yanking the previous content), ctrl-o to go back to where "drank" was and P (paste before cursor):
I ate all their food and drank all their whiskey.
(I also have a plugin which defines "function parameter" as a text object, so I use the same idiom in coding if I mix up, or refactor, the parameter order.)
The only thing I want to prevent more commonly is yank-on-paste in visual mode (so that I can paste the same content multiple times); for this, I use
xnoremap <expr> P '"_d"'.v:register.'P'
(from here). This only remaps P in visual mode (which is otherwise identical to p in visual mode). Neither p nor P outside visual mode yank, so it's a non-issue.
I'd like to be able to end a run of comments but retain the current indentation. Is this possible either through an existing command or with a function?
I have formatoptions -=o and autoindent so I normally get by using o from normal mode - the cursor is on the next line, the indentation is correct and I'm in insert mode. I'm only worrying about single line comments (eg '#'s - as for shell, python etc).
I'm interested in how I can make this more general (particularly not dependent on my formatoptions). I'd like to have an imap for ;; but I can't seem to find a straight forward way if I want to call a function (for example, to check whether I'm currently on a comment line).
I've played around with <expr> mappings and the expression register but either I lose the indentation (cursor ends up in the first column) or the comment continues. It seems like there might be a better alternative to either reimplementing the autoindent logic or trying to delete the extra comment characters. I've also tried saving/restoring formatoptions while using normal o but leaving insert mode when there's no other content on the line deletes the indentation.
I appreciate suggestions about how I should approach this.
I've been using vim for somewhat longer than a year now and during this time I have never feel really comfortable with the way vim works with yanking and pasting text (or maybe it is just me not using it in the most efficient way)
For example, I have the word "World" yanked onto a register, and I want to paste it after "Hello". (Note that there are no spaces on either of the words). So, what I would do is
Hello
|
Place cursor here, and press "p". Then, what I will end up with is
HelloWorld
So, in order to avoid this, I have always to swith into insert mode, insert a espace, and go back into normal mode (or either make sure that the yanked word has a space before it). Be as it may, this is quite annoying behaviour I can't think of a solution for... Am I missing something here?
Suggestions will be appreciated.
Thanks
option zero
just live with what you have now.
option one
create a mapping for your workflow. for example
nnoremap <leader>p i<space><esc>p
option two
:set ve=all
then you could move your cursor to anywhere and paste
option three
you could in insert mode use <c-o> do normal mode stuff or <c-r> to get register values
I recommend option zero
You can use the Smartput : Adjust spaces and commas when putting text plugin for that. It modifies the p / P commands (this can be toggled on / off).
I have discovered that it is possible in insert mode to execute a single command and return to insert mode by using Ctrl-O.
What about the possibility to insert a single word while in normal mode ?
I could, of course, switch to insert mode, write the word, escape and go back to normal mode.
But I wondered if it was possible to map a sequence (e.g. Ctrl-K) allowing without leaving normal mode to quickly add a single word at the cursor position ?
I tried mapping a function with a prompt (cf. question 11567596 - Ingo Karkat's answer - and Wikia tip 1616) but failed : the word was appended at the end of the line...
My best advice is to embrace insert mode; it's the vi way TM.
Seriously, I also had the idea of creating mappings that allow me to enter a word / sentence / whatever, and then automatically return to normal mode. But...
Whether you use the input() from romainl's answer, or a more elaborate approach (e.g. with a CursorMovedI hook), you have to press Enter or another key to indicate that you're done. That's no better than pressing Esc to leave insert mode the normal way!
You just make things more complex: you spend valuable (short) key sequences for it, you have to spend brain cycles to decide between both approaches, your muscle memory must learn to ways to enter text, and these specials aren't available in other vi-modes (e.g. in Bash).
So, I think it's just not worth it.
This simple function works, here:
function! InsertWord()
let l:user_word = input("Type something then hit ENTER: ")
execute "normal i".l:user_word
endfunction
command! InsertWord call InsertWord()
nnoremap <C-k> :InsertWord<CR>
The whole thing could probably be shortened to a one-liner, though, but I like it like that.
I've used vi for decades, and am now practicing using vim, expecting
eventually to switch to it entirely.
I have a number of questions, but I'll start with the one that
troubles me most. Something I have long done in vi is to type
a bottom-line command into the file I am editing, yank it to a named buffer
(e.g., using the keystrokes "ayy) and execute that buffer (using
:#a^M). This allows me to edit complicated commands till they
work right, and to keep commands that I will use many times as I
work in a file. (I have
in my .exrc file a mapping that reduces this yank-and-execute to a
single keystroke; but that isn't relevant to my question.)
I find that in vim, I need a lot more ^Vs than in vi. This
means, on the one hand, that when I have some command-line in a file
that I expect to use this way, I now need to keep it in two
versions, one for vi and one for vim. Also, the requirement of the
extra ^Vs seems inelegant: evidently various special characters
that are interpreted once when the named buffer is executed in vi
are interpreted twice when its is executed in vim -- but why?
As an example, a command of the form
map =f :w^V|e foo^M
(mapping the keystroke-sequence =f to write the current file
and go to the file foo) works this way in vi, but has to have the form
map =f :w^V^V|e foo^V^M
in vim. (Here in both commands, ^V is gotten by typing ^V^V,
and ^M is gotten by typing ^V^M; so typing the first version
involves typing three ^Vs, and the second, seven.) To be
exact: the first version does work in vim if one actually
types it into the bottom line (with the indicated extra ^Vs);
but the latter is required in an executed named buffer.
Any explanation? Anything I can set to fix this? ("compatible"
doesn't seem to do it.) Any hope that it will be fixed in a future
release? (The system I am on uses version 7.0.)
(I should confess that I'm not a programmer; just a user who has
become proficient in vi.)
Personally, I'd stop using ^V completely. In Vim (I've no idea about Vi), there are various key notations that get round the problems you're having. For your specific example, I'd recommend:
map =f :w<bar>e foo<CR>
where <bar> means 'insert the vertical bar here' and <CR> means 'insert a carriage return here'. See:
:help key-notation
for more information. I find the <CR> much easier to understand than ^V^M.
That's an interesting way of using :#, which I hadn't thought of before. I generally just use the command line history when I need to edit complicated commands, and I tend to save common or complicated commands as mappings or commands in my .vimrc (of course, I have a mapping that will pop open my .vimrc in a new tab). But there are certainly benefits to using vim's normal mode rather than command line mode for editing a complicated command.
As I understand it, you not only want to avoid so many <C-V> characters, you would also like to be able to use the same commands in vim and vi. Unfortunately, that would preclude you from using the (preferred in vim) key-notation. I think that you should be able to use the cmdline mode's Ctrl-R Ctrl-R register to help you out (:help c_<C-R>_<C-R>). E.g.
map <Leader>e mm^"ay$`m:<C-R><C-R>a<CR>
mm - mark cursor location so we can return later
^"ay$ - yank current line into register a (ignoring whitespace at beginning and newline at end)
``m` - return cursor to start position
: - enter command line mode
<C-R><C-R>a - place the literal contents of register a onto the command line, which seems to be where your problem with vim versus vi was coming to into play. I think that <C-R>a would give you the same behaviour you are seeing now with :#a.
- execute the whole thing
Using that mapping, I then typed your example of map =f :w^V|e foo^M into a file, placed my cursor on that line, ran my <Leader>e mapping, verified that your =f mapping had loaded correctly, and then ran it. Obviously you'll want to customize it to fit your needs, but I think that playing around with <C-R><C-R> will basically get you what you want.
All of that said, if you can, I'd strongly recommend taking the plunge and forgetting about compatibility with vi. Then you can use the much simpler key-notation and a host of other vim features. :-)