Skip to content

Commit 886d08b

Browse files
committed
Support autoimport keywords in completion
1 parent 16c0a71 commit 886d08b

File tree

5 files changed

+131
-56
lines changed

5 files changed

+131
-56
lines changed

after/ftplugin/python.vim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,9 @@ if g:pymode_rope && g:pymode_rope_completion
4141

4242
setlocal omnifunc=pymode#rope#completions
4343

44-
exe "inoremap <silent> <buffer> " . g:pymode_rope_completion_bind . " <C-R>=pymode#rope#complete()<CR>"
44+
exe "inoremap <silent> <buffer> " . g:pymode_rope_completion_bind . " <C-R>=pymode#rope#complete(0)<CR>"
4545
if tolower(g:pymode_rope_completion_bind) == '<c-space>'
46-
exe "inoremap <silent> <buffer> <Nul> <C-R>=pymode#rope#complete()<CR>"
46+
exe "inoremap <silent> <buffer> <Nul> <C-R>=pymode#rope#complete(0)<CR>"
4747
endif
4848

4949
end

autoload/pymode/rope.vim

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@ fun! pymode#rope#completions(findstart, base)
77
PymodePython rope.completions()
88
endfunction
99

10-
fun! pymode#rope#complete()
10+
fun! pymode#rope#complete(dot)
1111
if pumvisible()
1212
return "\<C-n>"
1313
end
14-
PymodePython rope.complete()
14+
if a:dot
15+
PymodePython rope.complete(True)
16+
else
17+
PymodePython rope.complete()
18+
end
1519
return pumvisible() ? "\<C-p>\<Down>" : ""
1620
endfunction
1721

@@ -26,7 +30,7 @@ fun! pymode#rope#complete_on_dot() "{{{
2630
endif
2731
endfor
2832
endfor
29-
return pymode#rope#complete()
33+
return pymode#rope#complete(1)
3034
endfunction "}}}
3135

3236
fun! pymode#rope#goto_definition()
@@ -121,6 +125,13 @@ fun! pymode#rope#inline() "{{{
121125
PymodePython rope.InlineRefactoring().run()
122126
endfunction "}}}
123127

128+
fun! pymode#rope#move() "{{{
129+
if !pymode#save()
130+
return 0
131+
endif
132+
PymodePython rope.MoveRefactoring().run()
133+
endfunction "}}}
134+
124135
fun! pymode#rope#use_function() "{{{
125136
if !pymode#save()
126137
return 0

ftplugin/python/pymode.vim

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,9 +76,9 @@ if g:pymode_lint
7676
endif
7777

7878
if g:pymode_lint_async
79-
let &l:updatetime = g:pymode_lint_async_updatetime
80-
au! pymode BufEnter <buffer> call pymode#lint#start()
81-
au! pymode BufLeave <buffer> call pymode#lint#stop()
79+
" let &l:updatetime = g:pymode_lint_async_updatetime
80+
" au! pymode BufEnter <buffer> call pymode#lint#start()
81+
" au! pymode BufLeave <buffer> call pymode#lint#stop()
8282
end
8383

8484
endif
@@ -131,6 +131,10 @@ if g:pymode_rope
131131
exe "noremap <silent> <buffer> " . g:pymode_rope_inline_bind . " :call pymode#rope#inline()<CR>"
132132
end
133133

134+
if g:pymode_rope_move_bind != ""
135+
exe "noremap <silent> <buffer> " . g:pymode_rope_move_bind . " :call pymode#rope#move()<CR>"
136+
end
137+
134138
if g:pymode_rope_use_function_bind != ""
135139
exe "noremap <silent> <buffer> " . g:pymode_rope_use_function_bind . " :call pymode#rope#use_function()<CR>"
136140
end

plugin/pymode.vim

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,12 @@ call pymode#default('g:pymode_rope', 1)
170170
" Enable Rope completion
171171
call pymode#default('g:pymode_rope_completion', 1)
172172

173+
" Complete keywords from not imported modules (could make completion slower)
174+
call pymode#default('g:pymode_rope_autoimport', 1)
175+
176+
" Autoimported modules
177+
call pymode#default('g:pymode_rope_autoimport_modules', ['os', 'shutil', 'datetime'])
178+
173179
" Automatic completion on dot
174180
call pymode#default('g:pymode_rope_complete_on_dot', 1)
175181

@@ -209,6 +215,9 @@ call pymode#default('g:pymode_rope_extract_variable_bind', '<C-c>rl')
209215
" Inline refactoring
210216
call pymode#default('g:pymode_rope_inline_bind', '<C-c>ri')
211217

