rails-core.el
1 ;;; rails-core.el --- core helper functions and macros for emacs-rails 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 ;; Rezikov Peter <crazypit13 (at) gmail.com> 7 8 ;; Keywords: ruby rails languages oop 9 ;; $URL: svn://rubyforge.org/var/svn/emacs-rails/trunk/rails-core.el $ 10 ;; $Id: rails-core.el 186 2007-04-20 15:34:51Z dimaexe $ 11 12 ;;; License 13 14 ;; This program is free software; you can redistribute it and/or 15 ;; modify it under the terms of the GNU General Public License 16 ;; as published by the Free Software Foundation; either version 2 17 ;; of the License, or (at your option) any later version. 18 19 ;; This program is distributed in the hope that it will be useful, 20 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of 21 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 ;; GNU General Public License for more details. 23 24 ;; You should have received a copy of the GNU General Public License 25 ;; along with this program; if not, write to the Free Software 26 ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 27 28 (eval-when-compile 29 (require 'rails-lib)) 30 31 (defvar rails-core:class-dirs 32 '("app/controllers" 33 "app/views" 34 "app/models" 35 "app/helpers" 36 "test/unit" 37 "test/functional" 38 "test/fixtures") 39 "Directories with Rails classes") 40 41 (defun rails-core:class-by-file (filename) 42 "Return the class associated with FILENAME. 43 <rails-root>/(app/models|app/controllers|app/helpers|test/unit|test/functional)/foo/bar_baz 44 --> Foo::BarBaz" 45 (let* ((case-fold-search nil) 46 (path (replace-regexp-in-string 47 (format 48 "\\(.*\\(%s\\)/\\)?\\([^\.]+\\)\\(.*\\)?" 49 (strings-join "\\|" rails-core:class-dirs)) "\\3" filename)) 50 (path (replace-regexp-in-string "/" " " path)) 51 (path (replace-regexp-in-string "_" " " path))) 52 (replace-regexp-in-string 53 " " "" 54 (replace-regexp-in-string 55 " " "::" 56 (if (string-match "^ *\\([0-9]+ *\\)?[A-Z]" path) 57 path 58 (capitalize path)))))) 59 60 (defun rails-core:file-by-class (classname &optional do-not-append-ext) 61 "Return the filename associated with CLASSNAME. 62 If the optional parameter DO-NOT-APPEND-EXT is set this function 63 will not append \".rb\" to result." 64 (let* ((case-fold-search nil) 65 (path (replace-regexp-in-string "::" "/" classname)) 66 (path (replace-regexp-in-string "\\([A-Z]+\\)\\([A-Z][a-z]\\)" "\\1_\\2" path)) 67 (path (replace-regexp-in-string "\\([a-z\\d]\\)\\([A-Z]\\)" "\\1_\\2" path))) 68 (concat (downcase path) 69 (unless do-not-append-ext ".rb")))) 70 71 ;;;;;;;;;; Files ;;;;;;;;;; 72 73 (defun rails-core:file (file-name) 74 "Return the full path for FILE-NAME in a Rails directory." 75 (when file-name 76 (if (file-name-absolute-p file-name) 77 file-name 78 (rails-project:with-root 79 (root) 80 (concat root file-name))))) 81 82 (defun rails-core:quoted-file (file-name) 83 "Return the quoted full path for FILE-NAME in a Rails directory." 84 (concat "\"" (rails-core:file file-name) "\"")) 85 86 (defun rails-core:find-file (file-name) 87 "Open the file named FILE_NAME in a Rails directory." 88 (when-bind (file (rails-core:file file-name)) 89 (find-file file))) 90 91 (defun rails-core:find-file-if-exist (file-name) 92 "Open the file named FILE-NAME in a Rails directory only if the file exists." 93 (let ((file-name (rails-core:file file-name))) 94 (when (file-exists-p file-name) 95 (find-file file-name)))) 96 97 (defun rails-core:find-or-ask-to-create (question file) 98 "Open the file named FILE in a Rails directory if it exists. If 99 it does not exist, ask to create it using QUESTION as a prompt." 100 (find-or-ask-to-create question (rails-core:file file))) 101 102 ;; Funtions, that retrun Rails objects full pathes 103 104 (defun rails-core:model-file (model-name) 105 "Return the model file from the model name." 106 (when model-name 107 (concat "app/models/" (rails-core:file-by-class model-name)))) 108 109 (defun rails-core:model-exist-p (model-name) 110 "Return t if controller CONTROLLER-NAME exists." 111 (when model-name 112 (and (file-exists-p 113 (rails-core:file 114 (rails-core:model-file model-name))) 115 (not (rails-core:observer-p model-name)) 116 (not (rails-core:mailer-p model-name))))) 117 118 (defun rails-core:controller-file (controller-name) 119 "Return the path to the controller CONTROLLER-NAME." 120 (when controller-name 121 (concat "app/controllers/" 122 (rails-core:file-by-class 123 (rails-core:short-controller-name controller-name) t) 124 (unless (string-equal controller-name "Application") "_controller") 125 ".rb"))) 126 127 (defun rails-core:controller-exist-p (controller-name) 128 "Return t if controller CONTROLLER-NAME exist." 129 (when controller-name 130 (file-exists-p 131 (rails-core:file 132 (rails-core:controller-file controller-name))))) 133 134 (defun rails-core:controller-file-by-model (model) 135 (when model 136 (let ((controller (pluralize-string model))) 137 (when (rails-core:controller-exist-p controller) 138 (rails-core:controller-file controller))))) 139 140 (defun rails-core:observer-file (observer-name) 141 "Return the path to the observer OBSERVER-NAME." 142 (when observer-name 143 (rails-core:model-file (concat observer-name "Observer")))) 144 145 (defun rails-core:mailer-file (mailer) 146 (when (and mailer 147 (rails-core:mailer-p mailer)) 148 (rails-core:model-file mailer))) 149 150 (defun rails-core:mailer-exist-p (mailer) 151 (when mailer 152 (file-exists-p (rails-core:file (rails-core:mailer-file mailer))))) 153 154 (defun rails-core:migration-file (migration-name) 155 "Return the model file from the MIGRATION-NAME." 156 (when migration-name 157 (let ((dir "db/migrate/") 158 (name (replace-regexp-in-string 159 " " "_" 160 (rails-core:file-by-class migration-name)))) 161 (when (string-match "^[^0-9]+[^_]" name) ; try search when the name without migration number 162 (let ((files (directory-files (rails-core:file dir) 163 nil 164 (concat "[0-9]+_" name "$")))) 165 (setq name (if files 166 (car files) 167 nil)))) 168 (when name 169 (concat dir name))))) 170 171 (defun rails-core:migration-file-by-model (model) 172 (when model 173 (rails-core:migration-file 174 (concat "Create" (rails-core:class-by-file (pluralize-string model)))))) 175 176 (defun rails-core:model-by-migration-filename (migration-filename) 177 (when migration-filename 178 (let ((model-name (singularize-string 179 (string=~ "[0-9]+_create_\\(\\w+\\)\.rb" (buffer-name) $1)))) 180 (when (and model-name 181 (rails-core:model-exist-p model-name)) 182 model-name)))) 183 184 (defun rails-core:plugin-file (plugin file) 185 "Return the path to the FILE in Rails PLUGIN." 186 (concat "vendor/plugins/" plugin "/" file)) 187 188 (defun rails-core:layout-file (layout) 189 "Return the path to the layout file named LAYOUT." 190 (let ((its rails-templates-list) 191 filename) 192 (while (and (car its) 193 (not filename)) 194 (when (file-exists-p (format "%sapp/views/layouts/%s.%s" (rails-project:root) layout (car its))) 195 (setq filename (format "app/views/layouts/%s.%s" layout (car its)))) 196 (setq its (cdr its))) 197 filename)) 198 199 (defun rails-core:js-file (js) 200 "Return the path to the JavaScript file named JS." 201 (concat "public/javascripts/" js ".js")) 202 203 (defun rails-core:partial-name (name) 204 "Return the file name of partial NAME." 205 (if (string-match "/" name) 206 (concat "app/views/" 207 (replace-regexp-in-string "\\([^/]*\\)$" "_\\1.rhtml" name)) 208 (concat (rails-core:views-dir (rails-core:current-controller)) 209 "_" name ".rhtml"))) 210 211 (defun rails-core:view-name (name) 212 "Return the file name of view NAME." 213 (concat (rails-core:views-dir (rails-core:current-controller)) 214 name ".rhtml")) ;; BUG: will fix it 215 216 (defun rails-core:helper-file (controller) 217 "Return the helper file name for the controller named 218 CONTROLLER." 219 (if (string= "Test/TestHelper" controller) 220 (rails-core:file (rails-core:file-by-class "Test/TestHelper")) 221 (when controller 222 (format "app/helpers/%s_helper.rb" 223 (replace-regexp-in-string "_controller" "" 224 (rails-core:file-by-class controller t)))))) 225 226 (defun rails-core:functional-test-file (controller) 227 "Return the functional test file name for the controller named 228 CONTROLLER." 229 (when controller 230 (format "test/functional/%s_test.rb" 231 (rails-core:file-by-class (rails-core:long-controller-name controller) t)))) 232 233 (defun rails-core:unit-test-file (model) 234 "Return the unit test file name for the model named MODEL." 235 (when model 236 (format "test/unit/%s_test.rb" (rails-core:file-by-class model t)))) 237 238 (defun rails-core:unit-test-exist-p (model) 239 "Return the unit test file name for the model named MODEL." 240 (let ((test (rails-core:unit-test-file model))) 241 (when test 242 (file-exists-p (rails-core:file test))))) 243 244 (defun rails-core:fixture-file (model) 245 "Return the fixtures file name for the model named MODEL." 246 (when model 247 (format "test/fixtures/%s.yml" (pluralize-string (rails-core:file-by-class model t))))) 248 249 (defun rails-core:fixture-exist-p (model) 250 (when model 251 (file-exists-p 252 (rails-core:file (rails-core:fixture-file model))))) 253 254 (defun rails-core:views-dir (controller) 255 "Return the view directory name for the controller named CONTROLLER." 256 (format "app/views/%s/" (replace-regexp-in-string "_controller" "" (rails-core:file-by-class controller t)))) 257 258 (defun rails-core:stylesheet-name (name) 259 "Return the file name of the stylesheet named NAME." 260 (concat "public/stylesheets/" name ".css")) 261 262 (defun rails-core:controller-name (controller-file) 263 "Return the class name of the controller named CONTROLLER. 264 Bar in Foo dir -> Foo::Bar" 265 (rails-core:class-by-file 266 (if (eq (elt controller-file 0) 47) ;;; 47 == '/' 267 (subseq controller-file 1) 268 (let ((current-controller (rails-core:current-controller))) 269 (if (string-match ":" current-controller) 270 (concat (replace-regexp-in-string "[^:]*$" "" current-controller) 271 controller-file) 272 controller-file))))) 273 274 (defun rails-core:short-controller-name (controller) 275 "Convert FooController -> Foo." 276 (remove-postfix controller "Controller" )) 277 278 (defun rails-core:long-controller-name (controller) 279 "Convert Foo/FooController -> FooController." 280 (if (string-match "Controller$" controller) 281 controller 282 (concat controller "Controller"))) 283 284 ;;;;;;;;;; Functions that return collection of Rails objects ;;;;;;;;;; 285 (defun rails-core:observer-p (name) 286 (when name 287 (if (string-match "\\(Observer\\|_observer\\(\\.rb\\)?\\)$" name) 288 t nil))) 289 290 (defun rails-core:mailer-p (name) 291 (when name 292 (if (string-match "\\(Mailer\\|Notifier\\|_mailer\\|_notifier\\(\\.rb\\)?\\)$" name) 293 t nil))) 294 295 (defun rails-core:controllers (&optional cut-contoller-suffix) 296 "Return a list of Rails controllers. Remove the '_controller' 297 suffix if CUT-CONTOLLER-SUFFIX is non nil." 298 (mapcar 299 #'(lambda (controller) 300 (rails-core:class-by-file 301 (if cut-contoller-suffix 302 (replace-regexp-in-string "_controller\\." "." controller) 303 controller))) 304 (delete-if-not 305 #'(lambda (controller) 306 (string-match "\\(application\\|[a-z0-9_]+_controller\\)\\.rb$" 307 controller)) 308 (find-recursive-files "\\.rb$" (rails-core:file "app/controllers/"))))) 309 310 (defun rails-core:functional-tests () 311 "Return a list of Rails functional tests." 312 (mapcar 313 #'(lambda(it) 314 (remove-postfix (rails-core:class-by-file it) 315 "ControllerTest")) 316 (find-recursive-files "\\.rb$" (rails-core:file "test/functional/")))) 317 318 (defun rails-core:models () 319 "Return a list of Rails models." 320 (mapcar 321 #'rails-core:class-by-file 322 (delete-if 323 #'(lambda (file) (or (rails-core:observer-p file) 324 (rails-core:mailer-p file))) 325 (find-recursive-files "\\.rb$" (rails-core:file "app/models/"))))) 326 327 (defun rails-core:unit-tests () 328 "Return a list of Rails functional tests." 329 (mapcar 330 #'(lambda(it) 331 (remove-postfix (rails-core:class-by-file it) 332 "Test")) 333 (find-recursive-files "\\.rb$" (rails-core:file "test/unit/")))) 334 335 (defun rails-core:observers () 336 "Return a list of Rails observers." 337 (mapcar 338 #'(lambda (observer) (replace-regexp-in-string "Observer$" "" observer)) 339 (mapcar 340 #'rails-core:class-by-file 341 (find-recursive-files "\\(_observer\\)\\.rb$" (rails-core:file "app/models/"))))) 342 343 (defun rails-core:mailers () 344 "Return a list of Rails mailers." 345 (mapcar 346 #'rails-core:class-by-file 347 (find-recursive-files "\\(_mailer\\|_notifier\\)\\.rb$" (rails-core:file "app/models/")))) 348 349 (defun rails-core:helpers () 350 "Return a list of Rails helpers." 351 (append 352 (mapcar 353 #'(lambda (helper) (replace-regexp-in-string "Helper$" "" helper)) 354 (mapcar 355 #'rails-core:class-by-file 356 (find-recursive-files "_helper\\.rb$" (rails-core:file "app/helpers/")))) 357 (list "Test/TestHelper"))) 358 359 (defun rails-core:migrations (&optional strip-numbers) 360 "Return a list of Rails migrations." 361 (let (migrations) 362 (setq 363 migrations 364 (reverse 365 (mapcar 366 #'(lambda (migration) 367 (replace-regexp-in-string "^\\([0-9]+\\)" "\\1 " migration)) 368 (mapcar 369 #'rails-core:class-by-file 370 (find-recursive-files "^[0-9]+_.*\\.rb$" (rails-core:file "db/migrate/")))))) 371 (if strip-numbers 372 (mapcar #'(lambda(i) (car (last (split-string i " ")))) 373 migrations) 374 migrations))) 375 376 (defun rails-core:migration-versions (&optional with-zero) 377 "Return a list of migtaion versions as the list of strings. If 378 second argument WITH-ZERO is present, append the \"000\" version 379 of migration." 380 (let ((ver (mapcar 381 #'(lambda(it) (car (split-string it " "))) 382 (rails-core:migrations)))) 383 (if with-zero 384 (append ver '("000")) 385 ver))) 386 387 (defun rails-core:plugins () 388 "Return a list of Rails plugins." 389 (mapcar 390 #'file-name-nondirectory 391 (delete-if-not 392 #'file-directory-p 393 (directory-files (rails-core:file "vendor/plugins") t "^[^\\.]")))) 394 395 (defun rails-core:plugin-files (plugin) 396 "Return a list of files in specific Rails plugin." 397 (find-recursive-files "^[^.]" (rails-core:file (concat "vendor/plugins/" plugin)))) 398 399 (defun rails-core:layouts () 400 "Return a list of Rails layouts." 401 (mapcar 402 #'(lambda (l) 403 (replace-regexp-in-string "\\.[^.]+$" "" l)) 404 (find-recursive-files (rails-core:regex-for-match-view) (rails-core:file "app/views/layouts")))) 405 406 (defun rails-core:fixtures () 407 "Return a list of Rails fixtures." 408 (mapcar 409 #'(lambda (l) 410 (replace-regexp-in-string "\\.[^.]+$" "" l)) 411 (find-recursive-files "\\.yml$" (rails-core:file "test/fixtures/")))) 412 413 (defun rails-core:regex-for-match-view () 414 "Return a regex to match Rails view templates. 415 The file extensions used for views are defined in `rails-templates-list'." 416 (format "\\.\\(%s\\)$" (strings-join "\\|" rails-templates-list))) 417 418 (defun rails-core:get-view-files (controller-class &optional action) 419 "Retun a list containing the view file for CONTROLLER-CLASS#ACTION. 420 If the action is nil, return all views for the controller." 421 (rails-project:with-root 422 (root) 423 (directory-files 424 (rails-core:file 425 (rails-core:views-dir 426 (rails-core:short-controller-name controller-class))) t 427 (if action 428 (concat "^" action (rails-core:regex-for-match-view)) 429 (rails-core:regex-for-match-view))))) 430 431 (defun rails-core:extract-ancestors (classes) 432 "Return the parent classes from a list of classes named CLASSES." 433 (delete "" 434 (uniq-list 435 (mapcar (lambda (class) 436 (replace-regexp-in-string 437 "::[^:]*$" "::" 438 (replace-regexp-in-string "^[^:]*$" "" class))) 439 classes)))) 440 441 (defun rails-core:models-ancestors () 442 "Return the parent classes of models." 443 (rails-core:extract-ancestors (rails-core:models))) 444 445 (defun rails-core:controllers-ancestors () 446 "Return the parent classes of controllers." 447 (rails-core:extract-ancestors (rails-core:controllers))) 448 449 ;;;;;;;;;; Getting Controllers/Model/Action from current buffer ;;;;;;;;;; 450 451 (defun rails-core:current-controller () 452 "Return the current Rails controller." 453 (let* ((file-class (rails-core:class-by-file (buffer-file-name)))) 454 (unless (rails-core:mailer-p file-class) 455 (case (rails-core:buffer-type) 456 (:controller (rails-core:short-controller-name file-class)) 457 (:view (rails-core:class-by-file 458 (directory-file-name (directory-of-file (buffer-file-name))))) 459 (:helper (remove-postfix file-class "Helper")) 460 (:functional-test (remove-postfix file-class "ControllerTest")))))) 461 462 (defun rails-core:current-model () 463 "Return the current Rails model." 464 (let* ((file-class (rails-core:class-by-file (buffer-file-name)))) 465 (unless (rails-core:mailer-p file-class) 466 (case (rails-core:buffer-type) 467 (:migration (rails-core:model-by-migration-filename (buffer-name))) 468 (:model file-class) 469 (:unit-test (remove-postfix file-class "Test")) 470 (:fixture (singularize-string file-class)))))) 471 472 (defun rails-core:current-mailer () 473 "Return the current Rails Mailer, else return nil." 474 (let* ((file-class (rails-core:class-by-file (buffer-file-name))) 475 (test (remove-postfix file-class "Test"))) 476 (when (or (rails-core:mailer-p file-class) 477 (rails-core:mailer-p test)) 478 (case (rails-core:buffer-type) 479 (:mailer file-class) 480 (:unit-test test) 481 (:view (rails-core:class-by-file 482 (directory-file-name (directory-of-file (buffer-file-name))))))))) 483 484 (defun rails-core:current-action () 485 "Return the current action in the current Rails controller." 486 (case (rails-core:buffer-type) 487 (:controller (rails-core:current-method-name)) 488 (:mailer (rails-core:current-method-name)) 489 (:view (string-match "/\\([a-z0-9_]+\\)\.[a-z]+$" (buffer-file-name)) 490 (match-string 1 (buffer-file-name))))) 491 492 (defun rails-core:current-helper () 493 "Return the current helper" 494 (rails-core:current-controller)) 495 496 (defun rails-core:current-plugin () 497 "Return the current plugin name." 498 (let ((name (buffer-file-name))) 499 (when (string-match "vendor\\/plugins\\/\\([^\\/]+\\)" name) 500 (match-string 1 name)))) 501 502 (defun rails-core:current-method-name () 503 (save-excursion 504 (when (search-backward-regexp "^[ ]*def \\([a-z0-9_]+\\)" nil t) 505 (match-string-no-properties 1)))) 506 507 ;;;;;;;;;; Determination of buffer type ;;;;;;;;;; 508 509 (defun rails-core:buffer-file-match (regexp) 510 "Match the current buffer file name to RAILS_ROOT + REGEXP." 511 (when-bind (file (rails-core:file regexp)) 512 (string-match file 513 (buffer-file-name (current-buffer))))) 514 515 (defun rails-core:buffer-type () 516 "Return the type of the current Rails file or nil if the type 517 cannot be determinated." 518 (loop for (type dir func) in rails-directory<-->types 519 when (and (rails-core:buffer-file-match dir) 520 (if func 521 (apply func (list (buffer-file-name (current-buffer)))) 522 t)) 523 do (return type))) 524 525 526 ;;;;;;;;;; Rails minor mode Buttons ;;;;;;;;;; 527 528 (define-button-type 'rails-button 529 'follow-link t 530 'action #'rails-core:button-action) 531 532 (defun rails-core:button-action (button) 533 (let* ((file-name (button-get button :rails:file-name)) 534 (line-number (button-get button :rails:line-number)) 535 (file (rails-core:file file-name))) 536 (when (and file 537 (file-exists-p file)) 538 (find-file-other-window file) 539 (when line-number 540 (goto-line line-number))))) 541 542 543 ;;;;;;;;;; Rails minor mode logs ;;;;;;;;;; 544 545 (defun rails-log-add (message) 546 "Add MESSAGE to the Rails minor mode log in RAILS_ROOT." 547 (rails-project:with-root 548 (root) 549 (append-string-to-file (rails-core:file "log/rails-minor-mode.log") 550 (format "%s: %s\n" 551 (format-time-string "%Y/%m/%d %H:%M:%S") message)))) 552 553 (defun rails-logged-shell-command (command buffer) 554 "Execute a shell command in the buffer and write the results to 555 the Rails minor mode log." 556 (shell-command (format "%s %s" rails-ruby-command command) buffer) 557 (rails-log-add 558 (format "\n%s> %s\n%s" (rails-project:name) 559 command (buffer-string-by-name buffer)))) 560 561 ;;;;;;;;;; Rails menu ;;;;;;;;;; 562 563 (defun rails-core:menu-separator () 564 (unless (rails-use-text-menu) 'menu (list "--" "--"))) 565 566 (if (fboundp 'completion-posn-at-point-as-event) 567 (defun rails-core:menu-position () 568 (completion-posn-at-point-as-event nil nil nil (+ (frame-char-height) 2))) 569 (defun rails-core:menu-position () 570 (list '(300 50) (get-buffer-window (current-buffer))))) 571 572 (defun rails-core:menu (menu) 573 "Show a menu." 574 (let ((result 575 (if (rails-use-text-menu) 576 (tmm-prompt menu) 577 (x-popup-menu (rails-core:menu-position) 578 (rails-core:prepare-menu menu))))) 579 (if (listp result) 580 (first result) 581 result))) 582 583 (defvar rails-core:menu-letters-list 584 (let ((res '())) 585 (loop for i from (string-to-char "1") upto (string-to-char "9") 586 do (add-to-list 'res (char-to-string i) t)) 587 (loop for i from (string-to-char "a") upto (string-to-char "z") 588 do (add-to-list 'res (char-to-string i) t)) 589 res) 590 "List contains 0-9a-z letter") 591 592 (defun rails-core:prepare-menu (menu) 593 "Append a prefix to each label of menu-item from MENU." 594 (let ((title (car menu)) 595 (menu (cdr menu)) 596 (result '()) 597 (result-line '()) 598 (letter 0)) 599 (dolist (line menu) 600 (setq result-line '()) 601 (dolist (it line) 602 (typecase it 603 (cons 604 (rails-core:menu-separator) 605 (if (and (string= (car (rails-core:menu-separator)) (car it)) 606 (string= (cadr (rails-core:menu-separator)) (cadr it))) 607 (add-to-list 'result-line it t) 608 (progn 609 (add-to-list 'result-line (cons (format "%s) %s" (nth letter rails-core:menu-letters-list) (car it)) 610 (cdr it)) t) 611 (setq letter (+ 1 letter))))) 612 (t 613 (add-to-list 'result-line it t)))) 614 (add-to-list 'result result-line t)) 615 (cons title result))) 616 617 ;;;;;;;;;; Misc ;;;;;;;;;; 618 619 (defun rails-core:erb-block-string () 620 "Return the contents of the current ERb block." 621 (save-excursion 622 (save-match-data 623 (let ((start (point))) 624 (search-backward-regexp "<%[=]?") 625 (let ((from (match-end 0))) 626 (search-forward "%>") 627 (let ((to (match-beginning 0))) 628 (when (>= to start) 629 (buffer-substring-no-properties from to)))))))) 630 631 (defun rails-core:rhtml-buffer-p () 632 "Return non nil if the current buffer is rhtml file." 633 (string-match "\\.rhtml$" (buffer-file-name))) 634 635 (provide 'rails-core)