How to remove digraph highlighting in vim - vim

Using vim or nvim, when I open a new vim terminal digraphs display correctly. See below:
However, whenever I change colorscheme (any, it is not specific to a particular colorscheme) - then the digraphs appear highlighted. The highlighting remains even when switching back to the original colorscheme. This happens with any digraph, not just the one shown in this question.
See below:
Cannot find a way to remove that highlighting, or prevent it happening in the first place. Have tried commands like :highlight nonascii none but had no luck. Any help / suggestions much appreciated.

Most/Some of the colorschemes aren't really made for hotswap.
It seems to be a rather common problem with solarized f.e.
There is a plugin which handles a change cleanly: https://github.com/xolox/vim-colorscheme-switcher (I haven't tested it).
And I copied a bunch of functions for that somewhere which works arround the problems most of the time. I don't know where I got it from, but I want to be clear, it is not my work!
function! s:Find_links() " {{{1
" Find and remember links between highlighting groups.
redir => listing
try
silent highlight
finally
redir END
endtry
for line in split(listing, "\n")
let tokens = split(line)
" We're looking for lines like "String xxx links to Constant" in the
" output of the :highlight command.
if len(tokens) == 5 && tokens[1] == 'xxx' && tokens[2] == 'links' && tokens[3] == 'to'
let fromgroup = tokens[0]
let togroup = tokens[4]
let s:known_links[fromgroup] = togroup
endif
endfor
endfunction
function! s:Restore_links() " {{{1
" Restore broken links between highlighting groups.
redir => listing
try
silent highlight
finally
redir END
endtry
let num_restored = 0
for line in split(listing, "\n")
let tokens = split(line)
" We're looking for lines like "String xxx cleared" in the
" output of the :highlight command.
if len(tokens) == 3 && tokens[1] == 'xxx' && tokens[2] == 'cleared'
let fromgroup = tokens[0]
let togroup = get(s:known_links, fromgroup, '')
if !empty(togroup)
execute 'hi link' fromgroup togroup
let num_restored += 1
endif
endif
endfor
endfunction
function! s:AccurateColorscheme(colo_name)
call <SID>Find_links()
exec "colorscheme " a:colo_name
call <SID>Restore_links()
endfunction
command! -nargs=1 -complete=color MyColorscheme call <SID>AccurateColorscheme(<q-args>)

Related

Vim not setting `tex` filetype on startup

I noticed that if I open a non-existent HTML file with Vim, the filetype is set automatically to html:
$ vim foobar.html
:set filetype # --> filetype=html
On the other hand, the same does not happen with TeX. If I create a non-existent file the filetype is plaintext, and I have to save the file and reopen it to have it correctly set:
$ vim blabla.tex
:set filetype # --> filetype=plaintext
I also tried with Python, C, VimL, Javascript files and the filetype is always set right away. I don't know why this does not happen with TeX files.
The only thing I can think might interfere is vim-latex. Could that be possible? If so, how do I fix this problem?
If it might be of help, here is my not so long .vimrc file.
Vim uses a giant heuristic to determine plaintex vs other variations of tex.
If you look in $VIMRUNTIME/filetype.vim you will find the following function
" Choose context, plaintex, or tex (LaTeX) based on these rules:
" 1. Check the first line of the file for "%&<format>".
" 2. Check the first 1000 non-comment lines for LaTeX or ConTeXt keywords.
" 3. Default to "latex" or to g:tex_flavor, can be set in user's vimrc.
func! s:FTtex()
let firstline = getline(1)
if firstline =~ '^%&\s*\a\+'
let format = tolower(matchstr(firstline, '\a\+'))
let format = substitute(format, 'pdf', '', '')
if format == 'tex'
let format = 'plain'
endif
else
" Default value, may be changed later:
let format = exists("g:tex_flavor") ? g:tex_flavor : 'plain'
" Save position, go to the top of the file, find first non-comment line.
let save_cursor = getpos('.')
call cursor(1,1)
let firstNC = search('^\s*[^[:space:]%]', 'c', 1000)
if firstNC " Check the next thousand lines for a LaTeX or ConTeXt keyword.
let lpat = 'documentclass\>\|usepackage\>\|begin{\|newcommand\>\|renewcommand\>'
let cpat = 'start\a\+\|setup\a\+\|usemodule\|enablemode\|enableregime\|setvariables\|useencoding\|usesymbols\|stelle\a\+\|verwende\a\+\|stel\a\+\|gebruik\a\+\|usa\a\+\|imposta\a\+\|regle\a\+\|utilisemodule\>'
let kwline = search('^\s*\\\%(' . lpat . '\)\|^\s*\\\(' . cpat . '\)',
\ 'cnp', firstNC + 1000)
if kwline == 1 " lpat matched
let format = 'latex'
elseif kwline == 2 " cpat matched
let format = 'context'
endif " If neither matched, keep default set above.
" let lline = search('^\s*\\\%(' . lpat . '\)', 'cn', firstNC + 1000)
" let cline = search('^\s*\\\%(' . cpat . '\)', 'cn', firstNC + 1000)
" if cline > 0
" let format = 'context'
" endif
" if lline > 0 && (cline == 0 || cline > lline)
" let format = 'tex'
" endif
endif " firstNC
call setpos('.', save_cursor)
endif " firstline =~ '^%&\s*\a\+'
" Translation from formats to file types. TODO: add AMSTeX, RevTex, others?
if format == 'plain'
setf plaintex
elseif format == 'context'
setf context
else " probably LaTeX
setf tex
endif
return
endfunc
This function determines which flavor of tex to use. If you look at it you can see that default value is taken from g:tex_flavor (if it exists, defaults to plain). If you set this variable to tex (in you vimrc), vim will default to the tex filetype.
let g:tex_flavor = 'tex'
There is a way to automate the process you're doing manually.
Adding autocmd BufRead,BufNewFile *.tex set filetype=tex to your .vimrc file will set tex filetype for each tex file, once you open them in vim.

