Skip to content

Commit ac13230

Browse files
committed
Resolve autoimport after autocomplete.
1 parent af36c15 commit ac13230

File tree

5 files changed

+86
-39
lines changed

5 files changed

+86
-39
lines changed

autoload/pymode/rope.vim

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ fun! pymode#rope#complete_on_dot() "{{{
3030
endif
3131
endfor
3232
endfor
33+
if g:pymode_rope_autoimport_import_after_complete
34+
PymodePython rope.complete_check()
35+
endif
3336
return pymode#rope#complete(1)
3437
endfunction "}}}
3538

ftplugin/python/pymode.vim

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,8 @@ if g:pymode_rope
108108
if g:pymode_rope_find_it_bind != ""
109109
exe "noremap <silent> <buffer> " . g:pymode_rope_find_it_bind . " :call pymode#rope#find_it()<CR>"
110110
end
111-
if g:pymode_rope_orgazine_imports_bind != ""
112-
exe "noremap <silent> <buffer> " . g:pymode_rope_orgazine_imports_bind . " :call pymode#rope#organize_imports()<CR>"
111+
if g:pymode_rope_organize_imports_bind != ""
112+
exe "noremap <silent> <buffer> " . g:pymode_rope_organize_imports_bind . " :call pymode#rope#organize_imports()<CR>"
113113
end
114114

115115
if g:pymode_rope_rename_bind != ""
@@ -144,6 +144,10 @@ if g:pymode_rope
144144
exe "noremap <silent> <buffer> " . g:pymode_rope_module_to_package_bind . " :call pymode#rope#module_to_package()<CR>"
145145
end
146146

147+
if g:pymode_rope_autoimport_bind != ""
148+
exe "noremap <silent> <buffer> " . g:pymode_rope_autoimport_bind . " :PymodeRopeAutoImport<CR>"
149+
end
150+
147151
if g:pymode_rope_completion && g:pymode_rope_complete_on_dot
148152
inoremap <silent> <buffer> . .<C-R>=pymode#rope#complete_on_dot()<CR>
149153
end

plugin/pymode.vim

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -151,9 +151,15 @@ call pymode#default('g:pymode_rope_completion', 1)
151151
" Enable autoimport used modules
152152
call pymode#default('g:pymode_rope_autoimport', 1)
153153

154+
" Import object after complete (if that not be imported before)
155+
call pymode#default('g:pymode_rope_autoimport_import_after_complete', 1)
156+
154157
" Autoimported modules
155158
call pymode#default('g:pymode_rope_autoimport_modules', ['os', 'shutil', 'datetime'])
156159

160+
" Bind keys to autoimport module for object under cursor
161+
call pymode#default('g:pymode_rope_autoimport_bind', '<C-c>ra')
162+
157163
" Automatic completion on dot
158164
call pymode#default('g:pymode_rope_complete_on_dot', 1)
159165

@@ -173,7 +179,7 @@ call pymode#default('g:pymode_rope_show_doc_bind', '<C-c>d')
173179
call pymode#default('g:pymode_rope_find_it_bind', '<C-c>f')
174180

175181
" Bind keys for organize imports (leave empty for disable)
176-
call pymode#default('g:pymode_rope_orgazine_imports_bind', '<C-c>ro')
182+
call pymode#default('g:pymode_rope_organize_imports_bind', '<C-c>ro')
177183

178184
" Bind keys for rename variable/method/class in the project (leave empty for disable)
179185
call pymode#default('g:pymode_rope_rename_bind', '<C-c>rr')

pymode/rope.py

Lines changed: 61 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,15 @@
1010
import json
1111
import multiprocessing
1212
from .utils import (
13-
pymode_message, PY2, pymode_error, pymode_input, pymode_inputlist, pymode_y_n)
13+
pymode_message, PY2, pymode_error, pymode_input, pymode_inputlist,
14+
pymode_confirm, catch_and_print_exceptions)
1415

1516
if PY2:
1617
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'libs'))
1718
else:
1819
sys.path.insert(0, os.path.join(os.path.dirname(__file__), 'libs3'))
1920

