Skip to content

mattkeller/mk-project

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

69 Commits
 
 
 
 

Repository files navigation

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 find-grep on the project's basedir, ignoring any files that match ignore-patterns or are excluded by the vcs setting. mk-project.el knows how to avoid the VCS-specific files and directories of git, cvs, subversion, mercurial and bzr. If given a C-u argument, start the search from the current buffer's directory.
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-find-file. The index can be cached to the file set in file-list-cache.
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 project-def.

Directive Required/Optional Description
basedir Required Base directory of the current project. Value is expanded with expand-file-name. Example: "/home/me/my-proj/"
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 project-find-file and project-grep. Example: '("*.class")
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 expand-file-name.
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 project-index will save to this file. Value is expanded with expand-file-name.
open-files-cache Optional Cache the names of open project files in this file. If set, project-load will open all files listed in this file and project-unload will write all open project files to this file. Value is expanded with expand-file-name.

The following advanced directives are useful if the 'find' commands generated by project-tags, project-grep or 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.

Directive Required/Optional Description
src-find-cmd Optional

Specifies a custom "find" command to locate all files to be included in the TAGS file (see project-tags). The value is either a string or a function of one argument that returns a string. The argument to the function will be the symbol 'src.

Examples:

  
  ;; A simple string with a custom find command. However, if your
  ;; command is this simple, you don't need src-find-cmd -- just
  ;; use src-patterns
  (src-find-cmd "find /home/me/my-java-project/ -type f -name '*.java'")
  
  
  
  ;; an anonymous function that builds a custom find command
  (src-find-cmd (lambda (context)
                  (concat "find " mk-proj-basedir " -type f -name '*java'")))
  
  
  
  ;; a single function that returns a more complex find command based on context
  (defun my-find-cmd (context)
    (let* ((ignore-clause  (concat "\\( -path " mk-proj-basedir "/thirdparty -prune \\)"))
           (src-clause     "\\( -type f \\( -name '*.cpp' -o -name '*.[cChH]' -o -name '*.java' \\) -print \\)"))
      (ecase context
        ('src   (concat "find " mk-proj-basedir " " ignore-clause " -o " src-clause))
        ('grep  (replace-regexp-in-string "-print" "-print0" (concat "find . " src-clause) t))
        ('index (concat "find " mk-proj-basedir " " ignore-clause " -o -print")))))
        
  (src-find-cmd   my-find-cmd)
  (index-find-cmd my-find-cmd)
  (grep-find-cmd  my-find-cmd)
  
  

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.

grep-find-cmd Optional

Specifies a custom "find" command to use as the default when running project-grep. The value is either a string or a function of one argument that returns a string. The argument to the function will be the symbol 'grep. The string or returned string MUST use find's "-print0" argument as the results of this command are piped to "xargs -0 ...".

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 to project-grep to run the command from the current buffer's directory.

See the documentation of src-find-cmd for example values.

index-find-cmd Optional

Specifies a custom "find" command to use when building an listing of all files in the project (to be used by project-find-file). The value is either a string or a function of one argument that returns a string. The argument to the function will be the symbol 'index.

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?

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.

Andreas Raster contributed code and ideas to the 1.5 release. Andreas also maintains a 'anything' integration module.

Various others have contributed bug reports and ideas.

Thanks to all for their code and ideas!

About

A Emacs project library. Quickly switch between projects and perform operations on a per-project basis.

Resources

Stars

Watchers

Forks

Packages

No packages published