commit fb0b4c0725e3ca220a210081b16d3d335bc94285
parent 512a4f0ee2e8e8818c23abcf5fb7d2e89648f860
Author: edvb54 <edvb54@gmail.com>
Date: Mon, 26 May 2014 10:29:20 -0700
Remove JavaRun and add Eclim
Diffstat:
325 files changed, 51636 insertions(+), 7 deletions(-)
diff --git a/bash_profile b/bash_profile
@@ -28,7 +28,6 @@ ${Cyan}❯${Color_Off}❯ "
PS2=' ${ICyan}❯${Color_Off} '
# basic{{{1
-set -o vi
bind -m vi-insert '"jj": vi-movement-mode'
export EDITOR='vim'
diff --git a/vim/bundle/JavaRun b/vim/bundle/JavaRun
@@ -1 +0,0 @@
-Subproject commit 1d2bd59638fff78c28c79d4bcf64dc3724a6c329
diff --git a/vim/bundle/vundle b/vim/bundle/vundle
@@ -1 +0,0 @@
-Subproject commit 8db3bcb5921103f0eb6de361c8b25cc03cb350b5
diff --git a/vim/eclim/autoload/eclim.vim b/vim/eclim/autoload/eclim.vim
@@ -0,0 +1,339 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Plugin that integrates vim with the eclipse plugin eclim (ECLipse
+" IMproved).
+"
+" This plugin contains shared functions that can be used regardless of the
+" current file type being edited.
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+ if !exists("g:EclimShowErrors")
+ let g:EclimShowErrors = 1
+ endif
+" }}}
+
+" Script Variables {{{
+ let s:command_ping = '-command ping'
+ let s:command_settings = '-command settings'
+ let s:command_settings_update = '-command settings_update -s "<settings>"'
+ let s:command_shutdown = "-command shutdown"
+ let s:connect= '^connect: .*$'
+" }}}
+
+function! eclim#Execute(command, ...) " {{{
+ " Optional args:
+ " options {
+ " One of the following to determine the eclimd instance to use, honored in
+ " the order shown here:
+ " instance: dictionary representing an eclimd instance.
+ " project: project name
+ " workspace: workspace path
+ " dir: directory path to use as the current dir
+ " exec: 1 to execute the command using execute instead of system.
+ " raw: 1 to get the result without evaluating as json
+ " }
+
+ if exists('g:EclimDisabled')
+ return
+ endif
+
+ if !eclim#EclimAvailable()
+ return
+ endif
+
+ let command = '-editor vim ' . a:command
+
+ " encode special characters
+ " http://www.w3schools.com/TAGS/ref_urlencode.asp
+ let command = substitute(command, '\*', '%2A', 'g')
+ let command = substitute(command, '\$', '%24', 'g')
+ let command = substitute(command, '<', '%3C', 'g')
+ let command = substitute(command, '>', '%3E', 'g')
+
+ " determine the eclimd instance to use
+ let options = a:0 ? a:1 : {}
+ let instance = get(options, 'instance', {})
+ if len(instance) == 0
+ let workspace = ''
+
+ let project = get(options, 'project', '')
+ if project != ''
+ let workspace = eclim#project#util#GetProjectWorkspace(project)
+ endif
+ if workspace == ''
+ let workspace = get(options, 'workspace', '')
+ endif
+
+ let dir = workspace != '' ? workspace : get(options, 'dir', '')
+ let chosen = eclim#client#nailgun#ChooseEclimdInstance(dir)
+ if type(chosen) != g:DICT_TYPE
+ return
+ endif
+ let instance = chosen
+ endif
+
+ let exec = get(options, 'exec', 0)
+ let [retcode, result] = eclim#client#nailgun#Execute(instance, command, exec)
+ let result = substitute(result, '\n$', '', '')
+
+ " not sure this is the best place to handle this, but when using the python
+ " client, the result has a trailing ctrl-m on windows. also account for
+ " running under cygwin vim.
+ if has('win32') || has('win64') || has('win32unix')
+ let result = substitute(result, "\<c-m>$", '', '')
+ endif
+
+ " an echo during startup causes an annoying issue with vim.
+ "call eclim#util#Echo(' ')
+
+ " check for errors
+ let error = ''
+ if result =~ '^[^\n]*Exception:\?[^\n]*\n\s\+\<at\> ' ||
+ \ result =~ '^[^\n]*ResourceException(.\{-})\[[0-9]\+\]:[^\n]*\n\s\+\<at\> '
+ if g:EclimLogLevel < 10
+ let error = substitute(result, '\(.\{-}\)\n.*', '\1', '')
+ else
+ let error = result
+ endif
+ elseif retcode
+ let error = result
+ endif
+
+ if retcode || error != ''
+ if g:EclimShowErrors
+ if error =~ s:connect
+ " if we are not in an autocmd or the autocmd is for an acwrite buffer,
+ " alert the user that eclimd is not running.
+ if expand('<abuf>') == '' || &buftype == 'acwrite'
+ call eclim#util#EchoWarning(
+ \ "unable to connect to eclimd (port: " . instance.port . ") - " . error)
+ endif
+ else
+ let error = error . "\n" .
+ \ 'while executing command (port: ' . instance.port . '): ' . command
+ " if we are not in an autocmd or in a autocmd for an acwrite buffer,
+ " echo the error, otherwise just log it.
+ if expand('<abuf>') == '' || &buftype == 'acwrite'
+ call eclim#util#EchoError(error)
+ else
+ call eclim#util#EchoDebug(error)
+ endif
+ endif
+ endif
+ return
+ endif
+
+ let raw = get(options, 'raw', 0)
+ return result != '' && !raw ? eval(result) : result
+endfunction " }}}
+
+function! eclim#Disable() " {{{
+ if !exists('g:EclimDisabled')
+ let g:EclimDisabled = 1
+ endif
+endfunction " }}}
+
+function! eclim#Enable() " {{{
+ if exists('g:EclimDisabled')
+ unlet g:EclimDisabled
+ endif
+endfunction " }}}
+
+function! eclim#EclimAvailable(...) " {{{
+ " Optional args:
+ " echo: Whether or not to echo an error if eclim is not available
+ " (default: 1)
+ let instances = eclim#UserHome() . '/.eclim/.eclimd_instances'
+ let available = filereadable(instances)
+ let echo = a:0 ? a:1 : 1
+ if echo && !available && expand('<abuf>') == ''
+ call eclim#util#EchoError(printf(
+ \ 'No eclimd instances found running (eclimd created file not found %s)',
+ \ eclim#UserHome() . '/.eclim/.eclimd_instances'))
+ endif
+ return available
+endfunction " }}}
+
+function! eclim#PingEclim(echo, ...) " {{{
+ " If echo is non 0, then the result is echoed to the user.
+ " Optional args:
+ " workspace
+
+ let workspace = a:0 ? a:1 : ''
+ if a:echo
+ let result = eclim#Execute(s:command_ping, {'workspace': workspace})
+ if type(result) == g:DICT_TYPE
+ call eclim#util#Echo(
+ \ 'eclim ' . result.eclim . "\n" .
+ \ 'eclipse ' . result.eclipse)
+ endif
+ else
+ let savedErr = g:EclimShowErrors
+ let savedLog = g:EclimLogLevel
+ let g:EclimShowErrors = 0
+ let g:EclimLogLevel = 0
+
+ let result = eclim#Execute(s:command_ping, {'workspace': workspace})
+
+ let g:EclimShowErrors = savedErr
+ let g:EclimLogLevel = savedLog
+
+ return type(result) == g:DICT_TYPE
+ endif
+endfunction " }}}
+
+function! eclim#ParseSettingErrors(errors) " {{{
+ let errors = []
+ for error in a:errors
+ let message = error.message
+ let setting = substitute(message, '^\(.\{-}\): .*', '\1', '')
+ let message = substitute(message, '^.\{-}: \(.*\)', '\1', '')
+ if error.line == 1 && setting != error.message
+ let line = search('^\s*' . setting . '\s*=', 'cnw')
+ let error.line = line > 0 ? line : 1
+ endif
+ call add(errors, {
+ \ 'bufnr': bufnr('%'),
+ \ 'lnum': error.line,
+ \ 'text': message,
+ \ 'type': error.warning == 1 ? 'w' : 'e',
+ \ })
+ endfor
+ return errors
+endfunction " }}}
+
+function! eclim#SaveSettings(command, project) " {{{
+ " don't check modified since undo seems to not set the modified flag
+ "if &modified
+ let tempfile = substitute(tempname(), '\', '/', 'g')
+
+ " get all lines, filtering out comments and blank lines
+ let lines = filter(getline(1, line('$')), 'v:val !~ "^\\s*\\(#\\|$\\)"')
+
+ " convert lines into a settings dict
+ let index = 0
+ let settings = {}
+ let pattern = '^\s*\([[:alnum:]_.-]\+\)\s*=\s*\(.*\)'
+ while index < len(lines)
+ if lines[index] =~ pattern
+ let name = substitute(lines[index], pattern, '\1', '')
+ let value = substitute(lines[index], pattern, '\2', '')
+ while value =~ '\\$'
+ let index += 1
+ let value = substitute(value, '\\$', '', '')
+ let value .= substitute(lines[index], '^\s*', '', '')
+ endwhile
+ let settings[name] = value
+ endif
+ let index += 1
+ endwhile
+ call writefile([string(settings)], tempfile)
+
+ if has('win32unix')
+ let tempfile = eclim#cygwin#WindowsPath(tempfile)
+ endif
+
+ let command = a:command
+ let command = substitute(command, '<project>', a:project, '')
+ let command = substitute(command, '<settings>', tempfile, '')
+
+ if exists('b:eclimd_instance')
+ let result = eclim#Execute(command, {'instance': b:eclimd_instance})
+ else
+ let result = eclim#Execute(command)
+ endif
+
+ if type(result) == g:LIST_TYPE
+ call eclim#util#EchoError
+ \ ("Operation contained errors. See location list for details.")
+ let errors = eclim#ParseSettingErrors(result)
+ call eclim#util#SetLocationList(errors)
+ else
+ call eclim#util#ClearLocationList()
+ call eclim#util#Echo(result)
+ endif
+
+ setlocal nomodified
+ "endif
+endfunction " }}}
+
+function! eclim#Settings(workspace) " {{{
+ let instance = eclim#client#nailgun#ChooseEclimdInstance(a:workspace)
+ if type(instance) != g:DICT_TYPE
+ return
+ endif
+
+ let settings = eclim#Execute(s:command_settings, {'instance': instance})
+ if type(settings) != g:LIST_TYPE
+ return
+ endif
+
+ let content = ['# Global settings for workspace: ' . instance.workspace, '']
+ let path = ''
+ for setting in settings
+ if setting.path != path
+ if path != ''
+ let content += ['# }', '']
+ endif
+ let path = setting.path
+ call add(content, '# ' . path . ' {')
+ endif
+ let description = split(setting.description, '\n')
+ let content += map(description, "'\t# ' . v:val")
+ call add(content, "\t" . setting.name . '=' . setting.value)
+ endfor
+ if path != ''
+ call add(content, '# }')
+ endif
+
+ call eclim#util#TempWindow("Eclim_Global_Settings", content)
+ setlocal buftype=acwrite
+ setlocal filetype=jproperties
+ setlocal noreadonly
+ setlocal modifiable
+ setlocal foldmethod=marker
+ setlocal foldmarker={,}
+ let b:eclimd_instance = instance
+
+ augroup eclim_settings
+ autocmd! BufWriteCmd <buffer>
+ exec 'autocmd BufWriteCmd <buffer> ' .
+ \ 'call eclim#SaveSettings(s:command_settings_update, "")'
+ augroup END
+endfunction " }}}
+
+function! eclim#ShutdownEclim() " {{{
+ call eclim#Execute(s:command_shutdown)
+endfunction " }}}
+
+function! eclim#UserHome() " {{{
+ let home = expand('$HOME')
+ if has('win32unix')
+ let home = eclim#cygwin#WindowsHome()
+ elseif has('win32') || has('win64')
+ let home = expand('$USERPROFILE')
+ endif
+ return substitute(home, '\', '/', 'g')
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/android.vim b/vim/eclim/autoload/eclim/android.vim
@@ -0,0 +1,39 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2012 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+let s:command_reload = '-command android_reload'
+" }}}
+
+function! eclim#android#Reload() " {{{
+ let result = eclim#Execute(s:command_reload)
+ if type(result) != g:DICT_TYPE
+ return
+ endif
+
+ if has_key(result, 'error')
+ call eclim#util#EchoError(result.error)
+ else
+ call eclim#util#Echo(result.message)
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/android/project.vim b/vim/eclim/autoload/eclim/android/project.vim
@@ -0,0 +1,170 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2012 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+let s:command_list_targets = '-command android_list_targets'
+" }}}
+
+function! eclim#android#project#ProjectCreatePre(folder) " {{{
+ return s:InitAndroid(a:folder)
+endfunction " }}}
+
+function! eclim#android#project#ProjectNatureAddPre(project) " {{{
+ return s:InitAndroid(eclim#project#util#GetProjectRoot(a:project))
+endfunction " }}}
+
+function! eclim#android#project#GetTargets(folder) " {{{
+ let results = eclim#Execute(s:command_list_targets, {'dir': a:folder})
+ if type(results) != g:LIST_TYPE
+ if type(results) == g:STRING_TYPE
+ call eclim#util#EchoError(results)
+ endif
+ return
+ endif
+ return results
+endfunction " }}}
+
+function! s:InitAndroid(folder) " {{{
+ let args = ''
+
+ let targets = eclim#android#project#GetTargets(a:folder)
+ if type(targets) != g:LIST_TYPE
+ return
+ endif
+
+ if len(targets) == 0
+ let message = "No android platform targets found."
+ let sdk = eclim#util#GetSetting('com.android.ide.eclipse.adt.sdk')
+ if type(sdk) == g:STRING_TYPE && sdk != ''
+ let sdk = substitute(sdk, '\\', '/', 'g')
+ if sdk !~ '[/\\]$'
+ let sdk .= '/'
+ endif
+ let managers = [
+ \ sdk . 'SDK Manager.exe',
+ \ sdk . 'tools/android',
+ \ ]
+ let manager = ''
+ for path in managers
+ if filereadable(path)
+ let manager = path
+ break
+ endif
+ endfor
+
+ if manager != ''
+ let message .=
+ \ "\nYou can use the SDK Manager to install target packages:" .
+ \ "\n " . manager .
+ \ "\nThen you can reload the android sdk by running the vim command:" .
+ \ "\n :AndroidReload"
+ endif
+ endif
+ call eclim#util#EchoError(message)
+ return 0
+ endif
+
+ if len(targets) == 1
+ let target = targets[0].hash
+ else
+ let answer = eclim#util#PromptList(
+ \ "Please choose the target android platform for this project",
+ \ map(copy(targets), 'v:val.name'))
+ if answer == -1
+ return 0
+ endif
+
+ let target = targets[answer].hash
+ redraw
+ endif
+ let args = '--target ' . target
+
+ let manifest = a:folder . '/AndroidManifest.xml'
+ if !filereadable(manifest)
+ " choose a package name
+ let package = eclim#util#Prompt(
+ \ "Please specify a package name",
+ \ function('eclim#android#project#ValidatePackage'))
+ if package == ''
+ call eclim#util#EchoWarning('Project create canceled.')
+ return 0
+ endif
+ let args .= ' --package ' . package
+
+ " choose an app name
+ let name = eclim#util#Prompt("Please specify a name for this application")
+ if name == ''
+ call eclim#util#EchoWarning('Project create canceled.')
+ return 0
+ endif
+ let args .= ' --application "' . escape(name, '"') . '"'
+
+ " is this a library?
+ let library = eclim#util#PromptConfirm('Is this a library project?')
+ if library == -1
+ call eclim#util#EchoWarning('Project create canceled.')
+ return 0
+ endif
+ if library
+ let args .= ' --library'
+ else
+ " create an activity?
+ let create = eclim#util#PromptConfirm('Create an activity?')
+ if create == -1
+ call eclim#util#EchoWarning('Project create canceled.')
+ return 0
+ endif
+ if create
+ " choose an app name
+ redraw
+ let default = substitute(name, '\W', '', 'g') . 'Activity'
+ let activity = eclim#util#Prompt(
+ \ ["Please specify an activity name", default],
+ \ function('eclim#android#project#ValidateActivity'))
+ if activity == ''
+ call eclim#util#EchoWarning('Project create canceled.')
+ return 0
+ endif
+ let args .= ' --activity ' . activity
+ endif
+ endif
+ endif
+
+ return args
+endfunction " }}}
+
+function! eclim#android#project#ValidateActivity(activity) " {{{
+ if a:activity !~? '^[a-z]\w*$'
+ return "Activity name must be a valid java identifier."
+ endif
+ return 1
+endfunction " }}}
+
+function! eclim#android#project#ValidatePackage(package) " {{{
+ if a:package !~? '^[a-z][a-z0-9_]*\(.[a-z][a-z0-9_]*\)*$'
+ return "Must be a valid package name with no trailing dots."
+ endif
+ return 1
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/c/complete.vim b/vim/eclim/autoload/eclim/c/complete.vim
@@ -0,0 +1,49 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/c/complete.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Varables {{{
+ if !exists("g:EclimCCompleteLayout")
+ if &completeopt !~ 'preview' && &completeopt =~ 'menu'
+ let g:EclimCCompleteLayout = 'standard'
+ else
+ let g:EclimCCompleteLayout = 'compact'
+ endif
+ endif
+" }}}
+
+" Script Varables {{{
+ let s:complete_command =
+ \ '-command c_complete -p "<project>" -f "<file>" ' .
+ \ '-o <offset> -e <encoding> -l <layout>'
+" }}}
+
+" CodeComplete(findstart, base) {{{
+" Handles code completion.
+function! eclim#c#complete#CodeComplete(findstart, base)
+ return eclim#lang#CodeComplete(
+ \ s:complete_command, a:findstart, a:base,
+ \ {'temp': 0, 'layout': g:EclimCCompleteLayout})
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/c/project.vim b/vim/eclim/autoload/eclim/c/project.vim
@@ -0,0 +1,331 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/c/project.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Varables {{{
+ let s:configs_command = '-command c_project_configs -p "<project>"'
+ let s:src_command =
+ \ '-command c_project_src -p "<project>" -a <action> -d "<dir>"'
+ let s:include_command =
+ \ '-command c_project_include -p "<project>" -a <action> -l <lang> -d "<dir>"'
+ let s:symbol_command =
+ \ '-command c_project_symbol -p "<project>" -a <action> -l <lang> -n "<name>"'
+" }}}
+
+" Configs([project]) {{{
+" Open a buffer with current project configs info.
+function! eclim#c#project#Configs(...)
+ if len(a:000) > 0 && a:000[0] != ''
+ let project = a:000[0]
+ else
+ let project = eclim#project#util#GetCurrentProjectName()
+ endif
+
+ if project == ''
+ " force printing of project error message
+ call eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let command = s:configs_command
+ let command = substitute(command, '<project>', project, '')
+
+ let configs = eclim#Execute(command, {'project': project})
+ if type(configs) != g:LIST_TYPE
+ return
+ endif
+
+ let content = []
+ for config in configs
+ call add(content, 'Config: ' . config.name)
+ call add(content, '')
+
+ call add(content, "\tSources: |add|")
+ if has_key(config, 'sources')
+ for src in config.sources
+ call add(content, "\t\tdir: " . src.dir)
+ if has_key(src, 'excludes')
+ call add(content, "\t\t\texcludes: " . join(src.excludes, ','))
+ endif
+ endfor
+ endif
+ call add(content, '')
+
+ if has_key(config, 'tools')
+ for tool in config.tools
+ call add(content, "\tTool: " . tool.name)
+ call add(content, "\t\tIncludes: |add|")
+ if has_key(tool, 'includes')
+ for include in tool.includes
+ call add(content, "\t\t\tpath: " . include)
+ endfor
+ endif
+ call add(content, "\t\tSymbols: |add|")
+ if has_key(tool, 'symbols')
+ for symbol in tool.symbols
+ call add(content, "\t\t\tname/value: " . symbol)
+ endfor
+ endif
+ call add(content, '')
+ endfor
+ endif
+ endfor
+
+ call eclim#util#TempWindow('[' . project . ' configs]', content)
+ let b:project = project
+ call s:Syntax()
+
+ nnoremap <silent> <buffer> <cr> :call <SID>FollowLink()<cr>
+ nnoremap <silent> <buffer> D :call <SID>Delete()<cr>
+endfunction " }}}
+
+" s:Syntax() {{{
+function! s:Syntax()
+ syntax match CProjectConfigLabel /^\s*[A-Z]\w\+:/
+ syntax match CProjectConfigSubLabel /^\s*[a-z][a-z\/]\+:/
+ syntax match CProjectConfigLink /|\S.\{-}\S|/
+ hi link CProjectConfigLabel Statement
+ hi link CProjectConfigSubLabel Identifier
+ hi link CProjectConfigLink Label
+endfunction " }}}
+
+" s:FollowLink() {{{
+function! s:FollowLink()
+ let line = getline('.')
+ let link = substitute(
+ \ getline('.'), '.*|\(.\{-}\%' . col('.') . 'c.\{-}\)|.*', '\1', '')
+ if link == line
+ return
+ endif
+
+ if line =~ '^\s*Sources:'
+ call s:AddSource()
+ elseif line =~ '^\s*Includes:'
+ call s:AddInclude()
+ elseif line =~ '^\s*Symbols:'
+ call s:AddSymbol()
+ endif
+endfunction " }}}
+
+" s:AddSource() {{{
+function! s:AddSource()
+ let project_root = eclim#project#util#GetProjectRoot(b:project)
+ let complete = 'customlist,eclim#project#util#CommandCompleteProjectRelative'
+ let dir = input('dir: ', '', complete)
+ while dir != '' && !isdirectory(project_root . '/' . dir)
+ call eclim#util#Echo('Directory "' . dir . '" not found in the project.')
+ let dir = input('dir: ', dir, complete)
+ endwhile
+
+ if dir == ''
+ return
+ endif
+
+ let excludes = input('excludes (comma separated patterns): ')
+
+ let command = s:src_command
+ let command = substitute(command, '<project>', b:project, '')
+ let command = substitute(command, '<action>', 'add', '')
+ let command = substitute(command, '<dir>', dir, '')
+ if excludes != ''
+ let command .= ' -e "' . excludes . '"'
+ endif
+
+ let result = eclim#Execute(command)
+ if result != '0'
+ call eclim#c#project#Configs(b:project)
+ call eclim#util#Echo(result)
+ endif
+endfunction " }}}
+
+" s:AddInclude() {{{
+function! s:AddInclude()
+ let project_root = eclim#project#util#GetProjectRoot(b:project)
+ let complete = 'customlist,eclim#project#util#CommandCompleteAbsoluteOrProjectRelativeDir'
+ let dir = input('dir: ', '', complete)
+
+ if dir == ''
+ return
+ endif
+
+ if has('win32unix') && dir =~ '^/'
+ let dir = eclim#cygwin#WindowsPath(dir)
+ endif
+
+ let command = s:include_command
+ let command = substitute(command, '<project>', b:project, '')
+ let command = substitute(command, '<action>', 'add', '')
+ let command = substitute(command, '<lang>', s:GetLang(), '')
+ let command = substitute(command, '<dir>', dir, '')
+
+ let result = eclim#Execute(command)
+ if result != '0'
+ call eclim#c#project#Configs(b:project)
+ call eclim#util#Echo(result)
+ endif
+endfunction " }}}
+
+" s:AddSymbol() {{{
+function! s:AddSymbol()
+ let project_root = eclim#project#util#GetProjectRoot(b:project)
+ let name = input('name: ', '')
+ if name == ''
+ return
+ endif
+
+ let value = input('value: ')
+ if value == ''
+ return
+ endif
+
+ let command = s:symbol_command
+ let command = substitute(command, '<project>', b:project, '')
+ let command = substitute(command, '<action>', 'add', '')
+ let command = substitute(command, '<lang>', s:GetLang(), '')
+ let command = substitute(command, '<name>', name, '')
+ let command .= ' -v "' . value . '"'
+
+ let result = eclim#Execute(command)
+ if result != '0'
+ call eclim#c#project#Configs(b:project)
+ call eclim#util#Echo(result)
+ endif
+endfunction " }}}
+
+" s:Delete() {{{
+function! s:Delete()
+ let reload = 0
+ let message = ''
+ let pos = getpos('.')
+ let lnum = line('.')
+ let line = getline(lnum)
+
+ " source entry excludes
+ if line =~ '^\s*excludes:\s\+'
+ let lnum -= 1
+ let line = getline(lnum)
+ endif
+
+ " source entry dir
+ if line =~ '^\s*dir:\s\+'
+ let reload = 1
+ let message = s:DeleteSource(lnum)
+
+ " include path entry
+ elseif line =~ '^\s*path:\s\+'
+ let reload = 1
+ let message = s:DeleteInclude(lnum)
+
+ " symbol entry
+ elseif line =~ '^\s*name/value:\s\+'
+ let reload = 1
+ let message = s:DeleteSymbol(lnum)
+ endif
+
+ if reload
+ call eclim#c#project#Configs(b:project)
+ call setpos('.', pos)
+ if message != ''
+ call eclim#util#Echo(message)
+ endif
+ endif
+endfunction " }}}
+
+" s:DeleteSource(lnum) {{{
+function! s:DeleteSource(lnum)
+ let dir = substitute(getline(a:lnum), '^\s*dir:\s\+\(.*\)', '\1', '')
+ let command = s:src_command
+ let command = substitute(command, '<project>', b:project, '')
+ let command = substitute(command, '<action>', 'delete', '')
+ let command = substitute(command, '<dir>', dir, '')
+
+ let result = eclim#Execute(command)
+ if result != '0'
+ return result
+ endif
+ return ''
+endfunction " }}}
+
+" s:DeleteInclude(lnum) {{{
+function! s:DeleteInclude(lnum)
+ let dir = substitute(getline(a:lnum), '^\s*path:\s\+\(.*\)', '\1', '')
+ let dir = substitute(dir, '\(^"\|"$\)', '', 'g')
+ let dir = substitute(dir, '^\$', '', '')
+ let dir = substitute(dir, '\(^{\|}$\)', '', 'g')
+ let dir = substitute(dir, '^workspace_loc:', '', '')
+
+ let command = s:include_command
+ let command = substitute(command, '<project>', b:project, '')
+ let command = substitute(command, '<action>', 'delete', '')
+ let command = substitute(command, '<lang>', s:GetLang(), '')
+ let command = substitute(command, '<dir>', dir, '')
+
+ let result = eclim#Execute(command)
+ if result != '0'
+ return result
+ endif
+ return ''
+endfunction " }}}
+
+" s:DeleteSymbol(lnum) {{{
+function! s:DeleteSymbol(lnum)
+ let name = substitute(
+ \ getline(a:lnum), '^\s*name/value:\s\+\(.\{-}\)=.*', '\1', '')
+
+ let command = s:symbol_command
+ let command = substitute(command, '<project>', b:project, '')
+ let command = substitute(command, '<action>', 'delete', '')
+ let command = substitute(command, '<lang>', s:GetLang(), '')
+ let command = substitute(command, '<name>', name, '')
+
+ let result = eclim#Execute(command)
+ if result != '0'
+ return result
+ endif
+ return ''
+endfunction " }}}
+
+" s:GetLang() {{{
+function! s:GetLang()
+ let lang_line = getline(search('^\s\+Tool:', 'bnW'))
+ if lang_line =~? 'assembl'
+ return 'assembly'
+ elseif lang_line =~? 'c++\|cpp'
+ return "c++"
+ endif
+ return 'c'
+endfunction " }}}
+
+" CommandCompleteProject(argLead, cmdLine, cursorPos) {{{
+" Custom command completion for project names.
+function! eclim#c#project#CommandCompleteProject(argLead, cmdLine, cursorPos)
+ let c_projects = eclim#project#util#CommandCompleteProjectByNature(
+ \ a:argLead, a:cmdLine, a:cursorPos, 'c')
+ let cpp_projects = eclim#project#util#CommandCompleteProjectByNature(
+ \ a:argLead, a:cmdLine, a:cursorPos, 'cpp')
+ let projects = c_projects + cpp_projects
+ call sort(projects)
+ return projects
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/c/search.vim b/vim/eclim/autoload/eclim/c/search.vim
@@ -0,0 +1,162 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/c/search.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Varables {{{
+ if !exists("g:EclimCSearchSingleResult")
+ " possible values ('split', 'edit', 'lopen')
+ let g:EclimCSearchSingleResult = g:EclimDefaultFileOpenAction
+ endif
+" }}}
+
+" Script Varables {{{
+ let s:search = '-command c_search'
+ let s:includepaths = '-command c_includepaths -p "<project>"'
+ let s:sourcepaths = '-command c_sourcepaths -p "<project>"'
+ let s:options = ['-p', '-t', '-s', '-x', '-i']
+ let s:scopes = ['all', 'project']
+ let s:types = [
+ \ 'class_struct',
+ \ 'function',
+ \ 'variable',
+ \ 'union',
+ \ 'method',
+ \ 'field',
+ \ 'enum',
+ \ 'enumerator',
+ \ 'namespace',
+ \ 'typedef',
+ \ 'macro'
+ \ ]
+ let s:contexts = [
+ \ 'all',
+ \ 'declarations',
+ \ 'definitions',
+ \ 'references'
+ \ ]
+" }}}
+
+" Search(argline) {{{
+" Executes a search.
+function! eclim#c#search#Search(argline)
+ return eclim#lang#Search(
+ \ s:search, g:EclimCSearchSingleResult, a:argline)
+endfunction " }}}
+
+" FindInclude() {{{
+" Finds the include file under the cursor
+function eclim#c#search#FindInclude()
+ if !eclim#project#util#IsCurrentFileInProject(1)
+ return
+ endif
+
+ let file = substitute(getline('.'), '.*#include\s*[<"]\(.*\)[>"].*', '\1', '')
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let command = substitute(s:includepaths, '<project>', project, '')
+ let result = eclim#Execute(command)
+ let paths = type(result) == g:LIST_TYPE ? result : []
+
+ let command = substitute(s:sourcepaths, '<project>', project, '')
+ let result = eclim#Execute(command)
+ let paths += type(result) == g:LIST_TYPE ? result : []
+
+ let dir = expand('%:p:h')
+ if index(paths, dir) == -1
+ call add(paths, dir)
+ endif
+ let results = split(globpath(join(paths, ','), file), '\n')
+
+ if !empty(results)
+ call eclim#util#SetLocationList(eclim#util#ParseLocationEntries(results))
+
+ " single result in another file.
+ if len(results) == 1 && g:EclimCSearchSingleResult != "lopen"
+ let entry = getloclist(0)[0]
+ call eclim#util#GoToBufferWindowOrOpen
+ \ (bufname(entry.bufnr), g:EclimCSearchSingleResult)
+ call eclim#display#signs#Update()
+ else
+ exec 'lopen ' . g:EclimLocationListHeight
+ endif
+ else
+ call eclim#util#EchoInfo("File not found.")
+ endif
+endfunction " }}}
+
+" SearchContext() {{{
+" Executes a contextual search.
+function! eclim#c#search#SearchContext()
+ if getline('.')[col('.') - 1] == '$'
+ call cursor(line('.'), col('.') + 1)
+ let cnum = eclim#util#GetCurrentElementColumn()
+ call cursor(line('.'), col('.') - 1)
+ else
+ let cnum = eclim#util#GetCurrentElementColumn()
+ endif
+
+ if getline('.') =~ '#include\s*[<"][A-Za-z0-9.]*\%' . cnum . 'c'
+ call eclim#c#search#FindInclude()
+ return
+ "elseif getline('.') =~ '\<\(class\|????\)\s\+\%' . cnum . 'c'
+ " call eclim#c#search#Search('-x references')
+ return
+ endif
+
+ call eclim#c#search#Search('-x context')
+endfunction " }}}
+
+" CommandCompleteCSearch(argLead, cmdLine, cursorPos) {{{
+" Custom command completion for CSearch
+function! eclim#c#search#CommandCompleteCSearch(argLead, cmdLine, cursorPos)
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+ if cmdLine =~ '-s\s\+[a-z]*$'
+ let scopes = deepcopy(s:scopes)
+ call filter(scopes, 'v:val =~ "^' . argLead . '"')
+ return scopes
+ elseif cmdLine =~ '-t\s\+[a-z]*$'
+ let types = deepcopy(s:types)
+ call filter(types, 'v:val =~ "^' . argLead . '"')
+ return types
+ elseif cmdLine =~ '-x\s\+[a-z]*$'
+ let contexts = deepcopy(s:contexts)
+ call filter(contexts, 'v:val =~ "^' . argLead . '"')
+ return contexts
+ elseif cmdLine =~ '\s\+[-]\?$'
+ let options = deepcopy(s:options)
+ let index = 0
+ for option in options
+ if a:cmdLine =~ option
+ call remove(options, index)
+ else
+ let index += 1
+ endif
+ endfor
+ return options
+ endif
+ return []
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/client/nailgun.vim b/vim/eclim/autoload/eclim/client/nailgun.vim
@@ -0,0 +1,193 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+ if !exists("g:EclimNailgunKeepAlive")
+ " keepAlive flag - can be re-defined in the user ~/.vimrc .
+ " Read once, on client initialization. Subsequent changes of
+ " this flag in run-time has no effect.
+ let g:EclimNailgunKeepAlive = 0
+ endif
+" }}}
+
+function! eclim#client#nailgun#ChooseEclimdInstance(...) " {{{
+ " Function which prompts the user to pick the target workspace and returns
+ " their choice or if only one workspace is active simply return it without
+ " prompting the user. If the optional 'dir' argument is supplied and that dir
+ " is a subdirectory of one of the workspaces, then that workspace will be
+ " returned.
+ " Optional args:
+ " dir
+
+ if !eclim#EclimAvailable()
+ return
+ endif
+
+ let instances = eclim#client#nailgun#GetEclimdInstances()
+ if len(instances) == 1
+ return instances[keys(instances)[0]]
+ endif
+
+ if len(instances) > 1
+ let path = a:0 && a:1 != '' ? a:1 : expand('%:p')
+ if path == ''
+ let path = getcwd() . '/'
+ endif
+ let path = substitute(path, '\', '/', 'g')
+
+ " when we are in a temp window, use the initiating filename
+ if &buftype != '' && exists('b:filename')
+ let path = b:filename
+ endif
+
+ " project inside of a workspace dir
+ for workspace in keys(instances)
+ if path =~ '^' . workspace
+ return instances[workspace]
+ endif
+ endfor
+
+ " project outside of a workspace dir
+ let project = eclim#project#util#GetProject(path)
+ if len(project) > 0
+ return get(instances, project.workspace, 0)
+ endif
+
+ let workspaces = keys(instances)
+ let response = eclim#util#PromptList(
+ \ 'Muliple workspaces found, please choose the target workspace',
+ \ workspaces, g:EclimInfoHighlight)
+
+ " user cancelled, error, etc.
+ if response < 0
+ return
+ endif
+
+ return instances[workspaces[response]]
+ endif
+
+ call eclim#util#Echo('No eclimd instances found running.')
+endfunction " }}}
+
+function! eclim#client#nailgun#GetEclimdInstances() " {{{
+ " Returns a dict with eclimd instances.
+ let instances = {}
+ if eclim#EclimAvailable()
+ let dotinstances = eclim#UserHome() . '/.eclim/.eclimd_instances'
+ let lines = readfile(dotinstances)
+ for line in lines
+ if line !~ '^{'
+ continue
+ endif
+ let values = eval(line)
+ let instances[values.workspace] = values
+ endfor
+ endif
+ return instances
+endfunction " }}}
+
+function! eclim#client#nailgun#Execute(instance, command, ...) " {{{
+ let exec = a:0 ? a:1 : 0
+
+ if !exec
+ if !exists('g:EclimNailgunClient')
+ call s:DetermineClient()
+ endif
+
+ if g:EclimNailgunClient == 'python' && has('python')
+ return eclim#client#python#nailgun#Execute(a:instance.port, a:command)
+ endif
+ endif
+
+ let eclim = eclim#client#nailgun#GetEclimCommand(a:instance.home)
+ if string(eclim) == '0'
+ return [1, g:EclimErrorReason]
+ endif
+
+ let command = a:command
+ if exec
+ let command = escape(command, '%#')
+ endif
+
+ " on windows/cygwin where cmd.exe is used, we need to escape any '^'
+ " characters in the command args.
+ if has('win32') || has('win64') || has('win32unix')
+ let command = substitute(command, '\^', '^^', 'g')
+ endif
+
+ let eclim .= ' --nailgun-port ' . a:instance.port . ' ' . command
+ if exec
+ let eclim = '!' . eclim
+ endif
+
+ let result = eclim#util#System(eclim, exec, exec)
+ return [v:shell_error, result]
+endfunction " }}}
+
+function! eclim#client#nailgun#GetEclimCommand(home) " {{{
+ " Gets the command to exexute eclim.
+ let command = a:home . 'bin/eclim'
+
+ if has('win32') || has('win64') || has('win32unix')
+ let command = command . (has('win95') ? '.bat' : '.cmd')
+ endif
+
+ if !filereadable(command)
+ let g:EclimErrorReason = 'Could not locate file: ' . command
+ return
+ endif
+
+ if has('win32unix')
+ " in cygwin, we must use 'cmd /c' to prevent issues with eclim script +
+ " some arg containing spaces causing a failure to invoke the script.
+ return 'cmd /c "' . eclim#cygwin#WindowsPath(command) . '"'
+ endif
+ return '"' . command . '"'
+endfunction " }}}
+
+function! s:DetermineClient() " {{{
+ " at least one ubuntu user had serious performance issues using the python
+ " client, so we are only going to default to python on windows machines
+ " where there is an actual potential benefit to using it.
+ if has('python') && (has('win32') || has('win64'))
+ let g:EclimNailgunClient = 'python'
+ else
+ let g:EclimNailgunClient = 'external'
+ endif
+endfunction " }}}
+
+function! eclim#client#nailgun#CommandCompleteWorkspaces(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for available workspaces.
+
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+
+ let instances = eclim#client#nailgun#GetEclimdInstances()
+ let workspaces = sort(keys(instances))
+ if cmdLine !~ '[^\\]\s$'
+ call filter(workspaces, 'v:val =~ "^' . argLead . '"')
+ endif
+
+ return workspaces
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/client/python/nailgun.py b/vim/eclim/autoload/eclim/client/python/nailgun.py
@@ -0,0 +1,214 @@
+"""
+Copyright (C) 2005 - 2011 Eric Van Dewoestine
+
+This program is free software: you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation, either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program. If not, see <http://www.gnu.org/licenses/>.
+
+@author: Anton Sharonov
+@author: Eric Van Dewoestine
+"""
+import socket
+
+try:
+ from cStringIO import StringIO
+except:
+ from StringIO import StringIO
+
+class Nailgun(object):
+ """
+ Client used to communicate with a nailgun server.
+ """
+
+ def __init__(self, **kwargs):
+ self.socket = None
+ self.port = kwargs.get('port')
+ self.keepAlive = int(kwargs.get('keepAlive', 0))
+ self.reconnectCounter = 0
+
+ def send(self, cmdline):
+ """
+ Sends a complete command to the nailgun server. Handles connecting to the
+ server if not currently connected.
+ @param cmdline command, which is sent to server, for instance
+ "-command ping".
+ @return tuple consisting of:
+ - retcode from server (0 for success, non-0 for failure)
+ - string response from server
+ """
+ if not self.isConnected():
+ # with keepAlive do only first reconnect
+ if not self.keepAlive or self.reconnectCounter == 0:
+ (retcode, result) = self.reconnect()
+ if retcode:
+ return (retcode, result)
+
+ if not self.isConnected(): # Only for keepAlive
+ return (-1, "connect: ERROR - socket is not connected (nailgun.py)")
+
+ try: # outer try for pre python 2.5 support.
+ try:
+ for arg in self.parseArgs(cmdline):
+ self.sendChunk("A", arg)
+
+ if self.keepAlive:
+ self.sendChunk("K")
+
+ self.sendChunk("C", "org.eclim.command.Main")
+
+ (retcode, result) = self.processResponse()
+ if self.keepAlive and retcode:
+ # force reconnect on error (may not be necessary)
+ self.reconnect()
+
+ return (retcode, result)
+ except socket.error, ex:
+ args = ex.args
+ if len(args) > 1:
+ retcode, msg = args[0], args[1]
+ elif len(args):
+ retcode, msg = 1, args[0]
+ else:
+ retcode, msg = 1, 'No message'
+ return (retcode, 'send: %s' % msg)
+ finally:
+ if not self.keepAlive:
+ try:
+ self.close()
+ except:
+ # don't let an error on close mask any previous error.
+ pass
+
+ def connect(self, port=None):
+ """
+ Establishes the connection to specified port or if not supplied,
+ uses the default.
+ """
+ port = port or self.port
+ try:
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ sock.connect(('localhost', port))
+ except socket.error, ex:
+ args = ex.args
+ if len(args) > 1:
+ retcode, msg = args[0], args[1]
+ elif len(args):
+ retcode, msg = 1, args[0]
+ else:
+ retcode, msg = 1, 'No message'
+ return (retcode, 'connect: %s' % msg)
+
+ self.socket = sock
+ return (0, '')
+
+ def reconnect(self):
+ if self.socket != None:
+ self.close()
+ self.reconnectCounter += 1
+ return self.connect()
+
+ def close(self):
+ self.socket.close()
+ self.socket = None
+
+ def isConnected(self):
+ return self.socket != None
+
+ def parseArgs(self, cmdline):
+ # FIXME: doesn't handle escaping of spaces/quotes yet (may never need to)
+ args = []
+ arg = ''
+ quote = ''
+ for char in cmdline:
+ if char == ' ' and not quote:
+ if arg:
+ args.append(arg)
+ arg = ''
+ elif char == '"' or char == "'":
+ if quote and char == quote:
+ quote = ''
+ elif not quote:
+ quote = char
+ else:
+ arg += char
+ else:
+ arg += char
+
+ if arg:
+ args.append(arg)
+
+ return args
+
+ def sendChunk(self, chunkType, text=''):
+ """
+ Sends a nailgun 'chunk' to the server.
+ """
+ #print("sendChunk " + chunkType + " " + text)
+ length = len(text)
+ str = "%c%c%c%c%c" % (
+ (length / (65536*256)) % 256,
+ (length / 65536) % 256,
+ (length / 256) % 256,
+ length % 256,
+ chunkType)
+ nbytes = self.socket.sendall(str)
+ nbytes = self.socket.sendall(text)
+
+ def processResponse(self):
+ result = StringIO()
+ exit = 0
+ exitFlag = 1 # expecting 1 times exit chunk
+ while exitFlag > 0:
+ answer = self.recvBlocked(5)
+ if len(answer) < 5:
+ print("error: socket closed unexpectedly\n")
+ return None
+ lenPayload = ord(answer[0]) * 65536 * 256 \
+ + ord(answer[1]) * 65536 \
+ + ord(answer[2]) * 256 \
+ + ord(answer[3])
+ #print("lenPayload detected : %d" % lenPayload)
+ chunkType = answer[4]
+ if chunkType == "1":
+ # STDOUT
+ result.write(self.recvToFD(1, answer, lenPayload))
+ elif chunkType == "2":
+ # STDERR
+ result.write(self.recvToFD(2, answer, lenPayload))
+ elif chunkType == "X":
+ exitFlag = exitFlag - 1
+ exit = int(self.recvToFD(2, answer, lenPayload))
+ else:
+ print("error: unknown chunk type = %d\n" % chunkType)
+ exitFlag = 0
+
+ return [exit, result.getvalue()]
+
+ def recvBlocked(self, lenPayload):
+ """
+ Receives until all data is read - necessary because usual recv sometimes
+ returns with number of bytes read less then asked.
+ """
+ received = ""
+ while (len(received) < lenPayload):
+ received = received + self.socket.recv(lenPayload - len(received))
+ return received
+
+ def recvToFD(self, destFD, buf, lenPayload):
+ """
+ This function just mimics the function with the same name from the C
+ client. We don't really care which file descriptor the server tells us to
+ write to - STDOUT and STDERR are the same on VIM side (see eclim.bat,
+ "2>&1" at the end of command).
+ """
+ received = self.recvBlocked(lenPayload)
+ return received
diff --git a/vim/eclim/autoload/eclim/client/python/nailgun.vim b/vim/eclim/autoload/eclim/client/python/nailgun.vim
@@ -0,0 +1,115 @@
+" Author: Anton Sharonov
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2010 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+ let s:python_dir = expand("<sfile>:h")
+" }}}
+
+" Execute(port, command) {{{
+" Sends to the eclimd server command, supplied as argument string.
+" Returns server's respond.
+function! eclim#client#python#nailgun#Execute(port, command)
+ call s:InitClient(a:port)
+ let result_viml = ""
+ let retcode = 0
+
+ let begin = localtime()
+ try
+python << PYTHONEOF
+command = vim.eval('a:command')
+(retcode, result) = client.send(command)
+vim.command('let retcode = %i' % retcode)
+vim.command("let result = '%s'" % result.replace("'", "''"))
+PYTHONEOF
+ finally
+ call eclim#util#EchoTrace(
+ \ 'nailgun.py (port: ' . a:port . '): ' . a:command, localtime() - begin)
+ endtry
+
+ return [retcode, result]
+endfunction " }}}
+
+" Reconnect(port) {{{
+" Does unconditional reconnect of the python_if
+" (useful to manual recover from errors in the python_if)
+function! eclim#client#python#nailgun#Reconnect(port)
+ call s:InitClient(a:port)
+python << PYTHONEOF
+client.reconnect()
+PYTHONEOF
+endfunction " }}}
+
+" SetKeepAlive(port, value) {{{
+" Updates the in runtime value of the keepAlive flag.
+function! eclim#client#python#nailgun#SetKeepAlive(port, value)
+ call s:InitClient(a:port)
+python << PYTHONEOF
+client.keepAlive = int(vim.eval('a:value'))
+PYTHONEOF
+endfunction " }}}
+
+" GetKeepAlive(port) {{{
+" Retrieves the value of the keepAlive flag.
+function! eclim#client#python#nailgun#GetKeepAlive(port)
+ call s:InitClient(a:port)
+ let result = 0
+python << PYTHONEOF
+vim.command("let result = %s" % client.keepAlive)
+PYTHONEOF
+ return result
+endfunction " }}}
+
+" GetReconnectCounter(port) {{{
+" Retrieves the value of the reconnect counter.
+function! eclim#client#python#nailgun#GetReconnectCounter(port)
+ call s:InitClient(a:port)
+ let result = 0
+python << PYTHONEOF
+vim.command("let result = %d" % client.reconnectCounter)
+PYTHONEOF
+ return result
+endfunction " }}}
+
+" s:InitClient(port) {{{
+" Initializes the python interface to the nailgun server.
+function! s:InitClient(port)
+python << PYTHONEOF
+if not vars().has_key('clients'):
+ import sys, vim
+ sys.path.append(vim.eval('s:python_dir'))
+ import nailgun
+
+ clients = {}
+
+port = int(vim.eval('a:port'))
+if not clients.has_key(port):
+ clients[port] = nailgun.Nailgun(
+ port=port,
+ keepAlive=vim.eval('g:EclimNailgunKeepAlive'),
+ )
+client = clients[port]
+PYTHONEOF
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/common/buffers.vim b/vim/eclim/autoload/eclim/common/buffers.vim
@@ -0,0 +1,400 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists('g:EclimBuffersSort')
+ let g:EclimBuffersSort = 'file'
+endif
+if !exists('g:EclimBuffersSortDirection')
+ let g:EclimBuffersSortDirection = 'asc'
+endif
+if !exists('g:EclimBuffersDefaultAction')
+ let g:EclimBuffersDefaultAction = g:EclimDefaultFileOpenAction
+endif
+if !exists('g:EclimBuffersDeleteOnTabClose')
+ let g:EclimBuffersDeleteOnTabClose = 0
+endif
+if !exists('g:EclimOnlyExclude')
+ let g:EclimOnlyExclude = '^NONE$'
+endif
+if !exists('g:EclimOnlyExcludeFixed')
+ let g:EclimOnlyExcludeFixed = 1
+endif
+" }}}
+
+" ScriptVariables {{{
+ let s:eclim_tab_id = 0
+" }}}
+
+function! eclim#common#buffers#Buffers(bang) " {{{
+ " Like, :buffers, but opens a temporary buffer.
+
+ let options = {'maxfilelength': 0}
+ let buffers = eclim#common#buffers#GetBuffers(options)
+
+ if g:EclimBuffersSort != ''
+ call sort(buffers, 'eclim#common#buffers#BufferCompare')
+ endif
+
+ let lines = []
+ let buflist = []
+ let filelength = options['maxfilelength']
+ let tabid = exists('*gettabvar') ? s:GetTabId() : 0
+ let tabbuffers = tabpagebuflist()
+ for buffer in buffers
+ let eclim_tab_id = getbufvar(buffer.bufnr, 'eclim_tab_id')
+ if a:bang != '' || eclim_tab_id == '' || eclim_tab_id == tabid
+ " for buffers w/ out a tab id, don't show them in the list if they
+ " are active, but aren't open on the current tab.
+ if a:bang == '' && buffer.status =~ 'a' && index(tabbuffers, buffer.bufnr) == -1
+ continue
+ endif
+
+ call add(lines, s:BufferEntryToLine(buffer, filelength))
+ call add(buflist, buffer)
+ endif
+ endfor
+
+ call eclim#util#TempWindow('[buffers]', lines)
+
+ setlocal modifiable noreadonly
+ call append(line('$'), ['', '" use ? to view help'])
+ setlocal nomodifiable readonly
+
+ let b:eclim_buffers = buflist
+
+ " syntax
+ set ft=eclim_buffers
+ hi link BufferActive Special
+ hi link BufferHidden Comment
+ syntax match BufferActive /+\?active\s\+\(\[RO\]\)\?/
+ syntax match BufferHidden /+\?hidden\s\+\(\[RO\]\)\?/
+ syntax match Comment /^".*/
+
+ " mappings
+ nnoremap <silent> <buffer> <cr> :call <SID>BufferOpen(g:EclimBuffersDefaultAction)<cr>
+ nnoremap <silent> <buffer> E :call <SID>BufferOpen('edit')<cr>
+ nnoremap <silent> <buffer> S :call <SID>BufferOpen('split')<cr>
+ nnoremap <silent> <buffer> V :call <SID>BufferOpen('vsplit')<cr>
+ nnoremap <silent> <buffer> T :call <SID>BufferOpen('tablast \| tabnew')<cr>
+ nnoremap <silent> <buffer> D :call <SID>BufferDelete()<cr>
+ nnoremap <silent> <buffer> R :Buffers<cr>
+
+ " assign to buffer var to get around weird vim issue passing list containing
+ " a string w/ a '<' in it on execution of mapping.
+ let b:buffers_help = [
+ \ '<cr> - open buffer with default action',
+ \ 'E - open with :edit',
+ \ 'S - open in a new split window',
+ \ 'V - open in a new vertically split window',
+ \ 'T - open in a new tab',
+ \ 'D - delete the buffer',
+ \ 'R - refresh the buffer list',
+ \ ]
+ nnoremap <buffer> <silent> ?
+ \ :call eclim#help#BufferHelp(b:buffers_help, 'vertical', 40)<cr>
+
+ "augroup eclim_buffers
+ " autocmd!
+ " autocmd BufAdd,BufWinEnter,BufDelete,BufWinLeave *
+ " \ call eclim#common#buffers#BuffersUpdate()
+ " autocmd BufUnload <buffer> autocmd! eclim_buffers
+ "augroup END
+endfunction " }}}
+
+function! eclim#common#buffers#BuffersToggle(bang) " {{{
+ let name = eclim#util#EscapeBufferName('[buffers]')
+ if bufwinnr(name) == -1
+ call eclim#common#buffers#Buffers(a:bang)
+ else
+ exec "bdelete " . bufnr(name)
+ endif
+endfunction " }}}
+
+function! eclim#common#buffers#BufferCompare(buffer1, buffer2) " {{{
+ exec 'let attr1 = a:buffer1.' . g:EclimBuffersSort
+ exec 'let attr2 = a:buffer2.' . g:EclimBuffersSort
+ let compare = attr1 == attr2 ? 0 : attr1 > attr2 ? 1 : -1
+ if g:EclimBuffersSortDirection == 'desc'
+ let compare = 0 - compare
+ endif
+ return compare
+endfunction " }}}
+
+function! eclim#common#buffers#Only() " {{{
+ let curwin = winnr()
+ let winnum = 1
+ while winnum <= winnr('$')
+ let fixed = g:EclimOnlyExcludeFixed && (
+ \ getwinvar(winnum, '&winfixheight') == 1 ||
+ \ getwinvar(winnum, '&winfixwidth') == 1)
+ let excluded = bufname(winbufnr(winnum)) =~ g:EclimOnlyExclude
+ if winnum != curwin && !fixed && !excluded
+ if winnum < curwin
+ let curwin -= 1
+ endif
+ exec winnum . 'winc w'
+ close
+ exec curwin . 'winc w'
+ continue
+ endif
+ let winnum += 1
+ endwhile
+endfunction " }}}
+
+function! eclim#common#buffers#GetBuffers(...) " {{{
+ let options = a:0 ? a:1 : {}
+
+ redir => list
+ silent buffers
+ redir END
+
+ let buffers = []
+ let maxfilelength = 0
+ for entry in split(list, '\n')
+ let buffer = {}
+ let buffer.status = substitute(entry, '\s*[0-9]\+\s\+\(.\{-}\)\s\+".*', '\1', '')
+ let buffer.path = substitute(entry, '.\{-}"\(.\{-}\)".*', '\1', '')
+ let buffer.path = fnamemodify(buffer.path, ':p')
+ let buffer.file = fnamemodify(buffer.path, ':p:t')
+ let buffer.dir = fnamemodify(buffer.path, ':p:h')
+ let buffer.bufnr = str2nr(substitute(entry, '\s*\([0-9]\+\).*', '\1', ''))
+ let buffer.lnum = str2nr(substitute(entry, '.*"\s\+\w\+\s\+\(\d\+\)', '\1', ''))
+ call add(buffers, buffer)
+
+ if len(buffer.file) > maxfilelength
+ let maxfilelength = len(buffer.file)
+ endif
+ endfor
+
+ if has_key(options, 'maxfilelength')
+ let options['maxfilelength'] = maxfilelength
+ endif
+
+ return buffers
+endfunction " }}}
+
+function! eclim#common#buffers#TabInit() " {{{
+ let tabnr = 1
+ while tabnr <= tabpagenr('$')
+ let tab_id = gettabvar(tabnr, 'eclim_tab_id')
+ if tab_id == ''
+ let s:eclim_tab_id += 1
+ call settabvar(tabnr, 'eclim_tab_id', s:eclim_tab_id)
+ for bufnr in tabpagebuflist(tabnr)
+ let btab_id = getbufvar(bufnr, 'eclim_tab_id')
+ if btab_id == ''
+ call setbufvar(bufnr, 'eclim_tab_id', s:eclim_tab_id)
+ endif
+ endfor
+ endif
+ let tabnr += 1
+ endwhile
+endfunction " }}}
+
+function! eclim#common#buffers#TabEnter() " {{{
+ if !s:GetTabId()
+ call s:SetTabId()
+ endif
+
+ if g:EclimBuffersDeleteOnTabClose
+ if exists('s:tab_count') && s:tab_count > tabpagenr('$')
+ " delete any buffers associated with the closed tab
+ let buffers = eclim#common#buffers#GetBuffers()
+ for buffer in buffers
+ let eclim_tab_id = getbufvar(buffer.bufnr, 'eclim_tab_id')
+ " don't delete active buffers, just in case the tab has the wrong
+ " eclim_tab_id
+ if eclim_tab_id == s:tab_prev && buffer.status !~ 'a'
+ try
+ exec 'bdelete ' . buffer.bufnr
+ catch /E89/
+ " ignore since it happens when using bd! on the last buffer for
+ " another tab.
+ endtry
+ endif
+ endfor
+ endif
+ endif
+endfunction " }}}
+
+function! eclim#common#buffers#TabLeave() " {{{
+ let s:tab_prev = s:GetTabId()
+ let s:tab_count = tabpagenr('$')
+endfunction " }}}
+
+function! eclim#common#buffers#TabLastOpenIn() " {{{
+ if !buflisted('%')
+ silent! unlet b:eclim_tab_id
+ endif
+
+ if !s:GetTabId()
+ call s:SetTabId()
+ endif
+
+ let tabnr = 1
+ let other_tab = 0
+ let bufnr = bufnr('%')
+ while tabnr <= tabpagenr('$')
+ if tabnr != tabpagenr() &&
+ \ eclim#util#ListContains(tabpagebuflist(tabnr), bufnr)
+ let other_tab = tabnr
+ break
+ endif
+ let tabnr += 1
+ endwhile
+
+ if !exists('b:eclim_tab_id') || !other_tab
+ let b:eclim_tab_id = s:GetTabId()
+ endif
+endfunction " }}}
+
+function! eclim#common#buffers#OpenNextHiddenTabBuffer(current) " {{{
+ let allbuffers = eclim#common#buffers#GetBuffers()
+
+ " build list of buffers open in other tabs to exclude
+ let tabbuffers = []
+ let lasttab = tabpagenr('$')
+ let index = 1
+ while index <= lasttab
+ if index != tabpagenr()
+ for bnum in tabpagebuflist(index)
+ call add(tabbuffers, bnum)
+ endfor
+ endif
+ let index += 1
+ endwhile
+
+ " build list of buffers not open in any window, and last seen on the
+ " current tab.
+ let hiddenbuffers = []
+ for buffer in allbuffers
+ let bnum = buffer.bufnr
+ if bnum != a:current && index(tabbuffers, bnum) == -1 && bufwinnr(bnum) == -1
+ let eclim_tab_id = getbufvar(bnum, 'eclim_tab_id')
+ if eclim_tab_id != '' && eclim_tab_id != t:eclim_tab_id
+ continue
+ endif
+
+ if bnum < a:current
+ call insert(hiddenbuffers, bnum)
+ else
+ call add(hiddenbuffers, bnum)
+ endif
+ endif
+ endfor
+
+ " we found a hidden buffer, so open it
+ if len(hiddenbuffers) > 0
+ exec 'buffer ' . hiddenbuffers[0]
+ doautocmd BufEnter
+ doautocmd BufWinEnter
+ doautocmd BufReadPost
+ return hiddenbuffers[0]
+ endif
+ return 0
+endfunction " }}}
+
+function! s:BufferDelete() " {{{
+ let line = line('.')
+ if line > len(b:eclim_buffers)
+ return
+ endif
+
+ let index = line - 1
+ setlocal modifiable
+ setlocal noreadonly
+ exec line . ',' . line . 'delete _'
+ setlocal nomodifiable
+ setlocal readonly
+ let buffer = b:eclim_buffers[index]
+ call remove(b:eclim_buffers, index)
+
+ let winnr = winnr()
+ " make sure the autocmds are executed in the following order
+ noautocmd exec 'bd ' . buffer.bufnr
+ doautocmd BufDelete
+ doautocmd BufEnter
+ exec winnr . 'winc w'
+endfunction " }}}
+
+function! s:BufferEntryToLine(buffer, filelength) " {{{
+ let line = ''
+ let line .= a:buffer.status =~ '+' ? '+' : ' '
+ let line .= a:buffer.status =~ 'a' ? 'active' : 'hidden'
+ let line .= a:buffer.status =~ '[-=]' ? ' [RO] ' : ' '
+ let line .= a:buffer.file
+
+ let pad = a:filelength - len(a:buffer.file) + 2
+ while pad > 0
+ let line .= ' '
+ let pad -= 1
+ endwhile
+
+ let line .= a:buffer.dir
+ return line
+endfunction " }}}
+
+function! s:BufferOpen(cmd) " {{{
+ let line = line('.')
+ if line > len(b:eclim_buffers)
+ return
+ endif
+
+ let file = bufname(b:eclim_buffers[line - 1].bufnr)
+ let winnr = b:winnr
+ close
+
+ " prevent opening the buffer in a split of a vertical tool window (project
+ " tree, taglist, etc.)
+ if exists('g:VerticalToolBuffers') && has_key(g:VerticalToolBuffers, winbufnr(winnr))
+ let winnr = 1
+ while has_key(g:VerticalToolBuffers, winbufnr(winnr))
+ let winnr += 1
+ if winnr > winnr('$')
+ let winnr -= 1
+ break
+ endif
+ endwhile
+ endif
+
+ exec winnr . 'winc w'
+ call eclim#util#GoToBufferWindowOrOpen(file, a:cmd)
+endfunction " }}}
+
+function! s:GetTabId(...) " {{{
+ let tabnr = a:0 ? a:1 : tabpagenr()
+ " using gettabvar over t:eclim_tab_id because while autocmds are executing,
+ " the tabpagenr() may return the correct tab number, but accessing
+ " t:eclim_tab_id may return the value from the previously focused tab.
+ return gettabvar(tabnr, 'eclim_tab_id')
+endfunction " }}}
+
+function! s:SetTabId(...) " {{{
+ let tabnr = a:0 ? a:1 : tabpagenr()
+ let s:eclim_tab_id += 1
+ " using settabvar for reason explained in s:GetTabId()
+ call settabvar(tabnr, 'eclim_tab_id', s:eclim_tab_id)
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/common/history.vim b/vim/eclim/autoload/eclim/common/history.vim
@@ -0,0 +1,332 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+ if !exists('g:EclimHistoryDiffOrientation')
+ let g:EclimHistoryDiffOrientation = 'vertical'
+ endif
+" }}}
+
+" Script Variables {{{
+let s:command_add = '-command history_add -p "<project>" -f "<file>"'
+let s:command_list = '-command history_list -p "<project>" -f "<file>"'
+let s:command_revision =
+ \ '-command history_revision -p "<project>" -f "<file>" -r <revision>'
+let s:command_clear = '-command history_clear -p "<project>" -f "<file>"'
+" }}}
+
+" AddHistory() {{{
+" Adds the current state of the file to the eclipse local history (should be
+" invoked prior to saving to disk).
+function! eclim#common#history#AddHistory()
+ if !filereadable(expand('%')) || !eclim#project#util#IsCurrentFileInProject(0)
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:command_add
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ call eclim#Execute(command)
+endfunction " }}}
+
+" History() {{{
+" Opens a temporary buffer with a list of local history revisions.
+function! eclim#common#history#History()
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:command_list
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let history = eclim#Execute(command)
+ if type(history) != g:LIST_TYPE
+ return
+ endif
+
+ let lines = [file]
+ let revisions = [0]
+ let indent = eclim#util#GetIndent(1)
+ for rev in history
+ call add(lines, indent . rev.datetime . ' (' . rev.delta . ')')
+ call add(revisions, rev.timestamp)
+ endfor
+ call add(lines, '')
+ call eclim#util#TempWindow('[History]', lines)
+
+ setlocal modifiable noreadonly
+ if !g:EclimProjectKeepLocalHistory
+ call append(line('$'),
+ \ '" Note: local history is current disabled: ' .
+ \ 'g:EclimProjectKeepLocalHistory = ' . g:EclimProjectKeepLocalHistory)
+ endif
+ call append(line('$'), '" use ? to view help')
+ setlocal nomodifiable readonly
+ syntax match Comment /^".*/
+
+ let b:history_revisions = revisions
+ call s:Syntax()
+
+ command! -count=1 HistoryDiffNext call s:DiffNextPrev(1, <count>)
+ command! -count=1 HistoryDiffPrev call s:DiffNextPrev(-1, <count>)
+ augroup eclim_history_window
+ autocmd! BufWinLeave <buffer>
+ autocmd BufWinLeave <buffer>
+ \ delcommand HistoryDiffNext |
+ \ delcommand HistoryDiffPrev
+ augroup END
+ noremap <buffer> <silent> <cr> :call <SID>View()<cr>
+ noremap <buffer> <silent> d :call <SID>Diff()<cr>
+ noremap <buffer> <silent> r :call <SID>Revert()<cr>
+ noremap <buffer> <silent> c :call <SID>Clear(1)<cr>
+
+ " assign to buffer var to get around weird vim issue passing list containing
+ " a string w/ a '<' in it on execution of mapping.
+ let b:history_help = [
+ \ '<cr> - view the entry',
+ \ 'd - diff the file with the version under the cursor',
+ \ 'r - revert the file to the version under the cursor',
+ \ 'c - clear the history',
+ \ ':HistoryDiffNext - diff the file with the next version in the history',
+ \ ':HistoryDiffPrev - diff the file with the previous version in the history',
+ \ ]
+ nnoremap <buffer> <silent> ?
+ \ :call eclim#help#BufferHelp(b:history_help, 'vertical', 50)<cr>
+endfunction " }}}
+
+" HistoryClear(bang) {{{
+" Clear the history for the current file.
+function! eclim#common#history#HistoryClear(bang)
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ call s:Clear(a:bang == '', expand('%:p'))
+endfunction " }}}
+
+" s:View([cmd]) {{{
+" View the contents of the revision under the cursor.
+function s:View(...)
+ if line('.') == 1 || line('.') > len(b:history_revisions)
+ return
+ endif
+
+ let current = b:filename
+ let entry = line('.') - 1
+ let revision = b:history_revisions[entry]
+ if eclim#util#GoToBufferWindow(current)
+ let filetype = &ft
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:command_revision
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<revision>', revision, '')
+ let result = eclim#Execute(command)
+ if result == "0"
+ return
+ endif
+
+ let cmd = len(a:000) > 0 ? a:000[0] : 'split'
+ call eclim#util#GoToBufferWindowOrOpen(current . '_' . revision, cmd)
+
+ setlocal modifiable
+ setlocal noreadonly
+
+ let temp = tempname()
+ call writefile(split(result, '\n'), temp)
+ try
+ silent 1,$delete _
+ silent read ++edit `=temp`
+ silent 1,1delete _
+ finally
+ call delete(temp)
+ endtry
+
+ exec 'setlocal filetype=' . filetype
+ setlocal nomodified
+ setlocal readonly
+ setlocal nomodifiable
+ setlocal noswapfile
+ setlocal nobuflisted
+ setlocal buftype=nofile
+ setlocal bufhidden=delete
+ doautocmd BufReadPost
+
+ call s:HighlightEntry(entry)
+
+ return 1
+ else
+ call eclim#util#EchoWarning('Target file is no longer open.')
+ endif
+endfunction " }}}
+
+" s:Diff() {{{
+" Diff the contents of the revision under the cursor against the current
+" contents.
+function s:Diff()
+ let hist_buf = bufnr('%')
+ let winend = winnr('$')
+ let winnum = 1
+ while winnum <= winend
+ let bufnr = winbufnr(winnum)
+ if getbufvar(bufnr, 'history_diff') != ''
+ exec bufnr . 'bd'
+ continue
+ endif
+ let winnum += 1
+ endwhile
+ call eclim#util#GoToBufferWindow(hist_buf)
+
+ let current = b:filename
+ let orien = g:EclimHistoryDiffOrientation == 'horizontal' ? '' : 'vertical'
+ if s:View(orien . ' below split')
+ let b:history_diff = 1
+ diffthis
+ augroup history_diff
+ autocmd! BufWinLeave <buffer>
+ call eclim#util#GoToBufferWindowRegister(current)
+ autocmd BufWinLeave <buffer> diffoff
+ augroup END
+
+ call eclim#util#GoToBufferWindow(current)
+ diffthis
+ endif
+endfunction " }}}
+
+" s:DiffNextPrev(dir, count) {{{
+function s:DiffNextPrev(dir, count)
+ let winnr = winnr()
+ if eclim#util#GoToBufferWindow('[History]')
+ let num = v:count > 0 ? v:count : a:count
+ let cur = exists('b:history_current_entry') ? b:history_current_entry : 0
+ let index = cur + (a:dir * num)
+ if index < 0 || index > len(b:history_revisions)
+ call eclim#util#EchoError('Operation exceeds history stack range.')
+ exec winnr . 'winc w'
+ return
+ endif
+ call cursor(index + 1, 0)
+ call s:Diff()
+ endif
+endfunction " }}}
+
+" s:Revert() {{{
+" Revert the file to the revision under the cursor.
+function s:Revert()
+ if line('.') == 1 || line('.') > len(b:history_revisions)
+ return
+ endif
+
+ let current = b:filename
+ let revision = b:history_revisions[line('.') - 1]
+ if eclim#util#GoToBufferWindow(current)
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:command_revision
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<revision>', revision, '')
+ let result = eclim#Execute(command)
+ if result == "0"
+ return
+ endif
+
+ let ff = &ff
+ let temp = tempname()
+ call writefile(split(result, '\n'), temp)
+ try
+ silent 1,$delete _
+ silent read ++edit `=temp`
+ silent 1,1delete _
+ finally
+ call delete(temp)
+ endtry
+
+ if ff != &ff
+ call eclim#util#EchoWarning(
+ \ "Warning: the file format is being reverted from '" . ff . "' to '" .
+ \ &ff . "'. Using vim's undo will not restore the previous format so " .
+ \ "if you choose to undo the reverting of this file, you will need to " .
+ \ "manually set the file format back to " . ff . " (set ff=" . ff . ").")
+ endif
+ endif
+endfunction " }}}
+
+" s:Clear(prompt, [filename]) {{{
+" Clear the history.
+function s:Clear(prompt, ...)
+ let response = 1
+ if a:prompt
+ let response = eclim#util#PromptConfirm(
+ \ 'Clear local history?', g:EclimInfoHighlight)
+ endif
+
+ if response == 1
+ let filename = len(a:000) > 0 ? a:000[0] : b:filename
+ let current = eclim#project#util#GetProjectRelativeFilePath(filename)
+ let project = eclim#project#util#GetCurrentProjectName()
+ let command = s:command_clear
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', current, '')
+ let result = eclim#Execute(command)
+ if result == "0"
+ return
+ endif
+
+ if filename != expand('%:p')
+ quit
+ endif
+ call eclim#util#Echo(result)
+ endif
+endfunction " }}}
+
+" s:Syntax() {{{
+function! s:Syntax()
+ set ft=eclim_history
+ hi link HistoryFile Identifier
+ hi link HistoryCurrentEntry Constant
+ syntax match HistoryFile /.*\%1l.*/
+ syntax match Comment /^".*/
+endfunction " }}}
+
+" s:HighlightEntry(index) {{{
+function s:HighlightEntry(index)
+ let winnr = winnr()
+ if eclim#util#GoToBufferWindow('[History]')
+ let b:history_current_entry = a:index
+ try
+ " forces reset of syntax
+ call s:Syntax()
+ exec 'syntax match HistoryCurrentEntry /.*\%' . (a:index + 1) . 'l.*/'
+ finally
+ exec winnr . 'winc w'
+ endtry
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/common/largefile.vim b/vim/eclim/autoload/eclim/common/largefile.vim
@@ -0,0 +1,58 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Initially based on vimscript 1506
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Settings {{{
+let s:file_size = g:EclimLargeFileSize * 1024 * 1024
+let s:events = ['BufRead', 'CursorHold', 'FileType']
+" }}}
+
+function! eclim#common#largefile#InitSettings() " {{{
+ let file = expand("<afile>")
+ let size = getfsize(file)
+ if size >= s:file_size || size == -2
+ if !exists('b:save_events')
+ let b:save_events = &eventignore
+ call s:ApplySettings()
+ setlocal noswapfile nowrap bufhidden=unload
+ autocmd eclim_largefile BufEnter,BufWinEnter <buffer> call <SID>ApplySettings()
+ autocmd eclim_largefile BufLeave,BufWinLeave <buffer> call <SID>RevertSettings()
+ endif
+ endif
+endfunction " }}}
+
+function! s:ApplySettings() " {{{
+ let &eventignore=join(s:events, ',')
+ if !exists('b:largefile_notified')
+ let b:largefile_notified = 1
+ call eclim#util#Echo('Note: Large file settings applied.')
+ endif
+endfunction " }}}
+
+function! s:RevertSettings() " {{{
+ if exists('b:save_events')
+ let &eventignore=b:save_events
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/common/license.vim b/vim/eclim/autoload/eclim/common/license.vim
@@ -0,0 +1,87 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+ let s:year = exists('*strftime') ? strftime('%Y') : '2009'
+" }}}
+
+" GetLicense() {{{
+" Retrieves the file containing the license text.
+function! eclim#common#license#GetLicense()
+ let file = eclim#project#util#GetProjectSetting('org.eclim.project.copyright')
+ if type(file) == g:NUMBER_TYPE
+ return
+ elseif file == ''
+ call eclim#util#EchoWarning(
+ \ "Project setting 'org.eclim.project.copyright' has not been supplied.")
+ return
+ endif
+
+ let file = eclim#project#util#GetCurrentProjectRoot() . '/' . file
+ if !filereadable(file)
+ return
+ endif
+ return file
+endfunction " }}}
+
+" License(pre, post, mid) {{{
+" Retrieves the license configured license and applies the specified prefix
+" and postfix as the lines before and after the license and uses 'mid' as the
+" prefix for every line.
+" Returns the license as a list of strings.
+function! eclim#common#license#License(pre, post, mid)
+ let file = eclim#common#license#GetLicense()
+ if type(file) == g:NUMBER_TYPE && file == 0
+ return ''
+ endif
+
+ let contents = readfile(file)
+ if a:mid != ''
+ call map(contents, 'a:mid . v:val')
+ endif
+
+ if a:pre != ''
+ call insert(contents, a:pre)
+ endif
+
+ if a:post != ''
+ call add(contents, a:post)
+ endif
+
+ call map(contents, "substitute(v:val, '${year}', s:year, 'g')")
+
+ let author = eclim#project#util#GetProjectSetting('org.eclim.user.name')
+ if type(author) == g:STRING_TYPE && author != ''
+ call map(contents, "substitute(v:val, '${author}', author, 'g')")
+ endif
+
+ let email = eclim#project#util#GetProjectSetting('org.eclim.user.email')
+ if type(email) == g:STRING_TYPE && email != ''
+ call map(contents, "substitute(v:val, '${email}', email, 'g')")
+ endif
+ call map(contents, "substitute(v:val, '\\s\\+$', '', '')")
+
+ return contents
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/common/locate.vim b/vim/eclim/autoload/eclim/common/locate.vim
@@ -0,0 +1,655 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Implements the :LocateFile functionality.
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists('g:EclimLocateFileDefaultAction')
+ let g:EclimLocateFileDefaultAction = g:EclimDefaultFileOpenAction
+endif
+
+if !exists('g:EclimLocateFileScope')
+ let g:EclimLocateFileScope = 'project'
+endif
+
+if !exists('g:EclimLocateFileNonProjectScope')
+ let g:EclimLocateFileNonProjectScope = 'workspace'
+endif
+
+if !exists('g:EclimLocateFileFuzzy')
+ let g:EclimLocateFileFuzzy = 1
+endif
+
+if !exists('g:EclimLocateFileCaseInsensitive')
+ " one of: 'lower', 'never', 'always'
+ let g:EclimLocateFileCaseInsensitive = 'lower'
+endif
+
+if !exists('g:EclimLocateUserScopes')
+ let g:EclimLocateUserScopes = []
+endif
+
+let g:eclim_locate_default_updatetime = &updatetime
+
+" disable autocomplpop in the locate prompt
+if exists('g:acp_behavior')
+ let g:acp_behavior['locate_prompt'] = []
+endif
+
+" }}}
+
+" Script Variables {{{
+let s:command_locate = '-command locate_file -s "<scope>"'
+let s:scopes = [
+ \ 'project',
+ \ 'workspace',
+ \ 'buffers',
+ \ 'quickfix',
+ \ ]
+
+let s:help = [
+ \ '<esc> - close the locate prompt + results',
+ \ '<tab>, <down> - select the next file',
+ \ '<s-tab>, <up> - select the previous file',
+ \ '<cr> - open selected file w/ default action',
+ \ '<c-e> - open with :edit',
+ \ '<c-s> - open in a split window',
+ \ '<c-t> - open in a new tab',
+ \ '<c-l> - choose search scope',
+ \ '<c-h> - toggle help buffer',
+ \ ]
+" }}}
+
+" LocateFile(action, file, [scope]) {{{
+" Locates a file using the specified action for opening the file when found.
+" action - '' (use user default), 'split', 'edit', etc.
+" file - 'somefile.txt',
+" '', (kick off completion mode),
+" '<cursor>' (locate the file under the cursor)
+" scope - optional scope to search in (project, workspace, buffers, etc.)
+function! eclim#common#locate#LocateFile(action, file, ...)
+ let project = eclim#project#util#GetCurrentProjectName()
+ let scope = a:0 > 0 ? a:1 : g:EclimLocateFileScope
+
+ if !eclim#util#ListContains(s:scopes, scope) &&
+ \ !eclim#util#ListContains(g:EclimLocateUserScopes, scope)
+ call eclim#util#EchoWarning('Unrecognized scope: ' . scope)
+ return
+ endif
+
+ if scope == 'project' && (project == '' || !eclim#EclimAvailable(0))
+ let scope = g:EclimLocateFileNonProjectScope
+ endif
+
+ let workspace = ''
+ if scope == 'project' || scope == 'workspace'
+ let instance = eclim#client#nailgun#ChooseEclimdInstance()
+ if type(instance) != g:DICT_TYPE
+ return
+ endif
+
+ let workspace = instance.workspace
+ if !eclim#PingEclim(0, workspace)
+ call eclim#util#EchoError('Unable to connect to eclimd.')
+ return
+ endif
+ endif
+
+ let results = []
+ let action = a:action
+ if action == ''
+ let action = g:EclimLocateFileDefaultAction
+ endif
+
+ let file = a:file
+ if file == ''
+ call s:LocateFileCompletionInit(action, scope, project, workspace)
+ return
+ elseif file == '<cursor>'
+ let file = eclim#util#GrabUri()
+
+ " if grabbing a relative url, remove any anchor info or query parameters
+ let file = substitute(file, '[#?].*', '', '')
+ endif
+
+ let name = fnamemodify(file, ':t')
+ if name == ''
+ call eclim#util#Echo('Please supply more than just a directory name.')
+ return
+ endif
+
+ let pattern = file
+ let pattern = s:LocateFileConvertPattern(pattern, 0)
+ let pattern = '[^/]*' . pattern
+ try
+ let b:workspace = workspace
+ let b:project = project
+ let results = s:LocateFileFunction(scope)(pattern)
+ finally
+ unlet! b:workspce
+ unlet! b:project
+ endtry
+
+ call map(results, "v:val.path")
+
+ let result = ''
+ " One result.
+ if len(results) == 1
+ let result = results[0]
+
+ " More than one result.
+ elseif len(results) > 1
+ let message = "Multiple results, choose the file to open"
+ let response = eclim#util#PromptList(message, results, g:EclimInfoHighlight)
+ if response == -1
+ return
+ endif
+
+ let result = results[response]
+
+ " No results
+ else
+ call eclim#util#Echo('Unable to locate file pattern "' . file . '".')
+ return
+ endif
+
+ if has('win32unix')
+ let result = eclim#cygwin#CygwinPath(result)
+ endif
+
+ call eclim#util#GoToBufferWindowOrOpen(eclim#util#Simplify(result), action)
+ call eclim#util#Echo(' ')
+endfunction " }}}
+
+function! eclim#common#locate#LocateFileCompletion() " {{{
+ let line = getline('.')
+ if line !~ '^> '
+ call setline(1, substitute(line, '^>\?\s*', '> \1', ''))
+ call cursor(1, 3)
+ let line = getline('.')
+ endif
+
+ let completions = []
+ let display = []
+ let name = substitute(line, '^>\s*', '', '')
+ if name !~ '^\s*$'
+ let pattern = name
+ let pattern = s:LocateFileConvertPattern(pattern, g:EclimLocateFileFuzzy)
+
+ let results = s:LocateFileFunction(b:scope)(pattern)
+ if !empty(results)
+ for result in results
+ let rel = eclim#util#Simplify(get(result, 'projectPath', result.path))
+ let dict = {'word': result.name, 'menu': rel, 'info': result.path}
+ call add(completions, dict)
+ call add(display, result.name . ' ' . rel)
+ endfor
+ endif
+ endif
+ let b:completions = completions
+ let winnr = winnr()
+ noautocmd exec bufwinnr(b:results_bufnum) . 'winc w'
+ setlocal modifiable
+ 1,$delete _
+ call append(1, display)
+ 1,1delete _
+ setlocal nomodifiable
+ exec winnr . 'winc w'
+
+ " part of bad hack for gvim on windows
+ let b:start_selection = 1
+
+ call s:LocateFileSelection(1)
+endfunction " }}}
+
+function! eclim#common#locate#LocateFileClose() " {{{
+ if bufname(bufnr('%')) !~ '^\[Locate.*\]$'
+ let bufnr = bufnr('\[Locate in *\]')
+ let winnr = bufwinnr(bufnr)
+ if winnr != -1
+ let curbuf = bufnr('%')
+ exec winnr . 'winc w'
+ try
+ exec 'bw ' . b:results_bufnum
+ bw
+ autocmd! locate_file_init
+ stopinsert
+ finally
+ exec bufwinnr(curbuf) . 'winc w'
+ endtry
+ endif
+ endif
+endfunction " }}}
+
+function! s:LocateFileCompletionInit(action, scope, project, workspace) " {{{
+ let file = expand('%')
+ let bufnum = bufnr('%')
+ let winrestcmd = winrestcmd()
+
+ topleft 12split [Locate\ Results]
+ set filetype=locate_results
+ setlocal nonumber nowrap
+ setlocal noswapfile nobuflisted
+ setlocal buftype=nofile bufhidden=delete
+
+ let results_bufnum = bufnr('%')
+
+ let locate_in = (a:scope == 'project' ? a:project : a:scope)
+ exec 'topleft 1split ' . escape('[Locate in ' . locate_in . ']', ' -')
+ setlocal modifiable
+ call setline(1, '> ')
+ call cursor(1, col('$'))
+ set filetype=locate_prompt
+ syntax match Keyword /^>/
+ setlocal winfixheight
+ setlocal nonumber
+ setlocal nolist
+ setlocal noswapfile nobuflisted
+ setlocal buftype=nofile bufhidden=delete
+
+ let b:bufnum = bufnum
+ let b:project = a:project
+ let b:workspace = a:workspace
+ let b:scope = a:scope
+ let b:results_bufnum = results_bufnum
+ let b:help_bufnum = 0
+ let b:selection = 1
+ let b:winrestcmd = winrestcmd
+
+ set updatetime=300
+
+ augroup locate_file_init
+ autocmd!
+ autocmd BufEnter <buffer> nested startinsert! | let &updatetime = 300
+ autocmd BufLeave \[Locate*\]
+ \ call eclim#util#DelayedCommand('call eclim#common#locate#LocateFileClose()')
+ exec 'autocmd InsertLeave <buffer> ' .
+ \ 'let &updatetime = g:eclim_locate_default_updatetime | ' .
+ \ 'doautocmd BufWinLeave | bw | ' .
+ \ 'doautocmd BufWinLeave | bw ' . b:results_bufnum . ' | ' .
+ \ 'call eclim#util#GoToBufferWindow(' . b:bufnum . ') | ' .
+ \ 'doautocmd BufEnter | ' .
+ \ 'doautocmd WinEnter | ' .
+ \ winrestcmd
+ exec 'autocmd WinEnter <buffer=' . b:results_bufnum .'> '
+ \ 'exec bufwinnr(' . bufnr('%') . ') "winc w"'
+ augroup END
+
+ " enable completion after user starts typing
+ call s:LocateFileCompletionAutocmdDeferred()
+
+ imap <buffer> <silent> <tab> <c-r>=<SID>LocateFileSelection("n")<cr>
+ imap <buffer> <silent> <down> <c-r>=<SID>LocateFileSelection("n")<cr>
+ imap <buffer> <silent> <s-tab> <c-r>=<SID>LocateFileSelection("p")<cr>
+ imap <buffer> <silent> <up> <c-r>=<SID>LocateFileSelection("p")<cr>
+ exec 'imap <buffer> <silent> <cr> ' .
+ \ '<c-r>=<SID>LocateFileSelect("' . a:action . '")<cr>'
+ imap <buffer> <silent> <c-e> <c-r>=<SID>LocateFileSelect('edit')<cr>
+ imap <buffer> <silent> <c-s> <c-r>=<SID>LocateFileSelect('split')<cr>
+ imap <buffer> <silent> <c-t> <c-r>=<SID>LocateFileSelect("tablast \| tabnew")<cr>
+ imap <buffer> <silent> <c-l> <c-r>=<SID>LocateFileChangeScope()<cr>
+ imap <buffer> <silent> <c-h> <c-r>=<SID>LocateFileHelp()<cr>
+
+ startinsert!
+endfunction " }}}
+
+function! s:LocateFileCompletionAutocmd() " {{{
+ augroup locate_file
+ autocmd!
+ autocmd CursorHoldI <buffer> call eclim#common#locate#LocateFileCompletion()
+ augroup END
+endfunction " }}}
+
+function! s:LocateFileCompletionAutocmdDeferred() " {{{
+ augroup locate_file
+ autocmd!
+ autocmd CursorMovedI <buffer> call <SID>LocateFileCompletionAutocmd()
+ augroup END
+endfunction " }}}
+
+function! s:LocateFileSelection(sel) " {{{
+ " pause completion while tabbing though results
+ augroup locate_file
+ autocmd!
+ augroup END
+
+ let sel = a:sel
+ let prev_sel = b:selection
+
+ " bad hack for gvim on windows
+ let start_sel = b:start_selection
+ let double_defer = 0
+ if sel =~ '^[np]$' && (has('win32') || has('win64'))
+ let double_defer = b:start_selection == 1
+ let b:start_selection = 0
+ endif
+
+ let winnr = winnr()
+ noautocmd exec bufwinnr(b:results_bufnum) . 'winc w'
+
+ if sel == 'n'
+ let sel = prev_sel < line('$') ? prev_sel + 1 : 1
+ elseif sel == 'p'
+ let sel = prev_sel > 1 ? prev_sel - 1 : line('$')
+ endif
+
+ syntax clear
+ exec 'syntax match PmenuSel /\%' . sel . 'l.*/'
+ exec 'call cursor(' . sel . ', 1)'
+ let save_scrolloff = &scrolloff
+ let &scrolloff = 5
+ normal! zt
+ let &scrolloff = save_scrolloff
+
+ exec winnr . 'winc w'
+
+ exec 'let b:selection = ' . sel
+
+ if double_defer
+ augroup locate_file
+ autocmd!
+ autocmd CursorMovedI <buffer> call <SID>LocateFileCompletionAutocmdDeferred()
+ augroup END
+ else
+ call s:LocateFileCompletionAutocmdDeferred()
+ endif
+
+ return ''
+endfunction " }}}
+
+function! s:LocateFileSelect(action) " {{{
+ if exists('b:completions') && !empty(b:completions)
+ let &updatetime = g:eclim_locate_default_updatetime
+
+ let file = eclim#util#Simplify(b:completions[b:selection - 1].info)
+ if has('win32unix')
+ let file = eclim#cygwin#CygwinPath(file)
+ endif
+
+ let bufnum = b:bufnum
+ let winrestcmd = b:winrestcmd
+
+ " close locate windows
+ exec 'bdelete ' . b:results_bufnum
+ exec 'bdelete ' . bufnr('%')
+
+ " reset windows to pre-locate sizes
+ exec winrestcmd
+
+ " open the selected result
+ call eclim#util#GoToBufferWindow(bufnum)
+ call eclim#util#GoToBufferWindowOrOpen(file, a:action)
+ call feedkeys("\<esc>", 'n')
+ doautocmd WinEnter
+ endif
+ return ''
+endfunction " }}}
+
+function! s:LocateFileChangeScope() " {{{
+ if b:help_bufnum && bufexists(b:help_bufnum)
+ exec 'bdelete ' . b:help_bufnum
+ endif
+
+ let bufnr = bufnr('%')
+ let winnr = winnr()
+
+ " trigger [Locate] buffer's BufLeave autocmd before we leave the buffer
+ doautocmd BufLeave
+
+ noautocmd exec bufwinnr(b:results_bufnum) . 'winc w'
+ silent noautocmd exec '50vnew [Locate\ Scope]'
+
+ let b:locate_bufnr = bufnr
+ let b:locate_winnr = winnr
+ stopinsert
+ setlocal modifiable
+ call append(1, s:scopes + g:EclimLocateUserScopes)
+ 1,1delete _
+ call append(line('$'),
+ \ ['', '" <cr> - select a scope', '" <c-c>, <c-l>, or q - cancel'])
+ syntax match Comment /^".*/
+ setlocal nomodifiable
+ setlocal winfixheight
+ setlocal nonumber
+ setlocal nolist
+ setlocal noswapfile nobuflisted
+ setlocal buftype=nofile bufhidden=delete
+
+ nnoremap <buffer> <silent> <cr> :call <SID>ChooseScope()<cr>
+ nnoremap <buffer> <silent> q :call <SID>CloseScopeChooser()<cr>
+ nnoremap <buffer> <silent> <c-c> :call <SID>CloseScopeChooser()<cr>
+ nnoremap <buffer> <silent> <c-l> :call <SID>CloseScopeChooser()<cr>
+
+ autocmd BufLeave <buffer> call <SID>CloseScopeChooser()
+
+ return ''
+endfunction " }}}
+
+function! s:ChooseScope() " {{{
+ let scope = getline('.')
+ if scope =~ '^"\|^\s*$'
+ return
+ endif
+
+ let workspace = ''
+ let project = ''
+ let locate_in = scope
+
+ if scope == 'project'
+ let project = ''
+ let names = eclim#project#util#GetProjectNames()
+ let prompt = 'Choose a project (ctrl-c to cancel): '
+ while project == ''
+ let project = input(
+ \ prompt, '', 'customlist,eclim#project#util#CommandCompleteProject')
+ if project == ''
+ echo ''
+ return
+ endif
+
+ if !eclim#util#ListContains(names, project)
+ let prompt = "Project '" . project . "' not found (ctrl-c to cancel): "
+ let project = ''
+ endif
+ endwhile
+ let locate_in = project
+ let workspace = eclim#project#util#GetProjectWorkspace(project)
+
+ elseif scope == 'workspace'
+ let project = ''
+ let instance = eclim#client#nailgun#ChooseEclimdInstance()
+ if type(instance) != g:DICT_TYPE
+ return
+ endif
+ let workspace = instance.workspace
+ endif
+
+ call s:CloseScopeChooser()
+
+ let b:scope = scope
+ let b:project = project
+ let b:workspace = workspace != '' ? workspace : b:workspace
+
+ exec 'file ' . escape('[Locate in ' . locate_in . ']', ' ')
+
+ call eclim#common#locate#LocateFileCompletion()
+endfunction " }}}
+
+function! s:CloseScopeChooser() " {{{
+ let winnum = b:locate_winnr
+ bwipeout
+ exec winnum . 'winc w'
+
+ " hack to make :q work like the other close mappings
+ doautocmd BufEnter
+ " if we end up in a non-Locate window, make sure everything is as it should
+ " be (a hack for the above hack).
+ augroup locate_file_chooser_hack
+ autocmd!
+ autocmd BufEnter *
+ \ if bufname('%') !~ '^\[Locate in .*\]$' |
+ \ call eclim#common#locate#LocateFileClose() |
+ \ endif |
+ \ autocmd! locate_file_chooser_hack
+ augroup END
+endfunction " }}}
+
+function! s:LocateFileHelp() " {{{
+ let winnr = winnr()
+ noautocmd exec bufwinnr(b:results_bufnum) . 'winc w'
+ let help_bufnum = eclim#help#BufferHelp(s:help, 'vertical', 50)
+ exec winnr . 'winc w'
+ let b:help_bufnum = help_bufnum
+
+ return ''
+endfunction " }}}
+
+function! s:LocateFileConvertPattern(pattern, fuzzy) " {{{
+ let pattern = a:pattern
+
+ if a:fuzzy
+ let pattern = '.*' . substitute(pattern, '\(.\)', '\1.*?', 'g')
+ let pattern = substitute(pattern, '\.\([^*]\)', '\\.\1', 'g')
+ else
+ " if the user supplied a path, prepend a '.*/' to it so that they don't need
+ " to type full paths to match.
+ if pattern =~ '.\+/'
+ let pattern = '.*/' . pattern
+ endif
+ let pattern = substitute(pattern, '\*\*', '.*', 'g')
+ let pattern = substitute(pattern, '\(^\|\([^.]\)\)\*', '\1[^/]*?', 'g')
+ let pattern = substitute(pattern, '\.\([^*]\)', '\\.\1', 'g')
+ "let pattern = substitute(pattern, '\([^*]\)?', '\1.', 'g')
+ let pattern .= '.*'
+ endif
+
+ return pattern
+endfunction " }}}
+
+function! s:LocateFileFunction(scope) " {{{
+ if eclim#util#ListContains(s:scopes, a:scope)
+ return function('s:LocateFile_' . a:scope)
+ endif
+ return function('LocateFile_' . a:scope)
+endfunction " }}}
+
+function! s:LocateFileCommand(pattern) " {{{
+ let command = s:command_locate
+ if g:EclimLocateFileCaseInsensitive == 'always' ||
+ \ (a:pattern !~# '[A-Z]' && g:EclimLocateFileCaseInsensitive != 'never')
+ let command .= ' -i'
+ endif
+ let command .= ' -p "' . a:pattern . '"'
+ return command
+endfunction " }}}
+
+function! s:LocateFile_workspace(pattern) " {{{
+ let command = substitute(s:LocateFileCommand(a:pattern), '<scope>', 'workspace', '')
+ let results = eclim#Execute(command, {'workspace': b:workspace})
+ if type(results) != g:LIST_TYPE
+ return []
+ endif
+ return results
+endfunction " }}}
+
+function! s:LocateFile_project(pattern) " {{{
+ let command = substitute(s:LocateFileCommand(a:pattern), '<scope>', 'project', '')
+ let command .= ' -n "' . b:project . '"'
+ let results = eclim#Execute(command, {'workspace': b:workspace})
+ if type(results) != g:LIST_TYPE
+ return []
+ endif
+ return results
+endfunction " }}}
+
+function! s:LocateFile_buffers(pattern) " {{{
+ redir => list
+ silent exec 'buffers'
+ redir END
+
+ let buffers = map(split(list, '\n'),
+ \ "substitute(v:val, '.\\{-}\"\\(.\\{-}\\)\".*', '\\1', '')")
+ if a:pattern =~ '/'
+ let buffers = map(buffers, "fnamemodify(v:val, ':p')")
+ endif
+
+ if len(buffers) > 0
+ let tempfile = substitute(tempname(), '\', '/', 'g')
+ call writefile(buffers, tempfile)
+ try
+ return eclim#common#locate#LocateFileFromFileList(a:pattern, tempfile)
+ finally
+ call delete(tempfile)
+ endtry
+ endif
+ return []
+endfunction " }}}
+
+function! s:LocateFile_quickfix(pattern) " {{{
+ let buffers = []
+ let prev = ''
+ for entry in getqflist()
+ let name = bufname(entry.bufnr)
+ if a:pattern =~ '/'
+ let name = fnamemodify(name, ':p')
+ endif
+ if name != prev
+ call add(buffers, name)
+ let prev = name
+ endif
+ endfor
+
+ if len(buffers) > 0
+ let tempfile = substitute(tempname(), '\', '/', 'g')
+ call writefile(buffers, tempfile)
+ try
+ return eclim#common#locate#LocateFileFromFileList(a:pattern, tempfile)
+ finally
+ call delete(tempfile)
+ endtry
+ endif
+ return []
+endfunction " }}}
+
+function! eclim#common#locate#LocateFileFromFileList(pattern, file) " {{{
+ let file = a:file
+ if has('win32unix')
+ let file = eclim#cygwin#WindowsPath(file)
+ endif
+ if eclim#EclimAvailable(0)
+ let command = substitute(s:LocateFileCommand(a:pattern), '<scope>', 'list', '')
+ let command .= ' -f "' . file . '"'
+ let results = eclim#Execute(command, {'workspace': b:workspace})
+ if type(results) != g:LIST_TYPE
+ return []
+ endif
+ else
+ let results = []
+ for result in readfile(file)
+ call add(results, {'name': fnamemodify(result, ':t'), 'path': result})
+ endfor
+ endif
+
+ return results
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/common/template.vim b/vim/eclim/autoload/eclim/common/template.vim
@@ -0,0 +1,237 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists("g:EclimTemplateDir")
+ let g:EclimTemplateDir = g:EclimBaseDir . '/template'
+endif
+if !exists("g:EclimTemplateExtension")
+ let g:EclimTemplateExtension = '.vim'
+endif
+if !exists("g:EclimTemplateIgnore")
+ let g:EclimTemplateIgnore = []
+endif
+" }}}
+
+" Script Variables {{{
+let s:quote = "['\"]"
+let s:tag_regex =
+ \ '<vim:[a-zA-Z]\+\(\s\+[a-zA-Z]\+\s*=\s*' . s:quote . '.*' . s:quote . '\)\?\s*/>'
+let s:tagname_regex = '.\{-}<vim:\([a-zA-Z]\+\).*'
+" }}}
+
+" Template() {{{
+" Main method for finding and executing the template.
+function! eclim#common#template#Template()
+ " allow some plugins to disable templates temporarily
+ if exists('g:EclimTemplateTempIgnore') && g:EclimTemplateTempIgnore
+ return
+ endif
+
+ " ignore certain file patterns
+ for ignore in g:EclimTemplateIgnore
+ if expand('%') =~ ignore
+ return
+ endif
+ endfor
+
+ let template = s:FindTemplate()
+ if template != ''
+ let lines = readfile(template)
+ call s:ExecuteTemplate(lines)
+ 1,1delete _
+ endif
+endfunction " }}}
+
+" s:FindTemplate() {{{
+" Finds the template file and returns the location.
+function! s:FindTemplate()
+ let templatesDir = expand(g:EclimTemplateDir)
+ if !isdirectory(templatesDir)
+ call eclim#util#EchoDebug(
+ \ 'Template dir not found (g:EclimTemplateDir): ' . templatesDir)
+ return ''
+ endif
+
+ let filename = expand('%:t')
+ let ext = ""
+
+ " template equal to the filename
+ if filereadable(templatesDir . '/' . filename . g:EclimTemplateExtension)
+ return templatesDir . '/' . filename . g:EclimTemplateExtension
+ endif
+
+ " template pattern
+ let templates = globpath(templatesDir, '*' . g:EclimTemplateExtension)
+ for template in split(templates, '\n')
+ " remove path info
+ let temp_template = substitute(template, '.*[/\\]', '', '')
+ if g:EclimTemplateExtension != ''
+ let temp_template =
+ \ strpart(temp_template, 0, stridx(temp_template, g:EclimTemplateExtension))
+ endif
+
+ while stridx(temp_template, '.') != -1
+ let ext = strpart(temp_template, stridx(temp_template, '.'))
+ let temp_template = strpart(temp_template, 0, stridx(temp_template, '.'))
+ if filename =~ '.*' . temp_template . '.*' . ext
+ return template
+ endif
+ endwhile
+ endfor
+
+ " template equal to file extension
+ if stridx(filename, '.') > 0
+ let ext = strpart(filename, stridx(filename, '.'))
+ while stridx(ext, '.') != -1
+ let ext = strpart(ext, stridx(ext, '.') + 1)
+ if filereadable(templatesDir . '/' . ext . g:EclimTemplateExtension)
+ return templatesDir . '/' . ext . g:EclimTemplateExtension
+ endif
+ endwhile
+ endif
+
+ " template equal to file type
+ if filereadable(templatesDir . '/' . &ft . g:EclimTemplateExtension)
+ return templatesDir . '/' . &ft . g:EclimTemplateExtension
+ endif
+
+ return ''
+endfunction " }}}
+
+" s:ExecuteTemplate(lines) {{{
+" Executes any logic in the supplied lines and appends those lines to the
+" current file.
+function! s:ExecuteTemplate(lines)
+ for line in a:lines
+ if line =~ s:tag_regex
+ let tag = substitute(line, s:tagname_regex, '\1', '')
+ call s:ExecuteTemplate(s:Process_{tag}(line))
+ else
+ call append(line('$'), line)
+ endif
+ endfor
+endfunction " }}}
+
+" s:EvaluateExpression(expression) {{{
+" Evaluates the supplied expression.
+function! s:EvaluateExpression(expression)
+ exec "return " . a:expression
+endfunction " }}}
+
+" s:GetAttribute(line, tag, attribute, fail) {{{
+" Gets the an attribute value.
+function! s:GetAttribute(line, tag, attribute, fail)
+ let attribute = substitute(a:line,
+ \ '.\{-}<vim:' . a:tag . '.\{-}\s\+' . a:attribute .
+ \ '\s*=\s*\(' . s:quote . '\)\(.\{-}\)\1.*/>.*',
+ \ '\2', '')
+
+ if attribute == a:line
+ if a:fail
+ call s:TemplateError(
+ \ a:line, "syntax error - missing '" . a:attribute . "' attribute")
+ endif
+ return ""
+ endif
+ return attribute
+endfunction " }}}
+
+" s:TemplateError(line, message) {{{
+" Echos an error message to the user.
+function! s:TemplateError(line, message)
+ call eclim#util#EchoError("Template error, line " . a:line . ": " . a:message)
+endfunction " }}}
+
+" s:Process_var(line) {{{
+" Process <vim:var/> tags.
+function! s:Process_var(line)
+ let name = expand(s:GetAttribute(a:line, 'var', 'name', 1))
+ let value = expand(s:GetAttribute(a:line, 'var', 'value', 1))
+
+ exec "let " . name . " = \"" . s:EvaluateExpression(value) . "\""
+
+ return []
+endfunction " }}}
+
+" s:Process_import(line) {{{
+" Process <vim:import/> tags.
+function! s:Process_import(line)
+ let resource = expand(s:GetAttribute(a:line, 'import', 'resource', 1))
+ if resource !~ '^/\'
+ let resource = expand(g:EclimTemplateDir . '/' . resource)
+ endif
+
+ if !filereadable(resource)
+ call s:TemplateError(a:line, "resource not found '" . resource . "'")
+ endif
+
+ exec "source " . resource
+
+ return []
+endfunction " }}}
+
+" s:Process_out(line) {{{
+" Process <vim:out/> tags.
+function! s:Process_out(line)
+ let value = s:GetAttribute(a:line, 'out', 'value', 1)
+ let result = s:EvaluateExpression(value)
+ return s:Out(a:line, '<vim:out\s\+.\{-}\s*\/>', result)
+endfunction " }}}
+
+" s:Process_include(line) {{{
+" Process <vim:include/> tags.
+function! s:Process_include(line)
+ let template = expand(
+ \ g:EclimTemplateDir . '/' . s:GetAttribute(a:line, 'include', 'template', 1))
+
+ if !filereadable(template)
+ call s:TemplateError(a:line, "template not found '" . template . "'")
+ return []
+ endif
+
+ return readfile(template)
+endfunction " }}}
+
+" s:Process_username(line) {{{
+" Process <vim:username/> tags.
+function! s:Process_username(line)
+ silent! let username = eclim#project#util#GetProjectSetting('org.eclim.user.name')
+ if type(username) == g:NUMBER_TYPE
+ let username = ''
+ endif
+ return s:Out(a:line, '<vim:username\s*\/>', username)
+endfunction " }}}
+
+" s:Out(line, pattern, value) {{{
+function! s:Out(line, pattern, value)
+ let results = type(a:value) == g:LIST_TYPE ? a:value : [a:value]
+ if results[0] == '' && a:line =~ '^\s*' . a:pattern . '\s*$'
+ return []
+ endif
+
+ let line = substitute(a:line, a:pattern, results[0], '')
+ return [line] + (len(results) > 1 ? results[1:] : [])
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/common/util.vim b/vim/eclim/autoload/eclim/common/util.vim
@@ -0,0 +1,195 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Various functions that are useful in and out of eclim.
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+let s:command_read = '-command archive_read -f "<file>"'
+" }}}
+
+" DiffLastSaved() {{{
+" Diff a modified file with the last saved version.
+function! eclim#common#util#DiffLastSaved()
+ if &modified
+ let winnum = winnr()
+ let filetype=&ft
+ vertical botright new | r #
+ 1,1delete _
+
+ diffthis
+ setlocal buftype=nofile
+ setlocal bufhidden=wipe
+ setlocal nobuflisted
+ setlocal noswapfile
+ setlocal readonly
+ exec "setlocal ft=" . filetype
+ let diffnum = winnr()
+
+ augroup diff_saved
+ autocmd! BufUnload <buffer>
+ autocmd BufUnload <buffer> :diffoff!
+ augroup END
+
+ exec winnum . "winc w"
+ diffthis
+
+ " for some reason, these settings only take hold if set here.
+ call setwinvar(diffnum, "&foldmethod", "diff")
+ call setwinvar(diffnum, "&foldlevel", "0")
+ else
+ echo "No changes"
+ endif
+endfunction " }}}
+
+" SwapTypedArguments() {{{
+" Swaps typed method declaration arguments.
+function! eclim#common#util#SwapTypedArguments()
+ " FIXME: add validation to see if user is executing on a valid position.
+ normal! w
+ SwapWords
+ normal! b
+ SwapWords
+ normal! www
+ SwapWords
+ normal! bb
+ SwapWords
+ normal! b
+endfunction " }}}
+
+" SwapWords() {{{
+" Initially based on http://www.vim.org/tips/tip.php?tip_id=329
+function! eclim#common#util#SwapWords()
+ " save the last search pattern
+ let save_search = @/
+
+ normal! "_yiw
+ s/\(\%#\w\+\)\(\_W\+\)\(\w\+\)/\3\2\1/
+ exec "normal! \<C-O>"
+
+ " restore the last search pattern
+ let @/ = save_search
+
+ silent! call repeat#set(":call eclim#common#util#SwapWords()\<cr>", v:count)
+endfunction " }}}
+
+" Tcd(dir) {{{
+" Like vim's :lcd, but tab local instead of window local.
+function! eclim#common#util#Tcd(dir)
+ let t:cwd = fnamemodify(a:dir, ':p')
+
+ " initialize the tab cwd for all other tabs if not already set
+ let curtab = tabpagenr()
+ try
+ let index = 1
+ while index <= tabpagenr('$')
+ if index != curtab
+ exec 'tabn ' . index
+ if !exists('t:cwd')
+ let t:cwd = getcwd()
+ " try to find a window without a localdir if necessary
+ if haslocaldir()
+ let curwin = winnr()
+ let windex = 1
+ while windex <= winnr('$')
+ if windex != curwin
+ exec windex . 'winc w'
+ if !haslocaldir()
+ let t:cwd = getcwd()
+ break
+ endif
+ endif
+ let windex += 1
+ endwhile
+ exec curwin . 'winc w'
+ endif
+ endif
+ endif
+ let index += 1
+ endwhile
+ finally
+ exec 'tabn ' . curtab
+ endtry
+
+ call s:ApplyTcd(0)
+
+ augroup tcd
+ autocmd!
+ autocmd TabEnter * call <SID>ApplyTcd(1)
+ augroup END
+endfunction " }}}
+
+" s:ApplyTcd(honor_lcd) {{{
+function! s:ApplyTcd(honor_lcd)
+ if !exists('t:cwd')
+ return
+ endif
+
+ if a:honor_lcd && haslocaldir()
+ let lcwd = getcwd()
+ exec 'cd ' . escape(t:cwd, ' ')
+ exec 'lcd ' . escape(lcwd, ' ')
+ else
+ exec 'cd ' . escape(t:cwd, ' ')
+ endif
+endfunction " }}}
+
+" ReadFile() {{{
+" Reads the contents of an archived file.
+function! eclim#common#util#ReadFile()
+ let archive = substitute(expand('%'), '\', '/', 'g')
+ let command = substitute(s:command_read, '<file>', archive, '')
+
+ let file = eclim#Execute(command)
+
+ if string(file) != '0'
+ let project = exists('b:eclim_project') ? b:eclim_project : ''
+ let bufnum = bufnr('%')
+ if has('win32unix')
+ let file = eclim#cygwin#CygwinPath(file)
+ endif
+ silent exec "keepalt keepjumps edit! " . escape(file, ' ')
+ if project != ''
+ let b:eclim_project = project
+ let b:eclim_file = archive
+ endif
+
+ exec 'bdelete ' . bufnum
+
+ " alternate solution, that keeps the archive url as the buffer's filename,
+ " but prevents taglist from being able to parse tags.
+ "setlocal noreadonly
+ "setlocal modifiable
+ "silent! exec "read " . file
+ "1,1delete _
+
+ silent exec "doautocmd BufReadPre " . file
+ silent exec "doautocmd BufReadPost " . file
+
+ setlocal readonly
+ setlocal nomodifiable
+ setlocal noswapfile
+ " causes taglist.vim errors (fold then delete fails)
+ "setlocal bufhidden=delete
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/css/complete.vim b/vim/eclim/autoload/eclim/css/complete.vim
@@ -0,0 +1,95 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/css/complete.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Varables {{{
+ let s:complete_command =
+ \ '-command css_complete -p "<project>" -f "<file>" -o <offset> -e <encoding>'
+" }}}
+
+" CodeComplete(findstart, base) {{{
+" Handles css code completion.
+function! eclim#css#complete#CodeComplete(findstart, base)
+ if !eclim#project#util#IsCurrentFileInProject(0)
+ return a:findstart ? -1 : []
+ endif
+
+ if a:findstart
+ call eclim#lang#SilentUpdate(1)
+
+ " locate the start of the word
+ let line = getline('.')
+
+ let start = col('.') - 1
+
+ while start > 0 && line[start - 1] =~ '[[:alnum:]_-]'
+ let start -= 1
+ endwhile
+
+ return start
+ else
+ let offset = eclim#util#GetOffset() + len(a:base)
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#lang#SilentUpdate(1, 0)
+ if file == ''
+ return []
+ endif
+
+ let command = s:complete_command
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+
+ let completions = []
+ let results = eclim#Execute(command)
+ if type(results) != g:LIST_TYPE
+ return
+ endif
+
+ let filter = 0
+ for result in results
+ let word = result.completion
+ if word =~ '^:'
+ let word = strpart(word, 1)
+ let filter = 1
+ endif
+
+ let menu = result.menu
+ let info = result.info
+
+ let dict = {'word': tolower(word), 'menu': menu, 'info': info}
+
+ call add(completions, dict)
+ endfor
+
+ " eclipse doesn't filter out :results properly.
+ if filter
+ call filter(completions, 'v:val.word =~ "^" . a:base')
+ endif
+
+ return completions
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/css/validate.vim b/vim/eclim/autoload/eclim/css/validate.vim
@@ -0,0 +1,51 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/css/validate.html
+"
+" License:
+"
+" Copyright (C) 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+function! eclim#css#validate#Filter(errors) " {{{
+ let results = []
+ let ignore_next_parse_error = 0
+ for error in a:errors
+ " ignore errors related to browser targeted properties
+ if error.text =~ '\(^\|\s\)-\(moz\|webkit\|khtml\|o\)-\w\+\>'
+ continue
+ endif
+
+ " ignore errors on IE filter property line
+ if getline(error.lnum) =~ '^\s*filter:\s*progid'
+ " next parse error will be because of this filter
+ let ignore_next_parse_error = 1
+ continue
+ endif
+ if error.text == 'Parse Error' && ignore_next_parse_error
+ let ignore_next_parse_error = 0
+ continue
+ endif
+
+ call add(results, error)
+ endfor
+
+ return results
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/cygwin.vim b/vim/eclim/autoload/eclim/cygwin.vim
@@ -0,0 +1,60 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Utility functions for cygwin usage.
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+function! eclim#cygwin#CygwinPath(path) " {{{
+ return s:Cygpath(a:path, 'cygwin')
+endfunction " }}}
+
+function! eclim#cygwin#WindowsPath(path) " {{{
+ if type(a:path) == g:STRING_TYPE && a:path =~? '^[a-z]:'
+ return substitute(a:path, '\', '/', 'g')
+ endif
+ return s:Cygpath(a:path, 'windows')
+endfunction " }}}
+
+function! eclim#cygwin#WindowsHome() " {{{
+ if !exists('s:cygpath_winhome')
+ let dir = s:Cygpath('-D', 'cygwin')
+ let s:cygpath_winhome = dir != '-D' ? fnamemodify(dir, ':h') : ''
+ endif
+ return s:cygpath_winhome
+endfunction " }}}
+
+function! s:Cygpath(paths, type) " {{{
+ if executable('cygpath')
+ let paths = type(a:paths) == g:LIST_TYPE ? a:paths : [a:paths]
+ let paths = map(paths, "'\"' . substitute(v:val, '\\', '/', 'g') . '\"'")
+
+ let args = a:type == 'windows' ? '-m ' : ''
+ let results = split(eclim#util#System('cygpath ' . args . join(paths)), "\n")
+
+ if type(a:paths) == g:LIST_TYPE
+ return results
+ endif
+ return results[0]
+ endif
+ return a:paths
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/display/menu.vim b/vim/eclim/autoload/eclim/display/menu.vim
@@ -0,0 +1,103 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Plugin to generate gvim eclim menus.
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+
+let s:eclim_menus_root = []
+let s:eclim_menus = {}
+
+" }}}
+
+" Generate() {{{
+" Generate gvim menu items for available eclim commands.
+function! eclim#display#menu#Generate()
+ " check that the menu bar is enabled or that we are running in a mac gui where
+ " the menu bar always exists regardless of guioptions
+ if &guioptions !~ 'm' && !has('gui_macvim')
+ if exists('b:eclim_menus')
+ unlet b:eclim_menus
+ endif
+ return
+ endif
+
+ redir => commands
+ silent exec 'command'
+ redir END
+
+ if !exists('b:eclim_menus')
+ let b:eclim_menus = {}
+
+ let pattern = '\<eclim#'
+ if len(s:eclim_menus_root) != 0
+ let pattern = '^..b.*\<eclim#'
+ endif
+
+ for cmd in split(commands, '\n')
+ if cmd =~ pattern
+ let name = substitute(cmd, '....\(\w\+\)\s.*', '\1', '')
+ if cmd =~ '\<eclim#[A-Z]'
+ if index(s:eclim_menus_root, name) == -1
+ call add(s:eclim_menus_root, name)
+ endif
+ else
+ let group = substitute(cmd, '.\{-}\<eclim#\(\w\+\)#.*', '\1', '')
+ let var = cmd =~ '^..b' ? 'b:eclim_menus' : 's:eclim_menus'
+ if !has_key({var}, group)
+ let {var}[group] = []
+ endif
+ if index({var}[group], name) == -1
+ call add({var}[group], name)
+ endif
+ endif
+ endif
+ endfor
+
+ call sort(s:eclim_menus_root)
+ endif
+
+ silent! unmenu &Plugin.eclim
+
+ " merge non-buffer items with buffer items
+ let menus = deepcopy(s:eclim_menus, 1)
+ for group in keys(b:eclim_menus)
+ if !has_key(menus, group)
+ let menus[group] = []
+ endif
+ for name in b:eclim_menus[group]
+ call add(menus[group], name)
+ endfor
+ endfor
+
+ for name in s:eclim_menus_root
+ exec 'menu &Plugin.eclim.' . name . ' :' . name . ' '
+ endfor
+
+ for group in sort(keys(menus))
+ for name in sort(menus[group])
+ exec 'menu &Plugin.eclim.' . group . '.' . name . ' :' . name . ' '
+ endfor
+ endfor
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/display/signs.vim b/vim/eclim/autoload/eclim/display/signs.vim
@@ -0,0 +1,388 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Functions for working with vim signs.
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists("g:EclimShowQuickfixSigns")
+ let g:EclimShowQuickfixSigns = 1
+endif
+
+if !exists("g:EclimShowLoclistSigns")
+ let g:EclimShowLoclistSigns = 1
+endif
+
+if !exists("g:EclimQuickfixSignText")
+ let g:EclimQuickfixSignText = '> '
+endif
+
+if !exists("g:EclimLoclistSignText")
+ let g:EclimLoclistSignText = '>>'
+endif
+
+if !exists("g:EclimUserSignText")
+ let g:EclimUserSignText = '#'
+endif
+
+if !exists("g:EclimUserSignHighlight")
+ let g:EclimUserSignHighlight = g:EclimInfoHighlight
+endif
+" }}}
+
+function! eclim#display#signs#Define(name, text, highlight) " {{{
+ " Defines a new sign name or updates an existing one.
+ exec "sign define " . a:name . " text=" . a:text . " texthl=" . a:highlight
+endfunction " }}}
+
+function! eclim#display#signs#Place(name, line) " {{{
+ " Places a sign in the current buffer.
+ if a:line > 0
+ let lastline = line('$')
+ let line = a:line <= lastline ? a:line : lastline
+ let id = a:name == 'placeholder' ? 999999 : line
+ exec "sign place " . id . " line=" . line . " name=" . a:name .
+ \ " buffer=" . bufnr('%')
+ endif
+endfunction " }}}
+
+function! eclim#display#signs#PlaceAll(name, list) " {{{
+ " Places a sign in the current buffer for each line in the list.
+
+ let lastline = line('$')
+ for line in a:list
+ if line > 0
+ let line = line <= lastline ? line : lastline
+ exec "sign place " . line . " line=" . line . " name=" . a:name .
+ \ " buffer=" . bufnr('%')
+ endif
+ endfor
+endfunction " }}}
+
+function! eclim#display#signs#Undefine(name) " {{{
+ " Undefines a sign name.
+ exec "sign undefine " . a:name
+endfunction " }}}
+
+function! eclim#display#signs#Unplace(id) " {{{
+ " Un-places a sign in the current buffer.
+ exec 'sign unplace ' . a:id . ' buffer=' . bufnr('%')
+endfunction " }}}
+
+function! eclim#display#signs#UnplaceAll(list) " {{{
+ " Un-places all signs in the supplied list from the current buffer.
+ " The list may be a list of ids or a list of dictionaries as returned by
+ " GetExisting()
+
+ for sign in a:list
+ if type(sign) == g:DICT_TYPE
+ call eclim#display#signs#Unplace(sign['id'])
+ else
+ call eclim#display#signs#Unplace(sign)
+ endif
+ endfor
+endfunction " }}}
+
+function! eclim#display#signs#Toggle(name, line) " {{{
+ if !g:EclimSignLevel
+ call eclim#util#Echo('Eclim signs have been disabled.')
+ return
+ endif
+
+ " Toggle a sign on the current line.
+ if a:line > 0
+ let existing = eclim#display#signs#GetExisting(a:name)
+ let exists = len(filter(existing, "v:val['line'] == a:line"))
+ if exists
+ call eclim#display#signs#Unplace(a:line)
+ else
+ call eclim#display#signs#Place(a:name, a:line)
+ endif
+ endif
+endfunction " }}}
+
+function! s:CompareSigns(s1, s2) " {{{
+ " Used by ViewSigns to sort list of sign dictionaries.
+
+ if a:s1.line == a:s2.line
+ return 0
+ endif
+ if a:s1.line > a:s2.line
+ return 1
+ endif
+ return -1
+endfunction " }}}
+
+function! eclim#display#signs#ViewSigns(name) " {{{
+ " Open a window to view all placed signs with the given name in the current
+ " buffer.
+
+ if !g:EclimSignLevel
+ call eclim#util#Echo('Eclim signs have been disabled.')
+ return
+ endif
+
+ let filename = expand('%:p')
+ let signs = eclim#display#signs#GetExisting(a:name)
+ call sort(signs, 's:CompareSigns')
+ let content = map(signs, "v:val.line . '|' . getline(v:val.line)")
+
+ call eclim#util#TempWindow('[Sign List]', content)
+
+ set ft=qf
+ nnoremap <silent> <buffer> <cr> :call <SID>JumpToSign()<cr>
+
+ " Store filename so that plugins can use it if necessary.
+ let b:filename = filename
+ augroup temp_window
+ autocmd! BufWinLeave <buffer>
+ call eclim#util#GoToBufferWindowRegister(filename)
+ augroup END
+endfunction " }}}
+
+function! s:JumpToSign() " {{{
+ let winnr = bufwinnr(bufnr('^' . b:filename))
+ if winnr != -1
+ let line = substitute(getline('.'), '^\(\d\+\)|.*', '\1', '')
+ exec winnr . "winc w"
+ call cursor(line, 1)
+ endif
+endfunction " }}}
+
+function! eclim#display#signs#GetDefined() " {{{
+ " Gets a list of defined sign names.
+
+ redir => list
+ silent exec 'sign list'
+ redir END
+
+ let names = []
+ for name in split(list, '\n')
+ let name = substitute(name, 'sign\s\(.\{-}\)\s.*', '\1', '')
+ call add(names, name)
+ endfor
+ return names
+endfunction " }}}
+
+function! eclim#display#signs#GetExisting(...) " {{{
+ " Gets a list of existing signs for the current buffer.
+ " The list consists of dictionaries with the following keys:
+ " id: The sign id.
+ " line: The line number.
+ " name: The sign name (erorr, warning, etc.)
+ "
+ " Optionally a sign name may be supplied to only retrieve signs of that name.
+
+ if !has('signs') || !g:EclimSignLevel
+ return []
+ endif
+
+ let bufnr = bufnr('%')
+
+ redir => signs
+ silent exec 'sign place buffer=' . bufnr
+ redir END
+
+ let existing = []
+ for line in split(signs, '\n')
+ if line =~ '.\{-}=.\{-}=' " only two equals to account for swedish output
+ call add(existing, s:ParseSign(line))
+ endif
+ endfor
+
+ if len(a:000) > 0
+ call filter(existing, "v:val['name'] == a:000[0]")
+ endif
+
+ return existing
+endfunction " }}}
+
+function! eclim#display#signs#HasExisting(...) " {{{
+ " Determines if there are any existing signs.
+ " Optionally a sign name may be supplied to only test for signs of that name.
+
+ if !has('signs') || !g:EclimSignLevel
+ return 0
+ endif
+
+ let bufnr = bufnr('%')
+
+ redir => results
+ silent exec 'sign place buffer=' . bufnr
+ redir END
+
+ for line in split(results, '\n')
+ if line =~ '.\{-}=.\{-}=' " only two equals to account for swedish output
+ if len(a:000) == 0
+ return 1
+ endif
+ let sign = s:ParseSign(line)
+ if sign.name == a:000[0]
+ return 1
+ endif
+ endif
+ endfor
+
+ return 0
+endfunction " }}}
+
+function! s:ParseSign(raw) " {{{
+ let attrs = split(a:raw)
+
+ exec 'let line = ' . split(attrs[0], '=')[1]
+
+ let id = split(attrs[1], '=')[1]
+ " hack for the italian localization
+ if id =~ ',$'
+ let id = id[:-2]
+ endif
+
+ " hack for the swedish localization
+ if attrs[2] =~ '^namn'
+ let name = substitute(attrs[2], 'namn=\?', '', '')
+ else
+ let name = split(attrs[2], '=')[1]
+ endif
+
+ return {'id': id, 'line': line, 'name': name}
+endfunction " }}}
+
+function! eclim#display#signs#Update() " {{{
+ " Updates the signs for the current buffer. This function will read both the
+ " location list and the quickfix list and place a sign for any entries for the
+ " current file.
+ " This function supports a severity level by examining the 'type' key of the
+ " dictionaries in the location or quickfix list. It supports 'i' (info), 'w'
+ " (warning), and 'e' (error).
+
+ if !has('signs') || !g:EclimSignLevel || &ft == 'qf'
+ return
+ endif
+
+ let save_lazy = &lazyredraw
+ set lazyredraw
+
+ let placeholder = eclim#display#signs#SetPlaceholder()
+
+ " remove all existing signs
+ let existing = eclim#display#signs#GetExisting()
+ for exists in existing
+ if exists.name =~ '^\(qf_\)\?\(error\|info\|warning\)$'
+ call eclim#display#signs#Unplace(exists.id)
+ endif
+ endfor
+
+ let qflist = filter(g:EclimShowQuickfixSigns ? getqflist() : [],
+ \ 'bufnr("%") == v:val.bufnr')
+ let show_loclist = g:EclimShowLoclistSigns && exists('b:eclim_loclist')
+ let loclist = filter(show_loclist ? getloclist(0) : [],
+ \ 'bufnr("%") == v:val.bufnr')
+
+ for [list, marker, prefix] in [
+ \ [qflist, g:EclimQuickfixSignText, 'qf_'],
+ \ [loclist, g:EclimLoclistSignText, '']]
+ if g:EclimSignLevel >= 4
+ let info = filter(copy(list), 'v:val.type == "" || tolower(v:val.type) == "i"')
+ call eclim#display#signs#Define(prefix . 'info', marker, g:EclimInfoHighlight)
+ call eclim#display#signs#PlaceAll(prefix . 'info', map(info, 'v:val.lnum'))
+ endif
+
+ if g:EclimSignLevel >= 3
+ let warnings = filter(copy(list), 'tolower(v:val.type) == "w"')
+ call eclim#display#signs#Define(prefix . 'warning', marker, g:EclimWarningHighlight)
+ call eclim#display#signs#PlaceAll(prefix . 'warning', map(warnings, 'v:val.lnum'))
+ endif
+
+ if g:EclimSignLevel >= 2
+ let errors = filter(copy(list), 'tolower(v:val.type) == "e"')
+ call eclim#display#signs#Define(prefix . 'error', marker, g:EclimErrorHighlight)
+ call eclim#display#signs#PlaceAll(prefix . 'error', map(errors, 'v:val.lnum'))
+ endif
+ endfor
+
+ if placeholder
+ call eclim#display#signs#RemovePlaceholder()
+ endif
+
+ let &lazyredraw = save_lazy
+endfunction " }}}
+
+function! eclim#display#signs#QuickFixCmdPost() " {{{
+ " Force 'make' results to be of type error if no type set.
+ if expand('<amatch>') == 'make'
+ let newentries = []
+ for entry in getqflist()
+ if entry['type'] == ''
+ let entry['type'] = 'e'
+ endif
+ call add(newentries, entry)
+ endfor
+ call setqflist(newentries, 'r')
+ endif
+ call eclim#display#signs#Update()
+ redraw!
+endfunction " }}}
+
+function! eclim#display#signs#SetPlaceholder(...) " {{{
+ " Set sign at line 1 to prevent sign column from collapsing, and subsiquent
+ " screen redraw.
+ " Optional args:
+ " only_if_necessary: if 1, only set a placeholder if there are no existing
+ " signs
+
+ if !has('signs') || !g:EclimSignLevel
+ return
+ endif
+
+ if len(a:000) > 0 && a:000[0]
+ let existing = eclim#display#signs#GetExisting()
+ if !len(existing)
+ return
+ endif
+ endif
+
+ call eclim#display#signs#Define('placeholder', '_ ', g:EclimInfoHighlight)
+ let existing = eclim#display#signs#GetExisting('placeholder')
+ if len(existing) == 0 && eclim#display#signs#HasExisting()
+ call eclim#display#signs#Place('placeholder', 1)
+ return 1
+ endif
+ return
+endfunction " }}}
+
+function! eclim#display#signs#RemovePlaceholder() " {{{
+ if !has('signs') || !g:EclimSignLevel
+ return
+ endif
+
+ let existing = eclim#display#signs#GetExisting('placeholder')
+ for exists in existing
+ call eclim#display#signs#Unplace(exists.id)
+ endfor
+endfunction " }}}
+
+" define signs for manually added user marks.
+if has('signs')
+ call eclim#display#signs#Define(
+ \ 'user', g:EclimUserSignText, g:EclimUserSignHighlight)
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/display/window.vim b/vim/eclim/autoload/eclim/display/window.vim
@@ -0,0 +1,352 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Utility functions for working with vim windows.
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" GlobalVariables {{{
+let g:VerticalToolBuffers = {}
+
+if !exists('g:VerticalToolWindowSide')
+ let g:VerticalToolWindowSide = 'left'
+endif
+
+if g:VerticalToolWindowSide == 'right'
+ let g:VerticalToolWindowPosition = 'botright vertical'
+else
+ let g:VerticalToolWindowPosition = 'topleft vertical'
+endif
+
+if !exists('g:VerticalToolWindowWidth')
+ let g:VerticalToolWindowWidth = 30
+endif
+" }}}
+
+function! eclim#display#window#VerticalToolWindowOpen(name, weight, ...) " {{{
+ " Handles opening windows in the vertical tool window on the left (taglist,
+ " project tree, etc.)
+
+ let taglist_window = -1
+ if exists('g:TagList_title')
+ let taglist_window = bufwinnr(eclim#util#EscapeBufferName(g:TagList_title))
+ let taglist_position = 'left'
+ if exists('g:Tlist_Use_Horiz_Window') && g:Tlist_Use_Horiz_Window
+ let taglist_position = 'horizontal'
+ elseif exists('g:TaglistTooPosition')
+ let taglist_position = g:TaglistTooPosition
+ elseif exists('g:Tlist_Use_Right_Window') && g:Tlist_Use_Right_Window
+ let taglist_position = 'right'
+ endif
+ endif
+ if taglist_window == -1 && exists(':TagbarOpen')
+ let taglist_window = bufwinnr('__Tagbar__')
+ let taglist_position = 'right'
+ if exists('g:tagbar_left') && g:tagbar_left
+ let taglist_position = 'left'
+ endif
+ endif
+ if taglist_window != -1
+ " don't consider horizontal taglist, or taglist configured to display
+ " opposite the tool windows as a tool window member.
+ if taglist_position != g:VerticalToolWindowSide
+ let taglist_window = -1
+ endif
+ endif
+
+
+ let relative_window = 0
+ let relative_window_loc = 'below'
+ if taglist_window != -1 || len(g:VerticalToolBuffers) > 0
+ if taglist_window != -1
+ let relative_window = taglist_window
+ endif
+ for toolbuf in keys(g:VerticalToolBuffers)
+ exec 'let toolbuf = ' . toolbuf
+ if bufwinnr(toolbuf) != -1
+ if relative_window == 0
+ let relative_window = bufwinnr(toolbuf)
+ if getbufvar(toolbuf, 'weight') > a:weight
+ let relative_window_loc = 'below'
+ else
+ let relative_window_loc = 'above'
+ endif
+ elseif getbufvar(toolbuf, 'weight') > a:weight
+ let relative_window = bufwinnr(toolbuf)
+ let relative_window_loc = 'below'
+ endif
+ endif
+ endfor
+ endif
+
+ if relative_window != 0
+ let wincmd = relative_window . 'winc w | ' . relative_window_loc . ' '
+ else
+ let wincmd = g:VerticalToolWindowPosition . ' ' . g:VerticalToolWindowWidth
+ endif
+
+ let escaped = substitute(
+ \ a:name, '\(.\{-}\)\[\(.\{-}\)\]\(.\{-}\)', '\1[[]\2[]]\3', 'g')
+ if a:0 && a:1
+ let bufnum = -1
+ for bnr in tabpagebuflist()
+ if bufname(bnr) == a:name
+ let bufnum = bnr
+ break
+ endif
+ endfor
+ else
+ let bufnum = bufnr(escaped)
+ endif
+ let name = bufnum == -1 ? a:name : '+buffer' . bufnum
+ silent call eclim#util#ExecWithoutAutocmds(wincmd . ' split ' . name)
+
+ doautocmd BufWinEnter
+ setlocal winfixwidth
+ setlocal nonumber
+ setlocal nospell norelativenumber
+
+ let b:weight = a:weight
+ let bufnum = bufnr('%')
+ let g:VerticalToolBuffers[bufnum] = a:name
+ augroup eclim_vertical_tool_windows
+ autocmd!
+ autocmd BufDelete * call s:PreventCloseOnBufferDelete()
+ autocmd BufEnter * nested call s:CloseIfLastWindow()
+ augroup END
+
+ if exists('g:TagList_title') &&
+ \ (!exists('g:Tlist_Use_Horiz_Window') || !g:Tlist_Use_Horiz_Window)
+ augroup eclim_vertical_tool_windows_move_taglist
+ autocmd!
+ exec 'autocmd BufWinEnter ' . eclim#util#EscapeBufferName(g:TagList_title) .
+ \ ' call s:MoveRelativeTo()'
+ augroup END
+ endif
+ if exists(':TagbarOpen')
+ augroup eclim_vertical_tool_windows_move_tagbar
+ autocmd!
+ autocmd BufWinEnter __Tagbar__ call s:MoveRelativeTo()
+ augroup END
+ endif
+ augroup eclim_vertical_tool_windows_buffer
+ exec 'autocmd BufWinLeave <buffer> ' .
+ \ 'silent! call remove(g:VerticalToolBuffers, ' . bufnum . ') | ' .
+ \ 'autocmd! eclim_vertical_tool_windows_buffer * <buffer=' . bufnum . '>'
+ augroup END
+endfunction " }}}
+
+function! eclim#display#window#VerticalToolWindowRestore() " {{{
+ " Used to restore the tool windows to their proper width if some action
+ " altered them.
+
+ for toolbuf in keys(g:VerticalToolBuffers)
+ exec 'let toolbuf = ' . toolbuf
+ if bufwinnr(toolbuf) != -1
+ exec 'vertical ' . bufwinnr(toolbuf) . 'resize ' . g:VerticalToolWindowWidth
+ endif
+ endfor
+endfunction " }}}
+
+function! eclim#display#window#GetWindowOptions(winnum) " {{{
+ " Gets a dictionary containing all the localy set options for the specified
+ " window.
+
+ let curwin = winnr()
+ try
+ exec a:winnum . 'winc w'
+ redir => list
+ silent exec 'setlocal'
+ redir END
+ finally
+ exec curwin . 'winc w'
+ endtry
+
+ let list = substitute(list, '---.\{-}---', '', '')
+ let winopts = {}
+ for wopt in split(list, '\(\n\|\s\s\+\)')[1:]
+ if wopt =~ '^[a-z]'
+ if wopt =~ '='
+ let key = substitute(wopt, '\(.\{-}\)=.*', '\1', '')
+ let value = substitute(wopt, '.\{-}=\(.*\)', '\1', '')
+ let winopts[key] = value
+ else
+ let winopts[wopt] = ''
+ endif
+ endif
+ endfor
+ return winopts
+endfunction " }}}
+
+function! eclim#display#window#SetWindowOptions(winnum, options) " {{{
+ " Given a dictionary of options, sets each as local options for the specified
+ " window.
+
+ let curwin = winnr()
+ try
+ exec a:winnum . 'winc w'
+ for key in keys(a:options)
+ if key =~ '^no'
+ silent! exec 'setlocal ' . key
+ else
+ silent! exec 'setlocal ' . key . '=' . escape(a:options[key], ' ')
+ endif
+ endfor
+ finally
+ exec curwin . 'winc w'
+ endtry
+endfunction " }}}
+
+function! s:CloseIfLastWindow() " {{{
+ if histget(':', -1) !~ '^bd'
+ let close = 1
+ for bufnr in tabpagebuflist()
+ if has_key(g:VerticalToolBuffers, bufnr)
+ continue
+ endif
+ if exists('g:TagList_title') && bufname(bufnr) == g:TagList_title
+ continue
+ endif
+ if exists('g:BufExplorer_title') && bufname(bufnr) == '[BufExplorer]'
+ let close = 0
+ break
+ endif
+
+ let buftype = getbufvar(bufnr, '&buftype')
+ if buftype != '' && buftype != 'help'
+ continue
+ endif
+
+ let close = 0
+ break
+ endfor
+
+ if close
+ if tabpagenr('$') > 1
+ tabclose
+ else
+ quitall
+ endif
+ endif
+ endif
+endfunction " }}}
+
+function! s:MoveRelativeTo() " {{{
+ " get the buffer that the taglist was opened from
+ let curwin = winnr()
+ let list_buffer = bufnr('%')
+ winc p
+ let orig_buffer = bufnr('%')
+ exec curwin . 'winc p'
+
+ for toolbuf in keys(g:VerticalToolBuffers)
+ exec 'let toolbuf = ' . toolbuf
+ if bufwinnr(toolbuf) != -1
+ call setwinvar(bufwinnr(toolbuf), 'marked_for_removal', 1)
+ let winoptions = eclim#display#window#GetWindowOptions(bufwinnr(toolbuf))
+ call remove(winoptions, 'filetype')
+ call remove(winoptions, 'syntax')
+ call eclim#display#window#VerticalToolWindowOpen(
+ \ g:VerticalToolBuffers[toolbuf], getbufvar(toolbuf, 'weight'))
+ call eclim#display#window#SetWindowOptions(winnr(), winoptions)
+ endif
+ endfor
+
+ let winnum = 1
+ while winnum <= winnr('$')
+ if getwinvar(winnum, 'marked_for_removal') == 1
+ exec winnum . 'winc w'
+ close
+ else
+ let winnum += 1
+ endif
+ endwhile
+ call eclim#display#window#VerticalToolWindowRestore()
+
+ " some window juggling so that winc p from taglist goes back to the original
+ " buffer
+ exec bufwinnr(orig_buffer) . 'winc w'
+ exec bufwinnr(list_buffer) . 'winc w'
+endfunction " }}}
+
+function! s:PreventCloseOnBufferDelete() " {{{
+ let index = 1
+ let numtoolwindows = 0
+ let numtempwindows = 0
+ let tempbuffersbot = []
+ while index <= winnr('$')
+ let buf = winbufnr(index)
+ let bufname = bufname(buf)
+ if index(keys(g:VerticalToolBuffers), string(buf)) != -1
+ let numtoolwindows += 1
+ elseif getwinvar(index, '&winfixheight') || getwinvar(index, '&winfixwidth')
+ let numtempwindows += 1
+ if getwinvar(index, '&winfixheight')
+ call add(tempbuffersbot, buf)
+ endif
+ endif
+ let index += 1
+ endwhile
+
+ if winnr('$') == (numtoolwindows + numtempwindows)
+ let toolbuf = bufnr('%')
+ if g:VerticalToolWindowSide == 'right'
+ vertical topleft new
+ else
+ vertical botright new
+ endif
+ setlocal noreadonly modifiable
+ let curbuf = bufnr('%')
+ let removed = str2nr(expand('<abuf>'))
+ let next = eclim#common#buffers#OpenNextHiddenTabBuffer(removed)
+ if next != 0
+ let curbuf = next
+ endif
+
+ " resize windows
+ exec bufwinnr(toolbuf) . 'winc w'
+ exec 'vertical resize ' . g:VerticalToolWindowWidth
+
+ " fix the position of the temp windows
+ for buf in tempbuffersbot
+ " open the buffer in the temp window position
+ botright 10new
+ exec 'buffer ' . buf
+ setlocal winfixheight
+
+ " close the old window
+ let winnr = winnr()
+ let index = 1
+ while index <= winnr('$')
+ if winbufnr(index) == buf && index != winnr
+ exec index . 'winc w'
+ close
+ winc p
+ break
+ endif
+ let index += 1
+ endwhile
+ endfor
+
+ exec bufwinnr(curbuf) . 'winc w'
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/help.vim b/vim/eclim/autoload/eclim/help.vim
@@ -0,0 +1,169 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Commands view / search eclim help files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+ let g:EclimHelpDir = g:EclimBaseDir . '/eclim/doc'
+" }}}
+
+" Help(tag) {{{
+function! eclim#help#Help(tag, link)
+ if !filereadable(substitute(g:EclimHelpDir, '\\\s', ' ', 'g') . '/tags')
+ call eclim#util#Echo('indexing eclim help files...')
+ exec 'helptags ' . g:EclimHelpDir
+ let paths = split(glob(g:EclimHelpDir . '/**/*'), '\n')
+ call filter(paths, 'isdirectory(v:val)')
+ for path in paths
+ exec 'helptags ' . path
+ endfor
+ call eclim#util#Echo('eclim help files indexed')
+ endif
+
+ let savetags = &tags
+ exec 'set tags=' . escape(escape(g:EclimHelpDir, ' '), ' ') . '/**/tags'
+ try
+ let tag = a:tag
+ if tag == '' && !a:link
+ let tag = 'index'
+ elseif tag ==''
+ let line = getline('.')
+ let tag = substitute(
+ \ line, '.*|\(\S\{-}\%' . col('.') . 'c\S\{-}\)|.*', '\1', '')
+ if tag == line
+ return
+ endif
+ endif
+
+ call s:HelpWindow()
+ exec 'tag ' . tag
+ let w:eclim_help = 1
+
+ " needed to ensure taglist is updated if open
+ doautocmd BufEnter
+ catch /^Vim\%((\a\+)\)\=:E426/
+ if !exists('w:eclim_help')
+ close
+ endif
+ call eclim#util#EchoError('Sorry no eclim help for ' . tag)
+ finally
+ let &tags = savetags
+ endtry
+endfunction " }}}
+
+" HelpGrep() {{{
+function! eclim#help#HelpGrep(args)
+ exec 'vimgrep ' a:args . ' ' . g:EclimHelpDir . '/**/*.txt'
+endfunction " }}}
+
+" s:HelpWindow() {{{
+function s:HelpWindow()
+ let max = winnr('$')
+ let index = 1
+ while index <= max
+ if getwinvar(index, 'eclim_help')
+ exec index . 'winc w'
+ return
+ endif
+ let index += 1
+ endwhile
+
+ new
+endfunction " }}}
+
+" BufferHelp(lines, orientation, size) {{{
+" Function to display a help window for the current buffer.
+function! eclim#help#BufferHelp(lines, orientation, size)
+ let orig_bufnr = bufnr('%')
+ let name = expand('%')
+ if name =~ '^\W.*\W$'
+ let name = name[:-2] . ' Help' . name[len(name) - 1]
+ else
+ let name .= ' Help'
+ endif
+
+ let bname = eclim#util#EscapeBufferName(name)
+
+ let orient = a:orientation == 'vertical' ? 'v' : ''
+ if bufwinnr(bname) != -1
+ exec 'bd ' . bufnr(bname)
+ return
+ endif
+
+ silent! noautocmd exec a:size . orient . "new " . escape(name, ' ')
+ if a:orientation == 'vertical'
+ setlocal winfixwidth
+ else
+ setlocal winfixheight
+ endif
+ setlocal nowrap
+ setlocal noswapfile nobuflisted nonumber
+ setlocal nospell norelativenumber
+ setlocal buftype=nofile bufhidden=delete
+ nnoremap <buffer> <silent> ? :bd<cr>
+ nnoremap <buffer> <silent> q :bd<cr>
+
+ setlocal modifiable noreadonly
+ silent 1,$delete _
+ call append(1, a:lines)
+ retab
+ silent 1,1delete _
+
+ if len(a:000) == 0 || a:000[0]
+ setlocal nomodified nomodifiable readonly
+ endif
+
+ let help_bufnr = bufnr('%')
+ augroup eclim_help_buffer
+ autocmd! BufWinLeave <buffer>
+ autocmd BufWinLeave <buffer> nested autocmd! eclim_help_buffer * <buffer>
+ exec 'autocmd BufWinLeave <buffer> nested ' .
+ \ 'autocmd! eclim_help_buffer * <buffer=' . orig_bufnr . '>'
+ exec 'autocmd! BufWinLeave <buffer=' . orig_bufnr . '>'
+ exec 'autocmd BufWinLeave <buffer=' . orig_bufnr . '> nested bd ' . help_bufnr
+ augroup END
+
+ return help_bufnr
+endfunction " }}}
+
+" CommandComplete(argLead, cmdLine, cursorPos) {{{
+function! eclim#help#CommandCompleteTag(argLead, cmdLine, cursorPos)
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+
+ let savetags = &tags
+ exec 'set tags=' . escape(escape(g:EclimHelpDir, ' '), ' ') . '/**/tags'
+ try
+ let tags = sort(map(taglist(argLead . '.*'), "v:val['name']"))
+ let results = []
+ for tag in tags
+ if index(results, tag) == -1
+ call add(results, tag)
+ endif
+ endfor
+ return results
+ finally
+ let &tags = savetags
+ endtry
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/html/complete.vim b/vim/eclim/autoload/eclim/html/complete.vim
@@ -0,0 +1,59 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/html/complete.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Varables {{{
+ let s:complete_command =
+ \ '-command html_complete -p "<project>" -f "<file>" -o <offset> -e <encoding>'
+" }}}
+
+" CodeComplete(findstart, base) {{{
+" Handles html code completion.
+function! eclim#html#complete#CodeComplete(findstart, base)
+ "if eclim#html#util#InJavascriptBlock()
+ " return eclim#javascript#complete#CodeComplete(a:findstart, a:base)
+ "endif
+
+ if eclim#html#util#InCssBlock()
+ return eclim#css#complete#CodeComplete(a:findstart, a:base)
+ endif
+
+ if a:findstart
+ call eclim#lang#SilentUpdate(1)
+
+ " locate the start of the word
+ let line = getline('.')
+
+ let start = col('.') - 1
+
+ while start > 0 && line[start - 1] =~ '[[:alnum:]_-]'
+ let start -= 1
+ endwhile
+
+ return start
+ else
+ return eclim#lang#CodeComplete(s:complete_command, a:findstart, a:base)
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/html/util.vim b/vim/eclim/autoload/eclim/html/util.vim
@@ -0,0 +1,135 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Various html relatd functions.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" HtmlToText() {{{
+" Converts the supplied basic html to text.
+function! eclim#html#util#HtmlToText(html)
+ let text = a:html
+ let text = substitute(text, '<br/\?>\c', '\n', 'g')
+ let text = substitute(text, '</\?b>\c', '', 'g')
+ let text = substitute(text, '</\?ul>\c', '', 'g')
+ let text = substitute(text, '<li>\c', '- ', 'g')
+ let text = substitute(text, '</li>\c', '', 'g')
+ let text = substitute(text, '</\?p/\?>\c', '', 'g')
+ let text = substitute(text, '</\?code>\c', '', 'g')
+ let text = substitute(text, '</\?pre>\c', '', 'g')
+ let text = substitute(text, '<a .\{-}>\c', '', 'g')
+ let text = substitute(text, '</a>', '', 'g')
+ let text = substitute(text, '"\c', '"', 'g')
+ let text = substitute(text, '&\c', '&', 'g')
+ let text = substitute(text, '<\c', '<', 'g')
+ let text = substitute(text, '>\c', '>', 'g')
+
+ return text
+endfunction " }}}
+
+" InCssBlock() {{{
+" Determines if the cusor is inside of <style> tags.
+function! eclim#html#util#InCssBlock()
+ let line = line('.')
+
+ let stylestart = search('<style\>', 'bcWn')
+ if stylestart > 0
+ let styleend = search('</style\s*>', 'bWn')
+ endif
+ if stylestart > 0 && stylestart < line &&
+ \ (styleend == 0 || (styleend > stylestart && line < styleend))
+ return stylestart
+ endif
+
+ return 0
+endfunction " }}}
+
+" InJavascriptBlock() {{{
+" Determines if the cursor is inside of <script> tags.
+function! eclim#html#util#InJavascriptBlock()
+ let line = line('.')
+
+ let scriptstart = search('<script\>', 'bcWn')
+ if scriptstart > 0
+ let scriptend = search('</script\s*>', 'bWn')
+ endif
+ if scriptstart > 0 && scriptstart < line &&
+ \ (scriptend == 0 || (scriptend > scriptstart && line < scriptend))
+ return scriptstart
+ endif
+
+ return 0
+endfunction " }}}
+
+" OpenInBrowser(file) {{{
+function! eclim#html#util#OpenInBrowser(file)
+ let file = a:file
+ if file == ''
+ let file = expand('%:p')
+ else
+ let file = getcwd() . '/' . file
+ endif
+ let url = 'file://' . file
+ call eclim#web#OpenUrl(url)
+endfunction " }}}
+
+" UrlEncode(string) {{{
+function! eclim#html#util#UrlEncode(string)
+ let result = a:string
+
+ " must be first
+ let result = substitute(result, '%', '%25', 'g')
+
+ let result = substitute(result, '\s', '%20', 'g')
+ let result = substitute(result, '!', '%21', 'g')
+ let result = substitute(result, '"', '%22', 'g')
+ let result = substitute(result, '#', '%23', 'g')
+ let result = substitute(result, '\$', '%24', 'g')
+ let result = substitute(result, '&', '%26', 'g')
+ let result = substitute(result, "'", '%27', 'g')
+ let result = substitute(result, '(', '%28', 'g')
+ let result = substitute(result, ')', '%29', 'g')
+ let result = substitute(result, '*', '%2A', 'g')
+ let result = substitute(result, '+', '%2B', 'g')
+ let result = substitute(result, ',', '%2C', 'g')
+ let result = substitute(result, '-', '%2D', 'g')
+ let result = substitute(result, '\.', '%2E', 'g')
+ let result = substitute(result, '\/', '%2F', 'g')
+ let result = substitute(result, ':', '%3A', 'g')
+ let result = substitute(result, ';', '%3B', 'g')
+ let result = substitute(result, '<', '%3C', 'g')
+ let result = substitute(result, '=', '%3D', 'g')
+ let result = substitute(result, '>', '%3E', 'g')
+ let result = substitute(result, '?', '%3F', 'g')
+ let result = substitute(result, '@', '%40', 'g')
+ let result = substitute(result, '[', '%5B', 'g')
+ let result = substitute(result, '\\', '%5C', 'g')
+ let result = substitute(result, ']', '%5D', 'g')
+ let result = substitute(result, '\^', '%5E', 'g')
+ let result = substitute(result, '`', '%60', 'g')
+ let result = substitute(result, '{', '%7B', 'g')
+ let result = substitute(result, '|', '%7C', 'g')
+ let result = substitute(result, '}', '%7D', 'g')
+ let result = substitute(result, '\~', '%7E', 'g')
+
+ return result
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/html/validate.vim b/vim/eclim/autoload/eclim/html/validate.vim
@@ -0,0 +1,64 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/html/validate.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+function! eclim#html#validate#Validate(on_save) " {{{
+ let validate = !a:on_save || (
+ \ g:EclimHtmlValidate &&
+ \ (!exists('g:EclimFileTypeValidate') || g:EclimFileTypeValidate))
+
+ if !validate || eclim#util#WillWrittenBufferClose()
+ return
+ endif
+
+ if !eclim#project#util#IsCurrentFileInProject(!a:on_save)
+ return
+ endif
+
+ " prevent closing of sign column between validation methods
+ call eclim#display#signs#SetPlaceholder()
+
+ call eclim#lang#Validate('html', a:on_save)
+
+ " prevent closing of sign column between validation methods
+ "call eclim#display#signs#SetPlaceholder()
+
+ " disabled for now since the parser will attempt to follow all style tags
+ " and interprets //domain.com/styles.css as an ftp path leading to
+ " long validation delays due to connection timeouts.
+ "let html_errors = getloclist(0)
+ "let css_errors = []
+ "if search('<style', 'cnw')
+ " call eclim#lang#Validate('css', a:on_save)
+ " let css_errors = getloclist(0)
+ "endif
+
+ "call eclim#util#SetLocationList(html_errors + css_errors)
+
+ if search('<script', 'cnw')
+ call eclim#javascript#util#UpdateSrcFile(a:on_save)
+ endif
+ call eclim#display#signs#RemovePlaceholder()
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/ant/complete.vim b/vim/eclim/autoload/eclim/java/ant/complete.vim
@@ -0,0 +1,144 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/ant/complete.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Varables {{{
+ let s:complete_command =
+ \ '-command ant_complete -p "<project>" -f "<file>" -o <offset> -e <encoding>'
+ let s:command_targets = '-command ant_targets -p "<project>" -f "<file>"'
+" }}}
+
+" CodeComplete(findstart, base) {{{
+" Handles ant code completion.
+function! eclim#java#ant#complete#CodeComplete(findstart, base)
+ if !eclim#project#util#IsCurrentFileInProject(0)
+ return a:findstart ? -1 : []
+ endif
+
+ if a:findstart
+ call eclim#lang#SilentUpdate(1)
+
+ " locate the start of the word
+ let line = getline('.')
+
+ let start = col('.') - 1
+
+ "exceptions that break the rule
+ if line[start - 1] == '.'
+ let start -= 1
+ endif
+
+ " always start in front of the the '<'
+ if line[start] == '<'
+ let start += 1
+ endif
+
+ while start > 0 && line[start - 1] =~ '\w'
+ let start -= 1
+ endwhile
+
+ " if prev char is '/' then back off the start pos, since the completion
+ " result will contain the '/'.
+ if line[start - 1] == '/'
+ let start -= 1
+ endif
+
+ return start
+ else
+ let offset = eclim#util#GetOffset() + len(a:base) - 1
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#lang#SilentUpdate(1, 0)
+ if file == ''
+ return []
+ endif
+
+ let command = s:complete_command
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+
+ let completions = []
+ let results = eclim#Execute(command)
+ if type(results) != g:LIST_TYPE
+ return
+ endif
+
+ " if the word has a '.' in it (like package completion) then we need to
+ " strip some off according to what is currently in the buffer.
+ let prefix = substitute(getline('.'),
+ \ '.\{-}\([[:alnum:].]\+\%' . col('.') . 'c\).*', '\1', '')
+
+ for result in results
+ let word = result.completion
+ " removed '<' and '>' from end tag results
+ let word = substitute(word, '^<\(.*\)>$', '\1', '')
+
+ " strip off prefix if necessary.
+ if word =~ '\.'
+ let word = substitute(word, escape(prefix, '*'), '', '')
+ endif
+
+ let menu = eclim#html#util#HtmlToText(result.menu)
+ let info = eclim#html#util#HtmlToText(result.info)
+
+ let dict = {'word': word, 'menu': menu, 'info': info}
+
+ call add(completions, dict)
+ endfor
+
+ return completions
+ endif
+endfunction " }}}
+
+" CommandCompleteTarget(argLead, cmdLine, cursorPos) {{{
+" Custom command completion for ant targets.
+function! eclim#java#ant#complete#CommandCompleteTarget(argLead, cmdLine, cursorPos)
+ let project = eclim#project#util#GetCurrentProjectName()
+ if project == ''
+ return []
+ endif
+
+ let file = eclim#java#ant#util#FindBuildFile()
+ if project != "" && file != ""
+ let file = eclim#project#util#GetProjectRelativeFilePath(file)
+ let command = s:command_targets
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+
+ let targets = eclim#Execute(command)
+ if type(targets) != g:LIST_TYPE
+ return []
+ endif
+
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+ call filter(targets, 'v:val =~ "^' . argLead . '"')
+
+ return targets
+ endif
+
+ return []
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/ant/doc.vim b/vim/eclim/autoload/eclim/java/ant/doc.vim
@@ -0,0 +1,171 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/ant/doc.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Varables {{{
+if !exists("g:AntDocDefaultUrl")
+ let g:AntDocDefaultUrl =
+ \ 'http://www.google.com/search?btnI=1&q=allintitle%3A<element>+task+%7C+type+site%3Aant.apache.org'
+endif
+
+if !exists("g:AntUserDocs")
+ let g:AntUserDocs = {}
+endif
+" }}}
+
+" Script Varables {{{
+let s:targets = 'http://ant.apache.org/manual/targets.html'
+let s:using = 'http://ant.apache.org/manual/using.html#<element>s'
+let s:conditions = 'http://ant.apache.org/manual/Tasks/conditions.html#<element>'
+let s:mappers = 'http://ant.apache.org/manual/Types/mapper.html'
+let s:paths = 'http://ant.apache.org/manual/using.html#path'
+let s:types =
+ \ 'http://ant.apache.org/manual/Types/<element>.html'
+let s:selectors =
+ \ 'http://ant.apache.org/manual/Types/selectors.html#<element>select'
+let s:contrib_1 =
+ \ 'http://ant-contrib.sourceforge.net/tasks/tasks/<element>.html'
+let s:contrib_2 =
+ \ 'http://ant-contrib.sourceforge.net/tasks/tasks/<element>_task.html'
+let s:element_docs = {
+ \ 'project' : s:using,
+ \ 'target' : s:targets,
+ \ 'and' : s:conditions,
+ \ 'checksum' : s:conditions,
+ \ 'checs' : s:conditions,
+ \ 'contains' : s:conditions,
+ \ 'equals' : s:conditions,
+ \ 'filesmatch' : s:conditions,
+ \ 'http' : s:conditions,
+ \ 'isfalse' : s:conditions,
+ \ 'isfileselected' : s:conditions,
+ \ 'isreference' : s:conditions,
+ \ 'isset' : s:conditions,
+ \ 'istrue' : s:conditions,
+ \ 'length' : s:conditions,
+ \ 'not' : s:conditions,
+ \ 'or' : s:conditions,
+ \ 'os' : s:conditions,
+ \ 'socket' : s:conditions,
+ \ 'compositemapper' : s:mappers,
+ \ 'filtermapper' : s:mappers,
+ \ 'flattenmapper' : s:mappers,
+ \ 'globmapper' : s:mappers,
+ \ 'identitymapper' : s:mappers,
+ \ 'mergemapper' : s:mappers,
+ \ 'packagemapper' : s:mappers,
+ \ 'regexmapper' : s:mappers,
+ \ 'antlib' : s:types,
+ \ 'description' : s:types,
+ \ 'dirset' : s:types,
+ \ 'filelist' : s:types,
+ \ 'fileset' : s:types,
+ \ 'filterchain' : s:types,
+ \ 'filterset' : s:types,
+ \ 'mapper' : s:types,
+ \ 'patternset' : s:types,
+ \ 'permissions' : s:types,
+ \ 'propertyset' : s:types,
+ \ 'redirector' : s:types,
+ \ 'regexp' : s:types,
+ \ 'xmlcatalog' : s:types,
+ \ 'zipfileset' : s:types,
+ \ 'classpath' : s:paths,
+ \ 'path' : s:paths,
+ \ 'containsregexp' : s:selectors,
+ \ 'date' : s:selectors,
+ \ 'depend' : s:selectors,
+ \ 'depth' : s:selectors,
+ \ 'different' : s:selectors,
+ \ 'filename' : s:selectors,
+ \ 'majority' : s:selectors,
+ \ 'modified' : s:selectors,
+ \ 'none' : s:selectors,
+ \ 'present' : s:selectors,
+ \ 'selector' : s:selectors,
+ \ 'size' : s:selectors,
+ \ 'type' : s:selectors,
+ \ 'for' : s:contrib_1,
+ \ 'foreach' : s:contrib_1,
+ \ 'if' : s:contrib_1,
+ \ 'outofdate' : s:contrib_1,
+ \ 'runtarget' : s:contrib_1,
+ \ 'switch' : s:contrib_1,
+ \ 'throw' : s:contrib_1,
+ \ 'timestampselector' : s:contrib_1,
+ \ 'trycatch' : s:contrib_1,
+ \ 'osfamily' : s:contrib_1,
+ \ 'shellscript' : s:contrib_1,
+ \ 'propertycopy' : s:contrib_1,
+ \ 'propertyselector' : s:contrib_1,
+ \ 'pathoffileset' : s:contrib_1,
+ \ 'propertyregex' : s:contrib_1,
+ \ 'sortlist' : s:contrib_1,
+ \ 'urlencode' : s:contrib_1,
+ \ 'forget' : s:contrib_1,
+ \ 'compilewithwalls' : s:contrib_1,
+ \ 'inifile' : s:contrib_1,
+ \ 'verifydesign' : s:contrib_1,
+ \ 'antcallback' : s:contrib_2,
+ \ 'antfetch' : s:contrib_2,
+ \ 'assert' : s:contrib_2,
+ \ 'post' : s:contrib_2,
+ \ 'stopwatch' : s:contrib_2,
+ \ 'match' : s:contrib_2,
+ \ 'variable' : s:contrib_2,
+ \ 'limit' : s:contrib_2,
+ \ 'antclipse' : s:contrib_2
+ \ }
+" }}}
+
+" FindDoc(element) {{{
+" Open the url to the documentation for the supplied element name or if not
+" provided, the element name under the cursor.
+function! eclim#java#ant#doc#FindDoc(element)
+ let element = a:element
+ if element == ''
+ let col = eclim#util#GetCurrentElementColumn()
+ if getline('.')[col - 2] !~ '<\|\/'
+ " not on an element
+ return
+ endif
+ let element = expand('<cword>')
+ endif
+ let element = tolower(element)
+
+ if has_key(s:element_docs, element)
+ let url = s:element_docs[element]
+ elseif has_key(g:AntUserDocs, element)
+ let url = g:AntUserDocs[element]
+ else
+ let url = g:AntDocDefaultUrl
+ endif
+
+ "let url = escape(url, '&%#')
+ "let url = escape(url, '%#')
+ let url = substitute(url, '<element>', element, 'g')
+
+ call eclim#web#OpenUrl(url)
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/ant/ivy.vim b/vim/eclim/autoload/eclim/java/ant/ivy.vim
@@ -0,0 +1,31 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/classpath.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" SetRepo(path) {{{
+" Sets the location of the ivy repository.
+function! eclim#java#ant#ivy#SetRepo(path)
+ call eclim#java#classpath#VariableCreate('IVY_REPO', a:path)
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/ant/util.vim b/vim/eclim/autoload/eclim/java/ant/util.vim
@@ -0,0 +1,36 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Utility functions for working with ant.
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" FindBuildFile() {{{
+" Finds the build file relative to the current file (like ant -find).
+function! eclim#java#ant#util#FindBuildFile()
+ let buildFile = eclim#util#Findfile('build.xml', fnamemodify(expand('%:p'), ':h') . ';')
+ if filereadable(buildFile)
+ return substitute(fnamemodify(buildFile, ':p'), '\', '/', 'g')
+ endif
+
+ return ''
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/classpath.vim b/vim/eclim/autoload/eclim/java/classpath.vim
@@ -0,0 +1,241 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/classpath.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+ let s:command_variables = '-command java_classpath_variables'
+ let s:command_variable_create =
+ \ '-command java_classpath_variable_create -n "<name>" -p "<path>"'
+ let s:command_variable_delete =
+ \ '-command java_classpath_variable_delete -n "<name>"'
+
+ let s:entry_project =
+ \ "\t<classpathentry exported=\"true\" kind=\"src\" path=\"/<path>\"/>"
+ let s:entry ="\t<classpathentry kind=\"<kind>\" path=\"<path>\"/>"
+ let s:entry_sourcepath =
+ \ "\t<classpathentry kind=\"<kind>\" path=\"<path>\"\n\t\t\tsourcepath=\"<src>\"/>"
+ let s:entry_javadoc =
+ \ "\t<classpathentry kind=\"<kind>\" path=\"<path>\"\n" .
+ \ "\t\t\tsourcepath=\"<src>\">\n" .
+ \ "\t\t<attributes>\n" .
+ \ "\t\t\t<attribute name=\"javadoc_location\" value=\"<javadoc>\"/>\n" .
+ \ "\t\t</attributes>\n" .
+ \ "\t</classpathentry>"
+" }}}
+
+function! eclim#java#classpath#NewClasspathEntry(kind, arg, ...) " {{{
+ " Adds a new entry to the current .classpath file.
+ let template_name = 's:entry'
+ let args = {'kind': a:kind, 'path': substitute(a:arg, '\', '/', 'g')}
+ if a:0
+ if a:0 == 1
+ let template_name = 's:entry_sourcepath'
+ let args['src'] = substitute(a:1, '\', '/', 'g')
+ elseif a:0 == 2
+ let template_name = 's:entry_javadoc'
+ let args['src'] = substitute(a:1, '\', '/', 'g')
+ let javadoc = substitute(a:2, '\', '/', 'g')
+ let absolute = javadoc =~? '^\([a-z]:\)\?/'
+
+ " handle absolute vs project relative javadoc location
+ if absolute
+ " windows paths need a leading slash
+ if javadoc =~? '^[a-z]:/'
+ let javadoc = '/' . javadoc
+ endif
+ let javadoc = 'file:' . javadoc
+ else
+ if !eclim#project#util#IsCurrentFileInProject(1)
+ return
+ endif
+ if javadoc =~? '\.jar$'
+ let project = eclim#project#util#GetCurrentProjectName()
+ let javadoc = 'platform:/resource/' . project . '/' . javadoc
+ else
+ " relative dirs must be made absolute
+ let project = eclim#project#util#GetCurrentProjectRoot()
+ let javadoc = project . '/' . javadoc
+ endif
+ endif
+
+ if javadoc =~? '\.jar$'
+ let javadoc = 'jar:' . javadoc . '!/'
+ elseif javadoc !~ '^file:'
+ let javadoc = 'file:' . javadoc
+ endif
+ let args['javadoc'] = javadoc
+ else
+ call eclim#util#EchoError('Too many arguments.')
+ return
+ endif
+ endif
+
+ if exists(template_name . '_' . a:kind)
+ let template = {template_name}_{a:kind}
+ else
+ let template = {template_name}
+ endif
+
+ for [key, value] in items(args)
+ let template = substitute(template, '<' . key . '>', value, 'g')
+ endfor
+
+ let cline = line('.')
+ let ccol = col('.')
+ call s:MoveToInsertPosition()
+ let line = line('.')
+ call append(line, split(template, '\n'))
+ call cursor(cline + 1, ccol)
+endfunction " }}}
+
+function! s:MoveToInsertPosition() " {{{
+ " If necessary moves the cursor to a valid insert position.
+ let start = search('<classpath\s*>', 'wn')
+ let end = search('</classpath\s*>', 'wn')
+ if line('.') < start || line('.') >= end
+ call cursor(end - 1, 1)
+ endif
+endfunction " }}}
+
+function! eclim#java#classpath#GetVariableNames() " {{{
+ let variables = eclim#Execute(s:command_variables)
+ if type(variables) != g:LIST_TYPE
+ return []
+ endif
+ return map(variables, "v:val.name")
+endfunction " }}}
+
+function! eclim#java#classpath#VariableList() " {{{
+ let variables = eclim#Execute(s:command_variables)
+ if type(variables) != g:LIST_TYPE
+ return
+ endif
+ if len(variables) == 0
+ call eclim#util#Echo("No variables.")
+ endif
+
+ let pad = 0
+ for variable in variables
+ let pad = len(variable.name) > pad ? len(variable.name) : pad
+ endfor
+
+ let output = []
+ for variable in variables
+ call add(output, eclim#util#Pad(variable.name, pad) . ' - ' . variable.path)
+ endfor
+
+ call eclim#util#Echo(join(output, "\n"))
+endfunction " }}}
+
+function! eclim#java#classpath#VariableCreate(name, path) " {{{
+ let path = substitute(fnamemodify(a:path, ':p'), '\', '/', 'g')
+ if has('win32unix')
+ let path = eclim#cygwin#WindowsPath(path)
+ endif
+ let command = s:command_variable_create
+ let command = substitute(command, '<name>', a:name, '')
+ let command = substitute(command, '<path>', path, '')
+
+ let result = eclim#Execute(command)
+ if result != '0'
+ call eclim#util#Echo(result)
+ endif
+endfunction " }}}
+
+function! eclim#java#classpath#VariableDelete(name) " {{{
+ let command = s:command_variable_delete
+ let command = substitute(command, '<name>', a:name, '')
+
+ let result = eclim#Execute(command)
+ if result != '0'
+ call eclim#util#Echo(result)
+ endif
+endfunction " }}}
+
+function! eclim#java#classpath#CommandCompleteVar(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for classpath var relative files.
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+
+ let vars = eclim#java#classpath#GetVariableNames()
+ call filter(vars, 'v:val =~ "\\M^' . argLead . '"')
+
+ return vars
+endfunction " }}}
+
+function! eclim#java#classpath#CommandCompleteVarPath(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for classpath var relative files.
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+
+ let vars = eclim#Execute(s:command_variables)
+
+ " just the variable name
+ if argLead !~ '/'
+ let var_names = deepcopy(vars)
+ call filter(var_names, 'v:val.name =~ "^' . argLead . '"')
+ if len(var_names) > 0
+ call map(var_names,
+ \ "isdirectory(v:val.path) ? v:val.name . '/' : v:val.name")
+ endif
+ return var_names
+ endif
+
+ " variable name + path
+ let var = substitute(argLead, '\(.\{-}\)/.*', '\1', '')
+ let var_dir = ""
+ for cv in vars
+ if cv.name =~ '^' . var
+ let var_dir = cv.path
+ break
+ endif
+ endfor
+ if var_dir == ''
+ return []
+ endif
+
+ let var_dir = escape(substitute(var_dir, '\', '/', 'g'), ' ')
+ let argLead = substitute(argLead, var, var_dir, '')
+ let files = eclim#util#CommandCompleteFile(argLead, a:cmdLine, a:cursorPos)
+ let replace = escape(var_dir, '\')
+ call map(files, "substitute(v:val, '" . replace . "', '" . var . "', '')")
+
+ return files
+endfunction " }}}
+
+function! eclim#java#classpath#CommandCompleteVarAndDir(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for classpath var relative files.
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+
+ " complete vars for first arg
+ if cmdLine =~ '^' . args[0] . '\s*' . escape(argLead, '~.\') . '$'
+ return eclim#java#classpath#CommandCompleteVar(argLead, a:cmdLine, a:cursorPos)
+ endif
+
+ return eclim#util#CommandCompleteDir(a:argLead, a:cmdLine, a:cursorPos)
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/complete.vim b/vim/eclim/autoload/eclim/java/complete.vim
@@ -0,0 +1,188 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/complete.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Varables {{{
+ if !exists("g:EclimJavaCompleteLayout")
+ if &completeopt !~ 'preview' && &completeopt =~ 'menu'
+ let g:EclimJavaCompleteLayout = 'standard'
+ else
+ let g:EclimJavaCompleteLayout = 'compact'
+ endif
+ endif
+ if !exists("g:EclimJavaCompleteCaseSensitive")
+ let g:EclimJavaCompleteCaseSensitive = !&ignorecase
+ endif
+" }}}
+
+" Script Varables {{{
+ let s:complete_command =
+ \ '-command java_complete -p "<project>" -f "<file>" ' .
+ \ '-o <offset> -e <encoding> -l <layout>'
+" }}}
+
+" CodeComplete(findstart, base) {{{
+" Handles java code completion.
+function! eclim#java#complete#CodeComplete(findstart, base)
+ if !eclim#project#util#IsCurrentFileInProject(0)
+ return a:findstart ? -1 : []
+ endif
+
+ if a:findstart
+ call eclim#lang#SilentUpdate(1)
+
+ " locate the start of the word
+ let line = getline('.')
+
+ let start = col('.') - 1
+
+ "exceptions that break the rule
+ if line[start] == '.' && line[start - 1] != '.'
+ let start -= 1
+ endif
+
+ while start > 0 && line[start - 1] =~ '\w'
+ let start -= 1
+ endwhile
+
+ return start
+ else
+ let offset = eclim#util#GetOffset() + len(a:base)
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#lang#SilentUpdate(1, 0)
+ if file == ''
+ return []
+ endif
+
+ let command = s:complete_command
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ let command = substitute(command, '<layout>', g:EclimJavaCompleteLayout, '')
+
+ let completions = []
+ let response = eclim#Execute(command)
+ if type(response) != g:DICT_TYPE
+ return
+ endif
+
+ if has_key(response, 'imports') && len(response.imports)
+ let imports = response.imports
+ if exists('g:TestEclimWorkspace') " allow this to be tested somewhat
+ call eclim#java#complete#ImportThenComplete(imports)
+ else
+ let func = "eclim#java#complete#ImportThenComplete(" . string(imports) . ")"
+ call feedkeys("\<c-e>\<c-r>=" . func . "\<cr>", 'n')
+ endif
+ " prevents supertab's completion chain from attempting the next
+ " completion in the chain.
+ return -1
+ endif
+
+ if has_key(response, 'error') && len(response.completions) == 0
+ call eclim#util#EchoError(response.error.message)
+ return -1
+ endif
+
+ " if the word has a '.' in it (like package completion) then we need to
+ " strip some off according to what is currently in the buffer.
+ let prefix = substitute(getline('.'),
+ \ '.\{-}\([[:alnum:].]\+\%' . col('.') . 'c\).*', '\1', '')
+
+ " as of eclipse 3.2 it will include the parens on a completion result even
+ " if the file already has them.
+ let open_paren = getline('.') =~ '\%' . col('.') . 'c\s*('
+ let close_paren = getline('.') =~ '\%' . col('.') . 'c\s*(\s*)'
+
+ " when completing imports, the completions include ending ';'
+ let semicolon = getline('.') =~ '\%' . col('.') . 'c\s*;'
+
+ for result in response.completions
+ let word = result.completion
+
+ " strip off prefix if necessary.
+ if word =~ '\.'
+ let word = substitute(word, prefix, '', '')
+ endif
+
+ " strip off close paren if necessary.
+ if word =~ ')$' && close_paren
+ let word = strpart(word, 0, strlen(word) - 1)
+ endif
+
+ " strip off open paren if necessary.
+ if word =~ '($' && open_paren
+ let word = strpart(word, 0, strlen(word) - 1)
+ endif
+
+ " strip off semicolon if necessary.
+ if word =~ ';$' && semicolon
+ let word = strpart(word, 0, strlen(word) - 1)
+ endif
+
+ " if user wants case sensitivity, then filter out completions that don't
+ " match
+ if g:EclimJavaCompleteCaseSensitive && a:base != ''
+ if word !~ '^' . a:base . '\C'
+ continue
+ endif
+ endif
+
+ let menu = result.menu
+ let info = eclim#html#util#HtmlToText(result.info)
+
+ let dict = {
+ \ 'word': word,
+ \ 'menu': menu,
+ \ 'info': info,
+ \ 'kind': result.type,
+ \ 'dup': 1,
+ \ 'icase': !g:EclimJavaCompleteCaseSensitive,
+ \ }
+
+ call add(completions, dict)
+ endfor
+
+ return completions
+ endif
+endfunction " }}}
+
+" ImportThenComplete {{{
+" Called by CodeComplete when the completion depends on a missing import.
+function! eclim#java#complete#ImportThenComplete(choices)
+ let choice = ''
+ if len(a:choices) > 1
+ let choice = eclim#java#import#ImportPrompt(a:choices)
+ elseif len(a:choices)
+ let choice = a:choices[0]
+ endif
+
+ if choice != ''
+ call eclim#java#import#Import(choice)
+ call feedkeys("\<c-x>\<c-u>", 'tn')
+ endif
+ return ''
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/correct.vim b/vim/eclim/autoload/eclim/java/correct.vim
@@ -0,0 +1,139 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/correct.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" define Correction group based on Normal.
+hi link Correction Normal
+hi Correction gui=underline,bold term=underline,bold cterm=underline,bold
+
+" Script Varables {{{
+ let s:command_correct =
+ \ '-command java_correct -p "<project>" -f "<file>" ' .
+ \ '-l <line> -o <offset> -e <encoding>'
+ let s:command_correct_apply = s:command_correct . ' -a <apply>'
+" }}}
+
+" Correct() {{{
+function! eclim#java#correct#Correct()
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ call eclim#lang#SilentUpdate()
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+
+ let command = s:command_correct
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<line>', line('.'), '')
+ let command = substitute(command, '<offset>', eclim#util#GetOffset(), '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+
+ let window_name = file . "_correct"
+ let filename = expand('%:p')
+ call eclim#util#TempWindowClear(window_name)
+
+ let result = eclim#Execute(command)
+
+ " error executing the command.
+ if type(result) != g:DICT_TYPE && type(result) != g:STRING_TYPE
+ return
+
+ " no error on the current line
+ elseif type(result) == g:STRING_TYPE
+ call eclim#util#Echo(result)
+ return
+
+ " no correction proposals found.
+ elseif len(result.corrections) == 0
+ call eclim#util#EchoInfo('No Suggestions')
+ return
+ endif
+
+ let content = []
+ call add(content, result.message)
+ for correction in result.corrections
+ call add(content,
+ \ correction.index . '.' . result.offset . ': ' . correction.description)
+ for line in split(correction.preview, '\n')
+ call add(content, line != '' ? ("\t" . line) : line)
+ endfor
+ endfor
+
+ call eclim#util#TempWindow(window_name, content)
+
+ let b:filename = filename
+ augroup temp_window
+ autocmd! BufWinLeave <buffer>
+ call eclim#util#GoToBufferWindowRegister(filename)
+ augroup END
+
+ setlocal ft=java
+
+ "exec "syntax match Normal /" . escape(getline(1), '^$/\') . "/"
+ syntax match Correction /^[0-9]\+\.[0-9]\+:.*/
+
+ nnoremap <silent> <buffer> <cr>
+ \ :call eclim#java#correct#CorrectApply()<cr>
+
+ redraw | echo ""
+endfunction " }}}
+
+" CorrectApply() {{{
+function! eclim#java#correct#CorrectApply()
+ let line = getline('.')
+ if line =~ '^[0-9]\+\.[0-9]\+:'
+ let winnr = bufwinnr('%')
+ let name = substitute(expand('%:p'), '_correct$', '', '')
+ let file_winnr = bufwinnr(bufnr('^' . b:filename))
+ if file_winnr != -1
+ let filename = b:filename
+ exec file_winnr . "winc w"
+ call eclim#lang#SilentUpdate()
+
+ let index = substitute(line, '^\([0-9]\+\)\..*', '\1', '')
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:command_correct_apply
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<line>', line('.'), '')
+ let command = substitute(command, '<offset>', eclim#util#GetOffset(), '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ let command = substitute(command, '<apply>', index, '')
+
+ call eclim#lang#Refactor(command)
+ call eclim#lang#UpdateSrcFile('java', 1)
+
+ exec winnr . "winc w"
+ close
+ else
+ call eclim#util#EchoError(name . ' no longer found in an open window.')
+ endif
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/doc.vim b/vim/eclim/autoload/eclim/java/doc.vim
@@ -0,0 +1,272 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/doc.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+let s:command_comment =
+ \ '-command javadoc_comment -p "<project>" -f "<file>" -o <offset> -e <encoding>'
+let s:command_element_doc =
+ \ '-command java_element_doc -p "<project>" -f "<file>" -o <offset> -l <length> -e <encoding>'
+let s:command_doc_link = '-command java_element_doc -u "<url>"'
+let s:command_source_dirs = '-command java_src_dirs -p "<project>"'
+" }}}
+
+function! eclim#java#doc#Comment() " {{{
+ " Add / update the comments for the element under the cursor.
+
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ call eclim#lang#SilentUpdate()
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let offset = eclim#util#GetCurrentElementOffset()
+
+ let command = s:command_comment
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+
+ let result = eclim#Execute(command)
+
+ if result != "0"
+ call eclim#util#Reload({'retab': 1})
+ write
+ endif
+endfunction " }}}
+
+function! eclim#java#doc#Preview() " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ if !eclim#java#util#IsValidIdentifier(expand('<cword>'))
+ call eclim#util#EchoError
+ \ ("Element under the cursor is not a valid java identifier.")
+ return 0
+ endif
+
+ exec 'pedit +:call\ eclim#java#doc#PreviewOpen(' . bufnr('%') . ') [javadoc]'
+endfunction " }}}
+
+function! eclim#java#doc#PreviewOpen(bufnr_or_url) " {{{
+ if a:bufnr_or_url =~ '^\d\+$'
+ let curwin = winnr()
+ exec bufwinnr(a:bufnr_or_url) . 'winc w'
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#lang#SilentUpdate(1, 1)
+ let position = eclim#util#GetCurrentElementPosition()
+ let offset = substitute(position, '\(.*\);\(.*\)', '\1', '')
+ let length = substitute(position, '\(.*\);\(.*\)', '\2', '')
+
+ exec curwin . 'winc w'
+
+ let command = s:command_element_doc
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<length>', length, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ else
+ let command = s:command_doc_link
+ let command = substitute(command, '<url>', a:bufnr_or_url, '')
+ endif
+
+ let result = eclim#Execute(command)
+ if type(result) == g:DICT_TYPE
+ if !exists('b:eclim_javadoc_stack')
+ let b:eclim_javadoc_stack = []
+ let b:eclim_javadoc_index = -1
+ elseif b:eclim_javadoc_index >= 0
+ let b:eclim_javadoc_stack = b:eclim_javadoc_stack[:b:eclim_javadoc_index]
+ endif
+ call add(b:eclim_javadoc_stack, result)
+ let b:eclim_javadoc_index += 1
+ let b:eclim_javadoc = result
+
+ setlocal modifiable
+ call append(0, split(result.text, '\n'))
+ retab
+ if getline('$') =~ '^\s*$'
+ $,$delete _
+ endif
+ call cursor(1, 1)
+
+ elseif type(result) == g:STRING_TYPE
+ if result == ''
+ call eclim#util#EchoWarning('No javadoc found.')
+ else
+ call eclim#util#EchoError(result)
+ endif
+
+ return
+ endif
+
+ setlocal wrap
+ setlocal nomodifiable
+ setlocal nolist
+ setlocal noswapfile
+ setlocal nobuflisted
+ setlocal buftype=nofile
+ setlocal bufhidden=delete
+ setlocal conceallevel=2 concealcursor=ncv
+
+ set ft=javadoc_preview
+ hi link javadocPreviewLink Label
+ syntax match javadocPreviewLinkStart contained /|/ conceal
+ syntax match javadocPreviewLinkEnd contained /\[\d\+\]|/ conceal
+ syntax region javadocPreviewLink start="|" end="" concealends
+ syntax match javadocPreviewLink /|.\{-}\[\d\+\]|/
+ \ contains=JavadocPreviewLinkStart,JavadocPreviewLinkEnd
+
+ nnoremap <silent> <buffer> <cr> :call eclim#java#doc#PreviewLink()<cr>
+ nnoremap <silent> <buffer> <c-]> :call eclim#java#doc#PreviewLink()<cr>
+ nnoremap <silent> <buffer> <c-o> :call eclim#java#doc#PreviewHistory(-1)<cr>
+ nnoremap <silent> <buffer> <c-i> :call eclim#java#doc#PreviewHistory(1)<cr>
+endfunction " }}}
+
+function! eclim#java#doc#PreviewLink() " {{{
+ let line = getline('.')
+ let cnum = col('.')
+ if line[cnum - 1] == '|'
+ let cnum += cnum > 1 && line[cnum - 2] == ']' ? -1 : 1
+ endif
+ let text = substitute(line, '.*|\(.\{-}\%' . cnum . 'c.\{-}\)|.*', '\1', '')
+ if text == line || text !~ '\[\d\+]$'
+ return
+ endif
+
+ exec 'let index = ' . substitute(text, '.*\[\(\d\+\)\]$', '\1', '')
+ if !exists('b:eclim_javadoc') || len(b:eclim_javadoc.links) <= index
+ return
+ endif
+
+ let url = b:eclim_javadoc.links[index].href
+ if url =~ '^eclipse-javadoc:'
+ exec 'pedit +:call\ eclim#java#doc#PreviewOpen("' . url . '") [javadoc]'
+ else
+ call eclim#web#OpenUrl(url)
+ endif
+endfunction " }}}
+
+function! eclim#java#doc#PreviewHistory(offset) " {{{
+ if !exists('b:eclim_javadoc_stack')
+ return
+ endif
+
+ let index = b:eclim_javadoc_index + a:offset
+ if index < 0 || index > len(b:eclim_javadoc_stack) -1
+ return
+ endif
+
+ let result = b:eclim_javadoc_stack[index]
+ let b:eclim_javadoc = result
+ let b:eclim_javadoc_index = index
+
+ setlocal modifiable
+ 1,$delete _
+ call append(0, split(result.text, '\n'))
+ retab
+ if getline('$') =~ '^\s*$'
+ $,$delete _
+ endif
+ setlocal nomodifiable
+ call cursor(1, 1)
+endfunction " }}}
+
+function! eclim#java#doc#Javadoc(bang, ...) " {{{
+ " Run javadoc for all, or the supplied, source files.
+ " Optional args:
+ " file, file, file, ...: one ore more source files.
+
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let project_path = eclim#project#util#GetCurrentProjectRoot()
+ let project = eclim#project#util#GetCurrentProjectName()
+ let args = '-p "' . project . '"'
+
+ if len(a:000) > 0 && (len(a:000) > 1 || a:000[0] != '')
+ let args .= ' -f "' . join(a:000, ' ') . '"'
+ endif
+
+ let cwd = getcwd()
+ try
+ exec 'lcd ' . escape(project_path, ' ')
+ call eclim#util#MakeWithCompiler('eclim_javadoc', a:bang, args)
+ finally
+ exec 'lcd ' . escape(cwd, ' ')
+ endtry
+endfunction " }}}
+
+function! eclim#java#doc#CommandCompleteJavadoc(argLead, cmdLine, cursorPos) " {{{
+ let dir = eclim#project#util#GetCurrentProjectRoot()
+
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let command = substitute(s:command_source_dirs, '<project>', project, '')
+ let result = eclim#Execute(command)
+ let paths = []
+ if result != '' && result != '0'
+ let paths = map(split(result, "\n"),
+ \ "eclim#project#util#GetProjectRelativeFilePath(v:val)")
+ endif
+
+ let results = []
+
+ if argLead !~ '^\s*$'
+ let follow = 0
+ for path in paths
+ if argLead =~ '^' . path
+ let follow = 1
+ break
+ elseif path =~ '^' . argLead
+ call add(results, path)
+ endif
+ endfor
+
+ if follow
+ let results = split(eclim#util#Glob(dir . '/' . argLead . '*', 1), '\n')
+ call filter(results, "isdirectory(v:val) || v:val =~ '\\.java$'")
+ call map(results, "substitute(v:val, '\\', '/', 'g')")
+ call map(results, 'isdirectory(v:val) ? v:val . "/" : v:val')
+ call map(results, 'substitute(v:val, dir, "", "")')
+ call map(results, 'substitute(v:val, "^\\(/\\|\\\\\\)", "", "g")')
+ call map(results, "substitute(v:val, ' ', '\\\\ ', 'g')")
+ endif
+ else
+ let results = paths
+ endif
+
+ return eclim#util#ParseCommandCompletionResults(argLead, results)
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/hierarchy.vim b/vim/eclim/autoload/eclim/java/hierarchy.vim
@@ -0,0 +1,147 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/hierarchy.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists('g:EclimJavaHierarchyDefaultAction')
+ let g:EclimJavaHierarchyDefaultAction = g:EclimDefaultFileOpenAction
+endif
+" }}}
+
+" Script Variables {{{
+let s:command_hierarchy =
+ \ '-command java_hierarchy -p "<project>" -f "<file>" -o <offset> -e <encoding>'
+
+" }}}
+
+" Hierarchy() {{{
+function! eclim#java#hierarchy#Hierarchy()
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:command_hierarchy
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', eclim#util#GetOffset(), '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ let result = eclim#Execute(command)
+ if type(result) != g:DICT_TYPE
+ return
+ endif
+
+ let lines = []
+ let info = []
+ call s:FormatHierarchy(result, lines, info, '')
+ call eclim#util#TempWindow('[Hierarchy]', lines)
+ set ft=java
+
+ setlocal modifiable noreadonly
+ call append(line('$'), ['', '" use ? to view help'])
+ setlocal nomodifiable readonly
+ syntax match Comment /^".*/
+
+ let b:hierarchy_info = info
+ call eclim#util#Echo(b:hierarchy_info[line('.') - 1])
+
+ augroup eclim_java_hierarchy
+ autocmd!
+ autocmd CursorMoved <buffer>
+ \ if line('.') <= len(b:hierarchy_info) |
+ \ call eclim#util#Echo(b:hierarchy_info[line('.') - 1]) |
+ \ else |
+ \ echo '' |
+ \ endif
+ augroup END
+
+ nnoremap <buffer> <silent> <cr>
+ \ :call <SID>Open(g:EclimJavaHierarchyDefaultAction)<cr>
+ nnoremap <buffer> <silent> E :call <SID>Open('edit')<cr>
+ nnoremap <buffer> <silent> S :call <SID>Open('split')<cr>
+ nnoremap <buffer> <silent> T :call <SID>Open("tablast \| tabnew")<cr>
+
+ " assign to buffer var to get around weird vim issue passing list containing
+ " a string w/ a '<' in it on execution of mapping.
+ let b:hierarchy_help = [
+ \ '<cr> - open file with default action',
+ \ 'E - open with :edit',
+ \ 'S - open in a new split window',
+ \ 'T - open in a new tab',
+ \ ]
+ nnoremap <buffer> <silent> ?
+ \ :call eclim#help#BufferHelp(b:hierarchy_help, 'vertical', 40)<cr>
+endfunction " }}}
+
+" s:FormatHierarchy(hierarchy, lines, indent) {{{
+function! s:FormatHierarchy(hierarchy, lines, info, indent)
+ call add(a:lines, a:indent . a:hierarchy.name)
+ call add(a:info, a:hierarchy.qualified)
+ let indent = eclim#util#GetIndent(1)
+ for child in a:hierarchy.children
+ call s:FormatHierarchy(child, a:lines, a:info, a:indent . indent)
+ endfor
+endfunction " }}}
+
+" s:Open(action) {{{
+function! s:Open(action)
+ let line = line('.')
+ if line > len(b:hierarchy_info)
+ return
+ endif
+
+ let type = b:hierarchy_info[line - 1]
+ " go to the buffer that initiated the hierarchy
+ exec b:winnr . 'winc w'
+
+ " source the search plugin if necessary
+ if !exists("g:EclimJavaSearchSingleResult")
+ runtime autoload/eclim/java/search.vim
+ endif
+
+ let action = a:action
+ let filename = expand('%:p')
+ if exists('b:filename')
+ let filename = b:filename
+ if !eclim#util#GoToBufferWindow(b:filename)
+ " if the file is no longer open, open it
+ silent! exec action . ' ' . b:filename
+ let action = 'edit'
+ endif
+ endif
+
+ if line != 1
+ let saved = g:EclimJavaSearchSingleResult
+ try
+ let g:EclimJavaSearchSingleResult = action
+ if eclim#java#search#SearchAndDisplay('java_search', '-x declarations -p ' . type)
+ let b:filename = filename
+ endif
+ finally
+ let g:EclimJavaSearchSingleResult = saved
+ endtry
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/impl.vim b/vim/eclim/autoload/eclim/java/impl.vim
@@ -0,0 +1,341 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/impl.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Varables {{{
+ let s:command_constructor =
+ \ '-command java_constructor -p "<project>" -f "<file>" -o <offset> -e <encoding>'
+ let s:command_properties =
+ \ '-command java_bean_properties -p "<project>" -f "<file>" ' .
+ \ '-o <offset> -e <encoding> -t <type> -r <properties> <indexed>'
+ let s:command_impl =
+ \ '-command java_impl -p "<project>" -f "<file>" -o <offset> -e <encoding>'
+ let s:command_impl_insert =
+ \ '-command java_impl -p "<project>" -f "<file>" -t "<type>" ' .
+ \ '-s "<superType>" <methods>'
+ let s:command_delegate =
+ \ '-command java_delegate -p "<project>" -f "<file>" -o <offset> -e <encoding>'
+ let s:command_delegate_insert =
+ \ '-command java_delegate -p "<project>" -f "<file>" -v "<type>" ' .
+ \ '-s "<superType>" <methods>'
+
+
+ let s:no_properties =
+ \ 'Unable to find property at current cursor position: ' .
+ \ 'Not on a field declaration or possible java syntax error.'
+ let s:cross_type_selection = "Visual selection is currently limited to methods of one super type at a time."
+" }}}
+
+function! eclim#java#impl#Constructor(first, last, bang) " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ call eclim#lang#SilentUpdate()
+
+ let properties = a:last == 1 ? [] :
+ \ eclim#java#util#GetSelectedFields(a:first, a:last)
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+
+ let command = s:command_constructor
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', eclim#util#GetOffset(), '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ if a:bang == ''
+ let command .= ' -s'
+ endif
+ if len(properties) > 0
+ let command .= ' -r ''' . substitute(string(properties), "'", '"', 'g') . ''''
+ endif
+
+ let result = eclim#Execute(command)
+ if type(result) == g:STRING_TYPE && result != ''
+ call eclim#util#EchoError(result)
+ return
+ endif
+
+ if result != "0"
+ call eclim#util#Reload({'retab': 1})
+ write
+ endif
+endfunction " }}}
+
+function! eclim#java#impl#GetterSetter(first, last, bang, type) " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ call eclim#lang#SilentUpdate()
+
+ let properties = eclim#java#util#GetSelectedFields(a:first, a:last)
+
+ if len(properties) == 0
+ call eclim#util#EchoError(s:no_properties)
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let indexed = a:bang != '' ? '-i' : ''
+
+ let command = s:command_properties
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', eclim#util#GetOffset(), '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ let command = substitute(command, '<type>', a:type, '')
+ let command = substitute(command, '<properties>', join(properties, ','), '')
+ let command = substitute(command, '<indexed>', indexed, '')
+
+ let result = eclim#Execute(command)
+ if result != "0"
+ call eclim#util#Reload({'retab': 1})
+ write
+ endif
+endfunction " }}}
+
+function! eclim#java#impl#Impl() " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ call eclim#lang#SilentUpdate()
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let offset = eclim#util#GetCurrentElementOffset()
+
+ let command = s:command_impl
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+
+ call eclim#java#impl#ImplWindow(command)
+endfunction " }}}
+
+function! eclim#java#impl#ImplWindow(command) " {{{
+ if (eclim#java#impl#Window(a:command, "impl"))
+ nnoremap <silent> <buffer> <cr> :call <SID>AddImpl(0)<cr>
+ vnoremap <silent> <buffer> <cr> :<C-U>call <SID>AddImpl(1)<cr>
+ endif
+endfunction " }}}
+
+function! eclim#java#impl#ImplWindowFolding() " {{{
+ setlocal foldmethod=syntax
+ setlocal foldlevel=99
+endfunction " }}}
+
+function! eclim#java#impl#Delegate() " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ call eclim#lang#SilentUpdate()
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let offset = eclim#util#GetCurrentElementOffset()
+ let encoding = eclim#util#GetEncoding()
+
+ let command = s:command_delegate
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<encoding>', encoding, '')
+
+ call eclim#java#impl#DelegateWindow(command)
+endfunction " }}}
+
+function! eclim#java#impl#DelegateWindow(command) " {{{
+ if (eclim#java#impl#Window(a:command, "delegate"))
+ nnoremap <silent> <buffer> <cr> :call <SID>AddDelegate(0)<cr>
+ vnoremap <silent> <buffer> <cr> :<C-U>call <SID>AddDelegate(1)<cr>
+ endif
+endfunction " }}}
+
+function! eclim#java#impl#Add(command, function, visual) " {{{
+ let winnr = bufwinnr(bufnr('^' . b:filename))
+ " src window is not longer open.
+ if winnr == -1
+ call eclim#util#EchoError(b:filename . ' no longer found in an open window.')
+ return
+ endif
+
+ if a:visual
+ let start = line("'<")
+ let end = line("'>")
+ endif
+
+ let superType = ""
+ let methods = []
+ " non-visual mode or only one line selected
+ if !a:visual || start == end
+ " not a valid selection
+ if line('.') == 1 || getline('.') =~ '^\(\s*//\|package\|$\|}\)'
+ return
+ endif
+
+ let line = getline('.')
+ if line =~ '^\s*throws'
+ let line = getline(line('.') - 1)
+ endif
+ " on a method line
+ if line =~ '^\s\+'
+ call add(methods, s:MethodSig(line))
+ let ln = search('^\w', 'bWn')
+ if ln > 0
+ let superType = substitute(getline(ln), '.*\s\(.*\) {', '\1', '')
+ endif
+ " on a type line
+ else
+ let superType = substitute(line, '.*\s\(.*\) {', '\1', '')
+ endif
+
+ " visual mode
+ else
+ let pos = getpos('.')
+ let index = start
+ while index <= end
+ let line = getline(index)
+ if line =~ '^\s*\($\|throws\|package\)'
+ " do nothing
+ " on a method line
+ elseif line =~ '^\s\+'
+ call add(methods, s:MethodSig(line))
+ call cursor(index, 1)
+ let ln = search('^\w', 'bWn')
+ if ln > 0
+ let super = substitute(getline(ln), '.*\s\(.*\) {', '\1', '')
+ if superType != "" && super != superType
+ call eclim#util#EchoError(s:cross_type_selection)
+ call setpos('.', pos)
+ return
+ endif
+ let superType = super
+ endif
+ " on a type line
+ else
+ let super = substitute(line, '.*\s\(.*\) {', '\1', '')
+ if superType != "" && super != superType
+ call eclim#util#EchoError(s:cross_type_selection)
+ call setpos('.', pos)
+ return
+ endif
+ let superType = super
+ endif
+ call setpos('.', pos)
+
+ let index += 1
+ endwhile
+
+ if superType == ""
+ return
+ endif
+ endif
+
+ " search up for the nearest package
+ let ln = search('^package', 'bWn')
+ if ln > 0
+ let package = substitute(getline(ln), '.*\s\(.*\);', '\1', '')
+ let superType = package . '.' . substitute(superType, '<.\{-}>', '', 'g')
+ endif
+
+ let type = getline(1)
+ let impl_winnr = winnr()
+ exec winnr . "winc w"
+ call eclim#lang#SilentUpdate()
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+
+ let command = a:command
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<type>', type, '')
+ let command = substitute(command, '<superType>', superType, '')
+ if len(methods)
+ let json = substitute(string(methods), "'", '"', 'g')
+ let command = substitute(command, '<methods>', '-m ''' . json . '''', '')
+ else
+ let command = substitute(command, '<methods>', '', '')
+ endif
+
+ call a:function(command)
+
+ noautocmd exec winnr . "winc w"
+ call eclim#util#Reload({'retab': 1})
+ write
+ noautocmd exec impl_winnr . "winc w"
+endfunction " }}}
+
+function! eclim#java#impl#Window(command, name) " {{{
+ let name = eclim#project#util#GetProjectRelativeFilePath() . '_' . a:name
+ let project = eclim#project#util#GetCurrentProjectName()
+ let result = eclim#Execute(a:command, {'project': project})
+ if type(result) == g:STRING_TYPE
+ call eclim#util#EchoError(result)
+ return
+ endif
+ if type(result) != g:DICT_TYPE
+ return
+ endif
+
+ let content = [result.type]
+ for super in result.superTypes
+ call add(content, '')
+ call add(content, 'package ' . super.packageName . ';')
+ call add(content, super.signature . ' {')
+ for method in super.methods
+ let signature = split(method, '\n')
+ let content += map(signature, '"\t" . v:val')
+ endfor
+ call add(content, '}')
+ endfor
+
+ call eclim#util#TempWindow(name, content, {'preserveCursor': 1})
+ setlocal ft=java
+ call eclim#java#impl#ImplWindowFolding()
+ return 1
+endfunction " }}}
+
+function! s:AddImpl(visual) " {{{
+ call eclim#java#impl#Add
+ \ (s:command_impl_insert, function("eclim#java#impl#ImplWindow"), a:visual)
+endfunction " }}}
+
+function! s:AddDelegate(visual) " {{{
+ call eclim#java#impl#Add
+ \ (s:command_delegate_insert, function("eclim#java#impl#DelegateWindow"), a:visual)
+endfunction " }}}
+
+function! s:MethodSig(line) " {{{
+ let sig = substitute(a:line, '.*\s\(\w\+(.*\)', '\1', '')
+ let sig = substitute(sig, ',\s', ',', 'g')
+ let sig = substitute(sig, '<.\{-}>', '', 'g')
+ return sig
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/import.vim b/vim/eclim/autoload/eclim/java/import.vim
@@ -0,0 +1,140 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/import.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+let s:command_import =
+ \ '-command java_import -p "<project>" -f "<file>" -o <offset> -e <encoding>'
+let s:command_organize =
+ \ '-command java_import_organize -p "<project>" -f "<file>" -o <offset> -e <encoding>'
+" }}}
+
+function! eclim#java#import#Import(...) " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ if !a:0
+ let name = expand('<cword>')
+ if !eclim#java#util#IsValidIdentifier(name) ||
+ \ eclim#java#util#IsKeyword(name)
+ call eclim#util#EchoError("'" . name . "' not a classname.")
+ return
+ endif
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#lang#SilentUpdate()
+ let offset = eclim#util#GetOffset()
+ let command = s:command_import
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ if a:0
+ let command .= ' -t ' . a:1
+ endif
+ let result = eclim#Execute(command)
+
+ if type(result) == g:STRING_TYPE
+ call eclim#util#EchoError(result)
+ return
+ endif
+
+ if type(result) == g:DICT_TYPE
+ call eclim#util#Reload({'pos': [result.line, result.column]})
+ call eclim#lang#UpdateSrcFile('java', 1)
+ if result.offset != offset
+ call eclim#util#Echo('Imported ' . (a:0 ? a:1 : ''))
+ endif
+ return
+ endif
+
+ if type(result) != g:LIST_TYPE
+ return
+ endif
+
+ let choice = eclim#java#import#ImportPrompt(result)
+ if choice != ''
+ call eclim#java#import#Import(choice)
+ endif
+endfunction " }}}
+
+function! eclim#java#import#OrganizeImports(...) " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#lang#SilentUpdate()
+ let offset = eclim#util#GetOffset()
+ let command = s:command_organize
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ if a:0
+ let command .= ' -t ' . join(a:1, ',')
+ endif
+ let result = eclim#Execute(command)
+
+ if type(result) == g:STRING_TYPE
+ call eclim#util#EchoError(result)
+ return
+ endif
+
+ if type(result) == g:DICT_TYPE
+ call eclim#util#Reload({'pos': [result.line, result.column]})
+ call eclim#lang#UpdateSrcFile('java', 1)
+ return
+ endif
+
+ if type(result) != g:LIST_TYPE
+ return
+ endif
+
+ let chosen = []
+ for choices in result
+ let choice = eclim#java#import#ImportPrompt(choices)
+ if choice == ''
+ return
+ endif
+ call add(chosen, choice)
+ endfor
+
+ if len(chosen)
+ call eclim#java#import#OrganizeImports(chosen)
+ endif
+endfunction " }}}
+
+function! eclim#java#import#ImportPrompt(choices) " {{{
+ " prompt the user to choose the class to import.
+ let response = eclim#util#PromptList("Choose the class to import", a:choices)
+ if response == -1
+ return ''
+ endif
+
+ return get(a:choices, response)
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/junit.vim b/vim/eclim/autoload/eclim/java/junit.vim
@@ -0,0 +1,247 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/junit.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+let s:command_junit = '-command java_junit -p "<project>"'
+let s:command_tests = '-command java_junit_tests -p "<project>"'
+let s:command_find_test =
+ \ '-command java_junit_find_test -p "<project>" -f "<file>" ' .
+ \ '-o <offset> -e <encoding>'
+let s:command_impl = '-command java_junit_impl -p "<project>" -f "<file>"'
+let s:command_insert =
+ \ '-command java_junit_impl -p "<project>" -f "<file>" ' .
+ \ '-t "<type>" -s "<superType>" <methods>'
+" }}}
+
+function! eclim#java#junit#JUnit(test, bang) " {{{
+ let project = eclim#project#util#GetCurrentProjectName()
+ if project == '' && exists('b:project')
+ let project = b:project
+ endif
+
+ if project == ''
+ call eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let command = s:command_junit
+ let command = substitute(command, '<project>', project, '')
+ if a:test != ''
+ if a:test == '%'
+ let command .= ' -f "' . eclim#project#util#GetProjectRelativeFilePath() . '"'
+ elseif a:test != '*'
+ let command .= ' -t "' . a:test . '"'
+ endif
+ else
+ let command .= ' -f "' . eclim#project#util#GetProjectRelativeFilePath() . '"'
+ let command .= ' -o ' . eclim#util#GetOffset()
+ let command .= ' -e ' . eclim#util#GetEncoding()
+ endif
+
+ let curbuf = bufnr('%')
+ let result = eclim#Execute(command, {'project': project, 'exec': 1, 'raw': 1})
+ let results = split(substitute(result, "^\n*", '', 'g'), "\n")
+ call eclim#util#TempWindow('[JUnit Output]', results)
+ let b:project = project
+
+ if exists(":JUnit") != 2
+ command -buffer -nargs=? -complete=customlist,eclim#java#junit#CommandCompleteTest
+ \ JUnit :call eclim#java#junit#JUnit('<args>', '<bang>')
+ endif
+
+ exec bufwinnr(curbuf) . 'winc w'
+endfunction " }}}
+
+function! eclim#java#junit#JUnitFindTest() " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ runtime eclim/autoload/eclim/java/search.vim
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#lang#SilentUpdate()
+ let command = s:command_find_test
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', eclim#util#GetOffset(), '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ let result = eclim#Execute(command)
+ if type(result) == g:STRING_TYPE
+ call eclim#util#EchoError(result)
+ return
+ endif
+
+ if type(result) != g:DICT_TYPE
+ return
+ endif
+
+ call eclim#util#SetLocationList(eclim#util#ParseLocationEntries([result]))
+ let entry = getloclist(0)[0]
+ let name = substitute(bufname(entry.bufnr), '\', '/', 'g')
+ if g:EclimJavaSearchSingleResult != 'lopen'
+ call eclim#util#GoToBufferWindowOrOpen(name, g:EclimJavaSearchSingleResult)
+ call eclim#util#SetLocationList(eclim#util#ParseLocationEntries([result]))
+ call eclim#display#signs#Update()
+ call cursor(entry.lnum, entry.col)
+ else
+ exec 'lopen ' . g:EclimLocationListHeight
+ endif
+endfunction " }}}
+
+function! eclim#java#junit#JUnitResult(test) " {{{
+ " Argument test can be one of the following:
+ " Empty string: Use the current file to determine the test result file.
+ " Class name of a test: Locate the results for class (ex. 'TestMe').
+ " The results dir relative results file name: TEST-org.foo.TestMe.xml
+
+ let path = s:GetResultsDir()
+ if path == ''
+ call eclim#util#EchoWarning(
+ \ "Output directory setting for 'junit' not set. " .
+ \ "Use :EclimSettings or :ProjectSettings to set it.")
+ return
+ endif
+
+ if a:test != ''
+ let file = a:test
+ if file !~ '^TEST-'
+ let file = '*' . file
+ endif
+ else
+ let file = substitute(eclim#java#util#GetFullyQualifiedClassname(), '\.', '/', 'g')
+ endif
+
+ if file !~ '^TEST-'
+ let file = substitute(file, '\/', '.', 'g')
+ let file = 'TEST-' . file . '.xml'
+ endif
+
+ let found = eclim#util#Globpath(path, file)
+
+ " try text version if xml not found.
+ if found == ""
+ let file = fnamemodify(file, ':r') . '.txt'
+ let found = eclim#util#Globpath(path, file)
+ endif
+
+ if found != ""
+ let filename = expand('%:p')
+ exec "below split " . escape(found, ' ')
+
+ augroup temp_window
+ autocmd! BufWinLeave <buffer>
+ call eclim#util#GoToBufferWindowRegister(filename)
+ augroup END
+
+ return
+ endif
+ call eclim#util#Echo("Test result file not found for: " . fnamemodify(file, ':r'))
+endfunction " }}}
+
+function! eclim#java#junit#JUnitImpl() " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ call eclim#lang#SilentUpdate()
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:command_impl
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ call eclim#java#junit#JUnitImplWindow(command)
+endfunction " }}}
+
+function! eclim#java#junit#JUnitImplWindow(command) " {{{
+ if (eclim#java#impl#Window(a:command, "impl"))
+ nnoremap <silent> <buffer> <cr> :call <SID>AddTestImpl(0)<cr>
+ vnoremap <silent> <buffer> <cr> :<C-U>call <SID>AddTestImpl(1)<cr>
+ endif
+endfunction " }}}
+
+function! s:AddTestImpl(visual) " {{{
+ call eclim#java#impl#Add
+ \ (s:command_insert, function("eclim#java#junit#JUnitImplWindow"), a:visual)
+endfunction " }}}
+
+function! s:GetResultsDir() " {{{
+ let path = eclim#project#util#GetProjectSetting("org.eclim.java.junit.output_dir")
+ if type(path) == g:NUMBER_TYPE
+ return
+ endif
+
+ let root = eclim#project#util#GetCurrentProjectRoot()
+ let path = substitute(path, '<project>', root, '')
+ let path = path != '' && path !~ '/$' ? path . '/' : path
+ if path != '' && has('win32unix')
+ let path = eclim#cygwin#CygwinPath(path)
+ endif
+ return path
+endfunction " }}}
+
+function! eclim#java#junit#CommandCompleteTest(argLead, cmdLine, cursorPos) " {{{
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ if project == '' && exists('b:project')
+ let project = b:project
+ endif
+ if project == ''
+ return []
+ endif
+
+ let command = s:command_tests
+ let command = substitute(command, '<project>', project, '')
+ let results = eclim#Execute(command)
+ if type(results) != g:LIST_TYPE
+ return []
+ endif
+
+ call filter(results, 'v:val =~ "' . argLead . '"')
+ return results
+endfunction " }}}
+
+function! eclim#java#junit#CommandCompleteResult(argLead, cmdLine, cursorPos) " {{{
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+
+ let path = s:GetResultsDir()
+ if path == ''
+ call eclim#util#EchoWarning(
+ \ "Output directory setting for 'junit' not set. " .
+ \ "Use :EclimSettings or :ProjectSettings to set it.")
+ return []
+ endif
+
+ let results = split(eclim#util#Globpath(path, '*'), '\n')
+ call map(results, 'fnamemodify(v:val, ":r:e")')
+ call filter(results, 'v:val =~ "^' . argLead . '"')
+
+ return results
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/logging.vim b/vim/eclim/autoload/eclim/java/logging.vim
@@ -0,0 +1,127 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/logging.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+function! eclim#java#logging#LoggingInit(var) " {{{
+ let char = nr2char(getchar())
+ " only execute if the user types a '.' for a method call and if the logger
+ " is not already present.
+ if char == '.' && s:InitLoggingSettings() &&
+ \ !search('\(final\|static\)\>.\{-}\<Log\(ger\)\?\s', 'n')
+ let line = line('.')
+ let col = col('.')
+ let position = eclim#java#util#GetClassDeclarationPosition(1)
+ if position
+ let logger = s:logger
+ let logger = substitute(logger, '\${class}', eclim#java#util#GetClassname(), '')
+ let logger = substitute(logger, '\${var}', a:var, '')
+ if strlen(logger) > &textwidth && logger !~ '\n'
+ let logger = substitute(logger,
+ \ '\(.*\)\s\(.*\)', '\1\n' . eclim#util#GetIndent(2) . '\2', '')
+ endif
+
+ let position = search('{')
+ let lines = split(logger, '\n')
+ let offset = len(lines) + 1
+ call append(position, '')
+ call append(position, lines)
+ call cursor(line + offset, col)
+ for import in s:logger_imports
+ call eclim#java#import#Import(import)
+ endfor
+ endif
+ endif
+ return char
+endfunction " }}}
+
+function! s:InitLoggingSettings() " {{{
+ let s:EclimLoggingImpl =
+ \ eclim#project#util#GetProjectSetting("org.eclim.java.logging.impl")
+ if type(s:EclimLoggingImpl) == g:NUMBER_TYPE || s:EclimLoggingImpl == '0'
+ unlet s:EclimLoggingImpl
+ return
+ endif
+
+ let indent = eclim#util#GetIndent(1)
+ if s:EclimLoggingImpl == "commons-logging"
+ let s:logger = indent .
+ \ "private static final Log ${var} = LogFactory.getLog(${class}.class);"
+ let s:logger_imports = [
+ \ "org.apache.commons.logging.Log",
+ \ "org.apache.commons.logging.LogFactory"]
+ elseif s:EclimLoggingImpl == "slf4j"
+ let s:logger = indent .
+ \ "private static final Logger ${var} = LoggerFactory.getLogger(${class}.class);"
+ let s:logger_imports = ["org.slf4j.Logger", "org.slf4j.LoggerFactory"]
+ elseif s:EclimLoggingImpl == "log4j"
+ let s:logger = indent .
+ \ "private static final Logger ${var} = Logger.getLogger(${class}.class);"
+ let s:logger_imports = ["org.apache.log4j.Logger"]
+ elseif s:EclimLoggingImpl == "jdk"
+ let s:logger = indent .
+ \ "private static final Logger ${var} = Logger.getLogger(${class}.class.getName());"
+ let s:logger_imports = ["java.util.logging.Logger"]
+ elseif s:EclimLoggingImpl == "custom"
+ let instance = eclim#client#nailgun#ChooseEclimdInstance()
+ if type(instance) != g:DICT_TYPE
+ return
+ endif
+
+ let name = eclim#project#util#GetProjectSetting("org.eclim.java.logging.template")
+ if type(name) == g:NUMBER_TYPE || name == ''
+ return
+ endif
+
+ let local = eclim#UserHome() . '/.eclim/resources/jdt/templates/' . name
+ let remote = substitute(instance.home, 'org.eclim_', 'org.eclim.jdt_', '') .
+ \ '/resources/templates/' . name
+ if filereadable(local)
+ let template = local
+ elseif filereadable(remote)
+ let template = remote
+ else
+ call eclim#util#EchoError(
+ \ "Custom logger template not found local or remote location:\n" .
+ \ " local: " . local . "\n" .
+ \ " remote: " . remote)
+ return
+ endif
+ let lines = readfile(template)
+ let s:logger_imports = lines[:]
+ call filter(s:logger_imports, "v:val =~ '^\\s*import\\>'")
+ call map(s:logger_imports,
+ \ "substitute(v:val, '^\\s*import\\>\\s*\\(.*\\);\\s*', '\\1', '')")
+ call filter(lines, "v:val !~ '\\(^\\s*$\\|^\\s*import\\>\\)'")
+ let s:logger = indent . join(lines, "\n" . indent)
+ elseif s:EclimLoggingImpl == ''
+ " no setting returned, probably not in a project, or user is attempting to
+ " disable this functionality for the current project.
+ return
+ else
+ echoe "Invalid logging implementation '" . s:EclimLoggingImpl . "' configured."
+ return
+ endif
+ return 1
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/maven.vim b/vim/eclim/autoload/eclim/java/maven.vim
@@ -0,0 +1,118 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+let s:update_command = '-command project_update -p "<project>" -b "<build>"'
+" }}}
+
+function! eclim#java#maven#SetClasspathVariable(cmd, variable, args) " {{{
+ let instance = eclim#client#nailgun#ChooseEclimdInstance()
+ if type(instance) != g:DICT_TYPE
+ return
+ endif
+
+ let workspace = instance.workspace
+
+ " maven 1.x
+ if a:cmd == 'Maven'
+ let prefs = workspace .
+ \ '/.metadata/.plugins/org.eclipse.jdt.core/pref_store.ini'
+ let command = a:cmd .
+ \ ' "-Dmaven.eclipse.workspace=' . workspace . '"' .
+ \ ' eclipse:add-maven-repo'
+
+ " maven 2.x
+ else
+ let prefs = workspace .
+ \ '/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs'
+ let command = a:cmd . ' ' . a:args .
+ \ ' "-Declipse.workspace=' . workspace . '"' .
+ \ ' eclipse:configure-workspace'
+ endif
+
+ call eclim#util#Exec(command)
+
+ if !v:shell_error
+ " the maven command edits the eclipse preference file directly, so in
+ " order to get the value in memory without restarting eclim, we read the
+ " value out and let the server set it again.
+ let winrestore = winrestcmd()
+
+ if filereadable(prefs)
+ silent exec 'sview ' . prefs
+ let line = search('org.eclipse.jdt.core.classpathVariable.' . a:variable, 'cnw')
+ let value = line ? substitute(getline(line), '.\{-}=\(.*\)', '\1', '') : ''
+ if line
+ call eclim#java#classpath#VariableCreate(a:variable, value)
+ endif
+
+ if substitute(bufname('%'), '\', '/', 'g') =~ prefs
+ close
+ exec winrestore
+ endif
+
+ if line
+ call eclim#util#Echo(a:variable . " classpath variable set to:\n" . value)
+ else
+ call eclim#util#EchoWarning(
+ \ "Unable to locate " . a:variable . " classpath variable.\n" .
+ \ "If it was successful set by maven, you may need to\n" .
+ \ "restart eclipse for the change to take affect.")
+ endif
+ else
+ call eclim#util#EchoWarning(
+ \ "Unable to read:\n" . prefs . "\n" .
+ \ "If the " . a:variable . " classpath variable was successfully set by maven\n" .
+ \ "you may need to restart eclipse for the change to take affect.")
+ endif
+ endif
+endfunction " }}}
+
+function! eclim#java#maven#UpdateClasspath() " {{{
+ " Updates the classpath on the server w/ the changes made to the current pom file.
+
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ " validate the xml first
+ if eclim#xml#validate#Validate(expand('%:p'), 0)
+ return
+ endif
+
+ let name = eclim#project#util#GetCurrentProjectName()
+ let command = s:update_command
+ let command = substitute(command, '<project>', name, '')
+ let command = substitute(command, '<build>', escape(expand('%:p'), '\'), '')
+ let result = eclim#Execute(command)
+
+ if type(result) == g:LIST_TYPE && len(result) > 0
+ let errors = eclim#util#ParseLocationEntries(
+ \ result, g:EclimValidateSortResults)
+ call eclim#util#SetLocationList(errors, 'r')
+ call eclim#util#EchoError(
+ \ "Operation contained errors. See location list for details (:lopen).")
+ else
+ call eclim#util#ClearLocationList()
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/refactor.vim b/vim/eclim/autoload/eclim/java/refactor.vim
@@ -0,0 +1,120 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Varables {{{
+ let s:command_rename = '-command java_refactor_rename ' .
+ \ '-p "<project>" -f "<file>" -o <offset> -e <encoding> -l <length> -n <name>'
+ let s:command_move = '-command java_refactor_move ' .
+ \ '-p "<project>" -f "<file>" -n <package>'
+" }}}
+
+function! eclim#java#refactor#Rename(name) " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let element = expand('<cword>')
+ if !eclim#java#util#IsValidIdentifier(element)
+ call eclim#util#EchoError
+ \ ("Element under the cursor is not a valid java identifier.")
+ return
+ endif
+
+ let line = getline('.')
+ let package_pattern = '^\s*package\s\+\(.*\%' . col('.') . 'c\w*\).*;'
+ if line =~ package_pattern
+ let element = substitute(line, package_pattern, '\1', '')
+ endif
+
+ let prompt = printf('Rename "%s" to "%s"', element, a:name)
+ let result = exists('g:EclimRefactorPromptDefault') ?
+ \ g:EclimRefactorPromptDefault : eclim#lang#RefactorPrompt(prompt)
+ if result <= 0
+ return
+ endif
+
+ " update the file before vim makes any changes.
+ call eclim#lang#SilentUpdate()
+ wall
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let position = eclim#util#GetCurrentElementPosition()
+ let offset = substitute(position, '\(.*\);\(.*\)', '\1', '')
+ let length = substitute(position, '\(.*\);\(.*\)', '\2', '')
+
+ let command = s:command_rename
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<length>', length, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ let command = substitute(command, '<name>', a:name, '')
+ " user chose preview at the prompt
+ if result == 2
+ let command .= ' -v'
+ call eclim#lang#RefactorPreview(command)
+ return
+ endif
+
+ call eclim#lang#Refactor(command)
+endfunction " }}}
+
+function! eclim#java#refactor#Move(package) " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let line = getline('.')
+ let package_pattern = '^\s*package\s\+\(.*\%' . col('.') . 'c\w*\).*;'
+ if line =~ package_pattern
+ let element = substitute(line, package_pattern, '\1', '')
+ endif
+
+ let name = eclim#java#util#GetClassname()
+ let package = eclim#java#util#GetPackage()
+ let prompt = printf('Move %s from "%s" to "%s"', name, package, a:package)
+ let result = exists('g:EclimRefactorPromptDefault') ?
+ \ g:EclimRefactorPromptDefault : eclim#lang#RefactorPrompt(prompt)
+ if result <= 0
+ return
+ endif
+
+ " update the file before vim makes any changes.
+ call eclim#lang#SilentUpdate()
+ wall
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:command_move
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<package>', a:package, '')
+ " user chose preview at the prompt
+ if result == 2
+ let command .= ' -v'
+ call eclim#lang#RefactorPreview(command)
+ return
+ endif
+ call eclim#lang#Refactor(command)
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/search.vim b/vim/eclim/autoload/eclim/java/search.vim
@@ -0,0 +1,409 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/search.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Varables {{{
+ if !exists("g:EclimJavaDocSearchSingleResult")
+ " possible values ('open', 'lopen')
+ let g:EclimJavaDocSearchSingleResult = "open"
+ endif
+
+ if !exists("g:EclimJavaSearchSingleResult")
+ " possible values ('split', 'edit', 'lopen')
+ let g:EclimJavaSearchSingleResult = g:EclimDefaultFileOpenAction
+ endif
+" }}}
+
+" Script Varables {{{
+ let s:search_src = "java_search"
+ let s:search_doc = "java_docsearch"
+ let s:search_element =
+ \ '-command <search> -n "<project>" -f "<file>" ' .
+ \ '-o <offset> -e <encoding> -l <length> <args>'
+ let s:search_pattern = '-command <search>'
+ let s:options = ['-p', '-t', '-x', '-s', '-i']
+ let s:contexts = ['all', 'declarations', 'implementors', 'references']
+ let s:scopes = ['all', 'project']
+ let s:types = [
+ \ 'annotation',
+ \ 'class',
+ \ 'classOrEnum',
+ \ 'classOrInterface',
+ \ 'constructor',
+ \ 'enum',
+ \ 'field',
+ \ 'interface',
+ \ 'method',
+ \ 'package',
+ \ 'type']
+
+ let s:search_alt_all = '\<<element>\>'
+ let s:search_alt_references = s:search_alt_all
+ let s:search_alt_implementors =
+ \ '\(implements\|extends\)\_[0-9A-Za-z,[:space:]]*\<<element>\>\_[0-9A-Za-z,[:space:]]*{'
+" }}}
+
+function! s:Search(command, ...) " {{{
+ " Executes a search.
+ " Usage closely resebles eclim command line client usage.
+ " When doing a non-pattern search the element under the cursor is searched for.
+ " Search for declarations of element under the cursor
+ " call s:Search("-x", "declarations")
+ " Search for references of HashMap
+ " call s:Search("-p", "HashM*", "-t", "class", "-x", "references")
+ " Or all the arguments can be passed in at once:
+ " call s:Search("-p 'HashM*' -t class -x references")
+
+ let argline = ""
+ let index = 1
+ while index <= a:0
+ if index != 1
+ let argline = argline . " "
+ endif
+ let argline = argline . a:{index}
+ let index = index + 1
+ endwhile
+
+ " check if pattern supplied without -p.
+ if argline !~ '^\s*-[a-z]' && argline !~ '^\s*$'
+ let argline = '-p ' . argline
+ endif
+
+ let in_project = eclim#project#util#IsCurrentFileInProject(0)
+
+ " element search
+ if argline !~ '-p\>'
+ if &ft != 'java'
+ call eclim#util#EchoWarning
+ \ ("Element searches only supported in java source files.")
+ return 0
+ endif
+
+ if !eclim#java#util#IsValidIdentifier(expand('<cword>'))
+ call eclim#util#EchoError
+ \ ("Element under the cursor is not a valid java identifier.")
+ return 0
+ endif
+
+ if !in_project
+ " build a pattern search and execute it
+ let results = s:SearchAlternate('-p ' . s:BuildPattern() . ' ' . argline, 1)
+ " kind of gross. if there was no alternate result and eclimd is not
+ " running, then make sure a message is echoed to the user so they know
+ " that eclimd not running *may* be the cause of no results.
+ if len(results) == 0 && !eclim#EclimAvailable()
+ return 0
+ endif
+ return results
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let position = eclim#util#GetCurrentElementPosition()
+ let offset = substitute(position, '\(.*\);\(.*\)', '\1', '')
+ let length = substitute(position, '\(.*\);\(.*\)', '\2', '')
+
+ let search_cmd = s:search_element
+ let search_cmd = substitute(search_cmd, '<project>', project, '')
+ let search_cmd = substitute(search_cmd, '<search>', a:command, '')
+ let search_cmd = substitute(search_cmd, '<file>', file, '')
+ let search_cmd = substitute(search_cmd, '<offset>', offset, '')
+ let search_cmd = substitute(search_cmd, '<encoding>', eclim#util#GetEncoding(), '')
+ let search_cmd = substitute(search_cmd, '<length>', length, '')
+ let search_cmd = substitute(search_cmd, '<args>', argline, '')
+
+ let result = eclim#Execute(search_cmd)
+
+ " pattern search
+ else
+ let project = eclim#project#util#GetCurrentProjectName()
+
+ " pattern search
+ let search_cmd = s:search_pattern
+ let search_cmd = substitute(search_cmd, '<search>', a:command, '')
+ if project != ''
+ let search_cmd .= ' -n "' . project . '"'
+ endif
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ if file != ''
+ let search_cmd .= ' -f "' . file . '"'
+ endif
+ let search_cmd .= ' ' . argline
+ " quote the search pattern
+ let search_cmd =
+ \ substitute(search_cmd, '\(.*-p\s\+\)\(.\{-}\)\(\s\|$\)\(.*\)', '\1"\2"\3\4', '')
+
+ let result = eclim#Execute(search_cmd)
+
+ if !in_project && filereadable(expand('%'))
+ return result + s:SearchAlternate(argline, 0)
+ endif
+ endif
+
+ return result
+endfunction " }}}
+
+function! s:SearchAlternate(argline, element) " {{{
+ " Alternate search for non-project src files using vimgrep and &path.
+
+ call eclim#util#EchoInfo("Executing alternate search...")
+ if a:argline =~ '-t'
+ call eclim#util#EchoError
+ \ ("Alternate search doesn't support the type (-t) option yet.")
+ return []
+ endif
+ let search_pattern = ""
+ if a:argline =~ '-x all'
+ let search_pattern = s:search_alt_all
+ elseif a:argline =~ '-x implementors'
+ let search_pattern = s:search_alt_implementors
+ elseif a:argline =~ '-x references'
+ let search_pattern = s:search_alt_references
+ endif
+
+ let pattern = substitute(a:argline, '.*-p\s\+\(.\{-}\)\(\s.*\|$\)', '\1', '')
+ let file_pattern = substitute(pattern, '\.', '/', 'g') . ".java"
+
+ " search relative to the current dir first.
+ let package_path = substitute(eclim#java#util#GetPackage(), '\.', '/', 'g')
+ let path = substitute(expand('%:p:h'), '\', '/', 'g')
+ let path = substitute(path, package_path, '', '')
+ let files = split(eclim#util#Globpath(path, "**/" . file_pattern), '\n')
+
+ " if none found, then search the path.
+ if len(files) == 0
+ let files = eclim#util#FindFileInPath(file_pattern, 1)
+ let path = ""
+ endif
+
+ let results = []
+
+ if len(files) > 0 && search_pattern != ''
+ " narrow down to, hopefully, a distribution path for a narrower search.
+ let response = eclim#util#PromptList(
+ \ "Multiple type matches. Please choose the relevant file.",
+ \ files, g:EclimInfoHighlight)
+ if response == -1
+ return
+ endif
+
+ let file = substitute(get(files, response), '\', '/', 'g')
+ if path == ""
+ let path = eclim#util#GetPathEntry(file)
+ endif
+ let path = escape(path, '/\')
+ let path = substitute(file, '\(' . path . '[/\\]\?.\{-}[/\\]\).*', '\1', '')
+ let pattern = substitute(pattern, '\*', '.\\\\{-}', 'g')
+ let search_pattern = substitute(search_pattern, '<element>', pattern, '')
+ let command = "vimgrep /" . search_pattern . "/gj " . path . "**/*.java"
+ silent! exec command
+
+ let loclist = getloclist(0)
+ for entry in loclist
+ let bufname = bufname(entry.bufnr)
+ let result = {
+ \ 'filename': bufname,
+ \ 'message': entry.text,
+ \ 'line': entry.lnum,
+ \ 'column': entry.col,
+ \ }
+ " when searching for implementors, prevent dupes from the somewhat
+ " greedy pattern search (may need some more updating post conversion to
+ " dict results).
+ if a:argline !~ '-x implementors' || !eclim#util#ListContains(results, result)
+ call add(results, result)
+ endif
+ endfor
+ elseif len(files) > 0
+ for file in files
+ let fully_qualified = eclim#java#util#GetPackage(file) . '.' .
+ \ eclim#java#util#GetClassname(file)
+ " if an element search, filter out results that are not imported.
+ if !a:element || eclim#java#util#IsImported(fully_qualified)
+ call add(results, {
+ \ 'filename': file,
+ \ 'message': fully_qualified,
+ \ 'line': 1,
+ \ 'column': 1,
+ \ })
+ endif
+ endfor
+ endif
+ call eclim#util#Echo(' ')
+ return results
+endfunction " }}}
+
+function! s:BuildPattern() " {{{
+ " Builds a pattern based on the cursors current position in the file.
+
+ let class = expand('<cword>')
+ " see if the classname element selected is fully qualified.
+ let line = getline('.')
+ let package =
+ \ substitute(line, '.*\s\([0-9A-Za-z._]*\)\.' . class . '\>.*', '\1', '')
+
+ " not fully qualified, so attempt to determine package from import.
+ if package == line
+ let package = eclim#java#util#GetPackageFromImport(class)
+
+ " maybe the element is the current class?
+ if package == ""
+ if eclim#java#util#GetClassname() == class
+ let package = eclim#java#util#GetPackage()
+ endif
+ endif
+ endif
+
+ if package != ""
+ return package . "." . class
+ endif
+ return class
+endfunction " }}}
+
+function! eclim#java#search#SearchAndDisplay(type, args) " {{{
+ " Execute a search and displays the results via quickfix.
+
+ " if running from a non java source file, no SilentUpdate needed.
+ if &ft == 'java'
+ call eclim#lang#SilentUpdate()
+ endif
+
+ let argline = a:args
+
+ " check if just a pattern was supplied.
+ if argline =~ '^\s*\w'
+ let argline = '-p ' . argline
+ endif
+
+ let results = s:Search(a:type, argline)
+ if type(results) != g:LIST_TYPE
+ return
+ endif
+ if !empty(results)
+ if a:type == 'java_search'
+ call eclim#util#SetLocationList(eclim#util#ParseLocationEntries(results))
+ let locs = getloclist(0)
+ " if only one result and it's for the current file, just jump to it.
+ " note: on windows the expand result must be escaped
+ if len(results) == 1 && locs[0].bufnr == bufnr('%')
+ if results[0].line != 1 && results[0].column != 1
+ lfirst
+ endif
+
+ " single result in another file.
+ elseif len(results) == 1 && g:EclimJavaSearchSingleResult != "lopen"
+ let entry = getloclist(0)[0]
+ let name = substitute(bufname(entry.bufnr), '\', '/', 'g')
+ call eclim#util#GoToBufferWindowOrOpen(name, g:EclimJavaSearchSingleResult)
+ call eclim#util#SetLocationList(eclim#util#ParseLocationEntries(results))
+ call eclim#display#signs#Update()
+ call cursor(entry.lnum, entry.col)
+ else
+ exec 'lopen ' . g:EclimLocationListHeight
+ endif
+ elseif a:type == 'java_docsearch'
+ let window_name = "javadoc_search_results"
+ let filename = expand('%:p')
+ call eclim#util#TempWindowClear(window_name)
+
+ if len(results) == 1 && g:EclimJavaDocSearchSingleResult == "open"
+ let entry = results[0]
+ call s:ViewDoc(entry)
+ else
+ call eclim#util#TempWindow(
+ \ window_name, results, {'height': g:EclimLocationListHeight})
+
+ nnoremap <silent> <buffer> <cr> :call <SID>ViewDoc()<cr>
+ augroup temp_window
+ autocmd! BufWinLeave <buffer>
+ call eclim#util#GoToBufferWindowRegister(filename)
+ augroup END
+ endif
+ endif
+ return 1
+ else
+ if argline =~ '-p '
+ let searchedFor = substitute(argline, '.*-p \(.\{-}\)\( .*\|$\)', '\1', '')
+ call eclim#util#EchoInfo("Pattern '" . searchedFor . "' not found.")
+ elseif &ft == 'java'
+ if !eclim#java#util#IsValidIdentifier(expand('<cword>'))
+ return
+ endif
+
+ let searchedFor = expand('<cword>')
+ call eclim#util#EchoInfo("No results for '" . searchedFor . "'.")
+ endif
+ endif
+endfunction " }}}
+
+function! s:ViewDoc(...) " {{{
+ " View the supplied file in a browser, or if none proved, the file under the
+ " cursor.
+ let url = a:0 > 0 ? a:1 : substitute(getline('.'), '\(.\{-}\)|.*', '\1', '')
+ call eclim#web#OpenUrl(url)
+endfunction " }}}
+
+function! eclim#java#search#CommandCompleteJavaSearch(argLead, cmdLine, cursorPos) " {{{
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+ if cmdLine =~ '-s\s\+[a-z]*$'
+ let scopes = deepcopy(s:scopes)
+ call filter(scopes, 'v:val =~ "^' . argLead . '"')
+ return scopes
+ elseif cmdLine =~ '-t\s\+[a-z]*$'
+ let types = deepcopy(s:types)
+ call filter(types, 'v:val =~ "^' . argLead . '"')
+ return types
+ elseif cmdLine =~ '-x\s\+[a-z]*$'
+ let contexts = deepcopy(s:contexts)
+ call filter(contexts, 'v:val =~ "^' . argLead . '"')
+ return contexts
+ elseif cmdLine =~ '\s\+[-]\?$'
+ let options = deepcopy(s:options)
+ let index = 0
+ for option in options
+ if a:cmdLine =~ option
+ call remove(options, index)
+ else
+ let index += 1
+ endif
+ endfor
+ return options
+ endif
+ return []
+endfunction " }}}
+
+function! eclim#java#search#FindClassDeclaration() " {{{
+ " Used by non java source files to find the declaration of a classname under
+ " the cursor.
+ let line = getline('.')
+ let class = substitute(line,
+ \ '.\{-}\([0-9a-zA-Z_.]*\%' . col('.') . 'c[0-9a-zA-Z_.]*\).*', '\1', '')
+ if class != line && class != '' && class =~ '^[a-zA-Z]'
+ call eclim#java#search#SearchAndDisplay(
+ \ 'java_search', '-t classOrInterface -p ' . class)
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/src.vim b/vim/eclim/autoload/eclim/java/src.vim
@@ -0,0 +1,88 @@
+" Author: Eric Van Dewoestine
+"
+" License: " {{{
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+ let s:format_command =
+ \ '-command java_format -p "<project>" -f "<file>" ' .
+ \ '-h <hoffset> -t <toffset> -e <encoding>'
+ let s:checkstyle_command = '-command java_checkstyle -p "<project>" -f "<file>"'
+" }}}
+
+function! eclim#java#src#Format(first, last) " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ call eclim#lang#SilentUpdate()
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+
+ let command = s:format_command
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let begin = eclim#util#GetOffset(a:first, 1)
+ let end = eclim#util#GetOffset(a:last, 1) + len(getline(a:last)) - 1
+ let command = substitute(command, '<hoffset>', begin, '')
+ let command = substitute(command, '<toffset>', end, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+
+ let result = eclim#Execute(command)
+ if result != "0"
+ call eclim#util#Reload({'retab': 1})
+ write
+ endif
+endfunction " }}}
+
+function! eclim#java#src#Checkstyle() " {{{
+ let project = eclim#project#util#GetCurrentProjectName()
+ if project != ""
+ let config =
+ \ eclim#project#util#GetProjectSetting('org.eclim.java.checkstyle.config')
+ if type(config) == g:NUMBER_TYPE
+ return
+ endif
+
+ if config == ''
+ call eclim#util#EchoWarning(
+ \ "Before invoking checkstyle, you must first configure the " .
+ \ "location of your\ncheckstyle config via the setting: " .
+ \ "'org.eclim.java.checkstyle.config'.")
+ return
+ endif
+
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:checkstyle_command
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+
+ let result = eclim#Execute(command)
+ if type(result) == g:LIST_TYPE && len(result) > 0
+ let errors = eclim#util#ParseLocationEntries(
+ \ result, g:EclimValidateSortResults)
+ call eclim#util#SetLocationList(errors)
+ else
+ call eclim#util#ClearLocationList('checkstyle')
+ endif
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/tools.vim b/vim/eclim/autoload/eclim/java/tools.vim
@@ -0,0 +1,310 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/tools.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+ let s:command_src_find = '-command java_src_find -p "<project>" -c "<classname>"'
+
+ let s:entry_match{'junit'} = 'Tests run:'
+ let s:entry_text_replace{'junit'} = '.*[junit] '
+ let s:entry_text_with{'junit'} = ''
+
+ let s:entry_match{'testng'} = 'eclim testng:'
+ let s:entry_text_replace{'testng'} = '.*eclim testng: .\{-}:'
+ let s:entry_text_with{'testng'} = ''
+
+ let s:open_console = 'Open jconsole'
+ let s:view_info = 'View Info'
+ let s:view_stacks = 'View Stacks'
+ let s:view_map = 'View Memory Map'
+ let s:args_main = 'Arguments To Main Method'
+ let s:args_vm = 'Arguments To JVM'
+
+ let s:supported_command = '\(' .
+ \ s:open_console . '\|' .
+ \ s:view_info . '\|' .
+ \ s:view_stacks . '\|' .
+ \ s:view_map .
+ \ '\)'
+
+ hi link JpsArguments Normal
+ hi link JpsViewAdditional Normal
+ hi JpsViewAdditional gui=underline,bold term=underline,bold cterm=underline,bold
+" }}}
+
+function! eclim#java#tools#MakeWithJavaBuildTool(compiler, bang, args) " {{{
+ augroup eclim_make_java_test
+ autocmd!
+ autocmd QuickFixCmdPost make
+ \ call eclim#java#tools#ResolveQuickfixResults(['junit', 'testng'])
+ augroup END
+
+ try
+ call eclim#util#MakeWithCompiler(a:compiler, a:bang, a:args)
+ finally
+ silent! autocmd! eclim_make_java_test
+ endtry
+endfunction " }}}
+
+function! eclim#java#tools#ResolveQuickfixResults(frameworks) " {{{
+ " Invoked after a :make to resolve any junit results in the quickfix entries.
+ let frameworks = type(a:frameworks) == g:LIST_TYPE ? a:frameworks : [a:frameworks]
+ let entries = getqflist()
+ let newentries = []
+ for entry in entries
+ let filename = bufname(entry.bufnr)
+ let text = entry.text
+
+ for framework in frameworks
+ if entry.text =~ s:entry_match{framework}
+ let filename = fnamemodify(filename, ':t')
+ let text = substitute(text,
+ \ s:entry_text_replace{framework}, s:entry_text_with{framework}, '')
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let command = s:command_src_find
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<classname>', filename, '')
+ let filename = eclim#Execute(command)
+ if filename == ''
+ " file not found.
+ continue
+ endif
+ endif
+ endfor
+
+ if !filereadable(filename)
+ continue
+ endif
+
+ let newentry = {
+ \ 'filename': filename,
+ \ 'lnum': entry.lnum,
+ \ 'col': entry.col,
+ \ 'type': entry.type,
+ \ 'text': text
+ \ }
+ call add(newentries, newentry)
+ endfor
+
+ call setqflist(newentries, 'r')
+
+ " vim is finicky about changing the quickfix list during a QuickFixCmdPost
+ " autocmd, so force a delayed reload of the quickfix results
+ call eclim#util#DelayedCommand('call setqflist(getqflist(), "r")')
+endfunction " }}}
+
+function! eclim#java#tools#Jps() " {{{
+ call eclim#util#Echo('Executing...')
+
+ let content = []
+ let processes = eclim#java#tools#GetJavaProcesses()
+ if len(processes) == 1 && string(processes[0]) == '0'
+ return
+ endif
+
+ for process in processes
+ if len(content) > 0
+ call add(content, "")
+ endif
+
+ call add(content, process.id . ' - ' . process.name)
+
+ if executable('jconsole')
+ call add(content, "\t" . s:open_console)
+ endif
+
+ if executable('jinfo')
+ call add(content, "\t" . s:view_info)
+ endif
+
+ if executable('jstack')
+ call add(content, "\t" . s:view_stacks)
+ endif
+
+ if executable('jmap')
+ call add(content, "\t" . s:view_map)
+ endif
+
+ call add(content, "")
+
+ call add(content, "\t" . s:args_main . " {")
+ let args_main = has_key(process, 'args_main') ?
+ \ map(split(process.args_main), '"\t\t" . v:val') : []
+ let content = content + args_main
+ call add(content, "\t}")
+
+ if has_key(process, 'args_vm')
+ call add(content, "")
+ call add(content, "\t" . s:args_vm . " {")
+ let args_vm = map(split(process.args_vm), '"\t\t" . v:val')
+ let content = content + args_vm
+ call add(content, "\t}")
+ endif
+ endfor
+
+ if len(content) == 0
+ call add(content, 'No Running Java Processes Found')
+ endif
+
+ call eclim#util#TempWindow('Java_Processes', content)
+
+ setlocal ft=jps_list
+ setlocal foldmethod=syntax
+ setlocal foldlevel=0
+ setlocal foldtext=getline(v:foldstart)
+
+ exec 'syntax match JpsViewAdditional /' . s:supported_command . '$/'
+ exec 'syntax region JpsArguments start=/' . s:args_main . ' {$/ end=/^\s*}$/ fold'
+ exec 'syntax region JpsArguments start=/' . s:args_vm . ' {$/ end=/^\s*}$/ fold'
+
+ nnoremap <silent> <buffer> <cr> :call <SID>ViewAdditionalInfo()<cr>
+
+ call eclim#util#Echo(' ')
+endfunction " }}}
+
+function! eclim#java#tools#GetJavaProcesses() " {{{
+ let java_processes = []
+ let result = eclim#util#System('jps -vV')
+ if v:shell_error
+ call eclim#util#EchoError('Unable to execute jps - ' . result)
+ return [0]
+ endif
+ let vm_args = split(result, '\n')
+ for process in split(eclim#util#System('jps -lm'), '\n')
+ if process =~ 'sun.tools.jps.Jps' "|| process =~ '^[0-9]\+\s*$'
+ continue
+ endif
+
+ let java_process_info = {}
+ let java_process_info['id'] = substitute(process, '\(.\{-}\) .*', '\1', '')
+ let java_process_info['name'] =
+ \ substitute(process, '.\{-} \(.\{-}\) .*', '\1', '')
+ if process =~ '.\{-} .\{-} \(.*\)'
+ let java_process_info['args_main'] =
+ \ substitute(process, '.\{-} .\{-} \(.*\)', '\1', '')
+ endif
+
+ let index = 0
+ for args in vm_args
+ if args =~ '^' . java_process_info.id . '\>'
+ if args =~ '.\{-} .\{-} \(.*\)'
+ let java_process_info['args_vm'] =
+ \ substitute(args, '.\{-} .\{-} \(.*\)', '\1', '')
+ endif
+ call remove(vm_args, index)
+ endif
+ let index += 1
+ endfor
+
+ call add(java_processes, java_process_info)
+ endfor
+ return java_processes
+endfunction " }}}
+
+function! s:ViewAdditionalInfo() " {{{
+ let line = getline('.')
+ if line =~ '^\s*' . s:supported_command . '$'
+ " get the process id.
+ let lnum = search('^[0-9]\+ - ', 'bn')
+ let id = substitute(getline(lnum), '^\([0-9]\+\) - .*', '\1', '')
+
+ if line =~ '^\s*' . s:open_console . '$'
+ call s:OpenConsole(id)
+ elseif line =~ '^\s*' . s:view_info . '$'
+ call s:ViewInfo(id)
+ elseif line =~ '^\s*' . s:view_stacks . '$'
+ call s:ViewStacks(id)
+ elseif line =~ '^\s*' . s:view_map . '$'
+ call s:ViewMap(id)
+ endif
+ endif
+endfunction " }}}
+
+function! s:OpenConsole(id) " {{{
+ call eclim#util#Echo('Executing...')
+
+ if has('win32') || has('win64')
+ call eclim#util#Exec('silent! !start jconsole ' . a:id)
+ else
+ call eclim#util#Exec('silent! !jconsole ' . a:id . ' &')
+ endif
+ exec "normal! \<c-l>"
+
+ call eclim#util#Echo(' ')
+endfunction " }}}
+
+function! s:ViewInfo(id) " {{{
+ if executable('jinfo')
+ call eclim#util#Echo('Executing...')
+
+ let content = split(eclim#util#System('jinfo ' . a:id), '\n')
+ if v:shell_error
+ call eclim#util#EchoError('Unable to execute jinfo.')
+ return
+ endif
+
+ call eclim#util#TempWindow('Java_Process_Info_' . a:id, content)
+ setlocal ft=jproperties
+
+ call eclim#util#Echo(' ')
+ endif
+endfunction " }}}
+
+function! s:ViewStacks(id) " {{{
+ if executable('jstack')
+ call eclim#util#Echo('Executing...')
+ let content = split(eclim#util#System('jstack ' . a:id), '\n')
+
+ if v:shell_error
+ call eclim#util#EchoError('Unable to execute jstack.')
+ return
+ endif
+
+ call map(content, 'substitute(v:val, "^ \\(\\S\\)", " \\1", "")')
+ call map(content, 'substitute(v:val, "^\t", " ", "")')
+
+ call eclim#util#TempWindow('Java_Process_Stacks_' . a:id, content)
+ setlocal ft=java
+
+ call eclim#util#Echo(' ')
+ endif
+endfunction " }}}
+
+function! s:ViewMap(id) " {{{
+ if executable('jmap')
+ call eclim#util#Echo('Executing...')
+ let content = split(eclim#util#System('jmap ' . a:id), '\n')
+
+ if v:shell_error
+ call eclim#util#EchoError('Unable to execute jmap.')
+ return
+ endif
+
+ call eclim#util#TempWindow('Java_Process_Map_' . a:id, content)
+
+ call eclim#util#Echo(' ')
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/java/util.vim b/vim/eclim/autoload/eclim/java/util.vim
@@ -0,0 +1,355 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Utility functions for java eclim ftplugins.
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+ let s:keywords = '\(abstract\|assert\|boolean\|case\|catch\|char\|class\|do\|double\|enum\|extends\|final\|finally\|float\|for\|if\|implements\|import\|int\|interface\|long\|new\|null\|package\|private\|protected\|public\|return\|short\|static\|switch\|throw\|throws\|try\|void\|while\)'
+
+ let s:class_declaration = '^\s*\(public\|private\|protected\)\?\(\s\+abstract\)\?\s\+\(class\|interface\|enum\)\s\+[A-Z]'
+
+ let s:command_src_exists = '-command java_src_exists -f "<file>"'
+ let s:command_list_installs = '-command java_list_installs'
+ let s:command_classpath = '-command java_classpath -p "<project>"'
+ let s:command_read_class = '-command java_class_prototype -c <class>'
+ let s:command_complete_package = '-command java_complete_package -p "<project>"'
+
+ let s:import_pattern = '^\s*import\_s\+<import>\_s*;'
+" }}}
+
+function! eclim#java#util#FileExists(name) " {{{
+ let command = substitute(s:command_src_exists, '<file>', a:name, '')
+ let result = eclim#Execute(command)
+ return result =~ '^true$'
+endfunction " }}}
+
+function! eclim#java#util#GetClassname(...) " {{{
+ if a:0 > 0
+ return fnamemodify(a:1, ":t:r")
+ endif
+ return expand("%:t:r")
+endfunction " }}}
+
+function! eclim#java#util#GetClassDeclarationPosition(movecursor) " {{{
+ let pos = getpos('.')
+ call cursor(1,1)
+
+ let position = search(s:class_declaration)
+
+ if !a:movecursor || !position
+ call setpos('.', pos)
+ endif
+
+ return position
+endfunction " }}}
+
+function! eclim#java#util#GetFullyQualifiedClassname(...) " {{{
+ let package = a:0 > 0 ?
+ \ eclim#java#util#GetPackage(a:1) :
+ \ eclim#java#util#GetPackage()
+ let classname = a:0 > 0 ?
+ \ eclim#java#util#GetClassname(a:1) :
+ \ eclim#java#util#GetClassname()
+ return len(package) ? (package . '.' . classname) : classname
+endfunction " }}}
+
+function! eclim#java#util#GetPackage(...) " {{{
+ if a:0 > 0
+ let winreset = winrestcmd()
+ silent exec "sview " . a:1
+ endif
+
+ let pos = getpos('.')
+
+ call cursor(1,1)
+
+ let package = ""
+ let packageLine = search('^\s*\<package\>', 'w')
+ if packageLine > 0
+ let package =
+ \ substitute(getline('.'), '.*\<package\>\s\+\(.\{-\}\)[ ;].*', '\1', '')
+ endif
+
+ if a:0 > 0
+ close
+ silent exec winreset
+
+ " not necessary and may screw up display (see autoload/project.vim)
+ "redraw
+ else
+ call setpos('.', pos)
+ endif
+
+ return package
+endfunction " }}}
+
+function! eclim#java#util#GetPackageFromImport(class) " {{{
+ let pattern = '^\s*import\s\+\([0-9A-Za-z._]*\)\.' . a:class . '\s*;'
+ let found = search(pattern, 'wn')
+ if found
+ return substitute(getline(found), pattern, '\1', '')
+ endif
+ return ""
+endfunction " }}}
+
+function! eclim#java#util#GetSelectedFields(first, last) range " {{{
+ " normalize each field statement into a single line.
+ let selection = ''
+ let index = a:first
+ let blockcomment = 0
+ while index <= a:last
+ let line = getline(index)
+
+ " ignore comment lines
+ if line =~ '^\s*/\*'
+ let blockcomment = 1
+ endif
+ if blockcomment && line =~ '\*/\s*$'
+ let blockcomment = 0
+ endif
+ if line !~ '^\s*//' && !blockcomment
+ " remove quoted values.
+ let line = substitute(line, '".\{-}"', '', 'g')
+ " strip off trailing comments
+ let line = substitute(line, '//.*', '', '')
+ let line = substitute(line, '/\*.*\*/', '', '')
+
+ let selection = selection . line
+ endif
+
+ let index += 1
+ endwhile
+
+ " compact comma separated multi field declarations
+ let selection = substitute(selection, ',\s*', ',', 'g')
+ " break fields back up into their own line.
+ let selection = substitute(selection, ';', ';\n', 'g')
+ " remove the assignment portion of the field.
+ let selection = substitute(selection, '\(.\{-}\)\s*=.\{-};', '\1;', 'g')
+
+ " extract field names
+ let properties = []
+ let lines = split(selection, '\n')
+ for line in lines
+ if line !~ '^\s*\/\/'
+ let fields = substitute(line, '.*\s\(.*\);', '\1', '')
+ if fields =~ '^[a-zA-Z0-9_,]'
+ for field in split(fields, ',')
+ call add(properties, field)
+ endfor
+ endif
+ endif
+ endfor
+
+ return properties
+endfunction " }}}
+
+function! eclim#java#util#IsKeyword(word) " {{{
+ return (a:word =~ '^' . s:keywords . '$\C')
+endfunction " }}}
+
+function! eclim#java#util#IsImported(classname) " {{{
+ " search for fully qualified import
+ let import_search = s:import_pattern
+ let import_search = substitute(import_search, '<import>', a:classname, '')
+ let found = search(import_search, 'wn')
+ if found
+ return 1
+ endif
+
+ " search for package.* import
+ let package = substitute(a:classname, '\(.*\)\..*', '\1', '')
+ let import_search = s:import_pattern
+ let import_search = substitute(import_search, '<import>', package . '\\.\\*', '')
+ let found = search(import_search, 'wn')
+ if found
+ return 1
+ endif
+
+ " check if current file and supplied classname are in the same package
+ if eclim#java#util#GetPackage() == package
+ return 1
+ endif
+
+ " not imported
+ return 0
+endfunction " }}}
+
+function! eclim#java#util#IsValidIdentifier(word) " {{{
+ if a:word == '' || a:word =~ '\W' || a:word =~ '^\d\+$' ||
+ \ eclim#java#util#IsKeyword(a:word)
+ return 0
+ endif
+ return 1
+endfunction " }}}
+
+function! eclim#java#util#Java(classname, args) " {{{
+ let project = eclim#project#util#GetCurrentProjectName()
+ if project == '' && exists('b:project')
+ let project = b:project
+ endif
+
+ if project == ''
+ call eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let args = eclim#util#ParseArgs(a:args)
+ let classname = a:classname
+ if classname == '' && len(args)
+ let arg1 = args[0]
+ if arg1 == '%'
+ let args = args[1:]
+ let classname = exists('b:filename') ?
+ \ eclim#java#util#GetFullyQualifiedClassname(b:filename) :
+ \ eclim#java#util#GetFullyQualifiedClassname()
+ endif
+ endif
+
+ let command = '-command java -p "' . project . '"'
+ if classname != ''
+ let command .= ' -c ' . classname
+ endif
+
+ if len(args)
+ let command .= ' -a'
+ for arg in args
+ let arg = substitute(arg, '^-', '\\-', '')
+ let command .= ' "' . escape(arg, '"') . '"'
+ endfor
+ endif
+
+ let result = eclim#Execute(command, {'project': project, 'exec': 1, 'raw': 1})
+ let results = split(result, "\n")
+ call eclim#util#TempWindow('[Java Output]', results)
+ let b:project = project
+
+ if exists(":Java") != 2
+ command -buffer -nargs=* Java :call eclim#java#util#Java('', <q-args>)
+ endif
+endfunction " }}}
+
+function! eclim#java#util#Classpath(...) " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let command = s:command_classpath
+ let command = substitute(command, '<project>', project, '')
+ for arg in a:000
+ if arg == '\n'
+ let arg = "\n"
+ endif
+ let command .= " \"" . arg . "\""
+ endfor
+ let result = eclim#Execute(command)
+ if result == '0'
+ return
+ endif
+ call eclim#util#Echo(result)
+endfunction " }}}
+
+function! eclim#java#util#ListInstalls() " {{{
+ let installs = eclim#Execute(s:command_list_installs)
+ if type(installs) != g:LIST_TYPE
+ return
+ endif
+ if len(installs) == 0
+ call eclim#util#Echo("No jdk/jre installs found.")
+ endif
+
+ let pad = 0
+ for install in installs
+ let name = install.name . ' ' . install.version
+ if install.default
+ let name .= ' (default)'
+ endif
+ let pad = len(name) > pad ? len(name) : pad
+ endfor
+
+ let output = []
+ let type = ''
+ for install in installs
+ if install.type != type
+ let type = install.type
+ call add(output, 'Type: ' . install.type)
+ endif
+ let name = install.name . ' ' . install.version
+ if install.default
+ let name .= ' (default)'
+ endif
+ call add(output, ' ' . eclim#util#Pad(name, pad) . ' - ' . install.dir)
+ endfor
+ call eclim#util#Echo(join(output, "\n"))
+endfunction " }}}
+
+function! eclim#java#util#ReadClassPrototype() " {{{
+ let file = substitute(expand('%:p'), '\', '/', 'g')
+ let command = s:command_read_class
+ let command = substitute(command, '<class>', expand('%:t:r'), '')
+ let command .= ' -f "' . file . '"'
+
+ let file = eclim#Execute(command)
+ if string(file) != '0'
+ let bufnum = bufnr('%')
+ if has('win32unix')
+ let file = eclim#cygwin#CygwinPath(file)
+ endif
+ silent exec "keepjumps edit! " . escape(file, ' ')
+
+ exec 'bdelete ' . bufnum
+
+ silent exec "doautocmd BufReadPre " . file
+ silent exec "doautocmd BufReadPost " . file
+
+ call eclim#util#DelayedCommand('set ft=java')
+ setlocal readonly
+ setlocal nomodifiable
+ setlocal noswapfile
+ endif
+endfunction " }}}
+
+function! eclim#java#util#CommandCompleteProject(argLead, cmdLine, cursorPos) " {{{
+ return eclim#project#util#CommandCompleteProjectByNature(
+ \ a:argLead, a:cmdLine, a:cursorPos, 'java')
+endfunction " }}}
+
+function! eclim#java#util#CommandCompletePackage(argLead, cmdLine, cursorPos) " {{{
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ if project == ''
+ return []
+ endif
+
+ let command = s:command_complete_package
+ let command = substitute(command, '<project>', project, '')
+ if argLead != ''
+ let command .= ' -n ' . argLead
+ endif
+ let results = eclim#Execute(command)
+ return type(results) == g:LIST_TYPE ? results : []
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/javascript/complete.vim b/vim/eclim/autoload/eclim/javascript/complete.vim
@@ -0,0 +1,37 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/javascript/complete.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Varables {{{
+ let s:complete_command =
+ \ '-command javascript_complete ' .
+ \ '-p "<project>" -f "<file>" -o <offset> -e <encoding>'
+" }}}
+
+" CodeComplete(findstart, base) {{{
+" Handles code completion.
+function! eclim#javascript#complete#CodeComplete(findstart, base)
+ return eclim#lang#CodeComplete(s:complete_command, a:findstart, a:base)
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/javascript/util.vim b/vim/eclim/autoload/eclim/javascript/util.vim
@@ -0,0 +1,143 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+
+ if !exists("g:EclimJavascriptValidate")
+ let g:EclimJavascriptValidate = 1
+ endif
+
+ if !exists("g:EclimJavascriptLintEnabled")
+ " enabling by default until jsdt validation is mature enough to use.
+ "let g:EclimJavascriptLintEnabled = 0
+ let g:EclimJavascriptLintEnabled = 1
+ endif
+
+ if !exists('g:EclimJavascriptLintConf')
+ let g:EclimJavascriptLintConf = eclim#UserHome() . '/.jslrc'
+ endif
+" }}}
+
+" Script Variables {{{
+ let s:warnings = '\(' . join([
+ \ 'imported but unused',
+ \ ], '\|') . '\)'
+" }}}
+
+function! eclim#javascript#util#UpdateSrcFile(on_save) " {{{
+ " Optional arg:
+ " validate: when 1 force the validation to execute, when 0 prevent it.
+
+ " Disabled until the jsdt matures.
+ "if !a:on_save
+ " call eclim#lang#UpdateSrcFile('javascript', 1)
+ "else
+ " call eclim#lang#UpdateSrcFile('javascript')
+ "endif
+
+ let validate = !a:on_save || (
+ \ g:EclimJavascriptValidate &&
+ \ (!exists('g:EclimFileTypeValidate') || g:EclimFileTypeValidate))
+
+ if validate && g:EclimJavascriptLintEnabled
+ call eclim#javascript#util#Jsl()
+ endif
+endfunction " }}}
+
+function! eclim#javascript#util#Jsl() " {{{
+ " Runs jsl (javascript lint) on the current file.
+
+ if eclim#util#WillWrittenBufferClose()
+ return
+ endif
+
+ let result = ''
+
+ if !executable('jsl')
+ if !exists('g:eclim_javascript_jsl_warn')
+ call eclim#util#EchoWarning("Unable to find 'jsl' command.")
+ let g:eclim_javascript_jsl_warn = 1
+ endif
+ else
+ if !exists('g:EclimJavascriptLintVersion')
+ call eclim#util#System('jsl --help')
+ let g:EclimJavascriptLintVersion = v:shell_error == 2 ? 'c' : 'python'
+ endif
+
+ let conf = expand(g:EclimJavascriptLintConf)
+
+ " the c version
+ if g:EclimJavascriptLintVersion == 'c'
+ let command = 'jsl -process "' . expand('%:p') . '"'
+ if filereadable(conf)
+ let command .= ' -conf "' . conf . '"'
+ endif
+
+ " the new python version
+ else
+ let command = 'jsl "' . expand('%:p') . '"'
+ if filereadable(conf)
+ let command .= ' --conf "' . conf . '"'
+ endif
+ endif
+
+ let result = eclim#util#System(command)
+ if v:shell_error == 2 "|| v:shell_error == 4
+ call eclim#util#EchoError('Error running command: ' . command)
+ return
+ endif
+ endif
+
+ if result =~ ':'
+ let results = split(result, '\n')
+ let errors = []
+ for error in results
+ if error =~ '.\{-}(\d\+): .\{-}: .\{-}'
+ let file = substitute(error, '\(.\{-}\)([0-9]\+):.*', '\1', '')
+ let line = substitute(error, '.\{-}(\([0-9]\+\)):.*', '\1', '')
+ let message = substitute(error, '.\{-}([0-9]\+):.\{-}: \(.*\)', '\1', '')
+ let dict = {
+ \ 'filename': eclim#util#Simplify(file),
+ \ 'lnum': line,
+ \ 'text': "[jsl] " . message,
+ \ 'type': error =~ ': \(lint \)\?warning:' ? 'w' : 'e',
+ \ }
+
+ call add(errors, dict)
+ endif
+ endfor
+
+ call eclim#display#signs#SetPlaceholder()
+ call eclim#util#ClearLocationList('jsl')
+ if &ft == 'javascript'
+ call eclim#util#SetLocationList(errors)
+ else
+ call eclim#util#SetLocationList(errors, 'a')
+ endif
+ call eclim#display#signs#RemovePlaceholder()
+ else
+ call eclim#util#ClearLocationList('jsl')
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/lang.vim b/vim/eclim/autoload/eclim/lang.vim
@@ -0,0 +1,649 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Common language functionality (validation, completion, etc.) abstracted
+" into re-usable functions.
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Varables {{{
+ if !exists('g:EclimTempFilesEnable')
+ let g:EclimTempFilesEnable = 1
+ endif
+
+ if !exists('g:EclimFileTypeValidate')
+ let g:EclimFileTypeValidate = 1
+ endif
+
+ if !exists('g:EclimRefactorDiffOrientation')
+ let g:EclimRefactorDiffOrientation = 'vertical'
+ endif
+" }}}
+
+" Script Variables {{{
+ let s:update_command = '-command <lang>_src_update -p "<project>" -f "<file>"'
+ let s:validate_command = '-command <type>_validate -p "<project>" -f "<file>"'
+ let s:undoredo_command = '-command refactor_<operation>'
+" }}}
+
+function! eclim#lang#CodeComplete(command, findstart, base, ...) " {{{
+ " Optional args:
+ " options: dict containing one or more of the following:
+ " temp: 1 to use a temp file, 0 otherwise
+ " regex: regular expression of characters to walk back over to find the
+ " starting position of the completion.
+ " layout: passed through to the eclimd completion for languages that
+ " support this (typically decides how overloaded method names are
+ " presented in the completion list).
+
+ if !eclim#project#util#IsCurrentFileInProject(0)
+ return a:findstart ? -1 : []
+ endif
+
+ let options = a:0 ? a:1 : {}
+
+ if a:findstart
+ call eclim#lang#SilentUpdate(get(options, 'temp', 1))
+
+ " locate the start of the word
+ let line = getline('.')
+
+ let start = col('.') - 1
+
+ "exceptions that break the rule
+ if line[start] =~ '\.'
+ let start -= 1
+ endif
+
+ let pattern = get(options, 'regex', '\w')
+ while start > 0 && line[start - 1] =~ pattern
+ let start -= 1
+ endwhile
+
+ return start
+ else
+ let offset = eclim#util#GetOffset() + len(a:base)
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#lang#SilentUpdate(get(options, 'temp', 1), 0)
+ if file == ''
+ return []
+ endif
+
+ let command = a:command
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ if has_key(options, 'layout')
+ let command = substitute(command, '<layout>', options.layout, '')
+ endif
+
+ let completions = []
+ let results = eclim#Execute(command)
+ if type(results) != g:LIST_TYPE
+ return
+ endif
+
+ let open_paren = getline('.') =~ '\%' . col('.') . 'c\s*('
+ let close_paren = getline('.') =~ '\%' . col('.') . 'c\s*(\s*)'
+
+ for result in results
+ let word = result.completion
+
+ " strip off close paren if necessary.
+ if word =~ ')$' && close_paren
+ let word = strpart(word, 0, strlen(word) - 1)
+ endif
+
+ " strip off open paren if necessary.
+ if word =~ '($' && open_paren
+ let word = strpart(word, 0, strlen(word) - 1)
+ endif
+
+ let menu = eclim#html#util#HtmlToText(result.menu)
+ let info = has_key(result, 'info') ?
+ \ eclim#html#util#HtmlToText(result.info) : ''
+
+ let dict = {
+ \ 'word': word,
+ \ 'menu': menu,
+ \ 'info': info,
+ \ 'dup': 1
+ \ }
+
+ call add(completions, dict)
+ endfor
+
+ return completions
+ endif
+endfunction " }}}
+
+" Search(command, singleResultAction, argline) {{{
+" Executes a search.
+function! eclim#lang#Search(command, singleResultAction, argline)
+ let argline = a:argline
+ "if argline == ''
+ " call eclim#util#EchoError('You must supply a search pattern.')
+ " return
+ "endif
+
+ " check if pattern supplied without -p.
+ if argline !~ '^\s*-[a-z]' && argline !~ '^\s*$'
+ let argline = '-p ' . argline
+ endif
+
+ if !eclim#project#util#IsCurrentFileInProject(0)
+ let args = eclim#util#ParseArgs(argline)
+ let index = index(args, '-s') + 1
+ if index && len(args) > index && args[index] != 'all'
+ return
+ endif
+ let argline .= ' -s all'
+ endif
+
+ let search_cmd = a:command
+ let project = eclim#project#util#GetCurrentProjectName()
+ if project != ''
+ let search_cmd .= ' -n "' . project . '"'
+ endif
+
+ " no pattern supplied, use element search.
+ if argline !~ '-p\>'
+ if !eclim#project#util#IsCurrentFileInProject(1)
+ return
+ endif
+ " update the file.
+ call eclim#util#ExecWithoutAutocmds('silent update')
+
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let position = eclim#util#GetCurrentElementPosition()
+ let offset = substitute(position, '\(.*\);\(.*\)', '\1', '')
+ let length = substitute(position, '\(.*\);\(.*\)', '\2', '')
+ let encoding = eclim#util#GetEncoding()
+ let search_cmd .= ' -f "' . file . '"' .
+ \ ' -o ' . offset . ' -l ' . length . ' -e ' . encoding
+ else
+ " quote the search pattern
+ let search_cmd = substitute(
+ \ search_cmd, '\(.*-p\s\+\)\(.\{-}\)\(\s\|$\)\(.*\)', '\1"\2"\3\4', '')
+ endif
+
+ let search_cmd .= ' ' . argline
+ let results = eclim#Execute(search_cmd)
+ if type(results) != g:LIST_TYPE
+ return
+ endif
+
+ if !empty(results)
+ call eclim#util#SetLocationList(eclim#util#ParseLocationEntries(results))
+ let locs = getloclist(0)
+ " if only one result and it's for the current file, just jump to it.
+ " note: on windows the expand result must be escaped
+ if len(results) == 1 && locs[0].bufnr == bufnr('%')
+ if results[0].line != 1 && results[0].column != 1
+ lfirst
+ endif
+
+ " single result in another file.
+ elseif len(results) == 1 && a:singleResultAction != "lopen"
+ let entry = getloclist(0)[0]
+ call eclim#util#GoToBufferWindowOrOpen
+ \ (bufname(entry.bufnr), a:singleResultAction)
+ call eclim#util#SetLocationList(eclim#util#ParseLocationEntries(results))
+ call eclim#display#signs#Update()
+
+ call cursor(entry.lnum, entry.col)
+ else
+ exec 'lopen ' . g:EclimLocationListHeight
+ endif
+ return 1
+ else
+ if argline !~ '-p\>'
+ call eclim#util#EchoInfo("Element not found.")
+ else
+ let searchedFor = substitute(argline, '.*-p \(.\{-}\)\( .*\|$\)', '\1', '')
+ call eclim#util#EchoInfo("Pattern '" . searchedFor . "' not found.")
+ endif
+ endif
+
+endfunction " }}}
+
+function! eclim#lang#IsFiletypeValidationEnabled(lang) " {{{
+ " global setting
+ if !g:EclimFileTypeValidate
+ return 0
+ endif
+ " per lang setting
+ exec 'let validate = g:Eclim' . toupper(a:lang[0]) . a:lang[1:] . 'Validate'
+ return validate
+endfunction " }}}
+
+function! eclim#lang#DisableSyntasticIfValidationIsEnabled(lang, ...) " {{{
+ "Optional arg:
+ " syntastic lang: The syntastic lang string if it doesn't match eclim's lang.
+
+ if exists('g:loaded_syntastic_plugin') &&
+ \ eclim#lang#IsFiletypeValidationEnabled(a:lang)
+ let lang = a:0 ? a:1 : a:lang
+ exec 'let syntastic_enabled = ' .
+ \ 'g:Eclim' . toupper(lang[0]) . lang[1:] . 'SyntasticEnabled'
+
+ if !syntastic_enabled
+ if !exists('g:syntastic_mode_map')
+ let g:syntastic_mode_map = {'passive_filetypes': []}
+ elseif !has_key(g:syntastic_mode_map, 'passive_filetypes')
+ let g:syntastic_mode_map.passive_filetypes = []
+ endif
+ if index(g:syntastic_mode_map.passive_filetypes, lang) == -1
+ call add(g:syntastic_mode_map.passive_filetypes, lang)
+ endif
+ endif
+ endif
+endfunction " }}}
+
+function! eclim#lang#UpdateSrcFile(lang, ...) " {{{
+ " Updates the src file on the server w/ the changes made to the current file.
+ " Optional arg:
+ " validate: when 1 force the validation to execute, when 0 prevent it.
+
+ if !a:0
+ let validate = eclim#lang#IsFiletypeValidationEnabled(a:lang)
+ else
+ " arg override
+ let validate = a:1
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ if project != ""
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:update_command
+ let command = substitute(command, '<lang>', a:lang, '')
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ if validate && !eclim#util#WillWrittenBufferClose()
+ let command = command . ' -v'
+ if eclim#project#problems#IsProblemsList() &&
+ \ g:EclimProjectProblemsUpdateOnSave
+ let command = command . ' -b'
+ endif
+ endif
+
+ let result = eclim#Execute(command)
+ if type(result) == g:LIST_TYPE && len(result) > 0
+ let errors = eclim#util#ParseLocationEntries(
+ \ result, g:EclimValidateSortResults)
+ call eclim#util#SetLocationList(errors)
+ else
+ call eclim#util#ClearLocationList('global')
+ endif
+
+ call eclim#project#problems#ProblemsUpdate('save')
+ elseif validate && expand('<amatch>') == ''
+ call eclim#project#util#IsCurrentFileInProject()
+ endif
+endfunction " }}}
+
+" Validate(type, on_save, [filter]) {{{
+" Validates the current file. Used by languages which are not validated via
+" UpdateSrcFile (pretty much all the xml dialects and wst langs).
+function! eclim#lang#Validate(type, on_save, ...)
+ if eclim#util#WillWrittenBufferClose()
+ return
+ endif
+
+ if !eclim#project#util#IsCurrentFileInProject(!a:on_save)
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:validate_command
+ let command = substitute(command, '<type>', a:type, '')
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+
+ let result = eclim#Execute(command)
+ if type(result) == g:LIST_TYPE && len(result) > 0
+ let errors = eclim#util#ParseLocationEntries(
+ \ result, g:EclimValidateSortResults)
+ if a:0
+ let errors = function(a:1)(errors)
+ endif
+ call eclim#util#SetLocationList(errors)
+ else
+ call eclim#util#ClearLocationList()
+ endif
+endfunction " }}}
+
+function! eclim#lang#SilentUpdate(...) " {{{
+ " Silently updates the current source file w/out validation.
+ " Optional args:
+ " temp: construct a temp file path for the current file and return that path
+ " (default is to not create a temp file)
+ " temp_write: when constructing a temp file path, whether or not to write
+ " the current file's contents to that path (default is to do so)
+
+ " i couldn't reproduce the issue, but at least one person experienced the
+ " cursor moving on update and breaking code completion:
+ " http://sourceforge.net/tracker/index.php?func=detail&aid=1995319&group_id=145869&atid=763323
+ let pos = getpos('.')
+ silent let file = eclim#project#util#GetProjectRelativeFilePath()
+ if file != ''
+ try
+ if a:0 && a:1 && g:EclimTempFilesEnable
+ " don't create temp files if no server is available to clean them up.
+ let project = eclim#project#util#GetCurrentProjectName()
+ let workspace = eclim#project#util#GetProjectWorkspace(project)
+ if workspace != '' && eclim#PingEclim(0, workspace)
+ let prefix = '__eclim_temp_'
+ let file = fnamemodify(file, ':h') . '/' . prefix . fnamemodify(file, ':t')
+ let tempfile = expand('%:p:h') . '/' . prefix . expand('%:t')
+ if a:0 < 2 || a:2
+ let savepatchmode = &patchmode
+ set patchmode=
+ exec 'silent noautocmd keepalt write! ' . escape(tempfile, ' ')
+ let &patchmode = savepatchmode
+ endif
+ endif
+ else
+ if a:0 < 2 || a:2
+ silent noautocmd update
+ endif
+ endif
+ finally
+ call setpos('.', pos)
+ endtry
+ endif
+ return file
+endfunction " }}}
+
+" Refactor(command) {{{
+" Executes the supplied refactoring command handle error response and
+" reloading files that have changed.
+function! eclim#lang#Refactor(command)
+ let cwd = substitute(getcwd(), '\', '/', 'g')
+ let cwd_return = 1
+
+ try
+ " turn off swap files temporarily to avoid issues with folder/file
+ " renaming.
+ let bufend = bufnr('$')
+ let bufnum = 1
+ while bufnum <= bufend
+ if bufexists(bufnum)
+ call setbufvar(bufnum, 'save_swapfile', getbufvar(bufnum, '&swapfile'))
+ call setbufvar(bufnum, '&swapfile', 0)
+ endif
+ let bufnum = bufnum + 1
+ endwhile
+
+ " cd to the project root to avoid folder renaming issues on windows.
+ exec 'cd ' . escape(eclim#project#util#GetCurrentProjectRoot(), ' ')
+
+ let result = eclim#Execute(a:command)
+ if type(result) != g:LIST_TYPE && type(result) != g:DICT_TYPE
+ return
+ endif
+
+ " error occurred
+ if type(result) == g:DICT_TYPE && has_key(result, 'errors')
+ call eclim#util#EchoError(result.errors)
+ return
+ endif
+
+ " reload affected files.
+ let curwin = winnr()
+ try
+ for info in result
+ let newfile = ''
+ " handle file renames
+ if has_key(info, 'to')
+ let file = info.from
+ let newfile = info.to
+ if has('win32unix')
+ let newfile = eclim#cygwin#CygwinPath(newfile)
+ endif
+ else
+ let file = info.file
+ endif
+
+ if has('win32unix')
+ let file = eclim#cygwin#CygwinPath(file)
+ endif
+
+ " ignore unchanged directories
+ if isdirectory(file)
+ continue
+ endif
+
+ " handle current working directory moved.
+ if newfile != '' && isdirectory(newfile)
+ if file =~ '^' . cwd . '\(/\|$\)'
+ while cwd !~ '^' . file . '\(/\|$\)'
+ let file = fnamemodify(file, ':h')
+ let newfile = fnamemodify(newfile, ':h')
+ endwhile
+ endif
+
+ if cwd =~ '^' . file . '\(/\|$\)'
+ let dir = substitute(cwd, file, newfile, '')
+ exec 'cd ' . escape(dir, ' ')
+ let cwd_return = 0
+ endif
+ continue
+ endif
+
+ let winnr = bufwinnr(file)
+ if winnr > -1
+ exec winnr . 'winc w'
+ if newfile != ''
+ let bufnr = bufnr('%')
+ enew
+ exec 'bdelete ' . bufnr
+ exec 'edit ' . escape(eclim#util#Simplify(newfile), ' ')
+ else
+ call eclim#util#Reload({'retab': 1})
+ endif
+ endif
+ endfor
+ finally
+ exec curwin . 'winc w'
+ if cwd_return
+ exec 'cd ' . escape(cwd, ' ')
+ endif
+ endtry
+ finally
+ " re-enable swap files
+ let bufnum = 1
+ while bufnum <= bufend
+ if bufexists(bufnum)
+ let save_swapfile = getbufvar(bufnum, 'save_swapfile')
+ if save_swapfile != ''
+ call setbufvar(bufnum, '&swapfile', save_swapfile)
+ endif
+ endif
+ let bufnum = bufnum + 1
+ endwhile
+ endtry
+endfunction " }}}
+
+" RefactorPreview(command) {{{
+" Executes the supplied refactor preview command and opens a corresponding
+" window to view that preview.
+function! eclim#lang#RefactorPreview(command)
+ let result = eclim#Execute(a:command)
+ if type(result) != g:DICT_TYPE
+ return
+ endif
+
+ " error occurred
+ if has_key(result, 'errors')
+ call eclim#util#EchoError(result.errors)
+ return
+ endif
+
+ let lines = []
+ for change in result.changes
+ if change.type == 'diff'
+ call add(lines, '|diff|: ' . change.file)
+ else
+ call add(lines, change.type . ': ' . change.message)
+ endif
+ endfor
+
+ call add(lines, '')
+ call add(lines, '|Execute Refactoring|')
+ call eclim#util#TempWindow('[Refactor Preview]', lines)
+ let b:refactor_command = result.apply
+
+ set ft=refactor_preview
+ hi link RefactorLabel Identifier
+ hi link RefactorLink Label
+ syntax match RefactorLabel /^\s*\w\+:/
+ syntax match RefactorLink /|\S.\{-}\S|/
+
+ nnoremap <silent> <buffer> <cr> :call eclim#lang#RefactorPreviewLink()<cr>
+endfunction " }}}
+
+" RefactorPreviewLink() {{{
+" Called when a user hits <cr> on a link in the refactor preview window,
+" issuing a diff for that file.
+function! eclim#lang#RefactorPreviewLink()
+ let line = getline('.')
+ if line =~ '^|'
+ let command = b:refactor_command
+
+ let winend = winnr('$')
+ let winnum = 1
+ while winnum <= winend
+ let bufnr = winbufnr(winnum)
+ if getbufvar(bufnr, 'refactor_preview_diff') != ''
+ exec bufnr . 'bd'
+ continue
+ endif
+ let winnum += 1
+ endwhile
+
+ if line == '|Execute Refactoring|'
+ call eclim#lang#Refactor(command)
+ let winnr = b:winnr
+ close
+ " the filename might change, so we have to use the winnr to get back to
+ " where we were.
+ exec winnr . 'winc w'
+
+ elseif line =~ '^|diff|'
+ let file = substitute(line, '^|diff|:\s*', '', '')
+ let command .= ' -v -d "' . file . '"'
+
+ let diff = eclim#Execute(command)
+ if type(diff) != g:STRING_TYPE
+ return
+ endif
+
+ " split relative to the original window
+ exec b:winnr . 'winc w'
+
+ if has('win32unix')
+ let file = eclim#cygwin#CygwinPath(file)
+ endif
+ let name = fnamemodify(file, ':t:r')
+ let ext = fnamemodify(file, ':e')
+ exec printf('silent below new %s.current.%s', name, ext)
+ silent 1,$delete _ " counter-act any templating plugin
+ exec 'read ' . escape(file, ' ')
+ silent 1,1delete _
+ let winnr = winnr()
+ let b:refactor_preview_diff = 1
+ setlocal readonly nomodifiable
+ setlocal noswapfile nobuflisted
+ setlocal buftype=nofile bufhidden=delete
+ diffthis
+
+ let orien = g:EclimRefactorDiffOrientation == 'horizontal' ? '' : 'vertical'
+ exec printf('silent below %s split %s.new.%s', orien, name, ext)
+ silent 1,$delete _ " counter-act any templating plugin
+ call append(1, split(diff, "\n"))
+ let b:refactor_preview_diff = 1
+ silent 1,1delete _
+ setlocal readonly nomodifiable
+ setlocal noswapfile nobuflisted
+ setlocal buftype=nofile bufhidden=delete
+ diffthis
+ exec winnr . 'winc w'
+ endif
+ endif
+endfunction " }}}
+
+" RefactorPrompt(prompt) {{{
+" Issues the standard prompt for language refactorings.
+function! eclim#lang#RefactorPrompt(prompt)
+ exec "echohl " . g:EclimInfoHighlight
+ try
+ " clear any previous messages
+ redraw
+ echo a:prompt . "\n"
+ let response = input("([e]xecute / [p]review / [c]ancel): ")
+ while response != '' &&
+ \ response !~ '^\c\s*\(e\(xecute\)\?\|p\(review\)\?\|c\(ancel\)\?\)\s*$'
+ let response = input("You must choose either e, p, or c. (Ctrl-C to cancel): ")
+ endwhile
+ finally
+ echohl None
+ endtry
+
+ if response == ''
+ return -1
+ endif
+
+ if response =~ '\c\s*\(c\(ancel\)\?\)\s*'
+ return 0
+ endif
+
+ return response =~ '\c\s*\(e\(execute\)\?\)\s*' ? 1 : 2 " preview
+endfunction " }}}
+
+" UndoRedo(operation, peek) {{{
+" Performs an undo or redo (operation = 'undo' or 'redo') for the last
+" executed refactoring.
+function! eclim#lang#UndoRedo(operation, peek)
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ " update the file before vim makes any changes.
+ call eclim#lang#SilentUpdate()
+ wall
+
+ let command = s:undoredo_command
+ let command = substitute(command, '<operation>', a:operation, '')
+ if a:peek
+ let command .= ' -p'
+ let result = eclim#Execute(command)
+ if type(result) == g:STRING_TYPE
+ call eclim#util#Echo(result)
+ endif
+ return
+ endif
+
+ call eclim#lang#Refactor(command)
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/lang/hierarchy.vim b/vim/eclim/autoload/eclim/lang/hierarchy.vim
@@ -0,0 +1,139 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+ let s:call_hierarchy =
+ \ '-command <lang>_callhierarchy -p "<project>" -f "<file>" ' .
+ \ '-o <offset> -l <length> -e <encoding>'
+" }}}
+
+function! eclim#lang#hierarchy#CallHierarchy(lang, default_action, bang) " {{{
+ if !eclim#project#util#IsCurrentFileInProject(1)
+ return
+ endif
+
+ call eclim#lang#SilentUpdate()
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let position = eclim#util#GetCurrentElementPosition()
+ let offset = substitute(position, '\(.*\);\(.*\)', '\1', '')
+ let length = substitute(position, '\(.*\);\(.*\)', '\2', '')
+ let command = s:call_hierarchy
+ let command = substitute(command, '<lang>', a:lang, '')
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<length>', length, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+ " return callees
+ if a:bang != ''
+ let command .= ' -c'
+ endif
+
+ let result = eclim#Execute(command)
+ if type(result) != g:DICT_TYPE
+ return
+ endif
+
+ if len(result) == 0
+ call eclim#util#Echo('No results found.')
+ return
+ endif
+
+ let lines = []
+ let info = []
+ let key = a:bang != '' ? 'callees' : 'callers'
+ call s:CallHierarchyFormat(result, key, lines, info, '')
+
+ call eclim#util#TempWindow('[Call Hierarchy]', lines)
+ exec 'set ft=' . a:lang
+ " fold function calls into their parent
+ setlocal foldmethod=expr
+ setlocal foldexpr='>'.len(substitute(getline(v:lnum),'^\\(\\s*\\).*','\\1',''))/2
+ setlocal foldtext=substitute(getline(v:foldstart),'^\\(\\s*\\)\\s\\s','\\1+\ ','').':\ '.(v:foldend-v:foldstart+1).'\ lines'
+
+ setlocal modifiable noreadonly
+ call append(line('$'), ['', '" use ? to view help'])
+ setlocal nomodifiable readonly
+ syntax match Comment /^".*/
+
+ let b:hierarchy_info = info
+
+ exec 'nnoremap <buffer> <silent> <cr> ' .
+ \ ':call <SID>Open("' . a:default_action . '")<cr>'
+ nnoremap <buffer> <silent> E :call <SID>Open('edit')<cr>
+ nnoremap <buffer> <silent> S :call <SID>Open('split')<cr>
+ nnoremap <buffer> <silent> T :call <SID>Open("tablast \| tabnew")<cr>
+
+ " assign to buffer var to get around weird vim issue passing list containing
+ " a string w/ a '<' in it on execution of mapping.
+ let b:hierarchy_help = [
+ \ '<cr> - open file with default action',
+ \ 'E - open with :edit',
+ \ 'S - open in a new split window',
+ \ 'T - open in a new tab',
+ \ ]
+ nnoremap <buffer> <silent> ?
+ \ :call eclim#help#BufferHelp(b:hierarchy_help, 'vertical', 40)<cr>
+endfunction " }}}
+
+function! s:CallHierarchyFormat(result, key, lines, info, indent) " {{{
+ if has_key(a:result, 'position')
+ call add(a:info, {
+ \ 'file': a:result.position.filename,
+ \ 'line': a:result.position.line,
+ \ 'col': a:result.position.column
+ \ })
+ call add(a:lines, a:indent . a:result.name)
+ else
+ call add(a:info, {'file': '', 'line': -1, 'col': -1})
+ call add(a:lines, a:indent . a:result.name)
+ endif
+
+ for call in get(a:result, a:key, [])
+ call s:CallHierarchyFormat(call, a:key, a:lines, a:info, a:indent . "\t")
+ endfor
+endfunction " }}}
+
+function! s:Open(action) " {{{
+ let line = line('.')
+ if line > len(b:hierarchy_info)
+ return
+ endif
+
+ let info = b:hierarchy_info[line - 1]
+ if info.file != ''
+ " go to the buffer that initiated the hierarchy
+ exec b:winnr . 'winc w'
+
+ let action = a:action
+ call eclim#util#GoToBufferWindowOrOpen(info.file, action)
+ call cursor(info.line, info.col)
+
+ " force any previous messge from else below to be cleared
+ echo ''
+ else
+ call eclim#util#Echo('No associated file was found.')
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/project/problems.vim b/vim/eclim/autoload/eclim/project/problems.vim
@@ -0,0 +1,133 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global variables {{{
+ if !exists('g:EclimProblemsQuickFixOpen')
+ let g:EclimProblemsQuickFixOpen = 'botright copen'
+ endif
+" }}}
+
+" Script variables {{{
+ let s:problems_command = '-command problems -p "<project>"'
+" }}}
+
+function! eclim#project#problems#Problems(project, open, bang) " {{{
+ let project = a:project
+ if project == ''
+ let project = eclim#project#util#GetCurrentProjectName()
+ endif
+ if project == ''
+ call eclim#project#util#UnableToDetermineProject()
+ return
+ endif
+
+ let command = s:problems_command
+ let command = substitute(command, '<project>', project, '')
+ if a:bang != ""
+ let command .= ' -e'
+ endif
+ let result = eclim#Execute(command)
+ let errors = []
+ if type(result) == g:LIST_TYPE && len(result) > 0
+ let errors = eclim#util#ParseLocationEntries(
+ \ result, g:EclimValidateSortResults)
+ endif
+
+ let action = eclim#project#problems#IsProblemsList() ? 'r' : ' '
+ call eclim#util#SetQuickfixList(errors, action)
+
+ " generate a 'signature' to distinguish the problems list from other qf
+ " lists.
+ let s:eclim_problems_sig = s:QuickfixSignature()
+ let s:eclim_problems_bang = a:bang
+
+ if a:open
+ exec g:EclimProblemsQuickFixOpen
+ endif
+endfunction " }}}
+
+function! eclim#project#problems#ProblemsUpdate(action) " {{{
+ if a:action == 'save' && !g:EclimProjectProblemsUpdateOnSave
+ return
+ endif
+
+ if a:action == 'build' && !g:EclimProjectProblemsUpdateOnBuild
+ return
+ endif
+
+ if !eclim#project#problems#IsProblemsList()
+ return
+ endif
+
+ " preserve the cursor position in the quickfix window
+ let qf_winnr = 0
+ let index = 1
+ while index <= winnr('$')
+ if getbufvar(winbufnr(index), '&ft') == 'qf'
+ let cur = winnr()
+ let qf_winnr = index
+ exec qf_winnr . 'winc w'
+ let pos = getpos('.')
+ exec cur . 'winc w'
+ break
+ endif
+ let index += 1
+ endwhile
+
+ let bang = exists('s:eclim_problems_bang') ? s:eclim_problems_bang : ''
+ call eclim#project#problems#Problems('', 0, bang)
+
+ " restore the cursor position
+ if qf_winnr
+ let cur = winnr()
+ exec qf_winnr . 'winc w'
+ call setpos('.', pos)
+ redraw
+ exec cur . 'winc w'
+ endif
+endfunction " }}}
+
+function! eclim#project#problems#IsProblemsList() " {{{
+ " if available, compare the problems signature against the signature of
+ " the current list to see if we are now on the problems list, probably via
+ " :colder or :cnewer.
+ if exists('s:eclim_problems_sig')
+ return s:QuickfixSignature() == s:eclim_problems_sig
+ endif
+ if exists('s:eclim_problems_bang')
+ unlet s:eclim_problems_bang
+ endif
+ return 0
+endfunction " }}}
+
+function! s:QuickfixSignature() " {{{
+ let qflist = getqflist()
+ let len = len(qflist)
+ return {
+ \ 'len': len,
+ \ 'first': len > 0 ? (qflist[0]['bufnr'] . ':' . qflist[0]['text']) : '',
+ \ 'last': len > 0 ? (qflist[-1]['bufnr'] . ':' . qflist[-1]['text']) : ''
+ \ }
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/project/tree.vim b/vim/eclim/autoload/eclim/project/tree.vim
@@ -0,0 +1,522 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+ if !exists('g:EclimProjectTreeActions')
+ let g:EclimProjectTreeActions = [
+ \ {'pattern': '.*', 'name': 'Split', 'action': 'split'},
+ \ {'pattern': '.*', 'name': 'VSplit', 'action': 'vsplit'},
+ \ {'pattern': '.*', 'name': 'Tab', 'action': 'tablast | tabnew'},
+ \ {'pattern': '.*', 'name': 'Edit', 'action': 'edit'},
+ \ ]
+ endif
+ if !exists('g:EclimProjectTreePathEcho')
+ let g:EclimProjectTreePathEcho = 1
+ endif
+" }}}
+
+" Script Variables {{{
+ let s:project_tree_ids = 0
+ let s:shared_instances_by_buffer = {}
+ let s:shared_instances_by_names = {}
+" }}}
+
+function! eclim#project#tree#ProjectTree(...) " {{{
+ " Open a tree view of the current or specified projects.
+
+ " no project dirs supplied, use current project
+ if len(a:000) == 0
+ let name = eclim#project#util#GetCurrentProjectName()
+ let names = [name]
+ if name == ''
+ if exists('t:cwd')
+ let names = [t:cwd]
+ else
+ call eclim#project#util#UnableToDetermineProject()
+ return
+ endif
+ endif
+
+ " list of project names supplied
+ elseif type(a:000[0]) == g:LIST_TYPE
+ let names = a:000[0]
+ if len(names) == 1 && (names[0] == '0' || names[0] == '')
+ return
+ endif
+
+ " list or project names
+ else
+ let names = a:000
+ endif
+
+ let dirs = []
+ let index = 0
+ let names_copy = copy(names)
+ for name in names
+ if name == 'CURRENT'
+ let name = eclim#project#util#GetCurrentProjectName()
+ let names_copy[index] = name
+ endif
+
+ let dir = eclim#project#util#GetProjectRoot(name)
+ if dir == ''
+ let dir = expand(name, ':p')
+ if !isdirectory(dir)
+ if eclim#EclimAvailable(0)
+ call eclim#util#EchoWarning('Project not found: ' . name)
+ endif
+ call remove(names_copy, index)
+ continue
+ endif
+ let names_copy[index] = fnamemodify(substitute(dir, '/$', '', ''), ':t')
+ endif
+ call add(dirs, dir)
+ let index += 1
+ endfor
+ let names = names_copy
+
+ if len(dirs) == 0
+ return
+ endif
+
+ " for session reload
+ let g:Eclim_project_tree_names = join(names, '|')
+
+ let display = len(names) == 1 ?
+ \ 'Project: ' . names[0] :
+ \ 'Projects: ' . join(names, ', ')
+
+ call eclim#project#tree#ProjectTreeClose()
+ call eclim#project#tree#ProjectTreeOpen(display, names, dirs)
+endfunction " }}}
+
+function! eclim#project#tree#ProjectTreeToggle() " {{{
+ let title = s:GetTreeTitle()
+ let bufnum = bufnr(title)
+ let winnum = bufwinnr(title)
+ if bufnum == -1 || winnum == -1
+ call eclim#project#tree#ProjectTree()
+ else
+ exec winnum . 'winc w'
+ close
+ winc p
+ endif
+endfunction " }}}
+
+function! eclim#project#tree#ProjectTreeOpen(display, names, dirs) " {{{
+ let expand = len(a:dirs) == 1
+ let expandDir = ''
+ if expand && g:EclimProjectTreeExpandPathOnOpen
+ let expandDir = substitute(expand('%:p:h'), '\', '/', 'g')
+ endif
+
+ " see if we should just use a shared tree
+ let shared = s:GetSharedTreeBuffer(a:names)
+ if shared != -1 && bufloaded(shared)
+ call eclim#display#window#VerticalToolWindowOpen(bufname(shared), 9)
+ "exec 'buffer ' . shared
+ if line('$') > 1 || getline(1) !~ '^\s*$'
+ setlocal nowrap nonumber
+ setlocal foldmethod=manual foldtext=getline(v:foldstart)
+ exec 'setlocal statusline=' . escape(a:display, ' ')
+ if !exists('t:project_tree_name')
+ exec 'let t:project_tree_id = ' .
+ \ substitute(bufname(shared), g:EclimProjectTreeTitle . '\(\d\+\)', '\1', '')
+ endif
+
+ if expand && expandDir != ''
+ call eclim#tree#ExpandPath(s:GetTreeTitle(), expandDir)
+ endif
+
+ return
+ endif
+ endif
+
+ " clear the project tree id if we are replacing a shared tree instance
+ if g:EclimProjectTreeSharedInstance && exists('t:project_tree_id')
+ unlet t:project_tree_id
+ endif
+
+ call eclim#display#window#VerticalToolWindowOpen(s:GetTreeTitle(), 9)
+
+ " command used to navigate to a content window before executing a command.
+ if !exists('g:EclimProjectTreeContentWincmd')
+ if g:VerticalToolWindowSide == 'right'
+ let g:EclimProjectTreeContentWincmd = 'winc h'
+ else
+ let g:EclimProjectTreeContentWincmd = 'winc l'
+ endif
+ endif
+
+ if exists('g:TreeSettingsFunction')
+ let s:TreeSettingsFunction = g:TreeSettingsFunction
+ endif
+ let g:TreeSettingsFunction = 'eclim#project#tree#ProjectTreeSettings'
+
+ try
+ call eclim#tree#Tree(s:GetTreeTitle(), a:dirs, a:names, expand, [])
+ finally
+ if exists('s:TreeSettingsFunction')
+ let g:TreeSettingsFunction = s:TreeSettingsFunction
+ else
+ unlet g:TreeSettingsFunction
+ endif
+ endtry
+
+ setlocal bufhidden=hide
+ exec 'setlocal statusline=' . escape(a:display, ' ')
+
+ if expand && expandDir != ''
+ call eclim#util#DelayedCommand(
+ \ 'call eclim#tree#ExpandPath("' . s:GetTreeTitle() . '", "' . expandDir . '")')
+ endif
+
+ normal! zs
+
+ let instance_names = join(a:names, '_')
+ let instance_names = substitute(instance_names, '\W', '_', 'g')
+
+ " remove the old associated tree value if one exists
+ silent! unlet s:shared_instances_by_names[s:shared_instances_by_buffer[bufnr('%')]]
+
+ let s:shared_instances_by_buffer[bufnr('%')] = instance_names
+ let s:shared_instances_by_names[instance_names] = bufnr('%')
+
+ call s:Mappings()
+ setlocal modifiable
+ call append(line('$'), ['', '" use ? to view help'])
+ call s:InfoLine()
+ setlocal nomodifiable
+endfunction " }}}
+
+function! eclim#project#tree#ProjectTreeClose() " {{{
+ if exists('t:project_tree_name') || exists('t:project_tree_id')
+ let winnr = bufwinnr(s:GetTreeTitle())
+ if winnr != -1
+ exec winnr . 'winc w'
+ close
+ endif
+ endif
+endfunction " }}}
+
+function! eclim#project#tree#Restore() " {{{
+ if exists('t:project_tree_restoring')
+ return
+ endif
+ let t:project_tree_restoring = 1
+
+ " prevent auto open from firing after session is loaded.
+ augroup project_tree_autoopen
+ autocmd!
+ augroup END
+
+ let title = s:GetTreeTitle()
+ let winnum = bufwinnr(title)
+ if winnum != -1
+ if exists('g:Eclim_project_tree_names')
+ let projects = split(g:Eclim_project_tree_names, '|')
+ call map(projects, 'escape(v:val, " ")')
+ let names = join(projects, ' ')
+ call eclim#util#DelayedCommand(
+ \ 'let bufnum = bufnr("%") | ' .
+ \ 'exec "ProjectTree ' . names . '" | ' .
+ \ 'exec bufwinnr(bufnum) . "winc w" | ' .
+ \ 'unlet t:project_tree_restoring')
+ else
+ exec 'bd ' . bufnr(title)
+ endif
+ endif
+endfunction " }}}
+
+function! s:GetTreeTitle() " {{{
+ " support a custom name from an external plugin
+ if exists('t:project_tree_name')
+ return t:project_tree_name
+ endif
+
+ if !exists('t:project_tree_id')
+ let t:project_tree_id = s:project_tree_ids + 1
+ let s:project_tree_ids += 1
+ endif
+ return g:EclimProjectTreeTitle . t:project_tree_id
+endfunction " }}}
+
+function! s:GetSharedTreeBuffer(names) " {{{
+ let instance_names = join(a:names, '_')
+ let instance_names = substitute(instance_names, '\W', '_', 'g')
+ if g:EclimProjectTreeSharedInstance &&
+ \ has_key(s:shared_instances_by_names, instance_names)
+ return s:shared_instances_by_names[instance_names]
+ endif
+ return -1
+endfunction " }}}
+
+function! s:Mappings() " {{{
+ nnoremap <buffer> <silent> E :call <SID>OpenFile('edit')<cr>
+ nnoremap <buffer> <silent> S :call <SID>OpenFile('split')<cr>
+ nnoremap <buffer> <silent> \| :call <SID>OpenFile('vsplit')<cr>
+ nnoremap <buffer> <silent> T :call <SID>OpenFile('tablast \| tabnew')<cr>
+ nnoremap <buffer> <silent> F :call <SID>OpenFileName()<cr>
+ nnoremap <buffer> <silent> Y :call <SID>YankFileName()<cr>
+
+ " assign to buffer var to get around weird vim issue passing list containing
+ " a string w/ a '<' in it on execution of mapping.
+ let b:project_tree_help = [
+ \ '<cr> - open/close dir, open file',
+ \ 'o - toggle dir fold, choose file open action',
+ \ 'E - open with :edit',
+ \ 'S - open in a new split window',
+ \ '| (pipe) - open in a new vertical split window',
+ \ 'T - open in a new tab',
+ \ 'R - refresh directory',
+ \ 'i - view file info',
+ \ 's - open shell at directory',
+ \ 'p - move cursor to parent dir',
+ \ 'P - move cursor to last child of dir',
+ \ 'C - set root to dir under the cursor',
+ \ 'B - set root up one dir',
+ \ '~ - set root to home dir',
+ \ 'K - set root to top most dir',
+ \ 'F - open/create a file by name',
+ \ 'D - create a new directory',
+ \ 'Y - yank current file/dir path to the clipboard',
+ \ 'A - toggle hide/view hidden files',
+ \ ':CD <dir> - set the root to <dir>',
+ \ ]
+ nnoremap <buffer> <silent> ?
+ \ :call eclim#help#BufferHelp(b:project_tree_help, 'horizontal', 10)<cr>
+endfunction " }}}
+
+function! s:InfoLine() " {{{
+ setlocal modifiable
+ let pos = getpos('.')
+ if len(b:roots) == 1
+ let lnum = line('$') - 1
+ if getline(lnum) =~ '^"'
+ exec lnum . ',' . lnum . 'delete _'
+ endif
+
+ let info = ''
+ try
+ let info = function('vcs#util#GetInfo')(b:roots[0])
+ catch /E\(117\|700\)/
+ " fall back to fugitive
+ try
+ " fugitive calls a User autocmd, so stop if that one is triggering
+ " this one to prevent a recursive loop
+ if exists('b:eclim_fugative_autocmd')
+ return
+ endif
+
+ " make sure fugitive has the git dir for the current project
+ if !exists('b:git_dir') || (b:git_dir !~ '^\M' . b:roots[0])
+ let cwd = ''
+ if getcwd() . '/' != b:roots[0]
+ let cwd = getcwd()
+ exec 'lcd ' . escape(b:roots[0], ' ')
+ endif
+
+ if exists('b:git_dir')
+ unlet b:git_dir
+ endif
+
+ " slight hack to prevent recursive autocmd loop with fugitive
+ let b:eclim_fugative_autocmd = 1
+
+ silent! doautocmd fugitive BufReadPost %
+
+ if cwd != ''
+ exec 'lcd ' . escape(cwd, ' ')
+ endif
+ endif
+
+ let info = function('fugitive#statusline')()
+ if info != ''
+ let branch = substitute(info, '^\[\Git(\(.*\))\]$', '\1', 'g')
+ if branch != info
+ let info = 'git:' . branch
+ endif
+ endif
+ catch /E\(117\|700\)/
+ " noop if the neither function was found
+ finally
+ silent! unlet b:eclim_fugative_autocmd
+ endtry
+ endtry
+
+ " &modifiable check for silly side effect of fugitive autocmd
+ if info != '' && &modifiable
+ call append(line('$') - 1, '" ' . info)
+ endif
+ endif
+ call setpos('.', pos)
+ setlocal nomodifiable
+endfunction " }}}
+
+function! s:PathEcho() " {{{
+ if mode() != 'n'
+ return
+ endif
+
+ let path = eclim#tree#GetPath()
+ let path = substitute(path, eclim#tree#GetRoot(), '', '')
+ if path !~ '^"'
+ call eclim#util#WideMessage('echo', path)
+ else
+ call eclim#util#WideMessage('echo', '')
+ endif
+endfunction " }}}
+
+function! s:OpenFile(action) " {{{
+ let path = eclim#tree#GetPath()
+ if path !~ '/$'
+ if !filereadable(path)
+ echo "File is not readable or has been deleted."
+ return
+ endif
+
+ call eclim#tree#ExecuteAction(path,
+ \ "call eclim#project#tree#OpenProjectFile('" . a:action . "', '<file>')")
+ endif
+endfunction " }}}
+
+function! s:OpenFileName() " {{{
+ let path = eclim#tree#GetPath()
+ if !isdirectory(path)
+ let path = fnamemodify(path, ':h') . '/'
+ endif
+
+ let response = input('file: ', path, 'file')
+ if response != ''
+ let actions = eclim#tree#GetFileActions(response)
+ call eclim#tree#ExecuteAction(response, actions[0].action)
+ endif
+endfunction " }}}
+
+function! s:YankFileName() " {{{
+ let path = eclim#tree#GetPath()
+ let [@*, @+, @"] = [path, path, path]
+ call eclim#util#Echo('Copied path to clipboard: ' . path)
+endfunction " }}}
+
+function! eclim#project#tree#ProjectTreeSettings() " {{{
+ for action in g:EclimProjectTreeActions
+ call eclim#tree#RegisterFileAction(action.pattern, action.name,
+ \ "call eclim#project#tree#OpenProjectFile('" . action.action . "', '<file>')")
+ endfor
+
+ call eclim#tree#RegisterDirAction(function('eclim#project#tree#InjectLinkedResources'))
+
+ if exists('s:TreeSettingsFunction')
+ let l:Settings = function(s:TreeSettingsFunction)
+ call l:Settings()
+ endif
+
+ augroup eclim_tree
+ autocmd User <buffer> call <SID>InfoLine()
+ if g:EclimProjectTreePathEcho
+ autocmd CursorMoved <buffer> call <SID>PathEcho()
+ endif
+ augroup END
+endfunction " }}}
+
+function! eclim#project#tree#OpenProjectFile(cmd, file) " {{{
+ " Execute the supplied command in one of the main content windows.
+ if eclim#util#GoToBufferWindow(a:file)
+ return
+ endif
+
+ let file = a:file
+ let cmd = a:cmd
+ let cwd = getcwd()
+
+ exec g:EclimProjectTreeContentWincmd
+
+ " if the buffer is a no name and action is split, use edit instead.
+ if cmd =~ 'split' && expand('%') == '' &&
+ \ !&modified && line('$') == 1 && getline(1) == ''
+ let cmd = 'edit'
+ endif
+
+ " current file doesn't share same cwd as the project tree
+ let lcwd = getcwd()
+ if lcwd != cwd && !filereadable(file)
+ let file = escape(substitute(cwd, '\', '/', 'g'), ' &') . '/' . file
+ endif
+
+ try
+ exec cmd . ' ' file
+ catch /E325/
+ " ignore attention error since the user should be prompted to handle it.
+ finally
+ if lcwd != cwd
+ exec 'lcd ' . escape(cwd, ' ')
+ endif
+ endtry
+endfunction " }}}
+
+function! eclim#project#tree#InjectLinkedResources(dir, contents) " {{{
+ let project = eclim#project#util#GetProject(a:dir)
+ if len(project) == 0
+ return
+ endif
+
+ " listing the project root, so inject our project links
+ if len(get(project, 'links', {})) &&
+ \ substitute(a:dir, '/$', '', '') == project.path
+ if !exists('b:links')
+ let b:links = {}
+ endif
+ call extend(b:links, project.links)
+
+ let links = keys(project.links)
+ call sort(links)
+
+ let index = 0
+ for entry in copy(a:contents)
+ if !len(links)
+ break
+ endif
+
+ while len(links) && links[0] < fnamemodify(entry, ':h:t')
+ call insert(a:contents, a:dir . remove(links, 0) . '/', index)
+ endwhile
+ let index += 1
+ endfor
+
+ for link in links
+ call add(a:contents, a:dir . link . '/')
+ endfor
+ endif
+endfunction " }}}
+
+function! eclim#project#tree#HorizontalContentWindow() " {{{
+ " Command for g:EclimProjectTreeContentWincmd used when relative to a
+ " horizontal taglist window.
+ winc k
+ if exists('g:TagList_title') && bufname(bufnr('%')) == g:TagList_title
+ winc k
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/project/util.vim b/vim/eclim/autoload/eclim/project/util.vim
@@ -0,0 +1,1461 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists('g:EclimTodoSearchPattern')
+ let g:EclimTodoSearchPattern = '\(\<fixme\>\|\<todo\>\)\c'
+endif
+
+if !exists('g:EclimTodoSearchExtensions')
+ let g:EclimTodoSearchExtensions = [
+ \ 'css',
+ \ 'html',
+ \ 'java',
+ \ 'js',
+ \ 'jsp',
+ \ 'php',
+ \ 'py',
+ \ 'rb',
+ \ 'sql',
+ \ 'xml',
+ \ ]
+endif
+
+if !exists('g:EclimProjectStatusLine')
+ let g:EclimProjectStatusLine = '${name}'
+endif
+" }}}
+
+" Script Variables {{{
+let s:command_create = '-command project_create -f "<folder>"'
+let s:command_create_name = ' -p "<name>"'
+let s:command_create_natures = ' -n <natures>'
+let s:command_create_depends = ' -d <depends>'
+let s:command_import = '-command project_import -f "<folder>"'
+let s:command_delete = '-command project_delete -p "<project>"'
+let s:command_rename = '-command project_rename -p "<project>" -n "<name>"'
+let s:command_move = '-command project_move -p "<project>" -d "<dir>"'
+let s:command_refresh = '-command project_refresh -p "<project>"'
+let s:command_refresh_file =
+ \ '-command project_refresh_file -p "<project>" -f "<file>"'
+let s:command_build = '-command project_build -p "<project>"'
+let s:command_projects = '-command projects'
+let s:command_project_list = '-command project_list'
+let s:command_project_by_resource = '-command project_by_resource -f "<file>"'
+let s:command_project_info = '-command project_info -p "<project>"'
+let s:command_project_settings = '-command project_settings -p "<project>"'
+let s:command_project_setting = '-command project_setting -p "<project>" -s <setting>'
+let s:command_project_update = '-command project_update -p "<project>"'
+let s:command_update = '-command project_update -p "<project>" -s "<settings>"'
+let s:command_open = '-command project_open -p "<project>"'
+let s:command_close = '-command project_close -p "<project>"'
+let s:command_nature_aliases = '-command project_nature_aliases'
+let s:command_natures = '-command project_natures'
+let s:command_nature_add =
+ \ '-command project_nature_add -p "<project>" -n "<natures>"'
+let s:command_nature_remove =
+ \ '-command project_nature_remove -p "<project>" -n "<natures>"'
+
+let s:workspace_projects = {}
+" }}}
+
+function! eclim#project#util#ClearProjectsCache() " {{{
+ " Flush the cached list of projects.
+ let s:workspace_projects = {}
+endfunction " }}}
+
+function! eclim#project#util#ProjectCD(scope) " {{{
+ " Change the current working directory to the current project root.
+ let dir = eclim#project#util#GetCurrentProjectRoot()
+ if a:scope == 0
+ exec 'cd ' . escape(dir, ' ')
+ elseif a:scope == 1
+ exec 'lcd ' . escape(dir, ' ')
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectCreate(args) " {{{
+ let args = eclim#util#ParseCmdLine(a:args)
+
+ let folder = fnamemodify(expand(args[0]), ':p')
+ let folder = substitute(folder, '\', '/', 'g')
+ if has('win32unix')
+ let folder = eclim#cygwin#WindowsPath(folder)
+ endif
+ let command = substitute(s:command_create, '<folder>', folder, '')
+
+ let name = substitute(a:args, '.* -p\s\+\(.\{-}\)\(\s\+-\(d\|n\)\>.*\|$\)', '\1', '')
+ if name != a:args
+ let command .= substitute(s:command_create_name, '<name>', name, '')
+ endif
+
+ let natureIds = []
+ let natures = substitute(a:args, '.* -n\s\+\(.\{-}\)\(\s\+-\(d\|p\)\>.*\|$\)', '\1', '')
+ if natures != a:args
+ let natures = substitute(natures, '\s\+', ',', 'g')
+ let natureIds = split(natures, ',')
+ let command .= substitute(s:command_create_natures, '<natures>', natures, '')
+ endif
+
+ let depends = substitute(a:args, '.* -d\s\+\(.\{-}\)\(\s\+-\(n\|p\)\>.*\|$\)', '\1', '')
+ if depends != a:args
+ let depends = substitute(depends, '\s\+', ',', 'g')
+ let command .= substitute(s:command_create_depends, '<depends>', depends, '')
+ endif
+
+ " execute any pre-project creation hooks
+ let hook_result = s:ProjectNatureHooks(natureIds, 'ProjectCreatePre', [folder])
+ if type(hook_result) == g:NUMBER_TYPE && !hook_result
+ return
+ elseif type(hook_result) == g:STRING_TYPE && len(hook_result)
+ let command .= ' -a ' . hook_result
+ endif
+
+ let result = eclim#Execute(command, {'dir': folder})
+ if result != '0'
+ call eclim#util#Echo(result)
+ call eclim#project#util#ClearProjectsCache()
+ endif
+
+ " execute any post-project creation hooks
+ call s:ProjectNatureHooks(natureIds, 'ProjectCreatePost', [folder])
+endfunction " }}}
+
+function! s:ProjectNatureHooks(natureIds, hookName, args) " {{{
+ let results = ''
+ for nature in a:natureIds
+ if nature == 'none'
+ continue
+ endif
+
+ exec 'runtime autoload/eclim/' . nature . '/project.vim'
+ try
+ let l:Hook = function('eclim#' . nature . '#project#' . a:hookName)
+ let result = call(l:Hook, a:args)
+ if type(result) == g:NUMBER_TYPE && !result
+ return result
+ endif
+ if type(result) == g:STRING_TYPE
+ if len(results)
+ let results .= ' '
+ endif
+ let results .= result
+ endif
+ catch /E\(117\|700\):.*/
+ " ignore
+ endtry
+ endfor
+
+ if len(results)
+ return results
+ endif
+
+ return 1
+endfunction " }}}
+
+function! eclim#project#util#ProjectImport(arg) " {{{
+ let folder = fnamemodify(expand(a:arg), ':p')
+ let folder = substitute(folder, '\', '/', 'g')
+ if has('win32unix')
+ let folder = eclim#cygwin#WindowsPath(folder)
+ endif
+ let command = substitute(s:command_import, '<folder>', folder, '')
+
+ let naturesDict = {}
+ for [key, value] in items(eclim#project#util#GetNatureAliasesDict())
+ let naturesDict[value[-1]] = key
+ endfor
+
+ let natureIds = []
+ let dotproject = folder . '/' . '.project'
+ if filereadable(dotproject)
+ for line in readfile(dotproject)
+ if line =~ '^\s*<nature>'
+ let id = substitute(line, '.*\<nature>\(.*\)</nature>.*', '\1', '')
+ if has_key(naturesDict, id)
+ call add(natureIds, naturesDict[id])
+ endif
+ endif
+ endfor
+ if !s:ProjectNatureHooks(natureIds, 'ProjectImportPre', [folder])
+ return
+ endif
+ endif
+
+ let result = eclim#Execute(command, {'dir': folder})
+ if result != '0'
+ let project = eclim#project#util#GetProject(folder)
+ if !len(natureIds)
+ let natureIds = eclim#project#util#GetProjectNatureAliases(project)
+ endif
+ call s:ProjectNatureHooks(natureIds, 'ProjectImportPost', [project])
+ call eclim#util#Echo(result)
+ call eclim#project#util#ClearProjectsCache()
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectDelete(name) " {{{
+ let command = substitute(s:command_delete, '<project>', a:name, '')
+ let result = eclim#Execute(command, {'project': a:name})
+ if result != '0'
+ call eclim#util#Echo(result)
+ call eclim#project#util#ClearProjectsCache()
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectRename(args) " {{{
+ let args = eclim#util#ParseCmdLine(a:args)
+ if len(args) == 1
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+ let project = eclim#project#util#GetCurrentProjectName()
+ let name = args[0]
+ else
+ let project = args[0]
+ let name = args[1]
+ endif
+
+ if exists('g:EclimProjectRenamePrompt') && !g:EclimProjectRenamePrompt
+ let response = 1
+ else
+ let response = eclim#util#PromptConfirm(
+ \ printf("Rename project '%s' to '%s'", project, name),
+ \ g:EclimInfoHighlight)
+ endif
+
+ if response == 1
+ let command = s:command_rename
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<name>', name, '')
+ call s:ProjectMove(project, name, command)
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectMove(args) " {{{
+ let args = eclim#util#ParseCmdLine(a:args)
+ if len(args) == 1
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+ let project = eclim#project#util#GetCurrentProjectName()
+ let dir = args[0]
+ else
+ let project = args[0]
+ let dir = args[1]
+ endif
+ let dir = expand(dir)
+ let dir = substitute(fnamemodify(dir, ':p'), '\', '/', 'g')
+ if has('win32unix')
+ let dir = eclim#cygwin#WindowsPath(dir)
+ endif
+
+ if exists('g:EclimProjectMovePrompt') && !g:EclimProjectMovePrompt
+ let response = 1
+ else
+ let response = eclim#util#PromptConfirm(
+ \ printf("Move project '%s' to '%s'", project, dir),
+ \ g:EclimInfoHighlight)
+ endif
+
+ if response == 1
+ let command = s:command_move
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<dir>', dir, '')
+ call s:ProjectMove(project, project, command)
+ endif
+endfunction " }}}
+
+function! s:ProjectMove(oldname, newname, command) " {{{
+ let cwd = substitute(getcwd(), '\', '/', 'g')
+ let cwd_return = 1
+ let oldpath = eclim#project#util#GetProjectRoot(a:oldname)
+
+ let curwin = winnr()
+ try
+ " cd to home to avoid folder renaming issues on windows.
+ cd ~
+
+ " turn off swap files temporarily to avoid issues with folder renaming.
+ let bufend = bufnr('$')
+ let bufnum = 1
+ while bufnum <= bufend
+ if bufexists(bufnum)
+ call setbufvar(bufnum, 'save_swapfile', getbufvar(bufnum, '&swapfile'))
+ call setbufvar(bufnum, '&swapfile', 0)
+ endif
+ let bufnum = bufnum + 1
+ endwhile
+
+ " write all changes before moving
+ wall
+
+ let result = eclim#Execute(a:command, {'project': a:oldname})
+ if result == "0"
+ return
+ endif
+ call eclim#project#util#ClearProjectsCache()
+ let newpath = eclim#project#util#GetProjectRoot(a:newname)
+ if cwd =~ '^' . oldpath
+ exec 'cd ' . substitute(cwd, oldpath, newpath, '')
+ let cwd_return = 0
+ endif
+
+ " reload files affected by the project renaming
+ let bufnum = 1
+ while bufnum <= bufend
+ if buflisted(bufnum)
+ let path = substitute(fnamemodify(bufname(bufnum), ':p'), '\', '/', 'g')
+ if path =~ '^' . oldpath
+ let path = substitute(path, oldpath, newpath, '')
+ if filereadable(path)
+ let winnr = bufwinnr(bufnum)
+ if winnr != -1
+ exec winnr . 'winc w'
+ exec 'edit ' . eclim#util#Simplify(path)
+ endif
+ exec 'bdelete ' . bufnum
+ endif
+ endif
+ endif
+ let bufnum = bufnum + 1
+ endwhile
+
+ finally
+ exec curwin 'winc w'
+ if cwd_return
+ exec 'cd ' . escape(cwd, ' ')
+ endif
+
+ " re-enable swap files
+ let bufnum = 1
+ while bufnum <= bufend
+ if bufexists(bufnum)
+ let save_swapfile = getbufvar(bufnum, 'save_swapfile')
+ if save_swapfile != ''
+ call setbufvar(bufnum, '&swapfile', save_swapfile)
+ endif
+ endif
+ let bufnum = bufnum + 1
+ endwhile
+ endtry
+
+ call eclim#util#Echo(result)
+endfunction " }}}
+
+function! eclim#project#util#ProjectRefreshAll() " {{{
+ call eclim#project#util#ClearProjectsCache()
+ let projects = eclim#project#util#GetProjectNames()
+ for project in projects
+ call eclim#project#util#ProjectRefresh(project, 0)
+ endfor
+ call eclim#util#Echo('Done.')
+endfunction " }}}
+
+function! eclim#project#util#ProjectRefresh(args, ...) " {{{
+ " Optional args:
+ " clear_cache: Clear the in memory project cache first
+
+ if a:0 == 0 || a:000[0] == 1
+ call eclim#project#util#ClearProjectsCache()
+ endif
+
+ if a:args != ''
+ let projects = eclim#util#ParseCmdLine(a:args)
+ else
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+ let project = eclim#project#util#GetCurrentProjectName()
+ let projects = [project]
+ endif
+
+ for project in projects
+ call eclim#util#Echo("Updating project '" . project . "'...")
+ let command = substitute(s:command_refresh, '<project>', project, '')
+ call eclim#util#Echo(eclim#Execute(command, {'project': project}))
+ endfor
+
+ if len(projects) > 1
+ call eclim#util#Echo('Done.')
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectBuild(...) " {{{
+ " Option args:
+ " project: The name of the project to build (use the current project
+ " otherwise)
+ let project = a:0 > 0 ? a:1 : ''
+
+ if project == ''
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+ let project = eclim#project#util#GetCurrentProjectName()
+ endif
+
+ call eclim#util#Echo("Building project '" . project . "'...")
+ let command = substitute(s:command_build, '<project>', project, '')
+ let result = eclim#Execute(command, {'project': project})
+ call eclim#project#problems#ProblemsUpdate('build')
+ call eclim#util#Echo(result)
+endfunction " }}}
+
+function! eclim#project#util#ProjectInfo(project) " {{{
+ let project = a:project
+ if project == ''
+ let project = eclim#project#util#GetCurrentProjectName()
+ endif
+ if project == ''
+ call eclim#project#util#UnableToDetermineProject()
+ return
+ endif
+
+ let command = substitute(s:command_project_info, '<project>', project, '')
+ let result = eclim#Execute(command, {'project': project})
+ if type(result) == g:DICT_TYPE
+ let output =
+ \ 'Name: ' . result.name . "\n" .
+ \ 'Path: ' . result.path . "\n" .
+ \ 'Workspace: ' . result.workspace . "\n" .
+ \ 'Open: ' . (result.open ? 'true' : 'false')
+ if has_key(result, 'natures')
+ let output .= "\n" . 'Natures: ' . join(result.natures, ', ')
+ endif
+ if has_key(result, 'depends')
+ let output .= "\n" . 'Depends On: ' . join(result.depends, ', ')
+ endif
+ if has_key(result, 'referenced')
+ let output .= "\n" . 'Referenced By: ' . join(result.referenced, ', ')
+ endif
+ call eclim#util#Echo(output)
+ elseif type(result) == g:STRING_TYPE
+ call eclim#util#Echo(result)
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectStatusLine() " {{{
+ " Includes status information for the current file to VIM status
+
+ let project = eclim#project#util#GetProject(expand('%:p'))
+ if !empty(project)
+ let status = g:EclimProjectStatusLine
+ while status =~ '\${\w\+}'
+ let m = matchstr(status, '\${\w\+}')
+ let key = substitute(m, '^\${\(\w\+\)}', '\1', '')
+ let val = ''
+ if has_key(project, key)
+ let type = type(project[key])
+ if type == 1
+ let val = project[key]
+ elseif type == 3
+ let val = join(project[key], ',')
+ else
+ let val = string(project[key])
+ endif
+ endif
+ let status = substitute(status, m, val, 'g')
+ endwhile
+ return status
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectOpen(name) " {{{
+ let name = a:name
+ if name == ''
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+ let name = eclim#project#util#GetCurrentProjectName()
+ endif
+
+ let command = substitute(s:command_open, '<project>', name, '')
+ let result = eclim#Execute(command, {'project': name})
+ if result != '0'
+ call eclim#util#Echo(result)
+ call eclim#project#util#ClearProjectsCache()
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectClose(name) " {{{
+ let name = a:name
+ if name == ''
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+ let name = eclim#project#util#GetCurrentProjectName()
+ endif
+
+ let command = substitute(s:command_close, '<project>', name, '')
+ let result = eclim#Execute(command, {'project': name})
+ if result != '0'
+ call eclim#util#Echo(result)
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectList(workspace) " {{{
+ let projects = eclim#Execute(s:command_project_list, {'workspace': a:workspace})
+ if len(projects) == 0
+ call eclim#util#Echo("No projects.")
+ endif
+ if type(projects) != g:LIST_TYPE
+ return
+ endif
+
+ let pad = 0
+ for project in projects
+ let pad = len(project.name) > pad ? len(project.name) : pad
+ endfor
+
+ let output = []
+ for project in projects
+ call add(output,
+ \ eclim#util#Pad(project.name, pad) . ' - ' .
+ \ (project.open ? ' open ' : 'closed') . ' - ' .
+ \ project.path)
+ endfor
+
+ call eclim#util#Echo(join(output, "\n"))
+endfunction " }}}
+
+function! eclim#project#util#ProjectNatures(project) " {{{
+ " Prints nature info of one or all projects.
+
+ if !eclim#EclimAvailable()
+ return
+ endif
+
+ let command = s:command_natures
+ if a:project != ''
+ let command .= ' -p "' . a:project . '"'
+ let projects = eclim#Execute(command, {'project': a:project})
+ if type(projects) != g:LIST_TYPE
+ return
+ endif
+ else
+ let projects = []
+ let instances = eclim#client#nailgun#GetEclimdInstances()
+ for workspace in keys(instances)
+ let results = eclim#Execute(command, {'instance': instances[workspace]})
+ if type(results) != g:LIST_TYPE
+ continue
+ endif
+ let projects += results
+ endfor
+ endif
+
+ if len(projects) == 0
+ call eclim#util#Echo("No projects.")
+ endif
+
+ let pad = 0
+ for project in projects
+ let pad = len(project.name) > pad ? len(project.name) : pad
+ endfor
+
+ let output = []
+ for project in projects
+ call add(output,
+ \ eclim#util#Pad(project.name, pad) . ' - ' . join(project.natures, ', '))
+ endfor
+ call eclim#util#Echo(join(output, "\n"))
+endfunction " }}}
+
+function! eclim#project#util#ProjectNatureModify(command, args) " {{{
+ " Modifies one or more natures for the specified project.
+
+ let args = eclim#util#ParseCmdLine(a:args)
+
+ let project = args[0]
+ let natures = args[1:]
+ let command = a:command == 'add' ? s:command_nature_add : s:command_nature_remove
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<natures>', join(natures, ','), '')
+
+ if a:command == 'add'
+ let hook_result = s:ProjectNatureHooks(natures, 'ProjectNatureAddPre', [project])
+ if type(hook_result) == g:NUMBER_TYPE && !hook_result
+ return
+ elseif type(hook_result) == g:STRING_TYPE && len(hook_result)
+ let command .= ' -a ' . hook_result
+ endif
+ endif
+
+ let result = eclim#Execute(command, {'project': project})
+ if result != '0'
+ if a:command == 'add'
+ call s:ProjectNatureHooks(natures, 'ProjectNatureAddPost', [project])
+ endif
+ call eclim#util#Echo(result)
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectSettings(project) " {{{
+ " Opens a window that can be used to edit a project's settings.
+
+ let project = a:project
+ if project == ''
+ let project = eclim#project#util#GetCurrentProjectName()
+ endif
+ if project == ''
+ call eclim#project#util#UnableToDetermineProject()
+ return
+ endif
+
+ let command = substitute(s:command_project_settings, '<project>', project, '')
+ let settings = eclim#Execute(command, {'project': project})
+ if type(settings) != g:LIST_TYPE
+ return
+ endif
+
+ let content = ['# Settings for project: eclim', '']
+ let path = ''
+ for setting in settings
+ if setting.path != path
+ if path != ''
+ let content += ['# }', '']
+ endif
+ let path = setting.path
+ call add(content, '# ' . path . ' {')
+ endif
+ let description = split(setting.description, '\n')
+ let content += map(description, "'\t# ' . v:val")
+ call add(content, "\t" . setting.name . '=' . setting.value)
+ endfor
+ if path != ''
+ call add(content, '# }')
+ endif
+
+ call eclim#util#TempWindow(project . "_settings", content)
+ exec "lcd " . escape(eclim#project#util#GetProjectRoot(project), ' ')
+ setlocal buftype=acwrite
+ setlocal filetype=jproperties
+ setlocal noreadonly
+ setlocal modifiable
+ setlocal foldmethod=marker
+ setlocal foldmarker={,}
+ setlocal foldlevel=0
+
+ let b:project = project
+ augroup project_settings
+ autocmd! BufWriteCmd <buffer>
+ autocmd BufWriteCmd <buffer> call <SID>SaveSettings()
+ augroup END
+endfunction " }}}
+
+function! eclim#project#util#ProjectUpdate() " {{{
+ " Executes a project update which may also validate nature specific resource
+ " file.
+
+ let name = eclim#project#util#GetCurrentProjectName()
+ if name == ''
+ call eclim#util#EchoError('Unable to determine the project.')
+ return
+ endif
+
+ let command = substitute(s:command_project_update, '<project>', name, '')
+
+ let result = eclim#Execute(command)
+ if type(result) == g:LIST_TYPE && len(result) > 0
+ let errors = eclim#util#ParseLocationEntries(
+ \ result, g:EclimValidateSortResults)
+ call eclim#util#SetLocationList(errors)
+ else
+ call eclim#util#ClearLocationList()
+ call eclim#util#Echo(result)
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectGrep(command, args) " {{{
+ " Executes the supplied vim grep command with the specified pattern against
+ " one or more file patterns.
+
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let project = eclim#project#util#GetProject(expand('%:p'))
+ let tail = substitute(a:args, '\(.\).\{-}\1\s\(.*\)', '\2', '')
+ let pattern = substitute(a:args, '\(.*\)\s\+\M' . tail . '\m$', '\1', '')
+ let cmd = a:command
+ let acd = &autochdir
+ set noautochdir
+ try
+ if pattern != a:args && tail != a:args && tail != ''
+ let files = eclim#util#ParseArgs(tail)
+ let paths = ''
+ for file in files
+ if paths != ''
+ let paths .= ' '
+ endif
+ let paths .= escape(project.path, ' ') . '/' . file
+ endfor
+ let links = get(project, 'links', {})
+ if len(links)
+ for link in values(links)
+ for file in files
+ let paths .= ' ' . escape(link, ' ') . '/' . file
+ endfor
+ endfor
+ endif
+ silent exec a:command . ' ' . pattern . ' ' . paths
+ else
+ " let vim generate the proper error
+ silent exec a:command . ' ' . a:args
+ endif
+ catch /E480/
+ " no results found
+ catch /.*/
+ call eclim#util#EchoError(v:exception)
+ return
+ finally
+ let &autochdir = acd
+ " force quickfix / location list signs to update.
+ call eclim#display#signs#Update()
+ endtry
+
+ let numresults = len(a:command =~ '^l' ? getloclist(0) : getqflist())
+ if numresults == 0
+ call eclim#util#EchoInfo('No results found.')
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectTab(project) " {{{
+ " Opens a new tab with the project tree and tab relative working directory for
+ " the specified project.
+
+ let project = a:project
+ let names = eclim#project#util#GetProjectNames()
+ if index(names, project) == -1
+ let is_project = 0
+ let dir = expand(project, ':p')
+ if !isdirectory(dir)
+ if eclim#EclimAvailable(0)
+ call eclim#util#EchoError("No project '" . project . "' found.")
+ endif
+ return
+ endif
+ let project = fnamemodify(substitute(dir, '/$', '', ''), ':t')
+ else
+ let is_project = 1
+ let dir = eclim#project#util#GetProjectRoot(project)
+ endif
+
+ if exists('t:eclim_project') ||
+ \ winnr('$') > 1 || expand('%') != '' ||
+ \ &modified || line('$') != 1 || getline(1) != ''
+ tablast | tabnew
+ endif
+
+ let t:eclim_project = project
+ call eclim#common#util#Tcd(dir)
+ if g:EclimProjectTabTreeAutoOpen
+ if is_project
+ call eclim#project#tree#ProjectTree(project)
+ else
+ call eclim#project#tree#ProjectTree(dir)
+ endif
+ else
+ call eclim#util#Echo('ProjectTab ' . project . ' cwd: ' . dir)
+ endif
+endfunction " }}}
+
+function! eclim#project#util#Todo() " {{{
+ " Show the todo tags of the curent file in the location list.
+
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let path = expand('%:p')
+ silent! exec 'lvimgrep /' . g:EclimTodoSearchPattern . '/gj ' . path
+ if !empty(getloclist(0))
+ exec 'lopen ' . g:EclimLocationListHeight
+ else
+ call eclim#util#Echo('No Results found')
+ endif
+endfunction " }}}
+
+function! eclim#project#util#ProjectTodo() " {{{
+ " Show the todo tags of the whole project in the location list.
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ if len(g:EclimTodoSearchExtensions) == 0
+ endif
+
+ let project = eclim#project#util#GetProject(expand('%:p'))
+ let paths = ''
+ for ext in g:EclimTodoSearchExtensions
+ if paths != ''
+ let paths .= ' '
+ endif
+ let paths .= escape(project.path, ' ') . '/**/*' . ext
+ endfor
+ let links = get(project, 'links', {})
+ if len(links)
+ for link in values(links)
+ for ext in g:EclimTodoSearchExtensions
+ let paths .= ' ' . escape(link, ' ') . '/**/*' . ext
+ endfor
+ endfor
+ endif
+
+ silent! exec 'lvimgrep /' . g:EclimTodoSearchPattern . '/gj ' . paths
+
+ if !empty(getloclist(0))
+ exec 'lopen ' . g:EclimLocationListHeight
+ else
+ call eclim#util#Echo('No Results found')
+ endif
+endfunction " }}}
+
+function! s:SaveSettings() " {{{
+ call eclim#SaveSettings(s:command_update, b:project)
+endfunction " }}}
+
+function! eclim#project#util#GetCurrentProjectName() " {{{
+ " Gets the project name that the current file is in.
+ let project = eclim#project#util#GetProject(expand('%:p'))
+ return len(project) > 0 ? project.name : ''
+endfunction " }}}
+
+function! eclim#project#util#GetCurrentProjectRoot() " {{{
+ " Gets the project root dir for the project that the current file is in.
+ let project = eclim#project#util#GetProject(expand('%:p'))
+ return len(project) > 0 ? project.path : ''
+endfunction " }}}
+
+function! eclim#project#util#GetProjectWorkspace(name) " {{{
+ " Gets the workspace that a project belongs to.
+ let project = {}
+ for p in eclim#project#util#GetProjects()
+ if p.name == a:name
+ let project = p
+ break
+ endif
+ endfor
+ return get(project, 'workspace', '')
+endfunction " }}}
+
+function! eclim#project#util#GetProjectRelativeFilePath(...) " {{{
+ " Gets the project relative path for the current or supplied file.
+ " Optional args:
+ " file: get the relative path for this file instead of the current one.
+
+ if exists('b:eclim_file')
+ return b:eclim_file
+ endif
+
+ let file = a:0 == 0 ? expand('%:p') : a:1
+ let project = eclim#project#util#GetProject(file)
+ if !len(project)
+ return ''
+ endif
+
+ let file = substitute(fnamemodify(file, ':p'), '\', '/', 'g')
+ let pattern = '\(/\|$\)'
+ if has('win32') || has('win64')
+ let pattern .= '\c'
+ endif
+ let result = substitute(file, get(project, 'path', '') . pattern, '', '')
+
+ " handle file in linked folder
+ if result == file
+ for name in keys(get(project, 'links', {}))
+ if file =~ '^' . project.links[name] . pattern
+ let result = substitute(file, project.links[name], name, '')
+ endif
+ endfor
+ endif
+
+ if result != file && result =~ '^/'
+ let result = result[1:]
+ endif
+ return result
+endfunction " }}}
+
+function! eclim#project#util#GetProjects() " {{{
+ " Returns a list of project dictionaries containing the following properties:
+ " workspace: The path of the workspace the project belongs to.
+ " name: The name of the project.
+ " path: The root path of the project.
+ " links: List of linked paths.
+ let instances = eclim#client#nailgun#GetEclimdInstances()
+
+ if keys(s:workspace_projects) != keys(instances)
+ let s:workspace_projects = {}
+ for workspace in keys(instances)
+ let instance = instances[workspace]
+ let results = eclim#Execute(
+ \ s:command_projects, {'instance': instance})
+ if type(results) != g:LIST_TYPE
+ continue
+ endif
+
+ if has('win32unix')
+ " gather paths to translate
+ let winpaths = []
+ for project in results
+ call add(winpaths, project['path'])
+ if has_key(project, 'links')
+ for key in sort(keys(project['links']))
+ call add(winpaths, project['links'][key])
+ endfor
+ endif
+ endfor
+
+ let cygpaths = eclim#cygwin#CygwinPath(winpaths)
+
+ " update each project with the cygwin version of its paths
+ let index = 0
+ for project in results
+ let project['path'] = cygpaths[index]
+ let index += 1
+ if has_key(project, 'links')
+ for key in sort(keys(project['links']))
+ let project['links'][key] = cygpaths[index]
+ let index += 1
+ endfor
+ endif
+ endfor
+ endif
+
+ for project in results
+ let project['workspace'] = instance.workspace
+ endfor
+
+ let s:workspace_projects[instance.workspace] = results
+ unlet results
+ endfor
+ endif
+
+ let all = []
+ for projects in values(s:workspace_projects)
+ let all += copy(projects)
+ endfor
+ return all
+endfunction " }}}
+
+function! eclim#project#util#GetProject(path) " {{{
+ " if a [No Name] buffer, use the current working directory.
+ let path = a:path != '' ? a:path : getcwd()
+
+ let path = substitute(fnamemodify(path, ':p'), '\', '/', 'g')
+ let pattern = '\(/\|$\)'
+ if has('win32') || has('win64')
+ let pattern .= '\c'
+ endif
+
+ let projects = eclim#project#util#GetProjects()
+
+ " sort projects depth wise by path to properly support nested projects.
+ call sort(projects, 's:ProjectSortPathDepth')
+
+ for project in projects
+ if path =~ '^' . project.path . pattern
+ return project
+ endif
+
+ if has_key(project, 'link') && path =~ '^' . project.link . pattern
+ return project
+ endif
+
+ " check linked folders
+ for name in keys(get(project, 'links', {}))
+ if path =~ '^' . project.links[name] . pattern
+ return project
+ endif
+ endfor
+ endfor
+
+ " project not found by path, fallback to buffer local variable
+ if exists('b:eclim_project')
+ for project in projects
+ if project.name == b:eclim_project
+ return project
+ endif
+ endfor
+ endif
+
+ return {}
+endfunction " }}}
+
+function! s:ProjectSortPathDepth(p1, p2) " {{{
+ return len(a:p2.path) - len(a:p1.path)
+endfunction " }}}
+
+function! eclim#project#util#GetProjectDirs() " {{{
+ " Gets list of all project root directories.
+ return map(eclim#project#util#GetProjects(), 'v:val.path')
+endfunction " }}}
+
+function! eclim#project#util#GetProjectNames(...) " {{{
+ " Gets list of all project names, with optional filter by the supplied nature
+ " alias.
+ " Option args:
+ " nature: The nature alias to filter projects by
+
+ " filter by nature
+ if a:0 > 0 && a:1 != ''
+ let projects = []
+ let command = s:command_project_list . ' -n ' . a:1
+ let instances = eclim#client#nailgun#GetEclimdInstances()
+ for workspace in keys(instances)
+ let results = eclim#Execute(command, {'instance': instances[workspace]})
+ if type(results) != g:LIST_TYPE
+ continue
+ endif
+ let projects += results
+ endfor
+
+ call map(projects, "v:val.name")
+ return projects
+ endif
+
+ let names = map(eclim#project#util#GetProjects(), 'v:val.name')
+ call sort(names)
+ return names
+endfunction " }}}
+
+function! eclim#project#util#GetProjectNatureAliases(...) " {{{
+ " Gets list of all project nature aliases or a list of aliases associated with
+ " a project if the project name is supplied.
+ " Optional args:
+ " project: the project to get natures aliases from.
+
+ if a:0 > 0 && a:1 != ''
+ let command = s:command_natures . ' -p "' . a:1 . '"'
+ let result = eclim#Execute(command)
+ if type(result) != g:LIST_TYPE || len(result) == 0
+ return []
+ endif
+ return result[0]['natures']
+ endif
+
+ let aliases = eclim#Execute(s:command_nature_aliases)
+ if type(aliases) != g:LIST_TYPE
+ return []
+ endif
+
+ return aliases
+endfunction " }}}
+
+function! eclim#project#util#GetNatureAliasesDict() " {{{
+ " Gets a dict of all natures aliases where the alias is the key and the nature
+ " id is the value.
+
+ let aliases = eclim#Execute(s:command_nature_aliases . ' -m')
+ if type(aliases) != g:DICT_TYPE
+ return {}
+ endif
+
+ return aliases
+endfunction " }}}
+
+function! eclim#project#util#GetProjectRoot(name) " {{{
+ " Gets the project root dir for the supplied project name.
+
+ let project = {}
+ for p in eclim#project#util#GetProjects()
+ if p.name == a:name
+ let project = p
+ break
+ endif
+ endfor
+ return get(project, 'path', '')
+endfunction " }}}
+
+function! eclim#project#util#GetProjectSetting(setting) " {{{
+ " Gets a project setting from eclim. Returns '' if the setting does not
+ " exist, 0 if not in a project or an error occurs communicating with the
+ " server.
+
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let command = s:command_project_setting
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<setting>', a:setting, '')
+
+ let result = eclim#Execute(command)
+ if result == '0'
+ return result
+ endif
+
+ if result == ''
+ call eclim#util#EchoWarning("Setting '" . a:setting . "' does not exist.")
+ endif
+ return result
+endfunction " }}}
+
+function! eclim#project#util#SetProjectSetting(setting, value) " {{{
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let command = s:command_project_setting
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<setting>', a:setting, '')
+ let command .= ' -v "' . a:value . '"'
+
+ call eclim#Execute(command)
+endfunction " }}}
+
+function! eclim#project#util#IsCurrentFileInProject(...) " {{{
+ " Determines if the current file is in a project directory.
+ " Accepts an optional arg that determines if a message is displayed to the
+ " user if the file is not in a project(defaults to 1, to display the
+ " message).
+ " Optional args:
+ " echo_error (default: 1): when non-0, echo an error to the user if project
+ " could not be determined.
+
+ let echo = a:0 ? a:1 : 1
+ if !echo
+ silent let project = eclim#project#util#GetCurrentProjectName()
+ else
+ let project = eclim#project#util#GetCurrentProjectName()
+ endif
+
+ if project == ''
+ " if eclimd isn't available, then that could be the reason the project
+ " couldn't be determined, so don't hide that message with this one.
+ if echo && eclim#EclimAvailable(0)
+ call eclim#util#EchoError('Unable to determine the project. ' .
+ \ 'Check that the current file is in a valid project.')
+ endif
+ return 0
+ endif
+ return 1
+endfunction " }}}
+
+function! eclim#project#util#RefreshFileBootstrap() " {{{
+ " Boostraps a post write autocommand for updating files, which forces a
+ " refresh by the eclim project. The command should only be called as part of
+ " the a BufWritePre autocmd.
+ if eclim#project#util#GetCurrentProjectName() != '' && &modified
+ let refresh = !exists('b:EclimRefreshDisabled') || !b:EclimRefreshDisabled
+ if refresh
+ augroup eclim_refresh_files_bootstrap
+ autocmd!
+ autocmd BufWritePost <buffer> call eclim#project#util#RefreshFile()
+ augroup END
+ endif
+ endif
+endfunction " }}}
+
+function! eclim#project#util#RefreshFile() " {{{
+ " Refreshes the current files in eclipse.
+ augroup eclim_refresh_files_bootstrap
+ autocmd! BufWritePost <buffer>
+ augroup END
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:command_refresh_file
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ call eclim#Execute(command)
+endfunction " }}}
+
+function! eclim#project#util#UnableToDetermineProject() " {{{
+ " if eclimd isn't available, then that could be the reason the project
+ " couldn't be determined, so don't hide that message with this one.
+ if eclim#EclimAvailable(0)
+ call eclim#util#EchoError("Unable to determine the project. " .
+ \ "Please specify a project name or " .
+ \ "execute from a valid project directory.")
+ endif
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteProject(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for project names.
+ return eclim#project#util#CommandCompleteProjectByNature(
+ \ a:argLead, a:cmdLine, a:cursorPos, '')
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteProjectContainsThis(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for project names, filtering by those that contain
+ " a file with the same path as the current file, excluding the current
+ " project.
+
+ let names = eclim#project#util#CommandCompleteProject(
+ \ a:argLead, a:cmdLine, a:cursorPos)
+
+ let path = eclim#project#util#GetProjectRelativeFilePath()
+ let project = eclim#project#util#GetCurrentProjectName()
+ let projects = eclim#project#util#GetProjects()
+ call filter(names, 'v:val != project && filereadable(eclim#project#util#GetProjectRoot(v:val) . "/" . path)')
+ return names
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteProjectByNature(argLead, cmdLine, cursorPos, nature) " {{{
+ " Custom command completion for project names limited by the supplied nature.
+
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+
+ let projects = eclim#project#util#GetProjectNames(a:nature)
+ if cmdLine !~ '[^\\]\s$'
+ let argLead = escape(escape(argLead, '~'), '~')
+ " remove escape slashes
+ let argLead = substitute(argLead, '\', '', 'g')
+ call filter(projects, 'v:val =~ "^' . argLead . '"')
+ endif
+
+ call map(projects, 'escape(v:val, " ")')
+ return projects
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteProjectCreate(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for ProjectCreate args.
+
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+
+ " complete dirs for first arg
+ if cmdLine =~ '^' . args[0] . '\s\+' . escape(argLead, '~.\') . '$'
+ return eclim#util#CommandCompleteDir(a:argLead, a:cmdLine, a:cursorPos)
+ endif
+
+ " complete nature aliases
+ if cmdLine =~ '-n\s\+[^-]*$'
+ let aliases = eclim#project#util#GetProjectNatureAliases()
+
+ " if one alias already supplied complete options as well
+ if cmdLine !~ '-n\s\+$' && argLead == ''
+ let aliases =
+ \ s:CommandCompleteProjectCreateOptions(argLead, a:cmdLine, a:cursorPos) +
+ \ aliases
+ endif
+
+ if cmdLine !~ '[^\\]\s$'
+ call filter(aliases, 'v:val =~ "^' . escape(escape(argLead, '~.\'), '\') . '"')
+ endif
+
+ return aliases
+ endif
+
+ " complete project dependencies
+ if cmdLine =~ '-d\s\+[^-]*$'
+ " if one dependency already supplied complete options as well
+ if cmdLine !~ '-d\s\+$' && argLead == ''
+ let options =
+ \ s:CommandCompleteProjectCreateOptions(argLead, a:cmdLine, a:cursorPos)
+ return options +
+ \ eclim#project#util#CommandCompleteProject(argLead, a:cmdLine, a:cursorPos)
+ endif
+ return eclim#project#util#CommandCompleteProject(argLead, a:cmdLine, a:cursorPos)
+ endif
+
+ return s:CommandCompleteProjectCreateOptions(argLead, a:cmdLine, a:cursorPos)
+endfunction " }}}
+
+function! s:CommandCompleteProjectCreateOptions(argLead, cmdLine, cursorPos) " {{{
+ let options = ['-n', '-d', '-p']
+ if a:cmdLine =~ '\s-n\>'
+ call remove(options, index(options, '-n'))
+ endif
+ if a:cmdLine =~ '\s-d\>'
+ call remove(options, index(options, '-d'))
+ endif
+ if a:cmdLine =~ '\s-p\>'
+ call remove(options, index(options, '-p'))
+ endif
+ return options
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteProjectMove(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for ProjectMove args.
+
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+
+ " complete dirs for second arg if first arg is a project name
+ if len(args) > 1 && eclim#project#util#GetProjectRoot(args[1]) != '' &&
+ \ cmdLine =~ '^' . args[0] . '\s\+' . args[1] . '\s\+' . escape(argLead, '~.\') . '$'
+ return eclim#util#CommandCompleteDir(a:argLead, a:cmdLine, a:cursorPos)
+ endif
+
+ " attempt complete project and dir for first arg
+ if cmdLine =~ '^' . args[0] . '\s\+' . escape(argLead, '~.\') . '$'
+ let projects = []
+ let dirs = eclim#util#CommandCompleteDir(a:argLead, a:cmdLine, a:cursorPos)
+ if argLead !~ '[~]'
+ let projects = eclim#project#util#CommandCompleteProject(
+ \ argLead, a:cmdLine, a:cursorPos)
+ endif
+ return projects + dirs
+ endif
+ return []
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteProjectRelative(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for project relative files and directories.
+
+ let dir = eclim#project#util#GetCurrentProjectRoot()
+ if dir == '' && exists('b:project')
+ let dir = eclim#project#util#GetProjectRoot(b:project)
+ endif
+
+ if dir == ''
+ return []
+ endif
+
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : (len(args) > 0 ? args[len(args) - 1] : '')
+
+ let results = split(eclim#util#Glob(dir . '/' . argLead . '*', 1), '\n')
+ call map(results, "substitute(v:val, '\\', '/', 'g')")
+ call map(results, 'isdirectory(v:val) ? v:val . "/" : v:val')
+ call map(results, 'substitute(v:val, dir, "", "")')
+ call map(results, 'substitute(v:val, "^\\(/\\|\\\\\\)", "", "g")')
+ call map(results, "substitute(v:val, ' ', '\\\\ ', 'g')")
+
+ return eclim#util#ParseCommandCompletionResults(argLead, results)
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteProjectRelativeDir(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for project relative files and directories.
+
+ let dir = eclim#project#util#GetCurrentProjectRoot()
+ if dir == '' && exists('b:project')
+ let dir = eclim#project#util#GetProjectRoot(b:project)
+ endif
+
+ if dir == ''
+ return []
+ endif
+
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : (len(args) > 0 ? args[len(args) - 1] : '')
+
+ let results = split(eclim#util#Glob(dir . '/' . argLead . '*', 1), '\n')
+ call map(results, "substitute(v:val, '\\', '/', 'g')")
+ call filter(results, 'isdirectory(v:val)')
+ call map(results, 'v:val . "/"')
+ call map(results, 'substitute(v:val, dir, "", "")')
+ call map(results, 'substitute(v:val, "^\\(/\\|\\\\\\)", "", "g")')
+ call map(results, "substitute(v:val, ' ', '\\\\ ', 'g')")
+
+ return eclim#util#ParseCommandCompletionResults(argLead, results)
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteProjectOrDirectory(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for :ProjectTree/:ProjectTab to complete project names or
+ " directories
+
+ let projects = []
+ if a:argLead !~ '[~/]'
+ let projects = eclim#project#util#CommandCompleteProjectByNature(
+ \ a:argLead, a:cmdLine, a:cursorPos, '')
+ endif
+ let dirs = eclim#util#CommandCompleteDir(a:argLead, a:cmdLine, a:cursorPos)
+ return projects + dirs
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteAbsoluteOrProjectRelative(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for project relative files and directories.
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ if len(args) > 0
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+ if argLead =~ '^\(/\|[a-zA-Z]:\)'
+ return eclim#util#CommandCompleteFile(a:argLead, a:cmdLine, a:cursorPos)
+ endif
+ endif
+ return eclim#project#util#CommandCompleteProjectRelative(
+ \ a:argLead, a:cmdLine, a:cursorPos)
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteAbsoluteOrProjectRelativeDir(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for project relative files and directories.
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ if len(args) > 0
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+ if argLead =~ '^\(/\|[a-zA-Z]:\)'
+ return eclim#util#CommandCompleteDir(a:argLead, a:cmdLine, a:cursorPos)
+ endif
+ endif
+ return eclim#project#util#CommandCompleteProjectRelativeDir(
+ \ a:argLead, a:cmdLine, a:cursorPos)
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteProjectNatureAdd(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for project names and natures.
+ return s:CommandCompleteProjectNatureModify(
+ \ a:argLead, a:cmdLine, a:cursorPos, function("s:AddAliases"))
+endfunction " }}}
+
+function! s:AddAliases(allAliases, projectAliases) " {{{
+ let aliases = a:allAliases
+ call filter(aliases, 'index(a:projectAliases, v:val) == -1')
+ return aliases
+endfunction " }}}
+
+function! eclim#project#util#CommandCompleteProjectNatureRemove(argLead, cmdLine, cursorPos) " {{{
+ " Custom command completion for project names and natures.
+ return s:CommandCompleteProjectNatureModify(
+ \ a:argLead, a:cmdLine, a:cursorPos, function("s:RemoveAliases"))
+endfunction " }}}
+
+function! s:RemoveAliases(allAliases, projectAliases) " {{{
+ return a:projectAliases
+endfunction " }}}
+
+function! s:CommandCompleteProjectNatureModify(argLead, cmdLine, cursorPos, aliasesFunc) " {{{
+ " Custom command completion for project names and natures.
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+
+ " complete dirs for first arg
+ if cmdLine =~ '^' . args[0] . '\s\+' . escape(argLead, '~.\') . '$'
+ return eclim#project#util#CommandCompleteProject(argLead, a:cmdLine, a:cursorPos)
+ endif
+
+ let allAliases = eclim#project#util#GetProjectNatureAliases()
+ call filter(allAliases, 'v:val != "none"')
+
+ let projectAliases = eclim#project#util#GetProjectNatureAliases(args[1])
+ let aliases = a:aliasesFunc(allAliases, projectAliases)
+ if cmdLine !~ '[^\\]\s$'
+ call filter(aliases, 'v:val =~ "^' . argLead . '"')
+ endif
+
+ call filter(aliases, 'index(args[2:], v:val) == -1')
+
+ return aliases
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/python/complete.vim b/vim/eclim/autoload/eclim/python/complete.vim
@@ -0,0 +1,113 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/complete.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" CodeComplete(findstart, base) {{{
+" Handles python code completion.
+function! eclim#python#complete#CodeComplete(findstart, base)
+ if !eclim#project#util#IsCurrentFileInProject(0)
+ return a:findstart ? -1 : []
+ endif
+
+ if a:findstart
+ call eclim#lang#SilentUpdate(1)
+
+ " locate the start of the word
+ let line = getline('.')
+
+ let start = col('.') - 1
+
+ "exceptions that break the rule
+ if line[start] =~ '\.'
+ let start -= 1
+ endif
+
+ while start > 0 && line[start - 1] =~ '\w'
+ let start -= 1
+ endwhile
+
+ return start
+ else
+ let offset = eclim#python#rope#GetOffset() + len(a:base)
+ let encoding = eclim#util#GetEncoding()
+ let project = eclim#project#util#GetCurrentProjectRoot()
+ let file = eclim#lang#SilentUpdate(1, 0)
+ if file == ''
+ return []
+ endif
+
+ let completions = []
+ let results = eclim#python#rope#Completions(project, file, offset, encoding)
+
+ let open_paren = getline('.') =~ '\%' . col('.') . 'c\s*('
+ let close_paren = getline('.') =~ '\%' . col('.') . 'c\s*(\s*)'
+
+ for result in results
+ let word = result[0]
+ let kind = result[1]
+ let info = ''
+ if result[2] != ''
+ let word .= '('
+ let info = result[0] . '(' . result[2] . ')'
+ let menu = info
+ else
+ if kind == 'f'
+ let word .= '()'
+ endif
+ let menu = word
+ endif
+
+ " map 'a' (attribute) to 'v'
+ if kind == 'a'
+ let kind = 'v'
+
+ " map 'c' (class) to 't'
+ elseif kind == 'c'
+ let kind = 't'
+ endif
+
+ " strip off close paren if necessary.
+ if word =~ ')$' && close_paren
+ let word = strpart(word, 0, strlen(word) - 1)
+ endif
+
+ " strip off open paren if necessary.
+ if word =~ '($' && open_paren
+ let word = strpart(word, 0, strlen(word) - 1)
+ endif
+
+ let dict = {
+ \ 'word': word,
+ \ 'kind': kind,
+ \ 'menu': menu,
+ \ 'info': info,
+ \ }
+
+ call add(completions, dict)
+ endfor
+
+ return completions
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/python/django/find.vim b/vim/eclim/autoload/eclim/python/django/find.vim
@@ -0,0 +1,253 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/django.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2010 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists('g:EclimDjangoFindAction')
+ let g:EclimDjangoFindAction = g:EclimDefaultFileOpenAction
+endif
+if !exists('g:EclimDjangoStaticPaths')
+ let g:EclimDjangoStaticPaths = []
+endif
+" }}}
+
+" FindFilterOrTag(project_dir, element, type) {{{
+" Finds and opens the supplied filter or tag definition.
+function! eclim#python#django#find#FindFilterOrTag(project_dir, element, type)
+ let loaded = eclim#python#django#util#GetLoadList(a:project_dir)
+ let cmd = 'lvimgrep /\<def\s\+' . a:element . '\>/j '
+ for file in loaded
+ let cmd .= ' ' . file
+ endfor
+
+ silent! exec cmd
+
+ let results = getloclist(0)
+ if len(results) > 0
+ call eclim#util#GoToBufferWindowOrOpen(
+ \ bufname(results[0].bufnr), g:EclimDjangoFindAction)
+ lfirst
+ return 1
+ endif
+ call eclim#util#EchoError(
+ \ 'Unable to find the definition for tag/file "' . a:element . '"')
+endfunction " }}}
+
+" FindFilterTagFile(project_dir, file) {{{
+" Finds and opens the supplied tag/file definition file.
+function! eclim#python#django#find#FindFilterTagFile(project_dir, file)
+ let file = findfile(a:file . '.py', a:project_dir . '*/templatetags/')
+ if file != ''
+ call eclim#util#GoToBufferWindowOrOpen(file, g:EclimDjangoFindAction)
+ return 1
+ endif
+ call eclim#util#EchoError('Could not find tag/filter file "' . a:file . '.py"')
+endfunction " }}}
+
+" FindSettingDefinition(project_dir, value) {{{
+" Finds and opens the definition for the supplied setting middleware, context
+" processor or template loader.
+function! eclim#python#django#find#FindSettingDefinition(project_dir, value)
+ let file = substitute(a:value, '\(.*\)\..*', '\1', '')
+ let def = substitute(a:value, '.*\.\(.*\)', '\1', '')
+ let file = substitute(file, '\.', '/', 'g') . '.py'
+
+ let project_dir = a:project_dir
+ let found = findfile(file, project_dir)
+
+ if found == ''
+ let project_dir = fnamemodify(a:project_dir, ':h')
+ let found = findfile(file, project_dir)
+ endif
+
+ if found == ''
+ let file = substitute(file, '\.py', '/__init__.py', '')
+ let found = findfile(file, project_dir)
+ endif
+
+ if found != ''
+ call eclim#util#GoToBufferWindowOrOpen(found, g:EclimDjangoFindAction)
+ call search('\(def\|class\)\s\+' . def . '\>', 'cw')
+ return 1
+ endif
+ call eclim#util#EchoError('Could not definition of "' . a:value . '"')
+endfunction " }}}
+
+" FindStaticFile(project_dir, file) {{{
+" Finds and opens the supplied static file name.
+function! eclim#python#django#find#FindStaticFile(project_dir, file)
+ for path in g:EclimDjangoStaticPaths + ['.', 'static', '../static']
+ if path !~ '^\(/\|\w:\)'
+ let path = a:project_dir . '/' . path
+ endif
+ let file = findfile(a:file, path)
+ if file != ''
+ call eclim#util#GoToBufferWindowOrOpen(file, g:EclimDjangoFindAction)
+ return 1
+ endif
+ endfor
+ call eclim#util#EchoError('Could not find the static file "' . a:file . '"')
+endfunction " }}}
+
+" FindTemplate(project_dir, template) {{{
+" Finds and opens the supplied template definition.
+function! eclim#python#django#find#FindTemplate(project_dir, template)
+ let dirs = eclim#python#django#util#GetTemplateDirs(a:project_dir)
+ for dir in dirs
+ let template_dir = dir
+ if template_dir !~ '^' . a:project_dir
+ if fnamemodify(a:project_dir, ':t') == split(dir, '/')[0]
+ let template_dir = fnamemodify(a:project_dir, ':h') . '/' . dir
+ else
+ let template_dir = a:project_dir . '/' . dir
+ endif
+ endif
+ let file = findfile(a:template, template_dir)
+ if file != ''
+ call eclim#util#GoToBufferWindowOrOpen(file, g:EclimDjangoFindAction)
+ return 1
+ endif
+ endfor
+ call eclim#util#EchoError('Could not find the template "' . a:template . '"')
+endfunction " }}}
+
+" FindView(project_dir, template) {{{
+" Finds and opens the supplied view.
+function! eclim#python#django#find#FindView(project_dir, view)
+ let view = a:view
+ let function = ''
+
+ " basic check to see if on a url pattern instead of the view.
+ if view =~ '[?(*^$]'
+ call eclim#util#EchoError(
+ \ 'String under the curser does not appear to be a view: "' . view . '"')
+ return
+ endif
+
+ if getline('.') !~ "\\(include\\|patterns\\)\\s*(\\s*['\"]" . view
+ " see if a view prefix was defined.
+ let start = search('patterns\_s*(', 'bnW')
+ let end = search("patterns\\_s*(\\_s*['\"]", 'bnWe')
+ if start && end
+ let line = getline(start)
+ if end != start
+ let line .= getline(end)
+ endif
+ let prefix = substitute(
+ \ line, ".*patterns\\s*(\\s*['\"]\\(.\\{-}\\)['\"].*", '\1', '')
+ if prefix != ''
+ let view = prefix . '.' . view
+ endif
+ endif
+
+ let function = split(view, '\.')[-1]
+ let view = join(split(view, '\.')[0:-2], '.')
+ endif
+
+ let parts = split(substitute(view, '\.', '/', 'g') . '.py', '/')
+
+ " first search for full reference
+ let file = findfile(join(parts, '/'), a:project_dir)
+
+ " if not found, try removing the first path since we probably have a top
+ " level namespace that we are in.
+ if file == ''
+ let file = findfile(join(parts[1:], '/'), a:project_dir)
+ endif
+
+ if file != ''
+ call eclim#util#GoToBufferWindowOrOpen(file, g:EclimDjangoFindAction)
+ if function != ''
+ let found = search('def\s\+' . function . '\>', 'cws')
+ if !found
+ call eclim#util#EchoWarning(
+ \ 'Could not find the view function "' . function . '" in file ' . file)
+ endif
+ endif
+ return 1
+ endif
+ call eclim#util#EchoError('Could not find the view "' . view . '"')
+endfunction " }}}
+
+" TemplateFind() {{{
+" Find the template, tag, or filter under the cursor.
+function! eclim#python#django#find#TemplateFind()
+ let project_dir = eclim#python#django#util#GetProjectPath()
+ if project_dir == ''
+ call eclim#util#EchoError(
+ \ 'Unable to locate django project path with manage.py and settings.py')
+ return
+ endif
+
+ let line = getline('.')
+ let element = eclim#util#GrabUri()
+ if element =~ '|'
+ let element = substitute(
+ \ getline('.'), '.*|.*\(\<\w*\%' . col('.') . 'c\w*\>\).*', '\1', '')
+ if element == getline('.')
+ return
+ endif
+ return eclim#python#django#find#FindFilterOrTag(project_dir, element, 'filter')
+ elseif line =~ '{%\s*' . element . '\>'
+ return eclim#python#django#find#FindFilterOrTag(project_dir, element, 'tag')
+ elseif line =~ '{%\s*load\s\+[^%]\{-}\%' . col('.') . 'c'
+ let element = expand('<cword>')
+ if element !~ '^\w\+$'
+ return
+ endif
+ return eclim#python#django#find#FindFilterTagFile(project_dir, element)
+ elseif line =~ "{%\\s*\\(extends\\|include\\)\\s\\+['\"]" . element . "['\"]"
+ return eclim#python#django#find#FindTemplate(project_dir, element)
+ elseif line =~ "\\(src\\|href\\)\\s*=\\s*['\"]\\?\\s*" . element
+ let element = substitute(element, '^/', '', '')
+ let element = substitute(element, '?.*', '', '')
+ return eclim#python#django#find#FindStaticFile(project_dir, element)
+ endif
+ call eclim#util#EchoError(
+ \ 'Element under the cursor does not appear to be a ' .
+ \ 'valid tag, filter, or template reference.')
+endfunction " }}}
+
+" ContextFind() {{{
+" Execute DjangoViewOpen, DjangoTemplateOpen, or PythonFindDefinition based on
+" the context of the text under the cursor.
+function! eclim#python#django#find#ContextFind()
+ if getline('.') =~ "['\"][^'\" ]*\\%" . col('.') . "c[^'\" ]*['\"]"
+ if eclim#util#GrabUri() !~ '\.html' && (
+ \ search("reverse\\_s*(\\_s*['\"][^'\" ]*\\%" . col('.') . "c[^'\" ]*['\"]", 'nw') ||
+ \ search('urlpatterns\s\+=\s\+patterns(', 'nw'))
+ return eclim#python#django#find#FindView(
+ \ eclim#python#django#util#GetProjectPath(), eclim#util#GrabUri())
+ elseif expand('%:t') == 'settings.py'
+ return eclim#python#django#find#FindSettingDefinition(
+ \ eclim#python#django#util#GetProjectPath(), eclim#util#GrabUri())
+ else
+ return eclim#python#django#find#FindTemplate(
+ \ eclim#python#django#util#GetProjectPath(), eclim#util#GrabUri())
+ endif
+ "else
+ " PythonFindDefinition
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/python/django/manage.vim b/vim/eclim/autoload/eclim/python/django/manage.vim
@@ -0,0 +1,198 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/django.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2010 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists('g:EclimPythonInterpreter')
+ let g:EclimPythonInterpreter = 'python'
+endif
+if !exists('g:EclimDjangoAdmin')
+ let g:EclimDjangoAdmin = 'django-admin.py'
+endif
+" }}}
+
+" Script Variables {{{
+" reset and runfcgi removed?
+" test requires django > 0.95
+let s:manage_actions = [
+ \ 'adminindex',
+ \ 'createcachetable',
+ \ 'dbshell',
+ \ 'diffsettings',
+ \ 'inspectdb',
+ \ 'install',
+ \ 'reset',
+ \ 'runfcgi',
+ \ 'runserver',
+ \ 'shell',
+ \ 'sql',
+ \ 'sqlall',
+ \ 'sqlclear',
+ \ 'sqlindexes',
+ \ 'sqlinitialdata',
+ \ 'sqlreset',
+ \ 'sqlsequencereset',
+ \ 'startapp',
+ \ 'startproject',
+ \ 'syncdb',
+ \ 'test',
+ \ 'validate',
+ \ ]
+
+let s:app_actions = [
+ \ 'adminindex',
+ \ 'install',
+ \ 'reset',
+ \ 'sql',
+ \ 'sqlall',
+ \ 'sqlclear',
+ \ 'sqlindexes',
+ \ 'sqlinitialdata',
+ \ 'sqlreset',
+ \ 'sqlsequencereset'
+ \ ]
+
+let s:output_actions = [
+ \ 'adminindex',
+ \ 'diffsettings',
+ \ 'inspectdb',
+ \ 'sql',
+ \ 'sqlall',
+ \ 'sqlclear',
+ \ 'sqlindexes',
+ \ 'sqlinitialdata',
+ \ 'sqlreset',
+ \ 'sqlsequencereset'
+ \ ]
+
+let s:sql_dialects = {
+ \ 'ado_mysql': 'mysql.vim',
+ \ 'mysql': 'mysql.vim',
+ \ 'mysql_old': 'mysql.vim',
+ \ 'postgresql': 'plsql.vim',
+ \ 'postgresql_psycopg2': 'plsql.vim',
+ \ 'sqlite3': 'sql.vim',
+ \ }
+
+" }}}
+
+" DjangoManage(args) {{{
+function! eclim#python#django#manage#Manage(args)
+ let cwd = getcwd()
+ if a:args =~ '^startproject\s'
+ if !executable(g:EclimDjangoAdmin)
+ call eclim#util#EchoError(
+ \ g:EclimDjangoAdmin . ' is either not executable or not in your path.')
+ return
+ endif
+ let command = g:EclimDjangoAdmin
+ else
+ if !executable(g:EclimPythonInterpreter)
+ call eclim#util#EchoError(
+ \ g:EclimPythonInterpreter . ' is either not executable or not in your path.')
+ return
+ endif
+ let command = g:EclimPythonInterpreter . ' manage.py'
+
+ " change to project directory before executing manage script.
+ let path = eclim#python#django#util#GetProjectPath()
+ if path == ''
+ call eclim#util#EchoError('Current file not in a django project.')
+ return
+ endif
+ exec 'cd ' . escape(path, ' ')
+ endif
+
+ try
+ let action = substitute(a:args, '^\(.\{-}\)\(\s.*\|$\)', '\1', '')
+ if eclim#util#ListContains(s:output_actions, action)
+ let result = eclim#util#System(command . ' ' . a:args)
+ if v:shell_error
+ if result =~ '^Error:'
+ let error = substitute(result, '^\(.\{-}\)\n.*', '\1', '')
+ else
+ let error = 'Error: ' .
+ \ substitute(result, '.*\n\s*\(' . action . '\s.\{-}\)\n.*', '\1', '')
+ endif
+ call eclim#util#EchoError(error)
+ else
+ let engine = eclim#python#django#util#GetSqlEngine(path)
+ let dialect = has_key(s:sql_dialects, engine) ? s:sql_dialects[engine] : 'plsql'
+
+ let filename = expand('%')
+ let name = '__' . action . '__'
+ call eclim#util#TempWindow(name, split(result, '\n'))
+ if action =~ '^sql'
+ set filetype=sql
+ if exists('b:current_syntax') && dialect !~ b:current_syntax
+ exec 'SQLSetType ' . dialect
+ endif
+ elseif action == 'adminindex'
+ set filetype=html
+ elseif action =~ '\(diffsettings\|inspectdb\)'
+ endif
+ setlocal nomodified
+ " Store filename so that plugins can use it if necessary.
+ let b:filename = filename
+
+ augroup temp_window
+ autocmd! BufWinLeave <buffer>
+ call eclim#util#GoToBufferWindowRegister(filename)
+ augroup END
+ endif
+ else
+ exec '!' . command . ' ' . a:args
+ endif
+ finally
+ " change back to original directory if necessary.
+ exec 'cd ' . escape(cwd, ' ')
+ endtry
+endfunction " }}}
+
+" CommandCompleteManage(argLead, cmdLine, cursorPos) {{{
+function! eclim#python#django#manage#CommandCompleteManage(argLead, cmdLine, cursorPos)
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+
+ if cmdLine =~ '^' . args[0] . '\s*' . escape(argLead, '~.\') . '$'
+ let actions = copy(s:manage_actions)
+ if cmdLine !~ '\s$'
+ call filter(actions, 'v:val =~ "^' . argLead . '"')
+ endif
+ return actions
+ endif
+
+ " complete app names if action support one
+ let action = args[1]
+ if eclim#util#ListContains(s:app_actions, action)
+ let apps = eclim#python#django#util#GetProjectApps(
+ \ eclim#python#django#util#GetProjectPath())
+ if cmdLine !~ '\s$'
+ call filter(apps, 'v:val =~ "^' . argLead . '"')
+ endif
+ return apps
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/python/django/template.vim b/vim/eclim/autoload/eclim/python/django/template.vim
@@ -0,0 +1,107 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/django.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+let s:starttag = '{%\s*\(end\)\@!\(\w\+\)\s*\([^}]\+\)\?\s*%}'
+let s:endtag = '{%\s*end\w\+\s*%}'
+
+let s:body_tags = {}
+function! s:InitBodyTags()
+ for elements in g:HtmlDjangoBodyElements
+ let s:body_tags[elements[0]] = elements[-1]
+ endfor
+endfunction
+call s:InitBodyTags()
+" }}}
+
+" CompleteEndTag() {{{
+" Function to complete a django template end tag.
+" Ex. imap <silent> % <c-r>=eclim#python#django#template#CompleteEndTag()<cr>
+function eclim#python#django#template#CompleteEndTag()
+ let line = getline('.')
+ let match_start = '.*{%\s*\%' . col('.') . 'c'
+ if line =~ match_start . '\(\s\|\s*%}\|$\)'
+ let tag = s:GetStartTag(line('.'))
+ if tag != '' && tag != 'endif'
+ let ops = ''
+ " account for case where the closing %} already exists (delete it)
+ if line =~ match_start . '\s*%}'
+ let chars = substitute(line, match_start . '\(\s*%}\).*', '\1', '')
+ let ops = substitute(chars, '.', "\<del>", "g")
+ endif
+ return tag . ops . ' %}'
+ endif
+ endif
+ return 'e'
+endfunction " }}}
+
+" s:GetStartTag(line) {{{
+function s:GetStartTag(line)
+ let pairpos = searchpairpos(s:starttag, '', '{%', 'bnW')
+ if pairpos[0]
+ let line = getline(pairpos[0])
+ let pos = getpos('.')
+ call cursor(pairpos[0], pairpos[1])
+ try
+ let tags = s:ExtractTags(line)
+ " place the cursor at the end of the line
+ call cursor(line('.'), col('$'))
+ for tag in reverse(tags)
+ " find first tag searching backwards
+ call search('{%\s*' . tag[0] . '\s*\([^}]\+\)\?\s*%}', 'b', line('.'))
+
+ " see if the tag has a matching close tag
+ let pairpos = searchpairpos(
+ \ '{%\s*' . tag[0] . '\s*\([^}]\+\)\?\s*%}', '',
+ \ '{%\s*' . tag[1], 'nW')
+ "\ '{%\s*' . tag[1] . '\s*%}', 'nW')
+ if !pairpos[0] || pairpos[0] > a:line
+ return tag[1]
+ endif
+ endfor
+ call cursor(line('.'), 1)
+ return s:GetStartTag(a:line)
+ finally
+ call setpos('.', pos)
+ endtry
+ endif
+ return ''
+endfunction " }}}
+
+" s:ExtractTags() {{{
+" Extracts a list of open tag names from the current line.
+function s:ExtractTags(line)
+ let line = a:line
+ let tags = []
+ while line =~ s:starttag
+ let tag = substitute(line, '.\{-}' . s:starttag . '.*', '\2', '')
+ if line !~ '{%\s*end' . tag . '\s*%}' && has_key(s:body_tags, tag)
+ call add(tags, [tag, s:body_tags[tag]])
+ endif
+ let line = substitute(line, '.\{-}{%\s*' . tag . '\>.\{-}%}', '\1', '')
+ endwhile
+ return tags
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/python/django/util.vim b/vim/eclim/autoload/eclim/python/django/util.vim
@@ -0,0 +1,125 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/django.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2010 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" GetLoadList(project_dir) {{{
+" Returns a list of tag/filter files loaded by the current template.
+function eclim#python#django#util#GetLoadList(project_dir)
+ let pos = getpos('.')
+
+ call cursor(1, 1)
+ let loaded = []
+ while search('{%\s*load\s', 'cW')
+ let elements = split(
+ \ substitute(getline('.'), '.*{%\s*load\s\+\(.\{-}\)\s*%}.*', '\1', ''))
+ let loaded += elements
+ call cursor(line('.') + 1, 1)
+ endwhile
+ call setpos('.', pos)
+
+ let file_names = []
+ for load in loaded
+ let file = findfile(load . '.py', a:project_dir . '*/templatetags/')
+ if file != ''
+ call add(file_names, file)
+ endif
+ endfor
+
+ return file_names
+endfunction " }}}
+
+" GetProjectPath([path]) {{{
+function eclim#python#django#util#GetProjectPath(...)
+ let path = len(a:000) > 0 ? a:000[0] : escape(expand('%:p:h'), ' ')
+ let dir = findfile("manage.py", path . ';')
+ if dir != ''
+ let dir = substitute(fnamemodify(dir, ':p:h'), '\', '/', 'g')
+ " secondary check on the dir, if settings.py exists, then probably the
+ " right dir, otherwise, search again from the parent.
+ if !filereadable(dir . '/settings.py')
+ return eclim#python#django#util#GetProjectPath(path . '/..')
+ endif
+ endif
+ return dir
+endfunction " }}}
+
+" GetProjectApps(project_dir) {{{
+" Gets a list of applications for the supplied project directory.
+function eclim#python#django#util#GetProjectApps(project_dir)
+ if a:project_dir != ''
+ let apps = split(globpath(a:project_dir, '*/views.py'), '\n')
+ call map(apps, "fnamemodify(v:val, ':p:h:t')")
+ return apps
+ endif
+ return []
+endfunction " }}}
+
+" GetSetting(project_dir, name) {{{
+function eclim#python#django#util#GetSetting(project_dir, name)
+ let cwd = getcwd()
+ try
+ exec (haslocaldir() ? 'lcd ' : 'cd ') . a:project_dir
+ let setting = eclim#util#System(
+ \ "python -c \"import settings; print(settings." . a:name . ")\"")
+ if v:shell_error
+ " try going up a dir and using that as a top level namespace
+ let ns = fnamemodify(a:project_dir, ':t')
+ exec (haslocaldir() ? 'lcd ' : 'cd ') . fnamemodify(a:project_dir, ':h')
+ let setting = eclim#util#System(
+ \ "python -c \"from " . ns . " import settings; print(settings." . a:name . ")\"")
+ if v:shell_error
+ return ''
+ endif
+ endif
+
+ let setting = substitute(setting, "\n$", '', '')
+ finally
+ exec (haslocaldir() ? 'lcd ' : 'cd') . cwd
+ endtry
+
+ return setting
+endfunction " }}}
+
+" GetSqlEngine(project_dir) {{{
+" Gets the configured sql engine for the project at the supplied project directory.
+function eclim#python#django#util#GetSqlEngine(project_dir)
+ let engine = 'postgresql'
+ let setting = eclim#python#django#util#GetSetting(a:project_dir, 'DATABASE_ENGINE')
+ let setting = substitute(setting, "^['\"]\\(.\\{-}\\)['\"]$", '\1', '')
+ if setting !~ '^\s*$'
+ let engine = setting
+ endif
+ return engine
+endfunction " }}}
+
+" GetTemplateDirs(project_dir) {{{
+" Gets the configured list of template directories relative to the project
+" dir.
+function eclim#python#django#util#GetTemplateDirs(project_dir)
+ let setting = eclim#python#django#util#GetSetting(a:project_dir, 'TEMPLATE_DIRS')
+ let setting = substitute(setting, '^[\[(]\(.\{-}\)[\])]$', '\1', '')
+ let dirs = split(setting, ',\s*')
+ return map(dirs, "substitute(v:val, \"^['\\\"]\\\\(.\\\\{-}\\\\)['\\\"]$\", '\\1', '')")
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/python/import.vim b/vim/eclim/autoload/eclim/python/import.vim
@@ -0,0 +1,194 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+if exists('g:EclimPythonSignificantPackages')
+ let s:significant_packages = g:EclimPythonSignificantPackages
+else
+ let s:significant_packages = []
+endif
+" }}}
+
+" SortImports() {{{
+function! eclim#python#import#SortImports()
+ let pos = getpos('.')
+
+ let import_data = eclim#python#import#GetImports()
+ let imports = import_data.imports
+ call sort(imports, 'eclim#python#import#CompareImports')
+
+ " remove unsorted imports from the file
+ silent exec import_data.start . ',' . import_data.end . 'delete _'
+
+ let pre_packages = copy(s:significant_packages)
+ let post_packages = copy(s:significant_packages)
+
+ " re-insert sorted imports in the file
+ let results = ''
+ let lastimport = ''
+ for import in imports
+ if results != ''
+ let results .= "\n"
+ endif
+
+ " blank line to seperate significant imports
+ let index = 0
+ for package in pre_packages
+ if import =~ '^\(from\|import\)\s*' . package . '\>'
+ if results != ''
+ let results .= "\n"
+ endif
+ call remove(pre_packages, index)
+ break
+ endif
+ let index += 1
+ endfor
+
+ " post significant package seperation
+ let index = 0
+ for package in post_packages
+ if lastimport =~ '^\(from\|import\)\s*' . package . '\>' &&
+ \ import !~ '^\(from\|import\)\s*' . package . '\>'
+ if results !~ "\n\n$"
+ let results .= "\n"
+ endif
+ call remove(post_packages, index)
+ break
+ endif
+ let index += 1
+ endfor
+
+ if lastimport =~ '^import' && import =~ '^from'
+ let results .= "\n"
+ endif
+
+ let results .= import
+ let lastimport = import
+ endfor
+ call cursor(import_data.start - 1, 1)
+ if import_data.start == 1
+ silent put! =results
+ else
+ silent put =results
+ endif
+
+ call setpos('.', pos)
+endfunction " }}}
+
+" CompareImports() {{{
+function! eclim#python#import#CompareImports(i1, i2)
+ if (a:i1 =~ '^from' && a:i2 =~ '^from') ||
+ \ (a:i1 =~ '^import' && a:i2 =~ '^import')
+ return a:i1 == a:i2 ? 0 : a:i1 > a:i2 ? 1 : -1
+ endif
+
+ if a:i1 =~ '^import'
+ return -1
+ endif
+
+ if a:i1 =~ '^from'
+ return 1
+ endif
+
+ return 0
+endfunction " }}}
+
+" CleanImports() {{{
+function! eclim#python#import#CleanImports()
+ let pos = getpos('.')
+
+ let import_data = eclim#python#import#GetImports()
+ let names = []
+ for import in import_data.imports
+ let importing = import
+ let importing = substitute(importing,
+ \ '.*\<import\>\s\+\(.\{-}\<as\>\s\+\)\?\(.\{-}\)\s*$', '\2', '')
+ let importing = substitute(importing, '\(\s\+\|\\\|\n\)', '', 'g')
+ let names += split(importing, ',')
+ endfor
+
+ let remove = []
+ call cursor(import_data.end, len(getline(import_data.end)))
+ for name in names
+ if !search('\<' . name . '\>', 'cnW')
+ call add(remove, name)
+ endif
+ endfor
+
+ for name in remove
+ call cursor(1, 1)
+ call search('\<' . name . '\>', 'W', import_data.end)
+ let import = getline('.')
+ if import =~ '\<import\>\s\+' . name . '\>\s*$' ||
+ \ import =~ '\<import\>\s\+.*as\s\+' . name . '\>\s*$'
+ exec line('.') . ',' . line('.') . 'delete _'
+ " if deleting of import results in 2 blank lines, delete one of them
+ if getline('.') =~ '^\s*$' && getline(line('.') - 1) =~ '^\s*$'
+ exec line('.') . ',' . line('.') . 'delete _'
+ endif
+ else
+ if import =~ ',\s*\<' . name . '\>'
+ let newimport = substitute(import, ',\s*\<' . name . '\>', '', '')
+ else
+ let newimport = substitute(import, '\<' . name . '\>\s*,\s\?', '', '')
+ endif
+ call setline(line('.'), newimport)
+ endif
+ endfor
+
+ call setpos('.', pos)
+endfunction " }}}
+
+" GetImports() {{{
+" Returns a dictionary containing:
+" - start: the line where the imports start (0 if none).
+" - end: the line where the imports end (0 if none).
+" - imports: list containing the import lines.
+function! eclim#python#import#GetImports()
+ let pos = getpos('.')
+
+ call cursor(1, 1)
+
+ let imports = []
+ let start = 0
+ let end = 0
+ while search('^\(import\|from\)\>\s\+', 'cW') && end != line('$')
+ let import = getline('.')
+ while import =~ '\\\s*$'
+ call cursor(line('.') + 1, 1)
+ let import = import . "\n" . getline('.')
+ endwhile
+ if len(imports) == 0
+ let start = line('.')
+ endif
+ let end = line('.')
+ call add(imports, import)
+ call cursor(line('.') + 1, 1)
+ endwhile
+
+ call setpos('.', pos)
+
+ return {'start': start, 'end': end, 'imports': imports}
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/python/jinja.vim b/vim/eclim/autoload/eclim/python/jinja.vim
@@ -0,0 +1,100 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/jinja.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+let s:starttag = '{%-\?\s*\(end\)\@!\(\w\+\)\s*\([^}]\+\)\?\s*-\?%}'
+let s:endtag = '{%-\?\s*end\w\+\s*-\?%}'
+
+let s:body_tags = {}
+function! s:InitBodyTags()
+ for elements in g:HtmlJinjaBodyElements
+ let s:body_tags[elements[0]] = elements[-1]
+ endfor
+endfunction
+call s:InitBodyTags()
+" }}}
+
+" CompleteEndTag() {{{
+" Function to complete a jinja template end tag.
+" Ex. imap <silent> % <c-r>=eclim#python#jinja#CompleteEndTag()<cr>
+function eclim#python#jinja#CompleteEndTag()
+ let line = getline('.')
+ if line =~ '.*{%-\?\s*\%' . col('.') . 'c\(\s\|$\)'
+ let tag = s:GetStartTag(line('.'))
+ if tag != '' && tag != 'endif'
+ return tag . ' %}'
+ endif
+ endif
+ return 'e'
+endfunction " }}}
+
+" s:GetStartTag(line) {{{
+function s:GetStartTag(line)
+ let pairpos = searchpairpos(s:starttag, '', '{%', 'bnW')
+ if pairpos[0]
+ let line = getline(pairpos[0])
+ let pos = getpos('.')
+ call cursor(pairpos[0], pairpos[1])
+ try
+ let tags = s:ExtractTags(line)
+ " place the cursor at the end of the line
+ call cursor(line('.'), col('$'))
+ for tag in reverse(tags)
+ " find first tag searching backwards
+ call search('{%-\?\s*' . tag[0] . '\s*\([^}]\+\)\?\s*-\?%}', 'b', line('.'))
+
+ " see if the tag has a matching close tag
+ let pairpos = searchpairpos(
+ \ '{%-\?\s*' . tag[0] . '\s*\([^}]\+\)\?\s*-\?%}', '',
+ \ '{%-\?\s*' . tag[1], 'nW')
+ "\ '{%-\?\s*' . tag[1] . '\s*-\?%}', 'nW')
+ if !pairpos[0] || pairpos[0] > a:line
+ return tag[1]
+ endif
+ endfor
+ call cursor(line('.'), 1)
+ return s:GetStartTag(a:line)
+ finally
+ call setpos('.', pos)
+ endtry
+ endif
+ return ''
+endfunction " }}}
+
+" s:ExtractTags() {{{
+" Extracts a list of open tag names from the current line.
+function s:ExtractTags(line)
+ let line = a:line
+ let tags = []
+ while line =~ s:starttag
+ let tag = substitute(line, '.\{-}' . s:starttag . '.*', '\2', '')
+ if line !~ '{%-\?\s*end' . tag . '\s*-\?%}' && has_key(s:body_tags, tag)
+ call add(tags, [tag, s:body_tags[tag]])
+ endif
+ let line = substitute(line, '.\{-}{%-\?\s*' . tag . '\>.\{-}-\?%}', '\1', '')
+ endwhile
+ return tags
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/python/rope.vim b/vim/eclim/autoload/eclim/python/rope.vim
@@ -0,0 +1,376 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/rope.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists("g:RopePath")
+ " The base directory where the rope code is located.
+ let g:RopePath = substitute(expand('<sfile>:p:h'), '\', '/', 'g')
+endif
+" }}}
+
+function! eclim#python#rope#Init(project) " {{{
+ if !has('python')
+ call eclim#util#EchoError(
+ \ "This functionality requires 'python' support compiled into vim.")
+ return 0
+ endif
+
+ let ropepath = g:RopePath
+ if ropepath == ''
+ return 0
+ endif
+
+python << EOF
+from __future__ import with_statement
+import os, sys, vim
+try:
+ from cStringIO import StringIO
+except:
+ from StringIO import StringIO
+
+ropepath = vim.eval('ropepath')
+if ropepath not in sys.path:
+ sys.path.insert(0, ropepath)
+
+from contextlib import contextmanager
+from rope.base import builtins, pyobjects, pynames
+
+@contextmanager
+def projectroot():
+ cwd = os.getcwd()
+ try:
+ # change working directory to the project root to prevent any modules in the
+ # same dir as the file we are working on from colliding with core python
+ # modules.
+ os.chdir(vim.eval('a:project'))
+ yield
+ finally:
+ os.chdir(cwd)
+
+def byteOffsetToCharOffset(filename, offset, encoding):
+ with(projectroot()):
+ f = file(filename)
+ ba = f.read(offset)
+ u = unicode(ba, encoding or 'utf8')
+ u = u.replace('\r\n', '\n') # rope ignore \r, so don't count them.
+ return len(u)
+
+def kind(proposal):
+ pyname = proposal.pyname
+ if hasattr(pyname, 'get_object'):
+ pyobject = pyname.get_object()
+ if isinstance(pyobject, pyobjects.AbstractClass):
+ return 'c'
+
+ if isinstance(pyobject, pyobjects.AbstractFunction):
+ return 'f'
+
+ return proposal.scope[0]
+
+def parameters(proposal):
+ pyname = proposal.pyname
+ if isinstance(pyname, pynames.ImportedName):
+ pyname = pyname._get_imported_pyname()
+ if hasattr(pyname, 'get_object'):
+ pyobject = pyname.get_object()
+ if isinstance(pyobject, builtins.BuiltinFunction):
+ params = pyobject.get_param_names()
+ if params and params[0] == 'self':
+ params = params[1:]
+ return ', '.join(params)
+
+ if isinstance(pyobject, pyobjects.AbstractFunction):
+ args = [(a.id, a.col_offset) for a in pyobject.arguments.args]
+ defaults = []
+ for d in pyobject.arguments.defaults:
+ value = _defaultValue(d)
+ defaults.append((value, d.col_offset))
+
+ params = StringIO()
+ for ii, arg in enumerate(args):
+ if arg[0] == 'self':
+ continue
+
+ if len(params.getvalue()) > 0:
+ params.write(', ')
+ if defaults:
+ if defaults[0][1] > arg[1]:
+ if (ii == len(args) - 1) or (args[ii + 1][1] > defaults[0][1]):
+ arg = (arg[0], arg[1], defaults[0][0])
+ defaults.pop(0)
+ if len(arg) > 2:
+ params.write('%s=%s' % (arg[0], arg[2]))
+ else:
+ params.write(arg[0])
+
+ if pyobject.arguments.vararg:
+ if len(params.getvalue()) > 0:
+ params.write(', ')
+ params.write('*args')
+
+ if pyobject.arguments.kwarg:
+ if len(params.getvalue()) > 0:
+ params.write(', ')
+ params.write('**kwargs')
+
+ return params.getvalue()
+ return ''
+
+def _defaultValue(default, nested=False):
+ value = None
+ for attr in ('id', 'n', 's', 'elts', 'keys'):
+ if hasattr(default, attr):
+ value = getattr(default, attr)
+ if attr == 's' and not nested:
+ value = repr(value)
+ elif attr == 'elts':
+ value = repr(tuple([_defaultValue(v, nested=True) for v in value]))
+ elif attr == 'keys':
+ value = repr(dict([
+ (_defaultValue(k, nested=True), _defaultValue(v, nested=True))
+ for k, v in zip(value, getattr(default, 'values'))
+ ]))
+ break
+ return value
+EOF
+
+ return 1
+endfunction " }}}
+
+function! eclim#python#rope#Completions(project, filename, offset, encoding) " {{{
+ " Attempts to suggest code completions for a given project path, project
+ " relative file path and offset.
+ if !eclim#python#rope#Init(a:project)
+ return []
+ endif
+
+ let results = []
+ let completion_error = ''
+
+python << EOF
+from __future__ import with_statement
+with(projectroot()):
+ from rope.base import project
+ from rope.base.exceptions import ModuleSyntaxError, RopeError
+ from rope.contrib import codeassist
+ project = project.Project(vim.eval('a:project'))
+
+ filename = vim.eval('a:filename')
+ offset = int(vim.eval('a:offset'))
+ encoding = vim.eval('a:encoding')
+
+ resource = project.get_resource(filename)
+ code = resource.read()
+
+ offset = byteOffsetToCharOffset(filename, offset, encoding)
+
+ # code completion
+ try:
+ proposals = codeassist.code_assist(
+ project, code, offset, resource=resource, maxfixes=3)
+ proposals = codeassist.sorted_proposals(proposals)
+ for ii, p in enumerate(proposals):
+ proposals[ii] = [p.name, kind(p), parameters(p)]
+ vim.command("let results = %r" % proposals)
+
+ if resource.name.startswith('__eclim_temp_'):
+ #resource.remove()
+ os.unlink(resource.real_path)
+ except IndentationError, e:
+ vim.command(
+ "let completion_error = 'Completion failed due to indentation error.'"
+ )
+ except ModuleSyntaxError, e:
+ message = 'Completion failed due to syntax error: %s' % e.args[0]
+ vim.command("let completion_error = %r" % message)
+ except RopeError, e:
+ message = 'Completion failed due to rope error: %s' % type(e)
+ vim.command("let completion_error = %r" % message)
+EOF
+
+ if completion_error != ''
+ call eclim#util#EchoError(completion_error)
+ endif
+
+ return results
+endfunction " }}}
+
+function! eclim#python#rope#Find(project, filename, offset, encoding, context) " {{{
+ if !eclim#python#rope#Init(a:project)
+ return []
+ endif
+
+ let results = []
+ let search_error = ''
+
+python << EOF
+from __future__ import with_statement
+with(projectroot()):
+ from rope.base import project
+ from rope.base.exceptions import ModuleSyntaxError, RopeError
+ from rope.contrib import codeassist
+ from rope.contrib import findit
+ project = project.Project(vim.eval('a:project'))
+
+ filename = vim.eval('a:filename')
+ offset = int(vim.eval('a:offset'))
+ encoding = vim.eval('a:encoding')
+ context = vim.eval('a:context')
+
+ resource = project.get_resource(filename)
+
+ offset = byteOffsetToCharOffset(filename, offset, encoding)
+
+ try:
+ if context == 'implementations':
+ locations = findit.find_implementations(project, resource, offset)
+ elif context == 'occurrences':
+ locations = findit.find_occurrences(project, resource, offset)
+ else:
+ code = resource.read()
+ location = codeassist.get_definition_location(
+ project, code, offset, maxfixes=3)
+ # using codeassist instead since it seems able to find some things that
+ # findit cannot.
+ #location = findit.find_definition(
+ # project, code, offset, resource=resource, maxfixes=3)
+ locations = location and [location]
+
+ results = []
+ if locations:
+ for location in locations:
+ if hasattr(location, 'resource'): # findit result
+ path = location.resource.real_path.replace('\\', '/')
+ lineno = location.lineno
+ else: # codeassist result
+ if location[1] is None:
+ continue
+
+ path = location[0] and \
+ location[0].real_path or \
+ '%s/%s' % (vim.eval('a:project'), vim.eval('a:filename'))
+ path = path.replace('\\', '/')
+ lineno = location[1]
+
+ # TODO: use location.offset
+ results.append(str('%s|%s col 1|' % (path, lineno)))
+
+ vim.command("let results = %r" % results)
+ except IndentationError, e:
+ vim.command(
+ "let search_error = 'Search failed due to indentation error.'"
+ )
+ except ModuleSyntaxError, e:
+ message = 'Search failed due to syntax error: %s' % e.args[0]
+ vim.command("let search_error = %r" % message)
+ except RopeError, e:
+ message = 'Search failed due to rope error: %s' % type(e)
+ vim.command("let search_error = %r" % message)
+EOF
+
+ if search_error != ''
+ call eclim#util#EchoError(search_error)
+ return
+ endif
+
+ return results
+endfunction " }}}
+
+function! eclim#python#rope#GetOffset() " {{{
+ " Gets the character offset for the current cursor position.
+ " NOTE: rope doesn't recognize dos line endings as 2 characters, so just
+ " handle as a single character. It uses true character offsets, vs eclipse
+ " which uses bytes.
+ let pos = getpos('.')
+
+ " count back from the current position to the beginning of the file.
+ let offset = col('.') - 1
+ while line('.') != 1
+ call cursor(line('.') - 1, 1)
+ let offset = offset + col('$')
+ endwhile
+
+ " restore the cursor position.
+ call setpos('.', pos)
+
+ return offset
+endfunction " }}}
+
+function! eclim#python#rope#GetSourceDirs(project) " {{{
+ " Attempts to determine the source directories for the supplied project.
+ if !eclim#python#rope#Init(a:project)
+ return []
+ endif
+
+ let dirs = []
+
+python << EOF
+from __future__ import with_statement
+with(projectroot()):
+ from rope.base import project
+ from rope.base.exceptions import ResourceNotFoundError
+ prj = project.Project(vim.eval('a:project'))
+ dirs = [d.real_path for d in prj.pycore.get_source_folders()]
+ for src in prj.prefs.get('python_path', []):
+ try:
+ src_folder = project.get_no_project().get_resource(src)
+ dirs.append(src_folder.real_path)
+ except ResourceNotFoundError:
+ pass
+ vim.command("let dirs = %r" % dirs)
+EOF
+
+ return dirs
+
+endfunction " }}}
+
+function! eclim#python#rope#Validate(project, filename) " {{{
+ " Attempts to validate the supplied file.
+ if !eclim#python#rope#Init(a:project)
+ return []
+ endif
+
+ let results = []
+
+python << EOF
+from __future__ import with_statement
+with(projectroot()):
+ from rope.base import project
+ from rope.contrib import finderrors
+ project = project.Project(vim.eval('a:project'))
+
+ resource = project.get_resource(vim.eval('a:filename'))
+ filepath = '%s/%s' % (vim.eval('a:project'), vim.eval('a:filename'))
+
+ # code completion
+ errors = finderrors.find_errors(project, resource)
+ errors = ['%s:%s:%s' % (filepath, e.lineno, e.error) for e in errors]
+ vim.command("let results = %r" % errors)
+EOF
+
+ return results
+
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/python/rope/__init__.py b/vim/eclim/autoload/eclim/python/rope/__init__.py
@@ -0,0 +1,17 @@
+"""rope, a python refactoring library"""
+
+INFO = __doc__
+VERSION = '0.9.3'
+COPYRIGHT = """\
+Copyright (C) 2006-2010 Ali Gholami Rudi
+Copyright (C) 2009-2010 Anton Gritsay
+
+This program is free software; you can redistribute it and/or modify it
+under the terms of GNU General Public License as published by the
+Free Software Foundation; either version 2 of the license, or (at your
+opinion) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details."""
diff --git a/vim/eclim/autoload/eclim/python/rope/base/__init__.py b/vim/eclim/autoload/eclim/python/rope/base/__init__.py
@@ -0,0 +1,8 @@
+"""Base rope package
+
+This package contains rope core modules that are used by other modules
+and packages.
+
+"""
+
+__all__ = ['project', 'libutils', 'exceptions']
diff --git a/vim/eclim/autoload/eclim/python/rope/base/arguments.py b/vim/eclim/autoload/eclim/python/rope/base/arguments.py
@@ -0,0 +1,109 @@
+import rope.base.evaluate
+from rope.base import ast
+
+
+class Arguments(object):
+ """A class for evaluating parameters passed to a function
+
+ You can use the `create_arguments` factory. It handles implicit
+ first arguments.
+
+ """
+
+ def __init__(self, args, scope):
+ self.args = args
+ self.scope = scope
+ self.instance = None
+
+ def get_arguments(self, parameters):
+ result = []
+ for pyname in self.get_pynames(parameters):
+ if pyname is None:
+ result.append(None)
+ else:
+ result.append(pyname.get_object())
+ return result
+
+ def get_pynames(self, parameters):
+ result = [None] * max(len(parameters), len(self.args))
+ for index, arg in enumerate(self.args):
+ if isinstance(arg, ast.keyword) and arg.arg in parameters:
+ result[parameters.index(arg.arg)] = self._evaluate(arg.value)
+ else:
+ result[index] = self._evaluate(arg)
+ return result
+
+ def get_instance_pyname(self):
+ if self.args:
+ return self._evaluate(self.args[0])
+
+ def _evaluate(self, ast_node):
+ return rope.base.evaluate.eval_node(self.scope, ast_node)
+
+
+def create_arguments(primary, pyfunction, call_node, scope):
+ """A factory for creating `Arguments`"""
+ args = list(call_node.args)
+ args.extend(call_node.keywords)
+ called = call_node.func
+ # XXX: Handle constructors
+ if _is_method_call(primary, pyfunction) and \
+ isinstance(called, ast.Attribute):
+ args.insert(0, called.value)
+ return Arguments(args, scope)
+
+
+class ObjectArguments(object):
+
+ def __init__(self, pynames):
+ self.pynames = pynames
+
+ def get_arguments(self, parameters):
+ result = []
+ for pyname in self.pynames:
+ if pyname is None:
+ result.append(None)
+ else:
+ result.append(pyname.get_object())
+ return result
+
+ def get_pynames(self, parameters):
+ return self.pynames
+
+ def get_instance_pyname(self):
+ return self.pynames[0]
+class MixedArguments(object):
+
+ def __init__(self, pyname, arguments, scope):
+ """`argumens` is an instance of `Arguments`"""
+ self.pyname = pyname
+ self.args = arguments
+
+ def get_pynames(self, parameters):
+ return [self.pyname] + self.args.get_pynames(parameters[1:])
+
+ def get_arguments(self, parameters):
+ result = []
+ for pyname in self.get_pynames(parameters):
+ if pyname is None:
+ result.append(None)
+ else:
+ result.append(pyname.get_object())
+ return result
+
+ def get_instance_pyname(self):
+ return self.pyname
+
+
+def _is_method_call(primary, pyfunction):
+ if primary is None:
+ return False
+ pyobject = primary.get_object()
+ if isinstance(pyobject.get_type(), rope.base.pyobjects.PyClass) and \
+ isinstance(pyfunction, rope.base.pyobjects.PyFunction) and \
+ isinstance(pyfunction.parent, rope.base.pyobjects.PyClass):
+ return True
+ if isinstance(pyobject.get_type(), rope.base.pyobjects.AbstractClass) and \
+ isinstance(pyfunction, rope.base.builtins.BuiltinFunction):
+ return True
+ return False
diff --git a/vim/eclim/autoload/eclim/python/rope/base/ast.py b/vim/eclim/autoload/eclim/python/rope/base/ast.py
@@ -0,0 +1,67 @@
+import _ast
+from _ast import *
+
+from rope.base import fscommands
+
+
+def parse(source, filename='<string>'):
+ # NOTE: the raw string should be given to `compile` function
+ if isinstance(source, unicode):
+ source = fscommands.unicode_to_file_data(source)
+ if '\r' in source:
+ source = source.replace('\r\n', '\n').replace('\r', '\n')
+ if not source.endswith('\n'):
+ source += '\n'
+ try:
+ return compile(source, filename, 'exec', _ast.PyCF_ONLY_AST)
+ except (TypeError, ValueError), e:
+ error = SyntaxError()
+ error.lineno = 1
+ error.filename = filename
+ error.msg = str(e)
+ raise error
+
+
+def walk(node, walker):
+ """Walk the syntax tree"""
+ method_name = '_' + node.__class__.__name__
+ method = getattr(walker, method_name, None)
+ if method is not None:
+ return method(node)
+ for child in get_child_nodes(node):
+ walk(child, walker)
+
+
+def get_child_nodes(node):
+ if isinstance(node, _ast.Module):
+ return node.body
+ result = []
+ if node._fields is not None:
+ for name in node._fields:
+ child = getattr(node, name)
+ if isinstance(child, list):
+ for entry in child:
+ if isinstance(entry, _ast.AST):
+ result.append(entry)
+ if isinstance(child, _ast.AST):
+ result.append(child)
+ return result
+
+
+def call_for_nodes(node, callback, recursive=False):
+ """If callback returns `True` the child nodes are skipped"""
+ result = callback(node)
+ if recursive and not result:
+ for child in get_child_nodes(node):
+ call_for_nodes(child, callback, recursive)
+
+
+def get_children(node):
+ result = []
+ if node._fields is not None:
+ for name in node._fields:
+ if name in ['lineno', 'col_offset']:
+ continue
+ child = getattr(node, name)
+ result.append(child)
+ return result
diff --git a/vim/eclim/autoload/eclim/python/rope/base/astutils.py b/vim/eclim/autoload/eclim/python/rope/base/astutils.py
@@ -0,0 +1,61 @@
+from rope.base import ast
+
+
+def get_name_levels(node):
+ """Return a list of ``(name, level)`` tuples for assigned names
+
+ The `level` is `None` for simple assignments and is a list of
+ numbers for tuple assignments for example in::
+
+ a, (b, c) = x
+
+ The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for
+ `c` is ``[1, 1]``.
+
+ """
+ visitor = _NodeNameCollector()
+ ast.walk(node, visitor)
+ return visitor.names
+
+
+class _NodeNameCollector(object):
+
+ def __init__(self, levels=None):
+ self.names = []
+ self.levels = levels
+ self.index = 0
+
+ def _add_node(self, node):
+ new_levels = []
+ if self.levels is not None:
+ new_levels = list(self.levels)
+ new_levels.append(self.index)
+ self.index += 1
+ self._added(node, new_levels)
+
+ def _added(self, node, levels):
+ if hasattr(node, 'id'):
+ self.names.append((node.id, levels))
+
+ def _Name(self, node):
+ self._add_node(node)
+
+ def _Tuple(self, node):
+ new_levels = []
+ if self.levels is not None:
+ new_levels = list(self.levels)
+ new_levels.append(self.index)
+ self.index += 1
+ visitor = _NodeNameCollector(new_levels)
+ for child in ast.get_child_nodes(node):
+ ast.walk(child, visitor)
+ self.names.extend(visitor.names)
+
+ def _Subscript(self, node):
+ self._add_node(node)
+
+ def _Attribute(self, node):
+ self._add_node(node)
+
+ def _Slice(self, node):
+ self._add_node(node)
diff --git a/vim/eclim/autoload/eclim/python/rope/base/builtins.py b/vim/eclim/autoload/eclim/python/rope/base/builtins.py
@@ -0,0 +1,728 @@
+"""This module trys to support builtin types and functions."""
+import inspect
+
+import rope.base.evaluate
+from rope.base import pynames, pyobjects, arguments, utils
+
+
+class BuiltinModule(pyobjects.AbstractModule):
+
+ def __init__(self, name, pycore=None, initial={}):
+ super(BuiltinModule, self).__init__()
+ self.name = name
+ self.pycore = pycore
+ self.initial = initial
+
+ parent = None
+
+ def get_attributes(self):
+ return self.attributes
+
+ def get_doc(self):
+ if self.module:
+ return self.module.__doc__
+
+ def get_name(self):
+ return self.name.split('.')[-1]
+
+ @property
+ @utils.saveit
+ def attributes(self):
+ result = _object_attributes(self.module, self)
+ result.update(self.initial)
+ if self.pycore is not None:
+ submodules = self.pycore._builtin_submodules(self.name)
+ for name, module in submodules.iteritems():
+ result[name] = rope.base.builtins.BuiltinName(module)
+ return result
+
+ @property
+ @utils.saveit
+ def module(self):
+ try:
+ result = __import__(self.name)
+ for token in self.name.split('.')[1:]:
+ result = getattr(result, token, None)
+ return result
+ except ImportError:
+ return
+
+
+class _BuiltinElement(object):
+
+ def __init__(self, builtin, parent=None):
+ self.builtin = builtin
+ self._parent = parent
+
+ def get_doc(self):
+ if self.builtin:
+ return getattr(self.builtin, '__doc__', None)
+
+ def get_name(self):
+ if self.builtin:
+ return getattr(self.builtin, '__name__', None)
+
+ @property
+ def parent(self):
+ if self._parent is None:
+ return builtins
+ return self._parent
+
+
+class BuiltinClass(_BuiltinElement, pyobjects.AbstractClass):
+
+ def __init__(self, builtin, attributes, parent=None):
+ _BuiltinElement.__init__(self, builtin, parent)
+ pyobjects.AbstractClass.__init__(self)
+ self.initial = attributes
+
+ @utils.saveit
+ def get_attributes(self):
+ result = _object_attributes(self.builtin, self)
+ result.update(self.initial)
+ return result
+
+
+class BuiltinFunction(_BuiltinElement, pyobjects.AbstractFunction):
+
+ def __init__(self, returned=None, function=None, builtin=None,
+ argnames=[], parent=None):
+ _BuiltinElement.__init__(self, builtin, parent)
+ pyobjects.AbstractFunction.__init__(self)
+ self.argnames = argnames
+ self.returned = returned
+ self.function = function
+
+ def get_returned_object(self, args):
+ if self.function is not None:
+ return self.function(_CallContext(self.argnames, args))
+ else:
+ return self.returned
+
+ def get_param_names(self, special_args=True):
+ return self.argnames
+
+
+class BuiltinUnknown(_BuiltinElement, pyobjects.PyObject):
+
+ def __init__(self, builtin):
+ super(BuiltinUnknown, self).__init__(pyobjects.get_unknown())
+ self.builtin = builtin
+ self.type = pyobjects.get_unknown()
+
+ @utils.saveit
+ def get_attributes(self):
+ return _object_attributes(self.builtin, self)
+
+
+def _object_attributes(obj, parent):
+ attributes = {}
+ for name in dir(obj):
+ if name == 'None':
+ continue
+ child = getattr(obj, name)
+ pyobject = None
+ if inspect.isclass(child):
+ pyobject = BuiltinClass(child, {}, parent=parent)
+ elif inspect.isroutine(child):
+ pyobject = BuiltinFunction(builtin=child, parent=parent)
+ else:
+ pyobject = BuiltinUnknown(builtin=child)
+ attributes[name] = BuiltinName(pyobject)
+ return attributes
+
+
+def _create_builtin_type_getter(cls):
+ def _get_builtin(*args):
+ if not hasattr(cls, '_generated'):
+ cls._generated = {}
+ if args not in cls._generated:
+ cls._generated[args] = cls(*args)
+ return cls._generated[args]
+ return _get_builtin
+
+def _create_builtin_getter(cls):
+ type_getter = _create_builtin_type_getter(cls)
+ def _get_builtin(*args):
+ return pyobjects.PyObject(type_getter(*args))
+ return _get_builtin
+
+
+class _CallContext(object):
+
+ def __init__(self, argnames, args):
+ self.argnames = argnames
+ self.args = args
+
+ def _get_scope_and_pyname(self, pyname):
+ if pyname is not None and isinstance(pyname, pynames.AssignedName):
+ pymodule, lineno = pyname.get_definition_location()
+ if pymodule is None:
+ return None, None
+ if lineno is None:
+ lineno = 1
+ scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
+ name = None
+ while name is None and scope is not None:
+ for current in scope.get_names():
+ if scope[current] is pyname:
+ name = current
+ break
+ else:
+ scope = scope.parent
+ return scope, name
+ return None, None
+
+ def get_argument(self, name):
+ if self.args:
+ args = self.args.get_arguments(self.argnames)
+ return args[self.argnames.index(name)]
+
+ def get_pyname(self, name):
+ if self.args:
+ args = self.args.get_pynames(self.argnames)
+ if name in self.argnames:
+ return args[self.argnames.index(name)]
+
+ def get_arguments(self, argnames):
+ if self.args:
+ return self.args.get_arguments(argnames)
+
+ def get_pynames(self, argnames):
+ if self.args:
+ return self.args.get_pynames(argnames)
+
+ def get_per_name(self):
+ if self.args is None:
+ return None
+ pyname = self.args.get_instance_pyname()
+ scope, name = self._get_scope_and_pyname(pyname)
+ if name is not None:
+ pymodule = pyname.get_definition_location()[0]
+ return pymodule.pycore.object_info.get_per_name(scope, name)
+ return None
+
+ def save_per_name(self, value):
+ if self.args is None:
+ return None
+ pyname = self.args.get_instance_pyname()
+ scope, name = self._get_scope_and_pyname(pyname)
+ if name is not None:
+ pymodule = pyname.get_definition_location()[0]
+ pymodule.pycore.object_info.save_per_name(scope, name, value)
+
+
+class _AttributeCollector(object):
+
+ def __init__(self, type):
+ self.attributes = {}
+ self.type = type
+
+ def __call__(self, name, returned=None, function=None,
+ argnames=['self'], check_existence=True):
+ try:
+ builtin = getattr(self.type, name)
+ except AttributeError:
+ if check_existence:
+ raise
+ builtin=None
+ self.attributes[name] = BuiltinName(
+ BuiltinFunction(returned=returned, function=function,
+ argnames=argnames, builtin=builtin))
+
+ def __setitem__(self, name, value):
+ self.attributes[name] = value
+
+
+class List(BuiltinClass):
+
+ def __init__(self, holding=None):
+ self.holding = holding
+ collector = _AttributeCollector(list)
+
+ collector('__iter__', function=self._iterator_get)
+ collector('__new__', function=self._new_list)
+
+ # Adding methods
+ collector('append', function=self._list_add, argnames=['self', 'value'])
+ collector('__setitem__', function=self._list_add,
+ argnames=['self', 'index', 'value'])
+ collector('insert', function=self._list_add,
+ argnames=['self', 'index', 'value'])
+ collector('extend', function=self._self_set,
+ argnames=['self', 'iterable'])
+
+ # Getting methods
+ collector('__getitem__', function=self._list_get)
+ collector('pop', function=self._list_get)
+ collector('__getslice__', function=self._self_get)
+
+ super(List, self).__init__(list, collector.attributes)
+
+ def _new_list(self, args):
+ return _create_builtin(args, get_list)
+
+ def _list_add(self, context):
+ if self.holding is not None:
+ return
+ holding = context.get_argument('value')
+ if holding is not None and holding != pyobjects.get_unknown():
+ context.save_per_name(holding)
+
+ def _self_set(self, context):
+ if self.holding is not None:
+ return
+ iterable = context.get_pyname('iterable')
+ holding = _infer_sequence_for_pyname(iterable)
+ if holding is not None and holding != pyobjects.get_unknown():
+ context.save_per_name(holding)
+
+ def _list_get(self, context):
+ if self.holding is not None:
+ return self.holding
+ return context.get_per_name()
+
+ def _iterator_get(self, context):
+ return get_iterator(self._list_get(context))
+
+ def _self_get(self, context):
+ return get_list(self._list_get(context))
+
+
+get_list = _create_builtin_getter(List)
+get_list_type = _create_builtin_type_getter(List)
+
+
+class Dict(BuiltinClass):
+
+ def __init__(self, keys=None, values=None):
+ self.keys = keys
+ self.values = values
+ item = get_tuple(self.keys, self.values)
+ collector = _AttributeCollector(dict)
+ collector('__new__', function=self._new_dict)
+ collector('__setitem__', function=self._dict_add)
+ collector('popitem', function=self._item_get)
+ collector('pop', function=self._value_get)
+ collector('get', function=self._key_get)
+ collector('keys', function=self._key_list)
+ collector('values', function=self._value_list)
+ collector('items', function=self._item_list)
+ collector('copy', function=self._self_get)
+ collector('__getitem__', function=self._value_get)
+ collector('__iter__', function=self._key_iter)
+ collector('update', function=self._self_set)
+ super(Dict, self).__init__(dict, collector.attributes)
+
+ def _new_dict(self, args):
+ def do_create(holding=None):
+ if holding is None:
+ return get_dict()
+ type = holding.get_type()
+ if isinstance(type, Tuple) and len(type.get_holding_objects()) == 2:
+ return get_dict(*type.get_holding_objects())
+ return _create_builtin(args, do_create)
+
+ def _dict_add(self, context):
+ if self.keys is not None:
+ return
+ key, value = context.get_arguments(['self', 'key', 'value'])[1:]
+ if key is not None and key != pyobjects.get_unknown():
+ context.save_per_name(get_tuple(key, value))
+
+ def _item_get(self, context):
+ if self.keys is not None:
+ return get_tuple(self.keys, self.values)
+ item = context.get_per_name()
+ if item is None or not isinstance(item.get_type(), Tuple):
+ return get_tuple(self.keys, self.values)
+ return item
+
+ def _value_get(self, context):
+ item = self._item_get(context).get_type()
+ return item.get_holding_objects()[1]
+
+ def _key_get(self, context):
+ item = self._item_get(context).get_type()
+ return item.get_holding_objects()[0]
+
+ def _value_list(self, context):
+ return get_list(self._value_get(context))
+
+ def _key_list(self, context):
+ return get_list(self._key_get(context))
+
+ def _item_list(self, context):
+ return get_list(self._item_get(context))
+
+ def _value_iter(self, context):
+ return get_iterator(self._value_get(context))
+
+ def _key_iter(self, context):
+ return get_iterator(self._key_get(context))
+
+ def _item_iter(self, context):
+ return get_iterator(self._item_get(context))
+
+ def _self_get(self, context):
+ item = self._item_get(context).get_type()
+ key, value = item.get_holding_objects()[:2]
+ return get_dict(key, value)
+
+ def _self_set(self, context):
+ if self.keys is not None:
+ return
+ new_dict = context.get_pynames(['self', 'd'])[1]
+ if new_dict and isinstance(new_dict.get_object().get_type(), Dict):
+ args = arguments.ObjectArguments([new_dict])
+ items = new_dict.get_object()['popitem'].\
+ get_object().get_returned_object(args)
+ context.save_per_name(items)
+ else:
+ holding = _infer_sequence_for_pyname(new_dict)
+ if holding is not None and isinstance(holding.get_type(), Tuple):
+ context.save_per_name(holding)
+
+
+get_dict = _create_builtin_getter(Dict)
+get_dict_type = _create_builtin_type_getter(Dict)
+
+
+class Tuple(BuiltinClass):
+
+ def __init__(self, *objects):
+ self.objects = objects
+ first = None
+ if objects:
+ first = objects[0]
+ attributes = {
+ '__getitem__': BuiltinName(BuiltinFunction(first)),
+ '__getslice__': BuiltinName(BuiltinFunction(pyobjects.PyObject(self))),
+ '__new__': BuiltinName(BuiltinFunction(function=self._new_tuple)),
+ '__iter__': BuiltinName(BuiltinFunction(get_iterator(first)))}
+ super(Tuple, self).__init__(tuple, attributes)
+
+ def get_holding_objects(self):
+ return self.objects
+
+ def _new_tuple(self, args):
+ return _create_builtin(args, get_tuple)
+
+
+get_tuple = _create_builtin_getter(Tuple)
+get_tuple_type = _create_builtin_type_getter(Tuple)
+
+
+class Set(BuiltinClass):
+
+ def __init__(self, holding=None):
+ self.holding = holding
+ collector = _AttributeCollector(set)
+ collector('__new__', function=self._new_set)
+
+ self_methods = ['copy', 'difference', 'intersection',
+ 'symmetric_difference', 'union']
+ for method in self_methods:
+ collector(method, function=self._self_get)
+ collector('add', function=self._set_add)
+ collector('update', function=self._self_set)
+ collector('update', function=self._self_set)
+ collector('symmetric_difference_update', function=self._self_set)
+ collector('difference_update', function=self._self_set)
+
+ collector('pop', function=self._set_get)
+ collector('__iter__', function=self._iterator_get)
+ super(Set, self).__init__(set, collector.attributes)
+
+ def _new_set(self, args):
+ return _create_builtin(args, get_set)
+
+ def _set_add(self, context):
+ if self.holding is not None:
+ return
+ holding = context.get_arguments(['self', 'value'])[1]
+ if holding is not None and holding != pyobjects.get_unknown():
+ context.save_per_name(holding)
+
+ def _self_set(self, context):
+ if self.holding is not None:
+ return
+ iterable = context.get_pyname('iterable')
+ holding = _infer_sequence_for_pyname(iterable)
+ if holding is not None and holding != pyobjects.get_unknown():
+ context.save_per_name(holding)
+
+ def _set_get(self, context):
+ if self.holding is not None:
+ return self.holding
+ return context.get_per_name()
+
+ def _iterator_get(self, context):
+ return get_iterator(self._set_get(context))
+
+ def _self_get(self, context):
+ return get_list(self._set_get(context))
+
+
+get_set = _create_builtin_getter(Set)
+get_set_type = _create_builtin_type_getter(Set)
+
+
+class Str(BuiltinClass):
+
+ def __init__(self):
+ self_object = pyobjects.PyObject(self)
+ collector = _AttributeCollector(str)
+ collector('__iter__', get_iterator(self_object), check_existence=False)
+
+ self_methods = ['__getitem__', '__getslice__', 'capitalize', 'center',
+ 'decode', 'encode', 'expandtabs', 'join', 'ljust',
+ 'lower', 'lstrip', 'replace', 'rjust', 'rstrip', 'strip',
+ 'swapcase', 'title', 'translate', 'upper', 'zfill']
+ for method in self_methods:
+ collector(method, self_object)
+
+ for method in ['rsplit', 'split', 'splitlines']:
+ collector(method, get_list(self_object))
+
+ super(Str, self).__init__(str, collector.attributes)
+
+ def get_doc(self):
+ return str.__doc__
+
+
+get_str = _create_builtin_getter(Str)
+get_str_type = _create_builtin_type_getter(Str)
+
+
+class BuiltinName(pynames.PyName):
+
+ def __init__(self, pyobject):
+ self.pyobject = pyobject
+
+ def get_object(self):
+ return self.pyobject
+
+ def get_definition_location(self):
+ return (None, None)
+
+class Iterator(pyobjects.AbstractClass):
+
+ def __init__(self, holding=None):
+ super(Iterator, self).__init__()
+ self.holding = holding
+ self.attributes = {
+ 'next': BuiltinName(BuiltinFunction(self.holding)),
+ '__iter__': BuiltinName(BuiltinFunction(self))}
+
+ def get_attributes(self):
+ return self.attributes
+
+ def get_returned_object(self, args):
+ return self.holding
+
+get_iterator = _create_builtin_getter(Iterator)
+
+
+class Generator(pyobjects.AbstractClass):
+
+ def __init__(self, holding=None):
+ super(Generator, self).__init__()
+ self.holding = holding
+ self.attributes = {
+ 'next': BuiltinName(BuiltinFunction(self.holding)),
+ '__iter__': BuiltinName(BuiltinFunction(get_iterator(self.holding))),
+ 'close': BuiltinName(BuiltinFunction()),
+ 'send': BuiltinName(BuiltinFunction()),
+ 'throw': BuiltinName(BuiltinFunction())}
+
+ def get_attributes(self):
+ return self.attributes
+
+ def get_returned_object(self, args):
+ return self.holding
+
+get_generator = _create_builtin_getter(Generator)
+
+
+class File(BuiltinClass):
+
+ def __init__(self):
+ self_object = pyobjects.PyObject(self)
+ str_object = get_str()
+ str_list = get_list(get_str())
+ attributes = {}
+ def add(name, returned=None, function=None):
+ builtin = getattr(file, name, None)
+ attributes[name] = BuiltinName(
+ BuiltinFunction(returned=returned, function=function,
+ builtin=builtin))
+ add('__iter__', get_iterator(str_object))
+ for method in ['next', 'read', 'readline', 'readlines']:
+ add(method, str_list)
+ for method in ['close', 'flush', 'lineno', 'isatty', 'seek', 'tell',
+ 'truncate', 'write', 'writelines']:
+ add(method)
+ super(File, self).__init__(file, attributes)
+
+
+get_file = _create_builtin_getter(File)
+get_file_type = _create_builtin_type_getter(File)
+
+
+class Property(BuiltinClass):
+
+ def __init__(self, fget=None, fset=None, fdel=None, fdoc=None):
+ self._fget = fget
+ self._fdoc = fdoc
+ attributes = {
+ 'fget': BuiltinName(BuiltinFunction()),
+ 'fset': BuiltinName(pynames.UnboundName()),
+ 'fdel': BuiltinName(pynames.UnboundName()),
+ '__new__': BuiltinName(BuiltinFunction(function=_property_function))}
+ super(Property, self).__init__(property, attributes)
+
+ def get_property_object(self, args):
+ if isinstance(self._fget, pyobjects.AbstractFunction):
+ return self._fget.get_returned_object(args)
+
+
+def _property_function(args):
+ parameters = args.get_arguments(['fget', 'fset', 'fdel', 'fdoc'])
+ return pyobjects.PyObject(Property(parameters[0]))
+
+
+class Lambda(pyobjects.AbstractFunction):
+
+ def __init__(self, node, scope):
+ super(Lambda, self).__init__()
+ self.node = node
+ self.scope = scope
+
+ def get_returned_object(self, args):
+ result = rope.base.evaluate.eval_node(self.scope, self.node.body)
+ if result is not None:
+ return result.get_object()
+ else:
+ return pyobjects.get_unknown()
+
+ def get_pattributes(self):
+ return {}
+
+
+class BuiltinObject(BuiltinClass):
+
+ def __init__(self):
+ super(BuiltinObject, self).__init__(object, {})
+
+
+class BuiltinType(BuiltinClass):
+
+ def __init__(self):
+ super(BuiltinType, self).__init__(type, {})
+
+
+def _infer_sequence_for_pyname(pyname):
+ if pyname is None:
+ return None
+ seq = pyname.get_object()
+ args = arguments.ObjectArguments([pyname])
+ if '__iter__' in seq:
+ iter = seq['__iter__'].get_object().\
+ get_returned_object(args)
+ if iter is not None and 'next' in iter:
+ holding = iter['next'].get_object().\
+ get_returned_object(args)
+ return holding
+
+
+def _create_builtin(args, creator):
+ passed = args.get_pynames(['sequence'])[0]
+ if passed is None:
+ holding = None
+ else:
+ holding = _infer_sequence_for_pyname(passed)
+ if holding is not None:
+ return creator(holding)
+ else:
+ return creator()
+
+
+def _range_function(args):
+ return get_list()
+
+def _reversed_function(args):
+ return _create_builtin(args, get_iterator)
+
+def _sorted_function(args):
+ return _create_builtin(args, get_list)
+
+def _super_function(args):
+ passed_class, passed_self = args.get_arguments(['type', 'self'])
+ if passed_self is None:
+ return passed_class
+ else:
+ #pyclass = passed_self.get_type()
+ pyclass = passed_class
+ if isinstance(pyclass, pyobjects.AbstractClass):
+ supers = pyclass.get_superclasses()
+ if supers:
+ return pyobjects.PyObject(supers[0])
+ return passed_self
+
+def _zip_function(args):
+ args = args.get_pynames(['sequence'])
+ objects = []
+ for seq in args:
+ if seq is None:
+ holding = None
+ else:
+ holding = _infer_sequence_for_pyname(seq)
+ objects.append(holding)
+ tuple = get_tuple(*objects)
+ return get_list(tuple)
+
+def _enumerate_function(args):
+ passed = args.get_pynames(['sequence'])[0]
+ if passed is None:
+ holding = None
+ else:
+ holding = _infer_sequence_for_pyname(passed)
+ tuple = get_tuple(None, holding)
+ return get_iterator(tuple)
+
+def _iter_function(args):
+ passed = args.get_pynames(['sequence'])[0]
+ if passed is None:
+ holding = None
+ else:
+ holding = _infer_sequence_for_pyname(passed)
+ return get_iterator(holding)
+
+def _input_function(args):
+ return get_str()
+
+
+_initial_builtins = {
+ 'list': BuiltinName(get_list_type()),
+ 'dict': BuiltinName(get_dict_type()),
+ 'tuple': BuiltinName(get_tuple_type()),
+ 'set': BuiltinName(get_set_type()),
+ 'str': BuiltinName(get_str_type()),
+ 'file': BuiltinName(get_file_type()),
+ 'open': BuiltinName(get_file_type()),
+ 'unicode': BuiltinName(get_str_type()),
+ 'range': BuiltinName(BuiltinFunction(function=_range_function, builtin=range)),
+ 'reversed': BuiltinName(BuiltinFunction(function=_reversed_function, builtin=reversed)),
+ 'sorted': BuiltinName(BuiltinFunction(function=_sorted_function, builtin=sorted)),
+ 'super': BuiltinName(BuiltinFunction(function=_super_function, builtin=super)),
+ 'property': BuiltinName(BuiltinFunction(function=_property_function, builtin=property)),
+ 'zip': BuiltinName(BuiltinFunction(function=_zip_function, builtin=zip)),
+ 'enumerate': BuiltinName(BuiltinFunction(function=_enumerate_function, builtin=enumerate)),
+ 'object': BuiltinName(BuiltinObject()),
+ 'type': BuiltinName(BuiltinType()),
+ 'iter': BuiltinName(BuiltinFunction(function=_iter_function, builtin=iter)),
+ 'raw_input': BuiltinName(BuiltinFunction(function=_input_function, builtin=raw_input)),
+ }
+
+builtins = BuiltinModule('__builtin__', initial=_initial_builtins)
diff --git a/vim/eclim/autoload/eclim/python/rope/base/change.py b/vim/eclim/autoload/eclim/python/rope/base/change.py
@@ -0,0 +1,448 @@
+import datetime
+import difflib
+import os
+import time
+import warnings
+
+import rope.base.fscommands
+from rope.base import taskhandle, exceptions, utils
+
+
+class Change(object):
+ """The base class for changes
+
+ Rope refactorings return `Change` objects. They can be previewed,
+ committed or undone.
+ """
+
+ def do(self, job_set=None):
+ """Perform the change
+
+ .. note:: Do use this directly. Use `Project.do()` instead.
+ """
+
+ def undo(self, job_set=None):
+ """Perform the change
+
+ .. note:: Do use this directly. Use `History.undo()` instead.
+ """
+
+ def get_description(self):
+ """Return the description of this change
+
+ This can be used for previewing the changes.
+ """
+ return str(self)
+
+ def get_changed_resources(self):
+ """Return the list of resources that will be changed"""
+ return []
+
+ @property
+ @utils.saveit
+ def _operations(self):
+ return _ResourceOperations(self.resource.project)
+
+
+class ChangeSet(Change):
+ """A collection of `Change` objects
+
+ This class holds a collection of changes. This class provides
+ these fields:
+
+ * `changes`: the list of changes
+ * `description`: the goal of these changes
+ """
+
+ def __init__(self, description, timestamp=None):
+ self.changes = []
+ self.description = description
+ self.time = timestamp
+
+ def do(self, job_set=taskhandle.NullJobSet()):
+ try:
+ done = []
+ for change in self.changes:
+ change.do(job_set)
+ done.append(change)
+ self.time = time.time()
+ except Exception:
+ for change in done:
+ change.undo()
+ raise
+
+ def undo(self, job_set=taskhandle.NullJobSet()):
+ try:
+ done = []
+ for change in reversed(self.changes):
+ change.undo(job_set)
+ done.append(change)
+ except Exception:
+ for change in done:
+ change.do()
+ raise
+
+ def add_change(self, change):
+ self.changes.append(change)
+
+ def get_description(self):
+ result = [str(self) + ':\n\n\n']
+ for change in self.changes:
+ result.append(change.get_description())
+ result.append('\n')
+ return ''.join(result)
+
+ def __str__(self):
+ if self.time is not None:
+ date = datetime.datetime.fromtimestamp(self.time)
+ if date.date() == datetime.date.today():
+ string_date = 'today'
+ elif date.date() == (datetime.date.today() - datetime.timedelta(1)):
+ string_date = 'yesterday'
+ elif date.year == datetime.date.today().year:
+ string_date = date.strftime('%b %d')
+ else:
+ string_date = date.strftime('%d %b, %Y')
+ string_time = date.strftime('%H:%M:%S')
+ string_time = '%s %s ' % (string_date, string_time)
+ return self.description + ' - ' + string_time
+ return self.description
+
+ def get_changed_resources(self):
+ result = set()
+ for change in self.changes:
+ result.update(change.get_changed_resources())
+ return result
+
+
+def _handle_job_set(function):
+ """A decorator for handling `taskhandle.JobSet`\s
+
+ A decorator for handling `taskhandle.JobSet`\s for `do` and `undo`
+ methods of `Change`\s.
+ """
+ def call(self, job_set=taskhandle.NullJobSet()):
+ job_set.started_job(str(self))
+ function(self)
+ job_set.finished_job()
+ return call
+
+
+class ChangeContents(Change):
+ """A class to change the contents of a file
+
+ Fields:
+
+ * `resource`: The `rope.base.resources.File` to change
+ * `new_contents`: What to write in the file
+ """
+
+ def __init__(self, resource, new_contents, old_contents=None):
+ self.resource = resource
+ # IDEA: Only saving diffs; possible problems when undo/redoing
+ self.new_contents = new_contents
+ self.old_contents = old_contents
+
+ @_handle_job_set
+ def do(self):
+ if self.old_contents is None:
+ self.old_contents = self.resource.read()
+ self._operations.write_file(self.resource, self.new_contents)
+
+ @_handle_job_set
+ def undo(self):
+ if self.old_contents is None:
+ raise exceptions.HistoryError(
+ 'Undoing a change that is not performed yet!')
+ self._operations.write_file(self.resource, self.old_contents)
+
+ def __str__(self):
+ return 'Change <%s>' % self.resource.path
+
+ def get_description(self):
+ new = self.new_contents
+ old = self.old_contents
+ if old is None:
+ if self.resource.exists():
+ old = self.resource.read()
+ else:
+ old = ''
+ result = difflib.unified_diff(
+ old.splitlines(True), new.splitlines(True),
+ 'a/' + self.resource.path, 'b/' + self.resource.path)
+ return ''.join(list(result))
+
+ def get_changed_resources(self):
+ return [self.resource]
+
+
+class MoveResource(Change):
+ """Move a resource to a new location
+
+ Fields:
+
+ * `resource`: The `rope.base.resources.Resource` to move
+ * `new_resource`: The destination for move; It is the moved
+ resource not the folder containing that resource.
+ """
+
+ def __init__(self, resource, new_location, exact=False):
+ self.project = resource.project
+ self.resource = resource
+ if not exact:
+ new_location = _get_destination_for_move(resource, new_location)
+ if resource.is_folder():
+ self.new_resource = self.project.get_folder(new_location)
+ else:
+ self.new_resource = self.project.get_file(new_location)
+
+ @_handle_job_set
+ def do(self):
+ self._operations.move(self.resource, self.new_resource)
+
+ @_handle_job_set
+ def undo(self):
+ self._operations.move(self.new_resource, self.resource)
+
+ def __str__(self):
+ return 'Move <%s>' % self.resource.path
+
+ def get_description(self):
+ return 'rename from %s\nrename to %s' % (self.resource.path,
+ self.new_resource.path)
+
+ def get_changed_resources(self):
+ return [self.resource, self.new_resource]
+
+
+class CreateResource(Change):
+ """A class to create a resource
+
+ Fields:
+
+ * `resource`: The resource to create
+ """
+
+ def __init__(self, resource):
+ self.resource = resource
+
+ @_handle_job_set
+ def do(self):
+ self._operations.create(self.resource)
+
+ @_handle_job_set
+ def undo(self):
+ self._operations.remove(self.resource)
+
+ def __str__(self):
+ return 'Create Resource <%s>' % (self.resource.path)
+
+ def get_description(self):
+ return 'new file %s' % (self.resource.path)
+
+ def get_changed_resources(self):
+ return [self.resource]
+
+ def _get_child_path(self, parent, name):
+ if parent.path == '':
+ return name
+ else:
+ return parent.path + '/' + name
+
+
+class CreateFolder(CreateResource):
+ """A class to create a folder
+
+ See docs for `CreateResource`.
+ """
+
+ def __init__(self, parent, name):
+ resource = parent.project.get_folder(self._get_child_path(parent, name))
+ super(CreateFolder, self).__init__(resource)
+
+
+class CreateFile(CreateResource):
+ """A class to create a file
+
+ See docs for `CreateResource`.
+ """
+
+ def __init__(self, parent, name):
+ resource = parent.project.get_file(self._get_child_path(parent, name))
+ super(CreateFile, self).__init__(resource)
+
+
+class RemoveResource(Change):
+ """A class to remove a resource
+
+ Fields:
+
+ * `resource`: The resource to be removed
+ """
+
+ def __init__(self, resource):
+ self.resource = resource
+
+ @_handle_job_set
+ def do(self):
+ self._operations.remove(self.resource)
+
+ # TODO: Undoing remove operations
+ @_handle_job_set
+ def undo(self):
+ raise NotImplementedError(
+ 'Undoing `RemoveResource` is not implemented yet.')
+
+ def __str__(self):
+ return 'Remove <%s>' % (self.resource.path)
+
+ def get_changed_resources(self):
+ return [self.resource]
+
+
+def count_changes(change):
+ """Counts the number of basic changes a `Change` will make"""
+ if isinstance(change, ChangeSet):
+ result = 0
+ for child in change.changes:
+ result += count_changes(child)
+ return result
+ return 1
+
+def create_job_set(task_handle, change):
+ return task_handle.create_jobset(str(change), count_changes(change))
+
+
+class _ResourceOperations(object):
+
+ def __init__(self, project):
+ self.project = project
+ self.fscommands = project.fscommands
+ self.direct_commands = rope.base.fscommands.FileSystemCommands()
+
+ def _get_fscommands(self, resource):
+ if self.project.is_ignored(resource):
+ return self.direct_commands
+ return self.fscommands
+
+ def write_file(self, resource, contents):
+ data = rope.base.fscommands.unicode_to_file_data(contents)
+ fscommands = self._get_fscommands(resource)
+ fscommands.write(resource.real_path, data)
+ for observer in list(self.project.observers):
+ observer.resource_changed(resource)
+
+ def move(self, resource, new_resource):
+ fscommands = self._get_fscommands(resource)
+ fscommands.move(resource.real_path, new_resource.real_path)
+ for observer in list(self.project.observers):
+ observer.resource_moved(resource, new_resource)
+
+ def create(self, resource):
+ if resource.is_folder():
+ self._create_resource(resource.path, kind='folder')
+ else:
+ self._create_resource(resource.path)
+ for observer in list(self.project.observers):
+ observer.resource_created(resource)
+
+ def remove(self, resource):
+ fscommands = self._get_fscommands(resource)
+ fscommands.remove(resource.real_path)
+ for observer in list(self.project.observers):
+ observer.resource_removed(resource)
+
+ def _create_resource(self, file_name, kind='file'):
+ resource_path = self.project._get_resource_path(file_name)
+ if os.path.exists(resource_path):
+ raise exceptions.RopeError('Resource <%s> already exists'
+ % resource_path)
+ resource = self.project.get_file(file_name)
+ if not resource.parent.exists():
+ raise exceptions.ResourceNotFoundError(
+ 'Parent folder of <%s> does not exist' % resource.path)
+ fscommands = self._get_fscommands(resource)
+ try:
+ if kind == 'file':
+ fscommands.create_file(resource_path)
+ else:
+ fscommands.create_folder(resource_path)
+ except IOError, e:
+ raise exceptions.RopeError(e)
+
+
+def _get_destination_for_move(resource, destination):
+ dest_path = resource.project._get_resource_path(destination)
+ if os.path.isdir(dest_path):
+ if destination != '':
+ return destination + '/' + resource.name
+ else:
+ return resource.name
+ return destination
+
+
+class ChangeToData(object):
+
+ def convertChangeSet(self, change):
+ description = change.description
+ changes = []
+ for child in change.changes:
+ changes.append(self(child))
+ return (description, changes, change.time)
+
+ def convertChangeContents(self, change):
+ return (change.resource.path, change.new_contents, change.old_contents)
+
+ def convertMoveResource(self, change):
+ return (change.resource.path, change.new_resource.path)
+
+ def convertCreateResource(self, change):
+ return (change.resource.path, change.resource.is_folder())
+
+ def convertRemoveResource(self, change):
+ return (change.resource.path, change.resource.is_folder())
+
+ def __call__(self, change):
+ change_type = type(change)
+ if change_type in (CreateFolder, CreateFile):
+ change_type = CreateResource
+ method = getattr(self, 'convert' + change_type.__name__)
+ return (change_type.__name__, method(change))
+
+
+class DataToChange(object):
+
+ def __init__(self, project):
+ self.project = project
+
+ def makeChangeSet(self, description, changes, time=None):
+ result = ChangeSet(description, time)
+ for child in changes:
+ result.add_change(self(child))
+ return result
+
+ def makeChangeContents(self, path, new_contents, old_contents):
+ resource = self.project.get_file(path)
+ return ChangeContents(resource, new_contents, old_contents)
+
+ def makeMoveResource(self, old_path, new_path):
+ resource = self.project.get_file(old_path)
+ return MoveResource(resource, new_path, exact=True)
+
+ def makeCreateResource(self, path, is_folder):
+ if is_folder:
+ resource = self.project.get_folder(path)
+ else:
+ resource = self.project.get_file(path)
+ return CreateResource(resource)
+
+ def makeRemoveResource(self, path, is_folder):
+ if is_folder:
+ resource = self.project.get_folder(path)
+ else:
+ resource = self.project.get_file(path)
+ return RemoveResource(resource)
+
+ def __call__(self, data):
+ method = getattr(self, 'make' + data[0])
+ return method(*data[1])
diff --git a/vim/eclim/autoload/eclim/python/rope/base/codeanalyze.py b/vim/eclim/autoload/eclim/python/rope/base/codeanalyze.py
@@ -0,0 +1,358 @@
+import bisect
+import re
+import token
+import tokenize
+
+
+class ChangeCollector(object):
+
+ def __init__(self, text):
+ self.text = text
+ self.changes = []
+
+ def add_change(self, start, end, new_text=None):
+ if new_text is None:
+ new_text = self.text[start:end]
+ self.changes.append((start, end, new_text))
+
+ def get_changed(self):
+ if not self.changes:
+ return None
+ def compare_changes(change1, change2):
+ return cmp(change1[:2], change2[:2])
+ self.changes.sort(compare_changes)
+ pieces = []
+ last_changed = 0
+ for change in self.changes:
+ start, end, text = change
+ pieces.append(self.text[last_changed:start] + text)
+ last_changed = end
+ if last_changed < len(self.text):
+ pieces.append(self.text[last_changed:])
+ result = ''.join(pieces)
+ if result != self.text:
+ return result
+
+
+class SourceLinesAdapter(object):
+ """Adapts source to Lines interface
+
+ Note: The creation of this class is expensive.
+ """
+
+ def __init__(self, source_code):
+ self.code = source_code
+ self.starts = None
+ self._initialize_line_starts()
+
+ def _initialize_line_starts(self):
+ self.starts = []
+ self.starts.append(0)
+ try:
+ i = 0
+ while True:
+ i = self.code.index('\n', i) + 1
+ self.starts.append(i)
+ except ValueError:
+ pass
+ self.starts.append(len(self.code) + 1)
+
+ def get_line(self, lineno):
+ return self.code[self.starts[lineno - 1]:
+ self.starts[lineno] - 1]
+
+ def length(self):
+ return len(self.starts) - 1
+
+ def get_line_number(self, offset):
+ return bisect.bisect(self.starts, offset)
+
+ def get_line_start(self, lineno):
+ return self.starts[lineno - 1]
+
+ def get_line_end(self, lineno):
+ return self.starts[lineno] - 1
+
+
+class ArrayLinesAdapter(object):
+
+ def __init__(self, lines):
+ self.lines = lines
+
+ def get_line(self, line_number):
+ return self.lines[line_number - 1]
+
+ def length(self):
+ return len(self.lines)
+
+
+class LinesToReadline(object):
+
+ def __init__(self, lines, start):
+ self.lines = lines
+ self.current = start
+
+ def readline(self):
+ if self.current <= self.lines.length():
+ self.current += 1
+ return self.lines.get_line(self.current - 1) + '\n'
+ return ''
+
+ def __call__(self):
+ return self.readline()
+
+
+class _CustomGenerator(object):
+
+ def __init__(self, lines):
+ self.lines = lines
+ self.in_string = ''
+ self.open_count = 0
+ self.continuation = False
+
+ def __call__(self):
+ size = self.lines.length()
+ result = []
+ i = 1
+ while i <= size:
+ while i <= size and not self.lines.get_line(i).strip():
+ i += 1
+ if i <= size:
+ start = i
+ while True:
+ line = self.lines.get_line(i)
+ self._analyze_line(line)
+ if not (self.continuation or self.open_count or
+ self.in_string) or i == size:
+ break
+ i += 1
+ result.append((start, i))
+ i += 1
+ return result
+
+ _main_chars = re.compile(r'[\'|"|#|\\|\[|\]|\{|\}|\(|\)]')
+ def _analyze_line(self, line):
+ char = None
+ for match in self._main_chars.finditer(line):
+ char = match.group()
+ i = match.start()
+ if char in '\'"':
+ if not self.in_string:
+ self.in_string = char
+ if char * 3 == line[i:i + 3]:
+ self.in_string = char * 3
+ elif self.in_string == line[i:i + len(self.in_string)] and \
+ not (i > 0 and line[i - 1] == '\\' and
+ not (i > 1 and line[i - 2] == '\\')):
+ self.in_string = ''
+ if self.in_string:
+ continue
+ if char == '#':
+ break
+ if char in '([{':
+ self.open_count += 1
+ elif char in ')]}':
+ self.open_count -= 1
+ if line and char != '#' and line.endswith('\\'):
+ self.continuation = True
+ else:
+ self.continuation = False
+
+def custom_generator(lines):
+ return _CustomGenerator(lines)()
+
+
+class LogicalLineFinder(object):
+
+ def __init__(self, lines):
+ self.lines = lines
+
+ def logical_line_in(self, line_number):
+ indents = count_line_indents(self.lines.get_line(line_number))
+ tries = 0
+ while True:
+ block_start = get_block_start(self.lines, line_number, indents)
+ try:
+ return self._block_logical_line(block_start, line_number)
+ except IndentationError, e:
+ tries += 1
+ if tries == 5:
+ raise e
+ lineno = e.lineno + block_start - 1
+ indents = count_line_indents(self.lines.get_line(lineno))
+
+ def generate_starts(self, start_line=1, end_line=None):
+ for start, end in self.generate_regions(start_line, end_line):
+ yield start
+
+ def generate_regions(self, start_line=1, end_line=None):
+ # XXX: `block_start` should be at a better position!
+ block_start = 1
+ readline = LinesToReadline(self.lines, block_start)
+ shifted = start_line - block_start + 1
+ try:
+ for start, end in self._logical_lines(readline):
+ real_start = start + block_start - 1
+ real_start = self._first_non_blank(real_start)
+ if end_line is not None and real_start >= end_line:
+ break
+ real_end = end + block_start - 1
+ if real_start >= start_line:
+ yield (real_start, real_end)
+ except tokenize.TokenError, e:
+ pass
+
+ def _block_logical_line(self, block_start, line_number):
+ readline = LinesToReadline(self.lines, block_start)
+ shifted = line_number - block_start + 1
+ region = self._calculate_logical(readline, shifted)
+ start = self._first_non_blank(region[0] + block_start - 1)
+ if region[1] is None:
+ end = self.lines.length()
+ else:
+ end = region[1] + block_start - 1
+ return start, end
+
+ def _calculate_logical(self, readline, line_number):
+ last_end = 1
+ try:
+ for start, end in self._logical_lines(readline):
+ if line_number <= end:
+ return (start, end)
+ last_end = end + 1
+ except tokenize.TokenError, e:
+ current = e.args[1][0]
+ return (last_end, max(last_end, current - 1))
+ return (last_end, None)
+
+ def _logical_lines(self, readline):
+ last_end = 1
+ for current_token in tokenize.generate_tokens(readline):
+ current = current_token[2][0]
+ if current_token[0] == token.NEWLINE:
+ yield (last_end, current)
+ last_end = current + 1
+
+ def _first_non_blank(self, line_number):
+ current = line_number
+ while current < self.lines.length():
+ line = self.lines.get_line(current).strip()
+ if line and not line.startswith('#'):
+ return current
+ current += 1
+ return current
+
+
+def tokenizer_generator(lines):
+ return LogicalLineFinder(lines).generate_regions()
+
+
+class CachingLogicalLineFinder(object):
+
+ def __init__(self, lines, generate=custom_generator):
+ self.lines = lines
+ self._generate = generate
+
+ _starts = None
+ @property
+ def starts(self):
+ if self._starts is None:
+ self._init_logicals()
+ return self._starts
+
+ _ends = None
+ @property
+ def ends(self):
+ if self._ends is None:
+ self._init_logicals()
+ return self._ends
+
+ def _init_logicals(self):
+ """Should initialize _starts and _ends attributes"""
+ size = self.lines.length() + 1
+ self._starts = [None] * size
+ self._ends = [None] * size
+ for start, end in self._generate(self.lines):
+ self._starts[start] = True
+ self._ends[end] = True
+
+ def logical_line_in(self, line_number):
+ start = line_number
+ while start > 0 and not self.starts[start]:
+ start -= 1
+ if start == 0:
+ try:
+ start = self.starts.index(True, line_number)
+ except ValueError:
+ return (line_number, line_number)
+ return (start, self.ends.index(True, start))
+
+ def generate_starts(self, start_line=1, end_line=None):
+ if end_line is None:
+ end_line = self.lines.length()
+ for index in range(start_line, end_line):
+ if self.starts[index]:
+ yield index
+
+
+def get_block_start(lines, lineno, maximum_indents=80):
+ """Approximate block start"""
+ pattern = get_block_start_patterns()
+ for i in range(lineno, 0, -1):
+ match = pattern.search(lines.get_line(i))
+ if match is not None and \
+ count_line_indents(lines.get_line(i)) <= maximum_indents:
+ striped = match.string.lstrip()
+ # Maybe we're in a list comprehension or generator expression
+ if i > 1 and striped.startswith('if') or striped.startswith('for'):
+ bracs = 0
+ for j in range(i, min(i + 5, lines.length() + 1)):
+ for c in lines.get_line(j):
+ if c == '#':
+ break
+ if c in '[(':
+ bracs += 1
+ if c in ')]':
+ bracs -= 1
+ if bracs < 0:
+ break
+ if bracs < 0:
+ break
+ if bracs < 0:
+ continue
+ return i
+ return 1
+
+
+_block_start_pattern = None
+
+def get_block_start_patterns():
+ global _block_start_pattern
+ if not _block_start_pattern:
+ pattern = '^\\s*(((def|class|if|elif|except|for|while|with)\\s)|'\
+ '((try|else|finally|except)\\s*:))'
+ _block_start_pattern = re.compile(pattern, re.M)
+ return _block_start_pattern
+
+
+def count_line_indents(line):
+ indents = 0
+ for char in line:
+ if char == ' ':
+ indents += 1
+ elif char == '\t':
+ indents += 8
+ else:
+ return indents
+ return 0
+
+
+def get_string_pattern():
+ start = r'(\b[uU]?[rR]?)?'
+ longstr = r'%s"""(\\.|"(?!"")|\\\n|[^"\\])*"""' % start
+ shortstr = r'%s"(\\.|[^"\\\n])*"' % start
+ return '|'.join([longstr, longstr.replace('"', "'"),
+ shortstr, shortstr.replace('"', "'")])
+
+def get_comment_pattern():
+ return r'#[^\n]*'
diff --git a/vim/eclim/autoload/eclim/python/rope/base/default_config.py b/vim/eclim/autoload/eclim/python/rope/base/default_config.py
@@ -0,0 +1,85 @@
+# The default ``config.py``
+
+
+def set_prefs(prefs):
+ """This function is called before opening the project"""
+
+ # Specify which files and folders to ignore in the project.
+ # Changes to ignored resources are not added to the history and
+ # VCSs. Also they are not returned in `Project.get_files()`.
+ # Note that ``?`` and ``*`` match all characters but slashes.
+ # '*.pyc': matches 'test.pyc' and 'pkg/test.pyc'
+ # 'mod*.pyc': matches 'test/mod1.pyc' but not 'mod/1.pyc'
+ # '.svn': matches 'pkg/.svn' and all of its children
+ # 'build/*.o': matches 'build/lib.o' but not 'build/sub/lib.o'
+ # 'build//*.o': matches 'build/lib.o' and 'build/sub/lib.o'
+ prefs['ignored_resources'] = ['*.pyc', '*~', '.ropeproject',
+ '.hg', '.svn', '_svn', '.git']
+
+ # Specifies which files should be considered python files. It is
+ # useful when you have scripts inside your project. Only files
+ # ending with ``.py`` are considered to be python files by
+ # default.
+ #prefs['python_files'] = ['*.py']
+
+ # Custom source folders: By default rope searches the project
+ # for finding source folders (folders that should be searched
+ # for finding modules). You can add paths to that list. Note
+ # that rope guesses project source folders correctly most of the
+ # time; use this if you have any problems.
+ # The folders should be relative to project root and use '/' for
+ # separating folders regardless of the platform rope is running on.
+ # 'src/my_source_folder' for instance.
+ #prefs.add('source_folders', 'src')
+
+ # You can extend python path for looking up modules
+ #prefs.add('python_path', '~/python/')
+
+ # Should rope save object information or not.
+ prefs['save_objectdb'] = True
+ prefs['compress_objectdb'] = False
+
+ # If `True`, rope analyzes each module when it is being saved.
+ prefs['automatic_soa'] = True
+ # The depth of calls to follow in static object analysis
+ prefs['soa_followed_calls'] = 0
+
+ # If `False` when running modules or unit tests "dynamic object
+ # analysis" is turned off. This makes them much faster.
+ prefs['perform_doa'] = True
+
+ # Rope can check the validity of its object DB when running.
+ prefs['validate_objectdb'] = True
+
+ # How many undos to hold?
+ prefs['max_history_items'] = 32
+
+ # Shows whether to save history across sessions.
+ prefs['save_history'] = True
+ prefs['compress_history'] = False
+
+ # Set the number spaces used for indenting. According to
+ # :PEP:`8`, it is best to use 4 spaces. Since most of rope's
+ # unit-tests use 4 spaces it is more reliable, too.
+ prefs['indent_size'] = 4
+
+ # Builtin and c-extension modules that are allowed to be imported
+ # and inspected by rope.
+ prefs['extension_modules'] = []
+
+ # Add all standard c-extensions to extension_modules list.
+ prefs['import_dynload_stdmods'] = True
+
+ # If `True` modules with syntax errors are considered to be empty.
+ # The default value is `False`; When `False` syntax errors raise
+ # `rope.base.exceptions.ModuleSyntaxError` exception.
+ prefs['ignore_syntax_errors'] = False
+
+ # If `True`, rope ignores unresolvable imports. Otherwise, they
+ # appear in the importing namespace.
+ prefs['ignore_bad_imports'] = False
+
+
+def project_opened(project):
+ """This function is called after opening the project"""
+ # Do whatever you like here!
diff --git a/vim/eclim/autoload/eclim/python/rope/base/evaluate.py b/vim/eclim/autoload/eclim/python/rope/base/evaluate.py
@@ -0,0 +1,317 @@
+import rope.base.builtins
+import rope.base.pynames
+import rope.base.pyobjects
+from rope.base import ast, astutils, exceptions, pyobjects, arguments, worder
+
+
+BadIdentifierError = exceptions.BadIdentifierError
+
+def eval_location(pymodule, offset):
+ """Find the pyname at the offset"""
+ return eval_location2(pymodule, offset)[1]
+
+
+def eval_location2(pymodule, offset):
+ """Find the primary and pyname at offset"""
+ pyname_finder = ScopeNameFinder(pymodule)
+ return pyname_finder.get_primary_and_pyname_at(offset)
+
+
+def eval_node(scope, node):
+ """Evaluate a `ast.AST` node and return a PyName
+
+ Return `None` if the expression cannot be evaluated.
+ """
+ return eval_node2(scope, node)[1]
+
+
+def eval_node2(scope, node):
+ evaluator = StatementEvaluator(scope)
+ ast.walk(node, evaluator)
+ return evaluator.old_result, evaluator.result
+
+
+def eval_str(holding_scope, name):
+ return eval_str2(holding_scope, name)[1]
+
+
+def eval_str2(holding_scope, name):
+ try:
+ # parenthesizing for handling cases like 'a_var.\nattr'
+ node = ast.parse('(%s)' % name)
+ except SyntaxError:
+ raise BadIdentifierError('Not a resolvable python identifier selected.')
+ return eval_node2(holding_scope, node)
+
+
+class ScopeNameFinder(object):
+
+ def __init__(self, pymodule):
+ self.module_scope = pymodule.get_scope()
+ self.lines = pymodule.lines
+ self.worder = worder.Worder(pymodule.source_code, True)
+
+ def _is_defined_in_class_body(self, holding_scope, offset, lineno):
+ if lineno == holding_scope.get_start() and \
+ holding_scope.parent is not None and \
+ holding_scope.parent.get_kind() == 'Class' and \
+ self.worder.is_a_class_or_function_name_in_header(offset):
+ return True
+ if lineno != holding_scope.get_start() and \
+ holding_scope.get_kind() == 'Class' and \
+ self.worder.is_name_assigned_in_class_body(offset):
+ return True
+ return False
+
+ def _is_function_name_in_function_header(self, scope, offset, lineno):
+ if scope.get_start() <= lineno <= scope.get_body_start() and \
+ scope.get_kind() == 'Function' and \
+ self.worder.is_a_class_or_function_name_in_header(offset):
+ return True
+ return False
+
+ def get_pyname_at(self, offset):
+ return self.get_primary_and_pyname_at(offset)[1]
+
+ def get_primary_and_pyname_at(self, offset):
+ lineno = self.lines.get_line_number(offset)
+ holding_scope = self.module_scope.get_inner_scope_for_line(lineno)
+ # function keyword parameter
+ if self.worder.is_function_keyword_parameter(offset):
+ keyword_name = self.worder.get_word_at(offset)
+ pyobject = self.get_enclosing_function(offset)
+ if isinstance(pyobject, pyobjects.PyFunction):
+ return (None, pyobject.get_parameters().get(keyword_name, None))
+ # class body
+ if self._is_defined_in_class_body(holding_scope, offset, lineno):
+ class_scope = holding_scope
+ if lineno == holding_scope.get_start():
+ class_scope = holding_scope.parent
+ name = self.worder.get_primary_at(offset).strip()
+ try:
+ return (None, class_scope.pyobject[name])
+ except rope.base.exceptions.AttributeNotFoundError:
+ return (None, None)
+ # function header
+ if self._is_function_name_in_function_header(holding_scope, offset, lineno):
+ name = self.worder.get_primary_at(offset).strip()
+ return (None, holding_scope.parent[name])
+ # from statement module
+ if self.worder.is_from_statement_module(offset):
+ module = self.worder.get_primary_at(offset)
+ module_pyname = self._find_module(module)
+ return (None, module_pyname)
+ if self.worder.is_from_aliased(offset):
+ name = self.worder.get_from_aliased(offset)
+ else:
+ name = self.worder.get_primary_at(offset)
+ return eval_str2(holding_scope, name)
+
+ def get_enclosing_function(self, offset):
+ function_parens = self.worder.find_parens_start_from_inside(offset)
+ try:
+ function_pyname = self.get_pyname_at(function_parens - 1)
+ except BadIdentifierError:
+ function_pyname = None
+ if function_pyname is not None:
+ pyobject = function_pyname.get_object()
+ if isinstance(pyobject, pyobjects.AbstractFunction):
+ return pyobject
+ elif isinstance(pyobject, pyobjects.AbstractClass) and \
+ '__init__' in pyobject:
+ return pyobject['__init__'].get_object()
+ elif '__call__' in pyobject:
+ return pyobject['__call__'].get_object()
+ return None
+
+ def _find_module(self, module_name):
+ dots = 0
+ while module_name[dots] == '.':
+ dots += 1
+ return rope.base.pynames.ImportedModule(
+ self.module_scope.pyobject, module_name[dots:], dots)
+
+
+class StatementEvaluator(object):
+
+ def __init__(self, scope):
+ self.scope = scope
+ self.result = None
+ self.old_result = None
+
+ def _Name(self, node):
+ self.result = self.scope.lookup(node.id)
+
+ def _Attribute(self, node):
+ pyname = eval_node(self.scope, node.value)
+ if pyname is None:
+ pyname = rope.base.pynames.UnboundName()
+ self.old_result = pyname
+ if pyname.get_object() != rope.base.pyobjects.get_unknown():
+ try:
+ self.result = pyname.get_object()[node.attr]
+ except exceptions.AttributeNotFoundError:
+ self.result = None
+
+ def _Call(self, node):
+ primary, pyobject = self._get_primary_and_object_for_node(node.func)
+ if pyobject is None:
+ return
+ def _get_returned(pyobject):
+ args = arguments.create_arguments(primary, pyobject,
+ node, self.scope)
+ return pyobject.get_returned_object(args)
+ if isinstance(pyobject, rope.base.pyobjects.AbstractClass):
+ result = None
+ if '__new__' in pyobject:
+ new_function = pyobject['__new__'].get_object()
+ result = _get_returned(new_function)
+ if result is None or \
+ result == rope.base.pyobjects.get_unknown():
+ result = rope.base.pyobjects.PyObject(pyobject)
+ self.result = rope.base.pynames.UnboundName(pyobject=result)
+ return
+
+ pyfunction = None
+ if isinstance(pyobject, rope.base.pyobjects.AbstractFunction):
+ pyfunction = pyobject
+ elif '__call__' in pyobject:
+ pyfunction = pyobject['__call__'].get_object()
+ if pyfunction is not None:
+ self.result = rope.base.pynames.UnboundName(
+ pyobject=_get_returned(pyfunction))
+
+ def _Str(self, node):
+ self.result = rope.base.pynames.UnboundName(
+ pyobject=rope.base.builtins.get_str())
+
+ def _Num(self, node):
+ type_name = type(node.n).__name__
+ self.result = self._get_builtin_name(type_name)
+
+ def _get_builtin_name(self, type_name):
+ pytype = rope.base.builtins.builtins[type_name].get_object()
+ return rope.base.pynames.UnboundName(
+ rope.base.pyobjects.PyObject(pytype))
+
+ def _BinOp(self, node):
+ self.result = rope.base.pynames.UnboundName(
+ self._get_object_for_node(node.left))
+
+ def _BoolOp(self, node):
+ self.result = rope.base.pynames.UnboundName(
+ self._get_object_for_node(node.values[0]))
+
+ def _Repr(self, node):
+ self.result = self._get_builtin_name('str')
+
+ def _UnaryOp(self, node):
+ self.result = rope.base.pynames.UnboundName(
+ self._get_object_for_node(node.operand))
+
+ def _Compare(self, node):
+ self.result = self._get_builtin_name('bool')
+
+ def _Dict(self, node):
+ keys = None
+ values = None
+ if node.keys:
+ keys = self._get_object_for_node(node.keys[0])
+ values = self._get_object_for_node(node.values[0])
+ self.result = rope.base.pynames.UnboundName(
+ pyobject=rope.base.builtins.get_dict(keys, values))
+
+ def _List(self, node):
+ holding = None
+ if node.elts:
+ holding = self._get_object_for_node(node.elts[0])
+ self.result = rope.base.pynames.UnboundName(
+ pyobject=rope.base.builtins.get_list(holding))
+
+ def _ListComp(self, node):
+ pyobject = self._what_does_comprehension_hold(node)
+ self.result = rope.base.pynames.UnboundName(
+ pyobject=rope.base.builtins.get_list(pyobject))
+
+ def _GeneratorExp(self, node):
+ pyobject = self._what_does_comprehension_hold(node)
+ self.result = rope.base.pynames.UnboundName(
+ pyobject=rope.base.builtins.get_iterator(pyobject))
+
+ def _what_does_comprehension_hold(self, node):
+ scope = self._make_comprehension_scope(node)
+ pyname = eval_node(scope, node.elt)
+ return pyname.get_object() if pyname is not None else None
+
+ def _make_comprehension_scope(self, node):
+ scope = self.scope
+ module = scope.pyobject.get_module()
+ names = {}
+ for comp in node.generators:
+ new_names = _get_evaluated_names(comp.target, comp.iter, module,
+ '.__iter__().next()', node.lineno)
+ names.update(new_names)
+ return rope.base.pyscopes.TemporaryScope(scope.pycore, scope, names)
+
+ def _Tuple(self, node):
+ objects = []
+ if len(node.elts) < 4:
+ for stmt in node.elts:
+ pyobject = self._get_object_for_node(stmt)
+ objects.append(pyobject)
+ else:
+ objects.append(self._get_object_for_node(node.elts[0]))
+ self.result = rope.base.pynames.UnboundName(
+ pyobject=rope.base.builtins.get_tuple(*objects))
+
+ def _get_object_for_node(self, stmt):
+ pyname = eval_node(self.scope, stmt)
+ pyobject = None
+ if pyname is not None:
+ pyobject = pyname.get_object()
+ return pyobject
+
+ def _get_primary_and_object_for_node(self, stmt):
+ primary, pyname = eval_node2(self.scope, stmt)
+ pyobject = None
+ if pyname is not None:
+ pyobject = pyname.get_object()
+ return primary, pyobject
+
+ def _Subscript(self, node):
+ if isinstance(node.slice, ast.Index):
+ self._call_function(node.value, '__getitem__',
+ [node.slice.value])
+ elif isinstance(node.slice, ast.Slice):
+ self._call_function(node.value, '__getslice__')
+
+ def _call_function(self, node, function_name, other_args=None):
+ pyname = eval_node(self.scope, node)
+ if pyname is not None:
+ pyobject = pyname.get_object()
+ else:
+ return
+ if function_name in pyobject:
+ call_function = pyobject[function_name].get_object()
+ args = [node]
+ if other_args:
+ args += other_args
+ arguments_ = arguments.Arguments(args, self.scope)
+ self.result = rope.base.pynames.UnboundName(
+ pyobject=call_function.get_returned_object(arguments_))
+
+ def _Lambda(self, node):
+ self.result = rope.base.pynames.UnboundName(
+ pyobject=rope.base.builtins.Lambda(node, self.scope))
+
+
+def _get_evaluated_names(targets, assigned, module, evaluation, lineno):
+ result = {}
+ for name, levels in astutils.get_name_levels(targets):
+ assignment = rope.base.pynames.AssignmentValue(assigned, levels,
+ evaluation)
+ # XXX: this module should not access `rope.base.pynamesdef`!
+ pyname = rope.base.pynamesdef.AssignedName(lineno, module)
+ pyname.assignments.append(assignment)
+ result[name] = pyname
+ return result
diff --git a/vim/eclim/autoload/eclim/python/rope/base/exceptions.py b/vim/eclim/autoload/eclim/python/rope/base/exceptions.py
@@ -0,0 +1,61 @@
+class RopeError(Exception):
+ """Base exception for rope"""
+
+
+class ResourceNotFoundError(RopeError):
+ """Resource not found exception"""
+
+
+class RefactoringError(RopeError):
+ """Errors for performing a refactoring"""
+
+
+class InterruptedTaskError(RopeError):
+ """The task has been interrupted"""
+
+
+class HistoryError(RopeError):
+ """Errors for history undo/redo operations"""
+
+
+class ModuleNotFoundError(RopeError):
+ """Module not found exception"""
+
+
+class AttributeNotFoundError(RopeError):
+ """Attribute not found exception"""
+
+
+class NameNotFoundError(RopeError):
+ """Name not found exception"""
+
+
+class BadIdentifierError(RopeError):
+ """The name cannot be resolved"""
+
+
+class ModuleSyntaxError(RopeError):
+ """Module has syntax errors
+
+ The `filename` and `lineno` fields indicate where the error has
+ occurred.
+
+ """
+
+ def __init__(self, filename, lineno, message):
+ self.filename = filename
+ self.lineno = lineno
+ self.message_ = message
+ super(ModuleSyntaxError, self).__init__(
+ 'Syntax error in file <%s> line <%s>: %s' %
+ (filename, lineno, message))
+
+
+class ModuleDecodeError(RopeError):
+ """Cannot decode module"""
+
+ def __init__(self, filename, message):
+ self.filename = filename
+ self.message_ = message
+ super(ModuleDecodeError, self).__init__(
+ 'Cannot decode file <%s>: %s' % (filename, message))
diff --git a/vim/eclim/autoload/eclim/python/rope/base/fscommands.py b/vim/eclim/autoload/eclim/python/rope/base/fscommands.py
@@ -0,0 +1,267 @@
+"""Project file system commands.
+
+This modules implements file system operations used by rope. Different
+version control systems can be supported by implementing the interface
+provided by `FileSystemCommands` class. See `SubversionCommands` and
+`MercurialCommands` for example.
+
+"""
+import os
+import shutil
+import subprocess
+
+
+def create_fscommands(root):
+ dirlist = os.listdir(root)
+ commands = {'.hg': MercurialCommands,
+ '.svn': SubversionCommands,
+ '.git': GITCommands,
+ '_svn': SubversionCommands,
+ '_darcs': DarcsCommands}
+ for key in commands:
+ if key in dirlist:
+ try:
+ return commands[key](root)
+ except (ImportError, OSError):
+ pass
+ return FileSystemCommands()
+
+
+class FileSystemCommands(object):
+
+ def create_file(self, path):
+ open(path, 'w').close()
+
+ def create_folder(self, path):
+ os.mkdir(path)
+
+ def move(self, path, new_location):
+ shutil.move(path, new_location)
+
+ def remove(self, path):
+ if os.path.isfile(path):
+ os.remove(path)
+ else:
+ shutil.rmtree(path)
+
+ def write(self, path, data):
+ file_ = open(path, 'wb')
+ try:
+ file_.write(data)
+ finally:
+ file_.close()
+
+
+class SubversionCommands(object):
+
+ def __init__(self, *args):
+ self.normal_actions = FileSystemCommands()
+ import pysvn
+ self.client = pysvn.Client()
+
+ def create_file(self, path):
+ self.normal_actions.create_file(path)
+ self.client.add(path, force=True)
+
+ def create_folder(self, path):
+ self.normal_actions.create_folder(path)
+ self.client.add(path, force=True)
+
+ def move(self, path, new_location):
+ self.client.move(path, new_location, force=True)
+
+ def remove(self, path):
+ self.client.remove(path, force=True)
+
+ def write(self, path, data):
+ self.normal_actions.write(path, data)
+
+
+class MercurialCommands(object):
+
+ def __init__(self, root):
+ self.hg = self._import_mercurial()
+ self.normal_actions = FileSystemCommands()
+ try:
+ self.ui = self.hg.ui.ui(
+ verbose=False, debug=False, quiet=True,
+ interactive=False, traceback=False, report_untrusted=False)
+ except:
+ self.ui = self.hg.ui.ui()
+ self.ui.setconfig('ui', 'interactive', 'no')
+ self.ui.setconfig('ui', 'debug', 'no')
+ self.ui.setconfig('ui', 'traceback', 'no')
+ self.ui.setconfig('ui', 'verbose', 'no')
+ self.ui.setconfig('ui', 'report_untrusted', 'no')
+ self.ui.setconfig('ui', 'quiet', 'yes')
+
+ self.repo = self.hg.hg.repository(self.ui, root)
+
+ def _import_mercurial(self):
+ import mercurial.commands
+ import mercurial.hg
+ import mercurial.ui
+ return mercurial
+
+ def create_file(self, path):
+ self.normal_actions.create_file(path)
+ self.hg.commands.add(self.ui, self.repo, path)
+
+ def create_folder(self, path):
+ self.normal_actions.create_folder(path)
+
+ def move(self, path, new_location):
+ self.hg.commands.rename(self.ui, self.repo, path,
+ new_location, after=False)
+
+ def remove(self, path):
+ self.hg.commands.remove(self.ui, self.repo, path)
+
+ def write(self, path, data):
+ self.normal_actions.write(path, data)
+
+
+class GITCommands(object):
+
+ def __init__(self, root):
+ self.root = root
+ self._do(['version'])
+ self.normal_actions = FileSystemCommands()
+
+ def create_file(self, path):
+ self.normal_actions.create_file(path)
+ self._do(['add', self._in_dir(path)])
+
+ def create_folder(self, path):
+ self.normal_actions.create_folder(path)
+
+ def move(self, path, new_location):
+ self._do(['mv', self._in_dir(path), self._in_dir(new_location)])
+
+ def remove(self, path):
+ self._do(['rm', self._in_dir(path)])
+
+ def write(self, path, data):
+ # XXX: should we use ``git add``?
+ self.normal_actions.write(path, data)
+
+ def _do(self, args):
+ _execute(['git'] + args, cwd=self.root)
+
+ def _in_dir(self, path):
+ if path.startswith(self.root):
+ return path[len(self.root) + 1:]
+ return self.root
+
+
+class DarcsCommands(object):
+
+ def __init__(self, root):
+ self.root = root
+ self.normal_actions = FileSystemCommands()
+
+ def create_file(self, path):
+ self.normal_actions.create_file(path)
+ self._do(['add', path])
+
+ def create_folder(self, path):
+ self.normal_actions.create_folder(path)
+ self._do(['add', path])
+
+ def move(self, path, new_location):
+ self._do(['mv', path, new_location])
+
+ def remove(self, path):
+ self.normal_actions.remove(path)
+
+ def write(self, path, data):
+ self.normal_actions.write(path, data)
+
+ def _do(self, args):
+ _execute(['darcs'] + args, cwd=self.root)
+
+
+def _execute(args, cwd=None):
+ process = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE)
+ process.wait()
+ return process.returncode
+
+
+def unicode_to_file_data(contents, encoding=None):
+ if not isinstance(contents, unicode):
+ return contents
+ if encoding is None:
+ encoding = read_str_coding(contents)
+ if encoding is not None:
+ return contents.encode(encoding)
+ try:
+ return contents.encode()
+ except UnicodeEncodeError:
+ return contents.encode('utf-8')
+
+def file_data_to_unicode(data, encoding=None):
+ result = _decode_data(data, encoding)
+ if '\r' in result:
+ result = result.replace('\r\n', '\n').replace('\r', '\n')
+ return result
+
+def _decode_data(data, encoding):
+ if isinstance(data, unicode):
+ return data
+ if encoding is None:
+ encoding = read_str_coding(data)
+ if encoding is None:
+ # there is no encoding tip, we need to guess.
+ # PEP263 says that "encoding not explicitly defined" means it is ascii,
+ # but we will use utf8 instead since utf8 fully covers ascii and btw is
+ # the only non-latin sane encoding.
+ encoding = 'utf-8'
+ try:
+ return data.decode(encoding)
+ except (UnicodeError, LookupError):
+ # fallback to latin1: it should never fail
+ return data.decode('latin1')
+
+
+def read_file_coding(path):
+ file = open(path, 'b')
+ count = 0
+ result = []
+ buffsize = 10
+ while True:
+ current = file.read(10)
+ if not current:
+ break
+ count += current.count('\n')
+ result.append(current)
+ file.close()
+ return _find_coding(''.join(result))
+
+
+def read_str_coding(source):
+ try:
+ first = source.index('\n') + 1
+ second = source.index('\n', first) + 1
+ except ValueError:
+ second = len(source)
+ return _find_coding(source[:second])
+
+
+def _find_coding(text):
+ coding = 'coding'
+ try:
+ start = text.index(coding) + len(coding)
+ if text[start] not in '=:':
+ return
+ start += 1
+ while start < len(text) and text[start].isspace():
+ start += 1
+ end = start
+ while end < len(text):
+ c = text[end]
+ if not c.isalnum() and c not in '-_':
+ break
+ end += 1
+ return text[start:end]
+ except ValueError:
+ pass
diff --git a/vim/eclim/autoload/eclim/python/rope/base/history.py b/vim/eclim/autoload/eclim/python/rope/base/history.py
@@ -0,0 +1,235 @@
+from rope.base import exceptions, change, taskhandle
+
+
+class History(object):
+ """A class that holds project history"""
+
+ def __init__(self, project, maxundos=None):
+ self.project = project
+ self._undo_list = []
+ self._redo_list = []
+ self._maxundos = maxundos
+ self._load_history()
+ self.project.data_files.add_write_hook(self.write)
+ self.current_change = None
+
+ def _load_history(self):
+ if self.save:
+ result = self.project.data_files.read_data(
+ 'history', compress=self.compress, import_=True)
+ if result is not None:
+ to_change = change.DataToChange(self.project)
+ for data in result[0]:
+ self._undo_list.append(to_change(data))
+ for data in result[1]:
+ self._redo_list.append(to_change(data))
+
+ def do(self, changes, task_handle=taskhandle.NullTaskHandle()):
+ """Perform the change and add it to the `self.undo_list`
+
+ Note that uninteresting changes (changes to ignored files)
+ will not be appended to `self.undo_list`.
+
+ """
+ try:
+ self.current_change = changes
+ changes.do(change.create_job_set(task_handle, changes))
+ finally:
+ self.current_change = None
+ if self._is_change_interesting(changes):
+ self.undo_list.append(changes)
+ self._remove_extra_items()
+ del self.redo_list[:]
+
+ def _remove_extra_items(self):
+ if len(self.undo_list) > self.max_undos:
+ del self.undo_list[0:len(self.undo_list) - self.max_undos]
+
+ def _is_change_interesting(self, changes):
+ for resource in changes.get_changed_resources():
+ if not self.project.is_ignored(resource):
+ return True
+ return False
+
+ def undo(self, change=None, drop=False,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Redo done changes from the history
+
+ When `change` is `None`, the last done change will be undone.
+ If change is not `None` it should be an item from
+ `self.undo_list`; this change and all changes that depend on
+ it will be undone. In both cases the list of undone changes
+ will be returned.
+
+ If `drop` is `True`, the undone change will not be appended to
+ the redo list.
+
+ """
+ if not self._undo_list:
+ raise exceptions.HistoryError('Undo list is empty')
+ if change is None:
+ change = self.undo_list[-1]
+ dependencies = self._find_dependencies(self.undo_list, change)
+ self._move_front(self.undo_list, dependencies)
+ self._perform_undos(len(dependencies), task_handle)
+ result = self.redo_list[-len(dependencies):]
+ if drop:
+ del self.redo_list[-len(dependencies):]
+ return result
+
+ def redo(self, change=None, task_handle=taskhandle.NullTaskHandle()):
+ """Redo undone changes from the history
+
+ When `change` is `None`, the last undone change will be
+ redone. If change is not `None` it should be an item from
+ `self.redo_list`; this change and all changes that depend on
+ it will be redone. In both cases the list of redone changes
+ will be returned.
+
+ """
+ if not self.redo_list:
+ raise exceptions.HistoryError('Redo list is empty')
+ if change is None:
+ change = self.redo_list[-1]
+ dependencies = self._find_dependencies(self.redo_list, change)
+ self._move_front(self.redo_list, dependencies)
+ self._perform_redos(len(dependencies), task_handle)
+ return self.undo_list[-len(dependencies):]
+
+ def _move_front(self, change_list, changes):
+ for change in changes:
+ change_list.remove(change)
+ change_list.append(change)
+
+ def _find_dependencies(self, change_list, change):
+ index = change_list.index(change)
+ return _FindChangeDependencies(change_list[index:])()
+
+ def _perform_undos(self, count, task_handle):
+ for i in range(count):
+ self.current_change = self.undo_list[-1]
+ try:
+ job_set = change.create_job_set(task_handle,
+ self.current_change)
+ self.current_change.undo(job_set)
+ finally:
+ self.current_change = None
+ self.redo_list.append(self.undo_list.pop())
+
+ def _perform_redos(self, count, task_handle):
+ for i in range(count):
+ self.current_change = self.redo_list[-1]
+ try:
+ job_set = change.create_job_set(task_handle,
+ self.current_change)
+ self.current_change.do(job_set)
+ finally:
+ self.current_change = None
+ self.undo_list.append(self.redo_list.pop())
+
+ def contents_before_current_change(self, file):
+ if self.current_change is None:
+ return None
+ result = self._search_for_change_contents([self.current_change], file)
+ if result is not None:
+ return result
+ if file.exists() and not file.is_folder():
+ return file.read()
+ else:
+ return None
+
+ def _search_for_change_contents(self, change_list, file):
+ for change_ in reversed(change_list):
+ if isinstance(change_, change.ChangeSet):
+ result = self._search_for_change_contents(change_.changes,
+ file)
+ if result is not None:
+ return result
+ if isinstance(change_, change.ChangeContents) and \
+ change_.resource == file:
+ return change_.old_contents
+
+ def write(self):
+ if self.save:
+ data = []
+ to_data = change.ChangeToData()
+ self._remove_extra_items()
+ data.append([to_data(change_) for change_ in self.undo_list])
+ data.append([to_data(change_) for change_ in self.redo_list])
+ self.project.data_files.write_data('history', data,
+ compress=self.compress)
+
+ def get_file_undo_list(self, resource):
+ result = []
+ for change in self.undo_list:
+ if resource in change.get_changed_resources():
+ result.append(change)
+ return result
+
+ def __str__(self):
+ return 'History holds %s changes in memory' % \
+ (len(self.undo_list) + len(self.redo_list))
+
+ undo_list = property(lambda self: self._undo_list)
+ redo_list = property(lambda self: self._redo_list)
+
+ @property
+ def tobe_undone(self):
+ """The last done change if available, `None` otherwise"""
+ if self.undo_list:
+ return self.undo_list[-1]
+
+ @property
+ def tobe_redone(self):
+ """The last undone change if available, `None` otherwise"""
+ if self.redo_list:
+ return self.redo_list[-1]
+
+ @property
+ def max_undos(self):
+ if self._maxundos is None:
+ return self.project.prefs.get('max_history_items', 100)
+ else:
+ return self._maxundos
+
+ @property
+ def save(self):
+ return self.project.prefs.get('save_history', False)
+
+ @property
+ def compress(self):
+ return self.project.prefs.get('compress_history', False)
+
+ def clear(self):
+ """Forget all undo and redo information"""
+ del self.undo_list[:]
+ del self.redo_list[:]
+
+
+class _FindChangeDependencies(object):
+
+ def __init__(self, change_list):
+ self.change = change_list[0]
+ self.change_list = change_list
+ self.changed_resources = set(self.change.get_changed_resources())
+
+ def __call__(self):
+ result = [self.change]
+ for change in self.change_list[1:]:
+ if self._depends_on(change, result):
+ result.append(change)
+ self.changed_resources.update(change.get_changed_resources())
+ return result
+
+ def _depends_on(self, changes, result):
+ for resource in changes.get_changed_resources():
+ if resource is None:
+ continue
+ if resource in self.changed_resources:
+ return True
+ for changed in self.changed_resources:
+ if resource.is_folder() and resource.contains(changed):
+ return True
+ if changed.is_folder() and changed.contains(resource):
+ return True
+ return False
diff --git a/vim/eclim/autoload/eclim/python/rope/base/libutils.py b/vim/eclim/autoload/eclim/python/rope/base/libutils.py
@@ -0,0 +1,65 @@
+"""A few useful functions for using rope as a library"""
+import os.path
+
+import rope.base.project
+import rope.base.pycore
+from rope.base import taskhandle
+
+
+def path_to_resource(project, path, type=None):
+ """Get the resource at path
+
+ You only need to specify `type` if `path` does not exist. It can
+ be either 'file' or 'folder'. If the type is `None` it is assumed
+ that the resource already exists.
+
+ Note that this function uses `Project.get_resource()`,
+ `Project.get_file()`, and `Project.get_folder()` methods.
+
+ """
+ project_path = relative(project.address, path)
+ if project_path is None:
+ project_path = rope.base.project._realpath(path)
+ project = rope.base.project.get_no_project()
+ if type is None:
+ return project.get_resource(project_path)
+ if type == 'file':
+ return project.get_file(project_path)
+ if type == 'folder':
+ return project.get_folder(project_path)
+ return None
+
+def relative(root, path):
+ root = rope.base.project._realpath(root).replace(os.path.sep, '/')
+ path = rope.base.project._realpath(path).replace(os.path.sep, '/')
+ if path == root:
+ return ''
+ if path.startswith(root + '/'):
+ return path[len(root) + 1:]
+
+def report_change(project, path, old_content):
+ """Report that the contents of file at `path` was changed
+
+ The new contents of file is retrieved by reading the file.
+
+ """
+ resource = path_to_resource(project, path)
+ if resource is None:
+ return
+ for observer in list(project.observers):
+ observer.resource_changed(resource)
+ if project.pycore.automatic_soa:
+ rope.base.pycore.perform_soa_on_changed_scopes(project, resource,
+ old_content)
+
+def analyze_modules(project, task_handle=taskhandle.NullTaskHandle()):
+ """Perform static object analysis on all python files in the project
+
+ Note that this might be really time consuming.
+ """
+ resources = project.pycore.get_python_files()
+ job_set = task_handle.create_jobset('Analyzing Modules', len(resources))
+ for resource in resources:
+ job_set.started_job(resource.path)
+ project.pycore.analyze_module(resource)
+ job_set.finished_job()
diff --git a/vim/eclim/autoload/eclim/python/rope/base/oi/__init__.py b/vim/eclim/autoload/eclim/python/rope/base/oi/__init__.py
@@ -0,0 +1,38 @@
+"""Rope object analysis and inference package
+
+Rope makes some simplifying assumptions about a python program. It
+assumes that a program only performs assignments and function calls.
+Tracking assignments is simple and `PyName` objects handle that. The
+main problem is function calls. Rope uses these two approaches for
+obtaining call information:
+
+* Static object analysis: `rope.base.pycore.PyCore.analyze_module()`
+
+ It can analyze modules to obtain information about functions. This
+ is done by analyzing function calls in a module or scope. Currently
+ SOA analyzes the scopes that are changed while saving or when the
+ user asks to analyze a module. That is mainly because static
+ analysis is time-consuming.
+
+* Dynamic object analysis: `rope.base.pycore.PyCore.run_module()`
+
+ When you run a module or your testsuite, when DOA is enabled, it
+ collects information about parameters passed to and objects returned
+ from functions. The main problem with this approach is that it is
+ quite slow; Not when looking up the information but when collecting
+ them.
+
+An instance of `rope.base.oi.objectinfo.ObjectInfoManager` can be used
+for accessing these information. It saves the data in a
+`rope.base.oi.objectdb.ObjectDB` internally.
+
+Now if our objectdb does not know anything about a function and we
+need the value returned by it, static object inference, SOI, comes
+into play. It analyzes function body and tries to infer the object
+that is returned from it (we usually need the returned value for the
+given parameter objects).
+
+Rope might collect and store information for other `PyName`\s, too.
+For instance rope stores the object builtin containers hold.
+
+"""
diff --git a/vim/eclim/autoload/eclim/python/rope/base/oi/doa.py b/vim/eclim/autoload/eclim/python/rope/base/oi/doa.py
@@ -0,0 +1,162 @@
+import cPickle as pickle
+import marshal
+import os
+import socket
+import subprocess
+import sys
+import tempfile
+import threading
+
+
+class PythonFileRunner(object):
+ """A class for running python project files"""
+
+ def __init__(self, pycore, file_, args=None, stdin=None,
+ stdout=None, analyze_data=None):
+ self.pycore = pycore
+ self.file = file_
+ self.analyze_data = analyze_data
+ self.observers = []
+ self.args = args
+ self.stdin = stdin
+ self.stdout = stdout
+
+ def run(self):
+ """Execute the process"""
+ env = dict(os.environ)
+ file_path = self.file.real_path
+ path_folders = self.pycore.get_source_folders() + \
+ self.pycore.get_python_path_folders()
+ env['PYTHONPATH'] = os.pathsep.join(folder.real_path
+ for folder in path_folders)
+ runmod_path = self.pycore.find_module('rope.base.oi.runmod').real_path
+ self.receiver = None
+ self._init_data_receiving()
+ send_info = '-'
+ if self.receiver:
+ send_info = self.receiver.get_send_info()
+ args = [sys.executable, runmod_path, send_info,
+ self.pycore.project.address, self.file.real_path]
+ if self.analyze_data is None:
+ del args[1:4]
+ if self.args is not None:
+ args.extend(self.args)
+ self.process = subprocess.Popen(
+ executable=sys.executable, args=args, env=env,
+ cwd=os.path.split(file_path)[0], stdin=self.stdin,
+ stdout=self.stdout, stderr=self.stdout, close_fds=os.name != 'nt')
+
+ def _init_data_receiving(self):
+ if self.analyze_data is None:
+ return
+ # Disabling FIFO data transfer due to blocking when running
+ # unittests in the GUI.
+ # XXX: Handle FIFO data transfer for `rope.ui.testview`
+ if True or os.name == 'nt':
+ self.receiver = _SocketReceiver()
+ else:
+ self.receiver = _FIFOReceiver()
+ self.receiving_thread = threading.Thread(target=self._receive_information)
+ self.receiving_thread.setDaemon(True)
+ self.receiving_thread.start()
+
+ def _receive_information(self):
+ #temp = open('/dev/shm/info', 'w')
+ for data in self.receiver.receive_data():
+ self.analyze_data(data)
+ #temp.write(str(data) + '\n')
+ #temp.close()
+ for observer in self.observers:
+ observer()
+
+ def wait_process(self):
+ """Wait for the process to finish"""
+ self.process.wait()
+ if self.analyze_data:
+ self.receiving_thread.join()
+
+ def kill_process(self):
+ """Stop the process"""
+ if self.process.poll() is not None:
+ return
+ try:
+ if hasattr(self.process, 'terminate'):
+ self.process.terminate()
+ elif os.name != 'nt':
+ os.kill(self.process.pid, 9)
+ else:
+ import ctypes
+ handle = int(self.process._handle)
+ ctypes.windll.kernel32.TerminateProcess(handle, -1)
+ except OSError:
+ pass
+
+ def add_finishing_observer(self, observer):
+ """Notify this observer when execution finishes"""
+ self.observers.append(observer)
+
+
+class _MessageReceiver(object):
+
+ def receive_data(self):
+ pass
+
+ def get_send_info(self):
+ pass
+
+
+class _SocketReceiver(_MessageReceiver):
+
+ def __init__(self):
+ self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ self.data_port = 3037
+ while self.data_port < 4000:
+ try:
+ self.server_socket.bind(('', self.data_port))
+ break
+ except socket.error, e:
+ self.data_port += 1
+ self.server_socket.listen(1)
+
+ def get_send_info(self):
+ return str(self.data_port)
+
+ def receive_data(self):
+ conn, addr = self.server_socket.accept()
+ self.server_socket.close()
+ my_file = conn.makefile('r')
+ while True:
+ try:
+ yield pickle.load(my_file)
+ except EOFError:
+ break
+ my_file.close()
+ conn.close()
+
+
+class _FIFOReceiver(_MessageReceiver):
+
+ def __init__(self):
+ # XXX: this is insecure and might cause race conditions
+ self.file_name = self._get_file_name()
+ os.mkfifo(self.file_name)
+
+ def _get_file_name(self):
+ prefix = tempfile.gettempdir() + '/__rope_'
+ i = 0
+ while os.path.exists(prefix + str(i).rjust(4, '0')):
+ i += 1
+ return prefix + str(i).rjust(4, '0')
+
+ def get_send_info(self):
+ return self.file_name
+
+ def receive_data(self):
+ my_file = open(self.file_name, 'rb')
+ while True:
+ try:
+ yield marshal.load(my_file)
+ except EOFError:
+ break
+ my_file.close()
+ os.remove(self.file_name)
diff --git a/vim/eclim/autoload/eclim/python/rope/base/oi/memorydb.py b/vim/eclim/autoload/eclim/python/rope/base/oi/memorydb.py
@@ -0,0 +1,106 @@
+from rope.base.oi import objectdb
+
+
+class MemoryDB(objectdb.FileDict):
+
+ def __init__(self, project, persist=None):
+ self.project = project
+ self._persist = persist
+ self.files = self
+ self._load_files()
+ self.project.data_files.add_write_hook(self.write)
+
+ def _load_files(self):
+ self._files = {}
+ if self.persist:
+ result = self.project.data_files.read_data(
+ 'objectdb', compress=self.compress, import_=True)
+ if result is not None:
+ self._files = result
+
+ def keys(self):
+ return self._files.keys()
+
+ def __contains__(self, key):
+ return key in self._files
+
+ def __getitem__(self, key):
+ return FileInfo(self._files[key])
+
+ def create(self, path):
+ self._files[path] = {}
+
+ def rename(self, file, newfile):
+ if file not in self._files:
+ return
+ self._files[newfile] = self._files[file]
+ del self[file]
+
+ def __delitem__(self, file):
+ del self._files[file]
+
+ def write(self):
+ if self.persist:
+ self.project.data_files.write_data('objectdb', self._files,
+ self.compress)
+
+ @property
+ def compress(self):
+ return self.project.prefs.get('compress_objectdb', False)
+
+ @property
+ def persist(self):
+ if self._persist is not None:
+ return self._persist
+ else:
+ return self.project.prefs.get('save_objectdb', False)
+
+
+class FileInfo(objectdb.FileInfo):
+
+ def __init__(self, scopes):
+ self.scopes = scopes
+
+ def create_scope(self, key):
+ self.scopes[key] = ScopeInfo()
+
+ def keys(self):
+ return self.scopes.keys()
+
+ def __contains__(self, key):
+ return key in self.scopes
+
+ def __getitem__(self, key):
+ return self.scopes[key]
+
+ def __delitem__(self, key):
+ del self.scopes[key]
+
+
+class ScopeInfo(objectdb.ScopeInfo):
+
+ def __init__(self):
+ self.call_info = {}
+ self.per_name = {}
+
+ def get_per_name(self, name):
+ return self.per_name.get(name, None)
+
+ def save_per_name(self, name, value):
+ self.per_name[name] = value
+
+ def get_returned(self, parameters):
+ return self.call_info.get(parameters, None)
+
+ def get_call_infos(self):
+ for args, returned in self.call_info.items():
+ yield objectdb.CallInfo(args, returned)
+
+ def add_call(self, parameters, returned):
+ self.call_info[parameters] = returned
+
+ def __getstate__(self):
+ return (self.call_info, self.per_name)
+
+ def __setstate__(self, data):
+ self.call_info, self.per_name = data
diff --git a/vim/eclim/autoload/eclim/python/rope/base/oi/objectdb.py b/vim/eclim/autoload/eclim/python/rope/base/oi/objectdb.py
@@ -0,0 +1,175 @@
+import UserDict
+
+
+class ObjectDB(object):
+
+ def __init__(self, db, validation):
+ self.db = db
+ self.validation = validation
+ self.observers = []
+ self.files = db.files
+
+ def validate_files(self):
+ for file in list(self.files):
+ if not self.validation.is_file_valid(file):
+ del self.files[file]
+ self._file_removed(file)
+
+ def validate_file(self, file):
+ if file not in self.files:
+ return
+ for key in list(self.files[file]):
+ if not self.validation.is_scope_valid(file, key):
+ del self.files[file][key]
+
+ def file_moved(self, file, newfile):
+ if file not in self.files:
+ return
+ self.files.rename(file, newfile)
+ self._file_removed(file)
+ self._file_added(newfile)
+
+ def get_files(self):
+ return self.files.keys()
+
+ def get_returned(self, path, key, args):
+ scope_info = self._get_scope_info(path, key, readonly=True)
+ result = scope_info.get_returned(args)
+ if self.validation.is_value_valid(result):
+ return result
+
+ def get_pername(self, path, key, name):
+ scope_info = self._get_scope_info(path, key, readonly=True)
+ result = scope_info.get_per_name(name)
+ if self.validation.is_value_valid(result):
+ return result
+
+ def get_callinfos(self, path, key):
+ scope_info = self._get_scope_info(path, key, readonly=True)
+ return scope_info.get_call_infos()
+
+ def add_callinfo(self, path, key, args, returned):
+ scope_info = self._get_scope_info(path, key, readonly=False)
+ old_returned = scope_info.get_returned(args)
+ if self.validation.is_more_valid(returned, old_returned):
+ scope_info.add_call(args, returned)
+
+ def add_pername(self, path, key, name, value):
+ scope_info = self._get_scope_info(path, key, readonly=False)
+ old_value = scope_info.get_per_name(name)
+ if self.validation.is_more_valid(value, old_value):
+ scope_info.save_per_name(name, value)
+
+ def add_file_list_observer(self, observer):
+ self.observers.append(observer)
+
+ def write(self):
+ self.db.write()
+
+ def _get_scope_info(self, path, key, readonly=True):
+ if path not in self.files:
+ if readonly:
+ return _NullScopeInfo()
+ self.files.create(path)
+ self._file_added(path)
+ if key not in self.files[path]:
+ if readonly:
+ return _NullScopeInfo()
+ self.files[path].create_scope(key)
+ result = self.files[path][key]
+ if isinstance(result, dict):
+ print self.files, self.files[path], self.files[path][key]
+ return result
+
+ def _file_removed(self, path):
+ for observer in self.observers:
+ observer.removed(path)
+
+ def _file_added(self, path):
+ for observer in self.observers:
+ observer.added(path)
+
+ def __str__(self):
+ scope_count = 0
+ for file_dict in self.files.values():
+ scope_count += len(file_dict)
+ return 'ObjectDB holds %s file and %s scope infos' % \
+ (len(self.files), scope_count)
+
+
+class _NullScopeInfo(object):
+
+ def __init__(self, error_on_write=True):
+ self.error_on_write = error_on_write
+
+ def get_per_name(self, name):
+ pass
+
+ def save_per_name(self, name, value):
+ if self.error_on_write:
+ raise NotImplementedError()
+
+ def get_returned(self, parameters):
+ pass
+
+ def get_call_infos(self):
+ return []
+
+ def add_call(self, parameters, returned):
+ if self.error_on_write:
+ raise NotImplementedError()
+
+
+class FileInfo(UserDict.DictMixin):
+
+ def create_scope(self, key):
+ pass
+
+
+class FileDict(UserDict.DictMixin):
+
+ def create(self, key):
+ pass
+
+ def rename(self, key, new_key):
+ pass
+
+
+class ScopeInfo(object):
+
+ def get_per_name(self, name):
+ pass
+
+ def save_per_name(self, name, value):
+ pass
+
+ def get_returned(self, parameters):
+ pass
+
+ def get_call_infos(self):
+ pass
+
+ def add_call(self, parameters, returned):
+ pass
+
+
+class CallInfo(object):
+
+ def __init__(self, args, returned):
+ self.args = args
+ self.returned = returned
+
+ def get_parameters(self):
+ return self.args
+
+ def get_returned(self):
+ return self.returned
+
+
+class FileListObserver(object):
+
+ def added(self, path):
+ pass
+
+ def removed(self, path):
+ pass
diff --git a/vim/eclim/autoload/eclim/python/rope/base/oi/objectinfo.py b/vim/eclim/autoload/eclim/python/rope/base/oi/objectinfo.py
@@ -0,0 +1,232 @@
+import warnings
+
+from rope.base import exceptions, resourceobserver
+from rope.base.oi import objectdb, memorydb, transform
+
+
+class ObjectInfoManager(object):
+ """Stores object information
+
+ It uses an instance of `objectdb.ObjectDB` for storing
+ information.
+
+ """
+
+ def __init__(self, project):
+ self.project = project
+ self.to_textual = transform.PyObjectToTextual(project)
+ self.to_pyobject = transform.TextualToPyObject(project)
+ self.doi_to_pyobject = transform.DOITextualToPyObject(project)
+ self._init_objectdb()
+ if project.prefs.get('validate_objectdb', False):
+ self._init_validation()
+
+ def _init_objectdb(self):
+ dbtype = self.project.get_prefs().get('objectdb_type', None)
+ persist = None
+ if dbtype is not None:
+ warnings.warn(
+ '"objectdb_type" project config is deprecated;\n'
+ 'Use "save_objectdb" instead in your project '
+ 'config file.\n(".ropeproject/config.py" by default)\n',
+ DeprecationWarning)
+ if dbtype != 'memory' and self.project.ropefolder is not None:
+ persist = True
+ self.validation = TextualValidation(self.to_pyobject)
+ db = memorydb.MemoryDB(self.project, persist=persist)
+ self.objectdb = objectdb.ObjectDB(db, self.validation)
+
+ def _init_validation(self):
+ self.objectdb.validate_files()
+ observer = resourceobserver.ResourceObserver(
+ changed=self._resource_changed, moved=self._resource_moved,
+ removed=self._resource_moved)
+ files = []
+ for path in self.objectdb.get_files():
+ resource = self.to_pyobject.path_to_resource(path)
+ if resource is not None and resource.project == self.project:
+ files.append(resource)
+ self.observer = resourceobserver.FilteredResourceObserver(observer,
+ files)
+ self.objectdb.add_file_list_observer(_FileListObserver(self))
+ self.project.add_observer(self.observer)
+
+ def _resource_changed(self, resource):
+ try:
+ self.objectdb.validate_file(
+ self.to_textual.resource_to_path(resource))
+ except exceptions.ModuleSyntaxError:
+ pass
+
+ def _resource_moved(self, resource, new_resource=None):
+ self.observer.remove_resource(resource)
+ if new_resource is not None:
+ old = self.to_textual.resource_to_path(resource)
+ new = self.to_textual.resource_to_path(new_resource)
+ self.objectdb.file_moved(old, new)
+ self.observer.add_resource(new_resource)
+
+ def get_returned(self, pyobject, args):
+ result = self.get_exact_returned(pyobject, args)
+ if result is not None:
+ return result
+ path, key = self._get_scope(pyobject)
+ if path is None:
+ return None
+ for call_info in self.objectdb.get_callinfos(path, key):
+ returned = call_info.get_returned()
+ if returned and returned[0] not in ('unknown', 'none'):
+ result = returned
+ break
+ if result is None:
+ result = returned
+ if result is not None:
+ return self.to_pyobject(result)
+
+ def get_exact_returned(self, pyobject, args):
+ path, key = self._get_scope(pyobject)
+ if path is not None:
+ returned = self.objectdb.get_returned(
+ path, key, self._args_to_textual(pyobject, args))
+ if returned is not None:
+ return self.to_pyobject(returned)
+
+ def _args_to_textual(self, pyfunction, args):
+ parameters = list(pyfunction.get_param_names(special_args=False))
+ arguments = args.get_arguments(parameters)[:len(parameters)]
+ textual_args = tuple([self.to_textual(arg)
+ for arg in arguments])
+ return textual_args
+
+ def get_parameter_objects(self, pyobject):
+ path, key = self._get_scope(pyobject)
+ if path is None:
+ return None
+ arg_count = len(pyobject.get_param_names(special_args=False))
+ unknowns = arg_count
+ parameters = [None] * arg_count
+ for call_info in self.objectdb.get_callinfos(path, key):
+ args = call_info.get_parameters()
+ for index, arg in enumerate(args[:arg_count]):
+ old = parameters[index]
+ if self.validation.is_more_valid(arg, old):
+ parameters[index] = arg
+ if self.validation.is_value_valid(arg):
+ unknowns -= 1
+ if unknowns == 0:
+ break
+ if unknowns < arg_count:
+ return [self.to_pyobject(parameter)
+ for parameter in parameters]
+
+ def get_passed_objects(self, pyfunction, parameter_index):
+ path, key = self._get_scope(pyfunction)
+ if path is None:
+ return []
+ result = []
+ for call_info in self.objectdb.get_callinfos(path, key):
+ args = call_info.get_parameters()
+ if len(args) > parameter_index:
+ parameter = self.to_pyobject(args[parameter_index])
+ if parameter is not None:
+ result.append(parameter)
+ return result
+
+ def doa_data_received(self, data):
+ def doi_to_normal(textual):
+ pyobject = self.doi_to_pyobject(textual)
+ return self.to_textual(pyobject)
+ function = doi_to_normal(data[0])
+ args = tuple([doi_to_normal(textual) for textual in data[1]])
+ returned = doi_to_normal(data[2])
+ if function[0] == 'defined' and len(function) == 3:
+ self._save_data(function, args, returned)
+
+ def function_called(self, pyfunction, params, returned=None):
+ function_text = self.to_textual(pyfunction)
+ params_text = tuple([self.to_textual(param)
+ for param in params])
+ returned_text = ('unknown',)
+ if returned is not None:
+ returned_text = self.to_textual(returned)
+ self._save_data(function_text, params_text, returned_text)
+
+ def save_per_name(self, scope, name, data):
+ path, key = self._get_scope(scope.pyobject)
+ if path is not None:
+ self.objectdb.add_pername(path, key, name, self.to_textual(data))
+
+ def get_per_name(self, scope, name):
+ path, key = self._get_scope(scope.pyobject)
+ if path is not None:
+ result = self.objectdb.get_pername(path, key, name)
+ if result is not None:
+ return self.to_pyobject(result)
+
+ def _save_data(self, function, args, returned=('unknown',)):
+ self.objectdb.add_callinfo(function[1], function[2], args, returned)
+
+ def _get_scope(self, pyobject):
+ resource = pyobject.get_module().get_resource()
+ if resource is None:
+ return None, None
+ textual = self.to_textual(pyobject)
+ if textual[0] == 'defined':
+ path = textual[1]
+ if len(textual) == 3:
+ key = textual[2]
+ else:
+ key = ''
+ return path, key
+ return None, None
+
+ def sync(self):
+ self.objectdb.sync()
+
+ def __str__(self):
+ return str(self.objectdb)
+
+
+class TextualValidation(object):
+
+ def __init__(self, to_pyobject):
+ self.to_pyobject = to_pyobject
+
+ def is_value_valid(self, value):
+ # ???: Should none and unknown be considered valid?
+ if value is None or value[0] in ('none', 'unknown'):
+ return False
+ return self.to_pyobject(value) is not None
+
+ def is_more_valid(self, new, old):
+ if old is None:
+ return True
+ return new[0] not in ('unknown', 'none')
+
+ def is_file_valid(self, path):
+ return self.to_pyobject.path_to_resource(path) is not None
+
+ def is_scope_valid(self, path, key):
+ if key == '':
+ textual = ('defined', path)
+ else:
+ textual = ('defined', path, key)
+ return self.to_pyobject(textual) is not None
+
+
+class _FileListObserver(object):
+
+ def __init__(self, object_info):
+ self.object_info = object_info
+ self.observer = self.object_info.observer
+ self.to_pyobject = self.object_info.to_pyobject
+
+ def removed(self, path):
+ resource = self.to_pyobject.path_to_resource(path)
+ if resource is not None:
+ self.observer.remove_resource(resource)
+
+ def added(self, path):
+ resource = self.to_pyobject.path_to_resource(path)
+ if resource is not None:
+ self.observer.add_resource(resource)
diff --git a/vim/eclim/autoload/eclim/python/rope/base/oi/runmod.py b/vim/eclim/autoload/eclim/python/rope/base/oi/runmod.py
@@ -0,0 +1,210 @@
+
+def __rope_start_everything():
+ import os
+ import sys
+ import socket
+ import cPickle as pickle
+ import marshal
+ import inspect
+ import types
+ import threading
+
+ class _MessageSender(object):
+
+ def send_data(self, data):
+ pass
+
+ class _SocketSender(_MessageSender):
+
+ def __init__(self, port):
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect(('127.0.0.1', port))
+ self.my_file = s.makefile('w')
+
+ def send_data(self, data):
+ if not self.my_file.closed:
+ pickle.dump(data, self.my_file)
+
+ def close(self):
+ self.my_file.close()
+
+ class _FileSender(_MessageSender):
+
+ def __init__(self, file_name):
+ self.my_file = open(file_name, 'wb')
+
+ def send_data(self, data):
+ if not self.my_file.closed:
+ marshal.dump(data, self.my_file)
+
+ def close(self):
+ self.my_file.close()
+
+
+ def _cached(func):
+ cache = {}
+ def newfunc(self, arg):
+ if arg in cache:
+ return cache[arg]
+ result = func(self, arg)
+ cache[arg] = result
+ return result
+ return newfunc
+
+ class _FunctionCallDataSender(object):
+
+ def __init__(self, send_info, project_root):
+ self.project_root = project_root
+ if send_info.isdigit():
+ self.sender = _SocketSender(int(send_info))
+ else:
+ self.sender = _FileSender(send_info)
+
+ def global_trace(frame, event, arg):
+ # HACK: Ignoring out->in calls
+ # This might lose some information
+ if self._is_an_interesting_call(frame):
+ return self.on_function_call
+ sys.settrace(global_trace)
+ threading.settrace(global_trace)
+
+ def on_function_call(self, frame, event, arg):
+ if event != 'return':
+ return
+ args = []
+ returned = ('unknown',)
+ code = frame.f_code
+ for argname in code.co_varnames[:code.co_argcount]:
+ try:
+ args.append(self._object_to_persisted_form(frame.f_locals[argname]))
+ except (TypeError, AttributeError):
+ args.append(('unknown',))
+ try:
+ returned = self._object_to_persisted_form(arg)
+ except (TypeError, AttributeError):
+ pass
+ try:
+ data = (self._object_to_persisted_form(frame.f_code),
+ tuple(args), returned)
+ self.sender.send_data(data)
+ except (TypeError):
+ pass
+ return self.on_function_call
+
+ def _is_an_interesting_call(self, frame):
+ #if frame.f_code.co_name in ['?', '<module>']:
+ # return False
+ #return not frame.f_back or not self._is_code_inside_project(frame.f_back.f_code)
+
+ if not self._is_code_inside_project(frame.f_code) and \
+ (not frame.f_back or not self._is_code_inside_project(frame.f_back.f_code)):
+ return False
+ return True
+
+ def _is_code_inside_project(self, code):
+ source = self._path(code.co_filename)
+ return source is not None and os.path.exists(source) and \
+ _realpath(source).startswith(self.project_root)
+
+ @_cached
+ def _get_persisted_code(self, object_):
+ source = self._path(object_.co_filename)
+ if not os.path.exists(source):
+ raise TypeError('no source')
+ return ('defined', _realpath(source), str(object_.co_firstlineno))
+
+ @_cached
+ def _get_persisted_class(self, object_):
+ try:
+ return ('defined', _realpath(inspect.getsourcefile(object_)),
+ object_.__name__)
+ except (TypeError, AttributeError):
+ return ('unknown',)
+
+ def _get_persisted_builtin(self, object_):
+ if isinstance(object_, (str, unicode)):
+ return ('builtin', 'str')
+ if isinstance(object_, list):
+ holding = None
+ if len(object_) > 0:
+ holding = object_[0]
+ return ('builtin', 'list', self._object_to_persisted_form(holding))
+ if isinstance(object_, dict):
+ keys = None
+ values = None
+ if len(object_) > 0:
+ keys = object_.keys()[0]
+ values = object_[keys]
+ return ('builtin', 'dict',
+ self._object_to_persisted_form(keys),
+ self._object_to_persisted_form(values))
+ if isinstance(object_, tuple):
+ objects = []
+ if len(object_) < 3:
+ for holding in object_:
+ objects.append(self._object_to_persisted_form(holding))
+ else:
+ objects.append(self._object_to_persisted_form(object_[0]))
+ return tuple(['builtin', 'tuple'] + objects)
+ if isinstance(object_, set):
+ holding = None
+ if len(object_) > 0:
+ for o in object_:
+ holding = o
+ break
+ return ('builtin', 'set', self._object_to_persisted_form(holding))
+ return ('unknown',)
+
+ def _object_to_persisted_form(self, object_):
+ if object_ is None:
+ return ('none',)
+ if isinstance(object_, types.CodeType):
+ return self._get_persisted_code(object_)
+ if isinstance(object_, types.FunctionType):
+ return self._get_persisted_code(object_.func_code)
+ if isinstance(object_, types.MethodType):
+ return self._get_persisted_code(object_.im_func.func_code)
+ if isinstance(object_, types.ModuleType):
+ return self._get_persisted_module(object_)
+ if isinstance(object_, (str, unicode, list, dict, tuple, set)):
+ return self._get_persisted_builtin(object_)
+ if isinstance(object_, (types.TypeType, types.ClassType)):
+ return self._get_persisted_class(object_)
+ return ('instance', self._get_persisted_class(type(object_)))
+
+ @_cached
+ def _get_persisted_module(self, object_):
+ path = self._path(object_.__file__)
+ if path and os.path.exists(path):
+ return ('defined', _realpath(path))
+ return ('unknown',)
+
+ def _path(self, path):
+ if path.endswith('.pyc'):
+ path = path[:-1]
+ if path.endswith('.py'):
+ return path
+
+ def close(self):
+ self.sender.close()
+
+ def _realpath(path):
+ return os.path.realpath(os.path.abspath(os.path.expanduser(path)))
+
+ send_info = sys.argv[1]
+ project_root = sys.argv[2]
+ file_to_run = sys.argv[3]
+ run_globals = globals()
+ run_globals.update({'__name__': '__main__',
+ '__builtins__': __builtins__,
+ '__file__': file_to_run})
+ if send_info != '-':
+ data_sender = _FunctionCallDataSender(send_info, project_root)
+ del sys.argv[1:4]
+ execfile(file_to_run, run_globals)
+ if send_info != '-':
+ data_sender.close()
+
+
+if __name__ == '__main__':
+ __rope_start_everything()
diff --git a/vim/eclim/autoload/eclim/python/rope/base/oi/soa.py b/vim/eclim/autoload/eclim/python/rope/base/oi/soa.py
@@ -0,0 +1,136 @@
+import rope.base.ast
+import rope.base.oi.soi
+import rope.base.pynames
+from rope.base import pyobjects, evaluate, astutils, arguments
+
+
+def analyze_module(pycore, pymodule, should_analyze,
+ search_subscopes, followed_calls):
+ """Analyze `pymodule` for static object inference
+
+ Analyzes scopes for collecting object information. The analysis
+ starts from inner scopes.
+
+ """
+ _analyze_node(pycore, pymodule, should_analyze,
+ search_subscopes, followed_calls)
+
+
+def _analyze_node(pycore, pydefined, should_analyze,
+ search_subscopes, followed_calls):
+ if search_subscopes(pydefined):
+ for scope in pydefined.get_scope().get_scopes():
+ _analyze_node(pycore, scope.pyobject, should_analyze,
+ search_subscopes, followed_calls)
+ if should_analyze(pydefined):
+ new_followed_calls = max(0, followed_calls - 1)
+ return_true = lambda pydefined: True
+ return_false = lambda pydefined: False
+ def _follow(pyfunction):
+ _analyze_node(pycore, pyfunction, return_true,
+ return_false, new_followed_calls)
+ if not followed_calls:
+ _follow = None
+ visitor = SOAVisitor(pycore, pydefined, _follow)
+ for child in rope.base.ast.get_child_nodes(pydefined.get_ast()):
+ rope.base.ast.walk(child, visitor)
+
+
+class SOAVisitor(object):
+
+ def __init__(self, pycore, pydefined, follow_callback=None):
+ self.pycore = pycore
+ self.pymodule = pydefined.get_module()
+ self.scope = pydefined.get_scope()
+ self.follow = follow_callback
+
+ def _FunctionDef(self, node):
+ pass
+
+ def _ClassDef(self, node):
+ pass
+
+ def _Call(self, node):
+ for child in rope.base.ast.get_child_nodes(node):
+ rope.base.ast.walk(child, self)
+ primary, pyname = evaluate.eval_node2(self.scope, node.func)
+ if pyname is None:
+ return
+ pyfunction = pyname.get_object()
+ if isinstance(pyfunction, pyobjects.AbstractFunction):
+ args = arguments.create_arguments(primary, pyfunction,
+ node, self.scope)
+ elif isinstance(pyfunction, pyobjects.PyClass):
+ pyclass = pyfunction
+ if '__init__' in pyfunction:
+ pyfunction = pyfunction['__init__'].get_object()
+ pyname = rope.base.pynames.UnboundName(pyobjects.PyObject(pyclass))
+ args = self._args_with_self(primary, pyname, pyfunction, node)
+ elif '__call__' in pyfunction:
+ pyfunction = pyfunction['__call__'].get_object()
+ args = self._args_with_self(primary, pyname, pyfunction, node)
+ else:
+ return
+ self._call(pyfunction, args)
+
+ def _args_with_self(self, primary, self_pyname, pyfunction, node):
+ base_args = arguments.create_arguments(primary, pyfunction,
+ node, self.scope)
+ return arguments.MixedArguments(self_pyname, base_args, self.scope)
+
+ def _call(self, pyfunction, args):
+ if isinstance(pyfunction, pyobjects.PyFunction):
+ if self.follow is not None:
+ before = self._parameter_objects(pyfunction)
+ self.pycore.object_info.function_called(
+ pyfunction, args.get_arguments(pyfunction.get_param_names()))
+ pyfunction._set_parameter_pyobjects(None)
+ if self.follow is not None:
+ after = self._parameter_objects(pyfunction)
+ if after != before:
+ self.follow(pyfunction)
+ # XXX: Maybe we should not call every builtin function
+ if isinstance(pyfunction, rope.base.builtins.BuiltinFunction):
+ pyfunction.get_returned_object(args)
+
+ def _parameter_objects(self, pyfunction):
+ result = []
+ for i in range(len(pyfunction.get_param_names(False))):
+ result.append(pyfunction.get_parameter(i))
+ return result
+
+ def _Assign(self, node):
+ for child in rope.base.ast.get_child_nodes(node):
+ rope.base.ast.walk(child, self)
+ visitor = _SOAAssignVisitor()
+ nodes = []
+ for child in node.targets:
+ rope.base.ast.walk(child, visitor)
+ nodes.extend(visitor.nodes)
+ for subscript, levels in nodes:
+ instance = evaluate.eval_node(self.scope, subscript.value)
+ args_pynames = []
+ args_pynames.append(evaluate.eval_node(self.scope,
+ subscript.slice.value))
+ value = rope.base.oi.soi._infer_assignment(
+ rope.base.pynames.AssignmentValue(node.value, levels), self.pymodule)
+ args_pynames.append(rope.base.pynames.UnboundName(value))
+ if instance is not None and value is not None:
+ pyobject = instance.get_object()
+ if '__setitem__' in pyobject:
+ pyfunction = pyobject['__setitem__'].get_object()
+ args = arguments.ObjectArguments([instance] + args_pynames)
+ self._call(pyfunction, args)
+ # IDEA: handle `__setslice__`, too
+
+
+class _SOAAssignVisitor(astutils._NodeNameCollector):
+
+ def __init__(self):
+ super(_SOAAssignVisitor, self).__init__()
+ self.nodes = []
+
+ def _added(self, node, levels):
+ if isinstance(node, rope.base.ast.Subscript) and \
+ isinstance(node.slice, rope.base.ast.Index):
+ self.nodes.append((node, levels))
diff --git a/vim/eclim/autoload/eclim/python/rope/base/oi/soi.py b/vim/eclim/autoload/eclim/python/rope/base/oi/soi.py
@@ -0,0 +1,186 @@
+"""A module for inferring objects
+
+For more information see the documentation in `rope.base.oi`
+package.
+
+"""
+import rope.base.builtins
+import rope.base.pynames
+import rope.base.pyobjects
+from rope.base import evaluate, utils, arguments
+
+
+_ignore_inferred = utils.ignore_exception(
+ rope.base.pyobjects.IsBeingInferredError)
+
+
+@_ignore_inferred
+def infer_returned_object(pyfunction, args):
+ """Infer the `PyObject` this `PyFunction` returns after calling"""
+ object_info = pyfunction.pycore.object_info
+ result = object_info.get_exact_returned(pyfunction, args)
+ if result is not None:
+ return result
+ result = _infer_returned(pyfunction, args)
+ if result is not None:
+ if args and pyfunction.get_module().get_resource() is not None:
+ params = args.get_arguments(
+ pyfunction.get_param_names(special_args=False))
+ object_info.function_called(pyfunction, params, result)
+ return result
+ return object_info.get_returned(pyfunction, args)
+
+@_ignore_inferred
+def infer_parameter_objects(pyfunction):
+ """Infer the `PyObject`\s of parameters of this `PyFunction`"""
+ object_info = pyfunction.pycore.object_info
+ result = object_info.get_parameter_objects(pyfunction)
+ if result is None:
+ result = _parameter_objects(pyfunction)
+ _handle_first_parameter(pyfunction, result)
+ return result
+
+def _handle_first_parameter(pyobject, parameters):
+ kind = pyobject.get_kind()
+ if parameters is None or kind not in ['method', 'classmethod']:
+ pass
+ if not parameters:
+ if not pyobject.get_param_names(special_args=False):
+ return
+ parameters.append(rope.base.pyobjects.get_unknown())
+ if kind == 'method':
+ parameters[0] = rope.base.pyobjects.PyObject(pyobject.parent)
+ if kind == 'classmethod':
+ parameters[0] = pyobject.parent
+
+@_ignore_inferred
+def infer_assigned_object(pyname):
+ if not pyname.assignments:
+ return
+ for assignment in reversed(pyname.assignments):
+ result = _infer_assignment(assignment, pyname.module)
+ if result is not None:
+ return result
+
+def get_passed_objects(pyfunction, parameter_index):
+ object_info = pyfunction.pycore.object_info
+ result = object_info.get_passed_objects(pyfunction,
+ parameter_index)
+ if not result:
+ statically_inferred = _parameter_objects(pyfunction)
+ if len(statically_inferred) > parameter_index:
+ result.append(statically_inferred[parameter_index])
+ return result
+
+def _infer_returned(pyobject, args):
+ if args:
+ # HACK: Setting parameter objects manually
+ # This is not thread safe and might cause problems if `args`
+ # does not come from a good call site
+ pyobject.get_scope().invalidate_data()
+ pyobject._set_parameter_pyobjects(
+ args.get_arguments(pyobject.get_param_names(special_args=False)))
+ scope = pyobject.get_scope()
+ if not scope._get_returned_asts():
+ return
+ maxtries = 3
+ for returned_node in reversed(scope._get_returned_asts()[-maxtries:]):
+ try:
+ resulting_pyname = evaluate.eval_node(scope, returned_node)
+ if resulting_pyname is None:
+ continue
+ pyobject = resulting_pyname.get_object()
+ if pyobject == rope.base.pyobjects.get_unknown():
+ continue
+ if not scope._is_generator():
+ return pyobject
+ else:
+ return rope.base.builtins.get_generator(pyobject)
+ except rope.base.pyobjects.IsBeingInferredError:
+ pass
+
+def _parameter_objects(pyobject):
+ params = pyobject.get_param_names(special_args=False)
+ return [rope.base.pyobjects.get_unknown()] * len(params)
+
+# handling `rope.base.pynames.AssignmentValue`
+
+@_ignore_inferred
+def _infer_assignment(assignment, pymodule):
+ result = _follow_pyname(assignment, pymodule)
+ if result is None:
+ return None
+ pyname, pyobject = result
+ pyobject = _follow_evaluations(assignment, pyname, pyobject)
+ if pyobject is None:
+ return None
+ return _follow_levels(assignment, pyobject)
+
+def _follow_levels(assignment, pyobject):
+ for index in assignment.levels:
+ if isinstance(pyobject.get_type(), rope.base.builtins.Tuple):
+ holdings = pyobject.get_type().get_holding_objects()
+ if holdings:
+ pyobject = holdings[min(len(holdings) - 1, index)]
+ else:
+ pyobject = None
+ elif isinstance(pyobject.get_type(), rope.base.builtins.List):
+ pyobject = pyobject.get_type().holding
+ else:
+ pyobject = None
+ if pyobject is None:
+ break
+ return pyobject
+
+@_ignore_inferred
+def _follow_pyname(assignment, pymodule, lineno=None):
+ assign_node = assignment.ast_node
+ if lineno is None:
+ lineno = _get_lineno_for_node(assign_node)
+ holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
+ pyname = evaluate.eval_node(holding_scope, assign_node)
+ if pyname is not None:
+ result = pyname.get_object()
+ if isinstance(result.get_type(), rope.base.builtins.Property) and \
+ holding_scope.get_kind() == 'Class':
+ arg = rope.base.pynames.UnboundName(
+ rope.base.pyobjects.PyObject(holding_scope.pyobject))
+ return pyname, result.get_type().get_property_object(
+ arguments.ObjectArguments([arg]))
+ return pyname, result
+
+@_ignore_inferred
+def _follow_evaluations(assignment, pyname, pyobject):
+ new_pyname = pyname
+ tokens = assignment.evaluation.split('.')
+ for token in tokens:
+ call = token.endswith('()')
+ if call:
+ token = token[:-2]
+ if token:
+ pyname = new_pyname
+ new_pyname = _get_attribute(pyobject, token)
+ if new_pyname is not None:
+ pyobject = new_pyname.get_object()
+ if pyobject is not None and call:
+ if isinstance(pyobject, rope.base.pyobjects.AbstractFunction):
+ args = arguments.ObjectArguments([pyname])
+ pyobject = pyobject.get_returned_object(args)
+ else:
+ pyobject = None
+ if pyobject is None:
+ break
+ if pyobject is not None and assignment.assign_type:
+ return rope.base.pyobjects.PyObject(pyobject)
+ return pyobject
+
+
+def _get_lineno_for_node(assign_node):
+ if hasattr(assign_node, 'lineno') and \
+ assign_node.lineno is not None:
+ return assign_node.lineno
+ return 1
+
+def _get_attribute(pyobject, name):
+ if pyobject is not None and name in pyobject:
+ return pyobject[name]
diff --git a/vim/eclim/autoload/eclim/python/rope/base/oi/transform.py b/vim/eclim/autoload/eclim/python/rope/base/oi/transform.py
@@ -0,0 +1,285 @@
+"""Provides classes for persisting `PyObject`\s"""
+import os
+import re
+
+import rope.base.builtins
+from rope.base import exceptions
+
+
+class PyObjectToTextual(object):
+ """For transforming `PyObject` to textual form
+
+ This can be used for storing `PyObjects` in files. Use
+ `TextualToPyObject` for converting back.
+
+ """
+
+ def __init__(self, project):
+ self.project = project
+
+ def transform(self, pyobject):
+ """Transform a `PyObject` to textual form"""
+ if pyobject is None:
+ return ('none',)
+ object_type = type(pyobject)
+ try:
+ method = getattr(self, object_type.__name__ + '_to_textual')
+ return method(pyobject)
+ except AttributeError:
+ return ('unknown',)
+
+ def __call__(self, pyobject):
+ return self.transform(pyobject)
+
+ def PyObject_to_textual(self, pyobject):
+ if isinstance(pyobject.get_type(), rope.base.pyobjects.AbstractClass):
+ result = self.transform(pyobject.get_type())
+ if result[0] == 'defined':
+ return ('instance', result)
+ return result
+ return ('unknown',)
+
+ def PyFunction_to_textual(self, pyobject):
+ return self._defined_to_textual(pyobject)
+
+ def PyClass_to_textual(self, pyobject):
+ return self._defined_to_textual(pyobject)
+
+ def _defined_to_textual(self, pyobject):
+ address = []
+ while pyobject.parent is not None:
+ address.insert(0, pyobject.get_name())
+ pyobject = pyobject.parent
+ return ('defined', self._get_pymodule_path(pyobject.get_module()),
+ '.'.join(address))
+
+ def PyModule_to_textual(self, pyobject):
+ return ('defined', self._get_pymodule_path(pyobject))
+
+ def PyPackage_to_textual(self, pyobject):
+ return ('defined', self._get_pymodule_path(pyobject))
+
+ def List_to_textual(self, pyobject):
+ return ('builtin', 'list', self.transform(pyobject.holding))
+
+ def Dict_to_textual(self, pyobject):
+ return ('builtin', 'dict', self.transform(pyobject.keys),
+ self.transform(pyobject.values))
+
+ def Tuple_to_textual(self, pyobject):
+ objects = [self.transform(holding)
+ for holding in pyobject.get_holding_objects()]
+ return tuple(['builtin', 'tuple'] + objects)
+
+ def Set_to_textual(self, pyobject):
+ return ('builtin', 'set', self.transform(pyobject.holding))
+
+ def Iterator_to_textual(self, pyobject):
+ return ('builtin', 'iter', self.transform(pyobject.holding))
+
+ def Generator_to_textual(self, pyobject):
+ return ('builtin', 'generator', self.transform(pyobject.holding))
+
+ def Str_to_textual(self, pyobject):
+ return ('builtin', 'str')
+
+ def File_to_textual(self, pyobject):
+ return ('builtin', 'file')
+
+ def BuiltinFunction_to_textual(self, pyobject):
+ return ('builtin', 'function', pyobject.get_name())
+
+ def _get_pymodule_path(self, pymodule):
+ return self.resource_to_path(pymodule.get_resource())
+
+ def resource_to_path(self, resource):
+ if resource.project == self.project:
+ return resource.path
+ else:
+ return resource.real_path
+
+
+class TextualToPyObject(object):
+ """For transforming textual form to `PyObject`"""
+
+ def __init__(self, project, allow_in_project_absolutes=False):
+ self.project = project
+
+ def __call__(self, textual):
+ return self.transform(textual)
+
+ def transform(self, textual):
+ """Transform an object from textual form to `PyObject`"""
+ if textual is None:
+ return None
+ type = textual[0]
+ try:
+ method = getattr(self, type + '_to_pyobject')
+ return method(textual)
+ except AttributeError:
+ return None
+
+ def builtin_to_pyobject(self, textual):
+ name = textual[1]
+ method = getattr(self, 'builtin_%s_to_pyobject' % textual[1], None)
+ if method is not None:
+ return method(textual)
+
+ def builtin_str_to_pyobject(self, textual):
+ return rope.base.builtins.get_str()
+
+ def builtin_list_to_pyobject(self, textual):
+ holding = self.transform(textual[2])
+ return rope.base.builtins.get_list(holding)
+
+ def builtin_dict_to_pyobject(self, textual):
+ keys = self.transform(textual[2])
+ values = self.transform(textual[3])
+ return rope.base.builtins.get_dict(keys, values)
+
+ def builtin_tuple_to_pyobject(self, textual):
+ objects = []
+ for holding in textual[2:]:
+ objects.append(self.transform(holding))
+ return rope.base.builtins.get_tuple(*objects)
+
+ def builtin_set_to_pyobject(self, textual):
+ holding = self.transform(textual[2])
+ return rope.base.builtins.get_set(holding)
+
+ def builtin_iter_to_pyobject(self, textual):
+ holding = self.transform(textual[2])
+ return rope.base.builtins.get_iterator(holding)
+
+ def builtin_generator_to_pyobject(self, textual):
+ holding = self.transform(textual[2])
+ return rope.base.builtins.get_generator(holding)
+
+ def builtin_file_to_pyobject(self, textual):
+ return rope.base.builtins.get_file()
+
+ def builtin_function_to_pyobject(self, textual):
+ if textual[2] in rope.base.builtins.builtins:
+ return rope.base.builtins.builtins[textual[2]].get_object()
+
+ def unknown_to_pyobject(self, textual):
+ return None
+
+ def none_to_pyobject(self, textual):
+ return None
+
+ def _module_to_pyobject(self, textual):
+ path = textual[1]
+ return self._get_pymodule(path)
+
+ def _hierarchical_defined_to_pyobject(self, textual):
+ path = textual[1]
+ names = textual[2].split('.')
+ pymodule = self._get_pymodule(path)
+ pyobject = pymodule
+ for name in names:
+ if pyobject is None:
+ return None
+ if isinstance(pyobject, rope.base.pyobjects.PyDefinedObject):
+ try:
+ pyobject = pyobject.get_scope()[name].get_object()
+ except exceptions.NameNotFoundError:
+ return None
+ else:
+ return None
+ return pyobject
+
+ def defined_to_pyobject(self, textual):
+ if len(textual) == 2 or textual[2] == '':
+ return self._module_to_pyobject(textual)
+ else:
+ return self._hierarchical_defined_to_pyobject(textual)
+
+ def instance_to_pyobject(self, textual):
+ type = self.transform(textual[1])
+ if type is not None:
+ return rope.base.pyobjects.PyObject(type)
+
+ def _get_pymodule(self, path):
+ resource = self.path_to_resource(path)
+ if resource is not None:
+ return self.project.pycore.resource_to_pyobject(resource)
+
+ def path_to_resource(self, path):
+ try:
+ root = self.project.address
+ if not os.path.isabs(path):
+ return self.project.get_resource(path)
+ if path == root or path.startswith(root + os.sep):
+ # INFO: This is a project file; should not be absolute
+ return None
+ import rope.base.project
+ return rope.base.project.get_no_project().get_resource(path)
+ except exceptions.ResourceNotFoundError:
+ return None
+
+
+class DOITextualToPyObject(TextualToPyObject):
+ """For transforming textual form to `PyObject`
+
+ The textual form DOI uses is different from rope's standard
+ textual form. The reason is that we cannot find the needed
+ information by analyzing live objects. This class can be
+ used to transform DOI textual form to `PyObject` and later
+ we can convert it to standard textual form using
+ `TextualToPyObject` class.
+
+ """
+
+ def _function_to_pyobject(self, textual):
+ path = textual[1]
+ lineno = int(textual[2])
+ pymodule = self._get_pymodule(path)
+ if pymodule is not None:
+ scope = pymodule.get_scope()
+ inner_scope = scope.get_inner_scope_for_line(lineno)
+ return inner_scope.pyobject
+
+ def _class_to_pyobject(self, textual):
+ path, name = textual[1:]
+ pymodule = self._get_pymodule(path)
+ if pymodule is None:
+ return None
+ module_scope = pymodule.get_scope()
+ suspected = None
+ if name in module_scope.get_names():
+ suspected = module_scope[name].get_object()
+ if suspected is not None and \
+ isinstance(suspected, rope.base.pyobjects.PyClass):
+ return suspected
+ else:
+ lineno = self._find_occurrence(name, pymodule.get_resource().read())
+ if lineno is not None:
+ inner_scope = module_scope.get_inner_scope_for_line(lineno)
+ return inner_scope.pyobject
+
+ def defined_to_pyobject(self, textual):
+ if len(textual) == 2:
+ return self._module_to_pyobject(textual)
+ else:
+ if textual[2].isdigit():
+ result = self._function_to_pyobject(textual)
+ else:
+ result = self._class_to_pyobject(textual)
+ if not isinstance(result, rope.base.pyobjects.PyModule):
+ return result
+
+ def _find_occurrence(self, name, source):
+ pattern = re.compile(r'^\s*class\s*' + name + r'\b')
+ lines = source.split('\n')
+ for i in range(len(lines)):
+ if pattern.match(lines[i]):
+ return i + 1
+
+ def path_to_resource(self, path):
+ import rope.base.libutils
+ root = self.project.address
+ relpath = rope.base.libutils.relative(root, path)
+ if relpath is not None:
+ path = relpath
+ return super(DOITextualToPyObject, self).path_to_resource(path)
diff --git a/vim/eclim/autoload/eclim/python/rope/base/prefs.py b/vim/eclim/autoload/eclim/python/rope/base/prefs.py
@@ -0,0 +1,41 @@
+class Prefs(object):
+
+ def __init__(self):
+ self.prefs = {}
+ self.callbacks = {}
+
+ def set(self, key, value):
+ """Set the value of `key` preference to `value`."""
+ if key in self.callbacks:
+ self.callbacks[key](value)
+ else:
+ self.prefs[key] = value
+
+ def add(self, key, value):
+ """Add an entry to a list preference
+
+ Add `value` to the list of entries for the `key` preference.
+
+ """
+ if not key in self.prefs:
+ self.prefs[key] = []
+ self.prefs[key].append(value)
+
+ def get(self, key, default=None):
+ """Get the value of the key preference"""
+ return self.prefs.get(key, default)
+
+ def add_callback(self, key, callback):
+ """Add `key` preference with `callback` function
+
+ Whenever `key` is set the callback is called with the
+ given `value` as parameter.
+
+ """
+ self.callbacks[key] = callback
+
+ def __setitem__(self, key, value):
+ self.set(key, value)
+
+ def __getitem__(self, key):
+ return self.get(key)
diff --git a/vim/eclim/autoload/eclim/python/rope/base/project.py b/vim/eclim/autoload/eclim/python/rope/base/project.py
@@ -0,0 +1,428 @@
+import cPickle as pickle
+import os
+import shutil
+import sys
+import warnings
+
+import rope.base.fscommands
+from rope.base import exceptions, taskhandle, prefs, history, pycore, utils
+from rope.base.resourceobserver import *
+from rope.base.resources import File, Folder, _ResourceMatcher
+
+
+class _Project(object):
+
+ def __init__(self, fscommands):
+ self.observers = []
+ self.fscommands = fscommands
+ self.prefs = prefs.Prefs()
+ self.data_files = _DataFiles(self)
+
+ def get_resource(self, resource_name):
+ """Get a resource in a project.
+
+ `resource_name` is the path of a resource in a project. It is
+ the path of a resource relative to project root. Project root
+ folder address is an empty string. If the resource does not
+ exist a `exceptions.ResourceNotFound` exception would be
+ raised. Use `get_file()` and `get_folder()` when you need to
+ get nonexistent `Resource`\s.
+
+ """
+ path = self._get_resource_path(resource_name)
+ if not os.path.exists(path):
+ raise exceptions.ResourceNotFoundError(
+ 'Resource <%s> does not exist' % resource_name)
+ elif os.path.isfile(path):
+ return File(self, resource_name)
+ elif os.path.isdir(path):
+ return Folder(self, resource_name)
+ else:
+ raise exceptions.ResourceNotFoundError('Unknown resource '
+ + resource_name)
+
+ def validate(self, folder):
+ """Validate files and folders contained in this folder
+
+ It validates all of the files and folders contained in this
+ folder if some observers are interested in them.
+
+ """
+ for observer in list(self.observers):
+ observer.validate(folder)
+
+ def add_observer(self, observer):
+ """Register a `ResourceObserver`
+
+ See `FilteredResourceObserver`.
+ """
+ self.observers.append(observer)
+
+ def remove_observer(self, observer):
+ """Remove a registered `ResourceObserver`"""
+ if observer in self.observers:
+ self.observers.remove(observer)
+
+ def do(self, changes, task_handle=taskhandle.NullTaskHandle()):
+ """Apply the changes in a `ChangeSet`
+
+ Most of the time you call this function for committing the
+ changes for a refactoring.
+ """
+ self.history.do(changes, task_handle=task_handle)
+
+ def get_pycore(self):
+ return self.pycore
+
+ def get_file(self, path):
+ """Get the file with `path` (it may not exist)"""
+ return File(self, path)
+
+ def get_folder(self, path):
+ """Get the folder with `path` (it may not exist)"""
+ return Folder(self, path)
+
+ def is_ignored(self, resource):
+ return False
+
+ def get_prefs(self):
+ return self.prefs
+
+ def _get_resource_path(self, name):
+ pass
+
+ @property
+ @utils.saveit
+ def history(self):
+ return history.History(self)
+
+ @property
+ @utils.saveit
+ def pycore(self):
+ return pycore.PyCore(self)
+
+ def close(self):
+ warnings.warn('Cannot close a NoProject',
+ DeprecationWarning, stacklevel=2)
+
+ ropefolder = None
+
+
+class Project(_Project):
+ """A Project containing files and folders"""
+
+ def __init__(self, projectroot, fscommands=None,
+ ropefolder='.ropeproject', **prefs):
+ """A rope project
+
+ :parameters:
+ - `projectroot`: The address of the root folder of the project
+ - `fscommands`: Implements the file system operations used
+ by rope; have a look at `rope.base.fscommands`
+ - `ropefolder`: The name of the folder in which rope stores
+ project configurations and data. Pass `None` for not using
+ such a folder at all.
+ - `prefs`: Specify project preferences. These values
+ overwrite config file preferences.
+
+ """
+ if projectroot != '/':
+ projectroot = _realpath(projectroot).rstrip('/\\')
+ self._address = projectroot
+ self._ropefolder_name = ropefolder
+ if not os.path.exists(self._address):
+ os.mkdir(self._address)
+ elif not os.path.isdir(self._address):
+ raise exceptions.RopeError('Project root exists and'
+ ' is not a directory')
+ if fscommands is None:
+ fscommands = rope.base.fscommands.create_fscommands(self._address)
+ super(Project, self).__init__(fscommands)
+ self.ignored = _ResourceMatcher()
+ self.file_list = _FileListCacher(self)
+ self.prefs.add_callback('ignored_resources', self.ignored.set_patterns)
+ if ropefolder is not None:
+ self.prefs['ignored_resources'] = [ropefolder]
+ self._init_prefs(prefs)
+
+ def get_files(self):
+ return self.file_list.get_files()
+
+ def _get_resource_path(self, name):
+ return os.path.join(self._address, *name.split('/'))
+
+ def _init_ropefolder(self):
+ if self.ropefolder is not None:
+ if not self.ropefolder.exists():
+ self._create_recursively(self.ropefolder)
+ if not self.ropefolder.has_child('config.py'):
+ config = self.ropefolder.create_file('config.py')
+ config.write(self._default_config())
+
+ def _create_recursively(self, folder):
+ if folder.parent != self.root and not folder.parent.exists():
+ self._create_recursively(folder.parent)
+ folder.create()
+
+ def _init_prefs(self, prefs):
+ run_globals = {}
+ if self.ropefolder is not None:
+ config = self.get_file(self.ropefolder.path + '/config.py')
+ run_globals.update({'__name__': '__main__',
+ '__builtins__': __builtins__,
+ '__file__': config.real_path})
+ if config.exists():
+ config = self.ropefolder.get_child('config.py')
+ execfile(config.real_path, run_globals)
+ else:
+ exec(self._default_config(), run_globals)
+ if 'set_prefs' in run_globals:
+ run_globals['set_prefs'](self.prefs)
+ for key, value in prefs.items():
+ self.prefs[key] = value
+ self._init_other_parts()
+ self._init_ropefolder()
+ if 'project_opened' in run_globals:
+ run_globals['project_opened'](self)
+
+ def _default_config(self):
+ import rope.base.default_config
+ import inspect
+ return inspect.getsource(rope.base.default_config)
+
+ def _init_other_parts(self):
+ # Forcing the creation of `self.pycore` to register observers
+ self.pycore
+
+ def is_ignored(self, resource):
+ return self.ignored.does_match(resource)
+
+ def sync(self):
+ """Closes project open resources"""
+ self.close()
+
+ def close(self):
+ """Closes project open resources"""
+ self.data_files.write()
+
+ def set(self, key, value):
+ """Set the `key` preference to `value`"""
+ self.prefs.set(key, value)
+
+ @property
+ def ropefolder(self):
+ if self._ropefolder_name is not None:
+ return self.get_folder(self._ropefolder_name)
+
+ def validate(self, folder=None):
+ if folder is None:
+ folder = self.root
+ super(Project, self).validate(folder)
+
+ root = property(lambda self: self.get_resource(''))
+ address = property(lambda self: self._address)
+
+
+class NoProject(_Project):
+ """A null object for holding out of project files.
+
+ This class is singleton use `get_no_project` global function
+ """
+
+ def __init__(self):
+ fscommands = rope.base.fscommands.FileSystemCommands()
+ super(NoProject, self).__init__(fscommands)
+
+ def _get_resource_path(self, name):
+ real_name = name.replace('/', os.path.sep)
+ return _realpath(real_name)
+
+ def get_resource(self, name):
+ universal_name = _realpath(name).replace(os.path.sep, '/')
+ return super(NoProject, self).get_resource(universal_name)
+
+ def get_files(self):
+ return []
+
+ _no_project = None
+
+
+def get_no_project():
+ if NoProject._no_project is None:
+ NoProject._no_project = NoProject()
+ return NoProject._no_project
+
+
+class _FileListCacher(object):
+
+ def __init__(self, project):
+ self.project = project
+ self.needs_gc = True
+ self.files = set()
+ self.folders = set()
+
+ def get_files(self):
+ if self.needs_gc:
+ # forcing the creation of the observer
+ self.observer
+ for file in list(self.files):
+ if not file.exists():
+ self.files.remove(file)
+ for folder in list(self.folders):
+ if not folder.exists():
+ self.folders.remove(folder)
+ self.observer.remove_resource(folder)
+ self.needs_gc = False
+ return self.files
+
+ def _updated_resources(self, folder):
+ if not folder.exists():
+ return set(), set()
+ files = set()
+ folders = set([folder])
+ files.update(folder.get_files())
+ for child in folder.get_folders():
+ if child not in self.folders:
+ newfiles, newfolders = self._updated_resources(child)
+ files.update(newfiles)
+ folders.update(newfolders)
+ return files, folders
+
+ def _update_folder(self, folder):
+ files, folders = self._updated_resources(folder)
+ self.files.update(files)
+ for child in folders - self.folders:
+ self.folders.add(child)
+ self.observer.add_resource(child)
+ self.needs_gc = True
+
+ @property
+ @utils.saveit
+ def observer(self):
+ rawobserver = ResourceObserver(
+ self._changed, self._moved, self._created,
+ self._removed, self._validate)
+ observer = FilteredResourceObserver(rawobserver)
+ self.project.add_observer(observer)
+ self._update_folder(self.project.root)
+ return observer
+
+ def _changed(self, resource):
+ if resource.is_folder():
+ self._update_folder(resource)
+
+ def _moved(self, resource, new_resource):
+ if resource.is_folder():
+ self._update_folder(resource)
+ self._update_folder(new_resource)
+ else:
+ self._removed(resource)
+ self._created(new_resource)
+
+ def _created(self, resource):
+ if resource.is_folder():
+ self._update_folder(resource)
+ else:
+ if not self.project.is_ignored(resource):
+ self.files.add(resource)
+
+ def _removed(self, resource):
+ if resource.is_folder():
+ self._update_folder(resource)
+ else:
+ if resource in self.files:
+ self.files.remove(resource)
+
+ def _validate(self, resource):
+ pass
+
+
+class _DataFiles(object):
+
+ def __init__(self, project):
+ self.project = project
+ self.hooks = []
+
+ def read_data(self, name, compress=False, import_=False):
+ if self.project.ropefolder is None:
+ return None
+ compress = compress and self._can_compress()
+ opener = self._get_opener(compress)
+ file = self._get_file(name, compress)
+ if not compress and import_:
+ self._import_old_files(name)
+ if file.exists():
+ input = opener(file.real_path, 'rb')
+ try:
+ result = []
+ try:
+ while True:
+ result.append(pickle.load(input))
+ except EOFError:
+ pass
+ if len(result) == 1:
+ return result[0]
+ if len(result) > 1:
+ return result
+ finally:
+ input.close()
+
+ def write_data(self, name, data, compress=False):
+ if self.project.ropefolder is not None:
+ compress = compress and self._can_compress()
+ file = self._get_file(name, compress)
+ opener = self._get_opener(compress)
+ output = opener(file.real_path, 'wb')
+ try:
+ pickle.dump(data, output, 2)
+ finally:
+ output.close()
+
+ def add_write_hook(self, hook):
+ self.hooks.append(hook)
+
+ def write(self):
+ for hook in self.hooks:
+ hook()
+
+ def _can_compress(self):
+ try:
+ import gzip
+ return True
+ except ImportError:
+ return False
+
+ def _import_old_files(self, name):
+ old = self._get_file(name + '.pickle', False)
+ new = self._get_file(name, False)
+ if old.exists() and not new.exists():
+ shutil.move(old.real_path, new.real_path)
+
+ def _get_opener(self, compress):
+ if compress:
+ try:
+ import gzip
+ return gzip.open
+ except ImportError:
+ pass
+ return open
+
+ def _get_file(self, name, compress):
+ path = self.project.ropefolder.path + '/' + name
+ if compress:
+ path += '.gz'
+ return self.project.get_file(path)
+
+
+def _realpath(path):
+ """Return the real path of `path`
+
+ Is equivalent to ``realpath(abspath(expanduser(path)))``.
+
+ """
+ # there is a bug in cygwin for os.path.abspath() for abs paths
+ if sys.platform == 'cygwin':
+ if path[1:3] == ':\\':
+ return path
+ return os.path.abspath(os.path.expanduser(path))
+ return os.path.realpath(os.path.abspath(os.path.expanduser(path)))
diff --git a/vim/eclim/autoload/eclim/python/rope/base/pycore.py b/vim/eclim/autoload/eclim/python/rope/base/pycore.py
@@ -0,0 +1,407 @@
+import bisect
+import difflib
+import sys
+import warnings
+
+import rope.base.oi.doa
+import rope.base.oi.objectinfo
+import rope.base.oi.soa
+from rope.base import ast, exceptions, taskhandle, utils, stdmods
+from rope.base.exceptions import ModuleNotFoundError
+from rope.base.pyobjectsdef import PyModule, PyPackage, PyClass
+import rope.base.resources
+import rope.base.resourceobserver
+from rope.base import builtins
+
+
+class PyCore(object):
+
+ def __init__(self, project):
+ self.project = project
+ self._init_resource_observer()
+ self.cache_observers = []
+ self.module_cache = _ModuleCache(self)
+ self.extension_cache = _ExtensionCache(self)
+ self.object_info = rope.base.oi.objectinfo.ObjectInfoManager(project)
+ self._init_python_files()
+ self._init_automatic_soa()
+ self._init_source_folders()
+
+ def _init_python_files(self):
+ self.python_matcher = None
+ patterns = self.project.prefs.get('python_files', None)
+ if patterns is not None:
+ self.python_matcher = rope.base.resources._ResourceMatcher()
+ self.python_matcher.set_patterns(patterns)
+
+ def _init_resource_observer(self):
+ callback = self._invalidate_resource_cache
+ observer = rope.base.resourceobserver.ResourceObserver(
+ changed=callback, moved=callback, removed=callback)
+ self.observer = rope.base.resourceobserver.FilteredResourceObserver(observer)
+ self.project.add_observer(self.observer)
+
+ def _init_source_folders(self):
+ self._custom_source_folders = []
+ for path in self.project.prefs.get('source_folders', []):
+ folder = self.project.get_resource(path)
+ self._custom_source_folders.append(folder)
+
+ def _init_automatic_soa(self):
+ if not self.automatic_soa:
+ return
+ callback = self._file_changed_for_soa
+ observer = rope.base.resourceobserver.ResourceObserver(
+ changed=callback, moved=callback, removed=callback)
+ self.project.add_observer(observer)
+
+ @property
+ def automatic_soa(self):
+ auto_soa = self.project.prefs.get('automatic_soi', None)
+ return self.project.prefs.get('automatic_soa', auto_soa)
+
+ def _file_changed_for_soa(self, resource, new_resource=None):
+ old_contents = self.project.history.\
+ contents_before_current_change(resource)
+ if old_contents is not None:
+ perform_soa_on_changed_scopes(self.project, resource, old_contents)
+
+ def is_python_file(self, resource):
+ if resource.is_folder():
+ return False
+ if self.python_matcher is None:
+ return resource.name.endswith('.py')
+ return self.python_matcher.does_match(resource)
+
+ def get_module(self, name, folder=None):
+ """Returns a `PyObject` if the module was found."""
+ module = self.find_module(name, folder)
+ if module is None:
+ module = self._builtin_module(name)
+ if module is None:
+ raise ModuleNotFoundError('Module %s not found' % name)
+ return module
+ return self.resource_to_pyobject(module)
+
+ def _builtin_submodules(self, modname):
+ result = {}
+ for extension in self.extension_modules:
+ if extension.startswith(modname + '.'):
+ name = extension[len(modname) + 1:]
+ if '.' not in name:
+ result[name] = self._builtin_module(extension)
+ return result
+
+ def _builtin_module(self, name):
+ return self.extension_cache.get_pymodule(name)
+
+ def get_relative_module(self, name, folder, level):
+ module = self.find_relative_module(name, folder, level)
+ if module is None:
+ raise ModuleNotFoundError('Module %s not found' % name)
+ return self.resource_to_pyobject(module)
+
+ def get_string_module(self, code, resource=None, force_errors=False):
+ """Returns a `PyObject` object for the given code
+
+ If `force_errors` is `True`, `exceptions.ModuleSyntaxError` is
+ raised if module has syntax errors. This overrides
+ ``ignore_syntax_errors`` project config.
+
+ """
+ return PyModule(self, code, resource, force_errors=force_errors)
+
+ def get_string_scope(self, code, resource=None):
+ """Returns a `Scope` object for the given code"""
+ return self.get_string_module(code, resource).get_scope()
+
+ def _invalidate_resource_cache(self, resource, new_resource=None):
+ for observer in self.cache_observers:
+ observer(resource)
+
+ def _find_module_in_folder(self, folder, modname):
+ module = folder
+ packages = modname.split('.')
+ for pkg in packages[:-1]:
+ if module.is_folder() and module.has_child(pkg):
+ module = module.get_child(pkg)
+ else:
+ return None
+ if module.is_folder():
+ if module.has_child(packages[-1]) and \
+ module.get_child(packages[-1]).is_folder():
+ return module.get_child(packages[-1])
+ elif module.has_child(packages[-1] + '.py') and \
+ not module.get_child(packages[-1] + '.py').is_folder():
+ return module.get_child(packages[-1] + '.py')
+
+ def get_python_path_folders(self):
+ import rope.base.project
+ result = []
+ for src in self.project.prefs.get('python_path', []) + sys.path:
+ try:
+ src_folder = rope.base.project.get_no_project().get_resource(src)
+ result.append(src_folder)
+ except rope.base.exceptions.ResourceNotFoundError:
+ pass
+ return result
+
+ def find_module(self, modname, folder=None):
+ """Returns a resource corresponding to the given module
+
+ returns None if it can not be found
+ """
+ return self._find_module(modname, folder)
+
+ def find_relative_module(self, modname, folder, level):
+ for i in range(level - 1):
+ folder = folder.parent
+ if modname == '':
+ return folder
+ else:
+ return self._find_module_in_folder(folder, modname)
+
+ def _find_module(self, modname, folder=None):
+ """Return `modname` module resource"""
+ for src in self.get_source_folders():
+ module = self._find_module_in_folder(src, modname)
+ if module is not None:
+ return module
+ for src in self.get_python_path_folders():
+ module = self._find_module_in_folder(src, modname)
+ if module is not None:
+ return module
+ if folder is not None:
+ module = self._find_module_in_folder(folder, modname)
+ if module is not None:
+ return module
+ return None
+
+ # INFO: It was decided not to cache source folders, since:
+ # - Does not take much time when the root folder contains
+ # packages, that is most of the time
+ # - We need a separate resource observer; `self.observer`
+ # does not get notified about module and folder creations
+ def get_source_folders(self):
+ """Returns project source folders"""
+ if self.project.root is None:
+ return []
+ result = list(self._custom_source_folders)
+ result.extend(self._find_source_folders(self.project.root))
+ return result
+
+ def resource_to_pyobject(self, resource, force_errors=False):
+ return self.module_cache.get_pymodule(resource, force_errors)
+
+ def get_python_files(self):
+ """Returns all python files available in the project"""
+ return [resource for resource in self.project.get_files()
+ if self.is_python_file(resource)]
+
+ def _is_package(self, folder):
+ if folder.has_child('__init__.py') and \
+ not folder.get_child('__init__.py').is_folder():
+ return True
+ else:
+ return False
+
+ def _find_source_folders(self, folder):
+ for resource in folder.get_folders():
+ if self._is_package(resource):
+ return [folder]
+ result = []
+ for resource in folder.get_files():
+ if resource.name.endswith('.py'):
+ result.append(folder)
+ break
+ for resource in folder.get_folders():
+ result.extend(self._find_source_folders(resource))
+ return result
+
+ def run_module(self, resource, args=None, stdin=None, stdout=None):
+ """Run `resource` module
+
+ Returns a `rope.base.oi.doa.PythonFileRunner` object for
+ controlling the process.
+
+ """
+ perform_doa = self.project.prefs.get('perform_doi', True)
+ perform_doa = self.project.prefs.get('perform_doa', perform_doa)
+ receiver = self.object_info.doa_data_received
+ if not perform_doa:
+ receiver = None
+ runner = rope.base.oi.doa.PythonFileRunner(
+ self, resource, args, stdin, stdout, receiver)
+ runner.add_finishing_observer(self.module_cache.forget_all_data)
+ runner.run()
+ return runner
+
+ def analyze_module(self, resource, should_analyze=lambda py: True,
+ search_subscopes=lambda py: True, followed_calls=None):
+ """Analyze `resource` module for static object inference
+
+ This function forces rope to analyze this module to collect
+ information about function calls. `should_analyze` is a
+ function that is called with a `PyDefinedObject` argument. If
+ it returns `True` the element is analyzed. If it is `None` or
+ returns `False` the element is not analyzed.
+
+ `search_subscopes` is like `should_analyze`; The difference is
+ that if it returns `False` the sub-scopes are all ignored.
+ That is it is assumed that `should_analyze` returns `False`
+ for all of its subscopes.
+
+ `followed_calls` override the value of ``soa_followed_calls``
+ project config.
+ """
+ if followed_calls is None:
+ followed_calls = self.project.prefs.get('soa_followed_calls', 0)
+ pymodule = self.resource_to_pyobject(resource)
+ self.module_cache.forget_all_data()
+ rope.base.oi.soa.analyze_module(
+ self, pymodule, should_analyze, search_subscopes, followed_calls)
+
+ def get_classes(self, task_handle=taskhandle.NullTaskHandle()):
+ warnings.warn('`PyCore.get_classes()` is deprecated',
+ DeprecationWarning, stacklevel=2)
+ return []
+
+ def __str__(self):
+ return str(self.module_cache) + str(self.object_info)
+
+ def modname(self, resource):
+ if resource.is_folder():
+ module_name = resource.name
+ source_folder = resource.parent
+ elif resource.name == '__init__.py':
+ module_name = resource.parent.name
+ source_folder = resource.parent.parent
+ else:
+ module_name = resource.name[:-3]
+ source_folder = resource.parent
+
+ while source_folder != source_folder.parent and \
+ source_folder.has_child('__init__.py'):
+ module_name = source_folder.name + '.' + module_name
+ source_folder = source_folder.parent
+ return module_name
+
+ @property
+ @utils.cacheit
+ def extension_modules(self):
+ result = set(self.project.prefs.get('extension_modules', []))
+ if self.project.prefs.get('import_dynload_stdmods', False):
+ result.update(stdmods.dynload_modules())
+ return result
+
+
+class _ModuleCache(object):
+
+ def __init__(self, pycore):
+ self.pycore = pycore
+ self.module_map = {}
+ self.pycore.cache_observers.append(self._invalidate_resource)
+ self.observer = self.pycore.observer
+
+ def _invalidate_resource(self, resource):
+ if resource in self.module_map:
+ self.forget_all_data()
+ self.observer.remove_resource(resource)
+ del self.module_map[resource]
+
+ def get_pymodule(self, resource, force_errors=False):
+ if resource in self.module_map:
+ return self.module_map[resource]
+ if resource.is_folder():
+ result = PyPackage(self.pycore, resource,
+ force_errors=force_errors)
+ else:
+ result = PyModule(self.pycore, resource=resource,
+ force_errors=force_errors)
+ self.module_map[resource] = result
+ self.observer.add_resource(resource)
+ return result
+
+ def forget_all_data(self):
+ for pymodule in self.module_map.values():
+ pymodule._forget_concluded_data()
+
+ def __str__(self):
+ return 'PyCore caches %d PyModules\n' % len(self.module_map)
+
+
+class _ExtensionCache(object):
+
+ def __init__(self, pycore):
+ self.pycore = pycore
+ self.extensions = {}
+
+ def get_pymodule(self, name):
+ if name == '__builtin__':
+ return builtins.builtins
+ allowed = self.pycore.extension_modules
+ if name not in self.extensions and name in allowed:
+ self.extensions[name] = builtins.BuiltinModule(name, self.pycore)
+ return self.extensions.get(name)
+
+
+def perform_soa_on_changed_scopes(project, resource, old_contents):
+ pycore = project.pycore
+ if resource.exists() and pycore.is_python_file(resource):
+ try:
+ new_contents = resource.read()
+ # detecting changes in new_contents relative to old_contents
+ detector = _TextChangeDetector(new_contents, old_contents)
+ def search_subscopes(pydefined):
+ scope = pydefined.get_scope()
+ return detector.is_changed(scope.get_start(), scope.get_end())
+ def should_analyze(pydefined):
+ scope = pydefined.get_scope()
+ start = scope.get_start()
+ end = scope.get_end()
+ return detector.consume_changes(start, end)
+ pycore.analyze_module(resource, should_analyze, search_subscopes)
+ except exceptions.ModuleSyntaxError:
+ pass
+
+
+class _TextChangeDetector(object):
+
+ def __init__(self, old, new):
+ self.old = old
+ self.new = new
+ self._set_diffs()
+
+ def _set_diffs(self):
+ differ = difflib.Differ()
+ self.lines = []
+ lineno = 0
+ for line in differ.compare(self.old.splitlines(True),
+ self.new.splitlines(True)):
+ if line.startswith(' '):
+ lineno += 1
+ elif line.startswith('-'):
+ lineno += 1
+ self.lines.append(lineno)
+
+ def is_changed(self, start, end):
+ """Tell whether any of start till end lines have changed
+
+ The end points are inclusive and indices start from 1.
+ """
+ left, right = self._get_changed(start, end)
+ if left < right:
+ return True
+ return False
+
+ def consume_changes(self, start, end):
+ """Clear the changed status of lines from start till end"""
+ left, right = self._get_changed(start, end)
+ if left < right:
+ del self.lines[left:right]
+ return left < right
+
+ def _get_changed(self, start, end):
+ left = bisect.bisect_left(self.lines, start)
+ right = bisect.bisect_right(self.lines, end)
+ return left, right
diff --git a/vim/eclim/autoload/eclim/python/rope/base/pynames.py b/vim/eclim/autoload/eclim/python/rope/base/pynames.py
@@ -0,0 +1,199 @@
+import rope.base.pyobjects
+from rope.base import exceptions, utils
+
+
+class PyName(object):
+ """References to `PyObject`\s inside python programs"""
+
+ def get_object(self):
+ """Return the `PyObject` object referenced by this `PyName`"""
+
+ def get_definition_location(self):
+ """Return a (module, lineno) tuple"""
+
+
+class DefinedName(PyName):
+
+ def __init__(self, pyobject):
+ self.pyobject = pyobject
+
+ def get_object(self):
+ return self.pyobject
+
+ def get_definition_location(self):
+ return (self.pyobject.get_module(), self.pyobject.get_ast().lineno)
+
+
+class AssignedName(PyName):
+ """Only a placeholder"""
+
+
+class UnboundName(PyName):
+
+ def __init__(self, pyobject=None):
+ self.pyobject = pyobject
+ if self.pyobject is None:
+ self.pyobject = rope.base.pyobjects.get_unknown()
+
+ def get_object(self):
+ return self.pyobject
+
+ def get_definition_location(self):
+ return (None, None)
+
+
+class AssignmentValue(object):
+ """An assigned expression"""
+
+ def __init__(self, ast_node, levels=None, evaluation='',
+ assign_type=False):
+ """The `level` is `None` for simple assignments and is
+ a list of numbers for tuple assignments for example in::
+
+ a, (b, c) = x
+
+ The levels for for `a` is ``[0]``, for `b` is ``[1, 0]`` and for
+ `c` is ``[1, 1]``.
+
+ """
+ self.ast_node = ast_node
+ if levels == None:
+ self.levels = []
+ else:
+ self.levels = levels
+ self.evaluation = evaluation
+ self.assign_type = assign_type
+
+ def get_lineno(self):
+ return self.ast_node.lineno
+
+
+class EvaluatedName(PyName):
+ """A name whose object will be evaluated later"""
+
+ def __init__(self, callback, module=None, lineno=None):
+ self.module = module
+ self.lineno = lineno
+ self.callback = callback
+ self.pyobject = _Inferred(callback, _get_concluded_data(module))
+
+ def get_object(self):
+ return self.pyobject.get()
+
+ def get_definition_location(self):
+ return (self.module, self.lineno)
+
+ def invalidate(self):
+ """Forget the `PyObject` this `PyName` holds"""
+ self.pyobject.set(None)
+
+
+class ParameterName(PyName):
+ """Only a placeholder"""
+
+
+class ImportedModule(PyName):
+
+ def __init__(self, importing_module, module_name=None,
+ level=0, resource=None):
+ self.importing_module = importing_module
+ self.module_name = module_name
+ self.level = level
+ self.resource = resource
+ self.pymodule = _get_concluded_data(self.importing_module)
+
+ def _current_folder(self):
+ resource = self.importing_module.get_module().get_resource()
+ if resource is None:
+ return None
+ return resource.parent
+
+ def _get_pymodule(self):
+ if self.pymodule.get() is None:
+ pycore = self.importing_module.pycore
+ if self.resource is not None:
+ self.pymodule.set(pycore.resource_to_pyobject(self.resource))
+ elif self.module_name is not None:
+ try:
+ if self.level == 0:
+ pymodule = pycore.get_module(self.module_name,
+ self._current_folder())
+ else:
+ pymodule = pycore.get_relative_module(
+ self.module_name, self._current_folder(), self.level)
+ self.pymodule.set(pymodule)
+ except exceptions.ModuleNotFoundError:
+ pass
+ return self.pymodule.get()
+
+ def get_object(self):
+ if self._get_pymodule() is None:
+ return rope.base.pyobjects.get_unknown()
+ return self._get_pymodule()
+
+ def get_definition_location(self):
+ pymodule = self._get_pymodule()
+ if not isinstance(pymodule, rope.base.pyobjects.PyDefinedObject):
+ return (None, None)
+ return (pymodule.get_module(), 1)
+
+
+class ImportedName(PyName):
+
+ def __init__(self, imported_module, imported_name):
+ self.imported_module = imported_module
+ self.imported_name = imported_name
+
+ def _get_imported_pyname(self):
+ try:
+ result = self.imported_module.get_object()[self.imported_name]
+ if result != self:
+ return result
+ except exceptions.AttributeNotFoundError:
+ pass
+ return UnboundName()
+
+ @utils.prevent_recursion(rope.base.pyobjects.get_unknown)
+ def get_object(self):
+ return self._get_imported_pyname().get_object()
+
+ @utils.prevent_recursion(lambda: (None, None))
+ def get_definition_location(self):
+ return self._get_imported_pyname().get_definition_location()
+
+
+def _get_concluded_data(module):
+ if module is None:
+ return rope.base.pyobjects._ConcludedData()
+ return module._get_concluded_data()
+
+
+def _circular_inference():
+ raise rope.base.pyobjects.IsBeingInferredError(
+ 'Circular Object Inference')
+
+class _Inferred(object):
+
+ def __init__(self, get_inferred, concluded=None):
+ self.get_inferred = get_inferred
+ self.concluded = concluded
+ if self.concluded is None:
+ self.temp = None
+
+ @utils.prevent_recursion(_circular_inference)
+ def get(self, *args, **kwds):
+ if self.concluded is None or self.concluded.get() is None:
+ self.set(self.get_inferred(*args, **kwds))
+ if self._get() is None:
+ self.set(rope.base.pyobjects.get_unknown())
+ return self._get()
+
+ def set(self, pyobject):
+ if self.concluded is not None:
+ self.concluded.set(pyobject)
+ self.temp = pyobject
+
+ def _get(self):
+ if self.concluded is not None:
+ return self.concluded.get()
+ return self.temp
diff --git a/vim/eclim/autoload/eclim/python/rope/base/pynamesdef.py b/vim/eclim/autoload/eclim/python/rope/base/pynamesdef.py
@@ -0,0 +1,55 @@
+import rope.base.oi.soi
+from rope.base import pynames
+from rope.base.pynames import *
+
+
+class AssignedName(pynames.AssignedName):
+
+ def __init__(self, lineno=None, module=None, pyobject=None):
+ self.lineno = lineno
+ self.module = module
+ self.assignments = []
+ self.pyobject = _Inferred(self._get_inferred,
+ pynames._get_concluded_data(module))
+ self.pyobject.set(pyobject)
+
+ @utils.prevent_recursion(lambda: None)
+ def _get_inferred(self):
+ if self.module is not None:
+ return rope.base.oi.soi.infer_assigned_object(self)
+
+ def get_object(self):
+ return self.pyobject.get()
+
+ def get_definition_location(self):
+ """Returns a (module, lineno) tuple"""
+ if self.lineno is None and self.assignments:
+ self.lineno = self.assignments[0].get_lineno()
+ return (self.module, self.lineno)
+
+ def invalidate(self):
+ """Forget the `PyObject` this `PyName` holds"""
+ self.pyobject.set(None)
+
+
+class ParameterName(pynames.ParameterName):
+
+ def __init__(self, pyfunction, index):
+ self.pyfunction = pyfunction
+ self.index = index
+
+ def get_object(self):
+ result = self.pyfunction.get_parameter(self.index)
+ if result is None:
+ result = rope.base.pyobjects.get_unknown()
+ return result
+
+ def get_objects(self):
+ """Returns the list of objects passed as this parameter"""
+ return rope.base.oi.soi.get_passed_objects(
+ self.pyfunction, self.index)
+
+ def get_definition_location(self):
+ return (self.pyfunction.get_module(), self.pyfunction.get_ast().lineno)
+
+_Inferred = pynames._Inferred
diff --git a/vim/eclim/autoload/eclim/python/rope/base/pyobjects.py b/vim/eclim/autoload/eclim/python/rope/base/pyobjects.py
@@ -0,0 +1,311 @@
+from rope.base.fscommands import _decode_data
+from rope.base import ast, exceptions, utils
+
+
+class PyObject(object):
+
+ def __init__(self, type_):
+ if type_ is None:
+ type_ = self
+ self.type = type_
+
+ def get_attributes(self):
+ if self.type is self:
+ return {}
+ return self.type.get_attributes()
+
+ def get_attribute(self, name):
+ if name not in self.get_attributes():
+ raise exceptions.AttributeNotFoundError(
+ 'Attribute %s not found' % name)
+ return self.get_attributes()[name]
+
+ def get_type(self):
+ return self.type
+
+ def __getitem__(self, key):
+ """The same as ``get_attribute(key)``"""
+ return self.get_attribute(key)
+
+ def __contains__(self, key):
+ """The same as ``key in self.get_attributes()``"""
+ return key in self.get_attributes()
+
+ def __eq__(self, obj):
+ """Check the equality of two `PyObject`\s
+
+ Currently it is assumed that instances (the direct instances
+ of `PyObject`, not the instances of its subclasses) are equal
+ if their types are equal. For every other object like
+ defineds or builtins rope assumes objects are reference
+ objects and their identities should match.
+
+ """
+ if self.__class__ != obj.__class__:
+ return False
+ if type(self) == PyObject:
+ if self is not self.type:
+ return self.type == obj.type
+ else:
+ return self.type is obj.type
+ return self is obj
+
+ def __ne__(self, obj):
+ return not self.__eq__(obj)
+
+ def __hash__(self):
+ """See docs for `__eq__()` method"""
+ if type(self) == PyObject and self != self.type:
+ return hash(self.type) + 1
+ else:
+ return super(PyObject, self).__hash__()
+
+ def __iter__(self):
+ """The same as ``iter(self.get_attributes())``"""
+ return iter(self.get_attributes())
+
+ _types = None
+ _unknown = None
+
+ @staticmethod
+ def _get_base_type(name):
+ if PyObject._types is None:
+ PyObject._types = {}
+ base_type = PyObject(None)
+ PyObject._types['Type'] = base_type
+ PyObject._types['Module'] = PyObject(base_type)
+ PyObject._types['Function'] = PyObject(base_type)
+ PyObject._types['Unknown'] = PyObject(base_type)
+ return PyObject._types[name]
+
+
+def get_base_type(name):
+ """Return the base type with name `name`.
+
+ The base types are 'Type', 'Function', 'Module' and 'Unknown'. It
+ was used to check the type of a `PyObject` but currently its use
+ is discouraged. Use classes defined in this module instead.
+ For example instead of
+ ``pyobject.get_type() == get_base_type('Function')`` use
+ ``isinstance(pyobject, AbstractFunction)``.
+
+ You can use `AbstractClass` for classes, `AbstractFunction` for
+ functions, and `AbstractModule` for modules. You can also use
+ `PyFunction` and `PyClass` for testing if an object is
+ defined somewhere and rope can access its source. These classes
+ provide more methods.
+
+ """
+ return PyObject._get_base_type(name)
+
+
+def get_unknown():
+ """Return a pyobject whose type is unknown
+
+ Note that two unknown objects are equal. So for example you can
+ write::
+
+ if pyname.get_object() == get_unknown():
+ print 'cannot determine what this pyname holds'
+
+ Rope could have used `None` for indicating unknown objects but
+ we had to check that in many places. So actually this method
+ returns a null object.
+
+ """
+ if PyObject._unknown is None:
+ PyObject._unknown = PyObject(get_base_type('Unknown'))
+ return PyObject._unknown
+
+
+class AbstractClass(PyObject):
+
+ def __init__(self):
+ super(AbstractClass, self).__init__(get_base_type('Type'))
+
+ def get_name(self):
+ pass
+
+ def get_doc(self):
+ pass
+
+ def get_superclasses(self):
+ return []
+
+
+class AbstractFunction(PyObject):
+
+ def __init__(self):
+ super(AbstractFunction, self).__init__(get_base_type('Function'))
+
+ def get_name(self):
+ pass
+
+ def get_doc(self):
+ pass
+
+ def get_param_names(self, special_args=True):
+ return []
+
+ def get_returned_object(self, args):
+ return get_unknown()
+
+
+class AbstractModule(PyObject):
+
+ def __init__(self, doc=None):
+ super(AbstractModule, self).__init__(get_base_type('Module'))
+
+ def get_doc(self):
+ pass
+
+ def get_resource(self):
+ pass
+
+
+class PyDefinedObject(object):
+ """Python defined names that rope can access their sources"""
+
+ def __init__(self, pycore, ast_node, parent):
+ self.pycore = pycore
+ self.ast_node = ast_node
+ self.scope = None
+ self.parent = parent
+ self.structural_attributes = None
+ self.concluded_attributes = self.get_module()._get_concluded_data()
+ self.attributes = self.get_module()._get_concluded_data()
+ self.defineds = None
+
+ visitor_class = None
+
+ @utils.prevent_recursion(lambda: {})
+ def _get_structural_attributes(self):
+ if self.structural_attributes is None:
+ self.structural_attributes = self._create_structural_attributes()
+ return self.structural_attributes
+
+ @utils.prevent_recursion(lambda: {})
+ def _get_concluded_attributes(self):
+ if self.concluded_attributes.get() is None:
+ self._get_structural_attributes()
+ self.concluded_attributes.set(self._create_concluded_attributes())
+ return self.concluded_attributes.get()
+
+ def get_attributes(self):
+ if self.attributes.get() is None:
+ result = dict(self._get_concluded_attributes())
+ result.update(self._get_structural_attributes())
+ self.attributes.set(result)
+ return self.attributes.get()
+
+ def get_attribute(self, name):
+ if name in self._get_structural_attributes():
+ return self._get_structural_attributes()[name]
+ if name in self._get_concluded_attributes():
+ return self._get_concluded_attributes()[name]
+ raise exceptions.AttributeNotFoundError('Attribute %s not found' %
+ name)
+
+ def get_scope(self):
+ if self.scope is None:
+ self.scope = self._create_scope()
+ return self.scope
+
+ def get_module(self):
+ current_object = self
+ while current_object.parent is not None:
+ current_object = current_object.parent
+ return current_object
+
+ def get_doc(self):
+ if len(self.get_ast().body) > 0:
+ expr = self.get_ast().body[0]
+ if isinstance(expr, ast.Expr) and \
+ isinstance(expr.value, ast.Str):
+ docstring = expr.value.s
+ coding = self.get_module().coding
+ return _decode_data(docstring, coding)
+
+ def _get_defined_objects(self):
+ if self.defineds is None:
+ self._get_structural_attributes()
+ return self.defineds
+
+ def _create_structural_attributes(self):
+ if self.visitor_class is None:
+ return {}
+ new_visitor = self.visitor_class(self.pycore, self)
+ for child in ast.get_child_nodes(self.ast_node):
+ ast.walk(child, new_visitor)
+ self.defineds = new_visitor.defineds
+ return new_visitor.names
+
+ def _create_concluded_attributes(self):
+ return {}
+
+ def get_ast(self):
+ return self.ast_node
+
+ def _create_scope(self):
+ pass
+
+
+class PyFunction(PyDefinedObject, AbstractFunction):
+ """Only a placeholder"""
+
+
+class PyClass(PyDefinedObject, AbstractClass):
+ """Only a placeholder"""
+
+
+class _ConcludedData(object):
+
+ def __init__(self):
+ self.data_ = None
+
+ def set(self, data):
+ self.data_ = data
+
+ def get(self):
+ return self.data_
+
+ data = property(get, set)
+
+ def _invalidate(self):
+ self.data = None
+
+ def __str__(self):
+ return '<' + str(self.data) + '>'
+
+
+class _PyModule(PyDefinedObject, AbstractModule):
+
+ def __init__(self, pycore, ast_node, resource):
+ self.resource = resource
+ self.concluded_data = []
+ AbstractModule.__init__(self)
+ PyDefinedObject.__init__(self, pycore, ast_node, None)
+
+ def _get_concluded_data(self):
+ new_data = _ConcludedData()
+ self.concluded_data.append(new_data)
+ return new_data
+
+ def _forget_concluded_data(self):
+ for data in self.concluded_data:
+ data._invalidate()
+
+ def get_resource(self):
+ return self.resource
+
+
+class PyModule(_PyModule):
+ """Only a placeholder"""
+
+
+class PyPackage(_PyModule):
+ """Only a placeholder"""
+
+
+class IsBeingInferredError(exceptions.RopeError):
+ pass
diff --git a/vim/eclim/autoload/eclim/python/rope/base/pyobjectsdef.py b/vim/eclim/autoload/eclim/python/rope/base/pyobjectsdef.py
@@ -0,0 +1,535 @@
+import rope.base.codeanalyze
+import rope.base.evaluate
+import rope.base.builtins
+import rope.base.oi.soi
+import rope.base.pyscopes
+from rope.base import (pynamesdef as pynames, exceptions, ast,
+ astutils, pyobjects, fscommands, arguments, utils)
+from rope.base.pyobjects import *
+
+
+class PyFunction(pyobjects.PyFunction):
+
+ def __init__(self, pycore, ast_node, parent):
+ AbstractFunction.__init__(self)
+ PyDefinedObject.__init__(self, pycore, ast_node, parent)
+ self.arguments = self.ast_node.args
+ self.parameter_pyobjects = pynames._Inferred(
+ self._infer_parameters, self.get_module()._get_concluded_data())
+ self.returned = pynames._Inferred(self._infer_returned)
+ self.parameter_pynames = None
+
+ def _create_structural_attributes(self):
+ return {}
+
+ def _create_concluded_attributes(self):
+ return {}
+
+ def _create_scope(self):
+ return rope.base.pyscopes.FunctionScope(self.pycore, self,
+ _FunctionVisitor)
+
+ def _infer_parameters(self):
+ pyobjects = rope.base.oi.soi.infer_parameter_objects(self)
+ self._handle_special_args(pyobjects)
+ return pyobjects
+
+ def _infer_returned(self, args=None):
+ return rope.base.oi.soi.infer_returned_object(self, args)
+
+ def _handle_special_args(self, pyobjects):
+ if len(pyobjects) == len(self.arguments.args):
+ if self.arguments.vararg:
+ pyobjects.append(rope.base.builtins.get_list())
+ if self.arguments.kwarg:
+ pyobjects.append(rope.base.builtins.get_dict())
+
+ def _set_parameter_pyobjects(self, pyobjects):
+ if pyobjects is not None:
+ self._handle_special_args(pyobjects)
+ self.parameter_pyobjects.set(pyobjects)
+
+ def get_parameters(self):
+ if self.parameter_pynames is None:
+ result = {}
+ for index, name in enumerate(self.get_param_names()):
+ # TODO: handle tuple parameters
+ result[name] = pynames.ParameterName(self, index)
+ self.parameter_pynames = result
+ return self.parameter_pynames
+
+ def get_parameter(self, index):
+ if index < len(self.parameter_pyobjects.get()):
+ return self.parameter_pyobjects.get()[index]
+
+ def get_returned_object(self, args):
+ return self.returned.get(args)
+
+ def get_name(self):
+ return self.get_ast().name
+
+ def get_param_names(self, special_args=True):
+ # TODO: handle tuple parameters
+ result = [node.id for node in self.arguments.args
+ if isinstance(node, ast.Name)]
+ if special_args:
+ if self.arguments.vararg:
+ result.append(self.arguments.vararg)
+ if self.arguments.kwarg:
+ result.append(self.arguments.kwarg)
+ return result
+
+ def get_kind(self):
+ """Get function type
+
+ It returns one of 'function', 'method', 'staticmethod' or
+ 'classmethod' strs.
+
+ """
+ scope = self.parent.get_scope()
+ if isinstance(self.parent, PyClass):
+ for decorator in self.decorators:
+ pyname = rope.base.evaluate.eval_node(scope, decorator)
+ if pyname == rope.base.builtins.builtins['staticmethod']:
+ return 'staticmethod'
+ if pyname == rope.base.builtins.builtins['classmethod']:
+ return 'classmethod'
+ return 'method'
+ return 'function'
+
+ @property
+ def decorators(self):
+ try:
+ return getattr(self.ast_node, 'decorator_list')
+ except AttributeError:
+ return getattr(self.ast_node, 'decorators', None)
+
+
+class PyClass(pyobjects.PyClass):
+
+ def __init__(self, pycore, ast_node, parent):
+ self.visitor_class = _ClassVisitor
+ AbstractClass.__init__(self)
+ PyDefinedObject.__init__(self, pycore, ast_node, parent)
+ self.parent = parent
+ self._superclasses = self.get_module()._get_concluded_data()
+
+ def get_superclasses(self):
+ if self._superclasses.get() is None:
+ self._superclasses.set(self._get_bases())
+ return self._superclasses.get()
+
+ def get_name(self):
+ return self.get_ast().name
+
+ def _create_concluded_attributes(self):
+ result = {}
+ for base in reversed(self.get_superclasses()):
+ result.update(base.get_attributes())
+ return result
+
+ def _get_bases(self):
+ result = []
+ for base_name in self.ast_node.bases:
+ base = rope.base.evaluate.eval_node(self.parent.get_scope(),
+ base_name)
+ if base is not None and \
+ base.get_object().get_type() == get_base_type('Type'):
+ result.append(base.get_object())
+ return result
+
+ def _create_scope(self):
+ return rope.base.pyscopes.ClassScope(self.pycore, self)
+
+
+class PyModule(pyobjects.PyModule):
+
+ def __init__(self, pycore, source=None,
+ resource=None, force_errors=False):
+ ignore = pycore.project.prefs.get('ignore_syntax_errors', False)
+ syntax_errors = force_errors or not ignore
+ try:
+ source, node = self._init_source(pycore, source, resource)
+ except exceptions.ModuleSyntaxError:
+ if syntax_errors:
+ raise
+ else:
+ source = '\n'
+ node = ast.parse('\n')
+ self.source_code = source
+ self.star_imports = []
+ self.visitor_class = _GlobalVisitor
+ self.coding = fscommands.read_str_coding(self.source_code)
+ super(PyModule, self).__init__(pycore, node, resource)
+
+ def _init_source(self, pycore, source_code, resource):
+ filename = 'string'
+ if resource:
+ filename = resource.path
+ try:
+ if source_code is None:
+ source_bytes = resource.read_bytes()
+ source_code = fscommands.file_data_to_unicode(source_bytes)
+ else:
+ if isinstance(source_code, unicode):
+ source_bytes = fscommands.unicode_to_file_data(source_code)
+ else:
+ source_bytes = source_code
+ ast_node = ast.parse(source_bytes, filename=filename)
+ except SyntaxError, e:
+ raise exceptions.ModuleSyntaxError(filename, e.lineno, e.msg)
+ except UnicodeDecodeError, e:
+ raise exceptions.ModuleSyntaxError(filename, 1, '%s' % (e.reason))
+ return source_code, ast_node
+
+ @utils.prevent_recursion(lambda: {})
+ def _create_concluded_attributes(self):
+ result = {}
+ for star_import in self.star_imports:
+ result.update(star_import.get_names())
+ return result
+
+ def _create_scope(self):
+ return rope.base.pyscopes.GlobalScope(self.pycore, self)
+
+ @property
+ @utils.saveit
+ def lines(self):
+ """A `SourceLinesAdapter`"""
+ return rope.base.codeanalyze.SourceLinesAdapter(self.source_code)
+
+ @property
+ @utils.saveit
+ def logical_lines(self):
+ """A `LogicalLinesFinder`"""
+ return rope.base.codeanalyze.CachingLogicalLineFinder(self.lines)
+
+
+class PyPackage(pyobjects.PyPackage):
+
+ def __init__(self, pycore, resource=None, force_errors=False):
+ self.resource = resource
+ init_dot_py = self._get_init_dot_py()
+ if init_dot_py is not None:
+ ast_node = pycore.resource_to_pyobject(
+ init_dot_py, force_errors=force_errors).get_ast()
+ else:
+ ast_node = ast.parse('\n')
+ super(PyPackage, self).__init__(pycore, ast_node, resource)
+
+ def _create_structural_attributes(self):
+ result = {}
+ modname = self.pycore.modname(self.resource)
+ extension_submodules = self.pycore._builtin_submodules(modname)
+ for name, module in extension_submodules.iteritems():
+ result[name] = rope.base.builtins.BuiltinName(module)
+ if self.resource is None:
+ return result
+ for name, resource in self._get_child_resources().items():
+ result[name] = pynames.ImportedModule(self, resource=resource)
+ return result
+
+ def _create_concluded_attributes(self):
+ result = {}
+ init_dot_py = self._get_init_dot_py()
+ if init_dot_py:
+ init_object = self.pycore.resource_to_pyobject(init_dot_py)
+ result.update(init_object.get_attributes())
+ return result
+
+ def _get_child_resources(self):
+ result = {}
+ for child in self.resource.get_children():
+ if child.is_folder():
+ result[child.name] = child
+ elif child.name.endswith('.py') and \
+ child.name != '__init__.py':
+ name = child.name[:-3]
+ result[name] = child
+ return result
+
+ def _get_init_dot_py(self):
+ if self.resource is not None and self.resource.has_child('__init__.py'):
+ return self.resource.get_child('__init__.py')
+ else:
+ return None
+
+ def _create_scope(self):
+ return self.get_module().get_scope()
+
+ def get_module(self):
+ init_dot_py = self._get_init_dot_py()
+ if init_dot_py:
+ return self.pycore.resource_to_pyobject(init_dot_py)
+ return self
+
+
+class _AssignVisitor(object):
+
+ def __init__(self, scope_visitor):
+ self.scope_visitor = scope_visitor
+ self.assigned_ast = None
+
+ def _Assign(self, node):
+ self.assigned_ast = node.value
+ for child_node in node.targets:
+ ast.walk(child_node, self)
+
+ def _assigned(self, name, assignment=None):
+ self.scope_visitor._assigned(name, assignment)
+
+ def _Name(self, node):
+ assignment = None
+ if self.assigned_ast is not None:
+ assignment = pynames.AssignmentValue(self.assigned_ast)
+ self._assigned(node.id, assignment)
+
+ def _Tuple(self, node):
+ names = astutils.get_name_levels(node)
+ for name, levels in names:
+ assignment = None
+ if self.assigned_ast is not None:
+ assignment = pynames.AssignmentValue(self.assigned_ast, levels)
+ self._assigned(name, assignment)
+
+ def _Attribute(self, node):
+ pass
+
+ def _Subscript(self, node):
+ pass
+
+ def _Slice(self, node):
+ pass
+
+
+class _ScopeVisitor(object):
+
+ def __init__(self, pycore, owner_object):
+ self.pycore = pycore
+ self.owner_object = owner_object
+ self.names = {}
+ self.defineds = []
+
+ def get_module(self):
+ if self.owner_object is not None:
+ return self.owner_object.get_module()
+ else:
+ return None
+
+ def _ClassDef(self, node):
+ pyclass = PyClass(self.pycore, node, self.owner_object)
+ self.names[node.name] = pynames.DefinedName(pyclass)
+ self.defineds.append(pyclass)
+
+ def _FunctionDef(self, node):
+ pyfunction = PyFunction(self.pycore, node, self.owner_object)
+ for decorator in pyfunction.decorators:
+ if isinstance(decorator, ast.Name) and decorator.id == 'property':
+ if isinstance(self, _ClassVisitor):
+ type_ = rope.base.builtins.Property(pyfunction)
+ arg = pynames.UnboundName(PyObject(self.owner_object))
+ def _eval(type_=type_, arg=arg):
+ return type_.get_property_object(
+ arguments.ObjectArguments([arg]))
+ self.names[node.name] = pynames.EvaluatedName(
+ _eval, module=self.get_module(), lineno=node.lineno)
+ break
+ else:
+ self.names[node.name] = pynames.DefinedName(pyfunction)
+ self.defineds.append(pyfunction)
+
+ def _Assign(self, node):
+ ast.walk(node, _AssignVisitor(self))
+
+ def _AugAssign(self, node):
+ pass
+
+ def _For(self, node):
+ names = self._update_evaluated(node.target, node.iter,
+ '.__iter__().next()')
+ for child in node.body + node.orelse:
+ ast.walk(child, self)
+
+ def _assigned(self, name, assignment):
+ pyname = self.names.get(name, None)
+ if pyname is None:
+ pyname = pynames.AssignedName(module=self.get_module())
+ if isinstance(pyname, pynames.AssignedName):
+ if assignment is not None:
+ pyname.assignments.append(assignment)
+ self.names[name] = pyname
+
+ def _update_evaluated(self, targets, assigned,
+ evaluation= '', eval_type=False):
+ result = {}
+ names = astutils.get_name_levels(targets)
+ for name, levels in names:
+ assignment = pynames.AssignmentValue(assigned, levels,
+ evaluation, eval_type)
+ self._assigned(name, assignment)
+ return result
+
+ def _With(self, node):
+ if node.optional_vars:
+ self._update_evaluated(node.optional_vars,
+ node.context_expr, '.__enter__()')
+ for child in node.body:
+ ast.walk(child, self)
+
+ def _excepthandler(self, node):
+ if node.name is not None and isinstance(node.name, ast.Name):
+ type_node = node.type
+ if isinstance(node.type, ast.Tuple) and type_node.elts:
+ type_node = type_node.elts[0]
+ self._update_evaluated(node.name, type_node, eval_type=True)
+ for child in node.body:
+ ast.walk(child, self)
+
+ def _ExceptHandler(self, node):
+ self._excepthandler(node)
+
+ def _Import(self, node):
+ for import_pair in node.names:
+ module_name = import_pair.name
+ alias = import_pair.asname
+ first_package = module_name.split('.')[0]
+ if alias is not None:
+ imported = pynames.ImportedModule(self.get_module(),
+ module_name)
+ if not self._is_ignored_import(imported):
+ self.names[alias] = imported
+ else:
+ imported = pynames.ImportedModule(self.get_module(),
+ first_package)
+ if not self._is_ignored_import(imported):
+ self.names[first_package] = imported
+
+ def _ImportFrom(self, node):
+ level = 0
+ if node.level:
+ level = node.level
+ imported_module = pynames.ImportedModule(self.get_module(),
+ node.module, level)
+ if self._is_ignored_import(imported_module):
+ return
+ if len(node.names) == 1 and node.names[0].name == '*':
+ if isinstance(self.owner_object, PyModule):
+ self.owner_object.star_imports.append(
+ StarImport(imported_module))
+ else:
+ for imported_name in node.names:
+ imported = imported_name.name
+ alias = imported_name.asname
+ if alias is not None:
+ imported = alias
+ self.names[imported] = pynames.ImportedName(imported_module,
+ imported_name.name)
+
+ def _is_ignored_import(self, imported_module):
+ if not self.pycore.project.prefs.get('ignore_bad_imports', False):
+ return False
+ return not isinstance(imported_module.get_object(), AbstractModule)
+
+ def _Global(self, node):
+ module = self.get_module()
+ for name in node.names:
+ if module is not None:
+ try:
+ pyname = module[name]
+ except exceptions.AttributeNotFoundError:
+ pyname = pynames.AssignedName(node.lineno)
+ self.names[name] = pyname
+
+
+class _GlobalVisitor(_ScopeVisitor):
+
+ def __init__(self, pycore, owner_object):
+ super(_GlobalVisitor, self).__init__(pycore, owner_object)
+
+
+class _ClassVisitor(_ScopeVisitor):
+
+ def __init__(self, pycore, owner_object):
+ super(_ClassVisitor, self).__init__(pycore, owner_object)
+
+ def _FunctionDef(self, node):
+ _ScopeVisitor._FunctionDef(self, node)
+ if len(node.args.args) > 0:
+ first = node.args.args[0]
+ if isinstance(first, ast.Name):
+ new_visitor = _ClassInitVisitor(self, first.id)
+ for child in ast.get_child_nodes(node):
+ ast.walk(child, new_visitor)
+
+
+class _FunctionVisitor(_ScopeVisitor):
+
+ def __init__(self, pycore, owner_object):
+ super(_FunctionVisitor, self).__init__(pycore, owner_object)
+ self.returned_asts = []
+ self.generator = False
+
+ def _Return(self, node):
+ if node.value is not None:
+ self.returned_asts.append(node.value)
+
+ def _Yield(self, node):
+ if node.value is not None:
+ self.returned_asts.append(node.value)
+ self.generator = True
+
+
+class _ClassInitVisitor(_AssignVisitor):
+
+ def __init__(self, scope_visitor, self_name):
+ super(_ClassInitVisitor, self).__init__(scope_visitor)
+ self.self_name = self_name
+
+ def _Attribute(self, node):
+ if not isinstance(node.ctx, ast.Store):
+ return
+ if isinstance(node.value, ast.Name) and \
+ node.value.id == self.self_name:
+ if node.attr not in self.scope_visitor.names:
+ self.scope_visitor.names[node.attr] = pynames.AssignedName(
+ lineno=node.lineno, module=self.scope_visitor.get_module())
+ if self.assigned_ast is not None:
+ pyname = self.scope_visitor.names[node.attr]
+ if isinstance(pyname, pynames.AssignedName):
+ pyname.assignments.append(
+ pynames.AssignmentValue(self.assigned_ast))
+
+ def _Tuple(self, node):
+ if not isinstance(node.ctx, ast.Store):
+ return
+ for child in ast.get_child_nodes(node):
+ ast.walk(child, self)
+
+ def _Name(self, node):
+ pass
+
+ def _FunctionDef(self, node):
+ pass
+
+ def _ClassDef(self, node):
+ pass
+
+ def _For(self, node):
+ pass
+
+ def _With(self, node):
+ pass
+
+
+class StarImport(object):
+
+ def __init__(self, imported_module):
+ self.imported_module = imported_module
+
+ def get_names(self):
+ result = {}
+ imported = self.imported_module.get_object()
+ for name in imported:
+ if not name.startswith('_'):
+ result[name] = pynames.ImportedName(self.imported_module, name)
+ return result
diff --git a/vim/eclim/autoload/eclim/python/rope/base/pyscopes.py b/vim/eclim/autoload/eclim/python/rope/base/pyscopes.py
@@ -0,0 +1,313 @@
+import rope.base.builtins
+import rope.base.codeanalyze
+import rope.base.pynames
+from rope.base import ast, exceptions, utils
+
+
+class Scope(object):
+
+ def __init__(self, pycore, pyobject, parent_scope):
+ self.pycore = pycore
+ self.pyobject = pyobject
+ self.parent = parent_scope
+
+ def get_names(self):
+ """Return the names defined or imported in this scope"""
+ return self.pyobject.get_attributes()
+
+ def get_defined_names(self):
+ """Return the names defined in this scope"""
+ return self.pyobject._get_structural_attributes()
+
+ def get_name(self, name):
+ """Return name `PyName` defined in this scope"""
+ if name not in self.get_names():
+ raise exceptions.NameNotFoundError('name %s not found' % name)
+ return self.get_names()[name]
+
+ def __getitem__(self, key):
+ """The same as ``get_name(key)``"""
+ return self.get_name(key)
+
+ def __contains__(self, key):
+ """The same as ``key in self.get_names()``"""
+ return key in self.get_names()
+
+ @utils.saveit
+ def get_scopes(self):
+ """Return the subscopes of this scope
+
+ The returned scopes should be sorted by the order they appear.
+ """
+ return self._create_scopes()
+
+ def lookup(self, name):
+ if name in self.get_names():
+ return self.get_names()[name]
+ if self.parent is not None:
+ return self.parent._propagated_lookup(name)
+ return None
+
+ def get_propagated_names(self):
+ """Return the visible names of this scope
+
+ Return the names defined in this scope that are visible from
+ scopes containing this scope. This method returns the same
+ dictionary returned by `get_names()` except for `ClassScope`
+ which returns an empty dict.
+ """
+ return self.get_names()
+
+ def _propagated_lookup(self, name):
+ if name in self.get_propagated_names():
+ return self.get_propagated_names()[name]
+ if self.parent is not None:
+ return self.parent._propagated_lookup(name)
+ return None
+
+ def _create_scopes(self):
+ return [pydefined.get_scope()
+ for pydefined in self.pyobject._get_defined_objects()]
+
+ def _get_global_scope(self):
+ current = self
+ while current.parent is not None:
+ current = current.parent
+ return current
+
+ def get_start(self):
+ return self.pyobject.get_ast().lineno
+
+ def get_body_start(self):
+ body = self.pyobject.get_ast().body
+ if body:
+ return body[0].lineno
+ return self.get_start()
+
+ def get_end(self):
+ pymodule = self._get_global_scope().pyobject
+ return pymodule.logical_lines.logical_line_in(self.logical_end)[1]
+
+ @utils.saveit
+ def get_logical_end(self):
+ global_scope = self._get_global_scope()
+ return global_scope._scope_finder.find_scope_end(self)
+
+ start = property(get_start)
+ end = property(get_end)
+ logical_end = property(get_logical_end)
+
+ def get_kind(self):
+ pass
+
+
+class GlobalScope(Scope):
+
+ def __init__(self, pycore, module):
+ super(GlobalScope, self).__init__(pycore, module, None)
+ self.names = module._get_concluded_data()
+
+ def get_start(self):
+ return 1
+
+ def get_kind(self):
+ return 'Module'
+
+ def get_name(self, name):
+ try:
+ return self.pyobject[name]
+ except exceptions.AttributeNotFoundError:
+ if name in self.builtin_names:
+ return self.builtin_names[name]
+ raise exceptions.NameNotFoundError('name %s not found' % name)
+
+ def get_names(self):
+ if self.names.get() is None:
+ result = dict(self.builtin_names)
+ result.update(super(GlobalScope, self).get_names())
+ self.names.set(result)
+ return self.names.get()
+
+ def get_inner_scope_for_line(self, lineno, indents=None):
+ return self._scope_finder.get_holding_scope(self, lineno, indents)
+
+ def get_inner_scope_for_offset(self, offset):
+ return self._scope_finder.get_holding_scope_for_offset(self, offset)
+
+ @property
+ @utils.saveit
+ def _scope_finder(self):
+ return _HoldingScopeFinder(self.pyobject)
+
+ @property
+ def builtin_names(self):
+ return rope.base.builtins.builtins.get_attributes()
+
+
+class FunctionScope(Scope):
+
+ def __init__(self, pycore, pyobject, visitor):
+ super(FunctionScope, self).__init__(pycore, pyobject,
+ pyobject.parent.get_scope())
+ self.names = None
+ self.returned_asts = None
+ self.is_generator = None
+ self.defineds = None
+ self.visitor = visitor
+
+ def _get_names(self):
+ if self.names is None:
+ self._visit_function()
+ return self.names
+
+ def _visit_function(self):
+ if self.names is None:
+ new_visitor = self.visitor(self.pycore, self.pyobject)
+ for n in ast.get_child_nodes(self.pyobject.get_ast()):
+ ast.walk(n, new_visitor)
+ self.names = new_visitor.names
+ self.names.update(self.pyobject.get_parameters())
+ self.returned_asts = new_visitor.returned_asts
+ self.is_generator = new_visitor.generator
+ self.defineds = new_visitor.defineds
+
+ def _get_returned_asts(self):
+ if self.names is None:
+ self._visit_function()
+ return self.returned_asts
+
+ def _is_generator(self):
+ if self.is_generator is None:
+ self._get_returned_asts()
+ return self.is_generator
+
+ def get_names(self):
+ return self._get_names()
+
+ def _create_scopes(self):
+ if self.defineds is None:
+ self._visit_function()
+ return [pydefined.get_scope() for pydefined in self.defineds]
+
+ def get_kind(self):
+ return 'Function'
+
+ def invalidate_data(self):
+ for pyname in self.get_names().values():
+ if isinstance(pyname, (rope.base.pynames.AssignedName,
+ rope.base.pynames.EvaluatedName)):
+ pyname.invalidate()
+
+
+class ClassScope(Scope):
+
+ def __init__(self, pycore, pyobject):
+ super(ClassScope, self).__init__(pycore, pyobject,
+ pyobject.parent.get_scope())
+
+ def get_kind(self):
+ return 'Class'
+
+ def get_propagated_names(self):
+ return {}
+
+
+class _HoldingScopeFinder(object):
+
+ def __init__(self, pymodule):
+ self.pymodule = pymodule
+
+ def get_indents(self, lineno):
+ return rope.base.codeanalyze.count_line_indents(
+ self.lines.get_line(lineno))
+
+ def _get_scope_indents(self, scope):
+ return self.get_indents(scope.get_start())
+
+ def get_holding_scope(self, module_scope, lineno, line_indents=None):
+ if line_indents is None:
+ line_indents = self.get_indents(lineno)
+ current_scope = module_scope
+ new_scope = current_scope
+ while new_scope is not None and \
+ (new_scope.get_kind() == 'Module' or
+ self._get_scope_indents(new_scope) <= line_indents):
+ current_scope = new_scope
+ if current_scope.get_start() == lineno and \
+ current_scope.get_kind() != 'Module':
+ return current_scope
+ new_scope = None
+ for scope in current_scope.get_scopes():
+ if scope.get_start() <= lineno:
+ if lineno <= scope.get_end():
+ new_scope = scope
+ break
+ else:
+ break
+ return current_scope
+
+ def _is_empty_line(self, lineno):
+ line = self.lines.get_line(lineno)
+ return line.strip() == '' or line.lstrip().startswith('#')
+
+ def _get_body_indents(self, scope):
+ return self.get_indents(scope.get_body_start())
+
+ def get_holding_scope_for_offset(self, scope, offset):
+ return self.get_holding_scope(
+ scope, self.lines.get_line_number(offset))
+
+ def find_scope_end(self, scope):
+ if not scope.parent:
+ return self.lines.length()
+ end = scope.pyobject.get_ast().body[-1].lineno
+ scope_start = self.pymodule.logical_lines.logical_line_in(scope.start)
+ if scope_start[1] >= end:
+ # handling one-liners
+ body_indents = self._get_scope_indents(scope) + 4
+ else:
+ body_indents = self._get_body_indents(scope)
+ for l in self.logical_lines.generate_starts(
+ min(end + 1, self.lines.length()), self.lines.length() + 1):
+ if not self._is_empty_line(l):
+ if self.get_indents(l) < body_indents:
+ return end
+ else:
+ end = l
+ return end
+
+ @property
+ def lines(self):
+ return self.pymodule.lines
+
+ @property
+ def code(self):
+ return self.pymodule.source_code
+
+ @property
+ def logical_lines(self):
+ return self.pymodule.logical_lines
+
+class TemporaryScope(Scope):
+ """Currently used for list comprehensions and generator expressions
+
+ These scopes do not appear in the `get_scopes()` method of their
+ parent scopes.
+ """
+
+ def __init__(self, pycore, parent_scope, names):
+ super(TemporaryScope, self).__init__(
+ pycore, parent_scope.pyobject, parent_scope)
+ self.names = names
+
+ def get_names(self):
+ return self.names
+
+ def get_defined_names(self):
+ return self.names
+
+ def _create_scopes(self):
+ return []
+
+ def get_kind(self):
+ return 'Temporary'
diff --git a/vim/eclim/autoload/eclim/python/rope/base/resourceobserver.py b/vim/eclim/autoload/eclim/python/rope/base/resourceobserver.py
@@ -0,0 +1,271 @@
+import os
+
+
+class ResourceObserver(object):
+ """Provides the interface for observing resources
+
+ `ResourceObserver`\s can be registered using `Project.
+ add_observer()`. But most of the time `FilteredResourceObserver`
+ should be used. `ResourceObserver`\s report all changes passed
+ to them and they don't report changes to all resources. For
+ example if a folder is removed, it only calls `removed()` for that
+ folder and not its contents. You can use
+ `FilteredResourceObserver` if you are interested in changes only
+ to a list of resources. And you want changes to be reported on
+ individual resources.
+
+ """
+
+ def __init__(self, changed=None, moved=None, created=None,
+ removed=None, validate=None):
+ self.changed = changed
+ self.moved = moved
+ self.created = created
+ self.removed = removed
+ self._validate = validate
+
+ def resource_changed(self, resource):
+ """It is called when the resource changes"""
+ if self.changed is not None:
+ self.changed(resource)
+
+ def resource_moved(self, resource, new_resource):
+ """It is called when a resource is moved"""
+ if self.moved is not None:
+ self.moved(resource, new_resource)
+
+ def resource_created(self, resource):
+ """Is called when a new resource is created"""
+ if self.created is not None:
+ self.created(resource)
+
+ def resource_removed(self, resource):
+ """Is called when a new resource is removed"""
+ if self.removed is not None:
+ self.removed(resource)
+
+ def validate(self, resource):
+ """Validate the existence of this resource and its children.
+
+ This function is called when rope need to update its resource
+ cache about the files that might have been changed or removed
+ by other processes.
+
+ """
+ if self._validate is not None:
+ self._validate(resource)
+
+
+class FilteredResourceObserver(object):
+ """A useful decorator for `ResourceObserver`
+
+ Most resource observers have a list of resources and are
+ interested only in changes to those files. This class satisfies
+ this need. It dispatches resource changed and removed messages.
+ It performs these tasks:
+
+ * Changes to files and folders are analyzed to check whether any
+ of the interesting resources are changed or not. If they are,
+ it reports these changes to `resource_observer` passed to the
+ constructor.
+ * When a resource is removed it checks whether any of the
+ interesting resources are contained in that folder and reports
+ them to `resource_observer`.
+ * When validating a folder it validates all of the interesting
+ files in that folder.
+
+ Since most resource observers are interested in a list of
+ resources that change over time, `add_resource` and
+ `remove_resource` might be useful.
+
+ """
+
+ def __init__(self, resource_observer, initial_resources=None,
+ timekeeper=None):
+ self.observer = resource_observer
+ self.resources = {}
+ if timekeeper is not None:
+ self.timekeeper = timekeeper
+ else:
+ self.timekeeper = ChangeIndicator()
+ if initial_resources is not None:
+ for resource in initial_resources:
+ self.add_resource(resource)
+
+ def add_resource(self, resource):
+ """Add a resource to the list of interesting resources"""
+ if resource.exists():
+ self.resources[resource] = self.timekeeper.get_indicator(resource)
+ else:
+ self.resources[resource] = None
+
+ def remove_resource(self, resource):
+ """Add a resource to the list of interesting resources"""
+ if resource in self.resources:
+ del self.resources[resource]
+
+ def clear_resources(self):
+ """Removes all registered resources"""
+ self.resources.clear()
+
+ def resource_changed(self, resource):
+ changes = _Changes()
+ self._update_changes_caused_by_changed(changes, resource)
+ self._perform_changes(changes)
+
+ def _update_changes_caused_by_changed(self, changes, changed):
+ if changed in self.resources:
+ changes.add_changed(changed)
+ if self._is_parent_changed(changed):
+ changes.add_changed(changed.parent)
+
+ def _update_changes_caused_by_moved(self, changes, resource,
+ new_resource=None):
+ if resource in self.resources:
+ changes.add_removed(resource, new_resource)
+ if new_resource in self.resources:
+ changes.add_created(new_resource)
+ if resource.is_folder():
+ for file in list(self.resources):
+ if resource.contains(file):
+ new_file = self._calculate_new_resource(
+ resource, new_resource, file)
+ changes.add_removed(file, new_file)
+ if self._is_parent_changed(resource):
+ changes.add_changed(resource.parent)
+ if new_resource is not None:
+ if self._is_parent_changed(new_resource):
+ changes.add_changed(new_resource.parent)
+
+ def _is_parent_changed(self, child):
+ return child.parent in self.resources
+
+ def resource_moved(self, resource, new_resource):
+ changes = _Changes()
+ self._update_changes_caused_by_moved(changes, resource, new_resource)
+ self._perform_changes(changes)
+
+ def resource_created(self, resource):
+ changes = _Changes()
+ self._update_changes_caused_by_created(changes, resource)
+ self._perform_changes(changes)
+
+ def _update_changes_caused_by_created(self, changes, resource):
+ if resource in self.resources:
+ changes.add_created(resource)
+ if self._is_parent_changed(resource):
+ changes.add_changed(resource.parent)
+
+ def resource_removed(self, resource):
+ changes = _Changes()
+ self._update_changes_caused_by_moved(changes, resource)
+ self._perform_changes(changes)
+
+ def _perform_changes(self, changes):
+ for resource in changes.changes:
+ self.observer.resource_changed(resource)
+ self.resources[resource] = self.timekeeper.get_indicator(resource)
+ for resource, new_resource in changes.moves.items():
+ self.resources[resource] = None
+ if new_resource is not None:
+ self.observer.resource_moved(resource, new_resource)
+ else:
+ self.observer.resource_removed(resource)
+ for resource in changes.creations:
+ self.observer.resource_created(resource)
+ self.resources[resource] = self.timekeeper.get_indicator(resource)
+
+ def validate(self, resource):
+ changes = _Changes()
+ for file in self._search_resource_moves(resource):
+ if file in self.resources:
+ self._update_changes_caused_by_moved(changes, file)
+ for file in self._search_resource_changes(resource):
+ if file in self.resources:
+ self._update_changes_caused_by_changed(changes, file)
+ for file in self._search_resource_creations(resource):
+ if file in self.resources:
+ changes.add_created(file)
+ self._perform_changes(changes)
+
+ def _search_resource_creations(self, resource):
+ creations = set()
+ if resource in self.resources and resource.exists() and \
+ self.resources[resource] is None:
+ creations.add(resource)
+ if resource.is_folder():
+ for file in self.resources:
+ if file.exists() and resource.contains(file) and \
+ self.resources[file] is None:
+ creations.add(file)
+ return creations
+
+ def _search_resource_moves(self, resource):
+ all_moved = set()
+ if resource in self.resources and not resource.exists():
+ all_moved.add(resource)
+ if resource.is_folder():
+ for file in self.resources:
+ if resource.contains(file):
+ if not file.exists():
+ all_moved.add(file)
+ moved = set(all_moved)
+ for folder in [file for file in all_moved if file.is_folder()]:
+ if folder in moved:
+ for file in list(moved):
+ if folder.contains(file):
+ moved.remove(file)
+ return moved
+
+ def _search_resource_changes(self, resource):
+ changed = set()
+ if resource in self.resources and self._is_changed(resource):
+ changed.add(resource)
+ if resource.is_folder():
+ for file in self.resources:
+ if file.exists() and resource.contains(file):
+ if self._is_changed(file):
+ changed.add(file)
+ return changed
+
+ def _is_changed(self, resource):
+ if self.resources[resource] is None:
+ return False
+ return self.resources[resource] != self.timekeeper.get_indicator(resource)
+
+ def _calculate_new_resource(self, main, new_main, resource):
+ if new_main is None:
+ return None
+ diff = resource.path[len(main.path):]
+ return resource.project.get_resource(new_main.path + diff)
+
+
+class ChangeIndicator(object):
+
+ def get_indicator(self, resource):
+ """Return the modification time and size of a `Resource`."""
+ path = resource.real_path
+ # on dos, mtime does not change for a folder when files are added
+ if os.name != 'posix' and os.path.isdir(path):
+ return (os.path.getmtime(path),
+ len(os.listdir(path)),
+ os.path.getsize(path))
+ return (os.path.getmtime(path),
+ os.path.getsize(path))
+
+
+class _Changes(object):
+
+ def __init__(self):
+ self.changes = set()
+ self.creations = set()
+ self.moves = {}
+
+ def add_changed(self, resource):
+ self.changes.add(resource)
+
+ def add_removed(self, resource, new_resource=None):
+ self.moves[resource] = new_resource
+
+ def add_created(self, resource):
+ self.creations.add(resource)
diff --git a/vim/eclim/autoload/eclim/python/rope/base/resources.py b/vim/eclim/autoload/eclim/python/rope/base/resources.py
@@ -0,0 +1,211 @@
+import os
+import re
+
+import rope.base.change
+import rope.base.fscommands
+from rope.base import exceptions
+
+
+class Resource(object):
+ """Represents files and folders in a project"""
+
+ def __init__(self, project, path):
+ self.project = project
+ self._path = path
+
+ def move(self, new_location):
+ """Move resource to `new_location`"""
+ self._perform_change(rope.base.change.MoveResource(self, new_location),
+ 'Moving <%s> to <%s>' % (self.path, new_location))
+
+ def remove(self):
+ """Remove resource from the project"""
+ self._perform_change(rope.base.change.RemoveResource(self),
+ 'Removing <%s>' % self.path)
+
+ def is_folder(self):
+ """Return true if the resource is a folder"""
+
+ def create(self):
+ """Create this resource"""
+
+ def exists(self):
+ return os.path.exists(self.real_path)
+
+ @property
+ def parent(self):
+ parent = '/'.join(self.path.split('/')[0:-1])
+ return self.project.get_folder(parent)
+
+ @property
+ def path(self):
+ """Return the path of this resource relative to the project root
+
+ The path is the list of parent directories separated by '/' followed
+ by the resource name.
+ """
+ return self._path
+
+ @property
+ def name(self):
+ """Return the name of this resource"""
+ return self.path.split('/')[-1]
+
+ @property
+ def real_path(self):
+ """Return the file system path of this resource"""
+ return self.project._get_resource_path(self.path)
+
+ def __eq__(self, obj):
+ return self.__class__ == obj.__class__ and self.path == obj.path
+
+ def __ne__(self, obj):
+ return not self.__eq__(obj)
+
+ def __hash__(self):
+ return hash(self.path)
+
+ def _perform_change(self, change_, description):
+ changes = rope.base.change.ChangeSet(description)
+ changes.add_change(change_)
+ self.project.do(changes)
+
+
+class File(Resource):
+ """Represents a file"""
+
+ def __init__(self, project, name):
+ super(File, self).__init__(project, name)
+
+ def read(self):
+ data = self.read_bytes()
+ try:
+ return rope.base.fscommands.file_data_to_unicode(data)
+ except UnicodeDecodeError, e:
+ raise exceptions.ModuleDecodeError(self.path, e.reason)
+
+ def read_bytes(self):
+ return open(self.real_path, 'rb').read()
+
+ def write(self, contents):
+ try:
+ if contents == self.read():
+ return
+ except IOError:
+ pass
+ self._perform_change(rope.base.change.ChangeContents(self, contents),
+ 'Writing file <%s>' % self.path)
+
+ def is_folder(self):
+ return False
+
+ def create(self):
+ self.parent.create_file(self.name)
+
+
+class Folder(Resource):
+ """Represents a folder"""
+
+ def __init__(self, project, name):
+ super(Folder, self).__init__(project, name)
+
+ def is_folder(self):
+ return True
+
+ def get_children(self):
+ """Return the children of this folder"""
+ result = []
+ for name in os.listdir(self.real_path):
+ try:
+ child = self.get_child(name)
+ except exceptions.ResourceNotFoundError:
+ continue
+ if not self.project.is_ignored(child):
+ result.append(self.get_child(name))
+ return result
+
+ def create_file(self, file_name):
+ self._perform_change(
+ rope.base.change.CreateFile(self, file_name),
+ 'Creating file <%s>' % self._get_child_path(file_name))
+ return self.get_child(file_name)
+
+ def create_folder(self, folder_name):
+ self._perform_change(
+ rope.base.change.CreateFolder(self, folder_name),
+ 'Creating folder <%s>' % self._get_child_path(folder_name))
+ return self.get_child(folder_name)
+
+ def _get_child_path(self, name):
+ if self.path:
+ return self.path + '/' + name
+ else:
+ return name
+
+ def get_child(self, name):
+ return self.project.get_resource(self._get_child_path(name))
+
+ def has_child(self, name):
+ try:
+ self.get_child(name)
+ return True
+ except exceptions.ResourceNotFoundError:
+ return False
+
+ def get_files(self):
+ return [resource for resource in self.get_children()
+ if not resource.is_folder()]
+
+ def get_folders(self):
+ return [resource for resource in self.get_children()
+ if resource.is_folder()]
+
+ def contains(self, resource):
+ if self == resource:
+ return False
+ return self.path == '' or resource.path.startswith(self.path + '/')
+
+ def create(self):
+ self.parent.create_folder(self.name)
+
+
+class _ResourceMatcher(object):
+
+ def __init__(self):
+ self.patterns = []
+ self._compiled_patterns = []
+
+ def set_patterns(self, patterns):
+ """Specify which resources to match
+
+ `patterns` is a `list` of `str`\s that can contain ``*`` and
+ ``?`` signs for matching resource names.
+
+ """
+ self._compiled_patterns = None
+ self.patterns = patterns
+
+ def _add_pattern(self, pattern):
+ re_pattern = pattern.replace('.', '\\.').\
+ replace('*', '[^/]*').replace('?', '[^/]').\
+ replace('//', '/(.*/)?')
+ re_pattern = '^(.*/)?' + re_pattern + '(/.*)?$'
+ self.compiled_patterns.append(re.compile(re_pattern))
+
+ def does_match(self, resource):
+ for pattern in self.compiled_patterns:
+ if pattern.match(resource.path):
+ return True
+ path = os.path.join(resource.project.address,
+ *resource.path.split('/'))
+ if os.path.islink(path):
+ return True
+ return False
+
+ @property
+ def compiled_patterns(self):
+ if self._compiled_patterns is None:
+ self._compiled_patterns = []
+ for pattern in self.patterns:
+ self._add_pattern(pattern)
+ return self._compiled_patterns
diff --git a/vim/eclim/autoload/eclim/python/rope/base/simplify.py b/vim/eclim/autoload/eclim/python/rope/base/simplify.py
@@ -0,0 +1,55 @@
+"""A module to ease code analysis
+
+This module is here to help source code analysis.
+"""
+import re
+
+from rope.base import codeanalyze, utils
+
+
+@utils.cached(7)
+def real_code(source):
+ """Simplify `source` for analysis
+
+ It replaces:
+
+ * comments with spaces
+ * strs with a new str filled with spaces
+ * implicit and explicit continuations with spaces
+ * tabs and semicolons with spaces
+
+ The resulting code is a lot easier to analyze if we are interested
+ only in offsets.
+ """
+ collector = codeanalyze.ChangeCollector(source)
+ for start, end in ignored_regions(source):
+ if source[start] == '#':
+ replacement = ' ' * (end - start)
+ else:
+ replacement = '"%s"' % (' ' * (end - start - 2))
+ collector.add_change(start, end, replacement)
+ source = collector.get_changed() or source
+ collector = codeanalyze.ChangeCollector(source)
+ parens = 0
+ for match in _parens.finditer(source):
+ i = match.start()
+ c = match.group()
+ if c in '({[':
+ parens += 1
+ if c in ')}]':
+ parens -= 1
+ if c == '\n' and parens > 0:
+ collector.add_change(i, i + 1, ' ')
+ source = collector.get_changed() or source
+ return source.replace('\\\n', ' ').replace('\t', ' ').replace(';', '\n')
+
+
+@utils.cached(7)
+def ignored_regions(source):
+ """Return ignored regions like strings and comments in `source` """
+ return [(match.start(), match.end()) for match in _str.finditer(source)]
+
+
+_str = re.compile('%s|%s' % (codeanalyze.get_comment_pattern(),
+ codeanalyze.get_string_pattern()))
+_parens = re.compile(r'[\({\[\]}\)\n]')
diff --git a/vim/eclim/autoload/eclim/python/rope/base/stdmods.py b/vim/eclim/autoload/eclim/python/rope/base/stdmods.py
@@ -0,0 +1,40 @@
+import os
+import sys
+
+from rope.base import utils
+
+
+def _stdlib_path():
+ import inspect
+ return os.path.dirname(inspect.getsourcefile(inspect))
+
+@utils.cached(1)
+def standard_modules():
+ return python_modules() | dynload_modules()
+
+@utils.cached(1)
+def python_modules():
+ result = set()
+ lib_path = _stdlib_path()
+ if os.path.exists(lib_path):
+ for name in os.listdir(lib_path):
+ path = os.path.join(lib_path, name)
+ if os.path.isdir(path):
+ if '-' not in name:
+ result.add(name)
+ else:
+ if name.endswith('.py'):
+ result.add(name[:-3])
+ return result
+
+@utils.cached(1)
+def dynload_modules():
+ result = set(sys.builtin_module_names)
+ dynload_path = os.path.join(_stdlib_path(), 'lib-dynload')
+ if os.path.exists(dynload_path):
+ for name in os.listdir(dynload_path):
+ path = os.path.join(dynload_path, name)
+ if os.path.isfile(path):
+ if name.endswith('.so') or name.endswith('.dll'):
+ result.add(os.path.splitext(name)[0])
+ return result
diff --git a/vim/eclim/autoload/eclim/python/rope/base/taskhandle.py b/vim/eclim/autoload/eclim/python/rope/base/taskhandle.py
@@ -0,0 +1,133 @@
+import warnings
+
+from rope.base import exceptions
+
+
+class TaskHandle(object):
+
+ def __init__(self, name='Task', interrupts=True):
+ """Construct a TaskHandle
+
+ If `interrupts` is `False` the task won't be interrupted by
+ calling `TaskHandle.stop()`.
+
+ """
+ self.name = name
+ self.interrupts = interrupts
+ self.stopped = False
+ self.job_sets = []
+ self.observers = []
+
+ def stop(self):
+ """Interrupts the refactoring"""
+ if self.interrupts:
+ self.stopped = True
+ self._inform_observers()
+
+ def current_jobset(self):
+ """Return the current `JobSet`"""
+ if self.job_sets:
+ return self.job_sets[-1]
+
+ def add_observer(self, observer):
+ """Register an observer for this task handle
+
+ The observer is notified whenever the task is stopped or
+ a job gets finished.
+
+ """
+ self.observers.append(observer)
+
+ def is_stopped(self):
+ return self.stopped
+
+ def get_jobsets(self):
+ return self.job_sets
+
+ def create_jobset(self, name='JobSet', count=None):
+ result = JobSet(self, name=name, count=count)
+ self.job_sets.append(result)
+ self._inform_observers()
+ return result
+
+ def _inform_observers(self):
+ for observer in list(self.observers):
+ observer()
+
+
+class JobSet(object):
+
+ def __init__(self, handle, name, count):
+ self.handle = handle
+ self.name = name
+ self.count = count
+ self.done = 0
+ self.job_name = None
+
+ def started_job(self, name):
+ self.check_status()
+ self.job_name = name
+ self.handle._inform_observers()
+
+ def finished_job(self):
+ self.check_status()
+ self.done += 1
+ self.handle._inform_observers()
+ self.job_name = None
+
+ def check_status(self):
+ if self.handle.is_stopped():
+ raise exceptions.InterruptedTaskError()
+
+ def get_active_job_name(self):
+ return self.job_name
+
+ def get_percent_done(self):
+ if self.count is not None and self.count > 0:
+ percent = self.done * 100 // self.count
+ return min(percent, 100)
+
+ def get_name(self):
+ return self.name
+
+
+class NullTaskHandle(object):
+
+ def __init__(self):
+ pass
+
+ def is_stopped(self):
+ return False
+
+ def stop(self):
+ pass
+
+ def create_jobset(self, *args, **kwds):
+ return NullJobSet()
+
+ def get_jobsets(self):
+ return []
+
+ def add_observer(self, observer):
+ pass
+
+
+class NullJobSet(object):
+
+ def started_job(self, name):
+ pass
+
+ def finished_job(self):
+ pass
+
+ def check_status(self):
+ pass
+
+ def get_active_job_name(self):
+ pass
+
+ def get_percent_done(self):
+ pass
+
+ def get_name(self):
+ pass
diff --git a/vim/eclim/autoload/eclim/python/rope/base/utils.py b/vim/eclim/autoload/eclim/python/rope/base/utils.py
@@ -0,0 +1,78 @@
+import warnings
+
+
+def saveit(func):
+ """A decorator that caches the return value of a function"""
+
+ name = '_' + func.__name__
+ def _wrapper(self, *args, **kwds):
+ if not hasattr(self, name):
+ setattr(self, name, func(self, *args, **kwds))
+ return getattr(self, name)
+ return _wrapper
+
+cacheit = saveit
+
+def prevent_recursion(default):
+ """A decorator that returns the return value of `default` in recursions"""
+ def decorator(func):
+ name = '_calling_%s_' % func.__name__
+ def newfunc(self, *args, **kwds):
+ if getattr(self, name, False):
+ return default()
+ setattr(self, name, True)
+ try:
+ return func(self, *args, **kwds)
+ finally:
+ setattr(self, name, False)
+ return newfunc
+ return decorator
+
+
+def ignore_exception(exception_class):
+ """A decorator that ignores `exception_class` exceptions"""
+ def _decorator(func):
+ def newfunc(*args, **kwds):
+ try:
+ return func(*args, **kwds)
+ except exception_class:
+ pass
+ return newfunc
+ return _decorator
+
+
+def deprecated(message=None):
+ """A decorator for deprecated functions"""
+ def _decorator(func, message=message):
+ if message is None:
+ message = '%s is deprecated' % func.__name__
+ def newfunc(*args, **kwds):
+ warnings.warn(message, DeprecationWarning, stacklevel=2)
+ return func(*args, **kwds)
+ return newfunc
+ return _decorator
+
+
+def cached(count):
+ """A caching decorator based on parameter objects"""
+ def decorator(func):
+ return _Cached(func, count)
+ return decorator
+
+class _Cached(object):
+
+ def __init__(self, func, count):
+ self.func = func
+ self.cache = []
+ self.count = count
+
+ def __call__(self, *args, **kwds):
+ key = (args, kwds)
+ for cached_key, cached_result in self.cache:
+ if cached_key == key:
+ return cached_result
+ result = self.func(*args, **kwds)
+ self.cache.append((key, result))
+ if len(self.cache) > self.count:
+ del self.cache[0]
+ return result
diff --git a/vim/eclim/autoload/eclim/python/rope/base/worder.py b/vim/eclim/autoload/eclim/python/rope/base/worder.py
@@ -0,0 +1,509 @@
+import bisect
+
+import rope.base.simplify
+
+
+def get_name_at(resource, offset):
+ source_code = resource.read()
+ word_finder = Worder(source_code)
+ return word_finder.get_word_at(offset)
+
+
+class Worder(object):
+ """A class for finding boundaries of words and expressions
+
+ Note that in these methods, offset should be the index of the
+ character not the index of the character after it.
+ """
+
+ def __init__(self, code, handle_ignores=False):
+ simplified = rope.base.simplify.real_code(code)
+ self.code_finder = _RealFinder(simplified, code)
+ self.handle_ignores = handle_ignores
+ self.code = code
+
+ def _init_ignores(self):
+ ignores = rope.base.simplify.ignored_regions(self.code)
+ self.dumb_finder = _RealFinder(self.code, self.code)
+ self.starts = [ignored[0] for ignored in ignores]
+ self.ends = [ignored[1] for ignored in ignores]
+
+ def _context_call(self, name, offset):
+ if self.handle_ignores:
+ if not hasattr(self, 'starts'):
+ self._init_ignores()
+ start = bisect.bisect(self.starts, offset)
+ if start > 0 and offset < self.ends[start - 1]:
+ return getattr(self.dumb_finder, name)(offset)
+ return getattr(self.code_finder, name)(offset)
+
+ def get_primary_at(self, offset):
+ return self._context_call('get_primary_at', offset)
+
+ def get_word_at(self, offset):
+ return self._context_call('get_word_at', offset)
+
+ def get_primary_range(self, offset):
+ return self._context_call('get_primary_range', offset)
+
+ def get_splitted_primary_before(self, offset):
+ return self._context_call('get_splitted_primary_before', offset)
+
+ def get_word_range(self, offset):
+ return self._context_call('get_word_range', offset)
+
+ def is_function_keyword_parameter(self, offset):
+ return self.code_finder.is_function_keyword_parameter(offset)
+
+ def is_a_class_or_function_name_in_header(self, offset):
+ return self.code_finder.is_a_class_or_function_name_in_header(offset)
+
+ def is_from_statement_module(self, offset):
+ return self.code_finder.is_from_statement_module(offset)
+
+ def is_from_aliased(self, offset):
+ return self.code_finder.is_from_aliased(offset)
+
+ def find_parens_start_from_inside(self, offset):
+ return self.code_finder.find_parens_start_from_inside(offset)
+
+ def is_a_name_after_from_import(self, offset):
+ return self.code_finder.is_a_name_after_from_import(offset)
+
+ def is_from_statement(self, offset):
+ return self.code_finder.is_from_statement(offset)
+
+ def get_from_aliased(self, offset):
+ return self.code_finder.get_from_aliased(offset)
+
+ def is_import_statement(self, offset):
+ return self.code_finder.is_import_statement(offset)
+
+ def is_assigned_here(self, offset):
+ return self.code_finder.is_assigned_here(offset)
+
+ def is_a_function_being_called(self, offset):
+ return self.code_finder.is_a_function_being_called(offset)
+
+ def get_word_parens_range(self, offset):
+ return self.code_finder.get_word_parens_range(offset)
+
+ def is_name_assigned_in_class_body(self, offset):
+ return self.code_finder.is_name_assigned_in_class_body(offset)
+
+ def is_on_function_call_keyword(self, offset):
+ return self.code_finder.is_on_function_call_keyword(offset)
+
+ def _find_parens_start(self, offset):
+ return self.code_finder._find_parens_start(offset)
+
+ def get_parameters(self, first, last):
+ return self.code_finder.get_parameters(first, last)
+
+ def get_from_module(self, offset):
+ return self.code_finder.get_from_module(offset)
+
+ def is_assigned_in_a_tuple_assignment(self, offset):
+ return self.code_finder.is_assigned_in_a_tuple_assignment(offset)
+
+ def get_assignment_type(self, offset):
+ return self.code_finder.get_assignment_type(offset)
+
+ def get_function_and_args_in_header(self, offset):
+ return self.code_finder.get_function_and_args_in_header(offset)
+
+ def find_function_offset(self, offset):
+ return self.code_finder.find_function_offset(offset)
+
+
+class _RealFinder(object):
+
+ def __init__(self, code, raw):
+ self.code = code
+ self.raw = raw
+
+ def _find_word_start(self, offset):
+ current_offset = offset
+ while current_offset >= 0 and self._is_id_char(current_offset):
+ current_offset -= 1
+ return current_offset + 1
+
+ def _find_word_end(self, offset):
+ while offset + 1 < len(self.code) and self._is_id_char(offset + 1):
+ offset += 1
+ return offset
+
+ def _find_last_non_space_char(self, offset):
+ while offset >= 0 and self.code[offset].isspace():
+ if self.code[offset] == '\n':
+ return offset
+ offset -= 1
+ return max(-1, offset)
+
+ def get_word_at(self, offset):
+ offset = self._get_fixed_offset(offset)
+ return self.raw[self._find_word_start(offset):
+ self._find_word_end(offset) + 1]
+
+ def _get_fixed_offset(self, offset):
+ if offset >= len(self.code):
+ return offset - 1
+ if not self._is_id_char(offset):
+ if offset > 0 and self._is_id_char(offset - 1):
+ return offset - 1
+ if offset < len(self.code) - 1 and self._is_id_char(offset + 1):
+ return offset + 1
+ return offset
+
+ def _is_id_char(self, offset):
+ return self.code[offset].isalnum() or self.code[offset] == '_'
+
+ def _find_string_start(self, offset):
+ kind = self.code[offset]
+ try:
+ return self.code.rindex(kind, 0, offset)
+ except ValueError:
+ return 0
+
+ def _find_parens_start(self, offset):
+ offset = self._find_last_non_space_char(offset - 1)
+ while offset >= 0 and self.code[offset] not in '[({':
+ if self.code[offset] not in ':,':
+ offset = self._find_primary_start(offset)
+ offset = self._find_last_non_space_char(offset - 1)
+ return offset
+
+ def _find_atom_start(self, offset):
+ old_offset = offset
+ if self.code[offset] == '\n':
+ return offset + 1
+ if self.code[offset].isspace():
+ offset = self._find_last_non_space_char(offset)
+ if self.code[offset] in '\'"':
+ return self._find_string_start(offset)
+ if self.code[offset] in ')]}':
+ return self._find_parens_start(offset)
+ if self._is_id_char(offset):
+ return self._find_word_start(offset)
+ return old_offset
+
+ def _find_primary_without_dot_start(self, offset):
+ """It tries to find the undotted primary start
+
+ It is different from `self._get_atom_start()` in that it
+ follows function calls, too; such as in ``f(x)``.
+
+ """
+ last_atom = offset
+ offset = self._find_last_non_space_char(last_atom)
+ while offset > 0 and self.code[offset] in ')]':
+ last_atom = self._find_parens_start(offset)
+ offset = self._find_last_non_space_char(last_atom - 1)
+ if offset >= 0 and (self.code[offset] in '"\'})]' or
+ self._is_id_char(offset)):
+ return self._find_atom_start(offset)
+ return last_atom
+
+ def _find_primary_start(self, offset):
+ if offset >= len(self.code):
+ offset = len(self.code) - 1
+ if self.code[offset] != '.':
+ offset = self._find_primary_without_dot_start(offset)
+ else:
+ offset = offset + 1
+ while offset > 0:
+ prev = self._find_last_non_space_char(offset - 1)
+ if offset <= 0 or self.code[prev] != '.':
+ break
+ offset = self._find_primary_without_dot_start(prev - 1)
+ if not self._is_id_char(offset):
+ break
+
+ return offset
+
+ def get_primary_at(self, offset):
+ offset = self._get_fixed_offset(offset)
+ start, end = self.get_primary_range(offset)
+ return self.raw[start:end].strip()
+
+ def get_splitted_primary_before(self, offset):
+ """returns expression, starting, starting_offset
+
+ This function is used in `rope.codeassist.assist` function.
+ """
+ if offset == 0:
+ return ('', '', 0)
+ end = offset - 1
+ word_start = self._find_atom_start(end)
+ real_start = self._find_primary_start(end)
+ if self.code[word_start:offset].strip() == '':
+ word_start = end
+ if self.code[end].isspace():
+ word_start = end
+ if self.code[real_start:word_start].strip() == '':
+ real_start = word_start
+ if real_start == word_start == end and not self._is_id_char(end):
+ return ('', '', offset)
+ if real_start == word_start:
+ return ('', self.raw[word_start:offset], word_start)
+ else:
+ if self.code[end] == '.':
+ return (self.raw[real_start:end], '', offset)
+ last_dot_position = word_start
+ if self.code[word_start] != '.':
+ last_dot_position = self._find_last_non_space_char(word_start - 1)
+ last_char_position = self._find_last_non_space_char(last_dot_position - 1)
+ if self.code[word_start].isspace():
+ word_start = offset
+ return (self.raw[real_start:last_char_position + 1],
+ self.raw[word_start:offset], word_start)
+
+ def _get_line_start(self, offset):
+ try:
+ return self.code.rindex('\n', 0, offset + 1)
+ except ValueError:
+ return 0
+
+ def _get_line_end(self, offset):
+ try:
+ return self.code.index('\n', offset)
+ except ValueError:
+ return len(self.code)
+
+ def is_name_assigned_in_class_body(self, offset):
+ word_start = self._find_word_start(offset - 1)
+ word_end = self._find_word_end(offset) + 1
+ if '.' in self.code[word_start:word_end]:
+ return False
+ line_start = self._get_line_start(word_start)
+ line = self.code[line_start:word_start].strip()
+ return not line and self.get_assignment_type(offset) == '='
+
+ def is_a_class_or_function_name_in_header(self, offset):
+ word_start = self._find_word_start(offset - 1)
+ line_start = self._get_line_start(word_start)
+ prev_word = self.code[line_start:word_start].strip()
+ return prev_word in ['def', 'class']
+
+ def _find_first_non_space_char(self, offset):
+ if offset >= len(self.code):
+ return len(self.code)
+ while offset < len(self.code) and self.code[offset].isspace():
+ if self.code[offset] == '\n':
+ return offset
+ offset += 1
+ return offset
+
+ def is_a_function_being_called(self, offset):
+ word_end = self._find_word_end(offset) + 1
+ next_char = self._find_first_non_space_char(word_end)
+ return next_char < len(self.code) and \
+ self.code[next_char] == '(' and \
+ not self.is_a_class_or_function_name_in_header(offset)
+
+ def _find_import_end(self, start):
+ return self._get_line_end(start)
+
+ def is_import_statement(self, offset):
+ try:
+ last_import = self.code.rindex('import ', 0, offset)
+ except ValueError:
+ return False
+ return self._find_import_end(last_import + 7) >= offset
+
+ def is_from_statement(self, offset):
+ try:
+ last_from = self.code.rindex('from ', 0, offset)
+ from_import = self.code.index(' import ', last_from)
+ from_names = from_import + 8
+ except ValueError:
+ return False
+ from_names = self._find_first_non_space_char(from_names)
+ return self._find_import_end(from_names) >= offset
+
+ def is_from_statement_module(self, offset):
+ if offset >= len(self.code) - 1:
+ return False
+ stmt_start = self._find_primary_start(offset)
+ line_start = self._get_line_start(stmt_start)
+ prev_word = self.code[line_start:stmt_start].strip()
+ return prev_word == 'from'
+
+ def is_a_name_after_from_import(self, offset):
+ try:
+ line_start = self._get_line_start(offset)
+ last_from = self.code.rindex('from ', line_start, offset)
+ from_import = self.code.index(' import ', last_from)
+ from_names = from_import + 8
+ except ValueError:
+ return False
+ if from_names - 1 > offset:
+ return False
+ return self._find_import_end(from_names) >= offset
+
+ def get_from_module(self, offset):
+ try:
+ last_from = self.code.rindex('from ', 0, offset)
+ import_offset = self.code.index(' import ', last_from)
+ end = self._find_last_non_space_char(import_offset)
+ return self.get_primary_at(end)
+ except ValueError:
+ pass
+
+ def is_from_aliased(self, offset):
+ if not self.is_a_name_after_from_import(offset):
+ return False
+ try:
+ end = self._find_word_end(offset)
+ as_end = min(self._find_word_end(end + 1), len(self.code))
+ as_start = self._find_word_start(as_end)
+ if self.code[as_start:as_end + 1] == 'as':
+ return True
+ except ValueError:
+ return False
+
+ def get_from_aliased(self, offset):
+ try:
+ end = self._find_word_end(offset)
+ as_ = self._find_word_end(end + 1)
+ alias = self._find_word_end(as_ + 1)
+ start = self._find_word_start(alias)
+ return self.raw[start:alias + 1]
+ except ValueError:
+ pass
+
+ def is_function_keyword_parameter(self, offset):
+ word_end = self._find_word_end(offset)
+ if word_end + 1 == len(self.code):
+ return False
+ next_char = self._find_first_non_space_char(word_end + 1)
+ equals = self.code[next_char:next_char + 2]
+ if equals == '==' or not equals.startswith('='):
+ return False
+ word_start = self._find_word_start(offset)
+ prev_char = self._find_last_non_space_char(word_start - 1)
+ return prev_char - 1 >= 0 and self.code[prev_char] in ',('
+
+ def is_on_function_call_keyword(self, offset):
+ stop = self._get_line_start(offset)
+ if self._is_id_char(offset):
+ offset = self._find_word_start(offset) - 1
+ offset = self._find_last_non_space_char(offset)
+ if offset <= stop or self.code[offset] not in '(,':
+ return False
+ parens_start = self.find_parens_start_from_inside(offset)
+ return stop < parens_start
+
+ def find_parens_start_from_inside(self, offset):
+ stop = self._get_line_start(offset)
+ opens = 1
+ while offset > stop:
+ if self.code[offset] == '(':
+ break
+ if self.code[offset] != ',':
+ offset = self._find_primary_start(offset)
+ offset -= 1
+ return max(stop, offset)
+
+ def is_assigned_here(self, offset):
+ return self.get_assignment_type(offset) is not None
+
+ def get_assignment_type(self, offset):
+ # XXX: does not handle tuple assignments
+ word_end = self._find_word_end(offset)
+ next_char = self._find_first_non_space_char(word_end + 1)
+ single = self.code[next_char:next_char + 1]
+ double = self.code[next_char:next_char + 2]
+ triple = self.code[next_char:next_char + 3]
+ if double not in ('==', '<=', '>=', '!='):
+ for op in [single, double, triple]:
+ if op.endswith('='):
+ return op
+
+ def get_primary_range(self, offset):
+ start = self._find_primary_start(offset)
+ end = self._find_word_end(offset) + 1
+ return (start, end)
+
+ def get_word_range(self, offset):
+ offset = max(0, offset)
+ start = self._find_word_start(offset)
+ end = self._find_word_end(offset) + 1
+ return (start, end)
+
+ def get_word_parens_range(self, offset):
+ end = self._find_word_end(offset)
+ start_parens = self.code.index('(', end)
+ index = start_parens
+ open_count = 0
+ while index < len(self.code):
+ if self.code[index] == '(':
+ open_count += 1
+ if self.code[index] == ')':
+ open_count -= 1
+ if open_count == 0:
+ return (start_parens, index + 1)
+ index += 1
+ return (start_parens, index)
+
+ def get_parameters(self, first, last):
+ keywords = []
+ args = []
+ current = self._find_last_non_space_char(last - 1)
+ while current > first:
+ primary_start = current
+ current = self._find_primary_start(current)
+ while current != first and self.code[current] not in '=,':
+ current = self._find_last_non_space_char(current - 1)
+ primary = self.raw[current + 1:primary_start + 1].strip()
+ if self.code[current] == '=':
+ primary_start = current - 1
+ current -= 1
+ while current != first and self.code[current] not in ',':
+ current = self._find_last_non_space_char(current - 1)
+ param_name = self.raw[current + 1:primary_start + 1].strip()
+ keywords.append((param_name, primary))
+ else:
+ args.append(primary)
+ current = self._find_last_non_space_char(current - 1)
+ args.reverse()
+ keywords.reverse()
+ return args, keywords
+
+ def is_assigned_in_a_tuple_assignment(self, offset):
+ start = self._get_line_start(offset)
+ end = self._get_line_end(offset)
+ primary_start = self._find_primary_start(offset)
+ primary_end = self._find_word_end(offset)
+
+ prev_char_offset = self._find_last_non_space_char(primary_start - 1)
+ next_char_offset = self._find_first_non_space_char(primary_end + 1)
+ next_char = prev_char = ''
+ if prev_char_offset >= start:
+ prev_char = self.code[prev_char_offset]
+ if next_char_offset < end:
+ next_char = self.code[next_char_offset]
+ try:
+ equals_offset = self.code.index('=', start, end)
+ except ValueError:
+ return False
+ if prev_char not in '(,' and next_char not in ',)':
+ return False
+ parens_start = self.find_parens_start_from_inside(offset)
+ # XXX: only handling (x, y) = value
+ return offset < equals_offset and \
+ self.code[start:parens_start].strip() == ''
+
+ def get_function_and_args_in_header(self, offset):
+ offset = self.find_function_offset(offset)
+ lparens, rparens = self.get_word_parens_range(offset)
+ return self.raw[offset:rparens + 1]
+
+ def find_function_offset(self, offset):
+ while True:
+ offset = self.code.index('def ', offset)
+ if offset == 0 or not self._is_id_char(offset - 1):
+ break
+ offset += 1
+ def_ = offset + 4
+ return self._find_first_non_space_char(def_)
diff --git a/vim/eclim/autoload/eclim/python/rope/contrib/__init__.py b/vim/eclim/autoload/eclim/python/rope/contrib/__init__.py
@@ -0,0 +1,7 @@
+"""rope IDE tools package
+
+This package contains modules that can be used in IDEs
+but do not depend on the UI. So these modules will be used
+by `rope.ui` modules.
+
+"""
diff --git a/vim/eclim/autoload/eclim/python/rope/contrib/autoimport.py b/vim/eclim/autoload/eclim/python/rope/contrib/autoimport.py
@@ -0,0 +1,217 @@
+import re
+
+from rope.base import (exceptions, pynames, resourceobserver,
+ taskhandle, pyobjects, builtins, resources)
+from rope.refactor import importutils
+
+
+class AutoImport(object):
+ """A class for finding the module that provides a name
+
+ This class maintains a cache of global names in python modules.
+ Note that this cache is not accurate and might be out of date.
+
+ """
+
+ def __init__(self, project, observe=True, underlined=False):
+ """Construct an AutoImport object
+
+ If `observe` is `True`, listen for project changes and update
+ the cache.
+
+ If `underlined` is `True`, underlined names are cached, too.
+ """
+ self.project = project
+ self.underlined = underlined
+ self.names = project.data_files.read_data('globalnames')
+ if self.names is None:
+ self.names = {}
+ project.data_files.add_write_hook(self._write)
+ # XXX: using a filtered observer
+ observer = resourceobserver.ResourceObserver(
+ changed=self._changed, moved=self._moved, removed=self._removed)
+ if observe:
+ project.add_observer(observer)
+
+ def import_assist(self, starting):
+ """Return a list of ``(name, module)`` tuples
+
+ This function tries to find modules that have a global name
+ that starts with `starting`.
+ """
+ # XXX: breaking if gave up! use generators
+ result = []
+ for module in self.names:
+ for global_name in self.names[module]:
+ if global_name.startswith(starting):
+ result.append((global_name, module))
+ return result
+
+ def get_modules(self, name):
+ """Return the list of modules that have global `name`"""
+ result = []
+ for module in self.names:
+ if name in self.names[module]:
+ result.append(module)
+ return result
+
+ def get_all_names(self):
+ """Return the list of all cached global names"""
+ result = set()
+ for module in self.names:
+ result.update(set(self.names[module]))
+ return result
+
+ def get_name_locations(self, name):
+ """Return a list of ``(resource, lineno)`` tuples"""
+ result = []
+ pycore = self.project.pycore
+ for module in self.names:
+ if name in self.names[module]:
+ try:
+ pymodule = pycore.get_module(module)
+ if name in pymodule:
+ pyname = pymodule[name]
+ module, lineno = pyname.get_definition_location()
+ if module is not None:
+ resource = module.get_module().get_resource()
+ if resource is not None and lineno is not None:
+ result.append((resource, lineno))
+ except exceptions.ModuleNotFoundError:
+ pass
+ return result
+
+ def generate_cache(self, resources=None, underlined=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Generate global name cache for project files
+
+ If `resources` is a list of `rope.base.resource.File`\s, only
+ those files are searched; otherwise all python modules in the
+ project are cached.
+
+ """
+ if resources is None:
+ resources = self.project.pycore.get_python_files()
+ job_set = task_handle.create_jobset(
+ 'Generatig autoimport cache', len(resources))
+ for file in resources:
+ job_set.started_job('Working on <%s>' % file.path)
+ self.update_resource(file, underlined)
+ job_set.finished_job()
+
+ def generate_modules_cache(self, modules, underlined=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Generate global name cache for modules listed in `modules`"""
+ job_set = task_handle.create_jobset(
+ 'Generatig autoimport cache for modules', len(modules))
+ for modname in modules:
+ job_set.started_job('Working on <%s>' % modname)
+ if modname.endswith('.*'):
+ mod = self.project.pycore.find_module(modname[:-2])
+ if mod:
+ for sub in submodules(mod):
+ self.update_resource(sub, underlined)
+ else:
+ self.update_module(modname, underlined)
+ job_set.finished_job()
+
+ def clear_cache(self):
+ """Clear all entries in global-name cache
+
+ It might be a good idea to use this function before
+ regenerating global names.
+
+ """
+ self.names.clear()
+
+ def find_insertion_line(self, code):
+ """Guess at what line the new import should be inserted"""
+ match = re.search(r'^(def|class)\s+', code)
+ if match is not None:
+ code = code[:match.start()]
+ try:
+ pymodule = self.project.pycore.get_string_module(code)
+ except exceptions.ModuleSyntaxError:
+ return 1
+ testmodname = '__rope_testmodule_rope'
+ importinfo = importutils.NormalImport(((testmodname, None),))
+ module_imports = importutils.get_module_imports(
+ self.project.pycore, pymodule)
+ module_imports.add_import(importinfo)
+ code = module_imports.get_changed_source()
+ offset = code.index(testmodname)
+ lineno = code.count('\n', 0, offset) + 1
+ return lineno
+
+ def update_resource(self, resource, underlined=None):
+ """Update the cache for global names in `resource`"""
+ try:
+ pymodule = self.project.pycore.resource_to_pyobject(resource)
+ modname = self._module_name(resource)
+ self._add_names(pymodule, modname, underlined)
+ except exceptions.ModuleSyntaxError:
+ pass
+
+ def update_module(self, modname, underlined=None):
+ """Update the cache for global names in `modname` module
+
+ `modname` is the name of a module.
+ """
+ try:
+ pymodule = self.project.pycore.get_module(modname)
+ self._add_names(pymodule, modname, underlined)
+ except exceptions.ModuleNotFoundError:
+ pass
+
+ def _module_name(self, resource):
+ return self.project.pycore.modname(resource)
+
+ def _add_names(self, pymodule, modname, underlined):
+ if underlined is None:
+ underlined = self.underlined
+ globals = []
+ if isinstance(pymodule, pyobjects.PyDefinedObject):
+ attributes = pymodule._get_structural_attributes()
+ else:
+ attributes = pymodule.get_attributes()
+ for name, pyname in attributes.items():
+ if not underlined and name.startswith('_'):
+ continue
+ if isinstance(pyname, (pynames.AssignedName, pynames.DefinedName)):
+ globals.append(name)
+ if isinstance(pymodule, builtins.BuiltinModule):
+ globals.append(name)
+ self.names[modname] = globals
+
+ def _write(self):
+ self.project.data_files.write_data('globalnames', self.names)
+
+ def _changed(self, resource):
+ if not resource.is_folder():
+ self.update_resource(resource)
+
+ def _moved(self, resource, newresource):
+ if not resource.is_folder():
+ modname = self._module_name(resource)
+ if modname in self.names:
+ del self.names[modname]
+ self.update_resource(newresource)
+
+ def _removed(self, resource):
+ if not resource.is_folder():
+ modname = self._module_name(resource)
+ if modname in self.names:
+ del self.names[modname]
+
+
+def submodules(mod):
+ if isinstance(mod, resources.File):
+ if mod.name.endswith('.py') and mod.name != '__init__.py':
+ return set([mod])
+ return set()
+ if not mod.has_child('__init__.py'):
+ return set()
+ result = set([mod])
+ for child in mod.get_children():
+ result |= submodules(child)
+ return result
diff --git a/vim/eclim/autoload/eclim/python/rope/contrib/changestack.py b/vim/eclim/autoload/eclim/python/rope/contrib/changestack.py
@@ -0,0 +1,52 @@
+"""For performing many refactorings as a single command
+
+`changestack` module can be used to perform many refactorings on top
+of each other as one bigger command. It can be used like::
+
+ stack = ChangeStack(project, 'my big command')
+
+ #..
+ stack.push(refactoring1.get_changes())
+ #..
+ stack.push(refactoring2.get_changes())
+ #..
+ stack.push(refactoringX.get_changes())
+
+ stack.pop_all()
+ changes = stack.merged()
+
+Now `changes` can be previewed or performed as before.
+"""
+
+from rope.base import change
+
+
+class ChangeStack(object):
+
+ def __init__(self, project, description='merged changes'):
+ self.project = project
+ self.description = description
+ self.stack = []
+
+ def push(self, changes):
+ self.stack.append(changes)
+ self.project.do(changes)
+
+ def pop_all(self):
+ for i in range(len(self.stack)):
+ self.project.history.undo(drop=True)
+
+ def merged(self):
+ result = change.ChangeSet(self.description)
+ for changes in self.stack:
+ for c in self._basic_changes(changes):
+ result.add_change(c)
+ return result
+
+ def _basic_changes(self, changes):
+ if isinstance(changes, change.ChangeSet):
+ for child in changes.changes:
+ for atom in self._basic_changes(child):
+ yield atom
+ else:
+ yield changes
diff --git a/vim/eclim/autoload/eclim/python/rope/contrib/codeassist.py b/vim/eclim/autoload/eclim/python/rope/contrib/codeassist.py
@@ -0,0 +1,646 @@
+import keyword
+import sys
+import warnings
+
+import rope.base.codeanalyze
+import rope.base.evaluate
+from rope.base import pyobjects, pyobjectsdef, pynames, builtins, exceptions, worder
+from rope.base.codeanalyze import SourceLinesAdapter
+from rope.contrib import fixsyntax
+from rope.refactor import functionutils
+
+
+def code_assist(project, source_code, offset, resource=None,
+ templates=None, maxfixes=1, later_locals=True):
+ """Return python code completions as a list of `CodeAssistProposal`\s
+
+ `resource` is a `rope.base.resources.Resource` object. If
+ provided, relative imports are handled.
+
+ `maxfixes` is the maximum number of errors to fix if the code has
+ errors in it.
+
+ If `later_locals` is `False` names defined in this scope and after
+ this line is ignored.
+
+ """
+ if templates is not None:
+ warnings.warn('Codeassist no longer supports templates',
+ DeprecationWarning, stacklevel=2)
+ assist = _PythonCodeAssist(
+ project, source_code, offset, resource=resource,
+ maxfixes=maxfixes, later_locals=later_locals)
+ return assist()
+
+
+def starting_offset(source_code, offset):
+ """Return the offset in which the completion should be inserted
+
+ Usually code assist proposals should be inserted like::
+
+ completion = proposal.name
+ result = (source_code[:starting_offset] +
+ completion + source_code[offset:])
+
+ Where starting_offset is the offset returned by this function.
+
+ """
+ word_finder = worder.Worder(source_code, True)
+ expression, starting, starting_offset = \
+ word_finder.get_splitted_primary_before(offset)
+ return starting_offset
+
+
+def get_doc(project, source_code, offset, resource=None, maxfixes=1):
+ """Get the pydoc"""
+ fixer = fixsyntax.FixSyntax(project.pycore, source_code,
+ resource, maxfixes)
+ pymodule = fixer.get_pymodule()
+ pyname = fixer.pyname_at(offset)
+ if pyname is None:
+ return None
+ pyobject = pyname.get_object()
+ return PyDocExtractor().get_doc(pyobject)
+
+
+def get_calltip(project, source_code, offset, resource=None,
+ maxfixes=1, ignore_unknown=False, remove_self=False):
+ """Get the calltip of a function
+
+ The format of the returned string is
+ ``module_name.holding_scope_names.function_name(arguments)``. For
+ classes `__init__()` and for normal objects `__call__()` function
+ is used.
+
+ Note that the offset is on the function itself *not* after the its
+ open parenthesis. (Actually it used to be the other way but it
+ was easily confused when string literals were involved. So I
+ decided it is better for it not to try to be too clever when it
+ cannot be clever enough). You can use a simple search like::
+
+ offset = source_code.rindex('(', 0, offset) - 1
+
+ to handle simple situations.
+
+ If `ignore_unknown` is `True`, `None` is returned for functions
+ without source-code like builtins and extensions.
+
+ If `remove_self` is `True`, the first parameter whose name is self
+ will be removed for methods.
+ """
+ fixer = fixsyntax.FixSyntax(project.pycore, source_code,
+ resource, maxfixes)
+ pymodule = fixer.get_pymodule()
+ pyname = fixer.pyname_at(offset)
+ if pyname is None:
+ return None
+ pyobject = pyname.get_object()
+ return PyDocExtractor().get_calltip(pyobject, ignore_unknown, remove_self)
+
+
+def get_definition_location(project, source_code, offset,
+ resource=None, maxfixes=1):
+ """Return the definition location of the python name at `offset`
+
+ Return a (`rope.base.resources.Resource`, lineno) tuple. If no
+ `resource` is given and the definition is inside the same module,
+ the first element of the returned tuple would be `None`. If the
+ location cannot be determined ``(None, None)`` is returned.
+
+ """
+ fixer = fixsyntax.FixSyntax(project.pycore, source_code,
+ resource, maxfixes)
+ pymodule = fixer.get_pymodule()
+ pyname = fixer.pyname_at(offset)
+ if pyname is not None:
+ module, lineno = pyname.get_definition_location()
+ if module is not None:
+ return module.get_module().get_resource(), lineno
+ return (None, None)
+
+
+def find_occurrences(*args, **kwds):
+ import rope.contrib.findit
+ warnings.warn('Use `rope.contrib.findit.find_occurrences()` instead',
+ DeprecationWarning, stacklevel=2)
+ return rope.contrib.findit.find_occurrences(*args, **kwds)
+
+
+class CompletionProposal(object):
+ """A completion proposal
+
+ The `scope` instance variable shows where proposed name came from
+ and can be 'global', 'local', 'builtin', 'attribute', 'keyword',
+ 'imported', 'parameter_keyword'.
+
+ The `type` instance variable shows the approximate type of the
+ proposed object and can be 'instance', 'class', 'function', 'module',
+ and `None`.
+
+ All possible relations between proposal's `scope` and `type` are shown
+ in the table below (different scopes in rows and types in columns):
+
+ | instance | class | function | module | None
+ local | + | + | + | + |
+ global | + | + | + | + |
+ builtin | + | + | + | |
+ attribute | + | + | + | + |
+ imported | + | + | + | + |
+ keyword | | | | | +
+ parameter_keyword | | | | | +
+
+ """
+
+ def __init__(self, name, scope, pyname=None):
+ self.name = name
+ self.scope = scope
+ self.pyname = pyname
+ if pyname is not None:
+ self.type = self._get_type()
+ else:
+ self.type = None
+
+ def __str__(self):
+ return '%s (%s, %s)' % (self.name, self.scope, self.type)
+
+ def __repr__(self):
+ return str(self)
+
+ @property
+ def parameters(self):
+ """The names of the parameters the function takes.
+
+ Returns None if this completion is not a function.
+ """
+ pyname = self.pyname
+ if isinstance(pyname, pynames.ImportedName):
+ pyname = pyname._get_imported_pyname()
+ if isinstance(pyname, pynames.DefinedName):
+ pyobject = pyname.get_object()
+ if isinstance(pyobject, pyobjects.AbstractFunction):
+ return pyobject.get_param_names()
+
+ def _get_type(self):
+ pyname = self.pyname
+ if isinstance(pyname, builtins.BuiltinName):
+ self.scope = 'builtin'
+ pyobject = pyname.get_object()
+ if isinstance(pyobject, builtins.BuiltinFunction):
+ return 'function'
+ elif isinstance(pyobject, builtins.BuiltinClass):
+ clsobj = pyobject.builtin
+ return 'class'
+ elif isinstance(pyobject, builtins.BuiltinObject) or \
+ isinstance(pyobject, builtins.BuiltinName):
+ return 'instance'
+ elif isinstance(pyname, pynames.ImportedModule):
+ self.scope = 'imported'
+ return 'module'
+ elif isinstance(pyname, pynames.ImportedName) or \
+ isinstance(pyname, pynames.DefinedName):
+ if isinstance(pyname, pynames.ImportedName):
+ self.scope = 'imported'
+ pyobject = pyname.get_object()
+ if isinstance(pyobject, pyobjects.AbstractFunction):
+ return 'function'
+ if isinstance(pyobject, pyobjects.AbstractClass):
+ return 'class'
+ return 'instance'
+
+ def get_doc(self):
+ """Get the proposed object's docstring.
+
+ Returns None if it can not be get.
+ """
+ if not self.pyname:
+ return None
+ pyobject = self.pyname.get_object()
+ if not hasattr(pyobject, 'get_doc'):
+ return None
+ return self.pyname.get_object().get_doc()
+
+ @property
+ def kind(self):
+ warnings.warn("the proposal's `kind` property is deprecated, " \
+ "use `scope` instead")
+ return self.scope
+
+
+# leaved for backward compatibility
+CodeAssistProposal = CompletionProposal
+
+
+class NamedParamProposal(CompletionProposal):
+ """A parameter keyword completion proposal
+
+ Holds reference to ``_function`` -- the function which
+ parameter ``name`` belongs to. This allows to determine
+ default value for this parameter.
+ """
+ def __init__(self, name, function):
+ self.argname = name
+ name = '%s=' % name
+ super(NamedParamProposal, self).__init__(name, 'parameter_keyword')
+ self._function = function
+
+ def get_default(self):
+ """Get a string representation of a param's default value.
+
+ Returns None if there is no default value for this param.
+ """
+ definfo = functionutils.DefinitionInfo.read(self._function)
+ for arg, default in definfo.args_with_defaults:
+ if self.argname == arg:
+ return default
+ return None
+
+
+def sorted_proposals(proposals, scopepref=None, typepref=None):
+ """Sort a list of proposals
+
+ Return a sorted list of the given `CodeAssistProposal`\s.
+
+ `scopepref` can be a list of proposal scopes. Defaults to
+ ``['parameter_keyword', 'local', 'global', 'imported',
+ 'attribute', 'builtin', 'keyword']``.
+
+ `typepref` can be a list of proposal types. Defaults to
+ ``['class', 'function', 'instance', 'module', None]``.
+ (`None` stands for completions with no type like keywords.)
+ """
+ sorter = _ProposalSorter(proposals, scopepref, typepref)
+ return sorter.get_sorted_proposal_list()
+
+
+def starting_expression(source_code, offset):
+ """Return the expression to complete"""
+ word_finder = worder.Worder(source_code, True)
+ expression, starting, starting_offset = \
+ word_finder.get_splitted_primary_before(offset)
+ if expression:
+ return expression + '.' + starting
+ return starting
+
+
+def default_templates():
+ warnings.warn('default_templates() is deprecated.',
+ DeprecationWarning, stacklevel=2)
+ return {}
+
+
+class _PythonCodeAssist(object):
+
+ def __init__(self, project, source_code, offset, resource=None,
+ maxfixes=1, later_locals=True):
+ self.project = project
+ self.pycore = self.project.pycore
+ self.code = source_code
+ self.resource = resource
+ self.maxfixes = maxfixes
+ self.later_locals = later_locals
+ self.word_finder = worder.Worder(source_code, True)
+ self.expression, self.starting, self.offset = \
+ self.word_finder.get_splitted_primary_before(offset)
+
+ keywords = keyword.kwlist
+
+ def _find_starting_offset(self, source_code, offset):
+ current_offset = offset - 1
+ while current_offset >= 0 and (source_code[current_offset].isalnum() or
+ source_code[current_offset] in '_'):
+ current_offset -= 1;
+ return current_offset + 1
+
+ def _matching_keywords(self, starting):
+ result = []
+ for kw in self.keywords:
+ if kw.startswith(starting):
+ result.append(CompletionProposal(kw, 'keyword'))
+ return result
+
+ def __call__(self):
+ if self.offset > len(self.code):
+ return []
+ completions = list(self._code_completions().values())
+ if self.expression.strip() == '' and self.starting.strip() != '':
+ completions.extend(self._matching_keywords(self.starting))
+ return completions
+
+ def _dotted_completions(self, module_scope, holding_scope):
+ result = {}
+ found_pyname = rope.base.evaluate.eval_str(holding_scope,
+ self.expression)
+ if found_pyname is not None:
+ element = found_pyname.get_object()
+ compl_scope = 'attribute'
+ if isinstance(element, (pyobjectsdef.PyModule,
+ pyobjectsdef.PyPackage)):
+ compl_scope = 'imported'
+ for name, pyname in element.get_attributes().items():
+ if name.startswith(self.starting):
+ result[name] = CompletionProposal(name, compl_scope, pyname)
+ return result
+
+ def _undotted_completions(self, scope, result, lineno=None):
+ if scope.parent != None:
+ self._undotted_completions(scope.parent, result)
+ if lineno is None:
+ names = scope.get_propagated_names()
+ else:
+ names = scope.get_names()
+ for name, pyname in names.items():
+ if name.startswith(self.starting):
+ compl_scope = 'local'
+ if scope.get_kind() == 'Module':
+ compl_scope = 'global'
+ if lineno is None or self.later_locals or \
+ not self._is_defined_after(scope, pyname, lineno):
+ result[name] = CompletionProposal(name, compl_scope,
+ pyname)
+
+ def _from_import_completions(self, pymodule):
+ module_name = self.word_finder.get_from_module(self.offset)
+ if module_name is None:
+ return {}
+ pymodule = self._find_module(pymodule, module_name)
+ result = {}
+ for name in pymodule:
+ if name.startswith(self.starting):
+ result[name] = CompletionProposal(name, scope='global',
+ pyname=pymodule[name])
+ return result
+
+ def _find_module(self, pymodule, module_name):
+ dots = 0
+ while module_name[dots] == '.':
+ dots += 1
+ pyname = pynames.ImportedModule(pymodule,
+ module_name[dots:], dots)
+ return pyname.get_object()
+
+ def _is_defined_after(self, scope, pyname, lineno):
+ location = pyname.get_definition_location()
+ if location is not None and location[1] is not None:
+ if location[0] == scope.pyobject.get_module() and \
+ lineno <= location[1] <= scope.get_end():
+ return True
+
+ def _code_completions(self):
+ lineno = self.code.count('\n', 0, self.offset) + 1
+ fixer = fixsyntax.FixSyntax(self.pycore, self.code,
+ self.resource, self.maxfixes)
+ pymodule = fixer.get_pymodule()
+ module_scope = pymodule.get_scope()
+ code = pymodule.source_code
+ lines = code.split('\n')
+ result = {}
+ start = fixsyntax._logical_start(lines, lineno)
+ indents = fixsyntax._get_line_indents(lines[start - 1])
+ inner_scope = module_scope.get_inner_scope_for_line(start, indents)
+ if self.word_finder.is_a_name_after_from_import(self.offset):
+ return self._from_import_completions(pymodule)
+ if self.expression.strip() != '':
+ result.update(self._dotted_completions(module_scope, inner_scope))
+ else:
+ result.update(self._keyword_parameters(module_scope.pyobject,
+ inner_scope))
+ self._undotted_completions(inner_scope, result, lineno=lineno)
+ return result
+
+ def _keyword_parameters(self, pymodule, scope):
+ offset = self.offset
+ if offset == 0:
+ return {}
+ word_finder = worder.Worder(self.code, True)
+ lines = SourceLinesAdapter(self.code)
+ lineno = lines.get_line_number(offset)
+ if word_finder.is_on_function_call_keyword(offset - 1):
+ name_finder = rope.base.evaluate.ScopeNameFinder(pymodule)
+ function_parens = word_finder.\
+ find_parens_start_from_inside(offset - 1)
+ primary = word_finder.get_primary_at(function_parens - 1)
+ try:
+ function_pyname = rope.base.evaluate.\
+ eval_str(scope, primary)
+ except exceptions.BadIdentifierError, e:
+ return {}
+ if function_pyname is not None:
+ pyobject = function_pyname.get_object()
+ if isinstance(pyobject, pyobjects.AbstractFunction):
+ pass
+ elif isinstance(pyobject, pyobjects.AbstractClass) and \
+ '__init__' in pyobject:
+ pyobject = pyobject['__init__'].get_object()
+ elif '__call__' in pyobject:
+ pyobject = pyobject['__call__'].get_object()
+ if isinstance(pyobject, pyobjects.AbstractFunction):
+ param_names = []
+ param_names.extend(
+ pyobject.get_param_names(special_args=False))
+ result = {}
+ for name in param_names:
+ if name.startswith(self.starting):
+ result[name + '='] = NamedParamProposal(
+ name, pyobject
+ )
+ return result
+ return {}
+
+
+class _ProposalSorter(object):
+ """Sort a list of code assist proposals"""
+
+ def __init__(self, code_assist_proposals, scopepref=None, typepref=None):
+ self.proposals = code_assist_proposals
+ if scopepref is None:
+ scopepref = ['parameter_keyword', 'local', 'global', 'imported',
+ 'attribute', 'builtin', 'keyword']
+ self.scopepref = scopepref
+ if typepref is None:
+ typepref = ['class', 'function', 'instance', 'module', None]
+ self.typerank = dict((type, index)
+ for index, type in enumerate(typepref))
+
+ def get_sorted_proposal_list(self):
+ """Return a list of `CodeAssistProposal`"""
+ proposals = {}
+ for proposal in self.proposals:
+ proposals.setdefault(proposal.scope, []).append(proposal)
+ result = []
+ for scope in self.scopepref:
+ scope_proposals = proposals.get(scope, [])
+ scope_proposals = [proposal for proposal in scope_proposals
+ if proposal.type in self.typerank]
+ scope_proposals.sort(self._proposal_cmp)
+ result.extend(scope_proposals)
+ return result
+
+ def _proposal_cmp(self, proposal1, proposal2):
+ if proposal1.type != proposal2.type:
+ return cmp(self.typerank.get(proposal1.type, 100),
+ self.typerank.get(proposal2.type, 100))
+ return self._compare_underlined_names(proposal1.name,
+ proposal2.name)
+
+ def _compare_underlined_names(self, name1, name2):
+ def underline_count(name):
+ result = 0
+ while result < len(name) and name[result] == '_':
+ result += 1
+ return result
+ underline_count1 = underline_count(name1)
+ underline_count2 = underline_count(name2)
+ if underline_count1 != underline_count2:
+ return cmp(underline_count1, underline_count2)
+ return cmp(name1, name2)
+
+
+class PyDocExtractor(object):
+
+ def get_doc(self, pyobject):
+ if isinstance(pyobject, pyobjects.AbstractFunction):
+ return self._get_function_docstring(pyobject)
+ elif isinstance(pyobject, pyobjects.AbstractClass):
+ return self._get_class_docstring(pyobject)
+ elif isinstance(pyobject, pyobjects.AbstractModule):
+ return self._trim_docstring(pyobject.get_doc())
+ return None
+
+ def get_calltip(self, pyobject, ignore_unknown=False, remove_self=False):
+ try:
+ if isinstance(pyobject, pyobjects.AbstractClass):
+ pyobject = pyobject['__init__'].get_object()
+ if not isinstance(pyobject, pyobjects.AbstractFunction):
+ pyobject = pyobject['__call__'].get_object()
+ except exceptions.AttributeNotFoundError:
+ return None
+ if ignore_unknown and not isinstance(pyobject, pyobjects.PyFunction):
+ return
+ if isinstance(pyobject, pyobjects.AbstractFunction):
+ result = self._get_function_signature(pyobject, add_module=True)
+ if remove_self and self._is_method(pyobject):
+ return result.replace('(self)', '()').replace('(self, ', '(')
+ return result
+
+ def _get_class_docstring(self, pyclass):
+ contents = self._trim_docstring(pyclass.get_doc(), 2)
+ supers = [super.get_name() for super in pyclass.get_superclasses()]
+ doc = 'class %s(%s):\n\n' % (pyclass.get_name(), ', '.join(supers)) + contents
+
+ if '__init__' in pyclass:
+ init = pyclass['__init__'].get_object()
+ if isinstance(init, pyobjects.AbstractFunction):
+ doc += '\n\n' + self._get_single_function_docstring(init)
+ return doc
+
+ def _get_function_docstring(self, pyfunction):
+ functions = [pyfunction]
+ if self._is_method(pyfunction):
+ functions.extend(self._get_super_methods(pyfunction.parent,
+ pyfunction.get_name()))
+ return '\n\n'.join([self._get_single_function_docstring(function)
+ for function in functions])
+
+ def _is_method(self, pyfunction):
+ return isinstance(pyfunction, pyobjects.PyFunction) and \
+ isinstance(pyfunction.parent, pyobjects.PyClass)
+
+ def _get_single_function_docstring(self, pyfunction):
+ signature = self._get_function_signature(pyfunction)
+ docs = self._trim_docstring(pyfunction.get_doc(), indents=2)
+ return signature + ':\n\n' + docs
+
+ def _get_super_methods(self, pyclass, name):
+ result = []
+ for super_class in pyclass.get_superclasses():
+ if name in super_class:
+ function = super_class[name].get_object()
+ if isinstance(function, pyobjects.AbstractFunction):
+ result.append(function)
+ result.extend(self._get_super_methods(super_class, name))
+ return result
+
+ def _get_function_signature(self, pyfunction, add_module=False):
+ location = self._location(pyfunction, add_module)
+ if isinstance(pyfunction, pyobjects.PyFunction):
+ info = functionutils.DefinitionInfo.read(pyfunction)
+ return location + info.to_string()
+ else:
+ return '%s(%s)' % (location + pyfunction.get_name(),
+ ', '.join(pyfunction.get_param_names()))
+
+ def _location(self, pyobject, add_module=False):
+ location = []
+ parent = pyobject.parent
+ while parent and not isinstance(parent, pyobjects.AbstractModule):
+ location.append(parent.get_name())
+ location.append('.')
+ parent = parent.parent
+ if add_module:
+ if isinstance(pyobject, pyobjects.PyFunction):
+ module = pyobject.get_module()
+ location.insert(0, self._get_module(pyobject))
+ if isinstance(parent, builtins.BuiltinModule):
+ location.insert(0, parent.get_name() + '.')
+ return ''.join(location)
+
+ def _get_module(self, pyfunction):
+ module = pyfunction.get_module()
+ if module is not None:
+ resource = module.get_resource()
+ if resource is not None:
+ return pyfunction.pycore.modname(resource) + '.'
+ return ''
+
+ def _trim_docstring(self, docstring, indents=0):
+ """The sample code from :PEP:`257`"""
+ if not docstring:
+ return ''
+ # Convert tabs to spaces (following normal Python rules)
+ # and split into a list of lines:
+ lines = docstring.expandtabs().splitlines()
+ # Determine minimum indentation (first line doesn't count):
+ indent = sys.maxint
+ for line in lines[1:]:
+ stripped = line.lstrip()
+ if stripped:
+ indent = min(indent, len(line) - len(stripped))
+ # Remove indentation (first line is special):
+ trimmed = [lines[0].strip()]
+ if indent < sys.maxint:
+ for line in lines[1:]:
+ trimmed.append(line[indent:].rstrip())
+ # Strip off trailing and leading blank lines:
+ while trimmed and not trimmed[-1]:
+ trimmed.pop()
+ while trimmed and not trimmed[0]:
+ trimmed.pop(0)
+ # Return a single string:
+ return '\n'.join((' ' * indents + line for line in trimmed))
+
+
+# Deprecated classes
+
+class TemplateProposal(CodeAssistProposal):
+ def __init__(self, name, template):
+ warnings.warn('TemplateProposal is deprecated.',
+ DeprecationWarning, stacklevel=2)
+ super(TemplateProposal, self).__init__(name, 'template')
+ self.template = template
+
+
+class Template(object):
+
+ def __init__(self, template):
+ self.template = template
+ warnings.warn('Template is deprecated.',
+ DeprecationWarning, stacklevel=2)
+
+ def variables(self):
+ return []
+
+ def substitute(self, mapping):
+ return self.template
+
+ def get_cursor_location(self, mapping):
+ return len(self.template)
diff --git a/vim/eclim/autoload/eclim/python/rope/contrib/finderrors.py b/vim/eclim/autoload/eclim/python/rope/contrib/finderrors.py
@@ -0,0 +1,91 @@
+"""Finding bad name and attribute accesses
+
+`find_errors` function can be used to find possible bad name and
+attribute accesses. As an example::
+
+ errors = find_errors(project, project.get_resource('mod.py'))
+ for error in errors:
+ print '%s: %s' % (error.lineno, error.error)
+
+prints possible errors for ``mod.py`` file.
+
+TODO:
+
+* use task handles
+* reporting names at most once
+* attributes of extension modules that don't appear in
+ extension_modules project config can be ignored
+* not calling `PyScope.get_inner_scope_for_line()` if it is a
+ bottleneck; needs profiling
+* not reporting occurrences where rope cannot infer the object
+* rope saves multiple objects for some of the names in its objectdb
+ use all of them not to give false positives
+* ... ;-)
+
+"""
+from rope.base import ast, evaluate, pyobjects
+
+
+def find_errors(project, resource):
+ """Find possible bad name and attribute accesses
+
+ It returns a list of `Error`\s.
+ """
+ pymodule = project.pycore.resource_to_pyobject(resource)
+ finder = _BadAccessFinder(pymodule)
+ ast.walk(pymodule.get_ast(), finder)
+ return finder.errors
+
+
+class _BadAccessFinder(object):
+
+ def __init__(self, pymodule):
+ self.pymodule = pymodule
+ self.scope = pymodule.get_scope()
+ self.errors = []
+
+ def _Name(self, node):
+ if isinstance(node.ctx, (ast.Store, ast.Param)):
+ return
+ scope = self.scope.get_inner_scope_for_line(node.lineno)
+ pyname = scope.lookup(node.id)
+ if pyname is None:
+ self._add_error(node, 'Unresolved variable')
+ elif self._is_defined_after(scope, pyname, node.lineno):
+ self._add_error(node, 'Defined later')
+
+ def _Attribute(self, node):
+ if not isinstance(node.ctx, ast.Store):
+ scope = self.scope.get_inner_scope_for_line(node.lineno)
+ pyname = evaluate.eval_node(scope, node.value)
+ if pyname is not None and \
+ pyname.get_object() != pyobjects.get_unknown():
+ if node.attr not in pyname.get_object():
+ self._add_error(node, 'Unresolved attribute')
+ ast.walk(node.value, self)
+
+ def _add_error(self, node, msg):
+ if isinstance(node, ast.Attribute):
+ name = node.attr
+ else:
+ name = node.id
+ if name != 'None':
+ error = Error(node.lineno, msg + ' ' + name)
+ self.errors.append(error)
+
+ def _is_defined_after(self, scope, pyname, lineno):
+ location = pyname.get_definition_location()
+ if location is not None and location[1] is not None:
+ if location[0] == self.pymodule and \
+ lineno <= location[1] <= scope.get_end():
+ return True
+
+
+class Error(object):
+
+ def __init__(self, lineno, error):
+ self.lineno = lineno
+ self.error = error
+
+ def __str__(self):
+ return '%s: %s' % (self.lineno, self.error)
diff --git a/vim/eclim/autoload/eclim/python/rope/contrib/findit.py b/vim/eclim/autoload/eclim/python/rope/contrib/findit.py
@@ -0,0 +1,110 @@
+import rope.base.codeanalyze
+import rope.base.evaluate
+import rope.base.pyobjects
+from rope.base import taskhandle, exceptions, worder
+from rope.contrib import fixsyntax
+from rope.refactor import occurrences
+
+
+def find_occurrences(project, resource, offset, unsure=False, resources=None,
+ in_hierarchy=False, task_handle=taskhandle.NullTaskHandle()):
+ """Return a list of `Location`\s
+
+ If `unsure` is `True`, possible matches are returned, too. You
+ can use `Location.unsure` to see which are unsure occurrences.
+ `resources` can be a list of `rope.base.resource.File`\s that
+ should be searched for occurrences; if `None` all python files
+ in the project are searched.
+
+ """
+ name = worder.get_name_at(resource, offset)
+ this_pymodule = project.pycore.resource_to_pyobject(resource)
+ primary, pyname = rope.base.evaluate.eval_location2(
+ this_pymodule, offset)
+ def is_match(occurrence):
+ return unsure
+ finder = occurrences.create_finder(
+ project.pycore, name, pyname, unsure=is_match,
+ in_hierarchy=in_hierarchy, instance=primary)
+ if resources is None:
+ resources = project.pycore.get_python_files()
+ job_set = task_handle.create_jobset('Finding Occurrences',
+ count=len(resources))
+ return _find_locations(finder, resources, job_set)
+
+
+def find_implementations(project, resource, offset, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Find the places a given method is overridden.
+
+ Finds the places a method is implemented. Returns a list of
+ `Location`\s.
+ """
+ name = worder.get_name_at(resource, offset)
+ this_pymodule = project.pycore.resource_to_pyobject(resource)
+ pyname = rope.base.evaluate.eval_location(this_pymodule, offset)
+ if pyname is not None:
+ pyobject = pyname.get_object()
+ if not isinstance(pyobject, rope.base.pyobjects.PyFunction) or \
+ pyobject.get_kind() != 'method':
+ raise exceptions.BadIdentifierError('Not a method!')
+ else:
+ raise exceptions.BadIdentifierError('Cannot resolve the identifier!')
+ def is_defined(occurrence):
+ if not occurrence.is_defined():
+ return False
+ def not_self(occurrence):
+ if occurrence.get_pyname().get_object() == pyname.get_object():
+ return False
+ filters = [is_defined, not_self,
+ occurrences.InHierarchyFilter(pyname, True)]
+ finder = occurrences.Finder(project.pycore, name, filters=filters)
+ if resources is None:
+ resources = project.pycore.get_python_files()
+ job_set = task_handle.create_jobset('Finding Implementations',
+ count=len(resources))
+ return _find_locations(finder, resources, job_set)
+
+
+def find_definition(project, code, offset, resource=None, maxfixes=1):
+ """Return the definition location of the python name at `offset`
+
+ A `Location` object is returned if the definition location can be
+ determined, otherwise ``None`` is returned.
+ """
+ fixer = fixsyntax.FixSyntax(project.pycore, code, resource, maxfixes)
+ main_module = fixer.get_pymodule()
+ pyname = fixer.pyname_at(offset)
+ if pyname is not None:
+ module, lineno = pyname.get_definition_location()
+ name = rope.base.worder.Worder(code).get_word_at(offset)
+ if lineno is not None:
+ start = module.lines.get_line_start(lineno)
+ def check_offset(occurrence):
+ if occurrence.offset < start:
+ return False
+ pyname_filter = occurrences.PyNameFilter(pyname)
+ finder = occurrences.Finder(project.pycore, name,
+ [check_offset, pyname_filter])
+ for occurrence in finder.find_occurrences(pymodule=module):
+ return Location(occurrence)
+
+
+class Location(object):
+
+ def __init__(self, occurrence):
+ self.resource = occurrence.resource
+ self.region = occurrence.get_word_range()
+ self.offset = self.region[0]
+ self.unsure = occurrence.is_unsure()
+ self.lineno = occurrence.lineno
+
+
+def _find_locations(finder, resources, job_set):
+ result = []
+ for resource in resources:
+ job_set.started_job(resource.path)
+ for occurrence in finder.find_occurrences(resource):
+ result.append(Location(occurrence))
+ job_set.finished_job()
+ return result
diff --git a/vim/eclim/autoload/eclim/python/rope/contrib/fixmodnames.py b/vim/eclim/autoload/eclim/python/rope/contrib/fixmodnames.py
@@ -0,0 +1,69 @@
+"""Fix the name of modules
+
+This module is useful when you want to rename many of the modules in
+your project. That can happen specially when you want to change their
+naming style.
+
+For instance::
+
+ fixer = FixModuleNames(project)
+ changes = fixer.get_changes(fixer=str.lower)
+ project.do(changes)
+
+Here it renames all modules and packages to use lower-cased chars.
+You can tell it to use any other style by using the ``fixer``
+argument.
+
+"""
+from rope.base import change, taskhandle
+from rope.contrib import changestack
+from rope.refactor import rename
+
+
+class FixModuleNames(object):
+
+ def __init__(self, project):
+ self.project = project
+
+ def get_changes(self, fixer=str.lower,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Fix module names
+
+ `fixer` is a function that takes and returns a `str`. Given
+ the name of a module, it should return the fixed name.
+
+ """
+ stack = changestack.ChangeStack(self.project, 'Fixing module names')
+ jobset = task_handle.create_jobset('Fixing module names',
+ self._count_fixes(fixer) + 1)
+ try:
+ while True:
+ for resource in self._tobe_fixed(fixer):
+ jobset.started_job(resource.path)
+ renamer = rename.Rename(self.project, resource)
+ changes = renamer.get_changes(fixer(self._name(resource)))
+ stack.push(changes)
+ jobset.finished_job()
+ break
+ else:
+ break
+ finally:
+ jobset.started_job('Reverting to original state')
+ stack.pop_all()
+ jobset.finished_job()
+ return stack.merged()
+
+ def _count_fixes(self, fixer):
+ return len(list(self._tobe_fixed(fixer)))
+
+ def _tobe_fixed(self, fixer):
+ for resource in self.project.pycore.get_python_files():
+ modname = self._name(resource)
+ if modname != fixer(modname):
+ yield resource
+
+ def _name(self, resource):
+ modname = resource.name.rsplit('.', 1)[0]
+ if modname == '__init__':
+ modname = resource.parent.name
+ return modname
diff --git a/vim/eclim/autoload/eclim/python/rope/contrib/fixsyntax.py b/vim/eclim/autoload/eclim/python/rope/contrib/fixsyntax.py
@@ -0,0 +1,178 @@
+import rope.base.codeanalyze
+import rope.base.evaluate
+from rope.base import worder, exceptions, utils
+from rope.base.codeanalyze import ArrayLinesAdapter, LogicalLineFinder
+
+
+class FixSyntax(object):
+
+ def __init__(self, pycore, code, resource, maxfixes=1):
+ self.pycore = pycore
+ self.code = code
+ self.resource = resource
+ self.maxfixes = maxfixes
+
+ @utils.saveit
+ def get_pymodule(self):
+ """Get a `PyModule`"""
+ errors = []
+ code = self.code
+ tries = 0
+ while True:
+ try:
+ if tries == 0 and self.resource is not None and \
+ self.resource.read() == code:
+ return self.pycore.resource_to_pyobject(self.resource,
+ force_errors=True)
+ return self.pycore.get_string_module(
+ code, resource=self.resource, force_errors=True)
+ except exceptions.ModuleSyntaxError, e:
+ if tries < self.maxfixes:
+ tries += 1
+ self.commenter.comment(e.lineno)
+ code = '\n'.join(self.commenter.lines)
+ errors.append(' * line %s: %s ... fixed' % (e.lineno,
+ e.message_))
+ else:
+ errors.append(' * line %s: %s ... raised!' % (e.lineno,
+ e.message_))
+ new_message = ('\nSyntax errors in file %s:\n' % e.filename) \
+ + '\n'.join(errors)
+ raise exceptions.ModuleSyntaxError(e.filename, e.lineno,
+ new_message)
+
+ @property
+ @utils.saveit
+ def commenter(self):
+ return _Commenter(self.code)
+
+ def pyname_at(self, offset):
+ pymodule = self.get_pymodule()
+ def old_pyname():
+ word_finder = worder.Worder(self.code, True)
+ expression = word_finder.get_primary_at(offset)
+ expression = expression.replace('\\\n', ' ').replace('\n', ' ')
+ lineno = self.code.count('\n', 0, offset)
+ scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
+ return rope.base.evaluate.eval_str(scope, expression)
+ new_code = pymodule.source_code
+ def new_pyname():
+ newoffset = self.commenter.transfered_offset(offset)
+ return rope.base.evaluate.eval_location(pymodule, newoffset)
+ if new_code.startswith(self.code[:offset + 1]):
+ return new_pyname()
+ result = old_pyname()
+ if result is None:
+ return new_pyname()
+ return result
+
+
+class _Commenter(object):
+
+ def __init__(self, code):
+ self.code = code
+ self.lines = self.code.split('\n')
+ self.lines.append('\n')
+ self.origs = range(len(self.lines) + 1)
+ self.diffs = [0] * (len(self.lines) + 1)
+
+ def comment(self, lineno):
+ start = _logical_start(self.lines, lineno, check_prev=True) - 1
+ # using self._get_stmt_end() instead of self._get_block_end()
+ # to lower commented lines
+ end = self._get_stmt_end(start)
+ indents = _get_line_indents(self.lines[start])
+ if 0 < start:
+ last_lineno = self._last_non_blank(start - 1)
+ last_line = self.lines[last_lineno]
+ if last_line.rstrip().endswith(':'):
+ indents = _get_line_indents(last_line) + 4
+ self._set(start, ' ' * indents + 'pass')
+ for line in range(start + 1, end + 1):
+ self._set(line, self.lines[start])
+ self._fix_incomplete_try_blocks(lineno, indents)
+
+ def transfered_offset(self, offset):
+ lineno = self.code.count('\n', 0, offset)
+ diff = sum(self.diffs[:lineno])
+ return offset + diff
+
+ def _last_non_blank(self, start):
+ while start > 0 and self.lines[start].strip() == '':
+ start -= 1
+ return start
+
+ def _get_block_end(self, lineno):
+ end_line = lineno
+ base_indents = _get_line_indents(self.lines[lineno])
+ for i in range(lineno + 1, len(self.lines)):
+ if _get_line_indents(self.lines[i]) >= base_indents:
+ end_line = i
+ else:
+ break
+ return end_line
+
+ def _get_stmt_end(self, lineno):
+ end_line = lineno
+ base_indents = _get_line_indents(self.lines[lineno])
+ for i in range(lineno + 1, len(self.lines)):
+ if _get_line_indents(self.lines[i]) <= base_indents:
+ return i - 1
+ return lineno
+
+ def _fix_incomplete_try_blocks(self, lineno, indents):
+ block_start = lineno
+ last_indents = current_indents = indents
+ while block_start > 0:
+ block_start = rope.base.codeanalyze.get_block_start(
+ ArrayLinesAdapter(self.lines), block_start) - 1
+ if self.lines[block_start].strip().startswith('try:'):
+ indents = _get_line_indents(self.lines[block_start])
+ if indents > last_indents:
+ continue
+ last_indents = indents
+ block_end = self._find_matching_deindent(block_start)
+ line = self.lines[block_end].strip()
+ if not (line.startswith('finally:') or
+ line.startswith('except ') or
+ line.startswith('except:')):
+ self._insert(block_end, ' ' * indents + 'finally:')
+ self._insert(block_end + 1, ' ' * indents + ' pass')
+
+ def _find_matching_deindent(self, line_number):
+ indents = _get_line_indents(self.lines[line_number])
+ current_line = line_number + 1
+ while current_line < len(self.lines):
+ line = self.lines[current_line]
+ if not line.strip().startswith('#') and not line.strip() == '':
+ # HACK: We should have used logical lines here
+ if _get_line_indents(self.lines[current_line]) <= indents:
+ return current_line
+ current_line += 1
+ return len(self.lines) - 1
+
+ def _set(self, lineno, line):
+ self.diffs[self.origs[lineno]] += len(line) - len(self.lines[lineno])
+ self.lines[lineno] = line
+
+ def _insert(self, lineno, line):
+ self.diffs[self.origs[lineno]] += len(line) + 1
+ self.origs.insert(lineno, self.origs[lineno])
+ self.lines.insert(lineno, line)
+
+def _logical_start(lines, lineno, check_prev=False):
+ logical_finder = LogicalLineFinder(ArrayLinesAdapter(lines))
+ if check_prev:
+ prev = lineno - 1
+ while prev > 0:
+ start, end = logical_finder.logical_line_in(prev)
+ if end is None or start <= lineno < end:
+ return start
+ if start <= prev:
+ break
+ prev -= 1
+ return logical_finder.logical_line_in(lineno)[0]
+
+
+def _get_line_indents(line):
+ return rope.base.codeanalyze.count_line_indents(line)
diff --git a/vim/eclim/autoload/eclim/python/rope/contrib/generate.py b/vim/eclim/autoload/eclim/python/rope/contrib/generate.py
@@ -0,0 +1,355 @@
+import rope.base.evaluate
+from rope.base import change, pyobjects, exceptions, pynames, worder, codeanalyze
+from rope.refactor import sourceutils, importutils, functionutils, suites
+
+
+def create_generate(kind, project, resource, offset):
+ """A factory for creating `Generate` objects
+
+ `kind` can be 'variable', 'function', 'class', 'module' or
+ 'package'.
+
+ """
+ generate = eval('Generate' + kind.title())
+ return generate(project, resource, offset)
+
+
+def create_module(project, name, sourcefolder=None):
+ """Creates a module and returns a `rope.base.resources.File`"""
+ if sourcefolder is None:
+ sourcefolder = project.root
+ packages = name.split('.')
+ parent = sourcefolder
+ for package in packages[:-1]:
+ parent = parent.get_child(package)
+ return parent.create_file(packages[-1] + '.py')
+
+def create_package(project, name, sourcefolder=None):
+ """Creates a package and returns a `rope.base.resources.Folder`"""
+ if sourcefolder is None:
+ sourcefolder = project.root
+ packages = name.split('.')
+ parent = sourcefolder
+ for package in packages[:-1]:
+ parent = parent.get_child(package)
+ made_packages = parent.create_folder(packages[-1])
+ made_packages.create_file('__init__.py')
+ return made_packages
+
+
+class _Generate(object):
+
+ def __init__(self, project, resource, offset):
+ self.project = project
+ self.resource = resource
+ self.info = self._generate_info(project, resource, offset)
+ self.name = self.info.get_name()
+ self._check_exceptional_conditions()
+
+ def _generate_info(self, project, resource, offset):
+ return _GenerationInfo(project.pycore, resource, offset)
+
+ def _check_exceptional_conditions(self):
+ if self.info.element_already_exists():
+ raise exceptions.RefactoringError(
+ 'Element <%s> already exists.' % self.name)
+ if not self.info.primary_is_found():
+ raise exceptions.RefactoringError(
+ 'Cannot determine the scope <%s> should be defined in.' % self.name)
+
+ def get_changes(self):
+ changes = change.ChangeSet('Generate %s <%s>' %
+ (self._get_element_kind(), self.name))
+ indents = self.info.get_scope_indents()
+ blanks = self.info.get_blank_lines()
+ base_definition = sourceutils.fix_indentation(self._get_element(), indents)
+ definition = '\n' * blanks[0] + base_definition + '\n' * blanks[1]
+
+ resource = self.info.get_insertion_resource()
+ start, end = self.info.get_insertion_offsets()
+
+ collector = codeanalyze.ChangeCollector(resource.read())
+ collector.add_change(start, end, definition)
+ changes.add_change(change.ChangeContents(
+ resource, collector.get_changed()))
+ return changes
+
+ def get_location(self):
+ return (self.info.get_insertion_resource(),
+ self.info.get_insertion_lineno())
+
+ def _get_element_kind(self):
+ raise NotImplementedError()
+
+ def _get_element(self):
+ raise NotImplementedError()
+
+
+class GenerateFunction(_Generate):
+
+ def _generate_info(self, project, resource, offset):
+ return _FunctionGenerationInfo(project.pycore, resource, offset)
+
+ def _get_element(self):
+ decorator = ''
+ args = []
+ if self.info.is_static_method():
+ decorator = '@staticmethod\n'
+ if self.info.is_method() or self.info.is_constructor() or \
+ self.info.is_instance():
+ args.append('self')
+ args.extend(self.info.get_passed_args())
+ definition = '%sdef %s(%s):\n pass\n' % (decorator, self.name,
+ ', '.join(args))
+ return definition
+
+ def _get_element_kind(self):
+ return 'Function'
+
+
+class GenerateVariable(_Generate):
+
+ def _get_element(self):
+ return '%s = None\n' % self.name
+
+ def _get_element_kind(self):
+ return 'Variable'
+
+
+class GenerateClass(_Generate):
+
+ def _get_element(self):
+ return 'class %s(object):\n pass\n' % self.name
+
+ def _get_element_kind(self):
+ return 'Class'
+
+
+class GenerateModule(_Generate):
+
+ def get_changes(self):
+ package = self.info.get_package()
+ changes = change.ChangeSet('Generate Module <%s>' % self.name)
+ new_resource = self.project.get_file('%s/%s.py' % (package.path, self.name))
+ if new_resource.exists():
+ raise exceptions.RefactoringError(
+ 'Module <%s> already exists' % new_resource.path)
+ changes.add_change(change.CreateResource(new_resource))
+ changes.add_change(_add_import_to_module(
+ self.project.pycore, self.resource, new_resource))
+ return changes
+
+ def get_location(self):
+ package = self.info.get_package()
+ return (package.get_child('%s.py' % self.name) , 1)
+
+
+class GeneratePackage(_Generate):
+
+ def get_changes(self):
+ package = self.info.get_package()
+ changes = change.ChangeSet('Generate Package <%s>' % self.name)
+ new_resource = self.project.get_folder('%s/%s' % (package.path, self.name))
+ if new_resource.exists():
+ raise exceptions.RefactoringError(
+ 'Package <%s> already exists' % new_resource.path)
+ changes.add_change(change.CreateResource(new_resource))
+ changes.add_change(_add_import_to_module(
+ self.project.pycore, self.resource, new_resource))
+ child = self.project.get_folder(package.path + '/' + self.name)
+ changes.add_change(change.CreateFile(child, '__init__.py'))
+ return changes
+
+ def get_location(self):
+ package = self.info.get_package()
+ child = package.get_child(self.name)
+ return (child.get_child('__init__.py') , 1)
+
+
+def _add_import_to_module(pycore, resource, imported):
+ pymodule = pycore.resource_to_pyobject(resource)
+ import_tools = importutils.ImportTools(pycore)
+ module_imports = import_tools.module_imports(pymodule)
+ module_name = pycore.modname(imported)
+ new_import = importutils.NormalImport(((module_name, None), ))
+ module_imports.add_import(new_import)
+ return change.ChangeContents(resource, module_imports.get_changed_source())
+
+
+class _GenerationInfo(object):
+
+ def __init__(self, pycore, resource, offset):
+ self.pycore = pycore
+ self.resource = resource
+ self.offset = offset
+ self.source_pymodule = self.pycore.resource_to_pyobject(resource)
+ finder = rope.base.evaluate.ScopeNameFinder(self.source_pymodule)
+ self.primary, self.pyname = finder.get_primary_and_pyname_at(offset)
+ self._init_fields()
+
+ def _init_fields(self):
+ self.source_scope = self._get_source_scope()
+ self.goal_scope = self._get_goal_scope()
+ self.goal_pymodule = self._get_goal_module(self.goal_scope)
+
+ def _get_goal_scope(self):
+ if self.primary is None:
+ return self._get_source_scope()
+ pyobject = self.primary.get_object()
+ if isinstance(pyobject, pyobjects.PyDefinedObject):
+ return pyobject.get_scope()
+ elif isinstance(pyobject.get_type(), pyobjects.PyClass):
+ return pyobject.get_type().get_scope()
+
+ def _get_goal_module(self, scope):
+ if scope is None:
+ return
+ while scope.parent is not None:
+ scope = scope.parent
+ return scope.pyobject
+
+ def _get_source_scope(self):
+ module_scope = self.source_pymodule.get_scope()
+ lineno = self.source_pymodule.lines.get_line_number(self.offset)
+ return module_scope.get_inner_scope_for_line(lineno)
+
+ def get_insertion_lineno(self):
+ lines = self.goal_pymodule.lines
+ if self.goal_scope == self.source_scope:
+ line_finder = self.goal_pymodule.logical_lines
+ lineno = lines.get_line_number(self.offset)
+ lineno = line_finder.logical_line_in(lineno)[0]
+ root = suites.ast_suite_tree(self.goal_scope.pyobject.get_ast())
+ suite = root.find_suite(lineno)
+ indents = sourceutils.get_indents(lines, lineno)
+ while self.get_scope_indents() < indents:
+ lineno = suite.get_start()
+ indents = sourceutils.get_indents(lines, lineno)
+ suite = suite.parent
+ return lineno
+ else:
+ return min(self.goal_scope.get_end() + 1, lines.length())
+
+ def get_insertion_resource(self):
+ return self.goal_pymodule.get_resource()
+
+ def get_insertion_offsets(self):
+ if self.goal_scope.get_kind() == 'Class':
+ start, end = sourceutils.get_body_region(self.goal_scope.pyobject)
+ if self.goal_pymodule.source_code[start:end].strip() == 'pass':
+ return start, end
+ lines = self.goal_pymodule.lines
+ start = lines.get_line_start(self.get_insertion_lineno())
+ return (start, start)
+
+ def get_scope_indents(self):
+ if self.goal_scope.get_kind() == 'Module':
+ return 0
+ return sourceutils.get_indents(self.goal_pymodule.lines,
+ self.goal_scope.get_start()) + 4
+
+ def get_blank_lines(self):
+ if self.goal_scope.get_kind() == 'Module':
+ base_blanks = 2
+ if self.goal_pymodule.source_code.strip() == '':
+ base_blanks = 0
+ if self.goal_scope.get_kind() == 'Class':
+ base_blanks = 1
+ if self.goal_scope.get_kind() == 'Function':
+ base_blanks = 0
+ if self.goal_scope == self.source_scope:
+ return (0, base_blanks)
+ return (base_blanks, 0)
+
+ def get_package(self):
+ primary = self.primary
+ if self.primary is None:
+ return self.pycore.get_source_folders()[0]
+ if isinstance(primary.get_object(), pyobjects.PyPackage):
+ return primary.get_object().get_resource()
+ raise exceptions.RefactoringError(
+ 'A module/package can be only created in a package.')
+
+ def primary_is_found(self):
+ return self.goal_scope is not None
+
+ def element_already_exists(self):
+ if self.pyname is None or isinstance(self.pyname, pynames.UnboundName):
+ return False
+ return self.get_name() in self.goal_scope.get_defined_names()
+
+ def get_name(self):
+ return worder.get_name_at(self.resource, self.offset)
+
+
+class _FunctionGenerationInfo(_GenerationInfo):
+
+ def _get_goal_scope(self):
+ if self.is_constructor():
+ return self.pyname.get_object().get_scope()
+ if self.is_instance():
+ return self.pyname.get_object().get_type().get_scope()
+ if self.primary is None:
+ return self._get_source_scope()
+ pyobject = self.primary.get_object()
+ if isinstance(pyobject, pyobjects.PyDefinedObject):
+ return pyobject.get_scope()
+ elif isinstance(pyobject.get_type(), pyobjects.PyClass):
+ return pyobject.get_type().get_scope()
+
+ def element_already_exists(self):
+ if self.pyname is None or isinstance(self.pyname, pynames.UnboundName):
+ return False
+ return self.get_name() in self.goal_scope.get_defined_names()
+
+ def is_static_method(self):
+ return self.primary is not None and \
+ isinstance(self.primary.get_object(), pyobjects.PyClass)
+
+ def is_method(self):
+ return self.primary is not None and \
+ isinstance(self.primary.get_object().get_type(), pyobjects.PyClass)
+
+ def is_constructor(self):
+ return self.pyname is not None and \
+ isinstance(self.pyname.get_object(), pyobjects.PyClass)
+
+ def is_instance(self):
+ if self.pyname is None:
+ return False
+ pyobject = self.pyname.get_object()
+ return isinstance(pyobject.get_type(), pyobjects.PyClass)
+
+ def get_name(self):
+ if self.is_constructor():
+ return '__init__'
+ if self.is_instance():
+ return '__call__'
+ return worder.get_name_at(self.resource, self.offset)
+
+ def get_passed_args(self):
+ result = []
+ source = self.source_pymodule.source_code
+ finder = worder.Worder(source)
+ if finder.is_a_function_being_called(self.offset):
+ start, end = finder.get_primary_range(self.offset)
+ parens_start, parens_end = finder.get_word_parens_range(end - 1)
+ call = source[start:parens_end]
+ parser = functionutils._FunctionParser(call, False)
+ args, keywords = parser.get_parameters()
+ for arg in args:
+ if self._is_id(arg):
+ result.append(arg)
+ else:
+ result.append('arg%d' % len(result))
+ for name, value in keywords:
+ result.append(name)
+ return result
+
+ def _is_id(self, arg):
+ def id_or_underline(c):
+ return c.isalpha() or c == '_'
+ for c in arg:
+ if not id_or_underline(c) and not c.isdigit():
+ return False
+ return id_or_underline(arg[0])
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/__init__.py b/vim/eclim/autoload/eclim/python/rope/refactor/__init__.py
@@ -0,0 +1,55 @@
+"""rope refactor package
+
+This package contains modules that perform python refactorings.
+Refactoring classes perform refactorings in 4 steps:
+
+1. Collect some data for performing the refactoring and use them
+ to construct a refactoring class. Like::
+
+ renamer = Rename(project, resource, offset)
+
+2. Some refactorings give you useful information about the
+ refactoring after their construction. Like::
+
+ print(renamer.get_old_name())
+
+3. Give the refactoring class more information about how to
+ perform the refactoring and get the changes this refactoring is
+ going to make. This is done by calling `get_changes` method of the
+ refactoring class. Like::
+
+ changes = renamer.get_changes(new_name)
+
+4. You can commit the changes. Like::
+
+ project.do(changes)
+
+These steps are like the steps IDEs usually do for performing a
+refactoring. These are the things an IDE does in each step:
+
+1. Construct a refactoring object by giving it information like
+ resource, offset and ... . Some of the refactoring problems (like
+ performing rename refactoring on language keywords) can be reported
+ here.
+2. Print some information about the refactoring and ask the user
+ about the information that are necessary for completing the
+ refactoring (like new name).
+3. Call the `get_changes` by passing it information asked from
+ the user (if necessary) and get and preview the changes returned by
+ it.
+4. perform the refactoring.
+
+From ``0.5m5`` release the `get_changes()` method of some time-
+consuming refactorings take an optional `rope.base.taskhandle.
+TaskHandle` parameter. You can use this object for stopping or
+monitoring the progress of refactorings.
+
+"""
+from rope.refactor.importutils import ImportOrganizer
+from rope.refactor.topackage import ModuleToPackage
+
+
+__all__ = ['rename', 'move', 'inline', 'extract', 'restructure', 'topackage',
+ 'importutils', 'usefunction', 'change_signature',
+ 'encapsulate_field', 'introduce_factory', 'introduce_parameter',
+ 'localtofield', 'method_object', 'multiproject']
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/change_signature.py b/vim/eclim/autoload/eclim/python/rope/refactor/change_signature.py
@@ -0,0 +1,342 @@
+import copy
+
+import rope.base.exceptions
+from rope.base import pyobjects, taskhandle, evaluate, worder, codeanalyze, utils
+from rope.base.change import ChangeContents, ChangeSet
+from rope.refactor import occurrences, functionutils
+
+
+class ChangeSignature(object):
+
+ def __init__(self, project, resource, offset):
+ self.pycore = project.pycore
+ self.resource = resource
+ self.offset = offset
+ self._set_name_and_pyname()
+ if self.pyname is None or self.pyname.get_object() is None or \
+ not isinstance(self.pyname.get_object(), pyobjects.PyFunction):
+ raise rope.base.exceptions.RefactoringError(
+ 'Change method signature should be performed on functions')
+
+ def _set_name_and_pyname(self):
+ self.name = worder.get_name_at(self.resource, self.offset)
+ this_pymodule = self.pycore.resource_to_pyobject(self.resource)
+ self.primary, self.pyname = evaluate.eval_location2(
+ this_pymodule, self.offset)
+ if self.pyname is None:
+ return
+ pyobject = self.pyname.get_object()
+ if isinstance(pyobject, pyobjects.PyClass) and \
+ '__init__' in pyobject:
+ self.pyname = pyobject['__init__']
+ self.name = '__init__'
+ pyobject = self.pyname.get_object()
+ self.others = None
+ if self.name == '__init__' and \
+ isinstance(pyobject, pyobjects.PyFunction) and \
+ isinstance(pyobject.parent, pyobjects.PyClass):
+ pyclass = pyobject.parent
+ self.others = (pyclass.get_name(),
+ pyclass.parent[pyclass.get_name()])
+
+ def _change_calls(self, call_changer, in_hierarchy=None, resources=None,
+ handle=taskhandle.NullTaskHandle()):
+ if resources is None:
+ resources = self.pycore.get_python_files()
+ changes = ChangeSet('Changing signature of <%s>' % self.name)
+ job_set = handle.create_jobset('Collecting Changes', len(resources))
+ finder = occurrences.create_finder(
+ self.pycore, self.name, self.pyname, instance=self.primary,
+ in_hierarchy=in_hierarchy and self.is_method())
+ if self.others:
+ name, pyname = self.others
+ constructor_finder = occurrences.create_finder(
+ self.pycore, name, pyname, only_calls=True)
+ finder = _MultipleFinders([finder, constructor_finder])
+ for file in resources:
+ job_set.started_job(file.path)
+ change_calls = _ChangeCallsInModule(
+ self.pycore, finder, file, call_changer)
+ changed_file = change_calls.get_changed_module()
+ if changed_file is not None:
+ changes.add_change(ChangeContents(file, changed_file))
+ job_set.finished_job()
+ return changes
+
+ def get_args(self):
+ """Get function arguments.
+
+ Return a list of ``(name, default)`` tuples for all but star
+ and double star arguments. For arguments that don't have a
+ default, `None` will be used.
+ """
+ return self._definfo().args_with_defaults
+
+ def is_method(self):
+ pyfunction = self.pyname.get_object()
+ return isinstance(pyfunction.parent, pyobjects.PyClass)
+
+ @utils.deprecated('Use `ChangeSignature.get_args()` instead')
+ def get_definition_info(self):
+ return self._definfo()
+
+ def _definfo(self):
+ return functionutils.DefinitionInfo.read(self.pyname.get_object())
+
+ @utils.deprecated()
+ def normalize(self):
+ changer = _FunctionChangers(
+ self.pyname.get_object(), self.get_definition_info(),
+ [ArgumentNormalizer()])
+ return self._change_calls(changer)
+
+ @utils.deprecated()
+ def remove(self, index):
+ changer = _FunctionChangers(
+ self.pyname.get_object(), self.get_definition_info(),
+ [ArgumentRemover(index)])
+ return self._change_calls(changer)
+
+ @utils.deprecated()
+ def add(self, index, name, default=None, value=None):
+ changer = _FunctionChangers(
+ self.pyname.get_object(), self.get_definition_info(),
+ [ArgumentAdder(index, name, default, value)])
+ return self._change_calls(changer)
+
+ @utils.deprecated()
+ def inline_default(self, index):
+ changer = _FunctionChangers(
+ self.pyname.get_object(), self.get_definition_info(),
+ [ArgumentDefaultInliner(index)])
+ return self._change_calls(changer)
+
+ @utils.deprecated()
+ def reorder(self, new_ordering):
+ changer = _FunctionChangers(
+ self.pyname.get_object(), self.get_definition_info(),
+ [ArgumentReorderer(new_ordering)])
+ return self._change_calls(changer)
+
+ def get_changes(self, changers, in_hierarchy=False, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Get changes caused by this refactoring
+
+ `changers` is a list of `_ArgumentChanger`\s. If `in_hierarchy`
+ is `True` the changers are applyed to all matching methods in
+ the class hierarchy.
+ `resources` can be a list of `rope.base.resource.File`\s that
+ should be searched for occurrences; if `None` all python files
+ in the project are searched.
+
+ """
+ function_changer = _FunctionChangers(self.pyname.get_object(),
+ self._definfo(), changers)
+ return self._change_calls(function_changer, in_hierarchy,
+ resources, task_handle)
+
+
+class _FunctionChangers(object):
+
+ def __init__(self, pyfunction, definition_info, changers=None):
+ self.pyfunction = pyfunction
+ self.definition_info = definition_info
+ self.changers = changers
+ self.changed_definition_infos = self._get_changed_definition_infos()
+
+ def _get_changed_definition_infos(self):
+ result = []
+ definition_info = self.definition_info
+ result.append(definition_info)
+ for changer in self.changers:
+ definition_info = copy.deepcopy(definition_info)
+ changer.change_definition_info(definition_info)
+ result.append(definition_info)
+ return result
+
+ def change_definition(self, call):
+ return self.changed_definition_infos[-1].to_string()
+
+ def change_call(self, primary, pyname, call):
+ call_info = functionutils.CallInfo.read(
+ primary, pyname, self.definition_info, call)
+ mapping = functionutils.ArgumentMapping(self.definition_info, call_info)
+
+ for definition_info, changer in zip(self.changed_definition_infos, self.changers):
+ changer.change_argument_mapping(definition_info, mapping)
+
+ return mapping.to_call_info(self.changed_definition_infos[-1]).to_string()
+
+
+class _ArgumentChanger(object):
+
+ def change_definition_info(self, definition_info):
+ pass
+
+ def change_argument_mapping(self, definition_info, argument_mapping):
+ pass
+
+
+class ArgumentNormalizer(_ArgumentChanger):
+ pass
+
+
+class ArgumentRemover(_ArgumentChanger):
+
+ def __init__(self, index):
+ self.index = index
+
+ def change_definition_info(self, call_info):
+ if self.index < len(call_info.args_with_defaults):
+ del call_info.args_with_defaults[self.index]
+ elif self.index == len(call_info.args_with_defaults) and \
+ call_info.args_arg is not None:
+ call_info.args_arg = None
+ elif (self.index == len(call_info.args_with_defaults) and
+ call_info.args_arg is None and call_info.keywords_arg is not None) or \
+ (self.index == len(call_info.args_with_defaults) + 1 and
+ call_info.args_arg is not None and call_info.keywords_arg is not None):
+ call_info.keywords_arg = None
+
+ def change_argument_mapping(self, definition_info, mapping):
+ if self.index < len(definition_info.args_with_defaults):
+ name = definition_info.args_with_defaults[0]
+ if name in mapping.param_dict:
+ del mapping.param_dict[name]
+
+
+class ArgumentAdder(_ArgumentChanger):
+
+ def __init__(self, index, name, default=None, value=None):
+ self.index = index
+ self.name = name
+ self.default = default
+ self.value = value
+
+ def change_definition_info(self, definition_info):
+ for pair in definition_info.args_with_defaults:
+ if pair[0] == self.name:
+ raise rope.base.exceptions.RefactoringError(
+ 'Adding duplicate parameter: <%s>.' % self.name)
+ definition_info.args_with_defaults.insert(self.index,
+ (self.name, self.default))
+
+ def change_argument_mapping(self, definition_info, mapping):
+ if self.value is not None:
+ mapping.param_dict[self.name] = self.value
+
+
+class ArgumentDefaultInliner(_ArgumentChanger):
+
+ def __init__(self, index):
+ self.index = index
+ self.remove = False
+
+ def change_definition_info(self, definition_info):
+ if self.remove:
+ definition_info.args_with_defaults[self.index] = \
+ (definition_info.args_with_defaults[self.index][0], None)
+
+ def change_argument_mapping(self, definition_info, mapping):
+ default = definition_info.args_with_defaults[self.index][1]
+ name = definition_info.args_with_defaults[self.index][0]
+ if default is not None and name not in mapping.param_dict:
+ mapping.param_dict[name] = default
+
+
+class ArgumentReorderer(_ArgumentChanger):
+
+ def __init__(self, new_order, autodef=None):
+ """Construct an `ArgumentReorderer`
+
+ Note that the `new_order` is a list containing the new
+ position of parameters; not the position each parameter
+ is going to be moved to. (changed in ``0.5m4``)
+
+ For example changing ``f(a, b, c)`` to ``f(c, a, b)``
+ requires passing ``[2, 0, 1]`` and *not* ``[1, 2, 0]``.
+
+ The `autodef` (automatic default) argument, forces rope to use
+ it as a default if a default is needed after the change. That
+ happens when an argument without default is moved after
+ another that has a default value. Note that `autodef` should
+ be a string or `None`; the latter disables adding automatic
+ default.
+
+ """
+ self.new_order = new_order
+ self.autodef = autodef
+
+ def change_definition_info(self, definition_info):
+ new_args = list(definition_info.args_with_defaults)
+ for new_index, index in enumerate(self.new_order):
+ new_args[new_index] = definition_info.args_with_defaults[index]
+ seen_default = False
+ for index, (arg, default) in enumerate(list(new_args)):
+ if default is not None:
+ seen_default = True
+ if seen_default and default is None and self.autodef is not None:
+ new_args[index] = (arg, self.autodef)
+ definition_info.args_with_defaults = new_args
+
+
+class _ChangeCallsInModule(object):
+
+ def __init__(self, pycore, occurrence_finder, resource, call_changer):
+ self.pycore = pycore
+ self.occurrence_finder = occurrence_finder
+ self.resource = resource
+ self.call_changer = call_changer
+
+ def get_changed_module(self):
+ word_finder = worder.Worder(self.source)
+ change_collector = codeanalyze.ChangeCollector(self.source)
+ for occurrence in self.occurrence_finder.find_occurrences(self.resource):
+ if not occurrence.is_called() and not occurrence.is_defined():
+ continue
+ start, end = occurrence.get_primary_range()
+ begin_parens, end_parens = word_finder.get_word_parens_range(end - 1)
+ if occurrence.is_called():
+ primary, pyname = occurrence.get_primary_and_pyname()
+ changed_call = self.call_changer.change_call(
+ primary, pyname, self.source[start:end_parens])
+ else:
+ changed_call = self.call_changer.change_definition(
+ self.source[start:end_parens])
+ if changed_call is not None:
+ change_collector.add_change(start, end_parens, changed_call)
+ return change_collector.get_changed()
+
+ @property
+ @utils.saveit
+ def pymodule(self):
+ return self.pycore.resource_to_pyobject(self.resource)
+
+ @property
+ @utils.saveit
+ def source(self):
+ if self.resource is not None:
+ return self.resource.read()
+ else:
+ return self.pymodule.source_code
+
+ @property
+ @utils.saveit
+ def lines(self):
+ return self.pymodule.lines
+
+
+class _MultipleFinders(object):
+
+ def __init__(self, finders):
+ self.finders = finders
+
+ def find_occurrences(self, resource=None, pymodule=None):
+ all_occurrences = []
+ for finder in self.finders:
+ all_occurrences.extend(finder.find_occurrences(resource, pymodule))
+ all_occurrences.sort(self._cmp_occurrences)
+ return all_occurrences
+
+ def _cmp_occurrences(self, o1, o2):
+ return cmp(o1.get_primary_range(), o2.get_primary_range())
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/encapsulate_field.py b/vim/eclim/autoload/eclim/python/rope/refactor/encapsulate_field.py
@@ -0,0 +1,202 @@
+from rope.base import pynames, taskhandle, evaluate, exceptions, worder, utils
+from rope.base.change import ChangeSet, ChangeContents
+from rope.refactor import sourceutils, occurrences
+
+
+class EncapsulateField(object):
+
+ def __init__(self, project, resource, offset):
+ self.pycore = project.pycore
+ self.name = worder.get_name_at(resource, offset)
+ this_pymodule = self.pycore.resource_to_pyobject(resource)
+ self.pyname = evaluate.eval_location(this_pymodule, offset)
+ if not self._is_an_attribute(self.pyname):
+ raise exceptions.RefactoringError(
+ 'Encapsulate field should be performed on class attributes.')
+ self.resource = self.pyname.get_definition_location()[0].get_resource()
+
+ def get_changes(self, getter=None, setter=None, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Get the changes this refactoring makes
+
+ If `getter` is not `None`, that will be the name of the
+ getter, otherwise ``get_${field_name}`` will be used. The
+ same is true for `setter` and if it is None set_${field_name} is
+ used.
+
+ `resources` can be a list of `rope.base.resource.File`\s that
+ the refactoring should be applied on; if `None` all python
+ files in the project are searched.
+
+ """
+ if resources is None:
+ resources = self.pycore.get_python_files()
+ changes = ChangeSet('Encapsulate field <%s>' % self.name)
+ job_set = task_handle.create_jobset('Collecting Changes',
+ len(resources))
+ if getter is None:
+ getter = 'get_' + self.name
+ if setter is None:
+ setter = 'set_' + self.name
+ renamer = GetterSetterRenameInModule(
+ self.pycore, self.name, self.pyname, getter, setter)
+ for file in resources:
+ job_set.started_job(file.path)
+ if file == self.resource:
+ result = self._change_holding_module(changes, renamer,
+ getter, setter)
+ changes.add_change(ChangeContents(self.resource, result))
+ else:
+ result = renamer.get_changed_module(file)
+ if result is not None:
+ changes.add_change(ChangeContents(file, result))
+ job_set.finished_job()
+ return changes
+
+ def get_field_name(self):
+ """Get the name of the field to be encapsulated"""
+ return self.name
+
+ def _is_an_attribute(self, pyname):
+ if pyname is not None and isinstance(pyname, pynames.AssignedName):
+ pymodule, lineno = self.pyname.get_definition_location()
+ scope = pymodule.get_scope().\
+ get_inner_scope_for_line(lineno)
+ if scope.get_kind() == 'Class':
+ return pyname in scope.get_names().values()
+ parent = scope.parent
+ if parent is not None and parent.get_kind() == 'Class':
+ return pyname in parent.get_names().values()
+ return False
+
+ def _get_defining_class_scope(self):
+ defining_scope = self._get_defining_scope()
+ if defining_scope.get_kind() == 'Function':
+ defining_scope = defining_scope.parent
+ return defining_scope
+
+ def _get_defining_scope(self):
+ pymodule, line = self.pyname.get_definition_location()
+ return pymodule.get_scope().get_inner_scope_for_line(line)
+
+ def _change_holding_module(self, changes, renamer, getter, setter):
+ pymodule = self.pycore.resource_to_pyobject(self.resource)
+ class_scope = self._get_defining_class_scope()
+ defining_object = self._get_defining_scope().pyobject
+ start, end = sourceutils.get_body_region(defining_object)
+
+ new_source = renamer.get_changed_module(pymodule=pymodule,
+ skip_start=start, skip_end=end)
+ if new_source is not None:
+ pymodule = self.pycore.get_string_module(new_source, self.resource)
+ class_scope = pymodule.get_scope().\
+ get_inner_scope_for_line(class_scope.get_start())
+ indents = sourceutils.get_indent(self.pycore) * ' '
+ getter = 'def %s(self):\n%sreturn self.%s' % \
+ (getter, indents, self.name)
+ setter = 'def %s(self, value):\n%sself.%s = value' % \
+ (setter, indents, self.name)
+ new_source = sourceutils.add_methods(pymodule, class_scope,
+ [getter, setter])
+ return new_source
+
+
+class GetterSetterRenameInModule(object):
+
+ def __init__(self, pycore, name, pyname, getter, setter):
+ self.pycore = pycore
+ self.name = name
+ self.finder = occurrences.create_finder(pycore, name, pyname)
+ self.getter = getter
+ self.setter = setter
+
+ def get_changed_module(self, resource=None, pymodule=None,
+ skip_start=0, skip_end=0):
+ change_finder = _FindChangesForModule(self, resource, pymodule,
+ skip_start, skip_end)
+ return change_finder.get_changed_module()
+
+
+class _FindChangesForModule(object):
+
+ def __init__(self, finder, resource, pymodule, skip_start, skip_end):
+ self.pycore = finder.pycore
+ self.finder = finder.finder
+ self.getter = finder.getter
+ self.setter = finder.setter
+ self.resource = resource
+ self.pymodule = pymodule
+ self.last_modified = 0
+ self.last_set = None
+ self.set_index = None
+ self.skip_start = skip_start
+ self.skip_end = skip_end
+
+ def get_changed_module(self):
+ result = []
+ for occurrence in self.finder.find_occurrences(self.resource,
+ self.pymodule):
+ start, end = occurrence.get_word_range()
+ if self.skip_start <= start < self.skip_end:
+ continue
+ self._manage_writes(start, result)
+ result.append(self.source[self.last_modified:start])
+ if self._is_assigned_in_a_tuple_assignment(occurrence):
+ raise exceptions.RefactoringError(
+ 'Cannot handle tuple assignments in encapsulate field.')
+ if occurrence.is_written():
+ assignment_type = self.worder.get_assignment_type(start)
+ if assignment_type == '=':
+ result.append(self.setter + '(')
+ else:
+ var_name = self.source[occurrence.get_primary_range()[0]:
+ start] + self.getter + '()'
+ result.append(self.setter + '(' + var_name
+ + ' %s ' % assignment_type[:-1])
+ current_line = self.lines.get_line_number(start)
+ start_line, end_line = self.pymodule.logical_lines.\
+ logical_line_in(current_line)
+ self.last_set = self.lines.get_line_end(end_line)
+ end = self.source.index('=', end) + 1
+ self.set_index = len(result)
+ else:
+ result.append(self.getter + '()')
+ self.last_modified = end
+ if self.last_modified != 0:
+ self._manage_writes(len(self.source), result)
+ result.append(self.source[self.last_modified:])
+ return ''.join(result)
+ return None
+
+ def _manage_writes(self, offset, result):
+ if self.last_set is not None and self.last_set <= offset:
+ result.append(self.source[self.last_modified:self.last_set])
+ set_value = ''.join(result[self.set_index:]).strip()
+ del result[self.set_index:]
+ result.append(set_value + ')')
+ self.last_modified = self.last_set
+ self.last_set = None
+
+ def _is_assigned_in_a_tuple_assignment(self, occurance):
+ offset = occurance.get_word_range()[0]
+ return self.worder.is_assigned_in_a_tuple_assignment(offset)
+
+ @property
+ @utils.saveit
+ def source(self):
+ if self.resource is not None:
+ return self.resource.read()
+ else:
+ return self.pymodule.source_code
+
+ @property
+ @utils.saveit
+ def lines(self):
+ if self.pymodule is None:
+ self.pymodule = self.pycore.resource_to_pyobject(self.resource)
+ return self.pymodule.lines
+
+ @property
+ @utils.saveit
+ def worder(self):
+ return worder.Worder(self.source)
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/extract.py b/vim/eclim/autoload/eclim/python/rope/refactor/extract.py
@@ -0,0 +1,789 @@
+import re
+
+from rope.base import ast, codeanalyze
+from rope.base.change import ChangeSet, ChangeContents
+from rope.base.exceptions import RefactoringError
+from rope.refactor import (sourceutils, similarfinder,
+ patchedast, suites, usefunction)
+
+
+# Extract refactoring has lots of special cases. I tried to split it
+# to smaller parts to make it more manageable:
+#
+# _ExtractInfo: holds information about the refactoring; it is passed
+# to the parts that need to have information about the refactoring
+#
+# _ExtractCollector: merely saves all of the information necessary for
+# performing the refactoring.
+#
+# _DefinitionLocationFinder: finds where to insert the definition.
+#
+# _ExceptionalConditionChecker: checks for exceptional conditions in
+# which the refactoring cannot be applied.
+#
+# _ExtractMethodParts: generates the pieces of code (like definition)
+# needed for performing extract method.
+#
+# _ExtractVariableParts: like _ExtractMethodParts for variables.
+#
+# _ExtractPerformer: Uses above classes to collect refactoring
+# changes.
+#
+# There are a few more helper functions and classes used by above
+# classes.
+class _ExtractRefactoring(object):
+
+ def __init__(self, project, resource, start_offset, end_offset,
+ variable=False):
+ self.project = project
+ self.pycore = project.pycore
+ self.resource = resource
+ self.start_offset = self._fix_start(resource.read(), start_offset)
+ self.end_offset = self._fix_end(resource.read(), end_offset)
+
+ def _fix_start(self, source, offset):
+ while offset < len(source) and source[offset].isspace():
+ offset += 1
+ return offset
+
+ def _fix_end(self, source, offset):
+ while offset > 0 and source[offset - 1].isspace():
+ offset -= 1
+ return offset
+
+ def get_changes(self, extracted_name, similar=False, global_=False):
+ """Get the changes this refactoring makes
+
+ :parameters:
+ - `similar`: if `True`, similar expressions/statements are also
+ replaced.
+ - `global_`: if `True`, the extracted method/variable will
+ be global.
+
+ """
+ info = _ExtractInfo(
+ self.project, self.resource, self.start_offset, self.end_offset,
+ extracted_name, variable=self.kind == 'variable',
+ similar=similar, make_global=global_)
+ new_contents = _ExtractPerformer(info).extract()
+ changes = ChangeSet('Extract %s <%s>' % (self.kind,
+ extracted_name))
+ changes.add_change(ChangeContents(self.resource, new_contents))
+ return changes
+
+
+class ExtractMethod(_ExtractRefactoring):
+
+ def __init__(self, *args, **kwds):
+ super(ExtractMethod, self).__init__(*args, **kwds)
+
+ kind = 'method'
+
+
+class ExtractVariable(_ExtractRefactoring):
+
+ def __init__(self, *args, **kwds):
+ kwds = dict(kwds)
+ kwds['variable'] = True
+ super(ExtractVariable, self).__init__(*args, **kwds)
+
+ kind = 'variable'
+
+
+class _ExtractInfo(object):
+ """Holds information about the extract to be performed"""
+
+ def __init__(self, project, resource, start, end, new_name,
+ variable, similar, make_global):
+ self.pycore = project.pycore
+ self.resource = resource
+ self.pymodule = self.pycore.resource_to_pyobject(resource)
+ self.global_scope = self.pymodule.get_scope()
+ self.source = self.pymodule.source_code
+ self.lines = self.pymodule.lines
+ self.new_name = new_name
+ self.variable = variable
+ self.similar = similar
+ self._init_parts(start, end)
+ self._init_scope()
+ self.make_global = make_global
+
+ def _init_parts(self, start, end):
+ self.region = (self._choose_closest_line_end(start),
+ self._choose_closest_line_end(end, end=True))
+
+ start = self.logical_lines.logical_line_in(
+ self.lines.get_line_number(self.region[0]))[0]
+ end = self.logical_lines.logical_line_in(
+ self.lines.get_line_number(self.region[1]))[1]
+ self.region_lines = (start, end)
+
+ self.lines_region = (self.lines.get_line_start(self.region_lines[0]),
+ self.lines.get_line_end(self.region_lines[1]))
+
+ @property
+ def logical_lines(self):
+ return self.pymodule.logical_lines
+
+ def _init_scope(self):
+ start_line = self.region_lines[0]
+ scope = self.global_scope.get_inner_scope_for_line(start_line)
+ if scope.get_kind() != 'Module' and scope.get_start() == start_line:
+ scope = scope.parent
+ self.scope = scope
+ self.scope_region = self._get_scope_region(self.scope)
+
+ def _get_scope_region(self, scope):
+ return (self.lines.get_line_start(scope.get_start()),
+ self.lines.get_line_end(scope.get_end()) + 1)
+
+ def _choose_closest_line_end(self, offset, end=False):
+ lineno = self.lines.get_line_number(offset)
+ line_start = self.lines.get_line_start(lineno)
+ line_end = self.lines.get_line_end(lineno)
+ if self.source[line_start:offset].strip() == '':
+ if end:
+ return line_start - 1
+ else:
+ return line_start
+ elif self.source[offset:line_end].strip() == '':
+ return min(line_end, len(self.source))
+ return offset
+
+ @property
+ def one_line(self):
+ return self.region != self.lines_region and \
+ (self.logical_lines.logical_line_in(self.region_lines[0]) ==
+ self.logical_lines.logical_line_in(self.region_lines[1]))
+
+ @property
+ def global_(self):
+ return self.scope.parent is None
+
+ @property
+ def method(self):
+ return self.scope.parent is not None and \
+ self.scope.parent.get_kind() == 'Class'
+
+ @property
+ def indents(self):
+ return sourceutils.get_indents(self.pymodule.lines,
+ self.region_lines[0])
+
+ @property
+ def scope_indents(self):
+ if self.global_:
+ return 0
+ return sourceutils.get_indents(self.pymodule.lines,
+ self.scope.get_start())
+
+ @property
+ def extracted(self):
+ return self.source[self.region[0]:self.region[1]]
+
+ _returned = None
+ @property
+ def returned(self):
+ """Does the extracted piece contain return statement"""
+ if self._returned is None:
+ node = _parse_text(self.extracted)
+ self._returned = usefunction._returns_last(node)
+ return self._returned
+
+
+class _ExtractCollector(object):
+ """Collects information needed for performing the extract"""
+
+ def __init__(self, info):
+ self.definition = None
+ self.body_pattern = None
+ self.checks = {}
+ self.replacement_pattern = None
+ self.matches = None
+ self.replacements = None
+ self.definition_location = None
+
+
+class _ExtractPerformer(object):
+
+ def __init__(self, info):
+ self.info = info
+ _ExceptionalConditionChecker()(self.info)
+
+ def extract(self):
+ extract_info = self._collect_info()
+ content = codeanalyze.ChangeCollector(self.info.source)
+ definition = extract_info.definition
+ lineno, indents = extract_info.definition_location
+ offset = self.info.lines.get_line_start(lineno)
+ indented = sourceutils.fix_indentation(definition, indents)
+ content.add_change(offset, offset, indented)
+ self._replace_occurrences(content, extract_info)
+ return content.get_changed()
+
+ def _replace_occurrences(self, content, extract_info):
+ for match in extract_info.matches:
+ replacement = similarfinder.CodeTemplate(
+ extract_info.replacement_pattern)
+ mapping = {}
+ for name in replacement.get_names():
+ node = match.get_ast(name)
+ if node:
+ start, end = patchedast.node_region(match.get_ast(name))
+ mapping[name] = self.info.source[start:end]
+ else:
+ mapping[name] = name
+ region = match.get_region()
+ content.add_change(region[0], region[1],
+ replacement.substitute(mapping))
+
+ def _collect_info(self):
+ extract_collector = _ExtractCollector(self.info)
+ self._find_definition(extract_collector)
+ self._find_matches(extract_collector)
+ self._find_definition_location(extract_collector)
+ return extract_collector
+
+ def _find_matches(self, collector):
+ regions = self._where_to_search()
+ finder = similarfinder.SimilarFinder(self.info.pymodule)
+ matches = []
+ for start, end in regions:
+ matches.extend((finder.get_matches(collector.body_pattern,
+ collector.checks, start, end)))
+ collector.matches = matches
+
+ def _where_to_search(self):
+ if self.info.similar:
+ if self.info.make_global or self.info.global_:
+ return [(0, len(self.info.pymodule.source_code))]
+ if self.info.method and not self.info.variable:
+ class_scope = self.info.scope.parent
+ regions = []
+ method_kind = _get_function_kind(self.info.scope)
+ for scope in class_scope.get_scopes():
+ if method_kind == 'method' and \
+ _get_function_kind(scope) != 'method':
+ continue
+ start = self.info.lines.get_line_start(scope.get_start())
+ end = self.info.lines.get_line_end(scope.get_end())
+ regions.append((start, end))
+ return regions
+ else:
+ if self.info.variable:
+ return [self.info.scope_region]
+ else:
+ return [self.info._get_scope_region(self.info.scope.parent)]
+ else:
+ return [self.info.region]
+
+ def _find_definition_location(self, collector):
+ matched_lines = []
+ for match in collector.matches:
+ start = self.info.lines.get_line_number(match.get_region()[0])
+ start_line = self.info.logical_lines.logical_line_in(start)[0]
+ matched_lines.append(start_line)
+ location_finder = _DefinitionLocationFinder(self.info, matched_lines)
+ collector.definition_location = (location_finder.find_lineno(),
+ location_finder.find_indents())
+
+ def _find_definition(self, collector):
+ if self.info.variable:
+ parts = _ExtractVariableParts(self.info)
+ else:
+ parts = _ExtractMethodParts(self.info)
+ collector.definition = parts.get_definition()
+ collector.body_pattern = parts.get_body_pattern()
+ collector.replacement_pattern = parts.get_replacement_pattern()
+ collector.checks = parts.get_checks()
+
+
+class _DefinitionLocationFinder(object):
+
+ def __init__(self, info, matched_lines):
+ self.info = info
+ self.matched_lines = matched_lines
+ # This only happens when subexpressions cannot be matched
+ if not matched_lines:
+ self.matched_lines.append(self.info.region_lines[0])
+
+ def find_lineno(self):
+ if self.info.variable and not self.info.make_global:
+ return self._get_before_line()
+ if self.info.make_global or self.info.global_:
+ toplevel = self._find_toplevel(self.info.scope)
+ ast = self.info.pymodule.get_ast()
+ newlines = sorted(self.matched_lines + [toplevel.get_end() + 1])
+ return suites.find_visible(ast, newlines)
+ return self._get_after_scope()
+
+ def _find_toplevel(self, scope):
+ toplevel = scope
+ if toplevel.parent is not None:
+ while toplevel.parent.parent is not None:
+ toplevel = toplevel.parent
+ return toplevel
+
+ def find_indents(self):
+ if self.info.variable and not self.info.make_global:
+ return sourceutils.get_indents(self.info.lines,
+ self._get_before_line())
+ else:
+ if self.info.global_ or self.info.make_global:
+ return 0
+ return self.info.scope_indents
+
+ def _get_before_line(self):
+ ast = self.info.scope.pyobject.get_ast()
+ return suites.find_visible(ast, self.matched_lines)
+
+ def _get_after_scope(self):
+ return self.info.scope.get_end() + 1
+
+
+class _ExceptionalConditionChecker(object):
+
+ def __call__(self, info):
+ self.base_conditions(info)
+ if info.one_line:
+ self.one_line_conditions(info)
+ else:
+ self.multi_line_conditions(info)
+
+ def base_conditions(self, info):
+ if info.region[1] > info.scope_region[1]:
+ raise RefactoringError('Bad region selected for extract method')
+ end_line = info.region_lines[1]
+ end_scope = info.global_scope.get_inner_scope_for_line(end_line)
+ if end_scope != info.scope and end_scope.get_end() != end_line:
+ raise RefactoringError('Bad region selected for extract method')
+ try:
+ extracted = info.source[info.region[0]:info.region[1]]
+ if info.one_line:
+ extracted = '(%s)' % extracted
+ if _UnmatchedBreakOrContinueFinder.has_errors(extracted):
+ raise RefactoringError('A break/continue without having a '
+ 'matching for/while loop.')
+ except SyntaxError:
+ raise RefactoringError('Extracted piece should '
+ 'contain complete statements.')
+
+ def one_line_conditions(self, info):
+ if self._is_region_on_a_word(info):
+ raise RefactoringError('Should extract complete statements.')
+ if info.variable and not info.one_line:
+ raise RefactoringError('Extract variable should not '
+ 'span multiple lines.')
+
+ def multi_line_conditions(self, info):
+ node = _parse_text(info.source[info.region[0]:info.region[1]])
+ count = usefunction._return_count(node)
+ if count > 1:
+ raise RefactoringError('Extracted piece can have only one '
+ 'return statement.')
+ if usefunction._yield_count(node):
+ raise RefactoringError('Extracted piece cannot '
+ 'have yield statements.')
+ if count == 1 and not usefunction._returns_last(node):
+ raise RefactoringError('Return should be the last statement.')
+ if info.region != info.lines_region:
+ raise RefactoringError('Extracted piece should '
+ 'contain complete statements.')
+
+ def _is_region_on_a_word(self, info):
+ if info.region[0] > 0 and self._is_on_a_word(info, info.region[0] - 1) or \
+ self._is_on_a_word(info, info.region[1] - 1):
+ return True
+
+ def _is_on_a_word(self, info, offset):
+ prev = info.source[offset]
+ if not (prev.isalnum() or prev == '_') or \
+ offset + 1 == len(info.source):
+ return False
+ next = info.source[offset + 1]
+ return next.isalnum() or next == '_'
+
+
+class _ExtractMethodParts(object):
+
+ def __init__(self, info):
+ self.info = info
+ self.info_collector = self._create_info_collector()
+
+ def get_definition(self):
+ if self.info.global_:
+ return '\n%s\n' % self._get_function_definition()
+ else:
+ return '\n%s' % self._get_function_definition()
+
+ def get_replacement_pattern(self):
+ variables = []
+ variables.extend(self._find_function_arguments())
+ variables.extend(self._find_function_returns())
+ return similarfinder.make_pattern(self._get_call(), variables)
+
+ def get_body_pattern(self):
+ variables = []
+ variables.extend(self._find_function_arguments())
+ variables.extend(self._find_function_returns())
+ variables.extend(self._find_temps())
+ return similarfinder.make_pattern(self._get_body(), variables)
+
+ def _get_body(self):
+ result = sourceutils.fix_indentation(self.info.extracted, 0)
+ if self.info.one_line:
+ result = '(%s)' % result
+ return result
+
+ def _find_temps(self):
+ return usefunction.find_temps(self.info.pycore.project,
+ self._get_body())
+
+ def get_checks(self):
+ if self.info.method and not self.info.make_global:
+ if _get_function_kind(self.info.scope) == 'method':
+ class_name = similarfinder._pydefined_to_str(
+ self.info.scope.parent.pyobject)
+ return {self._get_self_name(): 'type=' + class_name}
+ return {}
+
+ def _create_info_collector(self):
+ zero = self.info.scope.get_start() - 1
+ start_line = self.info.region_lines[0] - zero
+ end_line = self.info.region_lines[1] - zero
+ info_collector = _FunctionInformationCollector(start_line, end_line,
+ self.info.global_)
+ body = self.info.source[self.info.scope_region[0]:
+ self.info.scope_region[1]]
+ node = _parse_text(body)
+ ast.walk(node, info_collector)
+ return info_collector
+
+ def _get_function_definition(self):
+ args = self._find_function_arguments()
+ returns = self._find_function_returns()
+ result = []
+ if self.info.method and not self.info.make_global and \
+ _get_function_kind(self.info.scope) != 'method':
+ result.append('@staticmethod\n')
+ result.append('def %s:\n' % self._get_function_signature(args))
+ unindented_body = self._get_unindented_function_body(returns)
+ indents = sourceutils.get_indent(self.info.pycore)
+ function_body = sourceutils.indent_lines(unindented_body, indents)
+ result.append(function_body)
+ definition = ''.join(result)
+
+ return definition + '\n'
+
+ def _get_function_signature(self, args):
+ args = list(args)
+ prefix = ''
+ if self._extracting_method():
+ self_name = self._get_self_name()
+ if self_name is None:
+ raise RefactoringError('Extracting a method from a function '
+ 'with no self argument.')
+ if self_name in args:
+ args.remove(self_name)
+ args.insert(0, self_name)
+ return prefix + self.info.new_name + \
+ '(%s)' % self._get_comma_form(args)
+
+ def _extracting_method(self):
+ return self.info.method and not self.info.make_global and \
+ _get_function_kind(self.info.scope) == 'method'
+
+ def _get_self_name(self):
+ param_names = self.info.scope.pyobject.get_param_names()
+ if param_names:
+ return param_names[0]
+
+ def _get_function_call(self, args):
+ prefix = ''
+ if self.info.method and not self.info.make_global:
+ if _get_function_kind(self.info.scope) == 'method':
+ self_name = self._get_self_name()
+ if self_name in args:
+ args.remove(self_name)
+ prefix = self_name + '.'
+ else:
+ prefix = self.info.scope.parent.pyobject.get_name() + '.'
+ return prefix + '%s(%s)' % (self.info.new_name,
+ self._get_comma_form(args))
+
+ def _get_comma_form(self, names):
+ result = ''
+ if names:
+ result += names[0]
+ for name in names[1:]:
+ result += ', ' + name
+ return result
+
+ def _get_call(self):
+ if self.info.one_line:
+ args = self._find_function_arguments()
+ return self._get_function_call(args)
+ args = self._find_function_arguments()
+ returns = self._find_function_returns()
+ call_prefix = ''
+ if returns:
+ call_prefix = self._get_comma_form(returns) + ' = '
+ if self.info.returned:
+ call_prefix = 'return '
+ return call_prefix + self._get_function_call(args)
+
+ def _find_function_arguments(self):
+ # if not make_global, do not pass any global names; they are
+ # all visible.
+ if self.info.global_ and not self.info.make_global:
+ return ()
+ if not self.info.one_line:
+ result = (self.info_collector.prewritten &
+ self.info_collector.read)
+ result |= (self.info_collector.prewritten &
+ self.info_collector.postread &
+ (self.info_collector.maybe_written -
+ self.info_collector.written))
+ return list(result)
+ start = self.info.region[0]
+ if start == self.info.lines_region[0]:
+ start = start + re.search('\S', self.info.extracted).start()
+ function_definition = self.info.source[start:self.info.region[1]]
+ read = _VariableReadsAndWritesFinder.find_reads_for_one_liners(
+ function_definition)
+ return list(self.info_collector.prewritten.intersection(read))
+
+ def _find_function_returns(self):
+ if self.info.one_line or self.info.returned:
+ return []
+ written = self.info_collector.written | \
+ self.info_collector.maybe_written
+ return list(written & self.info_collector.postread)
+
+ def _get_unindented_function_body(self, returns):
+ if self.info.one_line:
+ return 'return ' + _join_lines(self.info.extracted)
+ extracted_body = self.info.extracted
+ unindented_body = sourceutils.fix_indentation(extracted_body, 0)
+ if returns:
+ unindented_body += '\nreturn %s' % self._get_comma_form(returns)
+ return unindented_body
+
+
+class _ExtractVariableParts(object):
+
+ def __init__(self, info):
+ self.info = info
+
+ def get_definition(self):
+ result = self.info.new_name + ' = ' + \
+ _join_lines(self.info.extracted) + '\n'
+ return result
+
+ def get_body_pattern(self):
+ return '(%s)' % self.info.extracted.strip()
+
+ def get_replacement_pattern(self):
+ return self.info.new_name
+
+ def get_checks(self):
+ return {}
+
+
+class _FunctionInformationCollector(object):
+
+ def __init__(self, start, end, is_global):
+ self.start = start
+ self.end = end
+ self.is_global = is_global
+ self.prewritten = set()
+ self.maybe_written = set()
+ self.written = set()
+ self.read = set()
+ self.postread = set()
+ self.postwritten = set()
+ self.host_function = True
+ self.conditional = False
+
+ def _read_variable(self, name, lineno):
+ if self.start <= lineno <= self.end:
+ if name not in self.written:
+ self.read.add(name)
+ if self.end < lineno:
+ if name not in self.postwritten:
+ self.postread.add(name)
+
+ def _written_variable(self, name, lineno):
+ if self.start <= lineno <= self.end:
+ if self.conditional:
+ self.maybe_written.add(name)
+ else:
+ self.written.add(name)
+ if self.start > lineno:
+ self.prewritten.add(name)
+ if self.end < lineno:
+ self.postwritten.add(name)
+
+ def _FunctionDef(self, node):
+ if not self.is_global and self.host_function:
+ self.host_function = False
+ for name in _get_argnames(node.args):
+ self._written_variable(name, node.lineno)
+ for child in node.body:
+ ast.walk(child, self)
+ else:
+ self._written_variable(node.name, node.lineno)
+ visitor = _VariableReadsAndWritesFinder()
+ for child in node.body:
+ ast.walk(child, visitor)
+ for name in visitor.read - visitor.written:
+ self._read_variable(name, node.lineno)
+
+ def _Name(self, node):
+ if isinstance(node.ctx, (ast.Store, ast.AugStore)):
+ self._written_variable(node.id, node.lineno)
+ if not isinstance(node.ctx, ast.Store):
+ self._read_variable(node.id, node.lineno)
+
+ def _Assign(self, node):
+ ast.walk(node.value, self)
+ for child in node.targets:
+ ast.walk(child, self)
+
+ def _ClassDef(self, node):
+ self._written_variable(node.name, node.lineno)
+
+ def _handle_conditional_node(self, node):
+ self.conditional = True
+ try:
+ for child in ast.get_child_nodes(node):
+ ast.walk(child, self)
+ finally:
+ self.conditional = False
+
+ def _If(self, node):
+ self._handle_conditional_node(node)
+
+ def _While(self, node):
+ self._handle_conditional_node(node)
+
+ def _For(self, node):
+ self._handle_conditional_node(node)
+
+
+
+def _get_argnames(arguments):
+ result = [node.id for node in arguments.args
+ if isinstance(node, ast.Name)]
+ if arguments.vararg:
+ result.append(arguments.vararg)
+ if arguments.kwarg:
+ result.append(arguments.kwarg)
+ return result
+
+
+class _VariableReadsAndWritesFinder(object):
+
+ def __init__(self):
+ self.written = set()
+ self.read = set()
+
+ def _Name(self, node):
+ if isinstance(node.ctx, (ast.Store, ast.AugStore)):
+ self.written.add(node.id)
+ if not isinstance(node, ast.Store):
+ self.read.add(node.id)
+
+ def _FunctionDef(self, node):
+ self.written.add(node.name)
+ visitor = _VariableReadsAndWritesFinder()
+ for child in ast.get_child_nodes(node):
+ ast.walk(child, visitor)
+ self.read.update(visitor.read - visitor.written)
+
+ def _Class(self, node):
+ self.written.add(node.name)
+
+ @staticmethod
+ def find_reads_and_writes(code):
+ if code.strip() == '':
+ return set(), set()
+ if isinstance(code, unicode):
+ code = code.encode('utf-8')
+ node = _parse_text(code)
+ visitor = _VariableReadsAndWritesFinder()
+ ast.walk(node, visitor)
+ return visitor.read, visitor.written
+
+ @staticmethod
+ def find_reads_for_one_liners(code):
+ if code.strip() == '':
+ return set(), set()
+ node = _parse_text(code)
+ visitor = _VariableReadsAndWritesFinder()
+ ast.walk(node, visitor)
+ return visitor.read
+
+
+class _UnmatchedBreakOrContinueFinder(object):
+
+ def __init__(self):
+ self.error = False
+ self.loop_count = 0
+
+ def _For(self, node):
+ self.loop_encountered(node)
+
+ def _While(self, node):
+ self.loop_encountered(node)
+
+ def loop_encountered(self, node):
+ self.loop_count += 1
+ for child in node.body:
+ ast.walk(child, self)
+ self.loop_count -= 1
+ if node.orelse:
+ ast.walk(node.orelse, self)
+
+ def _Break(self, node):
+ self.check_loop()
+
+ def _Continue(self, node):
+ self.check_loop()
+
+ def check_loop(self):
+ if self.loop_count < 1:
+ self.error = True
+
+ def _FunctionDef(self, node):
+ pass
+
+ def _ClassDef(self, node):
+ pass
+
+ @staticmethod
+ def has_errors(code):
+ if code.strip() == '':
+ return False
+ node = _parse_text(code)
+ visitor = _UnmatchedBreakOrContinueFinder()
+ ast.walk(node, visitor)
+ return visitor.error
+
+def _get_function_kind(scope):
+ return scope.pyobject.get_kind()
+
+
+def _parse_text(body):
+ body = sourceutils.fix_indentation(body, 0)
+ node = ast.parse(body)
+ return node
+
+def _join_lines(code):
+ lines = []
+ for line in code.splitlines():
+ if line.endswith('\\'):
+ lines.append(line[:-1].strip())
+ else:
+ lines.append(line.strip())
+ return ' '.join(lines)
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/functionutils.py b/vim/eclim/autoload/eclim/python/rope/refactor/functionutils.py
@@ -0,0 +1,213 @@
+import rope.base.exceptions
+import rope.base.pyobjects
+from rope.base import worder
+
+
+class DefinitionInfo(object):
+
+ def __init__(self, function_name, is_method, args_with_defaults,
+ args_arg, keywords_arg):
+ self.function_name = function_name
+ self.is_method = is_method
+ self.args_with_defaults = args_with_defaults
+ self.args_arg = args_arg
+ self.keywords_arg = keywords_arg
+
+ def to_string(self):
+ return '%s(%s)' % (self.function_name, self.arguments_to_string())
+
+ def arguments_to_string(self, from_index=0):
+ params = []
+ for arg, default in self.args_with_defaults:
+ if default is not None:
+ params.append('%s=%s' % (arg, default))
+ else:
+ params.append(arg)
+ if self.args_arg is not None:
+ params.append('*' + self.args_arg)
+ if self.keywords_arg:
+ params.append('**' + self.keywords_arg)
+ return ', '.join(params[from_index:])
+
+ @staticmethod
+ def _read(pyfunction, code):
+ scope = pyfunction.get_scope()
+ parent = scope.parent
+ parameter_names = pyfunction.get_param_names()
+ is_method = pyfunction.get_kind() == 'method'
+ info = _FunctionParser(code, is_method)
+ args, keywords = info.get_parameters()
+ args_arg = None
+ keywords_arg = None
+ if args and args[-1].startswith('**'):
+ keywords_arg = args[-1][2:]
+ del args[-1]
+ if args and args[-1].startswith('*'):
+ args_arg = args[-1][1:]
+ del args[-1]
+ args_with_defaults = [(name, None) for name in args]
+ args_with_defaults.extend(keywords)
+ return DefinitionInfo(info.get_function_name(), is_method,
+ args_with_defaults, args_arg, keywords_arg)
+
+ @staticmethod
+ def read(pyfunction):
+ pymodule = pyfunction.get_module()
+ word_finder = worder.Worder(pymodule.source_code)
+ lineno = pyfunction.get_ast().lineno
+ start = pymodule.lines.get_line_start(lineno)
+ call = word_finder.get_function_and_args_in_header(start)
+ return DefinitionInfo._read(pyfunction, call)
+
+
+class CallInfo(object):
+
+ def __init__(self, function_name, args, keywords, args_arg,
+ keywords_arg, implicit_arg, constructor):
+ self.function_name = function_name
+ self.args = args
+ self.keywords = keywords
+ self.args_arg = args_arg
+ self.keywords_arg = keywords_arg
+ self.implicit_arg = implicit_arg
+ self.constructor = constructor
+
+ def to_string(self):
+ function = self.function_name
+ if self.implicit_arg:
+ function = self.args[0] + '.' + self.function_name
+ params = []
+ start = 0
+ if self.implicit_arg or self.constructor:
+ start = 1
+ if self.args[start:]:
+ params.extend(self.args[start:])
+ if self.keywords:
+ params.extend(['%s=%s' % (name, value) for name, value in self.keywords])
+ if self.args_arg is not None:
+ params.append('*' + self.args_arg)
+ if self.keywords_arg:
+ params.append('**' + self.keywords_arg)
+ return '%s(%s)' % (function, ', '.join(params))
+
+ @staticmethod
+ def read(primary, pyname, definition_info, code):
+ is_method_call = CallInfo._is_method_call(primary, pyname)
+ is_constructor = CallInfo._is_class(pyname)
+ is_classmethod = CallInfo._is_classmethod(pyname)
+ info = _FunctionParser(code, is_method_call or is_classmethod)
+ args, keywords = info.get_parameters()
+ args_arg = None
+ keywords_arg = None
+ if args and args[-1].startswith('**'):
+ keywords_arg = args[-1][2:]
+ del args[-1]
+ if args and args[-1].startswith('*'):
+ args_arg = args[-1][1:]
+ del args[-1]
+ if is_constructor:
+ args.insert(0, definition_info.args_with_defaults[0][0])
+ return CallInfo(info.get_function_name(), args, keywords, args_arg,
+ keywords_arg, is_method_call or is_classmethod,
+ is_constructor)
+
+ @staticmethod
+ def _is_method_call(primary, pyname):
+ return primary is not None and \
+ isinstance(primary.get_object().get_type(),
+ rope.base.pyobjects.PyClass) and \
+ CallInfo._is_method(pyname)
+
+ @staticmethod
+ def _is_class(pyname):
+ return pyname is not None and \
+ isinstance(pyname.get_object(),
+ rope.base.pyobjects.PyClass)
+
+ @staticmethod
+ def _is_method(pyname):
+ if pyname is not None and \
+ isinstance(pyname.get_object(), rope.base.pyobjects.PyFunction):
+ return pyname.get_object().get_kind() == 'method'
+ return False
+
+ @staticmethod
+ def _is_classmethod(pyname):
+ if pyname is not None and \
+ isinstance(pyname.get_object(), rope.base.pyobjects.PyFunction):
+ return pyname.get_object().get_kind() == 'classmethod'
+ return False
+
+
+class ArgumentMapping(object):
+
+ def __init__(self, definition_info, call_info):
+ self.call_info = call_info
+ self.param_dict = {}
+ self.keyword_args = []
+ self.args_arg = []
+ for index, value in enumerate(call_info.args):
+ if index < len(definition_info.args_with_defaults):
+ name = definition_info.args_with_defaults[index][0]
+ self.param_dict[name] = value
+ else:
+ self.args_arg.append(value)
+ for name, value in call_info.keywords:
+ index = -1
+ for pair in definition_info.args_with_defaults:
+ if pair[0] == name:
+ self.param_dict[name] = value
+ break
+ else:
+ self.keyword_args.append((name, value))
+
+ def to_call_info(self, definition_info):
+ args = []
+ keywords = []
+ for index in range(len(definition_info.args_with_defaults)):
+ name = definition_info.args_with_defaults[index][0]
+ if name in self.param_dict:
+ args.append(self.param_dict[name])
+ else:
+ for i in range(index, len(definition_info.args_with_defaults)):
+ name = definition_info.args_with_defaults[i][0]
+ if name in self.param_dict:
+ keywords.append((name, self.param_dict[name]))
+ break
+ args.extend(self.args_arg)
+ keywords.extend(self.keyword_args)
+ return CallInfo(self.call_info.function_name, args, keywords,
+ self.call_info.args_arg, self.call_info.keywords_arg,
+ self.call_info.implicit_arg, self.call_info.constructor)
+
+
+class _FunctionParser(object):
+
+ def __init__(self, call, implicit_arg):
+ self.call = call
+ self.implicit_arg = implicit_arg
+ self.word_finder = worder.Worder(self.call)
+ self.last_parens = self.call.rindex(')')
+ self.first_parens = self.word_finder._find_parens_start(self.last_parens)
+
+ def get_parameters(self):
+ args, keywords = self.word_finder.get_parameters(self.first_parens,
+ self.last_parens)
+ if self.is_called_as_a_method():
+ instance = self.call[:self.call.rindex('.', 0, self.first_parens)]
+ args.insert(0, instance.strip())
+ return args, keywords
+
+ def get_instance(self):
+ if self.is_called_as_a_method():
+ return self.word_finder.get_primary_at(
+ self.call.rindex('.', 0, self.first_parens) - 1)
+
+ def get_function_name(self):
+ if self.is_called_as_a_method():
+ return self.word_finder.get_word_at(self.first_parens - 1)
+ else:
+ return self.word_finder.get_primary_at(self.first_parens - 1)
+
+ def is_called_as_a_method(self):
+ return self.implicit_arg and '.' in self.call[:self.first_parens]
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/importutils/__init__.py b/vim/eclim/autoload/eclim/python/rope/refactor/importutils/__init__.py
@@ -0,0 +1,299 @@
+"""A package for handling imports
+
+This package provides tools for modifying module imports after
+refactorings or as a separate task.
+
+"""
+import rope.base.evaluate
+from rope.base.change import ChangeSet, ChangeContents
+from rope.refactor import occurrences, rename
+from rope.refactor.importutils import module_imports, actions
+from rope.refactor.importutils.importinfo import NormalImport, FromImport
+import rope.base.codeanalyze
+
+
+class ImportOrganizer(object):
+ """Perform some import-related commands
+
+ Each method returns a `rope.base.change.Change` object.
+
+ """
+
+ def __init__(self, project):
+ self.project = project
+ self.pycore = project.pycore
+ self.import_tools = ImportTools(self.pycore)
+
+ def organize_imports(self, resource, offset=None):
+ return self._perform_command_on_import_tools(
+ self.import_tools.organize_imports, resource, offset)
+
+ def expand_star_imports(self, resource, offset=None):
+ return self._perform_command_on_import_tools(
+ self.import_tools.expand_stars, resource, offset)
+
+ def froms_to_imports(self, resource, offset=None):
+ return self._perform_command_on_import_tools(
+ self.import_tools.froms_to_imports, resource, offset)
+
+ def relatives_to_absolutes(self, resource, offset=None):
+ return self._perform_command_on_import_tools(
+ self.import_tools.relatives_to_absolutes, resource, offset)
+
+ def handle_long_imports(self, resource, offset=None):
+ return self._perform_command_on_import_tools(
+ self.import_tools.handle_long_imports, resource, offset)
+
+ def _perform_command_on_import_tools(self, method, resource, offset):
+ pymodule = self.pycore.resource_to_pyobject(resource)
+ before_performing = pymodule.source_code
+ import_filter = None
+ if offset is not None:
+ import_filter = self._line_filter(
+ pymodule.lines.get_line_number(offset))
+ result = method(pymodule, import_filter=import_filter)
+ if result is not None and result != before_performing:
+ changes = ChangeSet(method.__name__.replace('_', ' ') +
+ ' in <%s>' % resource.path)
+ changes.add_change(ChangeContents(resource, result))
+ return changes
+
+ def _line_filter(self, lineno):
+ def import_filter(import_stmt):
+ return import_stmt.start_line <= lineno < import_stmt.end_line
+ return import_filter
+
+
+class ImportTools(object):
+
+ def __init__(self, pycore):
+ self.pycore = pycore
+
+ def get_import(self, resource):
+ """The import statement for `resource`"""
+ module_name = self.pycore.modname(resource)
+ return NormalImport(((module_name, None), ))
+
+ def get_from_import(self, resource, name):
+ """The from import statement for `name` in `resource`"""
+ module_name = self.pycore.modname(resource)
+ names = []
+ if isinstance(name, list):
+ names = [(imported, None) for imported in name]
+ else:
+ names = [(name, None),]
+ return FromImport(module_name, 0, tuple(names))
+
+ def module_imports(self, module, imports_filter=None):
+ return module_imports.ModuleImports(self.pycore, module,
+ imports_filter)
+
+ def froms_to_imports(self, pymodule, import_filter=None):
+ pymodule = self._clean_up_imports(pymodule, import_filter)
+ module_imports = self.module_imports(pymodule, import_filter)
+ for import_stmt in module_imports.imports:
+ if import_stmt.readonly or \
+ not self._is_transformable_to_normal(import_stmt.import_info):
+ continue
+ pymodule = self._from_to_normal(pymodule, import_stmt)
+
+ # Adding normal imports in place of froms
+ module_imports = self.module_imports(pymodule, import_filter)
+ for import_stmt in module_imports.imports:
+ if not import_stmt.readonly and \
+ self._is_transformable_to_normal(import_stmt.import_info):
+ import_stmt.import_info = \
+ NormalImport(((import_stmt.import_info.module_name, None),))
+ module_imports.remove_duplicates()
+ return module_imports.get_changed_source()
+
+ def expand_stars(self, pymodule, import_filter=None):
+ module_imports = self.module_imports(pymodule, import_filter)
+ module_imports.expand_stars()
+ return module_imports.get_changed_source()
+
+ def _from_to_normal(self, pymodule, import_stmt):
+ resource = pymodule.get_resource()
+ from_import = import_stmt.import_info
+ module_name = from_import.module_name
+ for name, alias in from_import.names_and_aliases:
+ imported = name
+ if alias is not None:
+ imported = alias
+ occurrence_finder = occurrences.create_finder(
+ self.pycore, imported, pymodule[imported], imports=False)
+ source = rename.rename_in_module(
+ occurrence_finder, module_name + '.' + name,
+ pymodule=pymodule, replace_primary=True)
+ if source is not None:
+ pymodule = self.pycore.get_string_module(source, resource)
+ return pymodule
+
+ def _clean_up_imports(self, pymodule, import_filter):
+ resource = pymodule.get_resource()
+ module_with_imports = self.module_imports(pymodule, import_filter)
+ module_with_imports.expand_stars()
+ source = module_with_imports.get_changed_source()
+ if source is not None:
+ pymodule = self.pycore.get_string_module(source, resource)
+ source = self.relatives_to_absolutes(pymodule)
+ if source is not None:
+ pymodule = self.pycore.get_string_module(source, resource)
+
+ module_with_imports = self.module_imports(pymodule, import_filter)
+ module_with_imports.remove_duplicates()
+ module_with_imports.remove_unused_imports()
+ source = module_with_imports.get_changed_source()
+ if source is not None:
+ pymodule = self.pycore.get_string_module(source, resource)
+ return pymodule
+
+ def relatives_to_absolutes(self, pymodule, import_filter=None):
+ module_imports = self.module_imports(pymodule, import_filter)
+ to_be_absolute_list = module_imports.get_relative_to_absolute_list()
+ for name, absolute_name in to_be_absolute_list:
+ pymodule = self._rename_in_module(pymodule, name, absolute_name)
+ module_imports = self.module_imports(pymodule, import_filter)
+ module_imports.get_relative_to_absolute_list()
+ source = module_imports.get_changed_source()
+ if source is None:
+ source = pymodule.source_code
+ return source
+
+ def _is_transformable_to_normal(self, import_info):
+ if not isinstance(import_info, FromImport):
+ return False
+ return True
+
+ def organize_imports(self, pymodule,
+ unused=True, duplicates=True,
+ selfs=True, sort=True, import_filter=None):
+ if unused or duplicates:
+ module_imports = self.module_imports(pymodule, import_filter)
+ if unused:
+ module_imports.remove_unused_imports()
+ if duplicates:
+ module_imports.remove_duplicates()
+ source = module_imports.get_changed_source()
+ if source is not None:
+ pymodule = self.pycore.get_string_module(
+ source, pymodule.get_resource())
+ if selfs:
+ pymodule = self._remove_self_imports(pymodule, import_filter)
+ if sort:
+ return self.sort_imports(pymodule, import_filter)
+ else:
+ return pymodule.source_code
+
+ def _remove_self_imports(self, pymodule, import_filter=None):
+ module_imports = self.module_imports(pymodule, import_filter)
+ to_be_fixed, to_be_renamed = module_imports.get_self_import_fix_and_rename_list()
+ for name in to_be_fixed:
+ try:
+ pymodule = self._rename_in_module(pymodule, name, '', till_dot=True)
+ except ValueError:
+ # There is a self import with direct access to it
+ return pymodule
+ for name, new_name in to_be_renamed:
+ pymodule = self._rename_in_module(pymodule, name, new_name)
+ module_imports = self.module_imports(pymodule, import_filter)
+ module_imports.get_self_import_fix_and_rename_list()
+ source = module_imports.get_changed_source()
+ if source is not None:
+ pymodule = self.pycore.get_string_module(source, pymodule.get_resource())
+ return pymodule
+
+ def _rename_in_module(self, pymodule, name, new_name, till_dot=False):
+ old_name = name.split('.')[-1]
+ old_pyname = rope.base.evaluate.eval_str(pymodule.get_scope(), name)
+ occurrence_finder = occurrences.create_finder(
+ self.pycore, old_name, old_pyname, imports=False)
+ changes = rope.base.codeanalyze.ChangeCollector(pymodule.source_code)
+ for occurrence in occurrence_finder.find_occurrences(pymodule=pymodule):
+ start, end = occurrence.get_primary_range()
+ if till_dot:
+ new_end = pymodule.source_code.index('.', end) + 1
+ space = pymodule.source_code[end:new_end - 1].strip()
+ if not space == '':
+ for c in space:
+ if not c.isspace() and c not in '\\':
+ raise ValueError()
+ end = new_end
+ changes.add_change(start, end, new_name)
+ source = changes.get_changed()
+ if source is not None:
+ pymodule = self.pycore.get_string_module(source, pymodule.get_resource())
+ return pymodule
+
+ def sort_imports(self, pymodule, import_filter=None):
+ module_imports = self.module_imports(pymodule, import_filter)
+ module_imports.sort_imports()
+ return module_imports.get_changed_source()
+
+ def handle_long_imports(self, pymodule, maxdots=2, maxlength=27,
+ import_filter=None):
+ # IDEA: `maxdots` and `maxlength` can be specified in project config
+ # adding new from imports
+ module_imports = self.module_imports(pymodule, import_filter)
+ to_be_fixed = module_imports.handle_long_imports(maxdots, maxlength)
+ # performing the renaming
+ pymodule = self.pycore.get_string_module(
+ module_imports.get_changed_source(),
+ resource=pymodule.get_resource())
+ for name in to_be_fixed:
+ pymodule = self._rename_in_module(pymodule, name,
+ name.split('.')[-1])
+ # organizing imports
+ return self.organize_imports(pymodule, selfs=False, sort=False,
+ import_filter=import_filter)
+
+
+def get_imports(pycore, pydefined):
+ """A shortcut for getting the `ImportInfo`\s used in a scope"""
+ pymodule = pydefined.get_module()
+ module = module_imports.ModuleImports(pycore, pymodule)
+ if pymodule == pydefined:
+ return [stmt.import_info for stmt in module.imports]
+ return module.get_used_imports(pydefined)
+
+
+def get_module_imports(pycore, pymodule):
+ """A shortcut for creating a `module_imports.ModuleImports` object"""
+ return module_imports.ModuleImports(pycore, pymodule)
+
+
+def add_import(pycore, pymodule, module_name, name=None):
+ imports = get_module_imports(pycore, pymodule)
+ candidates = []
+ names = []
+ # from mod import name
+ if name is not None:
+ from_import = FromImport(module_name, 0, [(name, None)])
+ names.append(name)
+ candidates.append(from_import)
+ # from pkg import mod
+ if '.' in module_name:
+ pkg, mod = module_name.rsplit('.', 1)
+ candidates.append(FromImport(pkg, 0, [(mod, None)]))
+ if name:
+ names.append(mod + '.' + name)
+ else:
+ names.append(mod)
+ # import mod
+ normal_import = NormalImport([(module_name, None)])
+ if name:
+ names.append(module_name + '.' + name)
+ else:
+ names.append(module_name)
+
+ candidates.append(normal_import)
+
+ visitor = actions.AddingVisitor(pycore, candidates)
+ selected_import = normal_import
+ for import_statement in imports.imports:
+ if import_statement.accept(visitor):
+ selected_import = visitor.import_info
+ break
+ imports.add_import(selected_import)
+ imported_name = names[candidates.index(selected_import)]
+ return imports.get_changed_source(), imported_name
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/importutils/actions.py b/vim/eclim/autoload/eclim/python/rope/refactor/importutils/actions.py
@@ -0,0 +1,359 @@
+import os
+import sys
+
+from rope.base import pyobjects, exceptions, stdmods
+from rope.refactor import occurrences
+from rope.refactor.importutils import importinfo
+
+
+class ImportInfoVisitor(object):
+
+ def dispatch(self, import_):
+ try:
+ method_name = 'visit' + import_.import_info.__class__.__name__
+ method = getattr(self, method_name)
+ return method(import_, import_.import_info)
+ except exceptions.ModuleNotFoundError:
+ pass
+
+ def visitEmptyImport(self, import_stmt, import_info):
+ pass
+
+ def visitNormalImport(self, import_stmt, import_info):
+ pass
+
+ def visitFromImport(self, import_stmt, import_info):
+ pass
+
+
+class RelativeToAbsoluteVisitor(ImportInfoVisitor):
+
+ def __init__(self, pycore, current_folder):
+ self.to_be_absolute = []
+ self.pycore = pycore
+ self.folder = current_folder
+ self.context = importinfo.ImportContext(pycore, current_folder)
+
+ def visitNormalImport(self, import_stmt, import_info):
+ self.to_be_absolute.extend(self._get_relative_to_absolute_list(import_info))
+ new_pairs = []
+ for name, alias in import_info.names_and_aliases:
+ resource = self.pycore.find_module(name, folder=self.folder)
+ if resource is None:
+ new_pairs.append((name, alias))
+ continue
+ absolute_name = self.pycore.modname(resource)
+ new_pairs.append((absolute_name, alias))
+ if not import_info._are_name_and_alias_lists_equal(
+ new_pairs, import_info.names_and_aliases):
+ import_stmt.import_info = importinfo.NormalImport(new_pairs)
+
+ def _get_relative_to_absolute_list(self, import_info):
+ result = []
+ for name, alias in import_info.names_and_aliases:
+ if alias is not None:
+ continue
+ resource = self.pycore.find_module(name, folder=self.folder)
+ if resource is None:
+ continue
+ absolute_name = self.pycore.modname(resource)
+ if absolute_name != name:
+ result.append((name, absolute_name))
+ return result
+
+ def visitFromImport(self, import_stmt, import_info):
+ resource = import_info.get_imported_resource(self.context)
+ if resource is None:
+ return None
+ absolute_name = self.pycore.modname(resource)
+ if import_info.module_name != absolute_name:
+ import_stmt.import_info = importinfo.FromImport(
+ absolute_name, 0, import_info.names_and_aliases)
+
+
+class FilteringVisitor(ImportInfoVisitor):
+
+ def __init__(self, pycore, folder, can_select):
+ self.to_be_absolute = []
+ self.pycore = pycore
+ self.can_select = self._transform_can_select(can_select)
+ self.context = importinfo.ImportContext(pycore, folder)
+
+ def _transform_can_select(self, can_select):
+ def can_select_name_and_alias(name, alias):
+ imported = name
+ if alias is not None:
+ imported = alias
+ return can_select(imported)
+ return can_select_name_and_alias
+
+ def visitNormalImport(self, import_stmt, import_info):
+ new_pairs = []
+ for name, alias in import_info.names_and_aliases:
+ if self.can_select(name, alias):
+ new_pairs.append((name, alias))
+ return importinfo.NormalImport(new_pairs)
+
+ def visitFromImport(self, import_stmt, import_info):
+ if _is_future(import_info):
+ return import_info
+ new_pairs = []
+ if import_info.is_star_import():
+ for name in import_info.get_imported_names(self.context):
+ if self.can_select(name, None):
+ new_pairs.append(import_info.names_and_aliases[0])
+ break
+ else:
+ for name, alias in import_info.names_and_aliases:
+ if self.can_select(name, alias):
+ new_pairs.append((name, alias))
+ return importinfo.FromImport(
+ import_info.module_name, import_info.level, new_pairs)
+
+
+class RemovingVisitor(ImportInfoVisitor):
+
+ def __init__(self, pycore, folder, can_select):
+ self.to_be_absolute = []
+ self.pycore = pycore
+ self.filtering = FilteringVisitor(pycore, folder, can_select)
+
+ def dispatch(self, import_):
+ result = self.filtering.dispatch(import_)
+ if result is not None:
+ import_.import_info = result
+
+
+class AddingVisitor(ImportInfoVisitor):
+ """A class for adding imports
+
+ Given a list of `ImportInfo`\s, it tries to add each import to the
+ module and returns `True` and gives up when an import can be added
+ to older ones.
+
+ """
+
+ def __init__(self, pycore, import_list):
+ self.pycore = pycore
+ self.import_list = import_list
+ self.import_info = None
+
+ def dispatch(self, import_):
+ for import_info in self.import_list:
+ self.import_info = import_info
+ if ImportInfoVisitor.dispatch(self, import_):
+ return True
+
+ # TODO: Handle adding relative and absolute imports
+ def visitNormalImport(self, import_stmt, import_info):
+ if not isinstance(self.import_info, import_info.__class__):
+ return False
+ # Adding ``import x`` and ``import x.y`` that results ``import x.y``
+ if len(import_info.names_and_aliases) == \
+ len(self.import_info.names_and_aliases) == 1:
+ imported1 = import_info.names_and_aliases[0]
+ imported2 = self.import_info.names_and_aliases[0]
+ if imported1[1] == imported2[1] is None:
+ if imported1[0].startswith(imported2[0] + '.'):
+ return True
+ if imported2[0].startswith(imported1[0] + '.'):
+ import_stmt.import_info = self.import_info
+ return True
+ # Multiple imports using a single import statement is discouraged
+ # so we won't bother adding them.
+ if self.import_info._are_name_and_alias_lists_equal(
+ import_info.names_and_aliases, self.import_info.names_and_aliases):
+ return True
+
+ def visitFromImport(self, import_stmt, import_info):
+ if isinstance(self.import_info, import_info.__class__) and \
+ import_info.module_name == self.import_info.module_name and \
+ import_info.level == self.import_info.level:
+ if import_info.is_star_import():
+ return True
+ if self.import_info.is_star_import():
+ import_stmt.import_info = self.import_info
+ return True
+ new_pairs = list(import_info.names_and_aliases)
+ for pair in self.import_info.names_and_aliases:
+ if pair not in new_pairs:
+ new_pairs.append(pair)
+ import_stmt.import_info = importinfo.FromImport(
+ import_info.module_name, import_info.level, new_pairs)
+ return True
+
+
+class ExpandStarsVisitor(ImportInfoVisitor):
+
+ def __init__(self, pycore, folder, can_select):
+ self.pycore = pycore
+ self.filtering = FilteringVisitor(pycore, folder, can_select)
+ self.context = importinfo.ImportContext(pycore, folder)
+
+ def visitNormalImport(self, import_stmt, import_info):
+ self.filtering.dispatch(import_stmt)
+
+ def visitFromImport(self, import_stmt, import_info):
+ if import_info.is_star_import():
+ new_pairs = []
+ for name in import_info.get_imported_names(self.context):
+ new_pairs.append((name, None))
+ new_import = importinfo.FromImport(
+ import_info.module_name, import_info.level, new_pairs)
+ import_stmt.import_info = \
+ self.filtering.visitFromImport(None, new_import)
+ else:
+ self.filtering.dispatch(import_stmt)
+
+
+class SelfImportVisitor(ImportInfoVisitor):
+
+ def __init__(self, pycore, current_folder, resource):
+ self.pycore = pycore
+ self.folder = current_folder
+ self.resource = resource
+ self.to_be_fixed = set()
+ self.to_be_renamed = set()
+ self.context = importinfo.ImportContext(pycore, current_folder)
+
+ def visitNormalImport(self, import_stmt, import_info):
+ new_pairs = []
+ for name, alias in import_info.names_and_aliases:
+ resource = self.pycore.find_module(name, folder=self.folder)
+ if resource is not None and resource == self.resource:
+ imported = name
+ if alias is not None:
+ imported = alias
+ self.to_be_fixed.add(imported)
+ else:
+ new_pairs.append((name, alias))
+ if not import_info._are_name_and_alias_lists_equal(
+ new_pairs, import_info.names_and_aliases):
+ import_stmt.import_info = importinfo.NormalImport(new_pairs)
+
+ def visitFromImport(self, import_stmt, import_info):
+ resource = import_info.get_imported_resource(self.context)
+ if resource is None:
+ return
+ if resource == self.resource:
+ self._importing_names_from_self(import_info, import_stmt)
+ return
+ pymodule = self.pycore.resource_to_pyobject(resource)
+ new_pairs = []
+ for name, alias in import_info.names_and_aliases:
+ try:
+ result = pymodule[name].get_object()
+ if isinstance(result, pyobjects.PyModule) and \
+ result.get_resource() == self.resource:
+ imported = name
+ if alias is not None:
+ imported = alias
+ self.to_be_fixed.add(imported)
+ else:
+ new_pairs.append((name, alias))
+ except exceptions.AttributeNotFoundError:
+ new_pairs.append((name, alias))
+ if not import_info._are_name_and_alias_lists_equal(
+ new_pairs, import_info.names_and_aliases):
+ import_stmt.import_info = importinfo.FromImport(
+ import_info.module_name, import_info.level, new_pairs)
+
+ def _importing_names_from_self(self, import_info, import_stmt):
+ if not import_info.is_star_import():
+ for name, alias in import_info.names_and_aliases:
+ if alias is not None:
+ self.to_be_renamed.add((alias, name))
+ import_stmt.empty_import()
+
+
+class SortingVisitor(ImportInfoVisitor):
+
+ def __init__(self, pycore, current_folder):
+ self.pycore = pycore
+ self.folder = current_folder
+ self.standard = set()
+ self.third_party = set()
+ self.in_project = set()
+ self.future = set()
+ self.context = importinfo.ImportContext(pycore, current_folder)
+
+ def visitNormalImport(self, import_stmt, import_info):
+ if import_info.names_and_aliases:
+ name, alias = import_info.names_and_aliases[0]
+ resource = self.pycore.find_module(
+ name, folder=self.folder)
+ self._check_imported_resource(import_stmt, resource, name)
+
+ def visitFromImport(self, import_stmt, import_info):
+ resource = import_info.get_imported_resource(self.context)
+ self._check_imported_resource(import_stmt, resource,
+ import_info.module_name)
+
+ def _check_imported_resource(self, import_stmt, resource, imported_name):
+ info = import_stmt.import_info
+ if resource is not None and resource.project == self.pycore.project:
+ self.in_project.add(import_stmt)
+ elif _is_future(info):
+ self.future.add(import_stmt)
+ elif imported_name.split('.')[0] in stdmods.standard_modules():
+ self.standard.add(import_stmt)
+ else:
+ self.third_party.add(import_stmt)
+
+
+class LongImportVisitor(ImportInfoVisitor):
+
+ def __init__(self, current_folder, pycore, maxdots, maxlength):
+ self.maxdots = maxdots
+ self.maxlength = maxlength
+ self.to_be_renamed = set()
+ self.current_folder = current_folder
+ self.pycore = pycore
+ self.new_imports = []
+
+ def visitNormalImport(self, import_stmt, import_info):
+ new_pairs = []
+ for name, alias in import_info.names_and_aliases:
+ if alias is None and self._is_long(name):
+ self.to_be_renamed.add(name)
+ last_dot = name.rindex('.')
+ from_ = name[:last_dot]
+ imported = name[last_dot + 1:]
+ self.new_imports.append(
+ importinfo.FromImport(from_, 0, ((imported, None), )))
+
+ def _is_long(self, name):
+ return name.count('.') > self.maxdots or \
+ ('.' in name and len(name) > self.maxlength)
+
+
+class RemovePyNameVisitor(ImportInfoVisitor):
+
+ def __init__(self, pycore, pymodule, pyname, folder):
+ self.pymodule = pymodule
+ self.pyname = pyname
+ self.context = importinfo.ImportContext(pycore, folder)
+
+ def visitFromImport(self, import_stmt, import_info):
+ new_pairs = []
+ if not import_info.is_star_import():
+ for name, alias in import_info.names_and_aliases:
+ try:
+ pyname = self.pymodule[alias or name]
+ if occurrences.same_pyname(self.pyname, pyname):
+ continue
+ except exceptions.AttributeNotFoundError:
+ pass
+ new_pairs.append((name, alias))
+ return importinfo.FromImport(
+ import_info.module_name, import_info.level, new_pairs)
+
+ def dispatch(self, import_):
+ result = ImportInfoVisitor.dispatch(self, import_)
+ if result is not None:
+ import_.import_info = result
+
+
+def _is_future(info):
+ return isinstance(info, importinfo.FromImport) and \
+ info.module_name == '__future__'
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/importutils/importinfo.py b/vim/eclim/autoload/eclim/python/rope/refactor/importutils/importinfo.py
@@ -0,0 +1,201 @@
+class ImportStatement(object):
+ """Represent an import in a module
+
+ `readonly` attribute controls whether this import can be changed
+ by import actions or not.
+
+ """
+
+ def __init__(self, import_info, start_line, end_line,
+ main_statement=None, blank_lines=0):
+ self.start_line = start_line
+ self.end_line = end_line
+ self.readonly = False
+ self.main_statement = main_statement
+ self._import_info = None
+ self.import_info = import_info
+ self._is_changed = False
+ self.new_start = None
+ self.blank_lines = blank_lines
+
+ def _get_import_info(self):
+ return self._import_info
+
+ def _set_import_info(self, new_import):
+ if not self.readonly and \
+ new_import is not None and not new_import == self._import_info:
+ self._is_changed = True
+ self._import_info = new_import
+
+ import_info = property(_get_import_info, _set_import_info)
+
+ def get_import_statement(self):
+ if self._is_changed or self.main_statement is None:
+ return self.import_info.get_import_statement()
+ else:
+ return self.main_statement
+
+ def empty_import(self):
+ self.import_info = ImportInfo.get_empty_import()
+
+ def move(self, lineno, blank_lines=0):
+ self.new_start = lineno
+ self.blank_lines = blank_lines
+
+ def get_old_location(self):
+ return self.start_line, self.end_line
+
+ def get_new_start(self):
+ return self.new_start
+
+ def is_changed(self):
+ return self._is_changed or (self.new_start is not None or
+ self.new_start != self.start_line)
+
+ def accept(self, visitor):
+ return visitor.dispatch(self)
+
+
+class ImportInfo(object):
+
+ def get_imported_primaries(self, context):
+ pass
+
+ def get_imported_names(self, context):
+ return [primary.split('.')[0]
+ for primary in self.get_imported_primaries(context)]
+
+ def get_import_statement(self):
+ pass
+
+ def is_empty(self):
+ pass
+
+ def __hash__(self):
+ return hash(self.get_import_statement())
+
+ def _are_name_and_alias_lists_equal(self, list1, list2):
+ if len(list1) != len(list2):
+ return False
+ for pair1, pair2 in zip(list1, list2):
+ if pair1 != pair2:
+ return False
+ return True
+
+ def __eq__(self, obj):
+ return isinstance(obj, self.__class__) and \
+ self.get_import_statement() == obj.get_import_statement()
+
+ def __ne__(self, obj):
+ return not self.__eq__(obj)
+
+ @staticmethod
+ def get_empty_import():
+ return EmptyImport()
+
+
+class NormalImport(ImportInfo):
+
+ def __init__(self, names_and_aliases):
+ self.names_and_aliases = names_and_aliases
+
+ def get_imported_primaries(self, context):
+ result = []
+ for name, alias in self.names_and_aliases:
+ if alias:
+ result.append(alias)
+ else:
+ result.append(name)
+ return result
+
+ def get_import_statement(self):
+ result = 'import '
+ for name, alias in self.names_and_aliases:
+ result += name
+ if alias:
+ result += ' as ' + alias
+ result += ', '
+ return result[:-2]
+
+ def is_empty(self):
+ return len(self.names_and_aliases) == 0
+
+
+class FromImport(ImportInfo):
+
+ def __init__(self, module_name, level, names_and_aliases):
+ self.module_name = module_name
+ self.level = level
+ self.names_and_aliases = names_and_aliases
+
+ def get_imported_primaries(self, context):
+ if self.names_and_aliases[0][0] == '*':
+ module = self.get_imported_module(context)
+ return [name for name in module
+ if not name.startswith('_')]
+ result = []
+ for name, alias in self.names_and_aliases:
+ if alias:
+ result.append(alias)
+ else:
+ result.append(name)
+ return result
+
+ def get_imported_resource(self, context):
+ """Get the imported resource
+
+ Returns `None` if module was not found.
+ """
+ if self.level == 0:
+ return context.pycore.find_module(
+ self.module_name, folder=context.folder)
+ else:
+ return context.pycore.find_relative_module(
+ self.module_name, context.folder, self.level)
+
+ def get_imported_module(self, context):
+ """Get the imported `PyModule`
+
+ Raises `rope.base.exceptions.ModuleNotFoundError` if module
+ could not be found.
+ """
+ if self.level == 0:
+ return context.pycore.get_module(
+ self.module_name, context.folder)
+ else:
+ return context.pycore.get_relative_module(
+ self.module_name, context.folder, self.level)
+
+ def get_import_statement(self):
+ result = 'from ' + '.' * self.level + self.module_name + ' import '
+ for name, alias in self.names_and_aliases:
+ result += name
+ if alias:
+ result += ' as ' + alias
+ result += ', '
+ return result[:-2]
+
+ def is_empty(self):
+ return len(self.names_and_aliases) == 0
+
+ def is_star_import(self):
+ return len(self.names_and_aliases) > 0 and \
+ self.names_and_aliases[0][0] == '*'
+
+
+class EmptyImport(ImportInfo):
+
+ names_and_aliases = []
+
+ def is_empty(self):
+ return True
+
+ def get_imported_primaries(self, context):
+ return []
+
+
+class ImportContext(object):
+
+ def __init__(self, pycore, folder):
+ self.pycore = pycore
+ self.folder = folder
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/importutils/module_imports.py b/vim/eclim/autoload/eclim/python/rope/refactor/importutils/module_imports.py
@@ -0,0 +1,454 @@
+import rope.base.pynames
+from rope.base import ast, utils
+from rope.refactor.importutils import importinfo
+from rope.refactor.importutils import actions
+
+
+class ModuleImports(object):
+
+ def __init__(self, pycore, pymodule, import_filter=None):
+ self.pycore = pycore
+ self.pymodule = pymodule
+ self.separating_lines = 0
+ self.filter = import_filter
+
+ @property
+ @utils.saveit
+ def imports(self):
+ finder = _GlobalImportFinder(self.pymodule, self.pycore)
+ result = finder.find_import_statements()
+ self.separating_lines = finder.get_separating_line_count()
+ if self.filter is not None:
+ for import_stmt in result:
+ if not self.filter(import_stmt):
+ import_stmt.readonly = True
+ return result
+
+ def _get_unbound_names(self, defined_pyobject):
+ visitor = _GlobalUnboundNameFinder(self.pymodule, defined_pyobject)
+ ast.walk(self.pymodule.get_ast(), visitor)
+ return visitor.unbound
+
+ def remove_unused_imports(self):
+ can_select = _OneTimeSelector(self._get_unbound_names(self.pymodule))
+ visitor = actions.RemovingVisitor(
+ self.pycore, self._current_folder(), can_select)
+ for import_statement in self.imports:
+ import_statement.accept(visitor)
+
+ def get_used_imports(self, defined_pyobject):
+ result = []
+ can_select = _OneTimeSelector(self._get_unbound_names(defined_pyobject))
+ visitor = actions.FilteringVisitor(
+ self.pycore, self._current_folder(), can_select)
+ for import_statement in self.imports:
+ new_import = import_statement.accept(visitor)
+ if new_import is not None and not new_import.is_empty():
+ result.append(new_import)
+ return result
+
+ def get_changed_source(self):
+ imports = self.imports
+ after_removing = self._remove_imports(imports)
+ imports = [stmt for stmt in imports
+ if not stmt.import_info.is_empty()]
+
+ first_non_blank = self._first_non_blank_line(after_removing, 0)
+ first_import = self._first_import_line() - 1
+ result = []
+ # Writing module docs
+ result.extend(after_removing[first_non_blank:first_import])
+ # Writing imports
+ sorted_imports = sorted(imports, self._compare_import_locations)
+ for stmt in sorted_imports:
+ start = self._get_import_location(stmt)
+ if stmt != sorted_imports[0]:
+ result.append('\n' * stmt.blank_lines)
+ result.append(stmt.get_import_statement() + '\n')
+ if sorted_imports and first_non_blank < len(after_removing):
+ result.append('\n' * self.separating_lines)
+
+ # Writing the body
+ first_after_imports = self._first_non_blank_line(after_removing,
+ first_import)
+ result.extend(after_removing[first_after_imports:])
+ return ''.join(result)
+
+ def _get_import_location(self, stmt):
+ start = stmt.get_new_start()
+ if start is None:
+ start = stmt.get_old_location()[0]
+ return start
+
+ def _compare_import_locations(self, stmt1, stmt2):
+ def get_location(stmt):
+ if stmt.get_new_start() is not None:
+ return stmt.get_new_start()
+ else:
+ return stmt.get_old_location()[0]
+ return cmp(get_location(stmt1), get_location(stmt2))
+
+ def _remove_imports(self, imports):
+ lines = self.pymodule.source_code.splitlines(True)
+ after_removing = []
+ last_index = 0
+ for stmt in imports:
+ start, end = stmt.get_old_location()
+ after_removing.extend(lines[last_index:start - 1])
+ last_index = end - 1
+ for i in range(start, end):
+ after_removing.append('')
+ after_removing.extend(lines[last_index:])
+ return after_removing
+
+ def _first_non_blank_line(self, lines, lineno):
+ result = lineno
+ for line in lines[lineno:]:
+ if line.strip() == '':
+ result += 1
+ else:
+ break
+ return result
+
+ def add_import(self, import_info):
+ visitor = actions.AddingVisitor(self.pycore, [import_info])
+ for import_statement in self.imports:
+ if import_statement.accept(visitor):
+ break
+ else:
+ lineno = self._get_new_import_lineno()
+ blanks = self._get_new_import_blanks()
+ self.imports.append(importinfo.ImportStatement(
+ import_info, lineno, lineno,
+ blank_lines=blanks))
+
+ def _get_new_import_blanks(self):
+ return 0
+
+ def _get_new_import_lineno(self):
+ if self.imports:
+ return self.imports[-1].end_line
+ return 1
+
+ def filter_names(self, can_select):
+ visitor = actions.RemovingVisitor(
+ self.pycore, self._current_folder(), can_select)
+ for import_statement in self.imports:
+ import_statement.accept(visitor)
+
+ def expand_stars(self):
+ can_select = _OneTimeSelector(self._get_unbound_names(self.pymodule))
+ visitor = actions.ExpandStarsVisitor(
+ self.pycore, self._current_folder(), can_select)
+ for import_statement in self.imports:
+ import_statement.accept(visitor)
+
+ def remove_duplicates(self):
+ added_imports = []
+ for import_stmt in self.imports:
+ visitor = actions.AddingVisitor(self.pycore,
+ [import_stmt.import_info])
+ for added_import in added_imports:
+ if added_import.accept(visitor):
+ import_stmt.empty_import()
+ else:
+ added_imports.append(import_stmt)
+
+ def get_relative_to_absolute_list(self):
+ visitor = rope.refactor.importutils.actions.RelativeToAbsoluteVisitor(
+ self.pycore, self._current_folder())
+ for import_stmt in self.imports:
+ if not import_stmt.readonly:
+ import_stmt.accept(visitor)
+ return visitor.to_be_absolute
+
+ def get_self_import_fix_and_rename_list(self):
+ visitor = rope.refactor.importutils.actions.SelfImportVisitor(
+ self.pycore, self._current_folder(), self.pymodule.get_resource())
+ for import_stmt in self.imports:
+ if not import_stmt.readonly:
+ import_stmt.accept(visitor)
+ return visitor.to_be_fixed, visitor.to_be_renamed
+
+ def _current_folder(self):
+ return self.pymodule.get_resource().parent
+
+ def sort_imports(self):
+ # IDEA: Sort from import list
+ visitor = actions.SortingVisitor(self.pycore, self._current_folder())
+ for import_statement in self.imports:
+ import_statement.accept(visitor)
+ in_projects = sorted(visitor.in_project, self._compare_imports)
+ third_party = sorted(visitor.third_party, self._compare_imports)
+ standards = sorted(visitor.standard, self._compare_imports)
+ future = sorted(visitor.future, self._compare_imports)
+ blank_lines = 0
+ last_index = self._first_import_line()
+ last_index = self._move_imports(future, last_index, 0)
+ last_index = self._move_imports(standards, last_index, 1)
+ last_index = self._move_imports(third_party, last_index, 1)
+ last_index = self._move_imports(in_projects, last_index, 1)
+ self.separating_lines = 2
+
+ def _first_import_line(self):
+ nodes = self.pymodule.get_ast().body
+ lineno = 0
+ if self.pymodule.get_doc() is not None:
+ lineno = 1
+ if len(nodes) > lineno:
+ lineno = self.pymodule.logical_lines.logical_line_in(
+ nodes[lineno].lineno)[0]
+ else:
+ lineno = self.pymodule.lines.length()
+ while lineno > 1:
+ line = self.pymodule.lines.get_line(lineno - 1)
+ if line.strip() == '':
+ lineno -= 1
+ else:
+ break
+ return lineno
+
+ def _compare_imports(self, stmt1, stmt2):
+ str1 = stmt1.get_import_statement()
+ str2 = stmt2.get_import_statement()
+ if str1.startswith('from ') and not str2.startswith('from '):
+ return 1
+ if not str1.startswith('from ') and str2.startswith('from '):
+ return -1
+ return cmp(str1, str2)
+
+ def _move_imports(self, imports, index, blank_lines):
+ if imports:
+ imports[0].move(index, blank_lines)
+ index += 1
+ if len(imports) > 1:
+ for stmt in imports[1:]:
+ stmt.move(index)
+ index += 1
+ return index
+
+ def handle_long_imports(self, maxdots, maxlength):
+ visitor = actions.LongImportVisitor(
+ self._current_folder(), self.pycore, maxdots, maxlength)
+ for import_statement in self.imports:
+ if not import_statement.readonly:
+ import_statement.accept(visitor)
+ for import_info in visitor.new_imports:
+ self.add_import(import_info)
+ return visitor.to_be_renamed
+
+ def remove_pyname(self, pyname):
+ """Removes pyname when imported in ``from mod import x``"""
+ visitor = actions.RemovePyNameVisitor(self.pycore, self.pymodule,
+ pyname, self._current_folder())
+ for import_stmt in self.imports:
+ import_stmt.accept(visitor)
+
+
+class _OneTimeSelector(object):
+
+ def __init__(self, names):
+ self.names = names
+ self.selected_names = set()
+
+ def __call__(self, imported_primary):
+ if self._can_name_be_added(imported_primary):
+ for name in self._get_dotted_tokens(imported_primary):
+ self.selected_names.add(name)
+ return True
+ return False
+
+ def _get_dotted_tokens(self, imported_primary):
+ tokens = imported_primary.split('.')
+ for i in range(len(tokens)):
+ yield '.'.join(tokens[:i + 1])
+
+ def _can_name_be_added(self, imported_primary):
+ for name in self._get_dotted_tokens(imported_primary):
+ if name in self.names and name not in self.selected_names:
+ return True
+ return False
+
+
+class _UnboundNameFinder(object):
+
+ def __init__(self, pyobject):
+ self.pyobject = pyobject
+
+ def _visit_child_scope(self, node):
+ pyobject = self.pyobject.get_module().get_scope().\
+ get_inner_scope_for_line(node.lineno).pyobject
+ visitor = _LocalUnboundNameFinder(pyobject, self)
+ for child in ast.get_child_nodes(node):
+ ast.walk(child, visitor)
+
+ def _FunctionDef(self, node):
+ self._visit_child_scope(node)
+
+ def _ClassDef(self, node):
+ self._visit_child_scope(node)
+
+ def _Name(self, node):
+ if self._get_root()._is_node_interesting(node) and \
+ not self.is_bound(node.id):
+ self.add_unbound(node.id)
+
+ def _Attribute(self, node):
+ result = []
+ while isinstance(node, ast.Attribute):
+ result.append(node.attr)
+ node = node.value
+ if isinstance(node, ast.Name):
+ result.append(node.id)
+ primary = '.'.join(reversed(result))
+ if self._get_root()._is_node_interesting(node) and \
+ not self.is_bound(primary):
+ self.add_unbound(primary)
+ else:
+ ast.walk(node, self)
+
+ def _get_root(self):
+ pass
+
+ def is_bound(self, name, propagated=False):
+ pass
+
+ def add_unbound(self, name):
+ pass
+
+
+class _GlobalUnboundNameFinder(_UnboundNameFinder):
+
+ def __init__(self, pymodule, wanted_pyobject):
+ super(_GlobalUnboundNameFinder, self).__init__(pymodule)
+ self.unbound = set()
+ self.names = set()
+ for name, pyname in pymodule._get_structural_attributes().items():
+ if not isinstance(pyname, (rope.base.pynames.ImportedName,
+ rope.base.pynames.ImportedModule)):
+ self.names.add(name)
+ wanted_scope = wanted_pyobject.get_scope()
+ self.start = wanted_scope.get_start()
+ self.end = wanted_scope.get_end() + 1
+
+ def _get_root(self):
+ return self
+
+ def is_bound(self, primary, propagated=False):
+ name = primary.split('.')[0]
+ if name in self.names:
+ return True
+ return False
+
+ def add_unbound(self, name):
+ names = name.split('.')
+ for i in range(len(names)):
+ self.unbound.add('.'.join(names[:i + 1]))
+
+ def _is_node_interesting(self, node):
+ return self.start <= node.lineno < self.end
+
+
+class _LocalUnboundNameFinder(_UnboundNameFinder):
+
+ def __init__(self, pyobject, parent):
+ super(_LocalUnboundNameFinder, self).__init__(pyobject)
+ self.parent = parent
+
+ def _get_root(self):
+ return self.parent._get_root()
+
+ def is_bound(self, primary, propagated=False):
+ name = primary.split('.')[0]
+ if propagated:
+ names = self.pyobject.get_scope().get_propagated_names()
+ else:
+ names = self.pyobject.get_scope().get_names()
+ if name in names or self.parent.is_bound(name, propagated=True):
+ return True
+ return False
+
+ def add_unbound(self, name):
+ self.parent.add_unbound(name)
+
+
+class _GlobalImportFinder(object):
+
+ def __init__(self, pymodule, pycore):
+ self.current_folder = None
+ if pymodule.get_resource():
+ self.current_folder = pymodule.get_resource().parent
+ self.pymodule = pymodule
+ self.pycore = pycore
+ self.imports = []
+ self.pymodule = pymodule
+ self.lines = self.pymodule.lines
+
+ def visit_import(self, node, end_line):
+ start_line = node.lineno
+ import_statement = importinfo.ImportStatement(
+ importinfo.NormalImport(self._get_names(node.names)),
+ start_line, end_line, self._get_text(start_line, end_line),
+ blank_lines=self._count_empty_lines_before(start_line))
+ self.imports.append(import_statement)
+
+ def _count_empty_lines_before(self, lineno):
+ result = 0
+ for current in range(lineno - 1, 0, -1):
+ line = self.lines.get_line(current)
+ if line.strip() == '':
+ result += 1
+ else:
+ break
+ return result
+
+ def _count_empty_lines_after(self, lineno):
+ result = 0
+ for current in range(lineno + 1, self.lines.length()):
+ line = self.lines.get_line(current)
+ if line.strip() == '':
+ result += 1
+ else:
+ break
+ return result
+
+ def get_separating_line_count(self):
+ if not self.imports:
+ return 0
+ return self._count_empty_lines_after(self.imports[-1].end_line - 1)
+
+ def _get_text(self, start_line, end_line):
+ result = []
+ for index in range(start_line, end_line):
+ result.append(self.lines.get_line(index))
+ return '\n'.join(result)
+
+ def visit_from(self, node, end_line):
+ level = 0
+ if node.level:
+ level = node.level
+ import_info = importinfo.FromImport(
+ node.module, level, self._get_names(node.names))
+ start_line = node.lineno
+ self.imports.append(importinfo.ImportStatement(
+ import_info, node.lineno, end_line,
+ self._get_text(start_line, end_line),
+ blank_lines=self._count_empty_lines_before(start_line)))
+
+ def _get_names(self, alias_names):
+ result = []
+ for alias in alias_names:
+ result.append((alias.name, alias.asname))
+ return result
+
+ def find_import_statements(self):
+ nodes = self.pymodule.get_ast().body
+ for index, node in enumerate(nodes):
+ if isinstance(node, (ast.Import, ast.ImportFrom)):
+ lines = self.pymodule.logical_lines
+ end_line = lines.logical_line_in(node.lineno)[1] + 1
+ if isinstance(node, ast.Import):
+ self.visit_import(node, end_line)
+ if isinstance(node, ast.ImportFrom):
+ self.visit_from(node, end_line)
+ return self.imports
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/inline.py b/vim/eclim/autoload/eclim/python/rope/refactor/inline.py
@@ -0,0 +1,553 @@
+import re
+
+import rope.base.exceptions
+import rope.refactor.functionutils
+from rope.base import (pynames, pyobjects, codeanalyze,
+ taskhandle, evaluate, worder, utils)
+from rope.base.change import ChangeSet, ChangeContents
+from rope.refactor import (occurrences, rename, sourceutils,
+ importutils, move, change_signature)
+
+
+def create_inline(project, resource, offset):
+ """Create a refactoring object for inlining
+
+ Based on `resource` and `offset` it returns an instance of
+ `InlineMethod`, `InlineVariable` or `InlineParameter`.
+
+ """
+ pycore = project.pycore
+ pyname = _get_pyname(pycore, resource, offset)
+ message = 'Inline refactoring should be performed on ' \
+ 'a method, local variable or parameter.'
+ if pyname is None:
+ raise rope.base.exceptions.RefactoringError(message)
+ if isinstance(pyname, pynames.ImportedName):
+ pyname = pyname._get_imported_pyname()
+ if isinstance(pyname, pynames.AssignedName):
+ return InlineVariable(project, resource, offset)
+ if isinstance(pyname, pynames.ParameterName):
+ return InlineParameter(project, resource, offset)
+ if isinstance(pyname.get_object(), pyobjects.PyFunction):
+ return InlineMethod(project, resource, offset)
+ else:
+ raise rope.base.exceptions.RefactoringError(message)
+
+
+class _Inliner(object):
+
+ def __init__(self, project, resource, offset):
+ self.project = project
+ self.pycore = project.pycore
+ self.pyname = _get_pyname(self.pycore, resource, offset)
+ range_finder = worder.Worder(resource.read())
+ self.region = range_finder.get_primary_range(offset)
+ self.name = range_finder.get_word_at(offset)
+ self.offset = offset
+ self.original = resource
+
+ def get_changes(self, *args, **kwds):
+ pass
+
+ def get_kind(self):
+ """Return either 'variable', 'method' or 'parameter'"""
+
+
+class InlineMethod(_Inliner):
+
+ def __init__(self, *args, **kwds):
+ super(InlineMethod, self).__init__(*args, **kwds)
+ self.pyfunction = self.pyname.get_object()
+ self.pymodule = self.pyfunction.get_module()
+ self.resource = self.pyfunction.get_module().get_resource()
+ self.occurrence_finder = occurrences.create_finder(
+ self.pycore, self.name, self.pyname)
+ self.normal_generator = _DefinitionGenerator(self.project,
+ self.pyfunction)
+ self._init_imports()
+
+ def _init_imports(self):
+ body = sourceutils.get_body(self.pyfunction)
+ body, imports = move.moving_code_with_imports(
+ self.pycore, self.resource, body)
+ self.imports = imports
+ self.others_generator = _DefinitionGenerator(
+ self.project, self.pyfunction, body=body)
+
+ def _get_scope_range(self):
+ scope = self.pyfunction.get_scope()
+ lines = self.pymodule.lines
+ logicals = self.pymodule.logical_lines
+ start_line = scope.get_start()
+ if self.pyfunction.decorators:
+ decorators = self.pyfunction.decorators
+ if hasattr(decorators[0], 'lineno'):
+ start_line = decorators[0].lineno
+ start_offset = lines.get_line_start(start_line)
+ end_offset = min(lines.get_line_end(scope.end) + 1,
+ len(self.pymodule.source_code))
+ return (start_offset, end_offset)
+
+ def get_changes(self, remove=True, only_current=False, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Get the changes this refactoring makes
+
+ If `remove` is `False` the definition will not be removed. If
+ `only_current` is `True`, the the current occurrence will be
+ inlined, only.
+ """
+ changes = ChangeSet('Inline method <%s>' % self.name)
+ if resources is None:
+ resources = self.pycore.get_python_files()
+ if only_current:
+ resources = [self.original]
+ if remove:
+ resources.append(self.resource)
+ job_set = task_handle.create_jobset('Collecting Changes',
+ len(resources))
+ for file in resources:
+ job_set.started_job(file.path)
+ if file == self.resource:
+ changes.add_change(self._defining_file_changes(
+ changes, remove=remove, only_current=only_current))
+ else:
+ aim = None
+ if only_current and self.original == file:
+ aim = self.offset
+ handle = _InlineFunctionCallsForModuleHandle(
+ self.pycore, file, self.others_generator, aim)
+ result = move.ModuleSkipRenamer(
+ self.occurrence_finder, file, handle).get_changed_module()
+ if result is not None:
+ result = _add_imports(self.pycore, result,
+ file, self.imports)
+ if remove:
+ result = _remove_from(self.pycore, self.pyname,
+ result, file)
+ changes.add_change(ChangeContents(file, result))
+ job_set.finished_job()
+ return changes
+
+ def _get_removed_range(self):
+ scope = self.pyfunction.get_scope()
+ lines = self.pymodule.lines
+ logical = self.pymodule.logical_lines
+ start_line = scope.get_start()
+ start, end = self._get_scope_range()
+ end_line = scope.get_end()
+ for i in range(end_line + 1, lines.length()):
+ if lines.get_line(i).strip() == '':
+ end_line = i
+ else:
+ break
+ end = min(lines.get_line_end(end_line) + 1,
+ len(self.pymodule.source_code))
+ return (start, end)
+
+ def _defining_file_changes(self, changes, remove, only_current):
+ start_offset, end_offset = self._get_removed_range()
+ aim = None
+ if only_current:
+ if self.resource == self.original:
+ aim = self.offset
+ else:
+ # we don't want to change any of them
+ aim = len(self.resource.read()) + 100
+ handle = _InlineFunctionCallsForModuleHandle(
+ self.pycore, self.resource,
+ self.normal_generator, aim_offset=aim)
+ replacement = None
+ if remove:
+ replacement = self._get_method_replacement()
+ result = move.ModuleSkipRenamer(
+ self.occurrence_finder, self.resource, handle, start_offset,
+ end_offset, replacement).get_changed_module()
+ return ChangeContents(self.resource, result)
+
+ def _get_method_replacement(self):
+ if self._is_the_last_method_of_a_class():
+ indents = sourceutils.get_indents(
+ self.pymodule.lines, self.pyfunction.get_scope().get_start())
+ return ' ' * indents + 'pass\n'
+ return ''
+
+ def _is_the_last_method_of_a_class(self):
+ pyclass = self.pyfunction.parent
+ if not isinstance(pyclass, pyobjects.PyClass):
+ return False
+ class_start, class_end = sourceutils.get_body_region(pyclass)
+ source = self.pymodule.source_code
+ lines = self.pymodule.lines
+ func_start, func_end = self._get_scope_range()
+ if source[class_start:func_start].strip() == '' and \
+ source[func_end:class_end].strip() == '':
+ return True
+ return False
+
+ def get_kind(self):
+ return 'method'
+
+
+class InlineVariable(_Inliner):
+
+ def __init__(self, *args, **kwds):
+ super(InlineVariable, self).__init__(*args, **kwds)
+ self.pymodule = self.pyname.get_definition_location()[0]
+ self.resource = self.pymodule.get_resource()
+ self._check_exceptional_conditions()
+ self._init_imports()
+
+ def _check_exceptional_conditions(self):
+ if len(self.pyname.assignments) != 1:
+ raise rope.base.exceptions.RefactoringError(
+ 'Local variable should be assigned once for inlining.')
+
+ def get_changes(self, remove=True, only_current=False, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ if resources is None:
+ if rename._is_local(self.pyname):
+ resources = [self.resource]
+ else:
+ resources = self.pycore.get_python_files()
+ if only_current:
+ resources = [self.original]
+ if remove and self.original != self.resource:
+ resources.append(self.resource)
+ changes = ChangeSet('Inline variable <%s>' % self.name)
+ jobset = task_handle.create_jobset('Calculating changes',
+ len(resources))
+ for resource in resources:
+ jobset.started_job(resource.path)
+ if resource == self.resource:
+ source = self._change_main_module(remove, only_current)
+ changes.add_change(ChangeContents(self.resource, source))
+ else:
+ result = self._change_module(resource, remove, only_current)
+ if result is not None:
+ result = _add_imports(self.pycore, result,
+ resource, self.imports)
+ changes.add_change(ChangeContents(resource, result))
+ jobset.finished_job()
+ return changes
+
+ def _change_main_module(self, remove, only_current):
+ region = None
+ if only_current and self.original == self.resource:
+ region = self.region
+ return _inline_variable(self.pycore, self.pymodule, self.pyname,
+ self.name, remove=remove, region=region)
+
+ def _init_imports(self):
+ vardef = _getvardef(self.pymodule, self.pyname)
+ self.imported, self.imports = move.moving_code_with_imports(
+ self.pycore, self.resource, vardef)
+
+ def _change_module(self, resource, remove, only_current):
+ filters = [occurrences.NoImportsFilter(),
+ occurrences.PyNameFilter(self.pyname)]
+ if only_current and resource == self.original:
+ def check_aim(occurrence):
+ start, end = occurrence.get_primary_range()
+ if self.offset < start or end < self.offset:
+ return False
+ filters.insert(0, check_aim)
+ finder = occurrences.Finder(self.pycore, self.name, filters=filters)
+ changed = rename.rename_in_module(
+ finder, self.imported, resource=resource, replace_primary=True)
+ if changed and remove:
+ changed = _remove_from(self.pycore, self.pyname, changed, resource)
+ return changed
+
+ def get_kind(self):
+ return 'variable'
+
+
+class InlineParameter(_Inliner):
+
+ def __init__(self, *args, **kwds):
+ super(InlineParameter, self).__init__(*args, **kwds)
+ resource, offset = self._function_location()
+ index = self.pyname.index
+ self.changers = [change_signature.ArgumentDefaultInliner(index)]
+ self.signature = change_signature.ChangeSignature(self.project,
+ resource, offset)
+
+ def _function_location(self):
+ pymodule, lineno = self.pyname.get_definition_location()
+ resource = pymodule.get_resource()
+ start = pymodule.lines.get_line_start(lineno)
+ word_finder = worder.Worder(pymodule.source_code)
+ offset = word_finder.find_function_offset(start)
+ return resource, offset
+
+ def get_changes(self, **kwds):
+ """Get the changes needed by this refactoring
+
+ See `rope.refactor.change_signature.ChangeSignature.get_changes()`
+ for arguments.
+ """
+ return self.signature.get_changes(self.changers, **kwds)
+
+ def get_kind(self):
+ return 'parameter'
+
+
+def _join_lines(lines):
+ definition_lines = []
+ for unchanged_line in lines:
+ line = unchanged_line.strip()
+ if line.endswith('\\'):
+ line = line[:-1].strip()
+ definition_lines.append(line)
+ joined = ' '.join(definition_lines)
+ return joined
+
+
+class _DefinitionGenerator(object):
+
+ def __init__(self, project, pyfunction, body=None):
+ self.pycore = project.pycore
+ self.pyfunction = pyfunction
+ self.pymodule = pyfunction.get_module()
+ self.resource = self.pymodule.get_resource()
+ self.definition_info = self._get_definition_info()
+ self.definition_params = self._get_definition_params()
+ self._calculated_definitions = {}
+ if body is not None:
+ self.body = body
+ else:
+ self.body = sourceutils.get_body(self.pyfunction)
+
+ def _get_definition_info(self):
+ return rope.refactor.functionutils.DefinitionInfo.read(self.pyfunction)
+
+ def _get_definition_params(self):
+ definition_info = self.definition_info
+ paramdict = dict([pair for pair in definition_info.args_with_defaults])
+ if definition_info.args_arg is not None or \
+ definition_info.keywords_arg is not None:
+ raise rope.base.exceptions.RefactoringError(
+ 'Cannot inline functions with list and keyword arguements.')
+ if self.pyfunction.get_kind() == 'classmethod':
+ paramdict[definition_info.args_with_defaults[0][0]] = \
+ self.pyfunction.parent.get_name()
+ return paramdict
+
+ def get_function_name(self):
+ return self.pyfunction.get_name()
+
+ def get_definition(self, primary, pyname, call, returns=False):
+ # caching already calculated definitions
+ key = (call, returns)
+ if key not in self._calculated_definitions:
+ self._calculated_definitions[key] = self._calculate_definition(
+ primary, pyname, call, returns)
+ return self._calculated_definitions[key]
+
+ def _calculate_definition(self, primary, pyname, call, returns):
+ call_info = rope.refactor.functionutils.CallInfo.read(
+ primary, pyname, self.definition_info, call)
+ paramdict = self.definition_params
+ mapping = rope.refactor.functionutils.ArgumentMapping(
+ self.definition_info, call_info)
+ for param_name, value in mapping.param_dict.items():
+ paramdict[param_name] = value
+ header = ''
+ to_be_inlined = []
+ for name, value in paramdict.items():
+ if name != value and value is not None:
+ header += name + ' = ' + value.replace('\n', ' ') + '\n'
+ to_be_inlined.append(name)
+ source = header + self.body
+ for name in to_be_inlined:
+ pymodule = self.pycore.get_string_module(source, self.resource)
+ pyname = pymodule[name]
+ source = _inline_variable(self.pycore, pymodule, pyname, name)
+ return self._replace_returns_with(source, returns)
+
+ def _replace_returns_with(self, source, returns):
+ result = []
+ returned = None
+ last_changed = 0
+ for match in _DefinitionGenerator._get_return_pattern().finditer(source):
+ for key, value in match.groupdict().items():
+ if value and key == 'return':
+ result.append(source[last_changed:match.start('return')])
+ if returns:
+ self._check_nothing_after_return(source,
+ match.end('return'))
+ returned = _join_lines(
+ source[match.end('return'): len(source)].splitlines())
+ last_changed = len(source)
+ else:
+ current = match.end('return')
+ while current < len(source) and source[current] in ' \t':
+ current += 1
+ last_changed = current
+ if current == len(source) or source[current] == '\n':
+ result.append('pass')
+ result.append(source[last_changed:])
+ return ''.join(result), returned
+
+ def _check_nothing_after_return(self, source, offset):
+ lines = codeanalyze.SourceLinesAdapter(source)
+ lineno = lines.get_line_number(offset)
+ logical_lines = codeanalyze.LogicalLineFinder(lines)
+ lineno = logical_lines.logical_line_in(lineno)[1]
+ if source[lines.get_line_end(lineno):len(source)].strip() != '':
+ raise rope.base.exceptions.RefactoringError(
+ 'Cannot inline functions with statements after return statement.')
+
+ @classmethod
+ def _get_return_pattern(cls):
+ if not hasattr(cls, '_return_pattern'):
+ def named_pattern(name, list_):
+ return "(?P<%s>" % name + "|".join(list_) + ")"
+ comment_pattern = named_pattern('comment', [r'#[^\n]*'])
+ string_pattern = named_pattern('string',
+ [codeanalyze.get_string_pattern()])
+ return_pattern = r'\b(?P<return>return)\b'
+ cls._return_pattern = re.compile(comment_pattern + "|" +
+ string_pattern + "|" +
+ return_pattern)
+ return cls._return_pattern
+
+
+class _InlineFunctionCallsForModuleHandle(object):
+
+ def __init__(self, pycore, resource,
+ definition_generator, aim_offset=None):
+ """Inlines occurrences
+
+ If `aim` is not `None` only the occurrences that intersect
+ `aim` offset will be inlined.
+
+ """
+ self.pycore = pycore
+ self.generator = definition_generator
+ self.resource = resource
+ self.aim = aim_offset
+
+ def occurred_inside_skip(self, change_collector, occurrence):
+ if not occurrence.is_defined():
+ raise rope.base.exceptions.RefactoringError(
+ 'Cannot inline functions that reference themselves')
+
+ def occurred_outside_skip(self, change_collector, occurrence):
+ start, end = occurrence.get_primary_range()
+ # we remove out of date imports later
+ if occurrence.is_in_import_statement():
+ return
+ # the function is referenced outside an import statement
+ if not occurrence.is_called():
+ raise rope.base.exceptions.RefactoringError(
+ 'Reference to inlining function other than function call'
+ ' in <file: %s, offset: %d>' % (self.resource.path, start))
+ if self.aim is not None and (self.aim < start or self.aim > end):
+ return
+ end_parens = self._find_end_parens(self.source, end - 1)
+ lineno = self.lines.get_line_number(start)
+ start_line, end_line = self.pymodule.logical_lines.\
+ logical_line_in(lineno)
+ line_start = self.lines.get_line_start(start_line)
+ line_end = self.lines.get_line_end(end_line)
+ returns = self.source[line_start:start].strip() != '' or \
+ self.source[end_parens:line_end].strip() != ''
+ indents = sourceutils.get_indents(self.lines, start_line)
+ primary, pyname = occurrence.get_primary_and_pyname()
+ definition, returned = self.generator.get_definition(
+ primary, pyname, self.source[start:end_parens], returns=returns)
+ end = min(line_end + 1, len(self.source))
+ change_collector.add_change(
+ line_start, end, sourceutils.fix_indentation(definition, indents))
+ if returns:
+ name = returned
+ if name is None:
+ name = 'None'
+ change_collector.add_change(
+ line_end, end, self.source[line_start:start] + name +
+ self.source[end_parens:end])
+
+ def _find_end_parens(self, source, offset):
+ finder = worder.Worder(source)
+ return finder.get_word_parens_range(offset)[1]
+
+ @property
+ @utils.saveit
+ def pymodule(self):
+ return self.pycore.resource_to_pyobject(self.resource)
+
+ @property
+ @utils.saveit
+ def source(self):
+ if self.resource is not None:
+ return self.resource.read()
+ else:
+ return self.pymodule.source_code
+
+ @property
+ @utils.saveit
+ def lines(self):
+ return self.pymodule.lines
+
+
+def _inline_variable(pycore, pymodule, pyname, name,
+ remove=True, region=None):
+ definition = _getvardef(pymodule, pyname)
+ start, end = _assigned_lineno(pymodule, pyname)
+
+ occurrence_finder = occurrences.create_finder(pycore, name, pyname)
+ changed_source = rename.rename_in_module(
+ occurrence_finder, definition, pymodule=pymodule,
+ replace_primary=True, writes=False, region=region)
+ if changed_source is None:
+ changed_source = pymodule.source_code
+ if remove:
+ lines = codeanalyze.SourceLinesAdapter(changed_source)
+ source = changed_source[:lines.get_line_start(start)] + \
+ changed_source[lines.get_line_end(end) + 1:]
+ else:
+ source = changed_source
+ return source
+
+def _getvardef(pymodule, pyname):
+ assignment = pyname.assignments[0]
+ lines = pymodule.lines
+ start, end = _assigned_lineno(pymodule, pyname)
+ definition_with_assignment = _join_lines(
+ [lines.get_line(n) for n in range(start, end + 1)])
+ if assignment.levels:
+ raise rope.base.exceptions.RefactoringError(
+ 'Cannot inline tuple assignments.')
+ definition = definition_with_assignment[definition_with_assignment.\
+ index('=') + 1:].strip()
+ return definition
+
+def _assigned_lineno(pymodule, pyname):
+ definition_line = pyname.assignments[0].ast_node.lineno
+ return pymodule.logical_lines.logical_line_in(definition_line)
+
+def _add_imports(pycore, source, resource, imports):
+ if not imports:
+ return source
+ pymodule = pycore.get_string_module(source, resource)
+ module_import = importutils.get_module_imports(pycore, pymodule)
+ for import_info in imports:
+ module_import.add_import(import_info)
+ source = module_import.get_changed_source()
+ pymodule = pycore.get_string_module(source, resource)
+ import_tools = importutils.ImportTools(pycore)
+ return import_tools.organize_imports(pymodule, unused=False, sort=False)
+
+def _get_pyname(pycore, resource, offset):
+ pymodule = pycore.resource_to_pyobject(resource)
+ pyname = evaluate.eval_location(pymodule, offset)
+ if isinstance(pyname, pynames.ImportedName):
+ pyname = pyname._get_imported_pyname()
+ return pyname
+
+def _remove_from(pycore, pyname, source, resource):
+ pymodule = pycore.get_string_module(source, resource)
+ module_import = importutils.get_module_imports(pycore, pymodule)
+ module_import.remove_pyname(pyname)
+ return module_import.get_changed_source()
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/introduce_factory.py b/vim/eclim/autoload/eclim/python/rope/refactor/introduce_factory.py
@@ -0,0 +1,133 @@
+import rope.base.exceptions
+import rope.base.pyobjects
+from rope.base import taskhandle, evaluate
+from rope.base.change import (ChangeSet, ChangeContents)
+from rope.refactor import rename, occurrences, sourceutils, importutils
+
+
+class IntroduceFactory(object):
+
+ def __init__(self, project, resource, offset):
+ self.pycore = project.pycore
+ self.offset = offset
+
+ this_pymodule = self.pycore.resource_to_pyobject(resource)
+ self.old_pyname = evaluate.eval_location(this_pymodule, offset)
+ if self.old_pyname is None or not isinstance(self.old_pyname.get_object(),
+ rope.base.pyobjects.PyClass):
+ raise rope.base.exceptions.RefactoringError(
+ 'Introduce factory should be performed on a class.')
+ self.old_name = self.old_pyname.get_object().get_name()
+ self.pymodule = self.old_pyname.get_object().get_module()
+ self.resource = self.pymodule.get_resource()
+
+ def get_changes(self, factory_name, global_factory=False, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Get the changes this refactoring makes
+
+ `factory_name` indicates the name of the factory function to
+ be added. If `global_factory` is `True` the factory will be
+ global otherwise a static method is added to the class.
+
+ `resources` can be a list of `rope.base.resource.File`\s that
+ this refactoring should be applied on; if `None` all python
+ files in the project are searched.
+
+ """
+ if resources is None:
+ resources = self.pycore.get_python_files()
+ changes = ChangeSet('Introduce factory method <%s>' % factory_name)
+ job_set = task_handle.create_jobset('Collecting Changes',
+ len(resources))
+ self._change_module(resources, changes, factory_name,
+ global_factory, job_set)
+ return changes
+
+ def get_name(self):
+ """Return the name of the class"""
+ return self.old_name
+
+ def _change_module(self, resources, changes,
+ factory_name, global_, job_set):
+ if global_:
+ replacement = '__rope_factory_%s_' % factory_name
+ else:
+ replacement = self._new_function_name(factory_name, global_)
+
+ for file_ in resources:
+ job_set.started_job(file_.path)
+ if file_ == self.resource:
+ self._change_resource(changes, factory_name, global_)
+ job_set.finished_job()
+ continue
+ changed_code = self._rename_occurrences(file_, replacement,
+ global_)
+ if changed_code is not None:
+ if global_:
+ new_pymodule = self.pycore.get_string_module(changed_code,
+ self.resource)
+ modname = self.pycore.modname(self.resource)
+ changed_code, imported = importutils.add_import(
+ self.pycore, new_pymodule, modname, factory_name)
+ changed_code = changed_code.replace(replacement, imported)
+ changes.add_change(ChangeContents(file_, changed_code))
+ job_set.finished_job()
+
+ def _change_resource(self, changes, factory_name, global_):
+ class_scope = self.old_pyname.get_object().get_scope()
+ source_code = self._rename_occurrences(
+ self.resource, self._new_function_name(factory_name,
+ global_), global_)
+ if source_code is None:
+ source_code = self.pymodule.source_code
+ else:
+ self.pymodule = self.pycore.get_string_module(
+ source_code, resource=self.resource)
+ lines = self.pymodule.lines
+ start = self._get_insertion_offset(class_scope, lines)
+ result = source_code[:start]
+ result += self._get_factory_method(lines, class_scope,
+ factory_name, global_)
+ result += source_code[start:]
+ changes.add_change(ChangeContents(self.resource, result))
+
+ def _get_insertion_offset(self, class_scope, lines):
+ start_line = class_scope.get_end()
+ if class_scope.get_scopes():
+ start_line = class_scope.get_scopes()[-1].get_end()
+ start = lines.get_line_end(start_line) + 1
+ return start
+
+ def _get_factory_method(self, lines, class_scope,
+ factory_name, global_):
+ unit_indents = ' ' * sourceutils.get_indent(self.pycore)
+ if global_:
+ if self._get_scope_indents(lines, class_scope) > 0:
+ raise rope.base.exceptions.RefactoringError(
+ 'Cannot make global factory method for nested classes.')
+ return ('\ndef %s(*args, **kwds):\n%sreturn %s(*args, **kwds)\n' %
+ (factory_name, unit_indents, self.old_name))
+ unindented_factory = \
+ ('@staticmethod\ndef %s(*args, **kwds):\n' % factory_name +
+ '%sreturn %s(*args, **kwds)\n' % (unit_indents, self.old_name))
+ indents = self._get_scope_indents(lines, class_scope) + \
+ sourceutils.get_indent(self.pycore)
+ return '\n' + sourceutils.indent_lines(unindented_factory, indents)
+
+ def _get_scope_indents(self, lines, scope):
+ return sourceutils.get_indents(lines, scope.get_start())
+
+ def _new_function_name(self, factory_name, global_):
+ if global_:
+ return factory_name
+ else:
+ return self.old_name + '.' + factory_name
+
+ def _rename_occurrences(self, file_, changed_name, global_factory):
+ finder = occurrences.create_finder(self.pycore, self.old_name,
+ self.old_pyname, only_calls=True)
+ result = rename.rename_in_module(finder, changed_name, resource=file_,
+ replace_primary=global_factory)
+ return result
+
+IntroduceFactoryRefactoring = IntroduceFactory
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/introduce_parameter.py b/vim/eclim/autoload/eclim/python/rope/refactor/introduce_parameter.py
@@ -0,0 +1,95 @@
+import rope.base.change
+from rope.base import exceptions, evaluate, worder, codeanalyze
+from rope.refactor import functionutils, sourceutils, occurrences
+
+
+class IntroduceParameter(object):
+ """Introduce parameter refactoring
+
+ This refactoring adds a new parameter to a function and replaces
+ references to an expression in it with the new parameter.
+
+ The parameter finding part is different from finding similar
+ pieces in extract refactorings. In this refactoring parameters
+ are found based on the object they reference to. For instance
+ in::
+
+ class A(object):
+ var = None
+
+ class B(object):
+ a = A()
+
+ b = B()
+ a = b.a
+
+ def f(a):
+ x = b.a.var + a.var
+
+ using this refactoring on ``a.var`` with ``p`` as the new
+ parameter name, will result in::
+
+ def f(p=a.var):
+ x = p + p
+
+ """
+
+ def __init__(self, project, resource, offset):
+ self.pycore = project.pycore
+ self.resource = resource
+ self.offset = offset
+ self.pymodule = self.pycore.resource_to_pyobject(self.resource)
+ scope = self.pymodule.get_scope().get_inner_scope_for_offset(offset)
+ if scope.get_kind() != 'Function':
+ raise exceptions.RefactoringError(
+ 'Introduce parameter should be performed inside functions')
+ self.pyfunction = scope.pyobject
+ self.name, self.pyname = self._get_name_and_pyname()
+ if self.pyname is None:
+ raise exceptions.RefactoringError(
+ 'Cannot find the definition of <%s>' % self.name)
+
+ def _get_primary(self):
+ word_finder = worder.Worder(self.resource.read())
+ return word_finder.get_primary_at(self.offset)
+
+ def _get_name_and_pyname(self):
+ return (worder.get_name_at(self.resource, self.offset),
+ evaluate.eval_location(self.pymodule, self.offset))
+
+ def get_changes(self, new_parameter):
+ definition_info = functionutils.DefinitionInfo.read(self.pyfunction)
+ definition_info.args_with_defaults.append((new_parameter,
+ self._get_primary()))
+ collector = codeanalyze.ChangeCollector(self.resource.read())
+ header_start, header_end = self._get_header_offsets()
+ body_start, body_end = sourceutils.get_body_region(self.pyfunction)
+ collector.add_change(header_start, header_end,
+ definition_info.to_string())
+ self._change_function_occurances(collector, body_start,
+ body_end, new_parameter)
+ changes = rope.base.change.ChangeSet('Introduce parameter <%s>' %
+ new_parameter)
+ change = rope.base.change.ChangeContents(self.resource,
+ collector.get_changed())
+ changes.add_change(change)
+ return changes
+
+ def _get_header_offsets(self):
+ lines = self.pymodule.lines
+ start_line = self.pyfunction.get_scope().get_start()
+ end_line = self.pymodule.logical_lines.\
+ logical_line_in(start_line)[1]
+ start = lines.get_line_start(start_line)
+ end = lines.get_line_end(end_line)
+ start = self.pymodule.source_code.find('def', start) + 4
+ end = self.pymodule.source_code.rfind(':', start, end)
+ return start, end
+
+ def _change_function_occurances(self, collector, function_start,
+ function_end, new_name):
+ finder = occurrences.create_finder(self.pycore, self.name, self.pyname)
+ for occurrence in finder.find_occurrences(resource=self.resource):
+ start, end = occurrence.get_primary_range()
+ if function_start <= start < function_end:
+ collector.add_change(start, end, new_name)
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/localtofield.py b/vim/eclim/autoload/eclim/python/rope/refactor/localtofield.py
@@ -0,0 +1,50 @@
+from rope.base import pynames, evaluate, exceptions, worder
+from rope.refactor.rename import Rename
+
+
+class LocalToField(object):
+
+ def __init__(self, project, resource, offset):
+ self.project = project
+ self.pycore = project.pycore
+ self.resource = resource
+ self.offset = offset
+
+ def get_changes(self):
+ name = worder.get_name_at(self.resource, self.offset)
+ this_pymodule = self.pycore.resource_to_pyobject(self.resource)
+ pyname = evaluate.eval_location(this_pymodule, self.offset)
+ if not self._is_a_method_local(pyname):
+ raise exceptions.RefactoringError(
+ 'Convert local variable to field should be performed on \n'
+ 'a local variable of a method.')
+
+ pymodule, lineno = pyname.get_definition_location()
+ function_scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
+ # Not checking redefinition
+ #self._check_redefinition(name, function_scope)
+
+ new_name = self._get_field_name(function_scope.pyobject, name)
+ changes = Rename(self.project, self.resource, self.offset).\
+ get_changes(new_name, resources=[self.resource])
+ return changes
+
+ def _check_redefinition(self, name, function_scope):
+ class_scope = function_scope.parent
+ if name in class_scope.pyobject:
+ raise exceptions.RefactoringError(
+ 'The field %s already exists' % name)
+
+ def _get_field_name(self, pyfunction, name):
+ self_name = pyfunction.get_param_names()[0]
+ new_name = self_name + '.' + name
+ return new_name
+
+ def _is_a_method_local(self, pyname):
+ pymodule, lineno = pyname.get_definition_location()
+ holding_scope = pymodule.get_scope().get_inner_scope_for_line(lineno)
+ parent = holding_scope.parent
+ return isinstance(pyname, pynames.AssignedName) and \
+ pyname in holding_scope.get_names().values() and \
+ holding_scope.get_kind() == 'Function' and \
+ parent is not None and parent.get_kind() == 'Class'
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/method_object.py b/vim/eclim/autoload/eclim/python/rope/refactor/method_object.py
@@ -0,0 +1,87 @@
+import warnings
+
+from rope.base import pyobjects, exceptions, change, evaluate, codeanalyze
+from rope.refactor import sourceutils, occurrences, rename
+
+
+class MethodObject(object):
+
+ def __init__(self, project, resource, offset):
+ self.pycore = project.pycore
+ this_pymodule = self.pycore.resource_to_pyobject(resource)
+ pyname = evaluate.eval_location(this_pymodule, offset)
+ if pyname is None or not isinstance(pyname.get_object(),
+ pyobjects.PyFunction):
+ raise exceptions.RefactoringError(
+ 'Replace method with method object refactoring should be '
+ 'performed on a function.')
+ self.pyfunction = pyname.get_object()
+ self.pymodule = self.pyfunction.get_module()
+ self.resource = self.pymodule.get_resource()
+
+ def get_new_class(self, name):
+ body = sourceutils.fix_indentation(
+ self._get_body(), sourceutils.get_indent(self.pycore) * 2)
+ return 'class %s(object):\n\n%s%sdef __call__(self):\n%s' % \
+ (name, self._get_init(),
+ ' ' * sourceutils.get_indent(self.pycore), body)
+
+ def get_changes(self, classname=None, new_class_name=None):
+ if new_class_name is not None:
+ warnings.warn(
+ 'new_class_name parameter is deprecated; use classname',
+ DeprecationWarning, stacklevel=2)
+ classname = new_class_name
+ collector = codeanalyze.ChangeCollector(self.pymodule.source_code)
+ start, end = sourceutils.get_body_region(self.pyfunction)
+ indents = sourceutils.get_indents(
+ self.pymodule.lines, self.pyfunction.get_scope().get_start()) + \
+ sourceutils.get_indent(self.pycore)
+ new_contents = ' ' * indents + 'return %s(%s)()\n' % \
+ (classname, ', '.join(self._get_parameter_names()))
+ collector.add_change(start, end, new_contents)
+ insertion = self._get_class_insertion_point()
+ collector.add_change(insertion, insertion,
+ '\n\n' + self.get_new_class(classname))
+ changes = change.ChangeSet('Replace method with method object refactoring')
+ changes.add_change(change.ChangeContents(self.resource,
+ collector.get_changed()))
+ return changes
+
+ def _get_class_insertion_point(self):
+ current = self.pyfunction
+ while current.parent != self.pymodule:
+ current = current.parent
+ end = self.pymodule.lines.get_line_end(current.get_scope().get_end())
+ return min(end + 1, len(self.pymodule.source_code))
+
+ def _get_body(self):
+ body = sourceutils.get_body(self.pyfunction)
+ for param in self._get_parameter_names():
+ body = param + ' = None\n' + body
+ pymod = self.pycore.get_string_module(body, self.resource)
+ pyname = pymod[param]
+ finder = occurrences.create_finder(self.pycore, param, pyname)
+ result = rename.rename_in_module(finder, 'self.' + param,
+ pymodule=pymod)
+ body = result[result.index('\n') + 1:]
+ return body
+
+ def _get_init(self):
+ params = self._get_parameter_names()
+ indents = ' ' * sourceutils.get_indent(self.pycore)
+ if not params:
+ return ''
+ header = indents + 'def __init__(self'
+ body = ''
+ for arg in params:
+ new_name = arg
+ if arg == 'self':
+ new_name = 'host'
+ header += ', %s' % new_name
+ body += indents * 2 + 'self.%s = %s\n' % (arg, new_name)
+ header += '):'
+ return '%s\n%s\n' % (header, body)
+
+ def _get_parameter_names(self):
+ return self.pyfunction.get_param_names()
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/move.py b/vim/eclim/autoload/eclim/python/rope/refactor/move.py
@@ -0,0 +1,625 @@
+"""A module containing classes for move refactoring
+
+`create_move()` is a factory for creating move refactoring objects
+based on inputs.
+
+"""
+from rope.base import pyobjects, codeanalyze, exceptions, pynames, taskhandle, evaluate, worder
+from rope.base.change import ChangeSet, ChangeContents, MoveResource
+from rope.refactor import importutils, rename, occurrences, sourceutils, functionutils
+
+
+def create_move(project, resource, offset=None):
+ """A factory for creating Move objects
+
+ Based on `resource` and `offset`, return one of `MoveModule`,
+ `MoveGlobal` or `MoveMethod` for performing move refactoring.
+
+ """
+ if offset is None:
+ return MoveModule(project, resource)
+ this_pymodule = project.pycore.resource_to_pyobject(resource)
+ pyname = evaluate.eval_location(this_pymodule, offset)
+ if pyname is None:
+ raise exceptions.RefactoringError(
+ 'Move only works on classes, functions, modules and methods.')
+ pyobject = pyname.get_object()
+ if isinstance(pyobject, pyobjects.PyModule) or \
+ isinstance(pyobject, pyobjects.PyPackage):
+ return MoveModule(project, pyobject.get_resource())
+ if isinstance(pyobject, pyobjects.PyFunction) and \
+ isinstance(pyobject.parent, pyobjects.PyClass):
+ return MoveMethod(project, resource, offset)
+ if isinstance(pyobject, pyobjects.PyDefinedObject) and \
+ isinstance(pyobject.parent, pyobjects.PyModule):
+ return MoveGlobal(project, resource, offset)
+ raise exceptions.RefactoringError(
+ 'Move only works on global classes/functions, modules and methods.')
+
+
+class MoveMethod(object):
+ """For moving methods
+
+ It makes a new method in the destination class and changes
+ the body of the old method to call the new method. You can
+ inline the old method to change all of its occurrences.
+
+ """
+
+ def __init__(self, project, resource, offset):
+ self.project = project
+ self.pycore = project.pycore
+ this_pymodule = self.pycore.resource_to_pyobject(resource)
+ pyname = evaluate.eval_location(this_pymodule, offset)
+ self.method_name = worder.get_name_at(resource, offset)
+ self.pyfunction = pyname.get_object()
+ if self.pyfunction.get_kind() != 'method':
+ raise exceptions.RefactoringError('Only normal methods'
+ ' can be moved.')
+
+ def get_changes(self, dest_attr, new_name=None, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Return the changes needed for this refactoring
+
+ Parameters:
+
+ - `dest_attr`: the name of the destination attribute
+ - `new_name`: the name of the new method; if `None` uses
+ the old name
+ - `resources` can be a list of `rope.base.resources.File`\s to
+ apply this refactoring on. If `None`, the restructuring
+ will be applied to all python files.
+
+ """
+ changes = ChangeSet('Moving method <%s>' % self.method_name)
+ if resources is None:
+ resources = self.pycore.get_python_files()
+ if new_name is None:
+ new_name = self.get_method_name()
+ resource1, start1, end1, new_content1 = \
+ self._get_changes_made_by_old_class(dest_attr, new_name)
+ collector1 = codeanalyze.ChangeCollector(resource1.read())
+ collector1.add_change(start1, end1, new_content1)
+
+ resource2, start2, end2, new_content2 = \
+ self._get_changes_made_by_new_class(dest_attr, new_name)
+ if resource1 == resource2:
+ collector1.add_change(start2, end2, new_content2)
+ else:
+ collector2 = codeanalyze.ChangeCollector(resource2.read())
+ collector2.add_change(start2, end2, new_content2)
+ result = collector2.get_changed()
+ import_tools = importutils.ImportTools(self.pycore)
+ new_imports = self._get_used_imports(import_tools)
+ if new_imports:
+ goal_pymodule = self.pycore.get_string_module(result,
+ resource2)
+ result = _add_imports_to_module(
+ import_tools, goal_pymodule, new_imports)
+ if resource2 in resources:
+ changes.add_change(ChangeContents(resource2, result))
+
+ if resource1 in resources:
+ changes.add_change(ChangeContents(resource1,
+ collector1.get_changed()))
+ return changes
+
+ def get_method_name(self):
+ return self.method_name
+
+ def _get_used_imports(self, import_tools):
+ return importutils.get_imports(self.pycore, self.pyfunction)
+
+ def _get_changes_made_by_old_class(self, dest_attr, new_name):
+ pymodule = self.pyfunction.get_module()
+ indents = self._get_scope_indents(self.pyfunction)
+ body = 'return self.%s.%s(%s)\n' % (dest_attr, new_name,
+ self._get_passed_arguments_string())
+ region = sourceutils.get_body_region(self.pyfunction)
+ return (pymodule.get_resource(), region[0], region[1],
+ sourceutils.fix_indentation(body, indents))
+
+ def _get_scope_indents(self, pyobject):
+ pymodule = pyobject.get_module()
+ return sourceutils.get_indents(
+ pymodule.lines, pyobject.get_scope().get_start()) + \
+ sourceutils.get_indent(self.pycore)
+
+ def _get_changes_made_by_new_class(self, dest_attr, new_name):
+ old_pyclass = self.pyfunction.parent
+ if dest_attr not in old_pyclass:
+ raise exceptions.RefactoringError(
+ 'Destination attribute <%s> not found' % dest_attr)
+ pyclass = old_pyclass[dest_attr].get_object().get_type()
+ if not isinstance(pyclass, pyobjects.PyClass):
+ raise exceptions.RefactoringError(
+ 'Unknown class type for attribute <%s>' % dest_attr)
+ pymodule = pyclass.get_module()
+ resource = pyclass.get_module().get_resource()
+ start, end = sourceutils.get_body_region(pyclass)
+ pre_blanks = '\n'
+ if pymodule.source_code[start:end].strip() != 'pass':
+ pre_blanks = '\n\n'
+ start = end
+ indents = self._get_scope_indents(pyclass)
+ body = pre_blanks + sourceutils.fix_indentation(
+ self.get_new_method(new_name), indents)
+ return resource, start, end, body
+
+ def get_new_method(self, name):
+ return '%s\n%s' % (
+ self._get_new_header(name),
+ sourceutils.fix_indentation(self._get_body(),
+ sourceutils.get_indent(self.pycore)))
+
+ def _get_unchanged_body(self):
+ return sourceutils.get_body(self.pyfunction)
+
+ def _get_body(self, host='host'):
+ self_name = self._get_self_name()
+ body = self_name + ' = None\n' + self._get_unchanged_body()
+ pymodule = self.pycore.get_string_module(body)
+ finder = occurrences.create_finder(
+ self.pycore, self_name, pymodule[self_name])
+ result = rename.rename_in_module(finder, host, pymodule=pymodule)
+ if result is None:
+ result = body
+ return result[result.index('\n') + 1:]
+
+ def _get_self_name(self):
+ return self.pyfunction.get_param_names()[0]
+
+ def _get_new_header(self, name):
+ header = 'def %s(self' % name
+ if self._is_host_used():
+ header += ', host'
+ definition_info = functionutils.DefinitionInfo.read(self.pyfunction)
+ others = definition_info.arguments_to_string(1)
+ if others:
+ header += ', ' + others
+ return header + '):'
+
+ def _get_passed_arguments_string(self):
+ result = ''
+ if self._is_host_used():
+ result = 'self'
+ definition_info = functionutils.DefinitionInfo.read(self.pyfunction)
+ others = definition_info.arguments_to_string(1)
+ if others:
+ if result:
+ result += ', '
+ result += others
+ return result
+
+ def _is_host_used(self):
+ return self._get_body('__old_self') != self._get_unchanged_body()
+
+
+class MoveGlobal(object):
+ """For moving global function and classes"""
+
+ def __init__(self, project, resource, offset):
+ self.pycore = project.pycore
+ this_pymodule = self.pycore.resource_to_pyobject(resource)
+ self.old_pyname = evaluate.eval_location(this_pymodule, offset)
+ self.old_name = self.old_pyname.get_object().get_name()
+ pymodule = self.old_pyname.get_object().get_module()
+ self.source = pymodule.get_resource()
+ self.tools = _MoveTools(self.pycore, self.source,
+ self.old_pyname, self.old_name)
+ self.import_tools = self.tools.import_tools
+ self._check_exceptional_conditions()
+
+ def _check_exceptional_conditions(self):
+ if self.old_pyname is None or \
+ not isinstance(self.old_pyname.get_object(), pyobjects.PyDefinedObject):
+ raise exceptions.RefactoringError(
+ 'Move refactoring should be performed on a class/function.')
+ moving_pyobject = self.old_pyname.get_object()
+ if not self._is_global(moving_pyobject):
+ raise exceptions.RefactoringError(
+ 'Move refactoring should be performed on a global class/function.')
+
+ def _is_global(self, pyobject):
+ return pyobject.get_scope().parent == pyobject.get_module().get_scope()
+
+ def get_changes(self, dest, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ if resources is None:
+ resources = self.pycore.get_python_files()
+ if dest is None or not dest.exists():
+ raise exceptions.RefactoringError(
+ 'Move destination does not exist.')
+ if dest.is_folder() and dest.has_child('__init__.py'):
+ dest = dest.get_child('__init__.py')
+ if dest.is_folder():
+ raise exceptions.RefactoringError(
+ 'Move destination for non-modules should not be folders.')
+ if self.source == dest:
+ raise exceptions.RefactoringError(
+ 'Moving global elements to the same module.')
+ return self._calculate_changes(dest, resources, task_handle)
+
+ def _calculate_changes(self, dest, resources, task_handle):
+ changes = ChangeSet('Moving global <%s>' % self.old_name)
+ job_set = task_handle.create_jobset('Collecting Changes',
+ len(resources))
+ for file_ in resources:
+ job_set.started_job(file_.path)
+ if file_ == self.source:
+ changes.add_change(self._source_module_changes(dest))
+ elif file_ == dest:
+ changes.add_change(self._dest_module_changes(dest))
+ elif self.tools.occurs_in_module(resource=file_):
+ pymodule = self.pycore.resource_to_pyobject(file_)
+ # Changing occurrences
+ placeholder = '__rope_renaming_%s_' % self.old_name
+ source = self.tools.rename_in_module(placeholder,
+ resource=file_)
+ should_import = source is not None
+ # Removing out of date imports
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ source = self.tools.remove_old_imports(pymodule)
+ # Adding new import
+ if should_import:
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ source, imported = importutils.add_import(
+ self.pycore, pymodule, self._new_modname(dest), self.old_name)
+ source = source.replace(placeholder, imported)
+ source = self.tools.new_source(pymodule, source)
+ if source != file_.read():
+ changes.add_change(ChangeContents(file_, source))
+ job_set.finished_job()
+ return changes
+
+ def _source_module_changes(self, dest):
+ placeholder = '__rope_moving_%s_' % self.old_name
+ handle = _ChangeMoveOccurrencesHandle(placeholder)
+ occurrence_finder = occurrences.create_finder(
+ self.pycore, self.old_name, self.old_pyname)
+ start, end = self._get_moving_region()
+ renamer = ModuleSkipRenamer(occurrence_finder, self.source,
+ handle, start, end)
+ source = renamer.get_changed_module()
+ if handle.occurred:
+ pymodule = self.pycore.get_string_module(source, self.source)
+ # Adding new import
+ source, imported = importutils.add_import(
+ self.pycore, pymodule, self._new_modname(dest), self.old_name)
+ source = source.replace(placeholder, imported)
+ return ChangeContents(self.source, source)
+
+ def _new_modname(self, dest):
+ return self.pycore.modname(dest)
+
+ def _dest_module_changes(self, dest):
+ # Changing occurrences
+ pymodule = self.pycore.resource_to_pyobject(dest)
+ source = self.tools.rename_in_module(self.old_name, pymodule)
+ pymodule = self.tools.new_pymodule(pymodule, source)
+
+ moving, imports = self._get_moving_element_with_imports()
+ source = self.tools.remove_old_imports(pymodule)
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ pymodule, has_changed = self._add_imports2(pymodule, imports)
+
+ module_with_imports = self.import_tools.module_imports(pymodule)
+ source = pymodule.source_code
+ if module_with_imports.imports:
+ start = pymodule.lines.get_line_end(
+ module_with_imports.imports[-1].end_line - 1)
+ result = source[:start + 1] + '\n\n'
+ else:
+ result = ''
+ start = -1
+ result += moving + source[start + 1:]
+
+ # Organizing imports
+ source = result
+ pymodule = self.pycore.get_string_module(source, dest)
+ source = self.import_tools.organize_imports(pymodule, sort=False,
+ unused=False)
+ return ChangeContents(dest, source)
+
+ def _get_moving_element_with_imports(self):
+ return moving_code_with_imports(
+ self.pycore, self.source, self._get_moving_element())
+
+ def _get_module_with_imports(self, source_code, resource):
+ pymodule = self.pycore.get_string_module(source_code, resource)
+ return self.import_tools.module_imports(pymodule)
+
+ def _get_moving_element(self):
+ start, end = self._get_moving_region()
+ moving = self.source.read()[start:end]
+ return moving.rstrip() + '\n'
+
+ def _get_moving_region(self):
+ pymodule = self.pycore.resource_to_pyobject(self.source)
+ lines = pymodule.lines
+ scope = self.old_pyname.get_object().get_scope()
+ start = lines.get_line_start(scope.get_start())
+ end_line = scope.get_end()
+ while end_line < lines.length() and \
+ lines.get_line(end_line + 1).strip() == '':
+ end_line += 1
+ end = min(lines.get_line_end(end_line) + 1, len(pymodule.source_code))
+ return start, end
+
+ def _add_imports2(self, pymodule, new_imports):
+ source = self.tools.add_imports(pymodule, new_imports)
+ if source is None:
+ return pymodule, False
+ else:
+ resource = pymodule.get_resource()
+ pymodule = self.pycore.get_string_module(source, resource)
+ return pymodule, True
+
+
+class MoveModule(object):
+ """For moving modules and packages"""
+
+ def __init__(self, project, resource):
+ self.project = project
+ self.pycore = project.pycore
+ if not resource.is_folder() and resource.name == '__init__.py':
+ resource = resource.parent
+ if resource.is_folder() and not resource.has_child('__init__.py'):
+ raise exceptions.RefactoringError(
+ 'Cannot move non-package folder.')
+ dummy_pymodule = self.pycore.get_string_module('')
+ self.old_pyname = pynames.ImportedModule(dummy_pymodule,
+ resource=resource)
+ self.source = self.old_pyname.get_object().get_resource()
+ if self.source.is_folder():
+ self.old_name = self.source.name
+ else:
+ self.old_name = self.source.name[:-3]
+ self.tools = _MoveTools(self.pycore, self.source,
+ self.old_pyname, self.old_name)
+ self.import_tools = self.tools.import_tools
+
+ def get_changes(self, dest, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ moving_pyobject = self.old_pyname.get_object()
+ if resources is None:
+ resources = self.pycore.get_python_files()
+ if dest is None or not dest.is_folder():
+ raise exceptions.RefactoringError(
+ 'Move destination for modules should be packages.')
+ return self._calculate_changes(dest, resources, task_handle)
+
+ def _calculate_changes(self, dest, resources, task_handle):
+ changes = ChangeSet('Moving module <%s>' % self.old_name)
+ job_set = task_handle.create_jobset('Collecting changes',
+ len(resources))
+ for module in resources:
+ job_set.started_job(module.path)
+ if module == self.source:
+ self._change_moving_module(changes, dest)
+ else:
+ source = self._change_occurrences_in_module(dest,
+ resource=module)
+ if source is not None:
+ changes.add_change(ChangeContents(module, source))
+ job_set.finished_job()
+ if self.project == self.source.project:
+ changes.add_change(MoveResource(self.source, dest.path))
+ return changes
+
+ def _new_modname(self, dest):
+ destname = self.pycore.modname(dest)
+ if destname:
+ return destname + '.' + self.old_name
+ return self.old_name
+
+ def _new_import(self, dest):
+ return importutils.NormalImport([(self._new_modname(dest), None)])
+
+ def _change_moving_module(self, changes, dest):
+ if not self.source.is_folder():
+ pymodule = self.pycore.resource_to_pyobject(self.source)
+ source = self.import_tools.relatives_to_absolutes(pymodule)
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ source = self._change_occurrences_in_module(dest, pymodule)
+ source = self.tools.new_source(pymodule, source)
+ if source != self.source.read():
+ changes.add_change(ChangeContents(self.source, source))
+
+ def _change_occurrences_in_module(self, dest, pymodule=None,
+ resource=None):
+ if not self.tools.occurs_in_module(pymodule=pymodule,
+ resource=resource):
+ return
+ if pymodule is None:
+ pymodule = self.pycore.resource_to_pyobject(resource)
+ new_name = self._new_modname(dest)
+ new_import = self._new_import(dest)
+ source = self.tools.rename_in_module(
+ new_name, imports=True, pymodule=pymodule, resource=resource)
+ should_import = self.tools.occurs_in_module(
+ pymodule=pymodule, resource=resource, imports=False)
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ source = self.tools.remove_old_imports(pymodule)
+ if should_import:
+ pymodule = self.tools.new_pymodule(pymodule, source)
+ source = self.tools.add_imports(pymodule, [new_import])
+ source = self.tools.new_source(pymodule, source)
+ if source != pymodule.resource.read():
+ return source
+
+
+class _ChangeMoveOccurrencesHandle(object):
+
+ def __init__(self, new_name):
+ self.new_name = new_name
+ self.occurred = False
+
+ def occurred_inside_skip(self, change_collector, occurrence):
+ pass
+
+ def occurred_outside_skip(self, change_collector, occurrence):
+ start, end = occurrence.get_primary_range()
+ change_collector.add_change(start, end, self.new_name)
+ self.occurred = True
+
+
+class _MoveTools(object):
+
+ def __init__(self, pycore, source, pyname, old_name):
+ self.pycore = pycore
+ self.source = source
+ self.old_pyname = pyname
+ self.old_name = old_name
+ self.import_tools = importutils.ImportTools(self.pycore)
+
+ def remove_old_imports(self, pymodule):
+ old_source = pymodule.source_code
+ module_with_imports = self.import_tools.module_imports(pymodule)
+ class CanSelect(object):
+ changed = False
+ old_name = self.old_name
+ old_pyname = self.old_pyname
+ def __call__(self, name):
+ try:
+ if name == self.old_name and \
+ pymodule[name].get_object() == \
+ self.old_pyname.get_object():
+ self.changed = True
+ return False
+ except exceptions.AttributeNotFoundError:
+ pass
+ return True
+ can_select = CanSelect()
+ module_with_imports.filter_names(can_select)
+ new_source = module_with_imports.get_changed_source()
+ if old_source != new_source:
+ return new_source
+
+ def rename_in_module(self, new_name, pymodule=None,
+ imports=False, resource=None):
+ occurrence_finder = self._create_finder(imports)
+ source = rename.rename_in_module(
+ occurrence_finder, new_name, replace_primary=True,
+ pymodule=pymodule, resource=resource)
+ return source
+
+ def occurs_in_module(self, pymodule=None, resource=None, imports=True):
+ finder = self._create_finder(imports)
+ for occurrence in finder.find_occurrences(pymodule=pymodule,
+ resource=resource):
+ return True
+ return False
+
+ def _create_finder(self, imports):
+ return occurrences.create_finder(self.pycore, self.old_name,
+ self.old_pyname, imports=imports)
+
+ def new_pymodule(self, pymodule, source):
+ if source is not None:
+ return self.pycore.get_string_module(
+ source, pymodule.get_resource())
+ return pymodule
+
+ def new_source(self, pymodule, source):
+ if source is None:
+ return pymodule.source_code
+ return source
+
+ def add_imports(self, pymodule, new_imports):
+ return _add_imports_to_module(self.import_tools, pymodule, new_imports)
+
+
+def _add_imports_to_module(import_tools, pymodule, new_imports):
+ module_with_imports = import_tools.module_imports(pymodule)
+ for new_import in new_imports:
+ module_with_imports.add_import(new_import)
+ return module_with_imports.get_changed_source()
+
+
+def moving_code_with_imports(pycore, resource, source):
+ import_tools = importutils.ImportTools(pycore)
+ pymodule = pycore.get_string_module(source, resource)
+ origin = pycore.resource_to_pyobject(resource)
+
+ imports = []
+ for stmt in import_tools.module_imports(origin).imports:
+ imports.append(stmt.import_info)
+
+ back_names = []
+ for name in origin:
+ if name not in pymodule:
+ back_names.append(name)
+ imports.append(import_tools.get_from_import(resource, back_names))
+
+ source = _add_imports_to_module(import_tools, pymodule, imports)
+ pymodule = pycore.get_string_module(source, resource)
+
+ source = import_tools.relatives_to_absolutes(pymodule)
+ pymodule = pycore.get_string_module(source, resource)
+ source = import_tools.organize_imports(pymodule, selfs=False)
+ pymodule = pycore.get_string_module(source, resource)
+
+ # extracting imports after changes
+ module_imports = import_tools.module_imports(pymodule)
+ imports = [import_stmt.import_info
+ for import_stmt in module_imports.imports]
+ start = 1
+ if module_imports.imports:
+ start = module_imports.imports[-1].end_line
+ lines = codeanalyze.SourceLinesAdapter(source)
+ while start < lines.length() and not lines.get_line(start).strip():
+ start += 1
+ moving = source[lines.get_line_start(start):]
+ return moving, imports
+
+
+class ModuleSkipRenamerHandle(object):
+
+ def occurred_outside_skip(self, change_collector, occurrence):
+ pass
+
+ def occurred_inside_skip(self, change_collector, occurrence):
+ pass
+
+
+class ModuleSkipRenamer(object):
+ """Rename occurrences in a module
+
+ This class can be used when you want to treat a region in a file
+ separately from other parts when renaming.
+
+ """
+
+ def __init__(self, occurrence_finder, resource, handle=None,
+ skip_start=0, skip_end=0, replacement=''):
+ """Constructor
+
+ if replacement is `None` the region is not changed. Otherwise
+ it is replaced with `replacement`.
+
+ """
+ self.occurrence_finder = occurrence_finder
+ self.resource = resource
+ self.skip_start = skip_start
+ self.skip_end = skip_end
+ self.replacement = replacement
+ self.handle = handle
+ if self.handle is None:
+ self.handle = ModuleSkipHandle()
+
+ def get_changed_module(self):
+ source = self.resource.read()
+ change_collector = codeanalyze.ChangeCollector(source)
+ if self.replacement is not None:
+ change_collector.add_change(self.skip_start, self.skip_end,
+ self.replacement)
+ for occurrence in self.occurrence_finder.find_occurrences(self.resource):
+ start, end = occurrence.get_primary_range()
+ if self.skip_start <= start < self.skip_end:
+ self.handle.occurred_inside_skip(change_collector, occurrence)
+ else:
+ self.handle.occurred_outside_skip(change_collector, occurrence)
+ result = change_collector.get_changed()
+ if result is not None and result != source:
+ return result
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/multiproject.py b/vim/eclim/autoload/eclim/python/rope/refactor/multiproject.py
@@ -0,0 +1,78 @@
+"""This module can be used for performing cross-project refactorings
+
+See the "cross-project refactorings" section of ``docs/library.txt``
+file.
+
+"""
+
+from rope.base import resources, project, libutils
+
+
+class MultiProjectRefactoring(object):
+
+ def __init__(self, refactoring, projects, addpath=True):
+ """Create a multiproject proxy for the main refactoring
+
+ `projects` are other project.
+
+ """
+ self.refactoring = refactoring
+ self.projects = projects
+ self.addpath = addpath
+
+ def __call__(self, project, *args, **kwds):
+ """Create the refactoring"""
+ return _MultiRefactoring(self.refactoring, self.projects,
+ self.addpath, project, *args, **kwds)
+
+
+class _MultiRefactoring(object):
+
+ def __init__(self, refactoring, other_projects, addpath,
+ project, *args, **kwds):
+ self.refactoring = refactoring
+ self.projects = [project] + other_projects
+ for other_project in other_projects:
+ for folder in self.project.pycore.get_source_folders():
+ other_project.get_prefs().add('python_path', folder.real_path)
+ self.refactorings = []
+ for other in self.projects:
+ args, kwds = self._resources_for_args(other, args, kwds)
+ self.refactorings.append(
+ self.refactoring(other, *args, **kwds))
+
+ def get_all_changes(self, *args, **kwds):
+ """Get a project to changes dict"""
+ result = []
+ for project, refactoring in zip(self.projects, self.refactorings):
+ args, kwds = self._resources_for_args(project, args, kwds)
+ result.append((project, refactoring.get_changes(*args, **kwds)))
+ return result
+
+ def __getattr__(self, name):
+ return getattr(self.main_refactoring, name)
+
+ def _resources_for_args(self, project, args, kwds):
+ newargs = [self._change_project_resource(project, arg) for arg in args]
+ newkwds = dict((name, self._change_project_resource(project, value))
+ for name, value in kwds.items())
+ return newargs, newkwds
+
+ def _change_project_resource(self, project, obj):
+ if isinstance(obj, resources.Resource) and \
+ obj.project != project:
+ return libutils.path_to_resource(project, obj.real_path)
+ return obj
+
+ @property
+ def project(self):
+ return self.projects[0]
+
+ @property
+ def main_refactoring(self):
+ return self.refactorings[0]
+
+
+def perform(project_changes):
+ for project, changes in project_changes:
+ project.do(changes)
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/occurrences.py b/vim/eclim/autoload/eclim/python/rope/refactor/occurrences.py
@@ -0,0 +1,334 @@
+import re
+
+import rope.base.pynames
+from rope.base import pynames, pyobjects, codeanalyze, evaluate, exceptions, utils, worder
+
+
+class Finder(object):
+ """For finding occurrences of a name
+
+ The constructor takes a `filters` argument. It should be a list
+ of functions that take a single argument. For each possible
+ occurrence, these functions are called in order with the an
+ instance of `Occurrence`:
+
+ * If it returns `None` other filters are tried.
+ * If it returns `True`, the occurrence will be a match.
+ * If it returns `False`, the occurrence will be skipped.
+ * If all of the filters return `None`, it is skipped also.
+
+ """
+
+ def __init__(self, pycore, name, filters=[lambda o: True], docs=False):
+ self.pycore = pycore
+ self.name = name
+ self.docs = docs
+ self.filters = filters
+ self._textual_finder = _TextualFinder(name, docs=docs)
+
+ def find_occurrences(self, resource=None, pymodule=None):
+ """Generate `Occurrence` instances"""
+ tools = _OccurrenceToolsCreator(self.pycore, resource=resource,
+ pymodule=pymodule, docs=self.docs)
+ for offset in self._textual_finder.find_offsets(tools.source_code):
+ occurrence = Occurrence(tools, offset)
+ for filter in self.filters:
+ result = filter(occurrence)
+ if result is None:
+ continue
+ if result:
+ yield occurrence
+ break
+
+
+def create_finder(pycore, name, pyname, only_calls=False, imports=True,
+ unsure=None, docs=False, instance=None, in_hierarchy=False):
+ """A factory for `Finder`
+
+ Based on the arguments it creates a list of filters. `instance`
+ argument is needed only when you want implicit interfaces to be
+ considered.
+
+ """
+ pynames = set([pyname])
+ filters = []
+ if only_calls:
+ filters.append(CallsFilter())
+ if not imports:
+ filters.append(NoImportsFilter())
+ if isinstance(instance, rope.base.pynames.ParameterName):
+ for pyobject in instance.get_objects():
+ try:
+ pynames.add(pyobject[name])
+ except exceptions.AttributeNotFoundError:
+ pass
+ for pyname in pynames:
+ filters.append(PyNameFilter(pyname))
+ if in_hierarchy:
+ filters.append(InHierarchyFilter(pyname))
+ if unsure:
+ filters.append(UnsureFilter(unsure))
+ return Finder(pycore, name, filters=filters, docs=docs)
+
+
+class Occurrence(object):
+
+ def __init__(self, tools, offset):
+ self.tools = tools
+ self.offset = offset
+ self.resource = tools.resource
+
+ @utils.saveit
+ def get_word_range(self):
+ return self.tools.word_finder.get_word_range(self.offset)
+
+ @utils.saveit
+ def get_primary_range(self):
+ return self.tools.word_finder.get_primary_range(self.offset)
+
+ @utils.saveit
+ def get_pyname(self):
+ try:
+ return self.tools.name_finder.get_pyname_at(self.offset)
+ except exceptions.BadIdentifierError:
+ pass
+
+ @utils.saveit
+ def get_primary_and_pyname(self):
+ try:
+ return self.tools.name_finder.get_primary_and_pyname_at(self.offset)
+ except exceptions.BadIdentifierError:
+ pass
+
+ @utils.saveit
+ def is_in_import_statement(self):
+ return (self.tools.word_finder.is_from_statement(self.offset) or
+ self.tools.word_finder.is_import_statement(self.offset))
+
+ def is_called(self):
+ return self.tools.word_finder.is_a_function_being_called(self.offset)
+
+ def is_defined(self):
+ return self.tools.word_finder.is_a_class_or_function_name_in_header(self.offset)
+
+ def is_a_fixed_primary(self):
+ return self.tools.word_finder.is_a_class_or_function_name_in_header(self.offset) or \
+ self.tools.word_finder.is_a_name_after_from_import(self.offset)
+
+ def is_written(self):
+ return self.tools.word_finder.is_assigned_here(self.offset)
+
+ def is_unsure(self):
+ return unsure_pyname(self.get_pyname())
+
+ @property
+ @utils.saveit
+ def lineno(self):
+ offset = self.get_word_range()[0]
+ return self.tools.pymodule.lines.get_line_number(offset)
+
+
+def same_pyname(expected, pyname):
+ """Check whether `expected` and `pyname` are the same"""
+ if expected is None or pyname is None:
+ return False
+ if expected == pyname:
+ return True
+ if type(expected) not in (pynames.ImportedModule, pynames.ImportedName) and \
+ type(pyname) not in (pynames.ImportedModule, pynames.ImportedName):
+ return False
+ return expected.get_definition_location() == pyname.get_definition_location() and \
+ expected.get_object() == pyname.get_object()
+
+def unsure_pyname(pyname, unbound=True):
+ """Return `True` if we don't know what this name references"""
+ if pyname is None:
+ return True
+ if unbound and not isinstance(pyname, pynames.UnboundName):
+ return False
+ if pyname.get_object() == pyobjects.get_unknown():
+ return True
+
+
+class PyNameFilter(object):
+ """For finding occurrences of a name"""
+
+ def __init__(self, pyname):
+ self.pyname = pyname
+
+ def __call__(self, occurrence):
+ if same_pyname(self.pyname, occurrence.get_pyname()):
+ return True
+
+
+class InHierarchyFilter(object):
+ """For finding occurrences of a name"""
+
+ def __init__(self, pyname, implementations_only=False):
+ self.pyname = pyname
+ self.impl_only = implementations_only
+ self.pyclass = self._get_containing_class(pyname)
+ if self.pyclass is not None:
+ self.name = pyname.get_object().get_name()
+ self.roots = self._get_root_classes(self.pyclass, self.name)
+ else:
+ self.roots = None
+
+ def __call__(self, occurrence):
+ if self.roots is None:
+ return
+ pyclass = self._get_containing_class(occurrence.get_pyname())
+ if pyclass is not None:
+ roots = self._get_root_classes(pyclass, self.name)
+ if self.roots.intersection(roots):
+ return True
+
+ def _get_containing_class(self, pyname):
+ if isinstance(pyname, pynames.DefinedName):
+ scope = pyname.get_object().get_scope()
+ parent = scope.parent
+ if parent is not None and parent.get_kind() == 'Class':
+ return parent.pyobject
+
+ def _get_root_classes(self, pyclass, name):
+ if self.impl_only and pyclass == self.pyclass:
+ return set([pyclass])
+ result = set()
+ for superclass in pyclass.get_superclasses():
+ if name in superclass:
+ result.update(self._get_root_classes(superclass, name))
+ if not result:
+ return set([pyclass])
+ return result
+
+
+class UnsureFilter(object):
+
+ def __init__(self, unsure):
+ self.unsure = unsure
+
+ def __call__(self, occurrence):
+ if occurrence.is_unsure() and self.unsure(occurrence):
+ return True
+
+
+class NoImportsFilter(object):
+
+ def __call__(self, occurrence):
+ if occurrence.is_in_import_statement():
+ return False
+
+
+class CallsFilter(object):
+
+ def __call__(self, occurrence):
+ if not occurrence.is_called():
+ return False
+
+
+class _TextualFinder(object):
+
+ def __init__(self, name, docs=False):
+ self.name = name
+ self.docs = docs
+ self.comment_pattern = _TextualFinder.any('comment', [r'#[^\n]*'])
+ self.string_pattern = _TextualFinder.any(
+ 'string', [codeanalyze.get_string_pattern()])
+ self.pattern = self._get_occurrence_pattern(self.name)
+
+ def find_offsets(self, source):
+ if not self._fast_file_query(source):
+ return
+ if self.docs:
+ searcher = self._normal_search
+ else:
+ searcher = self._re_search
+ for matched in searcher(source):
+ yield matched
+
+ def _re_search(self, source):
+ for match in self.pattern.finditer(source):
+ for key, value in match.groupdict().items():
+ if value and key == 'occurrence':
+ yield match.start(key)
+
+ def _normal_search(self, source):
+ current = 0
+ while True:
+ try:
+ found = source.index(self.name, current)
+ current = found + len(self.name)
+ if (found == 0 or not self._is_id_char(source[found - 1])) and \
+ (current == len(source) or not self._is_id_char(source[current])):
+ yield found
+ except ValueError:
+ break
+
+ def _is_id_char(self, c):
+ return c.isalnum() or c == '_'
+
+ def _fast_file_query(self, source):
+ try:
+ source.index(self.name)
+ return True
+ except ValueError:
+ return False
+
+ def _get_source(self, resource, pymodule):
+ if resource is not None:
+ return resource.read()
+ else:
+ return pymodule.source_code
+
+ def _get_occurrence_pattern(self, name):
+ occurrence_pattern = _TextualFinder.any('occurrence',
+ ['\\b' + name + '\\b'])
+ pattern = re.compile(occurrence_pattern + '|' + self.comment_pattern +
+ '|' + self.string_pattern)
+ return pattern
+
+ @staticmethod
+ def any(name, list_):
+ return '(?P<%s>' % name + '|'.join(list_) + ')'
+
+
+class _OccurrenceToolsCreator(object):
+
+ def __init__(self, pycore, resource=None, pymodule=None, docs=False):
+ self.pycore = pycore
+ self.__resource = resource
+ self.__pymodule = pymodule
+ self.docs = docs
+
+ @property
+ @utils.saveit
+ def name_finder(self):
+ return evaluate.ScopeNameFinder(self.pymodule)
+
+ @property
+ @utils.saveit
+ def source_code(self):
+ if self.__resource is not None:
+ return self.resource.read()
+ else:
+ return self.pymodule.source_code
+
+ @property
+ @utils.saveit
+ def word_finder(self):
+ return worder.Worder(self.source_code, self.docs)
+
+ @property
+ @utils.saveit
+ def resource(self):
+ if self.__resource is not None:
+ return self.__resource
+ if self.__pymodule is not None:
+ return self.__pymodule.resource
+
+ @property
+ @utils.saveit
+ def pymodule(self):
+ if self.__pymodule is not None:
+ return self.__pymodule
+ return self.pycore.resource_to_pyobject(self.resource)
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/patchedast.py b/vim/eclim/autoload/eclim/python/rope/refactor/patchedast.py
@@ -0,0 +1,732 @@
+import collections
+import re
+import warnings
+
+from rope.base import ast, codeanalyze, exceptions
+
+
+def get_patched_ast(source, sorted_children=False):
+ """Adds ``region`` and ``sorted_children`` fields to nodes
+
+ Adds ``sorted_children`` field only if `sorted_children` is True.
+
+ """
+ return patch_ast(ast.parse(source), source, sorted_children)
+
+
+def patch_ast(node, source, sorted_children=False):
+ """Patches the given node
+
+ After calling, each node in `node` will have a new field named
+ `region` that is a tuple containing the start and end offsets
+ of the code that generated it.
+
+ If `sorted_children` is true, a `sorted_children` field will
+ be created for each node, too. It is a list containing child
+ nodes as well as whitespaces and comments that occur between
+ them.
+
+ """
+ if hasattr(node, 'region'):
+ return node
+ walker = _PatchingASTWalker(source, children=sorted_children)
+ ast.call_for_nodes(node, walker)
+ return node
+
+
+def node_region(patched_ast_node):
+ """Get the region of a patched ast node"""
+ return patched_ast_node.region
+
+
+def write_ast(patched_ast_node):
+ """Extract source form a patched AST node with `sorted_children` field
+
+ If the node is patched with sorted_children turned off you can use
+ `node_region` function for obtaining code using module source code.
+ """
+ result = []
+ for child in patched_ast_node.sorted_children:
+ if isinstance(child, ast.AST):
+ result.append(write_ast(child))
+ else:
+ result.append(child)
+ return ''.join(result)
+
+
+class MismatchedTokenError(exceptions.RopeError):
+ pass
+
+
+class _PatchingASTWalker(object):
+
+ def __init__(self, source, children=False):
+ self.source = _Source(source)
+ self.children = children
+ self.lines = codeanalyze.SourceLinesAdapter(source)
+ self.children_stack = []
+
+ Number = object()
+ String = object()
+
+ def __call__(self, node):
+ method = getattr(self, '_' + node.__class__.__name__, None)
+ if method is not None:
+ return method(node)
+ # ???: Unknown node; what should we do here?
+ warnings.warn('Unknown node type <%s>; please report!'
+ % node.__class__.__name__, RuntimeWarning)
+ node.region = (self.source.offset, self.source.offset)
+ if self.children:
+ node.sorted_children = ast.get_children(node)
+
+ def _handle(self, node, base_children, eat_parens=False, eat_spaces=False):
+ if hasattr(node, 'region'):
+ # ???: The same node was seen twice; what should we do?
+ warnings.warn(
+ 'Node <%s> has been already patched; please report!' %
+ node.__class__.__name__, RuntimeWarning)
+ return
+ base_children = collections.deque(base_children)
+ self.children_stack.append(base_children)
+ children = collections.deque()
+ formats = []
+ suspected_start = self.source.offset
+ start = suspected_start
+ first_token = True
+ while base_children:
+ child = base_children.popleft()
+ if child is None:
+ continue
+ offset = self.source.offset
+ if isinstance(child, ast.AST):
+ ast.call_for_nodes(child, self)
+ token_start = child.region[0]
+ else:
+ if child is self.String:
+ region = self.source.consume_string(
+ end=self._find_next_statement_start())
+ elif child is self.Number:
+ region = self.source.consume_number()
+ elif child == '!=':
+ # INFO: This has been added to handle deprecated ``<>``
+ region = self.source.consume_not_equal()
+ else:
+ region = self.source.consume(child)
+ child = self.source[region[0]:region[1]]
+ token_start = region[0]
+ if not first_token:
+ formats.append(self.source[offset:token_start])
+ if self.children:
+ children.append(self.source[offset:token_start])
+ else:
+ first_token = False
+ start = token_start
+ if self.children:
+ children.append(child)
+ start = self._handle_parens(children, start, formats)
+ if eat_parens:
+ start = self._eat_surrounding_parens(
+ children, suspected_start, start)
+ if eat_spaces:
+ if self.children:
+ children.appendleft(self.source[0:start])
+ end_spaces = self.source[self.source.offset:]
+ self.source.consume(end_spaces)
+ if self.children:
+ children.append(end_spaces)
+ start = 0
+ if self.children:
+ node.sorted_children = children
+ node.region = (start, self.source.offset)
+ self.children_stack.pop()
+
+ def _handle_parens(self, children, start, formats):
+ """Changes `children` and returns new start"""
+ opens, closes = self._count_needed_parens(formats)
+ old_end = self.source.offset
+ new_end = None
+ for i in range(closes):
+ new_end = self.source.consume(')')[1]
+ if new_end is not None:
+ if self.children:
+ children.append(self.source[old_end:new_end])
+ new_start = start
+ for i in range(opens):
+ new_start = self.source.rfind_token('(', 0, new_start)
+ if new_start != start:
+ if self.children:
+ children.appendleft(self.source[new_start:start])
+ start = new_start
+ return start
+
+ def _eat_surrounding_parens(self, children, suspected_start, start):
+ index = self.source.rfind_token('(', suspected_start, start)
+ if index is not None:
+ old_start = start
+ old_offset = self.source.offset
+ start = index
+ if self.children:
+ children.appendleft(self.source[start + 1:old_start])
+ children.appendleft('(')
+ token_start, token_end = self.source.consume(')')
+ if self.children:
+ children.append(self.source[old_offset:token_start])
+ children.append(')')
+ return start
+
+ def _count_needed_parens(self, children):
+ start = 0
+ opens = 0
+ for child in children:
+ if not isinstance(child, basestring):
+ continue
+ if child == '' or child[0] in '\'"':
+ continue
+ index = 0
+ while index < len(child):
+ if child[index] == ')':
+ if opens > 0:
+ opens -= 1
+ else:
+ start += 1
+ if child[index] == '(':
+ opens += 1
+ if child[index] == '#':
+ try:
+ index = child.index('\n', index)
+ except ValueError:
+ break
+ index += 1
+ return start, opens
+
+ def _find_next_statement_start(self):
+ for children in reversed(self.children_stack):
+ for child in children:
+ if isinstance(child, ast.stmt):
+ return self.lines.get_line_start(child.lineno)
+ return len(self.source.source)
+
+ _operators = {'And': 'and', 'Or': 'or', 'Add': '+', 'Sub': '-', 'Mult': '*',
+ 'Div': '/', 'Mod': '%', 'Pow': '**', 'LShift': '<<',
+ 'RShift': '>>', 'BitOr': '|', 'BitAnd': '&', 'BitXor': '^',
+ 'FloorDiv': '//', 'Invert': '~', 'Not': 'not', 'UAdd': '+',
+ 'USub': '-', 'Eq': '==', 'NotEq': '!=', 'Lt': '<',
+ 'LtE': '<=', 'Gt': '>', 'GtE': '>=', 'Is': 'is',
+ 'IsNot': 'is not', 'In': 'in', 'NotIn': 'not in'}
+
+ def _get_op(self, node):
+ return self._operators[node.__class__.__name__].split(' ')
+
+ def _Attribute(self, node):
+ self._handle(node, [node.value, '.', node.attr])
+
+ def _Assert(self, node):
+ children = ['assert', node.test]
+ if node.msg:
+ children.append(',')
+ children.append(node.msg)
+ self._handle(node, children)
+
+ def _Assign(self, node):
+ children = self._child_nodes(node.targets, '=')
+ children.append('=')
+ children.append(node.value)
+ self._handle(node, children)
+
+ def _AugAssign(self, node):
+ children = [node.target]
+ children.extend(self._get_op(node.op))
+ children.extend(['=', node.value])
+ self._handle(node, children)
+
+ def _Repr(self, node):
+ self._handle(node, ['`', node.value, '`'])
+
+ def _BinOp(self, node):
+ children = [node.left] + self._get_op(node.op) + [node.right]
+ self._handle(node, children)
+
+ def _BoolOp(self, node):
+ self._handle(node, self._child_nodes(node.values,
+ self._get_op(node.op)[0]))
+
+ def _Break(self, node):
+ self._handle(node, ['break'])
+
+ def _Call(self, node):
+ children = [node.func, '(']
+ args = list(node.args) + node.keywords
+ children.extend(self._child_nodes(args, ','))
+ if node.starargs is not None:
+ if args:
+ children.append(',')
+ children.extend(['*', node.starargs])
+ if node.kwargs is not None:
+ if args or node.starargs is not None:
+ children.append(',')
+ children.extend(['**', node.kwargs])
+ children.append(')')
+ self._handle(node, children)
+
+ def _ClassDef(self, node):
+ children = []
+ if getattr(node, 'decorator_list', None):
+ for decorator in node.decorator_list:
+ children.append('@')
+ children.append(decorator)
+ children.extend(['class', node.name])
+ if node.bases:
+ children.append('(')
+ children.extend(self._child_nodes(node.bases, ','))
+ children.append(')')
+ children.append(':')
+ children.extend(node.body)
+ self._handle(node, children)
+
+ def _Compare(self, node):
+ children = []
+ children.append(node.left)
+ for op, expr in zip(node.ops, node.comparators):
+ children.extend(self._get_op(op))
+ children.append(expr)
+ self._handle(node, children)
+
+ def _Delete(self, node):
+ self._handle(node, ['del'] + self._child_nodes(node.targets, ','))
+
+ def _Num(self, node):
+ self._handle(node, [self.Number])
+
+ def _Str(self, node):
+ self._handle(node, [self.String])
+
+ def _Continue(self, node):
+ self._handle(node, ['continue'])
+
+ def _Dict(self, node):
+ children = []
+ children.append('{')
+ if node.keys:
+ for index, (key, value) in enumerate(zip(node.keys, node.values)):
+ children.extend([key, ':', value])
+ if index < len(node.keys) - 1:
+ children.append(',')
+ children.append('}')
+ self._handle(node, children)
+
+ def _Ellipsis(self, node):
+ self._handle(node, ['...'])
+
+ def _Expr(self, node):
+ self._handle(node, [node.value])
+
+ def _Exec(self, node):
+ children = []
+ children.extend(['exec', node.body])
+ if node.globals:
+ children.extend(['in', node.globals])
+ if node.locals:
+ children.extend([',', node.locals])
+ self._handle(node, children)
+
+ def _ExtSlice(self, node):
+ children = []
+ for index, dim in enumerate(node.dims):
+ if index > 0:
+ children.append(',')
+ children.append(dim)
+ self._handle(node, children)
+
+ def _For(self, node):
+ children = ['for', node.target, 'in', node.iter, ':']
+ children.extend(node.body)
+ if node.orelse:
+ children.extend(['else', ':'])
+ children.extend(node.orelse)
+ self._handle(node, children)
+
+ def _ImportFrom(self, node):
+ children = ['from']
+ if node.level:
+ children.append('.' * node.level)
+ children.extend([node.module, 'import'])
+ children.extend(self._child_nodes(node.names, ','))
+ self._handle(node, children)
+
+ def _alias(self, node):
+ children = [node.name]
+ if node.asname:
+ children.extend(['as', node.asname])
+ self._handle(node, children)
+
+ def _FunctionDef(self, node):
+ children = []
+ try:
+ decorators = getattr(node, 'decorator_list')
+ except AttributeError:
+ decorators = getattr(node, 'decorators', None)
+ if decorators:
+ for decorator in decorators:
+ children.append('@')
+ children.append(decorator)
+ children.extend(['def', node.name, '(', node.args])
+ children.extend([')', ':'])
+ children.extend(node.body)
+ self._handle(node, children)
+
+ def _arguments(self, node):
+ children = []
+ args = list(node.args)
+ defaults = [None] * (len(args) - len(node.defaults)) + list(node.defaults)
+ for index, (arg, default) in enumerate(zip(args, defaults)):
+ if index > 0:
+ children.append(',')
+ self._add_args_to_children(children, arg, default)
+ if node.vararg is not None:
+ if args:
+ children.append(',')
+ children.extend(['*', node.vararg])
+ if node.kwarg is not None:
+ if args or node.vararg is not None:
+ children.append(',')
+ children.extend(['**', node.kwarg])
+ self._handle(node, children)
+
+ def _add_args_to_children(self, children, arg, default):
+ if isinstance(arg, (list, tuple)):
+ self._add_tuple_parameter(children, arg)
+ else:
+ children.append(arg)
+ if default is not None:
+ children.append('=')
+ children.append(default)
+
+ def _add_tuple_parameter(self, children, arg):
+ children.append('(')
+ for index, token in enumerate(arg):
+ if index > 0:
+ children.append(',')
+ if isinstance(token, (list, tuple)):
+ self._add_tuple_parameter(children, token)
+ else:
+ children.append(token)
+ children.append(')')
+
+ def _GeneratorExp(self, node):
+ children = [node.elt]
+ children.extend(node.generators)
+ self._handle(node, children, eat_parens=True)
+
+ def _comprehension(self, node):
+ children = ['for', node.target, 'in', node.iter]
+ if node.ifs:
+ for if_ in node.ifs:
+ children.append('if')
+ children.append(if_)
+ self._handle(node, children)
+
+ def _Global(self, node):
+ children = self._child_nodes(node.names, ',')
+ children.insert(0, 'global')
+ self._handle(node, children)
+
+ def _If(self, node):
+ if self._is_elif(node):
+ children = ['elif']
+ else:
+ children = ['if']
+ children.extend([node.test, ':'])
+ children.extend(node.body)
+ if node.orelse:
+ if len(node.orelse) == 1 and self._is_elif(node.orelse[0]):
+ pass
+ else:
+ children.extend(['else', ':'])
+ children.extend(node.orelse)
+ self._handle(node, children)
+
+ def _is_elif(self, node):
+ if not isinstance(node, ast.If):
+ return False
+ offset = self.lines.get_line_start(node.lineno) + node.col_offset
+ word = self.source[offset:offset + 4]
+ # XXX: This is a bug; the offset does not point to the first
+ alt_word = self.source[offset - 5:offset - 1]
+ return 'elif' in (word, alt_word)
+
+ def _IfExp(self, node):
+ return self._handle(node, [node.body, 'if', node.test,
+ 'else', node.orelse])
+
+ def _Import(self, node):
+ children = ['import']
+ children.extend(self._child_nodes(node.names, ','))
+ self._handle(node, children)
+
+ def _keyword(self, node):
+ self._handle(node, [node.arg, '=', node.value])
+
+ def _Lambda(self, node):
+ self._handle(node, ['lambda', node.args, ':', node.body])
+
+ def _List(self, node):
+ self._handle(node, ['['] + self._child_nodes(node.elts, ',') + [']'])
+
+ def _ListComp(self, node):
+ children = ['[', node.elt]
+ children.extend(node.generators)
+ children.append(']')
+ self._handle(node, children)
+
+ def _Module(self, node):
+ self._handle(node, list(node.body), eat_spaces=True)
+
+ def _Name(self, node):
+ self._handle(node, [node.id])
+
+ def _Pass(self, node):
+ self._handle(node, ['pass'])
+
+ def _Print(self, node):
+ children = ['print']
+ if node.dest:
+ children.extend(['>>', node.dest])
+ if node.values:
+ children.append(',')
+ children.extend(self._child_nodes(node.values, ','))
+ if not node.nl:
+ children.append(',')
+ self._handle(node, children)
+
+ def _Raise(self, node):
+ children = ['raise']
+ if node.type:
+ children.append(node.type)
+ if node.inst:
+ children.append(',')
+ children.append(node.inst)
+ if node.tback:
+ children.append(',')
+ children.append(node.tback)
+ self._handle(node, children)
+
+ def _Return(self, node):
+ children = ['return']
+ if node.value:
+ children.append(node.value)
+ self._handle(node, children)
+
+ def _Sliceobj(self, node):
+ children = []
+ for index, slice in enumerate(node.nodes):
+ if index > 0:
+ children.append(':')
+ if slice:
+ children.append(slice)
+ self._handle(node, children)
+
+ def _Index(self, node):
+ self._handle(node, [node.value])
+
+ def _Subscript(self, node):
+ self._handle(node, [node.value, '[', node.slice, ']'])
+
+ def _Slice(self, node):
+ children = []
+ if node.lower:
+ children.append(node.lower)
+ children.append(':')
+ if node.upper:
+ children.append(node.upper)
+ if node.step:
+ children.append(':')
+ children.append(node.step)
+ self._handle(node, children)
+
+ def _TryFinally(self, node):
+ children = []
+ if len(node.body) != 1 or not isinstance(node.body[0], ast.TryExcept):
+ children.extend(['try', ':'])
+ children.extend(node.body)
+ children.extend(['finally', ':'])
+ children.extend(node.finalbody)
+ self._handle(node, children)
+
+ def _TryExcept(self, node):
+ children = ['try', ':']
+ children.extend(node.body)
+ children.extend(node.handlers)
+ if node.orelse:
+ children.extend(['else', ':'])
+ children.extend(node.orelse)
+ self._handle(node, children)
+
+ def _ExceptHandler(self, node):
+ self._excepthandler(node)
+
+ def _excepthandler(self, node):
+ children = ['except']
+ if node.type:
+ children.append(node.type)
+ if node.name:
+ children.extend([',', node.name])
+ children.append(':')
+ children.extend(node.body)
+ self._handle(node, children)
+
+ def _Tuple(self, node):
+ if node.elts:
+ self._handle(node, self._child_nodes(node.elts, ','),
+ eat_parens=True)
+ else:
+ self._handle(node, ['(', ')'])
+
+ def _UnaryOp(self, node):
+ children = self._get_op(node.op)
+ children.append(node.operand)
+ self._handle(node, children)
+
+ def _Yield(self, node):
+ children = ['yield']
+ if node.value:
+ children.append(node.value)
+ self._handle(node, children)
+
+ def _While(self, node):
+ children = ['while', node.test, ':']
+ children.extend(node.body)
+ if node.orelse:
+ children.extend(['else', ':'])
+ children.extend(node.orelse)
+ self._handle(node, children)
+
+ def _With(self, node):
+ children = ['with', node.context_expr]
+ if node.optional_vars:
+ children.extend(['as', node.optional_vars])
+ children.append(':')
+ children.extend(node.body)
+ self._handle(node, children)
+
+ def _child_nodes(self, nodes, separator):
+ children = []
+ for index, child in enumerate(nodes):
+ children.append(child)
+ if index < len(nodes) - 1:
+ children.append(separator)
+ return children
+
+
+class _Source(object):
+
+ def __init__(self, source):
+ self.source = source
+ self.offset = 0
+
+ def consume(self, token):
+ try:
+ while True:
+ new_offset = self.source.index(token, self.offset)
+ if self._good_token(token, new_offset):
+ break
+ else:
+ self._skip_comment()
+ except (ValueError, TypeError):
+ raise MismatchedTokenError(
+ 'Token <%s> at %s cannot be matched' %
+ (token, self._get_location()))
+ self.offset = new_offset + len(token)
+ return (new_offset, self.offset)
+
+ def consume_string(self, end=None):
+ if _Source._string_pattern is None:
+ original = codeanalyze.get_string_pattern()
+ pattern = r'(%s)((\s|\\\n|#[^\n]*\n)*(%s))*' % \
+ (original, original)
+ _Source._string_pattern = re.compile(pattern)
+ repattern = _Source._string_pattern
+ return self._consume_pattern(repattern, end)
+
+ def consume_number(self):
+ if _Source._number_pattern is None:
+ _Source._number_pattern = re.compile(
+ self._get_number_pattern())
+ repattern = _Source._number_pattern
+ return self._consume_pattern(repattern)
+
+ def consume_not_equal(self):
+ if _Source._not_equals_pattern is None:
+ _Source._not_equals_pattern = re.compile(r'<>|!=')
+ repattern = _Source._not_equals_pattern
+ return self._consume_pattern(repattern)
+
+ def _good_token(self, token, offset, start=None):
+ """Checks whether consumed token is in comments"""
+ if start is None:
+ start = self.offset
+ try:
+ comment_index = self.source.rindex('#', start, offset)
+ except ValueError:
+ return True
+ try:
+ new_line_index = self.source.rindex('\n', start, offset)
+ except ValueError:
+ return False
+ return comment_index < new_line_index
+
+ def _skip_comment(self):
+ self.offset = self.source.index('\n', self.offset + 1)
+
+ def _get_location(self):
+ lines = self.source[:self.offset].split('\n')
+ return (len(lines), len(lines[-1]))
+
+ def _consume_pattern(self, repattern, end=None):
+ while True:
+ if end is None:
+ end = len(self.source)
+ match = repattern.search(self.source, self.offset, end)
+ if self._good_token(match.group(), match.start()):
+ break
+ else:
+ self._skip_comment()
+ self.offset = match.end()
+ return match.start(), match.end()
+
+ def till_token(self, token):
+ new_offset = self.source.index(token, self.offset)
+ return self[self.offset:new_offset]
+
+ def rfind_token(self, token, start, end):
+ index = start
+ while True:
+ try:
+ index = self.source.rindex(token, start, end)
+ if self._good_token(token, index, start=start):
+ return index
+ else:
+ end = index
+ except ValueError:
+ return None
+
+ def from_offset(self, offset):
+ return self[offset:self.offset]
+
+ def find_backwards(self, pattern, offset):
+ return self.source.rindex(pattern, 0, offset)
+
+ def __getitem__(self, index):
+ return self.source[index]
+
+ def __getslice__(self, i, j):
+ return self.source[i:j]
+
+ def _get_number_pattern(self):
+ # HACK: It is merely an approaximation and does the job
+ integer = r'(0|0x)?[\da-fA-F]+[lL]?'
+ return r'(%s(\.\d*)?|(\.\d+))([eE][-+]?\d*)?[jJ]?' % integer
+
+ _string_pattern = None
+ _number_pattern = None
+ _not_equals_pattern = None
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/rename.py b/vim/eclim/autoload/eclim/python/rope/refactor/rename.py
@@ -0,0 +1,216 @@
+import warnings
+
+from rope.base import exceptions, pyobjects, pynames, taskhandle, evaluate, worder, codeanalyze
+from rope.base.change import ChangeSet, ChangeContents, MoveResource
+from rope.refactor import occurrences, sourceutils
+
+
+class Rename(object):
+ """A class for performing rename refactoring
+
+ It can rename everything: classes, functions, modules, packages,
+ methods, variables and keyword arguments.
+
+ """
+
+ def __init__(self, project, resource, offset=None):
+ """If `offset` is None, the `resource` itself will be renamed"""
+ self.project = project
+ self.pycore = project.pycore
+ self.resource = resource
+ if offset is not None:
+ self.old_name = worder.get_name_at(self.resource, offset)
+ this_pymodule = self.pycore.resource_to_pyobject(self.resource)
+ self.old_instance, self.old_pyname = \
+ evaluate.eval_location2(this_pymodule, offset)
+ if self.old_pyname is None:
+ raise exceptions.RefactoringError(
+ 'Rename refactoring should be performed'
+ ' on resolvable python identifiers.')
+ else:
+ if not resource.is_folder() and resource.name == '__init__.py':
+ resource = resource.parent
+ dummy_pymodule = self.pycore.get_string_module('')
+ self.old_instance = None
+ self.old_pyname = pynames.ImportedModule(dummy_pymodule,
+ resource=resource)
+ if resource.is_folder():
+ self.old_name = resource.name
+ else:
+ self.old_name = resource.name[:-3]
+
+ def get_old_name(self):
+ return self.old_name
+
+ def get_changes(self, new_name, in_file=None, in_hierarchy=False,
+ unsure=None, docs=False, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Get the changes needed for this refactoring
+
+ Parameters:
+
+ - `in_hierarchy`: when renaming a method this keyword forces
+ to rename all matching methods in the hierarchy
+ - `docs`: when `True` rename refactoring will rename
+ occurrences in comments and strings where the name is
+ visible. Setting it will make renames faster, too.
+ - `unsure`: decides what to do about unsure occurrences.
+ If `None`, they are ignored. Otherwise `unsure` is
+ called with an instance of `occurrence.Occurrence` as
+ parameter. If it returns `True`, the occurrence is
+ considered to be a match.
+ - `resources` can be a list of `rope.base.resources.File`\s to
+ apply this refactoring on. If `None`, the restructuring
+ will be applied to all python files.
+ - `in_file`: this argument has been deprecated; use
+ `resources` instead.
+
+ """
+ if unsure in (True, False):
+ warnings.warn(
+ 'unsure parameter should be a function that returns '
+ 'True or False', DeprecationWarning, stacklevel=2)
+ def unsure_func(value=unsure):
+ return value
+ unsure = unsure_func
+ if in_file is not None:
+ warnings.warn(
+ '`in_file` argument has been deprecated; use `resources` '
+ 'instead. ', DeprecationWarning, stacklevel=2)
+ if in_file:
+ resources = [self.resource]
+ if _is_local(self.old_pyname):
+ resources = [self.resource]
+ if resources is None:
+ resources = self.pycore.get_python_files()
+ changes = ChangeSet('Renaming <%s> to <%s>' %
+ (self.old_name, new_name))
+ finder = occurrences.create_finder(
+ self.pycore, self.old_name, self.old_pyname, unsure=unsure,
+ docs=docs, instance=self.old_instance,
+ in_hierarchy=in_hierarchy and self.is_method())
+ job_set = task_handle.create_jobset('Collecting Changes', len(resources))
+ for file_ in resources:
+ job_set.started_job(file_.path)
+ new_content = rename_in_module(finder, new_name, resource=file_)
+ if new_content is not None:
+ changes.add_change(ChangeContents(file_, new_content))
+ job_set.finished_job()
+ if self._is_renaming_a_module():
+ resource = self.old_pyname.get_object().get_resource()
+ if self._is_allowed_to_move(resources, resource):
+ self._rename_module(resource, new_name, changes)
+ return changes
+
+ def _is_allowed_to_move(self, resources, resource):
+ if resource.is_folder():
+ try:
+ return resource.get_child('__init__.py') in resources
+ except exceptions.ResourceNotFoundError:
+ return False
+ else:
+ return resource in resources
+
+ def _is_renaming_a_module(self):
+ if isinstance(self.old_pyname.get_object(), pyobjects.AbstractModule):
+ return True
+ return False
+
+ def is_method(self):
+ pyname = self.old_pyname
+ return isinstance(pyname, pynames.DefinedName) and \
+ isinstance(pyname.get_object(), pyobjects.PyFunction) and \
+ isinstance(pyname.get_object().parent, pyobjects.PyClass)
+
+ def _rename_module(self, resource, new_name, changes):
+ if not resource.is_folder():
+ new_name = new_name + '.py'
+ parent_path = resource.parent.path
+ if parent_path == '':
+ new_location = new_name
+ else:
+ new_location = parent_path + '/' + new_name
+ changes.add_change(MoveResource(resource, new_location))
+
+
+class ChangeOccurrences(object):
+ """A class for changing the occurrences of a name in a scope
+
+ This class replaces the occurrences of a name. Note that it only
+ changes the scope containing the offset passed to the constructor.
+ What's more it does not have any side-effects. That is for
+ example changing occurrences of a module does not rename the
+ module; it merely replaces the occurrences of that module in a
+ scope with the given expression. This class is useful for
+ performing many custom refactorings.
+
+ """
+
+ def __init__(self, project, resource, offset):
+ self.pycore = project.pycore
+ self.resource = resource
+ self.offset = offset
+ self.old_name = worder.get_name_at(resource, offset)
+ self.pymodule = self.pycore.resource_to_pyobject(self.resource)
+ self.old_pyname = evaluate.eval_location(self.pymodule, offset)
+
+ def get_old_name(self):
+ word_finder = worder.Worder(self.resource.read())
+ return word_finder.get_primary_at(self.offset)
+
+ def _get_scope_offset(self):
+ lines = self.pymodule.lines
+ scope = self.pymodule.get_scope().\
+ get_inner_scope_for_line(lines.get_line_number(self.offset))
+ start = lines.get_line_start(scope.get_start())
+ end = lines.get_line_end(scope.get_end())
+ return start, end
+
+ def get_changes(self, new_name, only_calls=False, reads=True, writes=True):
+ changes = ChangeSet('Changing <%s> occurrences to <%s>' %
+ (self.old_name, new_name))
+ scope_start, scope_end = self._get_scope_offset()
+ finder = occurrences.create_finder(
+ self.pycore, self.old_name, self.old_pyname,
+ imports=False, only_calls=only_calls)
+ new_contents = rename_in_module(
+ finder, new_name, pymodule=self.pymodule, replace_primary=True,
+ region=(scope_start, scope_end), reads=reads, writes=writes)
+ if new_contents is not None:
+ changes.add_change(ChangeContents(self.resource, new_contents))
+ return changes
+
+
+def rename_in_module(occurrences_finder, new_name, resource=None, pymodule=None,
+ replace_primary=False, region=None, reads=True, writes=True):
+ """Returns the changed source or `None` if there is no changes"""
+ if resource is not None:
+ source_code = resource.read()
+ else:
+ source_code = pymodule.source_code
+ change_collector = codeanalyze.ChangeCollector(source_code)
+ for occurrence in occurrences_finder.find_occurrences(resource, pymodule):
+ if replace_primary and occurrence.is_a_fixed_primary():
+ continue
+ if replace_primary:
+ start, end = occurrence.get_primary_range()
+ else:
+ start, end = occurrence.get_word_range()
+ if (not reads and not occurrence.is_written()) or \
+ (not writes and occurrence.is_written()):
+ continue
+ if region is None or region[0] <= start < region[1]:
+ change_collector.add_change(start, end, new_name)
+ return change_collector.get_changed()
+
+def _is_local(pyname):
+ module, lineno = pyname.get_definition_location()
+ if lineno is None:
+ return False
+ scope = module.get_scope().get_inner_scope_for_line(lineno)
+ if isinstance(pyname, pynames.DefinedName) and \
+ scope.get_kind() in ('Function', 'Class'):
+ scope = scope.parent
+ return scope.get_kind() == 'Function' and \
+ pyname in scope.get_names().values() and \
+ isinstance(pyname, pynames.AssignedName)
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/restructure.py b/vim/eclim/autoload/eclim/python/rope/refactor/restructure.py
@@ -0,0 +1,307 @@
+import warnings
+
+from rope.base import change, taskhandle, builtins, ast, codeanalyze
+from rope.refactor import patchedast, similarfinder, sourceutils
+from rope.refactor.importutils import module_imports
+
+
+class Restructure(object):
+ """A class to perform python restructurings
+
+ A restructuring transforms pieces of code matching `pattern` to
+ `goal`. In the `pattern` wildcards can appear. Wildcards match
+ some piece of code based on their kind and arguments that are
+ passed to them through `args`.
+
+ `args` is a dictionary of wildcard names to wildcard arguments.
+ If the argument is a tuple, the first item of the tuple is
+ considered to be the name of the wildcard to use; otherwise the
+ "default" wildcard is used. For getting the list arguments a
+ wildcard supports, see the pydoc of the wildcard. (see
+ `rope.refactor.wildcard.DefaultWildcard` for the default
+ wildcard.)
+
+ `wildcards` is the list of wildcard types that can appear in
+ `pattern`. See `rope.refactor.wildcards`. If a wildcard does not
+ specify its kind (by using a tuple in args), the wildcard named
+ "default" is used. So there should be a wildcard with "default"
+ name in `wildcards`.
+
+ `imports` is the list of imports that changed modules should
+ import. Note that rope handles duplicate imports and does not add
+ the import if it already appears.
+
+ Example #1::
+
+ pattern ${pyobject}.get_attribute(${name})
+ goal ${pyobject}[${name}]
+ args pyobject: instance=rope.base.pyobjects.PyObject
+
+ Example #2::
+
+ pattern ${name} in ${pyobject}.get_attributes()
+ goal ${name} in {pyobject}
+ args pyobject: instance=rope.base.pyobjects.PyObject
+
+ Example #3::
+
+ pattern ${pycore}.create_module(${project}.root, ${name})
+ goal generate.create_module(${project}, ${name})
+
+ imports
+ from rope.contrib import generate
+
+ args
+ pycore: type=rope.base.pycore.PyCore
+ project: type=rope.base.project.Project
+
+ Example #4::
+
+ pattern ${pow}(${param1}, ${param2})
+ goal ${param1} ** ${param2}
+ args pow: name=mod.pow, exact
+
+ Example #5::
+
+ pattern ${inst}.longtask(${p1}, ${p2})
+ goal
+ ${inst}.subtask1(${p1})
+ ${inst}.subtask2(${p2})
+ args
+ inst: type=mod.A,unsure
+
+ """
+
+ def __init__(self, project, pattern, goal, args=None,
+ imports=None, wildcards=None):
+ """Construct a restructuring
+
+ See class pydoc for more info about the arguments.
+
+ """
+ self.pycore = project.pycore
+ self.pattern = pattern
+ self.goal = goal
+ self.args = args
+ if self.args is None:
+ self.args = {}
+ self.imports = imports
+ if self.imports is None:
+ self.imports = []
+ self.wildcards = wildcards
+ self.template = similarfinder.CodeTemplate(self.goal)
+
+ def get_changes(self, checks=None, imports=None, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ """Get the changes needed by this restructuring
+
+ `resources` can be a list of `rope.base.resources.File`\s to
+ apply the restructuring on. If `None`, the restructuring will
+ be applied to all python files.
+
+ `checks` argument has been deprecated. Use the `args` argument
+ of the constructor. The usage of::
+
+ strchecks = {'obj1.type': 'mod.A', 'obj2': 'mod.B',
+ 'obj3.object': 'mod.C'}
+ checks = restructuring.make_checks(strchecks)
+
+ can be replaced with::
+
+ args = {'obj1': 'type=mod.A', 'obj2': 'name=mod.B',
+ 'obj3': 'object=mod.C'}
+
+ where obj1, obj2 and obj3 are wildcard names that appear
+ in restructuring pattern.
+
+ """
+ if checks is not None:
+ warnings.warn(
+ 'The use of checks parameter is deprecated; '
+ 'use the args parameter of the constructor instead.',
+ DeprecationWarning, stacklevel=2)
+ for name, value in checks.items():
+ self.args[name] = similarfinder._pydefined_to_str(value)
+ if imports is not None:
+ warnings.warn(
+ 'The use of imports parameter is deprecated; '
+ 'use imports parameter of the constructor, instead.',
+ DeprecationWarning, stacklevel=2)
+ self.imports = imports
+ changes = change.ChangeSet('Restructuring <%s> to <%s>' %
+ (self.pattern, self.goal))
+ if resources is not None:
+ files = [resource for resource in resources
+ if self.pycore.is_python_file(resource)]
+ else:
+ files = self.pycore.get_python_files()
+ job_set = task_handle.create_jobset('Collecting Changes', len(files))
+ for resource in files:
+ job_set.started_job(resource.path)
+ pymodule = self.pycore.resource_to_pyobject(resource)
+ finder = similarfinder.SimilarFinder(pymodule,
+ wildcards=self.wildcards)
+ matches = list(finder.get_matches(self.pattern, self.args))
+ computer = self._compute_changes(matches, pymodule)
+ result = computer.get_changed()
+ if result is not None:
+ imported_source = self._add_imports(resource, result,
+ self.imports)
+ changes.add_change(change.ChangeContents(resource,
+ imported_source))
+ job_set.finished_job()
+ return changes
+
+ def _compute_changes(self, matches, pymodule):
+ return _ChangeComputer(
+ pymodule.source_code, pymodule.get_ast(),
+ pymodule.lines, self.template, matches)
+
+ def _add_imports(self, resource, source, imports):
+ if not imports:
+ return source
+ import_infos = self._get_import_infos(resource, imports)
+ pymodule = self.pycore.get_string_module(source, resource)
+ imports = module_imports.ModuleImports(self.pycore, pymodule)
+ for import_info in import_infos:
+ imports.add_import(import_info)
+ return imports.get_changed_source()
+
+ def _get_import_infos(self, resource, imports):
+ pymodule = self.pycore.get_string_module('\n'.join(imports),
+ resource)
+ imports = module_imports.ModuleImports(self.pycore, pymodule)
+ return [imports.import_info
+ for imports in imports.imports]
+
+ def make_checks(self, string_checks):
+ """Convert str to str dicts to str to PyObject dicts
+
+ This function is here to ease writing a UI.
+
+ """
+ checks = {}
+ for key, value in string_checks.items():
+ is_pyname = not key.endswith('.object') and \
+ not key.endswith('.type')
+ evaluated = self._evaluate(value, is_pyname=is_pyname)
+ if evaluated is not None:
+ checks[key] = evaluated
+ return checks
+
+ def _evaluate(self, code, is_pyname=True):
+ attributes = code.split('.')
+ pyname = None
+ if attributes[0] in ('__builtin__', '__builtins__'):
+ class _BuiltinsStub(object):
+ def get_attribute(self, name):
+ return builtins.builtins[name]
+ pyobject = _BuiltinsStub()
+ else:
+ pyobject = self.pycore.get_module(attributes[0])
+ for attribute in attributes[1:]:
+ pyname = pyobject[attribute]
+ if pyname is None:
+ return None
+ pyobject = pyname.get_object()
+ return pyname if is_pyname else pyobject
+
+
+def replace(code, pattern, goal):
+ """used by other refactorings"""
+ finder = similarfinder.RawSimilarFinder(code)
+ matches = list(finder.get_matches(pattern))
+ ast = patchedast.get_patched_ast(code)
+ lines = codeanalyze.SourceLinesAdapter(code)
+ template = similarfinder.CodeTemplate(goal)
+ computer = _ChangeComputer(code, ast, lines, template, matches)
+ result = computer.get_changed()
+ if result is None:
+ return code
+ return result
+
+
+class _ChangeComputer(object):
+
+ def __init__(self, code, ast, lines, goal, matches):
+ self.source = code
+ self.goal = goal
+ self.matches = matches
+ self.ast = ast
+ self.lines = lines
+ self.matched_asts = {}
+ self._nearest_roots = {}
+ if self._is_expression():
+ for match in self.matches:
+ self.matched_asts[match.ast] = match
+
+ def get_changed(self):
+ if self._is_expression():
+ result = self._get_node_text(self.ast)
+ if result == self.source:
+ return None
+ return result
+ else:
+ collector = codeanalyze.ChangeCollector(self.source)
+ last_end = -1
+ for match in self.matches:
+ start, end = match.get_region()
+ if start < last_end:
+ if not self._is_expression():
+ continue
+ last_end = end
+ replacement = self._get_matched_text(match)
+ collector.add_change(start, end, replacement)
+ return collector.get_changed()
+
+ def _is_expression(self):
+ return self.matches and isinstance(self.matches[0],
+ similarfinder.ExpressionMatch)
+
+ def _get_matched_text(self, match):
+ mapping = {}
+ for name in self.goal.get_names():
+ node = match.get_ast(name)
+ if node is None:
+ raise similarfinder.BadNameInCheckError(
+ 'Unknown name <%s>' % name)
+ force = self._is_expression() and match.ast == node
+ mapping[name] = self._get_node_text(node, force)
+ unindented = self.goal.substitute(mapping)
+ return self._auto_indent(match.get_region()[0], unindented)
+
+ def _get_node_text(self, node, force=False):
+ if not force and node in self.matched_asts:
+ return self._get_matched_text(self.matched_asts[node])
+ start, end = patchedast.node_region(node)
+ main_text = self.source[start:end]
+ collector = codeanalyze.ChangeCollector(main_text)
+ for node in self._get_nearest_roots(node):
+ sub_start, sub_end = patchedast.node_region(node)
+ collector.add_change(sub_start - start, sub_end - start,
+ self._get_node_text(node))
+ result = collector.get_changed()
+ if result is None:
+ return main_text
+ return result
+
+ def _auto_indent(self, offset, text):
+ lineno = self.lines.get_line_number(offset)
+ indents = sourceutils.get_indents(self.lines, lineno)
+ result = []
+ for index, line in enumerate(text.splitlines(True)):
+ if index != 0 and line.strip():
+ result.append(' ' * indents)
+ result.append(line)
+ return ''.join(result)
+
+ def _get_nearest_roots(self, node):
+ if node not in self._nearest_roots:
+ result = []
+ for child in ast.get_child_nodes(node):
+ if child in self.matched_asts:
+ result.append(child)
+ else:
+ result.extend(self._get_nearest_roots(child))
+ self._nearest_roots[node] = result
+ return self._nearest_roots[node]
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/similarfinder.py b/vim/eclim/autoload/eclim/python/rope/refactor/similarfinder.py
@@ -0,0 +1,362 @@
+"""This module can be used for finding similar code"""
+import re
+
+import rope.refactor.wildcards
+from rope.base import codeanalyze, evaluate, exceptions, ast, builtins
+from rope.refactor import (patchedast, sourceutils, occurrences,
+ wildcards, importutils)
+
+
+class BadNameInCheckError(exceptions.RefactoringError):
+ pass
+
+
+class SimilarFinder(object):
+ """`SimilarFinder` can be used to find similar pieces of code
+
+ See the notes in the `rope.refactor.restructure` module for more
+ info.
+
+ """
+
+ def __init__(self, pymodule, wildcards=None):
+ """Construct a SimilarFinder"""
+ self.source = pymodule.source_code
+ self.raw_finder = RawSimilarFinder(
+ pymodule.source_code, pymodule.get_ast(), self._does_match)
+ self.pymodule = pymodule
+ if wildcards is None:
+ self.wildcards = {}
+ for wildcard in [rope.refactor.wildcards.
+ DefaultWildcard(pymodule.pycore.project)]:
+ self.wildcards[wildcard.get_name()] = wildcard
+ else:
+ self.wildcards = wildcards
+
+ def get_matches(self, code, args={}, start=0, end=None):
+ self.args = args
+ if end is None:
+ end = len(self.source)
+ skip_region = None
+ if 'skip' in args.get('', {}):
+ resource, region = args['']['skip']
+ if resource == self.pymodule.get_resource():
+ skip_region = region
+ return self.raw_finder.get_matches(code, start=start, end=end,
+ skip=skip_region)
+
+ def get_match_regions(self, *args, **kwds):
+ for match in self.get_matches(*args, **kwds):
+ yield match.get_region()
+
+ def _does_match(self, node, name):
+ arg = self.args.get(name, '')
+ kind = 'default'
+ if isinstance(arg, (tuple, list)):
+ kind = arg[0]
+ arg = arg[1]
+ suspect = wildcards.Suspect(self.pymodule, node, name)
+ return self.wildcards[kind].matches(suspect, arg)
+
+
+class RawSimilarFinder(object):
+ """A class for finding similar expressions and statements"""
+
+ def __init__(self, source, node=None, does_match=None):
+ if node is None:
+ node = ast.parse(source)
+ if does_match is None:
+ self.does_match = self._simple_does_match
+ else:
+ self.does_match = does_match
+ self._init_using_ast(node, source)
+
+ def _simple_does_match(self, node, name):
+ return isinstance(node, (ast.expr, ast.Name))
+
+ def _init_using_ast(self, node, source):
+ self.source = source
+ self._matched_asts = {}
+ if not hasattr(node, 'region'):
+ patchedast.patch_ast(node, source)
+ self.ast = node
+
+ def get_matches(self, code, start=0, end=None, skip=None):
+ """Search for `code` in source and return a list of `Match`\es
+
+ `code` can contain wildcards. ``${name}`` matches normal
+ names and ``${?name} can match any expression. You can use
+ `Match.get_ast()` for getting the node that has matched a
+ given pattern.
+
+ """
+ if end is None:
+ end = len(self.source)
+ for match in self._get_matched_asts(code):
+ match_start, match_end = match.get_region()
+ if start <= match_start and match_end <= end:
+ if skip is not None and (skip[0] < match_end and
+ skip[1] > match_start):
+ continue
+ yield match
+
+ def _get_matched_asts(self, code):
+ if code not in self._matched_asts:
+ wanted = self._create_pattern(code)
+ matches = _ASTMatcher(self.ast, wanted,
+ self.does_match).find_matches()
+ self._matched_asts[code] = matches
+ return self._matched_asts[code]
+
+ def _create_pattern(self, expression):
+ expression = self._replace_wildcards(expression)
+ node = ast.parse(expression)
+ # Getting Module.Stmt.nodes
+ nodes = node.body
+ if len(nodes) == 1 and isinstance(nodes[0], ast.Expr):
+ # Getting Discard.expr
+ wanted = nodes[0].value
+ else:
+ wanted = nodes
+ return wanted
+
+ def _replace_wildcards(self, expression):
+ ropevar = _RopeVariable()
+ template = CodeTemplate(expression)
+ mapping = {}
+ for name in template.get_names():
+ mapping[name] = ropevar.get_var(name)
+ return template.substitute(mapping)
+
+
+class _ASTMatcher(object):
+
+ def __init__(self, body, pattern, does_match):
+ """Searches the given pattern in the body AST.
+
+ body is an AST node and pattern can be either an AST node or
+ a list of ASTs nodes
+ """
+ self.body = body
+ self.pattern = pattern
+ self.matches = None
+ self.ropevar = _RopeVariable()
+ self.matches_callback = does_match
+
+ def find_matches(self):
+ if self.matches is None:
+ self.matches = []
+ ast.call_for_nodes(self.body, self._check_node, recursive=True)
+ return self.matches
+
+ def _check_node(self, node):
+ if isinstance(self.pattern, list):
+ self._check_statements(node)
+ else:
+ self._check_expression(node)
+
+ def _check_expression(self, node):
+ mapping = {}
+ if self._match_nodes(self.pattern, node, mapping):
+ self.matches.append(ExpressionMatch(node, mapping))
+
+ def _check_statements(self, node):
+ for child in ast.get_children(node):
+ if isinstance(child, (list, tuple)):
+ self.__check_stmt_list(child)
+
+ def __check_stmt_list(self, nodes):
+ for index in range(len(nodes)):
+ if len(nodes) - index >= len(self.pattern):
+ current_stmts = nodes[index:index + len(self.pattern)]
+ mapping = {}
+ if self._match_stmts(current_stmts, mapping):
+ self.matches.append(StatementMatch(current_stmts, mapping))
+
+ def _match_nodes(self, expected, node, mapping):
+ if isinstance(expected, ast.Name):
+ if self.ropevar.is_var(expected.id):
+ return self._match_wildcard(expected, node, mapping)
+ if not isinstance(expected, ast.AST):
+ return expected == node
+ if expected.__class__ != node.__class__:
+ return False
+
+ children1 = self._get_children(expected)
+ children2 = self._get_children(node)
+ if len(children1) != len(children2):
+ return False
+ for child1, child2 in zip(children1, children2):
+ if isinstance(child1, ast.AST):
+ if not self._match_nodes(child1, child2, mapping):
+ return False
+ elif isinstance(child1, (list, tuple)):
+ if not isinstance(child2, (list, tuple)) or \
+ len(child1) != len(child2):
+ return False
+ for c1, c2 in zip(child1, child2):
+ if not self._match_nodes(c1, c2, mapping):
+ return False
+ else:
+ if child1 != child2:
+ return False
+ return True
+
+ def _get_children(self, node):
+ """Return not `ast.expr_context` children of `node`"""
+ children = ast.get_children(node)
+ return [child for child in children
+ if not isinstance(child, ast.expr_context)]
+
+ def _match_stmts(self, current_stmts, mapping):
+ if len(current_stmts) != len(self.pattern):
+ return False
+ for stmt, expected in zip(current_stmts, self.pattern):
+ if not self._match_nodes(expected, stmt, mapping):
+ return False
+ return True
+
+ def _match_wildcard(self, node1, node2, mapping):
+ name = self.ropevar.get_base(node1.id)
+ if name not in mapping:
+ if self.matches_callback(node2, name):
+ mapping[name] = node2
+ return True
+ return False
+ else:
+ return self._match_nodes(mapping[name], node2, {})
+
+
+class Match(object):
+
+ def __init__(self, mapping):
+ self.mapping = mapping
+
+ def get_region(self):
+ """Returns match region"""
+
+ def get_ast(self, name):
+ """Return the ast node that has matched rope variables"""
+ return self.mapping.get(name, None)
+
+
+class ExpressionMatch(Match):
+
+ def __init__(self, ast, mapping):
+ super(ExpressionMatch, self).__init__(mapping)
+ self.ast = ast
+
+ def get_region(self):
+ return self.ast.region
+
+
+class StatementMatch(Match):
+
+ def __init__(self, ast_list, mapping):
+ super(StatementMatch, self).__init__(mapping)
+ self.ast_list = ast_list
+
+ def get_region(self):
+ return self.ast_list[0].region[0], self.ast_list[-1].region[1]
+
+
+class CodeTemplate(object):
+
+ def __init__(self, template):
+ self.template = template
+ self._find_names()
+
+ def _find_names(self):
+ self.names = {}
+ for match in CodeTemplate._get_pattern().finditer(self.template):
+ if 'name' in match.groupdict() and \
+ match.group('name') is not None:
+ start, end = match.span('name')
+ name = self.template[start + 2:end - 1]
+ if name not in self.names:
+ self.names[name] = []
+ self.names[name].append((start, end))
+
+ def get_names(self):
+ return self.names.keys()
+
+ def substitute(self, mapping):
+ collector = codeanalyze.ChangeCollector(self.template)
+ for name, occurrences in self.names.items():
+ for region in occurrences:
+ collector.add_change(region[0], region[1], mapping[name])
+ result = collector.get_changed()
+ if result is None:
+ return self.template
+ return result
+
+ _match_pattern = None
+
+ @classmethod
+ def _get_pattern(cls):
+ if cls._match_pattern is None:
+ pattern = codeanalyze.get_comment_pattern() + '|' + \
+ codeanalyze.get_string_pattern() + '|' + \
+ r'(?P<name>\$\{[^\s\$\}]*\})'
+ cls._match_pattern = re.compile(pattern)
+ return cls._match_pattern
+
+
+class _RopeVariable(object):
+ """Transform and identify rope inserted wildcards"""
+
+ _normal_prefix = '__rope__variable_normal_'
+ _any_prefix = '__rope__variable_any_'
+
+ def get_var(self, name):
+ if name.startswith('?'):
+ return self._get_any(name)
+ else:
+ return self._get_normal(name)
+
+ def is_var(self, name):
+ return self._is_normal(name) or self._is_var(name)
+
+ def get_base(self, name):
+ if self._is_normal(name):
+ return name[len(self._normal_prefix):]
+ if self._is_var(name):
+ return '?' + name[len(self._any_prefix):]
+
+ def _get_normal(self, name):
+ return self._normal_prefix + name
+
+ def _get_any(self, name):
+ return self._any_prefix + name[1:]
+
+ def _is_normal(self, name):
+ return name.startswith(self._normal_prefix)
+
+ def _is_var(self, name):
+ return name.startswith(self._any_prefix)
+
+
+def make_pattern(code, variables):
+ variables = set(variables)
+ collector = codeanalyze.ChangeCollector(code)
+ def does_match(node, name):
+ return isinstance(node, ast.Name) and node.id == name
+ finder = RawSimilarFinder(code, does_match=does_match)
+ for variable in variables:
+ for match in finder.get_matches('${%s}' % variable):
+ start, end = match.get_region()
+ collector.add_change(start, end, '${%s}' % variable)
+ result = collector.get_changed()
+ return result if result is not None else code
+
+
+def _pydefined_to_str(pydefined):
+ address = []
+ if isinstance(pydefined, (builtins.BuiltinClass, builtins.BuiltinFunction)):
+ return '__builtins__.' + pydefined.get_name()
+ else:
+ while pydefined.parent is not None:
+ address.insert(0, pydefined.get_name())
+ pydefined = pydefined.parent
+ module_name = pydefined.pycore.modname(pydefined.resource)
+ return '.'.join(module_name.split('.') + address)
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/sourceutils.py b/vim/eclim/autoload/eclim/python/rope/refactor/sourceutils.py
@@ -0,0 +1,92 @@
+from rope.base import ast, codeanalyze
+
+
+def get_indents(lines, lineno):
+ return codeanalyze.count_line_indents(lines.get_line(lineno))
+
+
+def find_minimum_indents(source_code):
+ result = 80
+ lines = source_code.split('\n')
+ for line in lines:
+ if line.strip() == '':
+ continue
+ result = min(result, codeanalyze.count_line_indents(line))
+ return result
+
+
+def indent_lines(source_code, amount):
+ if amount == 0:
+ return source_code
+ lines = source_code.splitlines(True)
+ result = []
+ for l in lines:
+ if l.strip() == '':
+ result.append('\n')
+ continue
+ if amount < 0:
+ indents = codeanalyze.count_line_indents(l)
+ result.append(max(0, indents + amount) * ' ' + l.lstrip())
+ else:
+ result.append(' ' * amount + l)
+ return ''.join(result)
+
+
+def fix_indentation(code, new_indents):
+ """Change the indentation of `code` to `new_indents`"""
+ min_indents = find_minimum_indents(code)
+ return indent_lines(code, new_indents - min_indents)
+
+
+def add_methods(pymodule, class_scope, methods_sources):
+ source_code = pymodule.source_code
+ lines = pymodule.lines
+ insertion_line = class_scope.get_end()
+ if class_scope.get_scopes():
+ insertion_line = class_scope.get_scopes()[-1].get_end()
+ insertion_offset = lines.get_line_end(insertion_line)
+ methods = '\n\n' + '\n\n'.join(methods_sources)
+ indented_methods = fix_indentation(
+ methods, get_indents(lines, class_scope.get_start()) +
+ get_indent(pymodule.pycore))
+ result = []
+ result.append(source_code[:insertion_offset])
+ result.append(indented_methods)
+ result.append(source_code[insertion_offset:])
+ return ''.join(result)
+
+
+def get_body(pyfunction):
+ """Return unindented function body"""
+ scope = pyfunction.get_scope()
+ pymodule = pyfunction.get_module()
+ start, end = get_body_region(pyfunction)
+ return fix_indentation(pymodule.source_code[start:end], 0)
+
+
+def get_body_region(defined):
+ """Return the start and end offsets of function body"""
+ scope = defined.get_scope()
+ pymodule = defined.get_module()
+ lines = pymodule.lines
+ node = defined.get_ast()
+ start_line = node.lineno
+ if defined.get_doc() is None:
+ start_line = node.body[0].lineno
+ elif len(node.body) > 1:
+ start_line = node.body[1].lineno
+ start = lines.get_line_start(start_line)
+ scope_start = pymodule.logical_lines.logical_line_in(scope.start)
+ if scope_start[1] >= start_line:
+ # a one-liner!
+ # XXX: what if colon appears in a string
+ start = pymodule.source_code.index(':', start) + 1
+ while pymodule.source_code[start].isspace():
+ start += 1
+ end = min(lines.get_line_end(scope.end) + 1, len(pymodule.source_code))
+ return start, end
+
+
+def get_indent(pycore):
+ project = pycore.project
+ return project.prefs.get('indent_size', 4)
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/suites.py b/vim/eclim/autoload/eclim/python/rope/refactor/suites.py
@@ -0,0 +1,142 @@
+from rope.base import ast
+
+
+def find_visible(node, lines):
+ """Return the line which is visible from all `lines`"""
+ root = ast_suite_tree(node)
+ return find_visible_for_suite(root, lines)
+
+
+def find_visible_for_suite(root, lines):
+ if len(lines) == 1:
+ return lines[0]
+ line1 = lines[0]
+ line2 = find_visible_for_suite(root, lines[1:])
+ suite1 = root.find_suite(line1)
+ suite2 = root.find_suite(line2)
+ def valid(suite):
+ return suite is not None and not suite.ignored
+ if valid(suite1) and not valid(suite2):
+ return line1
+ if not valid(suite1) and valid(suite2):
+ return line2
+ if not valid(suite1) and not valid(suite2):
+ return None
+ while suite1 != suite2 and suite1.parent != suite2.parent:
+ if suite1._get_level() < suite2._get_level():
+ line2 = suite2.get_start()
+ suite2 = suite2.parent
+ elif suite1._get_level() > suite2._get_level():
+ line1 = suite1.get_start()
+ suite1 = suite1.parent
+ else:
+ line1 = suite1.get_start()
+ line2 = suite2.get_start()
+ suite1 = suite1.parent
+ suite2 = suite2.parent
+ if suite1 == suite2:
+ return min(line1, line2)
+ return min(suite1.get_start(), suite2.get_start())
+
+
+def ast_suite_tree(node):
+ if hasattr(node, 'lineno'):
+ lineno = node.lineno
+ else:
+ lineno = 1
+ return Suite(node.body, lineno)
+
+
+class Suite(object):
+
+ def __init__(self, child_nodes, lineno, parent=None, ignored=False):
+ self.parent = parent
+ self.lineno = lineno
+ self.child_nodes = child_nodes
+ self._children = None
+ self.ignored = ignored
+
+ def get_start(self):
+ if self.parent is None:
+ if self.child_nodes:
+ return self.local_start()
+ else:
+ return 1
+ return self.lineno
+
+ def get_children(self):
+ if self._children is None:
+ walker = _SuiteWalker(self)
+ for child in self.child_nodes:
+ ast.walk(child, walker)
+ self._children = walker.suites
+ return self._children
+
+ def local_start(self):
+ return self.child_nodes[0].lineno
+
+ def local_end(self):
+ end = self.child_nodes[-1].lineno
+ if self.get_children():
+ end = max(end, self.get_children()[-1].local_end())
+ return end
+
+ def find_suite(self, line):
+ if line is None:
+ return None
+ for child in self.get_children():
+ if child.local_start() <= line <= child.local_end():
+ return child.find_suite(line)
+ return self
+
+ def _get_level(self):
+ if self.parent is None:
+ return 0
+ return self.parent._get_level() + 1
+
+
+class _SuiteWalker(object):
+
+ def __init__(self, suite):
+ self.suite = suite
+ self.suites = []
+
+ def _If(self, node):
+ self._add_if_like_node(node)
+
+ def _For(self, node):
+ self._add_if_like_node(node)
+
+ def _While(self, node):
+ self._add_if_like_node(node)
+
+ def _With(self, node):
+ self.suites.append(Suite(node.body, node.lineno, self.suite))
+
+ def _TryFinally(self, node):
+ if len(node.finalbody) == 1 and \
+ isinstance(node.body[0], ast.TryExcept):
+ self._TryExcept(node.body[0])
+ else:
+ self.suites.append(Suite(node.body, node.lineno, self.suite))
+ self.suites.append(Suite(node.finalbody, node.lineno, self.suite))
+
+ def _TryExcept(self, node):
+ self.suites.append(Suite(node.body, node.lineno, self.suite))
+ for handler in node.handlers:
+ self.suites.append(Suite(handler.body, node.lineno, self.suite))
+ if node.orelse:
+ self.suites.append(Suite(node.orelse, node.lineno, self.suite))
+
+ def _add_if_like_node(self, node):
+ self.suites.append(Suite(node.body, node.lineno, self.suite))
+ if node.orelse:
+ self.suites.append(Suite(node.orelse, node.lineno, self.suite))
+
+ def _FunctionDef(self, node):
+ self.suites.append(Suite(node.body, node.lineno,
+ self.suite, ignored=True))
+
+ def _ClassDef(self, node):
+ self.suites.append(Suite(node.body, node.lineno,
+ self.suite, ignored=True))
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/topackage.py b/vim/eclim/autoload/eclim/python/rope/refactor/topackage.py
@@ -0,0 +1,32 @@
+import rope.refactor.importutils
+from rope.base.change import ChangeSet, ChangeContents, MoveResource, CreateFolder
+
+
+class ModuleToPackage(object):
+
+ def __init__(self, project, resource):
+ self.project = project
+ self.pycore = project.pycore
+ self.resource = resource
+
+ def get_changes(self):
+ changes = ChangeSet('Transform <%s> module to package' %
+ self.resource.path)
+ new_content = self._transform_relatives_to_absolute(self.resource)
+ if new_content is not None:
+ changes.add_change(ChangeContents(self.resource, new_content))
+ parent = self.resource.parent
+ name = self.resource.name[:-3]
+ changes.add_change(CreateFolder(parent, name))
+ parent_path = parent.path + '/'
+ if not parent.path:
+ parent_path = ''
+ new_path = parent_path + '%s/__init__.py' % name
+ if self.resource.project == self.project:
+ changes.add_change(MoveResource(self.resource, new_path))
+ return changes
+
+ def _transform_relatives_to_absolute(self, resource):
+ pymodule = self.pycore.resource_to_pyobject(resource)
+ import_tools = rope.refactor.importutils.ImportTools(self.pycore)
+ return import_tools.relatives_to_absolutes(pymodule)
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/usefunction.py b/vim/eclim/autoload/eclim/python/rope/refactor/usefunction.py
@@ -0,0 +1,171 @@
+from rope.base import (change, taskhandle, evaluate,
+ exceptions, pyobjects, pynames, ast)
+from rope.refactor import restructure, sourceutils, similarfinder, importutils
+
+
+class UseFunction(object):
+ """Try to use a function wherever possible"""
+
+ def __init__(self, project, resource, offset):
+ self.project = project
+ self.offset = offset
+ this_pymodule = project.pycore.resource_to_pyobject(resource)
+ pyname = evaluate.eval_location(this_pymodule, offset)
+ if pyname is None:
+ raise exceptions.RefactoringError('Unresolvable name selected')
+ self.pyfunction = pyname.get_object()
+ if not isinstance(self.pyfunction, pyobjects.PyFunction) or \
+ not isinstance(self.pyfunction.parent, pyobjects.PyModule):
+ raise exceptions.RefactoringError(
+ 'Use function works for global functions, only.')
+ self.resource = self.pyfunction.get_module().get_resource()
+ self._check_returns()
+
+ def _check_returns(self):
+ node = self.pyfunction.get_ast()
+ if _yield_count(node):
+ raise exceptions.RefactoringError('Use function should not '
+ 'be used on generators.')
+ returns = _return_count(node)
+ if returns > 1:
+ raise exceptions.RefactoringError('usefunction: Function has more '
+ 'than one return statement.')
+ if returns == 1 and not _returns_last(node):
+ raise exceptions.RefactoringError('usefunction: return should '
+ 'be the last statement.')
+
+ def get_changes(self, resources=None,
+ task_handle=taskhandle.NullTaskHandle()):
+ if resources is None:
+ resources = self.project.pycore.get_python_files()
+ changes = change.ChangeSet('Using function <%s>' %
+ self.pyfunction.get_name())
+ if self.resource in resources:
+ newresources = list(resources)
+ newresources.remove(self.resource)
+ for c in self._restructure(newresources, task_handle).changes:
+ changes.add_change(c)
+ if self.resource in resources:
+ for c in self._restructure([self.resource], task_handle,
+ others=False).changes:
+ changes.add_change(c)
+ return changes
+
+ def get_function_name(self):
+ return self.pyfunction.get_name()
+
+ def _restructure(self, resources, task_handle, others=True):
+ body = self._get_body()
+ pattern = self._make_pattern()
+ goal = self._make_goal(import_=others)
+ imports = None
+ if others:
+ imports = ['import %s' % self._module_name()]
+
+ body_region = sourceutils.get_body_region(self.pyfunction)
+ args_value = {'skip': (self.resource, body_region)}
+ args = {'': args_value}
+
+ restructuring = restructure.Restructure(
+ self.project, pattern, goal, args=args, imports=imports)
+ return restructuring.get_changes(resources=resources,
+ task_handle=task_handle)
+
+ def _find_temps(self):
+ return find_temps(self.project, self._get_body())
+
+ def _module_name(self):
+ return self.project.pycore.modname(self.resource)
+
+ def _make_pattern(self):
+ params = self.pyfunction.get_param_names()
+ body = self._get_body()
+ body = restructure.replace(body, 'return', 'pass')
+ wildcards = list(params)
+ wildcards.extend(self._find_temps())
+ if self._does_return():
+ if self._is_expression():
+ replacement = '${%s}' % self._rope_returned
+ else:
+ replacement = '%s = ${%s}' % (self._rope_result,
+ self._rope_returned)
+ body = restructure.replace(
+ body, 'return ${%s}' % self._rope_returned,
+ replacement)
+ wildcards.append(self._rope_result)
+ return similarfinder.make_pattern(body, wildcards)
+
+ def _get_body(self):
+ return sourceutils.get_body(self.pyfunction)
+
+ def _make_goal(self, import_=False):
+ params = self.pyfunction.get_param_names()
+ function_name = self.pyfunction.get_name()
+ if import_:
+ function_name = self._module_name() + '.' + function_name
+ goal = '%s(%s)' % (function_name,
+ ', ' .join(('${%s}' % p) for p in params))
+ if self._does_return() and not self._is_expression():
+ goal = '${%s} = %s' % (self._rope_result, goal)
+ return goal
+
+ def _does_return(self):
+ body = self._get_body()
+ removed_return = restructure.replace(body, 'return ${result}', '')
+ return removed_return != body
+
+ def _is_expression(self):
+ return len(self.pyfunction.get_ast().body) == 1
+
+ _rope_result = '_rope__result'
+ _rope_returned = '_rope__returned'
+
+
+def find_temps(project, code):
+ code = 'def f():\n' + sourceutils.indent_lines(code, 4)
+ pymodule = project.pycore.get_string_module(code)
+ result = []
+ function_scope = pymodule.get_scope().get_scopes()[0]
+ for name, pyname in function_scope.get_names().items():
+ if isinstance(pyname, pynames.AssignedName):
+ result.append(name)
+ return result
+
+
+def _returns_last(node):
+ return node.body and isinstance(node.body[-1], ast.Return)
+
+def _yield_count(node):
+ visitor = _ReturnOrYieldFinder()
+ visitor.start_walking(node)
+ return visitor.yields
+
+def _return_count(node):
+ visitor = _ReturnOrYieldFinder()
+ visitor.start_walking(node)
+ return visitor.returns
+
+class _ReturnOrYieldFinder(object):
+
+ def __init__(self):
+ self.returns = 0
+ self.yields = 0
+
+ def _Return(self, node):
+ self.returns += 1
+
+ def _Yield(self, node):
+ self.yields += 1
+
+ def _FunctionDef(self, node):
+ pass
+
+ def _ClassDef(self, node):
+ pass
+
+ def start_walking(self, node):
+ nodes = [node]
+ if isinstance(node, ast.FunctionDef):
+ nodes = ast.get_child_nodes(node)
+ for child in nodes:
+ ast.walk(child, self)
diff --git a/vim/eclim/autoload/eclim/python/rope/refactor/wildcards.py b/vim/eclim/autoload/eclim/python/rope/refactor/wildcards.py
@@ -0,0 +1,176 @@
+from rope.base import ast, evaluate, builtins, pyobjects
+from rope.refactor import patchedast, occurrences
+
+
+class Wildcard(object):
+
+ def get_name(self):
+ """Return the name of this wildcard"""
+
+ def matches(self, suspect, arg):
+ """Return `True` if `suspect` matches this wildcard"""
+
+
+class Suspect(object):
+
+ def __init__(self, pymodule, node, name):
+ self.name = name
+ self.pymodule = pymodule
+ self.node = node
+
+
+class DefaultWildcard(object):
+ """The default restructuring wildcard
+
+ The argument passed to this wildcard is in the
+ ``key1=value1,key2=value2,...`` format. Possible keys are:
+
+ * name - for checking the reference
+ * type - for checking the type
+ * object - for checking the object
+ * instance - for checking types but similar to builtin isinstance
+ * exact - matching only occurrences with the same name as the wildcard
+ * unsure - matching unsure occurrences
+
+ """
+
+ def __init__(self, project):
+ self.project = project
+
+ def get_name(self):
+ return 'default'
+
+ def matches(self, suspect, arg=''):
+ args = parse_arg(arg)
+
+ if not self._check_exact(args, suspect):
+ return False
+ if not self._check_object(args, suspect):
+ return False
+ return True
+
+ def _check_object(self, args, suspect):
+ kind = None
+ expected = None
+ unsure = args.get('unsure', False)
+ for check in ['name', 'object', 'type', 'instance']:
+ if check in args:
+ kind = check
+ expected = args[check]
+ if expected is not None:
+ checker = _CheckObject(self.project, expected,
+ kind, unsure=unsure)
+ return checker(suspect.pymodule, suspect.node)
+ return True
+
+ def _check_exact(self, args, suspect):
+ node = suspect.node
+ if args.get('exact'):
+ if not isinstance(node, ast.Name) or not node.id == suspect.name:
+ return False
+ else:
+ if not isinstance(node, ast.expr):
+ return False
+ return True
+
+
+def parse_arg(arg):
+ if isinstance(arg, dict):
+ return arg
+ result = {}
+ tokens = arg.split(',')
+ for token in tokens:
+ if '=' in token:
+ parts = token.split('=', 1)
+ result[parts[0].strip()] = parts[1].strip()
+ else:
+ result[token.strip()] = True
+ return result
+
+
+class _CheckObject(object):
+
+ def __init__(self, project, expected, kind='object', unsure=False):
+ self.project = project
+ self.kind = kind
+ self.unsure = unsure
+ self.expected = self._evaluate(expected)
+
+ def __call__(self, pymodule, node):
+ pyname = self._evaluate_node(pymodule, node)
+ if pyname is None or self.expected is None:
+ return self.unsure
+ if self._unsure_pyname(pyname, unbound=self.kind=='name'):
+ return True
+ if self.kind == 'name':
+ return self._same_pyname(self.expected, pyname)
+ else:
+ pyobject = pyname.get_object()
+ if self.kind == 'object':
+ objects = [pyobject]
+ if self.kind == 'type':
+ objects = [pyobject.get_type()]
+ if self.kind == 'instance':
+ objects = [pyobject]
+ objects.extend(self._get_super_classes(pyobject))
+ objects.extend(self._get_super_classes(pyobject.get_type()))
+ for pyobject in objects:
+ if self._same_pyobject(self.expected.get_object(), pyobject):
+ return True
+ return False
+
+ def _get_super_classes(self, pyobject):
+ result = []
+ if isinstance(pyobject, pyobjects.AbstractClass):
+ for superclass in pyobject.get_superclasses():
+ result.append(superclass)
+ result.extend(self._get_super_classes(superclass))
+ return result
+
+ def _same_pyobject(self, expected, pyobject):
+ return expected == pyobject
+
+ def _same_pyname(self, expected, pyname):
+ return occurrences.same_pyname(expected, pyname)
+
+ def _unsure_pyname(self, pyname, unbound=True):
+ return self.unsure and occurrences.unsure_pyname(pyname, unbound)
+
+ def _split_name(self, name):
+ parts = name.split('.')
+ expression, kind = parts[0], parts[-1]
+ if len(parts) == 1:
+ kind = 'name'
+ return expression, kind
+
+ def _evaluate_node(self, pymodule, node):
+ scope = pymodule.get_scope().get_inner_scope_for_line(node.lineno)
+ expression = node
+ if isinstance(expression, ast.Name) and \
+ isinstance(expression.ctx, ast.Store):
+ start, end = patchedast.node_region(expression)
+ text = pymodule.source_code[start:end]
+ return evaluate.eval_str(scope, text)
+ else:
+ return evaluate.eval_node(scope, expression)
+
+ def _evaluate(self, code):
+ attributes = code.split('.')
+ pyname = None
+ if attributes[0] in ('__builtin__', '__builtins__'):
+ class _BuiltinsStub(object):
+ def get_attribute(self, name):
+ return builtins.builtins[name]
+ def __getitem__(self, name):
+ return builtins.builtins[name]
+ def __contains__(self, name):
+ return name in builtins.builtins
+ pyobject = _BuiltinsStub()
+ else:
+ pyobject = self.project.pycore.get_module(attributes[0])
+ for attribute in attributes[1:]:
+ pyname = pyobject[attribute]
+ if pyname is None:
+ return None
+ pyobject = pyname.get_object()
+ return pyname
diff --git a/vim/eclim/autoload/eclim/python/search.vim b/vim/eclim/autoload/eclim/python/search.vim
@@ -0,0 +1,100 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/find.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Varables {{{
+ if !exists("g:EclimPythonSearchSingleResult")
+ " possible values ('split', 'edit', 'lopen')
+ let g:EclimPythonSearchSingleResult = g:EclimDefaultFileOpenAction
+ endif
+" }}}
+
+" Find(context) {{{
+function! eclim#python#search#Find(context)
+ if !eclim#project#util#IsCurrentFileInProject() || !filereadable(expand('%'))
+ return
+ endif
+
+ " update the file
+ call eclim#util#ExecWithoutAutocmds('silent update')
+
+ let offset = eclim#python#rope#GetOffset()
+ let encoding = eclim#util#GetEncoding()
+ let project = eclim#project#util#GetCurrentProjectRoot()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+
+ let results =
+ \ eclim#python#rope#Find(project, file, offset, encoding, a:context)
+ if type(results) == g:NUMBER_TYPE && results == 0
+ call eclim#util#SetLocationList([])
+ return
+ endif
+
+ if !empty(results)
+ call eclim#util#SetLocationList(eclim#util#ParseLocationEntries(results))
+ let locs = getloclist(0)
+ " if only one result and it's for the current file, just jump to it.
+ " note: on windows the expand result must be escaped
+ if len(results) == 1 && locs[0].bufnr == bufnr('%')
+ if results[0] !~ '|1 col 1|'
+ lfirst
+ endif
+
+ " single result in another file.
+ elseif len(results) == 1 && g:EclimPythonSearchSingleResult != "lopen"
+ let entry = getloclist(0)[0]
+ call eclim#util#GoToBufferWindowOrOpen(
+ \ bufname(entry.bufnr), g:EclimPythonSearchSingleResult)
+ call eclim#util#SetLocationList(eclim#util#ParseLocationEntries(results))
+ call eclim#display#signs#Update()
+
+ call cursor(entry.lnum, entry.col)
+ else
+ exec 'lopen ' . g:EclimLocationListHeight
+ endif
+ elseif has('python')
+ call eclim#util#EchoInfo("Element not found.")
+ endif
+endfunction " }}}
+
+" SearchContext() {{{
+" Executes a contextual search.
+function! eclim#python#search#SearchContext()
+ if getline('.')[col('.') - 1] == '$'
+ call cursor(line('.'), col('.') + 1)
+ let cnum = eclim#util#GetCurrentElementColumn()
+ call cursor(line('.'), col('.') - 1)
+ else
+ let cnum = eclim#util#GetCurrentElementColumn()
+ endif
+
+ if getline('.') =~ '\<\(class\|def\)\s\+\%' . cnum . 'c'
+ call eclim#python#search#Find('occurrences')
+ return
+ endif
+
+ call eclim#python#search#Find('definition')
+
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/python/validate.vim b/vim/eclim/autoload/eclim/python/validate.vim
@@ -0,0 +1,242 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/validate.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+ " if the user has the syntastic plugin (formerly pyflakes), then disable our
+ " validation since the two overlap and may result in errors
+ let s:pyflakes_enabled = 1
+ if exists('g:loaded_syntastic_plugin') || exists('g:pyflakes_builtins')
+ let s:pyflakes_enabled = 0
+ endif
+" }}}
+
+" Script Variables {{{
+ let s:warnings = '\(' . join([
+ \ 'imported but unused',
+ \ 'local variable .* assigned to but never used',
+ \ ], '\|') . '\)'
+" }}}
+
+" Validate(on_save) {{{
+" Validates the current file.
+function! eclim#python#validate#Validate(on_save)
+ let validate = !a:on_save || (
+ \ g:EclimPythonValidate &&
+ \ (!exists('g:EclimFileTypeValidate') || g:EclimFileTypeValidate))
+
+ if !validate || eclim#util#WillWrittenBufferClose()
+ return
+ endif
+
+ "if !eclim#project#util#IsCurrentFileInProject(!a:on_save)
+ " return
+ "endif
+
+ let results = []
+ let syntax_error = eclim#python#validate#ValidateSyntax()
+
+ if syntax_error == ''
+ if s:pyflakes_enabled
+ if !executable('pyflakes')
+ if !exists('g:eclim_python_pyflakes_warn')
+ call eclim#util#EchoWarning("Unable to find 'pyflakes' command.")
+ let g:eclim_python_pyflakes_warn = 1
+ endif
+ else
+ let command = 'pyflakes "' . expand('%:p') . '"'
+ let results = split(eclim#util#System(command), '\n')
+ if v:shell_error > 1 " pyflakes returns 1 if there where warnings.
+ call eclim#util#EchoError('Error running command: ' . command)
+ let results = []
+ endif
+ endif
+ endif
+
+ " rope validation
+ " currently too slow for running on every save.
+ if eclim#project#util#IsCurrentFileInProject(0) && !a:on_save
+ let project = eclim#project#util#GetCurrentProjectRoot()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let rope_results = eclim#python#rope#Validate(project, file)
+ " currently rope gets confused with iterator var on list comprehensions
+ let rope_results = filter(rope_results, "v:val !~ '^Unresolved variable'")
+ let results += rope_results
+ endif
+ endif
+
+ call filter(results, "v:val !~ 'unable to detect undefined names'")
+ if !empty(results) || syntax_error != ''
+ let errors = []
+ if syntax_error != ''
+ let lnum = substitute(syntax_error, '.*(line \(\d\+\))', '\1', '')
+ let text = substitute(syntax_error, '\(.*\)\s\+(line .*', '\1', '')
+ if lnum == syntax_error
+ let lnum = 1
+ let text .= ' (unknown line)'
+ endif
+ call add(errors, {
+ \ 'filename': eclim#util#Simplify(expand('%')),
+ \ 'lnum': lnum,
+ \ 'text': text,
+ \ 'type': 'e'
+ \ })
+ else
+ for error in results
+ let file = substitute(error, '\(.\{-}\):[0-9]\+:.*', '\1', '')
+ let line = substitute(error, '.\{-}:\([0-9]\+\):.*', '\1', '')
+ let message = substitute(error, '.\{-}:[0-9]\+:\(.*\)', '\1', '')
+ let dict = {
+ \ 'filename': eclim#util#Simplify(file),
+ \ 'lnum': line,
+ \ 'text': message,
+ \ 'type': message =~ s:warnings ? 'w' : 'e',
+ \ }
+
+ call add(errors, dict)
+ endfor
+ endif
+
+ call eclim#util#SetLocationList(errors)
+ else
+ call eclim#util#ClearLocationList()
+ endif
+endfunction " }}}
+
+" ValidateSyntax() {{{
+function! eclim#python#validate#ValidateSyntax()
+ let syntax_error = ''
+
+ if has('python')
+python << EOF
+import re, vim
+try:
+ try:
+ from ast import parse
+ filename = vim.eval('expand("%:p")')
+ with open(filename) as f:
+ parse(f.read(), filename)
+ except SyntaxError as se:
+ vim.command("let syntax_error = \"%s (line %s)\"" % (se.msg, se.lineno))
+ except ImportError:
+ from compiler import parseFile
+ try:
+ parseFile(vim.eval('expand("%:p")'))
+ except SyntaxError, se:
+ vim.command("let syntax_error = \"%s\"" % re.sub(r'"', r'\"', str(se)))
+ except IndentationError, ie:
+ vim.command("let syntax_error = \"%s (line %s)\"" % (
+ re.sub(r'"', r'\"', ie.msg), ie.lineno)
+ )
+except Exception, e:
+ vim.command("let syntax_error = \"%s\"" % str(e))
+EOF
+ endif
+
+ return syntax_error
+endfunction " }}}
+
+" PyLint() {{{
+function! eclim#python#validate#PyLint()
+ let file = expand('%:p')
+
+ if !executable('pylint')
+ call eclim#util#EchoError("Unable to find 'pylint' command.")
+ return
+ endif
+
+ let pylint_env = ''
+ if exists('g:EclimPyLintEnv')
+ let pylint_env = g:EclimPyLintEnv
+ else
+ let paths = []
+
+ let django_dir = eclim#python#django#util#GetProjectPath()
+ if django_dir != ''
+ call add(paths, fnamemodify(django_dir, ':h'))
+ if len($DJANGO_SETTINGS_MODULE)
+ let settings = $DJANGO_SETTINGS_MODULE
+ else
+ let settings = fnamemodify(django_dir, ':t')
+ endif
+ if has('win32') || has('win64')
+ let pylint_env =
+ \ 'set DJANGO_SETTINGS_MODULE='. settings . '.settings && '
+ else
+ let pylint_env =
+ \ 'DJANGO_SETTINGS_MODULE="'. settings . '.settings" '
+ endif
+ endif
+
+ if eclim#project#util#IsCurrentFileInProject(0)
+ let project = eclim#project#util#GetCurrentProjectRoot()
+ let paths += eclim#python#rope#GetSourceDirs(project)
+ endif
+
+ if !empty(paths)
+ if has('win32') || has('win64')
+ let pylint_env .= 'set "PYTHONPATH=' . join(paths, ';') . '" && '
+ else
+ let pylint_env .= 'PYTHONPATH="' . join(paths, ':') . ':$PYTHONPATH"'
+ endif
+ endif
+ endif
+
+ " TODO: switch to 'parseable' output format.
+ let command = pylint_env .
+ \ ' pylint --reports=n --output-format=text "' . file . '"'
+ if has('win32') || has('win64')
+ let command = 'cmd /c "' . command . ' "'
+ endif
+
+ call eclim#util#Echo('Running pylint (ctrl-c to cancel) ...')
+ let result = eclim#util#System(command)
+ call eclim#util#Echo(' ')
+ if v:shell_error >= 32
+ call eclim#util#EchoError('Error running command: ' . command)
+ return
+ endif
+
+ if result =~ ':'
+ let errors = []
+ for error in split(result, '\n')
+ if error =~ '^[CWERF]\d*\(:\s\+\)\?\d'
+ let line = substitute(error, '.\{-}:\s*\(\d\+\)[:,].*', '\1', '')
+ let message = substitute(error, '.\{-}:\s*.\{-}:\s*\(.*\)', '\1', '')
+ let dict = {
+ \ 'filename': eclim#util#Simplify(file),
+ \ 'lnum': line,
+ \ 'text': message,
+ \ 'type': error =~ '^E' ? 'e' : 'w',
+ \ }
+
+ call add(errors, dict)
+ endif
+ endfor
+ call eclim#util#SetQuickfixList(errors)
+ else
+ call eclim#util#SetQuickfixList([], 'r')
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/taglisttoo/lang/commonsvalidator.vim b/vim/eclim/autoload/eclim/taglisttoo/lang/commonsvalidator.vim
@@ -0,0 +1,33 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Parse(file, settings) {{{
+function! eclim#taglisttoo#lang#commonsvalidator#Parse(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['c', '<constant-name\s*>\s*(.*?)\s*</constant-name\s*>', 1],
+ \ ['f', "<form\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['v', "<validator\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ])
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/taglisttoo/lang/cproject.vim b/vim/eclim/autoload/eclim/taglisttoo/lang/cproject.vim
@@ -0,0 +1,40 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Parse(file, settings) {{{
+function! eclim#taglisttoo#lang#cproject#Parse(file, settings)
+ let tags = taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['c', "<configuration\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['t', "<toolChain\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['l', "<tool\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['i', "<option\\s+[^>]*?valueType=['\"]includePath['\"]", 'includes'],
+ \ ['s', "<option\\s+[^>]*?valueType=['\"]definedSymbols['\"]", 'symbols'],
+ \ ])
+
+ call taglisttoo#util#SetNestedParents(
+ \ a:settings.tags, tags, ['c'], '<configuration', '</configuration')
+
+ return tags
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/taglisttoo/lang/eclimhelp.vim b/vim/eclim/autoload/eclim/taglisttoo/lang/eclimhelp.vim
@@ -0,0 +1,32 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Parse(file, settings) {{{
+function! eclim#taglisttoo#lang#eclimhelp#Parse(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['a', '\*([^ *]+)\*', 1],
+ \ ['s', '\n([^\n]+)\n[=^-]{4,}', 1],
+ \ ])
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/taglisttoo/lang/forrest.vim b/vim/eclim/autoload/eclim/taglisttoo/lang/forrest.vim
@@ -0,0 +1,39 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" ParseDocument(file, settings) {{{
+function! eclim#taglisttoo#lang#forrest#ParseDocument(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['s', "<section\\s+[^>]*?id=['\"](.*?)['\"]", 1],
+ \ ])
+endfunction " }}}
+
+" ParseStatus(file, settings) {{{
+function! eclim#taglisttoo#lang#forrest#ParseStatus(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['t', "<actions\\s+[^>]*?priority=['\"](.*?)['\"]", 1],
+ \ ['r', "<release\\s+[^>]*?version=['\"](.*?)['\"]", 1],
+ \ ])
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/taglisttoo/lang/gant.vim b/vim/eclim/autoload/eclim/taglisttoo/lang/gant.vim
@@ -0,0 +1,33 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2010 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Parse(file, settings) {{{
+function! eclim#taglisttoo#lang#gant#Parse(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['t', "\\s*target\\s*\\(\\s*(?:name\\s*:)?\\s*['\"]?([^'\",: ]+)", 1],
+ \ ['f', "\\s*def\\s+(\\w+)\\s*\\(", 1],
+ \ ['f', "\\s*(?:final|def)?\\s*(\\w+)\\s*=\\s*\\{", 1],
+ \ ])
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/taglisttoo/lang/hibernate.vim b/vim/eclim/autoload/eclim/taglisttoo/lang/hibernate.vim
@@ -0,0 +1,37 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Parse(file, settings) {{{
+function! eclim#taglisttoo#lang#hibernate#Parse(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['c', "<class\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['j', "<joined-subclass\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['t', "<typedef\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['f', "<filter-def\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['i', "<import\\s+[^>]*?class=['\"](.*?)['\"]", 1],
+ \ ['q', "<query\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['s', "<sql-query\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ])
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/taglisttoo/lang/junit.vim b/vim/eclim/autoload/eclim/taglisttoo/lang/junit.vim
@@ -0,0 +1,33 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Parse(file, settings) {{{
+function! eclim#taglisttoo#lang#junit#Parse(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['t', "<testcase\\s+[^>]*?\\bname=['\"](.*?)['\"]", 1],
+ \ ['f', "<testcase\\s+[^>]*?\\bname=['\"]([^'\"]+?)['\"]\\s+[^>]*?>\\s*<failure\\b", 1],
+ \ ['o', '<system-(out|err)\s*>', 1],
+ \ ])
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/taglisttoo/lang/spring.vim b/vim/eclim/autoload/eclim/taglisttoo/lang/spring.vim
@@ -0,0 +1,33 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Parse(file, settings) {{{
+function! eclim#taglisttoo#lang#spring#Parse(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['b', "<bean\\s+[^>]*?(?:name|id)=['\"](.*?)['\"]", 1],
+ \ ['i', "<import\\s+[^>]*?resource=['\"](.*?)['\"]", 1],
+ \ ['a', "<alias\\s+[^>]*?alias=['\"](.*?)['\"]", 1],
+ \ ])
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/taglisttoo/lang/webxml.vim b/vim/eclim/autoload/eclim/taglisttoo/lang/webxml.vim
@@ -0,0 +1,43 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2010 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" ParseWebXml(file, settings) {{{
+function! eclim#taglisttoo#lang#webxml#ParseWebXml(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['p', '<context-param\s*>\s*<param-name\s*>\s*(.*?)\s*</param-name\s*>', 1],
+ \ ['f', '<filter\s*>\s*<filter-name\s*>\s*(.*?)\s*</filter-name\s*>', 1],
+ \ ['i', '<filter-mapping\s*>\s*<filter-name\s*>\s*(.*?)\s*</filter-name\s*>', 1],
+ \ ['l', '<listener\s*>\s*<listener-class\s*>\s*(.*?)\s*</listener-class\s*>', 1],
+ \ ['s', '<servlet\s*>\s*<servlet-name\s*>\s*(.*?)\s*</servlet-name\s*>', 1],
+ \ ['v', '<servlet-mapping\s*>\s*<servlet-name\s*>\s*(.*?)\s*</servlet-name\s*>', 1],
+ \ ])
+endfunction " }}}
+
+" ParseTld(file, settings) {{{
+function! eclim#taglisttoo#lang#webxml#ParseTld(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['t', '<tag\s*>\s*<name\s*>\s*(.*?)\s*</name\s*>', 1],
+ \ ])
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/taglisttoo/lang/wsdl.vim b/vim/eclim/autoload/eclim/taglisttoo/lang/wsdl.vim
@@ -0,0 +1,48 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+" Copyright (c) 2005 - 2011, Eric Van Dewoestine
+" All rights reserved.
+"
+" Redistribution and use of this software in source and binary forms, with
+" or without modification, are permitted provided that the following
+" conditions are met:
+"
+" * Redistributions of source code must retain the above
+" copyright notice, this list of conditions and the
+" following disclaimer.
+"
+" * Redistributions in binary form must reproduce the above
+" copyright notice, this list of conditions and the
+" following disclaimer in the documentation and/or other
+" materials provided with the distribution.
+"
+" * Neither the name of Eric Van Dewoestine nor the names of its
+" contributors may be used to endorse or promote products derived from
+" this software without specific prior written permission of
+" Eric Van Dewoestine.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+" IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+" THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+" PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+" }}}
+
+" Parse(file, settings) {{{
+function! eclim#taglisttoo#lang#wsdl#Parse(file, settings)
+ return taglisttoo#util#Parse(a:file, a:settings, [
+ \ ['t', "<xsd:complexType\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['m', "<message\\s+[^>]*?name=['\"](.*?)['\"]", 1],
+ \ ['p', "<operation\\s+[^>]*?name=['\"](.*?)['\"]>\\s*<input", 1],
+ \ ['b', "<operation\\s+[^>]*?name=['\"]([^\n]*?)['\"]>\\s*<soap:operation", 1],
+ \ ])
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/tree.vim b/vim/eclim/autoload/eclim/tree.vim
@@ -0,0 +1,1210 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Filesystem explorer.
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+ if !exists("g:TreeDirHighlight")
+ let g:TreeDirHighlight = "Statement"
+ endif
+ if !exists("g:TreeFileHighlight")
+ let g:TreeFileHighlight = "Normal"
+ endif
+ if !exists("g:TreeFileExecutableHighlight")
+ let g:TreeFileExecutableHighlight = "Constant"
+ endif
+ if !exists("g:TreeActionHighlight")
+ let g:TreeActionHighlight = "Statement"
+ endif
+ if !exists('g:TreeExpandSingleDirs')
+ let g:TreeExpandSingleDirs = 0
+ endif
+ if !exists('g:TreeIndent')
+ let g:TreeIndent = 4
+ endif
+ if g:TreeIndent < 2
+ call eclim#util#EchoWarning('g:TreeIndent cannot be less than 2.')
+ let g:TreeIndent = 2
+ endif
+" }}}
+
+" Script Variables {{{
+ let s:node_prefix = ''
+ let index = 0
+ while index < (g:TreeIndent - 2)
+ let s:node_prefix .= ' '
+ let index += 1
+ endwhile
+
+ let s:dir_opened_prefix = '- '
+ let s:dir_closed_prefix = '+ '
+ let s:file_prefix = ' '
+
+ let s:indent_length = len(s:node_prefix) + len(s:file_prefix)
+
+ let s:node_regex = s:node_prefix . '\(' .
+ \ s:dir_opened_prefix . '\|' .
+ \ s:dir_closed_prefix . '\|' .
+ \ s:file_prefix . '\)'
+ " \1 - indent, \2, node prefix + element prefix, \3 name
+ let s:nodevalue_regex = '\(\s*\)' . s:node_regex . '\(.*\)'
+ let s:root_regex = '^[/[:alpha:]]'
+
+ let s:settings_loaded = 0
+
+ let s:tree_count = 0
+ let s:refresh_nesting = 0
+
+ let s:has_ls = executable('ls') && !(has('win32') || has('win64'))
+
+ let s:vcol = 0
+" }}}
+
+function! eclim#tree#TreeHome() " {{{
+ let name = "Tree"
+ if s:tree_count > 0
+ let name .= s:tree_count
+ endif
+ let s:tree_count += 1
+
+ call eclim#tree#Tree(name, [eclim#UserHome()], [], 1, [])
+endfunction " }}}
+
+function! eclim#tree#TreePanes() " {{{
+ call eclim#tree#TreeHome()
+ vertical new
+ call eclim#tree#TreeHome()
+ 1winc w
+endfunction " }}}
+
+function! eclim#tree#Tree(name, roots, aliases, expand, filters) " {{{
+ " name - The name to use for the tree buffer.
+ " roots - List of paths to use as tree roots.
+ " aliases - List of aliases for root paths, or an empty list for no aliasing.
+ " expand - 1 to pre expand the root directories, 0 otherwise.
+ " filters - List of file name patterns to include in directory listings, or an
+ " empty list for no filtering.
+
+ silent exec 'edit ' . escape(a:name, ' ')
+ setlocal ft=tree
+ setlocal nowrap
+ setlocal noswapfile
+ setlocal nobuflisted
+ setlocal buftype=nofile
+ setlocal bufhidden=delete
+ setlocal foldmethod=manual
+ setlocal foldtext=getline(v:foldstart)
+ setlocal sidescrolloff=0
+
+ call s:Mappings()
+ call eclim#tree#Syntax()
+
+ " initialize autocmds before loading custom settings so that settings can
+ " add autocmd events.
+ augroup eclim_tree
+ "autocmd! BufEnter,User <buffer>
+ autocmd BufEnter <buffer> silent doautocmd eclim_tree User <buffer>
+ exec 'autocmd BufDelete,BufUnload <buffer> ' .
+ \ 'autocmd! eclim_tree * <buffer=' . bufnr('%') . '>'
+ augroup END
+
+ " register setting prior to listing any directories
+ if exists("g:TreeSettingsFunction")
+ let l:Settings = function(g:TreeSettingsFunction)
+ call l:Settings()
+ let s:settings_loaded = 1
+ endif
+
+ setlocal noreadonly modifiable
+ silent 1,$delete _
+
+ let roots = map(copy(a:roots), 'substitute(v:val, "\\([^/]\\)$", "\\1/", "")')
+ let [roots, _] = s:NormalizeEntries(roots)
+ let b:roots = copy(roots)
+ let b:filters = a:filters
+ let b:view_hidden = 0
+
+ if len(a:aliases) > 0
+ let b:aliases = {}
+ let index = 0
+ for alias in a:aliases
+ if alias != ''
+ let b:aliases[alias] = roots[index]
+ endif
+ let index += 1
+ endfor
+
+ call map(roots, 's:PathToAlias(v:val)')
+ endif
+
+ call append(line('$'), roots)
+
+ if a:expand
+ let index = len(roots)
+ while index > 0
+ call cursor(index + 1, 1)
+ call eclim#tree#ExpandDir()
+ let index = index - 1
+ endwhile
+ endif
+
+ " delete empty first line.
+ setlocal modifiable
+ 1,1delete _
+ setlocal nomodifiable
+endfunction " }}}
+
+function! eclim#tree#ToggleCollapsedDir(Expand) " {{{
+ if eclim#tree#GetPath() =~ '/$'
+ if getline('.') =~ '\s*' . s:node_prefix . s:dir_closed_prefix ||
+ \ (getline('.') =~ s:root_regex && eclim#tree#GetLastChildPosition() == line('.'))
+ call a:Expand()
+ else
+ call s:CollapseDir()
+ endif
+ endif
+endfunction " }}}
+
+function! eclim#tree#ToggleFoldedDir(Expand) " {{{
+ if eclim#tree#GetPath() =~ '/$'
+ if foldclosed(line('.')) != -1
+ call s:UnfoldDir()
+ elseif getline('.') =~ '\s*' . s:node_prefix . s:dir_opened_prefix ||
+ \ (getline('.') =~ s:root_regex && eclim#tree#GetLastChildPosition() != line('.'))
+ call s:FoldDir()
+ else
+ call a:Expand()
+ endif
+ endif
+endfunction " }}}
+
+function! eclim#tree#ToggleViewHidden() " {{{
+ let b:view_hidden = (b:view_hidden + 1) % 2
+
+ let line = getline('.')
+ let path = eclim#tree#GetPath()
+ call cursor(1, 1)
+ call eclim#tree#Refresh()
+ while search(s:root_regex, 'W') != 0
+ call eclim#tree#Refresh()
+ endwhile
+
+ call cursor(1, 1)
+ while search(line, 'W') != 0 && eclim#tree#GetPath() != path
+ endwhile
+ call eclim#tree#Cursor(line, 0)
+endfunction " }}}
+
+function! eclim#tree#GetFileInfo(file) " {{{
+ if executable('ls')
+ return split(eclim#util#System("ls -ld '" . a:file . "'"), '\n')[0]
+ endif
+ return ''
+endfunction "}}}
+
+function! eclim#tree#GetPath(...) " {{{
+ " Optional args:
+ " resolve_links
+ let line = getline('.')
+ let node = substitute(line, s:nodevalue_regex, '\3', '')
+
+ let node = eclim#tree#GetParent(a:0 ? a:1 : 1) . node
+ let path = s:AliasToPath(node)
+
+ " handle symbolic links
+ if path =~ '->'
+ if !a:0 || a:1 " resolve links
+ let link = substitute(path, '.* -> \(.*\)', '\1', '')
+ if link !~ '^/' && link !~ '^[a-zA-Z]:/'
+ let parent = substitute(path, '\(.*\) -> .*', '\1', '')
+ let parent = fnamemodify(substitute(parent, '/$', '', ''), ':h')
+ let link = parent . '/' . link
+ endif
+ let path = link
+ else
+ let path = substitute(path, '\(.*\) -> .*', '\1', '')
+ if node =~ '/$'
+ let path .= '/'
+ endif
+ endif
+ endif
+
+ " handle executable files.
+ if path =~ '\*$'
+ let path = strpart(path, 0, len(path) - 1)
+ endif
+
+ return path
+endfunction "}}}
+
+function! eclim#tree#GetParent(...) " {{{
+ " Optional args:
+ " resolve_links
+ let parent = ''
+
+ let lnum = eclim#tree#GetParentPosition()
+ if lnum
+ let pos = getpos('.')
+ call cursor(lnum, 1)
+ let parent = eclim#tree#GetPath(a:0 ? a:1 : 1)
+ call setpos('.', pos)
+ endif
+
+ return parent
+endfunction " }}}
+
+function! eclim#tree#GetParentPosition() " {{{
+ let lnum = 0
+ let line = getline('.')
+ if line =~ '\s*' . s:node_prefix
+ if line =~ '^' . s:node_regex . '\S'
+ let search = s:root_regex
+ else
+ let search = '^'
+ let index = 0
+ let indent = s:GetIndent(line('.'))
+ while index < indent - s:indent_length
+ let search .= ' '
+ let index += 1
+ endwhile
+ let search .= s:node_prefix . s:dir_opened_prefix
+ endif
+
+ let lnum = search(search, 'bnW')
+
+ " hack: most likely one of:
+ " - refresh from comment line
+ " - refresh from first level dir/file with g:TreeIndent < 4
+ if lnum == 0 && search != s:root_regex
+ let lnum = search(s:root_regex, 'bnW')
+ endif
+ endif
+
+ return lnum
+endfunction " }}}
+
+function! eclim#tree#GetLastChildPosition() " {{{
+ let line = getline('.')
+
+ " a root node
+ if line =~ s:root_regex
+ let lnum = search(s:root_regex, 'nW')
+ return lnum > 0 ? lnum - 1 : s:GetLastLine()
+ endif
+
+ " non root node
+ let sibling = '^' .
+ \ substitute(line, s:nodevalue_regex, '\1' . escape(s:node_regex. '[.[:alnum:]_]', '\'), '')
+ let lnum = line('.') + 1
+ let indent = s:GetIndent(line('.'))
+ while getline(lnum) !~ sibling &&
+ \ s:GetIndent(lnum) >= indent &&
+ \ lnum != s:GetLastLine()
+ let lnum += 1
+ endwhile
+
+ " back up one if on a node of equal or less depth
+ if s:GetIndent(lnum) <= indent
+ let lnum -= 1
+ endif
+
+ " no sibling below, use parent's value
+ if lnum == line('.') && getline(lnum + 1) !~ sibling
+ let pos = getpos('.')
+
+ call cursor(eclim#tree#GetParentPosition(), 1)
+ let lnum = eclim#tree#GetLastChildPosition()
+
+ call setpos('.', pos)
+ endif
+
+ return lnum
+endfunction " }}}
+
+function! eclim#tree#Execute(alt) " {{{
+ if getline('.') =~ '^"\|^\s*$'
+ return
+ endif
+
+ let path = eclim#tree#GetPath()
+
+ " execute action on dir
+ if path =~ '/$'
+ if a:alt || foldclosed(line('.')) != -1
+ call eclim#tree#ToggleFoldedDir(function('eclim#tree#ExpandDir'))
+ else
+ call eclim#tree#ToggleCollapsedDir(function('eclim#tree#ExpandDir'))
+ endif
+
+ " execute action on file
+ else
+ if !filereadable(path)
+ echo "File is not readable or has been deleted."
+ endif
+
+ let actions = eclim#tree#GetFileActions(path)
+ if len(actions) == 0
+ echo "No registered actions for file: " . path
+ return
+ endif
+
+ if a:alt
+ call eclim#tree#DisplayActionChooser(
+ \ path, actions, 'eclim#tree#ExecuteAction')
+ else
+ call eclim#tree#ExecuteAction(path, actions[0].action)
+ endif
+ endif
+endfunction " }}}
+
+function! eclim#tree#ExecuteAction(file, command) " {{{
+ let file = eclim#util#Simplify(a:file)
+ let file = escape(file, ' &()')
+ let file = escape(file, ' &()') " need to double escape
+ let file = escape(file, '&') " '&' needs to be escaped 3 times.
+
+ let command = a:command
+ let command = substitute(command, '<file>', file, 'g')
+ if command =~ '^!\w'
+ silent call eclim#util#Exec(command)
+ redraw!
+ else
+ exec command
+ endif
+
+ if command =~ '^!\w' && v:shell_error
+ call eclim#util#EchoError('Error executing command: ' . command)
+ endif
+endfunction " }}}
+
+function! eclim#tree#RegisterFileAction(regex, name, action) " {{{
+ " regex - Pattern to match the file name against.
+ " name - Name of the action used for display purposes.
+ " action - The action to execute where <file> is replaced with the filename.
+
+ if !exists('b:file_actions')
+ let b:file_actions = []
+ endif
+
+ let entry = {}
+ for e in b:file_actions
+ if e.regex == a:regex
+ let entry = e
+ break
+ endif
+ endfor
+
+ if len(entry) == 0
+ let entry = {'regex': a:regex, 'actions': []}
+ call add(b:file_actions, entry)
+ endif
+
+ call add(entry.actions, {'name': a:name, 'action': a:action})
+endfunction " }}}
+
+function! eclim#tree#RegisterDirAction(action) " {{{
+ " action - A funcref which will be invoked when expanding a directory with the
+ " directory path and a mutable list of current directory contents.
+ if !exists('b:dir_actions')
+ let b:dir_actions = []
+ endif
+ call add(b:dir_actions, a:action)
+endfunction " }}}
+
+function! eclim#tree#GetFileActions(file) " {{{
+ " Returns a list of dictionaries with keys 'name' and 'action'.
+ let actions = []
+ let thefile = tolower(a:file)
+ let bufnr = bufnr('%')
+ for entry in b:file_actions
+ if thefile =~ entry.regex
+ let actions += entry.actions
+ endif
+ endfor
+
+ return actions
+endfunction " }}}
+
+function! eclim#tree#Shell(external) " {{{
+ " Opens a shell either in the current vim session or externally.
+ let path = eclim#tree#GetPath()
+ if !isdirectory(path)
+ let path = fnamemodify(path, ':h')
+ endif
+
+ let cwd = getcwd()
+ silent exec "lcd " . escape(path, ' &')
+ if a:external
+ if !exists("g:TreeExternalShell")
+ echo "No external shell configured via 'g:TreeExternalShell' variable."
+ else
+ silent call eclim#util#Exec(g:TreeExternalShell)
+ redraw!
+ endif
+ else
+ shell
+ endif
+ silent exec "lcd " . escape(cwd, ' &')
+endfunction " }}}
+
+function! eclim#tree#Cursor(line, prevline) " {{{
+ let lnum = a:line
+ let line = getline(lnum)
+
+ if line =~ s:root_regex
+ call cursor(lnum, 1)
+ else
+ " get the starting column of the current line and the previous line
+ let start = len(line) - len(substitute(line, '^\s\+\W', '', ''))
+
+ " only use the real previous line if we've only moved one line
+ let moved = a:prevline - lnum
+ if moved < 0
+ let moved = -moved
+ endif
+ let pline = moved == 1 ? getline(a:prevline) : ''
+ let pstart = pline != '' ?
+ \ len(pline) - len(substitute(pline, '^\s\+\W', '', '')) : -1
+
+ " only change the cursor column if the hasn't user has moved it to the
+ " right to view more of the entry
+ let cnum = start == pstart ? 0 : start
+ call cursor(lnum, cnum)
+
+ " attempt to maximize the amount of text on the current line that is in
+ " view, but only if we've changed column position
+ let winwidth = winwidth(winnr())
+ let vcol = exists('s:vcol') ? s:vcol : 0
+ let col = col('.')
+ if cnum != 0 && (!vcol || ((len(line) - vcol) > winwidth))
+ if len(line) > winwidth
+ normal! zs
+ " scroll back enough to keep the start of the parent in view
+ normal! 6zh
+ let s:vcol = col - 6
+ endif
+ endif
+
+ " when the text view is shifted by vim it appears to always shift back one
+ " half of the window width, so recalculate our visible column accordingly
+ " if we detect such a shift... may not always be accurate.
+ if s:vcol > col
+ let s:vcol = max([start - (winwidth / 2), 0])
+ endif
+ endif
+endfunction " }}}
+
+function! eclim#tree#GetRoot() " {{{
+ if getline('.') =~ s:root_regex
+ return s:AliasToPath(getline('.'))
+ endif
+ let start = search(s:root_regex, 'bcnW')
+ return s:AliasToPath(getline(start))
+endfunction " }}}
+
+function! eclim#tree#SetRoot(path) " {{{
+ let path = s:AliasToPath(a:path)
+ let path = s:NormalizeEntries([fnamemodify(path, ':p')])[0][0]
+ if !isdirectory(path)
+ echo 'Directory does not exist or may have been deleted.'
+ return
+ endif
+
+ let path = s:PathToAlias(path)
+
+ " if on a root node
+ if getline('.') =~ s:root_regex
+ let start = line('.')
+
+ " not on a root node
+ else
+ let start = search(s:root_regex, 'bW')
+ endif
+ let end = eclim#tree#GetLastChildPosition()
+
+ setlocal noreadonly modifiable
+ silent exec start . ',' . end . 'delete _'
+
+ let line = line('.')
+ if line == 1
+ let line = 0
+ endif
+ call append(line, path)
+
+ " delete blank first line if any
+ if getline(1) =~ '^$'
+ silent 1,1delete _
+ endif
+ " delete blank last line if any
+ if getline('$') =~ '^$'
+ silent exec line('$') . ',' . line('$') . 'delete _'
+ endif
+
+ call cursor(line + 1, 1)
+ call eclim#tree#ExpandDir()
+ setlocal nomodifiable
+endfunction " }}}
+
+function! eclim#tree#Refresh() " {{{
+ " FIXME: in need of a serious rewrite (probably need to rewrite the whole
+ " plugin)
+
+ let ignore_pattern = ''
+ if &wildignore != ''
+ let ignore_pattern = substitute(escape(&wildignore, '.'), '\*', '.*', 'g')
+ let ignore_pattern = '\(' . join(split(ignore_pattern, ','), '\|') . '\)$'
+ endif
+
+ let clnum = line('.')
+ let ccnum = col('.')
+
+ let startpath = eclim#tree#GetPath()
+ if s:refresh_nesting == 0
+ let s:startpath = startpath
+ " let vim track shifts in line numbers with a mark
+ mark Z
+ endif
+
+ " if on a file or closed directory, refresh it's parent
+ if startpath !~ '/$' ||
+ \ getline('.') =~ '^\s*' . s:node_prefix . s:dir_closed_prefix
+ call cursor(eclim#tree#GetParentPosition(), 1)
+ let startpath = eclim#tree#GetPath()
+ endif
+
+ let start = line('.')
+ let end = eclim#tree#GetLastChildPosition()
+
+ " first check the node we are on
+ if (!isdirectory(startpath) && !filereadable(startpath)) ||
+ \ (getline('.') !~ s:root_regex && s:IsHidden(startpath, ignore_pattern))
+ setlocal modifiable
+ silent exec start . ',' . end . 'delete _'
+ setlocal nomodifiable
+ silent doautocmd eclim_tree User <buffer>
+ return
+ endif
+
+ if s:refresh_nesting == 0
+ call eclim#util#Echo('Refreshing...')
+ endif
+ let s:refresh_nesting += 1
+
+ " move cursor to first child
+ call cursor(start + 1, 1)
+ " get pattern to use to match children.
+ let match = substitute(getline('.'), '^' . s:nodevalue_regex, '\1', '')
+ let match = '^' . match . s:node_regex . '[.[:alnum:]_]'
+
+ " walk the tree
+ let lnum = line('.')
+ while lnum <= end && lnum <= s:GetLastLine()
+
+ let line = getline('.')
+
+ " open dir that needs to be refreshed as well.
+ if line =~ '\s*' . s:node_prefix . s:dir_opened_prefix
+ call eclim#tree#Refresh()
+ let lnum = eclim#tree#GetLastChildPosition()
+ let ldiff = lnum - line('.')
+ let end += ldiff
+ call cursor(lnum, 1)
+ endif
+
+ let path = eclim#tree#GetPath()
+
+ " delete files, and dirs that do not exist, or are hidden.
+ if (path =~ '/$' && !isdirectory(path)) ||
+ \ (path !~ '/$' && !filereadable(path)) ||
+ \ s:IsHidden(path, ignore_pattern)
+ let last = eclim#tree#GetLastChildPosition()
+ setlocal modifiable
+ silent exec lnum . ',' . last . 'delete _'
+ setlocal nomodifiable
+ let end -= (last - lnum) + 1
+ continue
+ endif
+
+ let lnum += 1
+ call cursor(lnum, 1)
+ endwhile
+ call cursor(start + 1, ccnum)
+
+ " merge in any dirs that have been added
+ let contents = eclim#tree#ListDir(startpath)
+ let [dirs, files] = s:NormalizeEntries(contents)
+ let contents = dirs + files
+ let root = eclim#tree#GetRoot()
+ let indent = eclim#tree#GetChildIndent(start)
+ let lnum = line('.')
+ setlocal modifiable
+ for entry in contents
+ let path = eclim#tree#GetPath(0)
+ let path_link = eclim#tree#GetPath(0)
+ let rewrote = s:RewriteSpecial(entry)
+ let norm_entry = substitute(entry, '[*@]$', '', '')
+ if rewrote =~ '/$' && norm_entry !~ '/$'
+ let norm_entry .= '/'
+ endif
+
+ " ugly
+ if exists('b:links')
+ for [link, target] in items(b:links)
+ if path =~ '^' . root . link
+ let path = substitute(path, root . link, target, '')
+ break
+ endif
+ endfor
+ endif
+
+ if path != norm_entry && path_link != norm_entry
+ " if we are adding a new entry we'll just add one that has the correct
+ " index + prefix and let the next block set the proper display path.
+ if s:MatchesFilter(norm_entry)
+ if isdirectory(entry)
+ let initial = fnamemodify(substitute(entry, '/$', '', ''), ':t') . '/'
+ else
+ let initial = fnamemodify(entry, ':t')
+ endif
+
+ if index(dirs, entry) != -1
+ let display_entry = indent . s:node_prefix . s:dir_closed_prefix . initial
+ else
+ let display_entry = indent . s:node_prefix . s:file_prefix . initial
+ endif
+ if lnum <= s:GetLastLine()
+ call append(lnum - 1, display_entry)
+ else
+ call append(s:GetLastLine(), display_entry)
+ endif
+ call cursor(lnum, 0)
+ endif
+ endif
+
+ let parent = eclim#tree#GetParent(0)
+ let parent_link = eclim#tree#GetParent()
+ if index(dirs, entry) != -1
+ let dir_prefix = s:dir_closed_prefix
+ if getline(lnum) =~ '\s*' . s:node_prefix . s:dir_opened_prefix
+ let dir_prefix = s:dir_opened_prefix
+ endif
+ let display_entry = indent . s:node_prefix . dir_prefix .
+ \ substitute(substitute(rewrote, parent, '', ''), parent_link, '', '')
+ else
+ let display_entry = indent . s:node_prefix . s:file_prefix .
+ \ substitute(substitute(rewrote, parent, '', ''), parent_link, '', '')
+ endif
+
+ call setline(lnum, display_entry)
+ if getline(lnum) =~ '\s*' . s:node_prefix . s:dir_opened_prefix
+ call cursor(eclim#tree#GetLastChildPosition() + 1, 1)
+ let lnum = line('.')
+ else
+ let lnum += 1
+ call cursor(lnum, 1)
+ endif
+
+ endfor
+ setlocal nomodifiable
+
+ call cursor(clnum, ccnum)
+ let s:refresh_nesting -= 1
+
+ if s:refresh_nesting == 0
+ call eclim#util#Echo(' ')
+ " return to marked position.
+ call cursor(line("'Z"), col("`Z"))
+ " if the entry that we started on is gone, move the cursor up a line.
+ if s:startpath != eclim#tree#GetPath()
+ call cursor(line('.') - 1, col('.'))
+ endif
+ endif
+ silent doautocmd eclim_tree User <buffer>
+endfunction " }}}
+
+function! eclim#tree#MoveToLastChild() " {{{
+ mark '
+ if getline('.') !~ '^\s*' . s:node_prefix . s:dir_opened_prefix . '[.[:alnum:]_]'
+ call cursor(eclim#tree#GetParentPosition(), 1)
+ endif
+ call eclim#tree#Cursor(eclim#tree#GetLastChildPosition(), 0)
+endfunction " }}}
+
+function! eclim#tree#MoveToParent() " {{{
+ mark '
+ call eclim#tree#Cursor(eclim#tree#GetParentPosition(), 0)
+endfunction " }}}
+
+function! eclim#tree#Mkdir() " {{{
+ let path = eclim#tree#GetPath()
+ if !isdirectory(path)
+ let path = fnamemodify(path, ':h') . '/'
+ endif
+
+ let response = input('mkdir: ', path, 'dir')
+ if response == '' || response == path
+ return
+ endif
+
+ " work around apparent vim bug attempting to create a dir with a trailing
+ " slash.
+ if response[-1:] == '/'
+ let response = response[:-2]
+ endif
+
+ call mkdir(response, 'p')
+ call eclim#tree#Refresh()
+endfunction " }}}
+
+function! s:AliasToPath(alias) " {{{
+ if exists('b:aliases')
+ let alias = ''
+ for alias in keys(b:aliases)
+ if alias != '' && a:alias =~ '^' . alias . '\>/'
+ return substitute(a:alias, '^' . alias . '/', b:aliases[alias], '')
+ endif
+ endfor
+ endif
+ return a:alias
+endfunction " }}}
+
+function! s:PathToAlias(path) " {{{
+ if exists('b:aliases')
+ let path = ''
+ for alias in keys(b:aliases)
+ let path = b:aliases[alias]
+ if alias != '' && a:path =~ '^' . path
+ return substitute(a:path, '^' . path, alias . '/', '')
+ endif
+ endfor
+ endif
+ return a:path
+endfunction " }}}
+
+function! s:Depth() " {{{
+ return len(split(eclim#tree#GetPath(), '/'))
+endfunction " }}}
+
+function! eclim#tree#ExpandDir() " {{{
+ let dir = eclim#tree#GetPath()
+
+ if !isdirectory(dir)
+ echo "Not a directory or directory may have been removed."
+ return
+ endif
+
+ let contents = eclim#tree#ListDir(dir)
+ let [dirs, files] = s:NormalizeEntries(contents)
+
+ if s:has_ls
+ call map(dirs, 'substitute(v:val, "@$", "", "")')
+ call map(files, 'substitute(v:val, "@$", "", "")')
+ endif
+
+ " filter files
+ let filtered = []
+ for file in files
+ if s:MatchesFilter(file)
+ call add(filtered, file)
+ endif
+ endfor
+ let files = filtered
+
+ " rewrite any special files (executables, symbolic links, etc).
+ call map(dirs, 's:RewriteSpecial(v:val)')
+ call map(files, 's:RewriteSpecial(v:val)')
+
+ call eclim#tree#WriteContents(dir, dirs, files)
+ if g:TreeExpandSingleDirs && len(files) == 0 && len(dirs) == 1 && s:Depth() < 50
+ TreeNextPrevLine j
+ call eclim#tree#ExpandDir()
+ endif
+endfunction " }}}
+
+function! eclim#tree#ExpandPath(name, path) " {{{
+ " Given the buffer name of a tree and a full path in that tree, either with an
+ " alias or real root path at the beginning, expand the tree node to reveal
+ " that path.
+
+ let winnr = winnr()
+ let treewin = bufwinnr(a:name)
+ if treewin == -1
+ return
+ endif
+
+ exec treewin . 'winc w'
+
+ let path = a:path
+ let root = ''
+ for r in b:roots
+ let r = substitute(r, '/$', '', '')
+ if path =~ '^' . r . '\>'
+ let root = r
+ break
+ endif
+ endfor
+
+ " try aliases
+ if root == ''
+ let path = substitute(path, '^/', '', '')
+ for r in keys(b:aliases)
+ if path =~ '^' . r . '\>'
+ let root = r
+ break
+ endif
+ endfor
+ endif
+
+ if root != ''
+ let path = substitute(path, '^' . root, '', '')
+ call cursor(1, 1)
+ for dir in split(path, '/')
+ call eclim#tree#MoveToLastChild()
+ let line = search('[+-] \<' . dir . '\>/', 'nbW')
+ if line
+ call eclim#tree#Cursor(line, 0)
+ if getline(line) =~ '^\s*+'
+ call eclim#tree#Execute(1)
+ endif
+ else
+ break
+ endif
+ endfor
+ endif
+
+ exec winnr . 'winc w'
+endfunction " }}}
+
+function! eclim#tree#WriteContents(dir, dirs, files) " {{{
+ let dirs = a:dirs
+ let files = a:files
+ let indent = eclim#tree#GetChildIndent(line('.'))
+ call map(dirs,
+ \ 'substitute(v:val, a:dir, indent . s:node_prefix . s:dir_closed_prefix, "")')
+ call map(files,
+ \ 'substitute(v:val, a:dir, indent . s:node_prefix . s:file_prefix, "")')
+
+ " update current line
+ call s:UpdateLine(s:node_prefix . s:dir_closed_prefix,
+ \ s:node_prefix . s:dir_opened_prefix)
+
+ setlocal noreadonly modifiable
+ let content = dirs + files
+ call append(line('.'), content)
+ setlocal nomodifiable
+ return content
+endfunction " }}}
+
+function! s:RewriteSpecial(file) " {{{
+ let file = a:file
+ if s:has_ls
+ let info = ''
+ let file = substitute(file, '@$', '', '')
+
+ " symbolic links
+ let tmpfile = file =~ '/$' ? strpart(file, 0, len(file) - 1) : file
+ if getftype(tmpfile) == 'link'
+ if info == ''
+ let info = eclim#util#System('ls -ldF ' . tmpfile)
+ endif
+ let linkto = substitute(info, '.*-> \(.*\)\n', '\1', '')
+
+ if linkto =~ '//$'
+ let linkto = strpart(linkto, 0, len(linkto) - 1)
+ endif
+
+ let file = tmpfile . ' -> ' . linkto
+ endif
+ endif
+
+ if exists('b:links')
+ if file =~ '/$'
+ let path = substitute(file, '/$', '', '')
+ let entry = substitute(path, eclim#tree#GetRoot(), '', '')
+ if has_key(b:links, entry)
+ let file = path . ' -> ' . get(b:links, entry)
+ let file = substitute(file, '\([^/]\)$', '\1/', '')
+ endif
+ endif
+ endif
+
+ return file
+endfunction " }}}
+
+function! s:CollapseDir() " {{{
+ " update current line
+ call s:UpdateLine(s:node_prefix . s:dir_opened_prefix,
+ \ s:node_prefix . s:dir_closed_prefix)
+
+ let lnum = line('.')
+ let cnum = col('.')
+ let start = lnum + 1
+ let end = eclim#tree#GetLastChildPosition()
+
+ if start > end
+ return
+ endif
+
+ setlocal noreadonly modifiable
+ silent exec start . ',' . end . 'delete _'
+ setlocal nomodifiable
+
+ call cursor(lnum, cnum)
+endfunction " }}}
+
+function! s:UnfoldDir() " {{{
+ foldopen
+endfunction " }}}
+
+function! s:FoldDir() " {{{
+ let start = line('.')
+ let end = eclim#tree#GetLastChildPosition()
+
+ exec start . ',' . end . 'fold'
+endfunction " }}}
+
+function! eclim#tree#ListDir(dir, ...) " {{{
+ " Optional args:
+ " execute_actions
+ if s:has_ls
+ let ls = 'ls -1F'
+ if b:view_hidden
+ let ls .= 'A'
+ endif
+ let contents = split(eclim#util#System(ls . " '" . a:dir . "'"), '\n')
+ if !b:view_hidden && &wildignore != ''
+ let pattern = substitute(escape(&wildignore, '.~'), '\*', '.*', 'g')
+ let pattern = '\(' . join(split(pattern, ','), '\|') . '\)$'
+ " Note: symlinks have a trailing @, so remove that before comparing
+ " against pattern
+ call filter(contents, 'substitute(v:val, "@$", "", "") !~ pattern')
+ endif
+ call map(contents, 'a:dir . v:val')
+ else
+ if !b:view_hidden
+ let contents = split(eclim#util#Globpath(escape(a:dir, ','), '*', 1), '\n')
+ else
+ let contents = split(eclim#util#Globpath(escape(a:dir, ','), '*'), '\n')
+ let contents = split(eclim#util#Globpath(escape(a:dir, ','), '.*'), '\n') + contents
+ endif
+
+ " append trailing '/' to dirs if necessary
+ call map(contents,
+ \ 'isdirectory(v:val) ? substitute(v:val, "\\([^/]\\)$", "\\1/", "") : v:val')
+ endif
+
+ if exists('b:dir_actions') && (!a:0 || a:1)
+ for l:Action in b:dir_actions
+ call l:Action(a:dir, contents)
+ endfor
+ endif
+
+ return contents
+endfunction " }}}
+
+function! s:GetIndent(line) " {{{
+ let indent = indent(a:line)
+ if getline(a:line) =~ s:file_prefix . '[.[:alnum:]_]' && s:file_prefix =~ '^\s*$'
+ let indent -= len(s:file_prefix)
+ endif
+ if s:node_prefix =~ '^\s*$'
+ let indent -= len(s:node_prefix)
+ endif
+
+ return indent
+endfunction " }}}
+
+function! s:GetLastLine() " {{{
+ let line = line('$')
+ while getline(line) =~ '^"\|^\s*$' && line > 1
+ let line -= 1
+ endwhile
+ return line
+endfunction " }}}
+
+function! eclim#tree#GetChildIndent(line) " {{{
+ let indent = ''
+ if getline(a:line) =~ '\s*' . s:node_prefix
+ let num = indent(a:line)
+
+ if s:node_prefix =~ '^\s*$'
+ let num -= len(s:node_prefix)
+ endif
+
+ let index = 0
+ while index < num + s:indent_length
+ let indent .= ' '
+ let index += 1
+ endwhile
+ endif
+
+ return indent
+endfunction " }}}
+
+function! s:MatchesFilter(file) " {{{
+ if len(b:filters) > 0
+ for filter in b:filters
+ if entry =~ filter
+ return 1
+ endif
+ endfor
+ return 0
+ endif
+
+ return 1
+endfunction " }}}
+
+function! s:IsHidden(path, ignore_pattern) " {{{
+ if !b:view_hidden
+ let path = a:path
+ if isdirectory(path)
+ let path = fnamemodify(path, ':h')
+ endif
+ let path = fnamemodify(path, ':t')
+ return path =~ '^\.' || (a:ignore_pattern != '' && path =~ a:ignore_pattern)
+ endif
+ return 0
+endfunction " }}}
+
+function! s:NormalizeEntries(dirs) " {{{
+ " normalize path separators
+ call map(a:dirs, 'substitute(v:val, "\\\\", "/", "g")')
+
+ let dirs = filter(copy(a:dirs),
+ \ 'v:val =~ "/$" || (v:val =~ "@$" && isdirectory(substitute(v:val, "@$", "", "")))')
+ let files = filter(copy(a:dirs), 'index(dirs, v:val) == -1')
+
+ return [dirs, files]
+endfunction " }}}
+
+function! s:UpdateLine(pattern, substitution) " {{{
+ let lnum = line('.')
+ let line = getline(lnum)
+ let line = substitute(line, a:pattern, a:substitution, '')
+
+ setlocal noreadonly modifiable
+ call append(lnum, line)
+ silent exec lnum . ',' . lnum . 'delete _'
+ setlocal nomodifiable
+endfunction " }}}
+
+function! eclim#tree#DisplayActionChooser(file, actions, executeFunc) " {{{
+ new
+ let height = len(a:actions) + 1
+
+ exec 'resize ' . height
+
+ setlocal noreadonly modifiable
+ let b:actions = a:actions
+ let b:file = a:file
+ for action in a:actions
+ call append(line('$'), action.name)
+ endfor
+
+ exec 'nnoremap <buffer> <silent> <cr> ' .
+ \ ':call eclim#tree#ActionExecute("' . a:executeFunc . '")<cr>'
+ nnoremap <buffer> q :q<cr>
+
+ exec "hi link TreeAction " . g:TreeActionHighlight
+ syntax match TreeAction /.*/
+
+ 1,1delete _
+ setlocal nomodifiable
+ setlocal noswapfile
+ setlocal buftype=nofile
+ setlocal bufhidden=delete
+endfunction "}}}
+
+function! eclim#tree#ActionExecute(executeFunc) " {{{
+ let command = ''
+ let line = getline('.')
+ for action in b:actions
+ if action.name == line
+ let command = action.action
+ break
+ endif
+ endfor
+
+ let file = b:file
+ close
+ call function(a:executeFunc)(file, command)
+endfunction "}}}
+
+function! s:Mappings() " {{{
+ nnoremap <buffer> <silent> <cr> :call eclim#tree#Execute(0)<cr>
+ nnoremap <buffer> <silent> o :call eclim#tree#Execute(1)<cr>
+
+ nnoremap <buffer> <silent> i :call eclim#util#Echo(
+ \ eclim#tree#GetFileInfo(eclim#tree#GetPath()))<cr>
+ nnoremap <buffer> <silent> I :call eclim#util#Echo(
+ \ eclim#tree#GetFileInfo(eclim#tree#GetPath()))<cr>
+
+ nnoremap <buffer> <silent> s :call eclim#tree#Shell(0)<cr>
+ nnoremap <buffer> <silent> S :call eclim#tree#Shell(1)<cr>
+
+ nnoremap <buffer> <silent> R :call eclim#tree#Refresh()<cr>
+
+ nnoremap <buffer> <silent> A :call eclim#tree#ToggleViewHidden()<cr>
+
+ nnoremap <buffer> <silent> ~ :call eclim#tree#SetRoot(eclim#UserHome())<cr>
+ nnoremap <buffer> <silent> C :call eclim#tree#SetRoot(eclim#tree#GetPath())<cr>
+ nnoremap <buffer> <silent> K :call eclim#tree#SetRoot(substitute(
+ \ <SID>PathToAlias(eclim#tree#GetRoot()),
+ \ '^\([^/]*/\).*', '\1', ''))<cr>
+ nnoremap <buffer> <silent> B :call eclim#tree#SetRoot(
+ \ fnamemodify(eclim#tree#GetRoot(), ':h:h'))<cr>
+
+ nnoremap <buffer> <silent> j :TreeNextPrevLine j<cr>
+ nnoremap <buffer> <silent> k :TreeNextPrevLine k<cr>
+ nnoremap <buffer> <silent> p :call eclim#tree#MoveToParent()<cr>
+ nnoremap <buffer> <silent> P :call eclim#tree#MoveToLastChild()<cr>
+
+ nnoremap <buffer> <silent> D :call eclim#tree#Mkdir()<cr>
+
+ let ctrl_l = escape(maparg('<c-l>'), '|')
+ exec 'nnoremap <buffer> <silent> <c-l> :silent doautocmd eclim_tree User <buffer><cr>' . ctrl_l
+
+ command! -nargs=1 -complete=dir -buffer CD :call eclim#tree#SetRoot('<args>')
+ command! -nargs=1 -complete=dir -buffer Cd :call eclim#tree#SetRoot('<args>')
+
+ " only needed as a command to support counts on the j/k mappings
+ command! -nargs=? -count=1 -buffer TreeNextPrevLine
+ \ let c = <count> |
+ \ let c = c > 1 ? c - line('.') + 1 : c |
+ \ let prev = line('.') |
+ \ exec 'normal! ' . c . '<args>' |
+ \ call eclim#tree#Cursor(line('.'), prev)
+endfunction " }}}
+
+function! eclim#tree#Syntax() " {{{
+ exec "hi link TreeDir " . g:TreeDirHighlight
+ exec "hi link TreeFile " . g:TreeFileHighlight
+ exec "hi link TreeFileExecutable " . g:TreeFileExecutableHighlight
+ hi link TreeMarker Normal
+ syntax match TreeMarker /^\s*[-+]/
+ syntax match TreeDir /\S.*\// contains=TreeMarker
+ syntax match TreeFile /\S.*[^\/]$/
+ syntax match TreeFileExecutable /\S.*[^\/]\*$/
+ syntax match Comment /^".*/
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/util.vim b/vim/eclim/autoload/eclim/util.vim
@@ -0,0 +1,1574 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+ let s:buffer_write_closing_commands = '^\s*\(' .
+ \ 'wq\|xa\|' .
+ \ '\d*w[nN]\|\d*wp\|' .
+ \ 'ZZ' .
+ \ '\)'
+
+ let s:bourne_shells = ['sh', 'bash', 'dash', 'ksh', 'zsh']
+ let s:c_shells = ['csh', 'tcsh']
+
+ let s:show_current_error_displaying = 0
+
+ let s:command_setting = '-command setting -s <setting>'
+" }}}
+
+" Balloon(message) {{{
+" Function for use as a vim balloonexpr expression.
+function! eclim#util#Balloon(message)
+ let message = a:message
+ if !has('balloon_multiline')
+ " remove any new lines
+ let message = substitute(message, '\n', ' ', 'g')
+ endif
+ return message
+endfunction " }}}
+
+" CompilerExists(compiler) {{{
+" Check whether a particular vim compiler is available.
+function! eclim#util#CompilerExists(compiler)
+ if !exists('s:compilers')
+ redir => compilers
+ silent compiler
+ redir END
+ let s:compilers = split(compilers, '\n')
+ call map(s:compilers, 'fnamemodify(v:val, ":t:r")')
+ endif
+ return index(s:compilers, a:compiler) != -1
+endfunction " }}}
+
+" DelayedCommand(command, [delay]) {{{
+" Executes a delayed command. Useful in cases where one would expect an
+" autocommand event (WinEnter, etc) to fire, but doesn't, or you need a
+" command to execute after other autocommands have finished.
+" Note: Nesting is not supported. A delayed command cannot be invoke off
+" another delayed command.
+function! eclim#util#DelayedCommand(command, ...)
+ let uid = fnamemodify(tempname(), ':t:r')
+ if &updatetime > 1
+ exec 'let g:eclim_updatetime_save' . uid . ' = &updatetime'
+ endif
+ exec 'let g:eclim_delayed_command' . uid . ' = a:command'
+ let &updatetime = len(a:000) ? a:000[0] : 1
+ exec 'augroup delayed_command' . uid
+ exec 'autocmd CursorHold * ' .
+ \ ' if exists("g:eclim_updatetime_save' . uid . '") | ' .
+ \ ' let &updatetime = g:eclim_updatetime_save' . uid . ' | ' .
+ \ ' unlet g:eclim_updatetime_save' . uid . ' | ' .
+ \ ' endif | ' .
+ \ ' exec g:eclim_delayed_command' . uid . ' | ' .
+ \ ' unlet g:eclim_delayed_command' . uid . ' | ' .
+ \ ' autocmd! delayed_command' . uid
+ exec 'augroup END'
+endfunction " }}}
+
+" EchoTrace(message, [time_elapsed]) {{{
+function! eclim#util#EchoTrace(message, ...)
+ if a:0 > 0
+ call s:EchoLevel('(' . a:1 . 's) ' . a:message, 6, g:EclimTraceHighlight)
+ else
+ call s:EchoLevel(a:message, 6, g:EclimTraceHighlight)
+ endif
+endfunction " }}}
+
+" EchoDebug(message) {{{
+function! eclim#util#EchoDebug(message)
+ call s:EchoLevel(a:message, 5, g:EclimDebugHighlight)
+endfunction " }}}
+
+" EchoInfo(message) {{{
+function! eclim#util#EchoInfo(message)
+ call s:EchoLevel(a:message, 4, g:EclimInfoHighlight)
+endfunction " }}}
+
+" EchoWarning(message) {{{
+function! eclim#util#EchoWarning(message)
+ call s:EchoLevel(a:message, 3, g:EclimWarningHighlight)
+endfunction " }}}
+
+" EchoError(message) {{{
+function! eclim#util#EchoError(message)
+ call s:EchoLevel(a:message, 2, g:EclimErrorHighlight)
+endfunction " }}}
+
+" EchoFatal(message) {{{
+function! eclim#util#EchoFatal(message)
+ call s:EchoLevel(a:message, 1, g:EclimFatalHighlight)
+endfunction " }}}
+
+" s:EchoLevel(message) {{{
+" Echos the supplied message at the supplied level with the specified
+" highlight.
+function! s:EchoLevel(message, level, highlight)
+ " don't echo if the message is 0, which signals an eclim#Execute failure.
+ if type(a:message) == g:NUMBER_TYPE && a:message == 0
+ return
+ endif
+
+ if g:EclimLogLevel < a:level
+ return
+ endif
+
+ if type(a:message) == g:LIST_TYPE
+ let messages = a:message
+ else
+ let messages = split(a:message, '\n')
+ endif
+
+ exec "echohl " . a:highlight
+ redraw
+ if mode() == 'n' || mode() == 'c'
+ " Note: in command mode, the message won't display, but the user can view
+ " it using :messages
+ for line in messages
+ echom line
+ endfor
+ else
+ " if we aren't in normal mode then use regular 'echo' since echom
+ " messages won't be displayed while the current mode is displayed in
+ " vim's command line.
+ echo join(messages, "\n") . "\n"
+ endif
+ echohl None
+endfunction " }}}
+
+" Echo(message) {{{
+" Echos a message using the info highlight regardless of what log level is set.
+function! eclim#util#Echo(message)
+ if a:message != "0" && g:EclimLogLevel > 0
+ exec "echohl " . g:EclimInfoHighlight
+ redraw
+ for line in split(a:message, '\n')
+ echom line
+ endfor
+ echohl None
+ endif
+endfunction " }}}
+
+" EscapeBufferName(name) {{{
+" Escapes the supplied buffer name so that it can be safely used by buf*
+" functions.
+function! eclim#util#EscapeBufferName(name)
+ let name = a:name
+ " escaping the space in cygwin could lead to the dos path error message that
+ " cygwin throws when a dos path is referenced.
+ if !has('win32unix')
+ let name = escape(a:name, ' ')
+ endif
+ return substitute(name, '\(.\{-}\)\[\(.\{-}\)\]\(.\{-}\)', '\1[[]\2[]]\3', 'g')
+endfunction " }}}
+
+" Exec(cmd [,output]) {{{
+" Used when executing ! commands that may be disrupted by non default vim
+" options.
+function! eclim#util#Exec(cmd, ...)
+ let exec_output = len(a:000) > 0 ? a:000[0] : 0
+ return eclim#util#System(a:cmd, 1, exec_output)
+endfunction " }}}
+
+" ExecWithoutAutocmds(cmd, [events]) {{{
+" Execute a command after disabling all autocommands (borrowed from taglist.vim)
+function! eclim#util#ExecWithoutAutocmds(cmd, ...)
+ let save_opt = &eventignore
+ let events = len(a:000) == 0 ? 'all' : a:000[0]
+ exec 'set eventignore=' . events
+ try
+ exec a:cmd
+ finally
+ let &eventignore = save_opt
+ endtry
+endfunction " }}}
+
+" FindFileInPath(file, exclude_relative) {{{
+" Searches for the supplied file in the &path.
+" If exclude_relative supplied is 1, then relative &path entries ('.' and '')
+" are not searched).
+function! eclim#util#FindFileInPath(file, exclude_relative)
+ let path = &path
+ if a:exclude_relative
+ " remove '' path entry
+ let path = substitute(path, '[,]\?[,]\?', '', 'g')
+ " remove '.' path entry
+ let path = substitute(path, '[,]\?\.[,]\?', '', 'g')
+ endif
+ return split(eclim#util#Globpath(path, "**/" . a:file), '\n')
+endfunction " }}}
+
+" Findfile(name, [path, count]) {{{
+" Used to issue a findfile() handling any vim options that may otherwise
+" disrupt it.
+function! eclim#util#Findfile(name, ...)
+ let savewig = &wildignore
+ set wildignore=""
+ if len(a:000) == 0
+ let result = findfile(a:name)
+ elseif len(a:000) == 1
+ let result = findfile(a:name, expand(escape(a:000[0], '*')))
+ elseif len(a:000) == 2
+ let result = findfile(a:name, expand(escape(a:000[0], '*')), a:000[1])
+ endif
+ let &wildignore = savewig
+
+ return result
+endfunction " }}}
+
+" GetEncoding() {{{
+" Gets the encoding of the current file.
+function! eclim#util#GetEncoding()
+ let encoding = &fileencoding
+ if encoding == ''
+ let encoding = &encoding
+ endif
+
+ " handle vim's compiled without multi-byte support
+ if encoding == ''
+ let encoding = 'utf-8'
+ endif
+
+ return encoding
+endfunction " }}}
+
+" GetOffset([line, col]) {{{
+" Gets the byte offset for the current cursor position or supplied line, col.
+function! eclim#util#GetOffset(...)
+ let lnum = a:0 > 0 ? a:000[0] : line('.')
+ let cnum = a:0 > 1 ? a:000[1] : col('.')
+ let offset = 0
+
+ " handle case where display encoding differs from the underlying file
+ " encoding
+ if &fileencoding != '' && &encoding != '' && &fileencoding != &encoding
+ let prev = lnum - 1
+ if prev > 0
+ let lineEnding = &ff == 'dos' ? "\r\n" : "\n"
+ " convert each line to the file encoding and sum their lengths
+ let offset = eval(
+ \ join(
+ \ map(
+ \ range(1, prev),
+ \ 'len(iconv(getline(v:val), &encoding, &fenc) . "' . lineEnding . '")'),
+ \ '+'))
+ endif
+
+ " normal case
+ else
+ let offset = line2byte(lnum) - 1
+ endif
+
+ let offset += cnum - 1
+ return offset
+endfunction " }}}
+
+" GetCurrentElementColumn() {{{
+" Gets the column for the element under the cursor.
+function! eclim#util#GetCurrentElementColumn()
+ let pos = getpos('.')
+
+ let line = getline('.')
+ " cursor not on the word
+ if line[col('.') - 1] =~ '\W'
+ silent normal! w
+
+ " cursor not at the beginning of the word
+ elseif line[col('.') - 2] =~ '\w'
+ silent normal! b
+ endif
+
+ let col = col('.')
+
+ " restore the cursor position.
+ call setpos('.', pos)
+
+ return col
+endfunction " }}}
+
+" GetCurrentElementPosition() {{{
+" Gets the byte offset and length for the element under the cursor.
+function! eclim#util#GetCurrentElementPosition()
+ let offset = eclim#util#GetCurrentElementOffset()
+ let word = expand('<cword>')
+
+ return offset . ";" . strlen(word)
+endfunction " }}}
+
+" GetCurrentElementOffset() {{{
+" Gets the byte offset for the element under the cursor.
+function! eclim#util#GetCurrentElementOffset()
+ let pos = getpos('.')
+
+ let line = getline('.')
+ " cursor not on the word
+ if line[col('.') - 1] =~ '\W'
+ silent normal! w
+
+ " cursor not at the beginning of the word
+ elseif line[col('.') - 2] =~ '\w'
+ silent normal! b
+ endif
+
+ let offset = eclim#util#GetOffset()
+
+ " restore the cursor position.
+ call setpos('.', pos)
+
+ return offset
+endfunction " }}}
+
+" GetIndent(level) {{{
+" Gets an indentation string for the supplied indentation level.
+function! eclim#util#GetIndent(level)
+ let result = ''
+
+ if a:level
+ if !exists('b:eclim_indent')
+ if exists('g:EclimIndent')
+ let b:eclim_indent = g:EclimIndent
+ else
+ if !&expandtab
+ let b:eclim_indent = "\t"
+ else
+ let b:eclim_indent = ''
+ let index = 0
+ while index < &shiftwidth
+ let b:eclim_indent = b:eclim_indent . " "
+ let index = index + 1
+ endwhile
+ endif
+ endif
+ endif
+
+ let num = a:level
+ while num > 0
+ let result .= b:eclim_indent
+ let num -= 1
+ endwhile
+ endif
+
+ return result
+endfunction " }}}
+
+" GetLineError(line) {{{
+" Gets the error (or message) for the supplie line number if one.
+function! eclim#util#GetLineError(line)
+ let line = line('.')
+ let col = col('.')
+
+ let errornum = 0
+ let errorcol = 0
+ let index = 0
+
+ let locerrors = getloclist(0)
+ let qferrors = getqflist()
+ let bufname = expand('%')
+ let lastline = line('$')
+ for error in qferrors + locerrors
+ let index += 1
+ if bufname(error.bufnr) == bufname &&
+ \ (error.lnum == line || (error.lnum > lastline && line == lastline))
+ if errornum == 0 || (col >= error.col && error.col != errorcol)
+ let errornum = index
+ let errorcol = error.col
+ endif
+ endif
+ endfor
+
+ if errornum > 0
+ let src = 'qf'
+ let cnt = len(qferrors)
+ let errors = qferrors
+ if errornum > cnt
+ let errornum -= cnt
+ let src = 'loc'
+ let cnt = len(locerrors)
+ let errors = locerrors
+ endif
+
+ let message = src . ' - (' . errornum . ' of ' . cnt . '): '
+ \ . substitute(errors[errornum - 1].text, '^\s\+', '', '')
+ return message
+ endif
+ return ''
+endfunction " }}}
+
+" GetPathEntry(file) {{{
+" Returns the path entry that contains the supplied file (excluding '.' and '').
+" The argument must be an absolute path to the file.
+" &path is expected to be using commas for path delineation.
+" Returns 0 if no path found.
+function! eclim#util#GetPathEntry(file)
+ let paths = split(&path, ',')
+ for path in paths
+ if path != "" && path != "."
+ let path = substitute(expand(path), '\', '/', 'g')
+ let file = substitute(expand(a:file), '\', '/', 'g')
+ if file =~ '^' . path
+ return path
+ endif
+ endif
+ endfor
+ return 0
+endfunction " }}}
+
+" GetSetting(setting, [workspace]) {{{
+" Gets a global setting from eclim. Returns '' if the setting does not
+" exist, 0 if an error occurs communicating with the server.
+function! eclim#util#GetSetting(setting, ...)
+ let command = s:command_setting
+ let command = substitute(command, '<setting>', a:setting, '')
+
+ let workspace = a:0 > 0 ? a:1 : ''
+ let result = eclim#Execute(command, {'workspace': workspace})
+ if result == '0'
+ return result
+ endif
+
+ if result == ''
+ call eclim#util#EchoWarning("Setting '" . a:setting . "' does not exist.")
+ endif
+ return result
+endfunction " }}}
+
+" GetVisualSelection(line1, line2, default) {{{
+" Returns the contents of, and then clears, the last visual selection.
+" If default is set, the default range will be honor.
+function! eclim#util#GetVisualSelection(line1, line2, default)
+ let lines = a:default ? getline(a:line1, a:line2) : []
+ let mode = visualmode(1)
+ if mode != '' && line("'<") == a:line1
+ if len(lines) == 0
+ let lines = getline(a:line1, a:line2)
+ endif
+ if mode == "v"
+ let start = col("'<") - 1
+ let end = col("'>") - 1
+ " slice in end before start in case the selection is only one line
+ let lines[-1] = lines[-1][: end]
+ let lines[0] = lines[0][start :]
+ elseif mode == "\<c-v>"
+ let start = col("'<")
+ if col("'>") < start
+ let start = col("'>")
+ endif
+ let start = start - 1
+ call map(lines, 'v:val[start :]')
+ endif
+ endif
+ return join(lines, "\n")
+endfunction " }}}
+
+" Glob(expr, [honor_wildignore]) {{{
+" Used to issue a glob() handling any vim options that may otherwise disrupt
+" it.
+function! eclim#util#Glob(expr, ...)
+ if len(a:000) == 0
+ let savewig = &wildignore
+ set wildignore=""
+ endif
+
+ let paths = split(a:expr, '\n')
+ if len(paths) == 1
+ let result = glob(paths[0])
+ else
+ let result = join(paths, "\n")
+ endif
+
+ if len(a:000) == 0
+ let &wildignore = savewig
+ endif
+
+ return result
+endfunction " }}}
+
+" Globpath(path, expr, [honor_wildignore]) {{{
+" Used to issue a globpath() handling any vim options that may otherwise disrupt
+" it.
+function! eclim#util#Globpath(path, expr, ...)
+ if len(a:000) == 0
+ let savewig = &wildignore
+ set wildignore=""
+ endif
+
+ let result = globpath(a:path, a:expr)
+
+ if len(a:000) == 0
+ let &wildignore = savewig
+ endif
+
+ return result
+endfunction " }}}
+
+" GoToBufferWindow(buf) {{{
+" Focuses the window containing the supplied buffer name or buffer number.
+" Returns 1 if the window was found, 0 otherwise.
+function! eclim#util#GoToBufferWindow(buf)
+ if type(a:buf) == g:NUMBER_TYPE
+ let winnr = bufwinnr(a:buf)
+ else
+ let name = eclim#util#EscapeBufferName(a:buf)
+ let winnr = bufwinnr(bufnr('^' . name . '$'))
+ endif
+ if winnr != -1
+ exec winnr . "winc w"
+ call eclim#util#DelayedCommand('doautocmd WinEnter')
+ return 1
+ endif
+ return 0
+endfunction " }}}
+
+" GoToBufferWindowOrOpen(name, cmd) {{{
+" Gives focus to the window containing the buffer for the supplied file, or if
+" none, opens the file using the supplied command.
+function! eclim#util#GoToBufferWindowOrOpen(name, cmd)
+ let name = eclim#util#EscapeBufferName(a:name)
+ let winnr = bufwinnr(bufnr('^' . name . '$'))
+ if winnr != -1
+ exec winnr . "winc w"
+ call eclim#util#DelayedCommand('doautocmd WinEnter')
+ else
+ let cmd = a:cmd
+ " if splitting and the buffer is a unamed empty buffer, then switch to an
+ " edit.
+ if cmd == 'split' && expand('%') == '' &&
+ \ !&modified && line('$') == 1 && getline(1) == ''
+ let cmd = 'edit'
+ endif
+ silent exec cmd . ' ' . escape(eclim#util#Simplify(a:name), ' ')
+ endif
+endfunction " }}}
+
+" GoToBufferWindowRegister(buf) {{{
+" Registers the autocmd for returning the user to the supplied buffer when the
+" current buffer is closed.
+function! eclim#util#GoToBufferWindowRegister(buf)
+ exec 'autocmd BufWinLeave <buffer> ' .
+ \ 'call eclim#util#GoToBufferWindow("' . escape(a:buf, '\') . '") | ' .
+ \ 'doautocmd BufEnter'
+endfunction " }}}
+
+" GrabUri([line, col]) {{{
+" Grabs an uri from the file's current cursor position.
+function! eclim#util#GrabUri(...)
+ if len(a:000) == 2
+ let lnum = a:000[0]
+ let cnum = a:000[1]
+ else
+ let lnum = line('.')
+ let cnum = col('.')
+ endif
+ let line = getline(lnum)
+ let uri = substitute(line,
+ \ "\\(.*[[:space:]\"',(\\[{><]\\|^\\)\\(.*\\%" .
+ \ cnum . "c.\\{-}\\)\\([[:space:]\"',)\\]}<>].*\\|$\\)",
+ \ '\2', '')
+
+ return uri
+endfunction " }}}
+
+" ListContains(list, element) {{{
+" Returns 1 if the supplied list contains the specified element, 0 otherwise.
+" To determine element equality both '==' and 'is' are tried as well as
+" ^element$ to support a regex supplied element string.
+function! eclim#util#ListContains(list, element)
+ let string = type(a:element) == g:STRING_TYPE ?
+ \ a:element : escape(string(a:element), '\')
+ for element in a:list
+ if element is a:element ||
+ \ (type(element) == type(a:element) && element == a:element)
+ return 1
+ else
+ let estring = type(element) == g:STRING_TYPE ? element : string(element)
+ if estring =~ '^' . string . '$'
+ return 1
+ endif
+ endif
+ endfor
+ return 0
+endfunction " }}}
+
+function! eclim#util#Make(bang, args) " {{{
+ " Executes make using the supplied arguments.
+
+ " tpope/vim-rake/plugin/rake.vim will execute :Make if it exists, so mimic
+ " Rake's behavior here if that's the case.
+ if b:current_compiler == 'rake'
+ " See tpope/vim-rage/plugin/rake.vim s:Rake(bang,arg)
+ exec 'make! ' . a:args
+ if a:bang !=# '!'
+ exec 'cwindow'
+ endif
+ return
+ endif
+ let makefile = findfile('makefile', '.;')
+ let makefile2 = findfile('Makefile', '.;')
+ if len(makefile2) > len(makefile)
+ let makefile = makefile2
+ endif
+ let cwd = getcwd()
+ let save_mlcd = g:EclimMakeLCD
+ exec 'lcd ' . fnamemodify(makefile, ':h')
+ let g:EclimMakeLCD = 0
+ try
+ call eclim#util#MakeWithCompiler('eclim_make', a:bang, a:args)
+ finally
+ exec 'lcd ' . escape(cwd, ' ')
+ let g:EclimMakeLCD = save_mlcd
+ endtry
+endfunction " }}}
+
+" MakeWithCompiler(compiler, bang, args) {{{
+" Executes :make using the supplied compiler.
+" Note: on windows the make program will be executed manually if the 'tee'
+" progam is available (only the cygwin version is currenty supported) to allow
+" the display of the make program output while running.
+function! eclim#util#MakeWithCompiler(compiler, bang, args, ...)
+ if exists('g:current_compiler')
+ let saved_compiler = g:current_compiler
+ endif
+ if exists('b:current_compiler')
+ let saved_compiler = b:current_compiler
+ endif
+ if !exists('saved_compiler')
+ let saved_makeprg = &makeprg
+ let saved_errorformat = &errorformat
+ endif
+ if has('win32') || has('win64')
+ let saved_shellpipe = &shellpipe
+ set shellpipe=>\ %s\ 2<&1
+ endif
+
+ try
+ unlet! g:current_compiler b:current_compiler
+ exec 'compiler ' . a:compiler
+ let make_cmd = substitute(&makeprg, '\$\*', a:args, '')
+
+ if g:EclimMakeLCD
+ let w:quickfix_dir = getcwd()
+ let dir = eclim#project#util#GetCurrentProjectRoot()
+ if dir != ''
+ exec 'lcd ' . escape(dir, ' ')
+ endif
+ endif
+
+ " windows machines where 'tee' is available
+ if (has('win32') || has('win64')) && (executable('tee') || executable('wtee'))
+ doautocmd QuickFixCmdPre make
+ let resultfile = eclim#util#Exec(make_cmd, 2)
+ if filereadable(resultfile)
+ if a:bang == ''
+ exec 'cfile ' . escape(resultfile, ' ')
+ else
+ exec 'cgetfile ' . escape(resultfile, ' ')
+ endif
+ call delete(resultfile)
+ endif
+ silent doautocmd QuickFixCmdPost make
+
+ " all other platforms
+ else
+ call eclim#util#EchoTrace('make: ' . make_cmd)
+ exec 'make' . a:bang . ' ' . a:args
+ endif
+ catch /E42\>/
+ " ignore 'E42: No Errors' which occurs when the make has qf results, but a
+ " QuickFixCmdPost filters them all out.
+ finally
+ if exists('saved_compiler')
+ unlet! g:current_compiler b:current_compiler
+ exec 'compiler ' . saved_compiler
+ unlet saved_compiler
+ else
+ let &makeprg = saved_makeprg
+ let &errorformat = saved_errorformat
+ endif
+ if has('win32') || has('win64')
+ let &shellpipe = saved_shellpipe
+ endif
+ if exists('w:quickfix_dir')
+ exec 'lcd ' . escape(w:quickfix_dir, ' ')
+ unlet w:quickfix_dir
+ endif
+ endtry
+endfunction " }}}
+
+" MarkRestore(markLine) {{{
+" Restores the ' mark with the new line.
+function! eclim#util#MarkRestore(markLine)
+ let pos = getpos('.')
+ call cursor(a:markLine, s:markCol)
+ mark '
+ call setpos('.', pos)
+endfunction " }}}
+
+" MarkSave() {{{
+" Saves the ' mark and returns the line.
+function! eclim#util#MarkSave()
+ let s:markCol = col("'`")
+ return line("''")
+endfunction " }}}
+
+" Pad(string, length, [char]) {{{
+" Pad the supplied string.
+function! eclim#util#Pad(string, length, ...)
+ let char = a:0 > 0 ? a:1 : ' '
+
+ let string = a:string
+ while len(string) < a:length
+ let string .= char
+ endwhile
+ return string
+endfunction " }}}
+
+" ParseArgs(args) {{{
+" Parses the supplied argument line into a list of args, handling quoted
+" strings, escaped spaces, etc.
+function! eclim#util#ParseArgs(args)
+ let args = []
+ let arg = ''
+ let quote = ''
+ let escape = 0
+ let index = 0
+ while index < len(a:args)
+ let char = a:args[index]
+ let index += 1
+ if char == ' ' && quote == '' && !escape
+ if arg != ''
+ call add(args, arg)
+ let arg = ''
+ endif
+ elseif char == '\'
+ if escape
+ let arg .= char
+ endif
+ let escape = !escape
+ elseif char == '"' || char == "'"
+ if !escape
+ if quote != '' && char == quote
+ let quote = ''
+ elseif quote == ''
+ let quote = char
+ else
+ let arg .= char
+ endif
+ else
+ let arg .= char
+ let escape = 0
+ endif
+ else
+ if escape && char != ' '
+ let arg .= '\'
+ endif
+ let arg .= char
+ let escape = 0
+ endif
+ endwhile
+
+ if arg != ''
+ call add(args, arg)
+ endif
+
+ return args
+endfunction " }}}
+
+" ParseLocationEntries(entries, [sort]) {{{
+" Parses the supplied list of location entry lines (%f|%l col %c|%m) into a
+" vim compatable list of dictionaries that can be passed to setqflist() or
+" setloclist().
+" In addition to the above line format, this function also supports
+" %f|%l col %c|%m|%s, where %s is the type of the entry. The value will
+" be placed in the dictionary under the 'type' key.
+" The optional 'sort' parameter currently only supports 'severity' as an
+" argument.
+function! eclim#util#ParseLocationEntries(entries, ...)
+ if len(a:000) > 0 && a:1 == 'severity'
+ let entries = {}
+ else
+ let entries = []
+ endif
+
+ for entry in a:entries
+ let dict = s:ParseLocationEntry(entry)
+
+ " partition by severity
+ if type(entries) == g:DICT_TYPE
+ " empty key not allowed
+ let type = dict.type == '' ? ' ' : tolower(dict.type)
+ if !has_key(entries, type)
+ let entries[type] = []
+ endif
+ call add(entries[type], dict)
+
+ " default sort
+ else
+ call add(entries, dict)
+ endif
+ endfor
+
+ " re-assemble severity partitioned results
+ if type(entries) == g:DICT_TYPE
+ let results = []
+ if has_key(entries, 'e')
+ let results += remove(entries, 'e')
+ endif
+ if has_key(entries, 'w')
+ let results += remove(entries, 'w')
+ endif
+ if has_key(entries, 'i')
+ let results += remove(entries, 'i')
+ endif
+ " should only be key '' (no type), but we don't want to accidentally
+ " filter out other possible types.
+ let keys = keys(entries)
+ call reverse(sort(keys))
+ for key in keys
+ let results += entries[key]
+ endfor
+ return results
+ endif
+
+ return entries
+endfunction " }}}
+
+" s:ParseLocationEntry(entry) {{{
+function! s:ParseLocationEntry(entry)
+ let entry = a:entry
+ if type(entry) == g:DICT_TYPE
+ let file = entry.filename
+ let line = entry.line
+ let col = entry.column
+ let message = entry.message
+ let type = ''
+ if has_key(entry, 'warning')
+ let type = entry.warning ? 'w' : 'e'
+ endif
+
+ " FIXME: should be safe to remove this block after all commands have gone
+ " through the json conversion.
+ else
+ let file = substitute(entry, '\(.\{-}\)|.*', '\1', '')
+ let line = substitute(entry, '.*|\([0-9]\+\) col.*', '\1', '')
+ let col = substitute(entry, '.*col \([0-9]\+\)|.*', '\1', '')
+ let message = substitute(entry, '.*col [0-9]\+|\(.\{-}\)\(|.*\|$\)', '\1', '')
+ let type = substitute(entry, '.*|\(e\|w\)$', '\1', '')
+ if type == entry
+ let type = ''
+ endif
+ endif
+
+ if has('win32unix')
+ let file = eclim#cygwin#CygwinPath(file)
+ endif
+
+ let dict = {
+ \ 'filename': eclim#util#Simplify(file),
+ \ 'lnum': line,
+ \ 'col': col,
+ \ 'text': message,
+ \ 'type': type
+ \ }
+
+ return dict
+endfunction " }}}
+
+" Prompt(prompt, [validator], [highlight]) {{{
+" Creates a prompt for the user using the supplied prompt string, validator
+" and highlight. The prompt can be either a just a string to be displayed to
+" the user or a 2 item list where the first item is the prompt and the second
+" is the defaut value. The validator may return 0 to indicate an invalid input
+" or a message indicating why the input is invalid, which will be displayed to
+" the user. The validator should return 1 or the empty string to indicate
+" valid input. Returns an empty string if the user doesn't enter a value or
+" cancels the prompt.
+function! eclim#util#Prompt(prompt, ...)
+ " for unit testing
+ if exists('g:EclimTestPromptQueue') && len(g:EclimTestPromptQueue)
+ return remove(g:EclimTestPromptQueue, 0)
+ endif
+
+ let highlight = g:EclimInfoHighlight
+ if a:0 > 0
+ if type(a:1) == g:FUNCREF_TYPE
+ let Validator = a:1
+ elseif type(a:1) == g:STRING_TYPE
+ let highlight = a:1
+ endif
+ endif
+
+ if a:0 > 1
+ if type(a:2) == g:FUNCREF_TYPE
+ let Validator = a:2
+ elseif type(a:2) == g:STRING_TYPE
+ let highlight = a:2
+ endif
+ endif
+
+ if type(a:prompt) == g:LIST_TYPE
+ let prompt = a:prompt[0]
+ let default = a:prompt[1]
+ else
+ let prompt = a:prompt
+ endif
+
+ exec "echohl " . highlight
+ try
+ if exists('l:default')
+ let result = input(prompt . ': ', default)
+ else
+ let result = input(prompt . ': ')
+ endif
+ while result != ''
+ if exists('l:Validator')
+ let valid = Validator(result)
+ if type(valid) == g:STRING_TYPE && valid != ''
+ let result = input(valid . " (Ctrl-C to cancel): ", result)
+ elseif type(valid) == g:NUMBER_TYPE && !valid
+ let result = input(prompt, result)
+ else
+ return result
+ endif
+ else
+ return result
+ endif
+ endwhile
+ finally
+ echohl None
+ endtry
+
+ return result
+endfunction " }}}
+
+" PromptList(prompt, list, [highlight]) {{{
+" Creates a prompt for the user using the supplied prompt string and list of
+" items to choose from. Returns -1 if the list is empty or if the user
+" canceled, and 0 if the list contains only one item.
+function! eclim#util#PromptList(prompt, list, ...)
+ " for unit testing
+ if exists('g:EclimTestPromptQueue') && len(g:EclimTestPromptQueue)
+ return remove(g:EclimTestPromptQueue, 0)
+ endif
+
+ " no elements, no prompt
+ if empty(a:list)
+ return -1
+ endif
+
+ " only one elment, no need to choose.
+ if len(a:list) == 1
+ return 0
+ endif
+
+ let prompt = ""
+ let index = 0
+ for item in a:list
+ let prompt = prompt . index . ") " . item . "\n"
+ let index = index + 1
+ endfor
+
+ exec "echohl " . (a:0 ? a:1 : g:EclimInfoHighlight)
+ try
+ " clear any previous messages
+ redraw
+ try
+ let response = input(prompt . "\n" . a:prompt . ": ")
+ catch
+ " echoing the list prompt vs. using it in the input() avoids apparent vim
+ " bug that causes "Internal error: get_tv_string_buf()".
+ echo prompt . "\n"
+ let response = input(a:prompt . ": ")
+ endtry
+ while response !~ '\(^$\|^[0-9]\+$\)' ||
+ \ response < 0 ||
+ \ response > (len(a:list) - 1)
+ let response = input("You must choose a value between " .
+ \ 0 . " and " . (len(a:list) - 1) . ". (Ctrl-C to cancel): ")
+ endwhile
+ finally
+ echohl None
+ redraw!
+ endtry
+
+ if response == ''
+ return -1
+ endif
+
+ return response
+endfunction " }}}
+
+" PromptConfirm(prompt, [highlight]) {{{
+" Creates a yes/no prompt for the user using the supplied prompt string.
+" Returns -1 if the user canceled, otherwise 1 for yes, and 0 for no.
+function! eclim#util#PromptConfirm(prompt, ...)
+ " for unit testing
+ if exists('g:EclimTestPromptQueue') && len(g:EclimTestPromptQueue)
+ let choice = remove(g:EclimTestPromptQueue, 0)
+ return choice =~ '\c\s*\(y\(es\)\?\)\s*'
+ endif
+
+ exec "echohl " . (a:0 ? a:1 : g:EclimInfoHighlight)
+ try
+ " clear any previous messages
+ redraw
+ echo a:prompt . "\n"
+ let response = input("(y/n): ")
+ while response != '' && response !~ '^\c\s*\(y\(es\)\?\|no\?\|\)\s*$'
+ let response = input("You must choose either y or n. (Ctrl-C to cancel): ")
+ endwhile
+ finally
+ echohl None
+ endtry
+
+ if response == ''
+ return -1
+ endif
+
+ return response =~ '\c\s*\(y\(es\)\?\)\s*'
+endfunction " }}}
+
+function! eclim#util#Reload(options) " {{{
+ " Reload the current file using ':edit' and perform other operations based on
+ " the options supplied.
+ " Supported Options:
+ " retab: Issue a retab of the file.
+ " pos: A line/column pair indicating the new cursor position post edit. When
+ " this pair is supplied, this function will attempt to preserve the
+ " current window's viewport.
+
+ let winview = winsaveview()
+ " save expand tab in case an indent detection plugin changes it based on code
+ " inserted by eclipse, which may not yet match the user's actual settings.
+ let save_expandtab = &expandtab
+
+ edit!
+
+ let &expandtab = save_expandtab
+
+ if has_key(a:options, 'pos') && len(a:options.pos) == 2
+ let lnum = a:options.pos[0]
+ let cnum = a:options.pos[1]
+ if winheight(0) < line('$')
+ let winview.topline += lnum - winview.lnum
+ let winview.lnum = lnum
+ let winview.col = cnum - 1
+ call winrestview(winview)
+ else
+ call cursor(lnum, cnum)
+ endif
+ endif
+
+ if has_key(a:options, 'retab') && a:options.retab && &expandtab
+ " set tabstop to the same value as shiftwidth if we may be expanding tabs
+ let save_tabstop = &tabstop
+ let &tabstop = &shiftwidth
+
+ try
+ retab
+ finally
+ let &tabstop = save_tabstop
+ endtry
+ endif
+endfunction " }}}
+
+function! eclim#util#SetLocationList(list, ...) " {{{
+ " Sets the contents of the location list for the current window.
+ " Optional args:
+ " action: The action passed to the setloclist() function call.
+ let loclist = a:list
+
+ " filter the list if the current buffer defines a list of filters.
+ if exists('b:EclimLocationListFilter')
+ let newlist = []
+ for item in loclist
+ let addit = 1
+
+ for filter in b:EclimLocationListFilter
+ if item.text =~ filter
+ let addit = 0
+ break
+ endif
+ endfor
+
+ if addit
+ call add(newlist, item)
+ endif
+ endfor
+ let loclist = newlist
+ endif
+
+ if a:0 == 0
+ call setloclist(0, loclist)
+ else
+ call setloclist(0, loclist, a:1)
+ endif
+
+ silent let projectName = eclim#project#util#GetCurrentProjectName()
+ if projectName != ''
+ " setbufvar seems to have the side affect of changing to the buffer's dir
+ " when autochdir is set.
+ let save_autochdir = &autochdir
+ set noautochdir
+
+ for item in getloclist(0)
+ call setbufvar(item.bufnr, 'eclim_project', projectName)
+ endfor
+
+ let &autochdir = save_autochdir
+ endif
+
+ if g:EclimShowCurrentError && len(loclist) > 0
+ call eclim#util#DelayedCommand('call eclim#util#ShowCurrentError()')
+ endif
+
+ let b:eclim_loclist = 1
+ call eclim#display#signs#Update()
+endfunction " }}}
+
+" ClearLocationList([namespace, namespace, ...]) {{{
+" Clears the current location list. Optionally 'namespace' arguments can be
+" supplied which will only clear items with text prefixed with '[namespace]'.
+" Also the special namespace 'global' may be supplied which will only remove
+" items with no namepace prefix.
+function! eclim#util#ClearLocationList(...)
+ if a:0 > 0
+ let loclist = getloclist(0)
+ if len(loclist) > 0
+ let pattern = ''
+ for ns in a:000
+ if pattern != ''
+ let pattern .= '\|'
+ endif
+ if ns == 'global'
+ let pattern .= '\(\[\w\+\]\)\@!'
+ else
+ let pattern .= '\[' . ns . '\]'
+ endif
+ endfor
+ let pattern = '^\(' . pattern . '\)'
+
+ call filter(loclist, 'v:val.text !~ pattern')
+ call setloclist(0, loclist, 'r')
+ endif
+ else
+ call setloclist(0, [], 'r')
+ endif
+ call eclim#display#signs#Update()
+ unlet! b:eclim_loclist
+endfunction " }}}
+
+" SetQuickfixList(list, [action]) {{{
+" Sets the contents of the quickfix list.
+function! eclim#util#SetQuickfixList(list, ...)
+ let qflist = a:list
+ if exists('b:EclimQuickfixFilter')
+ let newlist = []
+ for item in qflist
+ let addit = 1
+
+ for filter in b:EclimQuickfixFilter
+ if item.text =~ filter
+ let addit = 0
+ break
+ endif
+ endfor
+
+ if addit
+ call add(newlist, item)
+ endif
+ endfor
+ let qflist = newlist
+ endif
+ if a:0 == 0
+ call setqflist(qflist)
+ else
+ call setqflist(qflist, a:1)
+ endif
+ if g:EclimShowCurrentError && len(qflist) > 0
+ call eclim#util#DelayedCommand('call eclim#util#ShowCurrentError()')
+ endif
+ call eclim#display#signs#Update()
+endfunction " }}}
+
+" ShowCurrentError() {{{
+" Shows the error on the cursor line if one.
+function! eclim#util#ShowCurrentError()
+ if mode() != 'n' || expand('%') == ''
+ return
+ endif
+
+ let message = eclim#util#GetLineError(line('.'))
+ if message != ''
+ " remove any new lines
+ let message = substitute(message, '\n', ' ', 'g')
+ " convert tabs to spaces to ensure a consistent char to display length
+ let message = substitute(message, '\t', ' ', 'g')
+
+ call eclim#util#WideMessage('echo', message)
+ let s:show_current_error_displaying = 1
+ else
+ " clear the message if one of our error messages was displaying
+ if s:show_current_error_displaying
+ call eclim#util#WideMessage('echo', message)
+ let s:show_current_error_displaying = 0
+ endif
+ endif
+endfunction " }}}
+
+" Simplify(file) {{{
+" Simply the supplied file to the shortest valid name.
+function! eclim#util#Simplify(file)
+ let file = a:file
+
+ " Don't run simplify on url files, it will screw them up.
+ if file !~ '://'
+ let file = simplify(file)
+ endif
+
+ " replace all '\' chars with '/' except those escaping spaces.
+ let file = substitute(file, '\\\([^[:space:]]\)', '/\1', 'g')
+ let cwd = substitute(getcwd(), '\', '/', 'g')
+ if cwd !~ '/$'
+ let cwd .= '/'
+ endif
+
+ if file =~ '^' . cwd
+ let file = substitute(file, '^' . cwd, '', '')
+ endif
+
+ return file
+endfunction " }}}
+
+" System(cmd, [exec, exec_results]) {{{
+" Executes system() accounting for possibly disruptive vim options.
+" exec (0 or 1): whether or not to use exec instead of system
+" exec_results (0, 1, or 2): 0 to not return the results of an exec, 1 to
+" return the results, or 2 to return the filename containing the results.
+function! eclim#util#System(cmd, ...)
+ let saveshell = &shell
+ let saveshellcmdflag = &shellcmdflag
+ let saveshellpipe = &shellpipe
+ let saveshellquote = &shellquote
+ let saveshellredir = &shellredir
+ let saveshellslash = &shellslash
+ let saveshelltemp = &shelltemp
+ let saveshellxquote = &shellxquote
+
+ if has("win32") || has("win64")
+ set shell=cmd.exe
+ set shellcmdflag=/c
+ set shellpipe=>%s\ 2>&1
+ set shellquote=
+ set shellredir=>%s\ 2>&1
+ set noshellslash
+ set shelltemp
+ set shellxquote=
+ else
+ if executable('/bin/bash')
+ set shell=/bin/bash
+ else
+ set shell=/bin/sh
+ endif
+ set shellcmdflag=-c
+ set shellpipe=2>&1\|\ tee
+ set shellquote=
+ set shellredir=>%s\ 2>&1
+ set noshellslash
+ set shelltemp
+ set shellxquote=
+ endif
+
+ try
+ " use exec
+ if len(a:000) > 0 && a:000[0]
+ let cmd = a:cmd
+ let begin = localtime()
+ let exec_output = len(a:000) > 1 ? a:000[1] : 0
+ if exec_output
+ let outfile = g:EclimTempDir . '/eclim_exec_output.txt'
+ if has('win32') || has('win64') || has('win32unix')
+ let cmd = substitute(cmd, '^!', '', '')
+ if has('win32unix')
+ let cmd = '!cmd /c "' . cmd . ' 2>&1 " | tee "' . outfile . '"'
+ elseif executable('tee') || executable('wtee')
+ let tee = executable('wtee') ? 'wtee' : 'tee'
+ let cmd = '!cmd /c "' . cmd . ' 2>&1 | ' . tee . ' "' . outfile . '" "'
+ else
+ let cmd = '!cmd /c "' . cmd . ' >"' . outfile . '" 2>&1 "'
+ endif
+ else
+ let cmd .= ' 2>&1| tee "' . outfile . '"'
+ endif
+ endif
+
+ try
+ exec cmd
+ finally
+ call eclim#util#EchoTrace('exec: ' . cmd, localtime() - begin)
+ endtry
+
+ let result = ''
+ if exec_output == 1 && filereadable(outfile)
+ let result = join(readfile(outfile), "\n")
+ call delete(outfile)
+ elseif exec_output == 2
+ let result = outfile
+ endif
+
+ " use system
+ else
+ let begin = localtime()
+ let cmd = a:cmd
+ try
+ " Dos is pretty bad at dealing with quoting of commands resulting in
+ " eclim calls failing if the path to the eclim bat/cmd file is quoted
+ " and there is a quoted arg in that command as well. We can fix this
+ " by wrapping the whole command in quotes with a space between the
+ " quotes and the actual command.
+ if (has('win32') || has('win64')) && a:cmd =~ '^"'
+ let cmd = '" ' . cmd . ' "'
+ " same issue, but handle the fact that we prefix eclim calls with
+ " 'cmd /c' for cygwin
+ elseif has('win32unix') && a:cmd =~? '^cmd /c "[a-z]'
+ let cmd = 'cmd /c " ' . substitute(cmd, '^cmd /c ', '', '') . ' "'
+ endif
+ let result = system(cmd)
+ finally
+ call eclim#util#EchoTrace('system: ' . cmd, localtime() - begin)
+ endtry
+ endif
+ finally
+ let &shell = saveshell
+ let &shellcmdflag = saveshellcmdflag
+ let &shellquote = saveshellquote
+ let &shellslash = saveshellslash
+ let &shelltemp = saveshelltemp
+ let &shellxquote = saveshellxquote
+
+ " If a System call is executed at startup, it appears to interfere with
+ " vim's setting of 'shellpipe' and 'shellredir' to their shell specific
+ " values. So, if we detect that the values we are restoring look like
+ " uninitialized defaults, then attempt to mimic vim's documented
+ " (:h 'shellpipe' :h 'shellredir') logic for setting the proper values based
+ " on the shell.
+ " Note: still doesn't handle more obscure shells
+ if saveshellredir == '>'
+ if index(s:bourne_shells, fnamemodify(&shell, ':t')) != -1
+ set shellpipe=2>&1\|\ tee
+ set shellredir=>%s\ 2>&1
+ elseif index(s:c_shells, fnamemodify(&shell, ':t')) != -1
+ set shellpipe=\|&\ tee
+ set shellredir=>&
+ else
+ let &shellpipe = saveshellpipe
+ let &shellredir = saveshellredir
+ endif
+ else
+ let &shellpipe = saveshellpipe
+ let &shellredir = saveshellredir
+ endif
+ endtry
+
+ return result
+endfunction " }}}
+
+" TempWindow(name, lines, [options]) {{{
+" Opens a temp window w/ the given name and contents which is readonly unless
+" specified otherwise.
+function! eclim#util#TempWindow(name, lines, ...)
+ let options = a:0 > 0 ? a:1 : {}
+ let filename = expand('%:p')
+ let winnr = winnr()
+
+ let bufname = eclim#util#EscapeBufferName(a:name)
+ let name = escape(a:name, ' ')
+ if has('unix')
+ let name = escape(name, '[]')
+ endif
+
+ let line = 1
+ let col = 1
+
+ if bufwinnr(bufname) == -1
+ let height = get(options, 'height', 10)
+ silent! noautocmd exec "botright " . height . "sview " . name
+ setlocal nowrap
+ setlocal winfixheight
+ setlocal noswapfile
+ setlocal nobuflisted
+ setlocal buftype=nofile
+ setlocal bufhidden=delete
+ silent doautocmd WinEnter
+ else
+ let temp_winnr = bufwinnr(bufname)
+ if temp_winnr != winnr()
+ exec temp_winnr . 'winc w'
+ silent doautocmd WinEnter
+ if get(options, 'preserveCursor', 0)
+ let line = line('.')
+ let col = col('.')
+ endif
+ endif
+ endif
+
+ call eclim#util#TempWindowClear(a:name)
+
+ setlocal modifiable
+ setlocal noreadonly
+ call append(1, a:lines)
+ retab
+
+ let undolevels = &undolevels
+ set undolevels=-1
+ silent 1,1delete _
+ let &undolevels = undolevels
+
+ call cursor(line, col)
+
+ if get(options, 'readonly', 1)
+ setlocal nomodified
+ setlocal nomodifiable
+ setlocal readonly
+ nmap <buffer> q :q<cr>
+ endif
+
+ silent doautocmd BufEnter
+
+ " Store filename and window number so that plugins can use it if necessary.
+ if filename != expand('%:p')
+ let b:filename = filename
+ let b:winnr = winnr
+
+ augroup eclim_temp_window
+ autocmd! BufWinLeave <buffer>
+ call eclim#util#GoToBufferWindowRegister(b:filename)
+ augroup END
+ endif
+endfunction " }}}
+
+" TempWindowClear(name) {{{
+" Clears the contents of the temp window with the given name.
+function! eclim#util#TempWindowClear(name)
+ let name = eclim#util#EscapeBufferName(a:name)
+ if bufwinnr(name) != -1
+ let curwinnr = winnr()
+ exec bufwinnr(name) . "winc w"
+ setlocal modifiable
+ setlocal noreadonly
+ silent 1,$delete _
+ exec curwinnr . "winc w"
+ endif
+endfunction " }}}
+
+" WideMessage(command, message) {{{
+" Executes the supplied echo command and forces vim to display as much as
+" possible without the "Press Enter" prompt.
+" Thanks to vimtip #1289
+function! eclim#util#WideMessage(command, message)
+ let saved_ruler = &ruler
+ let saved_showcmd = &showcmd
+
+ let message = substitute(a:message, '^\s\+', '', '')
+
+ set noruler noshowcmd
+ redraw
+ let vimwidth = &columns * &cmdheight
+ if len(message) > vimwidth - 1
+ let remove = len(message) - vimwidth
+ let start = (len(message) / 2) - (remove / 2) - 4
+ let end = start + remove + 4
+ let message = substitute(message, '\%' . start . 'c.*\%' . end . 'c', '...', '')
+ endif
+ exec a:command . ' "' . escape(message, '"\') . '"'
+
+ let &ruler = saved_ruler
+ let &showcmd = saved_showcmd
+endfunction " }}}
+
+" WillWrittenBufferClose() {{{
+" Returns 1 if the current buffer is to be hidden/closed/deleted after it is
+" written, or 0 otherwise. This function is useful during a post write auto
+" command for determining whether or not to perform some operation based on
+" whether the buffer will still be visible to the user once the current
+" command has finished.
+" Note: This function only detects command typed by the user at the
+" command (:) prompt, not any normal mappings which may hide/close/delete the
+" buffer.
+function! eclim#util#WillWrittenBufferClose()
+ return histget("cmd") =~ s:buffer_write_closing_commands
+endfunction " }}}
+
+" CommandCompleteFile(argLead, cmdLine, cursorPos) {{{
+" Custom command completion for files.
+function! eclim#util#CommandCompleteFile(argLead, cmdLine, cursorPos)
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+ let results = split(eclim#util#Glob(argLead . '*', 1), '\n')
+ call map(results, 'isdirectory(v:val) ? v:val . "/" : v:val')
+ call map(results, "substitute(v:val, '\\', '/', 'g')")
+ call map(results, "substitute(v:val, ' ', '\\\\ ', 'g')")
+
+ return eclim#util#ParseCommandCompletionResults(argLead, results)
+endfunction " }}}
+
+" CommandCompleteDir(argLead, cmdLine, cursorPos) {{{
+" Custom command completion for directories.
+function! eclim#util#CommandCompleteDir(argLead, cmdLine, cursorPos)
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let args = eclim#util#ParseCmdLine(cmdLine)
+ let argLead = cmdLine =~ '\s$' ? '' : args[len(args) - 1]
+ let results = split(eclim#util#Glob(expand(argLead) . '*', 1), '\n')
+ let index = 0
+ for result in results
+ if !isdirectory(result)
+ call remove(results, index)
+ else
+ let result = result . '/'
+ let result = substitute(result, '\', '/', 'g')
+ let result = substitute(result, ' ', '\\\\ ', 'g')
+ exec "let results[" . index . "] = \"" . result . "\""
+ let index += 1
+ endif
+ endfor
+ return eclim#util#ParseCommandCompletionResults(argLead, results)
+endfunction " }}}
+
+" ParseCmdLine(args) {{{
+" Parses the supplied argument line into a list of args.
+function! eclim#util#ParseCmdLine(args)
+ let args = split(a:args, '[^\\]\s\zs')
+ call map(args, 'substitute(v:val, "\\([^\\\\]\\)\\s\\+$", "\\1", "")')
+
+ return args
+endfunction " }}}
+
+" ParseCommandCompletionResults(args) {{{
+" Bit of a hack for vim's lack of support for escaped spaces in custom
+" completion.
+function! eclim#util#ParseCommandCompletionResults(argLead, results)
+ let results = a:results
+ if stridx(a:argLead, ' ') != -1
+ let removePrefix = escape(substitute(a:argLead, '\(.*\s\).*', '\1', ''), '\')
+ call map(results, "substitute(v:val, '^" . removePrefix . "', '', '')")
+ endif
+ return results
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/vimplugin.vim b/vim/eclim/autoload/eclim/vimplugin.vim
@@ -0,0 +1,82 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Contains any global vim side code for embedding gvim in eclipse.
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" BufferWritten() {{{
+" Invoked when a buffer opened from eclipse is saved, to notify eclipse of the
+" save.
+function eclim#vimplugin#BufferWritten()
+ if has('netbeans_enabled') && exists('g:vimplugin_running')
+ if exists('b:eclim_file_modified')
+ unlet b:eclim_file_modified
+ endif
+ nbkey unmodified
+ endif
+endfunction " }}}
+
+" BufferModified() {{{
+" Invoked on cursor hold to check if a previously modified buffer is now
+" unmodified, and vice versa, so that eclipse can be notified.
+function eclim#vimplugin#BufferModified()
+ if has('netbeans_enabled') && exists('g:vimplugin_running')
+ if !exists('b:eclim_file_modified')
+ let b:eclim_file_modified = &modified
+ endif
+
+ if &modified != b:eclim_file_modified
+ unlet b:eclim_file_modified
+ exec 'nbkey ' . (&modified ? 'modified' : 'unmodified')
+ endif
+ let b:eclim_file_modified = &modified
+ endif
+endfunction " }}}
+
+" BufferClosed() {{{
+" Invoked when a buffer is removed from a window to signal that eclipse should
+" close the associated editor tab. This is only needed for external vim +
+" tabbed mode.
+function eclim#vimplugin#BufferClosed()
+ if has('netbeans_enabled') && exists('g:vimplugin_tabbed')
+ exec 'nbkey fileClosed ' . expand('<afile>:p')
+ endif
+endfunction " }}}
+
+" BufferEnter() {{{
+" Invoked when switching buffers so we can update the eclipse tab title.
+function eclim#vimplugin#BufferEnter()
+ if has('netbeans_enabled') && exists('g:vimplugin_running')
+ exec 'nbkey bufferEnter ' . expand('<afile>:p')
+ endif
+endfunction " }}}
+
+" FeedKeys(keys, [refocusGvim]) {{{
+" Feeds eclipse compatible key string to eclipse if current gvim instance is
+" attached via the netbeans protocol.
+function eclim#vimplugin#FeedKeys(keys, ...)
+ if has('netbeans_enabled') && exists('g:vimplugin_running')
+ let refocus = a:0 > 0 && a:1 ? ',refocus' : ''
+ silent exec 'nbkey feedkeys ' . a:keys . refocus
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/web.vim b/vim/eclim/autoload/eclim/web.vim
@@ -0,0 +1,232 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/common/web.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists("g:EclimOpenUrlInVimPatterns")
+ let g:EclimOpenUrlInVimPatterns = []
+endif
+if !exists("g:EclimOpenUrlInVimAction")
+ let g:EclimOpenUrlInVimAction = g:EclimDefaultFileOpenAction
+endif
+" }}}
+
+" Script Variables {{{
+ let s:win_browsers = [
+ \ 'C:/Program Files/Opera/Opera.exe',
+ \ 'C:/Program Files/Mozilla Firefox/firefox.exe',
+ \ 'C:/Program Files/Internet Explorer/iexplore.exe'
+ \ ]
+
+ let s:browsers = [
+ \ 'xdg-open', 'chromium', 'opera', 'firefox', 'konqueror',
+ \ 'epiphany', 'mozilla', 'netscape', 'iexplore'
+ \ ]
+" }}}
+
+function! eclim#web#OpenUrl(url, ...) " {{{
+ " Opens the supplied url in a web browser or opens the url under the cursor.
+
+ if !exists('s:browser') || s:browser == ''
+ let s:browser = s:DetermineBrowser()
+
+ " slight hack for IE which doesn't like the url to be quoted.
+ if s:browser =~ 'iexplore' && !has('win32unix')
+ let s:browser = substitute(s:browser, '"', '', 'g')
+ endif
+ endif
+
+ if s:browser == ''
+ return
+ endif
+
+ let url = a:url
+ if url == ''
+ if len(a:000) > 2
+ let start = a:000[1]
+ let end = a:000[2]
+ while start <= end
+ call eclim#web#OpenUrl(eclim#util#GrabUri(start, col('.')), a:000[0])
+ let start += 1
+ endwhile
+ return
+ else
+ let url = eclim#util#GrabUri()
+ endif
+ endif
+
+ if url == ''
+ call eclim#util#EchoError(
+ \ 'No url supplied at command line or found under the cursor.')
+ return
+ endif
+
+ " prepend http:// or file:// if no protocol defined.
+ if url !~ '^\(https\?\|file\):'
+ " absolute file on windows or unix
+ if url =~ '^\([a-zA-Z]:[/\\]\|/\)'
+ let url = 'file://' . url
+
+ " everything else
+ else
+ let url = 'http://' . url
+ endif
+ endif
+
+ if len(a:000) == 0 || a:000[0] == ''
+ for pattern in g:EclimOpenUrlInVimPatterns
+ if url =~ pattern
+ exec g:EclimOpenUrlInVimAction . ' ' . url
+ return
+ endif
+ endfor
+ endif
+
+ let url = substitute(url, '\', '/', 'g')
+ let url = escape(url, '&%!')
+ let url = escape(url, '%!')
+ let command = escape(substitute(s:browser, '<url>', url, ''), '#')
+ silent call eclim#util#Exec(command)
+ redraw!
+
+ if v:shell_error
+ call eclim#util#EchoError("Unable to open browser:\n" . s:browser .
+ \ "\nCheck that the browser executable is in your PATH " .
+ \ "or that you have properly configured g:EclimBrowser")
+ endif
+endfunction " }}}
+
+function! eclim#web#SearchEngine(url, args, line1, line2) " {{{
+ " Function to use a search engine to search for a word or phrase.
+
+ let search_string = a:args
+ if search_string == ''
+ let search_string = eclim#util#GetVisualSelection(a:line1, a:line2, 0)
+ if search_string == ''
+ let search_string = expand('<cword>')
+ endif
+ endif
+
+ let search_string = eclim#html#util#UrlEncode(search_string)
+ let url = substitute(a:url, '<query>', search_string, '')
+
+ call eclim#web#OpenUrl(url)
+endfunction " }}}
+
+function! eclim#web#WordLookup(url, word) " {{{
+ " Function to lookup a word on an online dictionary, thesaurus, etc.
+
+ let word = a:word
+ if word == ''
+ let word = expand('<cword>')
+ endif
+
+ let url = substitute(a:url, '<query>', word, '')
+
+ call eclim#web#OpenUrl(url)
+endfunction " }}}
+
+function! s:DetermineBrowser() " {{{
+ let browser = ''
+
+ " user specified a browser, we just need to fill in any gaps if necessary.
+ if exists("g:EclimBrowser")
+ let browser = g:EclimBrowser
+ " add "<url>" if necessary
+ if browser !~ '<url>'
+ let browser = substitute(browser,
+ \ '^\([[:alnum:][:blank:]-/\\_.:"]\+\)\(.*\)$',
+ \ '\1 "<url>" \2', '')
+ endif
+
+ if has("win32") || has("win64")
+ " add 'start' to run process in background if necessary.
+ if browser !~ '^[!]\?start'
+ let browser = 'start ' . browser
+ endif
+ else
+ " add '&' to run process in background if necessary.
+ if browser !~ '&\s*$' &&
+ \ browser !~ '^\(/[/a-zA-Z0-9]\+/\)\?\<\(links\|lynx\|elinks\|w3m\)\>'
+ let browser = browser . ' &'
+ endif
+
+ " add redirect of std out and error if necessary.
+ if browser !~ '/dev/null'
+ let browser = substitute(browser, '\s*&\s*$', '&> /dev/null &', '')
+ endif
+ endif
+
+ if browser !~ '^\s*!'
+ let browser = '!' . browser
+ endif
+
+ " user did not specify a browser, so attempt to find a suitable one.
+ else
+ if has('win32') || has('win64') || has('win32unix')
+ " Note: this version may not like .html suffixes on windows 2000
+ if executable('rundll32')
+ let browser = 'rundll32 url.dll,FileProtocolHandler <url>'
+ endif
+ " this doesn't handle local files very well or '&' in the url.
+ "let browser = '!cmd /c start <url>'
+ if browser == ''
+ for name in s:win_browsers
+ if has('win32unix')
+ let name = eclim#cygwin#CygwinPath(name)
+ endif
+ if executable(name)
+ let browser = name
+ if has('win32unix')
+ let browser = '"' . browser . '"'
+ endif
+ break
+ endif
+ endfor
+ endif
+ elseif has('mac')
+ let browser = '!open "<url>"'
+ else
+ for name in s:browsers
+ if executable(name)
+ let browser = name
+ break
+ endif
+ endfor
+ endif
+
+ if browser != ''
+ let g:EclimBrowser = browser
+ let browser = s:DetermineBrowser()
+ endif
+ endif
+
+ if browser == ''
+ call eclim#util#EchoError("Unable to determine browser. " .
+ \ "Please set g:EclimBrowser to your preferred browser.")
+ endif
+
+ return browser
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/xml/complete.vim b/vim/eclim/autoload/eclim/xml/complete.vim
@@ -0,0 +1,89 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/xml/complete.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Varables {{{
+ let s:complete_command =
+ \ '-command xml_complete -p "<project>" -f "<file>" ' .
+ \ '-o <offset> -e <encoding>'
+" }}}
+
+" CodeComplete(findstart, base) {{{
+" Handles xml code completion.
+function! eclim#xml#complete#CodeComplete(findstart, base)
+ if !eclim#project#util#IsCurrentFileInProject(0)
+ return a:findstart ? -1 : []
+ endif
+
+ if a:findstart
+ call eclim#lang#SilentUpdate(1)
+
+ " locate the start of the word
+ let line = getline('.')
+
+ let start = col('.') - 1
+
+ while start > 0 && line[start - 1] =~ '[[:alnum:]_-]'
+ let start -= 1
+ endwhile
+
+ return start
+ else
+ let offset = eclim#util#GetOffset() + len(a:base)
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#lang#SilentUpdate(1, 0)
+ if file == ''
+ return []
+ endif
+
+ let command = s:complete_command
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', offset, '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+
+ let completions = []
+ let results = eclim#Execute(command)
+ if type(results) != g:LIST_TYPE
+ return
+ endif
+
+ for result in results
+ let word = result.completion
+ if getline('.') =~ '\w:\w*\%' . col('.') . 'c'
+ let word = substitute(word, '^\w\+:', '', '')
+ endif
+
+ let menu = eclim#html#util#HtmlToText(result.menu)
+ let info = eclim#html#util#HtmlToText(result.info)
+
+ let dict = {'word': word, 'menu': menu, 'info': info}
+
+ call add(completions, dict)
+ endfor
+
+ return completions
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/xml/definition.vim b/vim/eclim/autoload/eclim/xml/definition.vim
@@ -0,0 +1,79 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/xml/definition.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+let s:element_def{'dtd'} = '<!ELEMENT\s\+<name>\>\(\s\|(\|$\)'
+let s:element_def{'xsd'} =
+ \ '<\s*\(.\{-}:\)\?element\>\_[^>]*name\s*=\s*' .
+ \ g:EclimQuote . '<name>' . g:EclimQuote
+" }}}
+
+" DtdDefinition(element) {{{
+" Opens the current xml file's dtd definition and optionally jumps to an
+" element if an element name supplied.
+function! eclim#xml#definition#DtdDefinition(element)
+ let dtd = eclim#xml#util#GetDtd()
+ let element = a:element == '' ? eclim#xml#util#GetElementName() : a:element
+ call s:OpenDefinition(dtd, element, 'dtd')
+endfunction " }}}
+
+" XsdDefinition(element) {{{
+" Opens the current xml file's xsd definition and optionally jumps to an
+" element if an element name supplied.
+function! eclim#xml#definition#XsdDefinition(element)
+ let element = a:element == '' ? eclim#xml#util#GetElementName() : a:element
+ if element =~ ':'
+ let namespace = substitute(element, ':.*', '', '')
+ let element = substitute(element, '.*:', '', '')
+ let xsd = eclim#xml#util#GetXsd(namespace)
+ else
+ let xsd = eclim#xml#util#GetXsd()
+ endif
+ call s:OpenDefinition(xsd, element, 'xsd')
+endfunction " }}}
+
+" OpenDefinition(file, element, type) {{{
+" Open the supplied definition file and jump to the element if supplied.
+function! s:OpenDefinition(file, element, type)
+ if a:file == ''
+ call eclim#util#EchoWarning('Unable to locate ' . a:type . ' in current file.')
+ return
+ endif
+
+ " see if file is already open.
+ let winnr = bufwinnr(a:file)
+ if winnr != -1
+ exec winnr . 'winc w'
+ else
+ exec 'split ' . a:file
+ endif
+
+ " jump to element definition if supplied
+ if a:element != ''
+ let search = substitute(s:element_def{a:type}, '<name>', a:element, 'g')
+ call search(search, 'w')
+ endif
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/xml/format.vim b/vim/eclim/autoload/eclim/xml/format.vim
@@ -0,0 +1,200 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/xml/format.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+ let s:command_format =
+ \ '-command xml_format -f "<file>" -w <width> -i <indent> -m <ff>'
+" }}}
+
+" Format() {{{
+function! eclim#xml#format#Format()
+ " first save the file and validate to ensure no errors
+ call eclim#util#ExecWithoutAutocmds('update')
+ call eclim#xml#validate#Validate(0, '!')
+ if len(getloclist(0)) > 0
+ call eclim#util#EchoError(
+ \ 'File contains errors (:lopen), please correct before formatting.')
+ return
+ endif
+
+ let file = substitute(expand('%:p'), '\', '/', 'g')
+ if has('win32unix')
+ let file = eclim#cygwin#WindowsPath(file)
+ endif
+
+ let command = s:command_format
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<width>', &textwidth, '')
+ let command = substitute(command, '<indent>', &shiftwidth, '')
+ let command = substitute(command, '<ff>', &ff, '')
+
+ let result = eclim#Execute(command)
+ if result != '0'
+ silent! 1,$delete _
+ silent put =result
+ silent! 1,1delete _
+ endif
+endfunction " }}}
+
+" Format(start, end) {{{
+"function! eclim#xml#format#Format(start, end)
+" if !exists('b:root')
+" let b:root = s:GetRootLine()
+"
+" if b:root < 1
+" return
+" endif
+" endif
+"
+" let pos = getpos('.')
+"
+" let start = a:start
+" let end = a:end
+" if start >= b:root
+" call cursor(start, 1)
+"
+" " handle xml delcaration case
+" let line = getline(start)
+" if line =~ '^\s*<?xml.\{-}?>\s*<'
+" call s:InsertCr(start, stridx(line, '?>') + 3)
+" let end += 1
+" let b:root += 1
+"
+" else
+" let outer = s:SelectOuterTag(1)
+" let inner = s:SelectInnerTag()
+"
+" " inner tags on the same line, push to a new line.
+" if outer.lstart == inner.lstart &&
+" \ (inner.lstart != outer.lstart || inner.cstart != outer.cstart)
+" call s:InsertCr(inner.lstart, inner.cstart)
+" let end += 1
+" endif
+"
+" " handle repositioning parent ending tag if necessary.
+" if getline(inner.lstart) =~ '^\s*<\w'
+" let element = s:SelectOuterTag(1)
+" let parent = s:SelectOuterTag(2)
+" else
+" let element = s:SelectInnerTag()
+" let parent = s:SelectOuterTag(1)
+" endif
+" if element.lend == parent.lend &&
+" \ (parent.lstart != parent.lend || parent.cstart != parent.cend)
+" call s:InsertCr(element.lend, element.cend + 1)
+" let end += 1
+" endif
+"
+" " handle sibling elements on the same line.
+" let element = s:SelectOuterTag(1)
+" if len(getline(element.lend)) > element.cend
+" call cursor(element.lend, element.cend + 1)
+" let sibling = s:SelectOuterTag(1)
+" if element.lend == sibling.lstart
+" call s:InsertCr(element.lend, element.cend + 1)
+" let end += 1
+" endif
+" endif
+" endif
+"
+" " let vim re-indent
+" call cursor(start, 1)
+" normal! ==
+" endif
+"
+" " recurse.
+" if start < end
+" call cursor(start + 1, 1)
+" call eclim#xml#format#Format(start + 1, end)
+" else
+" unlet b:root
+" endif
+"
+" call setpos('.', pos)
+"endfunction " }}}
+
+" SelectOuterTag(count) {{{
+function! s:SelectOuterTag(count)
+ let pos = getpos('.')
+
+ exec 'silent! normal! v' . a:count . 'atv'
+ call setpos('.', pos)
+
+ return s:VisualSelectionMap()
+endfunction " }}}
+
+" SelectInnerTag() {{{
+function! s:SelectInnerTag()
+ silent! normal! vit
+ normal! v
+ call cursor(line("'<"), col("'<"))
+
+ return s:VisualSelectionMap()
+endfunction " }}}
+
+" VisualSelectionMap() {{{
+function! s:VisualSelectionMap()
+ let lstart = line("'<")
+ let cstart = col("'<")
+ let lend = line("'>")
+ let cend = col("'>")
+
+ if cstart > len(getline(lstart))
+ let lstart += 1
+ let cstart = 1
+ endif
+
+ if strpart(getline(lend), 0, cend) =~ '^\s*$'
+ let lend -= 1
+ let cend = len(getline(lend))
+ endif
+
+ return {'lstart': lstart, 'cstart': cstart, 'lend': lend, 'cend': cend}
+endfunction " }}}
+
+" InsertCr(line, col) {{{
+function! s:InsertCr(line, col)
+ call cursor(a:line, a:col)
+ exec "normal! i\<cr>\<esc>"
+endfunction " }}}
+
+" GetRootLine() {{{
+function! s:GetRootLine()
+ let pos = getpos('.')
+
+ let line = 1
+ call cursor(1, 1)
+ while getline('.') !~ '<\w'
+ let line = line('.') + 1
+ if line > line('$')
+ break
+ endif
+ call cursor(line, 1)
+ endwhile
+
+ call setpos('.', pos)
+ return line
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/xml/util.vim b/vim/eclim/autoload/eclim/xml/util.vim
@@ -0,0 +1,137 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Utility functions for xml plugins.
+"
+" This plugin contains shared functions that can be used regardless of the
+" current file type being edited.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Script Variables {{{
+let s:dtd = '.*' . g:EclimQuote . '\(.*\)' . g:EclimQuote . '\s*>.*'
+let s:xsd = '.\{-}<ns>:schemaLocation\s*=\s*' .
+ \ g:EclimQuote . '\(.\{-}\)' . g:EclimQuote . '.*'
+let s:element = '.\{-}<\([a-zA-Z].\{-}\)\(\s\|>\|$\).*'
+" }}}
+
+" GetDtd() {{{
+" Get the dtd defined in the current file.
+function! eclim#xml#util#GetDtd()
+ let linenum = search('<!DOCTYPE\s\+\_.\{-}>', 'bcnw')
+ if linenum > 0
+ let line = ''
+ while getline(linenum) !~ '>'
+ let line = line . getline(linenum)
+ let linenum += 1
+ endwhile
+ let line = line . getline(linenum)
+
+ let dtd = substitute(line, s:dtd, '\1', '')
+ if dtd != line
+ return dtd
+ endif
+ endif
+ return ''
+endfunction " }}}
+
+" GetXsd() {{{
+" Get the schema defined in the current file, for the optionally provided
+" namespace prefix, or the default namespace.
+function! eclim#xml#util#GetXsd(...)
+ let namespace = ''
+ if len(a:000) > 0
+ let namespace = a:000[0]
+ endif
+
+ " if no namespace given, try 'xsi' as that is a common default.
+ if namespace == ''
+ let xsd = eclim#xml#util#GetXsd('xsi')
+ if xsd != ''
+ return xsd
+ endif
+ endif
+
+ let linenum = search(namespace . ':schemaLocation\>', 'bcnw')
+ if linenum > 0
+ let line = ''
+ while getline(linenum) !~ '>'
+ let line = line . getline(linenum)
+ let linenum += 1
+ endwhile
+ let line = line . getline(linenum)
+
+ let pattern = substitute(s:xsd, '<ns>', namespace, '')
+ let xsd = substitute(line, pattern, '\1', '')
+ if xsd != line
+ " last http definition is the schema
+ return strpart(xsd, strridx(xsd, 'http://'))
+ endif
+ endif
+ return ''
+endfunction " }}}
+
+" GetElementName() {{{
+" Get name of the element that the cursor is currently on.
+function! eclim#xml#util#GetElementName()
+ let line = getline('.')
+ let cnum = col('.')
+ if line[cnum - 1] == '<'
+ let cnum += 1
+ endif
+ if line[cnum - 1] == '>'
+ let cnum -= 1
+ endif
+
+ let name = substitute(line,
+ \ '.*</\?\s*\(.*\%' . cnum . 'c.\{-}\)\(\s.*\|\s*/\?>.*\|$\)', '\1', '')
+
+ if name == line || name =~ '<\|>' || name =~ '\S\s\S'
+ return ''
+ endif
+
+ let name = substitute(name, '\s\|/', '', 'g')
+
+ return name
+endfunction " }}}
+
+" GetParentElementName() {{{
+" Get the parent element name relative to the current cursor position.
+" Depends on 'at' visual selection ability.
+function! eclim#xml#util#GetParentElementName()
+ let pos = getpos('.')
+
+ " select tags (best solution I can think of).
+ silent! normal! v2at
+ normal! v
+
+ call cursor(line("'<"), col("'<"))
+ let parent = eclim#xml#util#GetElementName()
+
+ call setpos('.', pos)
+
+ if eclim#xml#util#GetElementName() == parent
+ return ''
+ endif
+
+ return parent
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/autoload/eclim/xml/validate.vim b/vim/eclim/autoload/eclim/xml/validate.vim
@@ -0,0 +1,84 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/xml/validate.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists("g:EclimXmlValidate")
+ let g:EclimXmlValidate = 1
+endif
+" }}}
+
+" Script Variables {{{
+let s:command_validate = '-command xml_validate -p "<project>" -f "<file>"'
+" }}}
+
+function! eclim#xml#validate#Validate(on_save, ...) " {{{
+ " Optional args:
+ " bang: '!' or '', where '!' indicates that we should not jump to the
+ " first error.
+ if a:on_save && (!g:EclimXmlValidate || eclim#util#WillWrittenBufferClose())
+ return
+ endif
+
+ if eclim#EclimAvailable(0)
+ if !eclim#project#util#IsCurrentFileInProject()
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+ let command = s:command_validate
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ if search('xsi:schemaLocation', 'cnw')
+ let command .= ' -s'
+ endif
+
+ let result = eclim#Execute(command)
+ if type(result) == g:LIST_TYPE && len(result) > 0
+ let errors = eclim#util#ParseLocationEntries(
+ \ result, g:EclimValidateSortResults)
+ call eclim#util#SetLocationList(errors)
+ " bang arg supplied, but no bang, so jump to first error.
+ if len(a:000) > 0 && a:000[0] == ''
+ lfirst
+ endif
+ return 1
+ else
+ call eclim#util#ClearLocationList()
+ return 0
+ endif
+ else
+ " alternative method via xmllint
+ if !a:on_save && executable('xmllint')
+ let file = substitute(expand('%:p'), '\', '/', 'g')
+ call eclim#util#MakeWithCompiler('eclim_xmllint', '', file)
+ call eclim#display#signs#Update()
+ elseif !a:on_save
+ call eclim#util#EchoWarning("eclimd not running.")
+ endif
+ endif
+ return 0
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/bin/bash_complete b/vim/eclim/bin/bash_complete
@@ -0,0 +1,21 @@
+#!/bin/bash
+##
+# Script to manually invoke a bash completion function and print the results
+# one result per line.
+##
+
+. /etc/bash_completion
+
+COMP_FUNC=$1
+shift
+COMP_WORDS=("${@}")
+COMP_CWORD=$((${#COMP_WORDS[@]}-1))
+
+CMD=${COMP_WORDS[0]}
+CUR=${COMP_WORDS[$COMP_CWORD]}
+PRE=${COMP_WORDS[$(($COMP_CWORD-1))]}
+
+$COMP_FUNC $CMD $CUR $PRE
+for reply in ${COMPREPLY[@]} ; do
+ echo $reply
+done
diff --git a/vim/eclim/compiler/eclim_ant.vim b/vim/eclim/compiler/eclim_ant.vim
@@ -0,0 +1,87 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Compiler for ant (enhancement to default ant compiler provided w/ vim).
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if exists("current_compiler")
+ finish
+endif
+let current_compiler = "eclim_ant"
+
+if !exists('g:EclimAntCompilerAdditionalErrorFormat')
+ let g:EclimAntCompilerAdditionalErrorFormat = ''
+endif
+
+if !exists('g:EclimAntErrorFormat')
+ let g:EclimAntErrorFormat = ''
+endif
+
+if !exists('g:EclimAntErrorsEnabled')
+ let g:EclimAntErrorsEnabled = 0
+endif
+if g:EclimAntErrorsEnabled
+ let g:EclimAntErrorFormat .= '\%A%f:%l:\ %m,'
+endif
+
+CompilerSet makeprg=ant\ -find\ build.xml\ $*
+
+" The two entries before the last one, are for catching ant build file names
+" and error line numbers.
+exec 'CompilerSet errorformat=' .
+ \ '\%-G%.%#[javac]\ %.%#:\ warning:\ unmappable\ character\ %.%#,' .
+ \ '\%A%.%#[javac]\ %f:%l:\ %m,' .
+ \ '\%C%.%#[javac]\ symbol\ %#:\ %m,' .
+ \ '\%-Z%.%#[javac]\ %p^,' .
+ \ '\%A%.%#[javadoc]\ %f:%l:\ %m,' .
+ \ '\%-C%.%#[javadoc]\ location:\ %.%#,' .
+ \ '\%-C%.%#[javadoc]\ %#,' .
+ \ '\%-Z%.%#[javadoc]\ %p^,' .
+ \ '\%-G%.%#[javadoc]\ Note:%.%#,' .
+ \ '\%-G%.%#[javadoc]\ javadoc:%.%#,' .
+ \ '\%.%#[javadoc]\ %f:\ %m,' .
+ \ '\%.%#[java]\ org\.apache\.jasper\.JasperException:\ file:%f(%l\\,%c)\ %m,' .
+ \ '\%+A%.%#[junit]\ %.%#Failures:\ %[%^0]%.%#\ Time\ elapsed:\ %.%#,' .
+ \ '\%-Z%.%#[junit]\ Test\ %f\ FAILED,' .
+ \ '\%+A%.%#[junit]\ %.%#Errors:\ %[%^0]%.%#\ Time\ elapsed:\ %.%#,' .
+ \ '\%-Z%.%#[junit]\ Test\ %f\ FAILED,' .
+ \ '\%+A%.%#[cactus]\ %.%#Failures:\ %[%^0]%.%#\ Time\ elapsed:\ %.%#,' .
+ \ '\%-Z%.%#[cactus]\ Test\ %f\ FAILED,' .
+ \ '\%+A%.%#[cactus]\ %.%#Errors:\ %[%^0]%.%#\ Time\ elapsed:\ %.%#,' .
+ \ '\%-Z%.%#[cactus]\ Test\ %f\ FAILED,' .
+ \ '\%.%#[checkstyle]\ %f:%l:%c:\ %m,' .
+ \ '\%.%#[checkstyle]\ %f:%l:\ %m,' .
+ \ '\%E%.%#[scalac]\ %f:%l:\ error:\ %m,' .
+ \ '\%-Z%.%#[scalac]\ %p^,' .
+ \ '\%W%.%#[scalac]\ %f:%l:\ warning:\ %m,' .
+ \ '\%-Z%.%#[scalac]\ %p^,' .
+ \ '\%A%.%#[scalac]\ %f:%l:\ %m,' .
+ \ '\%-Z%.%#[scalac]\ %p^,' .
+ \ '\%+A%.%#eclim\ testng:\ %f:%m,' .
+ \ '\%.%#\ ERROR\ %.%#\ line\ %l\ in\ file:\ %.%f%.:\ %m,' .
+ \ g:EclimAntCompilerAdditionalErrorFormat .
+ \ '\%.%#[exec]\ %f:%l:%c:\ %m,' .
+ \ '\%.%#[exec]\ %f:%l:\ %m,' .
+ \ '\%f:%l:%c:\ %m,' .
+ \ g:EclimAntErrorFormat .
+ \ '\%-G%.%#'
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/compiler/eclim_javadoc.vim b/vim/eclim/compiler/eclim_javadoc.vim
@@ -0,0 +1,44 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if exists("current_compiler")
+ finish
+endif
+let current_compiler = "eclim_javadoc"
+
+let instance = eclim#client#nailgun#ChooseEclimdInstance()
+let command = eclim#client#nailgun#GetEclimCommand(instance.home)
+let command .= ' --nailgun-port ' . instance.port
+let command .= ' -command javadoc $*'
+if has('win32') || has('win64') || has('win32unix')
+ let command = 'cmd /c " ' . command . ' "'
+else
+ let command = substitute(command, '"', '', 'g')
+endif
+exec 'CompilerSet makeprg=' . escape(command, ' "')
+
+exec 'CompilerSet errorformat=' .
+ \ '\%A%.%#[javadoc]\ %f:%l:\ %m,' .
+ \ '\%-Z%.%#[javadoc]\ %p^,' .
+ \ '\%-G%.%#[javadoc]%.%#,' .
+ \ '\%-G%.%#'
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/compiler/eclim_make.vim b/vim/eclim/compiler/eclim_make.vim
@@ -0,0 +1,56 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Compiler for make.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if exists("current_compiler")
+ finish
+endif
+let current_compiler = "eclim_make"
+
+if !exists('g:EclimMakeCompilerAdditionalErrorFormat')
+ let g:EclimMakeCompilerAdditionalErrorFormat = ''
+endif
+
+CompilerSet makeprg=make
+
+" With the exception of the last two lines, this is a straight copy from the
+" vim default.
+exec 'CompilerSet errorformat=' .
+ \ '%*[^\"]\"%f\"%*\\D%l:\ %m,' .
+ \ '\"%f\"%*\\D%l:\ %m,'.
+ \ '%-G%f:%l:\ (Each\ undeclared\ identifier\ is\ reported\ only\ once,' .
+ \ '%-G%f:%l:\ for\ each\ function\ it\ appears\ in.),' .
+ \ '%f:%l:%c:%m,' .
+ \ '%f(%l):%m,' .
+ \ '%f:%l:%m,' .
+ \ '\"%f\"\\,\ line\ %l%*\\D%c%*[^\ ]\ %m,' .
+ \ "%D%*\\\\a[%*\\\\d]:\\ Entering\\ directory\\ `%f'," .
+ \ "%X%*\\\\a[%*\\\\d]:\\ Leaving\\ directory\\ `%f'," .
+ \ "%D%*\\\\a:\\ Entering\\ directory\\ `%f'," .
+ \ "%X%*\\\\a:\\ Leaving\\ directory\\ `%f'," .
+ \ '%DMaking\ %*\\a\ in\ %f,' .
+ \ '%f\|%l\|\ %m,' .
+ \ g:EclimMakeCompilerAdditionalErrorFormat .
+ \ '\%-G%.%#'
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/compiler/eclim_maven.vim b/vim/eclim/compiler/eclim_maven.vim
@@ -0,0 +1,61 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Compiler for maven 1.x.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if exists("current_compiler")
+ finish
+endif
+let current_compiler = "eclim_maven"
+
+if !exists('g:EclimMavenCompilerAdditionalErrorFormat')
+ let g:EclimMavenCompilerAdditionalErrorFormat = ''
+endif
+
+CompilerSet makeprg=maven\ --find\ project.xml\ $*
+
+" Lines 17 - 20: javac minus adornments (must be last to prevent picking up
+" other errors in the wrong format).
+exec 'CompilerSet errorformat=' .
+ \ '\%A%.%#[javac]\ %f:%l:\ %m,' .
+ \ '\%C%.%#[javac]\ symbol%.%#:\ %m,' .
+ \ '\%C%.%#[javac]\ location%.%#:\ %m,' .
+ \ '\%-Z%.%#[javac]\ %p^,' .
+ \ '\%W%.%#[javadoc]\ %f:%l:\ warning\ -\ %m,' .
+ \ '\%E%.%#[javadoc]\ %f:%l:\ error\ -\ %m,' .
+ \ '\%A%.%#[javadoc]\ %f:%l:\ %m,' .
+ \ '\%-C%.%#[javadoc]\ location:\ %.%#,' .
+ \ '\%-Z%.%#[javadoc]\ %p^,' .
+ \ '\%-G%.%#[javadoc]\ Note:%.%#,' .
+ \ '\%-G%.%#[javadoc]\ javadoc:%.%#,' .
+ \ '\%+A%.%#[junit]\ %.%#Failures:\ %[%^0]%.%#\ Time\ elapsed:\ %.%#,' .
+ \ '\%-Z%.%#[junit]%.%#\ Test\ %f\ FAILED,' .
+ \ '\%+A%.%#[junit]%.%#\ %.%#Errors:\ %[%^0]%.%#\ Time\ elapsed:\ %.%#,' .
+ \ '\%-Z%.%#[junit]\ Test\ %f\ FAILED,' .
+ \ g:EclimMavenCompilerAdditionalErrorFormat .
+ \ '\%A%f:%l:\ %m,' .
+ \ '\%Csymbol%.%#:\ %m,' .
+ \ '\%Clocation%.%#:\ %m,' .
+ \ '\%-Z\ %p^,' .
+ \ '\%-G%.%#'
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/compiler/eclim_mvn.vim b/vim/eclim/compiler/eclim_mvn.vim
@@ -0,0 +1,51 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Compiler for maven 2.x.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if exists("current_compiler")
+ finish
+endif
+let current_compiler = "eclim_maven"
+
+if !exists('g:EclimMvnCompilerAdditionalErrorFormat')
+ let g:EclimMvnCompilerAdditionalErrorFormat = ''
+endif
+
+CompilerSet makeprg=mvn\ $*
+
+" Lines 1 - 3: javac
+" Lines 4 - 7: javadoc
+exec 'CompilerSet errorformat=' .
+ \ '\%A%f:[%l\\,%c]\ %m,' .
+ \ '\%Csymbol%.%#:\ %m,' .
+ \ '\%Zlocation%.%#:\ %m,' .
+ \ '\%AEmbedded\ error:%.%#\ -\ %f:%l:\ %m,' .
+ \ '\%-Z\ %p^,' .
+ \ '\%A%f:%l:\ %m,' .
+ \ '\%-Z\ %p^,' .
+ \ '\%ARunning\ %f,' .
+ \ '\%+ZTests\ run%.%#FAILURE!,' .
+ \ g:EclimMvnCompilerAdditionalErrorFormat .
+ \ '\%-G%.%#'
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/compiler/eclim_xmllint.vim b/vim/eclim/compiler/eclim_xmllint.vim
@@ -0,0 +1,39 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Compiler for xmllint.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if exists("current_compiler")
+ finish
+endif
+let current_compiler = "eclim_xmllint"
+
+CompilerSet makeprg=xmllint\ --valid\ --noout\ $*
+
+CompilerSet errorformat=
+ \%E%f:%l:\ %.%#\ error\ :\ %m,
+ \%W%f:%l:\ %.%#\ warning\ :\ %m,
+ \%-Z%p^,
+ \%-C%.%#,
+ \%-G%.%#
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/dict/java b/vim/eclim/dict/java
@@ -0,0 +1,32 @@
+author
+abstract
+boolean
+case
+catch
+char
+class
+double
+extends
+false
+final
+finally
+float
+implements
+int
+interface
+link
+new
+package
+param
+private
+protected
+public
+return
+short
+static
+switch
+throw
+throws
+true
+try
+version
diff --git a/vim/eclim/doc/404.txt b/vim/eclim/doc/404.txt
@@ -0,0 +1,11 @@
+*404*
+
+Page Not Found
+**************
+
+The page you requested does not exist or may have been moved.
+
+You can use the "Site" drop down or the search box in the nav bar
+above to search for your desired topic.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/archive/changes.txt b/vim/eclim/doc/archive/changes.txt
@@ -0,0 +1,1227 @@
+*archive-changes*
+
+Eclim Changes Archive
+*********************
+
+*1.7.2*
+
+
+1.7.2 (Sep. 10, 2011)
+=====================
+
+Bug Fixes:
+ - Various small bug fixes.
+Installer:
+ - Fixed deadlock on the vim install dir pane for java 7.
+Eclipse:
+ - Disabled listening for change events on embedded gvim. Should
+ fix most causes of gvim crashing.
+ - Other improvements for embedded gvim support.
+Eclimd:
+ - Improved OSX detection.
+ - Fix for passing jvm args to java when supplied as args to
+ eclimd script.
+Java:
+ - Fix passing of dash prefixed :Java args (ex. -p) to the class
+ to be run.
+Php:
+ - Improved completion of magic properties.
+ - Support new php 5.3 version in pdt.
+Git Log (1.7.2)
+(https://github.com/ervandew/eclim/compare/1.7.1...1.7.2)
+
+*1.7.1*
+
+
+1.7.1 (Jul. 02, 2011)
+=====================
+
+Bug Fixes:
+ - Fixed org.eclipse.swt.SWTError: Not implemented [multiple
+ displays] error when starting the eclipse gui after running
+ eclimd.
+Eclipse:
+ - Enable vim embedding on Solaris, AIX, and HP-UX versions of
+ eclipse.
+Git Log (1.7.1)
+(https://github.com/ervandew/eclim/compare/1.7.0...1.7.1)
+
+*1.7.0*
+
+
+1.7.0 (Jun. 26, 2011)
+=====================
+
+Bug Fixes:
+ - Bug fixes for eclipse 3.7 (Indigo) compatability.
+ - Other bug fixes.
+Eclipse:
+ - Eclim now requires the latest version of eclipse (Indigo, 3.7).
+Git Log (1.7.0)
+(https://github.com/ervandew/eclim/compare/1.6.3...1.7.0)
+
+*1.6.3*
+
+
+1.6.3 (Apr. 16, 2011)
+=====================
+
+Bug Fixes:
+ - Fixed bug where one or more closed projects would prevent
+ working with open projects.
+ - Other small bug fixes.
+Installer:
+ - Prevent possible OutOfMemoryError when invoking eclipse to
+ install plugin dependencies by setting a larger heap space.
+Java:
+ - Added |:JavaClasspath| to echo the project's current classpath.
+Git Log (1.6.3)
+(https://github.com/ervandew/eclim/compare/1.6.2...1.6.3)
+
+*1.6.2*
+
+
+1.6.2 (Feb. 26, 2011)
+=====================
+
+Bug Fixes:
+ - Fixed to use %USERPROFILE% on windows to retrieve the user home
+ (fixes several possible issues including "Unable to determine
+ your eclipse workspace").
+ - Various other bug fixes.
+Common:
+ - Added rudimentary auto generated menu items for gvim (can be
+ disabled via g:EclimMenus (|vim-core-eclim#g:EclimMenus|)).
+ - Added support for displaying project info (|:ProjectInfo|)
+ vim's status line (contributed by Brendan W. McAdams
+ (http://github.com/bwmcadams)).
+C/C++
+ - Updated context search to greatly improve performance in some
+ cases.
+Python:
+ - Updated all embedded python logic to be compatible with python
+ 2.6 and higher.
+ Note: Support for vim embedded python 2.5 or less no longer
+ supported.
+
+Other:
+ - All relative commands (:SplitRelative, :EditRelative, etc),
+ along with :Split and :Tabnew broken out from eclim to
+ http://github.com/ervandew/relative
+ (http://github.com/ervandew/relative).
+ - Archive viewing support broken out from eclim to
+ http://github.com/ervandew/archive
+ (http://github.com/ervandew/archive).
+ - Maximize/Minimize vim window support broken out from eclim to
+ http://github.com/ervandew/maximize
+ (http://github.com/ervandew/maximize).
+ - Sgml (html, xml, etc.) end tag completion broken out from eclim
+ to http://github.com/ervandew/sgmlendtag
+ (http://github.com/ervandew/sgmlendtag).
+ - Vcs support broken out from eclim to
+ http://github.com/ervandew/vcs (http://github.com/ervandew/vcs).
+ - Taglist support broken out from eclim to
+ http://github.com/ervandew/taglisttoo
+ (http://github.com/ervandew/taglisttoo).
+ - Regex testing support (:JavaRegex, :PythonRegex) broken out
+ from eclim to http://github.com/ervandew/regex
+ (http://github.com/ervandew/regex).
+ - Vim script help lookup along with user defined
+ variable/command/function definition/references lookup support
+ broken out from eclim to http://github.com/ervandew/lookup
+ (http://github.com/ervandew/lookup).
+Git Log (1.6.2)
+(https://github.com/ervandew/eclim/compare/1.6.1...1.6.2)
+
+*1.6.1*
+
+
+1.6.1 (Oct. 23, 2010)
+=====================
+
+Bug Fixes:
+ - Fix for |:ProjectProblems| command when any filters have been
+ set from the eclipse gui.
+ - Merged in JRuby's improvements to nailgun's build scripts to
+ increase compatibility with more platforms.
+ - Updated the installer and eclimd to not use the eclipse binary
+ and instead run the launcher jar directly. Removes the need to
+ locate the binary which varies by platform and some eclipse
+ distributions, and fixes issues with options located in the
+ eclipse.ini that are only supported by the IDE app.
+ - Various other bug fixes.
+Eclim:
+ - Add workspace locking to prevent colliding with other running
+ eclipse instances on the same workspace.
+Common:
+ - Added a :TreeTab command like |:ProjectTab| but for any
+ arbitrary directory.
+ - Added a |:BuffersToggle| command to toggle whether the eclim
+ buffers windows is open or closed.
+ - Refactored Vcs support, including a new :VcsLog layout.
+ Note: Support for cvs and subversion have been discontinued.
+
+Python:
+ - Upgraded included rope version to 0.9.3.
+ - Improved the detection of the completion entries types.
+Php:
+ - Fixed validating php files in eclipse 3.6.1.
+Git Log (1.6.1)
+(https://github.com/ervandew/eclim/compare/1.6.0...1.6.1)
+
+*1.6.0*
+
+
+1.6.0 (Aug. 01, 2010)
+=====================
+
+Bug Fixes:
+ - Several bug fixes for eclipse 3.6 (Helios) compatability.
+ - Various other bug fixes.
+Eclipse:
+ - Eclim now requires the latest version of eclipse (Helios, 3.6).
+Common:
+ - |:ProjectTree| now supports eclipse resource links.
+Git Log (1.6.0)
+(https://github.com/ervandew/eclim/compare/1.5.8...1.6.0)
+
+*1.5.8*
+
+
+1.5.8 (Jun. 26, 2010)
+=====================
+
+Bug Fixes:
+ - Fixed possible NPE during installation when one or more eclim
+ dependent eclipse features needs to be upgraded.
+ - Fixed code completion and search for php as well as search for
+ ruby, all of which were all affected by dltk module caching
+ introduced in galileo SR2.
+Git Log (1.5.8)
+(https://github.com/ervandew/eclim/compare/1.5.7...1.5.8)
+
+*1.5.7*
+
+
+1.5.7 (Jun. 20, 2010)
+=====================
+
+Bug Fixes:
+ - Fixed launching of MacVim from the eclipse gui.
+ - Various other bug fixes.
+Installer:
+ - The installer has undergone some extensive changes to make it
+ more reliable and to better support various environments.
+Git Log (1.5.7)
+(https://github.com/ervandew/eclim/compare/1.5.6...1.5.7)
+
+*1.5.6*
+
+
+1.5.6 (Mar. 06, 2010)
+=====================
+
+Bug Fixes:
+ - Avoid possible gvim crashes when launched from the eclipse gui
+ by disabling documentListen events if the current gvim version
+ doesn't include the patch which resolves the crash.
+ - Various bug fixes.
+Common:
+ - Added a |:ProjectTab| command providing the ability to work on
+ one or more projects each with a dedicated vim tab.
+ - Added a |:Tcd| command to mimic :lcd but local to the tab
+ instead of the window.
+ - Added branch info to the footer of the project tree when using
+ mercurial or git.
+Install:
+ - Added support for automated installs (|installer-automated|).
+Eclim:
+ - Added initial support for using eclim via vim in cygwin.
+ - The eclimd log file has been moved to:
+ <workspace>/.metadata/.log.eclimd
+ - Added support for specifying that gvim should be refocused
+ after executing an eclipse keybinding from vim using
+ eclim#vimplugin#FeedKeys (|FeedKeys|).
+ - Moved user local eclim resources (templates, taglist scripts,
+ etc) from ${vimfiles}/eclim/resources to ~/.eclim/resources.
+ Note: The eclim installer will move your existing files from
+ the old location to the new location, but you may want to back
+ those files up just in case.
+
+Git Log (1.5.6)
+(https://github.com/ervandew/eclim/compare/1.5.5...1.5.6)
+
+*1.5.5*
+
+
+1.5.5 (Feb. 22, 2010)
+=====================
+
+Bug Fixes:
+ - Fixed error using :ProjectTree if the project name has non-word
+ characters in it.
+Install:
+ - Fixed issue downloading content.jar from eclipse update site.
+Git Log (1.5.5)
+(https://github.com/ervandew/eclim/compare/1.5.4...1.5.5)
+
+*1.5.4*
+
+
+1.5.4 (Dec. 18, 2009)
+=====================
+
+Bug Fixes:
+ - Fixed eclim client on OSX.
+ - Fixed backspace key in the |:LocateFile| buffer.
+Common:
+ - Added support for interactively switching scopes from the
+ |:LocateFile| buffer.
+ - Added new search scopes (buffers, quickfix, vcsmodified) to
+ |:LocateFile|.
+Git Log (1.5.4)
+(https://github.com/ervandew/eclim/compare/1.5.3...1.5.4)
+
+*1.5.3*
+
+
+1.5.3 (Dec. 12, 2009)
+=====================
+
+Bug Fixes:
+ - Various bug fixes.
+Install:
+ - Fixed issues properly detecting write permissions on Windows
+ machines.
+Docs:
+ - Added a guide on running eclim on a headless server
+ (|install-headless|).
+Common:
+ - Added full support for running multiple eclimd instances
+ (|eclimd-multiworkspace|), each backed by a separate eclipse
+ workspace.
+ - Added 'K' mapping to |:ProjectTree| to set the tree root the
+ either the project root of file system root depending on the
+ context. Added 'D' mapping to create a new directory and 'F' to
+ open a new or existing file by name. Note: the 'H' mapping to set
+ the tree root to the user's home directory has been changed to
+ '~'.
+ - Added setting to allow |:ProjectTree| instances to be shared
+ across vim tabs.
+ - Updated :VcsWeb to support github, google code, and bitbucket.
+C/C++:
+ - Improved |:CSearchContext| to search for declaration when on a
+ definition, allowing you to jump back and forth between
+ declaration and definition.
+ - Added |:CCallHierarchy| to display the call hierarchy for the
+ function or method under the cursor.
+Java:
+ - Added |:JavaListInstalls| to list all the installed JDKs/JREs
+ that eclipse is aware of.
+Git Log (1.5.3)
+(https://github.com/ervandew/eclim/compare/1.5.2...1.5.3)
+
+*1.5.2*
+
+
+1.5.2 (Aug. 30, 2009)
+=====================
+
+Bug Fixes:
+ - Various bug fixes.
+Eclim:
+ - Added |:ProjectRename| and |:ProjectMove| commands to allow
+ renaming and moving of projects.
+ - Added |:ProjectProblems| command to populate vim's quickfix
+ with a list of all eclipse build errors and warnings for the
+ current and all related projects.
+ Note: To have problems reported for java projects created via
+ eclim, you may need to recreate your java projects to ensure
+ that the java builder is properly added. As of eclim 1.5.2,
+ eclim's java project creation now adds the java builder.
+
+ - Added |:HistoryDiffNext| and |:HistoryDiffPrev| commands to
+ view history diffs while navigating the history stack.
+ - Abbreviation support removed in favor of any one of the third
+ party snippets plugins available on vim.org (snipMate,
+ snippetsEmu, etc.).
+ - Added support for hosting third party nailgun apps in eclim via
+ an ext dir (|eclimd-extdir|).
+Java:
+ - Updated |:JavaImpl|, |:JavaDelegate|, and |:JUnitImpl| to
+ better support generics.
+ - Updated |:JUnitImpl| to support junit 4 method signatures.
+ - Updated |:JavaImport| and :JavaImportSort to honor eclipse's
+ import order preference and added the ability to edit that
+ preference via |:ProjectSettings| and :EclimSettings
+ (|vim-core-eclim#:EclimSettings|).
+ - Added initial refactoring (|vim-java-refactor|) support.
+Git Log (1.5.2)
+(https://github.com/ervandew/eclim/compare/1.5.1...1.5.2)
+
+*1.5.1*
+
+
+1.5.1 (Jul. 18, 2009)
+=====================
+
+Bug Fixes:
+ - Several minor bug fixes.
+Install:
+ - Installation on Mac OSX should hopefully work now without
+ manually creating a symlink to your eclipse executable.
+Eclipse:
+ - Fixed possible NPE when exiting or starting eclipse if a gvim
+ tab was left open.
+Eclim:
+ - Added initial support for linked folders in eclipse projects.
+ - Added new g:EclimValidateSortResults setting to support sorting
+ validation results (java (|vim-java-validate|), c/c++
+ (|vim-c-validate|), php (|vim-php-validate|), etc.) by priority
+ (errors > warnings > etc.).
+C/C++:
+ - Fixed :CSearch results on Windows platforms.
+ - Re-implemented c/c++ project creation.
+ Note: If you created any c or c++ projects via eclim (as
+ opposed to creating the project via the eclipse project
+ wizard), then you are strongly encouraged to recreate those
+ projects using the following steps:
+
+ 1. Delete the project using :ProjectDelete project_name
+ 2. Remove the .cproject file at the root of your project.
+ 3. Re-create the the project using :ProjectCreate
+ /project/path/ -n c (or cpp)
+ After that you will need to re-configure any src or include
+ folders you may have added.
+
+Git Log (1.5.1)
+(https://github.com/ervandew/eclim/compare/1.5.0...1.5.1)
+
+*1.5.0*
+
+
+1.5.0 (Jul. 12, 2009)
+=====================
+
+Bug Fixes:
+ - Many bug fixes and refinements.
+Eclipse:
+ - Eclim now requires the latest version of eclipse (Galileo,
+ 3.5.x).
+Ruby:
+ - Added ruby support for code completion (|vim-ruby-complete|),
+ searching (|vim-ruby-search|), and validation
+ (|vim-ruby-validate|).
+Java:
+ - Added ability to configure java indentation globally via
+ :EclimSettings (|vim-core-eclim#:EclimSettings|) or per project
+ using |:ProjectSettings|.
+Git Log (1.5.0)
+(https://github.com/ervandew/eclim/compare/1.4.9...1.5.0)
+
+*1.4.9*
+
+
+1.4.9 (Jun. 14, 2009)
+=====================
+
+Bug Fixes:
+ - Fixed possible installation issue on Windows.
+ - Various other bug fixes.
+Eclim:
+ - Vimplugin now supports auto starting eclimd view when gvim
+ editor is opened from eclipse.
+ - Handle possible key binding conflicts when using embedded gvim
+ for two common gvim bindings (ctrl-w, ctrl-u).
+Git Log (1.4.9)
+(https://github.com/ervandew/eclim/compare/1.4.8...1.4.9)
+
+*1.4.8*
+
+
+1.4.8 (May 30, 2009)
+====================
+
+Bug Fixes:
+ - Fixed C/C++ element search.
+ - Fixed possible issue with secondary python element search on
+ Windows.
+ - Various other bug fixes.
+Eclim:
+ - Added |:ProjectImport| command.
+Maven
+ - Switched repository searching to a new (hopefully more
+ dependable) site.
+Python:
+ - Added |:PythonSearchContext|.
+Git Log (1.4.8)
+(https://github.com/ervandew/eclim/compare/1.4.7...1.4.8)
+
+*1.4.7*
+
+
+1.4.7 (May 02, 2009)
+====================
+
+Bug Fixes:
+ - Fixed installation error on unix based operating systems.
+Git Log (1.4.7)
+(https://github.com/ervandew/eclim/compare/1.4.6...1.4.7)
+
+*1.4.6*
+
+
+1.4.6 (May 02, 2009)
+====================
+
+Bug Fixes:
+ - Various bug fixes.
+C/C++:
+ - Added c/c++ support for code completion (|vim-c-complete|),
+ searching (|vim-c-search|), and validation (|vim-c-validate|).
+ Requires the eclipse cdt (http://eclipse.org/cdt/) plugin.
+Java:
+ - Added command to run java (|:Java|).
+ - Added command to run javac.
+ - Added command to run javadoc (|:Javadoc|).
+Git Log (1.4.6)
+(https://github.com/ervandew/eclim/compare/1.4.5...1.4.6)
+
+*1.4.5*
+
+
+1.4.5 (Apr. 04, 2009)
+=====================
+
+Bug Fixes:
+ - Fixed pdt and wst code completion when invoked from headed
+ eclimd.
+ - Fixed closing of gvim from eclipse to cleanup swap files.
+ - Fixed python code completion and find support when editing
+ files with dos line endings or multi-byte unicode characters.
+ - Various other bug fixes.
+Eclim:
+ - Added integration with eclipse's local history
+ (|vim-core-history|) support.
+Java:
+ - Added command to view type hierarchy (|:JavaHierarchy|).
+ - Added command to import all undefined types.
+Git Log (1.4.5)
+(https://github.com/ervandew/eclim/compare/1.4.4...1.4.5)
+
+*1.4.4*
+
+
+1.4.4 (Jan. 10, 2009)
+=====================
+
+Bug Fixes:
+ - Various bug fixes.
+Java:
+ - |:Checkstyle| command now creates a project classloader giving
+ checkstyle access to any classes reachable via your project's
+ .classpath file.
+Eclim:
+ - Added the ability to run eclimd inside of eclipse
+ (|eclimd-headed|).
+ - Added support for embedding gvim inside of eclipse
+ (|gvim-embedded|).
+ - eclimd start scripts now available in the eclipse home.
+ - Consolidated the various :LocateFile* commands into a single
+ :LocateFile (|vim-core-locate|) command with a new setting to
+ specify the default means to open a result and various key
+ bindings for opening via other means.
+Php:
+ - Restored php support (|vim-php-index|) via the new eclipse pdt
+ (http://eclipse.org/pdt/) 2.0.
+Vcs:
+ - Added option to set the split orientation (horizontal or
+ vertical) used when executing diffs.
+ - Added option to allow users to change the pattern used to match
+ tracker ticket numbers in :VcsLog.
+Git Log (1.4.4)
+(https://github.com/ervandew/eclim/compare/1.4.3...1.4.4)
+
+*1.4.3*
+
+
+1.4.3 (Nov. 15, 2008)
+=====================
+
+Bug Fixes:
+ - Various bug fixes.
+Installer:
+ - Updated to make use of the new ganymede p2 provisioning system.
+Eclim:
+ - Rewrote :LocateFile* (|vim-core-locate|) commands to provide
+ functionality similar to eclipse's "Open Resource" command or
+ Textmate's "Find in Project".
+Python:
+ - Added support for code completion (|vim-python-complete|).
+ - Added support for finding an element definition
+ (|vim-python-search|).
+ - Improved |:PyLint| support.
+Git Log (1.4.3)
+(https://github.com/ervandew/eclim/compare/1.4.2...1.4.3)
+
+*1.4.2*
+
+
+1.4.2 (Sep. 30, 2008)
+=====================
+
+Bug Fixes:
+ - Fixed obtaining of character offset used by code completion and
+ various other commands.
+ - Fixed possible bug with :JavaCorrect when modifying the file
+ after obtaining a list of suggestions, and then attempting to
+ apply a suggestion that is no longer valid.
+Vcs:
+ - Added support for git to :Vcs commands
+Git Log (1.4.2)
+(https://github.com/ervandew/eclim/compare/1.4.1...1.4.2)
+
+*1.4.1*
+
+
+1.4.1 (Aug. 24, 2008)
+=====================
+
+Bug Fixes:
+ - Fixed determining of project paths outside of the workspace on
+ Windows.
+ - Fixed creation of project inside of the workspace on Windows.
+ - Fixed some issues with code completion, etc. in files
+ containing multi byte characters.
+ - Various other bug fixes.
+Eclim:
+ - Added commands :EclimDisable (|vim-core-eclim#:EclimDisable|)
+ and :EclimEnable (|vim-core-eclim#:EclimEnable|) to temporarily
+ disable, and then re-enable, communication with eclimd.
+Java:
+ - Added |:JavaFormat| command contributed by Anton Sharonov.
+ - Added |:Checkstyle| support.
+Git Log (1.4.1)
+(https://github.com/ervandew/eclim/compare/1.4.0...1.4.1)
+
+*1.4.0*
+
+
+1.4.0 (July 27, 2008)
+=====================
+
+Eclipse:
+ - Eclim now requires the latest version of eclipse (Ganymede,
+ 3.4.x).
+License:
+ - Eclim has switched from the Apache 2 license to the GPLv3.
+Bug Fixes:
+ - Fixed possible issue on Windows determining workspace for users
+ not using the default location.
+ - Fixed sign placement (used by all validation plugins) on
+ non-english vims.
+ - Various other bug fixes.
+Eclim:
+ - Added translation of html docs to vim doc format accessable via
+ :EclimHelp (|vim-core-eclim#:EclimHelp|) and :EclimHelpGrep
+ (|vim-core-eclim#:EclimHelpGrep|).
+ - Added |:Todo| and |:ProjectTodo|.
+ - Added :TrackerTicket for viewing tickets by id in your web
+ based tracking system.
+ - Renamed setting org.eclim.project.vcs.tracker to
+ org.eclim.project.tracker.
+Django:
+ - Added end tag completion (|htmldjango|) support for django
+ templates.
+Php:
+ - Support for php has been temporarily removed until the eclipse
+ pdt team releases a Ganymede (3.4) compatible version.
+Vcs:
+ - Removed :VcsAnnotateOff in favor of invoking :VcsAnnotate again
+ to remove the annotations.
+ - Added vcs editor plugin which allows you to view diff of a file
+ by hitting <enter> on a file name in the cvs, svn, or hg commit
+ editor.
+ - Removed :Trac* and :Viewvc* commands and replaced them with
+ :VcsWeb* commands
+Vim:
+ - Added |:Only| as a configurable alternative to vim's :only
+ command.
+ - Added :OtherWorkingCopyDiff, :OtherWorkingCopyEdit,
+ :OtherWorkingCopySplit, and :OtherWorkingCopyTabopen.
+Git Log (1.4.0)
+(https://github.com/ervandew/eclim/compare/1.3.5...1.4.0)
+
+*1.3.5*
+
+
+1.3.5 (Mar. 11, 2008)
+=====================
+
+Bug Fixes:
+ - Fixed exclusion of plugins not chosen by the user for
+ installation.
+ - Various bug fixes.
+Eclim:
+ - Added an archive (jar, tar, etc.) viewer.
+Html:
+ - Updated html validator to validate <style> and <script> tag
+ contents.
+Vcs:
+ - Added support for limiting the number of log entries returned
+ by :VcsLog (limits to 50 entries by default).
+ - Updated :VcsLog, :VcsChangeSet, etc. to support cvs and hg
+ where applicable.
+Trac:
+ - Added :TracLog, :TracAnnotate, :TracChangeSet, and :TracDiff.
+Git Log (1.3.5)
+(https://github.com/ervandew/eclim/compare/1.3.4...1.3.5)
+
+*1.3.4*
+
+
+1.3.4 (Feb. 05, 2008)
+=====================
+
+Bug Fixes:
+ - Fixed :JavaImpl when adding multi-argument methods.
+ - Various other bug fixes.
+Eclim:
+ - Added |:ProjectInfo|.
+ - Added an eclim/after directory to vim's runtime path for any
+ user scripts to be sourced after eclim.
+Installer:
+ - Updated installer to handle eclipse installs which have a local
+ user install location for plugins.
+ - Fixed some issues with running the installer on the icedtea
+ jvm.
+Php:
+ - Added php support for code completion (|vim-php-complete|),
+ searching (|vim-php-search|), and validation
+ (|vim-php-validate|). Requires the eclipse pdt
+ (http://eclipse.org/pdt/) plugin.
+Git Log (1.3.4)
+(https://github.com/ervandew/eclim/compare/1.3.3...1.3.4)
+
+*1.3.3*
+
+
+1.3.3 (Dec. 15, 2007)
+=====================
+
+Bug Fixes:
+ - Installer bug fixes.
+Git Log (1.3.3)
+(https://github.com/ervandew/eclim/compare/1.3.2...1.3.3)
+
+*1.3.2*
+
+
+1.3.2 (Dec. 04, 2007)
+=====================
+
+Bug Fixes:
+ - Various bug fixes.
+Eclim:
+ - Added commands to view or manipulate project natures:
+ |:ProjectNatures|, |:ProjectNatureAdd|, and
+ |:ProjectNatureRemove|.
+Css:
+ - Added css validation (|css|).
+Html:
+ - Added |:BrowserOpen|
+Html / Xml:
+ - Added auto completion of end tags when typing '</'. This can be
+ disabled by setting g:EclimSgmlCompleteEndTag to 0.
+Java / Python:
+ - :JavaRegex and :PythonRegex now support b:eclim_regex_type to
+ determine if the regex should be applied to the whole sample text
+ at once, or to each line individually.
+Java:
+ - Updated the java logger (|vim-java-logging|) functionality to
+ support a custom logger template.
+Javascript:
+ - Added javascript validation (|vim-javascript-index|) using jsl
+ (http://www.javascriptlint.com/).
+Python:
+ - Added basic python validation (|vim-python-validate|) using
+ pyflakes (http://www.divmod.org/trac/wiki/DivmodPyflakes) and the
+ python compiler.
+ - Added support for pylint (http://www.logilab.org/857) using new
+ |:PyLint| command.
+Vcs:
+ - Added :VcsInfo, :ViewvcAnnotate, :ViewvcChangeSet, and
+ :ViewvcDiff.
+Vcs (subversion):
+ - Added :VcsLog, :VcsDiff, and :VcsCat.
+Vim:
+ - Added vim window maximize and minimize support.
+ - Added an alternate implementation of taglist.
+ - Added command |:Buffers|.
+ - Added :VimgrepRelative, :VimgrepAddRelative, :LvimgrepRelative,
+ :LvimgrepAddRelative, :CdRelative, and :LcdRelative.
+Git Log (1.3.2)
+(https://github.com/ervandew/eclim/compare/1.3.1...1.3.2)
+
+*1.3.1*
+
+
+1.3.1 (July 13, 2007)
+=====================
+
+Bug Fixes:
+ - Fixed eclimd startup issues on non-gentoo linux machines as
+ well as similar issue in the installer when attempting to handle
+ plugin dependencies for wst integration.
+ - Fixed installer to not exclude html/util.vim when not
+ installing wst integrations (fixes dependent code like java code
+ completion).
+Git Log (1.3.1)
+(https://github.com/ervandew/eclim/compare/1.3.0...1.3.1)
+
+*1.3.0*
+
+
+1.3.0 (July 01, 2007)
+=====================
+
+Bug Fixes:
+ - Bug fixes.
+Eclim:
+ - New graphical installer for easing the installation and
+ upgrading procedure.
+ - In previous releases of eclim, any time a command required
+ access to the eclipse representation of a source file, eclim
+ would force a full refresh of the current project to ensure that
+ any external additions, deletions, or changes to other files
+ would be automatically detected. However, this approach, while
+ convenient and transparent to the user, comes with a performance
+ penalty that grows as the project size grows.
+ For some users this performance penalty has been more noticeable
+ than for others. So in response to this feedback, eclim no
+ longer performs an automatic project refresh. What this means
+ for you is that any time you perform an action that results in
+ any file additions, deletions, or changes, like a svn / cvs
+ update, you should issue a |:ProjectRefresh| to ensure that
+ eclipse and eclim are updated with the latest version of the
+ files on disk.
+
+ - |:ProjectCreate| now supports optional -p argument for
+ specifying the project name to use.
+ - Created new command |:ProjectRefreshAll| to support refreshing
+ all projects at once, and modified |:ProjectRefresh| to only
+ refresh the current project if no project names are supplied.
+ - Added |:ProjectGrep|, |:ProjectGrepAdd|, |:ProjectLGrep|, and
+ |:ProjectLGrepAdd|.
+ - Added support for buffer local variable
+ b:EclimLocationListFilter which can contain a list of regular
+ expression patterns used to filter location list entries with
+ text / message field matching one of the patterns. The main
+ intention of this new variable is to allow you to filter out
+ validation errors / warnings per file type, that you wish to
+ ignore.
+ Example which I have in my .vim/ftplugin/html/html.vim file:
+
+ >
+ let b:EclimLocationListFilter = [
+ \ '<table> lacks "summary" attribute'
+ \ ]
+
+ <
+
+Css:
+ - Added css code completion (|css|). Requires the eclipse wst
+ (http://eclipse.org/webtools/main.php) plugin.
+Dtd:
+ - Added dtd validation (|dtd|). Requires the eclipse wst
+ (http://eclipse.org/webtools/main.php) plugin.
+Html:
+ - Added html code completion (|vim-html-index|). Requires the
+ eclipse wst (http://eclipse.org/webtools/main.php) plugin.
+ - Added html validation (|vim-html-index|). Requires the eclipse
+ wst (http://eclipse.org/webtools/main.php) plugin.
+Log4j:
+ - Added log4j xml file validation (|log4j|).
+Python:
+ - Added support for testing regular expressions.
+Django:
+ - Added |:DjangoManage|, |:DjangoFind|, |:DjangoTemplateOpen|,
+ |:DjangoViewOpen|, and |:DjangoContextOpen|.
+WebXml:
+ - Added web.xml file validation (|vim-java-webxml|).
+Vim:
+ - Added :ArgsRelative, :ArgAddRelative, :ReadRelative.
+ - Added |:Sign|, |:Signs|, |:SignClearUser|, |:SignClearAll|.
+Vcs:
+ - Added :VcsAnnotate and :Viewvc.
+Wsdl:
+ - Added wsdl validation. Requires the eclipse wst
+ (http://eclipse.org/webtools/main.php) plugin.
+Xsd:
+ - Added xsd validation (|xsd|). Requires the eclipse wst
+ (http://eclipse.org/webtools/main.php) plugin.
+Xml:
+ - Added xml code completion (|vim-xml-index|). Requires the
+ eclipse wst (http://eclipse.org/webtools/main.php) plugin.
+Git Log (1.3.0)
+(https://github.com/ervandew/eclim/compare/1.2.3...1.3.0)
+
+*1.2.3*
+
+
+1.2.3 (Oct. 08, 2006)
+=====================
+
+Bug Fixes:
+ - Vim scripts now account for possibly disruptive 'wildignore'
+ option.
+ - On Windows, vim scripts account for users who have modified the
+ 'shell' that vim uses, temporarily restoring the default.
+ - Reimplemented :EclimSettings and :ProjectSettings saving to be
+ more fault tolerant.
+ - Several other bug fixes.
+Eclim:
+ - Renamed :Settings to :EclimSettings to increase the uniqueness
+ of the command name in an effort to avoid clashing with other vim
+ plugins.
+Java:
+ - Maven dependency searching now expanded to ivy files via
+ :IvyDependencySearch.
+ - Fixed junit support to handle execution via maven 1.x and 2.x.
+Xml:
+ - Added command |:XmlFormat| to reformat a xml file.
+Git Log (1.2.3)
+(https://github.com/ervandew/eclim/compare/1.2.2...1.2.3)
+
+*1.2.2*
+
+
+1.2.2 (Sep. 08, 2006)
+=====================
+
+Bug Fixes:
+ - Fixed NullPointerException when accessing eclim preferences
+ containing remnant property
+ <code>org.eclim.java.library.root</code>.
+ - Fixed plugin/eclim.vim to check vim version earlier to avoid
+ errors on pre Vim 7 instances.
+ - Fixed all usages of the temp window to account properly for
+ errors.
+Git Log (1.2.2)
+(https://github.com/ervandew/eclim/compare/1.2.1...1.2.2)
+
+*1.2.1*
+
+
+1.2.1 (Sep. 07, 2006)
+=====================
+
+Bug Fixes:
+ - Fixed issues when eclipse is installed in a directory
+ containing a space, like "Program Files".
+ - Fixed error when .classpath src dir is "" or ".".
+ - Fixed error if taglist.vim is not installed.
+ - Fixed auto setting of jre source.
+ - Fixed couple java code completion issues.
+ - Several other bug fixes.
+Ant:
+ - Made some improvements to ant code completion.
+Eclim:
+ - Added support for ~/.eclimrc (|eclimrc|) on unix platforms.
+Java:
+ - Added |:VariableList|, |:VariableCreate| and |:VariableDelete|.
+ - Added camel case searching support: JavaSearch (|:JavaSearch|)
+ NPE
+ - Removed the preference
+ <code>org.eclim.java.library.root</code>.
+ - Updated ivy support (|classpath-ivy|) to behave more like
+ maven.
+ - Added commands to ease setting of classpath repo variables for
+ maven's (|classpath-maven|) and mvn's (|classpath-maven|) eclipse
+ support.
+ - Added TestNG to ant compiler's error format.
+ - Added :JUnitExecute and |:JUnitResult|.
+Xml:
+ - Added |:DtdDefinition| and |:XsdDefinition|.
+Vim:
+ - Added :FindCommandDef and :FindCommandRef.
+ - Changed :FindFunctionVariableContext to :FindByContext.
+ - Added :Tabnew and :TabnewRelative.
+ - :Split and :SplitRelative now support '*' and '**' wildcards.
+Git Log (1.2.1)
+(https://github.com/ervandew/eclim/compare/1.2.0...1.2.1)
+
+*1.2.0*
+
+
+1.2.0 (July 16, 2006)
+=====================
+
+Bug Fixes:
+ - Fixed processing of dtd related xml validation errors on
+ Windows.
+ - Using Ctrl-C on a prompt list (like when choosing a java class
+ to import), stopped working. At some point during the vim 7
+ developement the vim behavor was modified. Eclim, has been fixed
+ to account for this.
+ - Greatly improved support for projects created from eclipse.
+ - Fixed support for projects created from eclipse that reside in
+ the workspace.
+ - Other various bug fixes.
+Eclipse:
+ - Eclim now works with and depends on eclipse 3.2.
+Eclim:
+ - Added |:ProjectRefresh|.
+ - Added |:ProjectOpen|, |:ProjectClose|, and updated
+ |:ProjectList| to show the current status of each project.
+ - Added |:ProjectTree| and |:ProjectsTree|.
+ - Added |:ProjectCD| and |:ProjectLCD|.
+ - Added |:JavaSearchContext|.
+ - Added means to preserve manually added classpath entries when
+ utilizing eclim's integration with ivy or maven dependency files.
+ - Updated |:JavaSearch| to provide sensible defaults if command
+ ommits various arguments. Also added support for supplying only a
+ pattern to the :JavaSearch command which will result in a search
+ for all types (classes, enums, interfaces) that match that
+ pattern.
+ - Added |:Jps| for viewing java process info.
+ - Removed support for auto update of .classpath upon writing of
+ maven project.xml in favor of new maven support.
+ - Added |:Maven| and |:Mvn| commands for executing maven 1.x and
+ 2.x.
+ - Added :MavenDependencySearch and :MvnDependencySearch for
+ searching for and adding dependencies to your maven pom file.
+ - <anchor id="upgrade_1.2.0"/> Re-organized eclim files within
+ the vim runtime path. Based on suggestion by Marc Weber.
+ Warning: This change will require you to remove all the old
+ eclim vim plugins prior to installing the new set. A
+ comprehensive list of plugins to be deleted is provided <a
+ href="upgrade/resources/1.2.0/vim_plugin_list.txt">here</a>.You
+ may also use one of the following scripts to help automate the
+ process. Just download the appropriate file to the directory
+ where you extracted the eclim vim plugins and execute it.
+ Please review the script before executing it so that you are
+ aware of what it does. Please report any issues as well.
+
+ *nix users:
+ <a href="upgrade/resources/1.2.0/upgrade.sh">upgrade.sh</a>
+ Be sure to either make the file executable
+ $ chmod 755 upgrade.sh
+ or run via sh
+ $ sh upgrade.sh
+
+ Windows users:
+ <a href="upgrade/resources/1.2.0/upgrade.bat">upgrade.bat</a>
+ Run via a command prompt so that you can monitor the output.
+
+ After executing either of these scripts you may be left with
+ one or more empty directories which are then safe to delete.I
+ appologize for this inconvience, and hopefully this change will
+ help ease future upgrades.
+
+Vim:
+ - Added :FindFunctionVariableContext to perform context sensitive
+ searching for vim functions or global variables.
+ - Added :Split, :SplitRelative, :EditRelative, :LocateFileEdit,
+ :LocateFileSplit, and :LocateFileTab.
+Git Log (1.2.0)
+(https://github.com/ervandew/eclim/compare/1.1.2...1.2.0)
+
+*1.1.2*
+
+
+1.1.2 (May 07, 2006)
+====================
+
+Bug Fixes:
+ - Fixed eclipse .classpath commands.
+ - Fixed java project update commands to refresh the project
+ resources so that new jars are recognized when added to the
+ .classpath file.
+ - Bug 1437025
+ (https://sourceforge.net/tracker/index.php?func=detail&aid=1437025&group_id=145869&atid=763323)
+ - Bug 1437005
+ (http://sourceforge.net/tracker/index.php?func=detail&aid=1437005&group_id=145869&atid=763323)
+ and other irregularities with calculation of the starting
+ position for the completion.
+ - Bug 1440606
+ (https://sourceforge.net/tracker/index.php?func=detail&aid=1440606&group_id=145869&atid=763323)
+ Note: The original implementation of :JavaImportClean was
+ written entirely in vim (didn't require eclim server). To
+ properly handle ignoring comments when determining what imports
+ are unused, this functionality had to be reimplemented with
+ server side help. However, the vim only version is preserved
+ and will be invoked if the current file is not in an eclipse
+ project.
+
+ - Other various bug fixes.
+Ant:
+ - Added |:Ant| command to allow execution of ant from any file.
+ - Added ant code completion (|vim-java-ant|).
+ - Added ant file validation (|vim-java-ant|).
+ - Added |:AntDoc| command to quickly find ant type / task
+ documentation.
+Java:
+ - Utilizing vim's new dictionary based completion results.
+ - Added |:JavaConstructor|.
+ - |:JavaImpl| now supports overriding constructors.
+ - Added |:JavaDocComment| command to add or update javadocs
+ comment for the element under the cursor.
+ - Added :JavaRegex for testing java regular expressions.
+ - JDT classpath_variables.properties no longer requires system
+ property placeholder to use '_' instead of '.'.
+ - Velocity templates broken up into more logical templates to
+ ease customization.
+ - |:JavaGetSet| now has variable to determine whether or not to
+ add indexed getters and setters.
+ - Removed preference org.eclim.java.validation.ignore.warnings in
+ favor of new g:EclimSignLevel
+ (|vim-core-eclim#g:EclimSignLevel|).
+Vim:
+ - Added couple miscellaneous vim commands for use in or outside
+ of eclim context.
+ - Added groovy script based ctags implementation for use with the
+ vim taglist plugin.
+ - All of the functionality that previously placed results /
+ errors into the quickfix window, now utilizes vim's new location
+ list functionality.
+ - Added web lookup commands.
+ - Added vim script function / global variable searching.
+ - Added vim doc lookup.
+ - Various improvements to 'sign' support for marking errors,
+ warnings, etc.
+Xml:
+ - Xml validation now caches remote entities (like dtds).
+Git Log (1.1.2)
+(https://github.com/ervandew/eclim/compare/1.1.1...1.1.2)
+
+*1.1.1*
+
+
+1.1.1 (Feb. 19, 2006)
+=====================
+
+Bug Fixes:
+ - Code completion results now sorted by type and then
+ alphabetically.
+ - Code corrections that cannot be applied in the standard way
+ (those with no previews) are excluded.
+ - Simple searching from spring / hiberate / web.xml files is
+ fixed.
+ - Java import command is now restricted to the current project.
+ - Java src file location (for almost all java commands) now uses
+ the full path to find the file in eclipse rather than build the
+ path from the file's package declaration and class name. Fixes
+ cases where the package name doesn't match up with the folder
+ structure.
+ - Xml validation errors that occur when no dtd is defined are
+ filtered out (limitation of using xerces to support jdk 1.4).
+ - Relative xml entities are now resolved when validating an xml
+ file.
+ - Fixed logging template code for slf4j.
+ - Fixed possible error when removing signs for marking errors /
+ warnings for the current file.
+ - Fixed |:JavaImport| to not import classes that are in the same
+ package as the current file.
+ - Fixed java source validation to clear out the quickfix results
+ when all errors have been fixed.
+ - Fixed |:JavaImpl| to get the interfaces of superclass lineage
+ in addition to directly implemented interfaces of the current
+ class.
+ - When adding methods from the resulting buffer of |:JavaImpl| or
+ |:JUnitImpl|, if the target class was an inner class of the src
+ file, then the methods were being added to the outer class
+ instead of the inner class.
+ - Fixed javadoc search results to restore <enter> as mapping to
+ open result in a browser after the quickfix window is closed and
+ then opened again.
+ - Other various bug fixes.
+Eclipse:
+ - Eclim now depends on eclispe version 3.1.2. The Eclipse team
+ made some improvements to how inner classes are handled that
+ eclim now depends on.
+Eclim:
+ - Added support for global settings/preferences via new
+ :EclimSettings (|vim-core-eclim#:EclimSettings|) command.
+Java:
+ - Delegate method creation.
+ - Added g:EclimJavaSearchSingleResult setting to determine action
+ to take when only a singe result is returned using the java
+ source code searching. Based on suggestion by Ivo Danihelka.
+ - Added g:EclimJavaDocSearchSingleResult setting to determine
+ action to take when only a singe result is returned using the
+ javadoc searching. Based on suggestion by Ivo Danihelka.
+ - Added preference to suppress warnings when using java source
+ code validation.
+Vim:
+ - Added CursorHold autocommand that shows the current error, if
+ any, on the current cursor line.
+ - Removed global variables g:EclimDebug and g:EclimEchoHighlight
+ in favor of new g:EclimLogLevel
+ (|vim-core-eclim#g:EclimLogLevel|) and the corresponding
+ highlight varibles.
+ - Removed all default key mappings. See the suggested set of
+ mappings.
+ - Now utilizing vim's autoload functionality to load functions on
+ demand.
+ One vim file was moved as a result, so you should delete the old
+ file when upgrading.
+
+ Warning: - ftplugin/java/eclim_util.vim removed.
+
+Git Log (1.1.1)
+(https://github.com/ervandew/eclim/compare/1.1.0...1.1.1)
+
+*1.1.0*
+
+
+1.1.0 (Dec. 26, 2005)
+=====================
+
+Bug Fixes:
+ - Code completion, searching, etc fixed on files with fileformat
+ == 'dos'.
+ - Several other minor fixes and enhancements.
+Java:
+ - Source validation (|vim-java-validate|).
+ - Javadoc (|vim-java-javadoc|) viewing.
+ - Override/Impl (|:JavaImpl|) stub generation.
+ - Bean getter/setter (|:JavaGetSet|) generation.
+ - Junit (|vim-java-unittests|) test method stub generation.
+ - Alternate searching (|vim-java-search|) in code bases outside
+ of an eclipse project.
+ - Code correction (|:JavaCorrect|) via eclipse quickfix
+ functionality.
+ - Support for viewing source files located in archives (zip, jar)
+ when searching.
+ - Support for generating a source prototype when viewing search
+ results that do not have a corresponding source file attached.
+ - Added some handy abbreviations.
+ - Added validation of the .classpath file when saving. Errors
+ are then reported via vim's quickfix.
+Vim:
+ - A few vim scripts were renamed, so you will need to delete the
+ old file when upgrading.
+ Warning: <ul> <li>
+ ftplugin/eclipse_classpath/eclipse_classpath.vim moved to
+ ftplugin/eclipse_classpath/eclim.vim </li> <li>
+ ftplugin/ivy/ivy.vim moved to ftplugin/ivy/eclim.vim </li> <li>
+ ftplugin/maven_project/maven_project.vim moved to
+ ftplugin/maven_project/eclim.vim </li> </ul>
+
+Xml:
+ - Xml validation (|xml-validation|).
+Git Log (1.1.0)
+(https://github.com/ervandew/eclim/compare/1.0.0...1.1.0)
+
+*1.0.0*
+
+
+1.0.0 (Oct. 16, 2005)
+=====================
+
+Eclim:
+ - Initial release.
+Git Log (1.0.0) (https://github.com/ervandew/eclim/commits/1.0.0)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/archive/news.txt b/vim/eclim/doc/archive/news.txt
@@ -0,0 +1,464 @@
+*archive-news*
+
+Eclim News Archive
+******************
+
+
+2011-09-10
+==========
+
+ Eclim 1.7.2 (|1.7.2|) is now available.
+ This version fixes running the installer with java 7 as well as several other
+ small bug fixes and improvements.
+
+I'd also like to announce the #eclim channel on freenode.
+
+
+2011-07-02
+==========
+
+ Eclim 1.7.1 (|1.7.1|) is now available.
+ This is a bug fix release.
+
+
+2011-06-26
+==========
+
+ Eclim 1.7.0 (|1.7.0|) is now available.
+ The most notable changes are:
+
+- Eclim has been upgraded to support Eclipse 3.7 (Indigo).
+ Note: Eclim now requires Eclipse 3.7.
+
+
+2011-04-16
+==========
+
+ Eclim 1.6.3 (|1.6.3|) is now available.
+ This is primarily a bug fix release.
+
+
+2011-02-26
+==========
+
+ Eclim 1.6.2 (|1.6.2|) is now available.
+ This is mostly a bug fix release, but please note that a handful of vim
+ features have been broken out into separate projects and are no longer shipped
+ with eclim.
+
+
+2010-10-23
+==========
+
+ Eclim 1.6.1 (|1.6.1|) is now available.
+ This is mostly a bug fix release with a few minor features tossed in.
+
+
+2010-08-01
+==========
+
+ Eclim 1.6.0 (|1.6.0|) is now available.
+ The most notable changes are:
+
+- Eclim has been upgraded to support Eclipse 3.6 (Helios).
+ Note: Eclim now requires Eclipse 3.6.
+
+
+2010-06-26
+==========
+
+ Eclim 1.5.8 (|1.5.8|) is now available.
+ This is a bug fix release for the installer as well as some php and ruby
+ features.
+
+
+2010-06-20
+==========
+
+ Eclim 1.5.7 (|1.5.7|) is now available.
+ The main focus of this release is bug fixes and improving the installer.
+
+
+2010-03-06
+==========
+
+ Eclim 1.5.6 (|1.5.6|) is now available.
+
+
+2010-02-22
+==========
+
+ Eclim 1.5.5 (|1.5.5|) is now available.
+ This is a bug fix release for the eclim installer.
+
+
+2009-12-18
+==========
+
+ Eclim 1.5.4 (|1.5.4|) is now available.
+ This is primarily a bug fix release for OSX users.
+
+
+2009-12-12
+==========
+
+ Eclim 1.5.3 (|1.5.3|) is now available.
+
+
+2009-08-30
+==========
+
+ Eclim 1.5.2 (|1.5.2|) is now available.
+
+
+2009-07-18
+==========
+
+ Eclim 1.5.1 (|1.5.1|) is now available.
+ This is primarily a bug fix release
+
+
+2009-07-12
+==========
+
+ Eclim 1.5.0 (|1.5.0|) is now available.
+ The most notable changes are:
+
+- Eclim has been upgraded to support Eclipse 3.5 (Galileo).
+ Note: Eclim now requires Eclipse 3.5.
+
+- Ruby support has been added using the eclipse dltk
+ (http://eclipse.org/dltk/).
+
+2009-06-14
+==========
+
+ Eclim 1.4.9 (|1.4.9|) is now available.
+ This is primarily a bug fix release, with a few refinements.
+
+
+2009-05-30
+==========
+
+ Eclim 1.4.8 (|1.4.8|) is now available.
+ This is primarily a bug fix release with a few enhancements.
+
+
+2009-05-02
+==========
+
+ Eclim 1.4.7 (|1.4.7|) is now available.
+ This is a bug fix release which resolves an installation on unix based
+ operating systems.
+
+
+2009-05-02
+==========
+
+ Eclim 1.4.6 (|1.4.6|) is now available.
+ The major highlight of this release is support for c/c++ using the
+ eclipse cdt (http://eclipse.org/cdt/) plugin.
+
+
+2009-04-04
+==========
+
+ Eclim 1.4.5 (|1.4.5|) is now available.
+ This is primarily a bug fix release.
+
+
+2009-01-10
+==========
+
+ Eclim 1.4.4 (|1.4.4|) is now available.
+ Highlights of this release include:
+
+- re-enabled php support
+- added ability to run eclimd inside of eclipse gui
+- added support for embedding gvim in eclipse
+
+2008-11-15
+==========
+
+ Eclim 1.4.3 (|1.4.3|) is now available.
+ This release focuses on updating the installer to support ganymede's p2 for
+ upgrading / installing external dependencies and adding additional python
+ support.
+
+
+2008-09-30
+==========
+
+ Eclim 1.4.2 (|1.4.2|) is now available.
+ This is primary a bug fix release.
+
+
+2008-08-24
+==========
+
+ Eclim 1.4.1 (|1.4.1|) is now available.
+ This is primary a bug fix release, but there are some new features included
+ as well.
+
+
+2008-07-27
+==========
+
+ Eclim 1.4.0 (|1.4.0|) is now available.
+ Please note that eclim now requires the latest version of eclipse (http://eclipse.org)
+ (Ganymede, 3.4.x).
+
+Also note that the eclipse pdt plugin which serves as the base for
+eclim's php support has not yet been released for the latest version
+of eclipse. For this reason php support has been temporarily removed
+from this release and will hopefully return soon after the pdt team
+release a Ganymede (3.4) compatible version.
+
+Another major change worth noting, is that eclim is now licensed under
+the GPLv3. This was done to give eclim the freedom to integrate with
+other GPL projects in the future.
+
+
+2008-03-11
+==========
+
+ Eclim 1.3.5 (|1.3.5|) is now available.
+ You can view the release notes (|release notes|) for
+ more info.
+
+
+2008-02-05
+==========
+
+ Eclim 1.3.4 (|1.3.4|) is now available.
+ This release fixes a few minor bugs, improves the installer to account for
+ eclipse installs with per user plugin locations, and adds php support.
+
+
+2007-12-15
+==========
+
+ Eclim 1.3.3 (|1.3.3|) is now available.
+ This release fixes some installer issues. If you have already installed
+ 1.3.2, then there is no need to upgrade to 1.3.3.
+
+
+2007-12-04
+==========
+
+ Eclim 1.3.2 (|1.3.2|) is now available.
+
+
+2007-07-13
+==========
+
+ Eclim 1.3.1 (|1.3.1|) is now available.
+ This is only a bug fix release.
+
+
+2007-07-01
+==========
+
+ Eclim 1.3.0 (|1.3.0|) is now available.
+ The most notable changes are:
+
+- Eclim has been upgraded to support Eclipse 3.3.
+ Note: Eclim now requires Eclipse 3.3 and JDK 1.5.
+
+- A new graphical installer (|installer|) built on the formic
+ (http://github.com/ervandew/formic/) installer framework.
+- New functionality based on and requiring the eclipse wst
+ (http://eclipse.org/webtools/).
+- Many more changes (|changes|).
+
+2006-10-09
+==========
+
+All Users: A bug made its way into the initial 1.2.3 release which
+prevents you from adding methods via :JavaImpl.
+
+An updated eclim_vim_1.2.3.jar is now available to resolve this issue.
+If you downloaded this file on October 8th or 9th you can either
+download the updated version or execute the following within vim:
+
+>
+
+ :PatchEclim eclim/autoload/eclim/util.vim 1.27
+
+<
+
+
+
+2006-10-08
+==========
+
+ Eclim 1.2.3 is now available.
+ This is primarily a bug fix release.
+
+Please view the release notes (|release notes|) for more info.
+
+
+2006-09-08
+==========
+
+ Eclim 1.2.2 is now available.
+ The previous release introduced two new bugs that managed to slip through the
+ cracks. These have now been fixed including a third that had been around for
+ some time but went previously unnoticed.
+
+To see a list of fixes you may view the release notes (|release
+notes|).
+
+
+2006-09-07
+==========
+
+ Eclim 1.2.1 is now available.
+ This is primarily a bug fix release, but some new functionality has been
+ added as well. This release should resolve all known issues.
+
+To see a list of what's new / changed, be sure to take a look at the
+release notes (|release notes|).
+
+
+2006-07-17
+==========
+
+Windows Users: Eclim 1.2.0 contained a couple issues that can
+potentially prevent eclim from functioning. A new version of
+eclim_vim_1.2.0.jar is now available, which fixes these issues.
+
+Simply download the new file and extract it as explained in the <a
+href="guides/install.html#step3">installation guide</a>. There is no
+need to download or re-install the Eclipse plugins.
+
+If any other issues are encountered please report them.
+
+
+2006-07-16
+==========
+
+ Eclim 1.2.0 is now available.
+ This release requires Eclipse 3.2 (http://eclipse.org/downloads).
+
+To see a list of what's new / changed, be sure to take a look at the
+release notes (|release notes|).
+
+Warning: The layout of eclim plugins within the Vim runtimepath has
+ changed. Please read the <a
+ href="changes.html#upgrade_1.2.0">details</a> in the release notes
+ and take the appropriate action prior to upgrading.
+
+
+2006-05-07
+==========
+
+ Eclim 1.1.2 is now available.
+ Before upgrading, you should upgrade your Vim installation to the stable
+ release of Vim 7.0 or greater.
+
+To see a list of what's new / changed, be sure to take a look at the
+release notes (|release notes|).
+
+
+2006-02-19
+==========
+
+ New version of eclim (1.1.1) is now available.
+ This is mostly a bug fix release will a few new additions.
+ Please note, that this latest version requires Eclipse version 3.1.2 for some
+ bug fixes and improvements.
+
+To see a list of what's new / changed, be sure to take a look at the
+release notes (|release notes|).
+
+
+2005-12-26
+==========
+
+ New version of eclim (1.1.0) is now available.
+ All questions, issues, suggestions are welcome and encouraged.
+
+To see a list of what's new / changed, be sure to take a look at the
+release notes (|release notes|).
+
+
+2005-10-16
+==========
+
+The first eclim release (1.0.0) is now available. All questions,
+issues, suggestions are welcome and encouraged.
+
+Be sure to read the docs to see what features are currently available,
+and take a look at the <a href="todo.html">todo</a> to see what's
+coming in future releases.
+
+
+2005-09-11
+==========
+
+Several new additions over the past couple weeks:
+
+- Java code completion: Integrated into Vim via Vim 7's new "User
+ Defined Completion".
+- Added eclim command line support for creating and updating
+ projects, including Vim support for editing Eclipse .classpath files
+ and updating Eclipse upon writing of those files.
+- Integrated nailgun (http://www.martiansoftware.com/nailgun/) to
+ greatly improve the command line client performance.
+- Started documenting eclim and its features.
+With the addition of these features I'm going to stop adding new
+functionality for the time being and focus on testing and ensuring
+that everything works as expected on Windows.
+
+
+2005-08-21
+==========
+
+Code navigation / searching is done! Most of the Vim integration for
+searching is done as well. The only thing missing is viewing code for
+results that are found in a jar file that have no corresponding source
+attachment. I may end up doing what Eclipse appears to do, which is
+to use javap to display the class and method signatures. That or I'll
+use jad to decompile the whole source. My only issue with jad, is
+that it is not up to date with the 1.5 byte code.
+
+I also have automated importing done as well. The eclim server
+request just returns a list of possible results to import for a given
+request and the editor (Vim in this case) handles prompting the user
+and updating the code.
+
+Note: The Vim integration now requires Vim 7. Even though Vim 7 is
+ still alpha, I haven't had any major issues with it and the new
+ additions to the Vim scripting language are just too good to pass
+ up.
+
+My next step is to start documenting everything and testing on a
+Windows environment to ensure there aren't any compatibility issues.
+
+After that I should be ready to put out a preliminary release. I'm
+trying to be very careful about releasing anything too soon. The last
+thing I want it to scare anyone off with a broken project that doesn't
+seem to work properly.
+
+
+2005-08-11
+==========
+
+Sourceforge site is up! Now it's just a matter of getting the ball
+rolling again.
+
+I'm hoping to have source code navigation working by the end of next
+week. This includes the ability to simply hit <enter> on a class name,
+method name, method call, etc. to jump to its declaration. Basically
+I want to replace my previous Vim plug-in
+(http://www.vim.org/scripts/script.php?script_id=1106) with the new
+Eclipse one.
+
+Before I put out any releases though, I want to have a comprehensive
+set of documentation. For the first few releases, setup will probably
+be pretty manual, with most of it occurring through the Eclipse
+interface. Going forward, I want to move more of that functionality
+into Vim.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/changes.txt b/vim/eclim/doc/changes.txt
@@ -0,0 +1,496 @@
+*changes*
+
+History of Changes
+******************
+
+*1.7.19*
+
+
+1.7.19 (May 07, 2014)
+=====================
+
+Indigo release which includes most of the changes from 2.3.3 and
+2.3.4, excluding the new pydev support. This will most likely be the
+final eclim release for indigo.
+
+ Git Log (1.7.19) (https://github.com/ervandew/eclim/compare/1.7.18...1.7.19)
+ *2.3.4*
+
+
+2.3.4 (Apr. 12, 2014)
+=====================
+
+Project:
+ - Fixed the projects command result on Windows.
+ Git Log (2.3.4) (https://github.com/ervandew/eclim/compare/2.3.3...2.3.4)
+ *2.3.3*
+
+
+2.3.3 (Apr. 06, 2014)
+=====================
+
+Installer:
+ - Fixed running of the installer with Java 8.
+Eclimd:
+ - Starting eclimd in the background is now done using the -b flag
+ instead of passing a start argument.
+ - Eclimd debug logging can now be enabled at startup using the
+ --debug flag.
+Ant:
+ - Fixed ant target completion for newer ant versions (those that
+ require java 5).
+C/C++:
+ - Fixed adding of includes etc. in the C++ sections of
+ :CProjectConfig.
+ - Fixed searching to include macro results.
+ - TODO/FIXME markers are now ignored by validation.
+Html:
+ - Fixed indentation after unclosed <br> and <input> tags.
+Java:
+ - Fixed possible infinite loop when adding imports using
+ :JavaImport.
+ - Fixed an edge case which caused an additional empty line to be
+ added between imports that should be grouped together when using
+ :JavaImport.
+ - Fixed :Java command if the main class has no package
+ declaration.
+ - Fixed issue with large portions of code being re-formatted when
+ applying a correction suggestion.
+ - TODO/FIXME markers are now ignored by validation.
+ - Some of the eclipse java code completion settings are now
+ available via :ProjectSettings.
+Javascript:
+ - Let tern supersede eclim's limited javascript completion.
+Maven/Ivy:
+ - Removed dependency searching since the search provider no
+ longer exists.
+Python:
+ - Eclim's python support been re-written to use pydev instead of
+ rope.
+ Note: Any exiting eclim python projects you have should be
+ re-created with the new python nature:>
+
+ :ProjectCreate /path/to/project -n python
+
+ <
+
+
+Scala:
+ - Disabled use of temp files which could cause some validation
+ errors.
+ - Added support for automated imports (|:ScalaImport|).
+Xml:
+ - Fixed validation of xml files with no dtd/schema to not raise
+ errors on missing dtd for non-english users.
+ Git Log (2.3.3) (https://github.com/ervandew/eclim/compare/2.3.2...2.3.3)
+ *2.3.2* *1.7.18*
+
+
+2.3.2 / 1.7.18 (Sep. 12, 2013)
+==============================
+
+Installer:
+ - Fixed extraction of scala vim files when installing scala
+ support.
+Php:
+ - Fixed completion of php namespaces.
+ Git Log (2.3.2) (https://github.com/ervandew/eclim/compare/2.3.1...2.3.2)
+ Git Log (1.7.18) (https://github.com/ervandew/eclim/compare/1.7.17...1.7.18)
+ *2.3.1*
+
+
+2.3.1 (Jul. 27, 2013)
+=====================
+
+Installer:
+ - Fixed dependencies to point at the Kepler update site.
+ Git Log (2.3.1) (https://github.com/ervandew/eclim/compare/2.3.0...2.3.1)
+ *2.3.0* *1.7.17*
+
+
+2.3.0 / 1.7.17 (Jul. 21, 2013)
+==============================
+
+Java:
+ - :NewJarEntry (|:NewJarEntry_java|) now accepts up to 3
+ arguments allowing you to create the jar entry with the path to
+ the jar, path to the source, and the path to the javadocs.
+ - On javadoc search, all results, including results found in jar
+ files, will be fully translated to usable urls to be opened by
+ vim instead of sending jar results back to eclipse to let it open
+ them. With this change your chosen brower on the vim side will
+ always be used.
+ - Fix for import grouping by package on Kepler.
+Php:
+ Warning: Reminder: The format of the h2 database used for php
+ searching and code completion has changed in Kepler which may
+ result in searching / code completion not returning any results,
+ both in eclim and in the standard eclipse php editor. To fix
+ this you'll need to stop eclipse, remove the old index, and then
+ restart:>
+
+ $ rm -r <your workspace>/.metadata/.plugins/org.eclipse.dltk.core.index.sql.h2/
+
+ <
+
+
+Scala:
+ - Updated to require 3.0.1 of the Scala IDE which now supports
+ Kepler (for eclim 2.3.0 only). Since this version of the Scala
+ IDE seems to only support Scala 2.10.x now, the option to install
+ 2.9.x version has been removed, however the indigo release of
+ eclim (1.7.17) still supports the Scala 2.9.x version of Scala
+ IDE 3.0.0.
+Xml:
+ - |:XmlFormat| now uses the DOM3 APIs to improve the formatted
+ result, honoring your textwidth and indent settings.
+ Git Log (2.3.0) (https://github.com/ervandew/eclim/compare/2.2.7...2.3.0)
+ Git Log (1.7.17) (https://github.com/ervandew/eclim/compare/1.7.16...1.7.17)
+ *2.2.7* *1.7.16*
+
+
+2.2.7 / 1.7.16 (Jul. 14, 2013)
+==============================
+
+Java:
+ - Fix for some completions on Kepler.
+ - Fix for rare case where an invalid classpath entry could result
+ in the .classpath file reverted to the eclipse default.
+ - |:JavaCallHierarchy| added to show the caller or callee
+ hierarchy of a method. Thanks to Alexandre Fonseca.
+Php:
+ Warning: The format of the h2 database used for php searching and
+ code completion has changed in Kepler which may result in
+ searching / code completion not returning any results, both in
+ eclim and in the standard eclipse php editor. To fix this you'll
+ need to stop eclipse, remove the old index, and then restart:>
+
+ $ rm -r <your workspace>/.metadata/.plugins/org.eclipse.dltk.core.index.sql.h2/
+
+ <
+
+
+Ruby:
+ - Fixed the inserted completion text for some ruby libraries.
+Scala:
+ - The graphical installer now includes a compiled eclim sdt
+ bundle for both scala 2.9.x and 2.10.x for which one will be
+ chosen for you if you already have the scala-ide installed,
+ otherwise you can pick one and the appropriate version of the
+ scala-ide will be installed for you.
+Vimplugin:
+ - The option to force focusing of gvim with a simulated click is
+ now disabled by default, but when enabled, it should be less
+ likely to have unintended side affects.
+Cygwin:
+ - Performance optimization for user's with many projects.
+Installer:
+ - The installer will now properly shutdown eclimd instances
+ registered using the old non-json format.
+Docs:
+ - Expanded the developer docs (|development-index|) to include
+ docs on creating new commands (|development-commands|) along with
+ some of the basics for adding new eclim plugins
+ (|development-plugins|).
+ Git Log (2.2.7) (https://github.com/ervandew/eclim/compare/2.2.6...2.2.7)
+ Git Log (1.7.16) (https://github.com/ervandew/eclim/compare/1.7.14...1.7.16)
+ *2.2.6* *1.7.14*
+
+
+2.2.6 / 1.7.14 (May 18, 2013)
+=============================
+
+Bug Fixes:
+ - Fixed eclimd to prevent incorrect addition of -d32 on 64bit
+ systems, which prevents eclimd from starting.
+ - Fix potential conflicts between syntastic validation vs eclim
+ validation (syntastic validation will be diabled if eclim
+ validation is available for the current file type).
+ - Many more fixes.
+Android:
+ - Updated for ADT 22.0.0
+C/C++:
+ - |:CCallHierarchy| now support showing callee tree.
+Java:
+ - |:JavaImpl| now supports anonymous inner classes and will also
+ properly handle suggesting methods from a nested superclass.
+Php:
+ - Eclim will no longer run php files through html validation by
+ default (see the Php Validation (|vim-php-validate|) doc for
+ settings to enable html validation).
+Scala:
+ - Scala support updated for Scala IDE 3.0.0.
+ - Scala now supported on both versions of eclim (Juno and
+ Indigo).
+ Git Log (2.2.6) (https://github.com/ervandew/eclim/compare/2.2.5...2.2.6)
+ Git Log (1.7.14) (https://github.com/ervandew/eclim/compare/1.7.13...1.7.14)
+ *2.2.5* *1.7.13*
+
+
+2.2.5 / 1.7.13 (Nov. 25, 2012)
+==============================
+
+Eclim:
+ - 1.7.13 and above will now support Eclipse 3.8 as well as 3.7.
+ - Fix |:ProjectGrep| and |:ProjectTodo| to search in all of the
+ project's links as well.
+ - Other minor bug fixes.
+ Git Log (2.2.5) (https://github.com/ervandew/eclim/compare/2.2.4...2.2.5)
+ Git Log (1.7.13) (https://github.com/ervandew/eclim/compare/1.7.12...1.7.13)
+ *2.2.4* *1.7.12*
+
+
+2.2.4 / 1.7.12 (Nov. 18, 2012)
+==============================
+
+Eclim:
+ - Updated |:ProjectTree| and |:ProjectTab| to support an
+ arbitrary directory as an argument, allowing you to use the
+ command for project's not managed by eclipse/eclim. :TreeTab has
+ been removed since the update to :ProjectTab makes it redundant.
+ - Creation of projects in nested directories in the eclipse
+ workspace (vs at the root of the workspace) is now properly
+ supported through eclim.
+Android:
+ - Updated for ADT 21.0.0.
+C/C++:
+ - Fix placement of some error markers.
+Php:
+ - Some indentation fixes.
+ Git Log (2.2.4) (https://github.com/ervandew/eclim/compare/2.2.3...2.2.4)
+ Git Log (1.7.12) (https://github.com/ervandew/eclim/compare/1.7.11...1.7.12)
+ *2.2.3* *1.7.11*
+
+
+2.2.3 / 1.7.11 (Oct. 19, 2012)
+==============================
+
+Eclim:
+ - Fixes execution of eclim commands from vim on Windows when
+ using the external nailgun client (vs the python client).
+ Git Log (2.2.3) (https://github.com/ervandew/eclim/compare/2.2.2...2.2.3)
+ Git Log (1.7.11) (https://github.com/ervandew/eclim/compare/1.7.10...1.7.11)
+ *2.2.2* *1.7.10*
+
+
+2.2.2 / 1.7.10 (Oct. 07, 2012)
+==============================
+
+Eclimd:
+ - Updated eclimd script for Linux/OSX to supply reasonable
+ defaults for heap and perm gen space if not already set by
+ ~/.eclimrc.
+C/C++:
+ - Fixed C++ project creation to auto add the required C nature.
+ - Fixed C/C++ issues introduced by the eclipse 4.2.1 release
+ (project create/refresh and call hierarchy).
+Java:
+ - :JavaImportSort, :JavaImportClean, and :JavaImportMissing all
+ removed in favor of a new command which performs the
+ functionality of all three: |:JavaImportOrganize|
+ - The vim option g:EclimJavaImportExclude has been replaced with
+ the eclim setting org.eclim.java.import.exclude
+ (|org-eclim-java-import-exclude|).
+ - The vim option g:EclimJavaImportPackageSeparationLevel has been
+ replaced with the eclim setting
+ org.eclim.java.import.package_separation_level
+ (|org-eclim-java-import-package-separation-level|).
+ - g:EclimJavaBeanInsertIndexed vim variable removed in favor of
+ suffixing :JavaGetSet methods with '!'.
+ - :JavaCorrect, :JavaImpl, :JavaDelegate, :JavaConstructor, and
+ :JUnitImpl all now perform their code manipulations using eclipse
+ operations.
+ - Initial support added for running :JavaSearch commands from
+ source file results (library source files) not in a project.
+ - g:EclimJavaCheckstyleOnSave replaced with the eclim setting
+ org.eclim.java.checkstyle.onvalidate
+ (|org-eclim-java-checkstyle-onvalidate|).
+ - g:EclimJavaSrcValidate renamed to g:EclimJavaValidate.
+ - :JUnitExecute replaced with a new and improved |:JUnit|
+ command.
+ - Added the command |:JUnitFindTest| to open the corresponding
+ test for the current file.
+ - Removed :Javac command since eclipse's continuous incremental
+ builds typically make the :Javac call a no op, and in cases where
+ you need to induce compilation, |:ProjectBuild| does so in a
+ language agnostic way.
+ - Added |:JavaMove| command to move a java source file from one
+ package to another.
+ - Added |:JavaDocPreview| to display the javadoc of the element
+ under the cursor in vim's preview window.
+ Git Log (2.2.2) (https://github.com/ervandew/eclim/compare/2.2.1...2.2.2)
+ Git Log (1.7.10) (https://github.com/ervandew/eclim/compare/1.7.9...1.7.10)
+ *1.7.9*
+
+
+1.7.9 (Sep. 09, 2012)
+=====================
+
+Scala:
+ - Add support for scala code completion (|vim-scala-complete|),
+ code validation (|vim-scala-validate|), and element definition
+ searches (|vim-scala-search|).
+Git Log (1.7.9)
+(https://github.com/ervandew/eclim/compare/1.7.8...1.7.9)
+
+*2.2.1* *1.7.8*
+
+
+2.2.1 / 1.7.8 (Sep. 01, 2012)
+=============================
+
+Documentation:
+ - Redesigned the eclim website using the sphinx bootstrap theme
+ (https://github.com/ervandew/sphinx-bootstrap-theme).
+ - Reorganized many of the docs to consolidate similar features to
+ hopefully make them easier to find and make the docs less
+ sprawling.
+ - Improved the translation of the docs to vim help files.
+Android:
+ - Eclim now has support for creating android projects
+ (|gettingstarted-android|).
+Java:
+ - Fixed searching for JDK classes on OSX.
+ - Added support for searching for inner classes and their
+ methods.
+ - Fixed remaining tab vs spaces indenting related issues with
+ code added via eclipse.
+Vimplugin:
+ - Fixed disabling of conflicting Eclipse keybindings on Juno
+ while the embedded vim has focus (fixes usage of Ctrl+V for
+ blockwise visual selections).
+ Git Log (2.2.1) (https://github.com/ervandew/eclim/compare/2.2.0...2.2.1)
+ Git Log (1.7.8) (https://github.com/ervandew/eclim/compare/1.7.7...1.7.8)
+ *2.2.0* *1.7.7*
+
+
+2.2.0 / 1.7.7 (Aug. 07, 2012)
+=============================
+
+Eclipse:
+ - Eclim 2.2.0 and above now requires Java 6 or later.
+ - Eclim 2.2.0 and above now requires the latest version of
+ eclipse (Juno, 4.2).
+Eclimd:
+ - Updated eclimd script to always set the jvm architecture
+ argument, preventing possible issue starting eclimd on OSX if the
+ default architecture order of the java executable doesn't match
+ the eclipse architecture.
+C/C++:
+ - Semantic errors are now included in the validation results.
+ - Added folding support to C/C++ call hierarchy buffer.
+ - |:ProjectRefresh| now waits on the C/C++ indexer to finish
+ before returning focus to the user.
+ - Fixed auto selecting of the tool chain when creating C/C++
+ projects from eclim.
+ - Fixed |:CCallHierarchy| from possibly using a cached version of
+ the file resulting in incorrect or no results.
+Java:
+ - Fixed inserted code from |:JavaCorrect| when file format is
+ 'dos'.
+ - Fixed off by one issue prevent several code correction
+ suggestions from being suggested.
+Ruby:
+ - Fixed to prompt for the path to the ruby interpreter if
+ necessary when importing a ruby project or adding the ruby nature
+ to an existing project.
+Vimplugin:
+ - Fixed executing of some operations when vim is currently in
+ insert mode (opening new file from eclipse in a new external vim
+ tab, using "Save As" from eclipse, and jumping to a line number
+ from the project tree etc.)
+ Git Log (2.2.0) (https://github.com/ervandew/eclim/compare/1.7.6...2.2.0)
+ Git Log (1.7.7) (https://github.com/ervandew/eclim/compare/1.7.6...1.7.7)
+ *1.7.6*
+
+
+1.7.6 (Jun. 07, 2012)
+=====================
+
+Bug Fixes:
+ - Couple other minor bug fixes.
+Installer:
+ - Fixed install location of eclim's vim help files (broken in the
+ previous release).
+Git Log (1.7.6)
+(https://github.com/ervandew/eclim/compare/1.7.5...1.7.6)
+
+*1.7.5*
+
+
+1.7.5 (Jun. 03, 2012)
+=====================
+
+Note: This release is not compatible with Eclipse Juno (4.2). The
+ next major release of eclim (2.2.0) will be built for Juno.
+
+Installer:
+ - Added uninstall (|uninstall|) support to the eclim installer.
+ - Updated the installer to fully embrace eclipse's provisioning
+ framework (p2).
+Common:
+ - Added |:ProjectTreeToggle|.
+Vimplugin
+ - Fixed key binding conflict handling to not inadvertently switch
+ your key binding scheme back to the default scheme.
+Java:
+ - Added support for importing the necessary type during code
+ completion.
+ - Improved location of a project's main class for the |:Java|
+ command, when not explicitly set.
+Git Log (1.7.5)
+(https://github.com/ervandew/eclim/compare/1.7.4...1.7.5)
+
+*1.7.4*
+
+
+1.7.4 (Apr. 22, 2012)
+=====================
+
+Bug Fixes:
+ - Fixed possible NPE saving eclim settings.
+ - Several other small bug fixes.
+C/C++:
+ - Fixed code completion by disabling the use of temp files.
+Java:
+ - Fixed :Java on windows as well as handling of stdin for ant
+ 1.8.2+.
+Git Log (1.7.4)
+(https://github.com/ervandew/eclim/compare/1.7.3...1.7.4)
+
+*1.7.3*
+
+
+1.7.3 (Mar. 18, 2012)
+=====================
+
+Bug Fixes:
+ - Lots of various bug fixes.
+Common:
+ - Added |:ProjectBuild| to build the current or supplied project.
+ - Updated |:ProjectProblems| to support optional bang
+ (:ProjectProblems!) to only show project errors.
+ - Updating eclipse's local history (|vim-core-history|) when
+ writing in vim is now only enabled by default when gvim is opened
+ from the eclipse gui.
+C/C++:
+ - Fixed project creation issue encountered on some systems.
+Java:
+ - Added project settings for specifying default jvm args for
+ |:Java| and default args for :Javac.
+ - Code inserted by |:JavaConstructor|, |:JavaGetSet|,
+ |:JavaImpl|, |:JavaDelegate|, and |:JUnitImpl| is now formatted
+ according to the eclipse code formatter settings configured from
+ the eclipse gui.
+Maven:
+ - Now when saving your pom.xml file your .classpath will be auto
+ updated (|classpath-maven-pom|) with the dependencies found in
+ your pom.xml.
+Php:
+ - Now handles completion from within php short tags.
+Git Log (1.7.3)
+(https://github.com/ervandew/eclim/compare/1.7.2...1.7.3)
+
+Eclim Changes Archive (|archive-changes|)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/cheatsheet.txt b/vim/eclim/doc/cheatsheet.txt
@@ -0,0 +1,333 @@
+*cheatsheet*
+
+Cheatsheet
+**********
+
+Here you will find a comprehensive list of eclim commands that you can
+use as a reference.
+
+
+Global Commands
+===============
+
+- :PingEclim (|vim-core-eclim#:PingEclim|) - Pings eclimd server.
+- :ShutdownEclim (|vim-core-eclim#:ShutdownEclim|) - Shuts down
+ eclimd server.
+- :EclimSettings (|vim-core-eclim#:EclimSettings|) - View / edit
+ global settings.
+- :EclimDisable (|vim-core-eclim#:EclimDisable|) - Temporarily
+ disables communication with eclimd.
+- :EclimEnable (|vim-core-eclim#:EclimEnable|) - Re-enables
+ communication with eclimd.
+- :EclimHelp (|vim-core-eclim#:EclimHelp|) [helptopic] - View eclim
+ documentation in vim.
+- :EclimHelpGrep (|vim-core-eclim#:EclimHelpGrep|) /regex/ - Search
+ the eclim documentation in vim.
+
+Project Commands
+================
+
+- |:ProjectCreate| <folder> [-p <project_name>] -n <nature> ... [-d
+ <project_dependency> ...] - Create a new project.
+- |:ProjectImport| <folder> - Import a project from an existing
+ eclipse project folder.
+- |:ProjectList| - List current projects.
+- |:ProjectSettings| [<project>] - View / edit project settings.
+- |:ProjectDelete| <project> - Delete a project.
+- |:ProjectRename| [<project>] <name> - Rename a project.
+- |:ProjectMove| [<project>] <dir> - Move a project.
+- |:ProjectRefresh| [<project> <project> ...] - Refresh supplied
+ list of projects against the current files on disk. If no project
+ names supplied, refresh the current project.
+- |:ProjectRefreshAll| - Refresh all projects.
+- |:ProjectBuild| [<project>] - Build the current or supplied
+ project.
+- |:ProjectInfo| [<project>] - Echos info for the current or
+ supplied project.
+- |:ProjectOpen| [<project>] - Opens a project.
+- |:ProjectClose| [<project>] - Closes a project.
+- |:ProjectNatures| [<project>] - View the configured natures for
+ one or all projects.
+- |:ProjectNatureAdd| <project> [<nature> ...] - Add one or more
+ natures to a project.
+- |:ProjectNatureRemove| <project> [<nature> ...] - Remove one or
+ more natures from a project.
+- |:ProjectProblems| [<project>] - Populates vim's quickfix with all
+ eclipse build errors and warnings for the current, or specified
+ project, and all related projects.
+- |:ProjectCD| - Changes the global current working directory to the
+ root directory of the current file's project (executes a :cd).
+- |:ProjectLCD| - Changes the current working directory of the
+ current window to the root directory of the current file's project
+ (executes a :lcd).
+- |:ProjectTree| [<project> <project> ...] - Opens navigable a tree
+ for one or more projects.
+- |:ProjectsTree| - Opens a tree containing all projects.
+- |:ProjectTab| <project> - Opens a new tab containing the project
+ tree and the tab local working directory set to the supplied
+ project's root.
+- |:ProjectGrep| /<pattern>/ file_pattern [file_pattern ...] -
+ Issues a vimgrep starting at the root of the current project.
+- |:ProjectGrepAdd| /<pattern>/ file_pattern [file_pattern ...] -
+ Issues a vimgrepadd starting at the root of the current project.
+- |:ProjectLGrep| /<pattern>/ file_pattern [file_pattern ...] -
+ Issues a lvimgrep starting at the root of the current project.
+- |:ProjectLGrepAdd| /<pattern>/ file_pattern [file_pattern ...] -
+ Issues a lvimgrepadd starting at the root of the current project.
+- |:ProjectTodo| - Searches project files for todo / fixme patterns
+ and adds them to the location list.
+- |:Todo| - Searches the current file for todo / fixme patterns and
+ adds them to the location list.
+
+Android Commands
+================
+
+- |:AndroidReload| - Reloads the Android SDK environment in the
+ running eclimd/eclipse instance. Useful if you've made changes to
+ the SDK outside of eclipse (installed a new target platform, etc).
+
+Ant Commands
+============
+
+- |:Ant| [<target> ...] - Execute ant from the current project.
+- |:AntDoc| [<element>] - Find and open the documentation for the
+ element under the cursor or the element supplied as an argument.
+- :Validate (|:Validate_ant|) - Validate the current ant build file.
+
+C/C++ Commands
+==============
+
+- :Validate (|:Validate_c|) - Validate the current file.
+- |:CSearch| [-p <pattern> -t <type> -s <scope> -x <context>] -
+ Search for classes, functions, methods, macros, etc.
+- |:CSearchContext| - Find the element under the cursor based on its
+ context.
+- |:CProjectConfigs| [project] - Open a temp buffer to view/modify
+ the current projects cdt configurations.
+- |:CCallHierarchy| - Display the call hierarchy for the function or
+ method under the cursor.
+
+Css Commands
+============
+
+- :Validate (|:Validate_css|) - Validate the current file.
+
+Dtd Commands
+============
+
+- :Validate (|:Validate_dtd|) - Validate the current file.
+
+Html Commands
+=============
+
+- :Validate (|:Validate_html|) - Validate the current file.
+- |:BrowserOpen| - Opens the current file in your configured
+ browser.
+
+Ivy Commands
+============
+
+- |:IvyRepo| <path> - Sets the necessary IVY_REPO classpath variable
+ for supporting automatic updates to .classpath files upon ivy.xml
+ updates.
+
+Java Commands
+=============
+
+- |:JavaGet| - Create a java bean getter method.
+- |:JavaSet| - Create a java bean setter method.
+- |:JavaGetSet| - Create both a java bean getter and setter method.
+- |:JavaConstructor| - Creates class constructor, either empty or
+ based on selected class fields.
+- |:JavaCallHierarchy| - Display the call hierarchy for the method
+ under the cursor.
+- |:JavaHierarchy| - View the type hierarchy tree.
+- |:JavaImpl| - View implementable / overridable methods from super
+ classes and implemented interfaces.
+- |:JavaDelegate| - View list of methods that delegate to the field
+ under the cursor.
+- |:JUnit| [testcase] - Allows you to execute junit test cases.
+- |:JUnitFindTest| - Attempts to find the corresponding test for the
+ current source file.
+- |:JUnitImpl| - Similar to :JavaImpl, but creates test methods.
+- |:JUnitResult| [testcase] - Allows you to view the results of a
+ test case.
+- |:JavaImport| - Import the class under the cursor.
+- |:JavaImportOrganize| - Import undefined types, remove unused
+ imports, sort and format imports.
+- |:JavaSearch| [-p <pattern>] [-t <type>] [-x <context>] [-s
+ <scope>] - Search for classes, methods, fields, etc. (With pattern
+ supplied, searches for the element under the cursor).
+- |:JavaSearchContext| - Perform a context sensitive search for the
+ element under the cursor.
+- |:JavaCorrect| - Suggest possible corrections for a source error.
+- |:JavaDocSearch| - Search for javadocs. Same usage as
+ :JavaSearch.
+- |:JavaDocComment| - Adds or updates the comments for the element
+ under the cursor.
+- |:JavaDocPreview| - Display the javadoc of the element under the
+ cursor in vim's preview window.
+- |:JavaRename| [new_name] - Rename the element under the cursor.
+- |:JavaMove| [new_package] - Move the current class/interface to
+ another package.
+- |:Java| - Executes the java using your project's main class.
+- |:JavaClasspath| [-d <delim>] - Echos the project's classpath
+ delimited by the system path separator or the supplied delimiter.
+- |:Javadoc| [file, file, ...] - Executes the javadoc utility
+ against all or just the supplied source files.
+- |:JavaListInstalls| - List known JDK/JRE installs.
+- |:JavaFormat| - Formats java source code.
+- |:Checkstyle| - Invokes checkstyle on the current file.
+- |:Jps| - Opens window with information about the currently running
+ java processes.
+- :Validate (|:Validate_java|) - Manually runs source code
+ validation.
+
+Java .classpath Commands
+========================
+
+- :NewSrcEntry (|:NewSrcEntry_java|) <dir> - Add a new source dir
+ entry.
+- :NewProjectEntry (|:NewProjectEntry_java|) <project> - Add a new
+ project entry.
+- :NewJarEntry (|:NewJarEntry_java|) <file> [<src_path>
+ <javadoc_path>] - Add a jar entry.
+- :NewVarEntry (|:NewVarEntry_java|) <VAR/file> [<src_path>
+ <javadoc_path>] - Add a new var entry.
+- |:VariableList| List available classpath variables and their
+ corresponding values.
+- |:VariableCreate| <name> <path> - Creates or updates the variable
+ with the supplied name.
+- |:VariableDelete| <name> - Deletes the variable with the supplied
+ name.
+
+Javascript Commands
+===================
+
+- :Validate (|:Validate_javascript|) - Validate the current
+ javascript file.
+
+Log4j Commands
+==============
+
+- :Validate (|:Validate_log4j|) - Validate the current log4j xml
+ configuration file.
+
+Maven Commands
+==============
+
+- |:Maven| [<goal> ...] - Execute maven 1.x from the current
+ project.
+- |:Mvn| [<goal> ...] - Execute maven 2.x from the current project.
+- |:MavenRepo| - Sets the necessary MAVEN_REPO classpath variable
+ for maven's (1.x) eclipse support.
+- |:MvnRepo| - Sets the necessary M2_REPO classpath variable for
+ maven's (2.x) eclipse support.
+
+Php Commands
+============
+
+- |:PhpSearch| [-p <pattern> -t <type> -s <scope> -x <context>] -
+ Search for classes, methods, and constants.
+- |:PhpSearchContext| - Find the element under the cursor based on
+ its context.
+- :Validate (|:Validate_php|) - Manually runs source code
+ validation.
+
+Python Commands
+===============
+
+- |:PythonFindDefinition| - Find the element under the cursor.
+- |:PythonSearchContext| - Find the element under the cursor based
+ on its context.
+- :Validate (|:Validate_python|) - Validates the current file using
+ pyflakes (http://www.divmod.org/trac/wiki/DivmodPyflakes).
+- |:PyLint| - Runs pylint (http://www.logilab.org/857) on the
+ current file.
+- |:DjangoManage| - Invokes django's manage.py from any file in the
+ same directory as your manage.py or in any of the child directories.
+- |:DjangoFind| - Available when editing a django html template
+ file. Finds tag/filter definition, other template files, and static
+ files.
+- |:DjangoTemplateOpen| - Available when editing a python file.
+ Finds the template referenced under the cursor.
+- |:DjangoViewOpen| - Available when editing a python file. When
+ within a django url patterns definition, finds the view referenced
+ under the cursor.
+- |:DjangoContextOpen| - Available when editing a python file.
+ Executes :DjangoViewOpen, :DjangoTemplateOpen, or
+ :PythonSearchContext depending on the context of the text under the
+ cursor.
+
+Ruby Commands
+=============
+
+- |:RubySearch| [-p <pattern> -t <type> -s <scope> -x <context>] -
+ Search for modules, classes, methods, etc.
+- |:RubySearchContext| - Find the element under the cursor based on
+ its context.
+- :Validate (|:Validate_ruby|) - Manually runs source code
+ validation.
+- |:RubyInterpreterAdd| [-n <name>] <path> - Add a ruby interpreter.
+- |:RubyInterpreterRemove| <path> - Remove a ruby interpreter.
+- |:RubyInterpreterList| - List the available ruby interpreters.
+
+WebXml Commands
+===============
+
+- :Validate (|:Validate_webxml|) - Validate the current web.xml
+ file.
+
+Xml Commands
+============
+
+- |:DtdDefinition| [<element>] - Open the current xml file's dtd and
+ jump to the element definition if supplied.
+- |:XsdDefinition| [<element>] - Open the current xml file's xsd and
+ jump to the element definition if supplied.
+- :Validate (|:Validate_xml|) [<file>] - Validates the supplied xml
+ file or the current file if none supplied.
+- |:XmlFormat| - Reformats the current xml file.
+
+Xsd Commands
+============
+
+- :Validate (|:Validate_xsd|) - Validate the current file.
+
+Misc. Commands
+==============
+
+- |:LocateFile| [file] - Locates a relative file and opens it.
+- |:Tcd| dir - Like :lcd but sets the tab's local working directory.
+- |:DiffLastSaved| - Performs a diffsplit with the last saved
+ version of the currently modifed file.
+- |:SwapWords| - Swaps two words (with cursor placed on the first
+ word). Supports swapping around non-word characters like commas,
+ periods, etc.
+- |:Sign| - Toggles adding or removing a vim sign on the current
+ line.
+- |:Signs| - Opens a new window containing a list of signs for the
+ current buffer.
+- |:SignClearUser| - Removes all vim signs added via :Sign.
+- |:SignClearAll| - Removes all vim signs.
+- |:QuickFixClear| - Removes all entries from the quick fix window.
+- |:LocationListClear| - Removes all entries from the location list
+ window.
+- |:Buffers| - Opens a temporary window with a list of all the
+ currently listed buffers, allowing you to open or remove them.
+- |:BuffersToggle| - Opens the buffers window if not open, otherwise
+ closes it.
+- |:Only| - Closes all but the current window and any windows
+ excluded by g:EclimOnlyExclude.
+- |:History| - View the local history entries for the current file.
+- |:HistoryClear| - Clear the local history entries for the current
+ file.
+- |:HistoryDiffNext| / |:HistoryDiffPrev| - Diff the current file
+ against the next/previous entry in the history stack.
+- |:RefactorUndo| / |:RefactorRedo| - Undo / Redo the last
+ refactoring.
+- |:RefactorUndoPeek| / |:RefactorRedoPeek| - Display a short
+ description of the refactoring to be undone / redone.
+- |:OpenUrl| [url] - Opens a url in your configured web browser.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/contribute.txt b/vim/eclim/doc/contribute.txt
@@ -0,0 +1,60 @@
+*contribute*
+
+Contribute
+**********
+
+Eclim is a project developed entirely in my spare time, so its growth
+and success can be directly impacted by contributions from the
+community. There are several ways in which you can contribute:
+
+1. Documentation: The documentation can always use improvements.
+ Right now it is written entirely by me, and as such, it may not be
+ as detailed in some areas as it should. What the documentation
+ could really use is some help from its users:
+ - Point out any grammar or spelling errors, since some always
+ manage to slip through.
+ - Point out areas of the documentation that are vague and could
+ use elaboration.
+ - Write new guides to be included in the "Guides" section of the
+ site.
+2. Bug Reports: Some people are a bit shy about speaking up and
+ reporting bugs. I want to urge people not to be. If something
+ doesn't work, report it. It may be a bug, but even if it is just a
+ configuration issue on your end, a misconception on how you thought
+ it should work, or some other quirk specific to your environment,
+ speak up. These can signal that some scripts may need to validate
+ or account for some aspect of the user's environment, or that the
+ documentation may need some work to ensure the user knows what to
+ expect. Any issue that goes unreported, goes unfixed, so please
+ report all issues, big and small.
+3. Feature Requests: On occasion I receive a request or two, but I
+ would like to encourage more people to voice their opinion on what
+ they think should be added or changed in eclim. Once again,
+ nothing is too small to suggest. Chances are, that if you have
+ something that you would like added or changed, there are others
+ out there that would benefit from the same addition or
+ modification.
+ To see what features I have already thought about, you can view my
+ todo list (http://github.com/ervandew/eclim/blob/master/notes.txt).
+
+4. Code Contributions: In addition to reporting bugs or requesting
+ features, you can also take that next step and implement a fix or
+ feature yourself. I just ask that you document your patch
+ accordingly so that I know exactly what you are attempting to fix
+ or add. Also, if you plan to add a medium or large feature, please
+ let me know prior to beginning your work. That way I can keep a
+ small list of who is working on what to avoid any duplication of
+ effort and link people together that wish to work on the same
+ feature. The list would also afford me the ability to contact you
+ should a change to eclim possibly affect what you are working on.
+ If you plan on making any code contributes, please read the
+ developer guide (|development-gettingstarted|) first.
+5. Monetary Contributions: I am not currently accepting any
+ donations. My day job pays well, and I work on eclim for the love
+ of it. If you have money you would like to donate, it would go to
+ much better use if you donated to vim
+ (http://www.vim.org/sponsor/index.php), where it is used to help
+ children in Uganda. Feel free to mention your referral from eclim
+ if appropriate.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/development/architecture.txt b/vim/eclim/doc/development/architecture.txt
@@ -0,0 +1,38 @@
+*development-architecture*
+
+Architecture
+************
+
+The eclim architecture is pretty straight forward. Commands issued by
+a user in vim are relayed via nailgun
+(http://www.martiansoftware.com/nailgun/) to the running eclim daemon
+and the proper command implementation is then located and executed.
+
+Here is a diagram showing the sequence in a bit more detail:
+
+[diagram]
+
+The commands which are executed on the eclimd side are also fairly
+simple. They accept an object containing the command line parameters
+passed into the eclim invocation and then return an object (String,
+Collection, etc) which is converted to a json response. Below is a
+simple class diagram showing the hierarchy of a couple typical
+commands.
+
+[diagram]
+
+Another important aspect of eclim's architecture is support for
+plugins. Plugins for eclim are bundled as eclipse plugins with their
+auto start attribute set to false. When the eclim daemon starts it
+will locate and load any eclipse plugin with an 'org.eclim.' prefix.
+
+When a plugin is loaded, eclim will locate the plugin's required
+resources provider and invoke its initialize method which will then
+inject its resources (messages, command options, etc) into eclim and
+register any new commands.
+
+Here is graphical representation of this process:
+
+[diagram]
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/development/commands.txt b/vim/eclim/doc/development/commands.txt
@@ -0,0 +1,242 @@
+*development-commands*
+
+Commands
+********
+
+For each eclipse feature that is exposed in eclim, there is a
+corresponding command on the daemon which handles calling the
+appropriate eclipse APIs and returning a result back to the client.
+This page will walk you through creating a simple command to
+familiarize you with the process.
+
+
+Creating a Command
+==================
+
+Commands are simple classes which extend AbstractCommand and are
+registered using the @Command annotation. They then define an execute
+method which can return any object that can be serialized
+appropriately using gson (http://code.google.com/p/google-gson/).
+
+Here is an example of a trivial command which returns a map of the
+arguments it was supplied, with the supplied project and file paths
+converted to absolute paths and the file byte offset converted to a
+character offset (eclim's vim function eclim#util#GetOffset() returns
+the offset in bytes since getting a character offset in vim with multi
+byte characters is less reliable, but most eclipse APIs expect
+character offsets):
+
+Note: Eclim's source code is grouped by bundles (org.eclim,
+ org.eclim.core, etc), each of which has java directory containing
+ the java source code for that bundle.
+
+>
+
+ package org.eclim.plugin.core.command.sample;
+
+ import java.util.HashMap;
+
+ import org.eclim.annotation.Command;
+
+ import org.eclim.command.CommandLine;
+ import org.eclim.command.Options;
+
+ import org.eclim.plugin.core.command.AbstractCommand;
+
+ import org.eclim.plugin.core.util.ProjectUtils;
+
+ import org.eclipse.core.resources.IProject;
+
+ @Command(
+ name = "echo",
+ options =
+ "REQUIRED p project ARG," +
+ "REQUIRED f file ARG," +
+ "REQUIRED o offset ARG," +
+ "OPTIONAL e encoding ARG"
+ )
+ public class EchoCommand
+ extends AbstractCommand
+ {
+ @Override
+ public Object execute(CommandLine commandLine)
+ throws Exception
+ {
+ String projectName = commandLine.getValue(Options.PROJECT_OPTION);
+ String file = commandLine.getValue(Options.FILE_OPTION);
+
+ IProject project = ProjectUtils.getProject(projectName);
+
+ // translates client supplied byte offset to a character offset using the
+ // 'project', 'file', 'offset', and 'encoding' command line args.
+ int offset = getOffset(commandLine);
+
+ HashMap<String,Object> result = new HashMap<String,Object>();
+ result.put("project", ProjectUtils.getPath(project));
+ result.put("file", ProjectUtils.getFilePath(project, file));
+ result.put("offset", offset);
+ if (commandLine.hasOption(Options.ENCODING_OPTION)){
+ result.put("encoding", commandLine.getValue(Options.ENCODING_OPTION));
+ }
+
+ return result;
+ }
+ }
+
+<
+
+
+When registering the command with the @Command annotation, you give it
+a name and a comma separated list of options. Each option consists of
+4 parts in the form of:
+
+>
+
+ REQUIRED|OPTIONAL s longname ARG|NOARG|ANY
+
+<
+
+
+Where each part is defined as:
+
+1. REQUIRED or OPTIONAL
+2. a single letter short name for the option
+3. a long name for the option
+4. whether the option requires an argument, no argument, or can
+ have any number of additional arguments. In the case of ANY, you
+ should only have one option with that value and when running the
+ command from the command line, that option should be supplied last.
+That should give you the basics on what's involved with creating a new
+command, but the biggest hurdle for creating most commands is locating
+and deciphering the eclipse API calls that are necessary to implement
+the feature you want. Unfortunately most of the eclipse code that
+you'll need to hook into will most likely have little to no
+documentation so you're going to have to dig through the eclipse code.
+Eclim does provide a couple ant tasks to at least help you to quickly
+extract any docs or source code found in your eclipse install:
+
+- eclipse.doc: This target will extract any doc jars from your
+ eclipse install to a 'doc' directory in your eclipse home (or user
+ local eclipse home).
+- eclipse.src: This target will extract any src jars from your
+ eclipse install to a 'src' directory in your eclipse home (or user
+ local eclipse home). If you download the sdk version of eclipse then
+ the jdt and all the core eclipse source will be available. Some
+ other plugins provide sdk versions which include the source code and
+ this target can extract those as well, but some plugins don't seem
+ to have this option when installing via eclipse's update manager
+ (and may not include the source when installed from a system package
+ manager). For those you can often download a zip version of their
+ update site which should include source bundles. Once you've
+ extracted that file, you can tell this target to extract source
+ bundles from a specified directory. Here is an example of extracting
+ the source from an unpacked dltk update site:
+ >
+ $ ant -Dsrc.dir=/home/ervandew/downloads/dltk-core-5.0.0/plugins eclipse.src
+
+ <
+
+
+Running a Command
+=================
+
+Once you've created your command you then need to compile the code
+using eclim's ant build file. After you've done that you can then
+start eclimd and execute your command from the command line to test
+it:
+
+>
+
+ $ eclim -pretty -command echo -p eclim -f org.eclim.core/plugin.properties -o 42 -e utf-8
+
+<
+
+
+Note: As you are developing your commands, you can avoid restarting
+ eclimd after every change by using eclim's reload command which will
+ reload all of eclim's plugin bundles with the exception of
+ org.eclim.core (so unfortunately it won't help with our example
+ above if we put that command in the org.eclim.core bundle):>
+
+ $ eclim -command reload
+
+ <
+
+
+
+Adding to Vim
+=============
+
+Continuing with our echo command example, we can add the command to
+vim by first defining a new vim command in
+org.eclim.core/vim/eclim/plugin/eclim.vim:
+
+Note: If the command should only be available for a specific file
+ type, then you'd put it in a vim/eclim/ftplugin/somefiltetype.vim
+ file instead.
+
+>
+
+ command EclimEcho :call eclim#echo#Echo()
+
+<
+
+
+Now that we've created the command, we then need to define our
+eclim#echo#Echo() function accordingly in
+org.eclim.core/vim/eclim/autoload/eclim/echo.vim:
+
+>
+
+ " Script Variables {{{
+ let s:echo_command =
+ \ '-command echo -p "<project>" -f "<file>" ' .
+ \ '-o <offset> -e <encoding>'
+ " }}}
+
+ function! eclim#echo#Echo() " {{{
+ if !eclim#project#util#IsCurrentFileInProject(0)
+ return
+ endif
+
+ let project = eclim#project#util#GetCurrentProjectName()
+ let file = eclim#project#util#GetProjectRelativeFilePath()
+
+ let command = s:echo_command
+ let command = substitute(command, '<project>', project, '')
+ let command = substitute(command, '<file>', file, '')
+ let command = substitute(command, '<offset>', eclim#util#GetOffset(), '')
+ let command = substitute(command, '<encoding>', eclim#util#GetEncoding(), '')
+
+ let response = eclim#Execute(command)
+
+ " if we didn't get back a dict as expected, then there was probably a
+ " failure in the command, which eclim#Execute will handle alerting the user
+ " to.
+ if type(response) != g:DICT_TYPE
+ return
+ endif
+
+ " simply print the response for the user.
+ call eclim#util#Echo(string(response))
+ endfunction " }}}
+
+<
+
+
+And that's all there is to it. After re-building eclim, restarting
+eclimd, and restarting vim, you can now execute the command :EclimEcho
+to see the response printed in vim.
+
+Now that you know the basics, you can explore the many existing eclim
+commands found in the eclim source code to see detailed examples of
+how to access various eclipse features to expose them for use in vim
+or the editor of your choice.
+
+You should also take a look at the eclim Plugins
+(|development-plugins|) documentation which documents how to create a
+new eclim plugin, including information on adding new eclim settings,
+managing the plugin's dependencies through its META-INF/MANIFEST.MF,
+etc.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/development/gettingstarted.txt b/vim/eclim/doc/development/gettingstarted.txt
@@ -0,0 +1,268 @@
+*development-gettingstarted*
+
+Developers Guide
+****************
+
+This guide is intended for those who wish to contribute to eclim by
+fixing bugs or adding new functionality.
+
+
+Checking out the code and building it.
+======================================
+
+
+1. Check out the code:
+----------------------
+
+>
+
+ $ git clone git://github.com/ervandew/eclim.git
+
+<
+
+
+Note: If you are still using Eclipse 3.7 (Indigo) you will need to
+ checkout the eclim indigo branch before attempting to build eclim:>
+
+ $ cd eclim
+ $ git checkout indigo
+
+ <
+
+
+
+2. Build eclim:
+---------------
+
+>
+
+ $ cd eclim
+ $ ant -Declipse.home=/your/eclipse/home/dir
+
+<
+
+
+Note: If your eclipse home path contains a space, be sure to quote
+ it:>
+
+ > ant "-Declipse.home=C:/Program Files/eclipse"
+
+ <
+
+
+This will build and deploy eclim to your eclipse and vim directories.
+
+Note: If your vimfiles directory is not located at the default
+ location for your OS, then you can specify the location using the
+ "vim.files" property:>
+
+ $ ant -Dvim.files=<your vimfiles dir>
+
+ <
+
+
+When the build starts, it will first examine your eclipse installation
+to find what eclipse plugins are available. It will then use that list
+to determine which eclim features/plugins should be built and will
+output a list like the one below showing what will be built vs what
+will be skipped:
+
+>
+
+ [echo] ${eclipse}: /opt/eclipse
+ [echo] # Skipping org.eclim.adt, missing com.android.ide.eclipse.adt
+ [echo] # Skipping org.eclim.dltk, missing org.eclipse.dltk.core
+ [echo] # Skipping org.eclim.dltkruby, missing org.eclipse.dltk.ruby
+ [echo] # Skipping org.eclim.pdt, missing org.eclipse.php
+ [echo] Plugins:
+ [echo] org.eclim.cdt
+ [echo] org.eclim.jdt
+ [echo] org.eclim.python
+ [echo] org.eclim.sdt
+ [echo] org.eclim.wst
+
+<
+
+
+In this case we can see that four eclim plugins will be skipped along
+with the eclipse feature that would be required to build those
+plugins. If you see an eclipse feature in that list that you know you
+have, it may be the case that you installed it as a regular user, so
+that feature was installed in your user local eclipse directory. In
+that case you will need to notify the build of that directory so it
+can examine it as well (just replace the <version> portion below with
+the actual version found in your ~/.eclipse directory):
+
+>
+
+ $ ant \
+ -Declipse.home=/opt/eclipse \
+ -Declipse.local=$HOME/.eclipse/org.eclipse.platform_<version>
+
+<
+
+
+If you don't want to supply the eclipse home directory, or any other
+properties, on the command line every time you build eclim, you can
+create a user.properties file at the eclim source root and put all
+your properties in there:
+
+>
+
+ $ vim user.properties
+ eclipse.home=/opt/eclipse
+ vim.files=${user.home}/.vim/bundle/eclim
+
+<
+
+
+Note: The eclim vim help files, used by the :EclimHelp
+ (|vim-core-eclim#:EclimHelp|) command, are not built by default. To
+ build these you first need to install sphinx
+ (http://sphinx-doc.org), then run the following command:>
+
+ $ ant vimdocs
+
+ <
+
+
+ This target also supports the vim.files property if you want the
+ docs deployed to a directory other than the default location.
+
+*coding-style*
+
+
+Coding Style
+============
+
+When contributing code please try to adhere to the coding style of
+similar code so that eclim's source can retain consistency throughout.
+For java code, eclim includes a checkstyle configuration which can be
+run against the whole project:
+
+>
+
+ $ ant checkstyle
+
+<
+
+
+or against the current java file from within vim:
+
+>
+
+ :Checkstyle
+
+<
+
+
+*development-patches*
+
+
+Developing / Submitting Patches
+===============================
+
+The preferred means of developing and submitting patches is to use a
+github fork. Github provides a nice guide to forking
+(http://help.github.com/forking/) which should get you started.
+
+Although using a github fork is preferred, you can of course still
+submit patches via email using git's format-patch command:
+
+>
+
+ $ git format-patch -M origin/master
+
+<
+
+
+Running the above command will generate a series of patch files which
+can be submitted to the eclim development group
+(http://groups.google.com/group/eclim-dev).
+
+
+Building the eclim installer
+============================
+
+It should be rare that someone should need to build the eclim
+installer, but should the need arise here are the instructions for
+doing so.
+
+To build the installer you first need a couple external tools
+installed:
+
+- sphinx (http://sphinx-doc.org): Sphinx is used to build the eclim
+ documentation which is included in the installer.
+ Eclim also uses a custom sphinx theme which is included in eclim as
+ a git submodule. So before you can build the installer you will need
+ to initialize the submodule:
+
+ >
+ $ git submodule init
+ $ git submodule update
+
+ <
+
+- graphviz (http://www.graphviz.org/): The docs include a few uml
+ diagrams which are generated using plantuml
+ (http://plantuml.sourceforge.net/) (included in the eclim source
+ tree) which in turn requires graphviz (http://www.graphviz.org/).
+- formic (http://github.com/ervandew/formic): The eclim installer
+ has been developed using the formic framework, and requires it to
+ build the installer distributables. Formic doesn't currently have
+ an official release, so you'll need to check out the source code:
+ >
+ $ git clone git://github.com/ervandew/formic.git
+
+ <
+
+ After checking out the code, you'll need to build the formic
+ distribution:
+
+ >
+ $ cd formic
+ $ ant dist
+
+ <
+
+ Then extract the formic tar to the location of your choice
+
+ >
+ $ tar -zxvf build/dist/formic-0.2.0.tar.gz -C /location/of/your/choice
+
+ <
+
+Once you have installed the above dependencies, you can then build the
+eclim installer with the following command.
+
+>
+
+ $ ant -Dformic.home=/your/formic/install/dir dist
+
+<
+
+
+In lieu of supplying the formic home on the command line, you can
+instead put it in a user.properties file at the eclim source root:
+
+>
+
+ $ vim user.properties
+ formic.home=/your/formic/install/dir
+
+<
+
+
+
+What's Next
+===========
+
+Now that you're familiar with the basics of building and patching
+eclim, the next step is to familiarize yourself with the eclim
+architecture and to review the detailed docs on how new features are
+added.
+
+All of that and more can be found in the eclim development docs
+(|development-index|).
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/development/index.txt b/vim/eclim/doc/development/index.txt
@@ -0,0 +1,21 @@
+*development-index*
+
+Development Docs
+****************
+
+Developers Guide (|development-gettingstarted|)
+
+Architecture (|development-architecture|)
+ Explains the underlying architecture that eclim utilizes including
+ an overview of the call sequence from vim to eclipse.
+
+Commands (|development-commands|)
+ Details the process of adding a new command to vim which calls to a
+ corresponding implementation in eclipse.
+
+Plugins (|development-plugins|)
+ Details the process of adding a new plugin to eclim.
+
+... More To Come
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/development/plugins.txt b/vim/eclim/doc/development/plugins.txt
@@ -0,0 +1,226 @@
+*development-plugins*
+
+Plugins
+*******
+
+Note: This guide is a work in progress. If in the process of writing
+ a new plugin you find anything here that is unclear or missing,
+ please don't hesitate to post to the eclim-dev
+ (http://groups.google.com/group/eclim-dev) mailing list with
+ questions, suggestions, etc.
+
+To allow eclim to support different languages, eclim is broken up into
+eclipse plugins, each of which depend on a corresponding eclipse
+feature which provides support for that language. When you install or
+build eclim, it will examine your eclipse install to determine which
+features are available and will add the corresponding eclim plugins to
+expose those features. This page documents the core aspects of what
+goes into the creation of a new eclim plugin.
+
+
+Bootstrapping the plugin artifacts
+==================================
+
+Eclim includes a set of templates to help you bootstrap a new plugin.
+To utilize them you can run the following ant target:
+
+>
+
+ $ ant plugin.create
+
+<
+
+
+You will be prompted to enter a name for this plugin along with some
+guidelines on choosing an appropriate name.
+
+Once you've chosen a name, the plugin's directory structure will be
+created and populated with bare bones version of the required
+artifacts. Eclim's build.xml file will also be updated to include a
+target to the new plugin's unit test target.
+
+
+Updating the initial artifacts
+==============================
+
+After you've bootstrapped your plugin, you can now start updating the
+generated artifacts:
+
+
+build_<plugin_name>.gant
+------------------------
+
+The first file you'll need to modify is a gant file for your plugin.
+The main eclim build.gant script will load this file during the build
+process to determine what the plugin's eclipse dependency is, so it
+knows whether it can be built against the target eclipse install. So
+the first thing we need to do is to fill in that information by
+updating the feature_<plugin_name> variable with the name of the
+eclipse feature that this plugin depends on. For example, the eclim
+jdt plugin has this set to 'org.eclipse.jdt'. The build script will
+look in the features directory of your eclipse install (including the
+dropins and your user local eclipse dir if set), to find this feature,
+so the value you set, must be found in one of those locations (the
+version suffixes will be removed from the features in order to match
+it against the value you've set).
+
+You'll also notice that there is a unit test target in the gant file.
+You can ignore that for now.
+
+
+META-INF/MANIFEST.MF
+--------------------
+
+The next file to note is the plugin's META-INF/MANIFEST.MF. This is
+the file that eclipse will use to determine how to load the bundle and
+what to include in its classpath. The only part of this file that you
+should edit is the Require-Bundle: section. This is a comma separated
+list of bundles (or plugins) which this bundle depends on. When this
+bundle is loaded only those bundles listed here will be available in
+the classpath. So when you start running commands you've written
+later, if you receive a ClassNotFoundException, that is likely due to
+the bundle containing that class not being listed in your plugin's
+Require-Bundle: list. At this point you probably don't know yet what
+bundles you need to add to this list. When you start writing commands
+for your plugin, you'll have to find out which bundles contain the
+classes imported from the eclipse plugin you are integrating with, and
+you'll need to add those bundles accordingly.
+
+It's also worth noting that eclim provides a custom classpath
+container which scans the manifest of each eclim plugin and loads the
+required bundles of each into the classpath. So when adding new
+bundles, if you want validation, search, code completion, etc to work
+with classes from those new bundles, you'll have to restart the eclim
+daemon. While restarting can be annoying, this is generally better
+than having to add/remove entries from the .classpath file or worrying
+about one user having different bundle version numbers from another.
+
+
+PluginResources.java
+--------------------
+
+At this point you'll typically need to start customizing your plugin's
+org.eclim.<name>/java/org/eclim/plugin/<name>/PluginResources.java
+file. Here is where you will map a short alias to the project nature,
+or natures, of the plugin you are integrating with, register a project
+manager for initializing project's for this plugin, register any
+plugin settings that users can configure, etc. You'll be doing all
+this inside of the initialize method which has been generated for you.
+
+
+Project Nature
+~~~~~~~~~~~~~~
+
+You'll first need to find out where the plugin's nature id is defined.
+Here are some examples that should give you an idea of where to look:
+
+- jdt: org.eclipse.jdt.core.JavaCore.NATURE_ID
+- cdt:
+ - org.eclipse.cdt.core.CProjectNature.CNATURE_ID
+ - org.eclipse.cdt.core.CCProjectNature.CC_NATURE_ID
+- dltkruby: org.eclipse.dltk.ruby.core.RubyNature.NATURE_ID
+- adt: com.android.ide.eclipse.adt.AdtConstants.NATURE_DEFAULT
+One way to find it is to open up the .project file in a project
+containing the nature, locate the fully qualified name in the
+<natures> section, then grep the plugin's code for that name.
+
+Once you have the reference to the nature id, you can then create a
+public static variable called NATURE:
+
+>
+
+ public static final String NATURE = SomeClass.NATURE_ID;
+
+<
+
+
+You'll be using this constant as the key to register features for
+project containing this nature, but first we'll register a short alias
+for this nature since the actual nature id tends to be long and
+unstandardized, and we don't want users to have to type it out when
+creating projects from eclim:
+
+>
+
+ ProjectNatureFactory.addNature("shortname", NATURE);
+
+<
+
+
+
+Project Manager
+~~~~~~~~~~~~~~~
+
+The next thing you'll probably need to do is to create a project
+manager for your project
+(org.eclim.<name>/java/org/eclim/plugin/<name>/project/SomeProjectManager.java).
+The project manager is responsible for performing any post create,
+update, delete, or refresh logic required for projects of this nature.
+This logic can include things such as creating an initial
+classpath/buildpath, validate the classpath/buildpath on update,
+forcing a full update of the search index on refresh, or any number of
+other things.
+
+Overriding the create method will almost certainly be necessary, but
+the logic you'll need here varies widely. Finding what you'll need is
+a matter of digging through the parent plugin's source code, typically
+looking for the project creation wizard class, to see what it does to
+create a project of this nature and later comparing the created
+artifacts from your code against those of a project created from the
+eclipse gui. This can be a difficult hurdle to get past for someone
+doing this the first time, so please don't be shy about asking for
+help on the eclim-dev (http://groups.google.com/group/eclim-dev)
+mailing list.
+
+Eclim does provide a couple ant tasks to at least help you to quickly
+extract any docs and source code found in your eclipse install:
+
+- eclipse.doc: This target will extract any doc jars from your
+ eclipse install to a 'doc' directory in your eclipse home (or user
+ local eclipse home).
+- eclipse.src: This target will extract any src jars from your
+ eclipse install to a 'src' directory in your eclipse home (or user
+ local eclipse home). If you download the sdk version of eclipse then
+ the jdt and all the core eclipse source will be available. Some
+ other plugins provide sdk versions which include the source code and
+ this target can extract those as well, but some plugins don't seem
+ to have this option when installing via eclipse's update manager
+ (and may not include the source when installed from a system package
+ manager). For those you can often download a zip version of their
+ update site which should include source bundles. Once you've
+ extracted that file, you can tell this target to extract source
+ bundles from a specified directory. Here is an example of extracting
+ the source from an unpacked dltk update site:
+ >
+ $ ant -Dsrc.dir=/home/ervandew/downloads/dltk-core-5.0.0/plugins eclipse.src
+
+ <
+
+Once you've created your project manager, you then map it to your
+plugin's nature inside of your PluginResources.initialize method like
+so:
+
+>
+
+ ProjectManagement.addProjectManager(NATURE, new SomeProjectManager());
+
+<
+
+
+
+Project Settings
+~~~~~~~~~~~~~~~~
+
+At this point you should have the minimum of what is needed for a new
+plugin. Hopefully you can now create new projects with your plugin's
+defined nature. The next step would be to start adding commands
+(|development-commands|) to provide validation, code completion, etc.
+The remaining items in this list are not required to continue. They
+provide you with the ability to setup your own preferences or to
+expose the parent plugin's defined preferences inside of vim. When
+you've come to the point that you need to work with preferences, then
+feel free to come back here and continue reading.
+
+To Be Continued...
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/eclimd.txt b/vim/eclim/doc/eclimd.txt
@@ -0,0 +1,434 @@
+*eclimd*
+
+The Eclim Daemon
+****************
+
+*eclimd-headless*
+
+
+Headless eclipse server
+=======================
+
+The most mature usage scenario that eclim provides, is the running of
+a headless eclipse server and communicating with that server inside of
+vim. Starting and stopping of the headless eclipse instance is
+detailed below.
+
+Starting eclimd
+
+Linux / Mac / BSD (and other unix based systems): To start eclimd from
+linux, simply execute the eclimd script found in your eclipse root
+directory: $ECLIPSE_HOME/eclimd
+
+Note: When starting the eclim daemon, you must start it as the same
+ user who will be running vim.
+
+Windows: The easiest way to start eclimd in windows is to double click
+on the eclimd.bat file found in your eclipse root directory:
+%ECLIPSE_HOME%/eclimd.bat
+
+Note: Even though an eclipse gui is not started in eclim's headless
+ mode, eclipse still requires a running X server to function. To run
+ eclimd on a truely headless server, please see the headless guide
+ (|install-headless|).
+
+Stopping eclimd
+
+To cleanly shutdown eclim use any one of the following.
+
+- From Vim:
+ >
+ :ShutdownEclim
+
+ <
+
+- From a console:
+ >
+ $ $ECLIPSE_HOME/eclim -command shutdown
+
+ <
+
+- Lastly you can use Ctrl-C at the console if you are running eclimd
+ in the foreground, or issue a kill to the eclimd java process.
+ >
+ $ kill *pid*
+
+ <
+
+ You will need to kill the java process since killing the eclimd or
+ eclipse process will not do so. While eclim provides a shutdown
+ hook to support a clean shutdown when the java process is killed in
+ this manner, it is still recommended that you utilize one of the
+ first two methods instead, and reserve this as a last resort. Also
+ note that when killing the java process eclipse will pop up an alert
+ dialog notifying you that the java process was terminated underneath
+ it. This is nothing to be alarmed about.
+
+*eclimd-headed*
+
+
+Headed eclipse server
+=====================
+
+For users that find themselves periodically needing the eclipse gui,
+or otherwise wanting to keep the gui open while using eclim, there is
+support for running the eclim server inside of a headed eclipse
+instance.
+
+Starting eclimd
+
+The eclim daemon inside of eclipse is implemented as an eclipse view
+which can be found via:
+
+Window ‣ Show View ‣ Other ‣ Eclim ‣ eclimd
+
+The view will be opened in a new tab in the same pane as the
+"Problems" tab, as shown below.
+
+[image]
+
+Note: By default, if you open an instance of gvim from within
+ eclipse, the eclimd view will be opened for you if necessary. This
+ behavior is configurable via the Vimplugin preferences.
+
+Stopping eclimd
+
+As long as the eclimd tab is open then the eclim daemon will be
+running. Stopping the eclim daemon is just a matter of closing the
+eclimd tab. Also note that leaving the tab open and closing eclipse
+will shutdown the daemon as well, and on the next start of eclipse the
+tab will be opened, but the eclim daemon will not start until the tab
+is forced to display itself. In other words, the daemon will not start
+until the eclimd tab is the active tab in that group.
+
+*gvim-embedded*
+
+
+Embedded gvim
+=============
+
+Note: Embedding is only supported on Windows and Unix systems (where
+ gvim is compiled with the gtk gui).Embedding of macvim for OSX is
+ not supported since macvim does not currently have the ability to be
+ embedded like gvim. Macvim can still be used to open files from
+ eclipse, but macvim will open as an external editor. Also note that
+ macvim snapshots 56 through 63 contain a bug
+ (https://github.com/b4winckler/macvim/pull/22) where opening a file
+ from eclipse will open an instance of macvim, but the file will not
+ be loaded into that instance.
+
+Another feature provided by eclim for those who prefer to work inside
+of the eclipse gui, is the embedding of gvim inside of eclipse. This
+feature is provided by an eclim local fork of vimplugin
+(http://vimplugin.org). The feature adds a new editor to eclipse
+which allows you to open files in gvim by right clicking the file name
+in the eclipse tree and then selecting:
+
+Open With ‣ Vim
+
+[image]
+
+Please note that if you want to use supported eclipse features (code
+completion, validation, searching, etc.) from the embedded gvim
+editor, you must have the eclimd view open.
+
+Note: If you'd like to have the embedded gvim editor as the default
+ for one or more file types, you can configure it to be in your
+ eclipse preferences:Window ‣ Preferences ‣ General ‣ Editors ‣ File
+ Associations
+
+The eclim installer should take care of locating your gvim
+installation for use inside of eclipse, but in the event that it could
+not locate it, you can set the location and other settings via the
+vimplugin preferences:
+
+Window ‣ Preferences ‣ Vimplugin
+
+For MacVim users on OSX, the eclim installer will attempt to locate
+MacVim's mvim script on your path. If it's not found you can set the
+location of that script in the Vimplugin preferences:
+
+Eclipse ‣ Preferences ‣ Vimplugin
+
+Note: If you have a non-eclim version of vimplugin installed you
+ should remove it prior to using the eclim version.
+
+Note: Some users have reported issues with the embedded gvim's
+ command line being cut off or possible rendering issues when
+ scrolling through the file. If you experience either of these
+ issues, try adding the following to your vimrc file, which should
+ hopefully resolve those problems:>
+
+ set guioptions-=m " turn off menu bar
+ set guioptions-=T " turn off toolbar
+
+ <
+
+
+ Additionally, some users have reported that gvim's left scrollbar
+ may also need to be disabled:>
+
+ set guioptions-=L " turn off left scrollbar
+ set guioptions-=l
+
+ <
+
+
+*eclim-gvim-embedded-focus*
+
+Embedded gvim focus
+
+In some windowing environments, the embedded gvim is treated more like
+a separate window. The result of this is that clicking the eclipse tab
+(or using tab focusing keyboard shortcuts) may focus that tab, but it
+won't focus the embedded gvim on that tab. Eclim adds a setting to
+vimplugin which when enabled, will attempt to simulate a click on the
+embedded gvim window to force it to focus:
+
+Window ‣ Preferences ‣ Vimplugin ‣ Force gvim focus via automated
+click
+
+*eclim-gvim-embedded-shortcuts*
+
+Eclipse/Vim key shortcuts in embedded gvim
+
+Depending on your OS and windowing system, when the embedded gvim has
+focus, you will fall into one of two groups:
+
+1. In the first group of users, all key presses are received by
+ eclipse prior to sending them to gvim.
+ For this group, when typing a possible key shortcut (ctrl-n for
+ example), eclipse will first evaluate that key stroke to see if
+ there are any eclipse key bindings registered. If there are, then
+ eclipse will run the associated command and the key stroke is never
+ sent to gvim. If no key binding is found, then eclipse will pass
+ the key stroke through to gvim. What this means for you is that
+ for any gvim key mappings that you use that have an eclipse key
+ binding, they will not be evaluated inside of gvim. So, if you
+ encounter this issue, you'll need to remap the keys in vim or
+ eclipse. To remove the key binding from the eclipse side, simply
+ open the "Keys" preferences page:
+
+ Window ‣ Preferences ‣ General ‣ Keys
+
+ Then find the entry in the list that corresponds with the key
+ binding you want to remove, select it, and hit the "Unbind Command"
+ button.
+
+ Note: By default eclim will auto-remove a couple of the standard
+ eclipse bindings whenever an embedded gvim editor has focus and
+ then restore them with a non-gvim editor gains focus:
+
+ - Ctrl+U: in eclipse this runs "Execute", but in gvim this is
+ needed to run code completion (ex. ctrl-x ctrl-u).
+ - Ctrl+N: in eclipse this runs the "New" wizard, but in gvim
+ this is also needed as a part of code completion, to scroll
+ through the results.
+ - Ctrl+V: in eclipse this pastes text from the clipboard
+ (though not into gvim), but in gvim this is needed for column
+ wise visual selections.
+ - Ctrl+W: in eclipse this closes a tab, but in gvim this is
+ needed to switch windows (ex. ctrl-w j).
+ - Ctrl+X: in eclipse this cuts a selection to the clipboard,
+ but in gvim this is needed to start various insert completions
+ (ex. ctrl-x ctrl-u).
+*FeedKeys*
+
+2. In the second group, all key presses are received by gvim and
+ not evaluated at all by eclipse.
+ For this group of users, you may have an eclipse key shortcut that
+ you like to use (Shift+Ctrl+R for example), but when you hit that
+ key combination, it will be evaluated by gvim instead of eclipse.
+ To remedy this situation, eclim provides a means to map eclipse
+ shortcuts inside of gvim. To register a shortcut, simply add your
+ mappings to your vimrc, gvimrc, or other standard gvim file like
+ so:
+
+ >
+ " maps Ctrl-F6 to eclipse's Ctrl-F6 key binding (switch editors)
+ nmap <silent> <c-f6> :call eclim#vimplugin#FeedKeys('Ctrl+F6')<cr>
+
+ " maps Ctrl-F7 to eclipse's Ctrl-F7 key binding (switch views)
+ nmap <silent> <c-f7> :call eclim#vimplugin#FeedKeys('Ctrl+F7')<cr>
+
+ " maps Ctrl-F to eclipse's Ctrl-Shift-R key binding (find resource)
+ nmap <silent> <c-f> :call eclim#vimplugin#FeedKeys('Ctrl+Shift+R')<cr>
+
+ " maps Ctrl-M to eclipse's Ctrl-M binding to maximize the editor
+ nmap <silent> <c-m> :call eclim#vimplugin#FeedKeys('Ctrl+M', 1)<cr>
+
+ <
+
+ The value supplied to the FeedKeys function must be an eclipse
+ compatible key binding string as found in:
+
+ Windows ‣ Preferences ‣ General ‣ Keys
+
+ Be sure to notice the extra argument to the FeedKeys function in
+ the last mapping. Supplying 1 as the arg will result in the
+ refocusing of gvim after the eclipse key binding has been executed.
+
+*eclimrc*
+
+
+~/.eclimrc
+==========
+
+On unix platforms (linux, mac, bsd) eclim supports an optional
+.eclimrc file located in your home directory. In this file you may
+supply any system properties or vm args which you would like passed to
+eclimd at startup. The format of this file is the same as the
+standard java properties file format with the exception of any vm args
+which you would like to include.
+
+Ex.
+
+>
+
+ # Bind eclimd to all interfaces
+ nailgun.server.host=0.0.0.0
+
+ # Specifies the port that nailgun / eclimd listens on for client requests.
+ nailgun.server.port=10012
+
+ # Specifies the workspace directory to use
+ # See $ECLIPSE_HOME/configuration/config.ini for other osgi properties.
+ osgi.instance.area.default=@user.home/myworkspace
+
+ # increase heap size
+ -Xmx256M
+
+ # increase perm gen size
+ -XX:PermSize=64m
+ -XX:MaxPermSize=128m
+
+<
+
+
+The eclim client will also utilize this file, but only to determine
+the nailgun server port should you choose to change the default.
+
+Note: Your system must have perl and sed available so that eclim can
+ process your .eclimrc file.
+
+Both the eclim and eclimd scripts also support a -f argument allowing
+you to specify an alternate location for your .eclimrc:
+
+>
+
+ $ eclimd -f ~/.my_eclimrc
+ $ eclim -f ~/.my_eclimrc -command ping
+
+<
+
+
+
+eclimd logging
+==============
+
+Eclimd utilizes log4j for all of its logging. As such, the logging
+can be configured via the
+$ECLIPSE_HOME/plugins/org.eclim_version/log4j.xml file.
+
+By default, eclimd writes all logging info to both the console and to
+a log file in your workspace: <workspace>/eclimd.log
+
+*eclimd-multiworkspace*
+
+
+Multiple Workspaces
+===================
+
+Running eclim against more than one eclipse workspace can be
+accomplished by running multiple eclimd instances. You must configure
+each instance to run nailgun on a unique port and supply the path to
+the workspace you which that instance to use. Once your eclimd
+instances are up and running the vim client will automatically
+determine which server to send requests to based on your context. In
+some cases you may be prompted for which workspace to use if one
+cannot be determined for you.
+
+Below are some different ways in which you can configure your eclimd
+instances:
+
+1. All Users: Supply the nailgun port and eclipse workspace path
+ when starting eclimd:
+ >
+ $ eclimd -Dosgi.instance.area.default=@user.home/workspace1 -Dnailgun.server.port=9091
+ $ eclimd -Dosgi.instance.area.default=@user.home/workspace2 -Dnailgun.server.port=9092
+
+ <
+
+ If you are using the eclimd view in the eclipse gui, then you can
+ start the eclipse gui with the desired nailgun server port (note
+ that you must place the -vmargs option before the list of jvm
+ arguments):
+
+ >
+ $ eclipse -vmargs -Dnailgun.server.port=9092
+
+ <
+
+2. Linux, OSX, BSD Users: Specify the port and workspace in eclimrc
+ files and start eclimd with the -f argument:
+ >
+ $ vim ~/.eclimrc1
+ osgi.instance.area.default=@user.home/workspace1
+ nailgun.server.port=9091
+
+ $ vim ~/.eclimrc2
+ osgi.instance.area.default=@user.home/workspace2
+ nailgun.server.port=9092
+
+ $ eclimd -f ~/.eclimrc1
+ $ eclimd -f ~/.eclimrc2
+
+ <
+
+ Note: The -f argument is not supported by eclipse so the above
+ option is only available when using a headless eclimd instance.
+
+3. Windows Users: Create Windows shortcuts:
+ - In Windows Explorer, open your eclipse folder.
+ - Hold down the right mouse button and drag the eclimd.bat file
+ to where you want the shortcut to exist (like your desktop) and
+ release the right mouse button.
+ - Choose "Create Shortcut(s) Here"
+ - Right click the shortcut and choose "Properties"
+ - On the "Shortcut" tab edit the "Target:" field and append:
+ -Dosgi.instance.area.default=@user.home/workspace1
+ -Dnailgun.server.port=9091
+ - Repeat this process for your other workspaces.
+*eclimd-extdir*
+
+
+Hosting third party nailgun apps in eclimd
+==========================================
+
+Since nailgun provides a simple way to alleviate the startup cost of
+the jvm, other projects utilize it as well. However, running several
+nailgun servers isn't ideal, so eclim supports hosting other nailgun
+apps via an ext dir where you can drop in jar files which will be made
+available to eclim's nailgun server.
+
+The ext dir that eclim reads from is located in your vim files
+directory:
+
+Linux / BSD / OSX:
+
+>
+
+ ~/.eclim/resources/ext
+
+<
+
+
+Windows:
+
+>
+
+ $HOME/.eclim/resources/ext
+
+<
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/faq.txt b/vim/eclim/doc/faq.txt
@@ -0,0 +1,356 @@
+*faq*
+
+FAQ / Troubleshooting
+*********************
+
+
+FAQ
+===
+
+*eclim_workspace*
+
+
+How do I tell eclim which eclipse workspace to use?
+---------------------------------------------------
+
+To configure the workspace you can start eclimd like so:
+
+>
+
+ $ eclimd -Dosgi.instance.area.default=@user.home/another_workspace
+
+<
+
+
+Note the system property osgi.instance.area.default, which is used to
+specify the location of your workspace. Also note the variable
+@user.home which will be replaced with your home directory at runtime.
+
+If you are running a unix variant (linux, mac osx, bsd, etc.) then you
+can specify the above system property in the .eclimrc file in your
+home directory.
+
+>
+
+ $ echo "osgi.instance.area.default=@user.home/another_workspace" >> ~/.eclimrc
+
+<
+
+
+*eclimd_options_windows*
+
+For Windows users there are a couple alternatives to the unsupported
+.eclimrc:
+
+1. Your first option is to add a new environment variable:
+ - Windows 2000: Control Panel ‣ System ‣ Advanced ‣ Environment
+ Variables Windows XP: Control Panel ‣ Performance And Maintenance
+ ‣ System ‣ Advanced ‣ Environment Variables
+ - Under "User variables..." click "New..." Variable Name:
+ ECLIMD_OPTS Variable Value:
+ -Dosgi.instance.area.default=@user.home/another_workspace
+ - Then you can start eclimd as normal (via the eclimd.bat file).
+2. The second option is to create a shortcut to the eclimd.bat
+ file:
+ - In Windows Explorer, open your eclipse folder.
+ - Hold down the right mouse button and drag the eclimd.bat file
+ to where you want the shortcut to exist (like your desktop) and
+ release the right mouse button.
+ - Choose "Create Shortcut(s) Here"
+ - Right click the shortcut and choose "Properties"
+ - On the "Shortcut" tab edit the "Target:" field and append:
+ -Dosgi.instance.area.default=@user.home/another_workspace
+*eclim_proxy*
+
+
+How can I configure eclim to use a proxy?
+-----------------------------------------
+
+The occasional eclim feature requires network access to function
+properly. For example, xml validation may require validating the file
+against a dtd or xsd located remotely. If you are behind a proxy then
+you may need to provide eclim with the necessary proxy settings.
+
+>
+
+ $ eclimd -Dhttp.proxyHost=my.proxy -Dhttp.proxyPort=8080
+
+<
+
+
+If you are running a unix variant (linux, mac osx, bsd, etc.) then you
+can specify the above system property in the .eclimrc file in your
+home directory.
+
+>
+
+ $ echo -e "http.proxyHost=my.proxy\nhttp.proxyPort=8080" >> ~/.eclimrc
+
+<
+
+
+If your proxy requires authentication, you'll need to supply the
+-Dhttp.proxyUser and -Dhttp.proxyPassword properties as well.
+
+On Windows systems you can use the same steps described above, for
+setting the workspace location, to also set the proxy settings.
+
+*eclim_memory*
+
+
+How do I specify jvm memory arguments for eclim (fix OutOfMemory errors).
+-------------------------------------------------------------------------
+
+If you are using the headless version of eclimd, then you have a
+couple options:
+
+1. pass the necessary jvm args to eclimd. For example, to increase
+ the heap size:
+ >
+ $ eclimd -Xmx256M
+
+ <
+
+2. if you are using a unix variant, then you can add the necessary
+ vm args to a .eclimrc file in your home directory.
+ >
+ # increase heap size
+ -Xmx256M
+
+ # increase perm gen size
+ -XX:PermSize=64m
+ -XX:MaxPermSize=128m
+
+ <
+
+ On Windows systems you can use the same steps described above, for
+ setting the workspace location, to also specify the jvm memory
+ args.
+
+If you are using the headed version of eclimd, then setting the jvm
+memory arguments for eclim is the same procedure as setting them for
+eclipse. Details can be found on the eclipse wiki
+(http://wiki.eclipse.org/Eclipse.ini).
+
+*eclim_troubleshoot*
+
+
+How do I troubleshoot features not functioning, or errors encountered?
+----------------------------------------------------------------------
+
+For troubleshooting eclim, please see the dedicated troubleshooting
+section below.
+
+*eclim_full_headless*
+
+
+How can I run eclimd on a truly headless server?
+------------------------------------------------
+
+Please see the headless guide (|install-headless|).
+
+*eclim_encoding*
+
+
+How can I set the default encoding used by eclipse/eclimd?
+----------------------------------------------------------
+
+To set the default encoding you can set the file.encoding system
+property according to your setup:
+
+1. Headless eclimd users on any unix variant (Linux, OSX, etc) can
+ simply add the property your .eclimrc file in your home directory:
+ >
+ # set the default file encoding
+ file.encoding=utf-8
+
+ <
+
+2. Headless eclimd users on Windows can add the system property
+ (eg. -Dfile.encoding=utf-8) using the same steps described above,
+ for setting the workspace location.
+3. Headed eclimd users can add the system property (eg.
+ -Dfile.encoding=utf-8) to your eclipse.ini file found in your
+ eclipse install's root directory. Be sure to add the property on a
+ new line after the -vmargs line:
+ >
+ ...
+ -vmargs
+ ...
+ -Dfile.encoding=utf-8
+
+ <
+
+ You can read more about the eclipse.ini file on the eclipse wiki
+ (http://wiki.eclipse.org/Eclipse.ini).
+
+*troubleshooting*
+
+
+Troubleshooting
+===============
+
+The purpose of this guide is to serve as a means to help troubleshoot
+common issues encountered when getting start with eclim, or providing
+information if you've discovered a possible bug.
+
+The first thing to note is that as of eclim 1.6.1, errors raised by
+eclimd when executing an autocmd from vim, like validating a file on
+write, are no longer echoed as errors to the user. Instead these
+errors are logged and only displayed if your eclim log level is set to
+a relevant level. You can set the log level at any time by running:
+
+>
+
+ :let g:EclimLogLevel = 10
+
+<
+
+
+in vim, which in this case sets the logging to verbose (the default
+log level is 4). After setting the log level any external commands
+that are run or autocmd errors encountered will be printed (you may
+need to run :messages to see them all).
+
+Below are a series of sections broken up by the behavior (or lack of)
+experienced and the steps for diagnosing the cause of that behavior.
+
+If you can't find the answer to your question here, be sure to take a
+look at the faq to see if your question is answered there.
+
+*ts_workspace*
+
+
+Eclim does not recognize any of my existing projects.
+-----------------------------------------------------
+
+A fairly common occurrence for users new to eclim, is that after
+starting eclimd and then attempting to execute some project dependent
+functionality, the functionality appears to do nothing or eclim
+complains that the project could not be determined. If you have
+existing projects created in eclipse and eclim is not finding them,
+then the likely cause is that your projects are located in a
+non-default workspace location.
+
+For the answer to how to specify the location of your workspace when
+starting eclimd, please see the faq devoted to this.
+
+*ts_completion*
+
+
+I'm editing a [java, python, php, etc] file and code completion doesn't work.
+-----------------------------------------------------------------------------
+
+- If you receive the message "E764: Option 'completefunc' is not
+ set", please see the file type section below.
+- Next step is to make sure that the current file is in an eclipse
+ project by running the following command in the vim windows
+ containing the file you are working on.
+ >
+ :ProjectInfo
+
+ <
+
+ If that returns an error that it is unable to determine the project,
+ then see the workspace section above or the guide on creating a new
+ project (|gettingstarted-create|).
+
+- If the correct project info is found, then try running the
+ completion again, if it still doesn't return any results run the
+ command:
+ >
+ :messages
+
+ <
+
+ This will print out any messages that you might have missed. If you
+ see an error regarding a java exception while running a command then
+ see the section on troubleshooting exceptions.
+
+*ts_ftplugin*
+
+
+I'm editing a [java, python, php, etc] file and none of the file type commands exist.
+-------------------------------------------------------------------------------------
+
+This usually indicates that you don't have file type plugins enabled
+in vim. To check you can run:
+
+>
+
+ :EclimValidate
+
+<
+
+
+If it complains about filetype plugin support not being found, then
+follow its directions on adding the following to your vimrc:
+
+>
+
+ filetype plugin indent on
+
+<
+
+
+*ts_signs_misplaced*
+
+
+Code validation signs are showing up on the wrong lines.
+--------------------------------------------------------
+
+This is most likely a result of eclipse being setup to use a different
+file encoding than vim, most likely cp1251 (windows-1251) vs utf-8.
+You should be able to resolve this issue by setting eclipse's default
+encoding accordingly.
+
+If you're unsure what encoding to use, try using utf-8.
+
+*ts_exception*
+
+
+I received a java exception "while executing command" message.
+--------------------------------------------------------------
+
+If you receive a java exception while performing some action in vim,
+it should also include a message indicating the issue. However, if
+you receive something like a NullPointerException or some other
+exception which doesn't include a helpful message, then you may have
+encountered a bug.
+
+Once you've encountered this type of issue, the first step it to get
+more details which you can do by enabling eclim debugging in vim:
+
+>
+
+ :let g:EclimLogLevel = 10
+
+<
+
+
+Then you can perform the same action that triggered the error again.
+This time you should receive the full stack trace of the error.
+
+Once you've obtained the stack trace, the next step it to send it to
+the eclim-user (http://groups.google.com/group/eclim-user) mailing
+list along with a description of what you were doing when the error
+occurred, as well as the OS you are on, and whether you were using
+eclimd headless or headed (inside of the eclipse gui).
+
+*ts_incompatible_plugins*
+
+
+Incompatible Plugins
+--------------------
+
+There are some third party eclipse plugins which currently may
+interfere with eclim. Below is a list of these known plugin
+incompatibilities.
+
+- Spring IDE: At least one user has reported that eclim's java
+ validation no longer works after installing the Spring IDE.
+- viPlugin: Attempting to open a file using the embedded gvim
+ support fails if viPlugin is installed. This issue has been
+ reported on the viPlugin site.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/features.txt b/vim/eclim/doc/features.txt
@@ -0,0 +1,133 @@
+*features*
+
+Features
+********
+
+The following is a partial list of eclim features with much more still
+to come. For more details please see the detailed documentation
+(|vim-index|). For a more comprehensive list you can also visit the
+cheatsheet (|cheatsheet|).
+
+
+Eclipse Projects
+================
+
+- Create, update, and delete Eclipse projects.
+- Easily manage Eclipse .classpath files (support for maven and
+ ivy).
+- Quickly and easily manage settings globally or on a project basis.
+
+C/C++
+=====
+
+- Context sensitive code completion.
+- Searching.
+- Source code validation.
+
+Css
+===
+
+- Context sensitive code completion.
+- Source code validation.
+
+Html
+====
+
+- Context sensitive code completion.
+- Automatic validation (w/ visual marking of errors and warnings).
+
+Java
+====
+
+- Automatic source code validation (w/ visual marking of errors and
+ warnings).
+- Context sensitive code completion.
+- Code correction suggestions with option to apply a suggestion.
+- Class constructor generation.
+- Java Bean getter and setter generation.
+- Generation of delegate methods.
+- Java source and java doc searching capabilities.
+- Generate stub methods from implemented interfaces or super
+ classes.
+- Generate stub methods for junit testing.
+- Quickly clean and sort imports and easily import new classes.
+- Automatic generation of logging initialization code, upon first
+ usage of a logger.
+- Javadoc generation for package, class, field, method, etc.
+- Java regular expression testing.
+- Support for Checkstyle.
+- Validation of log4j xml files.
+
+Android
+-------
+
+- Support for creating android projects from vim.
+
+Ant
+---
+
+- Ant execution from any file.
+- Context sensitive code completion when editing build files.
+- Automatic validation of build files (w/ visual marking of errors
+ and warnings).
+- Quick access to ant documentation.
+
+Maven
+-----
+
+- Maven execution from any file.
+- Maven repository searching and ability to add results to pom file.
+
+JavaScript
+==========
+
+- File validation using jsl (http://www.javascriptlint.com/).
+
+Php
+===
+
+- Code completion.
+- Searching.
+- Source code validation.
+
+Python
+======
+
+- Context sensitive code completion.
+- Find element definition support.
+- Regular expression testing.
+- Django functionality.
+- Validation via python compiler, pyflakes
+ (http://www.divmod.org/trac/wiki/DivmodPyflakes), and pylint
+ (http://www.logilab.org/857).
+
+Ruby
+====
+
+- Context sensitive code completion.
+- Searching.
+- Source code validation.
+
+Vim Script
+==========
+
+- Find user defined command, function, or global variable
+ declarations / references.
+- Quickly lookup help topic for a keyword, functions, command, etc.
+
+Xml / Dtd / Xsd
+===============
+
+- Automatic validation (w/ visual marking of errors and warnings).
+- Quickly look up element definition from the current xml file's dtd
+ or xsd.
+- Context sensitive code completion.
+
+Common Vim Functionality
+========================
+
+- Commands to locate a project, workspace, or current file relative
+ file and open it (split, edit, or tabnew).
+- Much more...
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/gettinghelp.txt b/vim/eclim/doc/gettinghelp.txt
@@ -0,0 +1,49 @@
+*gettinghelp*
+
+Getting Help
+************
+
+
+Mailing Lists
+=============
+
+If at any time you have any questions or feedback, feel free to post
+to one of the eclim mailing lists:
+
+- eclim-user (http://groups.google.com/group/eclim-user): For all
+ questions regarding installation, usage, troubleshooting, etc.
+- eclim-dev (http://groups.google.com/group/eclim-dev): For all
+ eclim development related discussions.
+
+IRC (#eclim on freenode.net)
+============================
+
+If you would like to get help or ask questions on IRC, then feel free
+to join #eclim on freenode.net. Please note that I (Eric Van
+Dewoestine, ervandew on irc) try to stay in the channel as much as
+possible, but I might not be available to answer questions
+immediately. It's also worth noting that I live in California, so if
+you are in Europe, Asia, or some other timezone whose normal waking
+hours don't overlap well with mine, then you may be better off getting
+help using one of the mailing lists above.
+
+
+Reporting Bugs
+==============
+
+If you've found a bug please report the issue to either the eclim-dev
+(http://groups.google.com/group/eclim-dev) mailing list or create a
+new issue on eclim's github issue tracker
+(http://github.com/ervandew/eclim/issues).
+
+When reporting a bug, please include the following information:
+
+- What OS are you on?
+ - Linux users: please include the distro and version.
+- What version of eclim, vim, and eclipse are you using?
+ - Linux users: please indicate whether you installed eclipse via
+ your distro's package manager or not, and if not, please indicate
+ what distribution of eclipse you are using ("Eclipse Classic",
+ "Eclipse IDE for C/C++ Developers", some other eclipse bundle).
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/gettingstarted.txt b/vim/eclim/doc/gettingstarted.txt
@@ -0,0 +1,324 @@
+*gettingstarted*
+
+Getting Started
+***************
+
+Once you've installed (|install|) eclim, the next step is to create
+your first project after which you can then start writing code and
+familiarizing yourself with eclim's features.
+
+First make sure eclimd is running (see the eclimd docs (|eclimd|) if
+you are unsure how to start eclimd).
+
+*gettingstarted-create*
+
+
+Creating your first project
+===========================
+
+Once you've got eclimd running, open an instance of vim and create
+your project like so:
+
+Note: Android Users: the android section below contains additional
+ info regarding the creation of android projects.Maven Users: you may
+ refer to the maven section below for an alternate way to create a
+ java project.
+
+>
+
+ :ProjectCreate /path/to/my_project -n java
+
+<
+
+
+This example creates a project with a java nature (-n java), but the
+same method can be used to create a project for other languages by
+simply changing the nature accordingly:
+
+>
+
+ :ProjectCreate /path/to/my_java_project -n android
+ :ProjectCreate /path/to/my_c_project -n c
+ :ProjectCreate /path/to/my_cpp_project -n c++
+ :ProjectCreate /path/to/my_java_project -n java
+ :ProjectCreate /path/to/my_php_project -n php
+ :ProjectCreate /path/to/my_python_project -n none
+ :ProjectCreate /path/to/my_ruby_project -n ruby
+
+<
+
+
+The only odd ball in the bunch is the creation of the python project
+which currently uses the 'none' nature.
+
+The path supplied to the |:ProjectCreate| command will be the path to
+the root of your project. This path may or may not exist. If it does
+not exist it will be created for you. After you've created your
+project, there will be a .project file added to your project's root
+along with another file where references to your project's source
+directories and any third party libraries your project uses reside.
+The name of this file will vary depending on your project's nature,
+but in all cases eclim will provide you with commands to manage this
+file:
+
+- java, android - .classpath file (|vim-java-classpath|)
+- php, ruby - .buildpath file (|vim-dltk-buildpath|)
+- c, c++ - .cproject, managed via the |:CProjectConfigs| command
+- python - .ropeproject (see the rope docs (|python-rope|))
+Once you've created your project you can use the :ProjectList command
+to list the available projects and you should see your newly created
+one in the list.
+
+>
+
+ my_project - open - /path/to/my_project
+
+<
+
+
+The :ProjectList result is in the form of projectName - (open|closed)
+- /project/root/path. When you create projects, the last path element
+will be used for the project name. If that element contains any
+spaces, these will be converted to underscores.
+
+
+Adding project source directories
+=================================
+
+Before you can start writing code, you will first need to create and
+register your project's source directories. If you created your
+project from an existing code base, then this step may have been
+perform automatically for you, but you should validate the settings to
+be sure.
+
+We will use a java project in this example but the steps for other
+languages are very similar. Please see the relevant docs for your
+language for more details:
+
+- java and android (|vim-java-classpath|)
+- php and ruby (|vim-dltk-buildpath|)
+- c and c++ (|:CProjectConfigs|)
+- python (|python-rope|)
+For the purpose of this example we will assume that you will store
+your source files at:
+
+>
+
+ /path/to/my_project/src/java
+
+<
+
+
+So, given that location, you will need to open the file
+/path/to/my_project/.classpath in Vim.
+
+>
+
+ vim /path/to/my_project/.classpath
+
+<
+
+
+To add the source directory simply execute the following
+
+>
+
+ :NewSrcEntry src/java
+
+<
+
+
+This will add the necessary entry to the end of your .classpath file.
+The contents of this file should now look something like this:
+
+>
+
+ <?xml version="1.0" encoding="UTF-8"?>
+ <classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+ <classpathentry kind="output" path="bin"/>
+ <classpathentry kind="src" path="src/java"/>
+ </classpath>
+
+<
+
+
+Now that your source directory is setup, you can proceed to edit java
+files in that directory and make use of the java functionality
+(|vim-java-index|) provided by eclim.
+
+*gettingstarted-coding*
+
+
+Writing code in your new project
+================================
+
+Now that you have a project created, you can start writing code and
+utilize the features that eclim provides.
+
+Note: Below we'll walk through a trivial java example, but some of
+ the steps apply to all the languages that eclim supports, although
+ the command names may differ a bit. For additional docs on working
+ with the language of your choice, please see the relevant section of
+ the docs:
+
+ - c/c++ (|vim-c-index|)
+ - java (|vim-java-index|)
+ - php (|vim-php-index|)
+ - python (|vim-python-index|)
+ - ruby (|vim-ruby-index|)
+ - etc. (|vim-index|)
+Lets get started writing our first java application using eclim.
+
+1. First, navigate to your new project's source directory (src/java
+ in this example) and create any necessary package directories:
+ >
+ $ cd /path/to/my_project/src/java
+ $ mkdir -p org/test/
+
+ <
+
+2. Then start editing your first java source file:
+ >
+ $ vim org/test/TestMain.java
+
+ <
+
+ >
+ package org.test;
+
+ public class TestMain
+ {
+ public static final void main(String[] args)
+ {
+
+ }
+ }
+
+ <
+
+3. You can start to use some of the core features now. For
+ example, lets add the following code to the main method so we can
+ test eclim's source code validation:
+ >
+ System.
+
+ <
+
+ Then save the file and note that an error marker is placed in the
+ left margin of your file and when the cursor is on that line an
+ error message is printed at the bottom of your vim window. You can
+ also run :lopen to view all the errors in the file at once.
+
+4. Now lets try out code completion. Place your cursor on the '.'
+ of 'System.' and start insert mode in vim using 'a', then follow
+ the example below:
+ >
+ System.<ctrl-x><ctrl-u> // starts the completion mode
+ System.<ctrl-n> // cycle through the completion suggestions
+ System.out // assuming you chose the 'out' suggestion
+ System.out.p<ctrl-x><ctrl-u> // now start completion again
+ System.out.p<ctrl-n> // hit <ctrl-n> until you get 'println'
+ System.out.println(
+ System.out.println("Hello World"); // finish up the example code.
+
+ <
+
+5. After saving the file you should have no more validation errors,
+ so now we can run the code like so:
+ >
+ :Java
+
+ <
+
+ After running the :Java command in vim you should now see your
+ output in a new split window.
+
+This only scratches the surface on the number of java features
+(|vim-java-index|) that eclim provides, but hopefully this example was
+enough to get you started.
+
+*gettingstarted-android*
+
+
+Android Users
+=============
+
+Creating an android project is the same as creating a regular java
+project, but you use the android nature instead:
+
+>
+
+ :ProjectCreate /path/to/my_project -n android
+
+<
+
+
+This will result in a series of prompts for you to input your
+project's information:
+
+Note: at any point in this process you can use Ctrl+C to cancel the
+project creation.
+
+1. First you will be asked to choose the target android platform.
+ If you have only one platform installed on your system, this prompt
+ will be skipped and that platform will be used when creating the
+ project. If you have no platforms installed then you will receive
+ an error directing you to install a platform using the Android SDK
+ Manager. If you install a new platform you will need to either
+ restart eclipse/eclimd or run the eclim supplied |:AndroidReload|
+ command.
+2. Next you will be asked to supply a package name (Ex:
+ com.mycompany.myapp).
+3. Then you will need to supply a name for your application.
+4. The next prompt will ask you if you are creating a library
+ project or not. Most likely you are not, so type 'n' here to
+ proceed.
+5. Lastly, if you are not creating a library project, you will be
+ asked whether or not you want to have a new android activity
+ created for you and if so, you will be asked for the name of that
+ activity.
+Once you've finished supplying the necessary information, your android
+project will be created. An android project is simply a specialized
+java project, so you can now leverage all the eclim provided java
+functionality (|vim-java-index|) while developing your app.
+
+*gettingstarted-maven*
+
+
+Maven Users
+===========
+
+Creating your first project with maven can be accomplished using the
+same method as any other java project, or you can utilize some of
+maven's built in features to get your project started.
+
+1. Run maven's generate archetype to create the project directory
+ and samples:
+ >
+ $ mvn archetype:generate
+
+ <
+
+2. Once you've created the initial project directory, cd into that
+ directory and run the following command to generate the necessary
+ eclipse files:
+ >
+ $ cd <project_dir>
+ $ mvn eclipse:eclipse
+
+ <
+
+3. Now you can start an instance of vim at the project's root
+ directory and run the following commands to:
+ - set the necessary eclipse classpath variable to point to your
+ maven repository.
+ - import your new project into eclipse.
+ >
+ $ vim
+ :MvnRepo
+ :ProjectImport /path/to/new/project
+
+ <
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/index.txt b/vim/eclim/doc/index.txt
@@ -0,0 +1,318 @@
+*index*
+
+Welcome to Eclim
+****************
+
+The power of Eclipse in your favorite editor.
+
+
+What is it?
+===========
+
+Eclim provides the ability to access Eclipse (http://eclipse.org) code
+editing features (code completion, searching, code validation, and
+many more (|features|)) via the command line or a local network
+connection, allowing those features to be integrated with your
+favorite editor. Eclim provides an integration with Vim
+(http://www.vim.org), but third party clients (|relatedprojects|) have
+been created to add eclim support to other editors as well (emacs,
+sublime text 2, textmate).
+
+There are three primary usage scenarios in which eclim is designed to
+be used:
+
+[image]
+
+1. The first scenario (|eclimd-headless|) is for those for which
+ vim is their primary editing interface. In this scenario you run a
+ headless instance of eclipse which all vim instances can then
+ communicate with to provide the various eclipse features.
+2. The second scenario (|eclimd-headed|) is for those who prefer
+ using vim as their main interface, but frequently end up jumping
+ back to eclipse for any features not provided by eclim. In this
+ case you can run the eclim server inside of the eclipse gui and
+ then interact with it via external vim instances just like the
+ first scenario.
+3. The last scenario (|gvim-embedded|) is for those who wish to use
+ the eclipse interface full time, but want to use gvim as an
+ embedded eclipse editor. Just like the previous use case, the eclim
+ server is run inside of the eclipse gui and the embedded gvim will
+ interact with it just like external vim instances would. This
+ feature is only support on Windows and Unix systems (where gvim is
+ compiled with the gtk gui).
+ Note: Please be aware that the embedded vim does not behave like
+ a standard eclipse editor. It's a separate program (vim) embedded
+ into eclipse, so eclipse features are provided by eclim's vim
+ plugins and not the usual eclipse key bindings, context menus,
+ etc. For those that just want vim like key bindings in their
+ eclipse editors, vrapper (http://vrapper.sourceforge.net/home/)
+ is an excellent alternative which provides exactly that.
+
+Eclim is released under the GPLv3
+(http://www.gnu.org/licenses/gpl-3.0-standalone.html).
+
+
+How do I get/install it?
+========================
+
+You can follow the eclim install guide (|install|) which will walk you
+through downloading and installing eclim.
+
+
+How do I use it?
+================
+
+After you've installed eclim, you can refer to the getting started
+(|gettingstarted|) page which will walk you through creating your
+first project.
+
+
+Where can I get help?
+=====================
+
+
+Mailing Lists
+-------------
+
+If at any time you have any questions or feedback, feel free to post
+to one of the eclim mailing lists:
+
+- eclim-user (http://groups.google.com/group/eclim-user): For all
+ questions regarding installation, usage, troubleshooting, etc.
+- eclim-dev (http://groups.google.com/group/eclim-dev): For all
+ eclim development related discussions.
+
+IRC (#eclim on freenode.net)
+----------------------------
+
+If you would like to get help or ask questions on IRC, then feel free
+to join #eclim on freenode.net. Please note that I (Eric Van
+Dewoestine, ervandew on irc) try to stay in the channel as much as
+possible, but I might not be available to answer questions
+immediately. It's also worth noting that I live in California, so if
+you are in Europe, Asia, or some other timezone whose normal waking
+hours don't overlap well with mine, then you may be better off getting
+help using one of the mailing lists above.
+
+
+How do I report a bug?
+======================
+
+
+Reporting Bugs
+--------------
+
+If you've found a bug please report the issue to either the eclim-dev
+(http://groups.google.com/group/eclim-dev) mailing list or create a
+new issue on eclim's github issue tracker
+(http://github.com/ervandew/eclim/issues).
+
+When reporting a bug, please include the following information:
+
+- What OS are you on?
+ - Linux users: please include the distro and version.
+- What version of eclim, vim, and eclipse are you using?
+ - Linux users: please indicate whether you installed eclipse via
+ your distro's package manager or not, and if not, please indicate
+ what distribution of eclipse you are using ("Eclipse Classic",
+ "Eclipse IDE for C/C++ Developers", some other eclipse bundle).
+
+What's New?
+===========
+
+[image: Rss Feed for What's New][image] (index.rss)
+
+
+May 07, 2014
+------------
+
+Release of eclim for indigo users.
+
+- Eclim 1.7.19 (|1.7.19|)
+
+Apr. 12, 2014
+-------------
+
+Eclim has been updated to fix an issue on Windows that could prevent
+many features from working.
+
+- Eclim 2.3.4 (|2.3.4|)
+
+Apr. 06, 2014
+-------------
+
+This release includes many bug fixes and refinements as well as a
+rewrite of eclim's python support to utilize pydev instead of rope.
+
+- Eclim 2.3.3 (|2.3.3|)
+Warning: Any exiting eclim python projects you have should be
+ re-created with the new python nature:>
+
+ :ProjectCreate /path/to/project -n python
+
+ <
+
+
+
+Sep. 12, 2013
+-------------
+
+This release fixes the extraction of the necessary vim files when
+installing scala support.
+
+- Eclim 2.3.2 (|2.3.2|) for Eclipse 4.3 (Kepler).
+- Eclim 1.7.18 (|1.7.18|) for Eclipse 3.7/3.8 (Indigo).
+
+Jul. 27, 2013
+-------------
+
+The previous eclim installer for Kepler was still pointing at the Juno
+update site. This release remedies that.
+
+- Eclim 2.3.1 (|2.3.1|) for Eclipse 4.3 (Kepler).
+
+Jul. 21, 2013
+-------------
+
+The focus of this release is to bring eclim fully up to date for
+Eclipse Kepler support. While the 2.3.0 release of eclim should still
+work fine on Juno, eclim will no longer officially support that
+version of Eclipse.
+
+- Eclim 2.3.0 (|2.3.0|) for Eclipse 4.3 (Kepler).
+- Eclim 1.7.17 (|1.7.17|) for Eclipse 3.7/3.8 (Indigo).
+
+Jul. 14, 2013
+-------------
+
+This is primarily a bug fix release with a few new features. Unless
+some critical error is found, this will be the last release targeting
+Juno. The next release will likely target Kepler though this release
+should work fine on Kepler as well, with the exception of scala
+support which has not been tested. Indigo support will continue but
+will likely end with the release of Luna, possibly sooner.
+
+- Eclim 2.2.7 (|2.2.7|) for Eclipse 4.2 (Juno).
+- Eclim 1.7.16 (|1.7.16|) for Eclipse 3.7/3.8 (Indigo).
+
+May 18, 2013
+------------
+
+Eclim has been updated to support the Android Development Toolkit
+version 22.0.0, scala is now supported for both Juno and Indigo, and
+there are a few other improvements and many bug fixes.
+
+- Eclim 2.2.6 (|2.2.6|) for Eclipse 4.2 (Juno).
+- Eclim 1.7.14 (|1.7.14|) for Eclipse 3.7/3.8 (Indigo).
+
+Nov. 25, 2012
+-------------
+
+The most notable change in this release is support for Eclipse 3.8
+with the Indigo release (1.7.13). Both releases also include several
+small bug fixes.
+
+- Eclim 2.2.5 (|2.2.5|) for Eclipse 4.2 (Juno).
+- Eclim 1.7.13 (|1.7.13|) for Eclipse 3.7/3.8 (Indigo).
+
+Nov. 18, 2012
+-------------
+
+This is another bug fix release which includes support for the latest
+Android development toolkit (21.0.0).
+
+- Eclim 2.2.4 (|2.2.4|) for Eclipse 4.2 (Juno).
+- Eclim 1.7.12 (|1.7.12|) for Eclipse 3.7 (Indigo).
+
+Oct. 19, 2012
+-------------
+
+This is a bug fix release for Windows users which fixes executing of
+eclim commands from vim:
+
+- Eclim 2.2.3 (|2.2.3|) for Eclipse 4.2 (Juno).
+- Eclim 1.7.11 (|1.7.11|) for Eclipse 3.7 (Indigo).
+
+Oct. 07, 2012
+-------------
+
+Two new eclim updates are once again available with several bug fixes
+and improvements.
+
+- Eclim 2.2.2 (|2.2.2|) for Eclipse 4.2 (Juno).
+- Eclim 1.7.10 (|1.7.10|) for Eclipse 3.7 (Indigo).
+
+Sep. 09, 2012
+-------------
+
+ Eclim 1.7.9 (|1.7.9|) for Eclipse 3.7 (Indigo) is now available.
+ This release adds initial support for scala (|vim-scala-index|).
+
+Please note that the Scala IDE (http://scala-ide.org) , which eclim
+uses to provide scala support, is not yet available for Eclipse 4.2
+(Juno), so eclim's scala support will not be available for the eclim
+2.2.x releases until sometime after the Scala IDE has been updated for
+Juno.
+
+
+Sep. 01, 2012
+-------------
+
+Another set of releases are now available for both Juno and Indigo.
+These both include several bug fixes along with new support for
+creating android projects.
+
+- Eclim 2.2.1 (|2.2.1|) for Eclipse 4.2 (Juno).
+- Eclim 1.7.8 (|1.7.8|) for Eclipse 3.7 (Indigo).
+Eclim also has a newly redesigned site using the sphinx bootstrap
+theme (https://github.com/ervandew/sphinx-bootstrap-theme).
+
+
+Aug. 07, 2012
+-------------
+
+Two new versions of eclim have been released, one for the latest
+Eclipse version, Juno, the other a bug fix release for the previous
+version of Eclipse, Indigo.
+
+- Eclim 2.2.0 (|2.2.0|) for Eclipse 4.2 (Juno).
+- Eclim 1.7.7 (|1.7.7|) for Eclipse 3.7 (Indigo).
+
+Jun. 07, 2012
+-------------
+
+ Eclim 1.7.6 (|1.7.6|) is now available.
+ This is a minor bug fix release.
+
+
+Jun. 03, 2012
+-------------
+
+ Eclim 1.7.5 (|1.7.5|) is now available.
+ This is a minor release with an improved installer, some bug fixes, and a few
+ minor enhancements.
+
+
+Apr. 22, 2012
+-------------
+
+ Eclim 1.7.4 (|1.7.4|) is now available.
+ This is a bug fix release.
+
+
+Mar. 18, 2012
+-------------
+
+ Eclim 1.7.3 (|1.7.3|) is now available.
+ This version fixes numerious small bugs and adds a handful of small features.
+
+Warning: Non vim users (emacs-eclim, subclim, etc.): The underlying
+ command response format for eclim has changed, which means that any
+ project relying on the old format isn't going to work. So if you are
+ installing eclim for use with a client other than vim, then be sure
+ to check with the client project to see if it has been updated for
+ eclim 1.7.3 or later.
+
+Eclim News Archive (|archive-news|)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/install.txt b/vim/eclim/doc/install.txt
@@ -0,0 +1,607 @@
+*install*
+
+Download / Install
+******************
+
+
+Requirements
+============
+
+Before beginning the installation, first confirm that you have met the
+following requirements.
+
+- Java Development Kit
+ (http://www.oracle.com/technetwork/java/javase/downloads/index.html)
+ 1.6 or greater
+- Vim (http://www.vim.org/download.php) 7.1 or greater
+- Eclipse 4.2.x (Juno) (http://eclipse.org/downloads/index.php)
+ (eclim 2.2.x), Eclipse 3.7.x (Indigo)
+ (http://eclipse.org/downloads/packages/release/indigo/sr2) (eclim
+ 1.7.x), or Eclipse 3.8
+ (http://download.eclipse.org/eclipse/downloads/drops/R-3.8-201206081200/)
+ (eclim 1.7.13 or greater)
+- Mac and Linux users must also have make and gcc installed.
+ Minimum Vim Settings: In order for eclim to function properly, there
+ is a minimum set of vim options that must be enabled in your vimrc
+ file (:h vimrc).
+
+ - set nocompatible
+ Execute :h 'compatible' for more info. You can confirm that
+ compatibliity is turned off by executing the following in vim:
+
+ >
+ :echo &compatible
+
+ <
+
+ Which should output '0', but if not, then add the following to
+ your ~/.vimrc files (_vimrc on Windows):
+
+ >
+ set nocompatible
+
+ <
+
+ - filetype plugin on
+ Execute :h filetype-plugin-on for more info. You can confirm that
+ file type plugins are enabled by executing the following:
+
+ >
+ :filetype
+
+ <
+
+ Which should output 'filetype detection:ON plugin:ON indent:ON',
+ showing at least 'ON' for 'detection' and 'plugin', but if not,
+ then update your ~/.vimrc (_vimrc on Windows) to include:
+
+ >
+ filetype plugin indent on
+
+ <
+
+
+Download
+========
+
+You can find the official eclim installer on eclim's sourceforge
+downloads page (https://sourceforge.net/projects/eclim/files/eclim/):
+
+- eclim_1.7.19.jar
+ (http://sourceforge.net/projects/eclim/files/eclim/1.7.19/eclim_1.7.19.jar/download)
+ (for Eclipse 4.2.x, Juno)
+- eclim_1.7.19.jar
+ (http://sourceforge.net/projects/eclim/files/eclim/1.7.19/eclim_1.7.19.jar/download)
+ (for Eclipse 3.8 or Eclipse 3.7.x, Indigo)
+
+Third Party Packages
+--------------------
+
+As an alternative to the official installer, there are also some
+packages maintained by third parties:
+
+- Arch: aur (eclim) (http://aur.archlinux.org/packages.php?ID=7291),
+ aur (eclim-git) (http://aur.archlinux.org/packages.php?ID=33120)
+
+Installing / Upgrading
+======================
+
+Eclim can be installed a few different ways depending on your
+preference and environment:
+
+- Graphical Installer
+- Unattended (automated) Installer
+- Build from source
+- Install on a headless server
+*installer*
+
+
+Graphical Installer
+-------------------
+
+
+Step 1: Run the installer
+~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Note: If you have eclipse running, please close it prior to starting
+ the installation procedure.
+
+- First download the installer: eclim_1.7.19.jar
+ (http://sourceforge.net/projects/eclim/files/eclim/1.7.19/eclim_1.7.19.jar/download)
+- Next run the installer:
+ >
+ $ java -jar eclim_1.7.19.jar
+
+ <
+
+ Windows and OSX users should be able to simply double click on the
+ jar file to start the installer.
+
+ After the installer starts up, simply follow the steps in the wizard
+ to install eclim.
+
+ If your machine is behind a proxy, take a look at the instructions
+ for running the installer behind a proxy.
+
+ If you encounter an error running the installer, then consult the
+ known potential issues below.
+
+
+Step 2: Test the installation
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+To test eclim you first need to start the eclim daemon. How you start
+the daemon will depend on how you intend to use eclim.
+
+Note: More info on running the eclim daemon can be found in the
+ eclimd (|eclimd|) docs.
+
+If you plan on using eclim along with the eclipse gui, then simply
+start eclipse and open the eclimd view:
+
+Window ‣ Show View ‣ Other ‣ Eclim ‣ eclimd
+
+By default the eclimd view will also be auto opened when you open a
+file using:
+
+Open With ‣ Vim
+
+If you plan on using eclim without the eclipse gui, then:
+
+- start the eclimd server.
+ - Linux / Mac / BSD (and other unix based systems): To start
+ eclimd from linux, simply execute the eclimd script found in your
+ eclipse root directory:
+ >
+ $ $ECLIPSE_HOME/eclimd
+
+ <
+
+ - Windows: The easiest way to start eclimd in windows is to double
+ click on the eclimd.bat file found in your eclipse root directory:
+ >
+ %ECLIPSE_HOME%/eclimd.bat
+
+ <
+
+Once you have the eclim daemon (headed or headless) running, you can
+then test eclim:
+
+- open a vim window and issue the command, :PingEclim
+ (|vim-core-eclim#:PingEclim|). The result of executing this command
+ should be the eclim and eclipse version echoed to the bottom of your
+ Vim window. If however, you receive unable to connect to eclimd -
+ connect: Connection refused, or something similar, then your eclimd
+ server is not running or something is preventing eclim from
+ connecting to it. If you receive this or any other errors you can
+ start by first examining the eclimd output to see if it gives any
+ info as to what went wrong. If at this point you are unsure how to
+ proceed you can view the troubleshooting guide (|troubleshooting|)
+ or feel free to post your issue on the eclim-user
+ (http://groups.google.com/group/eclim-user) mailing list.
+ Example of a successful ping:
+
+ [image]
+ Example of a failed ping:
+
+ [image]
+- Regardless of the ping result, you can also verify your vim
+ settings using the command :EclimValidate. This will check various
+ settings and options and report any problems. If all is ok you will
+ receive the following message:
+ >
+ Result: OK, required settings are valid.
+
+ <
+
+*installer-proxy*
+
+
+Running The Installer Behind a Proxy
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+If you are behind a proxy, you may need to run the installer like so
+(be sure to take a look at the related faq (|eclim-proxy|) as well):
+
+>
+
+ $ java -Dhttp.proxyHost=my.proxy -Dhttp.proxyPort=8080 -jar eclim_1.7.19.jar
+
+<
+
+
+If your proxy requires authentication, you'll need to supply the
+-Dhttp.proxyUser and -Dhttp.proxyPassword properties as well.
+
+You can also try the following which may be able to use your system
+proxy settings:
+
+>
+
+ $ java -Djava.net.useSystemProxies=true -jar eclim_1.7.19.jar
+
+<
+
+
+*installer-issues*
+
+
+Potential Installation Issues
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+In some rare cases you might encounter one of the following errors:
+
+1. Any exception which denotes usage of gcj.
+ >
+ java.lang.NullPointerException
+ at org.pietschy.wizard.HTMLPane.updateEditorColor(Unknown Source)
+ at org.pietschy.wizard.HTMLPane.setEditorKit(Unknown Source)
+ at javax.swing.JEditorPane.getEditorKit(libgcj.so.90)
+ ...
+
+ <
+
+ Gcj (GNU Compile for Java), is not currently supported. If you
+ receive any error which references libgcj, then gcj is your current
+ default jvm. So, you'll need to install the openjdk or a jdk from
+ oracle to resolve the installation error.
+
+2. >
+ java.lang.IncompatibleClassChangeError
+ at org.formic.ant.logger.Log4jLogger.printMessage(Log4jLogger.java:51)
+ ...
+
+ <
+
+ This is most likely caused by an incompatible version of log4j
+ installed in your jave ext.dirs. To combat this you can run the
+ installer like so:
+
+ >
+ $ java -Djava.ext.dirs -jar eclim_1.7.19.jar
+
+ <
+
+If you encounter an error not covered here, then please report it to
+the eclim-user (http://groups.google.com/group/eclim-user) mailing
+list.
+
+*installer-automated*
+
+
+Unattended (automated) install
+------------------------------
+
+As of eclim 1.5.6 the eclim installer supports the ability to run an
+automated install without launching the installer gui. Simply run the
+installer as shown below, supplying the location of your vim files and
+your eclipse install via system properties:
+
+>
+
+ $ java \
+ -Dvim.files=$HOME/.vim \
+ -Declipse.home=/opt/eclipse \
+ -jar eclim_1.7.19.jar install
+
+<
+
+
+Please note that when using this install method, the installer will
+only install eclim features whose third party dependecies are already
+present in your eclipse installation. So before installing eclim, you
+must make sure that you've already installed the necessary
+dependencies (for a full list of dependencies, you can reference
+eclim's installer dependencies
+(https://github.com/ervandew/eclim/blob/master/org.eclim.installer/build/resources/dependencies.xml)
+file).
+
+On exception to this is eclim's python plugin which currently does not
+rely on any eclipse features, so to enable the installation of that
+plugin, just add -DfeatureList.python=true to the install command
+above.
+
+Required Properties:
+
+- eclipse.home - The absolute path to your eclipse installation.
+- vim.files (or vim.skip=true) - The absolute path to your vim files
+ directory. Or if you want to omit the installation of the vim files
+ (emacs-eclim users for example) you can supply -Dvim.skip=true
+ instead.
+*install-source*
+
+
+Building from source
+--------------------
+
+
+1. Check out the code:
+~~~~~~~~~~~~~~~~~~~~~~
+
+>
+
+ $ git clone git://github.com/ervandew/eclim.git
+
+<
+
+
+Note: If you are still using Eclipse 3.7 (Indigo) you will need to
+ checkout the eclim indigo branch before attempting to build eclim:>
+
+ $ cd eclim
+ $ git checkout indigo
+
+ <
+
+
+
+2. Build eclim:
+~~~~~~~~~~~~~~~
+
+>
+
+ $ cd eclim
+ $ ant -Declipse.home=/your/eclipse/home/dir
+
+<
+
+
+Note: If your eclipse home path contains a space, be sure to quote
+ it:>
+
+ > ant "-Declipse.home=C:/Program Files/eclipse"
+
+ <
+
+
+This will build and deploy eclim to your eclipse and vim directories.
+
+Note: If your vimfiles directory is not located at the default
+ location for your OS, then you can specify the location using the
+ "vim.files" property:>
+
+ $ ant -Dvim.files=<your vimfiles dir>
+
+ <
+
+
+When the build starts, it will first examine your eclipse installation
+to find what eclipse plugins are available. It will then use that list
+to determine which eclim features/plugins should be built and will
+output a list like the one below showing what will be built vs what
+will be skipped:
+
+>
+
+ [echo] ${eclipse}: /opt/eclipse
+ [echo] # Skipping org.eclim.adt, missing com.android.ide.eclipse.adt
+ [echo] # Skipping org.eclim.dltk, missing org.eclipse.dltk.core
+ [echo] # Skipping org.eclim.dltkruby, missing org.eclipse.dltk.ruby
+ [echo] # Skipping org.eclim.pdt, missing org.eclipse.php
+ [echo] Plugins:
+ [echo] org.eclim.cdt
+ [echo] org.eclim.jdt
+ [echo] org.eclim.python
+ [echo] org.eclim.sdt
+ [echo] org.eclim.wst
+
+<
+
+
+In this case we can see that four eclim plugins will be skipped along
+with the eclipse feature that would be required to build those
+plugins. If you see an eclipse feature in that list that you know you
+have, it may be the case that you installed it as a regular user, so
+that feature was installed in your user local eclipse directory. In
+that case you will need to notify the build of that directory so it
+can examine it as well (just replace the <version> portion below with
+the actual version found in your ~/.eclipse directory):
+
+>
+
+ $ ant \
+ -Declipse.home=/opt/eclipse \
+ -Declipse.local=$HOME/.eclipse/org.eclipse.platform_<version>
+
+<
+
+
+If you don't want to supply the eclipse home directory, or any other
+properties, on the command line every time you build eclim, you can
+create a user.properties file at the eclim source root and put all
+your properties in there:
+
+>
+
+ $ vim user.properties
+ eclipse.home=/opt/eclipse
+ vim.files=${user.home}/.vim/bundle/eclim
+
+<
+
+
+Note: The eclim vim help files, used by the :EclimHelp
+ (|vim-core-eclim#:EclimHelp|) command, are not built by default. To
+ build these you first need to install sphinx
+ (http://sphinx-doc.org), then run the following command:>
+
+ $ ant vimdocs
+
+ <
+
+
+ This target also supports the vim.files property if you want the
+ docs deployed to a directory other than the default location.
+
+*install-headless*
+
+
+Installing on a headless server
+-------------------------------
+
+The eclim daemon supports running both inside of the eclipse gui and
+as a "headless" non-gui server. However, even in the headless mode,
+eclipse still requires a running X server to function. If you are
+running eclim on a desktop then this isn't a problem, but some users
+would like to run the eclim daemon on a truly headless server. To
+achieve this, you can make use of X.Org's Xvfb server.
+
+Note: This guide uses the Ubuntu server distribution to illustrate
+ the process of setting up a headless server, but you should be able
+ to run Xvfb on the distro of your choice by translating the package
+ names used here to your distro's equivalents.
+
+The first step is to install the packages that are required to run
+eclipse and eclim:
+
+- Install a java jdk, xvfb, and the necessary build tools to compile
+ eclim's nailgun client during installation (make, gcc, etc).
+ >
+ $ sudo apt-get install openjdk-6-jdk xvfb build-essential
+
+ <
+
+Then you'll need to install eclipse. You may do so by installing it
+from your distro's package manager or using a version found on
+eclipse.org (http://eclipse.org/downloads/). If you choose to install
+a version from you package manager, make sure that the version to be
+installed is compatible with eclim since the package manager version
+can often be out of date. If you choose to install an eclipse.org
+(http://eclipse.org/downloads/) version, you can do so by first
+downloading eclipse using either a console based browser like elinks,
+or you can navigate to the download page on your desktop and copy the
+download url and use wget to download the eclipse archive. Once
+downloaded, you can then extract the archive in the directory of your
+choice.
+
+>
+
+ $ wget <eclipse_mirror>/eclipse-<version>-linux-gtk.tar.gz
+ $ tar -zxf eclipse-<version>-linux-gtk.tar.gz
+
+<
+
+
+Note: Depending on what distribution of eclipse you installed and
+ what eclim features you would like to be installed, you may need to
+ install additional eclipse features. If you installed eclipse from
+ your package manager then your package manager may also have the
+ required dependency (eclipse-cdt for C/C++ support for example). If
+ not, you can install the required dependency using eclipse's p2
+ command line client. Make sure the command references the correct
+ repository for your eclipse install (juno in this example) and that
+ you have Xvfb running as described in the last step of this guide:>
+
+ DISPLAY=:1 ./eclipse/eclipse -nosplash -consolelog -debug
+ -application org.eclipse.equinox.p2.director
+ -repository http://download.eclipse.org/releases/juno
+ -installIU org.eclipse.wst.web_ui.feature.feature.group
+
+ <
+
+
+ For a list of eclim plugins and which eclipse features they require,
+ please see the installer dependencies
+ (https://github.com/ervandew/eclim/blob/master/org.eclim.installer/build/resources/dependencies.xml).
+ Note that the suffix '.feature.group' must be added to the
+ dependency id found in that file when supplying it to the
+ '-installIU' arg of the above command.
+
+Once eclipse is installed, you can then install eclim utilizing the
+eclim installer's automated install option (see the Unattended
+(automated) install section for additional details):
+
+>
+
+ $ java \
+ -Dvim.files=$HOME/.vim \
+ -Declipse.home=/opt/eclipse \
+ -jar eclim_1.7.19.jar install
+
+<
+
+
+The last step is to start Xvfb followed by eclimd:
+
+>
+
+ $ Xvfb :1 -screen 0 1024x768x24 &
+ $ DISPLAY=:1 ./eclipse/eclimd start
+
+<
+
+
+When starting Xvfb you may receive some errors regarding font paths
+and possibly dbus and hal, but as long as Xvfb continues to run, you
+should be able to ignore these errors.
+
+The first time you start eclimd you may want to omit the 'start'
+argument so that you can see the output on the console to ensure that
+eclimd starts correctly.
+
+Note: When starting the eclim daemon, you must start it as the same
+ user who will be running vim.
+
+
+Upgrading
+---------
+
+The upgrading procedure is the same as the installation procedure but
+please be aware that the installer will remove the previous version of
+eclim prior to installing the new one. The installer will delete all
+the org.eclim* eclipse plugins along with all the files eclim adds to
+your .vim or vimfiles directory (plugin/eclim.vim, eclim/**/*).
+
+*uninstall*
+
+
+Uninstall
+=========
+
+To uninstall eclim you can use any eclim distribution jar whose
+version is 1.7.5 or greater by running it with the 'uninstaller'
+argument like so:
+
+>
+
+ $ java -jar eclim_1.7.19.jar uninstaller
+
+<
+
+
+That will open a graphical wizard much like the install wizard which
+will ask you again for the location of your vimfiles and eclipse home
+where you've installed eclim and will then remove the eclim
+installation accordingly.
+
+Note: The uninstaller is backwards compatible and can be used to
+ uninstall older versions of eclim.
+
+*uninstall-automated*
+
+
+Unattended (automated) uninstall
+--------------------------------
+
+Like the installer, the uninstaller also supports an unattended
+uninstall. You just need to supply your vim files and eclipse paths as
+system properties:
+
+>
+
+ $ java \
+ -Dvim.files=$HOME/.vim \
+ -Declipse.home=/opt/eclipse \
+ -jar eclim_1.7.19.jar uninstall
+
+<
+
+
+Required Properties:
+
+- eclipse.home - The absolute path to your eclipse installation.
+- vim.files (or vim.skip=true) - The absolute path to your vim files
+ directory. Or if you never installed the vim files (emacs-eclim
+ users for example) you can supply -Dvim.skip=true instead.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/relatedprojects.txt b/vim/eclim/doc/relatedprojects.txt
@@ -0,0 +1,22 @@
+*relatedprojects*
+
+Related Projects
+****************
+
+
+Eclim clients for other editors:
+================================
+
+- Emacs (emacs-eclim (http://github.com/senny/emacs-eclim))
+- Sublime Text 2 (Subclim (http://github.com/JulianEberius/Subclim))
+- Texmate (Eclim.tmbundle
+ (http://github.com/JulianEberius/Eclim.tmbundle))
+
+Vim emulator plugins for Eclipse:
+=================================
+
+- Vrapper (http://vrapper.sourceforge.net) (free and open source)
+- viPlugin (http://www.satokar.com/viplugin/index.php)
+- Viable (http://viableplugin.com)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/c/complete.txt b/vim/eclim/doc/vim/c/complete.txt
@@ -0,0 +1,24 @@
+*vim-c-complete*
+
+C/C++ Code Completion
+*********************
+
+C/C++ code completion uses the standard Vim code completion mechanism
+(|vim-code_completion|) like so:
+
+>
+
+ #include <st<C-X><C-U>
+ #include <stio.h>
+
+ int main(void) {
+ pu<C-X><C-U>
+ puts(
+ puts("Hello World");
+ return EX<C-X><C-U>
+ return EXIT_SUCCESS;
+ }
+
+<
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/c/index.txt b/vim/eclim/doc/vim/c/index.txt
@@ -0,0 +1,30 @@
+*vim-c-index*
+
+C/C++
+*****
+
+
+Features
+========
+
+- C/C++ Project Configuration (vim-c-project)
+- C/C++ Code Completion (vim-c-complete)
+- C/C++ Validation (vim-c-validate)
+- C/C++ Search (vim-c-search)
+- C/C++ Code Inspection (vim-c-inspection)
+
+Suggested Mappings
+==================
+
+Here are some mappings for the c/c++ funtionality provided by eclim.
+To make use of these mappings, simply create a ftplugin file for c/cpp
+and place your mappings there (:help ftplugin-name).
+
+- The following mapping allows you to simply hit <enter> on an
+ element to perform a search to find it.
+ >
+ nnoremap <silent> <buffer> <cr> :CSearchContext<cr>
+
+ <
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/c/inspection.txt b/vim/eclim/doc/vim/c/inspection.txt
@@ -0,0 +1,59 @@
+*vim-c-inspection*
+
+*:CCallHierarchy*
+
+
+C/C++ Code Inspection
+*********************
+
+
+Call Hierarchy
+==============
+
+When viewing a c or c++ source file you can view the call hierarchy of
+a function or method by issuing the command :CCallHierarchy. This
+will open a temporary buffer with an inversed tree view of the
+hierarchy of callers of the requested function or method.
+
+>
+
+ fun2(int)
+ fun1(int)
+ main()
+ fun3(int)
+ fun3(int)
+
+<
+
+
+While you are in the hierarchy tree buffer, you can jump to the call
+under the cursor using one of the following key bindings:
+
+- <cr> - open the type using the (default action).
+- E - open the type via :edit
+- S - open the type via :split
+- T - open the type via :tabnew
+- ? - view help buffer
+:CCallHierarchy can also be used to view the callees for a function or
+method by invoking the command with a !:
+
+>
+
+ :CCallHierarchy!
+
+<
+
+
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimCCallHierarchyDefaultAction*
+
+- g:EclimCCallHierarchyDefaultAction (defaults to 'split') -
+ Determines the command used to open the file when hitting <enter> on
+ an entry in the hierarchy buffer.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/c/project.txt b/vim/eclim/doc/vim/c/project.txt
@@ -0,0 +1,62 @@
+*vim-c-project*
+
+*:CProjectConfigs*
+
+
+C/C++ Project Configuration
+***************************
+
+The eclipse cdt provides a large set of configuration support for your
+c/c++ projects. Eclim exposes a subset of these to you using the
+:CProjectConfigs command:
+
+>
+
+ :CProjectConfigs
+
+ " or if you are outside of the project
+ :CProjectConfigs my_c_project
+
+<
+
+
+This command will open a temporary buffer displaying some of the cdt
+configuration values available to you. In this buffer you can add or
+remove source directory references, include path references, and
+symbols.
+
+Here is a small example of what the contents may look like:
+
+>
+
+ Config: Linux GCC
+
+ Sources: |add|
+ dir: src
+
+ Tool: GCC C Compiler
+ Includes: |add|
+ path: "${workspace_loc:/my_c_project/includes}"
+ Symbols: |add|
+
+ Tool: GCC Assembler
+ Includes: |add|
+
+<
+
+
+To add a source directory, include path, or symbol, simply move the
+cursor over the relevant "|add|" link and hit <enter>. You will then
+be prompted to enter an appropriate value. For your convenience, tab
+completion is provided where possible.
+
+Note: Despite the odd looking value in the includes path section
+ above, to add the entry you simply need to supply the project
+ relative path, "includes/" in this case, when prompted by the add
+ command.
+
+If at any point you would like to remove a value, you can move the
+cursor over the line of the value you would like to remove and hit D
+(shift-d) to delete the entry.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/c/search.txt b/vim/eclim/doc/vim/c/search.txt
@@ -0,0 +1,125 @@
+*vim-c-search*
+
+C/C++ Search
+************
+
+*:CSearch*
+
+
+Pattern Search
+==============
+
+Pattern searching provides a means to widen a search beyond a single
+element. A pattern search can be executed using the command
+
+:CSearch -p <pattern> [-t <type> -s <scope> -x <context> -i]
+
+All of the results will be placed into the current window's location
+list (:help location-list) so that you can easily navigate the
+results.
+
+Vim command completion is supported through out the command with the
+exception of the pattern to search for.
+
+>
+
+ :CSearch <Tab>
+ :CSearch -p MyClass* <Tab>
+ :CSearch -p MyClass* -t <Tab>
+ :CSearch -p MyClass* -t class <Tab>
+ :CSearch -p MyClass* -t class -s <Tab>
+ :CSearch -p MyClass* -t class -s project
+ :CSearch -p MyClass* -t class -s project <Tab>
+ :CSearch -p MyClass* -t class -s project -x <Tab>
+ :CSearch -p MyClass* -t class -s project -x declarations
+
+<
+
+
+- -p <pattern>: The pattern to search for.
+ Ex.
+
+ >
+ MyClass
+ myFunction
+ my*
+
+ <
+
+- -t <type> (Default: all): The type of element to search for where
+ possible types include
+ - class_struct
+ - function
+ - variable
+ - union
+ - method
+ - field
+ - enum
+ - enumerator
+ - namespace
+ - typedef
+ - macro
+- -s <scope> (Default: all): The scope of the search where possible
+ scope values include
+ - all - Search the whole workspace.
+ - project - Search the current project, dependent projects, and
+ include paths.
+- -x <context> (Default: declarations): The context of the search,
+ where possible context values include
+ - all - Search for declarations and references.
+ - declarations - Search for declarations only.
+ - references - Search for all references.
+- -i: Ignore case when searching.
+
+Element Search
+==============
+
+Element searching allows you to place the cursor over just about any
+element in a source file (method call, class name, constant) and
+perform a search for that element. Performing an element search is
+the same as performing a pattern search with the exception that you do
+not specify the -p option since the element under the cursor will be
+searched for instead.
+
+If only one result is found and that result is in the current source
+file, the cursor will be moved to the element found. Otherwise, on
+single result matches, the value of |g:EclimCSearchSingleResult| will
+be consulted for the action to take. If there are multiple results,
+the location list will be opened with the list of results.
+
+*:CSearchContext*
+
+As a convenience eclim also provides the command :CSearchContext.
+This command accepts no arguments and will perform the appropriate
+search depending on the context of the element under the cursor.
+
+- If the cursor is on an #include name, it will search the
+ configured include path for the file.
+- Otherwise, it will search for the definition of the element (if
+ the cursor is on the definition, then it will search for the
+ declaration).
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimCSearchSingleResult*
+
+- g:EclimCSearchSingleResult (Default: 'split') - Determines what
+ action to take when a only a single result is found.
+ Possible values include:
+
+ - 'split' - open the result in a new window via "split".
+ - 'edit' - open the result in the current window.
+ - 'tabnew' - open the result in a new tab.
+ - 'lopen' - open the location list to display the result.
+ This setting overrides the global default for all supported language
+ types which can be set using the g:EclimDefaultFileOpenAction
+ setting which accepts the same possible values.
+
+- g:EclimLocationListHeight (Default: 10) - Sets the height in lines
+ of the location list window when eclim opens it to display search
+ results.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/c/validate.txt b/vim/eclim/doc/vim/c/validate.txt
@@ -0,0 +1,35 @@
+*vim-c-validate*
+
+*:Validate_c*
+
+
+C/C++ Validation
+****************
+
+When saving a c/c++ source file that resides in a project, eclim will
+update that source file in Eclipse and will report any validation
+errors found. Any errors will be placed in the current window's
+location list (:help location-list) and the corresponding lines in the
+source file will be marked via Vim's :sign functionality with '>>'
+markers in the left margin.
+
+Automatic validation of c/c++ source files can be disabled via the
+g:EclimCValidate variable (described below). If you choose to disable
+automatic validation, you can still use the :Validate command to
+manually validate the current file.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimCValidate*
+
+- g:EclimCValidate (Default: 1) - If set to 0, disables source code
+ validation.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/code_completion.txt b/vim/eclim/doc/vim/code_completion.txt
@@ -0,0 +1,127 @@
+*vim-code_completion*
+
+Code Completion
+***************
+
+
+Usage
+=====
+
+All the code completion functionality provided by eclim (ant, java,
+etc) makes use of the new "User Defined Completion" added to Vim 7.
+To initiate code completion enter insert mode and type Ctrl-X Ctrl-U.
+By default Vim will open a popup if there is more than one completion.
+
+*g:EclimCompletionMethod*
+
+Note: If you would prefer to have eclim use vim's omni code
+ completion instead, you can add the following to your vimrc:>
+
+ let g:EclimCompletionMethod = 'omnifunc'
+
+ <
+
+
+ When using omnifunc you will use Ctrl-X Ctrl-O to start code
+ completion.
+
+Example with java completion
+
+[image]
+
+Once you have started the completion you can use Ctrl-N to proceed to
+the next match and Ctrl-P to move to the previous match.
+
+To find out more about Vim's insert completion execute the following
+from within Vim:
+
+>
+
+ :h ins-completion
+
+<
+
+
+
+Third Party Completion Plugins
+==============================
+
+If you are like me and you find the above key strokes a bit
+cumbersome, then you might want to check out one of the following
+plugins which can make completion usage less cumbersome:
+
+- SuperTab (https://github.com/ervandew/supertab): This plugin's aim
+ is to allow you to use <tab> for all your code completion needs.
+ By default supertab will use vim's keyword completion on <tab>, so
+ you probably want to at least add the following setting to your
+ vimrc:
+
+ >
+ let g:SuperTabDefaultCompletionType = 'context'
+
+ <
+
+ That will tell supertab to use keyword completion unless you are
+ attempting to access a member of an object or class, in which case
+ it will use your user completion method, such as eclim.
+
+- AutoComplPop (https://bitbucket.org/ns9tks/vim-autocomplpop): This
+ plugin will automatically open the completion popup for you after
+ you've typed a preconfigured number of characters.
+ AutoComplPop by default only supports triggering code completion for
+ file types who have an omni completion that ships with vim, but you
+ can configure it to support eclim code completion. Here is an
+ example of some vim script you can add to your vimrc to enabled
+ AutoComlPop for java file types (this example will trigger the
+ completion popup when at least 3 characters have been typed after a
+ dot, but you can tweak this to your tastes):
+
+ >
+ let g:acp_behaviorJavaEclimLength = 3
+ function MeetsForJavaEclim(context)
+ return g:acp_behaviorJavaEclimLength >= 0 &&
+ \ a:context =~ '\k\.\k\{' . g:acp_behaviorJavaEclimLength . ',}$'
+ endfunction
+ let g:acp_behavior = {
+ \ 'java': [{
+ \ 'command': "\<c-x>\<c-u>",
+ \ 'completefunc' : 'eclim#java#complete#CodeComplete',
+ \ 'meets' : 'MeetsForJavaEclim',
+ \ }]
+ \ }
+
+ <
+
+- neocomplcache (https://github.com/Shougo/neocomplcache.vim):
+ Another completion plugin which will automatically open the
+ completion popup for you as you type. Configuring neocomplecache is
+ a bit easier than AutoComplPop. You just need to tell eclim to
+ register its completion to vim's omni complete, then force
+ neocomplcache to use it. Here is an example for forcing the use of
+ eclim's code completion for the java file type when you attempt to
+ access an object/class member:
+ >
+ let g:EclimCompletionMethod = 'omnifunc'
+
+ if !exists('g:neocomplcache_force_omni_patterns')
+ let g:neocomplcache_force_omni_patterns = {}
+ endif
+ let g:neocomplcache_force_omni_patterns.java = '\k\.\k*'
+
+ <
+
+- YouCompleteMe (https://github.com/Valloric/YouCompleteMe): Yet
+ another completion plugin which will automatically open the
+ completion popup for you and which also adds fuzzy matching of
+ completion results. This plugin does have a compiled component to it
+ so be sure to read their install docs thoroughly.
+ Once installed, the only required configuration you should need is
+ the following to tell eclim to register its completion to vim's omni
+ complete which YouCompleteMe will automatically detect and use:
+
+ >
+ let g:EclimCompletionMethod = 'omnifunc'
+
+ <
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/core/eclim.txt b/vim/eclim/doc/vim/core/eclim.txt
@@ -0,0 +1,165 @@
+*vim-core-eclim*
+
+Eclim Manage / Config
+*********************
+
+Below is a list of the core commands and configuration for eclim
+inside of vim.
+
+
+Commands
+========
+
+*:PingEclim*
+
+- :PingEclim - Pings eclimd to see if it is up and running.
+*:ShutdownEclim*
+
+- :ShutdownEclim - Shuts down the current running eclimd instance.
+*:EclimSettings*
+
+- :EclimSettings - Allows you to view / edit the global settings
+ (|vim-settings|). For project level settings see the
+ |:ProjectSettings| command on the project documentation page
+ (|vim-core-project|).
+*:EclimDisable*
+
+- :EclimDisable - Allows you to temporarily disable all
+ communication with eclimd for the current vim session. Useful if
+ you need to shutdown eclimd for one reason or antoher, and would
+ like to disable vim's attempts to communicate with the non-existant
+ server.
+*:EclimEnable*
+
+- :EclimEnable - Re-enables communication with eclimd (the converse
+ of :EclimDisable).
+*:EclimHelp*
+
+- :EclimHelp [<topic>] - Similar to vim's :help command, with the
+ exception that this command is limited to opening topics for eclim.
+*:EclimHelpGrep*
+
+- :EclimHelpGrep /<pattern>/ - Command which allows you to search
+ the eclim help files via vimgrep.
+ Ex.
+
+ >
+ :EclimHelpGrep /completion/
+
+ <
+
+
+Configuration
+=============
+
+Eclim Settings (|vim-settings|)
+
+*org.eclim.user.name*
+
+- org.eclim.user.name Should be set to your name. Used by various
+ commands that add contact or author information to a file.
+*org.eclim.user.email*
+
+- org.eclim.user.email Should be set to the email address where you
+ can be contacted. Used by various commands that add contact or
+ author information to a file.
+*org.eclim.project.version*
+
+- org.eclim.project.version Should be set to the version number of
+ your project. This is used by various commands that add version
+ info to a file or utilize the version number in some other manner.
+ Defaults to "1.0".
+
+Vim Settings (|vim-settings|)
+
+The following is a list of some of the common Vim variables available.
+
+*g:EclimLogLevel*
+
+- g:EclimLogLevel (Default: 4)
+ Much like the Vim 'verbose' option, this variable allows you to
+ control the level of output from eclim as follows:
+
+ - <= 0: No output.
+ - >= 1: Fatal errors.
+ - >= 2: Errors.
+ - >= 3: Warning messages.
+ - >= 4: Info messages.
+ - >= 5: Debug messages.
+ - >= 6: Trace messages.
+ Each level also has a corresponding variable to set the highlighting
+ group used for the text.
+
+ *g:EclimFatalHighlight*
+ - g:EclimFatalHighlight (Default: "Error")
+ *g:EclimErrorHighlight*
+ - g:EclimErrorHighlight (Default: "Error")
+ *g:EclimWarningHighlight*
+ - g:EclimWarningHighlight (Default: "WarningMsg")
+ *g:EclimInfoHighlight*
+ - g:EclimInfoHighlight (Default: "Statement")
+ *g:EclimDebugHighlight*
+ - g:EclimDebugHighlight (Default: "Normal")
+ *g:EclimTraceHighlight*
+ - g:EclimTraceHighlight (Default: "Normal")
+*g:EclimSignLevel*
+
+- g:EclimSignLevel (Default: 5)
+ Behaves just like g:EclimLogLevel except this applies to placing of
+ Vim signs for displaying validation errors / warnings, or marking
+ :[vim]grep matches.
+
+ The resulting signs also use the same highlighting variables above.
+
+*g:EclimEchoHighlight*
+
+- g:EclimEchoHighlight (Default: "Statement")
+ Determines which highlight group will be used for informative
+ messages.
+
+*g:EclimBrowser*
+
+- g:EclimBrowser (Default: Dependent on OS)
+ Configures the external web browser to use when opening urls. By
+ default eclim will attempt to set a default browser based on your
+ system, but if it cannot find a compatible browser, you will need to
+ set one in your vimrc.
+
+ - Firefox let g:EclimBrowser = 'firefox'
+ - Mozilla let g:EclimBrowser = 'mozilla'
+ - Opera let g:EclimBrowser = 'opera'
+ - IE let g:EclimBrowser = 'iexplore'
+ Note: The above examples assume that the browser executable is in
+ your path. On windows machines they won't be by default, so you will
+ need to add them.
+
+*g:EclimShowCurrentError*
+
+- g:EclimShowCurrentError (Default: 1)
+ This variable determines whether or not a CursorHold autocommand is
+ created that will echo the error associated with the current line if
+ any error exists. Setting this variable to 0 disables this feature.
+
+*g:EclimMakeLCD*
+
+- g:EclimMakeLCD (Default: 1)
+ When set to a non-0 value, all eclim based make commands (:Ant,
+ :Maven, :Mvn, etc) will change to the current file's project root
+ before executing.
+
+ Enabling this has the benefit of allowing you to run these commands
+ from any file regardless of where it was opened from without having
+ to worry about the directory it is executing from. For example if
+ you have a file open from project A and split a file from project B,
+ you can execute :Ant from the project B file and it will utilize
+ project B's build.xml even though your current working directory is
+ in project A.
+
+*g:EclimMenus*
+
+- g:EclimMenus (Default: 1)
+ When set to a non-0 value, enabled auto generation of gvim menus
+ (under Plugin.eclim) for each eclim command available for the
+ current buffer.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/core/history.txt b/vim/eclim/doc/vim/core/history.txt
@@ -0,0 +1,85 @@
+*vim-core-history*
+
+Eclipse Local History
+*********************
+
+Eclipse provides a feature called local history, which is basically a
+simplistic version control system that is updated every time you save
+a file. Using this local history, you can view diffs against
+previously saved versions of your file or revert to one of those
+revisions.
+
+Eclim supports updating eclipse's local history when writing files
+from vim, but by default this feature is disabled unless gvim was
+started from the eclipse gui, in which case eclim will honor the
+default eclipse editor behavior and update the local history. You can
+turn this feature on in all cases by adding the following to your
+vimrc:
+
+>
+
+ let g:EclimProjectKeepLocalHistory = 1
+
+<
+
+
+*:History*
+
+:History - Opens a temporary buffer showing the local history for the
+current file. In this buffer you can perform the following actions
+using the specified key bindings:
+
+- <cr> - view the contents of the revision under the cursor.
+- d - diff the revision under the cursor against the current
+ contents.
+- r - revert the current file to the revision under the cursor.
+- c - clear the local history for the file.
+*:HistoryClear*
+
+:HistoryClear[!] - Clears the local history for the current file.
+When the bang (!) is supplied, you are not prompted before clearing
+the history.
+
+*:HistoryDiffNext*
+
+:HistoryDiffNext - While the history buffer is open, this command
+allows you to diff the current file against the next entry in the
+history stack.
+
+*:HistoryDiffPrev*
+
+:HistoryDiffPrev - Just like :HistoryDiffNext but diffs against the
+previous entry in the stack.
+
+
+Configuration
+=============
+
+Eclipse Settings
+
+- When writing to the local history, eclim simply proxies the
+ request to eclipse, so all eclipse settings are honored. To modify
+ these settings you currently have to do so inside of the eclipse
+ gui. First shut down eclimd if you are running a headless version,
+ then open the eclipse gui and navigate to:
+ Window ‣ Preferences ‣ General ‣ Workspace ‣ Local History
+
+ And there you can edit your settings as necessary.
+
+Vim Settings (|vim-settings|)
+
+*g:EclimProjectKeepLocalHistory*
+
+- g:EclimProjectKeepLocalHistory (Default: 0) - Controls whether
+ writes in vim will update the eclipse local history. This is
+ disabled by default unless gvim was started from the eclipse gui, in
+ which case eclim will honor the default eclipse editor behavior and
+ update the local history.
+*g:EclimHistoryDiffOrientation*
+
+- g:EclimHistoryDiffOrientation (Default: 'vertical') - When
+ initiating diffs, this setting controls whether the diff window is
+ opened as a horizontal split or vertical. Supported values include
+ 'horizontal' and 'vertical'.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/core/index.txt b/vim/eclim/doc/vim/core/index.txt
@@ -0,0 +1,12 @@
+*vim-core-index*
+
+Core Functionality
+******************
+
+- Eclim Manage / Config (vim-core-eclim)
+- Eclipse Project Management (vim-core-project)
+- Eclipse Local History (vim-core-history)
+- Locate File (vim-core-locate)
+- Utility Commands (vim-core-util)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/core/locate.txt b/vim/eclim/doc/vim/core/locate.txt
@@ -0,0 +1,97 @@
+*vim-core-locate*
+
+*:LocateFile*
+
+
+Locate File
+***********
+
+Eclim provides the :LocateFile command to allow you to quickly find
+and open files or buffers.
+
+- :LocateFile [file_pattern] - Attempts to locate the supplied file
+ pattern or if no argument is supplied, opens a temporary window
+ where the text you type is turned into a pattern and search results
+ are presented as you type.
+ [image]
+ While in this completion mode the following key bindings are
+ available:
+ - <esc> - close the search window without selecting a file
+ - <tab> or <down> - cycle forward through the results
+ - <shift><tab> or <up> - cycle backwards through the results
+ - <enter> - open the selected file using the default action
+ - <ctrl>e - open the selected file via :edit
+ - <ctrl>s - open the selected file via :split
+ - <ctrl>t - open the selected file via :tabnew
+ - <ctrl>l - switch the locate scope
+ - <ctrl>h - toggle the help buffer
+ By default, the search string accepted by the completion mode is
+ intended to be just portions of the file name you are looking for,
+ which is then automatically expanded in an effort to help you find
+ the file with the fewest keystrokes possible.
+
+ The argument version of :LocateFile on the other hand, accepts a
+ hybrid glob/regex pattern. The glob portion allows you to use * and
+ ** to match portions of a path or traverse multiple directories.
+ You can mix * and ** with standard perl compatible regex operators
+ to construct your search pattern.
+
+ If you prefer the more explicit patterns supported by the argument
+ version of :LocateFile over the default "fuzzy" pattern supported by
+ the completion version of :LocateFile, then you can turn off the
+ fuzzy matching support using the g:EclimLocateFileFuzzy variable
+ described below.
+
+ By default, all searching by both variants of this command is
+ limited to the current project and any projects listed as
+ dependencies, but you can widen the search scope to include all open
+ projects by setting g:EclimLocateFileScope to 'workspace', which is
+ the default scope when :LocateFile is executed outside of a project.
+
+ In addition to the 'project' and 'workspace' scopes, :LocateFile
+ also supports the following scopes:
+
+ - buffers: search listed buffers
+ - quickfix: search the quickfix results
+ - vcsmodified: search files reported by your vcs as modified or
+ untracked.
+ Note: For performance reasons, locating files in the 'project' and
+ 'workspace' scopes depends on eclipse being aware of all your
+ project files. For the most part this is handled automatically as
+ you create and edit files within vim. However, actions you take
+ outside of vim or eclipse (moving/removing files, updates from a
+ version control system, etc.) will not be visible until you force
+ a project refresh via |:ProjectRefresh|.
+
+ Configuration
+
+ Vim Settings (|vim-settings|)
+
+ *g:EclimLocateFileDefaultAction*
+ - g:EclimLocateFileDefaultAction (Default: 'split') - Determines
+ the command used to open the file when hitting <enter> on an entry
+ in the locate file results.
+ *g:EclimLocateFileScope*
+ - g:EclimLocateFileScope (Default: 'project') - Determines the
+ scope for which to search for files.
+ - 'project': search only the current project and its
+ dependencies.
+ - 'workspace': search the entire workspace (all open projects).
+ - 'buffers': search listed buffers
+ - 'quickfix': search the quickfix results
+ - 'vcsmodified': search files reported by your vcs as modified
+ or untracked.
+ *g:EclimLocateFileFuzzy*
+ - g:EclimLocateFileFuzzy (Default: 1) - Determines whether or not
+ 'fuzzy' searching will be used on the no argument version of
+ :LocateFile.
+ *g:EclimLocateFileCaseInsensitive*
+ - g:EclimLocateFileCaseInsensitive (Default: 'lower') - Determines
+ when case insensitive searching is performed.
+ - 'lower': when the search string is all lower case the search
+ will be case insensitive, but if one or more capital letters are
+ present, then the search will be case sensitive.
+ - 'always': searching will always be case insensitive.
+ - 'never': searching will never be case insensitive.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/core/project.txt b/vim/eclim/doc/vim/core/project.txt
@@ -0,0 +1,452 @@
+*vim-core-project*
+
+Eclipse Project Management
+**************************
+
+The core concept in most IDEs is the that of a project, and Eclipse is
+no different. Since a project must exist before you can perform any
+of the more interesting tasks, eclim provides a set of commands to
+create and manage projects from within Vim.
+
+For the commands below that accept a project name as an argument, you
+may use Vim's command line completion to complete the project name.
+
+>
+
+ :ProjectSettings a_p<Tab>
+ :ProjectSettings a_project
+
+<
+
+
+*:ProjectCreate*
+
+- :ProjectCreate <folder> [-p <project_name>] -n <nature> ... [-d
+ <project_dependency> ...]
+ - -p: Optional argument used to specify the project name. If
+ omitted, eclim will use the last segment of the project's path,
+ with any spaces replaced with underscores, as the project name.
+ - -n: Required argument which specifies a space separated list of
+ project natures (java, php, etc.) to add to the project. If you
+ want to create a project with no natures, you can use the word
+ "none" here.
+ >
+ :ProjectCreate ~/workspace/test -n none
+
+ <
+
+ Note that eclim supports command completion of available nature
+ names.
+
+ >
+ :ProjectCreate ~/workspace/test -n p<tab>
+ :ProjectCreate ~/workspace/test -n php
+
+ <
+
+ - -d: Optional argument used to specify a space separated list of
+ project names which the project you're creating depends on.
+ Some Examples
+
+ >
+ :ProjectCreate ~/projects/a_project -n java
+ :ProjectCreate ~/projects/a_project -n java -d another_project yet_another_project
+ :ProjectCreate ~/projects/a_project -n java php -p My\ Project\ Name
+
+ <
+
+*:ProjectImport*
+
+- :ProjectImport <folder>
+ If you have an existing eclipse project folder which does not exist
+ as a project in your current workspace, you can import that project
+ using this command:
+
+ >
+ :ProjectImport ~/workspace/some_project
+
+ <
+
+*:ProjectList*
+
+- :ProjectList
+ Simply echo a list of available projects.
+
+*:ProjectSettings*
+
+- :ProjectSettings [<project>]
+ Opens a window with the project's available settings. If a project
+ name is supplied with this command, then the settings for that
+ project are opened. If no project name is supplied, and the current
+ file is in a project directory, then the settings for the current
+ project will be opened.
+
+ In the resulting window you can modify the values and save the
+ changes by simply writing the file in the usual Vim manner (:w). The
+ format of the buffer is in the standard properties file format as
+ supported by java, so all the same rules apply when editing. You can
+ refer to the settings (|vim-settings|) documentation for a
+ description of the available settings.
+
+*:ProjectDelete*
+
+- :ProjectDelete <project>
+ Deletes the project with the specified name.
+
+*:ProjectRename*
+
+- :ProjectRename [<project>] <name>
+ Renames a project. If two arguments are supplied then the first
+ argument is interpreted as the name of the project to rename and the
+ second argument as the new name for the project. When only a single
+ argument is supplied, then that argument is used as the new name for
+ the project which the current file belongs to.
+
+*:ProjectMove*
+
+- :ProjectMove [<project>] <dir>
+ Moves a project to the specified directory. If two arguments are
+ supplied then the first argument is interpreted as the name of the
+ project to move and the second argument as the directory to move the
+ project to. When only a single argument is supplied, then that
+ argument is used as the directory to move the current project to.
+
+ Warning: :ProjectMove, and possibly :ProjectRename, will result in
+ the renaming of your project's directory in the underlying file
+ system. Eclim will do its best to reload any files that have
+ moved as a result of the directory renaming and adjust your
+ current working directory if necessary, but only for the current
+ vim session. If you have other vim sessions open with files from
+ the project, then eclim will be unable to reload those files in
+ those sessions for you, so you will have to do so manually. A
+ best practice would be to close any other vim sessions that might
+ be affected by the moving or renaming of a project.
+
+ Note: When open files have moved as a result of :ProjectMove or
+ :ProjectRename, eclim will reload those files in the current
+ session, but it must do so via an :edit, which means that vim's
+ undo tree will be lost. However, you will still have access to the
+ eclipse history (|vim-core-history|).
+
+*:ProjectRefresh*
+
+- :ProjectRefresh [<project> <project> ...]
+ Refreshes the supplied list of named projects by synchronizing each
+ project against the current files on disk. If no projects names are
+ supplied, refresh the current project. Useful when files may have
+ been added, removed, or updated by a secondary application, like a
+ version control system (cvs, subversion, etc).
+
+*:ProjectRefreshAll*
+
+- :ProjectRefreshAll
+ Refreshes all projects.
+
+*:ProjectBuild*
+
+- :ProjectBuild [<project>]
+ Builds the current or supplied project.
+
+*:ProjectInfo*
+
+- :ProjectInfo [<project>]
+ Echo info about the current or supplied project.
+
+ *g:EclimProjectStatusLine*
+ Eclim supports displaying info about the current project in vim's
+ status line by adding a call to
+ eclim#project#util#ProjectStatusLine() to your statusline option:
+
+ >
+ set statusline=%<%f\ %M\ %h%r%=%-10.(%l,%c%V\ %{eclim#project#util#ProjectStatusLine()}%)\ %P
+
+ <
+
+ By default, this will just include the project name, but you can
+ customize the output by setting g:EclimProjectStatusLine:
+
+ >
+ let g:EclimProjectStatusLine = 'eclim(p=${name}, n=${natures})'
+
+ <
+
+*:ProjectOpen*
+
+- :ProjectOpen [<project>]
+ Opens a closed project.
+
+*:ProjectClose*
+
+- :ProjectClose [<project>]
+ Closes the current or supplied project. According to the Eclipse
+ documentation, closing unused projects can reduce the amount of
+ memory used, and may improve performance when building projects.
+
+*:ProjectNatures*
+
+- :ProjectNatures [<project>]
+ Echo list of natures for the supplied project name or for all
+ projects if no project name specified.
+
+*:ProjectNatureAdd*
+
+- :ProjectNatureAdd <project> [<nature> ...]
+ Adds one or more natures to a project. Supports command line
+ completion of nature names.
+
+*:ProjectNatureRemove*
+
+- :ProjectNatureRemove <project> [<nature> ...]
+ Removes one or more natures from a project. Supports command line
+ completion of nature names.
+
+*:ProjectProblems*
+
+- :ProjectProblems[!] [<project>] Populates vim's quickfix with a
+ list of all eclipse build errors and warnings for the current, or
+ specific project, and all related projects. Very similar to
+ eclipse's "Problems" view. By default, if the current quickfix list
+ represents a problems list, then as you save source files this list
+ will be updated accordingly.
+ Appending '!' limits the problem results to just errors.
+
+ Note: Problems are only reported for those projects that have an
+ associated builder in their .project file. If a project is not
+ reporting errors, first check that a proper builder is present in
+ the .project file. For java projects created via eclim prior to
+ eclim 1.5.2, the java builder may be missing, so you'll need to
+ recreate the project, at which time eclim will add the java
+ builder.
+
+ Configuration
+
+ Vim Settings (|vim-settings|)
+
+ *g:EclimProblemsQuickFixOpen*
+ - g:EclimProblemsQuickFixOpen (Default: 'botright copen')
+ Specified the command used to open the quickfix window when
+ executing the :ref`:ProjectProblems` command.
+
+ *g:EclimProjectProblemsUpdateOnSave*
+ - g:EclimProjectProblemsUpdateOnSave (Default: 1)
+ When non 0, indicates that the problems list should be updated
+ when saving source files, but only if the quickfix list currently
+ represents a problems list.
+
+ - g:EclimProjectProblemsUpdateOnBuild (Default: 1)
+ When non 0, indicates that the problems list should be updated
+ after a :ProjectBuild, but only if the quickfix list currently
+ represents a problems list.
+
+*:ProjectCD*
+
+- :ProjectCD
+ Changes the global current working directory to the root directory
+ of the current file's project (executes a :cd).
+
+*:ProjectLCD*
+
+- :ProjectLCD
+ Changes the current working directory of the current window to the
+ root directory of the current file's project (executes a :lcd).
+
+*:ProjectTree*
+
+ - :ProjectTree [<project> <project> ...] :ProjectTree <dir> [<dir>
+ <project> ...]
+ Opens a window containing a navigable tree for the root directory of
+ one or more projects. If no arguments are supplied, the resulting
+ tree is for the current project. Otherwise, the tree contains
+ multiple root nodes, one for each project root directory. The
+ command also supports one or more arbitrary directories as arguments
+ as well should you want to open a tree for a project not managed by
+ eclim/eclipse (Note: the last part of the path will be used as the
+ project's name).
+
+ Available key mappings in project tree window.
+
+ - <cr> - Toggles expansion / collapsing of a directory, or
+ executes the first available action for a file.
+ - E - Opens the current file using 'edit' in the content window.
+ - S - Opens the current file in a new split.
+ - | (pipe) - Opens the current file in a new vertical split.
+ - T - Opens the current file in a new tab.
+ - o - Toggles folding / unfolding of a directory, or opens a
+ window of available actions to be executed on the selected file.
+ Hitting <enter> on an entry in the action window will execute that
+ action on the current file.
+ - s - Executes :shell for the directory under the cursor or the
+ parent directory of the file under the cursor.
+ - R - Refreshes the current directory against the current state of
+ the file system.
+ - A - Toggles whether or not hidden files are displayed in the
+ tree.
+ - ~ - Changes the root node to the current user's home directory.
+ - C - Changes the root node to the directory under cursor.
+ - B - Changes the root node to the parent directory of the current
+ root node.
+ - K - Changes the root node to the root path which will be either
+ the project root or the file system root.
+ - p - Moves the cursor to the parent of the node under the cursor.
+ - P - Moves the cursor to the last child of the nearest open
+ directory.
+ - :CD <dir> - Changes the root to the supplied directory.
+ - D - Prompts you for a directory name to create, pre-filled with
+ the directory path in the tree where this mapping was executed.
+ - F - Prompts you for a new or existing filename to open,
+ pre-filled with the directory path in the tree where this mapping
+ was executed.
+ - Y - Yanks the path of the current file/directory to your
+ clipboard.
+ - ? - View the help buffer
+ Configuration
+
+ Vim Settings (|vim-settings|)
+
+ *g:EclimProjectTreeAutoOpen*
+ - g:EclimProjectTreeAutoOpen (Default: 0)
+ When non 0, a project tree window will be auto opened for new Vim
+ sessions or new tabs in existing sessions if the current file is
+ in a project.
+
+ *g:EclimProjectTreeAutoOpenProjects*
+ - g:EclimProjectTreeAutoOpenProjects (Default: ['CURRENT'])
+ List of project names that will be in the project tree when it is
+ auto opened. The special name 'CURRENT' represents the current
+ project of the file being loaded in Vim when the tree is auto
+ opened.
+
+ *g:EclimProjectTreeExpandPathOnOpen*
+ - g:EclimProjectTreeExpandPathOnOpen (Default: 0)
+ When non 0, the path of the current file will be expanded in the
+ project tree when the project tree window is opened.
+
+ *g:EclimProjectTreePathEcho*
+ - g:EclimProjectTreePathEcho (Default: 1)
+ When non 0, the root relative path of the node under the cursor
+ will be echoed as you move the cursor around.
+
+ *g:EclimProjectTreeSharedInstance*
+ - g:EclimProjectTreeSharedInstance (Default: 1)
+ When non 0, a tree instance with the same list of projects will be
+ shared across vim tabs. This allows you to have the same project
+ tree open in several tabs all with the same state (with the
+ exception of folds).
+
+ *g:EclimProjectTreeActions*
+ - g:EclimProjectTreeActions
+ Default:
+
+ >
+ let g:EclimProjectTreeActions = [
+ \ {'pattern': '.*', 'name': 'Split', 'action': 'split'},
+ \ {'pattern': '.*', 'name': 'Tab', 'action': 'tabnew'},
+ \ {'pattern': '.*', 'name': 'Edit', 'action': 'edit'},
+ \ ]
+
+ <
+
+ List of mappings which link file patterns to the available actions
+ for opening files that match those patterns. Note that the first
+ mapping is the list is used as the default (<cr>).
+
+ Note: ProjectTree honors vim's 'wildignore' option by filtering
+ out files matching those patterns from the tree. The 'A' mapping
+ will toggle the display of those files along with other hidden
+ files and directories.
+
+*:ProjectTreeToggle*
+
+- :ProjectTreeToggle
+ Toggles (opens/closes) the project tree for the current project.
+
+*:ProjectsTree*
+
+- :ProjectsTree
+ Similar to :ProjectTree but opens a tree containing all projects.
+
+*:ProjectTab*
+
+ - :ProjectTab <project> :ProjectTab <dir>
+ Command to initialize a new vim tab with the project tree open and
+ the tab relative working directory set to the project root. This
+ allows you to work on multiple projects within a single vim instance
+ where each project is isolated to its own tab. The command also
+ supports an arbitrary directory as an argument instead of a project
+ name should you want to open a tab for a project not managed by
+ eclim/eclipse (Note: the last part of the path will be used as the
+ project's name).
+
+ Configuration
+
+ Vim Settings (|vim-settings|)
+
+ *g:EclimProjectTabTreeAutoOpen*
+ - g:EclimProjectTabTreeAutoOpen (Default: 1)
+ When non 0, the project tree window will be auto opened on the
+ newly created tab.
+
+*:ProjectGrep*
+
+- :ProjectGrep /<pattern>/ <file_pattern> [<file_pattern> ...]
+ Executes vimgrep using the supplied arguments from the root of the
+ current project allowing you to run a project wide grep from any
+ file within the project.
+
+*:ProjectGrepAdd*
+
+- :ProjectGrepAdd /<pattern>/ <file_pattern> [<file_pattern> ...]
+ Just like :ProjectGrep but using vimgrepadd instead.
+
+*:ProjectLGrep*
+
+- :ProjectLGrep /<pattern>/ <file_pattern> [<file_pattern> ...]
+ Just like :ProjectGrep but using lvimgrep instead.
+
+*:ProjectLGrepAdd*
+
+- :ProjectLGrepAdd /<pattern>/ <file_pattern> [<file_pattern> ...]
+ Just like :ProjectGrep but using lvimgrepadd instead.
+
+*:ProjectTodo*
+
+- :ProjectTodo
+ Searches all the source files in the project (those with extensions
+ included in |g:EclimTodoSearchExtensions|) for the fixme / todo
+ pattern (defined by |g:EclimTodoSearchPattern|) and adds all
+ occurrences to the current location list.
+
+*:Todo*
+
+- :Todo
+ Just like :ProjectTodo, but limits the searching to the current
+ file.
+
+ Configuration
+
+ Vim Settings (|vim-settings|)
+
+ *g:EclimTodoSearchPattern*
+ - g:EclimTodoSearchPattern
+ Default:
+
+ >
+ let g:EclimTodoSearchPattern = '\(\<fixme\>\|\<todo\>\)\c'
+
+ <
+
+ Defines the regex pattern used to identify todo or fixme entries.
+
+ *g:EclimTodoSearchExtensions*
+ - g:EclimTodoSearchExtensions
+ Default:
+
+ >
+ let g:EclimTodoSearchExtensions = ['java', 'py', 'php', 'jsp', 'xml', 'html']
+
+ <
+
+ Defines a list of file extensions that will be searched for the
+ todo / fixme entries.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/core/util.txt b/vim/eclim/doc/vim/core/util.txt
@@ -0,0 +1,220 @@
+*vim-core-util*
+
+Utility Commands
+****************
+
+The following is a list of utility commands provided by eclim. These
+are general purpose commands that are useful in and outside the scope
+of eclim.
+
+*:Tcd*
+
+- :Tcd dir - Mimics vim's :lcd command but sets the current working
+ directory local to the current tab instead of just the current
+ window.
+*:DiffLastSaved*
+
+- :DiffLastSaved - Performs a diffsplit with the last saved version
+ of the currently modifed file.
+*:SwapWords*
+
+- :SwapWords - Swaps two words (with cursor placed on the first
+ word). Supports swapping around non-word characters like commas,
+ periods, etc.
+*:Sign*
+
+- :Sign - Toggles adding or removing a vim sign on the current line.
+*:Signs*
+
+- :Signs - Opens a new window containing a list of signs for the
+ current buffer. Hitting <enter> on one of the signs in the list
+ will take you to that sign in the corresponding buffer.
+*:SignClearUser*
+
+- :SignClearUser - Removes all vim signs added via :Sign.
+*:SignClearAll*
+
+- :SignClearAll - Removes all vim signs.
+*:QuickFixClear*
+
+- :QuickFixClear - Removes all entries from the quick fix window.
+*:LocationListClear*
+
+- :LocationListClear - Removes all entries from the location list
+ window.
+*:Buffers*
+
+- :Buffers - Opens a temporary window with a list of all the
+ currently listed buffers in vim (like :buffers). From this list you
+ can open any of the files using one of the following shortcuts:
+ - E (shift-e) - Open the file with 'edit'.
+ - S (shift-s) - Open the file with 'split'.
+ - V (shift-v) - Open the file with 'vsplit'.
+ - T (shift-t) - Open the file with 'tabnew'.
+ - D (shift-d) - Deletes the buffer and removes it from the list.
+ - ? - View the help buffer.
+ In addition to the above mappings you can also use <return> to
+ execute the configured default action on the buffer under the
+ cursor.
+
+ To configure the default action you can set the following variable:
+
+ g:EclimBuffersDefaultAction (defaults to 'split')
+
+ Note that eclim will track the tab where buffers are opened and
+ closed allowing :Buffers to filter the list to those whose primary
+ tab is the current tab, or for buffers not open, show those that
+ were last open on the current tab. If however you would like to
+ still see all listed buffers, you can append '!' to the command:
+ :Buffers!
+
+ By default entries will be sorted by path name, but you may change
+ the sorting via these two variables:
+
+ Configuration
+
+ Vim Settings (|vim-settings|)
+
+ *g:EclimBuffersSort*
+ - g:EclimBuffersSort (defaults to 'path') Supports one of 'path',
+ 'status' (active or hidden), 'bufnr'.
+ *g:EclimBuffersSortDirection*
+ - g:EclimBuffersSortDirection (defaults to 'asc') Supports one of
+ 'asc' or 'desc'.
+ *g:EclimBuffersTabTracking*
+ - g:EclimBuffersTabTracking (defaults to 1) When set to a non-0
+ value, eclim will keep track of which tabs buffers are opened on
+ allowing the :Buffers command to filter the list of buffers to
+ those accessed by the current tab. As noted above, you can still
+ view all buffers with this option enabled by using :Buffers! ('!'
+ appended).
+ *g:EclimBuffersDeleteOnTabClose*
+ - g:EclimBuffersDeleteOnTabClose (defaults to 0) When set to a
+ non-0 value and g:EclimBuffersTabTracking is enabled, then eclim
+ will delete any non-active buffers associated with the current tab
+ when that tab is closed. The can be useful if you use a tab per
+ project workflow and would like to close a project's tab and have
+ any buffers for that project deleted as well.
+*:BuffersToggle*
+
+- :BuffersToggle - A convenience command which opens the buffers
+ window if not open, otherwise closes it. Useful for creating a key
+ mapping to quickly open/close the buffers window.
+*:Only*
+
+- :Only - Alternative for vim's :only command. The purpose of this
+ command and the original vim version is to close all but the current
+ window. Unfortunately there is no way to tell the vim version to
+ exclude some windows you may wish to keep open (taglist, quickfix,
+ etc.). The eclim version provides that ability via the
+ g:EclimOnlyExclude and g:EclimOnlyExcludeFixed variables.
+ Configuration
+
+ Vim Settings (|vim-settings|)
+
+ *g:EclimOnlyExclude*
+ - g:EclimOnlyExclude (defaults to '^NONE$') - Regex used to match
+ buffer names for windows that should not be closed when issuing
+ the :Only command.
+ *g:EclimOnlyExcludeFixed*
+ - g:EclimOnlyExcludeFixed (defaults to 1) When non-0 all fixed
+ windows (ones which have 'winfixwidth' or 'winfixheight' set) will
+ be preserved when issuing the :Only command.
+*:OpenUrl*
+
+- :OpenUrl [url] - Opens a url in your web browser, or optionally in
+ Vim via netrw (:help netrw).
+ When executing the command you may supply the url to open, or if
+ ommitted, it will open the url under the cursor. By default all
+ urls will open in your web browser, but you may optionally configure
+ a list of url patterns to be opened via the netrw plugin. The
+ following example is configured to open all dtd, xml, xsd, and text
+ files via netrw.
+
+ >
+ let g:EclimOpenUrlInVimPatterns =
+ \ [
+ \ '\.\(dtd\|xml\|xsd\)$',
+ \ '\.txt$',
+ \ ]
+
+ <
+
+ For urls that match one of these patterns, you may also define how
+ the file is to be opened in Vim (split, edit, etc.).
+
+ >
+ let g:EclimOpenUrlInVimAction = 'split'
+
+ <
+
+ If a url you want to open matches one of these patterns, but you
+ want to force it to be opened in your browser, you can supply a bang
+ (!) to force it to do so:
+
+ >
+ :OpenUrl!
+
+ <
+
+ Configuration
+
+ Vim Settings (|vim-settings|)
+
+ *g:EclimOpenUrlInVimPatterns*
+ - g:EclimOpenUrlInVimPatterns (Default: []) - Defines a list of
+ url patterns to open in Vim via netrw.
+ *g:EclimOpenUrlInVimAction*
+ - g:EclimOpenUrlInVimAction (Default: 'split') - Defines the
+ command used to open files matched by g:EclimOpenUrlInVimPatterns.
+*eclim#web#SearchEngine*
+
+- eclim#web#SearchEngine Helper function which provides the
+ functionality needed to create search engine commands or mappings.
+ >
+ command -range -nargs=* Google call eclim#web#SearchEngine(
+ \ 'http://www.google.com/search?q=<query>', <q-args>, <line1>, <line2>)
+
+ <
+
+ Adding the above command to your vimrc or similar provides you with
+ a new :Google command allowing you to start a search on google.com
+ (http://google.com) in your browser from vim. This command can be
+ invoked in a few ways.
+
+ 1. First by supplying the word or words to search for as
+ arguments to the command.
+ >
+ :Google "vim eclim"
+ :Google vim eclim
+ :Google +vim -eclim
+
+ <
+
+ Note that you can supply the arguments to the command just as you
+ would when using the search input via google's homepage, allowing
+ you to utilize the full querying capabilities of google.
+
+ 2. The second method is to issue the command with no arguments.
+ The command will then query google with the word under the
+ cursor.
+ 3. The last method is to visually select the text you want to
+ search for and then execute the command.
+*eclim#web#WordLookup*
+
+- eclim#web#WordLookup Helper function which can be used to create
+ commands or mappings which lookup a word using an online reference
+ like a dictionary or thesaurus.
+ >
+ command -nargs=? Dictionary call eclim#web#WordLookup(
+ \ 'http://dictionary.reference.com/search?q=<query>', '<args>')
+
+ <
+
+ Adding the above command to your vimrc or similar provides you with
+ a new :Dictionary command which can be used to look up a word on
+ dictionary.reference.com (http://dictionary.reference.com). You can
+ either supply the word to lookup as an argument to the command or it
+ will otherwise use the word under the cursor.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/dltk/buildpath.txt b/vim/eclim/doc/vim/dltk/buildpath.txt
@@ -0,0 +1,55 @@
+*vim-dltk-buildpath*
+
+Source code completion, searching, and other features make use of the
+eclipse dltk's (http://eclipse.org/dltk/) .buildpath to locate
+resources. When you first create a dltk project (currently php
+(|vim-php-index|) or ruby (|vim-ruby-index|)), a .buildpath file is
+created in the project's root directory. If your project depends on
+any source files located outside your project or in another project,
+then you'll need to edit your .buildpath accordingly.
+
+To help you do this, eclim provides several commands to ease the
+creation of new build path entries and variables, all of which are
+made available when you edit your .buildpath file in vim. Also when
+you write the .buildpath file, Vim will issue a command to the eclim
+server to update the project's build path, and will report any errors
+via vim's location list (:help location-list).
+
+The following is a list of commands that eclim provides while editing
+your .buildpath.
+
+*:NewSrcEntry_dltk*
+
+- :NewSrcEntry <dir> [<dir> ...] - Adds one or more new entries
+ which reference source directories in your project.
+ >
+ <buildpathentry external="true" kind="lib" path="src/php"/>
+
+ <
+
+ This command supports command completion of project relative
+ directories.
+
+*:NewLibEntry_dltk*
+
+- :NewLibEntry <dir> [<dir> ...] - Adds one or more new entries
+ which reference external source directories.
+ >
+ <buildpathentry external="true" kind="lib" path="/usr/local/php/cake_1.1.16.5421"/>
+
+ <
+
+ This command supports command completion of directories.
+
+*:NewProjectEntry_dltk*
+
+- :NewProjectEntry <project> [<project> ...] - Adds one or more new
+ entries which reference other projects.
+ >
+ <buildpathentry combineaccessrules="false" kind="prj" path="/test_project"/>
+
+ <
+
+ This command supports command completion of project names.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/html/index.txt b/vim/eclim/doc/vim/html/index.txt
@@ -0,0 +1,146 @@
+*vim-html-index*
+
+Html / Css
+**********
+
+*html*
+
+
+Html
+====
+
+
+Code Completion
+---------------
+
+Html code completion uses the standard Vim code completion mechanism
+(|vim-code_completion|) like so:
+
+>
+
+ <ht<Ctrl-X><Ctrl-U>
+
+ <html>
+ <he<Ctrl-X><Ctrl-U>
+
+ <html>
+ <head>
+ <lin<Ctrl-X><Ctrl-U>
+
+ <html>
+ <head>
+ <link ty<Ctrl-X><Ctrl-U>
+
+ <html>
+ <head>
+ <link type
+ ...
+
+<
+
+
+
+File Validation
+---------------
+
+When editing a html file eclim will default to validating the file
+when it is written. Any errors will be added to the current window's
+location list (:help location-list) and their corresponding line
+number noted via Vim's sign functionality.
+
+If you do not want your html files validated automatically when saved,
+you can set the |g:EclimHtmlValidate| variable described in the
+configuration section below.
+
+*:Validate_html*
+
+Whether or not auto validation has been enabled, eclim also exposes
+the command :Validate to manually execute the validation of the file.
+
+
+Utils
+-----
+
+When editing html files eclim provides some utilility commands for
+your convience.
+
+*:BrowserOpen*
+
+:BrowserOpen - Opens the current html file in your configured browser.
+
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimHtmlValidate*
+
+- g:EclimHtmlValidate (Default: 1) - If set to 0, disables
+ validation when saving the file.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+*css*
+
+
+Css
+===
+
+
+Code Completion
+---------------
+
+Css code completion uses the standard Vim code completion mechanism
+(|vim-code_completion|) like so:
+
+>
+
+ bo<Ctrl-X><Ctrl-U>
+
+ body {
+ font-<Ctr-X><Ctrl-U>
+
+ body {
+ font-family: sa<Ctrl-X><Ctrl-U>
+
+ body {
+ font-family: sans-serif;
+ ...
+
+<
+
+
+
+Validation
+----------
+
+When editing a css file eclim will default to validating the file when
+it is written. Any errors will be added to the current window's
+location list (:help location-list) and their corresponding line
+number noted via Vim's sign functionality.
+
+If you do not want your css files validated automatically when saved,
+you can set the |g:EclimCssValidate| variable described in the
+configuration section below.
+
+*:Validate_css*
+
+Whether or not auto validation has been enabled, eclim also exposes
+the command :Validate to manually execute the validation of the file.
+
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimCssValidate*
+
+- g:EclimCssValidate (Default: 1) - If set to 0, disables validation
+ when saving the file.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/index.txt b/vim/eclim/doc/vim/index.txt
@@ -0,0 +1,31 @@
+*vim-index*
+
+Documentation
+*************
+
+
+Core Functionality
+==================
+
+- The Eclim Daemon (eclimd)
+- Core Functionality (vim-core-index)
+ - Eclim Manage / Config (vim-core-eclim)
+ - Eclipse Project Management (vim-core-project)
+ - Eclipse Local History (vim-core-history)
+ - Locate File (vim-core-locate)
+ - Utility Commands (vim-core-util)
+
+Supported Languages
+===================
+
+- C/C++ (vim-c-index)
+- Html / Css (vim-html-index)
+- Java (vim-java-index)
+- Javascript (vim-javascript-index)
+- Php (vim-php-index)
+- Python (vim-python-index)
+- Ruby (vim-ruby-index)
+- Scala (vim-scala-index)
+- Xml / Dtd / Xsd (vim-xml-index)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/android.txt b/vim/eclim/doc/vim/java/android.txt
@@ -0,0 +1,70 @@
+*vim-java-android*
+
+Android
+*******
+
+
+Creating a project
+==================
+
+Creating an android project is the same as creating a regular java
+project, but you use the android nature instead:
+
+>
+
+ :ProjectCreate /path/to/my_project -n android
+
+<
+
+
+This will result in a series of prompts for you to input your
+project's information:
+
+Note: at any point in this process you can use Ctrl+C to cancel the
+project creation.
+
+1. First you will be asked to choose the target android platform.
+ If you have only one platform installed on your system, this prompt
+ will be skipped and that platform will be used when creating the
+ project. If you have no platforms installed then you will receive
+ an error directing you to install a platform using the Android SDK
+ Manager. If you install a new platform you will need to either
+ restart eclipse/eclimd or run the eclim supplied |:AndroidReload|
+ command.
+2. Next you will be asked to supply a package name (Ex:
+ com.mycompany.myapp).
+3. Then you will need to supply a name for your application.
+4. The next prompt will ask you if you are creating a library
+ project or not. Most likely you are not, so type 'n' here to
+ proceed.
+5. Lastly, if you are not creating a library project, you will be
+ asked whether or not you want to have a new android activity
+ created for you and if so, you will be asked for the name of that
+ activity.
+Once you've finished supplying the necessary information, your android
+project will be created. An android project is simply a specialized
+java project, so you can now leverage all the eclim provided java
+functionality (|vim-java-index|) while developing your app.
+
+
+Commands
+========
+
+*:AndroidReload*
+
+:AndroidReload - Reloads the Android SDK environment in the running
+eclimd/eclipse instance. Useful if you've made changes to the SDK
+outside of eclipse (installed a new target platform, etc).
+
+
+Configuration
+=============
+
+Eclim Settings (|vim-settings|)
+
+*com.android.ide.eclipse.adt.sdk*
+
+- com.android.ide.eclipse.adt.sdk - Sets the path to your system's
+ android sdk install.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/ant.txt b/vim/eclim/doc/vim/java/ant.txt
@@ -0,0 +1,218 @@
+*vim-java-ant*
+
+Ant
+***
+
+
+Running
+=======
+
+For those that use Vim as an editor and ant as a build tool, is is
+common to set your Vim 'makeprg' option to execute ant so that you may
+navigate compilation errors via Vim's quickfix functionality.
+
+Eclim utilizes this same paradigm to provide users with ant execution
+functionality from any file without any of the setup required by Vim.
+
+*:Ant*
+
+Eclim provides the following command:
+
+:Ant [<target> ...]
+
+which performs the following steps:
+
+- Saves any previous 'makeprg' and 'errorformat' option settings so
+ that you can define your own settings for the :make command.
+- Sets 'makeprg' to execute ant with the -find option so that it
+ will search for your build.xml file in the current directory or in a
+ parent directory.
+- Sets 'errorformat' to recognize the following errors:
+ - javac errors.
+ - javadoc errors.
+ - jasper jsp compilattion errors.
+ - junit errors / failures.
+ - cactus errors / failures.
+- Executes :make.
+- Restores your previous 'makeprg' and 'errorformat' option
+ settings.
+Additionally, if g:EclimMakeLCD (|vim-core-eclim#g:EclimMakeLCD|) is
+enabled (which it is by default), then the execution of ant will be
+performed from the current buffer's project root directory, ensuring
+that ant's build file discovery method is performed from the buffer's
+working directory and not your own.
+
+Note: :Ant also supports use of '!' (:Ant!) just like :make does,
+ which tells Vim not to jump to the first error if one exists.
+
+The :Ant command also has the added benefit of command completion.
+
+>
+
+ :Ant com<Tab>
+ :Ant compile
+
+<
+
+
+Warning: If your ant file has a lot of imports, then the command
+ completion may be slow as Eclipse parses all the imports when
+ creating the ant model. You will notice the same slow behavior when
+ using Eclipse directly to perform ant code completion.
+
+
+Code Completion
+===============
+
+Ant code completion uses the standard Vim code completion mechanism
+(|vim-code_completion|) like so:
+
+>
+
+ <ja<Ctrl-X><Ctrl-U>
+ <jar de<Ctrl-X><Ctrl-U>
+ <jar destfile="${bas<Ctrl-X><Ctrl-U>
+ <jar destfile="${basdir
+ ...
+
+<
+
+
+Screenshot of completion in action:
+
+[image]
+
+Warning: If your ant file has a lot of imports, then the code
+ completion may be slow as Eclipse parses all the imports when
+ creating the ant model. You will notice the same slow behavior when
+ using Eclipse directly.
+
+
+Validation
+==========
+
+When editing an ant xml file eclim will default to validating the file
+when it is written. Any errors will be added to the current window's
+location list (:help location-list) and their corresponding line
+number noted via Vim's sign functionality.
+
+Currently the Eclipse ant file validation isn't as robust as one might
+hope. It doesn't validate that element attributes are correct, that
+child elements are valid, etc., but it does perform the following:
+
+- If a default target is specified, validate that it exists and that
+ the target dependencies exist.
+- Check for missing dependencies.
+- Check for circular dependencies.
+Eclim also combines the above validation with xml validation
+(|xml-validation|) to validate that the ant file is well formed.
+
+If you do not want your ant files validated automatically when saved,
+you can set the |g:EclimAntValidate| variable described in the
+configuration section below.
+
+*:Validate_ant*
+
+Whether or not auto validation has been enabled, eclim also exposes
+the command :Validate to manually execute the validation of the ant
+file.
+
+*:AntDoc*
+
+
+Documentation Lookup
+====================
+
+When editing an ant build file eclim defines a command named :AntDoc
+which will attempt to lookup and open in your configured browser
+(|vim-core-eclim#g:EclimBrowser|) the documentation for the element
+under the cursor or, if supplied, the element passed to it.
+
+This command will only lookup element names, not attribute names or
+values.
+
+By default this plugin is configured to find all the standard ant
+tasks, types, etc, as well as those defined by the antcontrib
+(http://ant-contrib.sourceforge.net) project.
+
+*:AntUserDoc*
+
+If you have other tasks that you wish to add to this plugin, you can
+do so by defining the global variable g:AntUserDocs. The value of
+this variable is expected to be a map of element names to the url
+where the documentation for that element can be found. The url also
+supports a substitution variable, <element> which will be substituted
+with the lower case version of the element name.
+
+The following is an example which adds the tasks from the apache
+cactus project.
+
+>
+
+ let s:cactus =
+ \ 'http://jakarta.apache.org/cactus/integration/ant/task_<element>.html'
+ let g:AntUserDocs = {
+ \ 'cactifywar' : s:cactus,
+ \ 'cactifyear' : s:cactus,
+ \ 'cactus' : s:cactus,
+ \ 'runservertests' : s:cactus,
+ \ 'webxmlmerge' : s:cactus,
+ \ }
+
+<
+
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimAntCompilerAdditionalErrorFormat*
+
+- g:EclimAntCompilerAdditionalErrorFormat (Default: '') - Since
+ there are many more ant tasks beyond javac, javadoc, etc., eclim
+ provides this variable as a means to add error format information
+ for any additional ant tasks that you may be using.
+ Example: Adding support for xslt
+
+ >
+ let g:EclimAntCompilerAdditionalErrorFormat =
+ \ '\%A%.%#[xslt]\ Loading\ stylesheet\ %f,' .
+ \ '\%Z%.%#[xslt]\ %.%#:%l:%c:\ %m,'
+
+ <
+
+ Note: The xslt task is a bit flaky when it comes to reporting the
+ file name on errors, so the above format will catch successful
+ runs as well. If anyone has a better solution, please submit it.
+
+*g:EclimAntErrorsEnabled*
+
+- g:EclimAntErrorsEnabled (Default: 0) - When non-zero, build file
+ error messages will be added to vim's quickfix if encountered during
+ :Ant invocations. Disabled by default because it's difficult to
+ distinguish between actual issues with the build file (invalid
+ property, task, etc.) and build failure messages which occur under
+ normal usage (junit task failed due to test failure, javac failures
+ due to compile error, etc.) leading to false positives.
+*g:EclimAntValidate*
+
+- g:EclimAntValidate (Default: 1) - If set to 0, disables ant xml
+ validation when saving the file.
+
+Suggested Mappings
+==================
+
+Here are some mappings for the ant funtionality provided by eclim. To
+make use of these mappings, simply create a ftplugin file for ant and
+place your mappings there (:help ftplugin-name).
+
+- Lookup and open the documentation for the ant element under the
+ cursor with <enter>.
+ >
+ noremap <silent> <buffer> <cr> :AntDoc<cr>
+
+ <
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/classpath.txt b/vim/eclim/doc/vim/java/classpath.txt
@@ -0,0 +1,361 @@
+*vim-java-classpath*
+
+Eclipse Classpath Editing
+*************************
+
+Source code completion, searching, auto imports, all rely on a
+properly configured classpath. When you first create a project, a
+.classpath file is created in the project's root directory. If you
+created the project on an existing code-base, eclim will attempt to
+setup the .classpath file with any source code directories or
+libraries in the project.
+
+Regardless of the state of your project you will at some point need to
+update the classpath. The primary method of doing so, is to directly
+edit the .classpath to add, update, or remove entries as needed. To
+help you do this, eclim provides several commands to ease the creation
+of new classpath entries and variables.
+
+Note: All of the commands described below are only available while
+ editing the .classpath file in vim.When you write the .classpath
+ file, Vim will issue a command to the eclim server to update the
+ project's classpath, and will report any errors via vim's location
+ list (:help location-list).In addition to directly editing the
+ .classpath file, you may also use maven's support for maintaining
+ the eclipse classpath. For users who use ivy
+ (http://jayasoft.org/ivy), eclim also provides a means to auto
+ update the eclipse classpath when saving changes to your ivy.xml.
+
+*:NewSrcEntry_java*
+
+- :NewSrcEntry <dir> - Adds a new entry for a source code directory
+ relative to the project's root directory.
+ >
+ <classpathentry kind="src" path="src/java"/>
+
+ <
+
+ This command supports command completion of the directory relative
+ to the .classpath file.
+
+*:NewProjectEntry_java*
+
+- :NewProjectEntry <project> - Adds a new entry for a dependency on
+ another project.
+ >
+ <classpathentry exported="true" kind="src" path="/a_project"/>
+
+ <
+
+ This command supports command completion of the project name.
+
+*:NewJarEntry_java*
+
+- :NewJarEntry <file> [<src_path> <javadoc_path>] - Adds a new entry
+ for a jar file dependency. If the jar file is not in a folder under
+ the project root, you must use an absolute path (apparent limitation
+ with Eclipse).
+ >
+ <classpathentry exported="true" kind="lib" path="lib/commons-beanutils-1.8.3.jar"/>
+
+ <
+
+ You may optionally supply the path to the source for this jar and
+ the entry created will include the sourcepath attribute:
+
+ >
+ :NewJarEntry lib/commons-beanutils-1.8.3.jar lib/commons-beanutils-1.8.3-sources.jar
+
+ <
+
+ >
+ <classpathentry kind="lib" path="lib/commons-beanutils-1.8.3.jar"
+ sourcepath="lib/commons-beanutils-1.8.3-sources.jar"/>
+
+ <
+
+ In addition to the source path you can all supply the path to the
+ javadocs:
+
+ >
+ :NewJarEntry lib/commons-beanutils-1.8.3.jar lib/commons-beanutils-1.8.3-sources.jar lib/commons-beanutils-1.8.3-javadoc.jar
+
+ <
+
+ >
+ <classpathentry kind="lib" path="lib/commons-beanutils-1.8.3.jar"
+ sourcepath="lib/commons-beanutils-1.8.3-sources.jar">
+ <attributes>
+ <attribute name="javadoc_location" value="jar:platform:/resource/my_project/lib/commons-beanutils-1.8.3-javadoc.jar"/>
+ </attributes>
+ </classpathentry>
+
+ <
+
+*:NewVarEntry_java*
+
+- :NewVarEntry <VAR/file> [<src_path> <javadoc_path>] - Just like
+ NewJarEntry except an Eclipse "var" entry is created. When a jar
+ entry references an absolute path, you should instead use a var
+ entry. The var entry allows you to define a base dir as a variable
+ (ex. USER_HOME = /home/username), and then reference files relative
+ to that variable.
+ >
+ <classpathentry exported="true" kind="var" path="USER_HOME/lib/hibernate-4.0.jar"/>
+
+ <
+
+ This allows you to share .classpath files with other developers
+ without each having a local copy with environment specific paths.
+
+ To add new base classpath variables, you can edit
+ $ECLIPSE_HOME/plugins/org.eclim_version/classpath_variables.properties
+
+ By default, a USER_HOME variable is created that defaults to the
+ java System property "user.home" and you can add more as needed.
+
+ This command supports command completion of Eclipse variable names
+ as well as the files and directories beneath the path the variable
+ represents.
+
+ To manage the classpath variables, eclim also provides the following
+ commands.
+
+ *:VariableList*
+ - :VariableList - Lists all the currently available classpath
+ variables and their corresponding values.
+ *:VariableCreate*
+ - :VariableCreate <name> <path> - Creates or updates the variable
+ with the supplied name.
+ *:VariableDelete*
+ - :VariableDelete <name> - Deletes the variable with the supplied
+ name.
+*classpath-src-javadocs*
+
+
+Source and Javadoc location
+===========================
+
+For your var and lib classpath entries, if you didn't do so when you
+created the entry, you can configure the location for that entry's
+source code and javadocs, like the example below, allowing you to jump
+to the source (|:JavaSearch|) or lookup the docs (|:JavaDocSearch|) of
+classes, etc found in that library. Note that the javadoc location
+must be a url, whether it be on the local file system (file:, jar:file
+(jar:file):) or remote (http:).
+
+>
+
+ <classpathentry exported="true" kind="lib" path="lib/hibernate-4.0.jar"
+ sourcepath="<path>">
+ <attributes>
+ <attribute name="javadoc_location" value="file:<javadoc_dir>"/>
+ </attributes>
+ </classpathentry>
+
+<
+
+
+Note: If your javadoc location is a jar in your workspace (in the
+ curent project or another project), then the url must be in the form
+ (where <project_name> is replaced with your project's name):>
+
+ jar:platform:/resource/<project_name>/path/to/javadoc.jar!/
+
+ <
+
+
+ If the jar file is outside of your workspace, then it would be in
+ the form:>
+
+ jar:file:/your/absolute/path/to/javadoc.jar!/
+
+ <
+
+
+*classpath-maven*
+
+
+Maven
+=====
+
+Maven (http://maven.apache.org) comes bundled with an Eclipse plugin
+that allows you to easily maintain your .classpath file based on your
+pom.xml (or project.xml for maven 1.x users).
+
+Note: For additional information on the Eclipse plugin from maven,
+ you may visit their online documentation for maven 1.x
+ (http://maven.apache.org/maven-1.x/plugins/eclipse/) or maven 2.x
+ (http://maven.apache.org/guides/mini/guide-ide-eclipse.html).
+
+*:MvnRepo* *:MavenRepo*
+
+- Initial Setup
+ To initialize maven's support for updating the eclipse classpath you
+ first need to set the M2_REPO (or MAVEN_REPO for 1.x) classpath
+ variable in the Eclipse workspace by executing the following command
+ in vim:
+
+ maven 2.x:
+
+ >
+ :MvnRepo
+
+ <
+
+ maven 1.x:
+
+ >
+ :MavenRepo
+
+ <
+
+- Updating your .classpath
+ Once you have performed the initial setup, updating the Eclipse
+ .classpath file is as easy as executing the following at a command
+ line:
+
+ maven 2.x:
+
+ >
+ mvn eclipse:eclipse
+
+ <
+
+ maven 1.x:
+
+ >
+ maven eclipse
+
+ <
+
+ or in Vim:
+
+ maven 2.x:
+
+ >
+ :Mvn eclipse:eclipse
+
+ <
+
+ maven 1.x:
+
+ >
+ :Maven eclipse
+
+ <
+
+ *classpath-maven-pom*
+ For maven 2.x users, eclim also provides support for auto updating
+ the .classpath for your project every time you save your pom.xml
+ file. Any entries found in the pom.xml that are not in the
+ .classpath will be added, any entries that differ in version will be
+ updated, and any stale entries deleted. This behavior can be
+ disabled by adding the following setting to your vimrc:
+
+ >
+ let g:EclimMavenPomClasspathUpdate = 0
+
+ <
+
+ Note: This feature simply updates the entries in your project's
+ .classpath file, it does not download any newly added jars. When
+ you'd like maven to download those new jars, you can run the
+ following from the command line:>
+
+ mvn dependency:resolve
+
+ <
+
+
+ or from within Vim:>
+
+ :Mvn dependency:resolve
+
+ <
+
+
+*classpath-ivy*
+
+
+Ivy
+===
+
+For users of ivy (http://jayasoft.org/ivy), eclim provides support for
+auto updating the .classpath for your project every time you save your
+ivy.xml file. Any entries found in the ivy.xml that are not in the
+.classpath will be added, any entries that differ in version will be
+updated, and any stale entries deleted.
+
+*:IvyRepo*
+
+- Initial Setup
+ Before you can start utilizing the auto updating support, you must
+ first set the location of your ivy repository (ivy cache). This is
+ the directory where ivy will download the dependencies to and where
+ eclipse will then pick them up to be added to your project's
+ classpath.
+
+ To set the repository location you can use the :IvyRepo command
+ which is made available when editing an ivy.xml file.
+
+ >
+ :IvyRepo ~/.ivy2/cache/
+
+ <
+
+ If you fail to set this prior to writing the ivy.xml file, eclim
+ will emit an error notifying you that you first need to set the
+ IVY_REPO variable via this command.
+
+- Updating your .classpath
+ Once you have performed the initial setup, updating the Eclipse
+ .classpath file is as easy as saving your ivy.xml file (:w) and
+ letting eclim do the rest.
+
+ Note: This will update your project's .classpath file accordingly,
+ but it will not download any newly added jars. For that you'll
+ need to have a target in your ant build file which you can run
+ that will force ivy to download dependencies. Something like the
+ example from the ivy docs:>
+
+ <target name="resolve" description="--> retrieve dependencies with ivy">
+ <ivy:retrieve/>
+ </target>
+
+ <
+
+
+ You can then run this target from the command line:>
+
+ ant resolve
+
+ <
+
+
+ or from within Vim>
+
+ :Ant resolve
+
+ <
+
+
+- Preserving manually added entries
+ When utilizing the ivy support, eclim will attempt to remove any
+ stale entries from your .classpath file. If you have some manually
+ added entries, these may be removed as well. To prevent this you
+ can add a classpath entry attribute notifying eclim that the entry
+ should be preserved.
+
+ Ex.
+
+ >
+ <classpathentry kind="lib" path="lib/j2ee-1.4.jar">
+ <attributes>
+ <attribute name="eclim.preserve" value="true"/>
+ </attributes>
+ </classpathentry>
+
+ <
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/complete.txt b/vim/eclim/doc/vim/java/complete.txt
@@ -0,0 +1,35 @@
+*vim-java-complete*
+
+Java Code Completion
+********************
+
+Java code completion uses the standard Vim code completion mechanism
+(|vim-code_completion|) like so:
+
+>
+
+ System.o<Ctrl-X><Ctrl-U>
+ System.out.pri<Ctrl-X><Ctrl-U>
+
+<
+
+
+Screenshot of completion in action:
+
+[image]
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimJavaCompleteCaseSensitive*
+
+- g:EclimJavaCompleteCaseSensitive (Default: !&ignorecase) - When
+ set to a value greater than 0, eclim will filter out completions
+ that don't start with the same case base that you are attempting to
+ complete (the base and the suggested completion must have the same
+ case).
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/format.txt b/vim/eclim/doc/vim/java/format.txt
@@ -0,0 +1,77 @@
+*vim-java-format*
+
+Java Source Code Formatting
+***************************
+
+Eclim provides the ability to format java source code using the
+eclipse formatter selected for your workspace.
+
+Source code formatting is invoked in eclipse using the shortcut
+<C-S-F>, or from the Source / Format menu. The eclim equivalent is
+invoked using the :JavaFormat command described below.
+
+*:JavaFormat*
+
+- :JavaFormat - Formats the current visual selection (or the current
+ line, if nothing is selected). To format the whole file, use
+ :%JavaFormat.
+Given the following file:
+
+>
+
+ /**
+ * @return
+ *
+ * Service
+ * for test Eclipse <C-F> formatting.
+ */
+ public
+ static String
+ getAbstractService
+ ()
+ {
+ if (abstractService == null)
+ {
+ throw new RuntimeException( "abstractService isn't initialized !");
+ }
+ return abstractService;
+ }
+
+<
+
+
+You can execute :%JavaFormat to format the code according to your
+eclipse settings.
+
+>
+
+ /**
+ * @return
+ *
+ * Service for test Eclipse <C-F> formatting.
+ */
+ public static String getAbstractService() {
+ if (abstractService == null) {
+ throw new RuntimeException("abstractService isn't initialized !");
+ }
+ return abstractService;
+ }
+
+<
+
+
+
+Configuration
+=============
+
+Currently source code formatting is only configurable via the eclipse
+GUI. To do so, shutdown eclim, start the eclipse GUI and configure
+your settings via:
+
+>
+
+ Preferences : Java / Code Style / Formatter / Active Profile: / Edit
+
+<
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/import.txt b/vim/eclim/doc/vim/java/import.txt
@@ -0,0 +1,60 @@
+*vim-java-import*
+
+*:JavaImport*
+
+
+Automated Imports
+*****************
+
+The automated import functionality is pretty straightforward. Simply
+place the cursor over the element to import and issue the command:
+
+:JavaImport
+
+and one of the following events will occur:
+
+- If only one matching element is found, its import statement will
+ be placed in the file.
+- If multiple matching elements are found, you will be prompted to
+ choose the element you wish to import from a list.
+- If an element with the same name is already imported, the element
+ is in java.lang, or the element is in the same package as the
+ current src file, then no changes will occur.
+*:JavaImportOrganize*
+
+In addition to adding imports one by one, you can also add them in
+bulk along with the removal of unused imports and the sorting and
+formating of all the file's import statements using the command:
+
+:JavaImportOrganize
+
+
+Configuration
+=============
+
+Eclim Settings (|vim-settings|)
+
+*org.eclipse.jdt.ui.importorder*
+
+- org.eclipse.jdt.ui.importorder (Default: java;javax;org;com) -
+ Semicolon separated list of package names which specify the sorting
+ order for import statements. This settings is the same setting used
+ by the eclipse gui in the "Organize Imports" preference dialog.
+*org.eclim.java.import.exclude*
+
+- org.eclim.java.import.exclude (Default: ["^com.sun..*",
+ "^sunw?..*"]) - List of patterns to exclude from import results.
+*org.eclim.java.import.package_separation_level*
+
+- org.eclim.java.import.package_separation_level (Default: 1) - Used
+ to determine how imports are grouped together (or spaced apart). The
+ number represents how many segments of the package name to use to
+ determine equality, where equal imports are grouped together and
+ separated from other groups with a blank line.
+ - -1: Use the entire package name. Only imports from the same full
+ package are grouped together.
+ - 0: Don't look at any package segments. All imports are grouped
+ together with no spacing.
+ - n: Look at the first n segments of the package name.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/index.txt b/vim/eclim/doc/vim/java/index.txt
@@ -0,0 +1,55 @@
+*vim-java-index*
+
+Java
+****
+
+
+Features
+========
+
+- Eclipse Classpath Editing (vim-java-classpath)
+- Java Validation / Correction (vim-java-validate)
+- Java Code Completion (vim-java-complete)
+- Java Search (vim-java-search)
+- Java / Jps (vim-java-java)
+- Javadoc Support (vim-java-javadoc)
+- Java Source Code Formatting (vim-java-format)
+- Java Refactoring (vim-java-refactor)
+- Java Code Inspection (vim-java-inspection)
+- Automated Imports (vim-java-import)
+- Method Generation (vim-java-methods)
+- Unit Tests (vim-java-unittests)
+- Logging (log4j, etc) (vim-java-logging)
+- Ant (vim-java-ant)
+- Maven (vim-java-maven)
+- Android (vim-java-android)
+- WEB-INF/web.xml (vim-java-webxml)
+
+Suggested Mappings
+==================
+
+Here are some mappings for the java funtionality provided by eclim.
+To make use of these mappings, simply create a ftplugin file for java
+and place your mappings there (:help ftplugin-name).
+
+- Import the class under the cursor with <leader>i (:h mapleader):
+ >
+ nnoremap <silent> <buffer> <leader>i :JavaImport<cr>
+
+ <
+
+- Search for the javadocs of the element under the cursor with
+ <leader>d.
+ >
+ nnoremap <silent> <buffer> <leader>d :JavaDocSearch -x declarations<cr>
+
+ <
+
+- Perform a context sensitive search of the element under the cursor
+ with <enter>.
+ >
+ nnoremap <silent> <buffer> <cr> :JavaSearchContext<cr>
+
+ <
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/inspection.txt b/vim/eclim/doc/vim/java/inspection.txt
@@ -0,0 +1,101 @@
+*vim-java-inspection*
+
+Java Code Inspection
+********************
+
+*:JavaHierarchy*
+
+
+Class / Interface Hierarchy
+===========================
+
+When viewing a java class or interface you can view the type hierarchy
+by issuing the command :JavaHierarchy. This will open a temporary
+buffer with an inversed tree view of the type hierarchy with the
+current class / interface at the root.
+
+>
+
+ public class XmlCodeCompleteCommand
+ public class WstCodeCompleteCommand
+ public class AbstractCodeCompleteCommand
+ public class AbstractCommand
+ public interface Command
+
+<
+
+
+Inner classes / interfaces are also supported. Just place the cursor
+on the inner class / interface before calling :JavaHierarchy.
+
+While you are in the hierarchy tree buffer, you can jump to the type
+under the cursor using one of the following key bindings:
+
+- <cr> - open the type using the (default action).
+- E - open the type via :edit
+- S - open the type via :split
+- T - open the type via :tabnew
+- ? - view help buffer
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimJavaHierarchyDefaultAction*
+
+- g:EclimJavaHierarchyDefaultAction (defaults to 'split') -
+ Determines the command used to open the type when hitting <enter> on
+ the type entry in the hierarchy buffer.
+*:JavaCallHierarchy*
+
+
+Call Hierarchy
+==============
+
+When viewing a java source file you can view the call hierarchy of a
+method by issuing the command :JavaCallHierarchy. This will open a
+temporary buffer with an inversed tree view of the hierarchy of
+callers of the requested method.
+
+>
+
+ foo(int) : Object - org.test.SomeClass
+ bar() : void - org.test.AnotherClass
+ main() : void - org.test.MainClass
+ baz(String) : int - org.test.AnotherClass
+
+<
+
+
+While you are in the hierarchy tree buffer, you can jump to the call
+under the cursor using one of the following key bindings:
+
+- <cr> - open the type using the (default action).
+- E - open the type via :edit
+- S - open the type via :split
+- T - open the type via :tabnew
+- ? - view help buffer
+:JavaCallHierarchy can also be used to view the callees for a method
+by invoking the command with a !:
+
+>
+
+ :JavaCallHierarchy!
+
+<
+
+
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimJavaCallHierarchyDefaultAction*
+
+- g:EclimJavaCallHierarchyDefaultAction (defaults to 'split') -
+ Determines the command used to open the file when hitting <enter> on
+ an entry in the hierarchy buffer.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/java.txt b/vim/eclim/doc/vim/java/java.txt
@@ -0,0 +1,109 @@
+*vim-java-java*
+
+Java / Jps
+**********
+
+*:Java*
+
+
+Java
+====
+
+To run the configured main class for your project, you may use the
+:Java command, which executes java and displays the results in a
+temporary buffer.
+
+Note: Please note that this command is not intended to be a full
+ replacement for the more advance support provided by eclipse, ant,
+ or maven.
+
+The :Java will locate the main class to run using the following steps:
+
+1. if the first argument is '%' (:Java %) then run the current
+ class.
+2. if the setting |org.eclim.java.run.mainclass| is set, then use
+ the value as the fully qualified class name to run.
+3. lastly, attempt to locate a class containing a static main
+ method, if only one is found, use that class.
+
+Configuration
+-------------
+
+*org.eclim.java.run.mainclass*
+
+Eclim Settings (|vim-settings|)
+
+- org.eclim.java.run.mainclass - Fully qualified name of the class
+ containing the main method.
+- org.eclim.java.run.jvmargs - Json formatted list of default jvm
+ args.
+*:JavaClasspath*
+
+
+Echo the classpath for the current project
+------------------------------------------
+
+When editing a java file, eclim provides the command :JavaClasspath
+which will echo the project's resolved classpath entries separated by
+the system path separator or a supplied delimiter:
+
+>
+
+ :JavaClasspath
+ :JavaClasspath -d \\n
+
+<
+
+
+If you would like to get the classpath from a script, you can also
+call eclim directly:
+
+>
+
+ $ $ECLIPSE_HOME/eclim -command java_classpath -p <project_name>
+
+<
+
+
+*:JavaListInstalls*
+
+
+Viewing list of known JDKs/JREs installed
+-----------------------------------------
+
+To view a list of all the JDKs/JREs that eclipse is aware of, eclim
+provides the command :JavaListInstalls.
+
+*:Jps*
+
+
+Jps (Process Status Tool)
+=========================
+
+As of Java 1.5 (Java 5.0), the sun jdk started shipping with some
+useful tools for viewing information about running java processes. To
+provide quick and easy access to some of the information these
+commands provide, eclim exposes the command :Jps.
+
+Note: For more information on the jdk tools you may view the online
+ documentation
+ (http://docs.oracle.com/javase/6/docs/technotes/tools/#monitor).
+
+When invoked it will open a window containing information about the
+current processes and some links for viewing additional info
+(depending upon availability of required tools on your platform).
+
+Example content:
+
+[image]
+
+- Line 1 consists of the process id followed by either the class
+ name the process was started with or the path to the jar file.
+- Lines 2 - 5 contains links that when you hit <enter> on, will open
+ another window displaying the requested additional info.
+- Lines 7 - 13 is a foldable block which contains a list of all the
+ arguments passed to the main method of the process.
+- Lines 15 - 21 is a foldable block which contains a list of all the
+ arguments passed to the JVM.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/javadoc.txt b/vim/eclim/doc/vim/java/javadoc.txt
@@ -0,0 +1,123 @@
+*vim-java-javadoc*
+
+Javadoc Support
+***************
+
+*:JavaDocComment*
+
+
+Commenting
+==========
+
+Eclim provides the :JavaDocComment command which will add or update
+the javadoc comments for the element under the cursor.
+
+*:JavaDocPreview*
+
+
+Viewing
+=======
+
+While editing java code, if you'd like to view the javadoc of the
+element under the cursor, you can run the :JavaDocPreview command
+which will open vim's preview window with the element's javadoc
+content. In the preview window any links to classes, methods, etc. in
+the javadoc will be highlighted and you can view follow those links by
+hitting <cr> on the link. You can also use <c-o> to navigate back to
+the previous javadoc preview and <c-i> to navigate forward.
+
+*:JavaDocSearch*
+
+
+Searching
+=========
+
+Eclim supports searching of javadocs just like you would search the
+source code (|vim-java-search|).
+
+The only difference is that you use :JavaDocSearch instead of
+:JavaSearch.
+
+The results will be displayed in a window and you can simply hit <cr>
+on an entry to open it using the browser you configured via
+g:EclimBrowser (|vim-core-eclim#g:EclimBrowser|).
+
+The locations of the javadocs are determined via your Eclipse
+project's .classpath file. For each library entry you can define a
+javadoc attribute that points to the base url of the javadoc (http,
+file, etc).
+
+>
+
+ <classpathentry kind="lib" path="lib/hibernate-3.0.jar">
+ <attributes>
+ <attribute value="http://hibernate.org/hib_docs/v3/api" name="javadoc_location"/>
+ </attributes>
+ </classpathentry>
+
+<
+
+
+If you would like to set the javadoc url for your project's source
+files, you will instead need to set the
+org.eclipse.jdt.ui.project_javadoc_location option via
+|:ProjectSettings|. Also note that the javadocs for your source files
+are not generated automatically, so if you would like to use
+:JavaDocSearch to open your project's javadocs, you will first need to
+generate those javadocs as described in the next section.
+
+*:Javadoc*
+
+
+Executing javadoc
+=================
+
+To run the javadoc utility on your project's source code, you may use
+the :Javadoc command, which with no arguments will execute javadoc
+against all your project's source code (as specified by any optional
+settings described below).
+
+If you wish to run javadoc only against one or more files, you can
+supply the project relative paths as arguments to the :Javadoc command
+and only those files will be used.
+
+Note: Please note that this command is not intended to be a full
+ replacement for javadoc support provided by more comprehensive build
+ tools like ant or maven.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimJavaDocSearchSingleResult*
+
+- g:EclimJavaDocSearchSingleResult (Default: 'open') - Determines
+ what action to take when only a singe result is found.
+ Possible values include:
+
+ - 'open' - open the result in a browser.
+ - 'lopen' - open the temp window to display the result.
+- g:EclimLocationListHeight (Default: 10) - Sets the height in lines
+ of the location list window when eclim opens it to display search
+ results.
+Eclim Settings (|vim-settings|)
+
+- org.eclim.user.name - Used as the name portion of the author tag.
+ Consult the settings page (|vim-settings|) for more info.
+- org.eclim.user.email - Used as the email portion of the author
+ tag. Consult the settings page (|vim-settings|) for more info.
+- org.eclim.java.doc.dest (Default: doc) - The project relative
+ directory where the javadocs with be written to.
+- org.eclim.java.doc.packagenames - Optional space separated list of
+ package names to run javadoc against.
+- org.eclim.java.doc.sourcepath - The project relative javadoc
+ sourcepath to use. This should be a space separated list of project
+ relative source directories which you want javadoc to be executed
+ against. When unset, all your configured source directories will be
+ used.
+- org.eclipse.jdt.ui.project_javadoc_location - URL where your
+ project's javadocs can be found.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/logging.txt b/vim/eclim/doc/vim/java/logging.txt
@@ -0,0 +1,103 @@
+*vim-java-logging*
+
+Logging (log4j, etc)
+********************
+
+
+Auto import / initialize
+========================
+
+While editing a java source file, if you start to create a logging
+statement (log. or logger.), the logging plugin will attempt to
+perform the appropriate initialization (imports, static variable) for
+the configured logging implementation.
+
+Eclim provides a handful of templates for the most widely used
+implementations (commons-logging, slf4j, log4j, and jdk). However, if
+you happen to use an alternate logging framework, or perhaps a home
+grown framework, eclim also provides the means to supply a custom
+template. To utilize it, simply set the org.eclim.java.logging.impl
+setting to "custom" and add your template to
+~/.eclim/resources/jdt/templates/logger.gst. Two variables will be
+supplied to your template: var, which is the logger instance variable,
+and class, which is the class name of the current class you are
+implementing.
+
+Here is an example which eclim uses for its logger implementation:
+
+>
+
+ import org.eclim.logging.Logger;
+ private static final Logger ${var} = Logger.getLogger(${class}.class);
+
+<
+
+
+After performing the necessary variable substitution, eclim will take
+any imports and insert them amongst your existing import statements.
+The remaining code will be inserted after your class definition.
+
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimLoggingDisabled*
+
+- g:EclimLoggingDisabled (Default: 0) - If set to a value greater
+ than 0, then this plugin will be disabled.
+Eclim Settings (|vim-settings|)
+
+*org.eclim.java.logging.impl*
+
+- org.eclim.java.logging.impl (Default: "commons-logging") -
+ Determines which logging implementation to use.
+ Possible values include "commons-logging", "slf4j", "log4j", "jdk",
+ and "custom".
+
+*org.eclim.java.logging.template*
+
+- org.eclim.java.logging.template (Default: 'logger.gst') -
+ Determines the name of the template to use for the custom logger.
+ The name must be a file name relative to
+ ~/.eclim/resources/jdt/templates/.
+*log4j*
+
+
+Log4j
+=====
+
+
+Validation
+----------
+
+When editing a log4j xml file eclim will default to validating the
+file when it is written. Any errors will be added to the current
+window's location list (:help location-list) and their corresponding
+line number noted via Vim's sign functionality.
+
+Eclim also combines the above validation with xml validation
+(|xml-validation|) to validate that the file is well formed.
+
+If you do not want your log4j files validated automatically when
+saved, you can set the |g:EclimLog4jValidate| variable described in
+the configuration section below.
+
+*:Validate_log4j*
+
+Whether or not auto validation has been enabled, eclim also exposes
+the command :Validate to manually execute the validation of the file.
+
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimLog4jValidate*
+
+- g:EclimLog4jValidate (Default: 1) - If set to 0, disables
+ validation when saving the file.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/maven.txt b/vim/eclim/doc/vim/java/maven.txt
@@ -0,0 +1,51 @@
+*vim-java-maven*
+
+Maven
+*****
+
+*:Maven* *:Mvn*
+
+
+Running
+=======
+
+Much like the provided ant (|vim-java-ant|) execution functionality,
+eclim also provides commands for running maven 1.x or 2.x.
+
+Eclim provides the following commands:
+
+>
+
+ :Maven [<goal> ...]
+ :Mvn [<goal> ...]
+
+<
+
+
+which perform the following steps:
+
+- Save any previous 'makeprg' and 'errorformat' option settings so
+ that you can define your own settings for the :make command.
+- Set 'makeprg' to execute maven or mvn with the --find option so
+ that it will search for your pom file in the current directory or in
+ a parent directory.
+- Set 'errorformat' to recognize the following errors:
+ - javac errors.
+ - javadoc errors.
+ - junit errors / failures.
+- Execute :make.
+- Restore your previous 'makeprg' and 'errorformat' option settings.
+Additionally, if g:EclimMakeLCD (|vim-core-eclim#g:EclimMakeLCD|) is
+enabled (which it is by default), then the execution of maven will be
+performed from the current buffer's project root directory, ensuring
+that mavens's build file discovery method is performed from the
+buffer's working directory and not your own.
+
+Note that :Mvn MUST have this enabled since maven 2.x no longer has
+support for the --find option.
+
+Note: Both :Maven and :Mvn also supports use of '!' (:Maven!) just
+ like :make does, which tells Vim not to jump to the first error if
+ one exists.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/methods.txt b/vim/eclim/doc/vim/java/methods.txt
@@ -0,0 +1,245 @@
+*vim-java-methods*
+
+Method Generation
+*****************
+
+*:JavaConstructor*
+
+
+Constructors
+============
+
+:JavaConstructor is a command that will create either an empty
+constructor, or one that takes any selected fields as arguments.
+
+For example if you have the following class:
+
+>
+
+ public class Foo
+ {
+ private int id;
+ private String name;
+ }
+
+<
+
+
+If you were to select the range containing the 'id' and 'name' fields
+and issue :JavaConstructor, then you would end up with the following
+code.
+
+>
+
+ public class Foo
+ {
+ private int id;
+ private String name;
+
+ /**
+ * @param id
+ * @param name
+ */
+ public Foo(int id, String name) {
+ this.id = id;
+ this.name = name;
+ }
+ }
+
+<
+
+
+If you issue the command with no fields selected, then a default empty
+constructor is created.
+
+When attempting to create an empty constructor, if the super class
+doesn't define a default constructor, but instead has one or more
+constructors which takes arguments, then calling :JavaConstructor
+without a range will result in the creation of a constructor which
+overrides the super class constructor containing the least number of
+arguments. Although an empty constructor won't pass code validation,
+you can force the creation of one in this case by suffixing the
+command with a '!':
+
+>
+
+ :JavaConstructor!
+
+<
+
+
+*:JavaGetSet*
+
+
+Getters / Setters
+=================
+
+- :JavaGetSet - Generates both getters and setters for the field
+ under the cursor or for all fields in the specified range.
+*:JavaGet*
+
+- :JavaGet - Generates getters for the field under the cursor or for
+ all fields in the specified range.
+*:JavaSet*
+
+- :JavaSet - Generates setters for the field under the cursor or for
+ all fields in the specified range.
+Note: If you would like to generate the indexed getter or setter
+ then you can suffix the appropriate command above with '!' and if
+ the property is an array, an indexed accessor will be created.>
+
+ :JavaGetSet!
+
+ <
+
+
+Given the following file:
+
+>
+
+ public class Foo
+ {
+ private String name;
+ private Bar[] bars;
+ }
+
+<
+
+
+You can place the cursor on one of the fields and execute :JavaGetSet
+to generate the getters and setters for the field. All of the above
+commands support ranges as well, so you can use a visual selection or
+a numbered range to generate methods for a set of fields.
+
+*:JavaImpl*
+
+
+Override / Impl
+===============
+
+Eclim provides the ability to view all the methods that the current
+source file can implement or override according to what interfaces it
+implements and classes it extends. From the list of methods you can
+then choose which you want to implement or override, and the
+appropriate method stub will be inserted into the file.
+
+The first step in the process is to execute :JavaImpl which will open
+a Vim window containing a list possible methods to implement /
+override and the interface / class which defines those methods.
+
+Here is some example content from a class that extends
+java.io.InputStream:
+
+>
+
+ com.test.TestStream
+
+ package java.io;
+ class InputStream
+ public int read()
+ public int read(byte[])
+ public int read(byte[], int, int)
+ public long skip(long)
+ public int available()
+ public void close()
+ public void mark(int)
+ public void reset()
+ public boolean markSupported ()
+
+ package java.lang;
+ class Object
+ public int hashCode()
+ public boolean equals(Object)
+ protected Object clone()
+ public String toString()
+ protected void finalize()
+
+<
+
+
+From the newly opened window you can select a method to generate a
+stub for by simply hitting <enter> with the cursor over the method
+signature.
+
+If you would like to generate stubs for all methods in an interface or
+class, then simply hit <enter> with the cursor over the class name and
+stub methods will be created for each method in that class or
+interface.
+
+This functionality supports outer, inner, and anonymous classes
+classes. To view the list of methods to override for an inner or
+anonymous class, simply execute :JavaImpl with the cursor somewhere in
+the body of the inner or anonymous class.
+
+*:JavaDelegate*
+
+
+Delegate Methods
+================
+
+Eclim supports generation of delegate methods via the :JavaDelegate
+command. To utilize this functionality you must first place the cursor
+on a global field (in the main source file class or within an inner
+class), and then invoke the :JavaDelegate command.
+
+In the following source, you can place the cursor anywhere starting
+from the first 'p' in private, to the trailing semicolon, and then
+invoke the :JavaDelegate command.
+
+>
+
+ private List myList;
+
+<
+
+
+Invoking this command with the cursor on some other source element
+will generate the appropriate error.
+
+Once successfully invoked, the result will be the opening of a lower
+window with all the methods that may be inserted that will delegate to
+the value of the field.
+
+Here is a section of the content displayed when invoking the command
+on a field of type java.util.List like the one above.
+
+>
+
+ com.test.TestList.myList
+
+ package java.util;
+ interface List
+ public abstract int size()
+ public abstract boolean isEmpty()
+ public abstract boolean contains(Object)
+ public abstract Object[] toArray()
+ ...
+
+<
+
+
+From this newly opened window you can select a method by simply
+hitting <enter> with the cursor over the method signature and a
+delegate method will be created.
+
+For example, if you hit <enter> on the size() method, then the
+following code will be inserted.
+
+>
+
+ /**
+ */
+ public int size ()
+ {
+ return myList.size();
+ }
+
+<
+
+
+If you would like to generate delegate methods for all methods in an
+interface or class, then simply hit <enter> with the cursor over the
+class name, and delegate methods will be created for each method in
+that interface or class.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/refactor.txt b/vim/eclim/doc/vim/java/refactor.txt
@@ -0,0 +1,171 @@
+*vim-java-refactor*
+
+Java Refactoring
+****************
+
+*:JavaRename*
+
+
+Rename
+======
+
+The first refactoring that eclim supports is :JavaRename, which can be
+used to rename various java elements.
+
+Example:
+
+>
+
+ package org.foo.bar;
+
+ public class Foo {
+ public void bar(){
+ }
+ }
+
+<
+
+
+To rename the class from 'Foo' to 'Bar' you simply position the cursor
+over the class name 'Foo' and execute:
+
+>
+
+ :JavaRename Bar
+
+<
+
+
+The result of which will the following prompt:
+
+>
+
+ Rename "Foo" to "Bar"
+ ([e]xecute / [p]review / [c]ancel):
+
+<
+
+
+This prompt give you three options:
+
+1. execute: Execute the refactoring without previewing the changes
+ to be made. The current file and any other changed files open in
+ the current instance of vim will be reloaded.
+2. preview: Preview the changes that the refactoring will perform.
+ This will open a scratch buffer with a list of changes to be made
+ along with a link at the bottom to execute the refactoring.
+ The contents of the preview window will vary depending on what you
+ are renaming.
+
+ If we are renaming 'Foo' to 'Bar' the contents would be like so:
+
+ >
+ other: Rename compilation unit 'Foo.java' to 'Bar.java'
+
+ |Execute Refactoring|
+
+ <
+
+ If we are renaming the method 'bar' to 'foo', the contents would
+ look like so:
+
+ >
+ |diff|: /home/someuser/workspace/test_java/src/org/foo/bar/Foo.java
+
+ |Execute Refactoring|
+
+ <
+
+ If the first instance, there is not much to preview. Since this
+ particular class is not referenced anywhere else, the only
+ operation eclipse will perform, is to rename the file from
+ 'Foo.java' to 'Bar.java' which will also update the class name in
+ that file.
+
+ In the second instance eclipse provides a preview of the actual
+ changes to the file what will be performed. If the method were
+ referenced elsewhere, you would see an entry for each file that
+ would be modified by the refactoring. To actually for a vim diff
+ split of the changes that will be performed, simple position the
+ cursor on the diff entry and hit <enter>.
+
+ Once you are satisfied with changes that eclipse will perform, you
+ can then execute the refactoring by positioning the cursor over the
+ "|Execute Refactoring|" link and hit <enter>.
+
+3. cancel: Cancel the refactoring (Hitting enter without typing a
+ choice or hitting Ctrl-C will also cancel the refactoring).
+Package Renaming
+
+Renaming a package is performed just like renaming any other element.
+However, the name you supply to the :JavaRename command must be the
+full package name that you are renaming the package to. For example.
+In sample java file above, if you place the cursor on the 'org'
+portion of the package declaration, you can rename 'org' to 'com' by
+running :JavaRename com. If you want to rename the 'foo' package to
+'baz' you can do so by running :JavaRename org.baz. Note that if you
+were to only supply the name 'baz', the 'foo' package would be moved
+to the same level as 'org' and then renamed.
+
+Warning: When renaming a package, the associated directory will also
+ be renamed in the underlying file system. Eclim will do its best to
+ reload any files that have moved as a result of the directory
+ renaming and adjust your current working directory if necessary, but
+ only for the current vim session. If you have other vim sessions
+ open with files located in the directory that is renamed, then eclim
+ will be unable to reload those files in those sessions for you, so
+ you will have to do so manually. A best practice would be to close
+ any other vim sessions that might be affected by the renaming of a
+ package.
+
+*:JavaMove*
+
+
+Move
+====
+
+Eclim also supports moving a top level class or interface from one
+package to another using the :JavaMove command.
+
+In this example the current file would be moved from its current
+package to the package org.foo:
+
+>
+
+ :JavaMove org.foo
+
+<
+
+
+Like the package renaming described in the previous section, the
+argument to :JavaMove must be the full package name you want to move
+the current file to.
+
+
+Refactor Undo/Redo
+==================
+
+In the event that you need to undo a refactoring, eclim provides the
+:RefactorUndo command. When executed, the last refactoring will be
+reverted. If you are unsure what the last refactoring was, the
+:RefactorUndoPeek command will print the name of the top most
+refactoring on the undo stack.
+
+Eclim also provides the :RefactorRedo and :RefactorRedoPeek commands
+which provide the redo counterpart to the undo commands.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimRefactorDiffOrientation_java*
+
+- g:EclimRefactorDiffOrientation (Default: 'vertical') - Specifies
+ the orientation used when previewing a refactoring and performing a
+ diff split between the current file contents and the changes to be
+ performed by the refactoring. Possible values include 'vertical' or
+ 'horizontal'.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/search.txt b/vim/eclim/doc/vim/java/search.txt
@@ -0,0 +1,225 @@
+*vim-java-search*
+
+Java Search
+***********
+
+*:JavaSearch*
+
+
+Pattern Search
+==============
+
+Pattern searching provides a means to widen a search beyond a single
+element. A pattern search can be executed using the command
+
+:JavaSearch -p <pattern> [-t <type> -x <context> -s <scope> -i]
+
+All of the results will be placed into the current window's location
+list (:help location-list) so that you can easily navigate the
+results.
+
+Vim command completion is supported through out the command with the
+excption of the pattern to search for.
+
+>
+
+ :JavaSearch <Tab>
+ :JavaSearch -p MyClass* <Tab>
+ :JavaSearch -p MyClass* -t <Tab>
+ :JavaSearch -p MyClass* -t all <Tab>
+ :JavaSearch -p MyClass* -t all -x <Tab>
+ :JavaSearch -p MyClass* -t all -x declarations
+
+<
+
+
+- -p <pattern>: The pattern to search for.
+ Ex.
+
+ >
+ MyClass*
+ MyClass.someMethod*
+
+ <
+
+- -t <type> (Default: type): The type of element to search for where
+ possible types include
+ - annotation
+ - class
+ - classOrEnum
+ - classOrInterface
+ - constructor
+ - enum
+ - field
+ - interface
+ - method
+ - package
+ - type
+- -x <context> (Default: declarations): The context of the search,
+ where possible context values include
+ - all - All occurances.
+ - declarations - Declarations matching the pattern or element.
+ - implementors - Implementors of the pattern or element.
+ - references - References of the pattern or element.
+- -s <scope> (Default: all): The scope of the search where possible
+ values include
+ - all - Search the whole workspace.
+ - project - Search the current project, dependent projects, and
+ libraries.
+- -i: Ignore case when searching.
+Eclim also provides a shortcut when issuing a pattern search for a
+type. You may simply invoke :JavaSearch supplying only the pattern.
+
+>
+
+ :JavaSearch SomeType
+
+<
+
+
+To shorten things even more, there is support for camel case searching
+as well.
+
+>
+
+ :JavaSearch NPE
+
+<
+
+
+However, please note that camel case searching does not permit wild
+card characters ('*', '?').
+
+
+Element Search
+==============
+
+Element searching allows you to place the cursor over just about any
+element in a source file (method call, class name, field) and perform
+a search for that element. Performing an element search is the same
+as performing a pattern search with the exception that you do not
+specify the -p option since the element under the cursor will be
+searched for instead.
+
+If only one result is found and that result is in the current source
+file, the cursor will be moved to the element found.
+
+*:JavaSearchContext*
+
+As a convenience eclim also provides the command :JavaSearchContext.
+This command accepts no arguments and will perform the appropriate
+search depending on the context of the element.
+
+- If the cursor is on a class or interface declaration, the command
+ will search for all classes / interfaces that implement / extend the
+ element.
+- If the cursor is on a method or field declaration, the command
+ will search for all references to the element.
+- Otherwise, it will search for the declaration of the element.
+
+Alternate Searching
+===================
+
+For those occasions that you find yourself browsing a third party
+source distribution that you want to be able to search without going
+through the steps of setting up a project, eclim provides an alternate
+searching mechanism. To utilize the alternate searching requires no
+change in behavior or commands, but to achieve the best results, you
+should know how it works.
+
+The first thing worth noting is that the alternate search is currently
+a bit limited. It only supports searches involving types (classes,
+interfaces, annotations, and enums). It doesn't currently have any
+support for methods or fields.
+
+Secondly, it can only search for and locate types within the current
+source tree. Searching across the jdk source or other third party
+source files without setting up an Eclipse or similar classpath, is
+difficult at worst, and slow at best.
+
+With that said, I've found that when I'm walking through a third party
+source tree, my main focus is on finding referenced classes /
+interfaces quickly and easily, and the eclim alternate searching does
+just that.
+
+Invoking the search is the same as the standard search mechanism. You
+simply use the same :JavaSearch command as you normally would. The
+only difference is that the alternate search doesn't support the -t
+option and will notify you of such if supplied.
+
+When invoked, the alternate search will perform the following:
+
+- It will grab the full path of the current source file, strip off
+ the package and search from the resulting directory.
+ Ex. When editing a file
+ /usr/local/java/foo/src/org/foo/bar/Baz.java, the alternate search
+ will first search the directory /usr/local/java/foo/src.
+
+- If no files are found in that directory, then it will proceed to
+ search Vim's 'path' option (:h 'path' for more info on this option).
+ As an example, I have my 'path' set to '/usr/local/java/java-src'
+ and in that directory is where I store all my third party source
+ distributions (hibernate, spring, axis, etc.).
+
+- Once one or more files are found, the search will stop if the
+ requested search was for declarations. For all searches, eclim will
+ first try to find the declarations and if the user requested a
+ search for implementors, references, or all, then the eclim will
+ proceed to the next step.
+- For non-declaration searches, if multiple declaring source files
+ are found, eclim will prompt you to narrow the results down to the
+ type you would like results for.
+- Once eclim has narrowed the search down to the specific type to
+ proceed with, it will then attempt to narrow the search down to a
+ specific source distribution directory. To do this it locates the
+ relevant entry from the 'path' option, tacks on one more level of
+ the path from the resulting file, and commences its search from
+ there.
+ Ex. When searching for all implementors of MyType, if eclim finds a
+ file /usr/local/java/java-src/myproject/core/src/org/my/MyType.java
+ and a 'path' entry of /usr/local/java/java-src exists, then eclim
+ will deduce that that search must continue in the directory
+ /usr/local/java/java-src/myproject.
+
+This may seem a bit complicated for a simple search, but in practice
+it's actually quite simple, and as usual, I'm open to any and all
+comments and suggestions.
+
+Note: Alternate searching is bound to the performance of the file
+ system and as such, the response time on Windows can be
+ significantly slower than Linux. This is most noticable when
+ searching for 'implementors', 'references', and 'all'. The number
+ of and depth of the directories in your Vim 'path' option may also
+ impact performance.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimJavaSearchSingleResult*
+
+- g:EclimJavaSearchSingleResult (Default: 'split') - Determines what
+ action to take when a only a single result is found.
+ Possible values include:
+
+ - 'split' - open the result in a new window via "split".
+ - 'edit' - open the result in the current window.
+ - 'tabnew' - open the result in a new tab.
+ - 'lopen' - open the location list to display the result.
+ This setting overrides the global default for all supported language
+ types which can be set using the g:EclimDefaultFileOpenAction
+ setting which accepts the same possible values.
+
+- g:EclimLocationListHeight (Default: 10) - Sets the height in lines
+ of the location list window when eclim opens it to display search
+ results.
+*g:EclimJavaSearchMapping*
+
+- g:EclimJavaSearchMapping (Default: 1) - When set to 1, <enter>
+ will be mapped to the java search functionality for the various java
+ related xml files (spring, hibernate, web.xml, and
+ struts-config.xml). By default this is enabled.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/unittests.txt b/vim/eclim/doc/vim/java/unittests.txt
@@ -0,0 +1,233 @@
+*vim-java-unittests*
+
+Unit Tests
+**********
+
+*:JUnit*
+
+
+JUnit
+=====
+
+
+Executing tests.
+----------------
+
+Eclim's :JUnit command allows you to execute individual test or
+individual methods from your tests.
+
+If you'd like to run a particular test you can do so by supplying the
+fully qualified class name of the test to run (you can use vim's tab
+completion here to alleviate having to type the full name):
+
+>
+
+ :JUnit org.test.MyTest
+
+<
+
+
+Another way is to simply run :JUnit with no arguments and let it
+decide what to run based on the current context of the cursor:
+
+- If you have a junit test file open and the cursor is not inside
+ one of the test methods, then all of the current file's test methods
+ will be executed.
+- If the cursor is on or inside of a test method, then just that
+ method will be run.
+- If you have a regular class open and run :JUnit, eclim will
+ attempt to locate the corresponding test and run it.
+- If the cursor is on or inside of a method in a regular class,
+ eclim will attempt to locate the test and then locate the
+ corresponding test method for the current method in that test and
+ run just that test method.
+If you'd like to run all tests for the current file, regardless of
+whether the cursor is on a method or not, you can do so by running
+:JUnit with the '%' argument:
+
+>
+
+ :JUnit %
+
+<
+
+
+For cases where you'd like to run all your unit tests you can run
+:JUnit with the '*' argument and eclim will locate all your test files
+and run them:
+
+>
+
+ :JUnit *
+
+<
+
+
+You can also pass in an ant compatible pattern
+(http://ant.apache.org/manual/dirtasks.html#patterns) to match the
+tests you'd like to run:
+
+>
+
+ :JUnit **/tests/*Test
+
+<
+
+
+*:JUnitFindTest*
+
+
+Find the test for the current source file.
+------------------------------------------
+
+When editing a java file, if you would like to open the corresponding
+test, you can issue the command :JUnitFindTest. When the cursor is on
+a method in your source file this command will also try to find the
+corresponding test method within the test file.
+
+If you run :JUnitFindTest from a test class, eclim will attempt to
+find the corresponding class that is being tested.
+
+*:JUnitResult*
+
+
+Opening test results run from you build tool.
+---------------------------------------------
+
+If you are running your unit tests from a build tool like ant or
+maven, then you most likely are writing those results to a directory
+in your project. If so then you can set the
+|org.eclim.java.junit.output_dir| setting to that location which then
+allows you to use the command :JUnitResult to locate and opening the
+result file for the currently open test or the test supplied as an
+argument.
+
+*:JUnitImpl*
+
+
+Generating test method stubs.
+-----------------------------
+
+While editing junit files, eclim provides functionality to generate
+test method stubs similar to the method override / impl (|:JavaImpl|)
+functionality provided for non-test-case classes. The only difference
+is that instead of :JavaImpl, you use :JUnitImpl to open the window of
+possible methods to implement.
+
+To determine what class the current test is for, eclim expects that
+the standard naming convention for tests is followed, where the test
+has the same fully qualified class name as the target class with a
+'Test' suffix.
+
+So for the test org.foo.bar.BazTest, the exepected class being tested
+would be org.foo.bar.Baz.
+
+Note: Eclim also supports tests with a 'Test' prefix instead of a
+ suffix and in the case of neither a 'Test' prefix or suffix, it will
+ search for a class of the same name in a different package should
+ you perhaps use a package convention for your tests rather than a
+ class name convention.
+
+When invoking :JUnitImpl from within org.foo.bar.BazTest, eclim will
+locate the class org.foo.bar.Baz and generate a list of methods to
+test from it.
+
+When you hit <enter> on the method to add, if that method belongs to a
+type in the hierarchy for the class being tested, then the
+corresponding test method stub will be inserted, otherwise a regular
+overriding stub will be generated.
+
+
+Configuration
+-------------
+
+Eclim Settings (|vim-settings|)
+
+*org.eclim.java.junit.output_dir*
+
+- org.eclim.java.junit.output_dir - Defines the project relative
+ location of the junit test results.
+ Ex.
+
+ >
+ org.eclim.java.junit.output_dir=build/test/results
+
+ <
+
+*org.eclim.java.junit.jvmargs*
+
+- org.eclim.java.junit.jvmargs - Json formatted list of strings to
+ supply as args to the jvm when forking to run unit tests.
+ Ex.
+
+ >
+ org.eclim.java.junit.jvmargs=["-Xmx512m", "-XX:MaxPermSize=128m"]
+
+ <
+
+*org.eclim.java.junit.sysprops*
+
+- org.eclim.java.junit.sysprops - Json formatted list of strings to
+ supply as system properties to the jvm when forking to run unit
+ tests.
+ Ex.
+
+ >
+ org.eclim.java.junit.sysprops=["file.encoding=UTF8", "foo.bar=baz"]
+
+ <
+
+*org.eclim.java.junit.envvars*
+
+- org.eclim.java.junit.envvars - Json formatted list of strings to
+ supply as environment variables to the jvm when forking to run unit
+ tests.
+ Ex.
+
+ >
+ org.eclim.java.junit.envvars=["FOO=bar"]
+
+ <
+
+
+TestNG
+======
+
+Currently eclim's support for TestNG (http://testng.org/doc) is
+limited to supporting Vim's :make in conjunction with ant to populate
+vim's quickfix results with failed tests.
+
+By default TestNG's output to the console is very terse. So in order
+to support monitoring of failed tests via vim's error format, eclim
+provides a custom TestNG listener which must be installed into your
+build environment.
+
+1. The first step is to place the eclim-testng.jar file in your
+ TestNG classpath you have configured for ant. You can find this
+ jar file in your $ECLIPSE_HOME/plugins/org.eclim.jdt_version/
+ directory.
+2. The second step is to add the listener attribute to your testng
+ task which references the required eclim testng listener:
+ >
+ ...
+ <testng ... listener="org.eclim.testng.TestNgListener">
+ ...
+
+ <
+
+ See the testng ant task docs (http://testng.org/doc/ant.html) for
+ more information.
+
+Once you have completed that setup, you should then be able to run
+your ant target from vim and (as long as eclim is running) all failed
+tests will be added to your vim quickfix results.
+
+Ex. Assuming your ant task is named 'test':
+
+>
+
+ :Ant test
+
+<
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/validate.txt b/vim/eclim/doc/vim/java/validate.txt
@@ -0,0 +1,129 @@
+*vim-java-validate*
+
+*:Validate_java*
+
+
+Java Validation / Correction
+****************************
+
+
+Validation
+==========
+
+When saving a java source file that resides in a project, eclim will
+update that source file in Eclipse and will report any validation
+errors found. Any errors will be placed in the current window's
+location list (:help location-list) and the corresponding lines in the
+source file will be marked via Vim's :sign functionality with '>>'
+markers in the left margin.
+
+Automatic validation of java source files can be disabled via the
+g:EclimJavaValidate variable (described below). If you choose to
+disable automatic validation, you can still use the :Validate command
+to manually validate the current file.
+
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimJavaSrcValidate*
+
+- g:EclimJavaValidate (Default: 1) - If set to 0, disables source
+ code validation.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+Eclim settings
+
+*org.eclipse.jdt.core.compiler.source*
+
+- org.eclipse.jdt.core.compiler.source - Determines the target java
+ vm version (1.2, 1.3, 1.4, 1.5).
+*:JavaCorrect*
+
+
+Code Correction
+===============
+
+Code correction in eclim is equivalent to the quick fix functionality
+of Eclipse. When you save a java source file, eclim validates the file
+and notes which lines contain errors. To have eclim suggest possible
+corrections for an error, you simply place the cursor on the error
+line and issue :JavaCorrect.
+
+The result will be a small window opened at the bottom of Vim where
+any correction proposals will be noted. To apply a suggested change,
+simply move the cursor to the line describing the modification and hit
+<enter>. Upon doing so, the change will be applied to the source file.
+
+Example output of :JavaCorrect.
+
+>
+
+ The serializable class Foo does not declare a static final serialVersionUID field of type long
+ 0.1227: Add @SuppressWarnings 'serial' to 'Foo'
+ ...
+ @SuppressWarnings("serial")
+ public class Foo
+ implements Serializable
+ ...
+
+<
+
+
+To apply the above change you would hit <enter> on the line:
+
+>
+
+ 0.1227: Add @SuppressWarnings 'serial' to 'Foo'
+
+<
+
+
+Note: Java code corrections are handled just like a refactoring
+ (|vim-java-refactor|) so the RefactorUndo (|:RefactorUndo|) and
+ RefactorRedo (|:RefactorRedo|) commands can be used to undo/redo
+ corrections that can't be handled by vim's undo (like file moves).
+
+*:Checkstyle*
+
+
+Checkstyle
+==========
+
+When editing a java source file, eclim provides the command
+:Checkstyle which will invoke checkstyle
+(http://checkstyle.sourceforge.net/) on the current file.
+
+Additionally, you can configure eclim to execute checkstyle
+automatically when you save a java source file by setting the eclim
+project settings org.eclim.java.checkstyle.onvalidate to true.
+
+Please note that both methods of invoking checkstyle require that you
+first configure the location of your checkstyle config file using the
+eclim setting org.eclim.java.checkstyle.config, described in the
+configuration section below.
+
+
+Configuration
+-------------
+
+Eclim Settings (|vim-settings|)
+
+*org.eclim.java.checkstyle.config*
+
+- org.eclim.java.checkstyle.config - Defines the location (project
+ relative or absolute) or your checkstyle config file.
+*org.eclim.java.checkstyle.properties*
+
+- org.eclim.java.checkstyle.properties - Defines the location
+ (project relative or absolute) or your checkstyle properties file.
+*org.eclim.java.checkstyle.onvalidate*
+
+- org.eclim.java.checkstyle.onvalidate - When set to true,
+ checkstyle will be run on the file along with the regular java
+ validation upon writing the file.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/java/webxml.txt b/vim/eclim/doc/vim/java/webxml.txt
@@ -0,0 +1,38 @@
+*vim-java-webxml*
+
+WEB-INF/web.xml
+***************
+
+
+Validation
+==========
+
+When editing a web.xml file eclim will default to validating the file
+when it is written. Any errors will be added to the current window's
+location list (:help location-list) and their corresponding line
+number noted via Vim's sign functionality.
+
+Eclim also combines the above validation with xml validation
+(|xml-validation|) to validate that the file is well formed.
+
+If you do not want your web.xml files validated automatically when
+saved, you can set the |g:EclimWebXmlValidate| variable described in
+the configuration section below.
+
+*:Validate_webxml*
+
+Whether or not auto validation has been enabled, eclim also exposes
+the command :Validate to manually execute the validation of the file.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimWebXmlValidate*
+
+- g:EclimWebXmlValidate (Default: 1) - If set to 0, disables
+ validation when saving the file.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/javascript/index.txt b/vim/eclim/doc/vim/javascript/index.txt
@@ -0,0 +1,66 @@
+*vim-javascript-index*
+
+Javascript
+**********
+
+
+Validation
+==========
+
+When editing a javascript file eclim will default to validating the
+file when it is written. Any errors will be added to the current
+window's location list (:help location-list) and their corresponding
+line number noted via Vim's sign functionality.
+
+Javascript validation currently uses JavaScript Lint
+(http://www.javascriptlint.com/) to perform the validation. To use it
+you will need to first install JavaScript Lint and put it in your
+path.
+
+Installing on windows and the mac should be very straight forward
+since pre-compiled version for each are available for download on the
+JavaScript Lint (http://www.javascriptlint.com/) site. For other unix
+based systems (linux, bsd, etc.) the installation procedure is not so
+obvious. Here are the steps used to compile and install it on a linux
+machine (your paths may vary):
+
+>
+
+ $ cd jsl-<version>/src
+ $ make -f Makefile.ref
+
+ # this path will undoubtedly vary on non-linux machines, so watch the
+ # make output for the real destination.
+ $ sudo cp Linux_All_DBG.OBJ/jsl /usr/local/bin
+
+<
+
+
+If you don't want javascript files validated when saving them, you can
+set the g:EclimJavascriptValidate variable described in the
+configuration section below.
+
+*:Validate_javascript*
+
+Regardless of whether you have validation enabled upon saving or not,
+the command :Validate is available to manually execute the validation.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimJavascriptValidate*
+
+- g:EclimJavascriptValidate (Default: 1) - If set to 0, disables
+ javascript validation when saving the file.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+*g:EclimJavascriptLintConf*
+
+- g:EclimJavascriptLintConf (Default: '~/.jslrc') - Used to set the
+ location of your jsl config file.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/php/buildpath.txt b/vim/eclim/doc/vim/php/buildpath.txt
@@ -0,0 +1,58 @@
+*vim-php-buildpath*
+
+Php Build Path
+**************
+
+Source code completion, searching, and other features make use of the
+eclipse dltk's (http://eclipse.org/dltk/) .buildpath to locate
+resources. When you first create a dltk project (currently php
+(|vim-php-index|) or ruby (|vim-ruby-index|)), a .buildpath file is
+created in the project's root directory. If your project depends on
+any source files located outside your project or in another project,
+then you'll need to edit your .buildpath accordingly.
+
+To help you do this, eclim provides several commands to ease the
+creation of new build path entries and variables, all of which are
+made available when you edit your .buildpath file in vim. Also when
+you write the .buildpath file, Vim will issue a command to the eclim
+server to update the project's build path, and will report any errors
+via vim's location list (:help location-list).
+
+The following is a list of commands that eclim provides while editing
+your .buildpath.
+
+*:NewSrcEntry_dltk_php*
+
+- :NewSrcEntry <dir> [<dir> ...] - Adds one or more new entries
+ which reference source directories in your project.
+ >
+ <buildpathentry external="true" kind="lib" path="src/php"/>
+
+ <
+
+ This command supports command completion of project relative
+ directories.
+
+*:NewLibEntry_dltk_php*
+
+- :NewLibEntry <dir> [<dir> ...] - Adds one or more new entries
+ which reference external source directories.
+ >
+ <buildpathentry external="true" kind="lib" path="/usr/local/php/cake_1.1.16.5421"/>
+
+ <
+
+ This command supports command completion of directories.
+
+*:NewProjectEntry_dltk_php*
+
+- :NewProjectEntry <project> [<project> ...] - Adds one or more new
+ entries which reference other projects.
+ >
+ <buildpathentry combineaccessrules="false" kind="prj" path="/test_project"/>
+
+ <
+
+ This command supports command completion of project names.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/php/complete.txt b/vim/eclim/doc/vim/php/complete.txt
@@ -0,0 +1,27 @@
+*vim-php-complete*
+
+Php Code Completion
+*******************
+
+Php code completion uses the standard Vim code completion mechanism
+(|vim-code_completion|) like so:
+
+>
+
+ <?php
+ class Test {
+ function getName () {
+ }
+ function getValue () {
+ }
+ }
+
+ $test = new Test();
+
+ $test->get<C-X><C-U>
+ $test->getName()
+ ?>
+
+<
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/php/index.txt b/vim/eclim/doc/vim/php/index.txt
@@ -0,0 +1,29 @@
+*vim-php-index*
+
+Php
+***
+
+
+Features
+========
+
+- Php Build Path (vim-php-buildpath)
+- Php Code Completion (vim-php-complete)
+- Php Validation (vim-php-validate)
+- Php Search (vim-php-search)
+
+Suggested Mappings
+==================
+
+Here are some mappings for the php funtionality provided by eclim. To
+make use of these mappings, simply create a ftplugin file for php and
+place your mappings there (:help ftplugin-name).
+
+- The following mapping allows you to simply hit <enter> on an
+ element to perform a search to find it.
+ >
+ nnoremap <silent> <buffer> <cr> :PhpSearchContext<cr>
+
+ <
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/php/search.txt b/vim/eclim/doc/vim/php/search.txt
@@ -0,0 +1,107 @@
+*vim-php-search*
+
+Php Search
+**********
+
+*:PhpSearch*
+
+
+Pattern Search
+==============
+
+Pattern searching provides a means to widen a search beyond a single
+element. A pattern search can be executed using the command
+
+:PhpSearch -p <pattern> [-t <type> -s <scope> -i]
+
+All of the results will be placed into the current window's location
+list (:help location-list) so that you can easily navigate the
+results.
+
+Vim command completion is supported through out the command with the
+exception of the pattern to search for.
+
+>
+
+ :PhpSearch <Tab>
+ :PhpSearch -p MyClass* <Tab>
+ :PhpSearch -p MyClass* -t <Tab>
+ :PhpSearch -p MyClass* -t class <Tab>
+ :PhpSearch -p MyClass* -t class -s <Tab>
+ :PhpSearch -p MyClass* -t class -s project
+
+<
+
+
+- -p <pattern>: The pattern to search for.
+ Ex.
+
+ >
+ MyClass
+ myFunction
+ my*
+
+ <
+
+- -t <type> (Default: all): The type of element to search for where
+ possible types include
+ - class
+ - function
+ - field
+- -s <scope> (Default: all): The scope of the search where possible
+ values include
+ - all - Search the whole workspace.
+ - project - Search the current project, dependent projects, and
+ libraries.
+- -i: Ignore case when searching.
+
+Element Search
+==============
+
+Element searching allows you to place the cursor over just about any
+element in a source file (method call, class name, constant) and
+perform a search for that element. Performing an element search is
+the same as performing a pattern search with the exception that you do
+not specify the -p option since the element under the cursor will be
+searched for instead.
+
+If only one result is found and that result is in the current source
+file, the cursor will be moved to the element found. Otherwise, on
+single result matches, the value of |g:EclimPhpSearchSingleResult|
+will be consulted for the action to take. If there are multiple
+results, the location list will be opened with the list of results.
+
+*:PhpSearchContext*
+
+As a convenience eclim also provides the command :PhpSearchContext.
+This command accepts no arguments and will perform the appropriate
+search depending on the context of the element.
+
+- If the cursor is on the file name in a require or include call, it
+ will search the configured include path for the file.
+- Otherwise, it will search for the declaration of the element.
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimPhpSearchSingleResult*
+
+- g:EclimPhpSearchSingleResult (Default: 'split') - Determines what
+ action to take when a only a single result is found.
+ Possible values include:
+
+ - 'split' - open the result in a new window via "split".
+ - 'edit' - open the result in the current window.
+ - 'tabnew' - open the result in a new tab.
+ - 'lopen' - open the location list to display the result.
+ This setting overrides the global default for all supported language
+ types which can be set using the g:EclimDefaultFileOpenAction
+ setting which accepts the same possible values.
+
+- g:EclimLocationListHeight (Default: 10) - Sets the height in lines
+ of the location list window when eclim opens it to display search
+ results.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/php/validate.txt b/vim/eclim/doc/vim/php/validate.txt
@@ -0,0 +1,44 @@
+*vim-php-validate*
+
+*:Validate_php*
+
+
+Php Validation
+**************
+
+When saving a php source file that resides in a project, eclim will
+update that source file in Eclipse and will report any validation
+errors found. Any errors will be placed in the current window's
+location list (:help location-list) and the corresponding lines in the
+source file will be marked via Vim's :sign functionality with '>>'
+markers in the left margin.
+
+Automatic validation of php source files can be disabled via the
+g:EclimPhpValidate variable (described below). If you choose to
+disable automatic validation, you can still use the :Validate command
+to manually validate the current file.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimPhpValidate*
+
+- g:EclimPhpValidate (Default: 1) - If set to 0, disables source
+ code validation.
+- g:EclimPhpHtmlValidate (Default: 0) - If set to a non 0 value,
+ enables validating html markup in the php file. Enabling of html
+ validation can also be enabled on a per buffer basis using a buffer
+ local setting:
+ >
+ let b:EclimPhpHtmlValidate = 1
+
+ <
+
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/python/complete.txt b/vim/eclim/doc/vim/python/complete.txt
@@ -0,0 +1,21 @@
+*vim-python-complete*
+
+Python Code Completion
+**********************
+
+Python code completion uses the standard Vim code completion mechanism
+(|vim-code_completion|) like so:
+
+>
+
+ class Test (object):
+ def testMethod (self):
+ pass
+
+ t = Test()
+ t.te<C-X><C-U>
+ t.testMethod
+
+<
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/python/django.txt b/vim/eclim/doc/vim/python/django.txt
@@ -0,0 +1,249 @@
+*vim-python-django*
+
+Django
+******
+
+*:DjangoManage*
+
+
+Django manage.py
+================
+
+For each project you create with the django framework, django provides
+you with a manage.py which can be used to perform various tasks. To
+make the invocation of the manage.py script even easier, eclim
+provides the command :DjangoManage which can be invoked from any file
+in the same directory as your manage.py or in any of the child
+directories.
+
+:DjangoManage supports all the same commands as manage.py and supports
+command line completion of command names and app names where
+supported.
+
+Several of the manage.py commands simply perform an action without
+generating much if any output. However there is also a set of
+commands which generate sql statements. For all of these commands,
+instead of just running the command in a shell, :DjangoManage will run
+the command and populate a new buffer with the resulting output and
+set the proper file type.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimPythonInterpreter*
+
+- g:EclimPythonInterpreter = 'python'
+*g:EclimDjangoAdmin*
+
+- g:EclimDjangoAdmin = 'django-admin.py'
+
+Django python support
+=====================
+
+*:DjangoTemplateOpen*
+
+Locating templates
+
+The command :DjangoTemplateOpen supports finding and opening a
+template referenced under the cursor.
+
+Ex.
+
+>
+
+ # w/ cursor on 'mytemplates/mytemplate.html'
+ return render_to_response('mytemplates/mytemplate.html', ...)
+
+<
+
+
+*:DjangoViewOpen*
+
+Locating views
+
+The command :DjangoViewOpen supports finding and opening a view
+referenced under the cursor.
+
+Ex.
+
+>
+
+ # w/ cursor on 'myproject.myapp.views' or 'my_view' on the second line.
+ urlpatterns = patterns('myproject.myapp.views',
+ (r'^$', 'my_view'),
+ )
+
+<
+
+
+*:DjangoContextOpen*
+
+Contextually locate file
+
+The command :DjangoContextOpen supports executing :DjangoViewOpen,
+:DjangoTemplateOpen, or :PythonFindDefinition depending on the context
+of the text under the cursor.
+
+*htmldjango*
+
+
+Django html template support
+============================
+
+Syntax
+
+Vim ships with a syntax file for django html template files, but eclim
+builds on that base to support highlighting of user defined tags and
+filters (see the configuration section below.
+
+Indent
+
+Using the same settings as the enhanced syntax file, eclim also ships
+with an indent script which provides indentation support all of the
+default django tags and any user defined tags that have been
+configured.
+
+Match It
+
+Again, using the same set of variables, eclim sets the necessary
+variables to allow proper matchit.vim support for django default and
+user defined tags.
+
+End Tag Completion
+
+Using the |g:HtmlDjangoUserBodyElements| setting along with the
+pre-configured default list of body elements, eclim includes support
+for auto completion of ending template tags when you type an '{%e' or
+'{% e'.
+
+*:DjangoFind*
+
+Contextual Find
+
+While editing django html templates, the command :DjangoFind which
+will attempt to locate the relevant resource depending on what is
+under the cursor.
+
+- If on a user defined tag, attempt to find the tag definition
+ within the python tag definition file.
+ Ex.
+
+ >
+ {# w/ cursor on 'mytag' #}
+ {% mytag somearg %}
+
+ <
+
+- If on a user defined filter, attempt to find the filter definition
+ within the python filter definition file.
+ Ex.
+
+ >
+ {# w/ cursor on 'myfilter' #}
+ {{ somevalue|myfilter }}
+
+ <
+
+- If on the tag/filter definition portion of of a 'load' tag,
+ attempt to find the definition file.
+ Ex.
+
+ >
+ {# w/ cursor on 'mytags' #}
+ {% load mytags %}
+
+ <
+
+- If on a reference to a template for ethier an 'extends' or
+ 'include' tag, attempt to find that template file.
+ Ex.
+
+ >
+ {# w/ cursor on 'include/mytemplate.html' #}
+ {% include "include/mytemplate.html" %}
+
+ <
+
+- If on static file reference, as defined in a 'src' or 'href'
+ attribute of an element, attempt to find that static file.
+ Ex.
+
+ >
+ {# w/ cursor on '/css/my.css' #}
+ <link rel="stylesheet" href="/css/my.css" type="text/css" />
+
+ <
+
+ Note: this functionality requires that g:EclimDjangoStaticPaths is
+ set to a list of absolute or django project relative (relative to
+ directory containing manage.py and settings.py) directories.
+
+ Ex.
+
+ >
+ let g:EclimDjangoStaticPaths = ["../static/"]
+
+ <
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:HtmlDjangoUserBodyElements*
+
+- g:HtmlDjangoUserBodyElements - List of lists, where each list
+ contains the name of the start and end tag, as well as any
+ intermediary tags of any custom tags which have a body.
+ Ex.
+
+ >
+ let g:HtmlDjangoUserBodyElements = [
+ \ ['repeat', 'endrepeat'],
+ \ ['try', 'except', 'finally', 'endtry'],
+ \ ]
+
+ <
+
+ This setting is used for indentation of the custom tag's body, as
+ well as arguments for proper matchit support, end tag completion,
+ and syntax highlighting.
+
+*g:HtmlDjangoUserTags*
+
+- g:HtmlDjangoUserTags - This setting is a list of any non-body tags
+ which don't require indentation or matchit support. The items
+ configured here will be used for syntax highlighting.
+*g:HtmlDjangoUserFilters*
+
+- g:HtmlDjangoUserFilters - This settings contains a list of any
+ user defined django filters. It is currently used for syntax
+ highlighting.
+*g:HtmlDjangoCompleteEndTag*
+
+- g:HtmlDjangoCompleteEndTag (Default: 1) - When set to 0, disables
+ the auto completion of end tags.
+*g:EclimDjangoStaticPaths*
+
+- g:EclimDjangoStaticPaths - Used as a list of directories to search
+ when looking for static files (js, css, etc). Expected to be a list
+ of absolute or django project relative (relative to directory
+ containing manage.py and settings.py) directories.
+ Ex.
+
+ >
+ let g:EclimDjangoStaticPaths = ["../static/"]
+
+ <
+
+*g:EclimDjangoFindAction*
+
+- g:EclimDjangoFindAction (Default: "split") - For :DjangoFind and
+ :DjangoTemplateOpen, used as the action to perform on the file
+ found.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/python/index.txt b/vim/eclim/doc/vim/python/index.txt
@@ -0,0 +1,117 @@
+*vim-python-index*
+
+Python
+******
+
+
+Features
+========
+
+- Python Validation (vim-python-validate)
+- Python Code Completion (vim-python-complete)
+- Python Search (vim-python-search)
+- Django (vim-python-django)
+*python-rope*
+
+
+Rope
+====
+
+Contrary to other languages supported by eclim, python support is not
+provided by an eclipse plugin. When evaluating the currently
+available eclipse plugins for python, namely pydev and dltk, we found
+that they had downsides making them less than ideal candidates for
+inclusion in eclim.
+
+After evaluating the eclipse plugins, attention turned to pure python
+solutions, which then lead to the eventual choice: rope
+(http://rope.sourceforge.net/)
+
+Note: Eclim comes bundled with a version of rope, so there is
+ nothing extra for you to install once you have met the minimum
+ requirements below.
+
+Minimum Requirements:
+ - python 2.5 or greater
+ - vim compiled with python support
+ Warning: Windows Users: gvim for windows does have python
+ support, but at the time of this writing, it is compiled
+ against python 2.4. So if you want to leverage eclim's rope
+ support, you will need to recompile gvim against python 2.5 or
+ higher or find a site which provides a pre-compiled version for
+ you. Here are is one such site providing binaries for python
+ 2.5 and 2.6: gooli.org
+ (http://www.gooli.org/blog/gvim-72-with-python-2526-support-windows-binaries/)
+
+Functionality Utilizing Rope
+ - code completion (|vim-python-complete|)
+ - find element definition (|vim-python-search|)
+ - |:PyLint|
+Creating A New Python Project
+
+Since python support is not provided by eclipse, you can create your
+project with the none nature:
+
+>
+
+ :ProjectCreate my_project -n none
+
+<
+
+
+Configuration
+
+When using functionality that in turn utilizes rope, eclim attempt to
+make the usage of rope as transparent as possible. Eclim will
+automatically create the rope project in the same directory as your
+eclim/eclipse project, resulting in a new directory and file
+(.ropeproject/config.py). Once that file has been created you can
+then modify it to suit your environment.
+
+For example, lets say you have another python project which is not on
+your python path, but you wish to have :PyLint, code completion, etc.
+recognize that project. To do so you can open the
+.ropeproject/config.py file and inside the set_prefs method you will
+see a commented example of how you can add paths to the rope
+'python_path'. You can then add your project like so:
+
+>
+
+ prefs.add('python_path', '~/myotherproject')
+
+<
+
+
+
+Suggested Mappings
+==================
+
+Here are some mappings for the python funtionality provided by eclim.
+To make use of these mappings, simply create a ftplugin file for
+python and place your mappings there (:help ftplugin-name).
+
+- The following mapping allows you to simply hit <enter> on an
+ element to perform a search to find its definition or occurrences
+ depending on the context.
+ >
+ nnoremap <silent> <buffer> <cr> :PythonSearchContext<cr>
+
+ <
+
+- If you are doing django development you may want to use the
+ following mapping which will execute :DjangoViewOpen, or
+ :DjangoTemplateOpen depending on the context of the text under the
+ cursor and if no results were found from either of those, it will
+ issue :PythonFindDefinition.
+ >
+ function! s:MyFind ()
+ let found = eclim#python#django#find#ContextFind()
+ if !found
+ PythonFindDefinition
+ endif
+ endfunction
+ nnoremap <silent> <buffer> <cr> :call <SID>MyFind()<cr>
+
+ <
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/python/search.txt b/vim/eclim/doc/vim/python/search.txt
@@ -0,0 +1,56 @@
+*vim-python-search*
+
+Python Search
+*************
+
+*:PythonFindDefinition*
+
+
+Element Search
+==============
+
+Element searching allows you to place the cursor over just about any
+element in a source file (method call, class name, constant) and
+perform a search for that element by issuing the command
+:PythonFindDefinition.
+
+If only one result is found and that result is in the current source
+file, the cursor will be moved to the element found. Otherwise, on
+single result matches, the value of |g:EclimPythonSearchSingleResult|
+will be consulted for the action to take. If there are multiple
+results, the location list will be opened with the list of results.
+
+*:PythonSearchContext*
+
+As a convenience eclim also provides the command :PythonSearchContext.
+This command accepts no arguments and will perform the appropriate
+search depending on the context of the element.
+
+- If the cursor is on the declaration of a class, function, or
+ method then it will search for all occurrences.
+- Otherwise, it will search for the declaration of the element.
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimPythonSearchSingleResult*
+
+- g:EclimPythonSearchSingleResult (Default: 'split') - Determines
+ what action to take when a only a single result is found.
+ Possible values include:
+
+ - 'split' - open the result in a new window via "split".
+ - 'edit' - open the result in the current window.
+ - 'tabnew' - open the result in a new tab.
+ - 'lopen' - open the location list to display the result.
+ This setting overrides the global default for all supported language
+ types which can be set using the g:EclimDefaultFileOpenAction
+ setting which accepts the same possible values.
+
+- g:EclimLocationListHeight (Default: 10) - Sets the height in lines
+ of the location list window when eclim opens it to display search
+ results.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/python/validate.txt b/vim/eclim/doc/vim/python/validate.txt
@@ -0,0 +1,52 @@
+*vim-python-validate*
+
+Python Validation
+*****************
+
+When editing a python file eclim will default to validating the file
+when it is written. Any errors will be added to the current window's
+location list (:help location-list) and their corresponding line
+number noted via Vim's sign functionality.
+
+Python validation currently uses both the python compiler to check for
+syntax errors and pyflakes
+(http://www.divmod.org/trac/wiki/DivmodPyflakes) to perform some
+additional validation. To make use of the pyflakes portion of the
+validation you will first need to install pyflakes and make sure it is
+in your path.
+
+If you don't want python files validated when saving them, you can set
+the g:EclimPythonValidate variable described in the configuration
+section below.
+
+*:Validate_python*
+
+Regardless of whether you have validation enabled upon saving or not,
+the command :Validate is available to manual validate the file.
+
+*:PyLint*
+
+:PyLint - Runs the pylint (http://www.logilab.org/857) tool on the
+current file, populates the quickfix list with the results (:h
+quickfix), and marks all the affected lines using vim's sign support.
+
+Note: When running :PyLint, determining additional directories to be
+ include on the path for pylint (http://www.logilab.org/857) is
+ provided via eclim's integration with rope (|python-rope|).Please
+ see the rope (|python-rope|) docs for more information.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimPythonValidate*
+
+- g:EclimPythonValidate (Default 1) - If set to 0, disables python
+ validation when saving the file.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/refactoring.txt b/vim/eclim/doc/vim/refactoring.txt
@@ -0,0 +1,42 @@
+*vim-refactoring*
+
+Refactoring
+***********
+
+Described below are some common commands and configuration for eclim's
+refactoring support.
+
+Note: Eclim does not provide refactoring support for all languages,
+ so be sure to check the available features for the language of your
+ choice.
+
+*:RefactorUndo* *:RefactorRedo* *:RefactorUndoPeek*
+
+
+Refactor Undo/Redo
+==================
+
+In the event that you need to undo a refactoring, eclim provides the
+:RefactorUndo command. When executed, the last refactoring will be
+reverted. If you are unsure what the last refactoring was, the
+:RefactorUndoPeek command will print the name of the top most
+refactoring on the undo stack.
+
+Eclim also provides the :RefactorRedo and :RefactorRedoPeek commands
+which provide the redo counterpart to the undo commands.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimRefactorDiffOrientation*
+
+- g:EclimRefactorDiffOrientation (Default: 'vertical') - Specifies
+ the orientation used when previewing a refactoring and performing a
+ diff split between the current file contents and the changes to be
+ performed by the refactoring. Possible values include 'vertical' or
+ 'horizontal'.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/ruby/buildpath.txt b/vim/eclim/doc/vim/ruby/buildpath.txt
@@ -0,0 +1,113 @@
+*vim-ruby-buildpath*
+
+Ruby Interpreters / Build Path
+******************************
+
+*:RubyInterpreterAdd* *:RubyInterpreterRemove* *:RubyInterpreterList*
+
+
+Interpreters
+============
+
+When creating your first ruby project you will be prompted to
+configure a new interpreter if you haven't already done so in eclipse.
+You can also manually manage your ruby interpreters with the following
+commands:
+
+- :RubyInterpreterAdd [-n <name>] <path> - Add a ruby interpreter.
+- :RubyInterpreterRemove <path> - Remove a ruby interpreter.
+- :RubyInterpreterList - List the available ruby interpreters.
+If you have more than one interpreter configured when you create
+subsequent projects you will be prompted to choose the interpreter to
+use. If you remove an interpreter used by one of your projects, you'll
+have to go back to that project and edit its .buildpath file and
+change the interpreter name in the container entry.
+
+Example (wrapped for readability): Changing ruby1.9 to ruby1.8:
+
+>
+
+ <buildpathentry kind="con"
+ path="org.eclipse.dltk.launching.INTERPRETER_CONTAINER/
+ org.eclipse.dltk.internal.debug.ui.launcher.GenericRubyInstallType/ruby1.9"/>
+
+<
+
+
+>
+
+ <buildpathentry kind="con"
+ path="org.eclipse.dltk.launching.INTERPRETER_CONTAINER/
+ org.eclipse.dltk.internal.debug.ui.launcher.GenericRubyInstallType/ruby1.8"/>
+
+<
+
+
+If there is no suffix on the container entry, that project will be
+using what ever is he default interpreter:
+
+>
+
+ <buildpathentry kind="con"
+ path="org.eclipse.dltk.launching.INTERPRETER_CONTAINER"/>
+
+<
+
+
+
+Build Path
+==========
+
+Source code completion, searching, and other features make use of the
+eclipse dltk's (http://eclipse.org/dltk/) .buildpath to locate
+resources. When you first create a dltk project (currently php
+(|vim-php-index|) or ruby (|vim-ruby-index|)), a .buildpath file is
+created in the project's root directory. If your project depends on
+any source files located outside your project or in another project,
+then you'll need to edit your .buildpath accordingly.
+
+To help you do this, eclim provides several commands to ease the
+creation of new build path entries and variables, all of which are
+made available when you edit your .buildpath file in vim. Also when
+you write the .buildpath file, Vim will issue a command to the eclim
+server to update the project's build path, and will report any errors
+via vim's location list (:help location-list).
+
+The following is a list of commands that eclim provides while editing
+your .buildpath.
+
+*:NewSrcEntry_dltk_ruby*
+
+- :NewSrcEntry <dir> [<dir> ...] - Adds one or more new entries
+ which reference source directories in your project.
+ >
+ <buildpathentry external="true" kind="lib" path="src/php"/>
+
+ <
+
+ This command supports command completion of project relative
+ directories.
+
+*:NewLibEntry_dltk_ruby*
+
+- :NewLibEntry <dir> [<dir> ...] - Adds one or more new entries
+ which reference external source directories.
+ >
+ <buildpathentry external="true" kind="lib" path="/usr/local/php/cake_1.1.16.5421"/>
+
+ <
+
+ This command supports command completion of directories.
+
+*:NewProjectEntry_dltk_ruby*
+
+- :NewProjectEntry <project> [<project> ...] - Adds one or more new
+ entries which reference other projects.
+ >
+ <buildpathentry combineaccessrules="false" kind="prj" path="/test_project"/>
+
+ <
+
+ This command supports command completion of project names.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/ruby/complete.txt b/vim/eclim/doc/vim/ruby/complete.txt
@@ -0,0 +1,25 @@
+*vim-ruby-complete*
+
+Ruby Code Completion
+********************
+
+Ruby code completion uses the standard Vim code completion mechanism
+(|vim-code_completion|) like so:
+
+>
+
+ class Test
+ def getName()
+ end
+
+ def getValue()
+ end
+ end
+
+ test = Test.new
+ test.get<C-X><C-U>
+ test.getName()
+
+<
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/ruby/index.txt b/vim/eclim/doc/vim/ruby/index.txt
@@ -0,0 +1,11 @@
+*vim-ruby-index*
+
+Ruby
+****
+
+- Ruby Interpreters / Build Path (vim-ruby-buildpath)
+- Ruby Code Completion (vim-ruby-complete)
+- Ruby Validation (vim-ruby-validate)
+- Ruby Search (vim-ruby-search)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/ruby/search.txt b/vim/eclim/doc/vim/ruby/search.txt
@@ -0,0 +1,112 @@
+*vim-ruby-search*
+
+Ruby Search
+***********
+
+*:RubySearch*
+
+
+Pattern Search
+==============
+
+Pattern searching provides a means to widen a search beyond a single
+element. A pattern search can be executed using the command
+
+:RubySearch -p <pattern> [-t <type> -s <scope> -i]
+
+All of the results will be placed into the current window's location
+list (:help location-list) so that you can easily navigate the
+results.
+
+Vim command completion is supported through out the command with the
+exception of the pattern to search for.
+
+>
+
+ :RubySearch <Tab>
+ :RubySearch -p MyClass* <Tab>
+ :RubySearch -p MyClass* -t <Tab>
+ :RubySearch -p MyClass* -t class <Tab>
+ :RubySearch -p MyClass* -t class -s <Tab>
+ :RubySearch -p MyClass* -t class -s project
+
+<
+
+
+- -p <pattern>: The pattern to search for.
+ Ex.
+
+ >
+ MyClass
+ myFunction
+ my*
+
+ <
+
+- -t <type> (Default: all): The type of element to search for where
+ possible types include
+ - class
+ - method
+ - field
+- -x <context> (Default: declarations): The context of the search,
+ where possible values include
+ - all - All occurances.
+ - declarations - Declarations matching the pattern or element.
+ - references - References of the pattern or element.
+- -s <scope> (Default: all): The scope of the search where possible
+ values include
+ - all - Search the whole workspace.
+ - project - Search the current project, dependent projects, and
+ libraries.
+- -i: Ignore case when searching.
+
+Element Search
+==============
+
+Element searching allows you to place the cursor over just about any
+element in a source file (method call, class name, constant) and
+perform a search for that element. Performing an element search is
+the same as performing a pattern search with the exception that you do
+not specify the -p option since the element under the cursor will be
+searched for instead.
+
+If only one result is found and that result is in the current source
+file, the cursor will be moved to the element found. Otherwise, on
+single result matches, the value of |g:EclimRubySearchSingleResult|
+will be consulted for the action to take. If there are multiple
+results, the location list will be opened with the list of results.
+
+*:RubySearchContext*
+
+As a convenience eclim also provides the command :RubySearchContext.
+This command accepts no arguments and will perform the appropriate
+search depending on the context of the element.
+
+- If the cursor is on a the definition of a method, class, module,
+ etc. then a search will be performed for all uses of that element.
+- Otherwise, it will search for the declaration of the element.
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimRubySearchSingleResult*
+
+- g:EclimRubySearchSingleResult (Default: 'split') - Determines what
+ action to take when a only a single result is found.
+ Possible values include:
+
+ - 'split' - open the result in a new window via "split".
+ - 'edit' - open the result in the current window.
+ - 'tabnew' - open the result in a new tab.
+ - 'lopen' - open the location list to display the result.
+ This setting overrides the global default for all supported language
+ types which can be set using the g:EclimDefaultFileOpenAction
+ setting which accepts the same possible values.
+
+- g:EclimLocationListHeight (Default: 10) - Sets the height in lines
+ of the location list window when eclim opens it to display search
+ results.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/ruby/validate.txt b/vim/eclim/doc/vim/ruby/validate.txt
@@ -0,0 +1,35 @@
+*vim-ruby-validate*
+
+*:Validate_ruby*
+
+
+Ruby Validation
+***************
+
+When saving a ruby source file that resides in a project, eclim will
+update that source file in Eclipse and will report any validation
+errors found. Any errors will be placed in the current window's
+location list (:help location-list) and the corresponding lines in the
+source file will be marked via Vim's :sign functionality with '>>'
+markers in the left margin.
+
+Automatic validation of ruby source files can be disabled via the
+g:EclimRubyValidate variable (described below). If you choose to
+disable automatic validation, you can still use the :Validate command
+to manually validate the current file.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimRubyValidate*
+
+- g:EclimRubyValidate (Default: 1) - If set to 0, disables source
+ code validation.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/scala/complete.txt b/vim/eclim/doc/vim/scala/complete.txt
@@ -0,0 +1,22 @@
+*vim-scala-complete*
+
+Scala Code Completion
+*********************
+
+Scala code completion uses the standard Vim code completion mechanism
+(|vim-code_completion|) like so:
+
+>
+
+ package eclim.test
+
+ class Test {
+ def test(){
+ val list = List("foo", "bar", "baz")
+ list.s<C-X><C-U>
+ }
+ }
+
+<
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/scala/import.txt b/vim/eclim/doc/vim/scala/import.txt
@@ -0,0 +1,35 @@
+*vim-scala-import*
+
+*:ScalaImport*
+
+
+Automated Imports
+*****************
+
+The automated import functionality is pretty straightforward. Simply
+place the cursor over the element to import and issue the command:
+
+:ScalaImport
+
+and one of the following events will occur:
+
+- If only one matching element is found, its import statement will
+ be placed in the file.
+- If multiple matching elements are found, you will be prompted to
+ choose the element you wish to import from a list.
+- If an element with the same name is already imported then no
+ changes will occur.
+Note: Like the scala-ide (as of the time of this writting), imports
+ are simply appended to the end of your file's import block. There is
+ no attempt made to sort or group imports.
+
+
+Configuration
+=============
+
+Eclim Settings (|vim-settings|)
+
+- |org.eclim.java.import.exclude| - Scala importing honors the java
+ import exclussion setting.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/scala/index.txt b/vim/eclim/doc/vim/scala/index.txt
@@ -0,0 +1,11 @@
+*vim-scala-index*
+
+Scala
+*****
+
+- Scala Code Completion (vim-scala-complete)
+- Scala Validation (vim-scala-validate)
+- Scala Search (vim-scala-search)
+- Automated Imports (vim-scala-import)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/scala/search.txt b/vim/eclim/doc/vim/scala/search.txt
@@ -0,0 +1,39 @@
+*vim-scala-search*
+
+*:ScalaSearch*
+
+
+Scala Search
+************
+
+Eclim's scala searching currently supports searching for the
+definition of the element under the cursor. Simply place the cursor on
+the element you wish to search for and run :ScalaSearch. If the
+definition of the element is found, the corresponding file will be
+opened and the cursor placed on the element's definition.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimScalaSearchSingleResult*
+
+- g:EclimScalaSearchSingleResult (Default: 'split') - Determines
+ what action to take when a only a single result is found.
+ Possible values include:
+
+ - 'split' - open the result in a new window via "split".
+ - 'edit' - open the result in the current window.
+ - 'tabnew' - open the result in a new tab.
+ - 'lopen' - open the location list to display the result.
+ This setting overrides the global default for all supported language
+ types which can be set using the g:EclimDefaultFileOpenAction
+ setting which accepts the same possible values.
+
+- g:EclimLocationListHeight (Default: 10) - Sets the height in lines
+ of the location list window when eclim opens it to display search
+ results.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/scala/validate.txt b/vim/eclim/doc/vim/scala/validate.txt
@@ -0,0 +1,35 @@
+*vim-scala-validate*
+
+*:Validate_scala*
+
+
+Scala Validation
+****************
+
+When saving a scala source file that resides in a project, eclim will
+update that source file in Eclipse and will report any validation
+errors found. Any errors will be placed in the current window's
+location list (:help location-list) and the corresponding lines in the
+source file will be marked via Vim's :sign functionality with '>>'
+markers in the left margin.
+
+Automatic validation of scala source files can be disabled via the
+g:EclimScalaValidate variable (described below). If you choose to
+disable automatic validation, you can still use the :Validate command
+to manually validate the current file.
+
+
+Configuration
+=============
+
+Vim Settings (|vim-settings|)
+
+*g:EclimScalaValidate*
+
+- g:EclimScalaValidate (Default: 1) - If set to 0, disables source
+ code validation.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/settings.txt b/vim/eclim/doc/vim/settings.txt
@@ -0,0 +1,52 @@
+*vim-settings*
+
+Settings
+********
+
+Certain aspects of eclim can be controlled by modifying one or more
+settings.
+
+There are two types of settings available:
+
+- Eclim global / project settings.
+ These are settings that reside in your Eclipse workspace and are
+ used to control certain aspects of the eclim server's behavior.
+ These settings can be viewed and modified using one of the following
+ commands:
+
+ - :EclimSettings (|vim-core-eclim#:EclimSettings|)
+ - |:ProjectSettings|
+- Vim global variable settings.
+ These are your typical global Vim variables which can be set within
+ your vimrc file.
+
+Givin these two types, you may be ask, why do we need two? Or, when a
+new setting is added, how do you decide which type to make it?
+
+The reasoning behind having two types is that there are some settings
+that may vary from one project to another. For instance, I may have
+one project that can be used in jdk 1.3 and utilizes log4j for
+logging, while another project of mine requires jdk 1.4 and utilizes
+slf4j for logging. Instances like this require that each project be
+capable of storing their own settings. Rather than reinvent this
+support in Vim, we utilize Eclipse's built in preferences system.
+
+If the Eclipse preferences system can store project level and global
+settings, why not make all the eclim settings of this type? Well, the
+downside to Eclipse preferences system is that an Eclipse instance
+must be running to obtain the value of that preference. Eclim
+however, requires access to many settings, regardless of whether
+Eclipse is running or not. So, to ensure that these settings are
+always available, we utilize the standard Vim global variable support.
+
+When adding a new setting, deciding between an Eclipse preference or a
+Vim global variable is a matter of answering the following:
+
+- Will this setting vary from one project to another?
+ Yes: Add this setting an Eclipse preference.
+
+- Does eclim need access to this setting regardless of whether an
+ Eclipse instance is running or not?
+ Yes: Add this setting a Vim global variable.
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/doc/vim/xml/index.txt b/vim/eclim/doc/vim/xml/index.txt
@@ -0,0 +1,204 @@
+*vim-xml-index*
+
+Xml / Dtd / Xsd
+***************
+
+*xml*
+
+
+Xml
+===
+
+
+Code Completion
+---------------
+
+Xml code completion uses the standard Vim code completion mechanism
+(|vim-code_completion|) like so:
+
+>
+
+ <ser<Ctrl-X><Ctrl-U>
+
+ <servlet>
+ <ser<Ctrl-X><Ctrl-U>
+
+ <servlet>
+ <servlet-name>
+ ...
+
+<
+
+
+Note: Requires a valid dtd or xsd to determine possible completions.
+
+
+Definition Lookup
+-----------------
+
+When editing xml files, eclim provides a couple commands which allow
+you to quickly and easily open the file's data definition and
+optionally jump to the definition of a particular element.
+
+Note: When opening urls, these commands rely on netrw (:help netrw).
+
+*:DtdDefinition*
+
+- :DtdDefinition [<element>] - When invoked, this command will
+ attempt to locate the dtd declaration in the current xml file and
+ open the dtd in a new split window. If you supply an element name
+ when invoking the command, it will attempt to locate and jump to the
+ definition of that element within the dtd. If no element name is
+ supplied, but the cursor is located on an element name when invoke,
+ that element name will be used.
+*:XsdDefinition*
+
+- :XsdDefinition [<element>] - Behaves like :DtdDefinition except
+ this command locates and opens the corresponding schema definition
+ file.
+*xml-validation*
+
+
+Validation
+----------
+
+When editing a xml file eclim will default to validating the file when
+it is written. Any errors will be added to the current window's
+location list (:help location-list) and their corresponding line
+number noted via Vim's sign functionality.
+
+If you don't want xml files validated when saving them, you can set
+the g:EclimXmlValidate variable described in the configuration section
+below.
+
+Regardless of whether you have validation enabled upon saving or not,
+the following command is still available for validating xml files on
+demand.
+
+*:Validate_xml*
+
+:Validate [<file>] - Validate the supplied file or the current file if
+no file name provided.
+
+If eclimd is not currently running, and the xmllint command is
+available, eclim will validate the xml file using that. Eclim will
+never use xmllint when saving the file with g:EclimXmlValidate
+enabled.
+
+*:XmlFormat*
+
+
+Format
+------
+
+On occasion you may encounter some xml content that is unformatted
+(like raw content from a web service).
+
+>
+
+ <blah><foo>one</foo><bar>two</bar></blah>
+
+<
+
+
+Executing :XmlFormat will reformat the current xml file like so:
+
+>
+
+ <blah>
+ <foo>one</foo>
+ <bar>two</bar>
+ </blah>
+
+<
+
+
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimXmlValidate*
+
+- g:EclimXmlValidate (Defualt: 1) - If set to 0, disables xml
+ validation when saving the file.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+*dtd*
+
+
+Dtd
+===
+
+
+Validation
+----------
+
+When editing a dtd file eclim will default to validating the file when
+it is written. Any errors will be added to the current window's
+location list (:help location-list) and their corresponding line
+number noted via Vim's sign functionality.
+
+If you do not want your dtd files validated automatically when saved,
+you can set the |g:EclimDtdValidate| variable described in the
+configuration section below.
+
+*:Validate_dtd*
+
+Whether or not auto validation has been enabled, eclim also exposes
+the command :Validate to manually execute the validation of the file.
+
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimDtdValidate*
+
+- g:EclimDtdValidate (Default: 1) - If set to 0, disables validation
+ when saving the file.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+*xsd*
+
+
+Xsd
+===
+
+
+Validation
+----------
+
+When editing a xsd file eclim will default to validating the file when
+it is written. Any errors will be added to the current window's
+location list (:help location-list) and their corresponding line
+number noted via Vim's sign functionality.
+
+If you do not want your xsd files validated automatically when saved,
+you can set the |g:EclimXsdValidate| variable described in the
+configuration section below.
+
+*:Validate_xsd*
+
+Whether or not auto validation has been enabled, eclim also exposes
+the command :Validate to manually execute the validation of the file.
+
+
+Configuration
+-------------
+
+Vim Settings (|vim-settings|)
+
+*g:EclimXsdValidate*
+
+- g:EclimXsdValidate (Default: 1) - If set to 0, disables validation
+ when saving the file.
+- g:EclimValidateSortResults (Default: 'occurrence') - If set to
+ 'severity', the validation results will be sorted by severity
+ (errors > warnings > info > etc.)
+
+vim:ft=eclimhelp+
\ No newline at end of file
diff --git a/vim/eclim/ftplugin/ant.vim b/vim/eclim/ftplugin/ant.vim
@@ -0,0 +1,60 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/ant/index.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+
+if !exists("g:EclimAntValidate")
+ let g:EclimAntValidate = 1
+endif
+
+" }}}
+
+" Options {{{
+
+exec 'setlocal ' . g:EclimCompletionMethod . '=eclim#java#ant#complete#CodeComplete'
+
+" }}}
+
+" Autocmds {{{
+
+if g:EclimAntValidate
+ augroup eclim_xml
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#lang#Validate('ant', 1)
+ augroup END
+endif
+
+" }}}
+
+" Command Declarations {{{
+
+if !exists(":AntDoc")
+ command -buffer -nargs=? AntDoc :call eclim#java#ant#doc#FindDoc('<args>')
+endif
+
+command! -nargs=0 -buffer Validate :call eclim#lang#Validate('ant', 0)
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/c.vim b/vim/eclim/ftplugin/c.vim
@@ -0,0 +1,81 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+
+if !exists("g:EclimCValidate")
+ let g:EclimCValidate = 1
+endif
+
+if !exists("g:EclimCSyntasticEnabled")
+ let g:EclimCSyntasticEnabled = 0
+endif
+
+if !exists("g:EclimCppSyntasticEnabled")
+ let g:EclimCppSyntasticEnabled = 0
+endif
+
+if !exists('g:EclimCCallHierarchyDefaultAction')
+ let g:EclimCCallHierarchyDefaultAction = g:EclimDefaultFileOpenAction
+endif
+
+" }}}
+
+" Options {{{
+
+exec 'setlocal ' . g:EclimCompletionMethod . '=eclim#c#complete#CodeComplete'
+
+call eclim#lang#DisableSyntasticIfValidationIsEnabled('c', &ft)
+
+" }}}
+
+" Autocmds {{{
+
+augroup eclim_c
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#lang#UpdateSrcFile('c')
+augroup END
+
+" }}}
+
+" Command Declarations {{{
+
+command! -nargs=0 -buffer Validate :call eclim#lang#UpdateSrcFile('c', 1)
+
+if !exists(":CSearch")
+ command -buffer -nargs=*
+ \ -complete=customlist,eclim#c#search#CommandCompleteCSearch
+ \ CSearch :call eclim#c#search#Search('<args>')
+endif
+
+if !exists(":CSearchContext")
+ command -buffer CSearchContext :call eclim#c#search#SearchContext()
+endif
+
+if !exists(":CCallHierarchy")
+ command -buffer -bang CCallHierarchy
+ \ :call eclim#lang#hierarchy#CallHierarchy(
+ \ 'c', g:EclimCCallHierarchyDefaultAction, '<bang>')
+endif
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/commonsvalidator.vim b/vim/eclim/ftplugin/commonsvalidator.vim
@@ -0,0 +1,35 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+
+if !exists('g:tlist_commonsvalidator_settings')
+ let g:tlist_commonsvalidator_settings = {
+ \ 'lang': 'commonsvalidator',
+ \ 'parse': 'eclim#taglisttoo#lang#commonsvalidator#Parse',
+ \ 'tags': {'c': 'constant', 'f': 'form', 'v': 'validator'}
+ \ }
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/cpp.vim b/vim/eclim/ftplugin/cpp.vim
@@ -0,0 +1,24 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime eclim/ftplugin/c.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/css.vim b/vim/eclim/ftplugin/css.vim
@@ -0,0 +1,60 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/css/index.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+
+if !exists("g:EclimCssValidate")
+ let g:EclimCssValidate = 1
+endif
+
+" }}}
+
+" Options {{{
+
+exec 'setlocal ' . g:EclimCompletionMethod . '=eclim#css#complete#CodeComplete'
+
+" }}}
+
+" Autocmds {{{
+
+if g:EclimCssValidate
+ augroup eclim_css_validate
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer>
+ \ call eclim#lang#Validate('css', 1, 'eclim#css#validate#Filter')
+ augroup END
+endif
+
+" }}}
+
+" Command Declarations {{{
+
+if !exists(":Validate")
+ command -nargs=0 -buffer Validate
+ \ :call eclim#lang#Validate('css', 0, 'eclim#css#validate#Filter')
+endif
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/dtd.vim b/vim/eclim/ftplugin/dtd.vim
@@ -0,0 +1,52 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/dtd/index.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+
+if !exists("g:EclimDtdValidate")
+ let g:EclimDtdValidate = 1
+endif
+
+" }}}
+
+" Autocmds {{{
+
+if g:EclimDtdValidate
+ augroup eclim_css_validate
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#lang#Validate('dtd', 1)
+ augroup END
+endif
+
+" }}}
+
+" Command Declarations {{{
+
+if !exists(":Validate")
+ command -nargs=0 -buffer Validate :call eclim#lang#Validate('dtd', 0)
+endif
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/eclimhelp.vim b/vim/eclim/ftplugin/eclimhelp.vim
@@ -0,0 +1,37 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/help.vim
+
+nnoremap <silent> <buffer> <cr> :call eclim#help#Help('', 1)<cr>
+nnoremap <silent> <buffer> <c-]> :call eclim#help#Help('', 1)<cr>
+
+if !exists("g:tlist_eclimhelp_settings")
+ let g:tlist_eclimhelp_settings = {
+ \ 'lang': 'eclimhelp',
+ \ 'parse': 'eclim#taglisttoo#lang#eclimhelp#Parse',
+ \ 'tags': {'s': 'section', 'a': 'anchor'}
+ \ }
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/eclipse_classpath.vim b/vim/eclim/ftplugin/eclipse_classpath.vim
@@ -0,0 +1,66 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/classpath.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" load any xml related functionality
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+
+augroup eclim_xml
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#project#util#ProjectUpdate()
+augroup END
+
+" Command Declarations {{{
+if !exists(":NewSrcEntry")
+ command -nargs=1 -complete=customlist,eclim#project#util#CommandCompleteProjectRelative -buffer
+ \ NewSrcEntry :call eclim#java#classpath#NewClasspathEntry('src', '<args>')
+endif
+if !exists(":NewProjectEntry")
+ command -nargs=1 -complete=customlist,eclim#java#util#CommandCompleteProject -buffer
+ \ NewProjectEntry :call eclim#java#classpath#NewClasspathEntry('project', '<args>')
+endif
+if !exists(":NewJarEntry")
+ command -nargs=+ -complete=customlist,eclim#project#util#CommandCompleteAbsoluteOrProjectRelative -buffer
+ \ NewJarEntry
+ \ :call eclim#java#classpath#NewClasspathEntry('lib', <f-args>)
+endif
+if !exists(":NewVarEntry")
+ command -nargs=+ -complete=customlist,eclim#java#classpath#CommandCompleteVarPath -buffer
+ \ NewVarEntry
+ \ :call eclim#java#classpath#NewClasspathEntry('var', <f-args>)
+endif
+if !exists(":VariableList")
+ command -buffer VariableList :call eclim#java#classpath#VariableList()
+endif
+if !exists(":VariableCreate")
+ command -nargs=+ -buffer -complete=customlist,eclim#java#classpath#CommandCompleteVarAndDir
+ \ VariableCreate :call eclim#java#classpath#VariableCreate(<f-args>)
+endif
+if !exists(":VariableDelete")
+ command -nargs=1 -buffer -complete=customlist,eclim#java#classpath#CommandCompleteVar
+ \ VariableDelete :call eclim#java#classpath#VariableDelete('<args>')
+endif
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/eclipse_cproject.vim b/vim/eclim/ftplugin/eclipse_cproject.vim
@@ -0,0 +1,76 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/c/paths.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+let g:tlist_eclipse_cproject_settings = {
+ \ 'lang': 'cproject',
+ \ 'parse': 'eclim#taglisttoo#lang#cproject#Parse',
+ \ 'tags': {
+ \ 'c': 'configuration',
+ \ 't': 'toolchain',
+ \ 'l': 'tool',
+ \ 'i': 'include',
+ \ 's': 'symbol',
+ \ }
+ \ }
+" }}}
+
+" Script Variables {{{
+ let s:entry_src = "\t<classpathentry kind=\"src\" path=\"<arg>\"/>"
+ let s:entry_project =
+ \ "\t<classpathentry exported=\"true\" kind=\"src\" path=\"/<arg>\"/>"
+ let s:entry_var =
+ \ "\t<classpathentry kind=\"<kind>\" path=\"<arg>\"/>"
+ " \ "\t<classpathentry exported=\"true\" kind=\"<kind>\" path=\"<arg>\">\n" .
+ " \ "\t\t<!--\n" .
+ " \ "\t\t\tsourcepath=\"<path>\">\n" .
+ " \ "\t\t-->\n" .
+ " \ "\t\t<!--\n" .
+ " \ "\t\t<attributes>\n" .
+ " \ "\t\t\t<attribute value=\"file:<javadoc>\" name=\"javadoc_location\"/>\n" .
+ " \ "\t\t</attributes>\n" .
+ " \ "\t\t-->\n" .
+ " \ "\t</classpathentry>"
+ let s:entry_jar = substitute(s:entry_var, '<kind>', 'lib', '')
+ let s:entry_var = substitute(s:entry_var, '<kind>', 'var', '')
+" }}}
+
+" load any xml related functionality
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+
+augroup eclim_xml
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#project#util#ProjectUpdate()
+augroup END
+
+" Command Declarations {{{
+
+if !exists(":CProjectConfigs")
+ command -nargs=0 -buffer CProjectConfigs :call eclim#c#project#Configs()
+endif
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/forrestdocument.vim b/vim/eclim/ftplugin/forrestdocument.vim
@@ -0,0 +1,37 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+
+set textwidth=80
+
+if !exists('g:tlist_forrestdocument_settings')
+ let g:tlist_forrestdocument_settings = {
+ \ 'lang': 'forrestdocument',
+ \ 'parse': 'eclim#taglisttoo#lang#forrest#ParseDocument',
+ \ 'tags': {'s': 'section'}
+ \ }
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/forreststatus.vim b/vim/eclim/ftplugin/forreststatus.vim
@@ -0,0 +1,37 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+
+set textwidth=80
+
+if !exists('g:tlist_forreststatus_settings')
+ let g:tlist_forreststatus_settings = {
+ \ 'lang': 'forreststatus',
+ \ 'parse': 'eclim#taglisttoo#lang#forrest#ParseStatus',
+ \ 'tags': {'t': 'todo', 'r': 'release'}
+ \ }
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/gant.vim b/vim/eclim/ftplugin/gant.vim
@@ -0,0 +1,35 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/groovy*.vim
+runtime! ftplugin/groovy/*.vim
+
+if !exists('g:tlist_gant_settings')
+ let g:tlist_gant_settings = {
+ \ 'lang': 'gant',
+ \ 'parse': 'eclim#taglisttoo#lang#gant#Parse',
+ \ 'tags': {'t': 'target', 'f': 'function'}
+ \ }
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/hibernate.vim b/vim/eclim/ftplugin/hibernate.vim
@@ -0,0 +1,44 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+runtime eclim/ftplugin/java-xml.vim
+
+if !exists("g:tlist_hibernate_settings")
+ let g:tlist_hibernate_settings = {
+ \ 'lang': 'hibernate',
+ \ 'parse': 'eclim#taglisttoo#lang#hibernate#Parse',
+ \ 'tags': {
+ \ 't': 'typedef',
+ \ 'f': 'filter-def',
+ \ 'i': 'import',
+ \ 'q': 'query',
+ \ 's': 'sql-query',
+ \ 'c': 'class',
+ \ 'j': 'joined-subclass'
+ \ }
+ \ }
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/html.vim b/vim/eclim/ftplugin/html.vim
@@ -0,0 +1,70 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/html/index.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+
+if !exists("g:EclimHtmlValidate")
+ let g:EclimHtmlValidate = 1
+endif
+
+if !exists("g:EclimHtmlSyntasticEnabled")
+ let g:EclimHtmlSyntasticEnabled = 0
+endif
+
+" }}}
+
+" Options {{{
+
+exec 'setlocal ' . g:EclimCompletionMethod . '=eclim#html#complete#CodeComplete'
+
+call eclim#lang#DisableSyntasticIfValidationIsEnabled('html')
+
+" }}}
+
+" Autocmds {{{
+
+if g:EclimHtmlValidate
+ augroup eclim_html_validate
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#html#validate#Validate(1)
+ augroup END
+endif
+
+" }}}
+
+" Command Declarations {{{
+
+if !exists(":Validate")
+ command -nargs=0 -buffer Validate
+ \ :call eclim#lang#Validate('html', 0)
+endif
+
+if !exists(":BrowserOpen")
+ command -nargs=? -complete=file -buffer BrowserOpen
+ \ :call eclim#html#util#OpenInBrowser(<q-args>)
+endif
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/htmldjango.vim b/vim/eclim/ftplugin/htmldjango.vim
@@ -0,0 +1,90 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/html.vim
+runtime! indent/html.vim
+runtime eclim/ftplugin/html.vim
+
+" Global Variables {{{
+
+if !exists('g:HtmlDjangoCompleteEndTag')
+ let g:HtmlDjangoCompleteEndTag = 1
+endif
+if !exists('g:HtmlDjangoUserBodyElements')
+ let g:HtmlDjangoUserBodyElements = []
+endif
+
+let g:HtmlDjangoBodyElements = [
+ \ ['block', 'endblock'],
+ \ ['comment', 'endcomment'],
+ \ ['filter', 'endfilter'],
+ \ ['for', 'endfor'],
+ \ ['if', 'else', 'endif'],
+ \ ['ifchanged', 'else', 'endifchanged'],
+ \ ['ifequal', 'else', 'endifequal'],
+ \ ['ifnotequal', 'else', 'endifnotequal'],
+ \ ['spaceless', 'else', 'endspaceless']
+ \ ] + g:HtmlDjangoUserBodyElements
+
+" add matchit.vim support for django tags
+if exists("b:match_words")
+ for element in g:HtmlDjangoBodyElements
+ let pattern = ''
+ for tag in element[:-2]
+ if pattern != ''
+ let pattern .= ':'
+ endif
+ let pattern .= '{%\s*\<' . tag . '\>.\{-}%}'
+ endfor
+ let pattern .= ':{%\s*\<' . element[-1:][0] . '\>\s*%}'
+ let b:match_words .= ',' . pattern
+ endfor
+endif
+
+" }}}
+
+" Mappings {{{
+
+if g:HtmlDjangoCompleteEndTag
+ imap <buffer> <silent> e <c-r>=eclim#python#django#template#CompleteEndTag()<cr>
+endif
+
+" }}}
+
+" Command Declarations {{{
+
+if !exists(':DjangoFind')
+ command -buffer DjangoFind :call eclim#python#django#find#TemplateFind()
+endif
+
+" }}}
+
+" Options {{{
+
+let b:endwise_addition = '{% end& %}'
+let b:endwise_words = 'block,if,while,for'
+let b:endwise_syngroups = 'djangoStatement'
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/htmljinja.vim b/vim/eclim/ftplugin/htmljinja.vim
@@ -0,0 +1,87 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/html.vim
+runtime! indent/html.vim
+runtime eclim/ftplugin/html.vim
+
+" Global Variables {{{
+if !exists('g:HtmlJinjaCompleteEndTag')
+ let g:HtmlJinjaCompleteEndTag = 1
+endif
+" }}}
+
+" Mappings {{{
+if g:HtmlJinjaCompleteEndTag
+ imap <buffer> <silent> e <c-r>=eclim#python#jinja#CompleteEndTag()<cr>
+endif
+" }}}
+
+" Options {{{
+
+if exists('b:jinja_line_statement_prefix')
+ let b:endwise_addition =
+ \ '\=getline(line(".") - 1)=~"^\\s*' . b:jinja_line_statement_prefix . '" ? '.
+ \ '"' . b:jinja_line_statement_prefix . ' end" . submatch(0) : ' .
+ \ '"{% end" . submatch(0) . " %}"'
+else
+ let b:endwise_addition = '{% end& %}'
+endif
+let b:endwise_words = 'block,call,if,while,filter,for,macro'
+let b:endwise_syngroups = 'jinjaStatement'
+
+" }}}
+
+let g:HtmlJinjaBodyElements = [
+ \ ['block', 'endblock'],
+ \ ['call', 'endcall'],
+ \ ['filter', 'endfilter'],
+ \ ['for', 'endfor'],
+ \ ['if', 'elif', 'else', 'endif'],
+ \ ['macro', 'endmacro'],
+ \ ]
+" excluding 'else' on for until matchit.vim can support a duplicate word
+" (doesn't break the matching of 'else' for 'if' statements.
+" \ ['for', 'else', 'endfor'],
+
+" add matchit.vim support for jinja tags
+if exists("b:match_words")
+ for element in g:HtmlJinjaBodyElements
+ let pattern = ''
+ for tag in element[:-2]
+ if pattern != ''
+ let pattern .= ':'
+ endif
+ let pattern .= '{%-\?\s*\<' . tag . '\>' "\_.\{-}-\?%}'
+ endfor
+ let pattern .= ':{%-\?\s*\<' . element[-1:][0] . '\>\s*-\?%}'
+ let b:match_words .= ',' . pattern
+ if exists('b:jinja_line_statement_prefix')
+ let pattern = substitute(pattern, '{%-\\?', b:jinja_line_statement_prefix, 'g')
+ let pattern = substitute(pattern, '-\\?%}', '', 'g')
+ let b:match_words .= ',' . pattern
+ endif
+ endfor
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/ivy.vim b/vim/eclim/ftplugin/ivy.vim
@@ -0,0 +1,48 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/classpath.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" load any xml related functionality
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+
+" turn off xml validation
+augroup eclim_xml
+ autocmd! BufWritePost <buffer>
+augroup END
+
+" Autocmds {{{
+augroup eclim_ivy
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#java#maven#UpdateClasspath()
+augroup END
+" }}}
+
+" Command Declarations {{{
+if !exists(":IvyRepo")
+ command -nargs=1 -complete=dir -buffer IvyRepo
+ \ :call eclim#java#ant#ivy#SetRepo('<args>')
+endif
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/java-xml.vim b/vim/eclim/ftplugin/java-xml.vim
@@ -0,0 +1,40 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Functionality exposed to java xml files (web.xml, spring xml files, etc.).
+
+" Global Variables {{{
+
+if !exists("g:EclimJavaSearchMapping")
+ let g:EclimJavaSearchMapping = 1
+endif
+
+" }}}
+
+" Mappings {{{
+
+if g:EclimJavaSearchMapping
+ noremap <silent> <buffer> <cr> :call eclim#java#search#FindClassDeclaration()<cr>
+endif
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/java.vim b/vim/eclim/ftplugin/java.vim
@@ -0,0 +1,250 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/index.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+
+if !exists("g:EclimJavaValidate")
+ let g:EclimJavaValidate = 1
+endif
+
+if !exists("g:EclimJavaSetCommonOptions")
+ let g:EclimJavaSetCommonOptions = 1
+endif
+
+if !exists("g:EclimJavaCompilerAutoDetect")
+ let g:EclimJavaCompilerAutoDetect = 1
+endif
+
+if !exists("g:EclimJavaSyntasticEnabled")
+ let g:EclimJavaSyntasticEnabled = 0
+endif
+
+if !exists('g:EclimJavaCallHierarchyDefaultAction')
+ let g:EclimJavaCallHierarchyDefaultAction = g:EclimDefaultFileOpenAction
+endif
+
+" }}}
+
+" Options {{{
+
+exec 'setlocal ' . g:EclimCompletionMethod . '=eclim#java#complete#CodeComplete'
+
+if g:EclimJavaSetCommonOptions
+ " allow cpp keywords in java files (delete, friend, union, template, etc).
+ let java_allow_cpp_keywords=1
+
+ " tell vim how to search for included files.
+ setlocal include=^\s*import
+ setlocal includeexpr=substitute(v:fname,'\\.','/','g')
+ setlocal suffixesadd=.java
+endif
+
+" set make program and error format accordingly.
+if g:EclimJavaCompilerAutoDetect
+ " use ant settings
+ if eclim#util#Findfile('build.xml', '.;') != '' &&
+ \ eclim#util#CompilerExists('eclim_ant')
+ compiler eclim_ant
+
+ " use mvn settings
+ elseif eclim#util#Findfile('pom.xml', '.;') != '' &&
+ \ eclim#util#CompilerExists('eclim_mvn')
+ compiler eclim_mvn
+
+ if !g:EclimMakeLCD && !exists('g:EclimMakeLCDWarning')
+ call eclim#util#EchoWarning("WARNING: g:EclimMakeLCD disabled.\n" .
+ \ "Unlike maven and ant, mvn does not provide a mechanism to " .
+ \ "search for the target build file.\n" .
+ \ "Disabling g:EclimMakeLCD may cause issues when executing :make or :Mvn")
+ let g:EclimMakeLCDWarning = 1
+ endif
+
+ " use maven settings
+ elseif eclim#util#Findfile('project.xml', '.;') != '' &&
+ \ eclim#util#CompilerExists('eclim_maven')
+ compiler eclim_maven
+
+ " use standard jikes if available
+ elseif executable('jikes')
+ compiler jikes
+ let g:EclimMakeLCD = 0
+
+ " default to standard javac settings
+ else
+ compiler javac
+ let g:EclimMakeLCD = 0
+ endif
+endif
+
+call eclim#lang#DisableSyntasticIfValidationIsEnabled('java')
+
+" }}}
+
+" Abbreviations {{{
+
+if !exists("g:EclimLoggingDisabled") || !g:EclimLoggingDisabled
+ inoreabbrev <buffer> log log<c-r>=eclim#java#logging#LoggingInit("log")<cr>
+ inoreabbrev <buffer> logger logger<c-r>=eclim#java#logging#LoggingInit("logger")<cr>
+endif
+
+" }}}
+
+" Autocmds {{{
+
+if &ft == 'java'
+ augroup eclim_java
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#lang#UpdateSrcFile('java')
+ augroup END
+endif
+
+" }}}
+
+" Command Declarations {{{
+
+if !exists(":Validate")
+ command -nargs=0 -buffer Validate :call eclim#lang#UpdateSrcFile('java', 1)
+endif
+
+if !exists(":JavaCorrect")
+ command -buffer JavaCorrect :call eclim#java#correct#Correct()
+endif
+
+if !exists(":JavaFormat")
+ command -buffer -range JavaFormat :call eclim#java#src#Format(<line1>, <line2>)
+endif
+
+if !exists(":JavaImport")
+ command -buffer JavaImport :call eclim#java#import#Import()
+endif
+if !exists(":JavaImportOrganize")
+ command -buffer JavaImportOrganize :call eclim#java#import#OrganizeImports()
+endif
+
+if !exists(":JavaDocComment")
+ command -buffer JavaDocComment :call eclim#java#doc#Comment()
+endif
+if !exists(":JavaDocPreview")
+ command -buffer JavaDocPreview :call eclim#java#doc#Preview()
+endif
+
+if !exists(":Javadoc")
+ command -buffer -bang -nargs=*
+ \ -complete=customlist,eclim#java#doc#CommandCompleteJavadoc
+ \ Javadoc :call eclim#java#doc#Javadoc('<bang>', <q-args>)
+endif
+if exists(":Java") != 2
+ command -buffer -nargs=* Java :call eclim#java#util#Java('', <q-args>)
+endif
+if exists(":JavaClasspath") != 2
+ command -buffer -nargs=* JavaClasspath :call eclim#java#util#Classpath(<f-args>)
+endif
+if exists(":JavaListInstalls") != 2
+ command -buffer -nargs=* JavaListInstalls :call eclim#java#util#ListInstalls()
+endif
+
+if !exists(":JavaConstructor")
+ command -buffer -range=0 -bang JavaConstructor
+ \ :call eclim#java#impl#Constructor(<line1>, <line2>, '<bang>')
+endif
+
+if !exists(":JavaGet")
+ command -buffer -range -bang JavaGet
+ \ :call eclim#java#impl#GetterSetter(<line1>, <line2>, '<bang>', 'getter')
+endif
+if !exists(":JavaSet")
+ command -buffer -range -bang JavaSet
+ \ :call eclim#java#impl#GetterSetter(<line1>, <line2>, '<bang>', 'setter')
+endif
+if !exists(":JavaGetSet")
+ command -buffer -range -bang JavaGetSet
+ \ :call eclim#java#impl#GetterSetter(<line1>, <line2>, '<bang>', 'getter_setter')
+endif
+
+if !exists(":JavaImpl")
+ command -buffer JavaImpl :call eclim#java#impl#Impl()
+endif
+if !exists(":JavaDelegate")
+ command -buffer JavaDelegate :call eclim#java#impl#Delegate()
+endif
+
+if !exists(":JavaSearch")
+ command -buffer -nargs=*
+ \ -complete=customlist,eclim#java#search#CommandCompleteJavaSearch
+ \ JavaSearch :call eclim#java#search#SearchAndDisplay('java_search', '<args>')
+endif
+if !exists(":JavaSearchContext")
+ command -buffer JavaSearchContext
+ \ :call eclim#java#search#SearchAndDisplay('java_search', '')
+endif
+if !exists(":JavaDocSearch")
+ command -buffer -nargs=*
+ \ -complete=customlist,eclim#java#search#CommandCompleteJavaSearch
+ \ JavaDocSearch :call eclim#java#search#SearchAndDisplay('java_docsearch', '<args>')
+endif
+
+if !exists(":JavaCallHierarchy")
+ command -buffer -bang JavaCallHierarchy
+ \ :call eclim#lang#hierarchy#CallHierarchy(
+ \ 'java', g:EclimJavaCallHierarchyDefaultAction, '<bang>')
+endif
+
+if !exists(":JavaHierarchy")
+ command -buffer -range JavaHierarchy :call eclim#java#hierarchy#Hierarchy()
+endif
+
+if !exists(":JavaRename")
+ command -nargs=1 -buffer JavaRename :call eclim#java#refactor#Rename('<args>')
+endif
+if !exists(":JavaMove")
+ command -nargs=1 -buffer -complete=customlist,eclim#java#util#CommandCompletePackage
+ \ JavaMove :call eclim#java#refactor#Move('<args>')
+endif
+
+if !exists(":JavaLoggingInit")
+ command -buffer JavaLoggingInit :call eclim#java#logging#LoggingInit()
+endif
+
+if !exists(":JUnit")
+ command -buffer -nargs=? -bang -complete=customlist,eclim#java#junit#CommandCompleteTest
+ \ JUnit :call eclim#java#junit#JUnit('<args>', '<bang>')
+endif
+if !exists(":JUnitFindTest")
+ command -buffer JUnitFindTest :call eclim#java#junit#JUnitFindTest()
+endif
+if !exists(":JUnitResult")
+ command -buffer -nargs=? -complete=customlist,eclim#java#junit#CommandCompleteResult
+ \ JUnitResult :call eclim#java#junit#JUnitResult('<args>')
+endif
+if !exists(":JUnitImpl")
+ command -buffer JUnitImpl :call eclim#java#junit#JUnitImpl()
+endif
+
+if !exists(":Checkstyle")
+ command -nargs=0 -buffer Checkstyle :call eclim#java#src#Checkstyle()
+endif
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/javascript.vim b/vim/eclim/ftplugin/javascript.vim
@@ -0,0 +1,49 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/javascript/index.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Options {{{
+
+" tern has better auto completion than eclipse
+if &omnifunc != 'tern#Complete'
+ exec 'setlocal ' . g:EclimCompletionMethod . '=eclim#javascript#complete#CodeComplete'
+endif
+
+" }}}
+
+" Autocmds {{{
+
+augroup eclim_javascript
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#javascript#util#UpdateSrcFile(0)
+augroup END
+
+" }}}
+
+" Command Declarations {{{
+
+command! -nargs=0 -buffer Validate :call eclim#javascript#util#UpdateSrcFile(1)
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/junitresult.vim b/vim/eclim/ftplugin/junitresult.vim
@@ -0,0 +1,35 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+
+if !exists("g:tlist_junitresult_settings")
+ let g:tlist_junitresult_settings = {
+ \ 'lang': 'junitresult',
+ \ 'parse': 'eclim#taglisttoo#lang#junit#Parse',
+ \ 'tags': {'t': 'testcase', 'f': 'failure', 'o': 'output'}
+ \ }
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/log4j.vim b/vim/eclim/ftplugin/log4j.vim
@@ -0,0 +1,59 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/log4j/index.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+runtime eclim/ftplugin/java-xml.vim
+
+" Global Variables {{{
+
+if !exists("g:EclimLog4jValidate")
+ let g:EclimLog4jValidate = 1
+endif
+
+" }}}
+
+" Autocmds {{{
+
+if g:EclimLog4jValidate
+ augroup eclim_log4j_validate
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#lang#Validate('log4j', 1)
+ augroup END
+endif
+
+" disable plain xml validation.
+augroup eclim_xml
+ autocmd! BufWritePost <buffer>
+augroup END
+
+" }}}
+
+" Command Declarations {{{
+
+command! -nargs=0 -buffer Validate :call eclim#lang#Validate('log4j', 0)
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/make.vim b/vim/eclim/ftplugin/make.vim
@@ -0,0 +1,32 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Command Declarations {{{
+
+if !exists(":CProjectConfigs")
+ command -nargs=0 -buffer CProjectConfigs :call eclim#c#project#Configs()
+endif
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/mvn_pom.vim b/vim/eclim/ftplugin/mvn_pom.vim
@@ -0,0 +1,48 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" load any xml related functionality
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+
+" turn off xml validation
+augroup eclim_xml
+ autocmd! BufWritePost <buffer>
+augroup END
+
+" Global Variables {{{
+if !exists('g:EclimMavenPomClasspathUpdate')
+ let g:EclimMavenPomClasspathUpdate = 1
+endif
+" }}}
+
+" Autocmds {{{
+if g:EclimMavenPomClasspathUpdate
+ augroup eclim_mvn
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#java#maven#UpdateClasspath()
+ augroup END
+endif
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/python.vim b/vim/eclim/ftplugin/python.vim
@@ -0,0 +1,87 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/index.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+
+if !exists("g:EclimPythonValidate")
+ let g:EclimPythonValidate = 1
+endif
+
+" }}}
+
+" Options {{{
+
+exec 'setlocal ' . g:EclimCompletionMethod . '=eclim#python#complete#CodeComplete'
+
+" }}}
+
+" Autocmds {{{
+
+if g:EclimPythonValidate
+ augroup eclim_python_validate
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#python#validate#Validate(1)
+ augroup END
+endif
+
+" }}}
+
+" Command Declarations {{{
+
+if !exists(":PythonFindDefinition")
+ command -buffer PythonFindDefinition :call eclim#python#search#Find('definition')
+endif
+if !exists(":PythonSearchContext")
+ command -buffer PythonSearchContext :call eclim#python#search#SearchContext()
+endif
+
+if !exists(':PythonImportClean')
+ command -buffer PythonImportClean :call eclim#python#import#CleanImports()
+endif
+if !exists(':PythonImportSort')
+ command -buffer PythonImportSort :call eclim#python#import#SortImports()
+endif
+
+if !exists(":Validate")
+ command -nargs=0 -buffer Validate :call eclim#python#validate#Validate(0)
+endif
+if !exists(":PyLint")
+ command -nargs=0 -buffer PyLint :call eclim#python#validate#PyLint()
+endif
+
+if !exists(':DjangoTemplateOpen')
+ command -buffer DjangoTemplateOpen :call eclim#python#django#find#FindTemplate(
+ \ eclim#python#django#util#GetProjectPath(), eclim#util#GrabUri())
+endif
+if !exists(':DjangoViewOpen')
+ command -buffer DjangoViewOpen :call eclim#python#django#find#FindView(
+ \ eclim#python#django#util#GetProjectPath(), eclim#util#GrabUri())
+endif
+if !exists(':DjangoContextOpen')
+ command -buffer DjangoContextOpen :call eclim#python#django#find#ContextFind()
+endif
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/spring.vim b/vim/eclim/ftplugin/spring.vim
@@ -0,0 +1,36 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+runtime eclim/ftplugin/java-xml.vim
+
+if !exists("g:tlist_spring_settings")
+ let g:tlist_spring_settings = {
+ \ 'lang': 'spring',
+ \ 'parse': 'eclim#taglisttoo#lang#spring#Parse',
+ \ 'tags': {'i': 'import', 'a': 'alias', 'b': 'bean'}
+ \ }
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/strutsconfig.vim b/vim/eclim/ftplugin/strutsconfig.vim
@@ -0,0 +1,28 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+runtime eclim/ftplugin/java-xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/tld.vim b/vim/eclim/ftplugin/tld.vim
@@ -0,0 +1,36 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+runtime eclim/ftplugin/java-xml.vim
+
+if !exists("g:tlist_tld_settings")
+ let g:tlist_tld_settings = {
+ \ 'lang': 'tld',
+ \ 'parse': 'eclim#taglisttoo#lang#webxml#ParseTld',
+ \ 'tags': {'t': 'tag'}
+ \ }
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/webxml.vim b/vim/eclim/ftplugin/webxml.vim
@@ -0,0 +1,73 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! ftplugin/xml.vim
+runtime! indent/xml.vim
+runtime eclim/ftplugin/java-xml.vim
+
+if !exists("g:tlist_webxml_settings")
+ let g:tlist_webxml_settings = {
+ \ 'lang': 'webxml',
+ \ 'parse': 'eclim#taglisttoo#lang#webxml#ParseWebXml',
+ \ 'tags': {
+ \ 'p': 'context-param',
+ \ 'f': 'filter',
+ \ 'i': 'filter-mapping',
+ \ 'l': 'listener',
+ \ 's': 'servlet',
+ \ 'v': 'servlet-mapping'
+ \ }
+ \ }
+endif
+
+" Global Variables {{{
+
+if !exists("g:EclimWebXmlValidate")
+ let g:EclimWebXmlValidate = 1
+endif
+
+" }}}
+
+" Autocmds {{{
+
+if g:EclimWebXmlValidate
+ augroup eclim_webxml_validate
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#lang#Validate('webxml', 1)
+ augroup END
+endif
+
+" disable plain xml validation.
+augroup eclim_xml
+ autocmd! BufWritePost <buffer>
+augroup END
+
+" }}}
+
+" Command Declarations {{{
+
+command! -nargs=0 -buffer Validate :call eclim#lang#Validate('webxml', 0)
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/wsdl.vim b/vim/eclim/ftplugin/wsdl.vim
@@ -0,0 +1,37 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2010 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if !exists('g:tlist_wsdl_settings')
+ let g:tlist_wsdl_settings = {
+ \ 'lang': 'wsdl',
+ \ 'parse': 'eclim#taglisttoo#lang#wsdl#Parse',
+ \ 'tags': {
+ \ 't': 'types',
+ \ 'm': 'messages',
+ \ 'p': 'ports',
+ \ 'b': 'bindings'
+ \ }
+ \ }
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/xml.vim b/vim/eclim/ftplugin/xml.vim
@@ -0,0 +1,63 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/xml/validate.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+
+if !exists("g:EclimXmlValidate")
+ let g:EclimXmlValidate = 1
+endif
+
+" }}}
+
+" Autocmds {{{
+
+if g:EclimXmlValidate
+ augroup eclim_xml
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#xml#validate#Validate(1, '!')
+ augroup END
+endif
+
+" }}}
+
+" Command Declarations {{{
+
+if !exists(":Validate")
+ command -nargs=0 -complete=file -bang -buffer Validate
+ \ :call eclim#xml#validate#Validate(0, '<bang>')
+
+ command -nargs=? -buffer DtdDefinition
+ \ :call eclim#xml#definition#DtdDefinition('<args>')
+ command -nargs=? -buffer XsdDefinition
+ \ :call eclim#xml#definition#XsdDefinition('<args>')
+endif
+
+if !exists(":XmlFormat")
+ "command -buffer -range XmlFormat :call eclim#xml#format#Format(<line1>, <line2>)
+ command -buffer XmlFormat :call eclim#xml#format#Format()
+endif
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/xml_complete.vim b/vim/eclim/ftplugin/xml_complete.vim
@@ -0,0 +1,30 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Options {{{
+
+exec 'setlocal ' . g:EclimCompletionMethod . '=eclim#xml#complete#CodeComplete'
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/ftplugin/xsd.vim b/vim/eclim/ftplugin/xsd.vim
@@ -0,0 +1,55 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/xsd/index.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+
+if !exists("g:EclimXsdValidate")
+ let g:EclimXsdValidate = 1
+endif
+
+" }}}
+
+" Autocmds {{{
+
+if g:EclimXsdValidate
+ augroup eclim_xsd_validate
+ autocmd! BufWritePost <buffer>
+ autocmd BufWritePost <buffer> call eclim#lang#Validate('xsd', 1)
+ augroup END
+endif
+
+" disable plain xml validation.
+augroup eclim_xml
+ autocmd! BufWritePost <buffer>
+augroup END
+
+" }}}
+
+" Command Declarations {{{
+
+command! -nargs=0 -buffer Validate :call eclim#lang#Validate('xsd', 0)
+
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/indent/css.vim b/vim/eclim/indent/css.vim
@@ -0,0 +1,73 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Css indent file using IndentAnything.
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+let b:did_indent = 1
+if &indentexpr =~ 'EclimGetCssIndent' ||
+ \ (!exists('b:disableOverride') && exists('g:EclimCssIndentDisabled'))
+ finish
+endif
+
+runtime eclim/indent/indentanything.vim
+
+setlocal indentexpr=EclimGetCssIndent(v:lnum)
+setlocal indentkeys=0{,0},!^F,o,O
+
+" EclimGetCssIndent(lnum) {{{
+function! EclimGetCssIndent(lnum)
+ let adj = 0
+ let prevline = prevnonblank(a:lnum - 1)
+
+ " handle case where previous line is a multi-line comment (/* */) on one
+ " line, which IndentAnything doesn't handle properly.
+ if getline(prevline) =~ '^\s\+/\*.\{-}\*/\s*$'
+ let adj = indent(prevline)
+ endif
+
+ return IndentAnything() + adj
+endfunction " }}}
+
+" CssIndentAnythingSettings() {{{
+function! CssIndentAnythingSettings()
+ " Syntax name REs for comments and strings.
+ let b:commentRE = 'cssComment'
+ let b:lineCommentRE = 'cssComment'
+ let b:blockCommentRE = 'cssComment'
+ let b:stringRE = 'cssStringQ\(Q\)\?'
+
+ " Setup for C-style comment indentation.
+ let b:blockCommentStartRE = '/\*'
+ let b:blockCommentMiddleRE = '\*'
+ let b:blockCommentEndRE = '\*/'
+ let b:blockCommentMiddleExtra = 1
+
+ " Indent another level for each non-closed paren/'(' and brace/'{' on the
+ " previous line.
+ let b:indentTrios = [
+ \ [ '{', '', '}' ]
+ \ ]
+endfunction " }}}
+
+call CssIndentAnythingSettings()
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/indent/dtd.vim b/vim/eclim/indent/dtd.vim
@@ -0,0 +1,73 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Dtd indent file using IndentAnything.
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+let b:did_indent = 1
+if &indentexpr =~ 'EclimGetDtdIndent' ||
+ \ (!exists('b:disableOverride') && exists('g:EclimDtdIndentDisabled'))
+ finish
+endif
+
+runtime eclim/indent/indentanything.vim
+
+setlocal indentexpr=EclimGetDtdIndent(v:lnum)
+setlocal indentkeys=o,O,*<Return>,<>>,<<>
+
+" EclimGetDtdIndent(lnum) {{{
+function! EclimGetDtdIndent(lnum)
+ let adj = 0
+ " handle case where previous line is a multi-line comment (<!-- -->) on one
+ " line, which IndentAnything doesn't handle properly.
+ let prevline = prevnonblank(a:lnum - 1)
+ if getline(prevline) =~ '^\s\+<!--.\{-}-->'
+ let adj = indent(prevline)
+ endif
+ return IndentAnything() + adj
+endfunction " }}}
+
+" DtdIndentAnythingSettings() {{{
+function! DtdIndentAnythingSettings()
+ " Syntax name REs for comments and strings.
+ let b:blockCommentRE = 'dtdComment\|xmlComment'
+ let b:commentRE = b:blockCommentRE
+ let b:lineCommentRE = b:blockCommentRE
+ let b:stringRE = 'dtdString\|xmlString'
+ let b:singleQuoteStringRE = b:stringRE
+ let b:doubleQuoteStringRE = b:stringRE
+
+ setlocal comments=sr:<!--,m:-,e:-->
+ let b:blockCommentStartRE = '<!--'
+ let b:blockCommentMiddleRE = '-'
+ let b:blockCommentEndRE = '-->'
+ let b:blockCommentMiddleExtra = 2
+
+ " Indent another level for each non-closed element tag.
+ let b:indentTrios = [
+ \ [ '<\!\w', '', '>' ],
+ \ [ '(', '', ')' ],
+ \ ]
+endfunction " }}}
+
+call DtdIndentAnythingSettings()
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/indent/html.vim b/vim/eclim/indent/html.vim
@@ -0,0 +1,177 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Html indent file using IndentAnything.
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if &indentexpr =~ 'EclimGetHtmlIndent' ||
+ \ (!exists('b:disableOverride') && exists('g:EclimHtmlIndentDisabled'))
+ finish
+endif
+
+let b:disableOverride = 1
+runtime! indent/javascript.vim
+runtime! indent/css.vim
+
+setlocal indentexpr=EclimGetHtmlIndent(v:lnum)
+setlocal indentkeys+=>,},0),0},),;,0{,!^F,o,O
+
+" EclimGetHtmlIndent(lnum) {{{
+function! EclimGetHtmlIndent(lnum)
+ let line = line('.')
+ let col = line('.')
+
+ let adj = 0
+
+ let scriptstart = search('<script\>', 'bcW')
+ if scriptstart > 0
+ let scriptstart = search('>', 'cW', scriptstart)
+ let scriptend = search('</script\s*>', 'cW')
+ endif
+ call cursor(line, col)
+
+ let stylestart = search('<style\>', 'bcW')
+ if stylestart > 0
+ let stylestart = search('>', 'cW', stylestart)
+ let styleend = search('</style\s*>', 'cW')
+ endif
+ call cursor(line, col)
+
+ " Inside <script> tags... let javascript indent file do the work.
+ let line = getline(scriptstart)
+ let js_type = "type\\s*=\\s*['\"]\\(text\\|application\\)/\\(java\\|ecma\\)script['\"]"
+ if scriptstart > 0 && scriptstart < a:lnum &&
+ \ (scriptend == 0 || (scriptend > scriptstart && a:lnum < scriptend)) &&
+ \ (line !~ 'type\s*=' || line =~ js_type)
+ call JavascriptIndentAnythingSettings()
+ if a:lnum == scriptstart + 1
+ let adj = &sw
+ endif
+ return EclimGetJavascriptIndent(a:lnum) + adj
+
+ " Inside <style> tags... let css indent file do the work.
+ elseif stylestart > 0 && stylestart < a:lnum &&
+ \ (styleend == 0 || (styleend > stylestart && a:lnum < styleend))
+ call CssIndentAnythingSettings()
+ if a:lnum == stylestart + 1
+ let adj = &sw
+ endif
+ return EclimGetCssIndent(a:lnum) + adj
+
+ " Indenting html code, do our work.
+ else
+ let l:Settings = exists('b:indent_settings') ?
+ \ function(b:indent_settings) : function('HtmlIndentAnythingSettings')
+ call l:Settings()
+ let adj = s:HtmlIndentAttributeWrap(a:lnum) * &sw
+
+ let prevlnum = prevnonblank(a:lnum - 1)
+ let prevline = getline(prevlnum)
+
+ " handle case where previous line is a multi-line comment (<!-- -->) on one
+ " line, which IndentAnything doesn't handle properly.
+ if prevline =~ '^\s\+<!--.\{-}-->'
+ let adj = indent(prevlnum)
+ endif
+
+ " handle <br> tags without '/>'
+ if prevline =~? '<br\s*>'
+ let line = tolower(prevline)
+ let occurrences = 0
+ while line =~ '<br\s*>'
+ let occurrences += 1
+ let line = substitute(line, '<br\s*>', '', '')
+ endwhile
+ let adj = 0 - (&sw * occurrences)
+
+ " handle <input> tags without '/>' NOTE: the '?' in this regex is to
+ " compat issues with php
+ elseif prevline =~? '<input[^/?]\{-}>' " FIXME: handle wrapped input tag
+ let adj = 0 - &sw
+ endif
+ endif
+ return IndentAnything() + adj
+endfunction " }}}
+
+" HtmlIndentAnythingSettings() {{{
+function! HtmlIndentAnythingSettings()
+ " Syntax name REs for comments and strings.
+ let b:blockCommentRE = 'htmlComment'
+ let b:commentRE = b:blockCommentRE
+ let b:stringRE = 'htmlString'
+ let b:singleQuoteStringRE = b:stringRE
+ let b:doubleQuoteStringRE = b:stringRE
+
+ " Overwrites option for other filetypes that have html indenting (eg. php)
+ "setlocal comments=sr:<!--,m:-,e:-->
+ "let b:blockCommentStartRE = '<!--'
+ "let b:blockCommentMiddleRE = '-'
+ "let b:blockCommentEndRE = '-->'
+ "let b:blockCommentMiddleExtra = 2
+
+ " Indent another level for each non-closed element tag.
+ let b:indentTrios = [
+ \ [ '<\w', '', '\(/>\|</\)' ],
+ \ ]
+
+ "let b:lineContList = [
+ " \ {'pattern' : '^<!DOCTYPE.*[^>]\s*$' },
+ " \ ]
+endfunction " }}}
+
+" HtmlIndentAttributeWrap(lnum) {{{
+" Function which indents line continued attributes an extra level for
+" readability.
+function! <SID>HtmlIndentAttributeWrap(lnum)
+ let line = line('.')
+ let col = col('.')
+ let adj = 0
+ try
+ " mover cursor to start of line to avoid matching start tag on first line
+ " of nested content.
+ call cursor(line, 1)
+ let open = search('<\w\|<!DOCTYPE', 'bW')
+ if open > 0
+ let close = search('>', 'cW')
+ if open != close
+ " continuation line
+ if close == 0 || close >= a:lnum
+ " first continuation line
+ if a:lnum == open + 1
+ return 1
+ endif
+ " additional continuation lines
+ return 0
+ endif
+
+ " line after last continuation line
+ if close != 0 && a:lnum == close + 1
+ " inner content
+ return -1
+ endif
+ endif
+ endif
+ finally
+ call cursor(line, col)
+ endtry
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/indent/htmldjango.vim b/vim/eclim/indent/htmldjango.vim
@@ -0,0 +1,62 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Django Html template indent file using IndentAnything.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if !exists('b:disableOverride') && exists('g:EclimHtmldjangoIndentDisabled')
+ finish
+endif
+
+let b:disableOverride = 1
+runtime! indent/html.vim
+
+let g:HtmlDjangoIndentOpenElements = ''
+let g:HtmlDjangoIndentMidElements = ''
+for element in g:HtmlDjangoBodyElements
+ if len(g:HtmlDjangoIndentOpenElements) > 0
+ let g:HtmlDjangoIndentOpenElements .= '\|'
+ endif
+ let g:HtmlDjangoIndentOpenElements .= element[0]
+
+ for tag in element[1:-2]
+ if len(g:HtmlDjangoIndentMidElements) > 0
+ let g:HtmlDjangoIndentMidElements .= '\|'
+ endif
+ let g:HtmlDjangoIndentMidElements .= tag
+ endfor
+endfor
+
+" HtmlDjangoIndentAnythingSettings() {{{
+function! HtmlDjangoIndentAnythingSettings()
+ call HtmlIndentAnythingSettings()
+
+ let b:indentTrios = [
+ \ [ '<\w', '', '\(/>\|</\)' ],
+ \ [ '{%\s*\%(' . g:HtmlDjangoIndentOpenElements . '\)\(\s\+.\{-}\)\?%}',
+ \ '{%\s*\%(' . g:HtmlDjangoIndentMidElements . '\)\(\s\+.\{-}\)\?%}',
+ \ '{%\s*end\w\+\s*%}' ],
+ \ ]
+endfunction " }}}
+
+let b:indent_settings = 'HtmlDjangoIndentAnythingSettings'
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/indent/htmljinja.vim b/vim/eclim/indent/htmljinja.vim
@@ -0,0 +1,73 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Jinja Html template indent file using IndentAnything.
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if !exists('b:disableOverride') && exists('g:EclimHtmljinjaIndentDisabled')
+ finish
+endif
+
+let b:disableOverride = 1
+runtime! indent/html.vim
+
+let g:HtmlJinjaIndentOpenElements = ''
+let g:HtmlJinjaIndentMidElements = ''
+for element in g:HtmlJinjaBodyElements
+ if len(g:HtmlJinjaIndentOpenElements) > 0
+ let g:HtmlJinjaIndentOpenElements .= '\|'
+ endif
+ let g:HtmlJinjaIndentOpenElements .= element[0]
+
+ for tag in element[1:-2]
+ if len(g:HtmlJinjaIndentMidElements) > 0
+ let g:HtmlJinjaIndentMidElements .= '\|'
+ endif
+ let g:HtmlJinjaIndentMidElements .= tag
+ endfor
+
+ exec 'setlocal indentkeys+==end' . element[0]
+endfor
+
+" HtmlJinjaIndentAnythingSettings() {{{
+function! HtmlJinjaIndentAnythingSettings()
+ if exists('*HtmlSettings')
+ call HtmlIndentAnythingSettings()
+ endif
+
+ let b:indentTrios = [
+ \ [ '<\w', '', '\(/>\|</\)' ],
+ \ [ '{%-\?\s*\(' . g:HtmlJinjaIndentOpenElements . '\)\(\s\+.\{-}\)\?-\?%}',
+ \ '{%-\?\s*\(' . g:HtmlJinjaIndentMidElements . '\)\(\s\+.\{-}\)\?-\?%}',
+ \ '{%-\?\s*end\w\+\s*-\?%}' ],
+ \ ]
+ if exists('b:jinja_line_statement_prefix')
+ call add(b:indentTrios, [
+ \ b:jinja_line_statement_prefix . '\s\+\(' . g:HtmlJinjaIndentOpenElements . '\)\>',
+ \ b:jinja_line_statement_prefix . '\s\+\(' . g:HtmlJinjaIndentMidElements . '\)\>',
+ \ b:jinja_line_statement_prefix . '\s\+end\w\+\>',
+ \ ])
+ endif
+endfunction " }}}
+
+let b:indent_settings = 'HtmlJinjaIndentAnythingSettings'
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/indent/indentanything.vim b/vim/eclim/indent/indentanything.vim
@@ -0,0 +1,683 @@
+"
+" Copyright 2006 Tye Zdrojewski
+"
+" Licensed under the Apache License, Version 2.0 (the "License"); you may not
+" use this file except in compliance with the License. You may obtain a copy of
+" the License at
+"
+" http://www.apache.org/licenses/LICENSE-2.0
+"
+" Unless required by applicable law or agreed to in writing, software distributed
+" under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
+" CONDITIONS OF ANY KIND, either express or implied. See the License for the
+" specific language governing permissions and limitations under the License.
+"
+"
+" Plugin:
+"
+" Indent Anything
+"
+" Version: 1.2
+"
+" Description:
+"
+" This is an indentation script that calculates the indent level based
+" on begin/end syntax pairs and line-continuation patterns. It allows one
+" to create an indent script without writing any code, taking it's
+" instruction from configurable values.
+"
+" Included with this script is Javascript indentation, an example that
+" explains the configurable values.
+"
+"
+" Installation:
+"
+" Place this file in your home directory under ~/.vim/indent/, or replace
+" the system indent/javascript.vim file to affect all users.
+"
+" Maintainer: Tye Z. < z d r o @ y a h o o . c o m >
+"
+" Customization:
+"
+" The only thing that can really be customized at this point is whether or
+" not a line is echoed explaining the indentation result. To turn this on,
+" set the following variable like so:
+"
+" let b:indent_anything_echo = 1
+"
+"
+" History:
+"
+" 1.2 - made some functions script-local to prevent naming collisions
+" - fixed some broken indentation in the middle of a block comment,
+" which showed up in Javascript indentation.
+"
+
+let s:supportedVimVersion = 700
+
+if version < s:supportedVimVersion
+ echoerr "IndentAnything only supported for Vim " . s:supportedVimVersion . " and up."
+ finish
+endif
+
+
+"
+" Initialize everything needed by this script. Only set those values that are
+" not set already.
+"
+function! s:IndentAnythingInit()
+ let b:IndentAnythingInitialized = 1
+ " Start with a regular expression that will never match. Matching
+ " will influence behavior, which the defaults should not do.
+ let s:nonMatcher = '[x]\&[^x]'
+ if !exists('b:commentRE')
+ let b:commentRE = s:nonMatcher
+ endif
+ if !exists('b:lineCommentRE')
+ let b:lineCommentRE = s:nonMatcher
+ endif
+ if !exists('b:blockCommentRE')
+ let b:blockCommentRE = s:nonMatcher
+ endif
+ if !exists('b:stringRE')
+ let b:stringRE = s:nonMatcher
+ endif
+ if !exists('b:singleQuoteStringRE')
+ let b:singleQuoteStringRE = s:nonMatcher
+ endif
+ if !exists('b:doubleQuoteStringRE')
+ let b:doubleQuoteStringRE = s:nonMatcher
+ endif
+
+ if !exists('b:blockCommentStartRE')
+ let b:blockCommentStartRE = s:nonMatcher
+ endif
+ if !exists('b:blockCommentMiddleRE')
+ let b:blockCommentMiddleRE = s:nonMatcher
+ endif
+ if !exists('b:blockCommentEndRE')
+ let b:blockCommentEndRE = s:nonMatcher
+ endif
+ if !exists('b:blockCommentMiddleExtra')
+ let b:blockCommentMiddleExtra = 0
+ endif
+
+ if !exists('b:indentTrios')
+ let b:indentTrios = []
+ endif
+ if !exists('b:lineContList')
+ let b:lineContList = []
+ endif
+
+ if !exists('b:contTraversesLineComments')
+ let b:contTraversesLineComments = 1
+ endif
+
+ if !exists('b:indent_anything_echo')
+ let b:indent_anything_echo = 0
+ endif
+endfunction
+
+function! s:SynHere()
+ return synIDattr(synID(line('.'), col('.'), 1), "name")
+endfunction
+"
+" Returns true if the cursor is currently inside a comment or a string
+"
+function! InCommentOrString()
+ let syn = synIDattr(synID(line("."), col("."), 1), "name")
+ if syn =~ b:commentRE || syn =~ b:stringRE
+ return 1
+ endif
+ return 0
+endfunction
+
+"
+" Returns true if the given line is a comment line (b:lineCommentRE)
+"
+function! s:IsLineComment(linenum)
+ let cursor = getpos('.')
+ exec a:linenum
+ normal! ^
+ let l:iscomment = 0
+ let l:syn = synIDattr(synID(line('.'), col('.'), 1), "name")
+ if l:syn =~ b:lineCommentRE " b:commentRE || l:syn =~ b:stringRE
+ let l:iscomment = 1
+ endif
+ call setpos('.', cursor)
+ return l:iscomment
+endfunction
+
+"
+" Returns true if the given line is a comment line (b:lineCommentRE)
+"
+function! s:IsComment(linenum)
+ let cursor = getpos('.')
+ exec a:linenum
+ normal! ^
+ let l:iscomment = 0
+ let l:syn = synIDattr(synID(line('.'), col('.'), 1), "name")
+ if l:syn =~ b:commentRE " b:commentRE || l:syn =~ b:stringRE
+ let l:iscomment = 1
+ endif
+ call setpos('.', cursor)
+ return l:iscomment
+endfunction
+
+"
+" Returns true if the given line is a comment line (b:lineCommentRE)
+"
+function! s:IsBlockComment(linenum)
+ let cursor = getpos('.')
+ exec a:linenum
+ normal! ^
+ let l:iscomment = 0
+ let l:syn = synIDattr(synID(line('.'), col('.'), 1), "name")
+ if l:syn =~ b:blockCommentRE " b:commentRE || l:syn =~ b:stringRE
+ let l:iscomment = 1
+ endif
+ call setpos('.', cursor)
+ return l:iscomment
+endfunction
+
+"
+" Get the first line at or on the given line that is not blank and is not a
+" comment line.
+"
+function! s:GetPrevNonBlankNonComment(begin)
+ let cursor = getpos('.')
+
+ let l:prevbegin = a:begin
+ while 1
+ let l:lnum = prevnonblank(l:prevbegin)
+ if l:lnum == 0
+ return 0
+ endif
+
+ "if s:IsLineComment(l:lnum)
+ if s:IsComment(l:lnum)
+ let l:prevbegin -= 1
+ continue
+ endif
+
+ break
+ endwhile
+
+ " Restore original cursor location
+ call setpos('.', cursor)
+ return l:lnum
+endfunction
+
+"
+" This does all the work. Does indentation for:
+"
+" - All pairs defined in b:indentTrios
+" - All line continuations in b:lineContList
+" - Block comments
+"
+function! IndentAnything()
+
+ if !exists('b:IndentAnythingInitialized')
+ call s:IndentAnythingInit()
+ endif
+
+ let adj = 0 " Adjustment
+
+ let g:lastindent = ""
+ let b:hardindent = -1
+ let currlnum = v:lnum
+ let currlnum = line('.')
+ let currline = getline(currlnum)
+ let lastline = ''
+ let prevline = ''
+
+ " Find non-blank lines above the current line.
+ let lastlnum = prevnonblank(currlnum - 1)
+ let prevlnum = prevnonblank(lastlnum - 1)
+ if lastlnum != 0
+ let lastline = getline(lastlnum)
+ endif
+ if prevlnum != 0
+ let prevline = getline(prevlnum)
+ endif
+ if b:contTraversesLineComments
+ let lastcodelnum = s:GetPrevNonBlankNonComment(currlnum - 1)
+ let prevcodelnum = s:GetPrevNonBlankNonComment(lastcodelnum - 1)
+ if lastcodelnum !=0
+ let lastcodeline = getline(lastcodelnum)
+ endif
+ endif
+
+ " Start from the first char on the line. Vim doesn't seem to consistently
+ " place the cursor there before calling the indent routines.
+ call cursor(0, 1)
+ call search('\S', 'W')
+
+ let l:cur = getpos('.')
+
+ "
+ " Call indentation adjustment functions.
+ "
+
+ "
+ " Block comments
+ "
+ let l:BlockCommentAdj = 0
+ let l:BlockCommentAdj += s:GetBlockCommentIndent(currlnum, lastlnum)
+ let adj += l:BlockCommentAdj
+
+ "
+ " Pairs
+ "
+ let b:lastclosed = { 'at' : 0 }
+ let b:pairadj = 0
+ if !l:BlockCommentAdj
+ " If we're not in the middle of a block comment (because we haven't
+ " made any adjustments for that), then process block indentation.
+ for trio in b:indentTrios
+ let b:pairadj += s:GetPairIndent(currline, lastline, lastlnum,
+ \ trio[0], trio[1], trio[2])
+ endfor
+ endif
+ let adj += b:pairadj
+
+ "
+ " Line continuations
+ "
+ let contadj = 0
+ let isBlockCommentStart = currline =~ '^\s*' . b:blockCommentStartRE
+ let isBlockCommentMid = (s:IsBlockComment(currlnum) && !isBlockCommentStart)
+ if !isBlockCommentMid
+ " If the current line is not the middle of a block comment, then
+ " process line continuations.
+ for ContRule in b:lineContList
+ if b:contTraversesLineComments "&& !isBlockCommentStart
+ let contadj = s:GetContIndent(ContRule, currline, lastcodeline, lastcodelnum, prevcodelnum)
+ else
+ let contadj = s:GetContIndent(ContRule, currline, lastline, lastlnum, prevlnum)
+ endif
+ " This is for line continuation patterns, of which there can be only
+ " one per line to indicate continuation
+ if contadj
+ break
+ endif
+ endfor
+ let adj += contadj
+ endif
+
+
+ "
+ " Find the previous indent to which we will add the adjustment
+ "
+ let prevind = indent(lastlnum)
+
+ if l:BlockCommentAdj
+ let g:lastindent .= " indent (prevblockcomment: " . prevind . " at " . lastcodelnum . ") "
+ elseif contadj && b:contTraversesLineComments
+ " If we have adjusted for line continuation, then use the indentation
+ " for the previous code line
+ let prevind = indent(lastcodelnum)
+ let g:lastindent .= " indent (prevcode: " . prevind . " at " . lastcodelnum . ") "
+
+ elseif (isBlockCommentStart || !s:IsBlockComment(currlnum)) && s:IsBlockComment(lastlnum)
+ " If this is the first line after a block comment, then add the
+ " adjustment to the line where the block comment started.
+ let prevind = s:GetPostBlockCommentIndent(lastlnum)
+ let g:lastindent .= " indent (prevblock: " . prevind . " at " . lastlnum . ") "
+
+ elseif exists("b:defaultIndentExpr")
+ let g:lastindent .= " using defaultIndentExpr (" . b:defaultIndentExpr . ") "
+ exec "let prevind = " . b:defaultIndentExpr
+ else
+ " Default to adjusting the previous line's indent.
+ let g:lastindent .= " indent (prev: " . prevind . " at " . lastlnum . ") "
+ endif
+
+ " Just in case there is no previous indent.
+ let prevind = (prevind == -1 ? 0 : prevind)
+
+ if b:indent_anything_echo
+ echom g:lastindent
+ endif
+
+ call setpos('.', l:cur)
+
+ return adj + prevind
+
+endfunction
+
+"
+" Get the adjustment for the second line of a block comment. The second line
+" will be aligned under the start of the block, even if it is not at the
+" beginning of the line. Extra adjustment (b:blockCommentMiddleExtra) will
+" be added.
+"
+function! s:GetBlockCommentIndent(CurrLNum, LastLNum)
+ let l:cursor = getpos('.')
+ let l:adj = 0
+ if a:LastLNum == searchpair(b:blockCommentStartRE, '', b:blockCommentEndRE, 'bWr')
+ \ && a:LastLNum > 0
+ let l:adj = col('.') + b:blockCommentMiddleExtra
+ normal! ^
+ let l:adj -= col('.')
+ endif
+ call setpos('.', l:cursor)
+ return l:adj
+endfunction
+
+function! s:GetPostBlockCommentIndent(LNum)
+
+ let l:cursor = getpos('.')
+ let l:ind = 0
+
+ " Find beginning of block comment containing the start of line LNum
+ exec a:LNum
+ normal! ^
+ let l:ind = indent(searchpair(b:blockCommentStartRE, '', b:blockCommentEndRE, 'bWr'))
+
+ if 1 || l:ind != 0 && b:indent_anything_echo
+ let g:lastindent = g:lastindent .
+ \ "GetBlockCommentIndent: " . l:ind
+ endif
+
+ call setpos('.', l:cursor)
+
+ "return l:ind
+ return l:ind > 0 ? l:ind : 0
+
+endfunction
+
+" EV ADDED
+" Function which determines if there are equal number of opening and closing
+" patterns on the supplied line.
+function! s:EqualPairs(Line, LNum, Head, Tail)
+ let lnum = line('.')
+ let cnum = col('.')
+ call cursor(a:LNum, 1)
+ try
+ let head_matches = search('\(' . a:Head . '\)', 'ncp', a:LNum)
+ let tail_matches = search('\(' . a:Tail . '\)', 'ncp', a:LNum)
+ if head_matches == tail_matches
+ call cursor(a:LNum, col('$'))
+ let last_head = searchpos('\(' . a:Head . '\)', 'bcn', a:LNum)
+ call cursor(a:LNum, col('$'))
+ let last_tail = searchpos('\(' . a:Tail . '\)', 'bcn', a:LNum)
+ return last_tail[1] > last_head[1]
+ endif
+ return 0
+ finally
+ call cursor(lnum, cnum)
+ endtry
+endfunction
+
+"
+" Get additional indentation based on blocks of code, as defined by the Head
+" and Tail patterns.
+"
+function! s:GetPairIndent(CurrLine, LastLine, LastLNum, Head, Mid, Tail)
+
+ let levels = 0
+ let adj = 0
+ let origcol = col(".")
+ let origline = line(".")
+
+
+ "
+ " How many levels were started on the last line? Search backwards for
+ " pair starters until we're not on the last nonblank. If the last line
+ " doesn't contain the pair-starter, then don't bother with searchpair();
+ " it's a performance bottleneck because (I think) it will always search
+ " all the way back until it finds a match or can't search any more.
+ "
+ "
+ if a:LastLine =~ a:Head
+ while 1
+ " EV ADDED
+ if s:EqualPairs(a:LastLine, a:LastLNum, a:Head, a:Tail)
+ break
+ endif
+ " END EV ADDED
+
+ "
+ " Include the limit of the search to be the last line. BIG
+ " performance booster! That also means we only have to see *if*
+ " there was a match, and not worry about where it is.
+ "
+ "let pairstart = searchpair(a:Head, a:Mid, a:Tail, 'Wb')
+ "if pairstart == 0 || pairstart != a:LastLNum
+ let pairstart = searchpair(a:Head, a:Mid, a:Tail, 'Wb', '', a:LastLNum)
+ if pairstart == 0 "|| pairstart != a:LastLNum
+ break
+ endif
+ let syn = synIDattr(synID(line("."), col("."), 1), "name")
+ " Also continue on the off chance that we find the match on the
+ " current line. This shouldn't happen, but the pattern might
+ " start with whitespace.
+ if syn =~ b:commentRE || syn =~ b:stringRE || pairstart == origline
+ continue
+ endif
+ let levels += 1
+ endwhile
+ endif
+
+ " If we aren't within a level that was started on the last line, then
+ " check how many levels were closed on the last line.
+ "
+ if levels == 0
+
+ " Move to the beginning of the last line
+ call cursor(a:LastLNum,0)
+ normal! ^
+
+ " If the line starts with an open, The close shouldn't be counted as
+ " such, because we're looking for closes that didn't start on this
+ " line.
+ if a:LastLine =~ '^\s*' . a:Head ||
+ \ (a:Mid != '' && a:LastLine =~ '^\s*' . a:Mid)
+ let levels = 1
+ endif
+
+ "
+ " Count the closes on the last line (i.e. LastLNum), stopping once
+ " we've hit comments. If the line doesn't even contain the end of the
+ " pair, don't bother with searchpair() (same aforementioned
+ " rationale).
+ "
+ if a:LastLine =~ a:Tail
+ while 1
+ "
+ " Include the limit of the search to be the last line. BIG
+ " performance booster! That also means we only have to see
+ " *if* there was a match, and not worry about where it is.
+ "
+ "let pairend = searchpair(a:Head, a:Mid, a:Tail, 'W')
+ "if pairend == 0 || a:LastLNum != pairend
+ "let pairend = searchpair(a:Head, a:Mid, a:Tail, 'W', '', a:LastLNum)
+ let pairend = searchpair(a:Head, a:Mid, a:Tail, 'W',
+ \'InCommentOrString()', a:LastLNum)
+ if pairend == 0 "|| a:LastLNum != pairend
+
+ " STARTS with a:Tail, since we already know the line
+ " matches it.
+ if b:lastclosed.at < col('.') && (
+ \ a:LastLine =~ '^\s*' . a:Tail
+ \ || (a:Mid != '' && a:LastLine =~ '^\s*' . a:Mid) )
+ let b:lastclosed = {
+ \ 'at' : col('.'),
+ \ 'head' : a:Head,
+ \ 'mid' : a:Mid,
+ \ 'tail' : a:Tail }
+ endif
+
+
+ break
+ endif
+ " This might not be needed with the expr included in the
+ " search call.
+ "let syn = synIDattr(synID(line("."), col("."), 1), "name")
+ "if syn =~ b:commentRE || syn =~ b:stringRE || syn == ''
+ " break
+ "endif
+ let levels -= 1
+
+ " Track the last close to try to match pairs that start on
+ " line continuations
+ if b:lastclosed.at < col('.')
+ let b:lastclosed = {
+ \ 'at' : col('.'),
+ \ 'head' : a:Head,
+ \ 'mid' : a:Mid,
+ \ 'tail' : a:Tail }
+ endif
+ endwhile
+ endif
+ endif
+
+ " This is redundant, as per above
+ " If the current line starts with a close, count it. It won't effect the
+ " indentation of the next line because it is the first thing on the line
+ " and won't be counted as a "close on the last line".
+ if a:CurrLine =~ '^\s*' . a:Tail
+ \ || (a:Mid != '' && a:CurrLine =~ '^\s*' . a:Mid)
+ let levels -= 1
+ endif
+
+ " Restore original cursor location
+ call cursor(origline, origcol)
+
+ let adj = &sw*levels
+ if adj != 0 && b:indent_anything_echo
+ let g:lastindent = g:lastindent .
+ \ "GetPairIndent(" . a:Head . "/" . b:lastclosed.at . "):" . adj . " "
+ endif
+
+ return adj
+
+endfunction
+
+
+function! s:GetContIndent(Rule, CurrLine, LastLine, LastLNum, PrevLNum)
+
+ let adj = 0
+ let origcol = col(".")
+ let origline = line(".")
+ let lastcont = 0
+ let prevcont = 0
+
+ let l:lastlnum = a:LastLNum
+ let l:prevlnum = a:PrevLNum
+
+ let l:preblockstart = -1
+
+ " Get the last matching line number. If the match occurs w/in a comment
+ " or string, then it's a non-match.
+ "
+ "let lastmatchlnum = search(a:Rule.pattern, 'Wb', a:PrevLNum)
+ let lastmatchlnum = search(a:Rule.pattern, 'Wb', a:LastLNum)
+ let syn = synIDattr(synID(line("."), col("."), 1), "name")
+
+ "if syn =~ b:commentRE || syn =~ b:stringRE
+ if syn =~ b:commentRE || syn =~ b:stringRE || b:lastclosed.at > 0
+ let lastmatchlnum = 0
+ endif
+
+ " Should be able to just search to the line....
+ " " Figure out the last and previous continuation status
+ " if lastmatchlnum && lastmatchlnum == a:LastLNum
+ " let lastcont = 1
+ " endif
+ if lastmatchlnum == a:LastLNum
+ let lastcont = 1
+ endif
+
+ " start checking at the start of the block that ended on the prev line
+ if b:lastclosed.at > 0
+ call cursor(a:LastLNum, b:lastclosed.at)
+ " TODO: add 'skip' to skip comments
+ let l:preblockstart = searchpair(b:lastclosed.head, b:lastclosed.mid, b:lastclosed.tail, 'bW')
+ let g:lastindent .= ' postpair ("' . b:lastclosed.head . '"): '
+ \ . l:preblockstart . '/' . col('.') . ' '
+
+ if b:contTraversesLineComments
+ let l:prevlnum = s:GetPrevNonBlankNonComment(line('.') - 1)
+ else
+ let l:prevlnum = prevnonblank(line('.') - 1)
+ endif
+ endif
+
+
+ " Get the previous matching line number. If the match occurs w/in a
+ " comment or string, then it's a non-match. Use the adjusted, local
+ " prevlnum as the limit of the search, since we don't care about matches
+ " beyond that.
+ let prevmatchlnum = search(a:Rule.pattern, 'Wb', l:prevlnum)
+
+
+ let syn = synIDattr(synID(line("."), col("."), 1), "name")
+ " Handle:
+ " if ()
+ " if () {
+ " this_line; // should not be reduced
+ "if syn =~ b:commentRE || syn =~ b:stringRE
+ if syn =~ b:commentRE || syn =~ b:stringRE
+ let prevmatchlnum = 0
+ endif
+
+ " Should be able to just search to the line....
+ " if ( lastmatchlnum && lastmatchlnum == a:PrevLNum )
+ " \ || ( prevmatchlnum && prevmatchlnum == l:prevlnum )
+ " let prevcont = 1
+ " endif
+ "
+ " If there is a previous line, it is a continued line, and we haven't
+ " already done a positive adjustment for a pair/block, then reduce.
+ " Don't undo a positive adjustment for a pair because the previous line
+ " was a continued line. That will happen after the end of the block.
+ "if prevmatchlnum == l:prevlnum && b:pairadj <= 0
+ if l:prevlnum && prevmatchlnum == l:prevlnum && b:pairadj <= 0
+ let prevcont = 1
+ endif
+
+ "echom "lastcont: " . lastcont .
+ " \ ", prevcont: " . prevcont .
+ " \ ", lastmatchlnum: " . lastmatchlnum .
+ " \ ", prevmatchlnum: " . prevmatchlnum .
+ " \ ", lastlnum: " . a:LastLNum .
+ " \ ", PrevLNum: " . a:PrevLNum
+ let firstcont = (lastcont && !prevcont)
+ let firstcont = ((lastcont && !prevcont) || (lastcont && b:pairadj))
+
+ " If we are adjusting the current line for a pair, then don't count this
+ " line as a post-continuation line. The post continuation line will be
+ " after the close of said pair.
+ let postcont = (!lastcont && prevcont)
+ "let postcont = (!lastcont && prevcont && !b:pairadj )
+
+ let g:lastindent .= 'lastcont (' . lastcont . '), prevcont (' . prevcont . ') '
+
+
+ "if firstcont && a:CurrLine !~ '^\s*{'
+ if firstcont
+ if has_key(a:Rule, 'ignore') && a:CurrLine =~ a:Rule.ignore
+ let g:lastindent .= "(ignoring '" . a:Rule.ignore . "') "
+ else
+ let adj = adj + &sw
+ endif
+ "elseif postcont && a:LastLine !~ '^\s*{' "&& !b:pairadj
+ elseif postcont
+ if has_key(a:Rule, 'ignore') && a:LastLine =~ a:Rule.ignore
+ let g:lastindent .= "(ignoring '" . a:Rule.ignore . "') "
+ else
+ let adj = adj - &sw
+ endif
+ endif
+
+ call cursor(origline, origcol)
+
+ if adj != 0 && b:indent_anything_echo
+ let g:lastindent = g:lastindent .
+ \ "GetContIndent('" . a:Rule.pattern . "'):" . adj . " "
+ endif
+ return adj
+
+endfunction
diff --git a/vim/eclim/indent/javascript.vim b/vim/eclim/indent/javascript.vim
@@ -0,0 +1,146 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Javascript indent file using IndentAnything.
+" Based on initial version developed by:
+" Tye Z. <zdro@yahoo.com>
+" The version accounts for a couple edge cases not handled in the ideal
+" manner by IndentAnything.
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+let b:did_indent = 1
+if &indentexpr =~ 'EclimGetJavascriptIndent' ||
+ \ (!exists('b:disableOverride') && exists('g:EclimJavascriptIndentDisabled'))
+ finish
+endif
+
+runtime eclim/indent/indentanything.vim
+
+setlocal indentexpr=EclimGetJavascriptIndent(v:lnum)
+setlocal indentkeys+=0),0},),;
+
+" EclimGetJavascriptIndent(lnum) {{{
+function! EclimGetJavascriptIndent(lnum)
+ let line = getline(a:lnum)
+ let prevlnum = prevnonblank(a:lnum - 1)
+ let prevline = getline(prevlnum)
+ let pattern_heads = '\(' . join(map(copy(b:indentTrios), 'v:val[0]'), '\|') . '\)'
+
+ for trio in b:indentTrios
+ " if the current line starts with any of the ending trios, then set the
+ " current line indent to the same indent as the line starting that trio.
+ if line =~ '^\s*' . trio[2]
+ let col = col('.')
+ call cursor(0, col('$'))
+
+ let matchstart = 0
+ while search(')\|}\|\]', 'bcW', line('.')) && col('.') != 1
+ let end = line[col('.') - 1]
+ let start = ''
+ for trio in b:indentTrios
+ if trio[2] == end
+ let start = trio[0]
+ break
+ endif
+ endfor
+ let matchstart = searchpair(start, '', end, 'bnW', 'InCommentOrString()')
+ if matchstart > 0 && matchstart < line('.')
+ break
+ endif
+ call cursor(0, col('.') - 1)
+ endwhile
+
+ call cursor(0, col)
+
+ if matchstart > 0
+ return indent(matchstart)
+ endif
+ endif
+ endfor
+
+ for trio in b:indentTrios
+ " if the previous line starts with any of the ending trios, then indent
+ " one level to compensate for our adjustment above.
+ if prevline =~ '^\s*' . trio[2] && prevline !~ pattern_heads . '$'
+ let col = col('.')
+ call cursor(a:lnum - 1, 1)
+ let matchstart = searchpair(trio[0], '', trio[2], 'bnW', 'InCommentOrString()')
+ call cursor(0, col)
+
+ " if the matching opener is on it's own line, then use the previous line
+ " indent.
+ if matchstart > 0 && getline(matchstart) =~ '^\s*' . trio[0]
+ return indent(prevnonblank(matchstart - 1))
+ endif
+ return indent(prevlnum)
+ endif
+ endfor
+
+ return IndentAnything()
+endfunction " }}}
+
+" JavascriptIndentAnythingSettings() {{{
+function! JavascriptIndentAnythingSettings()
+ " Syntax name REs for comments and strings.
+ let b:commentRE = 'javaScript\(Line\)\?Comment'
+ let b:lineCommentRE = 'javaScriptLineComment'
+ let b:blockCommentRE = 'javaScriptComment'
+ let b:stringRE = 'javaScript\(String\(S\|D\)\|RegexpString\|Special\)'
+ let b:singleQuoteStringRE = 'javaScriptStringS'
+ let b:doubleQuoteStringRE = 'javaScriptStringD'
+
+ " Setup for C-style comment indentation.
+ let b:blockCommentStartRE = '/\*'
+ let b:blockCommentMiddleRE = '\*'
+ let b:blockCommentEndRE = '\*/'
+ let b:blockCommentMiddleExtra = 1
+
+ " Indent another level for each non-closed paren/'(' and brace/'{' on the
+ " previous line.
+ let b:indentTrios = [
+ \ [ '(', '', ')' ],
+ \ [ '\[', '', '\]' ],
+ \ [ '{', '\(default:\|case.*:\)', '}' ]
+ \]
+
+
+ " Line continuations. Lines that are continued on the next line are
+ " if/for/while statements that are NOT followed by a '{' block and operators
+ " at the end of a line.
+ let b:lineContList = [
+ \ { 'pattern' : '^\s*\(if\|for\|while\)\s*(.*)\s*\(\(//.*\)\|/\*.*\*/\s*\)\?\_$\(\_s*{\)\@!' },
+ \ { 'pattern' : '^\s*else' . '\s*\(\(//.*\)\|/\*.*\*/\s*\)\?\_$\(\_s*{\)\@!' },
+ \ { 'pattern' : '\(+\|=\|+=\|-=\)\s*\(\(//.*\)\|/\*.*\*/\s*\)\?$' }
+ \]
+
+ " If a continued line and its continuation can have line-comments between
+ " them, then this should be true. For example,
+ "
+ " if (x)
+ " // comment here
+ " statement
+ "
+ let b:contTraversesLineComments = 1
+endfunction " }}}
+
+call JavascriptIndentAnythingSettings()
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/indent/xml.vim b/vim/eclim/indent/xml.vim
@@ -0,0 +1,169 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Xml indent file using IndentAnything.
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if &indentexpr =~ 'EclimGetXmlIndent' ||
+ \ (!exists('b:disableOverride') && exists('g:EclimXmlIndentDisabled'))
+ finish
+endif
+
+let b:did_indent = 1
+let b:disableOverride = 1
+runtime eclim/indent/indentanything.vim
+runtime! indent/dtd.vim
+
+setlocal indentexpr=EclimGetXmlIndent(v:lnum)
+setlocal indentkeys=o,O,*<Return>,<>>,<<>,/,{,}
+
+" EclimGetXmlIndent(lnum) {{{
+function! EclimGetXmlIndent(lnum)
+ let line = line('.')
+ let col = line('.')
+
+ let adj = 0
+
+ let doctypestart = search('<!DOCTYPE\>', 'bcW')
+ if doctypestart > 0
+ let doctypestart = search('\[', 'cW', doctypestart)
+ let doctypeend = search('\]>', 'cW')
+ endif
+ call cursor(line, col)
+
+ let cdatastart = search('<!\[CDATA\[', 'bcW')
+ if cdatastart > 0
+ let cdatastart = search('\[', 'cW', cdatastart)
+ let cdataend = search('\]\]>', 'cW')
+ endif
+ call cursor(line, col)
+
+ " Inside <DOCTYPE, let dtd indent do the work.
+ if doctypestart > 0 && doctypestart < a:lnum &&
+ \ (doctypeend == 0 || (doctypeend > doctypestart && a:lnum <= doctypeend))
+ if a:lnum < doctypeend
+ call DtdIndentAnythingSettings()
+ return EclimGetDtdIndent(a:lnum)
+ elseif a:lnum == doctypeend
+ return indent(a:lnum) - &sw
+ endif
+ else
+ " in a <[CDATA[ section
+ if cdatastart > 0 && cdatastart < a:lnum &&
+ \ (cdataend == 0 || (cdataend >= cdatastart && a:lnum <= cdataend))
+ " only indent if nested text looks like xml
+ if getline(a:lnum) =~ '^\s*<'
+ if a:lnum == cdatastart + 1
+ return indent(cdatastart) + &sw
+ endif
+ else
+ return indent(a:lnum)
+ endif
+
+ " make sure the closing of the CDATA lines up with the opening.
+ if a:lnum == cdataend
+ return indent(cdatastart)
+ endif
+ " make sure that tag following close of CDATA is properly indented.
+ elseif cdatastart > 0 && cdatastart < a:lnum &&
+ \ (cdataend >= cdatastart && prevnonblank(a:lnum - 1) == cdataend)
+ return indent(cdatastart) - &sw
+ endif
+
+ call XmlIndentAnythingSettings()
+ let adj = s:XmlIndentAttributeWrap(a:lnum) * &sw
+
+ " handle case where previous line is a multi-line comment (<!-- -->) on one
+ " line.
+ let prevline = prevnonblank(a:lnum - 1)
+ if getline(prevline) =~ '^\s\+<!--.\{-}-->'
+ let adj = indent(prevline)
+ endif
+
+ " handle case where comment end is on its own line.
+ if getline(line) =~ '^\s*-->'
+ let adj -= &sw
+ endif
+ endif
+
+ return IndentAnything() + adj
+endfunction " }}}
+
+" XmlIndentAnythingSettings() {{{
+function! XmlIndentAnythingSettings()
+ " Syntax name REs for comments and strings.
+ let b:blockCommentRE = 'xmlComment'
+ let b:commentRE = b:blockCommentRE
+ let b:lineCommentRE = 'xmlComment'
+ let b:stringRE = 'xmlString'
+ let b:singleQuoteStringRE = b:stringRE
+ let b:doubleQuoteStringRE = b:stringRE
+
+ setlocal comments=sr:<!--,mb:\ ,ex0:-->
+ let b:blockCommentStartRE = '<!--'
+ let b:blockCommentMiddleRE = ''
+ let b:blockCommentEndRE = '-->'
+ let b:blockCommentMiddleExtra = 2
+
+ " Indent another level for each non-closed element tag.
+ let b:indentTrios = [
+ \ [ '<\w', '', '\%(/>\|</\)' ],
+ \ ]
+endfunction " }}}
+
+" XmlIndentAttributeWrap(lnum) {{{
+" Function which indents line continued attributes an extra level for
+" readability.
+function! <SID>XmlIndentAttributeWrap(lnum)
+ let line = line('.')
+ let col = col('.')
+ let adj = 0
+ try
+ " mover cursor to start of line to avoid matching start tag on first line
+ " of nested content.
+ call cursor(line, 1)
+ let open = search('<\w\|<!DOCTYPE', 'bW')
+ if open > 0
+ let close = search('>', 'cW')
+ if open != close
+ " continuation line
+ if close == 0 || close >= a:lnum
+ " first continuation line
+ if a:lnum == open + 1
+ return 1
+ endif
+ " additional continuation lines
+ return 0
+ endif
+
+ " line after last continuation line
+ if close == prevnonblank(a:lnum - 1)
+ " inner content
+ return -1
+ endif
+ endif
+ endif
+ finally
+ call cursor(line, col)
+ endtry
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/android.vim b/vim/eclim/plugin/android.vim
@@ -0,0 +1,28 @@
+" Author: Eric Van Dewoestine
+"
+" License: {{{
+"
+" Copyright (C) 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Command Declarations {{{
+if !exists(":AndroidReload")
+ command AndroidReload :call eclim#android#Reload()
+endif
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/cproject.vim b/vim/eclim/plugin/cproject.vim
@@ -0,0 +1,31 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Command Declarations {{{
+if !exists(":CProjectConfigs")
+ command -nargs=? -complete=customlist,eclim#c#project#CommandCompleteProject
+ \ CProjectConfigs :call eclim#c#project#Configs('<args>')
+endif
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/django.vim b/vim/eclim/plugin/django.vim
@@ -0,0 +1,32 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/python/django/manage.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Command Declarations {{{
+if !exists(":DjangoManage")
+ command -nargs=+ -complete=customlist,eclim#python#django#manage#CommandCompleteManage
+ \ DjangoManage :call eclim#python#django#manage#Manage('<args>')
+endif
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/eclim.vim b/vim/eclim/plugin/eclim.vim
@@ -0,0 +1,330 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Plugin that integrates vim with the eclipse plugin eclim (ECLipse
+" IMproved).
+"
+" This plugin contains shared functions that can be used regardless of the
+" current file type being edited.
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+let g:NUMBER_TYPE = 0
+let g:STRING_TYPE = 1
+let g:FUNCREF_TYPE = 2
+let g:LIST_TYPE = 3
+let g:DICT_TYPE = 4
+let g:FLOAT_TYPE = 5
+
+if !exists("g:EclimLogLevel")
+ let g:EclimLogLevel = 4
+endif
+
+if !exists("g:EclimTraceHighlight")
+ let g:EclimTraceHighlight = "Normal"
+endif
+if !exists("g:EclimDebugHighlight")
+ let g:EclimDebugHighlight = "Normal"
+endif
+if !exists("g:EclimInfoHighlight")
+ let g:EclimInfoHighlight = "Statement"
+endif
+if !exists("g:EclimWarningHighlight")
+ let g:EclimWarningHighlight = "WarningMsg"
+endif
+if !exists("g:EclimErrorHighlight")
+ let g:EclimErrorHighlight = "Error"
+endif
+if !exists("g:EclimFatalHighlight")
+ let g:EclimFatalHighlight = "Error"
+endif
+
+if has("signs")
+ if !exists("g:EclimSignLevel")
+ let g:EclimSignLevel = 5
+ endif
+else
+ let g:EclimSignLevel = 0
+endif
+
+if !exists("g:EclimBuffersTabTracking")
+ let g:EclimBuffersTabTracking = 1
+endif
+
+if !exists("g:EclimSeparator")
+ let g:EclimSeparator = '/'
+ if has("win32") || has("win64")
+ let g:EclimSeparator = '\'
+ endif
+endif
+let g:EclimQuote = "['\"]"
+
+if !exists("g:EclimTempDir")
+ let g:EclimTempDir = expand('$TMP')
+ if g:EclimTempDir == '$TMP'
+ let g:EclimTempDir = expand('$TEMP')
+ endif
+ if g:EclimTempDir == '$TEMP' && has('unix')
+ let g:EclimTempDir = '/tmp'
+ endif
+ " FIXME: mac?
+
+ let g:EclimTempDir = substitute(g:EclimTempDir, '\', '/', 'g')
+endif
+
+if !exists("g:EclimShowCurrentError")
+ let g:EclimShowCurrentError = 1
+endif
+
+if !exists("g:EclimShowCurrentErrorBalloon")
+ let g:EclimShowCurrentErrorBalloon = 1
+endif
+
+if !exists("g:EclimValidateSortResults")
+ let g:EclimValidateSortResults = 'occurrence'
+endif
+
+if !exists("g:EclimDefaultFileOpenAction")
+ let g:EclimDefaultFileOpenAction = 'split'
+endif
+
+if !exists("g:EclimCompletionMethod")
+ let g:EclimCompletionMethod = 'completefunc'
+endif
+
+if !exists("g:EclimLocationListHeight")
+ let g:EclimLocationListHeight = 10
+endif
+
+if !exists("g:EclimMakeLCD")
+ let g:EclimMakeLCD = 1
+endif
+
+if !exists("g:EclimMakeQfFilter")
+ let g:EclimMakeQfFilter = 1
+endif
+
+if !exists("g:EclimMenus")
+ let g:EclimMenus = 1
+endif
+
+if !exists("g:EclimTemplatesDisabled")
+ " Disabled for now.
+ let g:EclimTemplatesDisabled = 1
+endif
+
+if !exists('g:EclimLargeFileEnabled')
+ let g:EclimLargeFileEnabled = 0
+endif
+if !exists('g:EclimLargeFileSize')
+ let g:EclimLargeFileSize = 5
+endif
+" }}}
+
+" Command Declarations {{{
+if !exists(":PingEclim")
+ command -nargs=? -complete=customlist,eclim#client#nailgun#CommandCompleteWorkspaces
+ \ PingEclim :call eclim#PingEclim(1, '<args>')
+endif
+if !exists(":ShutdownEclim")
+ command ShutdownEclim :call eclim#ShutdownEclim()
+endif
+if !exists(":EclimSettings")
+ command -nargs=? -complete=customlist,eclim#client#nailgun#CommandCompleteWorkspaces
+ \ EclimSettings :call eclim#Settings('<args>')
+endif
+if !exists(":EclimDisable")
+ command EclimDisable :call eclim#Disable()
+endif
+if !exists(":EclimEnable")
+ command EclimEnable :call eclim#Enable()
+endif
+if !exists(':EclimHelp')
+ command -nargs=? -complete=customlist,eclim#help#CommandCompleteTag
+ \ EclimHelp :call eclim#help#Help('<args>', 0)
+endif
+if !exists(':EclimHelpGrep')
+ command -nargs=+ EclimHelpGrep :call eclim#help#HelpGrep(<q-args>)
+endif
+
+if !exists(":RefactorUndo")
+ command RefactorUndo :call eclim#lang#UndoRedo('undo', 0)
+ command RefactorRedo :call eclim#lang#UndoRedo('redo', 0)
+ command RefactorUndoPeek :call eclim#lang#UndoRedo('undo', 1)
+ command RefactorRedoPeek :call eclim#lang#UndoRedo('redo', 1)
+endif
+
+if !exists(":Buffers")
+ command -bang Buffers :call eclim#common#buffers#Buffers('<bang>')
+ command -bang BuffersToggle :call eclim#common#buffers#BuffersToggle('<bang>')
+endif
+
+if !exists(":Only")
+ command Only :call eclim#common#buffers#Only()
+endif
+
+if !exists(":DiffLastSaved")
+ command DiffLastSaved :call eclim#common#util#DiffLastSaved()
+endif
+
+if !exists(":SwapWords")
+ command SwapWords :call eclim#common#util#SwapWords()
+endif
+if !exists(":SwapTypedArguments")
+ command SwapTypedArguments :call eclim#common#util#SwapTypedArguments()
+endif
+if !exists(":LocateFile")
+ command -nargs=? LocateFile :call eclim#common#locate#LocateFile('', '<args>')
+ command -nargs=? LocateBuffer
+ \ :call eclim#common#locate#LocateFile('', '<args>', 'buffers')
+endif
+
+if !exists(":QuickFixClear")
+ command QuickFixClear :call setqflist([]) | call eclim#display#signs#Update()
+endif
+if !exists(":LocationListClear")
+ command LocationListClear :call setloclist(0, []) | call eclim#display#signs#Update()
+endif
+
+if !exists(":Tcd")
+ command -nargs=1 -complete=dir Tcd :call eclim#common#util#Tcd('<args>')
+endif
+
+if !exists(":History")
+ command History call eclim#common#history#History()
+ command -bang HistoryClear call eclim#common#history#HistoryClear('<bang>')
+endif
+
+if has('signs')
+ if !exists(":Sign")
+ command Sign :call eclim#display#signs#Toggle('user', line('.'))
+ endif
+ if !exists(":Signs")
+ command Signs :call eclim#display#signs#ViewSigns('user')
+ endif
+ if !exists(":SignClearUser")
+ command SignClearUser :call eclim#display#signs#UnplaceAll(
+ \ eclim#display#signs#GetExisting('user'))
+ endif
+ if !exists(":SignClearAll")
+ command SignClearAll :call eclim#display#signs#UnplaceAll(
+ \ eclim#display#signs#GetExisting())
+ endif
+endif
+
+if !exists(":OpenUrl")
+ command -bang -range -nargs=? OpenUrl
+ \ :call eclim#web#OpenUrl('<args>', '<bang>', <line1>, <line2>)
+endif
+
+if !exists(":Make")
+ command -bang -nargs=* Make :call eclim#util#Make('<bang>', '<args>')
+endif
+" }}}
+
+" Auto Commands{{{
+augroup eclim_archive_read
+ autocmd!
+ if exists('#archive_read')
+ autocmd! archive_read
+ endif
+ autocmd BufReadCmd
+ \ jar:/*,jar:\*,jar:file:/*,jar:file:\*,
+ \tar:/*,tar:\*,tar:file:/*,tar:file:\*,
+ \tbz2:/*,tgz:\*,tbz2:file:/*,tbz2:file:\*,
+ \tgz:/*,tgz:\*,tgz:file:/*,tgz:file:\*,
+ \zip:/*,zip:\*,zip:file:/*,zip:file:\*
+ \ call eclim#common#util#ReadFile()
+augroup END
+
+if g:EclimShowCurrentError
+ " forcing load of util, otherwise a bug in vim is sometimes triggered when
+ " searching for a pattern where the pattern is echoed twice. Reproducable
+ " by opening a new vim and searching for 't' (/t<cr>).
+ runtime eclim/autoload/eclim/util.vim
+
+ augroup eclim_show_error
+ autocmd!
+ autocmd CursorMoved * call eclim#util#ShowCurrentError()
+ augroup END
+endif
+
+if g:EclimShowCurrentErrorBalloon && has('balloon_eval')
+ set ballooneval
+ set balloonexpr=eclim#util#Balloon(eclim#util#GetLineError(line('.')))
+endif
+
+if g:EclimMakeQfFilter
+ augroup eclim_qf_filter
+ autocmd!
+ autocmd QuickFixCmdPost make
+ \ if exists('b:EclimQuickfixFilter') |
+ \ call eclim#util#SetQuickfixList(getqflist(), 'r') |
+ \ endif
+ augroup END
+endif
+
+if g:EclimSignLevel
+ augroup eclim_qf
+ autocmd WinEnter,BufWinEnter * call eclim#display#signs#Update()
+ if has('gui_running')
+ " delayed to keep the :make output on the screen for gvim
+ autocmd QuickFixCmdPost * call eclim#util#DelayedCommand(
+ \ 'call eclim#display#signs#QuickFixCmdPost()')
+ else
+ autocmd QuickFixCmdPost * call eclim#display#signs#QuickFixCmdPost()
+ endif
+ augroup END
+endif
+
+if g:EclimBuffersTabTracking && exists('*gettabvar')
+ call eclim#common#buffers#TabInit()
+ augroup eclim_buffer_tab_tracking
+ autocmd!
+ autocmd BufWinEnter,BufWinLeave * call eclim#common#buffers#TabLastOpenIn()
+ autocmd TabEnter * call eclim#common#buffers#TabEnter()
+ autocmd TabLeave * call eclim#common#buffers#TabLeave()
+ augroup END
+endif
+
+if has('gui_running') && g:EclimMenus
+ augroup eclim_menus
+ autocmd BufNewFile,BufReadPost,WinEnter * call eclim#display#menu#Generate()
+ autocmd VimEnter * if expand('<amatch>')=='' | call eclim#display#menu#Generate() | endif
+ augroup END
+endif
+
+if !g:EclimTemplatesDisabled
+ augroup eclim_template
+ autocmd!
+ autocmd BufNewFile * call eclim#common#template#Template()
+ augroup END
+endif
+
+if !exists('#LargeFile') && g:EclimLargeFileEnabled
+ augroup eclim_largefile
+ autocmd!
+ autocmd BufReadPre * call eclim#common#largefile#InitSettings()
+ augroup END
+endif
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/ftdetect.vim b/vim/eclim/plugin/ftdetect.vim
@@ -0,0 +1,101 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Vim file type detection script for eclim.
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" EclimSetXmlFileType(map) {{{
+" Sets the filetype of the current xml file to the if its root element is in the
+" supplied map.
+function! EclimSetXmlFileType(map)
+ if !exists("b:eclim_xml_filetype")
+ " cache the root element so that subsiquent calls don't need to re-examine
+ " the file.
+ if !exists("b:xmlroot")
+ let b:xmlroot = s:GetRootElement()
+ endif
+
+ if has_key(a:map, b:xmlroot)
+ let b:eclim_xml_filetype = a:map[b:xmlroot]
+ let &filetype = b:eclim_xml_filetype
+ endif
+
+ " occurs when re-opening an existing buffer.
+ elseif &ft != b:eclim_xml_filetype
+ if has_key(a:map, b:xmlroot)
+ let &filetype = a:map[b:xmlroot]
+ endif
+ endif
+endfunction " }}}
+
+" GetRootElement() {{{
+" Get the root element name.
+function! s:GetRootElement()
+ " handle case where file doesn't have xml an extension or an xml declaration
+ if expand('%:e') != 'xml' && getline(1) !~ '<?\s*xml.*?>'
+ set filetype=xml
+ endif
+
+ let root = ''
+ let element = '.\{-}<\([a-zA-Z].\{-}\)\(\s\|>\|$\).*'
+
+ " search for usage of root element (first occurence of <[a-zA-Z]).
+ let numlines = line("$")
+ let line = 1
+ let pos = getpos('.')
+ try
+ while line <= numlines
+ call cursor(line, 1)
+ let found = searchpos('<[a-zA-Z]', 'cn', line)
+ if found[0]
+ let syntaxName = synIDattr(synID(found[0], found[1], 1), "name")
+ if syntaxName == 'xmlTag'
+ let root = substitute(getline(line), element, '\1', '')
+ break
+ endif
+ endif
+ let line = line + 1
+ endwhile
+ finally
+ call setpos('.', pos)
+ endtry
+
+ " no usage, so look for doctype definition of root element
+ if root == ''
+ let linenum = search('<!DOCTYPE\s\+\_.\{-}>', 'bcnw')
+ if linenum > 0
+ let line = ''
+ while getline(linenum) !~ '>'
+ let line = line . getline(linenum)
+ let linenum += 1
+ endwhile
+ let line = line . getline(linenum)
+
+ let root = substitute(line, '.*DOCTYPE\s\+\(.\{-}\)\s\+.*', '\1', '')
+
+ return root != line ? root : ''
+ endif
+ endif
+
+ return root
+endfunction " }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/ftdetect_adt.vim b/vim/eclim/plugin/ftdetect_adt.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Vim file type detection script for eclim.
+"
+" License:
+"
+" Copyright (C) 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+autocmd BufRead *.aidl set ft=java
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/ftdetect_cdt.vim b/vim/eclim/plugin/ftdetect_cdt.vim
@@ -0,0 +1,28 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Vim file type detection script for eclim.
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+autocmd BufRead .cproject
+ \ call EclimSetXmlFileType({'cproject': 'eclipse_cproject'})
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/ftdetect_jdt.vim b/vim/eclim/plugin/ftdetect_jdt.vim
@@ -0,0 +1,55 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Vim file type detection script for eclim.
+"
+" License:
+"
+" Copyright (C) 2005 - 2014 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+let xmltypes = {
+ \ 'project': 'ant',
+ \ 'hibernate-mapping': 'hibernate',
+ \ 'beans': 'spring',
+ \ 'document': 'forrestdocument',
+ \ 'form-validation': 'commonsvalidator',
+ \ 'status': 'forreststatus',
+ \ 'testsuite': 'junitresult',
+ \ 'log4j:configuration': 'log4j'
+ \ }
+
+autocmd BufRead .classpath
+ \ call EclimSetXmlFileType({'classpath': 'eclipse_classpath'})
+autocmd BufRead ivy.xml
+ \ call EclimSetXmlFileType({'ivy-module': 'ivy'})
+autocmd BufRead pom.xml
+ \ call EclimSetXmlFileType({'project': 'mvn_pom'})
+autocmd BufRead struts-config.xml
+ \ call EclimSetXmlFileType({'struts-config': 'strutsconfig'})
+autocmd BufRead *.tld
+ \ call EclimSetXmlFileType({'taglib': 'tld'})
+autocmd BufRead *web.xml
+ \ call EclimSetXmlFileType({'web-app': 'webxml'})
+autocmd BufRead *.wsdl
+ \ call EclimSetXmlFileType({'definitions': 'wsdl', 'wsdl:definitions': 'wsdl'})
+autocmd BufRead *.xml call EclimSetXmlFileType(xmltypes)
+
+autocmd BufRead *.gant set ft=gant
+autocmd BufRead *.gst set ft=groovy_simple_template
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/java_tools.vim b/vim/eclim/plugin/java_tools.vim
@@ -0,0 +1,60 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" see http://eclim.org/vim/java/tools.html
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Autocmds {{{
+augroup eclim_java_class_read
+ autocmd!
+ autocmd BufReadCmd *.class call eclim#java#util#ReadClassPrototype()
+augroup END
+" }}}
+
+" Command Declarations {{{
+if !exists(":Jps") && executable('jps')
+ command Jps :call eclim#java#tools#Jps()
+endif
+
+if !exists(":Ant")
+ command -bang -nargs=* -complete=customlist,eclim#java#ant#complete#CommandCompleteTarget
+ \ Ant :call eclim#java#tools#MakeWithJavaBuildTool('eclim_ant', '<bang>', '<args>')
+endif
+
+if !exists(":Maven")
+ command -bang -nargs=* Maven
+ \ :call eclim#java#tools#MakeWithJavaBuildTool('eclim_maven', '<bang>', '<args>')
+endif
+if !exists(":MavenRepo")
+ command -nargs=0 -buffer
+ \ MavenRepo :call eclim#java#maven#SetClasspathVariable('Maven', 'MAVEN_REPO', '')
+endif
+if !exists(":Mvn")
+ command -bang -nargs=* Mvn
+ \ :call eclim#java#tools#MakeWithJavaBuildTool('eclim_mvn', '<bang>', '<args>')
+endif
+if !exists(":MvnRepo")
+ command -nargs=* -buffer
+ \ MvnRepo :call eclim#java#maven#SetClasspathVariable('Mvn', 'M2_REPO', '<args>')
+endif
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/project.vim b/vim/eclim/plugin/project.vim
@@ -0,0 +1,209 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Global Variables {{{
+if !exists("g:EclimProjectRefreshFiles")
+ let g:EclimProjectRefreshFiles = 1
+endif
+
+if !exists("g:EclimProjectKeepLocalHistory")
+ let g:EclimProjectKeepLocalHistory = exists('g:vimplugin_running')
+endif
+
+if !exists("g:EclimProjectProblemsUpdateOnSave")
+ let g:EclimProjectProblemsUpdateOnSave = 1
+endif
+
+if !exists("g:EclimProjectProblemsUpdateOnBuild")
+ let g:EclimProjectProblemsUpdateOnBuild = 1
+endif
+
+let g:EclimProjectTreeTitle = 'ProjectTree_'
+
+if !exists('g:EclimProjectTreeAutoOpen') || exists('g:vimplugin_running')
+ let g:EclimProjectTreeAutoOpen = 0
+endif
+
+if !exists('g:EclimProjectTabTreeAutoOpen')
+ let g:EclimProjectTabTreeAutoOpen = 1
+endif
+
+if !exists('g:EclimProjectTreeExpandPathOnOpen')
+ let g:EclimProjectTreeExpandPathOnOpen = 0
+endif
+
+if !exists('g:EclimProjectTreeSharedInstance')
+ let g:EclimProjectTreeSharedInstance = 1
+endif
+
+if g:EclimProjectTreeAutoOpen && !exists('g:EclimProjectTreeAutoOpenProjects')
+ let g:EclimProjectTreeAutoOpenProjects = ['CURRENT']
+endif
+" }}}
+
+" Auto Commands {{{
+
+" w/ external vim refresh is optional, w/ embedded gvim it is mandatory
+" disabling at all though is discouraged.
+if g:EclimProjectRefreshFiles || exists('g:vimplugin_running')
+ augroup eclim_refresh_files
+ autocmd!
+ autocmd BufWritePre * call eclim#project#util#RefreshFileBootstrap()
+ augroup END
+endif
+
+if g:EclimProjectKeepLocalHistory
+ augroup eclim_history_add
+ autocmd!
+ autocmd BufWritePre * call eclim#common#history#AddHistory()
+ augroup END
+endif
+
+if g:EclimProjectTreeAutoOpen
+ augroup project_tree_autoopen
+ autocmd!
+ autocmd VimEnter *
+ \ if eclim#project#util#GetCurrentProjectRoot() != '' |
+ \ call eclim#project#tree#ProjectTree(copy(g:EclimProjectTreeAutoOpenProjects)) |
+ \ exec g:EclimProjectTreeContentWincmd |
+ \ endif
+ augroup END
+
+ autocmd BufWinEnter *
+ \ if tabpagenr() > 1 &&
+ \ !exists('t:project_tree_auto_opened') &&
+ \ !exists('g:SessionLoad') &&
+ \ eclim#project#util#GetCurrentProjectRoot() != '' |
+ \ let t:project_tree_auto_opened = 1 |
+ \ call eclim#project#tree#ProjectTree(copy(g:EclimProjectTreeAutoOpenProjects)) |
+ \ exec g:EclimProjectTreeContentWincmd |
+ \ endif
+endif
+
+autocmd SessionLoadPost * call eclim#project#tree#Restore()
+" }}}
+
+" Command Declarations {{{
+if !exists(":ProjectCreate")
+ command -nargs=+
+ \ -complete=customlist,eclim#project#util#CommandCompleteProjectCreate
+ \ ProjectCreate :call eclim#project#util#ProjectCreate('<args>')
+ command -nargs=1 -complete=dir
+ \ ProjectImport :call eclim#project#util#ProjectImport('<args>')
+ command -nargs=1
+ \ -complete=customlist,eclim#project#util#CommandCompleteProject
+ \ ProjectDelete :call eclim#project#util#ProjectDelete('<args>')
+ command -nargs=+
+ \ -complete=customlist,eclim#project#util#CommandCompleteProject
+ \ ProjectRename :call eclim#project#util#ProjectRename('<args>')
+ command -nargs=+
+ \ -complete=customlist,eclim#project#util#CommandCompleteProjectMove
+ \ ProjectMove :call eclim#project#util#ProjectMove('<args>')
+ command -nargs=*
+ \ -complete=customlist,eclim#project#util#CommandCompleteProject
+ \ ProjectRefresh :call eclim#project#util#ProjectRefresh('<args>')
+ command -nargs=?
+ \ -complete=customlist,eclim#project#util#CommandCompleteProject
+ \ ProjectBuild :call eclim#project#util#ProjectBuild('<args>')
+ command ProjectRefreshAll :call eclim#project#util#ProjectRefreshAll()
+ command ProjectCacheClear :call eclim#project#util#ClearProjectsCache()
+ command -nargs=? -complete=customlist,eclim#client#nailgun#CommandCompleteWorkspaces
+ \ ProjectList :call eclim#project#util#ProjectList('<args>')
+ command -nargs=?
+ \ -complete=customlist,eclim#project#util#CommandCompleteProject
+ \ ProjectSettings :call eclim#project#util#ProjectSettings('<args>')
+ command -nargs=?
+ \ -complete=customlist,eclim#project#util#CommandCompleteProject
+ \ ProjectInfo :call eclim#project#util#ProjectInfo('<args>')
+ command -nargs=?
+ \ -complete=customlist,eclim#project#util#CommandCompleteProject
+ \ ProjectOpen :call eclim#project#util#ProjectOpen('<args>')
+ command -nargs=?
+ \ -complete=customlist,eclim#project#util#CommandCompleteProject
+ \ ProjectClose :call eclim#project#util#ProjectClose('<args>')
+ command -nargs=?
+ \ -complete=customlist,eclim#project#util#CommandCompleteProject
+ \ ProjectNatures :call eclim#project#util#ProjectNatures('<args>')
+ command -nargs=+
+ \ -complete=customlist,eclim#project#util#CommandCompleteProjectNatureAdd
+ \ ProjectNatureAdd
+ \ :call eclim#project#util#ProjectNatureModify('add', '<args>')
+ command -nargs=+
+ \ -complete=customlist,eclim#project#util#CommandCompleteProjectNatureRemove
+ \ ProjectNatureRemove
+ \ :call eclim#project#util#ProjectNatureModify('remove', '<args>')
+endif
+
+if !exists(":ProjectProblems")
+ command -nargs=? -bang
+ \ -complete=customlist,eclim#project#util#CommandCompleteProject
+ \ ProjectProblems :call eclim#project#problems#Problems('<args>', 1, '<bang>')
+endif
+
+if !exists(":ProjectTree")
+ command -nargs=*
+ \ -complete=customlist,eclim#project#util#CommandCompleteProjectOrDirectory
+ \ ProjectTree :call eclim#project#tree#ProjectTree(<f-args>)
+ command -nargs=0 ProjectTreeToggle :call eclim#project#tree#ProjectTreeToggle()
+ command -nargs=0 ProjectsTree
+ \ :call eclim#project#tree#ProjectTree(eclim#project#util#GetProjectNames())
+ command -nargs=1
+ \ -complete=customlist,eclim#project#util#CommandCompleteProjectOrDirectory
+ \ ProjectTab :call eclim#project#util#ProjectTab('<args>')
+endif
+
+if !exists(":ProjectCD")
+ command ProjectCD :call eclim#project#util#ProjectCD(0)
+ command ProjectLCD :call eclim#project#util#ProjectCD(1)
+endif
+
+if !exists(":ProjectGrep")
+ command -nargs=+
+ \ -complete=customlist,eclim#project#util#CommandCompleteProjectRelative
+ \ ProjectGrep :call eclim#project#util#ProjectGrep('vimgrep', <q-args>)
+ command -nargs=+
+ \ -complete=customlist,eclim#project#util#CommandCompleteProjectRelative
+ \ ProjectGrepAdd :call eclim#project#util#ProjectGrep('vimgrepadd', <q-args>)
+ command -nargs=+
+ \ -complete=customlist,eclim#project#util#CommandCompleteProjectRelative
+ \ ProjectLGrep :call eclim#project#util#ProjectGrep('lvimgrep', <q-args>)
+ command -nargs=+
+ \ -complete=customlist,eclim#project#util#CommandCompleteProjectRelative
+ \ ProjectLGrepAdd :call eclim#project#util#ProjectGrep('lvimgrepadd', <q-args>)
+endif
+
+if !exists(":Todo")
+ command -nargs=0 Todo :call eclim#project#util#Todo()
+endif
+if !exists(":ProjectTodo")
+ command -nargs=0 ProjectTodo :call eclim#project#util#ProjectTodo()
+endif
+" }}}
+
+" Menu Items {{{
+"if has('gui')
+" amenu <silent> &Plugin.&eclim.Projects.List :ProjectList<cr>
+"endif
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/plugin/vimplugin.vim b/vim/eclim/plugin/vimplugin.vim
@@ -0,0 +1,38 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Setup for eclim's vimplugin (gvim in eclipse) support.
+"
+" License:
+"
+" Copyright (C) 2011 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Auto Commands{{{
+if exists('g:vimplugin_running')
+ augroup eclim_vimplugin
+ " autocommands used to work around the fact that the "unmodified" event in
+ " vim's netbean support is commentted out for some reason.
+ autocmd BufWritePost * call eclim#vimplugin#BufferWritten()
+ autocmd CursorHold,CursorHoldI * call eclim#vimplugin#BufferModified()
+ autocmd BufWinLeave * call eclim#vimplugin#BufferClosed()
+ autocmd BufEnter * call eclim#vimplugin#BufferEnter()
+ augroup END
+endif
+" }}}
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/ant.vim b/vim/eclim/syntax/ant.vim
@@ -0,0 +1,64 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Enhancement to default ant syntax file to add support for ant-contrib and
+" allow user to define list of additional tasks to be recognized.
+"
+" License:
+"
+" Copyright (C) 2005 - 2011 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" antcontrib elements
+syn keyword antElement if then else elseif for foreach switch
+syn keyword antElement throw trycatch try catch finally
+syn keyword antElement propertycopy propertyselector propertyregex var
+syn keyword antElement antcallback antfetch runtarget
+syn keyword antElement outofdate timestampselector osfamily shellscript
+syn keyword antElement pathtofileset sortlist urlencode compilewithwalls
+syn keyword antElement forget assert bool limit math post stopwatch
+syn keyword antElement inifile antclipse antserver remoteant
+
+" ant 1.7 tasks
+syn keyword antElement antversion echoxml
+" ant 1.7 resources and resource collections
+syn keyword antElement bzip2resource file gzipresource javaresource
+syn keyword antElement propertyresource string tarentry zipentry
+syn keyword antElement files first restrict resources sort tokens
+syn keyword antElement union intersect difference
+" ant 1.7 selectors
+syn keyword antElement date depend depth different filename present containsregexp
+syn keyword antElement size type modified signedselector scriptselector
+syn match antElement 'contains'
+" ant 1.7 conditions
+syn keyword antElement hasfreespace hasmethod isfailure length matches
+syn keyword antElement resourcecount resourcesmatch
+" ant 1.7 misc elements
+syn keyword antElement preserveintarget service
+
+function! s:InitUserSyntax()
+ if exists("g:AntSyntaxElements")
+ let elements = string(g:AntSyntaxElements)
+ let elements = substitute(elements, '\[\(.*\)\]', '\1', '')
+ let elements = substitute(elements, ',', '', 'g')
+ let elements = substitute(elements, "'", '', 'g')
+ exec 'syn keyword antElement ' . elements
+ endif
+endfunction
+call s:InitUserSyntax()
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/commonsvalidator.vim b/vim/eclim/syntax/commonsvalidator.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for apache commons validator files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/css.vim b/vim/eclim/syntax/css.vim
@@ -0,0 +1,47 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Extension to default css syntax to fix issues.
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+source $VIMRUNTIME/syntax/css.vim
+
+" fix issue where vim's css syntax file has issues if a curly immediately
+" follows a psudo class
+" Ex.
+" a:hover{
+" color: #fff;
+" }
+syn match cssPseudoClass ":[^ {]*" contains=cssPseudoClassId,cssUnicodeEscape
+
+" some css3 properties
+syn match cssBoxProp contained "\<border-\(\(top\|right\|bottom\|left\)-\)*radius\>"
+syn match cssBoxProp contained "\<box-shadow\>"
+syn match cssBoxProp contained "\<opacity\>"
+
+" css3 pseudo classes
+syn match cssPseudoClassId contained "\<\(root\|empty\)\>"
+syn match cssPseudoClassId contained "\<\(last\|only\)-child\>"
+syn match cssPseudoClassId contained "\<\(first\|last\|only\)-of-type\>"
+syn match cssPseudoClassId contained "\<nth-\(child\|last-child\|of-type\|last-of-type\)\>(\s*\(odd\|even\|[-+]\?\s*\d\+\(\s*n\(\s*[-+]\?\s*\d\+\)\?\)\?\)\s*)"
+syn region cssPseudoClassId contained start="\<not\>(" end=")" contains=cssPseudoClassId
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/eclimhelp.vim b/vim/eclim/syntax/eclimhelp.vim
@@ -0,0 +1,29 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for eclim help files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+source $VIMRUNTIME/syntax/help.vim
+
+syn region helpExample matchgroup=helpIgnore start=" >$" start="^>$" end="^[^ \t]"me=e-1 end="^\s*<$"
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/eclipse_classpath.vim b/vim/eclim/syntax/eclipse_classpath.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for eclipse .classpath files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/eclipse_cproject.vim b/vim/eclim/syntax/eclipse_cproject.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for eclipse cd .cproject files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/forrestdocument.vim b/vim/eclim/syntax/forrestdocument.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for forrest document xml files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/forreststatus.vim b/vim/eclim/syntax/forreststatus.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for forrest status xml files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/gant.vim b/vim/eclim/syntax/gant.vim
@@ -0,0 +1,33 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for gant build files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" set allowing of cpp keywords if only to prevent valid 'delete' task from
+" displaying as an error.
+let groovy_allow_cpp_keywords = 1
+
+runtime! syntax/groovy.vim
+
+hi link groovyUserLabel Normal
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/groovy_simple_template.vim b/vim/eclim/syntax/groovy_simple_template.vim
@@ -0,0 +1,31 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for template files using groovy's simple template syntax.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+syn region groovySimpleTemplateSection start="<%" end="%>"
+syn match groovySimpleTemplateVariable '\${.\{-}}'
+
+hi link groovySimpleTemplateSection Statement
+hi link groovySimpleTemplateVariable Constant
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/hg.vim b/vim/eclim/syntax/hg.vim
@@ -0,0 +1,48 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for hg commit messages.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+if exists("b:current_syntax")
+ finish
+endif
+
+if has("spell")
+ syn spell toplevel
+endif
+syn match hgComment '^HG:.*' contains=@NoSpell
+syn match hgModified '^HG: changed .*$' contained containedin=hgComment contains=@NoSpell
+syn match hgProperty '^HG: \(user:\|branch\|added\|changed\|removed\)'hs=s+3 contained containedin=hgComment nextgroup=hgPropertyValue contains=@NoSpell
+syn match hgPropertyValue '.*' contained contains=@NoSpell
+syn match hgAction '^HG: \(added\|changed\|removed\)'hs=s+3 contained containedin=hgComment contains=@NoSpell nextgroup=hgFile
+syn match hgFile '.*' contained contains=@NoSpell
+
+hi link hgComment Comment
+hi link hgModified Special
+hi link hgProperty Special
+hi link hgPropertyValue Special
+hi link hgAction Special
+hi link hgFile Constant
+
+let b:current_syntax = "hg"
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/hibernate.vim b/vim/eclim/syntax/hibernate.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for hibernate mapping files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/html.vim b/vim/eclim/syntax/html.vim
@@ -0,0 +1,39 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Extension to default html syntax to support spell checking in plain html
+" text, and set syntax group for doctype to fix indenting issue w/
+" IndentAnything.
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+source $VIMRUNTIME/syntax/html.vim
+
+syn region htmlBody start="<body\>" end="</body>"me=e-7 end="</html\>"me=e-7 contains=htmlTag,htmlEndTag,htmlSpecialChar,htmlPreProc,htmlComment,htmlLink,htmlTitle,javaScript,cssStyle,@htmlPreproc,@Spell
+syn region htmlDoctype start=+<!DOCTYPE+ keepend end=+>+
+
+syn region htmlTemplate start=+<script[^>]*type=['"]text/template['"][^>]*>+ keepend end=+</script>+me=s-1 contains=htmlTag,htmlEndTag,htmlSpecialChar,htmlComment,htmlLink,javaScript
+syn clear javaScript
+syn region javaScript start=+<script\s*\(type\s*=\s*['"]\(text\|application\)/\(java\|ecma\)script['"]\)\?\s*>+ keepend end=+</script>+me=s-1 contains=@htmlJavaScript,htmlCssStyleComment,htmlScriptTag,@htmlPreproc
+
+hi link htmlDoctype Comment
+hi link javaScript Normal
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/htmldjango.vim b/vim/eclim/syntax/htmldjango.vim
@@ -0,0 +1,55 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+source $VIMRUNTIME/syntax/htmldjango.vim
+
+if !exists('g:HtmlDjangoUserTags')
+ let g:HtmlDjangoUserTags = []
+endif
+
+if !exists('g:HtmlDjangoUserFilters')
+ let g:HtmlDjangoUserFilters = []
+endif
+
+" only defined here since at least one user has a case where this syntax file
+" is loaded before ftplugin/htmldjango.vim. tags defined by setting after
+" loading of this file won't be highlighted, but this will prevent an error.
+if !exists('g:HtmlDjangoUserBodyElements')
+ let g:HtmlDjangoUserBodyElements = []
+endif
+
+syn match djangoComment "{#.*#}"
+
+if len(g:HtmlDjangoUserTags)
+ exec 'syn keyword djangoStatement ' . join(g:HtmlDjangoUserTags)
+endif
+if len(g:HtmlDjangoUserBodyElements)
+ for element in g:HtmlDjangoUserBodyElements
+ exec 'syn keyword djangoStatement ' . join(element)
+ endfor
+endif
+if len(g:HtmlDjangoUserFilters)
+ exec 'syn keyword djangoFilter ' . join(g:HtmlDjangoUserFilters)
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/ivy.vim b/vim/eclim/syntax/ivy.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for ivy's ivy.xml files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/java.vim b/vim/eclim/syntax/java.vim
@@ -0,0 +1,36 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Extension to default java syntax to fix issues or make improvements.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+source $VIMRUNTIME/syntax/java.vim
+
+" syntax now found in the latest version of java.vim
+if hlID('javaFold') == 0
+ syn region javaFold start="{" end="}" transparent fold
+ syn match javaAnnotation "@\([_$a-zA-Z][_$a-zA-Z0-9]*\.\)*[_$a-zA-Z][_$a-zA-Z0-9]*\>"
+endif
+
+" allow folding of java doc comments.
+syn region javaDocComment start="/\*\*" end="\*/" keepend contains=javaCommentTitle,@javaHtml,javaDocTags,javaDocSeeTag,javaTodo,@Spell fold
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/junitresult.vim b/vim/eclim/syntax/junitresult.vim
@@ -0,0 +1,25 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for junit result files in xml format.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
diff --git a/vim/eclim/syntax/log4j.vim b/vim/eclim/syntax/log4j.vim
@@ -0,0 +1,49 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax for log4j.xml files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+syn cluster xmlTagHook add=log4jElement
+
+syn keyword log4jElement display renderer appender category logger root categoryFactory
+syn keyword log4jElement display errorHandler param layout filter
+syn keyword log4jElement display priority level
+
+syn match log4jElement /appender-ref/
+syn match log4jElement /logger-ref/
+syn match log4jElement /root-ref/
+
+syn match log4jElement /log4j:configuration/
+syn match log4jElement /log4j:event/
+syn match log4jElement /log4j:eventSet/
+syn match log4jElement /log4j:message/
+syn match log4jElement /log4j:NDC/
+syn match log4jElement /log4j:throwable/
+syn match log4jElement /log4j:locationInfo/
+
+hi def link log4jElement Statement
+
+let b:current_syntax = "ant"
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/mvn_pom.vim b/vim/eclim/syntax/mvn_pom.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for maven 2.x pom.xml files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/mysql.vim b/vim/eclim/syntax/mysql.vim
@@ -0,0 +1,45 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Extension to default mysql syntax to add additional syntax support.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+source $VIMRUNTIME/syntax/mysql.vim
+
+syn keyword mysqlKeyword engine
+syn keyword mysqlKeyword if elseif else loop leave while
+syn keyword mysqlKeyword before close cursor each fetch open set trigger
+syn keyword mysqlKeyword begin call declare return
+syn keyword mysqlKeyword delimiter
+syn keyword mysqlKeyword truncate
+syn keyword mysqlKeyword duplicate union
+syn keyword mysqlKeyword interval
+
+syn keyword sqlTodo TODO FIXME NOTE
+
+syn match mysqlEscaped "`.\{-}`"
+
+syn region mysqlVariable start="\(NEW\|OLD\)\." end="\W"
+
+hi def link sqlComment Comment
+hi def link sqlTodo Todo
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/perl.vim b/vim/eclim/syntax/perl.vim
@@ -0,0 +1,38 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Extension to default perl syntax to support spell checking in comments and
+" plain POD syntax.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+source $VIMRUNTIME/syntax/perl.vim
+
+syn match perlComment "#.*" contains=perlTodo,@Spell
+
+if !exists("perl_include_pod")
+ if exists("perl_fold")
+ syn region perlPOD start="^=[a-z]" end="^=cut" fold contains=@Spell
+ else
+ syn region perlPOD start="^=[a-z]" end="^=cut" contains=@Spell
+ endif
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/spring.vim b/vim/eclim/syntax/spring.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for spring bean xml files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/sql.vim b/vim/eclim/syntax/sql.vim
@@ -0,0 +1,50 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Replacement of vim's sql.vim which ensures that ALL db specific syntax
+" files are sourced.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Vim syntax file loader
+if exists("b:eclim_sql_current_syntax")
+ finish
+endif
+let b:eclim_sql_current_syntax = 1
+
+" Default to the standard Vim distribution file
+let filename = 'sqloracle'
+
+" Check for overrides. Buffer variables have the highest priority.
+if exists("b:sql_type_override")
+ " Check the runtimepath to see if the file exists
+ if globpath(&runtimepath, 'syntax/' . b:sql_type_override . '.vim') != ''
+ let filename = b:sql_type_override
+ endif
+elseif exists("g:sql_type_default")
+ if globpath(&runtimepath, 'syntax/' . g:sql_type_default . '.vim') != ''
+ let filename = g:sql_type_default
+ endif
+endif
+
+" Source the appropriate files
+exec 'runtime! syntax/' . filename . '.vim'
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/strutsconfig.vim b/vim/eclim/syntax/strutsconfig.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for struts-config.xml files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/tld.vim b/vim/eclim/syntax/tld.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for taglib definition files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/webxml.vim b/vim/eclim/syntax/webxml.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for web.xml files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/wsdl.vim b/vim/eclim/syntax/wsdl.vim
@@ -0,0 +1,27 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Syntax file for wsdl files.
+"
+" License:
+"
+" Copyright (C) 2005 - 2009 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+runtime! syntax/xml.vim
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/eclim/syntax/xml.vim b/vim/eclim/syntax/xml.vim
@@ -0,0 +1,43 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Default xml.vim only defines the xmlRegion if xml folding is enabled, but
+" xmlRegion is needed to allow spell check highlighting of xml text.
+"
+" License:
+"
+" Copyright (C) 2005 - 2013 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+source $VIMRUNTIME/syntax/xml.vim
+
+" the c# syntax file loads syntax/xml.vim, but the below changes may break
+" syntax highlighting in c#
+if &ft == 'cs'
+ finish
+endif
+
+if !exists('g:xml_syntax_folding')
+ " taken from syntax/xml.vim, but removed unecessary portions.
+ syn region xmlRegion
+ \ start=+<\z([^ /!?<>"']\+\)+
+ \ skip=+<!--\_.\{-}-->+
+ \ end=+</\z1\_\s\{-}>+
+ \ contains=xmlTag,xmlEndTag,xmlCdata,xmlRegion,xmlComment,xmlEntity,xmlProcessing,@xmlRegionHook,@Spell
+endif
+
+" vim:ft=vim:fdm=marker
diff --git a/vim/plugin/eclim.vim b/vim/plugin/eclim.vim
@@ -0,0 +1,176 @@
+" Author: Eric Van Dewoestine
+"
+" Description: {{{
+" Plugin which bootstraps the eclim environment.
+"
+" License:
+"
+" Copyright (C) 2005 - 2012 Eric Van Dewoestine
+"
+" This program is free software: you can redistribute it and/or modify
+" it under the terms of the GNU General Public License as published by
+" the Free Software Foundation, either version 3 of the License, or
+" (at your option) any later version.
+"
+" This program is distributed in the hope that it will be useful,
+" but WITHOUT ANY WARRANTY; without even the implied warranty of
+" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+" GNU General Public License for more details.
+"
+" You should have received a copy of the GNU General Public License
+" along with this program. If not, see <http://www.gnu.org/licenses/>.
+"
+" }}}
+
+" Command Declarations {{{
+if !exists(":EclimValidate")
+ command EclimValidate :call <SID>Validate()
+endif
+" }}}
+
+" Script Variables {{{
+let s:required_version = 700
+" }}}
+
+" Validate() {{{
+" Validates some settings and environment values required by eclim.
+" NOTE: don't add command-line continuation characters anywhere in the
+" function, just in case the user has &compatible set.
+function! s:Validate()
+ " Check vim version.
+ if v:version < s:required_version
+ let ver = strpart(v:version, 0, 1) . '.' . strpart(v:version, 2)
+ echom "Error: Your vim version is " . ver . "."
+ echom " Eclim requires version 7.x.x"
+ return
+ endif
+
+ call s:Validate7()
+endfunction " }}}
+
+" exit early if unsupported vim version
+if v:version < s:required_version
+ finish
+endif
+
+function! s:Validate7() " {{{
+ let errors = []
+
+ " Check 'compatible' option.
+ if &compatible
+ call add(errors, "Error: You have 'compatible' set:")
+ call add(errors, " Eclim requires 'set nocompatible' in your vimrc.")
+ call add(errors, " Type \":help 'compatible'\" for more details.")
+ endif
+
+ " Check filetype support
+ redir => ftsupport
+ silent filetype
+ redir END
+ let ftsupport = substitute(ftsupport, '\n', '', 'g')
+ if ftsupport !~ 'detection:ON' || ftsupport !~ 'plugin:ON'
+ echo " "
+ let chose = 0
+ while string(chose) !~ '1\|2'
+ redraw
+ echo "Filetype plugin support looks to be disabled, but due to possible"
+ echo "language differences, please check the following line manually."
+ echo " " . ftsupport
+ echo "Does it have detection and plugin 'ON'?"
+ echo "1) Yes"
+ echo "2) No"
+ let chose = input("Please Choose (1 or 2): ")
+ endwhile
+ if chose != 1
+ call add(errors, "Error: Eclim requires filetype plugins to be enabled.")
+ call add(errors, " Please add 'filetype plugin indent on' to your vimrc.")
+ call add(errors, " Type \":help filetype-plugin-on\" for more details.")
+ endif
+ endif
+
+ " Print the results.
+ redraw
+ echohl Statement
+ if len(errors) == 0
+ echom "Result: OK, required settings are valid."
+ else
+ for error in errors
+ echom error
+ endfor
+ endif
+ echohl None
+endfunction " }}}
+
+" exit early if compatible is set or eclim is disabled.
+if &compatible || exists("g:EclimDisabled")
+ finish
+endif
+
+" EclimBaseDir() {{{
+" Gets the base directory where the eclim vim scripts are located.
+function! EclimBaseDir()
+ if !exists("g:EclimBaseDir")
+ let savewig = &wildignore
+ set wildignore=""
+ let file = findfile('plugin/eclim.vim', escape(&runtimepath, ' '))
+ let &wildignore = savewig
+
+ if file == ''
+ echoe 'Unable to determine eclim basedir. ' .
+ \ 'Please report this issue on the eclim user mailing list.'
+ let g:EclimBaseDir = ''
+ return g:EclimBaseDir
+ endif
+ let basedir = substitute(fnamemodify(file, ':p:h:h'), '\', '/', 'g')
+
+ let g:EclimBaseDir = escape(basedir, ' ')
+ endif
+
+ return g:EclimBaseDir
+endfunction " }}}
+
+function! s:Init() " {{{
+ " add eclim dir to runtime path.
+ let basedir = EclimBaseDir()
+ if basedir == ''
+ return
+ endif
+
+ exec 'set runtimepath+=' .
+ \ basedir . '/eclim,' .
+ \ basedir . '/eclim/after'
+
+ " Alternate version which inserts the eclim path just after the currently
+ " executing runtime path element and puts the eclim/after path at the very
+ " end.
+ "let paths = split(&rtp, ',')
+ "let index = 0
+ "for path in paths
+ " let index += 1
+ " if tolower(path) == tolower(basedir)
+ " break
+ " endif
+ "endfor
+
+ "let tail = paths[index :]
+
+ "for path in tail
+ " exec 'set runtimepath-=' . escape(path, ' ')
+ "endfor
+
+ "exec 'set runtimepath+=' . basedir . '/eclim'
+
+ "for path in tail
+ " exec 'set runtimepath+=' . escape(path, ' ')
+ "endfor
+
+ "exec 'set runtimepath+=' . basedir . '/eclim/after'
+
+ " need to be manually sourced
+ runtime! eclim/plugin/*.vim
+ runtime! eclim/after/plugin/*.vim
+endfunction " }}}
+
+call <SID>Init()
+
+" vim:ft=vim:fdm=marker
diff --git a/vimrc b/vimrc
@@ -72,6 +72,9 @@ let g:vimfiler_as_default_explorer = 1
" allow for F3 ro turn on Tagbar plug-in
nmap <silent> <F3> :TagbarToggle<CR>
+" run eclim
+nmap <silent> <F5> :Java<CR>
+
" set ctrl-m to launch Crunch plug-in
" allows you to do math inside of vim
map gm :Crunch<CR>
@@ -87,7 +90,7 @@ nmap [og <Plug>IndentGuidesEnable
nmap ]og <Plug>IndentGuidesDisable
" Unite plug-in mapping
-nmap <silent> <C-p> :Unite -start-insert file<cr>
+nmap <silent> <C-p> :Unite -start-insert file<CR>
" GoldenView stuff
nmap <silent> <C-o> <Plug>GoldenViewSplit
diff --git a/vimrc.bundles b/vimrc.bundles
@@ -6,7 +6,7 @@ set rtp+=~/dotfiles/vim/bundle/Vundle.vim
call vundle#rc()
" load Vundle
-Bundle 'gmarik/vundle'
+Plugin 'gmarik/Vundle.vim'
" bow down to the Tim Pope plug-ins!!
" lots of commands to change words
@@ -37,8 +37,6 @@ Bundle 'fisadev/vim-isort'
Bundle 'MatchTag'
" jump to HTML/XML tags with %
Bundle 'matchit.zip'
-" test Java code
-Bundle 'JavaRun'
" window plug-ins
" allows you to have split widows that adjust