=pod For a long time, I've had a hack in my L that let me easily visit related files in my perl projects. For example, if I am editing C and want to get to C, that would normally require a lot of typing. My hack finds all modules and tests and presents them as an iswitch buffer, so I can get to the test with about 3 keystrokes. Very nice. Now that I've started programming more frequently in other languages, I've missed having this feature. Instead of hacking something together for every other language I might use, I decided to generalize the concept of a "project" and "related files". The result is L. There are a few extensions like this for emacs already, but they are too invasive. They either require you to pollute your project with special metadata files, or they just assume that every file is a member of a project, and globally bind project commands everywhere. These solutions are both sub-optimal, so eproject takes a different approach. You declare project types with the C macro. Then when you open a file, eproject runs "selectors" associated with each project type until one of them returns true. Then, once it's sure that the file is a member of a project, it turns on the eproject minor mode (bringing in the keybindings), and runs a user-definable hook. It is as minimal and extensible as possible, so you can easily build your own features on top of it. (My next project will be integrating emacs and SD, a distributed bug tracker, and this project support will be essential to making it work the way I want it to. C, here we come!) Anyway, the eproject.el file linked above is all you need to get started. Put it somewhere where emacs will find it, then C<(require 'eproject)> in your C<.emacs>. After that, you can define your project types. (See the docs in that file for details.) To get you started, I'll share my Perl and Lisp settings. Here is what I do for Perl: lang:Common Lisp (define-project-type perl (generic) (or (look-for "Makefile.PL") (look-for "Build.PL")) :relevant-files ("\\.pm$" "\\.t$" "\\.pl$" "\\.PL$")) This will determine that a project is a Perl project by looking up the directory tree for a Makefile.PL or Build.PL. Then, it declares that "relevant files" end in .pm, .t, .pl, or .PL. Now, whenever I open a file in a Perl module, I can press C to open a related project file quickly. I also add to the generated C to make using the L even easier: (defun perl-project-includes () "Return list of -I flags to pass to perl." (eproject-assert-type 'perl) (list (concat (eproject-root) "/lib"))) (add-hook 'perl-project-file-visit-hook (lambda () (ignore-errors (stylish-repl-eval-perl (format "use lib '%s'" (car (perl-project-includes))))))) This will automatically add the project library directory to my REPL's C<@INC> when I visit a file in the project. That means I can immediately C and get the version I'm developing instead of the version I have installed. It makes everything feel more integrated, and saves me typing. (Before this, I set C<@INC> manually using hippie-expand to type the filenames for me. Pretty simple, but this is automatic and I don't have to think about it all.) My Lisp setup is even simpler: (define-project-type lisp (generic) (eproject--scan-parents-for file (lambda (directory) (let ((dname (file-name-nondirectory directory))) (file-exists-p (format "%s/%s.asd" directory dname))))) :relevant-files ("\\.lisp$" "\\.asd$")) Here, I scan up the directory tree looking for a file named C<< .asd >>. When I find that, that means I'm in a Lisp project, where *.lisp and *.asd files are relevant. (As you can see, the "selector" is arbitrary Lisp. You can run anything you want here, as long as it returns the project root or nil.) I think at some point I will add to the C and have it start SLIME, load the project's system via C, and switch to the main package. I always do this whenever I first open up a Lisp project anyway, so it makes sense to automate it away. Anyway, the possibilities are infinite. Try it out and let me know how it goes! Patches and questions are most welcome.