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