Skip to content

Instantly share code, notes, and snippets.

@david
Created March 26, 2011 18:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save david/888509 to your computer and use it in GitHub Desktop.
Save david/888509 to your computer and use it in GitHub Desktop.
(load-library "simple-project")
(defun sp-ruby-activate-rvm ()
(if (and sp-current-root
(featurep 'rvm)
(locate-dominating-file sp-current-root ".rvmrc"))
(rvm-activate-corresponding-ruby)))
(add-hook 'sp-open-project-hook 'sp-ruby-activate-rvm)
(load-library "simple-project")
(if (featurep 'magit)
(progn
(defun sp-utils-magit (root)
(interactive (list (sp-get-root)))
(magit-status root))
(define-key sp-global-map "v" 'sp-utils-magit)))
(defun sp-utils-eshell (root)
(interactive (list (sp-get-root)))
(sp-with-root
root
(let ((eshell-buffer-name (format "*eshell<%s>*" sp-current-name)))
(eshell))))
(defun sp-git-grep (root)
(interactive (list (sp-get-root)))
(if (sp-file-in-project-p root (or (buffer-file-name) default-directory))
(call-interactively 'vc-git-grep)
(sp-with-root root
(call-interactively 'vc-git-grep))))
(define-key sp-global-map "s" 'sp-utils-eshell)
(define-key sp-global-map "g" 'sp-git-grep)
(defconst sp-open-projects nil
"The list of projects that are already open for this Emacs session.")
(defvar sp-current-name nil "Name of the current project.")
(make-variable-buffer-local 'sp-current-name)
(defvar sp-modeline-name nil "Name of the current project.")
(make-variable-buffer-local 'sp-modeline-name)
(defvar sp-current-root nil "Root directory of the current project.")
(make-variable-buffer-local 'sp-current-root)
(defvar sp-last-root nil "The root of the last project we visited.")
(defvar sp-open-project-hook nil "Hooks run whenever a project is initialized.")
(defvar sp-switch-project-hook nil "Hooks run whenever a project is switched to.")
(defvar sp-completing-read-function 'ido-completing-read
"Function used to read the project name.")
(defvar sp-base-root (expand-file-name "~/projects") "Directory holding project directories.")
(defvar sp-global-map (make-sparse-keymap)
"Keymap for global project bindings.")
(define-minor-mode sp-global-mode
"Toggle global simple project mode."
nil
nil
(list (cons "\C-c;" sp-global-map))
:global t
:group 'simple-project
(if sp-global-mode (sp-activate-global-mode) (sp-deactivate-global-mode)))
(define-minor-mode sp-mode
"Toggle project-mode."
nil
sp-current-name
:group 'simple-project
(if sp-mode (sp-activate-local-mode)))
(defmacro sp-with-root (root &rest body)
"Execute the forms in BODY in the root of the current project."
`(let* ((sp-current-root (file-name-as-directory root))
(sp-current-name (sp-name-from-root sp-current-root))
(default-directory sp-current-root))
,@body))
(defun sp-activate-global-mode ()
(add-hook 'change-major-mode-hook 'sp-switch-project)
(add-hook 'after-change-major-mode-hook 'sp-turn-on-local-mode))
(defun sp-deactivate-global-mode ()
(remove-hook 'change-major-mode-hook 'sp-turn-on-local-mode)
(remove-hook 'change-major-mode-hook 'sp-switch-project))
(defun sp-turn-on-local-mode () (sp-mode 1))
(defun sp-activate-local-mode ()
(let ((root (sp-find-root)))
(when root
(sp-set-project-vars root)
(message (format "Activating project %s with root %s."
sp-current-name
sp-current-root)))))
(defun sp-set-project-vars (root)
(setq sp-current-root root)
(setq sp-current-name (concat " " (sp-name-from-root root))))
(defun sp-switch-project ()
(let ((root (sp-find-root)))
(when (and root (not (member root sp-open-projects)))
(add-to-list 'sp-open-projects root)
(sp-with-root root (run-hooks 'sp-open-project-hook)))
(when (not (equal root sp-last-root))
(run-hooks 'sp-switch-project-hook)
(setq sp-last-root root))))
(defun sp-name-from-root (root)
(file-name-nondirectory (directory-file-name root)))
(defun sp-get-root ()
(if current-prefix-arg
(sp-completing-read)
(or sp-current-root (sp-completing-read))))
(defun sp-find-root ()
(let* ((from (or (buffer-file-name) default-directory))
(root (locate-dominating-file from ".git")))
(if root (file-name-as-directory (expand-file-name root)))))
(defun sp-completing-read ()
(let ((name
(funcall
sp-completing-read-function
"Project: " (directory-files sp-base-root nil "^[[:alpha:]]") nil t)))
(file-name-as-directory (expand-file-name name sp-base-root))))
(defun sp-file-in-project-p (root file)
(string-match root (expand-file-name file root)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment