I've recently started using AutoComplPop, but I find the popup annoying when I'm writing comments (as I usually don't need autocomplition when writing a comment).
Is there a configuration option or a quick hack that can effectively disable AutoComplPop when the insertion point is in a comment?
To answer the question of performance when checking the syntax on every cursor move, I had to implement this myself, and made this into the OnSyntaxChange plugin.
With this plugin, setting this up can be done in just three lines (e.g. in .vimrc):
call OnSyntaxChange#Install('Comment', '^Comment$', 0, 'i')
autocmd User SyntaxCommentEnterI silent! AcpLock
autocmd User SyntaxCommentLeaveI silent! AcpUnlock
For me, the performance impact is noticeable (depending on the filetype and syntax), but tolerable. Try for yourself!
You need to check via a hook into CursorMovedI that you're currently in a comment, and can then use AutoComplPop's :AcpLock to disable it temporarily. (And undo with :AcpUnlock once you move out of comments.)
Detecting comments for various filetypes is best done by querying the syntax highlighting; this way, you benefit from the syntax definitions of existing filetypes.
Here's a snippet for this:
function! IsOnSyntaxItem( syntaxItemPattern )
" Taking the example of comments:
" Other syntax groups (e.g. Todo) may be embedded in comments. We must thus
" check whole stack of syntax items at the cursor position for comments.
" Comments are detected via the translated, effective syntax name. (E.g. in
" Vimscript, 'vimLineComment' is linked to 'Comment'.)
for l:id in synstack(line('.'), col('.'))
let l:actualSyntaxItemName = synIDattr(l:id, 'name')
let l:effectiveSyntaxItemName = synIDattr(synIDtrans(l:id), 'name')
if l:actualSyntaxItemName =~# a:syntaxItemPattern || l:effectiveSyntaxItemName =~# a:syntaxItemPattern
return 1
endif
endfor
return 0
endfunction
With this, you should be able to stitch together a solution.
Related
My goal is to extend the foldmethod=syntax with an additional custom defined rule of my own.
My approach in doing so is to use foldmethod=expr and define this rule in my foldexpr (e.g. add a fold for '///' comments). After that the resources I found usually fall back to something similar to indentation folding. So is there a good way to fall back to syntax folding after the custom rules, without reproducing the complete grammar for whatever language I am using?
My attempt so far is this, which is not a very satisfying approximation of syntax folding:
function! GetFold(lnum)
let this_line=getline(a:lnum)
let pprev_i=indent(a:lnum - 2)/&shiftwidth
let prev_i=indent(a:lnum - 1)/&shiftwidth
let this_i=indent(a:lnum)/&shiftwidth
" comments
if this_line =~? '^\s*\/\/\/.*'
return this_i + 1
endif
" like indent folding, but includes the closing bracket line to the fold
if empty(this_line)
if prev_i < pprev_i
return prev_i
endif
return -1
endif
if this_i < prev_i
return prev_i
endif
return this_i
endfunction
The solution is to just use set fold=syntax and add a syntax region for the comments to your .vimrc. There you can use the fold keyword to mark the region as foldable (see :h syn-fold for more information):
syn region myFold start="///" end="///" transparent fold
(Note, take also a look at :h syn-transparent it is quite useful here)
No, there isn't a way to make Vim "fall back"; only one 'foldmethod' can be active at a time, and there's no API to evaluate another fold method "as if".
You could temporarily switch to syntax folding, store the generated folds, and then use that information in your fold information, extended with what your algorithm determines. (Or you could keep the same buffer in a window split, have syntax folding enabled there, and query it from the; this would save the complete re-creation of the folds, but you'd probably need to synchronize the cursor positions.)
This is cumbersome and possibly slow; I wouldn't recommend it.
I know that I can use :nmap, :vmap, :imap commands to display all the mapping for those 3 modes. However, I would like to display comments that I have for a single mapping.
So suppose I have the following entry in my vimrc:
" Execute current line in bash
nmap <F9> :exec '!'.getline('.')<CR>
This could also look like this:
nmap <F9> :exec '!'.getline('.')<CR> " Execute current line in bash
I would like to have a command that for this mapping that would look something like this:
<F9> Execute current line in bash
As this probably can only be done using custom function, where do I start? How do I parse .vimrc to strip only key mappings and their corresponding comments (I have only done some very basic Vim scripts)?
Do I understand correctly from :help map-comments that I should avoid inline comments in .vimrc?
It's very hard to "embed" comments into a mapping without affecting its functionality. And this would only help with our own mappings, not the ones from plugins.
Rather, I'd suggest to learn from (well-written) plugins, which provide :help targets for their (default) key mappings. So, to document your mapping(s), create a help file ~/.vim/doc/mymappings.txt with:
*<F9>*
<F9> Execute current line in bash
After :helptags ~/.vim/doc, you will be able to look up the comments via :h <F9>. By using the help file, you can use syntax highlighting, longer multi-line comments, and even examples, so I think that'a better and more straightforward solution.
Personally, I wouldn't have much use for such a feature for two reasons: the first one, is that I always have a vim session with a note taking buffer that contains all the tips/commands not yet in my muscle memory. Secondly, you can list all the maps using :map, and it's always a great exercise for your brain in learning vim to literally read vim commands.
That being said…
As this probably can only be done using custom function, where do I start?
…well I guess you could imagine using a function with a prototype such as:
AddMap(op, key, cmd, comment)
used like:
call AddMap("nmap", "<F9>", ":exec '!'.getline('.')<CR>", "Execute current line in shell")
which implementation would add key and comment to an array, so that you could list the array to get your own mappings declared. Using a function like ListMap().
let map_list = []
function! AddMap(op, key, cmd, comment)
" add to map list
insert(map_list, [op, key, comment])
" execute map assign
exec op.' '.key.' '.cmd
endfunction
function! ListMap()
for it in map_list
echo it[0] . '\t' . it[1] . '\t' . it[2]
endfor
endfunction
Of course, one could elaborate on the ListMap() function implementation to generate a more "proper" help file that you could open in a buffer. But that's an idea of how you could do an implementation for a feature close to what you're looking for.
N.B.: this snippet is mostly an idea of how I'd tackle this problem, and it's a one shot write that I did not actually try.
How do I parse .vimrc to strip only key mappings and their corresponding comments (I have only done some very basic Vim scripts)?
I don't think that would be a good solution, I think the better way to achieve your goal is my suggestion. Simpler and more explicit, though it won't show off all mappings. But you don't have all your mappings in your .vimrc.
Do I understand correctly from :help map-comments that I should avoid inline comments in .vimrc?
To be more precise you shall not use inline comments after maps, because they will be interpreted part of the mapping.
how to get mapping created by plugins?
Besides, using :map, you just don't. You look at the sources/documenation of your plugins and find out about them. There's no such thing as a reverse lookup from runtime to declaration point.
Just asked a question a few moments ago about how to wrap a line in a comment which yielded this fantastic snippet:
nnoremap - mzI/* <esc>A */<esc>`z
I wanted to open another thread to ask how I can turn this into a toggle. Meaning it first checks if the line is wrapped in /* */ and removes the comment or adds it if it is not there.
Does this have to be a script or can I do this with a map? Also I don't want to use a plugin for this because its simple and I would like to see how its done.
Here you go:
nnoremap <expr> - getline('.') =~ '^\s*/\*.\+\*/$' ? '^3x$daw' : "I/* \<esc>A */\<esc>"
The un-commenting is done by ^3x$daw which deletes the beginning and ending portions of the mapping. The detection is done via a regex on the current line, getline('.'). I have removed the z mark from the comment portion of the mapping as it does a poor job of keeping cursor in the "same" spot.
This is a great example of a fancier mapping. However there are somethings to think about:
This mapping pollutes the . and " registers.
Only works on filetypes with c-style comments
No visual or operator like mappings, meaning you can not mass toggle.
Does not repeat via .
I highly recommend a comment plugin. I currently use Tim Pope's vim-commentary plugin.
For more help see:
:h :map-<expr>
:h getline(
RE I don't want to use a plugin for this because its simple.
It's only simple until you use this heavily; Peter Rincker's answer already lists some issues. As you probably rely on (un-)commenting a lot, this is really a good indication for a robust, proven plugin.
Let me throw in a recommendation for The NERD Commenter; it has the toggle mapping you're asking for, and supports several languages. Apart from commentary, also have a look at tComment.
since dividing and loading each windows every time are kinda bothersome, I saved my session using:
mksession ~/session1.vim
and restored it using:
vim -S session1.vim
or
source session1.vim
it restores the previous session perfectly, but doesn't show any syntax highlighting at all.
I found a similar question over here: No syntax highlighting after session restore in terminal
but doesn't help much.
does anyone have any idea?
I had the same problem; if I saved sessions without 'options' in sessionoptions, when I reloaded Vim, the buffers were reloaded, but without syntax highlighting.
The solution is to use an autocmd with nested when reloading.
Wikia has an extensive article about loading and saving sessions. The 'nested' option is mentioned at the bottom.
I use a modified version of this StackOverflow answer, here it is:
fu! SaveSess()
execute 'mksession! ' . getcwd() . '/.session.vim'
endfunction
fu! RestoreSess()
if filereadable(getcwd() . '/.session.vim')
execute 'so ' . getcwd() . '/.session.vim'
if bufexists(1)
for l in range(1, bufnr('$'))
if bufwinnr(l) == -1
exec 'sbuffer ' . l
endif
endfor
endif
endif
endfunction
autocmd VimLeave * call SaveSess()
autocmd VimEnter * nested call RestoreSess()
set sessionoptions-=options " Don't save options
I can across this Issue using the Obsession vim plugin and Neovim aswell. The answer in this thread helped me finding the solution although in my case the solution provided here didn't work immediately.
I took a look at the sessionoptions help page. For me the setting that fixed the problem was set sessionoptions+=localoptions. Then after reloading vim with this option in the config and after reloading the syntax highlighting, the highlighting was saved in the session.
I had the same issue. I deleted my session file, I re-created it with mks and that fixed the issue. Probably it was in an inconsistent state.
If I do either of the following two:
call search("searchString")
exec "/ searchString"
From a script, then vim does the search but does not highlight the results, even though hlsearch. Doing the same searches from outside a script highlights the results.
Just found out the answer myself:
call search(l:searchString)
call matchadd('Search', l:searchString)
The
feedkeys()
function is the key (pun intended):
call feedkeys("/pattern\<CR>")
or cleaner:
" highlights – or doesn’t – according to 'hlsearch' option
function SearcH(pattern)
let #/ = a:pattern
call feedkeys("/\<CR>")
endfunction
I know this is late. However when I searched for the answer to this problem this page came up. So I feel compelled to help fix it.
call search(l:searchString)
call matchadd('Search', l:searchString)
Did not work for me. (when run from inside a function) It did higlight the words I wanted to search for but n/N wouldn't cycle between them. Also when I performed a new search the "l:serachStirng" pattern still remained highlighted. This answer on this link worked much better
Vim search and highlighting control from a script
Which gave me:
let #/ = l:searchString
then run
normal n
outside the funciton (so the highlighting is done immediately without the user needing to press n)
To turn on, press ESC type :set hls
To turn off, press ESC type :set nohls
Found answer here:
http://vim.1045645.n5.nabble.com/highlighting-search-results-from-within-a-function-tt5709191.html#a5709193
```
One solution would be
function! XXXX()
execute '/this'
return #/
endfunction
and to use the following instead of ":call XXXX()".
:let #/ = XXXX()
```
I believe this works from inside a function
(to just enable highlighting and nothing more):
call feedkeys(":\<C-u>set hlsearch \<enter>")
You need to put this in your .vimrc file
" Switch syntax highlighting on, when the terminal has colors
" Also switch on highlighting the last used search pattern.
if &t_Co > 2 || has("gui_running")
syntax on
set hlsearch
endif
The .vimrc file is usually located in your home directory, or you can find it using "locate .vimrc"