github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/misc/vim/ftplugin/go/import.vim (about) 1 " Copyright 2011 The Go Authors. All rights reserved. 2 " Use of this source code is governed by a BSD-style 3 " license that can be found in the LICENSE file. 4 " 5 " import.vim: Vim commands to import/drop Go packages. 6 " 7 " This filetype plugin adds three new commands for go buffers: 8 " 9 " :Import {path} 10 " 11 " Import ensures that the provided package {path} is imported 12 " in the current Go buffer, using proper style and ordering. 13 " If {path} is already being imported, an error will be 14 " displayed and the buffer will be untouched. 15 " 16 " :ImportAs {localname} {path} 17 " 18 " Same as Import, but uses a custom local name for the package. 19 " 20 " :Drop {path} 21 " 22 " Remove the import line for the provided package {path}, if 23 " present in the current Go buffer. If {path} is not being 24 " imported, an error will be displayed and the buffer will be 25 " untouched. 26 " 27 " In addition to these commands, there are also two shortcuts mapped: 28 " 29 " \f - Runs :Import fmt 30 " \F - Runs :Drop fmt 31 " 32 " The backslash is the default maplocalleader, so it is possible that 33 " your vim is set to use a different character (:help maplocalleader). 34 " 35 if exists("b:did_ftplugin_go_import") 36 finish 37 endif 38 39 command! -buffer -nargs=? -complete=customlist,go#complete#Package Drop call s:SwitchImport(0, '', <f-args>) 40 command! -buffer -nargs=1 -complete=customlist,go#complete#Package Import call s:SwitchImport(1, '', <f-args>) 41 command! -buffer -nargs=* -complete=customlist,go#complete#Package ImportAs call s:SwitchImport(1, <f-args>) 42 map <buffer> <LocalLeader>f :Import fmt<CR> 43 map <buffer> <LocalLeader>F :Drop fmt<CR> 44 45 function! s:SwitchImport(enabled, localname, path) 46 let view = winsaveview() 47 let path = a:path 48 49 " Quotes are not necessary, so remove them if provided. 50 if path[0] == '"' 51 let path = strpart(path, 1) 52 endif 53 if path[len(path)-1] == '"' 54 let path = strpart(path, 0, len(path) - 1) 55 endif 56 if path == '' 57 call s:Error('Import path not provided') 58 return 59 endif 60 61 " Extract any site prefix (e.g. github.com/). 62 " If other imports with the same prefix are grouped separately, 63 " we will add this new import with them. 64 " Only up to and including the first slash is used. 65 let siteprefix = matchstr(path, "^[^/]*/") 66 67 let qpath = '"' . path . '"' 68 if a:localname != '' 69 let qlocalpath = a:localname . ' ' . qpath 70 else 71 let qlocalpath = qpath 72 endif 73 let indentstr = 0 74 let packageline = -1 " Position of package name statement 75 let appendline = -1 " Position to introduce new import 76 let deleteline = -1 " Position of line with existing import 77 let linesdelta = 0 " Lines added/removed 78 79 " Find proper place to add/remove import. 80 let line = 0 81 while line <= line('$') 82 let linestr = getline(line) 83 84 if linestr =~# '^package\s' 85 let packageline = line 86 let appendline = line 87 88 elseif linestr =~# '^import\s\+(' 89 let appendstr = qlocalpath 90 let indentstr = 1 91 let appendline = line 92 let firstblank = -1 93 let lastprefix = "" 94 while line <= line("$") 95 let line = line + 1 96 let linestr = getline(line) 97 let m = matchlist(getline(line), '^\()\|\(\s\+\)\(\S*\s*\)"\(.\+\)"\)') 98 if empty(m) 99 if siteprefix == "" && a:enabled 100 " must be in the first group 101 break 102 endif 103 " record this position, but keep looking 104 if firstblank < 0 105 let firstblank = line 106 endif 107 continue 108 endif 109 if m[1] == ')' 110 " if there's no match, add it to the first group 111 if appendline < 0 && firstblank >= 0 112 let appendline = firstblank 113 endif 114 break 115 endif 116 let lastprefix = matchstr(m[4], "^[^/]*/") 117 if a:localname != '' && m[3] != '' 118 let qlocalpath = printf('%-' . (len(m[3])-1) . 's %s', a:localname, qpath) 119 endif 120 let appendstr = m[2] . qlocalpath 121 let indentstr = 0 122 if m[4] == path 123 let appendline = -1 124 let deleteline = line 125 break 126 elseif m[4] < path 127 " don't set candidate position if we have a site prefix, 128 " we've passed a blank line, and this doesn't share the same 129 " site prefix. 130 if siteprefix == "" || firstblank < 0 || match(m[4], "^" . siteprefix) >= 0 131 let appendline = line 132 endif 133 elseif siteprefix != "" && match(m[4], "^" . siteprefix) >= 0 134 " first entry of site group 135 let appendline = line - 1 136 break 137 endif 138 endwhile 139 break 140 141 elseif linestr =~# '^import ' 142 if appendline == packageline 143 let appendstr = 'import ' . qlocalpath 144 let appendline = line - 1 145 endif 146 let m = matchlist(linestr, '^import\(\s\+\)\(\S*\s*\)"\(.\+\)"') 147 if !empty(m) 148 if m[3] == path 149 let appendline = -1 150 let deleteline = line 151 break 152 endif 153 if m[3] < path 154 let appendline = line 155 endif 156 if a:localname != '' && m[2] != '' 157 let qlocalpath = printf("%s %" . len(m[2])-1 . "s", a:localname, qpath) 158 endif 159 let appendstr = 'import' . m[1] . qlocalpath 160 endif 161 162 elseif linestr =~# '^\(var\|const\|type\|func\)\>' 163 break 164 165 endif 166 let line = line + 1 167 endwhile 168 169 " Append or remove the package import, as requested. 170 if a:enabled 171 if deleteline != -1 172 call s:Error(qpath . ' already being imported') 173 elseif appendline == -1 174 call s:Error('No package line found') 175 else 176 if appendline == packageline 177 call append(appendline + 0, '') 178 call append(appendline + 1, 'import (') 179 call append(appendline + 2, ')') 180 let appendline += 2 181 let linesdelta += 3 182 let appendstr = qlocalpath 183 let indentstr = 1 184 endif 185 call append(appendline, appendstr) 186 execute appendline + 1 187 if indentstr 188 execute 'normal >>' 189 endif 190 let linesdelta += 1 191 endif 192 else 193 if deleteline == -1 194 call s:Error(qpath . ' not being imported') 195 else 196 execute deleteline . 'd' 197 let linesdelta -= 1 198 199 if getline(deleteline-1) =~# '^import\s\+(' && getline(deleteline) =~# '^)' 200 " Delete empty import block 201 let deleteline -= 1 202 execute deleteline . "d" 203 execute deleteline . "d" 204 let linesdelta -= 2 205 endif 206 207 if getline(deleteline) == '' && getline(deleteline - 1) == '' 208 " Delete spacing for removed line too. 209 execute deleteline . "d" 210 let linesdelta -= 1 211 endif 212 endif 213 endif 214 215 " Adjust view for any changes. 216 let view.lnum += linesdelta 217 let view.topline += linesdelta 218 if view.topline < 0 219 let view.topline = 0 220 endif 221 222 " Put buffer back where it was. 223 call winrestview(view) 224 225 endfunction 226 227 function! s:Error(s) 228 echohl Error | echo a:s | echohl None 229 endfunction 230 231 let b:did_ftplugin_go_import = 1 232 233 " vim:ts=4:sw=4:et