mk-project.el: An Emacs project library
What is it?
mk-project.el is an Emacs library to quickly switch between projects and perform operations on a per-project basis. A project in this sense is a directory of related files, usually a directory of source files. Projects are configured in pure Emacs lisp and do not require configuration files in the project's directory.
The "mk" in mk-project used to stand for me, Matt Keller, but now that I've published this library, let's say it stands for "make" as in "make project".
How does it work?
A project is configured in 100% pure elisp. For example, the following elisp code...
(project-def "my-java-project" '((basedir "/home/me/my-java-project/") (src-patterns ("*.java" "*.jsp")) (ignore-patterns ("*.class" "*.wsdl")) (tags-file "/home/me/.my-java-project/TAGS") (file-list-cache "/home/me/.my-java-project/files") (open-files-cache "/home/me/.my-java-project/open-files") (vcs git) (compile-cmd "ant") (ack-args "--java") (startup-hook my-java-project-startup) (shutdown-hook nil))) (defun my-java-project-startup () (setq c-basic-offset 3))
...defines a project called "my-java-project" under the /home/me/my-java-project directory with additional, optional settings to help identify which files should be included in your TAGS file, which files should be excluded from a grep operation, etc.
Once a project is configured via
project-def and loaded via
project-load, the following project functions can be used:
|Function||Recommended Key Binding||Description|
|project-load||C-c p l||Set project variables, open files named in the open-files-cache, run the user-defined startup hook.|
|project-unload||C-c p u||Save open files names to the open-files-cache, run shutdown hook, run the user-defined shutdown hook, unset project variables, prompt to close all project files.|
|project-compile||C-c p c||Run the project's compile-cmd with the given arguments.|
|project-grep||C-c p g||Run
|project-ack||C-c p a||Run ack from the project's basedir. If given a C-u argument, run ack from the current buffer's directory.|
|project-multi-occur||C-c p o||Search open project files using multi-occur.|
|project-find-file||C-c p f||Quickly open a file in the project's basedir by regex. The search excludes files matching ignore-patterns or excluded by the vcs setting.|
|project-find-file-ido||C-c p f||Quickly open a file in basedir using ido.|
|project-index||C-c p i||Re-index the project files. The index is stored in buffer *file-index*
and is used by
|project-tags||C-c p t||Regenerate the project's TAGS file. Only files matching src-patterns are indexed (see also src-find-cmd).|
|project-dired||C-c p d||Open dired on the project's basedir.|
|project-status||C-c p s||Print values of project variables|
|project-menu||Enable the 'mk-project' menu.|
|project-menu-remove||Disable the 'mk-project' menu.|
mk-project.el relies heavily on the find and grep commands in your environment. Unix and Linux systems certainly have find and grep. Cygwin can provide these commands for Windows.
The following table describes the configuration directives that are used in
|basedir||Required||Base directory of the current project. Value is expanded with
|src-patterns||Optional||List of shell patterns to include in the TAGS file. Example: '("*.java" "*.jsp")|
|ignore-patterns||Optional||List of shell patterns to avoid searching for with
|ack-args||Optional||String of arguments to pass to the ack command. Example: "--java"|
|vcs||Optional||When set to one of 'git, 'cvs, 'svn, 'bzr, 'hg, or 'darcs the grep and index commands will ignore the VCS's private files (for example, the .git directory or the .CVS directories).|
|tags-file||Optional||Path to the TAGS file for this project. Use an absolute path, not one relative to basedir. Value is expanded with
|compile-cmd||Optional||Command to build the project. Can be either a string specifying a shell command or the name of a function to call. Example: "make -k"|
|startup-hook||Optional||Hook function to run after the project is loaded. Project variables (e.g. mk-proj-basedir) will be set and can be referenced from this function.|
|shutdown-hook||Optional||Hook function to run after the project is unloaded. Project variables (e.g. mk-proj-basedir) will still be set and can be referenced from this function.|
|file-list-cache||Optional||Cache *file-index* buffer to this file. If set, the *file-index* buffer will take its initial value from this file and updates to the buffer via
|open-files-cache||Optional||Cache the names of open project files in this file. If set,
The following advanced directives are useful if the 'find' commands generated by
project-index aren't sophisticated enough for your project. For example, if you would like to exclude a particular directory from your TAGS file, you can write a custom find command which uses the "-prune" option to exclude the path.
Specifies a custom "find" command to locate all files to be included in the TAGS file (see
If non-null (or if the function returns non-null), the custom find command will be used and the src-patterns and vcs settings are ignored when finding files to include in TAGS.
Specifies a custom "find" command to use as the default when
If non-null (or if the function returns non-null), the custom find command will be used and the ignore-patterns and vcs settings will not be used in the grep command.
The custom find command should use "." (current directory) as
the path that find starts at -- this will allow the C-u argument
See the documentation of src-find-cmd for example values.
Specifies a custom "find" command to use when building an
listing of all files in the project (to be used by
If non-null (or if the function returns non-null), the custom find command will be used and the ignore-patterns and vcs settings are not used when in the grep command.
See the documentation of src-find-cmd for example values.
Where can I get it?
Releases of mk-project are uploaded to the Emacs Wiki.
You can track the code at github: http://github.com/mattkeller/mk-project.
How do I install it?
Download mk-project.el. Place it in your emacs load-path. Load the library with
(require 'mk-project). Then define your projects in your .emacs file.
The following key bindings are useful:
(global-set-key (kbd "C-c p c") 'project-compile) (global-set-key (kbd "C-c p l") 'project-load) (global-set-key (kbd "C-c p a") 'project-ack) (global-set-key (kbd "C-c p g") 'project-grep) (global-set-key (kbd "C-c p o") 'project-multi-occur) (global-set-key (kbd "C-c p u") 'project-unload) (global-set-key (kbd "C-c p f") 'project-find-file) ; or project-find-file-ido (global-set-key (kbd "C-c p i") 'project-index) (global-set-key (kbd "C-c p s") 'project-status) (global-set-key (kbd "C-c p h") 'project-home) (global-set-key (kbd "C-c p d") 'project-dired) (global-set-key (kbd "C-c p t") 'project-tags)
What's going on with it?
- 2010/10/23: Released version 1.5.1 with some new features.
- 2010/04/18: Released version 1.4.0 with several enhancements.
- 2010/02/09: Released version 1.3.1 with a default-directory bug fix.
- 2010/01/30: Released version 1.3 with custom find command support.
- 2009/12/16: Released version 1.2.1 with a bug fix.
- 2009/09/09: Released version 1.2 with ido integration.
- 2009/06/11: Released version 1.1 with ack support.
- 2009/05/26: Pushed mk-project v1.0.3 to github.
- 2009/05/26: Released version 1.0.2.
- 2009/05/23: Released version 1.0.1.
Why is it?
There are several Emacs libraries that do similar things (ProjMan, project-root), but none of them fit all my needs. Uniquely, mk-project.el allows users to define projects in pure elisp while most of the existing projects required per-directory config files which don't always fit well with your version control software. Specifically, the libraries I mentioned do not work well with Clearcase's dynamic views.
Found a bug or have a feature request?
Feel free to contact Matt at mk -at- littleredbat -dot- net or submit an issue online.
How is it licensed?
mk-project is licensed under the GPLv2.
Who wrote it?
Matt Keller is the primary author.
Various others have contributed bug reports and ideas.
Thanks to all for their code and ideas!