nhunsaker
nhunsaker

Reputation: 43

Vim Autocomplete Fails When Word to Autocomplete is Not Surrounded by Whitespace

Can anyone help me debug why autocomplete fails to work in this situation? (as an example where TAB is me actually hitting tab to autocomplete):

my $variable;

while(<>) {
    if($_ =~ m/$variabTAB/i)

But works fine here:

$second_var = $variabTAB

I believe it's because the second case has the word that is being auto-completed by itself, in other words surrounded by whitespace. It fails because the first example has the word padded by other characters.

The following is my vimrc:

set history=700
filetype on
filetype indent on
set autoread
let mapleader = ","
let g:mapleader = ","
nmap <leader>w :w!<cr>
set so=7
set wildmenu
set wildignore=*.o,*~,*.pyc
set ruler
map <C-J> <C-W>j<C-W>_
map <C-K> <C-W>k<C-W>_
set winminheight=0
set winwidth=80
set cmdheight=2
set hid
set backspace=eol,start,indent
set whichwrap+=<,>,h,l
set ignorecase
set smartcase
set nohlsearch
set incsearch
set lazyredraw
set magic
set showmatch
set matchtime=3
set mat=2
set noerrorbells
set novisualbell
set tm=500
set joinspaces
set nolist
set scrolloff=4
set foldminlines=1
set completeopt=menu
colorscheme desert
set background=dark
if has("gui_running")
    set guioptions-=T
    set guioptions+=e
    set t_Co=256
    set guitablabel=%M\ %t
endif
set guioptions=gmrLt
set guifont=Lucida_Consoloe:h8:cANSI
set encoding=utf8
set ffs=unix,dos,mac
set directory=./_backup
set backupdir=./.backup
set nowb
set noswapfile
set expandtab
set smarttab
set softtabstop=4
set smartindent
set nonumber
set nowarn
set shiftwidth=4
set tabstop=4
set lbr
set tw=500
set ai "Auto indent
set si "Smart indent
set wrap "Wrap lines
vnoremap <silent> * :call VisualSelection('f')<CR>
vnoremap <silent> # :call VisualSelection('b')<CR>
map <space> /
map <c-space> ?
map <silent> <leader><cr> :noh<cr>
map <leader>bd :Bclose<cr>
map <leader>ba :1,1000 bd!<cr>
map <leader>tn :tabnew<cr>
map <leader>to :tabonly<cr>
map <leader>tc :tabclose<cr>
map <leader>tm :tabmove
map <leader>te :tabedit <c-r>=expand("%:p:h")<cr>/
map <leader>cd :cd %:p:h<cr>:pwd<cr>
try
  set switchbuf=useopen,usetab,newtab
  set stal=2
catch
endtry
set laststatus=2
set statusline=\ %{HasPaste()}%F%m%r%h\ %w\ \ CWD:\ %r%{getcwd()}%h\ \ \ Line:\ %l
map 0 ^
vnoremap <silent> gv :call VisualSelection('gv')<CR>
map <leader>g :vimgrep // **/*.<left><left><left><left><left><left><left>
map <leader><space> :vimgrep // <C-R>%<C-A><right><right><right><right><right><right><right><right><right>
vnoremap <silent> <leader>r :call VisualSelection('replace')<CR>
map <leader>cc :botright cope<cr>
map <leader>co ggVGy:tabnew<cr>:set syntax=qf<cr>pgg
map <leader>n :cn<cr>
map <leader>p :cp<cr>
map <leader>ss :setlocal spell!<cr>
map <leader>sn ]s
map <leader>sp [s
map <leader>sa zg
map <leader>s? z=
noremap <Leader>m mmHmt:%s/<C-V><cr>//ge<cr>'tzt'm
map <leader>q :e ~/buffer<cr>
map <leader>pp :setlocal paste!<cr>
function! Smart_TabComplete()
  let line = getline('.')                         " current line
  let substr = strpart(line, -1, col('.')+1)      " from the start of the current
                                                  " of the cursor
  let substr = matchstr(substr, "[^ \t]*$")       " word till cursor
  if (strlen(substr)<2)                          " nothing to match on empty string
    return "\<tab>"
  endif
  let has_period = match(substr, '\.') != -1      " position of period, if any
  let has_slash = match(substr, '\/') != -1       " position of slash, if any
  if (!has_period && !has_slash)
    return "\<C-X>\<C-P>"                         " existing text matching
  elseif ( has_slash )
    return "\<C-X>\<C-F>"                         " file matching
  else
    return "\<C-X>\<C-O>"                         " plugin matching
  endif
endfunction

inoremap <tab> <c-r>=Smart_TabComplete()<CR>

Upvotes: 0

Views: 235

Answers (1)

Ingo Karkat
Ingo Karkat

Reputation: 172590

Your hunch is right. This line from your completion function

let substr = matchstr(substr, "[^ \t]*$")       " word till cursor

grabs all the non-whitespace characters in front of the cursor; m/$variab in your example.

Because it contains a slash, the file completion is then triggered, which doesn't consider the $variable, naturally.

To fix this, you could switch to matching only keyword characters (\k*$, what the default completion considers), but that might negatively affect the file completion case.

Upvotes: 1

Related Questions