218+
" Move refactoring
219+
call pymode#default('g:pymode_rope_move_bind', '<C-c>rv')
220+
212221
" Tries to find the places in which a function can be used and changes the
213222
" code to call it instead
214223
call pymode#default('g:pymode_rope_use_function_bind', '<C-c>ru')

pymode/rope.py

Lines changed: 99 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import sys
99
import re
1010
import json
11+
import multiprocessing
1112
from .utils import (
1213
message, PY2, error, pymode_input, pymode_inputlist, pymode_y_n)
1314

@@ -19,7 +20,7 @@
1920
from rope.base import project, libutils, exceptions, change # noqa
2021
from rope.base.fscommands import FileSystemCommands # noqa
2122
from rope.contrib import autoimport, codeassist, findit # noqa
22-
from rope.refactor import ModuleToPackage, ImportOrganizer, rename, extract, inline, usefunction # noqa
23+
from rope.refactor import ModuleToPackage, ImportOrganizer, rename, extract, inline, usefunction, move # noqa
2324
from rope.base.taskhandle import TaskHandle # noqa
2425

2526

@@ -85,15 +86,15 @@ def completions():
8586
vim.command("return %s" % json.dumps(proposals))
8687

8788

88-
def complete():
89+
def complete(dot=False):
8990
""" Ctrl+Space completion.
9091
9192
:return bool: success
9293
9394
"""
9495
row, column = vim.current.window.cursor
9596
source, offset = get_assist_params((row, column))
96-
proposals = get_proporsals(source, offset)
97+
proposals = get_proporsals(source, offset, dot=dot)
9798
if not proposals:
9899
return False
99100

@@ -116,7 +117,7 @@ def complete():
116117
return True
117118

118119

119-
def get_proporsals(source, offset, base=''):
120+
def get_proporsals(source, offset, base='', dot=False):
120121
""" Code assist.
121122
122123
:return str:
@@ -136,7 +137,7 @@ def get_proporsals(source, offset, base=''):
136137
proposals = sorted(proposals, key=_sort_proporsals)
137138

138139
out = []
139-
preview = 'preview' in ctx.completeopt
140+
preview = 'preview' in ctx.options.get('completeopt')
140141
for p in proposals:
141142
out.append(dict(
142143
word=p.name,
@@ -145,6 +146,8 @@ def get_proporsals(source, offset, base=''):
145146
info=p.get_doc() or "No docs." if preview else "",
146147
))
147148

149+
out = _get_autoimport_proposals(out, ctx, source, offset, dot=dot)
150+
148151
return out
149152

150153

@@ -334,17 +337,22 @@ def __init__(self, path, project_path):
334337
update_python_path(self.project.prefs.get('python_path', []))
335338

336339
self.resource = None
337-
self.completeopt = vim.eval('&completeopt')
338340
self.options = dict(
339-
goto_definition_cmd=vim.eval('g:pymode_rope_goto_definition_cmd')
341+
completeopt=vim.eval('&completeopt'),
342+
autoimport=vim.eval('g:pymode_rope_autoimport'),
343+
autoimport_modules=vim.eval('g:pymode_rope_autoimport_modules'),
344+
goto_definition_cmd=vim.eval('g:pymode_rope_goto_definition_cmd'),
340345
)
341-
self.encoding = vim.eval('&encoding')
342346

343347
if os.path.exists("%s/__init__.py" % project_path):
344348
sys.path.append(project_path)
345349

350+
if self.options.get('autoimport') == '1':
351+
self.generate_autoimport_cache()
352+
346353
def __enter__(self):
347354
self.project.validate(self.project.root)
355+
self.options['encoding'] = vim.eval('&encoding')
348356
self.resource = libutils.path_to_resource(
349357
self.project, vim.current.buffer.name, 'file')
350358
return self
@@ -353,11 +361,19 @@ def __exit__(self, t, value, traceback):
353361
if t is None:
354362
self.project.close()
355363

356-
def generate_modules_cache(self, modules):
357-
""" Generate modules cache. """
358-
message("Generate Modules cache ...")
359-
self.importer.generate_modules_cache(modules)
360-
self.project.sync()
364+
def generate_autoimport_cache(self):
365+
""" Update autoimport cache. """
366+
367+
def _update_cache(importer, modules=None):
368+
369+
importer.generate_cache()
370+
if modules:
371+
importer.generate_modules_cache(modules)
372+
importer.project.sync()
373+
374+
process = multiprocessing.Process(target=_update_cache, args=(
375+
self.importer, self.options.get('autoimport_modules')))
376+
process.start()
361377

362378

363379
class ProgressHandler(object):
@@ -397,6 +413,7 @@ def run(self):
397413

398414
with RopeContext() as ctx:
399415
try:
416+
message(self.__doc__)
400417
refactor = self.get_refactor(ctx)
401418
input_str = self.get_input_str(refactor, ctx)
402419
if not input_str:
@@ -435,15 +452,24 @@ def get_refactor(ctx):
435452

436453
@staticmethod
437454
def get_input_str(refactor, ctx):
438-
""" Get user input. """
455+
""" Get user input. Skip by default.
439456
440-
raise NotImplementedError
457+
:return bool: True
458+
459+
"""
460+
461+
return True
441462

442463
@staticmethod
443-
def get_changes(refactor, ctx):
444-
""" Get changes. """
464+
def get_changes(refactor, input_str):
465+
""" Get changes.
445466
446-
raise NotImplementedError
467+
:return Changes:
468+
469+
"""
470+
progress = ProgressHandler('Calculate changes ...')
471+
return refactor.get_changes(
472+
input_str, task_handle=progress.handle)
447473

448474

449475
class RenameRefactoring(Refactoring):
@@ -480,18 +506,6 @@ def get_input_str(self, refactor, ctx):
480506

481507
return newname
482508

483-
@staticmethod
484-
def get_changes(refactor, input_str):
485-
""" Get changes.
486-
487-
:return Changes:
488-
489-
"""
490-
491-
progress = ProgressHandler('Calculate changes ...')
492-
return refactor.get_changes(
493-
input_str, task_handle=progress.handle)
494-
495509

496510
class ExtractMethodRefactoring(Refactoring):
497511

@@ -567,12 +581,6 @@ class InlineRefactoring(Refactoring):
567581

568582
""" Inline variable/method. """
569583

570-
@staticmethod
571-
def get_input_str(refactor, ctx):
572-
""" Return user input. """
573-
574-
return True
575-
576584
@staticmethod
577585
def get_refactor(ctx):
578586
""" Function description.
@@ -598,12 +606,6 @@ class UseFunctionRefactoring(Refactoring):
598606

