0
;; URL: http://rinari.rubyforge.org
0
-;; Keywords: ruby, rails
0
+;; Keywords: ruby, rails
, project, convenience, web0
;; This file is NOT part of GNU Emacs.
0
;; See TODO file in this directory.
0
+(let ((this-dir (file-name-directory (or load-file-name buffer-file-name))))
0
+ (add-to-list 'load-path this-dir)
0
+ (add-to-list 'load-path (expand-file-name "util" this-dir))
0
+ (add-to-list 'load-path (expand-file-name "util/jump" this-dir)))
0
(require 'ruby-compilation)
0
-(require 'find-file-in-project)
0
-(require 'rinari-movement)
0
(defcustom rinari-browse-url-func
0
(defvar rinari-minor-mode-hook nil
0
"*Hook for customising Rinari.")
0
-(defadvice find-file-in-project (around find-file-in-rinari-project activate)
0
- "Wrap `find-file-in-project' to use `rinari-root' as the base of
0
- (let ((ffip-project-root (rinari-root)))
0
(defadvice ruby-run-w/compilation (around rinari-run-w/compilation activate)
0
"Set default directory to the root of the rails application
0
before running ruby processes."
0
@@ -128,14 +124,14 @@ directory of the rails application."
0
(defun rinari-test (&optional edit-cmd-args)
0
"Test the current ruby function. If current function is not a
0
-test, then try to jump to the related test using `toggle-buffer'.
0
-Dump output to a compilation buffer allowing jumping between
0
-errors and source code. With optional prefix argument allows
0
-editing of the test command arguments."
0
+test, then try to jump to the related test using
0
+`rinari-find-test'. Dump output to a compilation buffer allowing
0
+jumping between errors and source code. With optional prefix
0
+argument allows editing of the test command arguments."
0
(or (string-match "test" (or (ruby-add-log-current-method)
0
(file-name-nondirectory (buffer-file-name))))
0
(let* ((funname (ruby-add-log-current-method))
0
(string-match "#\\(.*\\)" funname)
0
@@ -240,6 +236,192 @@ With optional prefix argument just run `rgrep'."
0
"*.rb *.rhtml *.yml *.erb" (rinari-root))))
0
;;--------------------------------------------------------------------
0
+;; rinari movement using jump.el
0
+(defun rinari-generate (type name)
0
+ (message (shell-command-to-string
0
+ (format "ruby %sscript/generate %s %s" (rinari-root) type
0
+ (read-from-minibuffer (format "create %s: " type) name)))))
0
+(defvar rinari-ruby-hash-regexp
0
+ "\\(:[^[:space:]]*?\\)[[:space:]]*\\(=>[[:space:]]*[\"\':]?\\([^[:space:]]*?\\)[\"\']?[[:space:]]*\\)?[,){}\n]"
0
+ "Regexp to match subsequent key => value pairs of a ruby hash.")
0
+(defun rinari-ruby-values-from-render (controller action)
0
+ "Adjusts CONTROLLER and ACTION acording to keyword arguments in
0
+the hash at `point', then return (CONTROLLER . ACTION)"
0
+ (let ((end (save-excursion
0
+ (re-search-forward "[^,{(]$" nil t)
0
+ (while (and (< (point) end)
0
+ (re-search-forward rinari-ruby-hash-regexp end t))
0
+ (if (> (length (match-string 3)) 1)
0
+ (case (intern (match-string 1))
0
+ (:partial (setf action (concat "_" (match-string 3))))
0
+ (:action (setf action (match-string 3)))
0
+ (:controller (setf controller (match-string 3)))))))
0
+ (cons controller action)))
0
+(defun rinari-which-render (renders)
0
+ (let ((path (jump-completing-read
0
+ (concat (car lis) "/" (cdr lis)))
0
+ (string-match "\\(.*\\)/\\(.*\\)" path)
0
+ (cons (match-string 1 path) (match-string 2 path))))
0
+(defun rinari-follow-controller-and-action (controller action)
0
+ "Follow the current controller-and-action through all of the
0
+renders and redirects to find the final controller or view."
0
+ (save-excursion ;; if we can find the controller#action pair
0
+ (if (and (jump-to-path (format "app/controllers/%s_controller.rb#%s" controller action))
0
+ (equalp (jump-method) action))
0
+ (let ((start (point)) ;; demarcate the borders
0
+ (renders (list (cons controller action))) render view)
0
+ ;; collect redirection options and pursue
0
+ (while (re-search-backward "re\\(?:direct_to\\|nder\\)" start t)
0
+ (add-to-list 'renders (rinari-ruby-values-from-render controller action)))
0
+ (let ((render (if (equalp 1 (length renders))
0
+ (rinari-which-render renders))))
0
+ (if (and (equalp (cdr render) action)
0
+ (equalp (car render) controller))
0
+ (list controller action) ;; directed to here so return
0
+ (rinari-follow-controller-and-action (or (car render)
0
+ ;; no controller entry so return
0
+ (list controller action))))
0
+ (("app/controllers/\\1_controller.rb#\\2" . "app/models/\\1.rb#\\2")
0
+ ("app/views/\\1/.*" . "app/models/\\1.rb")
0
+ ("app/helpers/\\1_helper.rb" . "app/models/\\1.rb")
0
+ ("db/migrate/.*create_\\1.rb" . "app/models/\\1.rb")
0
+ ("test/functional/\\1_controller_test.rb" . "app/models/\\1.rb")
0
+ ("test/unit/\\1_test.rb#test_\\2" . "app/models/\\1.rb#\\2")
0
+ ("test/unit/\\1_test.rb" . "app/models/\\1.rb")
0
+ ("test/fixtures/\\1.yml" . "app/models/\\1.rb")
0
+ (rinari-generate "model"
0
+ (and (string-match ".*/\\(.+?\\)\.rb" path)
0
+ (match-string 1 path)))))
0
+ (("app/models/\\1.rb" . "app/controllers/\\1_controller.rb")
0
+ ("app/views/\\1/\\2\\..*" . "app/controllers/\\1_controller.rb#\\2")
0
+ ("app/helpers/\\1_helper.rb" . "app/controllers/\\1_controller.rb")
0
+ ("db/migrate/.*create_\\1.rb" . "app/controllers/\\1_controller.rb")
0
+ ("test/functional/\\1_controller_test.rb" . "app/controllers/\\1_controller.rb")
0
+ ("test/unit/\\1_test.rb#test_\\2" . "app/controllers/\\1_controller.rb#\\2")
0
+ ("test/unit/\\1_test.rb" . "app/controllers/\\1_controller.rb")
0
+ ("test/fixtures/\\1.yml" . "app/controllers/\\1_controller.rb")
0
+ (t . "app/controllers/"))
0
+ (rinari-generate "model"
0
+ (and (string-match ".*/\\(.+?\\)_controller\.rb" path)
0
+ (match-string 1 path)))))
0
+ (("app/models/\\1.rb" . "app/views/\\1/.*")
0
+ ((lambda () ;; find the controller/view
0
+ (rinari-follow-controller-and-action
0
+ (let ((file (file-name-nondirectory (buffer-file-name))))
0
+ (and (string-match "^\\(.*\\)_controller.rb" file)
0
+ (match-string 1 file)));; controller
0
+ (let ((method (ruby-add-log-current-method))) ;; action
0
+ (and (string-match "#\\(.*\\)" method) (match-string 1 method)))))
0
+ . "app/views/\\1/\\2\\..*")
0
+ ("app/helpers/\\1_helper.rb" . "app/views/\\1/.*")
0
+ ("db/migrate/.*create_\\1.rb" . "app/views/\\1/.*")
0
+ ("test/functional/\\1_controller_test.rb" . "app/views/\\1/.*")
0
+ ("test/unit/\\1_test.rb#test_\\2" . "app/views/\\1/_?\\2.*")
0
+ ("test/fixtures/\\1.yml" . "app/views/\\1/.*")
0
+ (("app/models/\\1.rb#\\2" . "test/unit/\\1_test.rb#test_\\2")
0
+ ("app/controllers/\\1.rb#\\2" . "test/functional/\\1_test.rb#test_\\2")
0
+ ("app/views/\\1/_?\\2\\..*" . "test/functional/\\1_controller_test.rb#test_\\2")
0
+ ("app/helpers/\\1_helper.rb" . "test/functional/\\1_controller_test.rb")
0
+ ("db/migrate/.*create_\\1.rb" . "test/unit/\\1_test.rb")
0
+ ("test/functional/\\1_controller_test.rb" . "test/unit/\\1_test.rb")
0
+ ("test/unit/\\1_test.rb" . "test/functional/\\1_controller_test.rb")
0
+ (("app/models/\\1.rb" . "test/fixtures/\\1.yml")
0
+ ("app/controllers/\\1_controller.rb" . "test/fixtures/\\1.yml")
0
+ ("app/views/\\1/.*" . "test/fixtures/\\1.yml")
0
+ ("app/helpers/\\1_helper.rb" . "test/fixtures/\\1.yml")
0
+ ("db/migrate/.*create_\\1.rb" . "test/fixtures/\\1.yml")
0
+ ("test/functional/\\1_controller_test.rb" . "test/fixtures/\\1.yml")
0
+ ("test/unit/\\1_test.rb" . "test/fixtures/\\1.yml")
0
+ (t . "test/fixtures/"))
0
+ (("app/models/\\1.rb" . "app/helpers/\\1_helper.rb")
0
+ ("app/controllers/\\1_controller.rb" . "app/helpers/\\1_helper.rb")
0
+ ("app/views/\\1/.*" . "app/helpers/\\1_helper.rb")
0
+ ("app/helpers/\\1_helper.rb" . "app/helpers/\\1_helper.rb")
0
+ ("db/migrate/.*create_\\1.rb" . "app/helpers/\\1_helper.rb")
0
+ ("test/functional/\\1_controller_test.rb" . "app/helpers/\\1_helper.rb")
0
+ ("test/unit/\\1_test.rb#test_\\2" . "app/helpers/\\1_helper.rb#\\2")
0
+ ("test/unit/\\1_test.rb" . "app/helpers/\\1_helper.rb")
0
+ (("app/controllers/\\1_controller.rb" . "db/migrate/.*create_\\1.rb")
0
+ ("app/views/\\1/.*" . "db/migrate/.*create_\\1.rb")
0
+ ("app/helpers/\\1_helper.rb" . "db/migrate/.*create_\\1.rb")
0
+ ("app/models/\\1.rb" . "db/migrate/.*create_\\1.rb")
0
+ ("test/functional/\\1_controller_test.rb" . "db/migrate/.*create_\\1.rb")
0
+ ("test/unit/\\1_test.rb#test_\\2" . "db/migrate/.*create_\\1.rb#\\2")
0
+ ("test/unit/\\1_test.rb" . "db/migrate/.*create_\\1.rb")
0
+ (rinari-generate "migration"
0
+ (and (string-match ".*create_\\(.+?\\)\.rb" path)
0
+ (match-string 1 path)))))
0
+ (environment "e" ((t . "config/environments/")) nil)
0
+ (configuration "n" ((t . "config/")) nil)
0
+ (script "s" ((t . "script/")) nil)
0
+ (lib "l" ((t . "lib/")) nil)
0
+ (log "o" ((t . "log/")) nil)
0
+ (worker "w" ((t . "lib/workers/")) nil)
0
+ (public "p" ((t . "public/")) nil)
0
+ (stylesheet "y" ((t . "public/stylesheets/.*")) nil)
0
+ (javascript "j" ((t . "public/javascripts/.*")) nil)
0
+ (plugin "l" ((t . "vendor/plugins/")) nil)
0
+ (file-in-project "f" ((t . ".*")) nil)))
0
+ (let ((name (first type))
0
+ (quote ,(read (format "rinari-find-%S" name)))
0
+ ,(format "Go to the most logical %S given the current location" name)
0
+ ,(if make `(quote ,make))
0
+ 'ruby-add-log-current-method))))
0
+;;--------------------------------------------------------------------
0
;; minor mode and keymaps
0
(defvar rinari-minor-mode-map
0
@@ -247,24 +429,26 @@ With optional prefix argument just run `rgrep'."
0
"Key map for Rinari minor mode.")
0
+(defun rinari-bind-key-to-func (key func)
0
+ (eval `(define-key rinari-minor-mode-map
0
+ ,(format "\C-c;%s" key) ,func))
0
+ (eval `(define-key rinari-minor-mode-map
0
+ ,(format "\C-c'%s" key) ,func)))
0
(defvar rinari-minor-mode-keybindings
0
- '(("o" . 'toggle-buffer) ("s" . 'rinari-script)
0
- ("e" . 'rinari-insert-erb-skeleton) ("t" . 'rinari-test)
0
- ("r" . 'rinari-rake) ("c" . 'rinari-console)
0
- ("w" . 'rinari-web-server) ("g" . 'rinari-rgrep)
0
- ("b" . 'rinari-browse-url) ("q" . 'rinari-sql)
0
- ("fc" . 'rinari-find-controller) ("ft" . 'rinari-find-test)
0
- ("fv" . 'rinari-find-view) ("fm" . 'rinari-find-model)
0
- ("fi" . 'rinari-find-migration) ("fe" . 'rinari-find-environment)
0
- ("fj" . 'rinari-find-javascript) ("fs" . 'rinari-find-stylesheet))
0
+ '(("s" . 'rinari-script)
0
+ ("e" . 'rinari-insert-erb-skeleton) ("t" . 'rinari-test)
0
+ ("r" . 'rinari-rake) ("c" . 'rinari-console)
0
+ ("w" . 'rinari-web-server) ("g" . 'rinari-rgrep)
0
+ ("b" . 'rinari-browse-url) ("q" . 'rinari-sql))
0
"alist mapping of keys to functions in `rinari-minor-mode'")
0
- (eval `(define-key rinari-minor-mode-map
0
- ,(format "\C-c;%s" (car el)) ,(cdr el)))
0
- (eval `(define-key rinari-minor-mode-map
0
- ,(format "\C-c'%s" (car el)) ,(cdr el))))
0
- rinari-minor-mode-keybindings)
0
+(mapcar (lambda (el) (rinari-bind-key-to-func (car el) (cdr el)))
0
+ (append (mapcar (lambda (el)
0
+ (cons (concat "f" (second el))
0
+ (read (format "'rinari-find-%S" (first el)))))
0
+ rinari-minor-mode-keybindings))
0
(defun rinari-launch ()
0
"Run `rinari-minor-mode' if inside of a rails projecct,
0
@@ -272,30 +456,13 @@ otherwise turn `rinari-minor-mode' off if it is on."
0
(let* ((root (rinari-root)) (r-tags-path (concat root rinari-tags-file-name)))
0
- ;; customize toggle.el for rinari
0
- 'toggle-mapping-styles
0
- '(rinari . (("app/controllers/\\1.rb#\\2" . "test/functional/\\1_test.rb#test_\\2")
0
- ("app/controllers/\\1.rb" . "test/functional/\\1_test.rb")
0
- ("app/models/\\1.rb#\\2" . "test/unit/\\1_test.rb#test_\\2")
0
- ("app/models/\\1.rb" . "test/unit/\\1_test.rb")
0
- ("lib/\\1.rb#\\2" . "test/unit/test_\\1.rb#test_\\2")
0
- ("lib/\\1.rb" . "test/unit/test_\\1.rb"))))
0
- (set (make-local-variable 'toggle-mapping-style) 'rinari)
0
- (set (make-local-variable 'toggle-which-function-command)
0
- 'ruby-add-log-current-method)
0
- (set (make-local-variable 'toggle-mappings)
0
- (toggle-style toggle-mapping-style))
0
- (set (make-local-variable 'toggle-method-format) "def %s")
0
(set (make-local-variable 'tags-file-name)
0
(and (file-exists-p r-tags-path) r-tags-path))
0
(run-hooks 'rinari-minor-mode-hook)
0
- ;; TODO: Why is there mode-toggling logic here? define-minor-mode handles that for us.
0
- (unless rinari-minor-mode (rinari-minor-mode t)))))
0
+ (rinari-minor-mode t))))
0
(defvar rinari-major-modes
0
- '('ruby-mode-hook 'yaml-mode-hook 'mumamo-after-change-major-mode-hook 'css-mode-hook
0
- 'javascript-mode-hook 'dired-mode-hook)
0
+ '('find-file-hook 'mumamo-after-change-major-mode-hook 'dired-mode-hook)
0
"Major Modes from which to launch Rinari.")
Comments
No one has commented yet.