How to match git conflict markers with % - vim

In vi and vim, % can be used to find a matching symbol e.g.:
/** <- With the cursor on / ...
* Some comment
*
...
*
*/ <- % moves the cursor to the / on this line
This works with matching {}, () [] pairs, and also works with c-conditionals like #ifdef.
Is there a setting to make this work with git conflict markers?
#! /usr/bin/env ruby
def hello
<<<<<<< HEAD <- With the cursor on this line
puts 'hola world'
=======
puts 'hello mundo'
>>>>>>> mundo <- % moves the cursor to this line
end
Can (and how) vi and/or vim be configured to do that?

In your startup files (eg $HOME/.vimrc) you can add:
packadd! matchit
let b:match_words = '<<<<<<<:=======:>>>>>>>'
packadd! enables the optional plugin, and match_words specifies the match pattern. Note that this will override any previous assignment of match_words, and this sort of thing is typically better suited to store in a filetype plugin. Adding those two lines directly in the main startup file should work, but may not be the best solution. (eg, if you're merging a file whose type is recognized, the filetype plugins may override the setting of match_words)

Assuming you are actually talking about Vim (which makes this configurable) and not vi (which doesn't).
The functionality is documented under :help %:
% Find the next item in this line after or under the
cursor and jump to its match. |inclusive| motion.
Items can be:
([{}]) parenthesis or (curly/square) brackets
(this can be changed with the
'matchpairs' option)
/* */ start or end of C-style comment
#if, #ifdef, #else, #elif, #endif
C preprocessor conditionals (when the
cursor is on the # or no ([{
is following)
For other items the matchit plugin can be used, see
|matchit-install|. This plugin also helps to skip
matches in comments.
From there, you can follow the 'matchpairs' tag to :help 'matchpairs', which won't help you because you can only add pairs of single characters like <:>.
You can then follow the promising matchit-install tag, which should put you on the right path.
Try harder.

Related

In vim toggle case of all characters in a text file with a single command

In Vim I need to convert all lowercase to uppercase and all uppercase to lowercase with a single command. So if my text file looks like this..
Hello World
.. it needs to be toggled to look like this..
hELLO wORLD
I know :%s/[a-z]/\U&/g will change all lowercase to uppercase and that :%s/[A-Z]/\L&/g will change all uppercase to lowercase. But how would I write that to do both at the same time?
In addition I know if my cursor is at the top of the file VG~ will toggle case everything but that's not the answer I need. Thank you.
<Esc>1GVG~
Explanation:
<Esc> — return to Normal mode; just in case we're in Insert mode or Command line
1G — jump to the 1st line
V — start Visual mode
G — jump to the last line extending selection
~ — toggle case in the selection
Or
<Esc>1Gg~G
g~<motion> — change case during motion; the motion is G (jump to last line)
Docs: http://vimdoc.sourceforge.net/htmldoc/change.html#~
Looks like you already know everything you need. ggVG~ marks all your code and toggles the case. If you want a single command you can either use:
:nnoremap <keybinding> ggVG~
or use this function, which does the same, but keeps your current position in the file:
function ToggleCase()
exec "normal! mqHmw"
exec "normal! ggVG~"
exec "normal! 'wzt`q"
endfunction
command ToggleCase silent call ToggleCase()
the first and last exec mark your position in the file and restore them, after the case toggling. See: :h marks
type :ToggleCase to use the function. Of cause you can bind this to a keybinding as well.
:nnoremap <keybinding> :ToggleCase<cr>
Since you mentioned using a single command and you mentioned some :%s/.../ substitutions, I'll offer this one:
:%normal! g~~
This will run the g~~ command to switch case of a single line, for each line of the buffer.
One more way to accomplish this, if you're ok adopting a plug-in, is to use the kana/vim-textobj-entire plug-in for a text object for the entire buffer.
As the plug-in README.md file says:
Though these are trivial operations (e.g. ggVG), text object versions are more handy, because you do not have to be conscious of the cursor position (e.g. vae).
With this plug-in installed and enabled, you can switch case of the whole buffer with:
g~ae

Using abbreviation to insert comment

I’m trying to set up an abbreviation in my .vimrc that will insert a comment template for heading-level comments in my CSS files.
The comment I want to insert is:
/* ==========================================================================
#
========================================================================== */
I will then jump back to the # and add my title there (e.g. BUTTONS).
The abbreviation I have attempted to set up looks like this:
iab comsec·
\/* ==========================================================================
\<Cr>#
\<Cr>========================================================================== */
(Where · represents a trailing space.)
Right away this feels pretty crude, but the specific problem is that if try and drop a comsec in my CSS, it starts wrapping it in more comments. The output looks like this:
/* ==========================================================================
* #
* ========================================================================== */
Notice the two * at the beginnings of lines 2 and 3?
Is there a way to tell vim not to try and be clever and to just drop in exactly what I’ve told it? A way to prevent vim from trying to wrap comments around the comment?
I’m not a particularly hardcore vim user, so there’s every chance I’m overcomplicating things, or missing something obvious, or using the wrong tool for the job.
Thanks!
If you are the type of person who can keep track of your personal utilities, this isn't so fancy but works. You can import the output of an external command into your buffer, so I put a mapping like this in my .vimrc file:
"bc = block comment
map ,bc :read! python ~/my_personal_utils/insert_css_comment.py
So, I just have to type ",bc" to add the comment. On my Mac at least, this leaves me hanging in command mode, so that my cursor is after '.py' and I can quickly type an argument like BUTTONS (i.e. the python script takes an optional argument).
Here is a function to do that.
:function! Comment()
:normal! i/*
:normal! 80a=
:normal! o#
:normal! o
:normal! 80i=
:normal! a*/
:endfunction
You can put this in vimrc file and create a command or map for this.
Command
:cmap comsec call Comment()
You can keep the cursor on a line and then call this command.
Or an in insert mode mapping
:imap comsec <ESC>:comsec<CR>
As alternatives I'd suggest nerdcommenter for commenting/uncommenting with a few key strokes.
Or, even better, ultisnips. In which you can easily make your own template for those headings:
open a .css file
exec command : UltiSnipsEdit
create your own snip:
snippet heading "heading comments"
/* ===================================
* ${1}
* =================================== */
endsnippet
Here is a better and simple way to to insert your comment which check everytime if the line is surrounded by the comment template.
All you have to do is to write your comment on new line and then press ; during the insert mode. (you can change the character ; by
any combination you want.)
The comment template is set by the variable l:start, l:begin, l:end
so you can change the number of spaces or = as you like.
If you would like to change the template completely keep in mind that you need to change also the regular expressions for the variables l:matchprev, l:matchhier, l:matchnext .
inoremap <silent> ; <Esc>mx:call Comment()<cr>i<Right>
function! Comment()
let l:start= "/* ====="
let l:begin=" # "
let l:end= " ==== */"
let l:next=getline(line(".")+1)
let l:hier=getline(line("."))
let l:prev=getline(line(".")-1)
let l:matchnext= matchstr( l:next , '^\s*=\+\s*\*/\s*$')
let l:matchhier= matchstr( l:hier , '^\s*#\s*.*$')
let l:matchprev= matchstr( l:prev , '^\s*/\*\s*=\+\s*$')
if l:matchnext != '' && l:matchprev != '' && l:matchhier != ''
return 0
else
execute ":s:^.*$:".l:start."\r".l:begin."&\r".l:end."\r:"
"the number 3 is the length of the variable l:begin
normal! `xj3l
endif
endfunction
write this code in another file scriptname and then you can use the mapping in any css file by typing in the command mode first :so scriptname
Another alternative is to put all that simply in your .vimrc file

Comment / uncomment multiple fixed lines in vim

In my code I have multiple scattered lines which help me to debug my program and show me what is going on during execution. Is there an easy and fast way to comment and uncomment (toggle) these fixed lines in vim? I thought about marking these lines with a special sign (e.g. //) like this in python:
print "Debug!" # //
and everytime a sepcific shortcut is pressed all lines which end with a "# 'some optional descriptive text' //" are commented or uncommented, respectively.
I've looked at NERD Commenter, but from what I read the lines to be commented / uncommented have to be selected each time?
First, find a pattern that selects the right lines. If you have :set hls, it will help spot the matches. I think something like /#.*\/\/$ is what you want.
Next, comment out the selected lines with
:g/<pattern>/s/^/# /
if # will comment out the line, and un-comment them with
:g/<pattern>/s/^# //
Now, you want a single command to toggle. You can either use a variable to keep track of the toggle state, or you can try to figure out the current state by examining the lines that match. Using a variable seems simpler.
The variable could be global, local to the buffer, or local to the script. I like using script-local variables in order to avoid cluttering the namespace. In this case, using a script-local variable might mean that vim will get confused when you switch buffers, so let's use a buffer-local variable, say b:commentToggle.
The first time the function is called, it notices that the variable is not set, so use search() to look for a line that starts with # (There is a space there!) and ends with the pattern we already have. The n flag means not to move the cursor, and w means to wrap around the end of the file (like searching with 'wrapscan' set). The search() function returns the line number (1-based!) if the pattern is found, 0 if not. See :help search().
This seems to work in a small test:
fun! CommentToggle()
if !exists('b:commentToggle')
let b:commentToggle = !search('^# .*#.*\/\/$', 'nw')
endif
if b:commentToggle == 1
g/#.*\/\/$/s/^/# /
else
g/#.*\/\/$/s/^# //e
endif
let b:commentToggle = !b:commentToggle
endfun
nnoremap <F4> :call CommentToggle()<CR>
If you want to put # in front of the first non-blank, then use ^\s*# in the search() command; s/\ze\S/# / or s/\S/\1# / in the first :g line; and s/^\s*\zs# // in the second :g line. See :help /\zs, :help /\ze, and :help sub-replace-special.

what function does vim call for completion with ctrl-n

My vim is throwing nasty errors 50% of the time when I use ctrl-n for completion
E854: path too long for completion
I really want to remap this, and call it with the :silent option to suppress the error, but I have no idea what function provides completion, so I can't remap it.
So my question is where can I find exactly what C-N calls when it is invoked in insert mode
Solution:
As mentioned in the comment on my accepted answer I found a way round this. Based off the instructions on building your own vim here : brilliantcorners.org/2011/02/building-vim-on-osx-snow-leopard
I grepped the source directory for E854 and it only comes up in 1 file. If you open that file you see it is only referenced twice. I just removed those error calls and built vim
This doesn't solve whatever the actual problem is, but it's the same effect as doing ignore. It works great now and doesn't throw any errors, I hope anyone else with this problem is helped by this.
In insert mode, <C-n> usually completes words with the content of your buffers. I don't know how it works internally but it may complain about a buffer's associated file's path length.
But I can't find a reference to E854 in Vim's :help, which can be normal if it comes from a plugin I don't have.
You could:
try :verbose imap <c-n> to locate its origin or
search the help for the tag E854, :help E854 or
search the help for the sting E854, :helpgrep E854 or
grep for E854 in your ~/.vim folder, $ grep -r E854 ~/.vim.
I had an issue like this similar. Turns out it was blowing up because the current ruby.vim that's distributed with Vim calls a deprecated Gem.all_load_paths which puts a nasty error in your path variable. Check out https://github.com/rubygems/rubygems/issues/161 and https://groups.google.com/forum/#!msg/vim_dev/wrouKpIDraU/xLxUuMT3_6QJ for a fix :)
My copy of the vim source code (obtained at some point using Mercurial and hg clone https://vim.googlecode.com/hg/) finds that error being thrown only in one spot, in the internal function vim_findfile_init():
static char_u e_pathtoolong[] = N_("E854: path too long for completion");
...
/*
* copy wc_path and add restricts to the '**' wildcard.
* The octet after a '**' is used as a (binary) counter.
* So '**3' is transposed to '**^C' ('^C' is ASCII value 3)
* or '**76' is transposed to '**N'( 'N' is ASCII value 76).
* For EBCDIC you get different character values.
* If no restrict is given after '**' the default is used.
* Due to this technique the path looks awful if you print it as a
* string.
*/
len = 0;
while (*wc_part != NUL)
{
if (len + 5 >= MAXPATHL)
{
EMSG(_(e_pathtoolong));
break;
}
...
So it looks like it's doing arbitrary-depth wildcard expansion. If I had to take a wild stab I'd say you have a path somewhere in the filesystem that has a circular symbolic link (say c -> a), so you end up doing path completion and getting /foo/bar/a/b/c/a/b/c/a/b/c/a/b/c/..... and the limit gets hit.
Edit
Scratch that last theory; based on actually reading the code, it looks like it's trying to find a tag file and blowing up. Can you post what you get when you do :set tags ?
Edit 2
Sigh, it's late... Here's the answer you originally wanted that I just found: do :help completefunc and :help completion-functions. completefunc is the one you want, if I (finally) understand your question.

Automatically folding #defines in vim

I work with quite a bit of multi-platform C/C++ code, separated by common #defines (#if WIN, #if UNIX, etc). It would be nice if I could have vim automatically fold the sections I'm currently not interested in when I open a file. I've searched through the vim script archives, but I haven't found anything useful. Any suggestions? Places to start?
Just add a folding region to your syntax
http://vim.wikia.com/wiki/Syntax_folding_of_Vim_scripts#Syntax_definitions
:syn region myFold start="\#IF" end="\#ENDIF" transparent fold
:syn sync fromstart
:set foldmethod=syntax
To add to #hometoasts answer, you can add that command as a comment in the first ten or last ten lines of the file and vim will automatically use it for that file.
/* vim: syn region regionName start="regex" end="regex": */
A quick addition to Denton's addition: to use the new syntax rule with any C or C++ code, add it to a file at $VIMRUNTIME/syntax/c.vim and cpp.vim. ($VIMRUNTIME is where your local Vim code lives: ~/.vim on Unix.) Also, the values for start and end in the syntax definition are regular expressions, so you can use ^#if and ^#endif to ensure they only match those strings at the start of a line.
I've always used forldmethod=marker and defined my own fold tags placed within comments.
this is for defining the characters that define the open and close folds. in this case open is "<(" and close is ")>" replace these with whatever you'd like.
set foldmethod=marker
set foldmarker=<(,)>
This is my custom function to decide what to display of the folded text:
set foldtext=GetCustomFoldText()
function GetCustomFoldText()
let preline = substitute(getline(v:foldstart),'<(','<(+)','')
let line = substitute(preline,"\t",' ','g')
let nextLnNum = v:foldstart + 1
let nextline = getline(nextLnNum)
let foldTtl = v:foldend - v:foldstart
return line . ' | ' . nextline . ' (' . foldTtl . ' lines)>'
endfunction
Hope that helps.
I have a huge code base and so a large number of #defines. Each file has numerous #ifdef's
and most of the times they are nested. I tried many of the vim scripts but they always
used to run into some error with the code I have. So in the end I put all my defines in
a header file and included it in the file that I wanted to work with and did a gcc on it
like this
gcc -E -C -P source.cpp > output.cpp
The -E command gets gcc to run only the pre-processor on the file, so all the unwanted
code within the undefined #ifdef's are removed.
The -C option retains the comments in the file.
The -P option inhibits generation of linemarkers in the output from the preprocessor.

Resources