From 94d2fc1815a919734353c942f224db1de4b4fcb8 Mon Sep 17 00:00:00 2001 From: Tom Willemsen Date: Mon, 7 Mar 2011 09:04:49 +0100 Subject: Django, org * Added nxhtml, mostly for django support. * Changed some org settings. --- emacs.d/nxhtml/util/ffip.el | 304 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 304 insertions(+) create mode 100644 emacs.d/nxhtml/util/ffip.el (limited to 'emacs.d/nxhtml/util/ffip.el') diff --git a/emacs.d/nxhtml/util/ffip.el b/emacs.d/nxhtml/util/ffip.el new file mode 100644 index 0000000..42d1893 --- /dev/null +++ b/emacs.d/nxhtml/util/ffip.el @@ -0,0 +1,304 @@ +;;; ffip.el --- Find files in project +;; +;; Authors: extracted from rinari by Phil Hagelberg and Doug Alcorn +;; Changed by Lennart Borgman +;; Created: 2008-08-14T23:46:22+0200 Thu +;; Version: 0.3 +;; Last-Updated: 2008-12-28 Sun +;; URL: +;; Keywords: +;; Compatibility: +;; +;; Features that might be required by this library: +;; +;; None +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Commentary: +;; +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Change log: +;; +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; This program is free software; you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as +;; published by the Free Software Foundation; either version 2, or +;; (at your option) any later version. +;; +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +;; General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program; see the file COPYING. If not, write to +;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth +;; Floor, Boston, MA 02110-1301, USA. +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;;; Code: + +(eval-when-compile (require 'cl)) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Project data + +;; Fix-me: Change the inner structure of ffip projects +(defvar ffip-project-name nil "Project name.") +(defvar ffip-project-roots nil "Project directory roots.") +(defvar ffip-project-type nil "Project type, `ffip-project-file-types'.") +(defcustom ffip-project-file-types + (list + '(ruby "\\(\\.el$\\|\\.rb$\\|\\.js$\\|\\.emacs\\)") + (list 'nxhtml (concat + (regexp-opt '(".html" ".htm" ".xhtml" + ".css" + ".js" + ".png" ".gif" + )) + "\\'")) + ) + "Project types and file types. +The values in this list are used to determine if a file belongs +to the current ffip project. Entries have the form + + \(TYPE FILE-REGEXP) + +TYPE is the parameter set by `ffip-set-current-project'. Files +matching FILE-REGEXP within the project roots are members of the +project." + :type '(repeat (list + (symbol :tag "Type") + (regexp :tag "File regexp"))) + :group 'ffip) + +(defvar ffip-project-file-matcher nil "Project file matcher.") +(defvar ffip-project-files-table nil "Project file cache.") + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Project handling + +(defun ffip-reset-project () + "Clear project data." + (remove-hook 'after-save-hook 'ffip-after-save) + (setq ffip-project-name nil) + (setq ffip-project-roots nil) + (setq ffip-project-files-table nil) + (setq ffip-project-type nil) + (setq ffip-project-file-matcher nil)) +;;(ffip-reset-project) + +(defun ffip-is-current (name root type) + "Return non-nil if NAME, ROOT and TYPE match current ffip project. +See `ffip-set-current-project'." + (and name + (string= ffip-project-name name) + (eq ffip-project-type type) + (equal ffip-project-roots root))) + +;;;###autoload +(defun ffip-set-current-project (name root type) + "Setup ffip project NAME with top directory ROOT of type TYPE. +ROOT can either be just a directory or a list of directory where +the first used just for prompting purposes and the files in the +rest are read into the ffip project. + +Type is a type in `ffip-project-file-types'." + (unless (ffip-is-current name root type) + (ffip-reset-project) + (setq ffip-project-name name) + (setq ffip-project-type type) + (setq ffip-project-roots root) + (message "Project %s with %s files setup for find-files-in-project" + name (length ffip-project-files-table)))) + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; File cache handling + +(defun ffip-cache-project-files (file-regexp) + "Read files and cache their names within the ffip project." + (let ((root ffip-project-roots)) + (message "... reading files in %s ..." root) + (add-hook 'after-save-hook 'ffip-after-save) + (if (not (listp root)) + (ffip-populate-files-table root file-regexp) + (setq root (cdr root)) + (dolist (r root) + (ffip-populate-files-table r file-regexp))))) + +(defun ffip-file-matcher () + (when ffip-project-type + (cadr (assoc ffip-project-type ffip-project-file-types)))) + +(defun ffip-project-files () + "Get a list of all files in ffip project. +The members in the list has the format + + \(SHORT-NAME . FULL-NAME) + +where SHORT-NAME is a unique name (normally file name without +directory) and FULL-NAME is the full file name." + (unless ffip-project-files-table + (let ((file-regexp (ffip-file-matcher))) + (ffip-cache-project-files file-regexp))) + ffip-project-files-table) + +;; Fix-me: Seems better to rewrite this to use +;; project-find-settings-file. +(defun ffip-project-root (&optional dir) + (setq dir (or dir + ffip-project-roots + default-directory)) + ;;(locate-dominating-file "." "\\`\\find-file-in-project.el\\'") + (let ((root (locate-dominating-file dir + ;;"\\`\\.emacs-project\\'" + "\\`\\.dir-settings\\.el\\'" + ))) + (if root + (file-name-directory root) + dir))) + +(defun ffip-populate-files-table (file file-regexp) + ;;(message "ffip-populate-files-table.file=%s" file) + (if (file-directory-p file) + (mapc (lambda (file) + (ffip-populate-files-table file file-regexp)) + (directory-files (expand-file-name file) t "^[^\.]")) + (let* ((file-name (file-name-nondirectory file)) + (existing-record (assoc file-name ffip-project-files-table)) + (unique-parts (ffip-get-unique-directory-names file + (cdr existing-record)))) + (when (or (not file-regexp) + (string-match file-regexp file-name)) + (if existing-record + (let ((new-key (concat file-name " - " (car unique-parts))) + (old-key (concat (car existing-record) " - " + (cadr unique-parts)))) + (setf (car existing-record) old-key) + (setq ffip-project-files-table + (acons new-key file ffip-project-files-table))) + (setq ffip-project-files-table + (acons file-name file ffip-project-files-table))))))) + +(defun ffip-get-unique-directory-names (path1 path2) + (let* ((parts1 (and path1 (split-string path1 "/" t))) + (parts2 (and path2 (split-string path2 "/" t))) + (part1 (pop parts1)) + (part2 (pop parts2)) + (looping t)) + (while (and part1 part2 looping) + (if (equal part1 part2) + (setq part1 (pop parts1) part2 (pop parts2)) + (setq looping nil))) + (list part1 part2))) + +(defun ffip-file-is-in-project (file-name) + "Return non-nil if file is in current ffip project." + (save-match-data + (let ((file-regexp (ffip-file-matcher)) + (roots ffip-project-roots) + regexp) + (if (not (listp roots)) + (setq roots (list roots)) + (setq roots (cdr roots))) + (catch 'found + (dolist (root roots) + (setq file-regexp (concat root ".*" file-regexp)) + (when (string-match file-regexp file-name) + (throw 'found t))))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Updating on file changes + +(defun ffip-add-file-if-in-project (file-name) + "Add file to cache if it in ffip project." + (when (ffip-file-is-in-project file-name) + ;; We have already checked so just use nil for the matcher. + (ffip-populate-files-table file-name nil))) + +;; For after-save-hook +(defun ffip-after-save () + "Check if a file should be added to cache." + (condition-case err + (ffip-add-file-if-in-project buffer-file-name) + (error (message "%s" (error-message-string err))))) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Interactive functions + +;;;###autoload +(defun ffip-find-file-in-dirtree (root) + "Find files in directory tree ROOT." + (interactive "DFind file in directory tree: ") + ;; Setup a temporary + (let ((ffip-project-name nil) + (ffip-project-roots nil) + (ffip-project-files-table nil) + (ffip-project-type nil) + (ffip-project-file-matcher nil)) + (ffip-set-current-project "(temporary)" root nil) + (call-interactively 'ffip-find-file-in-project))) + +(defun ffip-find-file-in-project (file) + "Find files in current ffip project." + (interactive + (list + (let* ((prompt (format "Find file in project %s: " + ffip-project-name))) + (if (memq ido-mode '(file 'both)) + (ido-completing-read prompt + (mapcar 'car (ffip-project-files))) + (let ((files (mapcar 'car (ffip-project-files)))) + (completing-read prompt + files + (lambda (elem) (member elem files)) + t)))))) + (find-file (cdr (assoc file ffip-project-files-table)))) + +;;(global-set-key (kbd "C-x C-M-f") 'find-file-in-project) + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Fix-me: This part should go somewhere else +(eval-after-load 'ruby-mode + '(progn + (defun ffip-rails-project-files (&optional file) + (let ((default-directory (or file (rails-root)))) + (unless (and ffip-project-roots + (string= default-directory ffip-project-roots)) + (ffip-set-current-project + "Rails proj" + root + (list default-directory + (expand-file-name "app") + (expand-file-name "lib") + (expand-file-name "test")) + 'ruby + ))) + (ffip-project-files)) + + (defun ffip-find-file-in-rails (file) + (interactive + (list (if (memq ido-mode '(file 'both)) + (ido-completing-read + "Find file in project: " + (mapcar 'car (ffip-rails-project-files))) + (completing-read "Find file in project: " + (mapcar 'car (rails-project-files)))))) + (find-file (cdr (assoc file ffip-project-files-table)))) + + (define-key ruby-mode-map (kbd "C-x C-M-f") 'find-file-in-rails) + (eval-after-load 'nxhtml-mode + '(define-key nxhtml-mode-map (kbd "C-x C-M-f") 'find-file-in-rails)))) + +(provide 'ffip) +;;; ffip.el ends here -- cgit v1.2.3-54-g00ecf