20-
from rope.base import project, libutils, exceptions, change # noqa
21+
from rope.base import project, libutils, exceptions, change, worder # noqa
2122
from rope.base.fscommands import FileSystemCommands # noqa
2223
from rope.contrib import autoimport as rope_autoimport, codeassist, findit # noqa
2324
from rope.refactor import ModuleToPackage, ImportOrganizer, rename, extract, inline, usefunction, move # noqa
@@ -86,6 +87,7 @@ def completions():
8687
vim.command("return %s" % json.dumps(proposals))
8788

8889

90+
@catch_and_print_exceptions
8991
def complete(dot=False):
9092
""" Ctrl+Space completion.
9193
@@ -151,25 +153,15 @@ def get_proporsals(source, offset, base='', dot=False):
151153
return out
152154

153155

156+
@catch_and_print_exceptions
154157
def goto():
155158
""" Goto definition. """
156159

157160
with RopeContext() as ctx:
158161
source, offset = get_assist_params()
159-
found_resource = None
160162

161-
try:
162-
found_resource, line = codeassist.get_definition_location(
163-
ctx.project, source, offset, ctx.resource, maxfixes=3)
164-
165-
except exceptions.BadIdentifierError as e:
166-
pass
167-
168-
except Exception as e:
169-
print(e)
170-
171-
if not found_resource:
172-
return
163+
found_resource, line = codeassist.get_definition_location(
164+
ctx.project, source, offset, ctx.resource, maxfixes=3)
173165

174166
if not os.path.abspath(found_resource.path) == vim.current.buffer.name:
175167
vim.command("%s +%s %s" % (
@@ -181,6 +173,7 @@ def goto():
181173
line, int(vim.eval('indent(%s)' % line)))
182174

183175

176+
@catch_and_print_exceptions
184177
def show_doc():
185178
""" Show documentation. """
186179

@@ -275,7 +268,7 @@ def undo():
275268
pymode_error('Nothing to undo!')
276269
return False
277270

278-
if pymode_y_n(yes=False, msg='Undo [%s]?' % str(changes)):
271+
if pymode_confirm(yes=False, msg='Undo [%s]?' % str(changes)):
279272
progress = ProgressHandler('Undo %s' % str(changes))
280273
for c in ctx.project.history.undo(task_handle=progress.handle):
281274
reload_changes(c)
@@ -294,7 +287,7 @@ def redo():
294287
pymode_error('Nothing to redo!')
295288
return False
296289

297-
if pymode_y_n(yes=False, msg='Redo [%s]?' % str(changes)):
290+
if pymode_confirm(yes=False, msg='Redo [%s]?' % str(changes)):
298291
progress = ProgressHandler('Redo %s' % str(changes))
299292
for c in ctx.project.history.redo(task_handle=progress.handle):
300293
reload_changes(c)
@@ -307,13 +300,18 @@ def cache_project(cls):
307300
308301
"""
309302
projects = dict()
303+
resources = dict()
310304

311305
def get_ctx(*args, **kwargs):
312306
path = vim.current.buffer.name
307+
if resources.get(path):
308+
return resources.get(path)
309+
313310
project_path = look_ropeproject(os.path.dirname(path))
314311
ctx = projects.get(project_path)
315312
if not ctx:
316313
projects[project_path] = ctx = cls(path, project_path)
314+
resources[path] = ctx
317315
return ctx
318316
return get_ctx
319317

@@ -329,11 +327,6 @@ def autoimport():
329327
pymode_error("Should be word under cursor.")
330328
return False
331329

332-
def insert_import(name, module, ctx, source):
333-
linenum = int(ctx.importer.find_insertion_line(source))
334-
line = 'from %s insert %s' % (module, name)
335-
vim.current.buffer[linenum - 1:linenum - 1] = [line]
336-
337330
with RopeContext() as ctx:
338331
if not ctx.importer.names:
339332
ctx.generate_autoimport_cache()
@@ -344,11 +337,11 @@ def insert_import(name, module, ctx, source):
344337

345338
source, _ = get_assist_params()
346339
if len(modules) == 1:
347-
insert_import(word, modules[0], ctx, source)
340+
_insert_import(word, modules[0], ctx, source)
348341

349342
else:
350343
module = pymode_inputlist('Wich module to import:', modules)
351-
insert_import(word, module, ctx, source)
344+
_insert_import(word, module, ctx, source)
352345

353346
return True
354347

@@ -358,8 +351,6 @@ class RopeContext(object):
358351

359352
""" A context manager to have a rope project context. """
360353

361-
projects = dict()
362-
363354
def __init__(self, path, project_path):
364355

