How can I use meta-dot (M-.) in python with emacs?
Asked Answered
G

6

25

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?

Gerome answered 17/8, 2010 at 9:24 Comment(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.Gerome
K
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
Kerguelen answered 17/8, 2010 at 14:45 Comment(7)
Yeah, but the relevant .py files are not in a subdirectory of my code, they are in ~/.virtualenv whereas I work in ~/src/project/fooGerome
With find you can use any directory you want: find ~/.virtualenv -type f -name '*.py' | xargs etagsKerguelen
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.Gerome
@Gerome sorry I don't get what you said. What I wrote to you is the shell command to generate the TAGS file.Kerguelen
@Kerguelen 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.Bacolod
Well emacs manual recommends find . -name "*.[py]" -print | etags - which removes de necesity for xargs. gnu.org/software/emacs/manual/html_node/emacs/…Illnatured
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 -Consequential
B
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.

Bioscope answered 14/9, 2015 at 11:49 Comment(0)
I
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.

Interinsurance answered 17/8, 2010 at 11:38 Comment(4)
I recommend looking at emacswiki.org/emacs/EtagsSelect as well, which provides a nicer interface if you bind M-. to etags-select-find-tagTearoom
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?Gerome
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'.Laddie
ctags does not support the option -e (at least on Mac OS X and Ubuntu). So, could you please fix it?Riha
B
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
Blockage answered 28/3, 2015 at 16:53 Comment(0)
G
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

Greasy answered 25/6, 2017 at 14:40 Comment(1)
"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).Gymnastics
S
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!

Singleton answered 6/3, 2018 at 10:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.