├── README └── plugin └── cmdline-complete.vim /README: -------------------------------------------------------------------------------- 1 | This is a mirror of http://www.vim.org/scripts/script.php?script_id=2222 2 | 3 | When editing the command-line (: / etc.), press Ctrl-P or Ctrl-N to complete the word before the cursor, using keywords in the current file. E.g: you want to search for "elephant" in the buffer, just type /ele and press Ctrl-P. So long as "elephant" is in the buffer, you will get "ele" completed into "elephant". 4 | 5 | This script is functional similar with (but far more better than) SearchComplete vimscript #474 (version 1.1). 6 | -------------------------------------------------------------------------------- /plugin/cmdline-complete.vim: -------------------------------------------------------------------------------- 1 | " Script Name: cmdline-complete.vim 2 | " Version: 1.1.3 3 | " Last Change: July 18, 2008 4 | " Author: Yuheng Xie 5 | " 6 | " Description: complete command-line (: / etc.) from the current file 7 | " 8 | " Usage: When editing the command-line, press or to complete 9 | " the word before the cursor, using keywords in the current file. 10 | " 11 | " Install: Just drop this script file into vim's plugin directory. 12 | " 13 | " If you want to use other keys instead of default to 14 | " trigger the completion, please say in your .vimrc 15 | " cmap CmdlineCompleteBackward 16 | " cmap CmdlineCompleteForward 17 | " this will use Ctrl-Y Ctrl-E for search backward and forward. 18 | " 19 | " Without python, speed will be a bit slow with large file (e.g. 20 | " > 100K). Compile your vim with python is recommended. 21 | 22 | " Anti reinclusion guards 23 | if exists('g:loaded_cmdline_complete') && !exists('g:force_reload_cmdline_complete') 24 | finish 25 | endif 26 | 27 | " Support for |line-continuation| 28 | let s:save_cpo = &cpo 29 | set cpo&vim 30 | 31 | " Default bindings 32 | 33 | if !hasmapto('CmdlineCompleteBackward', 'c') 34 | cmap CmdlineCompleteBackward 35 | endif 36 | if !hasmapto('CmdlineCompleteForward', 'c') 37 | cmap CmdlineCompleteForward 38 | endif 39 | 40 | cnoremap CmdlineCompleteBackward =CmdlineComplete(1) 41 | cnoremap CmdlineCompleteForward =CmdlineComplete(0) 42 | 43 | " Functions 44 | 45 | " define variables if they don't exist 46 | function! s:InitVariables() 47 | if !exists("s:seed") 48 | let s:seed = "" 49 | let s:completions = [""] 50 | let s:completions_set = {} 51 | let s:comp_i = 0 52 | let s:search_cursor = getpos(".") 53 | let s:sought_bw = 0 54 | let s:sought_fw = 0 55 | let s:last_cmdline = "" 56 | let s:last_pos = 0 57 | endif 58 | endfunction 59 | 60 | " generate completion list in python 61 | function! s:GenerateCompletionsPython(seed, backward) 62 | let success = 0 63 | 64 | python << EOF 65 | try: 66 | import sys, re, vim 67 | 68 | seed = vim.eval("a:seed") 69 | backward = int(vim.eval("a:backward")) 70 | 71 | def chars2range(list): 72 | range_text = "" 73 | for i in range(len(list)): 74 | if i > 0 and list[i - 1] == list[i] - 1 \ 75 | and i < len(list) - 1 and list[i + 1] == list[i] + 1: 76 | if range_text[-1] != "-": 77 | range_text += "-" 78 | else: 79 | range_text += '\\x%02X' % list[i] 80 | return "[" + range_text + "]" 81 | 82 | # simulate vim's \k 83 | k = chars2range(map(lambda x: int(x), vim.eval( \ 84 | "filter(range(256), 'nr2char(v:val) =~ \"\\\\k\"')"))) 85 | 86 | regexp = re.compile(r'(? len(buffer) - search_cursor[1] + 1: 104 | r2 = sought_fw - len(buffer) + search_cursor[1] 105 | if backward: 106 | r = [r1, r2] 107 | else: 108 | r = [r2, r1] 109 | if sought_fw < len(buffer) - search_cursor[1] + 1: 110 | r1 = len(buffer) 111 | r2 = search_cursor[1] + sought_fw 112 | if sought_bw > search_cursor[1]: 113 | r1 = len(buffer) - sought_bw + search_cursor[1] 114 | if backward: 115 | r = r + [r1, r2] 116 | else: 117 | r = [r2, r1] + r 118 | 119 | while r: 120 | candidates = regexp.findall(buffer[r[0] - 1]) 121 | if r[0] == search_cursor[1]: 122 | candidates = [] 123 | m = regexp.search(buffer[r[0] - 1]) 124 | while m: 125 | if backward and (not sought_bw and m.start() < search_cursor[2] \ 126 | or sought_bw and m.start() >= search_cursor[2]) \ 127 | or not backward and (sought_fw and m.end() < search_cursor[2] \ 128 | or not sought_fw and m.end() >= search_cursor[2]): 129 | candidates.append(m.group()) 130 | m = regexp.search(buffer[r[0] - 1], m.end()) 131 | 132 | found = False 133 | 134 | if candidates: 135 | if backward: 136 | for candidate in reversed(candidates): 137 | if candidate not in completions_set: 138 | completions_set[candidate] = 1 139 | vim.command("let s:completions_set['" + candidate + "'] = 1") 140 | vim.command("call insert(s:completions, '" + candidate + "')") 141 | vim.command("let s:comp_i = s:comp_i + 1") 142 | found = True 143 | else: 144 | for candidate in candidates: 145 | if candidate not in completions_set: 146 | completions_set[candidate] = 1 147 | vim.command("let s:completions_set['" + candidate + "'] = 1") 148 | vim.command("call add(s:completions, '" + candidate + "')") 149 | found = True 150 | 151 | if backward: 152 | vim.command("let s:sought_bw += 1") 153 | else: 154 | vim.command("let s:sought_fw += 1") 155 | 156 | if found: break 157 | 158 | if r[1] > r[0]: r[0] += 1 159 | elif r[1] < r[0]: r[0] -= 1 160 | else: del r[:2] 161 | 162 | vim.command("let success = 1") 163 | 164 | except ImportError: pass 165 | EOF 166 | 167 | return success 168 | endfunction 169 | 170 | " generate completion list 171 | function! s:GenerateCompletions(seed, backward) 172 | let regexp = '\<' . a:seed . '\k\+' 173 | if empty(a:seed) 174 | let regexp = '\<\k\k\+' 175 | elseif a:seed =~ '\K' 176 | let regexp = '\<\(\V' . a:seed . '\)\k\+' 177 | endif 178 | if &ignorecase && !(&smartcase && a:seed =~ '\C[A-Z]') 179 | let regexp = '\c' . regexp 180 | endif 181 | 182 | " backup 'ignorecase', do searching with 'noignorecase' 183 | let save_ignorecase = &ignorecase 184 | set noignorecase 185 | 186 | let r = [] 187 | if s:sought_bw < s:search_cursor[1] 188 | let r1 = s:search_cursor[1] - s:sought_bw 189 | let r2 = 1 190 | if s:sought_fw > line("$") - s:search_cursor[1] + 1 191 | let r2 = s:sought_fw - line("$") + s:search_cursor[1] 192 | endif 193 | if a:backward 194 | let r = [r1, r2] 195 | else 196 | let r = [r2, r1] 197 | endif 198 | endif 199 | if s:sought_fw < line("$") - s:search_cursor[1] + 1 200 | let r1 = line("$") 201 | let r2 = s:search_cursor[1] + s:sought_fw 202 | if s:sought_bw > s:search_cursor[1] 203 | let r1 = line("$") - s:sought_bw + s:search_cursor[1] 204 | endif 205 | if a:backward 206 | let r = r + [r1, r2] 207 | else 208 | let r = [r2, r1] + r 209 | endif 210 | endif 211 | 212 | while len(r) 213 | let candidates = [] 214 | 215 | let line = getline(r[0]) 216 | let start = match(line, regexp) 217 | while start != -1 218 | let candidate = matchstr(line, '\k\+', start) 219 | let next = start + len(candidate) 220 | if r[0] != s:search_cursor[1] 221 | \ || a:backward && (!s:sought_bw && start < s:search_cursor[2] 222 | \ || s:sought_bw && start >= s:search_cursor[2]) 223 | \ || !a:backward && (s:sought_fw && next < s:search_cursor[2] 224 | \ || !s:sought_fw && next >= s:search_cursor[2]) 225 | call add(candidates, candidate) 226 | endif 227 | let start = match(line, regexp, next) 228 | endwhile 229 | 230 | let found = 0 231 | 232 | if !empty(candidates) 233 | if a:backward 234 | let i = len(candidates) - 1 235 | while i >= 0 236 | if !has_key(s:completions_set, candidates[i]) 237 | let s:completions_set[candidates[i]] = 1 238 | call insert(s:completions, candidates[i]) 239 | let s:comp_i = s:comp_i + 1 240 | let found = 1 241 | endif 242 | let i = i - 1 243 | endwhile 244 | else 245 | let i = 0 246 | while i < len(candidates) 247 | if !has_key(s:completions_set, candidates[i]) 248 | let s:completions_set[candidates[i]] = 1 249 | call add(s:completions, candidates[i]) 250 | let found = 1 251 | endif 252 | let i = i + 1 253 | endwhile 254 | endif 255 | endif 256 | 257 | if a:backward 258 | let s:sought_bw += 1 259 | else 260 | let s:sought_fw += 1 261 | endif 262 | 263 | if found 264 | break 265 | endif 266 | 267 | if r[1] > r[0] 268 | let r[0] += 1 269 | elseif r[1] < r[0] 270 | let r[0] -= 1 271 | else 272 | call remove(r, 0, 1) 273 | endif 274 | endwhile 275 | 276 | " restore 'ignorecase' 277 | let &ignorecase = save_ignorecase 278 | 279 | return 1 280 | endfunction 281 | 282 | " return next completion, to be used in c_CTRL-R = 283 | function! s:CmdlineComplete(backward) 284 | " define variables if they don't exist 285 | call s:InitVariables() 286 | 287 | let cmdline = getcmdline() 288 | let pos = getcmdpos() 289 | 290 | " if cmdline, cmdpos or cursor changed since last call, 291 | " re-generate the completion list 292 | if cmdline != s:last_cmdline || pos != s:last_pos 293 | let s:last_cmdline = cmdline 294 | let s:last_pos = pos 295 | 296 | let s = match(strpart(cmdline, 0, pos - 1), '\k*$') 297 | let s:seed = strpart(cmdline, s, pos - 1 - s) 298 | let s:completions = [s:seed] 299 | let s:completions_set = {} 300 | let s:comp_i = 0 301 | let s:search_cursor = getpos(".") 302 | let s:sought_bw = 0 303 | let s:sought_fw = 0 304 | endif 305 | 306 | if s:sought_bw + s:sought_fw <= line("$") && ( 307 | \ a:backward && s:comp_i == 0 || 308 | \ !a:backward && s:comp_i == len(s:completions) - 1) 309 | let success = 0 310 | if has('python') 311 | let success = s:GenerateCompletionsPython(s:seed, a:backward) 312 | endif 313 | if !success 314 | let success = s:GenerateCompletions(s:seed, a:backward) 315 | endif 316 | endif 317 | 318 | let old = s:completions[s:comp_i] 319 | 320 | if a:backward 321 | if s:comp_i == 0 322 | let s:comp_i = len(s:completions) - 1 323 | else 324 | let s:comp_i = s:comp_i - 1 325 | endif 326 | else 327 | if s:comp_i == len(s:completions) - 1 328 | let s:comp_i = 0 329 | else 330 | let s:comp_i = s:comp_i + 1 331 | endif 332 | endif 333 | 334 | let new = s:completions[s:comp_i] 335 | 336 | " remember the last cmdline, cmdpos and cursor for next call 337 | let s:last_cmdline = strpart(s:last_cmdline, 0, s:last_pos - 1 - strlen(old)) 338 | \ . new . strpart(s:last_cmdline, s:last_pos - 1) 339 | let s:last_pos = s:last_pos - len(old) + len(new) 340 | 341 | " feed some keys to overcome map- 342 | call feedkeys(" \") 343 | 344 | return substitute(old, ".", "\", "g") . new 345 | endfunction 346 | --------------------------------------------------------------------------------