/ emacs.d / rails / rails-ruby.el
rails-ruby.el
  1  ;;; rails-ruby.el --- provide features for ruby-mode
  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-ruby.el $
  9  ;; $Id: rails-ruby.el 190 2007-04-27 19:04:46Z 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  (require 'inf-ruby)
 30  
 31  ;; setup align for ruby-mode
 32  (require 'align)
 33  
 34  (defconst align-ruby-modes '(ruby-mode)
 35    "align-perl-modes is a variable defined in `align.el'.")
 36  
 37  (defconst ruby-align-rules-list
 38    '((ruby-comma-delimiter
 39       (regexp . ",\\(\\s-*\\)[^/ \t\n]")
 40       (modes  . align-ruby-modes)
 41       (repeat . t))
 42      (ruby-symbol-after-func
 43       (regexp . "^\\s-*\\w+\\(\\s-+\\):\\w+")
 44       (modes  . align-ruby-modes)))
 45    "Alignment rules specific to the ruby mode.
 46  See the variable `align-rules-list' for more details.")
 47  
 48  (add-to-list 'align-perl-modes 'ruby-mode)
 49  (add-to-list 'align-dq-string-modes 'ruby-mode)
 50  (add-to-list 'align-sq-string-modes 'ruby-mode)
 51  (add-to-list 'align-open-comment-modes 'ruby-mode)
 52  (dolist (it ruby-align-rules-list)
 53    (add-to-list 'align-rules-list it))
 54  
 55  ;; other stuff
 56  
 57  (defun ruby-newline-and-indent ()
 58    (interactive)
 59    (newline)
 60    (ruby-indent-command))
 61  
 62  (defun ruby-toggle-string<>simbol ()
 63    "Easy to switch between strings and symbols."
 64    (interactive)
 65    (let ((initial-pos (point)))
 66      (save-excursion
 67        (when (looking-at "[\"']") ;; skip beggining quote
 68          (goto-char (+ (point) 1))
 69          (unless (looking-at "\\w")
 70            (goto-char (- (point) 1))))
 71        (let* ((point (point))
 72               (start (skip-syntax-backward "w"))
 73               (end (skip-syntax-forward "w"))
 74               (end (+ point start end))
 75               (start (+ point start))
 76               (start-quote (- start 1))
 77               (end-quote (+ end 1))
 78               (quoted-str (buffer-substring-no-properties start-quote end-quote))
 79               (symbol-str (buffer-substring-no-properties start end)))
 80          (cond
 81           ((or (string-match "^\"\\w+\"$" quoted-str)
 82                (string-match "^\'\\w+\'$" quoted-str))
 83            (setq quoted-str (substring quoted-str 1 (- (length quoted-str) 1)))
 84            (kill-region start-quote end-quote)
 85            (goto-char start-quote)
 86            (insert (concat ":" quoted-str)))
 87           ((string-match "^\:\\w+$" symbol-str)
 88            (setq symbol-str (substring symbol-str 1))
 89            (kill-region start end)
 90            (goto-char start)
 91            (insert (format "'%s'" symbol-str))))))
 92      (goto-char initial-pos)))
 93  
 94  (defun run-ruby-in-buffer (cmd buf)
 95    "Run CMD as a ruby process in BUF if BUF does not exist."
 96    (let ((abuf (concat "*" buf "*")))
 97      (when (not (comint-check-proc abuf))
 98        (set-buffer (make-comint buf rails-ruby-command nil cmd)))
 99      (inferior-ruby-mode)
100      (make-local-variable 'inferior-ruby-first-prompt-pattern)
101      (make-local-variable 'inferior-ruby-prompt-pattern)
102      (setq inferior-ruby-first-prompt-pattern "^>> "
103            inferior-ruby-prompt-pattern "^>> ")
104      (pop-to-buffer abuf)))
105  
106  (defun complete-ruby-method (prefix &optional maxnum)
107    (if (capital-word-p prefix)
108        (let* ((cmd "x = []; ObjectSpace.each_object(Class){|i| x << i.to_s}; x.map{|i| i.match(/^%s/) ? i.gsub(/^%s/, '') : nil }.compact.sort{|x,y| x.size <=> y.size}")
109               (cmd (if maxnum (concat cmd (format "[0...%s]" maxnum)) cmd)))
110          (el4r-ruby-eval (format cmd prefix prefix)))
111      (save-excursion
112        (goto-char (- (point) (+ 1 (length prefix))))
113        (when (and (looking-at "\\.")
114                   (capital-word-p (word-at-point))
115                   (el4r-ruby-eval (format "::%s rescue nil" (word-at-point))))
116          (let* ((cmd "%s.public_methods.map{|i| i.match(/^%s/) ? i.gsub(/^%s/, '') : nil }.compact.sort{|x,y| x.size <=> y.size}")
117                 (cmd (if maxnum (concat cmd (format "[0...%s]" maxnum)) cmd)))
118            (el4r-ruby-eval (format cmd (word-at-point) prefix prefix)))))))
119  
120  ;; flymake ruby support
121  
122  (require 'flymake nil t)
123  
124  (defconst flymake-allowed-ruby-file-name-masks
125    '(("\\.rb\\'"      flymake-ruby-init)
126      ("\\.rxml\\'"    flymake-ruby-init)
127      ("\\.builder\\'" flymake-ruby-init)
128      ("\\.rjs\\'"     flymake-ruby-init))
129    "Filename extensions that switch on flymake-ruby mode syntax checks.")
130  
131  (defconst flymake-ruby-error-line-pattern-regexp
132    '("^\\([^:]+\\):\\([0-9]+\\): *\\([\n]+\\)" 1 2 nil 3)
133    "Regexp matching ruby error messages.")
134  
135  (defun flymake-ruby-init ()
136    (condition-case er
137        (let* ((temp-file (flymake-init-create-temp-buffer-copy
138                           'flymake-create-temp-inplace))
139               (local-file  (file-relative-name
140                             temp-file
141                             (file-name-directory buffer-file-name))))
142          (list rails-ruby-command (list "-c" local-file)))
143      ('error ())))
144  
145  (defun flymake-ruby-load ()
146    (when (and (buffer-file-name)
147               (string-match
148                (format "\\(%s\\)"
149                        (string-join
150                         "\\|"
151                         (mapcar 'car flymake-allowed-ruby-file-name-masks)))
152                (buffer-file-name)))
153      (setq flymake-allowed-file-name-masks
154            (append flymake-allowed-file-name-masks flymake-allowed-ruby-file-name-masks))
155      (setq flymake-err-line-patterns
156            (cons flymake-ruby-error-line-pattern-regexp flymake-err-line-patterns))
157      (flymake-mode t)
158      (local-set-key (rails-key "d") 'flymake-display-err-menu-for-current-line)))
159  
160  (when (featurep 'flymake)
161    (add-hook 'ruby-mode-hook 'flymake-ruby-load))
162  
163  (provide 'rails-ruby)