branch: elpa/evil-matchit commit 0b2c287826ea6c0bbbfb849aa5611f44ae9b6b7b Author: Chen Bin <chenbin...@gmail.com> Commit: Chen Bin <chenbin...@gmail.com>
perfect support for ruby-mode v1.3.3 #29 --- README.org | 2 +- evil-matchit-pkg.el | 2 +- evil-matchit-ruby.el | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ evil-matchit-sdk.el | 69 +++++++++++++++++++++++++++---------------------- evil-matchit.el | 22 +++++++++------- 5 files changed, 125 insertions(+), 42 deletions(-) diff --git a/README.org b/README.org index 976ec9b588..eba628503f 100644 --- a/README.org +++ b/README.org @@ -1,4 +1,4 @@ -* evil-matchit (v1.3.2) +* evil-matchit (v1.3.3) Vim [[http://www.vim.org/scripts/script.php?script_id=39][matchit.vim]] by Benji Fisher ported into Emacs. diff --git a/evil-matchit-pkg.el b/evil-matchit-pkg.el index 16b99b3935..2cdc74d0e3 100644 --- a/evil-matchit-pkg.el +++ b/evil-matchit-pkg.el @@ -1,2 +1,2 @@ -(define-package "evil-matchit" "1.3.2" +(define-package "evil-matchit" "1.3.3" "Vim matchit ported into Emacs (requires EVIL)") diff --git a/evil-matchit-ruby.el b/evil-matchit-ruby.el new file mode 100644 index 0000000000..5d4a5280ad --- /dev/null +++ b/evil-matchit-ruby.el @@ -0,0 +1,72 @@ +;;; evil-matchit-ruby.el ---ruby plugin of evil-matchit + +;; Copyright (C) 2014 Chen Bin <chenbin...@gmail.com> + +;; Author: Chen Bin <chenbin...@gmail.com> + +;; This file is not part of GNU Emacs. + +;;; License: + +;; This file is part of evil-matchit +;; +;; evil-matchit is free software: you can redistribute it and/or +;; modify it under the terms of the GNU General Public License as published +;; by the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. +;; +;; evil-matchit is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. +;; +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see <http://www.gnu.org/licenses/>. + + +;;; Code: + +;; OPTIONAL, you don't need SDK to write a plugin for evil-matchit +;; but SDK don make you write less code, isn't it? +;; All you need to do is just define the match-tags for SDK algorithm to lookup. +(require 'evil-matchit-sdk) + +(defvar evilmi-ruby-extract-keyword-howtos + '(("^[ \t]*\\([a-z]+\\)\\( .*\\| *\\)$" 1) + ("^.* \\(do\\) |[a-z0-9A-Z,|]+|$" 1) + ) + "The list of HOWTO on extracting keyword from current line. +Each howto is actually a pair. The first element of pair is the regular +expression to match the current line. The second is the index of sub-matches +to extract the keyword which starts from one. The sub-match is the match defined +between '\\(' and '\\)' in regular expression. +") + +(defvar evilmi-ruby-match-tags + '((("unless" "if") ("elsif" "else") ("end")) + ("begin" ("rescue" "ensure") "end") + ("case" ("when" "else") ("end")) + (("class" "def" "while" "do" "module" "for" "until") () ("end")) + ) + "The table we look up match tags. This is a three column table. +The first column contains the open tag(s). +The second column contains the middle tag(s). +The third column contains the closed tags(s). +The forth column is optional, t means the tags could be function exit +") + +;;;###autoload +(defun evilmi-ruby-get-tag () + (let (rlt) + (message "evilmi-ruby-get-tag called") + (setq rlt (evilmi-sdk-get-tag evilmi-ruby-match-tags evilmi-ruby-extract-keyword-howtos)) + (message "rlt=%s" rlt) + rlt)) + +;;;###autoload +(defun evilmi-ruby-jump (rlt NUM) + (message "evilmi-ruby-jump called") + (evilmi-sdk-jump rlt NUM evilmi-ruby-match-tags evilmi-ruby-extract-keyword-howtos) + ) + +(provide 'evil-matchit-ruby) diff --git a/evil-matchit-sdk.el b/evil-matchit-sdk.el index 73b1aaacd1..fd543634d3 100644 --- a/evil-matchit-sdk.el +++ b/evil-matchit-sdk.el @@ -7,17 +7,29 @@ Each howto is actually a pair. The first element of pair is the regular expression to match the current line. The second is the index of sub-matches to extract the keyword which starts from one. The sub-match is the match defined between '\\(' and '\\)' in regular expression. -" - ) +") - -(defun evilmi-sdk-tags-match (level orig-tag-info cur-tag-info) +(defun evilmi-sdk-tags-is-matched (level orig-tag-info cur-tag-info match-tags) (let (rlt) - (when (nth 2 cur-tag-info) ;; handle function exit point - (setq level 1) - ) - (setq rlt (and (= 1 level) (= (nth 0 orig-tag-info) (nth 0 cur-tag-info)))) - )) + (if (nth 2 cur-tag-info) ;; handle function exit point + (setq level 1)) + + (if (= 1 level) + (let ((orig-keyword (nth 3 orig-tag-info)) + (cur-keyword (nth 3 cur-tag-info)) + (orig-row-idx (nth 0 orig-tag-info)) + (cur-row-idx (nth 0 cur-tag-info)) + (orig-type (nth 1 orig-tag-info)) + (cur-type (nth 1 cur-tag-info))) + ;; end tag could be the same + (cond + ((and (< orig-type 2) (= cur-type 2)) + (setq rlt (evilmi-sdk-member cur-keyword (nth 2 (nth orig-row-idx match-tags))))) + ((and (< cur-type 2) (= orig-type 2)) + (setq rlt (evilmi-sdk-member orig-keyword (nth 2 (nth cur-row-idx match-tags))))) + (t (setq rlt (= (nth 0 orig-tag-info) (nth 0 cur-tag-info)))) + ))) + rlt)) ;;;###autoload (defun evilmi-sdk-member (KEYWORD LIST) @@ -39,13 +51,12 @@ between '\\(' and '\\)' in regular expression. ;;;###autoload -(defun evilmi-sdk-get-tag-info (tag match-tags) - "return (row column is-function-exit-point), +(defun evilmi-sdk-get-tag-info (KEYWORD match-tags) + "return (row column is-function-exit-point keyword), the row and column marked position in evilmi-mylang-match-tags is-function-exit-point could be t or nil " - (let (rlt elems elem tag-type - found i j) + (let (rlt elems elem found i j) (setq i 0) (while (and (< i (length match-tags)) (not found)) @@ -55,11 +66,11 @@ is-function-exit-point could be t or nil (setq elem (nth j elems)) (cond ((stringp elem) - (if (string-match (concat "^" elem "$") tag) + (if (string-match (concat "^" elem "$") KEYWORD) (setq found t) )) ((listp elem) - (if (evilmi-sdk-member tag elem) + (if (evilmi-sdk-member KEYWORD elem) (setq found t) )) ) @@ -69,8 +80,8 @@ is-function-exit-point could be t or nil ) (when found (if (nth 3 (nth i match-tags)) - (setq rlt (list i j t)) - (setq rlt (list i j)) + (setq rlt (list i j t KEYWORD)) + (setq rlt (list i j nil KEYWORD)) )) rlt )) @@ -78,9 +89,11 @@ is-function-exit-point could be t or nil (defun evilmi--sdk-extract-keyword (cur-line match-tags howtos) "extract keyword from cur-line. keyword should be defined in match-tags" (let (keyword howto i) + (setq i 0) (while (and (not keyword) (< i (length howtos))) (setq howto (nth i howtos)) + (when (string-match (nth 0 howto) cur-line) (setq keyword (match-string (nth 1 howto) cur-line)) ;; keep search keyword by using next howto (regex and match-string index) @@ -94,8 +107,7 @@ is-function-exit-point could be t or nil ;;;###autoload (defun evilmi-sdk-get-tag (match-tags howtos) - "return '(start-point tag-info) -" + "return '(start-point tag-info)" (let (rlt keyword (cur-line (buffer-substring-no-properties @@ -116,9 +128,7 @@ is-function-exit-point could be t or nil tag-info)) ) ) - rlt - ) - ) + rlt)) ;;;###autoload (defun evilmi-sdk-jump (rlt NUM match-tags howtos) @@ -139,14 +149,11 @@ is-function-exit-point could be t or nil (forward-line (if (= orig-tag-type 2) -1 1)) (setq cur-line (buffer-substring-no-properties (line-beginning-position) - (line-end-position)) - ) + (line-end-position))) (setq keyword (evilmi--sdk-extract-keyword cur-line match-tags howtos)) - ;; (message "keyword=%s cur-line=%s" keyword cur-line) (when keyword - (setq cur-tag-info (evilmi-sdk-get-tag-info keyword match-tags)) (setq cur-tag-type (nth 1 cur-tag-info)) @@ -155,7 +162,7 @@ is-function-exit-point could be t or nil ;; handle open tag ;; open (0) -> mid (1) found when level is one else ignore ((and (= orig-tag-type 0) (= cur-tag-type 1)) - (when (evilmi-sdk-tags-match level orig-tag-info cur-tag-info) + (when (evilmi-sdk-tags-is-matched level orig-tag-info cur-tag-info match-tags) (back-to-indentation) (setq where-to-jump-in-theory (1- (line-beginning-position))) (setq found t) @@ -163,7 +170,7 @@ is-function-exit-point could be t or nil ) ;; open (0) -> closed (2) found when level is zero, level-- ((and (= orig-tag-type 0) (= cur-tag-type 2)) - (when (evilmi-sdk-tags-match level orig-tag-info cur-tag-info) + (when (evilmi-sdk-tags-is-matched level orig-tag-info cur-tag-info match-tags) (goto-char (line-end-position)) (setq where-to-jump-in-theory (line-end-position)) (setq found t) @@ -183,7 +190,7 @@ is-function-exit-point could be t or nil ;; level is one means we are not in some embedded loop/conditional statements ((and (= orig-tag-type 1) (= cur-tag-type 1)) - (when (evilmi-sdk-tags-match level orig-tag-info cur-tag-info) + (when (evilmi-sdk-tags-is-matched level orig-tag-info cur-tag-info match-tags) (back-to-indentation) (setq where-to-jump-in-theory (1- (line-beginning-position))) (setq found t) @@ -191,7 +198,7 @@ is-function-exit-point could be t or nil ) ;; mid (1) -> closed (2) found when level is zero, level -- ((and (= orig-tag-type 1) (= cur-tag-type 2)) - (when (evilmi-sdk-tags-match level orig-tag-info cur-tag-info) + (when (evilmi-sdk-tags-is-matched level orig-tag-info cur-tag-info match-tags) (goto-char (line-end-position)) (setq where-to-jump-in-theory (line-end-position)) (setq found t) @@ -213,7 +220,7 @@ is-function-exit-point could be t or nil ) ;; closed (2) -> open (0) found when level is zero, level-- ((and (= orig-tag-type 2) (= cur-tag-type 0)) - (when (evilmi-sdk-tags-match level orig-tag-info cur-tag-info) + (when (evilmi-sdk-tags-is-matched level orig-tag-info cur-tag-info match-tags) (setq where-to-jump-in-theory (line-beginning-position)) (back-to-indentation) (setq found t) diff --git a/evil-matchit.el b/evil-matchit.el index 35ee8e34d3..280c97badd 100644 --- a/evil-matchit.el +++ b/evil-matchit.el @@ -4,7 +4,7 @@ ;; Author: Chen Bin <chenbin...@gmail.com> ;; URL: http://github.com/redguardtoo/evil-matchit -;; Version: 1.3.2 +;; Version: 1.3.3 ;; Keywords: matchit vim evil ;; Package-Requires: ((evil "1.0.7")) ;; @@ -86,16 +86,14 @@ (autoload 'evilmi-simple-get-tag "evil-matchit-simple" nil) (autoload 'evilmi-simple-jump "evil-matchit-simple" nil) (mapc (lambda (mode) - (plist-put evilmi-plugins mode '((evilmi-simple-get-tag evilmi-simple-jump))) - ) + (plist-put evilmi-plugins mode '((evilmi-simple-get-tag evilmi-simple-jump)))) '(java-mode perl-mode cperl-mode go-mode)) ;; Javascript (autoload 'evilmi-javascript-get-tag "evil-matchit-javascript" nil) (autoload 'evilmi-javascript-jump "evil-matchit-javascript" nil) (mapc (lambda (mode) - (plist-put evilmi-plugins mode '((evilmi-javascript-get-tag evilmi-javascript-jump))) - ) + (plist-put evilmi-plugins mode '((evilmi-javascript-get-tag evilmi-javascript-jump)))) '(js-mode js2-mode js3-mode javascript-mode)) ;; Html @@ -147,9 +145,15 @@ (autoload 'evilmi-script-jump "evil-matchit-script" nil) (mapc (lambda (mode) (plist-put evilmi-plugins mode '((evilmi-simple-get-tag evilmi-simple-jump) - (evilmi-script-get-tag evilmi-script-jump))) - ) - '(lua-mode ruby-mode vimrc-mode)) + (evilmi-script-get-tag evilmi-script-jump)))) + '(lua-mode vimrc-mode)) + + (autoload 'evilmi-ruby-get-tag "evil-matchit-ruby" nil) + (autoload 'evilmi-ruby-jump "evil-matchit-ruby" nil) + (mapc (lambda (mode) + (plist-put evilmi-plugins mode '((evilmi-simple-get-tag evilmi-simple-jump) + (evilmi-ruby-get-tag evilmi-ruby-jump)))) + '(ruby-mode)) ) (evil-define-text-object evilmi-text-object (&optional NUM begin end type) @@ -181,7 +185,7 @@ )) ;;;###autoload -(defun evilmi-version() (interactive) (message "1.3.2")) +(defun evilmi-version() (interactive) (message "1.3.3")) ;;;###autoload (define-minor-mode evil-matchit-mode