24

Is there an equivalent of slime for python?

For example, if I position the cursor on foo() and do M-. (jump to definition) I would like to see the source definition of the function foo

This should work regardless of whether foo is in

1) the local project directory

2) in some ~/.virtualenvs/bar/lib/site-packages

3) in some other python-path

4) virtual env is in use (ie, it should look in my current virtualenv)

Does the pymacs/ropemacs combination do any of this?

nunb
  • 339
  • 1
  • 2
  • 14
  • 1
    I would prefer the equivalent of slime, which is to say, something that groks python at the code/semantic level, not just at the textual level. Ropemacs or pymacs may be what I want, though I don't know if it helps with M-. in any way. – nunb Aug 18 '10 at 05:02

6 Answers6

18

To avoid the -e you can use etags and with a find you recursively add the py file:

find . -type f -name '*.py' | xargs etags
mathk
  • 7,973
  • 6
  • 45
  • 74
  • Yeah, but the relevant .py files are not in a subdirectory of my code, they are in ~/.virtualenv whereas I work in ~/src/project/foo – nunb Aug 18 '10 at 04:59
  • With find you can use any directory you want: `find ~/.virtualenv -type f -name '*.py' | xargs etags` – mathk Aug 18 '10 at 07:07
  • I guess this calls for a virtualenv hook then, so that the tags can automatically be generated for whatever working directory + virtualenv combo the user is in. – nunb Aug 18 '10 at 08:42
  • @nunb sorry I don't get what you said. What I wrote to you is the shell command to generate the TAGS file. – mathk Aug 18 '10 at 09:06
  • @mathk with virtualenv-wrapper you can execute a script when a virtualenv is being switched to. So I believe he is planning to run your find with both the virtualenv's lib/python/site-packages and his project's python file directories and pipe them to etags. I think there are other times when it would be useful to update the etags too. – saschwarz Nov 19 '12 at 03:26
  • 1
    Well emacs manual recommends find . -name "*.[py]" -print | etags - which removes de necesity for xargs. http://www.gnu.org/software/emacs/manual/html_node/emacs/Create-Tags-Table.html – PuercoPop Dec 21 '12 at 18:07
  • xargs works but comes with some limitations: Unix file names may contain blanks or newlines, causing incorrect processing by xargs because it will see a space separated file name as 2 or more separate files. If you use xargs its better to use the ```-0``` flag and make sure the program sending input to xargs uses null character ('\0') as separator to define end of file names. If you are using find then you should use: ```find . -type f -name '*.py' -print0 | xargs etags```. However emacs manual advises the simpler IMO: ```find . -type f -name '*.py' -print | etags -``` – cmaceachern Jul 13 '18 at 14:32
9

Most of the answers mentioned here are outdated. A simple solution is to use elpy for M-. without etags(which requires additional work).

Install elpy as mentioned here.

M-x package-install elpy

and then install python packages

$ sudo pip install rope jedi

Restart emacs , open any python file and run M-.

Elpy is fully documented, you can read about M-. here.

Chillar Anand
  • 27,936
  • 9
  • 119
  • 136
5

M-. normally runs the "find-tag" function. You should create a TAGS file of your python source files. Then you "visit-tags-table" before doing a M-. That way, Emacs will jump to all the definitions of the tag. Type C-u M-. to jump the next definition of your tag. See find-tag documentation for help. Consult Emacs help to know how to create a TAGS file from python source files.

You can for example use Exuberant Ctags for creating the TAGS file.

Go to the root directory of your python files and do this :

ctags -e -R .

A TAGS file is normally created at the root directory of the project.

Jérôme Radix
  • 10,285
  • 4
  • 34
  • 40
  • 3
    I recommend looking at http://www.emacswiki.org/emacs/EtagsSelect as well, which provides a nicer interface if you bind `M-.` to `etags-select-find-tag` – phils Aug 17 '10 at 22:13
  • With an etags in root, and several projects wouldn't it get confused between different installs of the same package (multiple site-packages?). Or at least, each time it'd pop up a buffer asking me *which* source defn I wanted to go to? – nunb Aug 18 '10 at 05:01
  • You create a TAGS file for each of your project at their respective root directory (not the root directory / of the system). Then you use 'visit-tags-table' on each TAGS file that interest you. All TAGS files reference are appended to 'tags-table-list' variable. Then, using M-. , emacs search for the keyword in all TAGS files referenced in 'tags-table-list'. – Jérôme Radix Aug 19 '10 at 15:14
  • `ctags` does not support the option `-e` (at least on Mac OS X and Ubuntu). So, could you please fix it? – ipinak Mar 18 '14 at 15:08
2

The following will index your current project

find . -type f -name '*.py' | xargs etags

But if you want to index your imported libs. You first activate your virtualenv. Then use which python to detect where your libs are and then pipe them to etags.

workon my-project # if using virtualenvwrappwer
source bin/activate # if using virtualenv

find ${$(which python)/\/bin\/python/} -type f -name '*.py' | xargs etags
cevaris
  • 5,671
  • 2
  • 49
  • 34
2

Accepted answer misses an important point, if you execute etags like find . -type f -name '*.py' | xargs etags then the TAGS file would be generated every time for each file.

The correct way to do it is to append data to the existing TAGS file with --append like

rm -f TAGS
find . -type f -name '*.py' -print0 | xargs -0 etags --append

Also if you want to include identifiers from virtual env site packages dir (e.g.: ~/.virtualenvs/bar/lib/site-packages):

SITEPACKAGES=$(cdvirtualenv;pwd)/lib/python3.6/site-packages/
find $SITEPACKAGES -type f -name '*.py' -print0 | xargs -0 etags -a

*adjust python3.6 to your current Python version

marcanuy
  • 23,118
  • 9
  • 64
  • 113
  • "then the TAGS file would be generated every time for each file": Why? xargs appends all filenames as arguments. `etags` is only invoked once (unless command line length exceeds limit). – jimis Dec 30 '20 at 15:48
1

Try emacs's anaconda-mode and company-anaconda packages. Update config:

(eval-after-load "company"
 '(add-to-list 'company-backends 'company-anaconda))
(add-hook 'python-mode-hook 'anaconda-mode)
(add-hook 'python-mode-hook 'company-mode)

Switch to virtualenv with pythonic-activate, if you have one.

Now you've got M-. and you can press M-* to go back!

simno
  • 418
  • 9
  • 14