I am writing a mapping to autocomplete tags
Pattern: <.*?>, matches complete HTML tags only.
The goal is to lookbehind and see if there exists a text like <html>.
Mapping: inoremap <expr> <leader>< TagComplete()
func! TagComplete() { let match=search('<.*?>', 'b', '.') return match } Once I run the Mapping in insert mode after typing <html>, on execution of function TagComplete, if the pattern is matched, the match variable should have value <html> and at the cursor position <\html> should be inserted. Once done the editor should be in insert mode, keeping the cursor between the tags.
I am having difficulty in returning the match applying search().
Also vim does not understand non-greedy ? in pattern.
EDIT:
I am able to print closing tag:
inoremap <expr> <C-V> AutoCompleteTag() func! AutoCompleteTag() let l:match = search('<[^/].\{-}>', 'bn', line(".")) let l:pat="<\zs\/.\{-}\ze>" if l:match > 0 let l:lastMatch=MatchStrLast(getline(l:match), '<\zs.\{-}\ze>') if l:lastMatch!~"\/.*" return '</'.l:lastMatch.'>' endif endif endfunc " use the {count} parameter for matchstr() to increment your way through the " string function! MatchStrLast(expr, pat, ...) let start = a:0 ? a:1 : 0 let last = '' let cnt = 1 let found = match(a:expr, a:pat, start, cnt) while found != -1 let last=matchstr(a:expr, a:pat, start, cnt) let cnt += 1 let found = match(a:expr, a:pat, start, cnt) endwhile return last endfunction Explanation:
search('<[^/].\{-}>', 'bn', line(".")), I am searching to see if a valid tag pattern exits on current line. If yes, store line number inl:match. Is there a way to search backwards from cursor position and match the opening tag.MatchStrLast(getline(l:match), '<\zs.\{-}\ze>'), gets the name of the tag.
Concerns:
I am not able to find a way to move the cursor so that it is in the middle of the tags.
Once the mapping is run, it prints a 0 if the match is not found. How not to print anything in case the regexp does not match the pattern?
Also, in if condition if l:lastMatch!~"\/.*", I tried the pattern <\zs\/.\{-}\ze> in place of \/.*, that I expected to match string "/S.Component", but it did not. Reason?.
Since, I am new to vimscript, I appreciate anyone pointing out an anti-pattern and please suggest improvements.
.*?is not a valid vim regex pattern, have a look at:h non-greedyfor the correct way of non-greedy patterns.<.*>\{-}for non greedy match? With this pattern it just matched entire tags with content included<[^>]*>to match complete tags?\/\?\zs\a\+\ze[ >]. But I can't get it to match a tag name "S.Container" in<S.Container>, but it does match "container" in<container>