How to convert leading spaces to tabs?

Many people use spaces rather than tabs. I use both of them. Tabs at the beginning of line and spaces from the first non-whitespace character. No problem for starting new document and in case I have to modify one better adapt to using format. Still sometimes I need to fix the spaces issue anyway.
According to Search and replace I can just do :%s/spaces_for_tab/tab/g. It is simple and it will work for many cases. Anyway I want to refactor only spaces at the beginning of line.
This is more of a regex issue. To anchor at the beginning of the line, use the caret, e.g.
s/^ /\t/
Or do it using vim's builtin functionality:
:set tabstop=4 "four spaces will make up for one tab
:set noexpandtab "tell vim to keep tabs instead of inserting spaces
:retab "let vim handle your case
By the way, I too prefer tabs for indentation and spaces for alignment. Unfortunately, vim doesn't handle this well (and I don't know what other editors do), so I mostly use :set expandtab (maybe see :set softtabstop).
I've written a simple func for it. Anyway it will work only for 4-space tab.
fu! Fixspaces()
while search('^\t* \{4}') != 0
execute ':%s/^\t*\zs \{4}/\t/g'
endwhile
endfu
You can suggest better solution, if exists, and I will use it with pleasure.
The issue is that this func replaces spaces in strings as well.
David's response is very elegant but it doesn't address leading whitespace that has a mixture of tabs and spaces. For example to convert a line like:
<SPACE><SPACE><TAB>something...
you have to know the position of the tab to determine the number of spaces needed to replace the <TAB> and reach the next tabstop. My solution below, although not as compact as David's, addresses this. It also allows me to select which way to use leading whitespace without depending upon &expandtab. I would appreciate any suggestions to improve my code...
function! TabsToSpaces(...)
let ts = &tabstop
let pos = getpos('.')
while search('^ *\zs\t', "w") != 0
let l:curpos = getcharpos('.')
" The number of spaces needed depends upon the position of the <TAB>
let numsp = 1 + ts - ( curpos[2] % ts )
if numsp == 9
let numsp = 1
endif
silent execute ':s/^ *\zs\t/'.repeat(' ', numsp).'/'
endwhile
if a:0 == 0
echo 'Changed leading tabs to spaces'
endif
call setpos('.', pos)
endfunction
function! SpacesToTabs(...)
let ts = &tabstop
let pos = getpos('.')
" First normalize all tabs to spaces
call TabsToSpaces("quiet")
while search('^\t* \{'.ts.'}') != 0
silent execute ':%s/^\t*\zs \{'.ts.'}/\t/g'
endwhile
if a:0 == 0
echo 'Changed leading spaces to tabs'
endif
call setpos('.', pos)
endfunction
" Some keystrokes to implement the spaces/tabs functions
nmap <Leader>st :execute SpacesToTabs()<CR>
nmap <Leader>ts :execute TabsToSpaces()<CR>
I took Martin's answer and improved on it a bit if anyone's interested:
function Fixspaces()
let ts = &tabstop
let pos = getpos('.')
if &expandtab
while search('^ *\t') != 0
silent execute ':%s/^ *\zs\t/'.repeat(' ', ts).'/g'
endwhile
echo 'Changed tabs to spaces'
else
while search('^\t* \{'.ts.'}') != 0
silent execute ':%s/^\t*\zs \{'.ts.'}/\t/g'
endwhile
echo 'Changed spaces to tabs'
endif
call setpos('.', pos)
endfunction
This function does the appropriate thing depending on the values of the expandtab and tabstop settings and also remembers where the cursor is.

