From abfbbcf8e3c49d0f6890973a13affc643e17ef07 Mon Sep 17 00:00:00 2001 From: nobu Date: Thu, 25 Jul 2002 00:09:03 +0000 Subject: [PATCH] * misc/ruby-mode.el (ruby-delimiter): include here document. * misc/ruby-mode.el (ruby-deep-arglist): skips spaces after parenthesis when 'space. * misc/ruby-mode.el (ruby-imenu-create-index): fix for nested classes. * misc/ruby-mode.el (ruby-accurate-end-of-block): added. scan a block in the order. * misc/ruby-mode.el (ruby-expr-beg): support for here document. * misc/ruby-mode.el (ruby-parse-partial): splitted from ruby-parse-region. * misc/ruby-mode.el (ruby-move-to-block): skips RD style comments. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@2651 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- ChangeLog | 20 ++ misc/ruby-mode.el | 535 +++++++++++++++++++++++++--------------------- 2 files changed, 308 insertions(+), 247 deletions(-) diff --git a/ChangeLog b/ChangeLog index f16fd9b7d8..1a0e634c8f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,23 @@ +Thu Jul 25 09:05:02 2002 Nobuyoshi Nakada + + * misc/ruby-mode.el (ruby-delimiter): include here document. + + * misc/ruby-mode.el (ruby-deep-arglist): skips spaces after + parenthesis when 'space. + + * misc/ruby-mode.el (ruby-imenu-create-index): fix for nested + classes. + + * misc/ruby-mode.el (ruby-accurate-end-of-block): added. scan a + block in the order. + + * misc/ruby-mode.el (ruby-expr-beg): support for here document. + + * misc/ruby-mode.el (ruby-parse-partial): splitted from + ruby-parse-region. + + * misc/ruby-mode.el (ruby-move-to-block): skips RD style comments. + Thu Jul 18 11:52:02 2002 Shugo Maeda * lib/net/ftp.rb (set_socket): new method. diff --git a/misc/ruby-mode.el b/misc/ruby-mode.el index 13ca032bb9..556f72387d 100644 --- a/misc/ruby-mode.el +++ b/misc/ruby-mode.el @@ -48,7 +48,7 @@ (defconst ruby-block-end-re "end") (defconst ruby-delimiter - (concat "[?$/%(){}#\"'`.:]\\|\\[\\|\\]\\|\\<\\(" + (concat "[?$/%(){}#\"'`.:]\\|<<\\|\\[\\|\\]\\|\\<\\(" ruby-block-beg-re "\\|" ruby-block-end-re "\\)\\>\\|^=begin") @@ -127,33 +127,54 @@ "*Indentation of ruby statements.") (defvar ruby-deep-arglist t - "*Deep indent argument lists when non-nil.") + "*Deep indent argument lists when non-nil. +Also ignores spaces after parenthesis when 'space.") (eval-when-compile (require 'cl)) -(defun ruby-imenu-create-index () - (let ((index-alist '()) - class-name class-begin method-name method-begin decl) - (goto-char (point-min)) - (while (re-search-forward "^\\s *\\(class\\|def\\)\\s *\\([^(\n ]+\\)" nil t) - (setq decl (buffer-substring (match-beginning 1) (match-end 1))) +(defun ruby-imenu-create-index-in-block (prefix beg end) + (let ((index-alist '()) (nest '()) (case-fold-search nil) + name next pos decl sing) + (goto-char beg) + (while (re-search-forward "^\\s *\\(\\(class\\>\\(\\s *<<\\)?\\|module\\>\\)\\s *\\([^\(<\n ]+\\)\\|\\(def\\|alias\\)\\>\\s *\\([^\(\n ]+\\)\\)" end t) + (setq sing (match-beginning 3)) + (setq decl (match-string 5)) + (setq next (match-end 0)) + (setq name (or (match-string 4) (match-string 6))) + (setq pos (match-beginning 0)) (cond - ((string= "class" decl) - (setq class-begin (match-beginning 2)) - (setq class-name (buffer-substring class-begin (match-end 2))) - (push (cons class-name (match-beginning 0)) index-alist) - (ruby-mark-defun) - (save-restriction - (narrow-to-region (region-beginning) (region-end)) - (while (re-search-forward "^\\s *def\\s *\\([^(\n ]+\\)" nil 'move) - (setq method-begin (match-beginning 1)) - (setq method-name (buffer-substring method-begin (match-end 1))) - (push (cons (concat class-name "#" method-name) (match-beginning 0)) index-alist)))) + ((string= "alias" decl) + (if prefix (setq name (concat prefix name))) + (push (cons name pos) index-alist)) ((string= "def" decl) - (setq method-begin (match-beginning 2)) - (setq method-name (buffer-substring method-begin (match-end 2))) - (push (cons method-name (match-beginning 0)) index-alist)))) + (if prefix + (setq name + (cond + ((string-match "^self\." name) + (concat (substring prefix 0 -1) (substring name 4))) + (t (concat prefix name))))) + (push (cons name pos) index-alist) + (ruby-accurate-end-of-block)) + (t + (if (string= "self" name) + (if prefix (setq name (substring prefix 0 -1))) + (if prefix (setq name (concat (substring prefix 0 -1) "::" name))) + (push (cons name pos) index-alist)) + (ruby-accurate-end-of-block) + (setq beg (point)) + (setq index-alist + (nconc (ruby-imenu-create-index-in-block + (concat name (if sing "." "#")) + next beg) index-alist)) + (goto-char beg)))) index-alist)) +(defun ruby-imenu-create-index () + (nreverse (ruby-imenu-create-index-in-block nil (point-min) nil))) + +(defun ruby-accurate-end-of-block () + (let (state) + (while (>= (nth 2 (setq state (apply 'ruby-parse-partial end state))) 0)))) + (defun ruby-mode-variables () (set-syntax-table ruby-mode-syntax-table) (setq local-abbrev-table ruby-mode-abbrev-table) @@ -239,31 +260,33 @@ The variable ruby-indent-level controls the amount of indentation. (defun ruby-expr-beg (&optional option) (save-excursion (store-match-data nil) - (skip-chars-backward " \t") - (cond - ((bolp) t) - ((looking-at "\\?") - (or (bolp) (forward-char -1)) - (not (looking-at "\\sw"))) - (t - (forward-char -1) - (or (looking-at ruby-operator-re) - (looking-at "[\\[({,;]") - (and (not (eq option 'modifier)) - (looking-at "[!?]")) - (and (looking-at ruby-symbol-re) - (skip-chars-backward ruby-symbol-chars) - (cond - ((or (looking-at ruby-block-beg-re) - (looking-at ruby-block-op-re) - (looking-at ruby-block-mid-re)) - (goto-char (match-end 0)) - (looking-at "\\>")) - ((eq option 'expr-qstr) - (looking-at "[a-zA-Z][a-zA-z0-9_]* +%[^ \t]")) - ((eq option 'expr-re) - (looking-at "[a-zA-Z][a-zA-z0-9_]* +/[^ \t]")) - (t nil)))))))) + (let ((space (skip-chars-backward " \t"))) + (cond + ((bolp) t) + ((looking-at "\\?") + (or (bolp) (forward-char -1)) + (not (looking-at "\\sw"))) + (t + (forward-char -1) + (or (looking-at ruby-operator-re) + (looking-at "[\\[({,;]") + (and (or (eq option 'modifier) + (not (eq option 'heredoc)) + (< space 0)) + (looking-at "[!?]")) + (and (looking-at ruby-symbol-re) + (skip-chars-backward ruby-symbol-chars) + (cond + ((or (looking-at ruby-block-beg-re) + (looking-at ruby-block-op-re) + (looking-at ruby-block-mid-re)) + (goto-char (match-end 0)) + (looking-at "\\>")) + ((eq option 'expr-qstr) + (looking-at "[a-zA-Z][a-zA-z0-9_]* +%[^ \t]")) + ((eq option 'expr-re) + (looking-at "[a-zA-Z][a-zA-z0-9_]* +/[^ \t]")) + (t nil))))))))) (defun ruby-forward-string (term &optional end no-error expand) (let ((n 1) (c (string-to-char term)) @@ -280,184 +303,202 @@ The variable ruby-indent-level controls the amount of indentation. (no-error nil) (error "unterminated string")))) -(defun ruby-parse-region (start end) - (let ((indent-point end) - (indent 0) - (in-string nil) - (in-paren nil) - (depth 0) - (nest nil) - (pcol nil)) - (save-excursion - (if start - (goto-char start) - (ruby-beginning-of-indent)) - (save-restriction - (narrow-to-region (point) end) - (while (and (> indent-point (point)) - (re-search-forward ruby-delimiter indent-point t)) - (or depth (setq depth 0)) - (let ((pnt (point)) w re expand) - (goto-char (match-beginning 0)) - (cond - ((or (looking-at "\"") ;skip string - (looking-at "`")) - (cond - ((and (not (eobp)) - (ruby-forward-string (buffer-substring (point) (1+ (point))) indent-point t t)) - nil) - (t - (setq in-string (point)) - (goto-char indent-point)))) - ((looking-at "'") - (cond - ((and (not (eobp)) - (re-search-forward "[^\\]\\(\\\\\\\\\\)*'" indent-point t)) - nil) - (t - (setq in-string (point)) - (goto-char indent-point)))) - ((looking-at "/") - (cond - ((and (not (eobp)) (ruby-expr-beg 'expr-re)) - (if (ruby-forward-string "/" indent-point t t) - nil - (setq in-string (point)) - (goto-char indent-point))) - (t - (goto-char pnt)))) - ((looking-at "%") - (cond - ((and (not (eobp)) - (ruby-expr-beg 'expr-qstr) - (not (looking-at "%=")) - (looking-at "%[Qqrxw]?\\(.\\)")) - (goto-char (match-beginning 1)) - (setq expand (not (eq (char-before) ?q))) - (setq w (buffer-substring (match-beginning 1) - (match-end 1))) - (cond - ((string= w "[") (setq re "][")) - ((string= w "{") (setq re "}{")) - ((string= w "(") (setq re ")(")) - ((string= w "<") (setq re "><")) - ((or (and expand (string= w "\\")) - (member w '("*" "." "+" "?" "^" "$"))) - (setq w (concat "\\" w)))) - (unless (cond (re (ruby-forward-string re indent-point t expand)) - (expand (ruby-forward-string w indent-point t t)) - (t (re-search-forward - (if (string= w "\\") - "\\\\[^\\]*\\\\" - (concat "[^\\]\\(\\\\\\\\\\)*" w)) - indent-point t))) - (setq in-string (point)) - (goto-char indent-point))) - (t - (goto-char pnt)))) - ((looking-at "\\?") ;skip ?char - (cond - ((ruby-expr-beg) - (looking-at "?\\(\\\\C-\\|\\\\M-\\)*.") - (goto-char (match-end 0))) - (t - (goto-char pnt)))) - ((looking-at "\\$") ;skip $char - (goto-char pnt) - (forward-char 1)) - ((looking-at "#") ;skip comment - (forward-line 1) - (goto-char (point)) - ) - ((and (looking-at "(") ruby-deep-arglist) - (setq nest (cons (cons (char-after (point)) pnt) nest)) - (setq pcol (cons (cons pnt depth) pcol)) - (setq depth 0) - (goto-char pnt) - ) - ((looking-at "[\\[{(]") - (setq nest (cons (cons (char-after (point)) pnt) nest)) - (setq depth (1+ depth)) - (goto-char pnt) - ) - ((and (looking-at ")") ruby-deep-arglist) - (setq nest (cdr nest)) - (setq depth (cdr (car pcol))) - (setq pcol (cdr pcol)) - (goto-char pnt)) - ((looking-at "[])}]") - (setq nest (cdr nest)) - (setq depth (1- depth)) - (goto-char pnt)) - ((looking-at ruby-block-end-re) - (if (or (and (not (bolp)) - (progn - (forward-char -1) - (setq w (char-after (point))) - (or (eq ?_ w) - (eq ?. w)))) - (progn - (goto-char pnt) - (setq w (char-after (point))) - (or (eq ?_ w) - (eq ?! w) - (eq ?? w)))) - nil - (setq nest (cdr nest)) - (setq depth (1- depth))) - (goto-char pnt)) - ((looking-at "def\\s +[^(\n;]*") - (if (or (bolp) - (progn - (forward-char -1) - (not (eq ?_ (char-after (point)))))) - (progn - (setq nest (cons (cons nil pnt) nest)) - (setq depth (1+ depth)))) - (goto-char (match-end 0))) - ((looking-at ruby-block-beg-re) - (and - (save-match-data - (or (not (looking-at "do\\>[^_]")) - (save-excursion - (back-to-indentation) - (not (looking-at ruby-non-block-do-re))))) - (or (bolp) +(defun ruby-parse-partial (&optional end in-string nest depth pcol indent) + (or depth (setq depth 0)) + (or indent (setq indent 0)) + (when (re-search-forward ruby-delimiter end 'move) + (let ((pnt (point)) w re expand) + (goto-char (match-beginning 0)) + (cond + ((or (looking-at "\"") ;skip string + (looking-at "`")) + (cond + ((and (not (eobp)) + (ruby-forward-string (buffer-substring (point) (1+ (point))) end t t)) + nil) + (t + (setq in-string (point)) + (goto-char end)))) + ((looking-at "'") + (cond + ((and (not (eobp)) + (re-search-forward "[^\\]\\(\\\\\\\\\\)*'" end t)) + nil) + (t + (setq in-string (point)) + (goto-char end)))) + ((looking-at "/") + (cond + ((and (not (eobp)) (ruby-expr-beg 'expr-re)) + (if (ruby-forward-string "/" end t t) + nil + (setq in-string (point)) + (goto-char end))) + (t + (goto-char pnt)))) + ((looking-at "%") + (cond + ((and (not (eobp)) + (ruby-expr-beg 'expr-qstr) + (not (looking-at "%=")) + (looking-at "%[QqrxWw]?\\(.\\)")) + (goto-char (match-beginning 1)) + (setq expand (not (memq (char-before) '(?q ?w)))) + (setq w (match-string 1)) + (cond + ((string= w "[") (setq re "][")) + ((string= w "{") (setq re "}{")) + ((string= w "(") (setq re ")(")) + ((string= w "<") (setq re "><")) + ((and expand (string= w "\\")) + (setq w (concat "\\" w)))) + (unless (cond (re (ruby-forward-string re end t expand)) + (expand (ruby-forward-string w end t t)) + (t (re-search-forward + (if (string= w "\\") + "\\\\[^\\]*\\\\" + (concat "[^\\]\\(\\\\\\\\\\)*" w)) + end t))) + (setq in-string (point)) + (goto-char end))) + (t + (goto-char pnt)))) + ((looking-at "\\?") ;skip ?char + (cond + ((and (ruby-expr-beg) + (looking-at "?\\(\\\\C-\\|\\\\M-\\)*.")) + (goto-char (match-end 0))) + (t + (goto-char pnt)))) + ((looking-at "\\$") ;skip $char + (goto-char pnt) + (forward-char 1)) + ((looking-at "#") ;skip comment + (forward-line 1) + (goto-char (point)) + ) + ((and (looking-at "(") ruby-deep-arglist) + (and (eq ruby-deep-arglist 'space) (looking-at ".\\s +") + (setq pnt (match-end 0))) + (setq nest (cons (cons (char-after (point)) pnt) nest)) + (setq pcol (cons (cons pnt depth) pcol)) + (setq depth 0) + (goto-char pnt) + ) + ((looking-at "[\\[{(]") + (setq nest (cons (cons (char-after (point)) pnt) nest)) + (setq depth (1+ depth)) + (goto-char pnt) + ) + ((and (looking-at ")") ruby-deep-arglist) + (setq nest (cdr nest)) + (setq depth (cdr (car pcol))) + (setq pcol (cdr pcol)) + (goto-char pnt)) + ((looking-at "[])}]") + (setq nest (cdr nest)) + (setq depth (1- depth)) + (goto-char pnt)) + ((looking-at ruby-block-end-re) + (if (or (and (not (bolp)) (progn (forward-char -1) (setq w (char-after (point))) - (not (or (eq ?_ w) - (eq ?. w))))) - (goto-char pnt) - (setq w (char-after (point))) - (not (eq ?_ w)) - (not (eq ?! w)) - (not (eq ?? w)) - (skip-chars-forward " \t") - (goto-char (match-beginning 0)) - (or (not (looking-at ruby-modifier-re)) - (ruby-expr-beg 'modifier)) - (goto-char pnt) - (setq nest (cons (cons nil pnt) nest)) - (setq depth (1+ depth))) - (goto-char pnt)) - ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*\\)?") - (goto-char (match-end 0))) - ((or (looking-at "\\.") - (looking-at "\\.\\.\\.?") - (looking-at "\\.[0-9]+") - (looking-at "\\.[a-zA-Z_0-9]+")) - (goto-char (match-end 0))) - ((looking-at "^=begin") - (if (re-search-forward "^=end" indent-point t) - (forward-line 1) - (setq in-string (match-end 0)) - (goto-char indent-point))) - (t - (error (format "bad string %s" - (buffer-substring (point) pnt) - ))))))) - (list in-string (car nest) depth (car (car pcol)))))) + (or (eq ?_ w) + (eq ?. w)))) + (progn + (goto-char pnt) + (setq w (char-after (point))) + (or (eq ?_ w) + (eq ?! w) + (eq ?? w)))) + nil + (setq nest (cdr nest)) + (setq depth (1- depth))) + (goto-char pnt)) + ((looking-at "def\\s +[^(\n;]*") + (if (or (bolp) + (progn + (forward-char -1) + (not (eq ?_ (char-after (point)))))) + (progn + (setq nest (cons (cons nil pnt) nest)) + (setq depth (1+ depth)))) + (goto-char (match-end 0))) + ((looking-at ruby-block-beg-re) + (and + (save-match-data + (or (not (looking-at "do\\>[^_]")) + (save-excursion + (back-to-indentation) + (not (looking-at ruby-non-block-do-re))))) + (or (bolp) + (progn + (forward-char -1) + (setq w (char-after (point))) + (not (or (eq ?_ w) + (eq ?. w))))) + (goto-char pnt) + (setq w (char-after (point))) + (not (eq ?_ w)) + (not (eq ?! w)) + (not (eq ?? w)) + (skip-chars-forward " \t") + (goto-char (match-beginning 0)) + (or (not (looking-at ruby-modifier-re)) + (ruby-expr-beg 'modifier)) + (goto-char pnt) + (setq nest (cons (cons nil pnt) nest)) + (setq depth (1+ depth))) + (goto-char pnt)) + ((looking-at ":\\([a-zA-Z_][a-zA-Z_0-9]*\\)?") + (goto-char (match-end 0))) + ((or (looking-at "\\.\\.\\.?") + (looking-at "\\.[0-9]+") + (looking-at "\\.[a-zA-Z_0-9]+") + (looking-at "\\.")) + (goto-char (match-end 0))) + ((looking-at "^=begin") + (if (re-search-forward "^=end" end t) + (forward-line 1) + (setq in-string (match-end 0)) + (goto-char end))) + ((looking-at "<<") + (cond + ((and (ruby-expr-beg 'heredoc) + (looking-at "<<\\(-\\)?\\(\\([\"'`]\\)\\([^\n]+?\\)\\3\\|\\sw+\\)")) + (setq re (regexp-quote (or (match-string 4) (match-string 2)))) + (if (match-beginning 1) (setq re (concat "\\s *" re))) + (if (re-search-forward (concat "^" re "$") end 'move) + (forward-line 1) + (setq in-string (match-end 0)) + (goto-char end))) + (t + (goto-char pnt)))) + ((looking-at "^__END__$") + (goto-char pnt)) + (t + (error (format "bad string %s" + (buffer-substring (point) pnt) + )))))) + (list in-string nest depth pcol)) + +(defun ruby-parse-region (start end) + (let (state) + (save-excursion + (if start + (goto-char start) + (ruby-beginning-of-indent)) + (save-restriction + (narrow-to-region (point) end) + (while (and (> end (point)) + (setq state (apply 'ruby-parse-partial end state)))))) + (list (nth 0 state) ; in-string + (car (nth 1 state)) ; nest + (nth 2 state) ; depth + (car (car (nth 3 state))) ; pcol + ;(car (nth 5 state)) ; indent + ))) (defun ruby-indent-size (pos nest) (+ pos (* (if nest nest 1) ruby-indent-level))) @@ -627,27 +668,30 @@ An end of a defun is found by moving forward from the beginning of one." (defun ruby-move-to-block (n) (let (start pos done down) (setq start (ruby-calculate-indent)) - (if (eobp) - nil - (while (and (not (bobp)) (not (eobp)) (not done)) - (forward-line n) + (setq down (looking-at (if (< n 0) ruby-block-end-re ruby-block-beg-re))) + (while (and (not done) (not (if (< n 0) (bobp) (eobp)))) + (forward-line n) + (cond + ((looking-at "^\\s *$")) + ((looking-at "^\\s *#")) + ((and (> n 0) (looking-at "^=begin\\>")) + (re-search-forward "^=end\\>")) + ((and (< n 0) (looking-at "^=end\\>")) + (re-search-backward "^=begin\\>")) + (t + (setq pos (current-indentation)) (cond - ((looking-at "^$")) - ((looking-at "^\\s *#")) - (t - (setq pos (current-indentation)) - (cond - ((< start pos) - (setq down t)) - ((and down (= pos start)) - (setq done t)) - ((> start pos) - (setq done t))))) - (if done - (progn - (back-to-indentation) - (if (looking-at ruby-block-mid-re) - (setq done nil))))))) + ((< start pos) + (setq down t)) + ((and down (= pos start)) + (setq done t)) + ((> start pos) + (setq done t))))) + (if done + (progn + (back-to-indentation) + (if (looking-at ruby-block-mid-re) + (setq done nil)))))) (back-to-indentation)) (defun ruby-beginning-of-block () @@ -706,8 +750,7 @@ An end of a defun is found by moving forward from the beginning of one." "\\(" ruby-symbol-re "+\\)") nil t) (progn - (setq mlist (list (buffer-substring - (match-beginning 2) (match-end 2)))) + (setq mlist (list (match-string 2))) (goto-char (match-beginning 1)) (setq indent (current-column)) (beginning-of-line))) @@ -721,9 +764,7 @@ An end of a defun is found by moving forward from the beginning of one." (goto-char (match-beginning 1)) (if (< (current-column) indent) (progn - (setq mlist - (cons (buffer-substring - (match-beginning 2) (match-end 2)) mlist)) + (setq mlist (cons (match-string 2) mlist)) (setq indent (current-column)) (beginning-of-line)))) ;; generate string