changeset 654:441f938ea9e9 v7.0192

updated for version 7.0192
author vimboss
date Sat, 04 Feb 2006 00:59:56 +0000
parents 5acda076fb0c
children 7566e1cda7bf
files runtime/autoload/ccomplete.vim runtime/doc/todo.txt runtime/doc/version7.txt runtime/mswin.vim
diffstat 4 files changed, 183 insertions(+), 74 deletions(-) [+]
line wrap: on
line diff
--- a/runtime/autoload/ccomplete.vim
+++ b/runtime/autoload/ccomplete.vim
@@ -1,13 +1,13 @@
 " Vim completion script
 " Language:	C
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last Change:	2006 Jan 30
+" Last Change:	2006 Feb 03
 
 
 " This function is used for the 'omnifunc' option.
 function! ccomplete#Complete(findstart, base)
   if a:findstart
-    " Locate the start of the item, including "." and "->".
+    " Locate the start of the item, including ".", "->" and "[...]".
     let line = getline('.')
     let start = col('.') - 1
     let lastword = -1
@@ -24,6 +24,21 @@ function! ccomplete#Complete(findstart, 
 	  let lastword = start
 	endif
 	let start -= 2
+      elseif line[start - 1] == ']'
+	" Skip over [...].
+	let n = 0
+	let start -= 1
+	while start > 0
+	  let start -= 1
+	  if line[start] == '['
+	    if n == 0
+	      break
+	    endif
+	    let n -= 1
+	  elseif line[start] == ']'  " nested []
+	    let n += 1
+	  endif
+	endwhile
       else
 	break
       endif
@@ -43,20 +58,53 @@ function! ccomplete#Complete(findstart, 
 
   let base = s:prepended . a:base
 
+  " Don't do anything for an empty base, would result in all the tags in the
+  " tags file.
+  if base == ''
+    return []
+  endif
+
   " Split item in words, keep empty word after "." or "->".
   " "aa" -> ['aa'], "aa." -> ['aa', ''], "aa.bb" -> ['aa', 'bb'], etc.
-  let items = split(base, '\.\|->', 1)
-  if len(items) <= 1
-    " Don't do anything for an empty base, would result in all the tags in the
-    " tags file.
-    if base == ''
-      return []
+  " We can't use split, because we need to skip nested [...].
+  let items = []
+  let s = 0
+  while 1
+    let e = match(base, '\.\|->\|\[', s)
+    if e < 0
+      if s == 0 || base[s - 1] != ']'
+	call add(items, strpart(base, s))
+      endif
+      break
+    endif
+    if s == 0 || base[s - 1] != ']'
+      call add(items, strpart(base, s, e - s))
     endif
-
-    " Only one part, no "." or "->": complete from tags file.
-    " When local completion is wanted CTRL-N would have been used.
-    return map(taglist('^' . base), 's:Tag2item(v:val)')
-  endif
+    if base[e] == '.'
+      let s = e + 1	" skip over '.'
+    elseif base[e] == '-'
+      let s = e + 2	" skip over '->'
+    else
+      " Skip over [...].
+      let n = 0
+      let s = e
+      let e += 1
+      while e < len(base)
+	if base[e] == ']'
+	  if n == 0
+	    break
+	  endif
+	  let n -= 1
+	elseif base[e] == '['  " nested [...]
+	  let n += 1
+	endif
+	let e += 1
+      endwhile
+      let e += 1
+      call add(items, strpart(base, s, e - s))
+      let s = e
+    endif
+  endwhile
 
   " Find the variable items[0].
   " 1. in current function (like with "gd")
@@ -68,7 +116,33 @@ function! ccomplete#Complete(findstart, 
     " TODO: join previous line if it makes sense
     let line = getline('.')
     let col = col('.')
-    let res = s:Nextitem(strpart(line, 0, col), items[1:])
+    if len(items) == 1
+      " Completing one word and it's a local variable: May add '[', '.' or
+      " '->'.
+      let match = items[0]
+      if match(line, match . '\s*\[') > 0
+	let match .= '['
+      else
+	let res = s:Nextitem(strpart(line, 0, col), [''], 0)
+	if len(res) > 0
+	  " There are members, thus add "." or "->".
+	  if match(line, '\*[ \t(]*' . match . '\>') > 0
+	    let match .= '->'
+	  else
+	    let match .= '.'
+	  endif
+	endif
+      endif
+      let res = [{'match': match, 'tagline' : ''}]
+    else
+      " Completing "var.", "var.something", etc.
+      let res = s:Nextitem(strpart(line, 0, col), items[1:], 0)
+    endif
+  endif
+
+  if len(items) == 1
+    " Only one part, no "." or "->": complete from tags file.
+    call extend(res, map(taglist('^' . base), 's:Tag2item(v:val)'))
   endif
 
   if len(res) == 0