How to get group name of highlighting under cursor in vim?

I usually customize existing colorscheme to meet my needs.
If I could get the syntax group name under cursor, it would help me a lot, just like Firebug but in Vim. I'd like to know how to do it.
There is this function that was floating around the web when I was doing the same thing:
function! SynStack()
if !exists("*synstack")
return
endif
echo map(synstack(line('.'), col('.')), 'synIDattr(v:val, "name")')
endfunc
The following function will output both the name of the syntax group, and the translated syntax group of the character the cursor is on:
function! SynGroup()
let l:s = synID(line('.'), col('.'), 1)
echo synIDattr(l:s, 'name') . ' -> ' . synIDattr(synIDtrans(l:s), 'name')
endfun
To make this more convenient it can be wrapped in a custom command or key binding.
How this works:
line('.') and col('.') return the current position
synID(...) returns a numeric syntax ID
synIDtrans(l:s) translates the numeric syntax id l:s by following highlight links
synIDattr(l:s, 'name') returns the name corresponding to the numeric syntax ID
This will echo something like:
vimMapModKey -> Special
Here's a mapping that will show the hierarchy of the synstack() and also show the highlight links. press gm to use it.
function! SynStack ()
for i1 in synstack(line("."), col("."))
let i2 = synIDtrans(i1)
let n1 = synIDattr(i1, "name")
let n2 = synIDattr(i2, "name")
echo n1 "->" n2
endfor
endfunction
map gm :call SynStack()<CR>
Try this:
" diagnostics {{{
if has('balloon_eval')
nnoremap <F12> : setl beval!<CR>
set bexpr=InspectSynHL()
endif
fun! InspectSynHL()
let l:synNames = []
let l:idx = 0
for id in synstack(v:beval_lnum, v:beval_col)
call add(l:synNames, printf('%s%s', repeat(' ', idx), synIDattr(id, 'name')))
let l:idx+=1
endfor
return join(l:synNames, "\n")
endfun
"}}}

Vim autocommand trigger on opening "nothing"

I want vim to open up the :Explorer when no file is opened or created. Eg. when I call vim without any options.
calling vim newfile.txt should still behave the normal way though.
How would I go about doing this? I can't seem to find the correct autocmd for it.
If you want to do this for vim invocation only, the best way is to use argc():
autocmd VimEnter * :if argc() is 0 | Explore | endif
argc() function returns a number of filenames specified on command-line when vim was invoked unless something modified arguments list, more information at :h argc().
Found the answer myself:
"open to Explorer when no file is opened
function! TabIsEmpty()
" Remember which window we're in at the moment
let initial_win_num = winnr()
let win_count = 0
" Add the length of the file name on to count:
" this will be 0 if there is no file name
windo let win_count += len(expand('%'))
" Go back to the initial window
exe initial_win_num . "wincmd w"
" Check count
if win_count == 0
" Tab page is empty
return 1
else
return 0
endif
endfunction
" Test it like this:
" echo TabIsEmpty()
function! OpenExplorer()
if (TabIsEmpty())
:Explore
end
endfunction
The greatest part of this code was taken from this question.

Is there any easy way to toggle "do/end" and "{}" in ruby in Vim?

Is there any easy way to toggle "do/end" and "{}" in ruby in Vim?
(TextMate does this with ^{.)
You'd have to either use searchpair(), or to play with % (as long as matchit is installed, and as you are on begin/end), then mark the two positions, test whether it's text or brackets, and finally update the two lines.
nnoremap <buffer> <c-x>{ :call <sid>ToggleBeginOrBracket()<cr>
let s:k_be = [ 'begin', 'end' ]
function! s:ToggleBeginOrBracket()
let c = lh#position#char_at_mark('.')
if c =~ '[{}]'
" don't use matchit for {,}
exe 'normal! %s'.s:k_be[1-(c=='}')]."\<esc>``s".s:k_be[(c=='}')]."\<esc>"
else
let w = expand('<cword>')
if w == 'begin'
" use mathit
normal %
exe "normal! ciw}\<esc>``ciw{\<esc>"
elseif w == 'end'
" use mathit
normal %
exe "normal! ciw{\<esc>``ciw}\<esc>"
else
throw 'Cannot toggle block: cursor is not on {, }, begin, nor end'
endif
endif
endfunction
Where lh#position#char_at_mark() is defined here.
PS: this is definitively a SO question as it combines ruby context, and advanced vim scripting.
Check out this new plugin: https://github.com/jgdavey/vim-blockle.
30 chars pad
There is a splitjoin.vim plugin that does this nicely (gJ/gS mappings for splitting/joining).

Resources