365356
self.path = path
@@ -399,15 +390,17 @@ def __exit__(self, t, value, traceback):
399390
def generate_autoimport_cache(self):
400391
""" Update autoimport cache. """
401392

402-
def _update_cache(importer, modules=None):
393+
pymode_message('Regenerate autoimport cache.')
394+
modules = self.options.get('autoimport_modules', [])
403395

396+
def _update_cache(importer, modules=None):
404397
importer.generate_cache()
405398
if modules:
406399
importer.generate_modules_cache(modules)
407400
importer.project.sync()
408401

409402
process = multiprocessing.Process(target=_update_cache, args=(
410-
self.importer, self.options.get('autoimport_modules')))
403+
self.importer, modules))
411404
process.start()
412405

413406

@@ -467,7 +460,7 @@ def run(self):
467460
print("-------------------------------")
468461
print("\n%s\n" % changes.get_description())
469462
print("-------------------------------\n\n")
470-
if not pymode_y_n(False):
463+
if not pymode_confirm(False):
471464
return False
472465

473466
progress = ProgressHandler('Apply changes ...')
@@ -762,7 +755,7 @@ def _get_autoimport_proposals(out, ctx, source, offset, dot=False):
762755
return out
763756

764757
current_offset = offset - 1
765-
while current_offset >= 0 and (
758+
while current_offset > 0 and (
766759
source[current_offset].isalnum() or source[current_offset] == '_'):
767760
current_offset -= 1
768761
starting = source[current_offset:offset]
@@ -779,3 +772,41 @@ def _get_autoimport_proposals(out, ctx, source, offset, dot=False):
779772
))
780773

781774
return out
775+
776+
777+
def complete_check():
778+
""" Function description. """
779+
780+
row, column = vim.current.window.cursor
781+
line = vim.current.buffer[row - 1]
782+
word_finder = worder.Worder(line, True)
783+
parent, name, _ = word_finder.get_splitted_primary_before(column - 1)
784+
if parent:
785+
return False
786+
787+
with RopeContext() as ctx:
788+
modules = ctx.importer.get_modules(name)
789+
790+
if not modules:
791+
return False
792+
793+
if name in ctx.project.pycore.resource_to_pyobject(ctx.resource):
794+
return False
795+
796+
if not pymode_confirm(True, "Import %s?" % name):
797+
return False
798+
799+
source, _ = get_assist_params()
800+
if len(modules) == 1:
801+
_insert_import(name, modules[0], ctx, source)
802+
803+
else:
804+
module = pymode_inputlist('With module to import:', modules)
805+
if module:
806+
_insert_import(name, module, ctx, source)
807+
808+
809+
def _insert_import(name, module, ctx, source):
810+
linenum = int(ctx.importer.find_insertion_line(source))
811+
line = 'from %s import %s' % (module, name)
812+
vim.current.buffer[linenum - 1:linenum - 1] = [line]

pymode/utils.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
""" Pymode utils. """
2+
import sys
23

3-
import vim # noqa
4-
import traceback
54
import json
6-
import sys
5+
6+
import vim # noqa
7+
78

89
PY2 = sys.version_info[0] == 2
910

@@ -26,7 +27,7 @@ def pymode_message(content):
2627
vim.command('call pymode#wide_message("%s")' % str(content))
2728

2829

29-
def pymode_y_n(yes=True, msg='Do the changes:'):
30+
def pymode_confirm(yes=True, msg='Do the changes:'):
3031
""" Confirmation.
3132
3233
:return bool:
@@ -74,7 +75,9 @@ def pymode_input(umsg, udefault='', opts=None):
7475
msg += '[%s] ' % default
7576

7677
try:
78+
vim.command('echohl Debug')
7779
input_str = vim.eval('input("%s> ")' % msg)
80+
vim.command('echohl none')
7881
except KeyboardInterrupt:
7982
input_str = ''
8083

@@ -116,7 +119,7 @@ def catch_and_print_exceptions(func):
116119
def wrapper(*args, **kwargs):
117120
try:
118121
return func(*args, **kwargs)
119-
except (Exception, vim.error): # noqa
120-
pymode_error(traceback.format_exc())
122+
except (Exception, vim.error) as e: # noqa
123+
pymode_error(e)
121124
return None
122125
return wrapper

0 commit comments

Comments
 (0)