branch: elpa/evil-matchit
commit 43a626541dc2e02ddd7587da3eadcb61adc772f7
Author: Chen Bin <[email protected]>
Commit: Chen Bin <[email protected]>
support script language, v1.1.0
- ruby
- lua
- bash
- vimrc
---
README.org | 2 +-
evil-matchit-pkg.el | 2 +-
evil-matchit-script.el | 221 +++++++++++++++++++++++++++++++++++++++++++++++++
evil-matchit.el | 36 +++++++-
pkg.sh | 2 +-
5 files changed, 257 insertions(+), 6 deletions(-)
diff --git a/README.org b/README.org
index 7b6eb4e39a..f2478a4b0a 100644
--- a/README.org
+++ b/README.org
@@ -1,4 +1,4 @@
-* evil-matchit (current version 1.0.2)
+* evil-matchit (current version 1.1.0)
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 b4921f932b..1287bbcf78 100644
--- a/evil-matchit-pkg.el
+++ b/evil-matchit-pkg.el
@@ -1,2 +1,2 @@
-(define-package "evil-matchit" "1.0.2"
+(define-package "evil-matchit" "1.1.0"
"Vim matchit ported into Emacs (requires EVIL)")
diff --git a/evil-matchit-script.el b/evil-matchit-script.el
new file mode 100644
index 0000000000..b1618bed90
--- /dev/null
+++ b/evil-matchit-script.el
@@ -0,0 +1,221 @@
+;;; evil-matchit-script.el ---script (ruby/lua) plugin of evil-matchit
+
+;; Copyright (C) 2013 Chen Bin <[email protected]>
+
+;; Author: Chen Bin <[email protected]>
+
+;; 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:
+
+(require 'evil-matchit)
+
+;; ruby/bash/lua/vimrc
+(defvar evilmi--script-match-tags
+ '((("unless" "if") ("elif" "elsif" "elseif" "else") ( "end" "fi" "endif"))
+ ("begin" ("rescue" "ensure") "end")
+ ("case" ("when" "else") ("esac" "end"))
+ (("fun!" "function!" "class" "def" "while" "function" "do") () ("end"
"endfun" "endfunction"))
+ ("repeat" () "until")
+ )
+ "the table we look up matched tags"
+ )
+
+(defun evilmi--script-get-tag-info (tag)
+ "return (row column)"
+ (let (rlt elems elem tag-type
+ found i j)
+
+ (setq i 0)
+ (while (and (< i (length evilmi--script-match-tags)) (not found))
+ (setq elems (nth i evilmi--script-match-tags))
+ (setq j 0)
+ (while (and (not found) (< j (length elems)))
+ (setq elem (nth j elems))
+ (cond
+ ((stringp elem)
+ (if (string= tag elem)
+ (setq found t)
+ ))
+ ((listp elem)
+ (if (member tag elem)
+ (setq found t)
+ ))
+ )
+ (if (not found) (setq j (1+ j)))
+ )
+ (if (not found) (setq i (1+ i)))
+ )
+ (if found
+ (setq rlt (list i j))
+ )
+ rlt
+ )
+ )
+
+(defun evilmi--script-extract-keyword (cur-line)
+ "extract keyword from cur-line"
+ (let (keyword
+ (regexp "^[ \t]*\\([a-z]+\!?\\)\\( .*\\| *\\)$")
+ (regexp-do "^.* \\(do\\) |[a-z0-9A-Z,|]+|$")
+ )
+ (if (string-match regexp cur-line)
+ (setq keyword (match-string 1 cur-line))
+ )
+
+ (if (evilmi--member keyword evilmi--script-match-tags) keyword
+ (when (string-match regexp-do cur-line)
+ (setq keyword (match-string 1 cur-line))
+ (if (evilmi--member keyword evilmi--script-match-tags) keyword)
+ )
+ )
+ )
+ )
+
+;;;###autoload
+(defun evilmi-script-get-tag ()
+ (let (rlt
+ keyword
+ (cur-line (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position)))
+ tag-info)
+ (when (setq keyword (evilmi--script-extract-keyword cur-line))
+ ;; since we mixed ruby and lua mode here
+ ;; maybe we should be strict at the keyword
+ (if (setq tag-info (evilmi--script-get-tag-info keyword))
+ ;; 0 - open tag; 1 - middle tag; 2 - close tag;
+ (setq rlt (list
+ (if (= 2 (nth 1 tag-info))
+ (line-end-position)
+ (line-beginning-position))
+ tag-info))
+ )
+ )
+ rlt
+ ))
+
+;;;###autoload
+(defun evilmi-script-jump (rlt NUM)
+ (let ((orig-tag-type (nth 1 (nth 1 rlt)))
+ cur-tag-type
+ (level 1)
+ (cur-line (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position)))
+ keyword
+ found
+ where-to-jump-in-theory
+ )
+
+ (while (not found)
+ (forward-line (if (= orig-tag-type 2) -1 1))
+ (setq cur-line (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position))
+ )
+
+ (setq keyword (evilmi--script-extract-keyword cur-line))
+ (when keyword
+ (setq cur-tag-type (nth 1 (evilmi--script-get-tag-info keyword)))
+
+ ;; key algorithm
+ (cond
+ ;; handle open tag
+ ;; open (0) -> mid (1) found when level is one else ignore
+ ((and (= orig-tag-type 0) (= cur-tag-type 1))
+ (when (= 1 level)
+ (back-to-indentation)
+ (setq where-to-jump-in-theory (1- (line-beginning-position)))
+ (setq found t)
+ )
+ )
+ ;; open (0) -> closed (2) found when level is zero, level--
+ ((and (= orig-tag-type 0) (= cur-tag-type 2))
+ (setq level (1- level))
+ (when (= 0 level)
+ (goto-char (line-end-position))
+ (setq where-to-jump-in-theory (line-end-position))
+ (setq found t)
+ )
+ )
+ ;; open (0) -> open (0) level++
+ ((and (= orig-tag-type 0) (= cur-tag-type 0))
+ (setq level (1+ level))
+ )
+
+ ;; now handle mid tag
+ ;; mid (1) -> mid (1) found when level is zero else ignore
+ ((and (= orig-tag-type 1) (= cur-tag-type 1))
+ (when (= 1 level)
+ (back-to-indentation)
+ (setq where-to-jump-in-theory (1- (line-beginning-position)))
+ (setq found t)
+ )
+ )
+ ;; mid (1) -> closed (2) found when level is zero, level --
+ ((and (= orig-tag-type 1) (= cur-tag-type 2))
+ (setq level (1- level))
+ (when (= 0 level)
+ (goto-char (line-end-position))
+ (setq where-to-jump-in-theory (line-end-position))
+ (setq found t)
+ )
+ )
+ ;; mid (1) -> open (0) level++
+ ((and (= orig-tag-type 1) (= cur-tag-type 0))
+ (setq level (1+ level))
+ )
+
+ ;; now handle closed tag
+ ;; closed (2) -> mid (1) ignore,impossible
+ ((and (= orig-tag-type 2) (= cur-tag-type 1))
+ (message "impossible to be here")
+ )
+ ;; closed (2) -> closed (2) level++
+ ((and (= orig-tag-type 2) (= cur-tag-type 2))
+ (setq level (1+ level))
+ )
+ ;; closed (2) -> open (0) found when level is zero, level--
+ ((and (= orig-tag-type 2) (= cur-tag-type 0))
+ (setq level (1- level))
+ (when (= 0 level)
+ (setq where-to-jump-in-theory (line-beginning-position))
+ (back-to-indentation)
+ (setq found t)
+ )
+ )
+ (t (message "why here?"))
+ )
+ )
+
+ ;; we will stop at end or beginning of buffer anyway
+ (if (or (= (line-end-position) (point-max))
+ (= (line-beginning-position) (point-min))
+ )
+ (setq found t)
+ )
+ )
+ where-to-jump-in-theory
+ )
+ )
+
+(provide 'evil-matchit-script)
\ No newline at end of file
diff --git a/evil-matchit.el b/evil-matchit.el
index 423512272d..f27ada90c9 100644
--- a/evil-matchit.el
+++ b/evil-matchit.el
@@ -4,7 +4,7 @@
;; Author: Chen Bin <[email protected]>
;; URL: http://github.com/redguardtoo/evil-matchit
-;; Version: 1.0.2
+;; Version: 1.1.0
;; Keywords: matchit vim evil
;; Package-Requires: ((evil "1.0.7"))
;;
@@ -43,6 +43,27 @@
((evilmi-simple-get-tag evilmi-simple-jump))
))
+(defun evilmi--member (k l)
+ (let (rlt)
+ (cond
+ ((not l) nil)
+ ((stringp (car l))
+ (if (string= k (car l)) t
+ (evilmi--member k (cdr l))
+ )
+ )
+ ((listp (car l))
+ (setq rlt (evilmi--member k (car l)))
+ (if rlt rlt (evilmi--member k (cdr l)))
+ )
+ (t
+ ;; just ignore first element
+ (evilmi--member k (cdr l))
+ )
+ )
+ )
+ )
+
(defun evilmi--operate-on-item (NUM &optional FUNC)
(let (plugin
rlt
@@ -79,7 +100,7 @@
(push-mark (nth 0 rlt) t t)
)
-(defun evilmi--init-plugins ()
+(defun evilmi-init-plugins ()
(interactive)
;; html
(autoload 'evilmi-html-get-tag "evil-matchit-html" nil t)
@@ -108,6 +129,15 @@
(plist-put evilmi-plugins mode '((evilmi-c-get-tag evilmi-c-jump)))
)
'(c-mode c++-mode java-mode js-mode js2-mode javascript-mode perl-mode
cperl-mode))
+
+ ;; script language (bash/lua/ruby)
+ (autoload 'evilmi-script-get-tag "evil-matchit-script" nil t)
+ (autoload 'evilmi-script-jump "evil-matchit-script" nil t)
+ (mapc (lambda (mode)
+ (plist-put evilmi-plugins mode '((evilmi-simple-get-tag
evilmi-simple-jump)
+ (evilmi-script-get-tag
evilmi-script-jump)))
+ )
+ '(lua-mode sh-mode ruby-mode vimrc-mode))
)
;;;###autoload
@@ -152,7 +182,7 @@
)
)
(evil-normalize-keymaps)
- (evilmi--init-plugins)
+ (evilmi-init-plugins)
)
;;;###autoload
diff --git a/pkg.sh b/pkg.sh
index f6d89f7370..7d9a8c9f41 100755
--- a/pkg.sh
+++ b/pkg.sh
@@ -1,5 +1,5 @@
#!/bin/bash
-pkg=evil-matchit-1.0.2
+pkg=evil-matchit-1.1.0
mkdir $pkg
cp README.org $pkg
cp *.el $pkg