@@ -88,7 +162,7 @@ function! ccomplete#Complete(findstart, 
 	let line = diclist[i]['cmd']
 	if line[0] == '/' && line[1] == '^'
 	  let col = match(line, '\<' . items[0] . '\>')
-	  call extend(res, s:Nextitem(strpart(line, 2, col - 2), items[1:]))
+	  call extend(res, s:Nextitem(strpart(line, 2, col - 2), items[1:], 0))
 	endif
       endif
     endfor
@@ -99,46 +173,70 @@ function! ccomplete#Complete(findstart, 
     " TODO: join previous line if it makes sense
     let line = getline('.')
     let col = col('.')
-    let res = s:Nextitem(strpart(line, 0, col), items[1:])
+    let res = s:Nextitem(strpart(line, 0, col), items[1:], 0)
   endif
 
-  " If the one and only match was what's already there and it is a composite
-  " type, add a "." or "->".
-  if len(res) == 1 && res[0]['match'] == items[-1] && len(s:SearchMembers(res, [''])) > 0
-    " If there is a '*' before the name use "->".
-    if match(res[0]['tagline'], '\*\s*' . res[0]['match'] . '\>') > 0
-      let res[0]['match'] .= '->'
-    else
-      let res[0]['match'] .= '.'
+  " If the last item(s) are [...] they need to be added to the matches.
+  let last = len(items) - 1
+  let brackets = ''
+  while last >= 0
+    if items[last][0] != '['
+      break
     endif
-  endif
+    let brackets = items[last] . brackets
+    let last -= 1
+  endwhile
 
-  return map(res, 'v:val["match"]')
+  return map(res, 's:Tagline2item(v:val, brackets)')
 endfunc
 
-"
+function! s:GetAddition(line, match, memarg, bracket)
+  " Guess if the item is an array.
+  if a:bracket && match(a:line, a:match . '\s*\[') > 0
+    return '['
+  endif
+
+  " Check if the item has members.
+  if len(s:SearchMembers(a:memarg, [''])) > 0
+    " If there is a '*' before the name use "->".
+    if match(a:line, '\*[ \t(]*' . a:match . '\>') > 0
+      return '->'
+    else
+      return '.'
+    endif
+  endif
+  return ''
+endfunction
+
 " Turn the tag info "val" into an item for completion.
 " "val" is is an item in the list returned by taglist().
+" If it is a variable we may add "." or "->".  Don't do it for other types,
+" such as a typedef, by not including the info that s:GetAddition() uses.
 function! s:Tag2item(val)
-  if has_key(a:val, "kind") && a:val["kind"] == 'v'
-    if len(s:SearchMembers([{'match': a:val["name"], 'dict': a:val}], [''])) > 0
-      " If there is a '*' before the name use "->".  This assumes the command
-      " is a search pattern!
-      if match(a:val['cmd'], '\*\s*' . a:val['name'] . '\>') > 0
-        return a:val["name"] . '->'
-      else
-        return a:val["name"] . '.'
-      endif
+  if has_key(a:val, "kind")
+    if a:val["kind"] == 'v'
+      return {'match': a:val['name'], 'tagline': "\t" . a:val['cmd'], 'dict': a:val}
+    endif
+    if a:val["kind"] == 'f'
+      return {'match': a:val['name'] . '(', 'tagline': ""}
     endif
   endif
-  return a:val["name"]
+  return {'match': a:val['name'], 'tagline': ''}
+endfunction
+
+" Turn a match item "val" into an item for completion.
+" "val['match']" is the matching item.
+" "val['tagline']" is the tagline in which the last part was found.
+function! s:Tagline2item(val, brackets)
+  return a:val['match'] . a:brackets . s:GetAddition(a:val['tagline'], a:val['match'], [a:val], a:brackets == '')
 endfunction
 
 
 " Find composing type in "lead" and match items[0] with it.
 " Repeat this recursively for items[1], if it's there.
+" When resolving typedefs "depth" is used to avoid infinite recursion.
 " Return the list of matches.