599607
""" Use selected function as possible. """
600608

601-
@staticmethod
602-
def get_input_str(refactor, ctx):
603-
""" Return user input. """
604-
605-
return True
606-
607609
@staticmethod
608610
def get_refactor(ctx):
609611
""" Function description.
@@ -630,12 +632,6 @@ class ModuleToPackageRefactoring(Refactoring):
630632

631633
""" Convert module to package. """
632634

633-
@staticmethod
634-
def get_input_str(refactor, ctx):
635-
""" Return user input. """
636-
637-
return True
638-
639635
@staticmethod
640636
def get_refactor(ctx):
641637
""" Function description.
@@ -655,6 +651,33 @@ def get_changes(refactor, input_str):
655651
return refactor.get_changes()
656652

657653

654+
class MoveRefactoring(Refactoring):
655+
656+
""" Move method/module to other class/global. """
657+
658+
@staticmethod
659+
def get_input_str(refactor, ctx):
660+
""" Get destination.
661+
662+
:return str:
663+
664+
"""
665+
666+
return pymode_input('Enter destination:')
667+
668+
@staticmethod
669+
def get_refactor(ctx):
670+
""" Function description.
671+
672+
:return Rename:
673+
674+
"""
675+
_, offset = get_assist_params()
676+
if offset == 0:
677+
offset = None
678+
return move.create_move(ctx.project, ctx.resource, offset)
679+
680+
658681
def reload_changes(changes):
659682
""" Reload changed buffers. """
660683

@@ -693,3 +716,31 @@ def _get_moved_resources(changes):
693716
moved[changes.resource] = changes.new_resource
694717

695718
return moved
719+
720+
721+
def _get_autoimport_proposals(out, ctx, source, offset, dot=False):
722+
723+
if not ctx.options.get('autoimport') or dot:
724+
return out
725+
726+
if '.' in codeassist.starting_expression(source, offset):
727+
return out
728+
729+
current_offset = offset - 1
730+
while current_offset >= 0 and (
731+
source[current_offset].isalnum() or source[current_offset] == '_'):
732+
current_offset -= 1
733+
starting = source[current_offset:offset]
734+
starting = starting.strip()
735+
736+
if not starting:
737+
return out
738+
739+
for assist in ctx.importer.import_assist(starting):
740+
out.append(dict(
741+
abbr=' : '.join(assist),
742+
word=assist[0],
743+
kind='autoimport:',
744+
))
745+
746+
return out

0 commit comments

Comments
 (0)