rails-controller-layout.el
1 ;;; rails-controller-layout.el --- 2 3 ;; Copyright (C) 2006 Dmitry Galinsky <dima dot exe at gmail dot com> 4 5 ;; Authors: Dmitry Galinsky <dima dot exe at gmail dot com> 6 7 ;; Keywords: ruby rails languages oop 8 ;; $URL: svn://rubyforge.org/var/svn/emacs-rails/trunk/rails-controller-layout.el $ 9 ;; $Id: rails-controller-layout.el 173 2007-04-09 15:15:02Z dimaexe $ 10 11 ;;; License 12 13 ;; This program is free software; you can redistribute it and/or 14 ;; modify it under the terms of the GNU General Public License 15 ;; as published by the Free Software Foundation; either version 2 16 ;; of the License, or (at your option) any later version. 17 18 ;; This program is distributed in the hope that it will be useful, 19 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 20 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 ;; GNU General Public License for more details. 22 23 ;; You should have received a copy of the GNU General Public License 24 ;; along with this program; if not, write to the Free Software 25 ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 26 27 ;;; Code: 28 29 (defvar rails-controller-layout:recent-template-type nil) 30 31 (defun rails-controller-layout:switch-to-action-in-controller (controller-name action-name) 32 "Open CONTROLLER-NAME and go to ACTION-NAME." 33 (if (or (rails-core:find-file-if-exist (rails-core:controller-file controller-name)) 34 (rails-core:find-file-if-exist (rails-core:mailer-file controller-name))) 35 (progn 36 (goto-char (point-min)) 37 (when action-name 38 (if (search-forward-regexp (concat "^[ ]*def[ ]*" action-name) nil t) 39 (recenter)) 40 (message (format "%s: %s" (substring (symbol-name (rails-core:buffer-type)) 1) controller-name)))))) 41 42 (defun rails-controller-layout:switch-to-view (controller-name action-name) 43 "Open the ACTION-NAME file for CONTROLLER-NAME in the views directory." 44 (when action-name 45 (let ((views (rails-controller-layout:view-files controller-name action-name)) 46 (title (substring (symbol-name (rails-core:buffer-type)) 1))) 47 (cond 48 ((= (length views) 1) 49 (find-file (first views)) 50 (message "%s: %s#%s" title controller-name action-name)) 51 ((= (length views) 0) 52 (rails-controller-layout:create-view-for-action controller-name action-name)))))) 53 54 (defun rails-controller-layout:toggle-action-view () 55 (interactive) 56 (let ((controller-name (rails-core:current-controller)) 57 (action-name (rails-core:current-action))) 58 (case (rails-core:buffer-type) 59 (:view 60 (rails-controller-layout:switch-to-action-in-controller controller-name action-name)) 61 (:mailer 62 (rails-controller-layout:switch-to-view controller-name action-name)) 63 (:controller 64 (if action-name 65 (rails-controller-layout:switch-to-view controller-name action-name) 66 (rails-controller-layout:switch-to :functional-test)))))) 67 68 (defun rails-controller-layout:create-view-for-action (controller-name action-name) 69 (let ((type 70 (if rails-controller-layout:recent-template-type 71 rails-controller-layout:recent-template-type 72 (car rails-templates-list)))) 73 (setq type 74 (completing-read (format "View for %s#%s not found, create %s.[%s]? " 75 controller-name action-name action-name type) 76 rails-templates-list 77 nil t type)) 78 (setq rails-controller-layout:recent-template-type type) 79 (let ((file (rails-core:file (concat "app/views/" 80 (replace-regexp-in-string "_controller" "" 81 (rails-core:file-by-class controller-name t)))))) 82 (make-directory file t) 83 (find-file (format "%s/%s.%s" file action-name type))))) 84 85 (defun rails-controller-layout:view-files (controller-name &optional action) 86 "Retun a list containing the view file for CONTROLLER-NAME#ACTION. 87 If the action is nil, return all views for the controller." 88 (rails-project:with-root 89 (root) 90 (directory-files 91 (rails-core:file 92 (rails-core:views-dir 93 (rails-core:short-controller-name controller-name))) t 94 (if action 95 (concat "^" action (rails-core:regex-for-match-view)) 96 (rails-core:regex-for-match-view))))) 97 98 (defun rails-controller-layout:views-menu (controller-name) 99 "Make a menu of views for CONTROLLER-NAME." 100 (let (menu) 101 (setq menu 102 (mapcar (lambda(i) 103 (list (concat (if (string-match "^_" (file-name-nondirectory i)) "Partial" "View") 104 ": " 105 (file-name-nondirectory i)) 106 i)) 107 (rails-controller-layout:view-files controller-name nil))) 108 (when (zerop (length menu)) 109 (setq menu (list))) 110 menu)) 111 112 (defun rails-controller-layout:keymap (type) 113 (let* ((name (capitalize (substring (symbol-name type) 1))) 114 (map (make-sparse-keymap)) 115 (menu (make-sparse-keymap))) 116 (when type 117 (define-keys menu 118 ([goto-migration] '(menu-item "Go to Migration" 119 rails-controller-layout:switch-to-migration 120 :enable (and (not (rails-core:current-mailer)) 121 (rails-core:migration-file-by-model 122 (singularize-string (rails-core:current-controller)))))) 123 ([goto-model] '(menu-item "Go to Model" 124 rails-controller-layout:switch-to-model 125 :enable (and (not (rails-core:current-mailer)) 126 (rails-core:model-exist-p 127 (singularize-string (rails-core:current-controller)))))) 128 ([goto-helper] '(menu-item "Go to Helper" 129 rails-controller-layout:switch-to-helper 130 :enable (and (not (rails-core:current-mailer)) 131 (not (eq (rails-core:buffer-type) :helper))))) 132 ([goto-ftest] '(menu-item "Go to Functional Test" 133 rails-controller-layout:switch-to-functional-test 134 :enable (and (not (rails-core:current-mailer)) 135 (not (eq (rails-core:buffer-type) :functional-test))))) 136 ([goto-controller] '(menu-item "Go to Controller" 137 rails-controller-layout:switch-to-controller 138 :enable (and (not (rails-core:current-mailer)) 139 (not (eq (rails-core:buffer-type) :controller))))) 140 ([goto-utest] '(menu-item "Go to Unit Test" 141 rails-controller-layout:switch-to-unit-test 142 :enable (rails-core:current-mailer)))) 143 (define-keys map 144 ((rails-key "g") 'rails-controller-layout:switch-to-migration) 145 ((rails-key "m") 'rails-controller-layout:switch-to-model) 146 ((rails-key "h") 'rails-controller-layout:switch-to-helper) 147 ((rails-key "f") 'rails-controller-layout:switch-to-functional-test) 148 ((rails-key "c") 'rails-controller-layout:switch-to-controller) 149 ((rails-key "u") 'rails-controller-layout:switch-to-unit-test) 150 ([menu-bar rails-controller-layout] (cons name menu)))) 151 map)) 152 153 (defun rails-controller-layout:switch-to (type) 154 (let* ((name (capitalize (substring (symbol-name type) 1))) 155 (controller (rails-core:current-controller)) 156 (model (singularize-string controller)) 157 (mailer (rails-core:current-mailer)) 158 (item (case type 159 (:helper (rails-core:helper-file controller)) 160 (:functional-test (rails-core:functional-test-file controller)) 161 (:controller (rails-core:controller-file controller)) 162 (:model (rails-core:model-file model)) 163 (:unit-test (rails-core:unit-test-file mailer)) 164 (:migration (rails-core:migration-file-by-model model))))) 165 (if item 166 (let ((file (rails-core:file item))) 167 (if (file-exists-p file) 168 (progn 169 (find-file file) 170 (message (format "%s: %s" (substring (symbol-name type) 1) item))) 171 (message "File %s does not exist" file))) 172 (message "%s not found" name)))) 173 174 (defun rails-controller-layout:switch-to-helper () (interactive) (rails-controller-layout:switch-to :helper)) 175 (defun rails-controller-layout:switch-to-functional-test () (interactive) (rails-controller-layout:switch-to :functional-test)) 176 (defun rails-controller-layout:switch-to-controller () (interactive) (rails-controller-layout:switch-to :controller)) 177 (defun rails-controller-layout:switch-to-model () (interactive) (rails-controller-layout:switch-to :model)) 178 (defun rails-controller-layout:switch-to-migration () (interactive) (rails-controller-layout:switch-to :migration)) 179 (defun rails-controller-layout:switch-to-unit-test () (interactive) (rails-controller-layout:switch-to :unit-test)) 180 181 (defun rails-controller-layout:menu () 182 (interactive) 183 (let* ((type (rails-core:buffer-type)) 184 (title (capitalize (substring (symbol-name type) 1))) 185 (controller (rails-core:current-controller)) 186 (action (rails-core:current-action)) 187 (model (singularize-string controller)) 188 (mailer (rails-core:current-mailer)) 189 (item (rails-controller-layout:views-menu (or controller mailer)))) 190 (add-to-list 'item (rails-core:menu-separator)) 191 (when controller 192 (when (rails-core:model-exist-p model) 193 (when (rails-core:migration-file-by-model model) 194 (add-to-list 'item (cons "Migration" :migration))) 195 (add-to-list 'item (cons "Model" :model))) 196 (unless (eq type :helper) 197 (add-to-list 'item (cons "Helper" :helper))) 198 (unless (eq type :functional-test) 199 (add-to-list 'item (cons "Functional Test" :functional-test))) 200 (unless (eq type :controller) 201 (add-to-list 'item (cons "Controller" :controller)))) 202 (when mailer 203 (add-to-list 'item (cons "Unit Test" (rails-core:unit-test-file mailer))) 204 (when (eq type :view) 205 (add-to-list 'item (cons "Mailer" (rails-core:mailer-file mailer))))) 206 (setq item 207 (rails-core:menu 208 (list (concat title " " controller 209 (when action (format " (%s)" action))) 210 (cons "Please select..." 211 item)))) 212 (typecase item 213 (symbol (rails-controller-layout:switch-to item)) 214 (string (rails-core:find-file-if-exist item))))) 215 216 (provide 'rails-controller-layout)