-function! s:Nextitem(lead, items)
+function! s:Nextitem(lead, items, depth)
 
   " Use the text up to the variable name and split it in tokens.
   let tokens = split(a:lead, '\s\+\|\<')
@@ -154,7 +252,7 @@ function! s:Nextitem(lead, items)
     endif
 
     " TODO: add more reserved words
-    if index(['int', 'float', 'static', 'unsigned', 'extern'], tokens[tidx]) >= 0
+    if index(['int', 'short', 'char', 'float', 'double', 'static', 'unsigned', 'extern'], tokens[tidx]) >= 0
       continue
     endif
 
@@ -191,9 +289,9 @@ function! s:Nextitem(lead, items)
 	    if name != ''
 	      call extend(res, s:StructMembers(cmdtokens[0] . ':' . name, a:items))
 	    endif
-	  else
+	  elseif a:depth < 10
 	    " Could be "typedef other_T some_T".
-	    call extend(res, s:Nextitem(cmdtokens[0], a:items))
+	    call extend(res, s:Nextitem(cmdtokens[0], a:items, a:depth + 1))
 	  endif
 	endif
       endif
@@ -207,6 +305,7 @@ function! s:Nextitem(lead, items)
 endfunction
 
 
+" Search for members of structure "typename" in tags files.
 " Return a list with resulting matches.
 " Each match is a dictionary with "match" and "tagline" entries.
 function! s:StructMembers(typename, items)
