Mercurial > hg > dotemacs
changeset 126:29cff77e2387
update elpa packges
author | Jordi Gutiérrez Hermoso <jordigh@octave.org> |
---|---|
date | Wed, 05 Aug 2015 12:01:26 -0400 |
parents | 7e4cbc0555a4 |
children | 7c2cf3608b63 |
files | elpa/company-0.8.12.signed elpa/company-0.8.12/.dir-locals.el elpa/company-0.8.12/.elpaignore elpa/company-0.8.12/ChangeLog elpa/company-0.8.12/NEWS.md elpa/company-0.8.12/README.md elpa/company-0.8.12/company-abbrev.el elpa/company-0.8.12/company-autoloads.el elpa/company-0.8.12/company-bbdb.el elpa/company-0.8.12/company-capf.el elpa/company-0.8.12/company-clang.el elpa/company-0.8.12/company-cmake.el elpa/company-0.8.12/company-css.el elpa/company-0.8.12/company-dabbrev-code.el elpa/company-0.8.12/company-dabbrev.el elpa/company-0.8.12/company-eclim.el elpa/company-0.8.12/company-elisp.el elpa/company-0.8.12/company-etags.el elpa/company-0.8.12/company-files.el elpa/company-0.8.12/company-gtags.el elpa/company-0.8.12/company-ispell.el elpa/company-0.8.12/company-keywords.el elpa/company-0.8.12/company-nxml.el elpa/company-0.8.12/company-oddmuse.el elpa/company-0.8.12/company-pkg.el elpa/company-0.8.12/company-pysmell.el elpa/company-0.8.12/company-ropemacs.el elpa/company-0.8.12/company-semantic.el elpa/company-0.8.12/company-template.el elpa/company-0.8.12/company-tempo.el elpa/company-0.8.12/company-xcode.el elpa/company-0.8.12/company-yasnippet.el elpa/company-0.8.12/company.el elpa/company-0.8.12/test/all.el elpa/company-0.8.12/test/async-tests.el elpa/company-0.8.12/test/clang-tests.el elpa/company-0.8.12/test/core-tests.el elpa/company-0.8.12/test/elisp-tests.el elpa/company-0.8.12/test/frontends-tests.el elpa/company-0.8.12/test/keywords-tests.el elpa/company-0.8.12/test/template-tests.el elpa/company-0.8.12/test/transformers-tests.el elpa/company-0.8.6/.dir-locals.el elpa/company-0.8.6/.travis.yml elpa/company-0.8.6/ChangeLog elpa/company-0.8.6/Makefile elpa/company-0.8.6/NEWS.md elpa/company-0.8.6/README.md elpa/company-0.8.6/company-abbrev.el elpa/company-0.8.6/company-autoloads.el elpa/company-0.8.6/company-bbdb.el elpa/company-0.8.6/company-capf.el elpa/company-0.8.6/company-clang.el elpa/company-0.8.6/company-cmake.el elpa/company-0.8.6/company-css.el elpa/company-0.8.6/company-dabbrev-code.el elpa/company-0.8.6/company-dabbrev.el elpa/company-0.8.6/company-eclim.el elpa/company-0.8.6/company-elisp-tests.el elpa/company-0.8.6/company-elisp.el elpa/company-0.8.6/company-etags.el elpa/company-0.8.6/company-files.el elpa/company-0.8.6/company-gtags.el elpa/company-0.8.6/company-ispell.el elpa/company-0.8.6/company-keywords.el elpa/company-0.8.6/company-nxml.el elpa/company-0.8.6/company-oddmuse.el elpa/company-0.8.6/company-pkg.el elpa/company-0.8.6/company-pysmell.el elpa/company-0.8.6/company-ropemacs.el elpa/company-0.8.6/company-semantic.el elpa/company-0.8.6/company-template.el elpa/company-0.8.6/company-tempo.el elpa/company-0.8.6/company-tests.el elpa/company-0.8.6/company-xcode.el elpa/company-0.8.6/company-yasnippet.el elpa/company-0.8.6/company.el elpa/elpy-1.5.1/LICENSE elpa/elpy-1.5.1/README.rst elpa/elpy-1.5.1/elpy-autoloads.el elpa/elpy-1.5.1/elpy-pkg.el elpa/elpy-1.5.1/elpy-refactor.el elpa/elpy-1.5.1/elpy.el elpa/elpy-1.5.1/elpy/__init__.py elpa/elpy-1.5.1/elpy/__init__.pyc elpa/elpy-1.5.1/elpy/__main__.py elpa/elpy-1.5.1/elpy/compat.py elpa/elpy-1.5.1/elpy/compat.pyc elpa/elpy-1.5.1/elpy/jedibackend.py elpa/elpy-1.5.1/elpy/jedibackend.pyc elpa/elpy-1.5.1/elpy/pydocutils.py elpa/elpy-1.5.1/elpy/pydocutils.pyc elpa/elpy-1.5.1/elpy/refactor.py elpa/elpy-1.5.1/elpy/ropebackend.py elpa/elpy-1.5.1/elpy/ropebackend.pyc elpa/elpy-1.5.1/elpy/rpc.py elpa/elpy-1.5.1/elpy/rpc.pyc elpa/elpy-1.5.1/elpy/server.py elpa/elpy-1.5.1/elpy/server.pyc elpa/elpy-1.5.1/snippets/python-mode/.yas-setup.el elpa/elpy-1.5.1/snippets/python-mode/__abs__ elpa/elpy-1.5.1/snippets/python-mode/__add__ elpa/elpy-1.5.1/snippets/python-mode/__and__ elpa/elpy-1.5.1/snippets/python-mode/__bool__ elpa/elpy-1.5.1/snippets/python-mode/__call__ elpa/elpy-1.5.1/snippets/python-mode/__cmp__ elpa/elpy-1.5.1/snippets/python-mode/__coerce__ elpa/elpy-1.5.1/snippets/python-mode/__complex__ elpa/elpy-1.5.1/snippets/python-mode/__contains__ elpa/elpy-1.5.1/snippets/python-mode/__del__ elpa/elpy-1.5.1/snippets/python-mode/__delattr__ elpa/elpy-1.5.1/snippets/python-mode/__delete__ elpa/elpy-1.5.1/snippets/python-mode/__delitem__ elpa/elpy-1.5.1/snippets/python-mode/__div__ elpa/elpy-1.5.1/snippets/python-mode/__divmod__ elpa/elpy-1.5.1/snippets/python-mode/__enter__ elpa/elpy-1.5.1/snippets/python-mode/__eq__ elpa/elpy-1.5.1/snippets/python-mode/__exit__ elpa/elpy-1.5.1/snippets/python-mode/__float__ elpa/elpy-1.5.1/snippets/python-mode/__floordiv__ elpa/elpy-1.5.1/snippets/python-mode/__ge__ elpa/elpy-1.5.1/snippets/python-mode/__get__ elpa/elpy-1.5.1/snippets/python-mode/__getattr__ elpa/elpy-1.5.1/snippets/python-mode/__getattribute__ elpa/elpy-1.5.1/snippets/python-mode/__getitem__ elpa/elpy-1.5.1/snippets/python-mode/__gt__ elpa/elpy-1.5.1/snippets/python-mode/__hash__ elpa/elpy-1.5.1/snippets/python-mode/__hex__ elpa/elpy-1.5.1/snippets/python-mode/__iadd__ elpa/elpy-1.5.1/snippets/python-mode/__iand__ elpa/elpy-1.5.1/snippets/python-mode/__idiv__ elpa/elpy-1.5.1/snippets/python-mode/__ifloordiv__ elpa/elpy-1.5.1/snippets/python-mode/__ilshift__ elpa/elpy-1.5.1/snippets/python-mode/__imod__ elpa/elpy-1.5.1/snippets/python-mode/__imul__ elpa/elpy-1.5.1/snippets/python-mode/__index__ elpa/elpy-1.5.1/snippets/python-mode/__init__ elpa/elpy-1.5.1/snippets/python-mode/__instancecheck__ elpa/elpy-1.5.1/snippets/python-mode/__int__ elpa/elpy-1.5.1/snippets/python-mode/__invert__ elpa/elpy-1.5.1/snippets/python-mode/__ior__ elpa/elpy-1.5.1/snippets/python-mode/__ipow__ elpa/elpy-1.5.1/snippets/python-mode/__irshift__ elpa/elpy-1.5.1/snippets/python-mode/__isub__ elpa/elpy-1.5.1/snippets/python-mode/__iter__ elpa/elpy-1.5.1/snippets/python-mode/__itruediv__ elpa/elpy-1.5.1/snippets/python-mode/__ixor__ elpa/elpy-1.5.1/snippets/python-mode/__le__ elpa/elpy-1.5.1/snippets/python-mode/__len__ elpa/elpy-1.5.1/snippets/python-mode/__long__ elpa/elpy-1.5.1/snippets/python-mode/__lshift__ elpa/elpy-1.5.1/snippets/python-mode/__lt__ elpa/elpy-1.5.1/snippets/python-mode/__mod__ elpa/elpy-1.5.1/snippets/python-mode/__mul__ elpa/elpy-1.5.1/snippets/python-mode/__ne__ elpa/elpy-1.5.1/snippets/python-mode/__neg__ elpa/elpy-1.5.1/snippets/python-mode/__new__ elpa/elpy-1.5.1/snippets/python-mode/__nonzero__ elpa/elpy-1.5.1/snippets/python-mode/__oct__ elpa/elpy-1.5.1/snippets/python-mode/__or__ elpa/elpy-1.5.1/snippets/python-mode/__pos__ elpa/elpy-1.5.1/snippets/python-mode/__pow__ elpa/elpy-1.5.1/snippets/python-mode/__radd__ elpa/elpy-1.5.1/snippets/python-mode/__rand__ elpa/elpy-1.5.1/snippets/python-mode/__rdivmod__ elpa/elpy-1.5.1/snippets/python-mode/__repr__ elpa/elpy-1.5.1/snippets/python-mode/__reversed__ elpa/elpy-1.5.1/snippets/python-mode/__rfloordiv__ elpa/elpy-1.5.1/snippets/python-mode/__rlshift__ elpa/elpy-1.5.1/snippets/python-mode/__rmod__ elpa/elpy-1.5.1/snippets/python-mode/__rmul__ elpa/elpy-1.5.1/snippets/python-mode/__ror__ elpa/elpy-1.5.1/snippets/python-mode/__rpow__ elpa/elpy-1.5.1/snippets/python-mode/__rrshift__ elpa/elpy-1.5.1/snippets/python-mode/__rshift__ elpa/elpy-1.5.1/snippets/python-mode/__rsub__ elpa/elpy-1.5.1/snippets/python-mode/__rtruediv__ elpa/elpy-1.5.1/snippets/python-mode/__rxor__ elpa/elpy-1.5.1/snippets/python-mode/__set__ elpa/elpy-1.5.1/snippets/python-mode/__setattr__ elpa/elpy-1.5.1/snippets/python-mode/__setitem__ elpa/elpy-1.5.1/snippets/python-mode/__slots__ elpa/elpy-1.5.1/snippets/python-mode/__str__ elpa/elpy-1.5.1/snippets/python-mode/__sub__ elpa/elpy-1.5.1/snippets/python-mode/__subclasscheck__ elpa/elpy-1.5.1/snippets/python-mode/__truediv__ elpa/elpy-1.5.1/snippets/python-mode/__unicode__ elpa/elpy-1.5.1/snippets/python-mode/__xor__ elpa/elpy-1.5.1/snippets/python-mode/ase elpa/elpy-1.5.1/snippets/python-mode/asne elpa/elpy-1.5.1/snippets/python-mode/asr elpa/elpy-1.5.1/snippets/python-mode/class elpa/elpy-1.5.1/snippets/python-mode/defs elpa/elpy-1.5.1/snippets/python-mode/enc elpa/elpy-1.5.1/snippets/python-mode/env elpa/elpy-1.5.1/snippets/python-mode/from elpa/elpy-1.5.1/snippets/python-mode/pdb elpa/elpy-1.5.1/snippets/python-mode/py3 elpa/elpy-1.5.1/snippets/python-mode/super elpa/elpy-1.8.0/LICENSE elpa/elpy-1.8.0/README.rst elpa/elpy-1.8.0/elpy-autoloads.el elpa/elpy-1.8.0/elpy-pkg.el elpa/elpy-1.8.0/elpy-refactor.el elpa/elpy-1.8.0/elpy.el elpa/elpy-1.8.0/elpy/__init__.py elpa/elpy-1.8.0/elpy/__main__.py elpa/elpy-1.8.0/elpy/compat.py elpa/elpy-1.8.0/elpy/impmagic.py elpa/elpy-1.8.0/elpy/jedibackend.py elpa/elpy-1.8.0/elpy/pydocutils.py elpa/elpy-1.8.0/elpy/refactor.py elpa/elpy-1.8.0/elpy/ropebackend.py elpa/elpy-1.8.0/elpy/rpc.py elpa/elpy-1.8.0/elpy/server.py elpa/elpy-1.8.0/snippets/python-mode/.yas-setup.el elpa/elpy-1.8.0/snippets/python-mode/__abs__ elpa/elpy-1.8.0/snippets/python-mode/__add__ elpa/elpy-1.8.0/snippets/python-mode/__and__ elpa/elpy-1.8.0/snippets/python-mode/__bool__ elpa/elpy-1.8.0/snippets/python-mode/__call__ elpa/elpy-1.8.0/snippets/python-mode/__cmp__ elpa/elpy-1.8.0/snippets/python-mode/__coerce__ elpa/elpy-1.8.0/snippets/python-mode/__complex__ elpa/elpy-1.8.0/snippets/python-mode/__contains__ elpa/elpy-1.8.0/snippets/python-mode/__del__ elpa/elpy-1.8.0/snippets/python-mode/__delattr__ elpa/elpy-1.8.0/snippets/python-mode/__delete__ elpa/elpy-1.8.0/snippets/python-mode/__delitem__ elpa/elpy-1.8.0/snippets/python-mode/__div__ elpa/elpy-1.8.0/snippets/python-mode/__divmod__ elpa/elpy-1.8.0/snippets/python-mode/__enter__ elpa/elpy-1.8.0/snippets/python-mode/__eq__ elpa/elpy-1.8.0/snippets/python-mode/__exit__ elpa/elpy-1.8.0/snippets/python-mode/__float__ elpa/elpy-1.8.0/snippets/python-mode/__floordiv__ elpa/elpy-1.8.0/snippets/python-mode/__ge__ elpa/elpy-1.8.0/snippets/python-mode/__get__ elpa/elpy-1.8.0/snippets/python-mode/__getattr__ elpa/elpy-1.8.0/snippets/python-mode/__getattribute__ elpa/elpy-1.8.0/snippets/python-mode/__getitem__ elpa/elpy-1.8.0/snippets/python-mode/__gt__ elpa/elpy-1.8.0/snippets/python-mode/__hash__ elpa/elpy-1.8.0/snippets/python-mode/__hex__ elpa/elpy-1.8.0/snippets/python-mode/__iadd__ elpa/elpy-1.8.0/snippets/python-mode/__iand__ elpa/elpy-1.8.0/snippets/python-mode/__idiv__ elpa/elpy-1.8.0/snippets/python-mode/__ifloordiv__ elpa/elpy-1.8.0/snippets/python-mode/__ilshift__ elpa/elpy-1.8.0/snippets/python-mode/__imod__ elpa/elpy-1.8.0/snippets/python-mode/__imul__ elpa/elpy-1.8.0/snippets/python-mode/__index__ elpa/elpy-1.8.0/snippets/python-mode/__init__ elpa/elpy-1.8.0/snippets/python-mode/__instancecheck__ elpa/elpy-1.8.0/snippets/python-mode/__int__ elpa/elpy-1.8.0/snippets/python-mode/__invert__ elpa/elpy-1.8.0/snippets/python-mode/__ior__ elpa/elpy-1.8.0/snippets/python-mode/__ipow__ elpa/elpy-1.8.0/snippets/python-mode/__irshift__ elpa/elpy-1.8.0/snippets/python-mode/__isub__ elpa/elpy-1.8.0/snippets/python-mode/__iter__ elpa/elpy-1.8.0/snippets/python-mode/__itruediv__ elpa/elpy-1.8.0/snippets/python-mode/__ixor__ elpa/elpy-1.8.0/snippets/python-mode/__le__ elpa/elpy-1.8.0/snippets/python-mode/__len__ elpa/elpy-1.8.0/snippets/python-mode/__long__ elpa/elpy-1.8.0/snippets/python-mode/__lshift__ elpa/elpy-1.8.0/snippets/python-mode/__lt__ elpa/elpy-1.8.0/snippets/python-mode/__mod__ elpa/elpy-1.8.0/snippets/python-mode/__mul__ elpa/elpy-1.8.0/snippets/python-mode/__ne__ elpa/elpy-1.8.0/snippets/python-mode/__neg__ elpa/elpy-1.8.0/snippets/python-mode/__new__ elpa/elpy-1.8.0/snippets/python-mode/__nonzero__ elpa/elpy-1.8.0/snippets/python-mode/__oct__ elpa/elpy-1.8.0/snippets/python-mode/__or__ elpa/elpy-1.8.0/snippets/python-mode/__pos__ elpa/elpy-1.8.0/snippets/python-mode/__pow__ elpa/elpy-1.8.0/snippets/python-mode/__radd__ elpa/elpy-1.8.0/snippets/python-mode/__rand__ elpa/elpy-1.8.0/snippets/python-mode/__rdivmod__ elpa/elpy-1.8.0/snippets/python-mode/__repr__ elpa/elpy-1.8.0/snippets/python-mode/__reversed__ elpa/elpy-1.8.0/snippets/python-mode/__rfloordiv__ elpa/elpy-1.8.0/snippets/python-mode/__rlshift__ elpa/elpy-1.8.0/snippets/python-mode/__rmod__ elpa/elpy-1.8.0/snippets/python-mode/__rmul__ elpa/elpy-1.8.0/snippets/python-mode/__ror__ elpa/elpy-1.8.0/snippets/python-mode/__rpow__ elpa/elpy-1.8.0/snippets/python-mode/__rrshift__ elpa/elpy-1.8.0/snippets/python-mode/__rshift__ elpa/elpy-1.8.0/snippets/python-mode/__rsub__ elpa/elpy-1.8.0/snippets/python-mode/__rtruediv__ elpa/elpy-1.8.0/snippets/python-mode/__rxor__ elpa/elpy-1.8.0/snippets/python-mode/__set__ elpa/elpy-1.8.0/snippets/python-mode/__setattr__ elpa/elpy-1.8.0/snippets/python-mode/__setitem__ elpa/elpy-1.8.0/snippets/python-mode/__slots__ elpa/elpy-1.8.0/snippets/python-mode/__str__ elpa/elpy-1.8.0/snippets/python-mode/__sub__ elpa/elpy-1.8.0/snippets/python-mode/__subclasscheck__ elpa/elpy-1.8.0/snippets/python-mode/__truediv__ elpa/elpy-1.8.0/snippets/python-mode/__unicode__ elpa/elpy-1.8.0/snippets/python-mode/__xor__ elpa/elpy-1.8.0/snippets/python-mode/ase elpa/elpy-1.8.0/snippets/python-mode/asne elpa/elpy-1.8.0/snippets/python-mode/asr elpa/elpy-1.8.0/snippets/python-mode/class elpa/elpy-1.8.0/snippets/python-mode/defs elpa/elpy-1.8.0/snippets/python-mode/enc elpa/elpy-1.8.0/snippets/python-mode/env elpa/elpy-1.8.0/snippets/python-mode/from elpa/elpy-1.8.0/snippets/python-mode/pdb elpa/elpy-1.8.0/snippets/python-mode/py3 elpa/elpy-1.8.0/snippets/python-mode/super elpa/pyvenv-1.4/pyvenv-autoloads.el elpa/pyvenv-1.4/pyvenv-pkg.el elpa/pyvenv-1.4/pyvenv.el elpa/pyvenv-1.7/pyvenv-autoloads.el elpa/pyvenv-1.7/pyvenv-pkg.el elpa/pyvenv-1.7/pyvenv.el |
diffstat | 171 files changed, 2325 insertions(+), 3495 deletions(-) [+] |
line wrap: on
line diff
new file mode 100644 --- /dev/null +++ b/elpa/company-0.8.12.signed @@ -0,0 +1,1 @@ +Good signature from 474F05837FBDEF9B GNU ELPA Signing Agent <elpasign@elpa.gnu.org> (trust undefined) created at 2015-03-05T05:05:01-0500 using DSA \ No newline at end of file
new file mode 100644 --- /dev/null +++ b/elpa/company-0.8.12/.elpaignore @@ -0,0 +1,5 @@ +.travis.yml +.gitignore +Makefile +test/ +company-tests.el
rename from elpa/company-0.8.6/ChangeLog rename to elpa/company-0.8.12/ChangeLog --- a/elpa/company-0.8.6/ChangeLog +++ b/elpa/company-0.8.12/ChangeLog @@ -1,3 +1,42 @@ +2015-03-04 Dmitry Gutov <dgutov@yandex.ru> + + Merge commit 'e085a333867959a1b36015a3ad8e12e5bd6550d9' from company + +2015-02-04 Dmitry Gutov <dgutov@yandex.ru> + + Merge commit '3e70e12bd942bbd0acac4963b5caca63756ad784' from company + +2015-02-02 Dmitry Gutov <dgutov@yandex.ru> + + Merge commit 'a015fb350abe50d250e3e7a9c3c762397326977f' from company + +2015-01-23 Dmitry Gutov <dgutov@yandex.ru> + + Merge commit 'a4ac0dead8e9cb440c1f8aec9141d6c64bad4933' from company + +2015-01-15 Stefan Monnier <monnier@iro.umontreal.ca> + + * packages/company/test/clang-tests.el: Add copyright notice + +2015-01-13 Dmitry Gutov <dgutov@yandex.ru> + + Merge commit 'd12ddaa05f582ecc00e74bc42fd46652153ec7a6' from company + +2015-01-13 Dmitry Gutov <dgutov@yandex.ru> + + Merge commit 'eb0d8d9e687e1364098f9abc6f9281fcbc0d3abd' from company + +2014-10-28 Dmitry Gutov <dgutov@yandex.ru> + + Merge commit 'd3fcbefcf56d2caad172e22f24de95397c635bf2' from company + +2014-10-15 Stefan Monnier <monnier@iro.umontreal.ca> + + * packages/company/company-xcode.el (company-xcode-fetch): Avoid + add-to-list on local var. + * packages/company/company.el (company--window-height) + (company--window-width): Move before first use. + 2014-10-15 Dmitry Gutov <dgutov@yandex.ru> Merge commit '60d4c09c982a1c562a70cd6aa705f47ab3badcfb' from company
rename from elpa/company-0.8.6/NEWS.md rename to elpa/company-0.8.12/NEWS.md --- a/elpa/company-0.8.6/NEWS.md +++ b/elpa/company-0.8.12/NEWS.md @@ -1,5 +1,34 @@ # History of user-visible changes +## 2015-02-02 (0.8.10) + +* New variable `company-lighter-base`. +* Better tracking of the current selection. +* Pressing `M-0`...`M-9` works in the search mode. +* Pressing `<up>` or `<down>` doesn't quit the search mode. + +## 2015-01-23 (0.8.9) + +* New commands `company-next-page` and `company-previous-page`, remapping + `scroll-up-command` and `scroll-down-command` during completion. + +## 2015-01-13 (0.8.8) + +* Pressing `M-n` or `M-p` doesn't quit the search mode. +* New command `company-complete-common-or-cycle`. No default binding. +* `company-search-toggle-filtering` replaced `company-search-kill-others`. +* Quitting the search mode resets the filtering. +* Pressing `backspace` in the search mode deletes the character at the end of + the search string. +* `company-semantic` displays function arguments as annotations. +* New user option, `company-bbdb-modes`. +* `company-show-numbers` and `company-complete-number` now use visual numbering + of the candidates, taking into account only the ones currently displayed. +* `company-complete-number` can be bound to keypad numbers directly, with or + without modifiers. +* `company-cmake` expands `<LANG>` and `<CONFIG>` placeholders inside variable + names. + ## 2014-10-15 (0.8.6) * `company-clang` and `company-template-c-like-templatify` support templated @@ -14,7 +43,7 @@ * `company-ropemacs` is only used when `ropemacs-mode` is on. * `company-gtags` is enabled in all `prog-mode` derivatives by default. * `company-end-of-buffer-workaround` is not used anymore. -* `company-begin-commands` includes several `cc-mode` commands. +* `company-begin-commands` includes some of `cc-mode` commands. ## 2014-08-27 (0.8.3)
rename from elpa/company-0.8.6/company-autoloads.el rename to elpa/company-0.8.12/company-autoloads.el --- a/elpa/company-0.8.6/company-autoloads.el +++ b/elpa/company-0.8.12/company-autoloads.el @@ -1,10 +1,10 @@ ;;; company-autoloads.el --- automatically extracted autoloads ;; ;;; Code: - +(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) -;;;### (autoloads (global-company-mode company-mode) "company" "company.el" -;;;;;; (21577 27289 362636 15000)) +;;;### (autoloads nil "company" "company.el" (21954 12868 340604 +;;;;;; 538000)) ;;; Generated autoloads from company.el (autoload 'company-mode "company" "\ @@ -57,8 +57,8 @@ ;;;*** -;;;### (autoloads (company-abbrev) "company-abbrev" "company-abbrev.el" -;;;;;; (21577 27288 826633 362000)) +;;;### (autoloads nil "company-abbrev" "company-abbrev.el" (21954 +;;;;;; 12868 296604 536000)) ;;; Generated autoloads from company-abbrev.el (autoload 'company-abbrev "company-abbrev" "\ @@ -68,19 +68,19 @@ ;;;*** -;;;### (autoloads (company-bbdb) "company-bbdb" "company-bbdb.el" -;;;;;; (21577 27289 410636 258000)) +;;;### (autoloads nil "company-bbdb" "company-bbdb.el" (21954 12868 +;;;;;; 344604 538000)) ;;; Generated autoloads from company-bbdb.el (autoload 'company-bbdb "company-bbdb" "\ -`company-mode' completion back-end for `bbdb'. +`company-mode' completion back-end for BBDB. \(fn COMMAND &optional ARG &rest IGNORE)" t nil) ;;;*** -;;;### (autoloads (company-css) "company-css" "company-css.el" (21577 -;;;;;; 27288 878633 614000)) +;;;### (autoloads nil "company-css" "company-css.el" (21954 12868 +;;;;;; 300604 536000)) ;;; Generated autoloads from company-css.el (autoload 'company-css "company-css" "\ @@ -90,8 +90,8 @@ ;;;*** -;;;### (autoloads (company-dabbrev) "company-dabbrev" "company-dabbrev.el" -;;;;;; (21577 27288 918633 818000)) +;;;### (autoloads nil "company-dabbrev" "company-dabbrev.el" (21954 +;;;;;; 12868 300604 536000)) ;;; Generated autoloads from company-dabbrev.el (autoload 'company-dabbrev "company-dabbrev" "\ @@ -101,8 +101,8 @@ ;;;*** -;;;### (autoloads (company-dabbrev-code) "company-dabbrev-code" "company-dabbrev-code.el" -;;;;;; (21577 27289 658637 478000)) +;;;### (autoloads nil "company-dabbrev-code" "company-dabbrev-code.el" +;;;;;; (21954 12868 356604 539000)) ;;; Generated autoloads from company-dabbrev-code.el (autoload 'company-dabbrev-code "company-dabbrev-code" "\ @@ -114,8 +114,8 @@ ;;;*** -;;;### (autoloads (company-elisp) "company-elisp" "company-elisp.el" -;;;;;; (21577 27289 46634 451000)) +;;;### (autoloads nil "company-elisp" "company-elisp.el" (21954 12868 +;;;;;; 304604 537000)) ;;; Generated autoloads from company-elisp.el (autoload 'company-elisp "company-elisp" "\ @@ -125,8 +125,8 @@ ;;;*** -;;;### (autoloads (company-etags) "company-etags" "company-etags.el" -;;;;;; (21577 27288 630632 387000)) +;;;### (autoloads nil "company-etags" "company-etags.el" (21954 12868 +;;;;;; 288604 536000)) ;;; Generated autoloads from company-etags.el (autoload 'company-etags "company-etags" "\ @@ -136,8 +136,8 @@ ;;;*** -;;;### (autoloads (company-files) "company-files" "company-files.el" -;;;;;; (21577 27289 90634 661000)) +;;;### (autoloads nil "company-files" "company-files.el" (21954 12868 +;;;;;; 304604 537000)) ;;; Generated autoloads from company-files.el (autoload 'company-files "company-files" "\ @@ -149,8 +149,8 @@ ;;;*** -;;;### (autoloads (company-gtags) "company-gtags" "company-gtags.el" -;;;;;; (21577 27289 698637 683000)) +;;;### (autoloads nil "company-gtags" "company-gtags.el" (21954 12868 +;;;;;; 356604 539000)) ;;; Generated autoloads from company-gtags.el (autoload 'company-gtags "company-gtags" "\ @@ -160,8 +160,8 @@ ;;;*** -;;;### (autoloads (company-ispell) "company-ispell" "company-ispell.el" -;;;;;; (21577 27288 582632 140000)) +;;;### (autoloads nil "company-ispell" "company-ispell.el" (21954 +;;;;;; 12868 284604 536000)) ;;; Generated autoloads from company-ispell.el (autoload 'company-ispell "company-ispell" "\ @@ -171,8 +171,8 @@ ;;;*** -;;;### (autoloads (company-keywords) "company-keywords" "company-keywords.el" -;;;;;; (21577 27288 670632 578000)) +;;;### (autoloads nil "company-keywords" "company-keywords.el" (21954 +;;;;;; 12868 288604 536000)) ;;; Generated autoloads from company-keywords.el (autoload 'company-keywords "company-keywords" "\ @@ -182,8 +182,8 @@ ;;;*** -;;;### (autoloads (company-nxml) "company-nxml" "company-nxml.el" -;;;;;; (21577 27288 714632 794000)) +;;;### (autoloads nil "company-nxml" "company-nxml.el" (21954 12868 +;;;;;; 292604 536000)) ;;; Generated autoloads from company-nxml.el (autoload 'company-nxml "company-nxml" "\ @@ -193,8 +193,8 @@ ;;;*** -;;;### (autoloads (company-oddmuse) "company-oddmuse" "company-oddmuse.el" -;;;;;; (21577 27289 130634 851000)) +;;;### (autoloads nil "company-oddmuse" "company-oddmuse.el" (21954 +;;;;;; 12868 308604 537000)) ;;; Generated autoloads from company-oddmuse.el (autoload 'company-oddmuse "company-oddmuse" "\ @@ -204,8 +204,8 @@ ;;;*** -;;;### (autoloads (company-pysmell) "company-pysmell" "company-pysmell.el" -;;;;;; (21577 27289 274635 580000)) +;;;### (autoloads nil "company-pysmell" "company-pysmell.el" (21954 +;;;;;; 12868 336604 538000)) ;;; Generated autoloads from company-pysmell.el (autoload 'company-pysmell "company-pysmell" "\ @@ -216,8 +216,8 @@ ;;;*** -;;;### (autoloads (company-semantic) "company-semantic" "company-semantic.el" -;;;;;; (21577 27289 938638 872000)) +;;;### (autoloads nil "company-semantic" "company-semantic.el" (21954 +;;;;;; 12868 368604 540000)) ;;; Generated autoloads from company-semantic.el (autoload 'company-semantic "company-semantic" "\ @@ -227,8 +227,8 @@ ;;;*** -;;;### (autoloads (company-tempo) "company-tempo" "company-tempo.el" -;;;;;; (21577 27289 486636 631000)) +;;;### (autoloads nil "company-tempo" "company-tempo.el" (21954 12868 +;;;;;; 348604 539000)) ;;; Generated autoloads from company-tempo.el (autoload 'company-tempo "company-tempo" "\ @@ -238,8 +238,8 @@ ;;;*** -;;;### (autoloads (company-xcode) "company-xcode" "company-xcode.el" -;;;;;; (21577 27289 574637 68000)) +;;;### (autoloads nil "company-xcode" "company-xcode.el" (21954 12868 +;;;;;; 352604 539000)) ;;; Generated autoloads from company-xcode.el (autoload 'company-xcode "company-xcode" "\ @@ -249,8 +249,8 @@ ;;;*** -;;;### (autoloads (company-yasnippet) "company-yasnippet" "company-yasnippet.el" -;;;;;; (21577 27289 814638 249000)) +;;;### (autoloads nil "company-yasnippet" "company-yasnippet.el" +;;;;;; (21954 12868 356604 539000)) ;;; Generated autoloads from company-yasnippet.el (autoload 'company-yasnippet "company-yasnippet" "\ @@ -281,17 +281,14 @@ ;;;*** ;;;### (autoloads nil nil ("company-capf.el" "company-clang.el" "company-cmake.el" -;;;;;; "company-eclim.el" "company-elisp-tests.el" "company-pkg.el" -;;;;;; "company-ropemacs.el" "company-template.el" "company-tests.el") -;;;;;; (21577 27290 27673 442000)) +;;;;;; "company-eclim.el" "company-pkg.el" "company-ropemacs.el" +;;;;;; "company-template.el") (21954 12868 375764 380000)) ;;;*** -(provide 'company-autoloads) ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t -;; coding: utf-8 ;; End: ;;; company-autoloads.el ends here
rename from elpa/company-0.8.6/company-bbdb.el rename to elpa/company-0.8.12/company-bbdb.el --- a/elpa/company-0.8.6/company-bbdb.el +++ b/elpa/company-0.8.12/company-bbdb.el @@ -27,6 +27,15 @@ (declare-function bbdb-dwim-mail "bbdb-com") (declare-function bbdb-search "bbdb-com") +(defgroup company-bbdb nil + "Completion back-end for BBDB." + :group 'company) + +(defcustom company-bbdb-modes '(message-mode) + "Major modes in which `company-bbdb' may complete." + :type '(repeat (symbol :tag "Major mode")) + :package-version '(company . "0.8.8")) + (defun company-bbdb--candidates (arg) (cl-mapcan (lambda (record) (mapcar (lambda (mail) (bbdb-dwim-mail record mail)) @@ -35,15 +44,15 @@ ;;;###autoload (defun company-bbdb (command &optional arg &rest ignore) - "`company-mode' completion back-end for `bbdb'." + "`company-mode' completion back-end for BBDB." (interactive (list 'interactive)) (cl-case command (interactive (company-begin-backend 'company-bbdb)) - (prefix (and (eq major-mode 'message-mode) + (prefix (and (memq major-mode company-bbdb-modes) (featurep 'bbdb-com) - (looking-back "^\\(To\\|Cc\\|Bcc\\):.*" + (looking-back "^\\(To\\|Cc\\|Bcc\\): *\\(.*\\)" (line-beginning-position)) - (company-grab-symbol))) + (match-string-no-properties 2))) (candidates (company-bbdb--candidates arg)) (sorted t) (no-cache t)))
rename from elpa/company-0.8.6/company-capf.el rename to elpa/company-0.8.12/company-capf.el --- a/elpa/company-0.8.6/company-capf.el +++ b/elpa/company-0.8.12/company-capf.el @@ -138,9 +138,14 @@ (`init nil) ;Don't bother: plenty of other ways to initialize the code. (`post-completion (let* ((res (company--capf-data)) - (exit-function (plist-get (nthcdr 4 res) :exit-function))) + (exit-function (plist-get (nthcdr 4 res) :exit-function)) + (table (nth 3 res)) + (pred (plist-get (nthcdr 4 res) :predicate))) (if exit-function - (funcall exit-function arg 'finished)))) + ;; Follow the example of `completion--done'. + (funcall exit-function arg + (if (eq (try-completion arg table pred) t) + 'finished 'sole))))) )) (provide 'company-capf)
rename from elpa/company-0.8.6/company-clang.el rename to elpa/company-0.8.12/company-clang.el --- a/elpa/company-0.8.6/company-clang.el +++ b/elpa/company-0.8.12/company-clang.el @@ -110,7 +110,7 @@ ;; TODO: Handle Pattern (syntactic hints would be neat). ;; Do we ever see OVERLOAD (or OVERRIDE)? (defconst company-clang--completion-pattern - "^COMPLETION: \\_<\\(%s[a-zA-Z0-9_:<>]*\\)\\(?: : \\(.*\\)$\\)?$") + "^COMPLETION: \\_<\\(%s[a-zA-Z0-9_:]*\\)\\(?: : \\(.*\\)$\\)?$") (defconst company-clang--error-buffer-name "*clang-error*") @@ -150,7 +150,13 @@ ((string-match "[^:]:[^:]" meta) (substring meta (1+ (match-beginning 0)))) ((string-match "\\((.*)[ a-z]*\\'\\)" meta) - (match-string 1 meta))))) + (let ((paren (match-beginning 1))) + (if (not (eq (aref meta (1- paren)) ?>)) + (match-string 1 meta) + (with-temp-buffer + (insert meta) + (goto-char paren) + (substring meta (1- (search-backward "<")))))))))) (defun company-clang--strip-formatting (text) (replace-regexp-in-string @@ -182,7 +188,9 @@ (defun company-clang--start-process (prefix callback &rest args) (let ((objc (derived-mode-p 'objc-mode)) - (buf (get-buffer-create "*clang-output*"))) + (buf (get-buffer-create "*clang-output*")) + ;; Looks unnecessary in Emacs 25.1 and later. + (process-adaptive-read-buffering nil)) (with-current-buffer buf (erase-buffer)) (if (get-buffer-process buf) (funcall callback nil)
rename from elpa/company-0.8.6/company-cmake.el rename to elpa/company-0.8.12/company-cmake.el --- a/elpa/company-0.8.6/company-cmake.el +++ b/elpa/company-0.8.12/company-cmake.el @@ -1,9 +1,9 @@ ;;; company-cmake.el --- company-mode completion back-end for CMake -;; Copyright (C) 2013 Free Software Foundation, Inc. +;; Copyright (C) 2013-2014 Free Software Foundation, Inc. ;; Author: Chen Bin <chenbin DOT sh AT gmail> -;; Version: 0.1 +;; Version: 0.2 ;; 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 @@ -45,48 +45,115 @@ They affect which types of symbols we get completion candidates for.") (defvar company-cmake--completion-pattern - "^\\(%s[a-zA-Z0-9_]%s\\)$" + "^\\(%s[a-zA-Z0-9_<>]%s\\)$" "Regexp to match the candidates.") (defvar company-cmake-modes '(cmake-mode) "Major modes in which cmake may complete.") +(defvar company-cmake--candidates-cache nil + "Cache for the raw candidates.") + (defvar company-cmake--meta-command-cache nil "Cache for command arguments to retrieve descriptions for the candidates.") -(defun company-cmake--parse-output (prefix cmd) - "Analyze the temp buffer and collect lines." - (goto-char (point-min)) - (let ((pattern (format company-cmake--completion-pattern +(defun company-cmake--replace-tags (rlt) + (setq rlt (replace-regexp-in-string + "\\(.*?\\(IS_GNU\\)?\\)<LANG>\\(.*\\)" + (lambda (_match) + (mapconcat 'identity + (if (match-beginning 2) + '("\\1CXX\\3" "\\1C\\3" "\\1G77\\3") + '("\\1CXX\\3" "\\1C\\3" "\\1Fortran\\3")) + "\n")) + rlt t)) + (setq rlt (replace-regexp-in-string + "\\(.*\\)<CONFIG>\\(.*\\)" + (mapconcat 'identity '("\\1DEBUG\\2" "\\1RELEASE\\2" + "\\1RELWITHDEBINFO\\2" "\\1MINSIZEREL\\2") + "\n") + rlt)) + rlt) + +(defun company-cmake--fill-candidates-cache (arg) + "Fill candidates cache if needed." + (let (rlt) + (unless company-cmake--candidates-cache + (setq company-cmake--candidates-cache (make-hash-table :test 'equal))) + + ;; If hash is empty, fill it. + (unless (gethash arg company-cmake--candidates-cache) + (with-temp-buffer + (let ((res (call-process company-cmake-executable nil t nil arg))) + (unless (zerop res) + (message "cmake executable exited with error=%d" res))) + (setq rlt (buffer-string))) + (setq rlt (company-cmake--replace-tags rlt)) + (puthash arg rlt company-cmake--candidates-cache)) + )) + +(defun company-cmake--parse (prefix content cmd) + (let ((start 0) + (pattern (format company-cmake--completion-pattern (regexp-quote prefix) (if (zerop (length prefix)) "+" "*"))) - (case-fold-search nil) - lines match) - (while (re-search-forward pattern nil t) - (setq match (match-string-no-properties 1)) - (puthash match cmd company-cmake--meta-command-cache) - (push match lines)) - lines)) + (lines (split-string content "\n")) + match + rlt) + (dolist (line lines) + (when (string-match pattern line) + (let ((match (match-string 1 line))) + (when match + (puthash match cmd company-cmake--meta-command-cache) + (push match rlt))))) + rlt)) (defun company-cmake--candidates (prefix) - (let ((res 0) - results - cmd) - (setq company-cmake--meta-command-cache (make-hash-table :test 'equal)) + (let (results + cmd-opts + str) + + (unless company-cmake--meta-command-cache + (setq company-cmake--meta-command-cache (make-hash-table :test 'equal))) + (dolist (arg company-cmake-executable-arguments) - (with-temp-buffer - (setq res (call-process company-cmake-executable nil t nil arg)) - (unless (eq 0 res) - (message "cmake executable exited with error=%d" res)) - (setq cmd (replace-regexp-in-string "-list$" "" arg) ) - (setq results (nconc results (company-cmake--parse-output prefix cmd))))) + (company-cmake--fill-candidates-cache arg) + (setq cmd-opts (replace-regexp-in-string "-list$" "" arg) ) + + (setq str (gethash arg company-cmake--candidates-cache)) + (when str + (setq results (nconc results + (company-cmake--parse prefix str cmd-opts))))) results)) -(defun company-cmake--meta (prefix) - (let ((cmd-opts (gethash prefix company-cmake--meta-command-cache)) +(defun company-cmake--unexpand-candidate (candidate) + (cond + ((string-match "^CMAKE_\\(C\\|CXX\\|Fortran\\)\\(_.*\\)$" candidate) + (setq candidate (concat "CMAKE_<LANG>" (match-string 2 candidate)))) + + ;; C flags + ((string-match "^\\(.*_\\)IS_GNU\\(C\\|CXX\\|G77\\)$" candidate) + (setq candidate (concat (match-string 1 candidate) "IS_GNU<LANG>"))) + + ;; C flags + ((string-match "^\\(.*_\\)OVERRIDE_\\(C\\|CXX\\|Fortran\\)$" candidate) + (setq candidate (concat (match-string 1 candidate) "OVERRIDE_<LANG>"))) + + ((string-match "^\\(.*\\)\\(_DEBUG\\|_RELEASE\\|_RELWITHDEBINFO\\|_MINSIZEREL\\)\\(.*\\)$" candidate) + (setq candidate (concat (match-string 1 candidate) + "_<CONFIG>" + (match-string 3 candidate))))) + candidate) + +(defun company-cmake--meta (candidate) + (let ((cmd-opts (gethash candidate company-cmake--meta-command-cache)) result) + (setq candidate (company-cmake--unexpand-candidate candidate)) + + ;; Don't cache the documentation of every candidate (command) + ;; Cache in this case will cost too much memory. (with-temp-buffer - (call-process company-cmake-executable nil t nil cmd-opts prefix) + (call-process company-cmake-executable nil t nil cmd-opts candidate) ;; Go to the third line, trim it and return the result. ;; Tested with cmake 2.8.9. (goto-char (point-min)) @@ -96,10 +163,12 @@ (setq result (replace-regexp-in-string "^[ \t\n\r]+" "" result)) result))) -(defun company-cmake--doc-buffer (prefix) - (let ((cmd-opts (gethash prefix company-cmake--meta-command-cache))) +(defun company-cmake--doc-buffer (candidate) + (let ((cmd-opts (gethash candidate company-cmake--meta-command-cache))) + + (setq candidate (company-cmake--unexpand-candidate candidate)) (with-temp-buffer - (call-process company-cmake-executable nil t nil cmd-opts prefix) + (call-process company-cmake-executable nil t nil cmd-opts candidate) ;; Go to the third line, trim it and return the doc buffer. ;; Tested with cmake 2.8.9. (goto-char (point-min))
rename from elpa/company-0.8.6/company-dabbrev-code.el rename to elpa/company-0.8.12/company-dabbrev-code.el
rename from elpa/company-0.8.6/company-etags.el rename to elpa/company-0.8.12/company-etags.el --- a/elpa/company-0.8.6/company-etags.el +++ b/elpa/company-0.8.12/company-etags.el @@ -54,7 +54,7 @@ (let ((file (locate-dominating-file (or buffer-file-name default-directory) "TAGS"))) - (when file + (when (and file (file-regular-p file)) (list (expand-file-name file))))) (defun company-etags-buffer-table ()
rename from elpa/company-0.8.6/company-files.el rename to elpa/company-0.8.12/company-files.el --- a/elpa/company-0.8.6/company-files.el +++ b/elpa/company-0.8.12/company-files.el @@ -64,6 +64,7 @@ (expand-file-name dir) (nth 5 (file-attributes dir)))) (file (file-name-nondirectory prefix)) + (completion-ignore-case read-file-name-completion-ignore-case) candidates directories) (unless (company-file--keys-match-p key (car company-files--completion-cache)) (dolist (file (company-files--directory-files dir file))
rename from elpa/company-0.8.6/company-ispell.el rename to elpa/company-0.8.12/company-ispell.el --- a/elpa/company-0.8.6/company-ispell.el +++ b/elpa/company-0.8.12/company-ispell.el @@ -1,6 +1,6 @@ ;;; company-ispell.el --- company-mode completion back-end using Ispell -;; Copyright (C) 2009-2011 Free Software Foundation, Inc. +;; Copyright (C) 2009-2011, 2013-2015 Free Software Foundation, Inc. ;; Author: Nikolaj Schumacher @@ -60,8 +60,15 @@ (interactive (company-begin-backend 'company-ispell)) (prefix (when (company-ispell-available) (company-grab-word))) - (candidates (lookup-words arg (or company-ispell-dictionary - ispell-complete-word-dict))) + (candidates + (let ((words (lookup-words arg (or company-ispell-dictionary + ispell-complete-word-dict))) + (completion-ignore-case t)) + (if (string= arg "") + ;; Small optimization. + words + ;; Work around issue #284. + (all-completions arg words)))) (sorted t) (ignore-case 'keep-prefix)))
rename from elpa/company-0.8.6/company-keywords.el rename to elpa/company-0.8.12/company-keywords.el
rename from elpa/company-0.8.6/company-pkg.el rename to elpa/company-0.8.12/company-pkg.el --- a/elpa/company-0.8.6/company-pkg.el +++ b/elpa/company-0.8.12/company-pkg.el @@ -1,2 +1,2 @@ ;; Generated package description from company.el -(define-package "company" "0.8.6" "Modular text completion framework" '((emacs "24.1") (cl-lib "0.5")) :url "http://company-mode.github.io/" :keywords '("abbrev" "convenience" "matching")) +(define-package "company" "0.8.12" "Modular text completion framework" '((emacs "24.1") (cl-lib "0.5")) :url "http://company-mode.github.io/" :keywords '("abbrev" "convenience" "matching"))
rename from elpa/company-0.8.6/company-ropemacs.el rename to elpa/company-0.8.12/company-ropemacs.el
rename from elpa/company-0.8.6/company-semantic.el rename to elpa/company-0.8.12/company-semantic.el --- a/elpa/company-0.8.6/company-semantic.el +++ b/elpa/company-0.8.12/company-semantic.el @@ -99,6 +99,14 @@ (push tag company-semantic--current-tags))) (delete "" (mapcar 'semantic-tag-name company-semantic--current-tags))) +(defun company-semantic-annotation (argument tags) + (let* ((tag (assoc argument tags)) + (kind (when tag (elt tag 1)))) + (cl-case kind + (function (let* ((prototype (semantic-format-tag-prototype tag nil nil)) + (par-pos (string-match "(" prototype))) + (when par-pos (substring prototype par-pos))))))) + (defun company-semantic--pre-prefix-length (prefix-length) "Sum up the length of all chained symbols before POS. Symbols are chained by \".\" or \"->\"." @@ -133,6 +141,8 @@ (company-semantic-completions arg))) (meta (funcall company-semantic-metadata-function (assoc arg company-semantic--current-tags))) + (annotation (company-semantic-annotation arg + company-semantic--current-tags)) (doc-buffer (company-semantic-doc-buffer (assoc arg company-semantic--current-tags))) ;; Because "" is an empty context and doesn't return local variables.
rename from elpa/company-0.8.6/company-template.el rename to elpa/company-0.8.12/company-template.el --- a/elpa/company-0.8.6/company-template.el +++ b/elpa/company-0.8.12/company-template.el @@ -152,9 +152,7 @@ (cnt 0) (templ (company-template-declare-template beg end)) paren-open paren-close) - (with-syntax-table (make-char-table 'syntax-table nil) - (modify-syntax-entry ?\( "(") - (modify-syntax-entry ?\) ")") + (with-syntax-table (make-syntax-table (syntax-table)) (modify-syntax-entry ?< "(") (modify-syntax-entry ?> ")") (when (search-backward ")" beg t)
rename from elpa/company-0.8.6/company-xcode.el rename to elpa/company-0.8.12/company-xcode.el --- a/elpa/company-0.8.6/company-xcode.el +++ b/elpa/company-0.8.12/company-xcode.el @@ -1,6 +1,6 @@ ;;; company-xcode.el --- company-mode completion back-end for Xcode projects -;; Copyright (C) 2009-2011 Free Software Foundation, Inc. +;; Copyright (C) 2009-2011, 2014 Free Software Foundation, Inc. ;; Author: Nikolaj Schumacher @@ -80,7 +80,7 @@ "\t[^\t\n]*\t[^\t\n]*")) candidates) (while (re-search-forward regexp nil t) - (add-to-list 'candidates (match-string 1))) + (cl-pushnew (match-string 1) candidates :test #'equal)) (message "Retrieving dump from %s...done" project-bundle) candidates))))
rename from elpa/company-0.8.6/company-yasnippet.el rename to elpa/company-0.8.12/company-yasnippet.el
rename from elpa/company-0.8.6/company.el rename to elpa/company-0.8.12/company.el --- a/elpa/company-0.8.6/company.el +++ b/elpa/company-0.8.12/company.el @@ -1,11 +1,11 @@ ;;; company.el --- Modular text completion framework -*- lexical-binding: t -*- -;; Copyright (C) 2009-2014 Free Software Foundation, Inc. +;; Copyright (C) 2009-2015 Free Software Foundation, Inc. ;; Author: Nikolaj Schumacher ;; Maintainer: Dmitry Gutov <dgutov@yandex.ru> ;; URL: http://company-mode.github.io/ -;; Version: 0.8.6 +;; Version: 0.8.12 ;; Keywords: abbrev, convenience, matching ;; Package-Requires: ((emacs "24.1") (cl-lib "0.5")) @@ -340,20 +340,20 @@ of the following: `prefix': The back-end should return the text to be completed. It must be -text immediately before point. Returning nil passes control to the next -back-end. The function should return `stop' if it should complete but -cannot (e.g. if it is in the middle of a string). Instead of a string, -the back-end may return a cons where car is the prefix and cdr is used in -`company-minimum-prefix-length' test. It must be either number or t, and -in the latter case the test automatically succeeds. +text immediately before point. Returning nil from this command passes +control to the next back-end. The function should return `stop' if it +should complete but cannot (e.g. if it is in the middle of a string). +Instead of a string, the back-end may return a cons where car is the prefix +and cdr is used in `company-minimum-prefix-length' test. It must be either +number or t, and in the latter case the test automatically succeeds. `candidates': The second argument is the prefix to be completed. The return value should be a list of candidates that match the prefix. Non-prefix matches are also supported (candidates that don't start with the prefix, but match it in some backend-defined way). Backends that use this -feature must disable cache (return t to `no-cache') and should also respond -to `match'. +feature must disable cache (return t to `no-cache') and might also want to +respond to `match'. Optional commands: @@ -384,10 +384,10 @@ backends should store the related information on candidates using text properties. -`match': The second argument is a completion candidate. Backends that -provide non-prefix completions should return the position of the end of -text in the candidate that matches `prefix'. It will be used when -rendering the popup. +`match': The second argument is a completion candidate. Return the index +after the end of text matching `prefix' within the candidate string. It +will be used when rendering the popup. This command only makes sense for +backends that provide non-prefix completion. `require-match': If this returns t, the user is not allowed to enter anything not offered as a candidate. Use with care! The default value nil @@ -449,9 +449,11 @@ (put 'company-backends 'safe-local-variable 'company-safe-backends-p) (defcustom company-transformers nil - "Functions to change the list of candidates received from backends, -after sorting and removal of duplicates (if appropriate). -Each function gets called with the return value of the previous one." + "Functions to change the list of candidates received from backends. + +Each function gets called with the return value of the previous one. +The first one gets passed the list of candidates, already sorted and +without duplicates." :type '(choice (const :tag "None" nil) (const :tag "Sort by occurrence" (company-sort-by-occurrence)) @@ -612,6 +614,8 @@ (define-key keymap (kbd "M-p") 'company-select-previous) (define-key keymap (kbd "<down>") 'company-select-next-or-abort) (define-key keymap (kbd "<up>") 'company-select-previous-or-abort) + (define-key keymap [remap scroll-up-command] 'company-next-page) + (define-key keymap [remap scroll-down-command] 'company-previous-page) (define-key keymap [down-mouse-1] 'ignore) (define-key keymap [down-mouse-3] 'ignore) (define-key keymap [mouse-1] 'company-complete-mouse) @@ -658,9 +662,26 @@ (unless (keywordp b) (company-init-backend b)))))) -(defvar company-default-lighter " company") - -(defvar-local company-lighter company-default-lighter) +(defcustom company-lighter-base "company" + "Base string to use for the `company-mode' lighter." + :type 'string + :package-version '(company . "0.8.10")) + +(defvar company-lighter '(" " + (company-backend + (:eval + (if (consp company-backend) + (company--group-lighter (nth company-selection + company-candidates) + company-lighter-base) + (symbol-name company-backend))) + company-lighter-base)) + "Mode line lighter for Company. + +The value of this variable is a mode line template as in +`mode-line-format'.") + +(put 'company-lighter 'risky-local-variable t) ;;;###autoload (define-minor-mode company-mode @@ -767,10 +788,10 @@ (interactive) (setq this-command last-command)) -(global-set-key '[31415926] 'company-ignore) +(global-set-key '[company-dummy-event] 'company-ignore) (defun company-input-noop () - (push 31415926 unread-command-events)) + (push 'company-dummy-event unread-command-events)) (defun company--posn-col-row (posn) (let ((col (car (posn-col-row posn))) @@ -913,26 +934,26 @@ (cons :async (lambda (callback) - (let* (lst pending + (let* (lst + (pending (mapcar #'car pairs)) (finisher (lambda () (unless pending (funcall callback (funcall merger (nreverse lst))))))) (dolist (pair pairs) - (let ((val (car pair)) - (mapper (cdr pair))) + (push nil lst) + (let* ((cell lst) + (val (car pair)) + (mapper (cdr pair)) + (this-finisher (lambda (res) + (setq pending (delq val pending)) + (setcar cell (funcall mapper res)) + (funcall finisher)))) (if (not (eq :async (car-safe val))) - (push (funcall mapper val) lst) - (push nil lst) - (let ((cell lst) - (fetcher (cdr val))) - (push fetcher pending) - (funcall fetcher - (lambda (res) - (setq pending (delq fetcher pending)) - (setcar cell (funcall mapper res)) - (funcall finisher))))))))))))) + (funcall this-finisher val) + (let ((fetcher (cdr val))) + (funcall fetcher this-finisher))))))))))) (defun company--prefix-str (prefix) (or (car-safe prefix) prefix)) @@ -978,8 +999,9 @@ ;; XXX: Return value we check here is subject to change. (if (eq (company-call-backend 'ignore-case) 'keep-prefix) (insert (company-strip-prefix candidate)) - (delete-region (- (point) (length company-prefix)) (point)) - (insert candidate))) + (unless (equal company-prefix candidate) + (delete-region (- (point) (length company-prefix)) (point)) + (insert candidate)))) (defmacro company-with-candidate-inserted (candidate &rest body) "Evaluate BODY with CANDIDATE temporarily inserted. @@ -1040,58 +1062,49 @@ (mod selection company-candidates-length) (max 0 (min (1- company-candidates-length) selection)))) (when (or force-update (not (equal selection company-selection))) - (company--update-group-lighter (nth selection company-candidates)) (setq company-selection selection company-selection-changed t) (company-call-frontends 'update))) -(defun company--update-group-lighter (candidate) - (when (listp company-backend) - (let ((backend (or (get-text-property 0 'company-backend candidate) - (car company-backend)))) - (when (and backend (symbolp backend)) - (let ((name (replace-regexp-in-string "company-\\|-company" "" - (symbol-name backend)))) - (setq company-lighter (format " company-<%s>" name))))))) - -(defun company-apply-predicate (candidates predicate) - (let (new) - (dolist (c candidates) - (when (funcall predicate c) - (push c new))) - (nreverse new))) +(defun company--group-lighter (candidate base) + (let ((backend (or (get-text-property 0 'company-backend candidate) + (car company-backend)))) + (when (and backend (symbolp backend)) + (let ((name (replace-regexp-in-string "company-\\|-company" "" + (symbol-name backend)))) + (format "%s-<%s>" base name))))) (defun company-update-candidates (candidates) (setq company-candidates-length (length candidates)) - (if (> company-selection 0) + (if company-selection-changed ;; Try to restore the selection (let ((selected (nth company-selection company-candidates))) (setq company-selection 0 company-candidates candidates) (when selected - (while (and candidates (string< (pop candidates) selected)) - (cl-incf company-selection)) - (unless candidates - ;; Make sure selection isn't out of bounds. - (setq company-selection (min (1- company-candidates-length) - company-selection))))) + (catch 'found + (while candidates + (let ((candidate (pop candidates))) + (when (and (string= candidate selected) + (equal (company-call-backend 'annotation candidate) + (company-call-backend 'annotation selected))) + (throw 'found t))) + (cl-incf company-selection)) + (setq company-selection 0 + company-selection-changed nil)))) (setq company-selection 0 company-candidates candidates)) - ;; Save in cache: - (push (cons company-prefix company-candidates) company-candidates-cache) ;; Calculate common. (let ((completion-ignore-case (company-call-backend 'ignore-case))) ;; We want to support non-prefix completion, so filtering is the ;; responsibility of each respective backend, not ours. ;; On the other hand, we don't want to replace non-prefix input in - ;; `company-complete-common'. + ;; `company-complete-common', unless there's only one candidate. (setq company-common (if (cdr company-candidates) - (let ((common (try-completion company-prefix company-candidates))) - (if (eq common t) - ;; Mulple equal strings, probably with different - ;; annotations. - company-prefix + (let ((common (try-completion "" company-candidates))) + (when (string-prefix-p company-prefix common + completion-ignore-case) common)) (car company-candidates))))) @@ -1108,11 +1121,14 @@ company-candidates-cache))) (setq candidates (all-completions prefix prev)) (cl-return t))))) - ;; no cache match, call back-end - (setq candidates - (company--process-candidates - (company--fetch-candidates prefix)))) - (setq candidates (company--transform-candidates candidates)) + (progn + ;; No cache match, call the backend. + (setq candidates (company--preprocess-candidates + (company--fetch-candidates prefix))) + ;; Save in cache. + (push (cons prefix candidates) company-candidates-cache))) + ;; Only now apply the predicate and transformers. + (setq candidates (company--postprocess-candidates candidates)) (when candidates (if (or (cdr candidates) (not (eq t (compare-strings (car candidates) nil nil @@ -1137,13 +1153,13 @@ (cdr c) (lambda (candidates) (if (not (and candidates (eq res 'done))) - ;; Fetcher called us back right away. + ;; There's no completions to display, + ;; or the fetcher called us back right away. (setq res candidates) (setq company-backend backend company-candidates-cache (list (cons prefix - (company--process-candidates - candidates)))) + (company--preprocess-candidates candidates)))) (company-idle-begin buf win tick pt))))) ;; FIXME: Relying on the fact that the callers ;; will interpret nil as "do nothing" is shaky. @@ -1151,33 +1167,40 @@ (or res (progn (setq res 'done) nil))))) -(defun company--process-candidates (candidates) - (when company-candidates-predicate - (setq candidates - (company-apply-predicate candidates - company-candidates-predicate))) +(defun company--preprocess-candidates (candidates) (unless (company-call-backend 'sorted) (setq candidates (sort candidates 'string<))) (when (company-call-backend 'duplicates) (company--strip-duplicates candidates)) candidates) +(defun company--postprocess-candidates (candidates) + (when (or company-candidates-predicate company-transformers) + (setq candidates (copy-sequence candidates))) + (when company-candidates-predicate + (setq candidates (cl-delete-if-not company-candidates-predicate candidates))) + (company--transform-candidates candidates)) + (defun company--strip-duplicates (candidates) - (let ((c2 candidates)) + (let ((c2 candidates) + (annos 'unk)) (while c2 (setcdr c2 - (let ((str (car c2)) - (anno 'unk)) - (pop c2) + (let ((str (pop c2))) (while (let ((str2 (car c2))) (if (not (equal str str2)) - nil - (when (eq anno 'unk) - (setq anno (company-call-backend - 'annotation str))) - (equal anno - (company-call-backend - 'annotation str2)))) + (progn + (setq annos 'unk) + nil) + (when (eq annos 'unk) + (setq annos (list (company-call-backend + 'annotation str)))) + (let ((anno2 (company-call-backend + 'annotation str2))) + (if (member anno2 annos) + t + (push anno2 annos) + nil)))) (pop c2)) c2))))) @@ -1288,15 +1311,14 @@ (not company-candidates) (let ((company-idle-delay 'now)) (condition-case-unless-debug err - (company--perform) + (progn + (company--perform) + ;; Return non-nil if active. + company-candidates) (error (message "Company: An error occurred in auto-begin") (message "%s" (error-message-string err)) (company-cancel)) - (quit (company-cancel))))) - (unless company-candidates - (setq company-backend nil)) - ;; Return non-nil if active. - company-candidates) + (quit (company-cancel)))))) (defun company-manual-begin () (interactive) @@ -1304,7 +1326,8 @@ (setq company--manual-action t) (unwind-protect (let ((company-minimum-prefix-length 0)) - (company-auto-begin)) + (or company-candidates + (company-auto-begin))) (unless company-candidates (setq company--manual-action nil)))) @@ -1366,6 +1389,7 @@ ((and (or (not (company-require-match-p)) ;; Don't require match if the new prefix ;; doesn't continue the old one, and the latter was a match. + (not (stringp new-prefix)) (<= (length new-prefix) (length company-prefix))) (member company-prefix company-candidates)) ;; Last input was a success, @@ -1443,9 +1467,6 @@ (message "No completion found")) (when company--manual-action (setq company--manual-prefix prefix)) - (if (symbolp backend) - (setq company-lighter (concat " " (symbol-name backend))) - (company--update-group-lighter (car c))) (company-update-candidates c) (run-hook-with-args 'company-completion-started-hook (company-explicit-action-p)) @@ -1455,7 +1476,8 @@ (defun company--perform () (or (and company-candidates (company--continue)) (and (company--should-complete) (company--begin-new))) - (when company-candidates + (if (not company-candidates) + (setq company-backend nil) (setq company-point (point) company--point-max (point-max)) (company-ensure-emulation-alist) @@ -1482,7 +1504,6 @@ company-selection-changed nil company--manual-action nil company--manual-prefix nil - company-lighter company-default-lighter company--point-max nil company-point nil) (when company-timer @@ -1565,15 +1586,22 @@ ;;; search ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -(defvar-local company-search-string nil) - -(defvar-local company-search-lighter " Search: \"\"") - -(defvar-local company-search-old-map nil) - -(defvar-local company-search-old-selection 0) - -(defun company-search (text lines) +(defvar-local company-search-string "") + +(defvar company-search-lighter '(" " + (company-search-filtering "Filter" "Search") + ": \"" + company-search-string + "\"")) + +(defvar-local company-search-filtering nil + "Non-nil to filter the completion candidates by the search string") + +(defvar-local company--search-old-selection 0) + +(defvar-local company--search-old-changed nil) + +(defun company--search (text lines) (let ((quoted (regexp-quote text)) (i 0)) (cl-dolist (line lines) @@ -1581,24 +1609,48 @@ (cl-return i)) (cl-incf i)))) +(defun company-search-keypad () + (interactive) + (let* ((name (symbol-name last-command-event)) + (last-command-event (aref name (1- (length name))))) + (company-search-printing-char))) + (defun company-search-printing-char () (interactive) - (company-search-assert-enabled) - (let* ((ss (concat company-search-string (string last-command-event))) - (pos (company-search ss (nthcdr company-selection company-candidates)))) + (company--search-assert-enabled) + (let ((ss (concat company-search-string (string last-command-event)))) + (when company-search-filtering + (company--search-update-predicate ss)) + (company--search-update-string ss))) + +(defun company--search-update-predicate (&optional ss) + (let* ((company-candidates-predicate + (and (not (string= ss "")) + company-search-filtering + (lambda (candidate) (string-match ss candidate)))) + (cc (company-calculate-candidates company-prefix))) + (unless cc (error "No match")) + (company-update-candidates cc))) + +(defun company--search-update-string (new) + (let* ((pos (company--search new (nthcdr company-selection company-candidates)))) (if (null pos) (ding) - (setq company-search-string ss - company-search-lighter (concat " Search: \"" ss "\"")) + (setq company-search-string new) (company-set-selection (+ company-selection pos) t)))) +(defun company--search-assert-input () + (company--search-assert-enabled) + (when (string= company-search-string "") + (error "Empty search string"))) + (defun company-search-repeat-forward () "Repeat the incremental search in completion candidates forward." (interactive) - (company-search-assert-enabled) - (let ((pos (company-search company-search-string - (cdr (nthcdr company-selection - company-candidates))))) + (company--search-assert-input) + (let ((pos (company--search company-search-string + (cdr (nthcdr company-selection + company-candidates))))) (if (null pos) (ding) (company-set-selection (+ company-selection pos 1) t)))) @@ -1606,52 +1658,48 @@ (defun company-search-repeat-backward () "Repeat the incremental search in completion candidates backwards." (interactive) - (company-search-assert-enabled) - (let ((pos (company-search company-search-string - (nthcdr (- company-candidates-length - company-selection) - (reverse company-candidates))))) + (company--search-assert-input) + (let ((pos (company--search company-search-string + (nthcdr (- company-candidates-length + company-selection) + (reverse company-candidates))))) (if (null pos) (ding) (company-set-selection (- company-selection pos 1) t)))) -(defun company-create-match-predicate () - (let ((ss company-search-string)) - (setq company-candidates-predicate - (when ss (lambda (candidate) (string-match ss candidate))))) - (company-update-candidates - (company-apply-predicate company-candidates company-candidates-predicate)) - ;; Invalidate cache. - (setq company-candidates-cache (cons company-prefix company-candidates))) - -(defun company-filter-printing-char () +(defun company-search-toggle-filtering () + "Toggle `company-search-filtering'." (interactive) - (company-search-assert-enabled) - (company-search-printing-char) - (company-create-match-predicate) - (company-call-frontends 'update)) - -(defun company-search-kill-others () - "Limit the completion candidates to the ones matching the search string." - (interactive) - (company-search-assert-enabled) - (company-create-match-predicate) - (company-search-mode 0) - (company-call-frontends 'update)) + (company--search-assert-enabled) + (setq company-search-filtering (not company-search-filtering)) + (let ((ss company-search-string)) + (company--search-update-predicate ss) + (company--search-update-string ss))) (defun company-search-abort () "Abort searching the completion candidates." (interactive) - (company-search-assert-enabled) - (company-set-selection company-search-old-selection t) - (company-search-mode 0)) + (company--search-assert-enabled) + (company-search-mode 0) + (company-set-selection company--search-old-selection t) + (setq company-selection-changed company--search-old-changed)) (defun company-search-other-char () (interactive) - (company-search-assert-enabled) + (company--search-assert-enabled) (company-search-mode 0) (company--unread-last-input)) +(defun company-search-delete-char () + (interactive) + (company--search-assert-enabled) + (if (string= company-search-string "") + (ding) + (let ((ss (substring company-search-string 0 -1))) + (when company-search-filtering + (company--search-update-predicate ss)) + (company--search-update-string ss)))) + (defvar company-search-map (let ((i 0) (keymap (make-keymap))) @@ -1672,18 +1720,26 @@ (while (< i 256) (define-key keymap (vector i) 'company-search-printing-char) (cl-incf i)) + (dotimes (i 10) + (define-key keymap (read (format "[kp-%s]" i)) 'company-search-keypad)) (let ((meta-map (make-sparse-keymap))) (define-key keymap (char-to-string meta-prefix-char) meta-map) (define-key keymap [escape] meta-map)) (define-key keymap (vector meta-prefix-char t) 'company-search-other-char) + (define-key keymap (kbd "M-n") 'company-select-next) + (define-key keymap (kbd "M-p") 'company-select-previous) + (define-key keymap (kbd "<down>") 'company-select-next-or-abort) + (define-key keymap (kbd "<up>") 'company-select-previous-or-abort) (define-key keymap "\e\e\e" 'company-search-other-char) (define-key keymap [escape escape escape] 'company-search-other-char) - (define-key keymap (kbd "DEL") 'company-search-other-char) - + (define-key keymap (kbd "DEL") 'company-search-delete-char) + (define-key keymap [backspace] 'company-search-delete-char) (define-key keymap "\C-g" 'company-search-abort) (define-key keymap "\C-s" 'company-search-repeat-forward) (define-key keymap "\C-r" 'company-search-repeat-backward) - (define-key keymap "\C-o" 'company-search-kill-others) + (define-key keymap "\C-o" 'company-search-toggle-filtering) + (dotimes (i 10) + (define-key keymap (read-kbd-macro (format "M-%d" i)) 'company-complete-number)) keymap) "Keymap used for incrementally searching the completion candidates.") @@ -1695,15 +1751,21 @@ (if company-search-mode (if (company-manual-begin) (progn - (setq company-search-old-selection company-selection) - (company-call-frontends 'update)) + (setq company--search-old-selection company-selection + company--search-old-changed company-selection-changed) + (company-call-frontends 'update) + (company-enable-overriding-keymap company-search-map)) (setq company-search-mode nil)) (kill-local-variable 'company-search-string) - (kill-local-variable 'company-search-lighter) - (kill-local-variable 'company-search-old-selection) + (kill-local-variable 'company-search-filtering) + (kill-local-variable 'company--search-old-selection) + (kill-local-variable 'company--search-old-changed) + (when company-backend + (company--search-update-predicate "") + (company-call-frontends 'update)) (company-enable-overriding-keymap company-active-map))) -(defun company-search-assert-enabled () +(defun company--search-assert-enabled () (company-assert-enabled) (unless company-search-mode (company-uninstall-map) @@ -1716,14 +1778,14 @@ - `company-search-repeat-forward' (\\[company-search-repeat-forward]) - `company-search-repeat-backward' (\\[company-search-repeat-backward]) - `company-search-abort' (\\[company-search-abort]) +- `company-search-delete-char' (\\[company-search-delete-char]) Regular characters are appended to the search string. -The command `company-search-kill-others' (\\[company-search-kill-others]) -uses the search string to limit the completion candidates." +The command `company-search-toggle-filtering' (\\[company-search-toggle-filtering]) +uses the search string to filter the completion candidates." (interactive) - (company-search-mode 1) - (company-enable-overriding-keymap company-search-map)) + (company-search-mode 1)) (defvar company-filter-map (let ((keymap (make-keymap))) @@ -1736,10 +1798,10 @@ (defun company-filter-candidates () "Start filtering the completion candidates incrementally. This works the same way as `company-search-candidates' immediately -followed by `company-search-kill-others' after each input." +followed by `company-search-toggle-filtering'." (interactive) (company-search-mode 1) - (company-enable-overriding-keymap company-filter-map)) + (setq company-search-filtering t)) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -1773,6 +1835,20 @@ (company-abort) (company--unread-last-input))) +(defun company-next-page () + "Select the candidate one page further." + (interactive) + (when (company-manual-begin) + (company-set-selection (+ company-selection + company-tooltip-limit)))) + +(defun company-previous-page () + "Select the candidate one page earlier." + (interactive) + (when (company-manual-begin) + (company-set-selection (- company-selection + company-tooltip-limit)))) + (defvar company-pseudo-tooltip-overlay) (defvar company-tooltip-offset) @@ -1843,6 +1919,16 @@ (when company-common (company--insert-candidate company-common))))) +(defun company-complete-common-or-cycle () + "Insert the common part of all candidates, or select the next one." + (interactive) + (when (company-manual-begin) + (let ((tick (buffer-chars-modified-tick))) + (call-interactively 'company-complete-common) + (when (eq tick (buffer-chars-modified-tick)) + (let ((company-selection-wrap-around t)) + (call-interactively 'company-select-next)))))) + (defun company-complete () "Insert the common part of all candidates or the current selection. The first time this is called, the common part is inserted, the second @@ -1857,18 +1943,26 @@ (setq this-command 'company-complete-common)))) (defun company-complete-number (n) - "Insert the Nth candidate. + "Insert the Nth candidate visible in the tooltip. To show the number next to the candidates in some back-ends, enable `company-show-numbers'. When called interactively, uses the last typed character, stripping the modifiers. That character must be a digit." (interactive - (list (let ((n (- (event-basic-type last-command-event) ?0))) + (list (let* ((type (event-basic-type last-command-event)) + (char (if (characterp type) + ;; Number on the main row. + type + ;; Keypad number, if bound directly. + (car (last (string-to-list (symbol-name type)))))) + (n (- char ?0))) (if (zerop n) 10 n)))) (when (company-manual-begin) - (and (or (< n 1) (> n company-candidates-length)) + (and (or (< n 1) (> n (- company-candidates-length + company-tooltip-offset))) (error "No candidate number %d" n)) (cl-decf n) - (company-finish (nth n company-candidates)))) + (company-finish (nth (+ n company-tooltip-offset) + company-candidates)))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -2095,7 +2189,6 @@ (string-width company-common) 0))) (ann-ralign company-tooltip-align-annotations) - (value (company--clean-string value)) (ann-truncate (< width (+ (length value) (length annotation) (if ann-ralign 1 0)))) @@ -2134,16 +2227,15 @@ mouse-face company-tooltip-mouse) line)) (when selected - (if (and company-search-string + (if (and (not (string= company-search-string "")) (string-match (regexp-quote company-search-string) value (length company-prefix))) (let ((beg (+ margin (match-beginning 0))) - (end (+ margin (match-end 0)))) - (add-text-properties beg end '(face company-tooltip-search) - line) - (when (< beg common) - (add-text-properties beg common - '(face company-tooltip-common-selection) + (end (+ margin (match-end 0))) + (width (- width (length right)))) + (when (< beg width) + (add-text-properties beg (min end width) + '(face company-tooltip-search) line))) (add-text-properties 0 width '(face company-tooltip-selection mouse-face company-tooltip-selection) @@ -2178,7 +2270,8 @@ (defun company-buffer-lines (beg end) (goto-char beg) (let (lines lines-moved) - (while (and (> (setq lines-moved (vertical-motion 1)) 0) + (while (and (not (eobp)) ; http://debbugs.gnu.org/19553 + (> (setq lines-moved (vertical-motion 1)) 0) (<= (point) end)) (let ((bound (min end (1- (point))))) ;; A visual line can contain several physical lines (e.g. with outline's @@ -2208,6 +2301,30 @@ limit (length lst))) +(defsubst company--window-height () + (if (fboundp 'window-screen-lines) + (floor (window-screen-lines)) + (window-body-height))) + +(defun company--window-width () + (let ((ww (window-body-width))) + ;; Account for the line continuation column. + (when (zerop (cadr (window-fringes))) + (cl-decf ww)) + (unless (or (display-graphic-p) + (version< "24.3.1" emacs-version)) + ;; Emacs 24.3 and earlier included margins + ;; in window-width when in TTY. + (cl-decf ww + (let ((margins (window-margins))) + (+ (or (car margins) 0) + (or (cdr margins) 0))))) + (when (and word-wrap + (version< emacs-version "24.4.51.5")) + ;; http://debbugs.gnu.org/18384 + (cl-decf ww)) + ww)) + (defun company--replacement-string (lines old column nl &optional align-top) (cl-decf column company-tooltip-margin) @@ -2232,7 +2349,8 @@ (while old (push (company-modify-line (pop old) (company--offset-line (pop lines) offset) - column) new)) + column) + new)) ;; Append whole new lines. (while lines (push (concat (company-space-string column) @@ -2254,7 +2372,6 @@ (defun company--create-lines (selection limit) (let ((len company-candidates-length) - (numbered 99999) (window-width (company--window-width)) lines width @@ -2296,11 +2413,14 @@ (dotimes (_ len) (let* ((value (pop lines-copy)) (annotation (company-call-backend 'annotation value))) - (when (and annotation company-tooltip-align-annotations) - ;; `lisp-completion-at-point' adds a space. - (setq annotation (comment-string-strip annotation t nil))) + (setq value (company--clean-string (company-reformat value))) + (when annotation + (when company-tooltip-align-annotations + ;; `lisp-completion-at-point' adds a space. + (setq annotation (comment-string-strip annotation t nil))) + (setq annotation (company--clean-string annotation))) (push (cons value annotation) items) - (setq width (max (+ (string-width value) + (setq width (max (+ (length value) (if (and annotation company-tooltip-align-annotations) (1+ (length annotation)) (length annotation))) @@ -2308,22 +2428,19 @@ (setq width (min window-width (max company-tooltip-minimum-width - (if (and company-show-numbers - (< company-tooltip-offset 10)) + (if company-show-numbers (+ 2 width) width)))) - ;; number can make tooltip too long - (when company-show-numbers - (setq numbered company-tooltip-offset)) - - (let ((items (nreverse items)) new) + (let ((items (nreverse items)) + (numbered (if company-show-numbers 0 99999)) + new) (when previous (push (company--scrollpos-line previous width) new)) (dotimes (i len) (let* ((item (pop items)) - (str (company-reformat (car item))) + (str (car item)) (annotation (cdr item)) (right (company-space-string company-tooltip-margin)) (width width)) @@ -2367,26 +2484,6 @@ ;; show -(defsubst company--window-height () - (if (fboundp 'window-screen-lines) - (floor (window-screen-lines)) - (window-body-height))) - -(defsubst company--window-width () - (let ((ww (window-body-width))) - ;; Account for the line continuation column. - (when (zerop (cadr (window-fringes))) - (cl-decf ww)) - (unless (or (display-graphic-p) - (version< "24.3.1" emacs-version)) - ;; Emacs 24.3 and earlier included margins - ;; in window-width when in TTY. - (cl-decf ww - (let ((margins (window-margins))) - (+ (or (car margins) 0) - (or (cdr margins) 0))))) - ww)) - (defun company--pseudo-tooltip-height () "Calculate the appropriate tooltip height. Returns a negative number if the tooltip should be displayed above point." @@ -2413,7 +2510,7 @@ (end (save-excursion (move-to-window-line (+ row (abs height))) (point))) - (ov (make-overlay (if nl beg (1- beg)) end nil t t)) + (ov (make-overlay (if nl beg (1- beg)) end nil t)) (args (list (mapcar 'company-plainify (company-buffer-lines beg end)) column nl above))) @@ -2518,8 +2615,6 @@ (defun company-preview-show-at-point (pos) (company-preview-hide) - (setq company-preview-overlay (make-overlay pos pos)) - (let ((completion (nth company-selection company-candidates))) (setq completion (propertize completion 'face 'company-preview)) (add-text-properties 0 (length company-common) @@ -2537,11 +2632,26 @@ (and (equal pos (point)) (not (equal completion "")) - (add-text-properties 0 1 '(cursor t) completion)) - - (let ((ov company-preview-overlay)) - (overlay-put ov 'after-string completion) - (overlay-put ov 'window (selected-window))))) + (add-text-properties 0 1 '(cursor 1) completion)) + + (let* ((beg pos) + (pto company-pseudo-tooltip-overlay) + (ptf-workaround (and + pto + (char-before pos) + (eq pos (overlay-start pto))))) + ;; Try to accomodate for the pseudo-tooltip overlay, + ;; which may start at the same position if it's at eol. + (when ptf-workaround + (cl-decf beg) + (setq completion (concat (buffer-substring beg pos) completion))) + + (setq company-preview-overlay (make-overlay beg pos)) + + (let ((ov company-preview-overlay)) + (overlay-put ov (if ptf-workaround 'display 'after-string) + completion) + (overlay-put ov 'window (selected-window)))))) (defun company-preview-hide () (when company-preview-overlay
copy from elpa/company-0.8.6/company-abbrev.el copy to elpa/company-0.8.12/test/all.el --- a/elpa/company-0.8.6/company-abbrev.el +++ b/elpa/company-0.8.12/test/all.el @@ -1,8 +1,8 @@ -;;; company-abbrev.el --- company-mode completion back-end for abbrev +;;; all-tests.el --- company-mode tests -*- lexical-binding: t -*- -;; Copyright (C) 2009-2011 Free Software Foundation, Inc. +;; Copyright (C) 2015 Free Software Foundation, Inc. -;; Author: Nikolaj Schumacher +;; Author: Dmitry Gutov ;; This file is part of GNU Emacs. @@ -19,33 +19,10 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; - -;;; Code: - -(require 'company) -(require 'cl-lib) -(require 'abbrev) - -(defun company-abbrev-insert (match) - "Replace MATCH with the expanded abbrev." - (expand-abbrev)) +(defvar company-test-path + (file-name-directory (or load-file-name buffer-file-name))) -;;;###autoload -(defun company-abbrev (command &optional arg &rest ignored) - "`company-mode' completion back-end for abbrev." - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'company-abbrev - 'company-abbrev-insert)) - (prefix (company-grab-symbol)) - (candidates (nconc - (delete "" (all-completions arg global-abbrev-table)) - (delete "" (all-completions arg local-abbrev-table)))) - (meta (abbrev-expansion arg)) - (require-match t))) +(require 'ert) -(provide 'company-abbrev) -;;; company-abbrev.el ends here +(dolist (test-file (directory-files company-test-path t "-tests.el$")) + (load test-file nil t))
rename from elpa/company-0.8.6/company-tests.el rename to elpa/company-0.8.12/test/async-tests.el --- a/elpa/company-0.8.6/company-tests.el +++ b/elpa/company-0.8.12/test/async-tests.el @@ -1,8 +1,8 @@ -;;; company-tests.el --- company-mode tests -*- lexical-binding: t -*- +;;; async-tests.el --- company-mode tests -*- lexical-binding: t -*- -;; Copyright (C) 2011, 2013-2014 Free Software Foundation, Inc. +;; Copyright (C) 2015 Free Software Foundation, Inc. -;; Author: Nikolaj Schumacher +;; Author: Dmitry Gutov ;; This file is part of GNU Emacs. @@ -19,665 +19,9 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; - -;;; Code: - -(require 'ert) -(require 'company) -(require 'company-keywords) -(require 'company-clang) - -(defun company--column (&optional pos) - (car (company--col-row pos))) - -;;; Core - -(ert-deftest company-sorted-keywords () - "Test that keywords in `company-keywords-alist' are in alphabetical order." - (dolist (pair company-keywords-alist) - (when (consp (cdr pair)) - (let ((prev (cadr pair))) - (dolist (next (cddr pair)) - (should (not (equal prev next))) - (should (string< prev next)) - (setq prev next)))))) - -(ert-deftest company-good-prefix () - (let ((company-minimum-prefix-length 5) - company-abort-manual-when-too-short - company--manual-action ;idle begin - (company-selection-changed t)) ;has no effect - (should (eq t (company--good-prefix-p "!@#$%"))) - (should (eq nil (company--good-prefix-p "abcd"))) - (should (eq nil (company--good-prefix-p 'stop))) - (should (eq t (company--good-prefix-p '("foo" . 5)))) - (should (eq nil (company--good-prefix-p '("foo" . 4)))) - (should (eq t (company--good-prefix-p '("foo" . t)))))) - -(ert-deftest company--manual-prefix-set-and-unset () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abc" "abd"))))))) - (company-manual-begin) - (should (equal "ab" company--manual-prefix)) - (company-abort) - (should (null company--manual-prefix))))) - -(ert-deftest company-abort-manual-when-too-short () - (let ((company-minimum-prefix-length 5) - (company-abort-manual-when-too-short t) - (company-selection-changed t)) ;has not effect - (let ((company--manual-action nil)) ;idle begin - (should (eq t (company--good-prefix-p "!@#$%"))) - (should (eq t (company--good-prefix-p '("foo" . 5)))) - (should (eq t (company--good-prefix-p '("foo" . t))))) - (let ((company--manual-action t) - (company--manual-prefix "abc")) ;manual begin from this prefix - (should (eq t (company--good-prefix-p "!@#$"))) - (should (eq nil (company--good-prefix-p "ab"))) - (should (eq nil (company--good-prefix-p 'stop))) - (should (eq t (company--good-prefix-p '("foo" . 4)))) - (should (eq t (company--good-prefix-p "abcd"))) - (should (eq t (company--good-prefix-p "abc"))) - (should (eq t (company--good-prefix-p '("bar" . t))))))) - -(ert-deftest company-multi-backend-with-lambdas () - (let ((company-backend - (list (lambda (command &optional arg &rest ignore) - (cl-case command - (prefix "z") - (candidates '("a" "b")))) - (lambda (command &optional arg &rest ignore) - (cl-case command - (prefix "z") - (candidates '("c" "d"))))))) - (should (equal (company-call-backend 'candidates "z") '("a" "b" "c" "d"))))) - -(ert-deftest company-multi-backend-filters-backends-by-prefix () - (let ((company-backend - (list (lambda (command &optional arg &rest ignore) - (cl-case command - (prefix (cons "z" t)) - (candidates '("a" "b")))) - (lambda (command &optional arg &rest ignore) - (cl-case command - (prefix "t") - (candidates '("c" "d")))) - (lambda (command &optional arg &rest ignore) - (cl-case command - (prefix "z") - (candidates '("e" "f"))))))) - (should (equal (company-call-backend 'candidates "z") '("a" "b" "e" "f"))))) - -(ert-deftest company-multi-backend-remembers-candidate-backend () - (let ((company-backend - (list (lambda (command &optional arg) - (cl-case command - (ignore-case nil) - (annotation "1") - (candidates '("a" "c")) - (post-completion "13"))) - (lambda (command &optional arg) - (cl-case command - (ignore-case t) - (annotation "2") - (candidates '("b" "d")) - (post-completion "42"))) - (lambda (command &optional arg) - (cl-case command - (annotation "3") - (candidates '("e")) - (post-completion "74")))))) - (let ((candidates (company-calculate-candidates nil))) - (should (equal candidates '("a" "b" "c" "d" "e"))) - (should (equal t (company-call-backend 'ignore-case))) - (should (equal "1" (company-call-backend 'annotation (nth 0 candidates)))) - (should (equal "2" (company-call-backend 'annotation (nth 1 candidates)))) - (should (equal "13" (company-call-backend 'post-completion (nth 2 candidates)))) - (should (equal "42" (company-call-backend 'post-completion (nth 3 candidates)))) - (should (equal "3" (company-call-backend 'annotation (nth 4 candidates)))) - (should (equal "74" (company-call-backend 'post-completion (nth 4 candidates))))))) - -(ert-deftest company-multi-backend-handles-keyword-with () - (let ((primo (lambda (command &optional arg) - (cl-case command - (prefix "a") - (candidates '("abb" "abc" "abd"))))) - (secundo (lambda (command &optional arg) - (cl-case command - (prefix "a") - (candidates '("acc" "acd")))))) - (let ((company-backend (list 'ignore 'ignore :with secundo))) - (should (null (company-call-backend 'prefix)))) - (let ((company-backend (list 'ignore primo :with secundo))) - (should (equal "a" (company-call-backend 'prefix))) - (should (equal '("abb" "abc" "abd" "acc" "acd") - (company-call-backend 'candidates "a")))))) - -(ert-deftest company-begin-backend-failure-doesnt-break-company-backends () - (with-temp-buffer - (insert "a") - (company-mode) - (should-error - (company-begin-backend (lambda (command &rest ignore)))) - (let (company-frontends - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix "a") - (candidates '("a" "ab" "ac"))))))) - (let (this-command) - (company-call 'complete)) - (should (eq 3 company-candidates-length))))) - -(ert-deftest company-require-match-explicit () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-require-match 'company-explicit-action-p) - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abc" "abd"))))))) - (let (this-command) - (company-complete)) - (let ((last-command-event ?e)) - (company-call 'self-insert-command 1)) - (should (eq 2 company-candidates-length)) - (should (eq 3 (point)))))) - -(ert-deftest company-dont-require-match-when-idle () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-minimum-prefix-length 2) - (company-require-match 'company-explicit-action-p) - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abc" "abd"))))))) - (company-idle-begin (current-buffer) (selected-window) - (buffer-chars-modified-tick) (point)) - (should (eq 2 company-candidates-length)) - (let ((last-command-event ?e)) - (company-call 'self-insert-command 1)) - (should (eq nil company-candidates-length)) - (should (eq 4 (point)))))) - -(ert-deftest company-dont-require-match-if-old-prefix-ended-and-was-a-match () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-require-match 'company-explicit-action-p) - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (company-grab-word)) - (candidates '("abc" "ab" "abd")) - (sorted t)))))) - (let (this-command) - (company-complete)) - (let ((last-command-event ?e)) - (company-call 'self-insert-command 1)) - (should (eq 3 company-candidates-length)) - (should (eq 3 (point))) - (let ((last-command-event ? )) - (company-call 'self-insert-command 1)) - (should (null company-candidates-length)) - (should (eq 4 (point)))))) - -(ert-deftest company-should-complete-whitelist () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - company-begin-commands - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abc" "abd"))))))) - (let ((company-continue-commands nil)) - (let (this-command) - (company-complete)) - (company-call 'backward-delete-char 1) - (should (null company-candidates-length))) - (let ((company-continue-commands '(backward-delete-char))) - (let (this-command) - (company-complete)) - (company-call 'backward-delete-char 1) - (should (eq 2 company-candidates-length)))))) - -(ert-deftest company-should-complete-blacklist () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - company-begin-commands - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abc" "abd"))))))) - (let ((company-continue-commands '(not backward-delete-char))) - (let (this-command) - (company-complete)) - (company-call 'backward-delete-char 1) - (should (null company-candidates-length))) - (let ((company-continue-commands '(not backward-delete-char-untabify))) - (let (this-command) - (company-complete)) - (company-call 'backward-delete-char 1) - (should (eq 2 company-candidates-length)))))) - -(ert-deftest company-auto-complete-explicit () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-auto-complete 'company-explicit-action-p) - (company-auto-complete-chars '(? )) - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abcd" "abef"))))))) - (let (this-command) - (company-complete)) - (let ((last-command-event ? )) - (company-call 'self-insert-command 1)) - (should (string= "abcd " (buffer-string)))))) - -(ert-deftest company-no-auto-complete-when-idle () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-auto-complete 'company-explicit-action-p) - (company-auto-complete-chars '(? )) - (company-minimum-prefix-length 2) - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abcd" "abef"))))))) - (company-idle-begin (current-buffer) (selected-window) - (buffer-chars-modified-tick) (point)) - (let ((last-command-event ? )) - (company-call 'self-insert-command 1)) - (should (string= "ab " (buffer-string)))))) - -(ert-deftest company-clears-explicit-action-when-no-matches () - (with-temp-buffer - (company-mode) - (let (company-frontends - company-backends) - (company-call 'manual-begin) ;; fails - (should (null company-candidates)) - (should (null (company-explicit-action-p)))))) +(require 'company-tests) -(ert-deftest company-ignore-case-replaces-prefix () - (with-temp-buffer - (company-mode) - (let (company-frontends - company-end-of-buffer-workaround - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abcd" "abef")) - (ignore-case t)))))) - (insert "A") - (let (this-command) - (company-complete)) - (should (string= "ab" (buffer-string))) - (delete-char -2) - (insert "A") ; hack, to keep it in one test - (company-complete-selection) - (should (string= "abcd" (buffer-string)))))) - -(ert-deftest company-ignore-case-with-keep-prefix () - (with-temp-buffer - (insert "AB") - (company-mode) - (let (company-frontends - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abcd" "abef")) - (ignore-case 'keep-prefix)))))) - (let (this-command) - (company-complete)) - (company-complete-selection) - (should (string= "ABcd" (buffer-string)))))) - -(ert-deftest company-non-prefix-completion () - (with-temp-buffer - (insert "tc") - (company-mode) - (let (company-frontends - company-end-of-buffer-workaround - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("tea-cup" "teal-color"))))))) - (let (this-command) - (company-complete)) - (should (string= "tc" (buffer-string))) - (company-complete-selection) - (should (string= "tea-cup" (buffer-string)))))) - -(ert-deftest company-pseudo-tooltip-does-not-get-displaced () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (save-excursion (insert " ff")) - (company-mode) - (let ((company-frontends '(company-pseudo-tooltip-frontend)) - (company-begin-commands '(self-insert-command)) - (company-backends - (list (lambda (c &optional arg) - (cl-case c (prefix "") (candidates '("a" "b" "c"))))))) - (let (this-command) - (company-call 'complete)) - (company-call 'open-line 1) - (should (eq 1 (overlay-start company-pseudo-tooltip-overlay))))))) - -(ert-deftest company-pseudo-tooltip-show () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "aaaa\n bb\nccccccc\nddd") - (search-backward "bb") - (let ((col (company--column)) - (company-candidates-length 2) - (company-candidates '("123" "45")) - (company-backend 'ignore)) - (company-pseudo-tooltip-show (company--row) col 0) - (let ((ov company-pseudo-tooltip-overlay)) - ;; With margins. - (should (eq (overlay-get ov 'company-width) 5)) - ;; FIXME: Make it 2? - (should (eq (overlay-get ov 'company-height) company-tooltip-limit)) - (should (eq (overlay-get ov 'company-column) col)) - (should (string= (overlay-get ov 'company-display) - "\n 123 \nc 45 c\nddd\n"))))))) - -(ert-deftest company-pseudo-tooltip-edit-updates-width () - :tags '(interactive) - (with-temp-buffer - (set-window-buffer nil (current-buffer)) - (let ((company-candidates-length 5) - (company-candidates '("123" "45" "67" "89" "1011")) - (company-backend 'ignore) - (company-tooltip-limit 4) - (company-tooltip-offset-display 'scrollbar)) - (company-pseudo-tooltip-show (company--row) - (company--column) - 0) - (should (eq (overlay-get company-pseudo-tooltip-overlay 'company-width) - 6)) - (company-pseudo-tooltip-edit 4) - (should (eq (overlay-get company-pseudo-tooltip-overlay 'company-width) - 7))))) - -(ert-deftest company-preview-show-with-annotations () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (save-excursion (insert "\n")) - (let ((company-candidates-length 1) - (company-candidates '("123"))) - (company-preview-show-at-point (point)) - (let* ((ov company-preview-overlay) - (str (overlay-get ov 'after-string))) - (should (string= str "123")) - (should (eq (get-text-property 0 'cursor str) t))))))) - -(ert-deftest company-pseudo-tooltip-show-with-annotations () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert " ") - (save-excursion (insert "\n")) - (let ((company-candidates-length 2) - (company-backend (lambda (action &optional arg &rest _ignore) - (when (eq action 'annotation) - (cdr (assoc arg '(("123" . "(4)"))))))) - (company-candidates '("123" "45")) - company-tooltip-align-annotations) - (company-pseudo-tooltip-show-at-point (point) 0) - (let ((ov company-pseudo-tooltip-overlay)) - ;; With margins. - (should (eq (overlay-get ov 'company-width) 8)) - (should (string= (overlay-get ov 'company-display) - "\n 123(4) \n 45 \n"))))))) - -(ert-deftest company-pseudo-tooltip-show-with-annotations-right-aligned () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert " ") - (save-excursion (insert "\n")) - (let ((company-candidates-length 3) - (company-backend (lambda (action &optional arg &rest _ignore) - (when (eq action 'annotation) - (cdr (assoc arg '(("123" . "(4)") - ("67" . "(891011)"))))))) - (company-candidates '("123" "45" "67")) - (company-tooltip-align-annotations t)) - (company-pseudo-tooltip-show-at-point (point) 0) - (let ((ov company-pseudo-tooltip-overlay)) - ;; With margins. - (should (eq (overlay-get ov 'company-width) 13)) - (should (string= (overlay-get ov 'company-display) - "\n 123 (4) \n 45 \n 67 (891011) \n"))))))) - -(ert-deftest company-create-lines-shows-numbers () - (let ((company-show-numbers t) - (company-candidates '("x" "y" "z")) - (company-candidates-length 3) - (company-backend 'ignore)) - (should (equal '(" x 1 " " y 2 " " z 3 ") - (company--create-lines 0 999))))) - -(ert-deftest company-create-lines-truncates-annotations () - (let* ((ww (company--window-width)) - (data `(("1" . "(123)") - ("2" . nil) - ("3" . ,(concat "(" (make-string (- ww 2) ?4) ")")) - (,(make-string ww ?4) . "<4>"))) - (company-candidates (mapcar #'car data)) - (company-candidates-length 4) - (company-tooltip-margin 1) - (company-backend (lambda (cmd &optional arg) - (when (eq cmd 'annotation) - (cdr (assoc arg data))))) - company-tooltip-align-annotations) - (should (equal (list (format " 1(123)%s " (company-space-string (- ww 8))) - (format " 2%s " (company-space-string (- ww 3))) - (format " 3(444%s " (make-string (- ww 7) ?4)) - (format " %s " (make-string (- ww 2) ?4))) - (company--create-lines 0 999))) - (let ((company-tooltip-align-annotations t)) - (should (equal (list (format " 1%s(123) " (company-space-string (- ww 8))) - (format " 2%s " (company-space-string (- ww 3))) - (format " 3 (444%s " (make-string (- ww 8) ?4)) - (format " %s " (make-string (- ww 2) ?4))) - (company--create-lines 0 999)))))) - -(ert-deftest company-create-lines-truncates-common-part () - (let* ((ww (company--window-width)) - (company-candidates-length 2) - (company-tooltip-margin 1) - (company-backend #'ignore)) - (let* ((company-common (make-string (- ww 3) ?1)) - (company-candidates `(,(concat company-common "2") - ,(concat company-common "3")))) - (should (equal (list (format " %s2 " (make-string (- ww 3) ?1)) - (format " %s3 " (make-string (- ww 3) ?1))) - (company--create-lines 0 999)))) - (let* ((company-common (make-string (- ww 2) ?1)) - (company-candidates `(,(concat company-common "2") - ,(concat company-common "3")))) - (should (equal (list (format " %s " company-common) - (format " %s " company-common)) - (company--create-lines 0 999)))) - (let* ((company-common (make-string ww ?1)) - (company-candidates `(,(concat company-common "2") - ,(concat company-common "3"))) - (res (company--create-lines 0 999))) - (should (equal (list (format " %s " (make-string (- ww 2) ?1)) - (format " %s " (make-string (- ww 2) ?1))) - res)) - (should (eq 'company-tooltip-common-selection - (get-text-property (- ww 2) 'face - (car res)))) - (should (eq 'company-tooltip-selection - (get-text-property (1- ww) 'face - (car res)))) - ))) - -(ert-deftest company-create-lines-clears-out-non-printables () - :tags '(interactive) - (let (company-show-numbers - (company-candidates (list - (decode-coding-string "avalis\351e" 'utf-8) - "avatar")) - (company-candidates-length 2) - (company-backend 'ignore)) - (should (equal '(" avalis‗e " - " avatar ") - (company--create-lines 0 999))))) - -(ert-deftest company-create-lines-handles-multiple-width () - :tags '(interactive) - (let (company-show-numbers - (company-candidates '("蛙蛙蛙蛙" "蛙abc")) - (company-candidates-length 2) - (company-backend 'ignore)) - (should (equal '(" 蛙蛙蛙蛙 " - " 蛙abc ") - (company--create-lines 0 999))))) - -(ert-deftest company-column-with-composition () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "lambda ()") - (compose-region 1 (1+ (length "lambda")) "\\") - (should (= (company--column) 4))))) - -(ert-deftest company-column-with-line-prefix () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "foo") - (put-text-property (point-min) (point) 'line-prefix " ") - (should (= (company--column) 5))))) - -(ert-deftest company-column-with-line-prefix-on-empty-line () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "\n") - (forward-char -1) - (put-text-property (point-min) (point-max) 'line-prefix " ") - (should (= (company--column) 2))))) - -(ert-deftest company-column-with-tabs () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "|\t|\t|\t(") - (let ((tab-width 8)) - (should (= (company--column) 25)))))) - -(ert-deftest company-row-with-header-line-format () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (should (= (company--row) 0)) - (setq header-line-format "aaaaaaa") - (should (= (company--row) 0))))) - -(ert-deftest company-plainify () - (let ((tab-width 8)) - (should (equal-including-properties - (company-plainify "\tabc\td\t") - (concat " " - "abc " - "d ")))) - (should (equal-including-properties - (company-plainify (propertize "foobar" 'line-prefix "-*-")) - "-*-foobar"))) - -(ert-deftest company-buffer-lines-with-lines-folded () - :tags '(interactive) - (with-temp-buffer - (insert (propertize "aaa\nbbb\nccc\nddd\n" 'display "aaa+\n")) - (insert "eee\nfff\nggg") - (should (equal (company-buffer-lines (point-min) (point-max)) - '("aaa" "eee" "fff" "ggg"))))) - -(ert-deftest company-buffer-lines-with-multiline-display () - :tags '(interactive) - (with-temp-buffer - (insert (propertize "a" 'display "bbb\nccc\ndddd\n")) - (insert "eee\nfff\nggg") - (should (equal (company-buffer-lines (point-min) (point-max)) - '("" "" "" "eee" "fff" "ggg"))))) - -(ert-deftest company-modify-line () - (let ((str "-*-foobar")) - (should (equal-including-properties - (company-modify-line str "zz" 4) - "-*-fzzbar")) - (should (equal-including-properties - (company-modify-line str "xx" 0) - "xx-foobar")) - (should (equal-including-properties - (company-modify-line str "zz" 10) - "-*-foobar zz")))) - -(ert-deftest company-scrollbar-bounds () - (should (equal nil (company--scrollbar-bounds 0 3 3))) - (should (equal nil (company--scrollbar-bounds 0 4 3))) - (should (equal '(0 . 0) (company--scrollbar-bounds 0 1 2))) - (should (equal '(1 . 1) (company--scrollbar-bounds 2 2 4))) - (should (equal '(2 . 3) (company--scrollbar-bounds 7 4 12))) - (should (equal '(1 . 2) (company--scrollbar-bounds 3 4 12))) - (should (equal '(1 . 3) (company--scrollbar-bounds 4 5 11)))) - -;;; Async - -(defun company-async-backend (command &optional arg) +(defun company-async-backend (command &optional _) (pcase command (`prefix "foo") (`candidates @@ -788,7 +132,7 @@ (ert-deftest company-multi-backend-merges-deferred-candidates () (with-temp-buffer - (let* ((immediate (lambda (command &optional arg) + (let* ((immediate (lambda (command &optional _) (pcase command (`prefix "foo") (`candidates @@ -805,7 +149,7 @@ (run-with-timer 0.01 nil (lambda () (funcall cb '("a" "b"))))))))) - (lambda (command &optional arg) + (lambda (command &optional _) (pcase command (`prefix "foo") (`candidates '("c" "d" "e")))) @@ -816,130 +160,58 @@ (let ((company-backend (list immediate))) (should (equal '("f") (company-call-backend 'candidates "foo"))))))) -;;; Transformers - -(ert-deftest company-occurrence-prefer-closest-above () - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "foo0 -foo1 -") - (save-excursion - (insert " -foo3 -foo2")) - (let ((company-backend 'company-dabbrev) - (company-occurrence-weight-function - 'company-occurrence-prefer-closest-above)) - (should (equal '("foo1" "foo0" "foo3" "foo2" "foo4") - (company-sort-by-occurrence - '("foo0" "foo1" "foo2" "foo3" "foo4")))))))) - -(ert-deftest company-occurrence-prefer-any-closest () +(ert-deftest company-multi-backend-merges-deferred-candidates-2 () (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "foo0 -foo1 -") - (save-excursion - (insert " -foo3 -foo2")) - (let ((company-backend 'company-dabbrev) - (company-occurrence-weight-function - 'company-occurrence-prefer-any-closest)) - (should (equal '("foo1" "foo3" "foo0" "foo2" "foo4") - (company-sort-by-occurrence - '("foo0" "foo1" "foo2" "foo3" "foo4")))))))) - -;;; Template + (let ((company-backend (list (lambda (command &optional _) + (pcase command + (`prefix "foo") + (`candidates + (cons :async + (lambda (cb) (funcall cb '("a" "b"))))))) + (lambda (command &optional _) + (pcase command + (`prefix "foo") + (`candidates + (cons :async + (lambda (cb) (funcall cb '("c" "d"))))))) + (lambda (command &optional _) + (pcase command + (`prefix "foo") + (`candidates + (cons :async + (lambda (cb) (funcall cb '("e" "f")))))))))) + (should (equal :async (car (company-call-backend-raw 'candidates "foo")))) + (should (equal '("a" "b" "c" "d" "e" "f") + (company-call-backend 'candidates "foo")))))) -(ert-deftest company-template-removed-after-the-last-jump () - (with-temp-buffer - (insert "{ }") - (goto-char 2) - (let ((tpl (company-template-declare-template (point) (1- (point-max))))) - (save-excursion - (dotimes (i 2) - (insert " ") - (company-template-add-field tpl (point) "foo"))) - (company-call 'template-forward-field) - (should (= 3 (point))) - (company-call 'template-forward-field) - (should (= 7 (point))) - (company-call 'template-forward-field) - (should (= 11 (point))) - (should (zerop (length (overlay-get tpl 'company-template-fields)))) - (should (null (overlay-buffer tpl)))))) - -(ert-deftest company-template-removed-after-input-and-jump () +(ert-deftest company-multi-backend-merges-deferred-candidates-3 () (with-temp-buffer - (insert "{ }") - (goto-char 2) - (let ((tpl (company-template-declare-template (point) (1- (point-max))))) - (save-excursion - (insert " ") - (company-template-add-field tpl (point) "bar")) - (company-call 'template-move-to-first tpl) - (should (= 3 (point))) - (dolist (c (string-to-list "tee")) - (let ((last-command-event c)) - (company-call 'self-insert-command 1))) - (should (string= "{ tee }" (buffer-string))) - (should (overlay-buffer tpl)) - (company-call 'template-forward-field) - (should (= 7 (point))) - (should (null (overlay-buffer tpl)))))) - -(defun company-call (name &rest args) - (let* ((maybe (intern (format "company-%s" name))) - (command (if (fboundp maybe) maybe name))) - (let ((this-command command)) - (run-hooks 'pre-command-hook)) - (apply command args) - (let ((this-command command)) - (run-hooks 'post-command-hook)))) - -(ert-deftest company-template-c-like-templatify () - (with-temp-buffer - (let ((text "foo(int a, short b)")) - (insert text) - (company-template-c-like-templatify text) - (should (equal "foo(arg0, arg1)" (buffer-string))) - (should (looking-at "arg0")) - (should (equal "int a" - (overlay-get (company-template-field-at) 'display)))))) - -(ert-deftest company-template-c-like-templatify-trims-after-closing-paren () - (with-temp-buffer - (let ((text "foo(int a, short b)!@ #1334 a")) - (insert text) - (company-template-c-like-templatify text) - (should (equal "foo(arg0, arg1)" (buffer-string))) - (should (looking-at "arg0"))))) - -(ert-deftest company-template-c-like-templatify-generics () - (with-temp-buffer - (let ((text "foo<TKey, TValue>(int i, Dict<TKey, TValue>, long l)")) - (insert text) - (company-template-c-like-templatify text) - (should (equal "foo<arg0, arg1>(arg2, arg3, arg4)" (buffer-string))) - (should (looking-at "arg0")) - (should (equal "TKey" (overlay-get (company-template-field-at) 'display))) - (search-forward "arg3") - (forward-char -1) - (should (equal "Dict<TKey, TValue>" - (overlay-get (company-template-field-at) 'display)))))) - -;;; Clang - -(ert-deftest company-clang-objc-templatify () - (with-temp-buffer - (let ((text "createBookWithTitle:andAuthor:")) - (insert text) - (company-clang-objc-templatify text) - (should (equal "createBookWithTitle:arg0 andAuthor:arg1" (buffer-string))) - (should (looking-at "arg0")) - (should (null (overlay-get (company-template-field-at) 'display)))))) + (let ((company-backend (list (lambda (command &optional _) + (pcase command + (`prefix "foo") + (`candidates + (cons :async + (lambda (cb) (funcall cb '("a" "b"))))))) + (lambda (command &optional _) + (pcase command + (`prefix "foo") + (`candidates + (cons :async + (lambda (cb) + (run-with-timer + 0.01 nil + (lambda () + (funcall cb '("c" "d"))))))))) + (lambda (command &optional _) + (pcase command + (`prefix "foo") + (`candidates + (cons :async + (lambda (cb) + (run-with-timer + 0.01 nil + (lambda () + (funcall cb '("e" "f")))))))))))) + (should (equal :async (car (company-call-backend-raw 'candidates "foo")))) + (should (equal '("a" "b" "c" "d" "e" "f") + (company-call-backend 'candidates "foo"))))))
copy from elpa/company-0.8.6/company-abbrev.el copy to elpa/company-0.8.12/test/clang-tests.el --- a/elpa/company-0.8.6/company-abbrev.el +++ b/elpa/company-0.8.12/test/clang-tests.el @@ -1,8 +1,8 @@ -;;; company-abbrev.el --- company-mode completion back-end for abbrev +;;; clang-tests.el --- company-mode tests -*- lexical-binding: t -*- -;; Copyright (C) 2009-2011 Free Software Foundation, Inc. +;; Copyright (C) 2015 Free Software Foundation, Inc. -;; Author: Nikolaj Schumacher +;; Author: Dmitry Gutov ;; This file is part of GNU Emacs. @@ -19,33 +19,28 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; - -;;; Code: +(require 'company-tests) +(require 'company-clang) -(require 'company) -(require 'cl-lib) -(require 'abbrev) - -(defun company-abbrev-insert (match) - "Replace MATCH with the expanded abbrev." - (expand-abbrev)) +(ert-deftest company-clang-objc-templatify () + (with-temp-buffer + (let ((text "createBookWithTitle:andAuthor:")) + (insert text) + (company-clang-objc-templatify text) + (should (equal "createBookWithTitle:arg0 andAuthor:arg1" (buffer-string))) + (should (looking-at "arg0")) + (should (null (overlay-get (company-template-field-at) 'display)))))) -;;;###autoload -(defun company-abbrev (command &optional arg &rest ignored) - "`company-mode' completion back-end for abbrev." - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'company-abbrev - 'company-abbrev-insert)) - (prefix (company-grab-symbol)) - (candidates (nconc - (delete "" (all-completions arg global-abbrev-table)) - (delete "" (all-completions arg local-abbrev-table)))) - (meta (abbrev-expansion arg)) - (require-match t))) +(ert-deftest company-clang-simple-annotation () + (let ((str (propertize + "foo" 'meta + "wchar_t * wmemchr(wchar_t *__p, wchar_t __c, size_t __n)"))) + (should (equal (company-clang 'annotation str) + "(wchar_t *__p, wchar_t __c, size_t __n)")))) -(provide 'company-abbrev) -;;; company-abbrev.el ends here +(ert-deftest company-clang-generic-annotation () + (let ((str (propertize + "foo" 'meta + "shared_ptr<_Tp> make_shared<typename _Tp>(_Args &&__args...)"))) + (should (equal (company-clang 'annotation str) + "<typename _Tp>(_Args &&__args...)"))))
copy from elpa/company-0.8.6/company-tests.el copy to elpa/company-0.8.12/test/core-tests.el --- a/elpa/company-0.8.6/company-tests.el +++ b/elpa/company-0.8.12/test/core-tests.el @@ -1,8 +1,8 @@ -;;; company-tests.el --- company-mode tests -*- lexical-binding: t -*- +;;; core-tests.el --- company-mode tests -*- lexical-binding: t -*- -;; Copyright (C) 2011, 2013-2014 Free Software Foundation, Inc. +;; Copyright (C) 2015 Free Software Foundation, Inc. -;; Author: Nikolaj Schumacher +;; Author: Dmitry Gutov ;; This file is part of GNU Emacs. @@ -19,31 +19,7 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; - -;;; Code: - -(require 'ert) -(require 'company) -(require 'company-keywords) -(require 'company-clang) - -(defun company--column (&optional pos) - (car (company--col-row pos))) - -;;; Core - -(ert-deftest company-sorted-keywords () - "Test that keywords in `company-keywords-alist' are in alphabetical order." - (dolist (pair company-keywords-alist) - (when (consp (cdr pair)) - (let ((prev (cadr pair))) - (dolist (next (cddr pair)) - (should (not (equal prev next))) - (should (string< prev next)) - (setq prev next)))))) +(require 'company-tests) (ert-deftest company-good-prefix () (let ((company-minimum-prefix-length 5) @@ -63,7 +39,7 @@ (company-mode) (let (company-frontends (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (buffer-substring (point-min) (point))) (candidates '("abc" "abd"))))))) @@ -90,13 +66,27 @@ (should (eq t (company--good-prefix-p "abc"))) (should (eq t (company--good-prefix-p '("bar" . t))))))) +(ert-deftest company-common-with-non-prefix-completion () + (let ((company-backend #'ignore) + (company-prefix "abc") + company-candidates + company-candidates-length + company-candidates-cache + company-common) + (company-update-candidates '("abc" "def-abc")) + (should (null company-common)) + (company-update-candidates '("abc" "abe-c")) + (should (null company-common)) + (company-update-candidates '("abcd" "abcde" "abcdf")) + (should (equal "abcd" company-common)))) + (ert-deftest company-multi-backend-with-lambdas () (let ((company-backend - (list (lambda (command &optional arg &rest ignore) + (list (lambda (command &optional _ &rest _r) (cl-case command (prefix "z") (candidates '("a" "b")))) - (lambda (command &optional arg &rest ignore) + (lambda (command &optional _ &rest _r) (cl-case command (prefix "z") (candidates '("c" "d"))))))) @@ -104,15 +94,15 @@ (ert-deftest company-multi-backend-filters-backends-by-prefix () (let ((company-backend - (list (lambda (command &optional arg &rest ignore) + (list (lambda (command &optional _ &rest _r) (cl-case command (prefix (cons "z" t)) (candidates '("a" "b")))) - (lambda (command &optional arg &rest ignore) + (lambda (command &optional _ &rest _r) (cl-case command (prefix "t") (candidates '("c" "d")))) - (lambda (command &optional arg &rest ignore) + (lambda (command &optional _ &rest _r) (cl-case command (prefix "z") (candidates '("e" "f"))))))) @@ -120,19 +110,19 @@ (ert-deftest company-multi-backend-remembers-candidate-backend () (let ((company-backend - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (ignore-case nil) (annotation "1") (candidates '("a" "c")) (post-completion "13"))) - (lambda (command &optional arg) + (lambda (command &optional _) (cl-case command (ignore-case t) (annotation "2") (candidates '("b" "d")) (post-completion "42"))) - (lambda (command &optional arg) + (lambda (command &optional _) (cl-case command (annotation "3") (candidates '("e")) @@ -148,11 +138,11 @@ (should (equal "74" (company-call-backend 'post-completion (nth 4 candidates))))))) (ert-deftest company-multi-backend-handles-keyword-with () - (let ((primo (lambda (command &optional arg) + (let ((primo (lambda (command &optional _) (cl-case command (prefix "a") (candidates '("abb" "abc" "abd"))))) - (secundo (lambda (command &optional arg) + (secundo (lambda (command &optional _) (cl-case command (prefix "a") (candidates '("acc" "acd")))))) @@ -168,10 +158,10 @@ (insert "a") (company-mode) (should-error - (company-begin-backend (lambda (command &rest ignore)))) + (company-begin-backend #'ignore)) (let (company-frontends (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix "a") (candidates '("a" "ab" "ac"))))))) @@ -186,7 +176,7 @@ (let (company-frontends (company-require-match 'company-explicit-action-p) (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (buffer-substring (point-min) (point))) (candidates '("abc" "abd"))))))) @@ -205,7 +195,7 @@ (company-minimum-prefix-length 2) (company-require-match 'company-explicit-action-p) (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (buffer-substring (point-min) (point))) (candidates '("abc" "abd"))))))) @@ -217,14 +207,15 @@ (should (eq nil company-candidates-length)) (should (eq 4 (point)))))) -(ert-deftest company-dont-require-match-if-old-prefix-ended-and-was-a-match () +(ert-deftest company-dont-require-match-if-was-a-match-and-old-prefix-ended () (with-temp-buffer (insert "ab") (company-mode) (let (company-frontends - (company-require-match 'company-explicit-action-p) + company-auto-complete + (company-require-match t) (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (company-grab-word)) (candidates '("abc" "ab" "abd")) @@ -240,6 +231,26 @@ (should (null company-candidates-length)) (should (eq 4 (point)))))) +(ert-deftest company-dont-require-match-if-was-a-match-and-new-prefix-is-stop () + (with-temp-buffer + (company-mode) + (insert "c") + (let (company-frontends + (company-require-match t) + (company-backends + (list (lambda (command &optional _) + (cl-case command + (prefix (if (> (point) 2) + 'stop + (buffer-substring (point-min) (point)))) + (candidates '("a" "b" "c"))))))) + (let (this-command) + (company-complete)) + (should (eq 3 company-candidates-length)) + (let ((last-command-event ?e)) + (company-call 'self-insert-command 1)) + (should (not company-candidates))))) + (ert-deftest company-should-complete-whitelist () (with-temp-buffer (insert "ab") @@ -247,7 +258,7 @@ (let (company-frontends company-begin-commands (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (buffer-substring (point-min) (point))) (candidates '("abc" "abd"))))))) @@ -269,7 +280,7 @@ (let (company-frontends company-begin-commands (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (buffer-substring (point-min) (point))) (candidates '("abc" "abd"))))))) @@ -292,7 +303,7 @@ (company-auto-complete 'company-explicit-action-p) (company-auto-complete-chars '(? )) (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (buffer-substring (point-min) (point))) (candidates '("abcd" "abef"))))))) @@ -311,7 +322,7 @@ (company-auto-complete-chars '(? )) (company-minimum-prefix-length 2) (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (buffer-substring (point-min) (point))) (candidates '("abcd" "abef"))))))) @@ -334,9 +345,8 @@ (with-temp-buffer (company-mode) (let (company-frontends - company-end-of-buffer-workaround (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (buffer-substring (point-min) (point))) (candidates '("abcd" "abef")) @@ -356,7 +366,7 @@ (company-mode) (let (company-frontends (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (buffer-substring (point-min) (point))) (candidates '("abcd" "abef")) @@ -371,9 +381,8 @@ (insert "tc") (company-mode) (let (company-frontends - company-end-of-buffer-workaround (company-backends - (list (lambda (command &optional arg) + (list (lambda (command &optional _) (cl-case command (prefix (buffer-substring (point-min) (point))) (candidates '("tea-cup" "teal-color"))))))) @@ -383,203 +392,47 @@ (company-complete-selection) (should (string= "tea-cup" (buffer-string)))))) -(ert-deftest company-pseudo-tooltip-does-not-get-displaced () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (save-excursion (insert " ff")) - (company-mode) - (let ((company-frontends '(company-pseudo-tooltip-frontend)) - (company-begin-commands '(self-insert-command)) - (company-backends - (list (lambda (c &optional arg) - (cl-case c (prefix "") (candidates '("a" "b" "c"))))))) - (let (this-command) - (company-call 'complete)) - (company-call 'open-line 1) - (should (eq 1 (overlay-start company-pseudo-tooltip-overlay))))))) - -(ert-deftest company-pseudo-tooltip-show () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "aaaa\n bb\nccccccc\nddd") - (search-backward "bb") - (let ((col (company--column)) - (company-candidates-length 2) - (company-candidates '("123" "45")) - (company-backend 'ignore)) - (company-pseudo-tooltip-show (company--row) col 0) - (let ((ov company-pseudo-tooltip-overlay)) - ;; With margins. - (should (eq (overlay-get ov 'company-width) 5)) - ;; FIXME: Make it 2? - (should (eq (overlay-get ov 'company-height) company-tooltip-limit)) - (should (eq (overlay-get ov 'company-column) col)) - (should (string= (overlay-get ov 'company-display) - "\n 123 \nc 45 c\nddd\n"))))))) +(defvar ct-sorted nil) -(ert-deftest company-pseudo-tooltip-edit-updates-width () - :tags '(interactive) - (with-temp-buffer - (set-window-buffer nil (current-buffer)) - (let ((company-candidates-length 5) - (company-candidates '("123" "45" "67" "89" "1011")) - (company-backend 'ignore) - (company-tooltip-limit 4) - (company-tooltip-offset-display 'scrollbar)) - (company-pseudo-tooltip-show (company--row) - (company--column) - 0) - (should (eq (overlay-get company-pseudo-tooltip-overlay 'company-width) - 6)) - (company-pseudo-tooltip-edit 4) - (should (eq (overlay-get company-pseudo-tooltip-overlay 'company-width) - 7))))) - -(ert-deftest company-preview-show-with-annotations () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (save-excursion (insert "\n")) - (let ((company-candidates-length 1) - (company-candidates '("123"))) - (company-preview-show-at-point (point)) - (let* ((ov company-preview-overlay) - (str (overlay-get ov 'after-string))) - (should (string= str "123")) - (should (eq (get-text-property 0 'cursor str) t))))))) - -(ert-deftest company-pseudo-tooltip-show-with-annotations () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert " ") - (save-excursion (insert "\n")) - (let ((company-candidates-length 2) - (company-backend (lambda (action &optional arg &rest _ignore) - (when (eq action 'annotation) - (cdr (assoc arg '(("123" . "(4)"))))))) - (company-candidates '("123" "45")) - company-tooltip-align-annotations) - (company-pseudo-tooltip-show-at-point (point) 0) - (let ((ov company-pseudo-tooltip-overlay)) - ;; With margins. - (should (eq (overlay-get ov 'company-width) 8)) - (should (string= (overlay-get ov 'company-display) - "\n 123(4) \n 45 \n"))))))) +(defun ct-equal-including-properties (list1 list2) + (or (and (not list1) (not list2)) + (and (ert-equal-including-properties (car list1) (car list2)) + (ct-equal-including-properties (cdr list1) (cdr list2))))) -(ert-deftest company-pseudo-tooltip-show-with-annotations-right-aligned () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert " ") - (save-excursion (insert "\n")) - (let ((company-candidates-length 3) - (company-backend (lambda (action &optional arg &rest _ignore) - (when (eq action 'annotation) - (cdr (assoc arg '(("123" . "(4)") - ("67" . "(891011)"))))))) - (company-candidates '("123" "45" "67")) - (company-tooltip-align-annotations t)) - (company-pseudo-tooltip-show-at-point (point) 0) - (let ((ov company-pseudo-tooltip-overlay)) - ;; With margins. - (should (eq (overlay-get ov 'company-width) 13)) - (should (string= (overlay-get ov 'company-display) - "\n 123 (4) \n 45 \n 67 (891011) \n"))))))) - -(ert-deftest company-create-lines-shows-numbers () - (let ((company-show-numbers t) - (company-candidates '("x" "y" "z")) - (company-candidates-length 3) - (company-backend 'ignore)) - (should (equal '(" x 1 " " y 2 " " z 3 ") - (company--create-lines 0 999))))) - -(ert-deftest company-create-lines-truncates-annotations () - (let* ((ww (company--window-width)) - (data `(("1" . "(123)") - ("2" . nil) - ("3" . ,(concat "(" (make-string (- ww 2) ?4) ")")) - (,(make-string ww ?4) . "<4>"))) - (company-candidates (mapcar #'car data)) - (company-candidates-length 4) - (company-tooltip-margin 1) - (company-backend (lambda (cmd &optional arg) - (when (eq cmd 'annotation) - (cdr (assoc arg data))))) - company-tooltip-align-annotations) - (should (equal (list (format " 1(123)%s " (company-space-string (- ww 8))) - (format " 2%s " (company-space-string (- ww 3))) - (format " 3(444%s " (make-string (- ww 7) ?4)) - (format " %s " (make-string (- ww 2) ?4))) - (company--create-lines 0 999))) - (let ((company-tooltip-align-annotations t)) - (should (equal (list (format " 1%s(123) " (company-space-string (- ww 8))) - (format " 2%s " (company-space-string (- ww 3))) - (format " 3 (444%s " (make-string (- ww 8) ?4)) - (format " %s " (make-string (- ww 2) ?4))) - (company--create-lines 0 999)))))) +(ert-deftest company-strips-duplicates-within-groups () + (let* ((kvs '(("a" . "b") + ("a" . nil) + ("a" . "b") + ("a" . "c") + ("a" . "b") + ("b" . "c") + ("b" . nil) + ("a" . "b"))) + (fn (lambda (kvs) + (mapcar (lambda (kv) (propertize (car kv) 'ann (cdr kv))) + kvs))) + (company-backend + (lambda (command &optional arg) + (pcase command + (`prefix "") + (`sorted ct-sorted) + (`duplicates t) + (`annotation (get-text-property 0 'ann arg))))) + (reference '(("a" . "b") + ("a" . nil) + ("a" . "c") + ("b" . "c") + ("b" . nil) + ("a" . "b")))) + (let ((ct-sorted t)) + (should (ct-equal-including-properties + (company--preprocess-candidates (funcall fn kvs)) + (funcall fn reference)))) + (should (ct-equal-including-properties + (company--preprocess-candidates (funcall fn kvs)) + (funcall fn (butlast reference)))))) -(ert-deftest company-create-lines-truncates-common-part () - (let* ((ww (company--window-width)) - (company-candidates-length 2) - (company-tooltip-margin 1) - (company-backend #'ignore)) - (let* ((company-common (make-string (- ww 3) ?1)) - (company-candidates `(,(concat company-common "2") - ,(concat company-common "3")))) - (should (equal (list (format " %s2 " (make-string (- ww 3) ?1)) - (format " %s3 " (make-string (- ww 3) ?1))) - (company--create-lines 0 999)))) - (let* ((company-common (make-string (- ww 2) ?1)) - (company-candidates `(,(concat company-common "2") - ,(concat company-common "3")))) - (should (equal (list (format " %s " company-common) - (format " %s " company-common)) - (company--create-lines 0 999)))) - (let* ((company-common (make-string ww ?1)) - (company-candidates `(,(concat company-common "2") - ,(concat company-common "3"))) - (res (company--create-lines 0 999))) - (should (equal (list (format " %s " (make-string (- ww 2) ?1)) - (format " %s " (make-string (- ww 2) ?1))) - res)) - (should (eq 'company-tooltip-common-selection - (get-text-property (- ww 2) 'face - (car res)))) - (should (eq 'company-tooltip-selection - (get-text-property (1- ww) 'face - (car res)))) - ))) - -(ert-deftest company-create-lines-clears-out-non-printables () - :tags '(interactive) - (let (company-show-numbers - (company-candidates (list - (decode-coding-string "avalis\351e" 'utf-8) - "avatar")) - (company-candidates-length 2) - (company-backend 'ignore)) - (should (equal '(" avalis‗e " - " avatar ") - (company--create-lines 0 999))))) - -(ert-deftest company-create-lines-handles-multiple-width () - :tags '(interactive) - (let (company-show-numbers - (company-candidates '("蛙蛙蛙蛙" "蛙abc")) - (company-candidates-length 2) - (company-backend 'ignore)) - (should (equal '(" 蛙蛙蛙蛙 " - " 蛙abc ") - (company--create-lines 0 999))))) +;;; Row and column (ert-deftest company-column-with-composition () :tags '(interactive) @@ -626,320 +479,3 @@ (should (= (company--row) 0)) (setq header-line-format "aaaaaaa") (should (= (company--row) 0))))) - -(ert-deftest company-plainify () - (let ((tab-width 8)) - (should (equal-including-properties - (company-plainify "\tabc\td\t") - (concat " " - "abc " - "d ")))) - (should (equal-including-properties - (company-plainify (propertize "foobar" 'line-prefix "-*-")) - "-*-foobar"))) - -(ert-deftest company-buffer-lines-with-lines-folded () - :tags '(interactive) - (with-temp-buffer - (insert (propertize "aaa\nbbb\nccc\nddd\n" 'display "aaa+\n")) - (insert "eee\nfff\nggg") - (should (equal (company-buffer-lines (point-min) (point-max)) - '("aaa" "eee" "fff" "ggg"))))) - -(ert-deftest company-buffer-lines-with-multiline-display () - :tags '(interactive) - (with-temp-buffer - (insert (propertize "a" 'display "bbb\nccc\ndddd\n")) - (insert "eee\nfff\nggg") - (should (equal (company-buffer-lines (point-min) (point-max)) - '("" "" "" "eee" "fff" "ggg"))))) - -(ert-deftest company-modify-line () - (let ((str "-*-foobar")) - (should (equal-including-properties - (company-modify-line str "zz" 4) - "-*-fzzbar")) - (should (equal-including-properties - (company-modify-line str "xx" 0) - "xx-foobar")) - (should (equal-including-properties - (company-modify-line str "zz" 10) - "-*-foobar zz")))) - -(ert-deftest company-scrollbar-bounds () - (should (equal nil (company--scrollbar-bounds 0 3 3))) - (should (equal nil (company--scrollbar-bounds 0 4 3))) - (should (equal '(0 . 0) (company--scrollbar-bounds 0 1 2))) - (should (equal '(1 . 1) (company--scrollbar-bounds 2 2 4))) - (should (equal '(2 . 3) (company--scrollbar-bounds 7 4 12))) - (should (equal '(1 . 2) (company--scrollbar-bounds 3 4 12))) - (should (equal '(1 . 3) (company--scrollbar-bounds 4 5 11)))) - -;;; Async - -(defun company-async-backend (command &optional arg) - (pcase command - (`prefix "foo") - (`candidates - (cons :async - (lambda (cb) - (run-with-timer 0.05 nil - #'funcall cb '("abc" "abd"))))))) - -(ert-deftest company-call-backend-forces-sync () - (let ((company-backend 'company-async-backend) - (company-async-timeout 0.1)) - (should (equal '("abc" "abd") (company-call-backend 'candidates))))) - -(ert-deftest company-call-backend-errors-on-timeout () - (with-temp-buffer - (let* ((company-backend (lambda (command &optional _arg) - (pcase command - (`candidates (cons :async 'ignore))))) - (company-async-timeout 0.1) - (err (should-error (company-call-backend 'candidates "foo")))) - (should (string-match-p "async timeout" (cadr err)))))) - -(ert-deftest company-call-backend-raw-passes-return-value-verbatim () - (let ((company-backend 'company-async-backend)) - (should (equal "foo" (company-call-backend-raw 'prefix))) - (should (equal :async (car (company-call-backend-raw 'candidates "foo")))) - (should (equal 'closure (cadr (company-call-backend-raw 'candidates "foo")))))) - -(ert-deftest company-manual-begin-forces-async-candidates-to-sync () - (with-temp-buffer - (company-mode) - (let (company-frontends - company-transformers - (company-backends (list 'company-async-backend))) - (company-manual-begin) - (should (equal "foo" company-prefix)) - (should (equal '("abc" "abd") company-candidates))))) - -(ert-deftest company-idle-begin-allows-async-candidates () - (with-temp-buffer - (company-mode) - (let (company-frontends - company-transformers - (company-backends (list 'company-async-backend))) - (company-idle-begin (current-buffer) (selected-window) - (buffer-chars-modified-tick) (point)) - (should (null company-candidates)) - (sleep-for 0.1) - (should (equal "foo" company-prefix)) - (should (equal '("abc" "abd") company-candidates))))) - -(ert-deftest company-idle-begin-cancels-async-candidates-if-buffer-changed () - (with-temp-buffer - (company-mode) - (let (company-frontends - (company-backends (list 'company-async-backend))) - (company-idle-begin (current-buffer) (selected-window) - (buffer-chars-modified-tick) (point)) - (should (null company-candidates)) - (insert "a") - (sleep-for 0.1) - (should (null company-candidates))))) - -(ert-deftest company-idle-begin-async-allows-immediate-callbacks () - (with-temp-buffer - (company-mode) - (let (company-frontends - (company-backends - (list (lambda (command &optional arg) - (pcase command - (`prefix (buffer-substring (point-min) (point))) - (`candidates - (let ((c (all-completions arg '("abc" "def")))) - (cons :async - (lambda (cb) (funcall cb c))))) - (`no-cache t))))) - (company-minimum-prefix-length 0)) - (company-idle-begin (current-buffer) (selected-window) - (buffer-chars-modified-tick) (point)) - (should (equal '("abc" "def") company-candidates)) - (let ((last-command-event ?a)) - (company-call 'self-insert-command 1)) - (should (equal '("abc") company-candidates))))) - -(ert-deftest company-multi-backend-forces-prefix-to-sync () - (with-temp-buffer - (let ((company-backend (list 'ignore - (lambda (command) - (should (eq command 'prefix)) - (cons :async - (lambda (cb) - (run-with-timer - 0.01 nil - (lambda () (funcall cb nil)))))) - (lambda (command) - (should (eq command 'prefix)) - "foo")))) - (should (equal "foo" (company-call-backend-raw 'prefix)))) - (let ((company-backend (list (lambda (_command) - (cons :async - (lambda (cb) - (run-with-timer - 0.01 nil - (lambda () (funcall cb "bar")))))) - (lambda (_command) - "foo")))) - (should (equal "bar" (company-call-backend-raw 'prefix)))))) - -(ert-deftest company-multi-backend-merges-deferred-candidates () - (with-temp-buffer - (let* ((immediate (lambda (command &optional arg) - (pcase command - (`prefix "foo") - (`candidates - (cons :async - (lambda (cb) (funcall cb '("f")))))))) - (company-backend (list 'ignore - (lambda (command &optional arg) - (pcase command - (`prefix "foo") - (`candidates - (should (equal arg "foo")) - (cons :async - (lambda (cb) - (run-with-timer - 0.01 nil - (lambda () (funcall cb '("a" "b"))))))))) - (lambda (command &optional arg) - (pcase command - (`prefix "foo") - (`candidates '("c" "d" "e")))) - immediate))) - (should (equal :async (car (company-call-backend-raw 'candidates "foo")))) - (should (equal '("a" "b" "c" "d" "e" "f") - (company-call-backend 'candidates "foo"))) - (let ((company-backend (list immediate))) - (should (equal '("f") (company-call-backend 'candidates "foo"))))))) - -;;; Transformers - -(ert-deftest company-occurrence-prefer-closest-above () - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "foo0 -foo1 -") - (save-excursion - (insert " -foo3 -foo2")) - (let ((company-backend 'company-dabbrev) - (company-occurrence-weight-function - 'company-occurrence-prefer-closest-above)) - (should (equal '("foo1" "foo0" "foo3" "foo2" "foo4") - (company-sort-by-occurrence - '("foo0" "foo1" "foo2" "foo3" "foo4")))))))) - -(ert-deftest company-occurrence-prefer-any-closest () - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "foo0 -foo1 -") - (save-excursion - (insert " -foo3 -foo2")) - (let ((company-backend 'company-dabbrev) - (company-occurrence-weight-function - 'company-occurrence-prefer-any-closest)) - (should (equal '("foo1" "foo3" "foo0" "foo2" "foo4") - (company-sort-by-occurrence - '("foo0" "foo1" "foo2" "foo3" "foo4")))))))) - -;;; Template - -(ert-deftest company-template-removed-after-the-last-jump () - (with-temp-buffer - (insert "{ }") - (goto-char 2) - (let ((tpl (company-template-declare-template (point) (1- (point-max))))) - (save-excursion - (dotimes (i 2) - (insert " ") - (company-template-add-field tpl (point) "foo"))) - (company-call 'template-forward-field) - (should (= 3 (point))) - (company-call 'template-forward-field) - (should (= 7 (point))) - (company-call 'template-forward-field) - (should (= 11 (point))) - (should (zerop (length (overlay-get tpl 'company-template-fields)))) - (should (null (overlay-buffer tpl)))))) - -(ert-deftest company-template-removed-after-input-and-jump () - (with-temp-buffer - (insert "{ }") - (goto-char 2) - (let ((tpl (company-template-declare-template (point) (1- (point-max))))) - (save-excursion - (insert " ") - (company-template-add-field tpl (point) "bar")) - (company-call 'template-move-to-first tpl) - (should (= 3 (point))) - (dolist (c (string-to-list "tee")) - (let ((last-command-event c)) - (company-call 'self-insert-command 1))) - (should (string= "{ tee }" (buffer-string))) - (should (overlay-buffer tpl)) - (company-call 'template-forward-field) - (should (= 7 (point))) - (should (null (overlay-buffer tpl)))))) - -(defun company-call (name &rest args) - (let* ((maybe (intern (format "company-%s" name))) - (command (if (fboundp maybe) maybe name))) - (let ((this-command command)) - (run-hooks 'pre-command-hook)) - (apply command args) - (let ((this-command command)) - (run-hooks 'post-command-hook)))) - -(ert-deftest company-template-c-like-templatify () - (with-temp-buffer - (let ((text "foo(int a, short b)")) - (insert text) - (company-template-c-like-templatify text) - (should (equal "foo(arg0, arg1)" (buffer-string))) - (should (looking-at "arg0")) - (should (equal "int a" - (overlay-get (company-template-field-at) 'display)))))) - -(ert-deftest company-template-c-like-templatify-trims-after-closing-paren () - (with-temp-buffer - (let ((text "foo(int a, short b)!@ #1334 a")) - (insert text) - (company-template-c-like-templatify text) - (should (equal "foo(arg0, arg1)" (buffer-string))) - (should (looking-at "arg0"))))) - -(ert-deftest company-template-c-like-templatify-generics () - (with-temp-buffer - (let ((text "foo<TKey, TValue>(int i, Dict<TKey, TValue>, long l)")) - (insert text) - (company-template-c-like-templatify text) - (should (equal "foo<arg0, arg1>(arg2, arg3, arg4)" (buffer-string))) - (should (looking-at "arg0")) - (should (equal "TKey" (overlay-get (company-template-field-at) 'display))) - (search-forward "arg3") - (forward-char -1) - (should (equal "Dict<TKey, TValue>" - (overlay-get (company-template-field-at) 'display)))))) - -;;; Clang - -(ert-deftest company-clang-objc-templatify () - (with-temp-buffer - (let ((text "createBookWithTitle:andAuthor:")) - (insert text) - (company-clang-objc-templatify text) - (should (equal "createBookWithTitle:arg0 andAuthor:arg1" (buffer-string))) - (should (looking-at "arg0")) - (should (null (overlay-get (company-template-field-at) 'display))))))
rename from elpa/company-0.8.6/company-elisp-tests.el rename to elpa/company-0.8.12/test/elisp-tests.el --- a/elpa/company-0.8.6/company-elisp-tests.el +++ b/elpa/company-0.8.12/test/elisp-tests.el @@ -1,6 +1,6 @@ -;;; company-elisp-tests.el --- company-elisp tests +;;; elisp-tests.el --- company-elisp tests -;; Copyright (C) 2013-2014 Free Software Foundation, Inc. +;; Copyright (C) 2013-2015 Free Software Foundation, Inc. ;; Author: Dmitry Gutov @@ -19,12 +19,9 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; - ;;; Code: +(require 'company-tests) (require 'company-elisp) (defmacro company-elisp-with-buffer (contents &rest body)
copy from elpa/company-0.8.6/company-tests.el copy to elpa/company-0.8.12/test/frontends-tests.el --- a/elpa/company-0.8.6/company-tests.el +++ b/elpa/company-0.8.12/test/frontends-tests.el @@ -1,8 +1,8 @@ -;;; company-tests.el --- company-mode tests -*- lexical-binding: t -*- +;;; frontends-tests.el --- company-mode tests -*- lexical-binding: t -*- -;; Copyright (C) 2011, 2013-2014 Free Software Foundation, Inc. +;; Copyright (C) 2015 Free Software Foundation, Inc. -;; Author: Nikolaj Schumacher +;; Author: Dmitry Gutov ;; This file is part of GNU Emacs. @@ -19,369 +19,7 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; - -;;; Code: - -(require 'ert) -(require 'company) -(require 'company-keywords) -(require 'company-clang) - -(defun company--column (&optional pos) - (car (company--col-row pos))) - -;;; Core - -(ert-deftest company-sorted-keywords () - "Test that keywords in `company-keywords-alist' are in alphabetical order." - (dolist (pair company-keywords-alist) - (when (consp (cdr pair)) - (let ((prev (cadr pair))) - (dolist (next (cddr pair)) - (should (not (equal prev next))) - (should (string< prev next)) - (setq prev next)))))) - -(ert-deftest company-good-prefix () - (let ((company-minimum-prefix-length 5) - company-abort-manual-when-too-short - company--manual-action ;idle begin - (company-selection-changed t)) ;has no effect - (should (eq t (company--good-prefix-p "!@#$%"))) - (should (eq nil (company--good-prefix-p "abcd"))) - (should (eq nil (company--good-prefix-p 'stop))) - (should (eq t (company--good-prefix-p '("foo" . 5)))) - (should (eq nil (company--good-prefix-p '("foo" . 4)))) - (should (eq t (company--good-prefix-p '("foo" . t)))))) - -(ert-deftest company--manual-prefix-set-and-unset () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abc" "abd"))))))) - (company-manual-begin) - (should (equal "ab" company--manual-prefix)) - (company-abort) - (should (null company--manual-prefix))))) - -(ert-deftest company-abort-manual-when-too-short () - (let ((company-minimum-prefix-length 5) - (company-abort-manual-when-too-short t) - (company-selection-changed t)) ;has not effect - (let ((company--manual-action nil)) ;idle begin - (should (eq t (company--good-prefix-p "!@#$%"))) - (should (eq t (company--good-prefix-p '("foo" . 5)))) - (should (eq t (company--good-prefix-p '("foo" . t))))) - (let ((company--manual-action t) - (company--manual-prefix "abc")) ;manual begin from this prefix - (should (eq t (company--good-prefix-p "!@#$"))) - (should (eq nil (company--good-prefix-p "ab"))) - (should (eq nil (company--good-prefix-p 'stop))) - (should (eq t (company--good-prefix-p '("foo" . 4)))) - (should (eq t (company--good-prefix-p "abcd"))) - (should (eq t (company--good-prefix-p "abc"))) - (should (eq t (company--good-prefix-p '("bar" . t))))))) - -(ert-deftest company-multi-backend-with-lambdas () - (let ((company-backend - (list (lambda (command &optional arg &rest ignore) - (cl-case command - (prefix "z") - (candidates '("a" "b")))) - (lambda (command &optional arg &rest ignore) - (cl-case command - (prefix "z") - (candidates '("c" "d"))))))) - (should (equal (company-call-backend 'candidates "z") '("a" "b" "c" "d"))))) - -(ert-deftest company-multi-backend-filters-backends-by-prefix () - (let ((company-backend - (list (lambda (command &optional arg &rest ignore) - (cl-case command - (prefix (cons "z" t)) - (candidates '("a" "b")))) - (lambda (command &optional arg &rest ignore) - (cl-case command - (prefix "t") - (candidates '("c" "d")))) - (lambda (command &optional arg &rest ignore) - (cl-case command - (prefix "z") - (candidates '("e" "f"))))))) - (should (equal (company-call-backend 'candidates "z") '("a" "b" "e" "f"))))) - -(ert-deftest company-multi-backend-remembers-candidate-backend () - (let ((company-backend - (list (lambda (command &optional arg) - (cl-case command - (ignore-case nil) - (annotation "1") - (candidates '("a" "c")) - (post-completion "13"))) - (lambda (command &optional arg) - (cl-case command - (ignore-case t) - (annotation "2") - (candidates '("b" "d")) - (post-completion "42"))) - (lambda (command &optional arg) - (cl-case command - (annotation "3") - (candidates '("e")) - (post-completion "74")))))) - (let ((candidates (company-calculate-candidates nil))) - (should (equal candidates '("a" "b" "c" "d" "e"))) - (should (equal t (company-call-backend 'ignore-case))) - (should (equal "1" (company-call-backend 'annotation (nth 0 candidates)))) - (should (equal "2" (company-call-backend 'annotation (nth 1 candidates)))) - (should (equal "13" (company-call-backend 'post-completion (nth 2 candidates)))) - (should (equal "42" (company-call-backend 'post-completion (nth 3 candidates)))) - (should (equal "3" (company-call-backend 'annotation (nth 4 candidates)))) - (should (equal "74" (company-call-backend 'post-completion (nth 4 candidates))))))) - -(ert-deftest company-multi-backend-handles-keyword-with () - (let ((primo (lambda (command &optional arg) - (cl-case command - (prefix "a") - (candidates '("abb" "abc" "abd"))))) - (secundo (lambda (command &optional arg) - (cl-case command - (prefix "a") - (candidates '("acc" "acd")))))) - (let ((company-backend (list 'ignore 'ignore :with secundo))) - (should (null (company-call-backend 'prefix)))) - (let ((company-backend (list 'ignore primo :with secundo))) - (should (equal "a" (company-call-backend 'prefix))) - (should (equal '("abb" "abc" "abd" "acc" "acd") - (company-call-backend 'candidates "a")))))) - -(ert-deftest company-begin-backend-failure-doesnt-break-company-backends () - (with-temp-buffer - (insert "a") - (company-mode) - (should-error - (company-begin-backend (lambda (command &rest ignore)))) - (let (company-frontends - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix "a") - (candidates '("a" "ab" "ac"))))))) - (let (this-command) - (company-call 'complete)) - (should (eq 3 company-candidates-length))))) - -(ert-deftest company-require-match-explicit () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-require-match 'company-explicit-action-p) - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abc" "abd"))))))) - (let (this-command) - (company-complete)) - (let ((last-command-event ?e)) - (company-call 'self-insert-command 1)) - (should (eq 2 company-candidates-length)) - (should (eq 3 (point)))))) - -(ert-deftest company-dont-require-match-when-idle () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-minimum-prefix-length 2) - (company-require-match 'company-explicit-action-p) - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abc" "abd"))))))) - (company-idle-begin (current-buffer) (selected-window) - (buffer-chars-modified-tick) (point)) - (should (eq 2 company-candidates-length)) - (let ((last-command-event ?e)) - (company-call 'self-insert-command 1)) - (should (eq nil company-candidates-length)) - (should (eq 4 (point)))))) - -(ert-deftest company-dont-require-match-if-old-prefix-ended-and-was-a-match () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-require-match 'company-explicit-action-p) - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (company-grab-word)) - (candidates '("abc" "ab" "abd")) - (sorted t)))))) - (let (this-command) - (company-complete)) - (let ((last-command-event ?e)) - (company-call 'self-insert-command 1)) - (should (eq 3 company-candidates-length)) - (should (eq 3 (point))) - (let ((last-command-event ? )) - (company-call 'self-insert-command 1)) - (should (null company-candidates-length)) - (should (eq 4 (point)))))) - -(ert-deftest company-should-complete-whitelist () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - company-begin-commands - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abc" "abd"))))))) - (let ((company-continue-commands nil)) - (let (this-command) - (company-complete)) - (company-call 'backward-delete-char 1) - (should (null company-candidates-length))) - (let ((company-continue-commands '(backward-delete-char))) - (let (this-command) - (company-complete)) - (company-call 'backward-delete-char 1) - (should (eq 2 company-candidates-length)))))) - -(ert-deftest company-should-complete-blacklist () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - company-begin-commands - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abc" "abd"))))))) - (let ((company-continue-commands '(not backward-delete-char))) - (let (this-command) - (company-complete)) - (company-call 'backward-delete-char 1) - (should (null company-candidates-length))) - (let ((company-continue-commands '(not backward-delete-char-untabify))) - (let (this-command) - (company-complete)) - (company-call 'backward-delete-char 1) - (should (eq 2 company-candidates-length)))))) - -(ert-deftest company-auto-complete-explicit () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-auto-complete 'company-explicit-action-p) - (company-auto-complete-chars '(? )) - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abcd" "abef"))))))) - (let (this-command) - (company-complete)) - (let ((last-command-event ? )) - (company-call 'self-insert-command 1)) - (should (string= "abcd " (buffer-string)))))) - -(ert-deftest company-no-auto-complete-when-idle () - (with-temp-buffer - (insert "ab") - (company-mode) - (let (company-frontends - (company-auto-complete 'company-explicit-action-p) - (company-auto-complete-chars '(? )) - (company-minimum-prefix-length 2) - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abcd" "abef"))))))) - (company-idle-begin (current-buffer) (selected-window) - (buffer-chars-modified-tick) (point)) - (let ((last-command-event ? )) - (company-call 'self-insert-command 1)) - (should (string= "ab " (buffer-string)))))) - -(ert-deftest company-clears-explicit-action-when-no-matches () - (with-temp-buffer - (company-mode) - (let (company-frontends - company-backends) - (company-call 'manual-begin) ;; fails - (should (null company-candidates)) - (should (null (company-explicit-action-p)))))) - -(ert-deftest company-ignore-case-replaces-prefix () - (with-temp-buffer - (company-mode) - (let (company-frontends - company-end-of-buffer-workaround - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abcd" "abef")) - (ignore-case t)))))) - (insert "A") - (let (this-command) - (company-complete)) - (should (string= "ab" (buffer-string))) - (delete-char -2) - (insert "A") ; hack, to keep it in one test - (company-complete-selection) - (should (string= "abcd" (buffer-string)))))) - -(ert-deftest company-ignore-case-with-keep-prefix () - (with-temp-buffer - (insert "AB") - (company-mode) - (let (company-frontends - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("abcd" "abef")) - (ignore-case 'keep-prefix)))))) - (let (this-command) - (company-complete)) - (company-complete-selection) - (should (string= "ABcd" (buffer-string)))))) - -(ert-deftest company-non-prefix-completion () - (with-temp-buffer - (insert "tc") - (company-mode) - (let (company-frontends - company-end-of-buffer-workaround - (company-backends - (list (lambda (command &optional arg) - (cl-case command - (prefix (buffer-substring (point-min) (point))) - (candidates '("tea-cup" "teal-color"))))))) - (let (this-command) - (company-complete)) - (should (string= "tc" (buffer-string))) - (company-complete-selection) - (should (string= "tea-cup" (buffer-string)))))) +(require 'company-tests) (ert-deftest company-pseudo-tooltip-does-not-get-displaced () :tags '(interactive) @@ -393,7 +31,7 @@ (let ((company-frontends '(company-pseudo-tooltip-frontend)) (company-begin-commands '(self-insert-command)) (company-backends - (list (lambda (c &optional arg) + (list (lambda (c &optional _) (cl-case c (prefix "") (candidates '("a" "b" "c"))))))) (let (this-command) (company-call 'complete)) @@ -451,7 +89,7 @@ (let* ((ov company-preview-overlay) (str (overlay-get ov 'after-string))) (should (string= str "123")) - (should (eq (get-text-property 0 'cursor str) t))))))) + (should (eq (get-text-property 0 'cursor str) 1))))))) (ert-deftest company-pseudo-tooltip-show-with-annotations () :tags '(interactive) @@ -567,8 +205,8 @@ "avatar")) (company-candidates-length 2) (company-backend 'ignore)) - (should (equal '(" avalis‗e " - " avatar ") + (should (equal '(" avalis‗e " + " avatar ") (company--create-lines 0 999))))) (ert-deftest company-create-lines-handles-multiple-width () @@ -581,6 +219,52 @@ " 蛙abc ") (company--create-lines 0 999))))) +(ert-deftest company-create-lines-handles-multiple-width-in-annotation () + (let* (company-show-numbers + (alist '(("a" . " ︸") ("b" . " ︸︸"))) + (company-candidates (mapcar #'car alist)) + (company-candidates-length 2) + (company-backend (lambda (c &optional a) + (when (eq c 'annotation) + (assoc-default a alist))))) + (should (equal '(" a ︸ " + " b ︸︸ ") + (company--create-lines 0 999))))) + +(ert-deftest company-create-lines-with-multiple-width-and-keep-prefix () + :tags '(interactive) + (let* (company-show-numbers + (company-candidates '("MIRAI発売1カ月" + "MIRAI発売2カ月")) + (company-candidates-length 2) + (company-prefix "MIRAI発") + (company-backend (lambda (c &optional _arg) + (pcase c + (`ignore-case 'keep-prefix))))) + (should (equal '(" MIRAI発売1カ月 " + " MIRAI発売2カ月 ") + (company--create-lines 0 999))))) + +(ert-deftest company-fill-propertize-truncates-search-highlight () + (let ((company-search-string "foo") + (company-backend #'ignore) + (company-prefix "")) + (should (equal-including-properties + (company-fill-propertize "barfoo" nil 6 t nil nil) + #("barfoo" + 0 3 (face company-tooltip mouse-face company-tooltip-mouse) + 3 6 (face company-tooltip-search mouse-face company-tooltip-mouse)))) + (should (equal-including-properties + (company-fill-propertize "barfoo" nil 5 t "" " ") + #("barfo " + 0 3 (face company-tooltip mouse-face company-tooltip-mouse) + 3 5 (face company-tooltip-search mouse-face company-tooltip-mouse) + 5 6 (face company-tooltip mouse-face company-tooltip-mouse)))) + (should (equal-including-properties + (company-fill-propertize "barfoo" nil 3 t " " " ") + #(" bar " + 0 5 (face company-tooltip mouse-face company-tooltip-mouse)))))) + (ert-deftest company-column-with-composition () :tags '(interactive) (with-temp-buffer @@ -590,43 +274,6 @@ (compose-region 1 (1+ (length "lambda")) "\\") (should (= (company--column) 4))))) -(ert-deftest company-column-with-line-prefix () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "foo") - (put-text-property (point-min) (point) 'line-prefix " ") - (should (= (company--column) 5))))) - -(ert-deftest company-column-with-line-prefix-on-empty-line () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "\n") - (forward-char -1) - (put-text-property (point-min) (point-max) 'line-prefix " ") - (should (= (company--column) 2))))) - -(ert-deftest company-column-with-tabs () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "|\t|\t|\t(") - (let ((tab-width 8)) - (should (= (company--column) 25)))))) - -(ert-deftest company-row-with-header-line-format () - :tags '(interactive) - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (should (= (company--row) 0)) - (setq header-line-format "aaaaaaa") - (should (= (company--row) 0))))) - (ert-deftest company-plainify () (let ((tab-width 8)) (should (equal-including-properties @@ -654,6 +301,15 @@ (should (equal (company-buffer-lines (point-min) (point-max)) '("" "" "" "eee" "fff" "ggg"))))) +(ert-deftest company-buffer-lines-with-multiline-after-string-at-eob () + :tags '(interactive) + (with-temp-buffer + (insert "a\nb\nc\n") + (let ((ov (make-overlay (point-max) (point-max) nil t t))) + (overlay-put ov 'after-string "~\n~\n~")) + (should (equal (company-buffer-lines (point-min) (point-max)) + '("a" "b" "c"))))) + (ert-deftest company-modify-line () (let ((str "-*-foobar")) (should (equal-including-properties @@ -674,272 +330,3 @@ (should (equal '(2 . 3) (company--scrollbar-bounds 7 4 12))) (should (equal '(1 . 2) (company--scrollbar-bounds 3 4 12))) (should (equal '(1 . 3) (company--scrollbar-bounds 4 5 11)))) - -;;; Async - -(defun company-async-backend (command &optional arg) - (pcase command - (`prefix "foo") - (`candidates - (cons :async - (lambda (cb) - (run-with-timer 0.05 nil - #'funcall cb '("abc" "abd"))))))) - -(ert-deftest company-call-backend-forces-sync () - (let ((company-backend 'company-async-backend) - (company-async-timeout 0.1)) - (should (equal '("abc" "abd") (company-call-backend 'candidates))))) - -(ert-deftest company-call-backend-errors-on-timeout () - (with-temp-buffer - (let* ((company-backend (lambda (command &optional _arg) - (pcase command - (`candidates (cons :async 'ignore))))) - (company-async-timeout 0.1) - (err (should-error (company-call-backend 'candidates "foo")))) - (should (string-match-p "async timeout" (cadr err)))))) - -(ert-deftest company-call-backend-raw-passes-return-value-verbatim () - (let ((company-backend 'company-async-backend)) - (should (equal "foo" (company-call-backend-raw 'prefix))) - (should (equal :async (car (company-call-backend-raw 'candidates "foo")))) - (should (equal 'closure (cadr (company-call-backend-raw 'candidates "foo")))))) - -(ert-deftest company-manual-begin-forces-async-candidates-to-sync () - (with-temp-buffer - (company-mode) - (let (company-frontends - company-transformers - (company-backends (list 'company-async-backend))) - (company-manual-begin) - (should (equal "foo" company-prefix)) - (should (equal '("abc" "abd") company-candidates))))) - -(ert-deftest company-idle-begin-allows-async-candidates () - (with-temp-buffer - (company-mode) - (let (company-frontends - company-transformers - (company-backends (list 'company-async-backend))) - (company-idle-begin (current-buffer) (selected-window) - (buffer-chars-modified-tick) (point)) - (should (null company-candidates)) - (sleep-for 0.1) - (should (equal "foo" company-prefix)) - (should (equal '("abc" "abd") company-candidates))))) - -(ert-deftest company-idle-begin-cancels-async-candidates-if-buffer-changed () - (with-temp-buffer - (company-mode) - (let (company-frontends - (company-backends (list 'company-async-backend))) - (company-idle-begin (current-buffer) (selected-window) - (buffer-chars-modified-tick) (point)) - (should (null company-candidates)) - (insert "a") - (sleep-for 0.1) - (should (null company-candidates))))) - -(ert-deftest company-idle-begin-async-allows-immediate-callbacks () - (with-temp-buffer - (company-mode) - (let (company-frontends - (company-backends - (list (lambda (command &optional arg) - (pcase command - (`prefix (buffer-substring (point-min) (point))) - (`candidates - (let ((c (all-completions arg '("abc" "def")))) - (cons :async - (lambda (cb) (funcall cb c))))) - (`no-cache t))))) - (company-minimum-prefix-length 0)) - (company-idle-begin (current-buffer) (selected-window) - (buffer-chars-modified-tick) (point)) - (should (equal '("abc" "def") company-candidates)) - (let ((last-command-event ?a)) - (company-call 'self-insert-command 1)) - (should (equal '("abc") company-candidates))))) - -(ert-deftest company-multi-backend-forces-prefix-to-sync () - (with-temp-buffer - (let ((company-backend (list 'ignore - (lambda (command) - (should (eq command 'prefix)) - (cons :async - (lambda (cb) - (run-with-timer - 0.01 nil - (lambda () (funcall cb nil)))))) - (lambda (command) - (should (eq command 'prefix)) - "foo")))) - (should (equal "foo" (company-call-backend-raw 'prefix)))) - (let ((company-backend (list (lambda (_command) - (cons :async - (lambda (cb) - (run-with-timer - 0.01 nil - (lambda () (funcall cb "bar")))))) - (lambda (_command) - "foo")))) - (should (equal "bar" (company-call-backend-raw 'prefix)))))) - -(ert-deftest company-multi-backend-merges-deferred-candidates () - (with-temp-buffer - (let* ((immediate (lambda (command &optional arg) - (pcase command - (`prefix "foo") - (`candidates - (cons :async - (lambda (cb) (funcall cb '("f")))))))) - (company-backend (list 'ignore - (lambda (command &optional arg) - (pcase command - (`prefix "foo") - (`candidates - (should (equal arg "foo")) - (cons :async - (lambda (cb) - (run-with-timer - 0.01 nil - (lambda () (funcall cb '("a" "b"))))))))) - (lambda (command &optional arg) - (pcase command - (`prefix "foo") - (`candidates '("c" "d" "e")))) - immediate))) - (should (equal :async (car (company-call-backend-raw 'candidates "foo")))) - (should (equal '("a" "b" "c" "d" "e" "f") - (company-call-backend 'candidates "foo"))) - (let ((company-backend (list immediate))) - (should (equal '("f") (company-call-backend 'candidates "foo"))))))) - -;;; Transformers - -(ert-deftest company-occurrence-prefer-closest-above () - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "foo0 -foo1 -") - (save-excursion - (insert " -foo3 -foo2")) - (let ((company-backend 'company-dabbrev) - (company-occurrence-weight-function - 'company-occurrence-prefer-closest-above)) - (should (equal '("foo1" "foo0" "foo3" "foo2" "foo4") - (company-sort-by-occurrence - '("foo0" "foo1" "foo2" "foo3" "foo4")))))))) - -(ert-deftest company-occurrence-prefer-any-closest () - (with-temp-buffer - (save-window-excursion - (set-window-buffer nil (current-buffer)) - (insert "foo0 -foo1 -") - (save-excursion - (insert " -foo3 -foo2")) - (let ((company-backend 'company-dabbrev) - (company-occurrence-weight-function - 'company-occurrence-prefer-any-closest)) - (should (equal '("foo1" "foo3" "foo0" "foo2" "foo4") - (company-sort-by-occurrence - '("foo0" "foo1" "foo2" "foo3" "foo4")))))))) - -;;; Template - -(ert-deftest company-template-removed-after-the-last-jump () - (with-temp-buffer - (insert "{ }") - (goto-char 2) - (let ((tpl (company-template-declare-template (point) (1- (point-max))))) - (save-excursion - (dotimes (i 2) - (insert " ") - (company-template-add-field tpl (point) "foo"))) - (company-call 'template-forward-field) - (should (= 3 (point))) - (company-call 'template-forward-field) - (should (= 7 (point))) - (company-call 'template-forward-field) - (should (= 11 (point))) - (should (zerop (length (overlay-get tpl 'company-template-fields)))) - (should (null (overlay-buffer tpl)))))) - -(ert-deftest company-template-removed-after-input-and-jump () - (with-temp-buffer - (insert "{ }") - (goto-char 2) - (let ((tpl (company-template-declare-template (point) (1- (point-max))))) - (save-excursion - (insert " ") - (company-template-add-field tpl (point) "bar")) - (company-call 'template-move-to-first tpl) - (should (= 3 (point))) - (dolist (c (string-to-list "tee")) - (let ((last-command-event c)) - (company-call 'self-insert-command 1))) - (should (string= "{ tee }" (buffer-string))) - (should (overlay-buffer tpl)) - (company-call 'template-forward-field) - (should (= 7 (point))) - (should (null (overlay-buffer tpl)))))) - -(defun company-call (name &rest args) - (let* ((maybe (intern (format "company-%s" name))) - (command (if (fboundp maybe) maybe name))) - (let ((this-command command)) - (run-hooks 'pre-command-hook)) - (apply command args) - (let ((this-command command)) - (run-hooks 'post-command-hook)))) - -(ert-deftest company-template-c-like-templatify () - (with-temp-buffer - (let ((text "foo(int a, short b)")) - (insert text) - (company-template-c-like-templatify text) - (should (equal "foo(arg0, arg1)" (buffer-string))) - (should (looking-at "arg0")) - (should (equal "int a" - (overlay-get (company-template-field-at) 'display)))))) - -(ert-deftest company-template-c-like-templatify-trims-after-closing-paren () - (with-temp-buffer - (let ((text "foo(int a, short b)!@ #1334 a")) - (insert text) - (company-template-c-like-templatify text) - (should (equal "foo(arg0, arg1)" (buffer-string))) - (should (looking-at "arg0"))))) - -(ert-deftest company-template-c-like-templatify-generics () - (with-temp-buffer - (let ((text "foo<TKey, TValue>(int i, Dict<TKey, TValue>, long l)")) - (insert text) - (company-template-c-like-templatify text) - (should (equal "foo<arg0, arg1>(arg2, arg3, arg4)" (buffer-string))) - (should (looking-at "arg0")) - (should (equal "TKey" (overlay-get (company-template-field-at) 'display))) - (search-forward "arg3") - (forward-char -1) - (should (equal "Dict<TKey, TValue>" - (overlay-get (company-template-field-at) 'display)))))) - -;;; Clang - -(ert-deftest company-clang-objc-templatify () - (with-temp-buffer - (let ((text "createBookWithTitle:andAuthor:")) - (insert text) - (company-clang-objc-templatify text) - (should (equal "createBookWithTitle:arg0 andAuthor:arg1" (buffer-string))) - (should (looking-at "arg0")) - (should (null (overlay-get (company-template-field-at) 'display))))))
copy from elpa/company-0.8.6/company-abbrev.el copy to elpa/company-0.8.12/test/keywords-tests.el --- a/elpa/company-0.8.6/company-abbrev.el +++ b/elpa/company-0.8.12/test/keywords-tests.el @@ -1,6 +1,6 @@ -;;; company-abbrev.el --- company-mode completion back-end for abbrev +;;; keywords-tests.el --- company-keywords tests -*- lexical-binding: t -*- -;; Copyright (C) 2009-2011 Free Software Foundation, Inc. +;; Copyright (C) 2011, 2013-2015 Free Software Foundation, Inc. ;; Author: Nikolaj Schumacher @@ -19,33 +19,14 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; - -;;; Code: - -(require 'company) -(require 'cl-lib) -(require 'abbrev) - -(defun company-abbrev-insert (match) - "Replace MATCH with the expanded abbrev." - (expand-abbrev)) +(require 'company-keywords) -;;;###autoload -(defun company-abbrev (command &optional arg &rest ignored) - "`company-mode' completion back-end for abbrev." - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'company-abbrev - 'company-abbrev-insert)) - (prefix (company-grab-symbol)) - (candidates (nconc - (delete "" (all-completions arg global-abbrev-table)) - (delete "" (all-completions arg local-abbrev-table)))) - (meta (abbrev-expansion arg)) - (require-match t))) - -(provide 'company-abbrev) -;;; company-abbrev.el ends here +(ert-deftest company-sorted-keywords () + "Test that keywords in `company-keywords-alist' are in alphabetical order." + (dolist (pair company-keywords-alist) + (when (consp (cdr pair)) + (let ((prev (cadr pair))) + (dolist (next (cddr pair)) + (should (not (equal prev next))) + (should (string< prev next)) + (setq prev next))))))
copy from elpa/company-0.8.6/company-abbrev.el copy to elpa/company-0.8.12/test/template-tests.el --- a/elpa/company-0.8.6/company-abbrev.el +++ b/elpa/company-0.8.12/test/template-tests.el @@ -1,8 +1,8 @@ -;;; company-abbrev.el --- company-mode completion back-end for abbrev +;;; template-tests.el --- company-mode tests -*- lexical-binding: t -*- -;; Copyright (C) 2009-2011 Free Software Foundation, Inc. +;; Copyright (C) 2015 Free Software Foundation, Inc. -;; Author: Nikolaj Schumacher +;; Author: Dmitry Gutov ;; This file is part of GNU Emacs. @@ -19,33 +19,73 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; - -;;; Code: +(require 'company-tests) +(require 'company-template) -(require 'company) -(require 'cl-lib) -(require 'abbrev) - -(defun company-abbrev-insert (match) - "Replace MATCH with the expanded abbrev." - (expand-abbrev)) +(ert-deftest company-template-removed-after-the-last-jump () + (with-temp-buffer + (insert "{ }") + (goto-char 2) + (let ((tpl (company-template-declare-template (point) (1- (point-max))))) + (save-excursion + (dotimes (_ 2) + (insert " ") + (company-template-add-field tpl (point) "foo"))) + (company-call 'template-forward-field) + (should (= 3 (point))) + (company-call 'template-forward-field) + (should (= 7 (point))) + (company-call 'template-forward-field) + (should (= 11 (point))) + (should (zerop (length (overlay-get tpl 'company-template-fields)))) + (should (null (overlay-buffer tpl)))))) -;;;###autoload -(defun company-abbrev (command &optional arg &rest ignored) - "`company-mode' completion back-end for abbrev." - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'company-abbrev - 'company-abbrev-insert)) - (prefix (company-grab-symbol)) - (candidates (nconc - (delete "" (all-completions arg global-abbrev-table)) - (delete "" (all-completions arg local-abbrev-table)))) - (meta (abbrev-expansion arg)) - (require-match t))) +(ert-deftest company-template-removed-after-input-and-jump () + (with-temp-buffer + (insert "{ }") + (goto-char 2) + (let ((tpl (company-template-declare-template (point) (1- (point-max))))) + (save-excursion + (insert " ") + (company-template-add-field tpl (point) "bar")) + (company-call 'template-move-to-first tpl) + (should (= 3 (point))) + (dolist (c (string-to-list "tee")) + (let ((last-command-event c)) + (company-call 'self-insert-command 1))) + (should (string= "{ tee }" (buffer-string))) + (should (overlay-buffer tpl)) + (company-call 'template-forward-field) + (should (= 7 (point))) + (should (null (overlay-buffer tpl)))))) -(provide 'company-abbrev) -;;; company-abbrev.el ends here +(ert-deftest company-template-c-like-templatify () + (with-temp-buffer + (let ((text "foo(int a, short b)")) + (insert text) + (company-template-c-like-templatify text) + (should (equal "foo(arg0, arg1)" (buffer-string))) + (should (looking-at "arg0")) + (should (equal "int a" + (overlay-get (company-template-field-at) 'display)))))) + +(ert-deftest company-template-c-like-templatify-trims-after-closing-paren () + (with-temp-buffer + (let ((text "foo(int a, short b)!@ #1334 a")) + (insert text) + (company-template-c-like-templatify text) + (should (equal "foo(arg0, arg1)" (buffer-string))) + (should (looking-at "arg0"))))) + +(ert-deftest company-template-c-like-templatify-generics () + (with-temp-buffer + (let ((text "foo<TKey, TValue>(int i, Dict<TKey, TValue>, long l)")) + (insert text) + (company-template-c-like-templatify text) + (should (equal "foo<arg0, arg1>(arg2, arg3, arg4)" (buffer-string))) + (should (looking-at "arg0")) + (should (equal "TKey" (overlay-get (company-template-field-at) 'display))) + (search-forward "arg3") + (forward-char -1) + (should (equal "Dict<TKey, TValue>" + (overlay-get (company-template-field-at) 'display))))))
copy from elpa/company-0.8.6/company-abbrev.el copy to elpa/company-0.8.12/test/transformers-tests.el --- a/elpa/company-0.8.6/company-abbrev.el +++ b/elpa/company-0.8.12/test/transformers-tests.el @@ -1,8 +1,8 @@ -;;; company-abbrev.el --- company-mode completion back-end for abbrev +;;; transformers-tests.el --- company-mode tests -*- lexical-binding: t -*- -;; Copyright (C) 2009-2011 Free Software Foundation, Inc. +;; Copyright (C) 2015 Free Software Foundation, Inc. -;; Author: Nikolaj Schumacher +;; Author: Dmitry Gutov ;; This file is part of GNU Emacs. @@ -19,33 +19,40 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. - -;;; Commentary: -;; - -;;; Code: - -(require 'company) -(require 'cl-lib) -(require 'abbrev) - -(defun company-abbrev-insert (match) - "Replace MATCH with the expanded abbrev." - (expand-abbrev)) +(require 'company-tests) -;;;###autoload -(defun company-abbrev (command &optional arg &rest ignored) - "`company-mode' completion back-end for abbrev." - (interactive (list 'interactive)) - (cl-case command - (interactive (company-begin-backend 'company-abbrev - 'company-abbrev-insert)) - (prefix (company-grab-symbol)) - (candidates (nconc - (delete "" (all-completions arg global-abbrev-table)) - (delete "" (all-completions arg local-abbrev-table)))) - (meta (abbrev-expansion arg)) - (require-match t))) +(ert-deftest company-occurrence-prefer-closest-above () + (with-temp-buffer + (save-window-excursion + (set-window-buffer nil (current-buffer)) + (insert "foo0 +foo1 +") + (save-excursion + (insert " +foo3 +foo2")) + (let ((company-backend 'company-dabbrev) + (company-occurrence-weight-function + 'company-occurrence-prefer-closest-above)) + (should (equal '("foo1" "foo0" "foo3" "foo2" "foo4") + (company-sort-by-occurrence + '("foo0" "foo1" "foo2" "foo3" "foo4")))))))) -(provide 'company-abbrev) -;;; company-abbrev.el ends here +(ert-deftest company-occurrence-prefer-any-closest () + (with-temp-buffer + (save-window-excursion + (set-window-buffer nil (current-buffer)) + (insert "foo0 +foo1 +") + (save-excursion + (insert " +foo3 +foo2")) + (let ((company-backend 'company-dabbrev) + (company-occurrence-weight-function + 'company-occurrence-prefer-any-closest)) + (should (equal '("foo1" "foo3" "foo0" "foo2" "foo4") + (company-sort-by-occurrence + '("foo0" "foo1" "foo2" "foo3" "foo4"))))))))
deleted file mode 100644 --- a/elpa/company-0.8.6/.travis.yml +++ /dev/null @@ -1,23 +0,0 @@ -# https://github.com/rolandwalker/emacs-travis - -language: emacs-lisp - -env: - matrix: - - EMACS=emacs24 - - EMACS=emacs-snapshot - -install: - - if [ "$EMACS" = "emacs24" ]; then - sudo add-apt-repository -y ppa:cassou/emacs && - sudo apt-get update -qq && - sudo apt-get install -qq emacs24 emacs24-el; - fi - - if [ "$EMACS" = "emacs-snapshot" ]; then - sudo add-apt-repository -y ppa:ubuntu-elisp/ppa && - sudo apt-get update -qq && - sudo apt-get install -qq emacs-snapshot; - fi - -script: - make test-batch EMACS=${EMACS}
deleted file mode 100644 --- a/elpa/company-0.8.6/Makefile +++ /dev/null @@ -1,31 +0,0 @@ -EMACS=emacs - -.PHONY: ert test test-batch - -package: *.el - @ver=`grep -o "Version: .*" company.el | cut -c 10-`; \ - tar cjvf company-$$ver.tar.bz2 --mode 644 `git ls-files '*.el' | xargs` - -elpa: *.el - @version=`grep -o "Version: .*" company.el | cut -c 10-`; \ - dir=company-$$version; \ - mkdir -p "$$dir"; \ - cp `git ls-files '*.el' | xargs` company-$$version; \ - echo "(define-package \"company\" \"$$version\" \ - \"Modular in-buffer completion framework\")" \ - > "$$dir"/company-pkg.el; \ - tar cvf company-$$version.tar --mode 644 "$$dir" - -clean: - @rm -rf company-*/ company-*.tar company-*.tar.bz2 *.elc ert.el - -test: - ${EMACS} -Q -nw -L . -l company-tests.el -l company-elisp-tests.el \ - --eval "(let (pop-up-windows) (ert t))" - -test-batch: - ${EMACS} -Q --batch -L . -l company-tests.el -l company-elisp-tests.el \ - --eval "(ert-run-tests-batch-and-exit '(not (tag interactive)))" - -compile: - ${EMACS} -Q --batch -L . -f batch-byte-compile company.el company-*.el
deleted file mode 100644 index d1c1410ec3ba0434e22a95ed90e6ceece46880ed..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch literal 0 Hc$@<O00001
deleted file mode 100644 index d46fc4ac5cdb8c95a47e77b76680302d24e5711d..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch literal 0 Hc$@<O00001
deleted file mode 100644 index 9cda496db8b06578ad90d4b79b8c771fccc88911..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch literal 0 Hc$@<O00001
deleted file mode 100644 index 4aa36a8ead0ffd0c76237532060f48d1c5d16dae..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch literal 0 Hc$@<O00001
deleted file mode 100644 index a12efefc1c26714ee53f92a50367f0d4ef087478..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch literal 0 Hc$@<O00001
deleted file mode 100644 index 01dd78f6fdb18ba30a76e00b39c287a2744800ce..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch literal 0 Hc$@<O00001
deleted file mode 100644 index ae6c1e9ba563171bf4687379b24f0c15683821d9..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 GIT binary patch literal 0 Hc$@<O00001
rename from elpa/elpy-1.5.1/README.rst rename to elpa/elpy-1.8.0/README.rst --- a/elpa/elpy-1.5.1/README.rst +++ b/elpa/elpy-1.8.0/README.rst @@ -24,7 +24,14 @@ First, install the required Python packages::: + # Either of these pip install rope + pip install jedi + # flake8 for code checks + pip install flake8 + # and importmagic for automatic imports + pip install importmagic + Evaluate this in your ``*scratch*`` buffer: @@ -48,6 +55,15 @@ Done. +Contact +======= + +For questions regarding Elpy, do not hesitate to open an `issue on +github`_ or visit us on IRC, channel ``#emacs-elpy`` on +``irc.freenode.net``. + +.. _issue on github: https://github.com/jorgenschaefer/elpy/issues/new + License =======
rename from elpa/elpy-1.5.1/elpy-autoloads.el rename to elpa/elpy-1.8.0/elpy-autoloads.el --- a/elpa/elpy-1.5.1/elpy-autoloads.el +++ b/elpa/elpy-1.8.0/elpy-autoloads.el @@ -1,10 +1,9 @@ ;;; elpy-autoloads.el --- automatically extracted autoloads ;; ;;; Code: - +(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) -;;;### (autoloads (elpy-config elpy-mode elpy-enable) "elpy" "elpy.el" -;;;;;; (21577 27296 562671 713000)) +;;;### (autoloads nil "elpy" "elpy.el" (21954 12867 40604 476000)) ;;; Generated autoloads from elpy.el (autoload 'elpy-enable "elpy" "\ @@ -20,9 +19,6 @@ \\[elpy-rpc-restart] to make the elpy Python process use your virtualenv. -See https://github.com/jorgenschaefer/elpy/wiki/Keybindings for a -more structured list. - \\{elpy-mode-map} \(fn &optional ARG)" t nil) @@ -35,18 +31,21 @@ \(fn)" t nil) -;;;*** - -;;;### (autoloads nil nil ("elpy-pkg.el" "elpy-refactor.el") (21577 -;;;;;; 27301 481452 517000)) +(autoload 'elpy-version "elpy" "\ +Display the version of Elpy. + +\(fn)" t nil) ;;;*** -(provide 'elpy-autoloads) +;;;### (autoloads nil nil ("elpy-pkg.el" "elpy-refactor.el") (21954 +;;;;;; 12867 294239 466000)) + +;;;*** + ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t -;; coding: utf-8 ;; End: ;;; elpy-autoloads.el ends here
rename from elpa/elpy-1.5.1/elpy-pkg.el rename to elpa/elpy-1.8.0/elpy-pkg.el --- a/elpa/elpy-1.5.1/elpy-pkg.el +++ b/elpa/elpy-1.8.0/elpy-pkg.el @@ -1,9 +1,8 @@ -(define-package "elpy" "1.5.1" +(define-package "elpy" "1.8.0" "Emacs Python Development Environment" '((company "0.8.2") (find-file-in-project "3.3") (highlight-indentation "0.5.0") - (idomenu "0.1") (pyvenv "1.3") (yasnippet "0.8.0")) )
rename from elpa/elpy-1.5.1/elpy.el rename to elpa/elpy-1.8.0/elpy.el --- a/elpa/elpy-1.5.1/elpy.el +++ b/elpa/elpy-1.8.0/elpy.el @@ -4,9 +4,9 @@ ;; Author: Jorgen Schaefer <contact@jorgenschaefer.de> ;; URL: https://github.com/jorgenschaefer/elpy -;; Version: 1.5.1 +;; Version: 1.8.0 ;; Keywords: Python, IDE, Languages, Tools -;; Package-Requires: ((company "0.8.2") (find-file-in-project "3.3") (highlight-indentation "0.5.0") (idomenu "0.1") (pyvenv "1.3") (yasnippet "0.8.0")) +;; Package-Requires: ((company "0.8.2") (find-file-in-project "3.3") (highlight-indentation "0.5.0") (pyvenv "1.3") (yasnippet "0.8.0")) ;; This program is free software; you can redistribute it and/or ;; modify it under the terms of the GNU General Public License @@ -26,46 +26,12 @@ ;; The Emacs Lisp Python Environment in Emacs ;; Elpy is an Emacs package to bring powerful Python editing to Emacs. -;; It combines a number of existing Emacs packages, and uses one of a -;; selection of Python packages for code introspection. - -;; To use, you need to install not only this package, but a few Python -;; packages as well. See the installation instructions on the wiki. - -;; Documentation is available there as well. - -;; https://github.com/jorgenschaefer/elpy/wiki - -;;; Writing Elpy Modules: - -;; A module is a function which is called with one or more arguments. -;; This first argument is the command specifier symbol, which can be -;; one of the following: - -;; global-init: -;; - Called once, when Elpy is enabled using `elpy-enable'. - -;; global-stop: -;; - Called once, when Elpy is disabled using `elpy-disable'. - -;; buffer-init: -;; - Called in a buffer when elpy-mode is enabled. - -;; buffer-stop: -;; - Called in a buffer when elpy-mode is disabled. - -;;; Writing test runners: - -;; A test runner is a function that receives four arguments, described -;; in the docstring of `elpy-test-at-point'. If only the first -;; argument is given, the test runner should find tests under this -;; directory and run them. If the others are given, the test runner -;; should run the specified test only, or as few as it can. - -;; Test runners should use an interactive spec of (interactive -;; (elpy-test-at-point)) so they can be called directly by the user. -;; For their main work, they can simply call `elpy-test-run'. See the -;; `elpy-test-discover-runner' for an example. +;; It combines a number of existing Emacs packages, both written in +;; Emacs Lisp as well as Python. + +;; For more information, read the Elpy manual: + +;; http://elpy.readthedocs.org/en/latest/index.html ;;; Code: @@ -80,7 +46,7 @@ (require 'elpy-refactor) (require 'pyvenv) -(defconst elpy-version "1.5.1" +(defconst elpy-version "1.8.0" "The version of the Elpy lisp code.") ;;;;;;;;;;;;;;;;;;;;;; @@ -91,32 +57,6 @@ :prefix "elpy-" :group 'languages) -(defcustom elpy-interactive-python-command "python" - "Command to use for the interactive shell. - -Customize this option to use a different interactive shell. If -the value starts with \"ipython\", it will set up python.el so -that it deals with ipytohon's particular prompt and features. - -From your .emacs, you can use `elpy-use-ipython' and -`elpy-use-cpython' instead." - :type '(choice (const :tag "Standard Python (python)" "python") - (const :tag "Standard Python 2 (python2)" "python2") - (const :tag "Standard Python 3 (python3)" "python3") - (const :tag "IPython" "ipython") - (string :tag "Other")) - :set (lambda (var val) - (set-default var val) - (if (string-match "ipython" val) - (elpy-use-ipython val) - (elpy-use-cpython val))) - ;; Don't use the default function because the default values are - ;; correct, and `elpy-use-cpython' is not available yet. - :initialize #'set-default - :safe (lambda (val) - (member val '("python" "python2" "python3" "ipython"))) - :group 'elpy) - (defcustom elpy-mode-hook nil "Hook run when `elpy-mode' is enabled. @@ -164,12 +104,20 @@ (defcustom elpy-project-root nil "The root of the project the current buffer is in. -The value is automatically set for new buffers using -`elpy-project-root-finder-functions', which see. +There is normally no use in setting this variable directly, as +Elpy tries to detect the project root automatically. See +`elpy-project-root-finder-functions' for a way of influencing +this. + +Setting this variable globally will override Elpy's automatic +project detection facilities entirely. Alternatively, you can set this in file- or directory-local variables using \\[add-file-local-variable] or -\\[add-dir-local-variable]." +\\[add-dir-local-variable]. + +Do not use this variable in Emacs Lisp programs. Instead, call +the `elpy-project-root' function. It will do the right thing." :type 'directory :safe 'file-directory-p :group 'elpy) @@ -211,6 +159,20 @@ (member val '("rope" "jedi" "native" nil))) :group 'elpy) +(defcustom elpy-rpc-maximum-buffer-age (* 5 60) + "Seconds after which Elpy automatically closes an unused RPC buffer. + +Elpy creates RPC buffers over time, depending on python interpreters +and the project root. When there are many projects being worked on, +these can accumulate. Setting this variable to an integer will close +buffers and processes when they have not been used for this amount of +seconds. + +Setting this variable to nil will disable the behavior." + :type '(choice (const :tag "Never" nil) + integer) + :group 'elpy) + (defcustom elpy-rpc-large-buffer-size 4096 "Size for a source buffer up to which it will be sent directly. @@ -222,7 +184,18 @@ :safe #'integerp :group 'elpy) -(defcustom elpy-rpc-python-command (if (eq window-system 'w32) +(defcustom elpy-rpc-ignored-buffer-size 102400 + "Size for a source buffer over which Elpy completion will not work. + +To provide completion, Elpy's backends have to parse the whole +file every time. For very large files, this is slow, and can make +Emacs laggy. Elpy will simply not work on buffers larger than +this to prevent this from happening." + :type 'integer + :safe #'integerp + :group 'elpy) + +(defcustom elpy-rpc-python-command (if (equal system-type "windows-nt") "pythonw" "python") "The Python interpreter for the RPC backend. @@ -264,15 +237,64 @@ (null val))) :group 'elpy) +(defcustom elpy-rpc-error-timeout 30 + "Minimum number of seconds between error popups. + +When Elpy encounters an error in the backend, it will display a +lengthy description of the problem for a bug report. This hangs +Emacs for a moment, and can be rather annoying if it happens +repeatedly while editing a source file. + +If this variabl is non-nil, Elpy will not display the error +message again within this amount of seconds." + :type 'integer + :group 'elpy) + +(defcustom elpy-eldoc-show-current-function t + "If true, show the current function if no calltip is available. + +When Elpy can not find the calltip of the function call at point, +it can show the name of the function or class and method being +edited instead. Setting this variable to nil disables this feature." + :type 'boolean + :group 'elpy) + (defcustom elpy-test-runner 'elpy-test-discover-runner "The test runner to use to run tests." :type '(choice (const :tag "Unittest Discover" elpy-test-discover-runner) (const :tag "Django Discover" elpy-test-django-runner) (const :tag "Nose" elpy-test-nose-runner) - (const :tag "py.test" elpy-test-pytest-runner)) + (const :tag "py.test" elpy-test-pytest-runner) + (const :tag "Twisted Trial" elpy-test-trial-runner)) :safe 'elpy-test-runner-p :group 'elpy) +(defcustom elpy-test-discover-runner-command '("python" "-m" "unittest") + "The command to use for `elpy-test-discover-runner'." + :type '(repeat string) + :group 'elpy) + +(defcustom elpy-test-django-runner-command '("django-admin.py" "test" + "--noinput") + "The command to use for `elpy-test-django-runner'." + :type '(repeat string) + :group 'elpy) + +(defcustom elpy-test-nose-runner-command '("nosetests") + "The command to use for `elpy-test-nose-runner'." + :type '(repeat string) + :group 'elpy) + +(defcustom elpy-test-trial-runner-command '("trial") + "The command to use for `elpy-test-trial-runner'." + :type '(repeat string) + :group 'elpy) + +(defcustom elpy-test-pytest-runner-command '("py.test") + "The command to use for `elpy-test-pytest-runner'." + :type '(repeat string) + :group 'elpy) + ;;;;;;;;;;;;; ;;; Elpy Mode @@ -292,7 +314,8 @@ (define-key map (kbd "C-c C-d") 'elpy-doc) (define-key map (kbd "C-c C-e") 'elpy-multiedit-python-symbol-at-point) (define-key map (kbd "C-c C-f") 'elpy-find-file) - (define-key map (kbd "C-c C-j") 'idomenu) + (define-key map (kbd "C-c RET") 'elpy-importmagic-add-import) + (define-key map (kbd "C-c <S-return>") 'elpy-importmagic-fixup) (define-key map (kbd "C-c C-n") 'elpy-flymake-next-error) (define-key map (kbd "C-c C-o") 'elpy-occur-definitions) (define-key map (kbd "C-c C-p") 'elpy-flymake-previous-error) @@ -305,15 +328,15 @@ (define-key map (kbd "<S-return>") 'elpy-open-and-indent-line-below) (define-key map (kbd "<C-S-return>") 'elpy-open-and-indent-line-above) - (define-key map (kbd "<C-down>") 'elpy-nav-next-iblock) - (define-key map (kbd "<C-up>") 'elpy-nav-previous-iblock) - (define-key map (kbd "<C-left>") 'elpy-nav-backward-iblock) - (define-key map (kbd "<C-right>") 'elpy-nav-forward-iblock) - - (define-key map (kbd "<M-down>") 'elpy-nav-move-iblock-down) - (define-key map (kbd "<M-up>") 'elpy-nav-move-iblock-up) - (define-key map (kbd "<M-left>") 'elpy-nav-move-iblock-left) - (define-key map (kbd "<M-right>") 'elpy-nav-move-iblock-right) + (define-key map (kbd "<C-down>") 'elpy-nav-forward-block) + (define-key map (kbd "<C-up>") 'elpy-nav-backward-block) + (define-key map (kbd "<C-left>") 'elpy-nav-backward-indent) + (define-key map (kbd "<C-right>") 'elpy-nav-forward-indent) + + (define-key map (kbd "<M-down>") 'elpy-nav-move-line-or-region-down) + (define-key map (kbd "<M-up>") 'elpy-nav-move-line-or-region-up) + (define-key map (kbd "<M-left>") 'elpy-nav-move-region-or-line-left) + (define-key map (kbd "<M-right>") 'elpy-nav-move-region-or-line-right) (define-key map (kbd "M-.") 'elpy-goto-definition) (define-key map (kbd "M-TAB") 'elpy-company-backend) @@ -366,16 +389,16 @@ ["Previous Error" elpy-flymake-previous-error :help "Go to the previous inline error, if any"]) ("Indentation Blocks" - ["Dedent" elpy-nav-move-iblock-left + ["Dedent" elpy-nav-move-region-or-line-left :help "Dedent current block or region" :suffix (if (use-region-p) "Region" "Block")] - ["Indent" elpy-nav-move-iblock-right + ["Indent" elpy-nav-move-region-or-line-right :help "Indent current block or region" :suffix (if (use-region-p) "Region" "Block")] - ["Up" elpy-nav-move-iblock-up + ["Up" elpy-nav-move-line-or-region-up :help "Move current block or region up" :suffix (if (use-region-p) "Region" "Block")] - ["Down" elpy-nav-move-iblock-down + ["Down" elpy-nav-move-line-or-region-down :help "Move current block or region down" :suffix (if (use-region-p) "Region" "Block")]) "---" @@ -416,9 +439,6 @@ \\[elpy-rpc-restart] to make the elpy Python process use your virtualenv. -See https://github.com/jorgenschaefer/elpy/wiki/Keybindings for a -more structured list. - \\{elpy-mode-map}" :lighter " Elpy" (when (not (eq major-mode 'python-mode)) @@ -463,6 +483,27 @@ (defvar elpy-config--get-config "import json import sys + +try: + import xmlrpclib +except ImportError: + import xmlrpc.client as xmlrpclib + +from distutils.version import LooseVersion + + +def latest(package, version=None): + try: + pypi = xmlrpclib.ServerProxy('https://pypi.python.org/pypi') + latest = pypi.package_releases(package)[0] + if version is None or LooseVersion(version) < LooseVersion(latest): + return latest + else: + return None + except: + return None + + config = {} config['python_version'] = ('{major}.{minor}.{micro}' .format(major=sys.version_info[0], @@ -481,15 +522,29 @@ config['jedi_version'] = '.'.join(str(x) for x in jedi.__version__) else: config['jedi_version'] = jedi.__version__ + config['jedi_latest'] = latest('jedi', config['jedi_version']) except: config['jedi_version'] = None + config['jedi_latest'] = latest('jedi') try: import rope config['rope_version'] = rope.VERSION + if sys.version_info[0] <= 2: + config['rope_latest'] = latest('rope', config['rope_version']) + else: + config['rope_latest'] = latest('rope_py3k', config['rope_version']) except: config['rope_version'] = None - + config['rope_latest'] = latest('rope') + +try: + import importmagic + config['importmagic_version'] = importmagic.__version__ + config['importmagic_latest'] = latest('importmagic', config['importmagic_version']) +except: + config['importmagic_version'] = None + config['importmagic_latest'] = latest('importmagic') json.dump(config, sys.stdout) ") @@ -534,6 +589,12 @@ (goto-char (point-min)))) (pop-to-buffer-same-window buf))) +;;;###autoload +(defun elpy-version () + "Display the version of Elpy." + (interactive) + (message "Elpy %s (use M-x elpy-config for details)" elpy-version)) + (defun elpy-config--insert-help () (let ((start (point))) ;; Help display from `customize-browse' @@ -571,108 +632,164 @@ "Insert help text and widgets for configuration problems." (when (not config) (setq config (elpy-config--get-config))) - (elpy-config--insert-configuration-table config) - (insert "\n") - - ;; Python not found - (when (not (gethash "python_rpc_executable" config)) - (elpy-insert--para - "Elpy can not find the configured Python interpreter. Please make " - "sure that the variable `elpy-rpc-python-command' points to a " - "command in your PATH. You can change the variable below.\n\n")) - - ;; No virtual env - (when (and (gethash "python_rpc_executable" config) - (not (gethash "virtual_env" (elpy-config--get-config)))) - (elpy-insert--para - "You have not activated a virtual env. While Elpy supports this, " - "it is often a good idea to work inside a virtual env. You can use " - "M-x pyvenv-activate or M-x pyvenv-workon to activate a virtual " - "env.\n\n")) - - ;; Python found, but can't find the elpy module - (when (and (gethash "python_rpc_executable" config) - (not (gethash "elpy_version" config))) - (elpy-insert--para - "The Python interpreter could not find the elpy module. " - "Make sure the module is installed" - (if (getenv "virtual_env" config) - " in the current virtualenv.\n" - ".\n")) + (let* ((python-version (gethash "python_version" config)) + (rope-pypi-package (if (and python-version + (string-match "^3\\." python-version)) + "rope_py3k" + "rope"))) + + (elpy-config--insert-configuration-table config) (insert "\n") - (widget-create 'elpy-insert--pip-button "elpy") - (insert "\n\n")) - - ;; Otherwise unparseable output. - (when (gethash "error_output" config) - (elpy-insert--para - "There was an unexpected problem starting the RPC process. Please " - "check the following output to see if this makes sense to you. " - "To me, it doesn't.\n") - (insert "\n" - (gethash "error_output" config) "\n" - "\n")) - - ;; Requested backend unavailable - (when (and (gethash "python_rpc_executable" config) - (or (and (equal elpy-rpc-backend "rope") - (not (gethash "rope_version" config))) - (and (equal elpy-rpc-backend "jedi") - (not (gethash "jedi_version" config))))) - (elpy-insert--para - "You requested Elpy to use the backend " elpy-rpc-backend ", " - "but the Python interpreter could not load that module. Make " - "sure the module is installed, or change the value of " - "`elpy-rpc-backend' below to one of the available backends.\n") - (insert "\n") - (widget-create 'elpy-insert--pip-button elpy-rpc-backend) - (insert "\n\n")) - - ;; Only native backend available, but requested automatic choice - (when (and (gethash "python_rpc_executable" config) - (and (not elpy-rpc-backend) - (not (gethash "rope_version" config)) - (not (gethash "jedi_version" config)))) - (elpy-insert--para - "You did not specify a preference for an RPC backend, but there " - "is only the native backend available. The native backend has " - "seriously limited capabilities. If you really want to use the " - "native backend, please change the value of `elpy-rpc-backend' " - "below to make this explicit. Alternatively, you can install the " - "module for one of the supported backends.\n") - (insert "\n") - (let ((python-version (gethash "python_version" config))) - (if (and python-version (string-match "^3\\." python-version)) - (widget-create 'elpy-insert--pip-button "rope_py3k") - (widget-create 'elpy-insert--pip-button "rope"))) - (insert "\n") - (widget-create 'elpy-insert--pip-button "jedi") - (insert "\n\n")) - - ;; Bad backend version - (when (and (gethash "elpy_version" config) - (not (equal (gethash "elpy_version" config) - elpy-version))) - (let ((elpy-python-version (gethash "elpy_version" config))) + + ;; Python not found + (when (not (gethash "python_rpc_executable" config)) + (elpy-insert--para + "Elpy can not find the configured Python interpreter. Please make " + "sure that the variable `elpy-rpc-python-command' points to a " + "command in your PATH. You can change the variable below.\n\n")) + + ;; No virtual env + (when (and (gethash "python_rpc_executable" config) + (not (gethash "virtual_env" config))) + (elpy-insert--para + "You have not activated a virtual env. While Elpy supports this, " + "it is often a good idea to work inside a virtual env. You can use " + "M-x pyvenv-activate or M-x pyvenv-workon to activate a virtual " + "env.\n\n")) + + ;; No virtual env, but ~/.local/bin not in PATH + (when (and (not (memq system-type '(ms-dos windows-nt))) + (gethash "python_rpc_executable" config) + (not pyvenv-virtual-env) + (not (or (member (expand-file-name "~/.local/bin") + exec-path) + (member (expand-file-name "~/.local/bin/") + exec-path)))) + (elpy-insert--para + "The directory ~/.local/bin/ is not in your PATH, even though you " + "do not have an active virtualenv. Installing Python packages " + "locally will create executables in that directory, so Emacs " + "won't find them. If you are missing some commands, do add this " + "directory to your PATH.\n\n")) + + ;; Python found, but can't find the elpy module + (when (and (gethash "python_rpc_executable" config) + (not (gethash "elpy_version" config))) + (elpy-insert--para + "The Python interpreter could not find the elpy module. " + "Make sure the module is installed" + (if (gethash "virtual_env" config) + " in the current virtualenv.\n" + ".\n")) + (insert "\n") + (widget-create 'elpy-insert--pip-button :package "elpy") + (insert "\n\n")) + + ;; Bad backend version + (when (and (gethash "elpy_version" config) + (not (equal (gethash "elpy_version" config) + elpy-version))) + (let ((elpy-python-version (gethash "elpy_version" config))) + (elpy-insert--para + "The Elpy backend is version " elpy-python-version " while " + "the Emacs package is " elpy-version ". This is incompatible. " + (if (version< elpy-python-version elpy-version) + "Please upgrade the Python module." + "Please upgrade the Emacs Lisp package.") + "\n"))) + + ;; Otherwise unparseable output. + (when (gethash "error_output" config) + (elpy-insert--para + "There was an unexpected problem starting the RPC process. Please " + "check the following output to see if this makes sense to you. " + "To me, it doesn't.\n") + (insert "\n" + (gethash "error_output" config) "\n" + "\n")) + + ;; Requested backend unavailable + (when (and (gethash "python_rpc_executable" config) + (or (and (equal elpy-rpc-backend "rope") + (not (gethash "rope_version" config))) + (and (equal elpy-rpc-backend "jedi") + (not (gethash "jedi_version" config))))) (elpy-insert--para - "The Elpy backend is version " elpy-python-version " while " - "the Emacs package is " elpy-version ". This is incompatible. " - (if (version< elpy-python-version elpy-version) - "Please upgrade the Python module." - "Please upgrade the Emacs Lisp package.") - "\n"))) - - ;; flake8, the default syntax checker, not found - (when (not (executable-find "flake8")) - (elpy-insert--para - "The configured syntax checker could not be found. Elpy uses this " - "program to provide syntax checks of your programs, so you might " - "want to install one. Elpy by default uses flake8.\n") - (insert "\n") - (widget-create 'elpy-insert--pip-button "flake8") - (insert "\n\n")) - - ) + "You requested Elpy to use the backend " elpy-rpc-backend ", " + "but the Python interpreter could not load that module. Make " + "sure the module is installed, or change the value of " + "`elpy-rpc-backend' below to one of the available backends.\n") + (insert "\n") + (widget-create 'elpy-insert--pip-button + :package (if (equal elpy-rpc-backend "rope") + rope-pypi-package + "jedi")) + (insert "\n\n")) + + ;; No backend available. + (when (and (gethash "python_rpc_executable" config) + (and (not elpy-rpc-backend) + (not (gethash "rope_version" config)) + (not (gethash "jedi_version" config)))) + (elpy-insert--para + "There is no backend available. Please install either Rope or Jedi.\n") + (insert "\n") + (widget-create 'elpy-insert--pip-button :package rope-pypi-package) + (insert "\n") + (widget-create 'elpy-insert--pip-button :package "jedi") + (insert "\n\n")) + + ;; Newer version of Rope available + (when (and (gethash "rope_version" config) + (gethash "rope_latest" config)) + (elpy-insert--para + "There is a newer version of Rope available.\n") + (insert "\n") + (widget-create 'elpy-insert--pip-button + :package rope-pypi-package :upgrade t) + (insert "\n\n")) + + ;; Newer version of Jedi available + (when (and (gethash "jedi_version" config) + (gethash "jedi_latest" config)) + (elpy-insert--para + "There is a newer version of Jedi available.\n") + (insert "\n") + (widget-create 'elpy-insert--pip-button + :package "jedi" :upgrade t) + (insert "\n\n")) + + ;; No importmagic available + (when (not (gethash "importmagic_version" config)) + (elpy-insert--para + "The importmagic package is not available. Commands using this will " + "not work.\n") + (insert "\n") + (widget-create 'elpy-insert--pip-button + :package "importmagic") + (insert "\n\n")) + + ;; Newer version of importmagic available + (when (and (gethash "importmagic_version" config) + (gethash "importmagic_latest" config)) + (elpy-insert--para + "There is a newer version of the importmagic package available.\n") + (insert "\n") + (widget-create 'elpy-insert--pip-button + :package "importmagic" :upgrade t) + (insert "\n\n")) + + ;; flake8, the default syntax checker, not found + (when (not (executable-find "flake8")) + (elpy-insert--para + "The configured syntax checker could not be found. Elpy uses this " + "program to provide syntax checks of your programs, so you might " + "want to install one. Elpy by default uses flake8.\n") + (insert "\n") + (widget-create 'elpy-insert--pip-button :package "flake8") + (insert "\n\n")) + + )) (defun elpy-config--get-config () "Return the configuration from `elpy-rpc-python-command'. @@ -707,12 +824,14 @@ (executable-find interactive-python) config)) (let ((venv (getenv "VIRTUAL_ENV"))) - (when venv - (puthash "virtual_env" venv config) - (puthash "virtual_env_short" (file-name-nondirectory venv) config))) + (puthash "virtual_env" venv config) + (if venv + (puthash "virtual_env_short" (file-name-nondirectory venv) config) + (puthash "virtual_env_short" nil config))) (let ((return-value (ignore-errors (let ((process-environment - (elpy-rpc--environment))) + (elpy-rpc--environment)) + (default-directory "/")) (call-process elpy-rpc-python-command nil (current-buffer) @@ -743,7 +862,11 @@ config)) (elpy-python-version (gethash "elpy_version" config)) (jedi-version (gethash "jedi_version" config)) + (jedi-latest (gethash "jedi_latest" config)) (rope-version (gethash "rope_version" config)) + (rope-latest (gethash "rope_latest" config)) + (importmagic-version (gethash "importmagic_version" config)) + (importmagic-latest (gethash "importmagic_latest" config)) (virtual-env (gethash "virtual_env" config)) (virtual-env-short (gethash "virtual_env_short" config)) table maxwidth) @@ -786,12 +909,15 @@ (t (format "Not found (Python), %s (Emacs Lisp)" elpy-version)))) - ("Jedi" . ,(if jedi-version - jedi-version - "Not found")) - ("Rope" . ,(if rope-version - rope-version - "Not found")) + ("Jedi" . ,(elpy-config--package-link "jedi" + jedi-version + jedi-latest)) + ("Rope" . ,(elpy-config--package-link "rope" + rope-version + rope-latest)) + ("Importmagic" . ,(elpy-config--package-link "importmagic" + importmagic-version + importmagic-latest)) ("Syntax checker" . ,(let ((syntax-checker (executable-find python-check-command))) @@ -815,6 +941,22 @@ (cdr row) "\n")))) +(defun elpy-config--package-link (name version latest) + "Return a string detailing a Python package. + +NAME is the PyPI name of the package. VERSION is the currently +installed version. LATEST is the latest-available version on +PyPI, or nil if that's VERSION." + (cond + ((and (not version) (not latest)) + "Not found") + ((not latest) + version) + ((not version) + (format "Not found (%s available)" latest)) + (t + (format "%s (%s available)" version latest)))) + ;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Elpy Formatted Insertion @@ -854,17 +996,24 @@ (defun elpy-insert--pip-button-value-create (widget) "The :value-create option for the pip button widget." - (let* ((python-module (widget-get widget :value)) + (let* ((python-package (widget-get widget :package)) + (do-upgrade (widget-get widget :upgrade)) + (upgrade-option (if do-upgrade + "--upgrade " + "")) (do-user-install (not (or (getenv "VIRTUAL_ENV") pyvenv-virtual-env))) (user-option (if do-user-install "--user " "")) + (command (cond ((executable-find "pip") - (format "pip install %s%s" user-option python-module)) + (format "pip install %s%s%s" + user-option upgrade-option python-package)) ((executable-find "easy_install") - (format "easy_install %s%s" user-option python-module)) + (format "easy_install %s%s" + user-option python-package)) (t (error "Neither easy_install nor pip found"))))) (widget-put widget :command command) @@ -1178,6 +1327,8 @@ (read-file-name "IPython command: ")))) (when (not ipython) (setq ipython "ipython")) + (when (not (executable-find ipython)) + (error "Command %S not found" ipython)) (cond ;; Emacs 24 until 24.3 ((boundp 'python-python-command) @@ -1199,8 +1350,16 @@ "';'.join(get_ipython().Completer.all_completions('''%s'''))\n")) ;; Emacs 24.4 ((boundp 'python-shell-interpreter-interactive-arg) - (setq python-shell-interpreter "ipython" - python-shell-interpreter-args "-i")) + (setq python-shell-interpreter ipython + python-shell-interpreter-args "-i") + ;; Windows requires some special handling here, see #422 + (let ((exe "C:\\Python27\\python.exe") + (ipython_py "C:\\Python27\\Scripts\\ipython-script.py")) + (when (and (eq system-type 'windows-nt) + (file-exists-p exe) + (file-exists-p ipython_py)) + (setq python-shell-interpreter exe + python-shell-interpreter-args "-i " + ipython_py)))) (t (error "I don't know how to set ipython settings for this Emacs")))) @@ -1212,6 +1371,8 @@ (read-file-name "Python command: ")))) (when (not cpython) (setq cpython "python")) + (when (not (executable-find cpython)) + (error "Command %S not found" cpython)) (cond ;; Emacs 24 until 24.3 ((boundp 'python-python-command) @@ -1224,7 +1385,7 @@ python-shell-prompt-regexp ">>> " python-shell-prompt-output-regexp "" python-shell-completion-setup-code -"try: + "try: import readline except ImportError: def __COMPLETER_all_completions(text): [] @@ -1249,7 +1410,7 @@ "';'.join(__COMPLETER_all_completions('''%s'''))\n")) ;; Emacs 24.4 ((boundp 'python-shell-interpreter-interactive-arg) - (setq python-shell-interpreter "python" + (setq python-shell-interpreter cpython python-shell-interpreter-args "-i")) (t (error "I don't know how to set ipython settings for this Emacs")))) @@ -1273,6 +1434,8 @@ (let ((region (elpy-shell--region-without-indentation (region-beginning) (region-end)))) (setq has-if-main (string-match if-main-regex region)) + (when (string-match "\t" region) + (message "Region contained tabs, this might cause weird errors")) (python-shell-send-string region)) (save-excursion (goto-char (point-min)) @@ -1288,7 +1451,7 @@ (defun elpy-shell-switch-to-shell () "Switch to inferior Python process buffer." (interactive) - (pop-to-buffer (process-buffer (elpy-shell-get-or-create-process)) t)) + (pop-to-buffer (process-buffer (elpy-shell-get-or-create-process)))) (defun elpy-shell-get-or-create-process () "Get or create an inferior Python process for current buffer and return it." @@ -1374,215 +1537,168 @@ (let ((buffer (find-file filename))) (with-current-buffer buffer (with-selected-window (get-buffer-window buffer) - (goto-char (1+ offset)))))) - -(defun elpy-nav--iblock (direction skip) - "Move point forward, skipping lines indented more than the current one. - -DIRECTION should be 1 or -1 for forward or backward. - -SKIP should be #'> to skip lines with larger indentation or #'< -to skip lines with smaller indentation." - (let ((start-indentation (current-indentation))) - (python-nav-forward-statement direction) - (while (and (not (eobp)) - (not (bobp)) - (or (looking-at "^\\s-*$") - (funcall skip - (current-indentation) - start-indentation))) - (python-nav-forward-statement direction)))) - - -(defun elpy-nav-next-iblock (&optional direction) - "Move forward to the beginning of the next indentation block. - -An indentation block is a block indented further than the current -one." + (goto-char (1+ offset)) + (recenter 0))))) + +(defun elpy-nav-forward-block () + "Move to the next line indented like point. + +This will skip over lines and statements with different +indentation levels." (interactive) - (let ((start-indentation (current-indentation)) - (new-pos (point))) - (unwind-protect - (progn - (elpy-nav--iblock direction #'>) - (when (= (current-indentation) - start-indentation) - (back-to-indentation) - (setq new-pos (point)))) - (goto-char new-pos)))) - -(defun elpy-nav-previous-iblock () - "Move forward to the beginning of the previous indentation block. - -An indentation block is a block indented further than the current -one." + (let ((indent (current-column)) + (start (point))) + (when (/= (% indent python-indent-offset) + 0) + (setq indent (* (1+ (/ indent python-indent-offset)) + python-indent-offset))) + (python-nav-forward-statement) + (while (and (< indent (current-indentation)) + (not (eobp))) + (python-nav-forward-statement)) + (when (< (current-indentation) + indent) + (goto-char start)))) + +(defun elpy-nav-backward-block () + "Move to the previous line indented like point. + +This will skip over lines and statements with different +indentation levels." (interactive) - (elpy-nav-next-iblock -1)) - -(defun elpy-nav-backward-iblock () - "Move back to the previous line less indented than the current one." - (interactive) - (let ((start-indentation (current-indentation)) - (new-pos (point))) - (unwind-protect - (progn - (elpy-nav--iblock -1 #'>=) - (when (< (current-indentation) - start-indentation) - (back-to-indentation) - (setq new-pos (point)))) - (goto-char new-pos)))) - -(defun elpy-nav-forward-iblock () - "Move forward to the next line indented more than the current one." - (interactive) - (let ((start-indentation (current-indentation)) - (new-pos (point))) - (unwind-protect - (progn - (elpy-nav--iblock 1 #'<=) - (when (> (current-indentation) - start-indentation) - (back-to-indentation) - (setq new-pos (point)))) - (goto-char new-pos)))) - -(defun elpy-nav-move-iblock-down (&optional beg end) - "Move the current indentation block below the next one. - -With an active region, move that instead of the current block. - -An indentation block is a block indented further than the current -one." + (let ((indent (current-column)) + (start (point))) + (when (/= (% indent python-indent-offset) + 0) + (setq indent (* (1+ (/ indent python-indent-offset)) + python-indent-offset))) + (python-nav-backward-statement) + (while (and (< indent (current-indentation)) + (not (bobp))) + (python-nav-backward-statement)) + (when (< (current-indentation) + indent) + (goto-char start)))) + +(defun elpy-nav-forward-indent () + "Move forward to the next indent level, or over the next word." + (interactive "^") + (if (< (current-column) (current-indentation)) + (let* ((current (current-column)) + (next (* (1+ (/ current python-indent-offset)) + python-indent-offset))) + (goto-char (+ (point-at-bol) + next))) + (let ((eol (point-at-eol))) + (forward-word) + (when (> (point) eol) + (goto-char (point-at-bol)))))) + +(defun elpy-nav-backward-indent () + "Move backward to the previous indent level, or over the previous word." + (interactive "^") + (if (and (<= (current-column) (current-indentation)) + (/= (current-column) 0)) + (let* ((current (current-column)) + (next (* (1- (/ current python-indent-offset)) + python-indent-offset))) + (goto-char (+ (point-at-bol) + next))) + (backward-word))) + +(defun elpy-nav-move-line-or-region-down (&optional beg end) + "Move the current line or active region down." (interactive "r") - (let ((use-region (use-region-p)) - (startm (make-marker)) - (starti nil) - (midm (make-marker)) - (midi nil) - (endm (make-marker)) - (deactivate-mark nil)) + (if (use-region-p) + (elpy--nav-move-region-vertically beg end 1) + (elpy--nav-move-line-vertically 1))) + +(defun elpy-nav-move-line-or-region-up (&optional beg end) + "Move the current line or active region down." + (interactive "r") + (if (use-region-p) + (elpy--nav-move-region-vertically beg end -1) + (elpy--nav-move-line-vertically -1))) + +(defun elpy--nav-move-line-vertically (dir) + (let* ((beg (point-at-bol)) + (end (point-at-bol 2)) + (col (current-column)) + (region (delete-and-extract-region beg end))) + (forward-line dir) (save-excursion - (when use-region - (goto-char beg)) - (set-marker startm (line-beginning-position)) - (setq starti (current-indentation)) - (if use-region - (progn - (goto-char end) - (when (> (current-column) - 0) - (forward-line 1))) - (elpy-nav--iblock 1 #'>)) - (set-marker midm (line-beginning-position)) - (setq midi (current-indentation)) - (elpy-nav--iblock 1 #'>) - (goto-char (line-beginning-position)) - (when (<= (current-indentation) - starti) - (when (/= (skip-chars-backward "[:space:]\n") 0) - (forward-line 1))) - (when (and (= midm (point)) - (/= (point) - (line-end-position)) - (= (line-end-position) - (point-max))) - (goto-char (point-max)) - (insert "\n")) - (set-marker endm (line-beginning-position))) - (when (and (/= startm midm) - (/= midm endm) - (/= startm endm) - (= starti midi)) - (goto-char endm) - (insert (buffer-substring startm midm)) - (when use-region - (set-mark (point))) - (delete-region startm midm) - (goto-char endm) - (back-to-indentation)))) - -(defun elpy-nav-move-iblock-up (&optional beg end) - "Move the current indentation block below the next one. - -With an active region, move that instead of the current block. - -An indentation block is a block indented further than the current -one." - (interactive "r") - (let ((use-region (use-region-p)) - (startm (make-marker)) - (starti nil) - (midm (make-marker)) - (midi nil) - (endm (make-marker)) - (deactivate-mark nil)) + (insert region)) + (goto-char (+ (point) col)))) + +(defun elpy--nav-move-region-vertically (beg end dir) + (let* ((point-before-mark (< (point) (mark))) + (beg (save-excursion + (goto-char beg) + (point-at-bol))) + (end (save-excursion + (goto-char end) + (if (bolp) + (point) + (point-at-bol 2)))) + (region (delete-and-extract-region beg end))) + (goto-char beg) + (forward-line dir) (save-excursion - (when use-region - (goto-char beg)) - (set-marker startm (line-beginning-position)) - (setq starti (current-indentation)) - (if use-region - (progn - (goto-char end) - (when (> (current-column) - 0) - (forward-line 1))) - (elpy-nav--iblock 1 #'>) - (cond - ((and (save-excursion - (goto-char (line-end-position)) - (and (> (current-column) 0) - (= (point-max) (point))))) - (goto-char (line-end-position)) - (insert "\n")) - ((< (current-indentation) - starti) - (when (/= (skip-chars-backward "[:space:]\n") 0) - (forward-line 1))))) - (set-marker midm (line-beginning-position)) - (goto-char startm) - (elpy-nav--iblock -1 #'>) - (goto-char (line-beginning-position)) - (set-marker endm (line-beginning-position)) - (setq midi (current-indentation))) - (when (and (/= startm midm) - (/= midm endm) - (/= startm endm) - (= starti midi)) - (goto-char endm) - (insert (buffer-substring startm midm)) - (when use-region - (set-mark (point))) - (delete-region startm midm) - (goto-char endm) - (back-to-indentation)))) - -(defun elpy-nav-move-iblock-left () + (insert region)) + (if point-before-mark + (set-mark (+ (point) + (length region))) + (set-mark (point)) + (goto-char (+ (point) + (length region)))) + (setq deactivate-mark nil))) + +(defun elpy-nav-move-region-or-line-left () "Dedent the current indentation block, or the active region." (interactive) - (let (beg end) - (if (use-region-p) - (setq beg (region-beginning) - end (region-end)) - (save-excursion - (setq beg (line-beginning-position)) - (elpy-nav--iblock 1 #'>) - (setq end (line-beginning-position)))) - (python-indent-shift-left beg end))) - -(defun elpy-nav-move-iblock-right () + (if (use-region-p) + (elpy--nav-move-region-left) + (elpy--nav-move-line-left))) + +(defun elpy-nav-move-region-or-line-right () "Indent the current indentation block, or the active region." (interactive) - (let (beg end) - (if (use-region-p) - (setq beg (region-beginning) - end (region-end)) - (save-excursion - (setq beg (line-beginning-position)) - (elpy-nav--iblock 1 #'>) - (setq end (line-beginning-position)))) - (python-indent-shift-right beg end))) + (if (use-region-p) + (elpy--nav-move-region-right) + (elpy--nav-move-line-right ))) + +(defun elpy--nav-move-line-left () + (save-excursion + (goto-char (point-at-bol)) + (when (looking-at (format "^ \\{%i\\}" python-indent)) + (replace-match "")))) + +(defun elpy--nav-move-line-right () + (save-excursion + (goto-char (point-at-bol)) + (insert (make-string python-indent ?\s)))) + +(defun elpy--nav-move-region-left () + (save-excursion + (let ((beg (region-beginning)) + (end (region-end))) + (goto-char beg) + (goto-char (point-at-bol)) + (while (< (point) end) + (elpy--nav-move-line-left) + (forward-line 1))) + (setq deactivate-mark nil))) + +(defun elpy--nav-move-region-right () + (save-excursion + (let ((beg (region-beginning)) + (end (region-end))) + (goto-char beg) + (goto-char (point-at-bol)) + (while (< (point) end) + (elpy--nav-move-line-right) + (forward-line 1))) + (setq deactivate-mark nil))) (defun elpy-open-and-indent-line-below () "Open a line below the current one, move there, and indent." @@ -1671,7 +1787,7 @@ (let* ((top (elpy-library-root)) (file buffer-file-name) (module (elpy-test--module-name-for-file top file)) - (test (python-info-current-defun))) + (test (elpy-test--current-test-name))) (if (and file (string-match "/test[^/]*$" file)) (progn (save-buffer) @@ -1679,6 +1795,13 @@ (save-some-buffers) (list top nil nil nil))))) +(defun elpy-test--current-test-name () + (let ((name (python-info-current-defun))) + (if (and name + (string-match "\\`\\([^.]+\\.[^.]+\\)\\." name)) + (match-string 1 name) + name))) + (defun elpy-test--module-name-for-file (top-level module-file) "Return the module name relative to TOP-LEVEL for MODULE-FILE. @@ -1715,8 +1838,10 @@ (test (format "%s.%s" module test)) (module module) (t "discover")))) - (elpy-test-run top - "python" "-m" "unittest" test))) + (apply #'elpy-test-run + top + (append elpy-test-discover-runner-command + (list test))))) (put 'elpy-test-discover-runner 'elpy-test-runner-p t) (defun elpy-test-django-runner (top file module test) @@ -1725,13 +1850,15 @@ This requires Django 1.6 or the django-discover-runner package." (interactive (elpy-test-at-point)) (if module - (elpy-test-run top - "django-admin.py" "test" "--noinput" - (if test - (format "%s.%s" module test) - module)) - (elpy-test-run top - "django-admin.py" "test" "--noinput"))) + (apply #'elpy-test-run + top + (append elpy-test-django-runner-command + (list (if test + (format "%s.%s" module test) + module)))) + (apply #'elpy-test-run + top + elpy-test-django-runner-command))) (put 'elpy-test-django-runner 'elpy-test-runner-p t) (defun elpy-test-nose-runner (top file module test) @@ -1740,14 +1867,32 @@ This requires the nose package to be installed." (interactive (elpy-test-at-point)) (if module - (elpy-test-run top - "nosetests" (if test - (format "%s:%s" module test) - module)) - (elpy-test-run top - "nosetests"))) + (apply #'elpy-test-run + top + (append elpy-test-nose-runner-command + (list (if test + (format "%s:%s" module test) + module)))) + (apply #'elpy-test-run + top + elpy-test-nose-runner-command))) (put 'elpy-test-nose-runner 'elpy-test-runner-p t) +(defun elpy-test-trial-runner (top file module test) + "Test the project using Twisted's Trial test runner. + +This requires the twisted-core package to be installed." + (interactive (elpy-test-at-point)) + (if module + (apply #'elpy-test-run + top + (append elpy-test-trial-runner-command + (list (if test + (format "%s.%s" module test) + module)))) + (apply #'elpy-test-run top elpy-test-trial-runner-command))) +(put 'elpy-test-trial-runner 'elpy-test-runner-p t) + (defun elpy-test-pytest-runner (top file module test) "Test the project using the py.test test runner. @@ -1756,16 +1901,17 @@ (cond (test (let ((test-list (split-string test "\\."))) - (elpy-test-run top - "py.test" (mapconcat #'identity - (cons file test-list) - "::")))) + (apply #'elpy-test-run + top + (append elpy-test-pytest-runner-command + (list (mapconcat #'identity + (cons file test-list) + "::")))))) (module - (elpy-test-run top - "py.test" file)) + (apply #'elpy-test-run top (append elpy-test-pytest-runner-command + (list file)))) (t - (elpy-test-run top - "py.test")))) + (apply #'elpy-test-run top elpy-test-pytest-runner-command)))) (put 'elpy-test-pytest-runner 'elpy-test-runner-p t) ;;;;;;;;;;;;;;;;; @@ -1831,6 +1977,78 @@ nil)))) ;;;;;;;;;;;;;; +;;; Import manipulation + +(defun elpy-importmagic--replace-block (spec) + "Replace an imports block. SPEC is (startline endline newblock)." + (let ((start-line (nth 0 spec)) + (end-line (nth 1 spec)) + (new-block (nth 2 spec))) + (save-excursion + (save-restriction + (widen) + (goto-char (point-min)) + (forward-line start-line) + (let ((beg (point)) + (end (progn (forward-line (- end-line start-line)) (point)))) + ;; Avoid deleting and re-inserting when the blocks are equal. + (unless (string-equal (buffer-substring beg end) new-block) + (delete-region beg end) + (insert new-block))))))) + +(defun elpy-importmagic--add-import-read-args (&optional object prompt) + (let* ((default-object (save-excursion + (let ((bounds (with-syntax-table python-dotty-syntax-table + (bounds-of-thing-at-point 'symbol)))) + (if bounds (buffer-substring (car bounds) (cdr bounds)) "")))) + (object-to-import (or object (read-string "Object to import: " default-object))) + (possible-imports (elpy-rpc "get_import_symbols" (list buffer-file-name + (elpy-rpc--buffer-contents) + object-to-import))) + (statement-prompt (or prompt "New import statement: "))) + (cond + ;; An elpy warning (i.e. index not ready) is returned as a string. + ((stringp possible-imports) + (list "")) + ;; If there is no candidate, we exit immediately. + ((null possible-imports) + (message "No import candidate found") + (list "")) + ;; We have some candidates, let the user choose one. + (t + (let ((first-choice (car possible-imports)) + (user-choice (completing-read statement-prompt possible-imports))) + (list (if (equal user-choice "") first-choice user-choice))))))) + +(defun elpy-importmagic-add-import (statement) + (interactive (elpy-importmagic--add-import-read-args)) + (unless (equal statement "") + (let* ((res (elpy-rpc "add_import" (list buffer-file-name + (elpy-rpc--buffer-contents) + statement)))) + (elpy-importmagic--replace-block res)))) + +(defun elpy-importmagic-fixup () + "Query for new imports of unresolved symbols, and remove unreferenced imports. + +Also sort the imports in the import statement blocks." + (interactive) + ;; get all unresolved names, and interactively add imports for them + (let* ((res (elpy-rpc "get_unresolved_symbols" (list buffer-file-name + (elpy-rpc--buffer-contents))))) + (unless (stringp res) + (if (null res) (message "No imports to add.")) + (dolist (object res) + (let* ((prompt (format "How to import \"%s\": " object)) + (choice (elpy-importmagic--add-import-read-args object prompt))) + (elpy-importmagic-add-import (car choice)))))) + ;; now get a new import statement block (this also sorts) + (let* ((res (elpy-rpc "remove_unreferenced_imports" (list buffer-file-name + (elpy-rpc--buffer-contents))))) + (unless (stringp res) + (elpy-importmagic--replace-block res)))) + +;;;;;;;;;;;;;; ;;; Multi-Edit (defvar elpy-multiedit-overlays nil @@ -1873,7 +2091,8 @@ This updates all other overlays." (when (and after-change - (not undo-in-progress)) + (not undo-in-progress) + (overlay-buffer ov)) (let ((text (buffer-substring (overlay-start ov) (overlay-end ov))) (inhibit-modification-hooks t)) @@ -1956,7 +2175,9 @@ (this-name (cdr (assq 'name usage))) (offset (cdr (assq 'offset usage)))) (setq name this-name) - (with-current-buffer (find-file-noselect filename) + (with-current-buffer (if filename + (find-file-noselect filename) + (current-buffer)) (elpy-multiedit-add-overlay (+ offset 1) (+ offset 1 (length this-name))) (save-excursion @@ -2155,6 +2376,13 @@ This maps call IDs to functions.") (make-variable-buffer-local 'elpy-rpc--backend-callbacks) +(defvar elpy-rpc--last-call nil + "The time of the last RPC call issued for this backend.") +(make-variable-buffer-local 'elpy-rpc--last-call) + +(defvar elpy-rpc--last-error-popup nil + "The last time an error popup happened.") + (defun elpy-rpc (method params &optional success error) "Call METHOD with PARAMS in the backend. @@ -2202,7 +2430,8 @@ Returns a PROMISE object." (let ((promise (elpy-promise success error))) (with-current-buffer (elpy-rpc--get-rpc-buffer) - (setq elpy-rpc--call-id (1+ elpy-rpc--call-id)) + (setq elpy-rpc--call-id (1+ elpy-rpc--call-id) + elpy-rpc--last-call (float-time)) (elpy-rpc--register-callback elpy-rpc--call-id promise) (process-send-string (get-buffer-process (current-buffer)) @@ -2257,40 +2486,42 @@ (defun elpy-rpc--find-buffer (library-root python-command) "Return an existing RPC buffer for this project root and command." (catch 'return - (dolist (buf (buffer-list)) - (when (and (elpy-rpc--process-buffer-p buf) - (equal (buffer-local-value 'elpy-rpc--backend-library-root - buf) - library-root) - (equal (buffer-local-value 'elpy-rpc--backend-python-command - buf) - python-command)) - (throw 'return buf))) + (let ((full-python-command (executable-find python-command))) + (dolist (buf (buffer-list)) + (when (and (elpy-rpc--process-buffer-p buf) + (equal (buffer-local-value 'elpy-rpc--backend-library-root + buf) + library-root) + (equal (buffer-local-value 'elpy-rpc--backend-python-command + buf) + full-python-command)) + (throw 'return buf)))) nil)) (defun elpy-rpc--open (library-root python-command) "Start a new RPC process and return the associated buffer." - ;; Prevent configuration errors (when (and elpy-rpc-backend (not (stringp elpy-rpc-backend))) (error "`elpy-rpc-backend' should be nil or a string.")) - (let* ((name (format "*elpy-rpc [project:%s python:%s]*" + (elpy-rpc--cleanup-buffers) + (let* ((full-python-command (executable-find python-command)) + (name (format " *elpy-rpc [project:%s python:%s]*" library-root - python-command)) + full-python-command)) (new-elpy-rpc-buffer (generate-new-buffer name)) (proc nil)) (with-current-buffer new-elpy-rpc-buffer (setq elpy-rpc--buffer-p t elpy-rpc--buffer (current-buffer) elpy-rpc--backend-library-root library-root - elpy-rpc--backend-python-command python-command + elpy-rpc--backend-python-command full-python-command default-directory "/" proc (condition-case err (let ((process-connection-type nil) (process-environment (elpy-rpc--environment))) (start-process name (current-buffer) - python-command + full-python-command "-W" "ignore" "-m" "elpy.__main__")) (error @@ -2310,6 +2541,21 @@ elpy-rpc-backend backend)))))) new-elpy-rpc-buffer)) +(defun elpy-rpc--cleanup-buffers () + "Close RPC buffers that have not been used in five minutes." + (when elpy-rpc-maximum-buffer-age + (let ((old (- (float-time) + elpy-rpc-maximum-buffer-age))) + (dolist (buffer (buffer-list)) + (when (and (elpy-rpc--process-buffer-p buffer) + (< (or (buffer-local-value 'elpy-rpc--last-call buffer) + old) + old)) + (ignore-errors + (kill-process (get-buffer-process buffer))) + (ignore-errors + (kill-buffer buffer))))))) + (defun elpy-rpc--sentinel (process event) "The sentinel for the RPC process. @@ -2333,35 +2579,42 @@ (let ((buffer (process-buffer process))) (when (and buffer (buffer-live-p buffer)) - (with-current-buffer (process-buffer process) + (with-current-buffer buffer (goto-char (point-max)) (insert output) - (catch 'return - (while (progn - (goto-char (point-min)) - (search-forward "\n" nil t)) - (goto-char (point-min)) - (let (json did-read-json) - (condition-case err - (setq json (let ((json-array-type 'list)) - (json-read)) - did-read-json t) - (error + (while (progn (goto-char (point-min)) - (cond - ((looking-at "elpy-rpc ready\n") - (replace-match "") - (elpy-rpc--check-backend-version "1.1")) - ((looking-at "elpy-rpc ready (\\([^ ]*\\))\n") - (let ((rpc-version (match-string 1))) - (replace-match "") - (elpy-rpc--check-backend-version rpc-version))) - (t - (elpy-rpc--handle-unexpected-line) - (throw 'return nil))))) - (when did-read-json - (delete-region (point-min) (1+ (point))) - (elpy-rpc--handle-json json))))))))) + (search-forward "\n" nil t)) + (let ((line-end (point)) + (json nil) + (did-read-json nil)) + (goto-char (point-min)) + (condition-case err + (setq json (let ((json-array-type 'list)) + (json-read)) + line-end (1+ (point)) + did-read-json t) + (error + (goto-char (point-min)))) + (cond + (did-read-json + (delete-region (point-min) line-end) + (elpy-rpc--handle-json json)) + ((looking-at "elpy-rpc ready\n") + (replace-match "") + (elpy-rpc--check-backend-version "1.1")) + ((looking-at "elpy-rpc ready (\\([^ ]*\\))\n") + (let ((rpc-version (match-string 1))) + (replace-match "") + (elpy-rpc--check-backend-version rpc-version))) + ((looking-at ".*No module named elpy\n") + (replace-match "") + (elpy-config-error "Elpy module not found")) + (t + (let ((line (buffer-substring (point-min) + line-end))) + (delete-region (point-min) line-end) + (elpy-rpc--handle-unexpected-line line)))))))))) (defun elpy-rpc--check-backend-version (rpc-version) "Check that we are using the right version." @@ -2377,26 +2630,24 @@ "Elpy Emacs Lisp version: " elpy-version "\n" "Elpy Python version....: " rpc-version "\n")))) -(defun elpy-rpc--handle-unexpected-line () +(defun elpy-rpc--handle-unexpected-line (line) "Handle an unexpected line from the backend. This is usually an error or backtrace." - (goto-char (point-min)) - (let ((missing-module (when (re-search-forward "No module named \\(.*\\)" - nil t) - (match-string 1)))) - (if (equal missing-module "elpy") - (elpy-config-error "Elpy module not found") - (let ((data (buffer-string))) - (elpy-insert--popup "*Elpy Error*" - (elpy-insert--header "Error initializing Elpy") - (elpy-insert--para - "There was an error when trying to start the backend. " - "Elpy can not work until this problem is solved. " - "The following lines were received from Python, and might " - "help identifying the problem.\n") - (insert "\n" - data)))))) + (let ((buf (get-buffer "*Elpy Output*"))) + (when (not buf) + (elpy-insert--popup "*Elpy Output*" + (elpy-insert--header "Output from Backend") + (elpy-insert--para + "There was some unexpected output from the Elpy backend. " + "This is usually some module that does not use correct logging, " + "but might indicate a configuration problem.\n\n") + (elpy-insert--header "Output") + (setq buf (current-buffer)))) + (with-current-buffer buf + (goto-char (point-max)) + (let ((inhibit-read-only t)) + (insert line))))) (defun elpy-rpc--handle-json (json) "Handle a single JSON object from the RPC backend." @@ -2427,6 +2678,13 @@ (message "Elpy warning: %s" message)) ((< code 500) (error "Elpy error: %s" message)) + ((and elpy-rpc-error-timeout + elpy-rpc--last-error-popup + (<= (float-time) + (+ elpy-rpc--last-error-popup + elpy-rpc-error-timeout))) + (message "Elpy error popup ignored, see `elpy-rpc-error-timeout': %s" + message)) (t (let ((config (elpy-config--get-config))) (elpy-insert--popup "*Elpy Error*" @@ -2466,8 +2724,7 @@ (insert "\n" "```\n" "\n" - "Reproduction:" - "\n" + "Reproduction:\n" "\n") (let ((method (cdr (assq 'method jedi-info))) (source (cdr (assq 'source jedi-info))) @@ -2481,21 +2738,54 @@ "\n" "script = jedi.Script(" script-args ")\n" "script." method "()\n")))) + (let ((rope-info (cdr (assq 'rope_debug_info data)))) + (when rope-info + (insert "\n") + (elpy-insert--header "Rope Debug Information") + (insert "```\n" + "\n" + "Reproduction:\n" + "\n") + (let ((project-root (cdr (assq 'project_root rope-info))) + (filename (cdr (assq 'filename rope-info))) + (source (cdr (assq 'source rope-info))) + (function-name (cdr (assq 'function_name rope-info))) + (function-args (cdr (assq 'function_args rope-info)))) + (insert "```Python\n") + (insert "\n" + "source = '''\n" + source + "'''\n" + "\n") + (insert "project = rope.base.project.Project(\n" + (format " %S,\n" project-root) + " ropefolder=None\n" + ")\n") + (insert "resource = rope.base.libutils.path_to_resource(\n" + " project,\n" + (format " %S,\n" filename) + " 'file'\n" + ")\n") + (insert (format "%s(\n %s\n)\n" + function-name function-args))))) (when (not (= 0 (current-column))) (insert "\n")) - (insert "```")))))))) + (insert "```")) + (setq elpy-rpc--last-error-popup (float-time)))))))) (defun elpy-rpc--environment () "Return a `process-environment' for the RPC process. This includes `elpy-rpc-pythonpath' in the PYTHONPATH, if set." (if (or (not elpy-rpc-pythonpath) - (not (file-exists-p (format "%s/elpy/__init__.py" - elpy-rpc-pythonpath)))) + (not (file-exists-p (expand-file-name "elpy/__init__.py" + elpy-rpc-pythonpath)))) process-environment (let* ((old-pythonpath (getenv "PYTHONPATH")) (new-pythonpath (if old-pythonpath - (concat elpy-rpc-pythonpath ":" old-pythonpath) + (concat elpy-rpc-pythonpath + path-separator + old-pythonpath) elpy-rpc-pythonpath))) (cons (concat "PYTHONPATH=" new-pythonpath) process-environment)))) @@ -2543,24 +2833,26 @@ "Call the get_calltip API function. Returns a calltip string for the function call at point." - (elpy-rpc "get_calltip" - (list buffer-file-name - (elpy-rpc--buffer-contents) - (- (point) - (point-min))) - success error)) + (when (< (buffer-size) elpy-rpc-ignored-buffer-size) + (elpy-rpc "get_calltip" + (list buffer-file-name + (elpy-rpc--buffer-contents) + (- (point) + (point-min))) + success error))) (defun elpy-rpc-get-completions (&optional success error) "Call the get_completions API function. Returns a list of possible completions for the Python symbol at point." - (elpy-rpc "get_completions" - (list buffer-file-name - (elpy-rpc--buffer-contents) - (- (point) - (point-min))) - success error)) + (when (< (buffer-size) elpy-rpc-ignored-buffer-size) + (elpy-rpc "get_completions" + (list buffer-file-name + (elpy-rpc--buffer-contents) + (- (point) + (point-min))) + success error))) (defun elpy-rpc-get-completion-docstring (completion &optional success error) "Call the get_completion_docstring API function. @@ -2664,8 +2956,10 @@ ((eq mode-name 'eldoc-minor-mode) (setq eldoc-minor-mode-string nil)) (t - (setcdr (assq mode-name minor-mode-alist) - (list ""))))) + (let ((cell (assq mode-name minor-mode-alist))) + (when cell + (setcdr cell + (list ""))))))) ;;;;;;;;;;;;;;;;;;;;;;;;; ;;; Module: Sane Defaults @@ -2785,19 +3079,17 @@ (elpy-company--cache-completions arg result)) ;; Nothing from the backend, try dabbrev-code. ((> (length arg) company-minimum-prefix-length) - (company-dabbrev-code 'candidates arg)) + (elpy--sort-and-strip-duplicates + (company-dabbrev-code 'candidates arg))) ;; Well, ok, let's go meh. (t nil)))))))) ;; sorted => t if the list is already sorted - ;; - We could sort it ourselves according to "how likely it is". - ;; Does a backend do that? + (`sorted + t) ;; duplicates => t if there could be duplicates (`duplicates - ;; While elpy backends won't return duplicates, we are passing - ;; this on to `company-dabbrev-code' if we have no completions of - ;; our own, so return t just in case. - t) + nil) ;; no-cache <prefix> => t if company shouldn't cache results ;; meta <candidate> => short docstring for minibuffer (`meta @@ -2831,6 +3123,12 @@ ;; post-completion <candidate> => after insertion, for snippets )) +(defun elpy--sort-and-strip-duplicates (seq) + "Sort SEQ and remove any duplicates." + (sort (delete-dups seq) + (lambda (a b) + (string< a b)))) + ;;;;;;;;;;;;;;;;; ;;; Module: ElDoc @@ -2849,32 +3147,42 @@ (kill-local-variable 'eldoc-documentation-function)))) (defun elpy-eldoc-documentation () - "Return a call tip for the python call at point." - (elpy-rpc-get-calltip - (lambda (calltip) - (eldoc-message - (cond - ((not calltip) - (let ((current-defun (python-info-current-defun))) - (when current-defun - (format "In: %s()" current-defun)))) - ((stringp calltip) - calltip) - (t - (let ((name (cdr (assq 'name calltip))) - (index (cdr (assq 'index calltip))) - (params (cdr (assq 'params calltip)))) - (when index - (setf (nth index params) - (propertize (nth index params) - 'face - 'eldoc-highlight-function-argument))) - (format "%s(%s)" - name - (mapconcat #'identity params ", ")) - )))))) - ;; Return the last message until we're done - eldoc-last-message) + "Return some interesting information for the code at point. + +This will return flymake errors for the line at point if there +are any. If not, this will do an asynchronous call to the RPC +backend to get a call tip, and display that using +`eldoc-message'. If the backend has no call tip, this will +display the current class and method instead." + (let ((flymake-error (elpy-flymake-error-at-point))) + (if flymake-error + flymake-error + (elpy-rpc-get-calltip + (lambda (calltip) + (eldoc-message + (cond + ((not calltip) + (when elpy-eldoc-show-current-function + (let ((current-defun (python-info-current-defun))) + (when current-defun + (format "In: %s()" current-defun))))) + ((stringp calltip) + calltip) + (t + (let ((name (cdr (assq 'name calltip))) + (index (cdr (assq 'index calltip))) + (params (cdr (assq 'params calltip)))) + (when index + (setf (nth index params) + (propertize (nth index params) + 'face + 'eldoc-highlight-function-argument))) + (format "%s(%s)" + name + (mapconcat #'identity params ", ")) + )))))) + ;; Return the last message until we're done + eldoc-last-message))) ;;;;;;;;;;;;;;;;;;; ;;; Module: Flymake @@ -2952,13 +3260,21 @@ (defun elpy-flymake-show-error () "Show the flymake error message at point." - (let* ((lineno (line-number-at-pos)) - (err-info (car (flymake-find-err-info flymake-err-info - lineno))) - (text (mapconcat #'flymake-ler-text - err-info - ", "))) - (message "%s" text))) + (interactive) + (let ((error-message (elpy-flymake-error-at-point))) + (when error-message + (message "%s" error-message)))) + +(defun elpy-flymake-error-at-point () + "Return the flymake error at point, or nil if there is none." + (when (boundp 'flymake-err-info) + (let* ((lineno (line-number-at-pos)) + (err-info (car (flymake-find-err-info flymake-err-info + lineno)))) + (when err-info + (mapconcat #'flymake-ler-text + err-info + ", "))))) (defun elpy-flymake--standard-value (var) "Return the standard value of the given variable."
rename from elpa/elpy-1.5.1/elpy/__init__.py rename to elpa/elpy-1.8.0/elpy/__init__.py --- a/elpa/elpy-1.5.1/elpy/__init__.py +++ b/elpa/elpy-1.8.0/elpy/__init__.py @@ -37,5 +37,5 @@ """ __author__ = "Jorgen Schaefer" -__version__ = "1.5.1" +__version__ = "1.8.0" __license__ = "GPL"
rename from elpa/elpy-1.5.1/elpy/__main__.py rename to elpa/elpy-1.8.0/elpy/__main__.py --- a/elpa/elpy-1.5.1/elpy/__main__.py +++ b/elpa/elpy-1.8.0/elpy/__main__.py @@ -9,13 +9,17 @@ """ +import os import sys import elpy from elpy.server import ElpyRPCServer if __name__ == '__main__': - sys.stdout.write('elpy-rpc ready ({0})\n' - .format(elpy.__version__)) - sys.stdout.flush() - ElpyRPCServer().serve_forever() + stdin = sys.stdin + stdout = sys.stdout + sys.stdout = sys.stderr = open(os.devnull, "w") + stdout.write('elpy-rpc ready ({0})\n' + .format(elpy.__version__)) + stdout.flush() + ElpyRPCServer(stdin, stdout).serve_forever()
rename from elpa/elpy-1.5.1/elpy/compat.py rename to elpa/elpy-1.8.0/elpy/compat.py --- a/elpa/elpy-1.5.1/elpy/compat.py +++ b/elpa/elpy-1.8.0/elpy/compat.py @@ -18,7 +18,7 @@ else: PYTHON3 = False - from StringIO import StringIO + from StringIO import StringIO # noqa def ensure_not_unicode(obj): """Return obj. If it's a unicode string, convert it to str first.
rename from elpa/elpy-1.5.1/elpy/server.py rename to elpa/elpy-1.8.0/elpy/impmagic.py --- a/elpa/elpy-1.5.1/elpy/server.py +++ b/elpa/elpy-1.8.0/elpy/impmagic.py @@ -1,212 +1,95 @@ -"""Method implementations for the Elpy JSON-RPC server. - -This file implements the methods exported by the JSON-RPC server. It -handles backend selection and passes methods on to the selected -backend. +"""Glue for the "importmagic" library. """ -import io -import os -import pydoc -from elpy.pydocutils import get_pydoc_completions -from elpy.rpc import JSONRPCServer, Fault -from elpy import compat +import os +import sys +import threading + try: - from elpy import jedibackend + import importmagic.index + import importmagic.symbols + import importmagic.importer except ImportError: # pragma: no cover - jedibackend = None - -try: - from elpy import ropebackend -except ImportError: # pragma: no cover - ropebackend = None + importmagic = None -class ElpyRPCServer(JSONRPCServer): - """The RPC server for elpy. - - See the rpc_* methods for exported method documentation. - - """ - def __init__(self): - super(ElpyRPCServer, self).__init__() - self.backend = None - self.project_root = None - - def _call_backend(self, method, default, *args, **kwargs): - """Call the backend method with args. - - If there is currently no backend, return default.""" - meth = getattr(self.backend, method, None) - if meth is None: - return default - else: - return meth(*args, **kwargs) +class ImportMagic(object): - def rpc_echo(self, *args): - """Return the arguments. - - This is a simple test method to see if the protocol is - working. - - """ - return args - - def rpc_init(self, options): - self.project_root = options["project_root"] - - if ropebackend and options["backend"] == "rope": - self.backend = ropebackend.RopeBackend(self.project_root) - elif jedibackend and options["backend"] == "jedi": - self.backend = jedibackend.JediBackend(self.project_root) - elif ropebackend: - self.backend = ropebackend.RopeBackend(self.project_root) - elif jedibackend: - self.backend = jedibackend.JediBackend(self.project_root) - else: - self.backend = None + def __init__(self): + self.is_enabled = bool(importmagic) + # fail_message is reported to the user when symbol_index + # is (still) None + self.fail_message = "symbol index is not yet ready" + self.project_root = None + self.symbol_index = None + self.favorites = set() + self._thread = None - return { - 'backend': (self.backend.name if self.backend is not None - else None) - } - - def rpc_get_calltip(self, filename, source, offset): - """Get the calltip for the function at the offset. - - """ - return self._call_backend("rpc_get_calltip", None, filename, - get_source(source), offset) - - def rpc_get_completions(self, filename, source, offset): - """Get a list of completion candidates for the symbol at offset. - - """ - return self._call_backend("rpc_get_completions", [], filename, - get_source(source), offset) - - def rpc_get_completion_docstring(self, completion): - """Return documentation for a previously returned completion. + def _build_symbol_index(self, project_root, custom_path, blacklist_re): + try: + index = importmagic.index.SymbolIndex(blacklist_re=blacklist_re) + if os.environ.get('ELPY_TEST'): + # test suite support: do not index the whole PYTHONPATH, it + # takes much too long + index.build_index([]) + elif custom_path: + index.build_index(custom_path) + else: + index.build_index([project_root] + sys.path) + except Exception as e: + self.fail_message = "symbol index failed to build: %s" % e + else: + self.symbol_index = index - """ - return self._call_backend("rpc_get_completion_docstring", - None, completion) - - def rpc_get_completion_location(self, completion): - """Return the location for a previously returned completion. - - This returns a list of [file name, line number]. - - """ - return self._call_backend("rpc_get_completion_location", None, - completion) + def build_index(self, project_root, custom_path=None, blacklist_re=None): + self.project_root = None + self._thread = threading.Thread(target=self._build_symbol_index, + args=(project_root, custom_path, + blacklist_re)) + self._thread.setDaemon(True) + self._thread.start() - def rpc_get_definition(self, filename, source, offset): - """Get the location of the definition for the symbol at the offset. - - """ - return self._call_backend("rpc_get_definition", None, filename, - get_source(source), offset) - - def rpc_get_docstring(self, filename, source, offset): - """Get the docstring for the symbol at the offset. - - """ - return self._call_backend("rpc_get_docstring", None, filename, - get_source(source), offset) + def get_import_symbols(self, symbol): + scores = self.symbol_index.symbol_scores(symbol) - def rpc_get_pydoc_completions(self, name=None): - """Return a list of possible strings to pass to pydoc. - - If name is given, the strings are under name. If not, top - level modules are returned. - - """ - return get_pydoc_completions(name) - - def rpc_get_pydoc_documentation(self, symbol): - """Get the Pydoc documentation for the given symbol. - - Uses pydoc and can return a string with backspace characters - for bold highlighting. + def sort_key(item): + score, mod, var = item + if mod in self.favorites: + return 2 + score, mod, var + return score, mod, var - """ - try: - docstring = pydoc.render_doc(str(symbol), - "Elpy Pydoc Documentation for %s", - False) - except (ImportError, pydoc.ErrorDuringImport): - return None - else: - if isinstance(docstring, bytes): - docstring = docstring.decode("utf-8", "replace") - return docstring - - def rpc_get_refactor_options(self, filename, start, end=None): - """Return a list of possible refactoring options. - - This list will be filtered depending on whether it's - applicable at the point START and possibly the region between - START and END. - - """ - try: - from elpy import refactor - except: - raise ImportError("Rope not installed, refactorings unavailable") - ref = refactor.Refactor(self.project_root, filename) - return ref.get_refactor_options(start, end) - - def rpc_refactor(self, filename, method, args): - """Return a list of changes from the refactoring action. + scores.sort(key=sort_key, reverse=True) + return ["from %s import %s" % (mod, var) if var else "import %s" % mod + for (_, mod, var) in scores] - A change is a dictionary describing the change. See - elpy.refactor.translate_changes for a description. - - """ - try: - from elpy import refactor - except: - raise ImportError("Rope not installed, refactorings unavailable") - if args is None: - args = () - ref = refactor.Refactor(self.project_root, filename) - return ref.get_changes(method, *args) - - def rpc_get_usages(self, filename, source, offset): - """Get usages for the symbol at point. - - """ - source = get_source(source) - if hasattr(self.backend, "rpc_get_usages"): - return self.backend.rpc_get_usages(filename, source, offset) + def add_import(self, source, statement): + imports = importmagic.importer.Imports(self.symbol_index, source) + if statement.startswith('import '): + modname = statement[7:] + imports.add_import(modname) + self.favorites.add(modname) else: - raise Fault("get_usages not implemented by current backend", - code=400) + sep = statement.find(' import ') + modname = statement[5:sep] + if sep > -1: + self.favorites.add(modname) + imports.add_import_from(statement[5:sep], statement[sep+8:]) + start_line, end_line, import_block = imports.get_update() + return start_line, end_line, import_block - -def get_source(fileobj): - """Translate fileobj into file contents. - - fileobj is either a string or a dict. If it's a string, that's the - file contents. If it's a string, then the filename key contains - the name of the file whose contents we are to use. - - If the dict contains a true value for the key delete_after_use, - the file should be deleted once read. + def get_unresolved_symbols(self, source): + scope = importmagic.symbols.Scope.from_source(source) + unres, unref = scope.find_unresolved_and_unreferenced_symbols() + return list(unres) - """ - if not isinstance(fileobj, dict): - return fileobj - else: - try: - with io.open(fileobj["filename"], encoding="utf-8") as f: - return f.read() - finally: - if fileobj.get('delete_after_use'): - try: - os.remove(fileobj["filename"]) - except: # pragma: no cover - pass + def remove_unreferenced_imports(self, source): + scope = importmagic.symbols.Scope.from_source(source) + unres, unref = scope.find_unresolved_and_unreferenced_symbols() + # Note: we do not supply "unres" to the call below, since we do + # not want to add imports without querying the user from which + # module symbols should be imported. + start_line, end_line, import_block = importmagic.importer.get_update( + source, self.symbol_index, set(), unref) + return start_line, end_line, import_block
rename from elpa/elpy-1.5.1/elpy/jedibackend.py rename to elpa/elpy-1.8.0/elpy/jedibackend.py --- a/elpa/elpy-1.5.1/elpy/jedibackend.py +++ b/elpa/elpy-1.8.0/elpy/jedibackend.py @@ -58,6 +58,21 @@ else: return (proposal.module_path, proposal.line) + def rpc_get_docstring(self, filename, source, offset): + line, column = pos_to_linecol(source, offset) + try: + locations = run_with_debug(jedi, 'goto_definitions', + source=source, line=line, column=column, + path=filename, encoding='utf-8', + re_raise=jedi.NotFoundError) + except jedi.NotFoundError: + return None + if locations: + return ('Documentation for {0}:\n\n'.format( + locations[-1].full_name) + locations[-1].docstring()) + else: + return None + def rpc_get_definition(self, filename, source, offset): line, column = pos_to_linecol(source, offset) try: @@ -93,6 +108,8 @@ offset = linecol_to_pos(f.read(), loc.line, loc.column) + else: + return None except IOError: return None return (loc.module_path, offset) @@ -134,7 +151,7 @@ for use in uses: if use.module_path == filename: offset = linecol_to_pos(source, use.line, use.column) - else: + elif use.module_path is not None: with open(use.module_path) as f: text = f.read() offset = linecol_to_pos(text, use.line, use.column) @@ -215,6 +232,57 @@ # Bug in Python 2.6, see #275 if isinstance(e, OSError) and e.errno == 13: return None + # Bug jedi#466 + if ( + isinstance(e, SyntaxError) and + "EOL while scanning string literal" in str(e) + ): + return None + # Bug jedi#482 + if isinstance(e, UnicodeEncodeError): + return None + # Bug jedi#485 + if ( + isinstance(e, ValueError) and + "invalid \\x escape" in str(e) + ): + return None + # Bug jedi#485 in Python 3 + if ( + isinstance(e, SyntaxError) and + "truncated \\xXX escape" in str(e) + ): + return None + # Bug jedi#465 + if ( + isinstance(e, SyntaxError) and + "encoding declaration in Unicode string" in str(e) + ): + return None + # Bug #337 / jedi#471 + if ( + isinstance(e, ImportError) and + "No module named" in str(e) + ): + return None + # Bug #365 / jedi#486 - fixed in Jedi 0.8.2 + if ( + isinstance(e, UnboundLocalError) and + "local variable 'path' referenced before assignment" in str(e) + ): + return None + # Bug #366 / jedi#491 + if ( + isinstance(e, ValueError) and + "__loader__ is None" in str(e) + ): + return None + # Bug #353 + if ( + isinstance(e, OSError) and + "No such file or directory" in str(e) + ): + return None from jedi import debug @@ -227,7 +295,7 @@ prefix = "[W]" else: prefix = "[?]" - debug_info.append("{0} {1}".format(prefix, str_out)) + debug_info.append(u"{0} {1}".format(prefix, str_out)) jedi.set_debug_function(_debug, speed=False) try:
rename from elpa/elpy-1.5.1/elpy/refactor.py rename to elpa/elpy-1.8.0/elpy/refactor.py --- a/elpa/elpy-1.5.1/elpy/refactor.py +++ b/elpa/elpy-1.8.0/elpy/refactor.py @@ -50,7 +50,10 @@ """ +from elpy.rpc import Fault + try: + from rope.base.exceptions import RefactoringError from rope.base.project import Project from rope.base.libutils import path_to_resource from rope.base import change as rope_change @@ -234,12 +237,21 @@ @options("Rename symbol at point", category="Symbol", args=[("offset", "offset", None), - ("new_name", "string", "Rename to: ")], + ("new_name", "string", "Rename to: "), + ("in_hierarchy", "boolean", + "Rename in super-/subclasses as well? "), + ("docs", "boolean", + "Replace occurences in docs and strings? ") + ], available=ROPE_AVAILABLE) - def refactor_rename_at_point(self, offset, new_name): + def refactor_rename_at_point(self, offset, new_name, in_hierarchy, docs): """Rename the symbol at point.""" - refactor = Rename(self.project, self.resource, offset) - changes = refactor.get_changes(new_name) + try: + refactor = Rename(self.project, self.resource, offset) + except RefactoringError as e: + raise Fault(str(e), code=400) + changes = refactor.get_changes(new_name, in_hierarchy=in_hierarchy, + docs=docs) return translate_changes(changes) @options("Rename current module", category="Module",
rename from elpa/elpy-1.5.1/elpy/ropebackend.py rename to elpa/elpy-1.8.0/elpy/ropebackend.py --- a/elpa/elpy-1.5.1/elpy/ropebackend.py +++ b/elpa/elpy-1.8.0/elpy/ropebackend.py @@ -5,8 +5,10 @@ http://rope.sourceforge.net/ """ + import os import time +import traceback import rope.contrib.codeassist import rope.base.project @@ -14,6 +16,7 @@ import rope.base.exceptions import rope.contrib.findit +from elpy import rpc import elpy.pydocutils VALIDATE_EVERY_SECONDS = 5 @@ -33,6 +36,11 @@ def __init__(self, project_root): super(RopeBackend, self).__init__() self.last_validation = 0 + if not os.path.exists(project_root): + raise rpc.Fault( + "rope does not support files without a local project root", + code=400 + ) self.project_root = project_root self.completions = {} prefs = dict(ignored_resources=['*.pyc', '*~', '.ropeproject', @@ -73,35 +81,83 @@ """ now = time.time() if now > self.last_validation + VALIDATE_EVERY_SECONDS: - self.project.validate() + try: + self.project.validate() + except rope.base.exceptions.ResourceNotFoundError: + pass self.last_validation = now - def rpc_get_completions(self, filename, source, offset): + def call_rope(self, rope_function, filename, source, offset, + **kwargs): self.validate() resource = self.get_resource(filename) try: - proposals = rope.contrib.codeassist.code_assist(self.project, - source, offset, - resource, - maxfixes=MAXFIXES) + return rope_function(self.project, + source, offset, + resource, + maxfixes=MAXFIXES, + **kwargs) + except (rope.base.exceptions.BadIdentifierError, + rope.base.exceptions.ModuleSyntaxError, + rope.base.exceptions.ResourceNotFoundError, + rope.base.exceptions.NameNotFoundError, + IndentationError, + LookupError, + AttributeError): + return None + except Exception as e: + data = { + "traceback": traceback.format_exc(), + "rope_debug_info": { + "project_root": self.project_root, + "filename": filename, + "source": source, + "function_name": (rope_function.__module__ + + "." + + rope_function.__name__), + "function_args": ", ".join([ + "project", "source", str(offset), "resource", + "maxfixes={0}".format(MAXFIXES) + ] + [ + u"{}={}".format(k, v) + for (k, v) in kwargs.items() + ]) + } + } + raise rpc.Fault( + code=500, + message=str(e), + data=data + ) + + def rpc_get_completions(self, filename, source, offset): + proposals = self.call_rope( + rope.contrib.codeassist.code_assist, + filename, source, offset + ) + if proposals is None: + return [] + try: starting_offset = rope.contrib.codeassist.starting_offset(source, offset) except (rope.base.exceptions.BadIdentifierError, rope.base.exceptions.ModuleSyntaxError, IndentationError, - IndexError, - LookupError): - # Rope can't parse this file + LookupError, + AttributeError): return [] - prefixlen = offset - starting_offset self.completions = dict((proposal.name, proposal) for proposal in proposals) - return [{'name': proposal.name, - 'suffix': proposal.name[prefixlen:], - 'annotation': proposal.type, - 'meta': str(proposal)} - for proposal in proposals] + try: + return [{'name': proposal.name, + 'suffix': proposal.name[prefixlen:], + 'annotation': proposal.type, + 'meta': str(proposal)} + for proposal in proposals] + except rope.base.exceptions.ModuleSyntaxError: + # Bug#406 + return [] def rpc_get_completion_docstring(self, completion): proposal = self.completions.get(completion) @@ -124,77 +180,48 @@ return (resource.real_path, lineno) def rpc_get_definition(self, filename, source, offset): - self.validate() - - # The find_definition call fails on an empty strings - if source == '': - return None - - resource = self.get_resource(filename) - try: - location = rope.contrib.findit.find_definition(self.project, - source, offset, - resource, MAXFIXES) - except (rope.base.exceptions.BadIdentifierError, - rope.base.exceptions.ModuleSyntaxError, - IndentationError, - LookupError): - # Rope can't parse this file - return None - + location = self.call_rope( + rope.contrib.findit.find_definition, + filename, source, offset + ) if location is None: return None else: return (location.resource.real_path, location.offset) def rpc_get_calltip(self, filename, source, offset): - self.validate() offset = find_called_name_offset(source, offset) - resource = self.get_resource(filename) if 0 < offset < len(source) and source[offset] == ')': offset -= 1 - try: - calltip = rope.contrib.codeassist.get_calltip( - self.project, source, offset, resource, MAXFIXES, - remove_self=True) - if calltip: - calltip = calltip.replace(".__init__(", "(") - calltip = calltip.replace("(self)", "()") - calltip = calltip.replace("(self, ", "(") - # "elpy.tests.support.source_and_offset(source)" - # => - # "support.source_and_offset(source)" - try: - openpos = calltip.index("(") - period2 = calltip.rindex(".", 0, openpos) - period1 = calltip.rindex(".", 0, period2) - calltip = calltip[period1 + 1:] - except ValueError: - pass - return calltip - except (rope.base.exceptions.BadIdentifierError, - rope.base.exceptions.ModuleSyntaxError, - IndentationError, - IndexError, - LookupError): - # Rope can't parse this file + + calltip = self.call_rope( + rope.contrib.codeassist.get_calltip, + filename, source, offset, + remove_self=True + ) + if calltip is None: return None - def rpc_get_docstring(self, filename, source, offset): - self.validate() - resource = self.get_resource(filename) + calltip = calltip.replace(".__init__(", "(") + calltip = calltip.replace("(self)", "()") + calltip = calltip.replace("(self, ", "(") + # "elpy.tests.support.source_and_offset(source)" + # => + # "support.source_and_offset(source)" try: - docstring = rope.contrib.codeassist.get_doc(self.project, - source, offset, - resource, MAXFIXES) - except (rope.base.exceptions.BadIdentifierError, - rope.base.exceptions.ModuleSyntaxError, - IndentationError, - IndexError, - LookupError): - # Rope can't parse this file - docstring = None - return docstring + openpos = calltip.index("(") + period2 = calltip.rindex(".", 0, openpos) + period1 = calltip.rindex(".", 0, period2) + calltip = calltip[period1 + 1:] + except ValueError: + pass + return calltip + + def rpc_get_docstring(self, filename, source, offset): + return self.call_rope( + rope.contrib.codeassist.get_doc, + filename, source, offset + ) def find_called_name_offset(source, orig_offset):
copy from elpa/elpy-1.5.1/elpy/server.py copy to elpa/elpy-1.8.0/elpy/server.py --- a/elpa/elpy-1.5.1/elpy/server.py +++ b/elpa/elpy-1.8.0/elpy/server.py @@ -11,7 +11,8 @@ from elpy.pydocutils import get_pydoc_completions from elpy.rpc import JSONRPCServer, Fault -from elpy import compat +from elpy.impmagic import ImportMagic + try: from elpy import jedibackend @@ -30,9 +31,10 @@ See the rpc_* methods for exported method documentation. """ - def __init__(self): - super(ElpyRPCServer, self).__init__() + def __init__(self, *args, **kwargs): + super(ElpyRPCServer, self).__init__(*args, **kwargs) self.backend = None + self.import_magic = ImportMagic() self.project_root = None def _call_backend(self, method, default, *args, **kwargs): @@ -57,6 +59,9 @@ def rpc_init(self, options): self.project_root = options["project_root"] + if self.import_magic.is_enabled: + self.import_magic.build_index(self.project_root) + if ropebackend and options["backend"] == "rope": self.backend = ropebackend.RopeBackend(self.project_root) elif jedibackend and options["backend"] == "jedi": @@ -84,8 +89,13 @@ """Get a list of completion candidates for the symbol at offset. """ - return self._call_backend("rpc_get_completions", [], filename, - get_source(source), offset) + results = self._call_backend("rpc_get_completions", [], filename, + get_source(source), offset) + # Uniquify by name + results = list(dict((res['name'], res) for res in results) + .values()) + results.sort(key=lambda cand: _pysymbol_key(cand["name"])) + return results def rpc_get_completion_docstring(self, completion): """Return documentation for a previously returned completion. @@ -186,6 +196,44 @@ raise Fault("get_usages not implemented by current backend", code=400) + def _ensure_import_magic(self): # pragma: no cover + if not self.import_magic.is_enabled: + raise Fault("fixup_imports not enabled; install importmagic module", + code=400) + if not self.import_magic.symbol_index: + raise Fault(self.import_magic.fail_message, code=200) # XXX code? + + def rpc_get_import_symbols(self, filename, source, symbol): + """Return a list of modules from which the given symbol can be imported. + + """ + self._ensure_import_magic() + return self.import_magic.get_import_symbols(symbol) + + def rpc_add_import(self, filename, source, statement): + """Add an import statement to the module. + + """ + self._ensure_import_magic() + source = get_source(source) + return self.import_magic.add_import(source, statement) + + def rpc_get_unresolved_symbols(self, filename, source): + """Return a list of unreferenced symbols in the module. + + """ + self._ensure_import_magic() + source = get_source(source) + return self.import_magic.get_unresolved_symbols(source) + + def rpc_remove_unreferenced_imports(self, filename, source): + """Remove unused import statements. + + """ + self._ensure_import_magic() + source = get_source(source) + return self.import_magic.remove_unreferenced_imports(source) + def get_source(fileobj): """Translate fileobj into file contents. @@ -210,3 +258,18 @@ os.remove(fileobj["filename"]) except: # pragma: no cover pass + + +def _pysymbol_key(name): + """Return a sortable key index for name. + + Sorting is case-insensitive, with the first underscore counting as + worse than any character, but subsequent underscores do not. This + means that dunder symbols (like __init__) are sorted after symbols + that start with an alphabetic character, but before those that + start with only a single underscore. + + """ + if name.startswith("_"): + name = "~" + name[1:] + return name.lower()
rename from elpa/elpy-1.5.1/snippets/python-mode/.yas-setup.el rename to elpa/elpy-1.8.0/snippets/python-mode/.yas-setup.el
rename from elpa/elpy-1.5.1/snippets/python-mode/__abs__ rename to elpa/elpy-1.8.0/snippets/python-mode/__abs__
rename from elpa/elpy-1.5.1/snippets/python-mode/__add__ rename to elpa/elpy-1.8.0/snippets/python-mode/__add__
rename from elpa/elpy-1.5.1/snippets/python-mode/__and__ rename to elpa/elpy-1.8.0/snippets/python-mode/__and__
rename from elpa/elpy-1.5.1/snippets/python-mode/__bool__ rename to elpa/elpy-1.8.0/snippets/python-mode/__bool__
rename from elpa/elpy-1.5.1/snippets/python-mode/__call__ rename to elpa/elpy-1.8.0/snippets/python-mode/__call__
rename from elpa/elpy-1.5.1/snippets/python-mode/__cmp__ rename to elpa/elpy-1.8.0/snippets/python-mode/__cmp__
rename from elpa/elpy-1.5.1/snippets/python-mode/__coerce__ rename to elpa/elpy-1.8.0/snippets/python-mode/__coerce__
rename from elpa/elpy-1.5.1/snippets/python-mode/__complex__ rename to elpa/elpy-1.8.0/snippets/python-mode/__complex__
rename from elpa/elpy-1.5.1/snippets/python-mode/__contains__ rename to elpa/elpy-1.8.0/snippets/python-mode/__contains__
rename from elpa/elpy-1.5.1/snippets/python-mode/__del__ rename to elpa/elpy-1.8.0/snippets/python-mode/__del__
rename from elpa/elpy-1.5.1/snippets/python-mode/__delattr__ rename to elpa/elpy-1.8.0/snippets/python-mode/__delattr__
rename from elpa/elpy-1.5.1/snippets/python-mode/__delete__ rename to elpa/elpy-1.8.0/snippets/python-mode/__delete__
rename from elpa/elpy-1.5.1/snippets/python-mode/__delitem__ rename to elpa/elpy-1.8.0/snippets/python-mode/__delitem__
rename from elpa/elpy-1.5.1/snippets/python-mode/__div__ rename to elpa/elpy-1.8.0/snippets/python-mode/__div__
rename from elpa/elpy-1.5.1/snippets/python-mode/__divmod__ rename to elpa/elpy-1.8.0/snippets/python-mode/__divmod__
rename from elpa/elpy-1.5.1/snippets/python-mode/__enter__ rename to elpa/elpy-1.8.0/snippets/python-mode/__enter__
rename from elpa/elpy-1.5.1/snippets/python-mode/__eq__ rename to elpa/elpy-1.8.0/snippets/python-mode/__eq__
rename from elpa/elpy-1.5.1/snippets/python-mode/__exit__ rename to elpa/elpy-1.8.0/snippets/python-mode/__exit__
rename from elpa/elpy-1.5.1/snippets/python-mode/__float__ rename to elpa/elpy-1.8.0/snippets/python-mode/__float__
rename from elpa/elpy-1.5.1/snippets/python-mode/__floordiv__ rename to elpa/elpy-1.8.0/snippets/python-mode/__floordiv__
rename from elpa/elpy-1.5.1/snippets/python-mode/__ge__ rename to elpa/elpy-1.8.0/snippets/python-mode/__ge__
rename from elpa/elpy-1.5.1/snippets/python-mode/__get__ rename to elpa/elpy-1.8.0/snippets/python-mode/__get__
rename from elpa/elpy-1.5.1/snippets/python-mode/__getattr__ rename to elpa/elpy-1.8.0/snippets/python-mode/__getattr__
rename from elpa/elpy-1.5.1/snippets/python-mode/__getattribute__ rename to elpa/elpy-1.8.0/snippets/python-mode/__getattribute__
rename from elpa/elpy-1.5.1/snippets/python-mode/__getitem__ rename to elpa/elpy-1.8.0/snippets/python-mode/__getitem__
rename from elpa/elpy-1.5.1/snippets/python-mode/__gt__ rename to elpa/elpy-1.8.0/snippets/python-mode/__gt__
rename from elpa/elpy-1.5.1/snippets/python-mode/__hash__ rename to elpa/elpy-1.8.0/snippets/python-mode/__hash__
rename from elpa/elpy-1.5.1/snippets/python-mode/__hex__ rename to elpa/elpy-1.8.0/snippets/python-mode/__hex__
rename from elpa/elpy-1.5.1/snippets/python-mode/__iadd__ rename to elpa/elpy-1.8.0/snippets/python-mode/__iadd__
rename from elpa/elpy-1.5.1/snippets/python-mode/__iand__ rename to elpa/elpy-1.8.0/snippets/python-mode/__iand__
rename from elpa/elpy-1.5.1/snippets/python-mode/__idiv__ rename to elpa/elpy-1.8.0/snippets/python-mode/__idiv__
rename from elpa/elpy-1.5.1/snippets/python-mode/__ifloordiv__ rename to elpa/elpy-1.8.0/snippets/python-mode/__ifloordiv__
rename from elpa/elpy-1.5.1/snippets/python-mode/__ilshift__ rename to elpa/elpy-1.8.0/snippets/python-mode/__ilshift__
rename from elpa/elpy-1.5.1/snippets/python-mode/__imod__ rename to elpa/elpy-1.8.0/snippets/python-mode/__imod__
rename from elpa/elpy-1.5.1/snippets/python-mode/__imul__ rename to elpa/elpy-1.8.0/snippets/python-mode/__imul__
rename from elpa/elpy-1.5.1/snippets/python-mode/__index__ rename to elpa/elpy-1.8.0/snippets/python-mode/__index__
rename from elpa/elpy-1.5.1/snippets/python-mode/__init__ rename to elpa/elpy-1.8.0/snippets/python-mode/__init__
rename from elpa/elpy-1.5.1/snippets/python-mode/__instancecheck__ rename to elpa/elpy-1.8.0/snippets/python-mode/__instancecheck__
rename from elpa/elpy-1.5.1/snippets/python-mode/__int__ rename to elpa/elpy-1.8.0/snippets/python-mode/__int__
rename from elpa/elpy-1.5.1/snippets/python-mode/__invert__ rename to elpa/elpy-1.8.0/snippets/python-mode/__invert__
rename from elpa/elpy-1.5.1/snippets/python-mode/__ior__ rename to elpa/elpy-1.8.0/snippets/python-mode/__ior__
rename from elpa/elpy-1.5.1/snippets/python-mode/__ipow__ rename to elpa/elpy-1.8.0/snippets/python-mode/__ipow__
rename from elpa/elpy-1.5.1/snippets/python-mode/__irshift__ rename to elpa/elpy-1.8.0/snippets/python-mode/__irshift__
rename from elpa/elpy-1.5.1/snippets/python-mode/__isub__ rename to elpa/elpy-1.8.0/snippets/python-mode/__isub__
rename from elpa/elpy-1.5.1/snippets/python-mode/__iter__ rename to elpa/elpy-1.8.0/snippets/python-mode/__iter__
rename from elpa/elpy-1.5.1/snippets/python-mode/__itruediv__ rename to elpa/elpy-1.8.0/snippets/python-mode/__itruediv__
rename from elpa/elpy-1.5.1/snippets/python-mode/__ixor__ rename to elpa/elpy-1.8.0/snippets/python-mode/__ixor__
rename from elpa/elpy-1.5.1/snippets/python-mode/__le__ rename to elpa/elpy-1.8.0/snippets/python-mode/__le__
rename from elpa/elpy-1.5.1/snippets/python-mode/__len__ rename to elpa/elpy-1.8.0/snippets/python-mode/__len__
rename from elpa/elpy-1.5.1/snippets/python-mode/__long__ rename to elpa/elpy-1.8.0/snippets/python-mode/__long__
rename from elpa/elpy-1.5.1/snippets/python-mode/__lshift__ rename to elpa/elpy-1.8.0/snippets/python-mode/__lshift__
rename from elpa/elpy-1.5.1/snippets/python-mode/__lt__ rename to elpa/elpy-1.8.0/snippets/python-mode/__lt__
rename from elpa/elpy-1.5.1/snippets/python-mode/__mod__ rename to elpa/elpy-1.8.0/snippets/python-mode/__mod__
rename from elpa/elpy-1.5.1/snippets/python-mode/__mul__ rename to elpa/elpy-1.8.0/snippets/python-mode/__mul__
rename from elpa/elpy-1.5.1/snippets/python-mode/__ne__ rename to elpa/elpy-1.8.0/snippets/python-mode/__ne__
rename from elpa/elpy-1.5.1/snippets/python-mode/__neg__ rename to elpa/elpy-1.8.0/snippets/python-mode/__neg__
rename from elpa/elpy-1.5.1/snippets/python-mode/__new__ rename to elpa/elpy-1.8.0/snippets/python-mode/__new__
rename from elpa/elpy-1.5.1/snippets/python-mode/__nonzero__ rename to elpa/elpy-1.8.0/snippets/python-mode/__nonzero__
rename from elpa/elpy-1.5.1/snippets/python-mode/__oct__ rename to elpa/elpy-1.8.0/snippets/python-mode/__oct__
rename from elpa/elpy-1.5.1/snippets/python-mode/__or__ rename to elpa/elpy-1.8.0/snippets/python-mode/__or__
rename from elpa/elpy-1.5.1/snippets/python-mode/__pos__ rename to elpa/elpy-1.8.0/snippets/python-mode/__pos__
rename from elpa/elpy-1.5.1/snippets/python-mode/__pow__ rename to elpa/elpy-1.8.0/snippets/python-mode/__pow__
rename from elpa/elpy-1.5.1/snippets/python-mode/__radd__ rename to elpa/elpy-1.8.0/snippets/python-mode/__radd__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rand__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rand__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rdivmod__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rdivmod__
rename from elpa/elpy-1.5.1/snippets/python-mode/__repr__ rename to elpa/elpy-1.8.0/snippets/python-mode/__repr__
rename from elpa/elpy-1.5.1/snippets/python-mode/__reversed__ rename to elpa/elpy-1.8.0/snippets/python-mode/__reversed__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rfloordiv__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rfloordiv__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rlshift__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rlshift__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rmod__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rmod__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rmul__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rmul__
rename from elpa/elpy-1.5.1/snippets/python-mode/__ror__ rename to elpa/elpy-1.8.0/snippets/python-mode/__ror__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rpow__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rpow__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rrshift__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rrshift__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rshift__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rshift__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rsub__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rsub__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rtruediv__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rtruediv__
rename from elpa/elpy-1.5.1/snippets/python-mode/__rxor__ rename to elpa/elpy-1.8.0/snippets/python-mode/__rxor__
rename from elpa/elpy-1.5.1/snippets/python-mode/__set__ rename to elpa/elpy-1.8.0/snippets/python-mode/__set__
rename from elpa/elpy-1.5.1/snippets/python-mode/__setattr__ rename to elpa/elpy-1.8.0/snippets/python-mode/__setattr__
rename from elpa/elpy-1.5.1/snippets/python-mode/__setitem__ rename to elpa/elpy-1.8.0/snippets/python-mode/__setitem__
rename from elpa/elpy-1.5.1/snippets/python-mode/__slots__ rename to elpa/elpy-1.8.0/snippets/python-mode/__slots__
rename from elpa/elpy-1.5.1/snippets/python-mode/__str__ rename to elpa/elpy-1.8.0/snippets/python-mode/__str__
rename from elpa/elpy-1.5.1/snippets/python-mode/__sub__ rename to elpa/elpy-1.8.0/snippets/python-mode/__sub__
rename from elpa/elpy-1.5.1/snippets/python-mode/__subclasscheck__ rename to elpa/elpy-1.8.0/snippets/python-mode/__subclasscheck__
rename from elpa/elpy-1.5.1/snippets/python-mode/__truediv__ rename to elpa/elpy-1.8.0/snippets/python-mode/__truediv__
rename from elpa/elpy-1.5.1/snippets/python-mode/__unicode__ rename to elpa/elpy-1.8.0/snippets/python-mode/__unicode__
rename from elpa/elpy-1.5.1/snippets/python-mode/__xor__ rename to elpa/elpy-1.8.0/snippets/python-mode/__xor__
rename from elpa/elpy-1.5.1/snippets/python-mode/ase rename to elpa/elpy-1.8.0/snippets/python-mode/ase
rename from elpa/elpy-1.5.1/snippets/python-mode/asne rename to elpa/elpy-1.8.0/snippets/python-mode/asne
rename from elpa/elpy-1.5.1/snippets/python-mode/asr rename to elpa/elpy-1.8.0/snippets/python-mode/asr
rename from elpa/elpy-1.5.1/snippets/python-mode/class rename to elpa/elpy-1.8.0/snippets/python-mode/class
rename from elpa/elpy-1.5.1/snippets/python-mode/defs rename to elpa/elpy-1.8.0/snippets/python-mode/defs
rename from elpa/elpy-1.5.1/snippets/python-mode/enc rename to elpa/elpy-1.8.0/snippets/python-mode/enc
rename from elpa/elpy-1.5.1/snippets/python-mode/env rename to elpa/elpy-1.8.0/snippets/python-mode/env
rename from elpa/elpy-1.5.1/snippets/python-mode/from rename to elpa/elpy-1.8.0/snippets/python-mode/from
rename from elpa/elpy-1.5.1/snippets/python-mode/pdb rename to elpa/elpy-1.8.0/snippets/python-mode/pdb
rename from elpa/elpy-1.5.1/snippets/python-mode/py3 rename to elpa/elpy-1.8.0/snippets/python-mode/py3
rename from elpa/elpy-1.5.1/snippets/python-mode/super rename to elpa/elpy-1.8.0/snippets/python-mode/super
deleted file mode 100644 --- a/elpa/pyvenv-1.4/pyvenv-pkg.el +++ /dev/null @@ -1,1 +0,0 @@ -(define-package "pyvenv" "1.4" "Python virtual environment interface" (quote nil))
rename from elpa/pyvenv-1.4/pyvenv-autoloads.el rename to elpa/pyvenv-1.7/pyvenv-autoloads.el --- a/elpa/pyvenv-1.4/pyvenv-autoloads.el +++ b/elpa/pyvenv-1.7/pyvenv-autoloads.el @@ -1,11 +1,9 @@ ;;; pyvenv-autoloads.el --- automatically extracted autoloads ;; ;;; Code: - +(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) -;;;### (autoloads (pyvenv-restart-python pyvenv-tracking-mode pyvenv-mode -;;;;;; pyvenv-workon pyvenv-deactivate pyvenv-activate) "pyvenv" -;;;;;; "pyvenv.el" (21577 27285 746618 82000)) +;;;### (autoloads nil "pyvenv" "pyvenv.el" (21954 12863 384604 302000)) ;;; Generated autoloads from pyvenv.el (autoload 'pyvenv-activate "pyvenv" "\ @@ -65,15 +63,9 @@ ;;;*** -;;;### (autoloads nil nil ("pyvenv-pkg.el") (21577 27285 829394 107000)) - -;;;*** - -(provide 'pyvenv-autoloads) ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t -;; coding: utf-8 ;; End: ;;; pyvenv-autoloads.el ends here
new file mode 100644 --- /dev/null +++ b/elpa/pyvenv-1.7/pyvenv-pkg.el @@ -0,0 +1,1 @@ +(define-package "pyvenv" "1.7" "Python virtual environment interface" 'nil)
rename from elpa/pyvenv-1.4/pyvenv.el rename to elpa/pyvenv-1.7/pyvenv.el --- a/elpa/pyvenv-1.4/pyvenv.el +++ b/elpa/pyvenv-1.7/pyvenv.el @@ -1,10 +1,10 @@ ;;; pyvenv.el --- Python virtual environment interface -*- lexical-binding: t -*- -;; Copyright (C) 2013, 2014 Jorgen Schaefer <contact@jorgenschaefer.de> +;; Copyright (C) 2013-2015 Jorgen Schaefer <contact@jorgenschaefer.de> ;; Author: Jorgen Schaefer <contact@jorgenschaefer.de> ;; URL: http://github.com/jorgenschaefer/pyvenv -;; Version: 1.4 +;; Version: 1.7 ;; Keywords: Python, Virtualenv, Tools ;; This program is free software; you can redistribute it and/or @@ -145,7 +145,9 @@ (setq directory (expand-file-name directory)) (pyvenv-deactivate) (setq pyvenv-virtual-env directory - pyvenv-virtual-env-name (file-name-nondirectory directory)) + pyvenv-virtual-env-name (file-name-nondirectory directory) + python-shell-virtualenv-path directory + python-shell-virtualenv-root directory) ;; Preserve variables from being overwritten. (let ((old-exec-path exec-path) (old-process-environment process-environment)) @@ -167,7 +169,7 @@ (format "PATH=%s" (mapconcat (lambda (x) (or x ".")) exec-path - (if (eq system-type 'windows-nt) ";" ":"))) + path-separator)) ;; No "=" means to unset "PYTHONHOME") process-environment) @@ -200,7 +202,9 @@ process-environment old-process-environment))) (run-hooks 'pyvenv-post-deactivate-hooks)) (setq pyvenv-virtual-env nil - pyvenv-virtual-env-name nil)) + pyvenv-virtual-env-name nil + python-shell-virtualenv-root nil + python-shell-virtualenv-path nil)) (defvar pyvenv-workon-history nil "Prompt history for `pyvenv-workon'.") @@ -218,42 +222,46 @@ ;; https://github.com/jorgenschaefer/elpy/issues/144 (equal name nil))) (pyvenv-activate (format "%s/%s" - (or (getenv "WORKON_HOME") - "~/.virtualenvs") + (pyvenv-workon-home) name)))) -(defun pyvenv-virtualenv-list () - "Prompt the user for a name in $WORKON_HOME." - (let ((workon-home (or (getenv "WORKON_HOME") - "~/.virtualenvs")) +(defun pyvenv-virtualenv-list (&optional noerror) + "Prompt the user for a name in $WORKON_HOME. + +If NOERROR is set, do not raise an error if WORKON_HOME is not +configured." + (let ((workon-home (pyvenv-workon-home)) (result nil)) - (when (not (file-directory-p workon-home)) - (error "Can't find a workon home directory, set $WORKON_HOME")) - (dolist (name (directory-files workon-home)) - (when (or (file-exists-p (format "%s/%s/bin/activate" - workon-home name)) - (file-exists-p (format "%s/%s/Scripts/activate.bat" - workon-home name))) - (setq result (cons name result)))) - (sort result (lambda (a b) - (string-lessp (downcase a) - (downcase b)))))) + (if (not (file-directory-p workon-home)) + (when (not noerror) + (error "Can't find a workon home directory, set $WORKON_HOME")) + (dolist (name (directory-files workon-home)) + (when (or (file-exists-p (format "%s/%s/bin/activate" + workon-home name)) + (file-exists-p (format "%s/%s/Scripts/activate.bat" + workon-home name))) + (setq result (cons name result)))) + (sort result (lambda (a b) + (string-lessp (downcase a) + (downcase b))))))) (define-widget 'pyvenv-workon 'choice "Select an available virtualenv from virtualenvwrapper." - :convert-widget (lambda (widget) - (setq widget (widget-copy widget)) - (widget-put widget - :args (cons '(const :tag "None" nil) - (mapcar (lambda (env) - (list 'const env)) - (pyvenv-virtualenv-list)))) - (widget-types-convert-widget widget)) + :convert-widget + (lambda (widget) + (setq widget (widget-copy widget)) + (widget-put widget + :args (cons '(const :tag "None" nil) + (mapcar (lambda (env) + (list 'const env)) + (pyvenv-virtualenv-list t)))) + (widget-types-convert-widget widget)) + :prompt-value (lambda (widget prompt value unbound) (let ((name (completing-read prompt (cons "None" - (pyvenv-virtualenv-list)) + (pyvenv-virtualenv-list t)) nil t))) (if (equal name "None") nil @@ -274,7 +282,7 @@ :style 'radio :selected `(equal pyvenv-virtual-env-name ,venv))) - (pyvenv-virtualenv-list)))) + (pyvenv-virtualenv-list t)))) ["Activate" pyvenv-activate :help "Activate a virtual environment by directory"] ["Deactivate" pyvenv-deactivate @@ -340,46 +348,47 @@ CAREFUL! This will modify your `process-environment' and `exec-path'." - (with-temp-buffer - (let ((tmpfile (make-temp-file "pyvenv-virtualenvwrapper-"))) - (unwind-protect - (progn - (apply #'call-process - pyvenv-virtualenvwrapper-python - nil t nil - "-c" - "from virtualenvwrapper.hook_loader import main; main()" - "--script" tmpfile - (if (getenv "HOOK_VERBOSE_OPTION") - (cons (getenv "HOOK_VERBOSE_OPTION") - (cons hook args)) - (cons hook args))) - (call-process-shell-command - (format ". '%s' ; echo ; echo =-=-= ; python -c \"import os, json ; print(json.dumps(dict(os.environ)))\"" - tmpfile) - nil t nil)) - (delete-file tmpfile))) - (goto-char (point-min)) - (when (and (not (re-search-forward "ImportError: No module named virtualenvwrapper" nil t)) - (re-search-forward "\n=-=-=\n" nil t)) - (let ((output (buffer-substring (point-min) - (match-beginning 0)))) - (when (> (length output) 0) - (with-help-window "*Virtualenvwrapper Hook Output*" - (with-current-buffer "*Virtualenvwrapper Hook Output*" - (let ((inhibit-read-only t)) - (erase-buffer) - (insert - (format - "Output from the virtualenvwrapper hook %s:\n\n" - hook) - output)))))) - (dolist (binding (json-read)) - (let ((env (format "%s=%s" (car binding) (cdr binding)))) - (when (not (member env process-environment)) - (setq process-environment (cons env process-environment)))) - (when (eq (car binding) 'PATH) - (setq exec-path (split-string (cdr binding) ":"))))))) + (when (pyvenv-hook-dir) + (with-temp-buffer + (let ((tmpfile (make-temp-file "pyvenv-virtualenvwrapper-"))) + (unwind-protect + (progn + (apply #'call-process + pyvenv-virtualenvwrapper-python + nil t nil + "-c" + "from virtualenvwrapper.hook_loader import main; main()" + "--script" tmpfile + (if (getenv "HOOK_VERBOSE_OPTION") + (cons (getenv "HOOK_VERBOSE_OPTION") + (cons hook args)) + (cons hook args))) + (call-process-shell-command + (format ". '%s' ; echo ; echo =-=-= ; python -c \"import os, json ; print(json.dumps(dict(os.environ)))\"" + tmpfile) + nil t nil)) + (delete-file tmpfile))) + (goto-char (point-min)) + (when (and (not (re-search-forward "ImportError: No module named virtualenvwrapper" nil t)) + (re-search-forward "\n=-=-=\n" nil t)) + (let ((output (buffer-substring (point-min) + (match-beginning 0)))) + (when (> (length output) 0) + (with-help-window "*Virtualenvwrapper Hook Output*" + (with-current-buffer "*Virtualenvwrapper Hook Output*" + (let ((inhibit-read-only t)) + (erase-buffer) + (insert + (format + "Output from the virtualenvwrapper hook %s:\n\n" + hook) + output)))))) + (dolist (binding (json-read)) + (let ((env (format "%s=%s" (car binding) (cdr binding)))) + (when (not (member env process-environment)) + (setq process-environment (cons env process-environment)))) + (when (eq (car binding) 'PATH) + (setq exec-path (split-string (cdr binding) ":")))))))) ;;;###autoload (defun pyvenv-restart-python () @@ -406,6 +415,22 @@ (run-python cmd dedicated show) (goto-char (point-max))))))) +(defun pyvenv-hook-dir () + "Return the current hook directory. + +This is usually the value of $VIRTUALENVWRAPPER_HOOK_DIR, but +virtualenvwrapper has stopped exporting that variable, so we go +back to the default of $WORKON_HOME or even just ~/.virtualenvs/." + (or (getenv "VIRTUALENVWRAPPER_HOOK_DIR") + (pyvenv-workon-home))) + +(defun pyvenv-workon-home () + "Return the current workon home. + +This is the value of $WORKON_HOME or ~/.virtualenvs." + (or (getenv "WORKON_HOME") + (expand-file-name "~/.virtualenvs"))) + ;;; Compatibility (when (not (fboundp 'file-name-base))