Source

nosemacs / nose.el

Diff from to
 ;; Note that if your global nose isn't called "nosetests", then you'll want to
 ;; redefine nose-global-name to be the command that should be used.
 
+;; By default, the root of a project is found by looking for any of the files
+;; 'setup.py', '.hg' and '.git'. You can add files to check for to the file
+;; list:
+;;
+;; ; (add-to-list 'nose-project-root-files "something")
+
+;; or you can change the project root test to detect in some other way 
+;; whether a directory is the project root:
+;;
+;; ; (setq nose-project-root-test (lambda (dirname) (equal dirname "foo")))
+
 ;; Probably also want some keybindings:
 ;; (add-hook 'python-mode-hook
 ;;           (lambda ()
 ;;             (local-set-key "\C-cp." 'nosetests-pdb-one)))
 
 (defvar nose-project-names '("eco/bin/test"))
+(defvar nose-project-root-files '("setup.py" ".hg" ".git"))
+(defvar nose-project-root-test 'nose-project-root)
 (defvar nose-global-name "nosetests")
 
 (defun run-nose (&optional tests debug)
   "run nosetests"
   (let* ((nose (nose-find-test-runner))
-         (where (expand-file-name "../.." (file-name-directory nose)))
+         (where (nose-find-project-root))
          (args (if debug "--pdb" ""))
          (tnames (if tests tests "")))
-    (funcall (if debug 'pdb '(lambda (command)
-                               (compilation-start command
-                                                  nil
-                                                  (lambda (mode) (concat "*nosetests*")))))
-             (format "%s -v %s -w %s -c %s/setup.cfg %s"
+    (funcall (if debug 
+                 'pdb 
+               '(lambda (command)
+                  (compilation-start command
+                                     nil
+                                     (lambda (mode) (concat "*nosetests*")))))
+             (format "%s -v %s -w %s -c %ssetup.cfg %s"
                      (nose-find-test-runner) args where where tnames)))
   )
 
 
 (defun nose-find-test-runner ()
   (message
-   (let ((result (reduce '(lambda (x y) (or x y))
-                         (mapcar 'nose-find-test-runner-names nose-project-names))))
+   (let ((result 
+          (reduce '(lambda (x y) (or x y))
+        (mapcar 'nose-find-test-runner-names nose-project-names))))
      (if result
          result
        nose-global-name))))
 
 (defun nose-find-test-runner-names (runner)
   "find eggs/bin/test in a parent dir of current buffer's file"
-  (nose-find-test-runner-in-dir-named (file-name-directory buffer-file-name) runner))
+  (nose-find-test-runner-in-dir-named 
+   (file-name-directory buffer-file-name) runner))
 
 (defun nose-find-test-runner-in-dir-named (dn runner)
   (let ((fn (expand-file-name runner dn)))
           runner)))))
 
 (defun nose-py-testable ()
-  (let ((remember-point (point)))
+  (let* ((inner-obj (inner-testable))
+         (outer (outer-testable))
+         ;; elisp can't return multiple values
+         (outer-def (car outer))
+         (outer-obj (cdr outer)))
+    (cond ((equal outer-def "def") outer-obj)
+          ((equal inner-obj outer-obj) outer-obj)
+          (t (format "%s.%s" outer-obj inner-obj)))))
+           
+(defun inner-testable ()
+  (save-excursion
     (re-search-backward
      "^ \\{0,4\\}\\(class\\|def\\)[ \t]+\\([a-zA-Z0-9_]+\\)" nil t)
-    (setq t1 (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
-    (goto-char remember-point)
+    (buffer-substring-no-properties (match-beginning 2) (match-end 2))))
+
+(defun outer-testable ()
+  (save-excursion
     (re-search-backward
      "^\\(class\\|def\\)[ \t]+\\([a-zA-Z0-9_]+\\)" nil t)
-    (setq outer
-          (buffer-substring-no-properties (match-beginning 1) (match-end 1)))
-    (setq t2 (buffer-substring-no-properties (match-beginning 2) (match-end 2)))
-    (let
-        ((result (cond ((string= outer "def") t2)
-                       ((string= t1 t2) t2)
-                       (t (format "%s.%s" t2 t1)))))
-      (goto-char remember-point)
-      result)))
+    (let ((result 
+            (buffer-substring-no-properties (match-beginning 2) (match-end 2))))
 
+      (cons 
+       (buffer-substring-no-properties (match-beginning 1) (match-end 1))
+       result))))
+
+(defun nose-find-project-root (&optional dirname)  
+  (let ((dn
+         (if dirname
+             dirname 
+           (file-name-directory buffer-file-name))))
+    (cond ((funcall nose-project-root-test dn) (expand-file-name dn))
+          ((equal (expand-file-name dn) "/") nil)
+        (t1 (nose-find-project-root
+             (file-name-directory (directory-file-name dn)))))))
+
+(defun nose-project-root (dirname)
+  (reduce '(lambda (x y) (or x y))
+          (mapcar (lambda (d) (member d (directory-files dirname)))
+                  nose-project-root-files)))
+       
 (provide 'nose)