@@ -237,14 +336,21 @@ function! s:StructMembers(typename, item
   endfor
 
   if len(matches) > 0
-    " No further items, return the result.
-    if len(a:items) == 1
-      return matches
-    endif
+    " Skip over [...] items
+    let idx = 1
+    while 1
+      if idx >= len(a:items)
+	return matches		" No further items, return the result.
+      endif
+      if a:items[idx][0] != '['
+	break
+      endif
+      let idx += 1
+    endwhile
 
     " More items following.  For each of the possible members find the
     " matching following members.
-    return s:SearchMembers(matches, a:items[1:])
+    return s:SearchMembers(matches, a:items[idx :])
   endif
 
   " Failed to find anything.
@@ -257,9 +363,6 @@ function! s:SearchMembers(matches, items
   for i in range(len(a:matches))
     let typename = ''
     if has_key(a:matches[i], 'dict')
-      "if a:matches[i].dict['name'] == "gui"
-	"echomsg string(a:matches[i].dict)
-      "endif
       if has_key(a:matches[i].dict, 'typename')
 	let typename = a:matches[i].dict['typename']
       endif
@@ -273,17 +376,14 @@ function! s:SearchMembers(matches, items
       endif
     endif
     if typename != ''
-      call extend(res, s:StructMembers(name, a:items))
+      call extend(res, s:StructMembers(typename, a:items))
     else
       " Use the search command (the declaration itself).
       let s = match(line, '\t\zs/^')
       if s > 0
 	let e = match(line, '\<' . a:matches[i]['match'] . '\>', s)
 	if e > 0
-	  "if a:matches[i].dict['name'] == "gui"
-	    "echomsg strpart(line, s, e - s)
-	  "endif
-	  call extend(res, s:Nextitem(strpart(line, s, e - s), a:items))
+	  call extend(res, s:Nextitem(strpart(line, s, e - s), a:items, 0))
 	endif
       endif
     endif
--- a/runtime/doc/todo.txt
+++ b/runtime/doc/todo.txt
@@ -1,4 +1,4 @@
-*todo.txt*      For Vim version 7.0aa.  Last change: 2006 Feb 01
+*todo.txt*      For Vim version 7.0aa.  Last change: 2006 Feb 03
 
 
 		  VIM REFERENCE MANUAL	  by Bram Moolenaar
@@ -37,7 +37,15 @@ Variant of ":helpgrep" that uses a locat
     :lmake
 
 ccomplete / omnicomplete:
-- Also add . or -> when completing struct members.  use s:Tag2item()
+- Extra info for each entry to show in a tooltip kind of thing.
+    Should use a dictionary for each entry.  Fields could be:
+	word	the completed word
+	menu	menu text (use word when missing)
+	info	extra info, to be displayed in balloon (e.g., function args)
+	kind	single letter indicating the type of word:
+		    v = variable, f = function/method, c = composite (object,
+		    struct pointer).
+  For C add tag "kind" field?
 - When an option is set: In completion mode and the user types (identifier)
   characters, advance to the first match instead of removing the popup menu.
   If there is no match remove the selection. (Yegappan Lakshmanan)
@@ -49,17 +57,10 @@ ccomplete / omnicomplete:
     Need to postpone inserting anything until all matches have been found.
     Then add a completion item with the longest common string (after what was
     typed), if there is one.
-- When completing something that is a structure, add the "." or "->" right
-  away.  How to figure out if it's a pointer or not?
+- Finding out if an item has members (to add '.' or '->') requires a grep in
+  the tags files, that is very slow.  Is there another solution?  At least
+  stop at the first match.
 - When a typedef or struct is local to a file only use it in that file?
-- Extra info for each entry to show in a tooltip kind of thing.
-    Should use a dictionary for each entry.  Fields could be:
-	word	the completed word
-	menu	menu text (use word when missing)
-	info	extra info, to be displayed in balloon (e.g., function args)
-	kind	single letter indicating the type of word:
-		    v = variable, f = function/method, c = composite (object,
-		    struct pointer).
 - Special mappings for when the popup menu is visible?  Would allow for making
   a specific selection (e.g, methods vs variables).
 
@@ -113,6 +114,9 @@ 7   Add plugins for formatting.  Should 
 Edward L. Fox explains how it should be done for most Asian languages. (2005
 Nov 24)
 
+An error in a function uses a line number that doesn't take line continuation
+into account. (Mikolaj Machowski)  Store line count in an extra array?
+
 Mac unicode patch (Da Woon Jung):
 - selecting proportional font breaks display
 - UTF-8 text causes display problems.  Font replacement causes this.
@@ -166,7 +170,7 @@ Awaiting response:
 -   mblen(NULL, 0) also in Vim 6.3?
 
 
-PLANNED FOR VERSION 7.0:
+CONSIDERED FOR VERSION 7.0:
 
 -   Omni completion: Understands the programming language and finds matches
     that make sense.  Esp. members of classes/structs.
@@ -278,7 +282,7 @@ 7   Support WINDOW TABS.  Works like sev
     Then add GUI Tabs for some systems.
     Patch for GTK 1.2 passed on by Christian Michon, 2004 Jan 6.
     Simple patch for GTK by Luis M (nov 7).
-    Don't forget to provide an "X" to close a tab.
+    Don't forget to provide an "X" to close the current tab.
     Implementation: keep the list of windows as-is.  When switching to another
     tab make the buffers in the current windows hidden, save the window
     layout, buildup the other window layout and fill with buffers.
--- a/runtime/doc/version7.txt
+++ b/runtime/doc/version7.txt
@@ -1,4 +1,4 @@
-*version7.txt*  For Vim version 7.0aa.  Last change: 2006 Feb 01
+*version7.txt*  For Vim version 7.0aa.  Last change: 2006 Feb 02
 
 
 		  VIM REFERENCE MANUAL    by Bram Moolenaar
@@ -1636,4 +1636,9 @@ characters in v:this_session.
 In a multi-byte file the foldmarker could be recognized in the trail byte.
 (Taro Muraoka)
 
+Pasting with CTRL-V and menu didn't work properly when some commands are
+mapped.  Use ":normal!" instead of ":normal". (Tony Apuzzo)
+
+Crashed when expanding a file name argument in backticks.
+
  vim:tw=78:ts=8:ft=help:norl:
--- a/runtime/mswin.vim
+++ b/runtime/mswin.vim
@@ -1,7 +1,7 @@
 " Set options and add mapping such that Vim behaves a lot like MS-Windows
 "
 " Maintainer:	Bram Moolenaar <Bram@vim.org>
-" Last change:	2005 Dec 28
+" Last change:	2006 Feb 02
 
 " bail out if this isn't wanted (mrsvim.vim uses this).
 if exists("g:skip_loading_mswin") && g:skip_loading_mswin
@@ -47,18 +47,18 @@ if has("virtualedit")
   func! <SID>Paste()
     let ove = &ve
     set ve=all
-    normal `^
+    normal! `^
     if @+ != ''
-      normal "+gP
+      normal! "+gP
     endif
     let c = col(".")
-    normal i
+    normal! i
     if col(".") < c	" compensate for i<ESC> moving the cursor left
       " Avoid a beep when the text ends at the window edge.
       let vb_save = &vb
       let t_vb_save = &t_vb
       set vb t_vb=
-      normal l
+      normal! l
       let &vb = vb_save
       let &t_vb = t_vb_save
     endif