branch: elpa/evil-matchit
commit 3c98cf064fb3b12a632bca519508ae5d64b974fb
Author: Chen Bin <[email protected]>
Commit: Chen Bin <[email protected]>

    new framework v1.0.0
    
    - support plugins
    - latex-mode
    - python-mode
---
 README.org             |  73 +++++++++++-
 evil-matchit-html.el   | 102 +++++++++++++++++
 evil-matchit-latex.el  |  70 ++++++++++++
 evil-matchit-pkg.el    |   2 +-
 evil-matchit-python.el | 293 +++++++++++++++++++++++++++++++++++++++++++++++++
 evil-matchit.el        | 239 +++++++++++++++-------------------------
 pkg.sh                 |   2 +-
 7 files changed, 623 insertions(+), 158 deletions(-)

diff --git a/README.org b/README.org
index cf3f5213e0..199e184f4d 100644
--- a/README.org
+++ b/README.org
@@ -1,4 +1,4 @@
-* evil-matchit (current version 0.0.7)
+* evil-matchit (current version 1.0.0)
 
 Vim [[http://www.vim.org/scripts/script.php?script_id=39][matchit.vim]] by 
Benji Fisher ported into Emacs.
 
@@ -11,6 +11,13 @@ Alternatively, you can enable evil-matchit-mode along a 
major mode by adding `tu
 
 *This package uses Evil as its vi layer*!
 
+* Why use evil-matchit 
+- No learning curve. You only need press "%" to jump between matched tags. 
That's all!
+- Powerful. For example, if you mix jsp, freemarker, html, jquery template or 
any wierd syntax in one file. It still work perfectly.
+- Extendable. You can write a plugin for it in 5 minutes.
+- Many languages will be supported soon.
+- I will provide long term support for it (say next 10 years) because Emacs is 
my last editor.
+
 * Install
 evil-matchit is already uploaded to [[http://marmalade-repo.org/]]. So the 
best way to install it is using Emacs' package manager.
 
@@ -25,13 +32,26 @@ All commands support numeric argument like "3%", "5,si" or 
"9,di"
 
 * Advanced set up
 ** Support more major modes
-html tags are automatically supported in nxml-mode, web-mode, html-mode and 
nxhtml-mode.
+Let's use html tag matching as an example.
+
+html tags are automatically supported in sgml-mode, nxml-mode, web-mode, 
html-mode and nxhtml-mode,.
+
+Let's say you want a new major-mode "my-mode" to do the html tag matching. 
Easy. Please add below line into your ~/.emacs:
 
-Add below line into ~/.emacs to support more major modes:
 #+BEGIN_SRC elisp
-(setq evilmi-html-major-modes '(nxml-mode web-mode html-mode nxhtml-mode 
php-mode jsp-mode))
+(plist-put evilmi-plugins my-mode '((evilmi-html-get-tag evilmi-html-jump)))
 #+END_SRC
 
+Further explanation: "evilmi-html-get-tag" and "evilmi-html-jump" are existing 
APIs which are defined in evil-matchit-python.el. The above line means that in 
my-mode, use "evilmi-html-get-tag" to find open/closed tag in current line and 
use "evilmi-html-jump" to jump to matched closed/open tag.
+
+** mixed languages in one html template file can be supported
+Say you embed python language in a html file. You can match both html tags and 
python statement by inserting below code into your ~/.emacs:
+#+BEGIN_SRC elisp
+(plist-put evilmi-plugins web-mode
+           '((evilmi-python-get-tag evilmi-python-jump)
+             (evilmi-html-get-tag evilmi-html-jump)
+             ))
+#+END_SRC
 ** re-define keybinding
 You can define your own key bindings instead using evil-matchit default key 
binding.
 
@@ -47,5 +67,50 @@ All you need to do is define function 
evilmi-customize-keybinding before turning
 (global-evil-matchit-mode 1)
 #+END_SRC
 
+* Developer guide
+** Writing elisp code to support a new language
+Simple. All you need to is define two functions and tell evil-matchit in which 
major-mode they should be used.
+
+Here is a complete sample:
+#+BEGIN_SRC elisp
+;; detect tag in current line and return the result in variable rlt
+;; the rlt will be used by evilmi-mylanguage-jump as the first
+;; parameter.
+;; if not tag found, the rlt SHOULD be nil
+;;
+;; @return the data to be used by evilmi-mylanguage-jump
+(defun evilmi-mylanguage-find-tag ()
+  (let (rlt )
+    (setq rlt '("anything-you-like" "anything-you-like" "anything-you-like")
+    rlt
+    )
+  )
+
+;; @parama rlt result from evilmi-mylanguage-find-tag
+;; @param NUM numeric argument when user press "%" to match tag
+;; @return the matching tag position in theory, useful only for
+;;         selecting or deleting text between matching tags and tags
+(defun evilmi-mylanguage-jump (rlt NUM)
+  (message "rlt=%s" rlt)
+  ;; just a sample, the data type of rlt is totally controlled by you
+  (goto-char (nth 0 rlt))
+  )
+
+;; tell evil-matchit how to use above functions
+(plist-put evilmi-plugins mylanguage-mode
+           '((evilmi-mylanguage-get-tag evilmi-mylanguage-jump)
+             ))
+#+END_SRC
+
+Place above code into your ~/.emacs, after the line "(global-evil-matchit-mode 
1)"
+** Share your code to the world
+Tweak your code a little bit to make it a plugin and ask me to merge it into 
main stream.
+
+Please check "evil-matchit-latext.el" for general guidance on naming 
convention and other tech details of plugin.
+
+Here are some suggestions about quality of plugin:
+- minimum dependency. For example, if your plugin for html template files are 
just some web-mode API wrapper, it will break when user don't have web-mode
+- support emacs 23
+- performance is the first priority
 * Contact me
 You can report bugs at [[https://github.com/redguardtoo/evil-matchit]].
diff --git a/evil-matchit-html.el b/evil-matchit-html.el
new file mode 100644
index 0000000000..c487065070
--- /dev/null
+++ b/evil-matchit-html.el
@@ -0,0 +1,102 @@
+;;; evil-matchit-html.el ---html 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)
+
+(autoload 'sgml-skip-tag-backward "sgml-mode" nil t)
+(autoload 'sgml-skip-tag-forward "sgml-mode" nil t)
+
+;;;###autoload
+(defun evilmi-html-get-tag ()
+  (let ((b (line-beginning-position))
+        (e (line-end-position))
+        (html-tag-char (string-to-char "<"))
+        (char (following-char))
+        (p (point))
+        (found_tag -1)
+        (rlt nil)
+        )
+
+    (save-excursion
+      ;; search backward
+      (if (not (= char html-tag-char))
+          (while (and (<= b (point)) (not (= char 60)))
+            (setq char (following-char))
+            (setq p (point))
+            (backward-char)
+            )
+        )
+      ;; search forward
+      (if (not (= char html-tag-char))
+          (save-excursion
+            (while (and (>= e (point)) (not (= char 60)))
+              (setq char (following-char))
+              (setq p (point))
+              (forward-char)
+              )
+            )
+        )
+
+      ;; is end tag?
+      (when (and (= char html-tag-char) (< p e))
+        (goto-char p)
+        (forward-char)
+        (if (= (following-char) 47)
+            (progn
+              ;; </
+              (skip-chars-forward "^>")
+              (forward-char)
+              (setq p (point))
+              (setq found_tag 1)
+              )
+          (progn
+            ;; < , looks fine
+            (backward-char)
+            (setq found_tag 0)
+            )
+          )
+        )
+      )
+    (setq rlt (list p found_tag ""))
+    rlt
+    )
+  )
+
+;;;###autoload
+(defun evilmi-html-jump (rlt NUM)
+  (let ((p (nth 0 rlt))
+        (tag-type (nth 1 rlt))
+        (tag-keyword (nth 2 rlt))
+        )
+
+    (if (=  1 tag-type) (sgml-skip-tag-backward NUM))
+    (if (=  0 tag-type) (sgml-skip-tag-forward NUM))
+    )
+  )
+
+(provide 'evil-matchit-html)
diff --git a/evil-matchit-latex.el b/evil-matchit-latex.el
new file mode 100644
index 0000000000..89a775fbc4
--- /dev/null
+++ b/evil-matchit-latex.el
@@ -0,0 +1,70 @@
+;;; evil-matchit-latex.el ---latex 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)
+
+(autoload 'LaTeX-find-matching-begin "latex-mode" nil t)
+(autoload 'LaTeX-find-matching-end "latex-mode" nil t)
+
+;;;###autoload
+(defun evilmi-latex-get-tag ()
+  (let (rlt
+        (regexp (concat (regexp-quote "\\") "\\(begin\\|end\\)\\b"))
+        keyword
+        p
+        )
+    (skip-chars-backward "a-zA-Z \t{}")
+    ;; move cursor to the beginning of tag
+    (unless (bolp)
+      (backward-char 1)
+      )
+    (re-search-forward regexp (line-end-position) t)
+    (setq keyword (match-string 1))
+    (setq rlt (list p
+                    (if (string= keyword "begin")
+                        0
+                      (if (string= keyword "end")
+                          1
+                        -1))
+                    )
+          )
+    rlt
+    )
+  )
+
+;;;###autoload
+(defun evilmi-latex-jump (rlt NUM)
+  (let ((p (nth 0 rlt))
+        (tag-type (nth 1 rlt))
+        )
+    (if (=  1 tag-type) (LaTeX-find-matching-begin))
+    (if (=  0 tag-type) (LaTeX-find-matching-end))
+    )
+  )
+
+(provide 'evil-matchit-latex)
\ No newline at end of file
diff --git a/evil-matchit-pkg.el b/evil-matchit-pkg.el
index 1e50b163bd..ff8578f832 100644
--- a/evil-matchit-pkg.el
+++ b/evil-matchit-pkg.el
@@ -1,2 +1,2 @@
-(define-package "evil-matchit" "0.0.7"
+(define-package "evil-matchit" "1.0.0"
                 "Vim matchit ported into Emacs (requires EVIL)")
diff --git a/evil-matchit-python.el b/evil-matchit-python.el
new file mode 100644
index 0000000000..c22867f22e
--- /dev/null
+++ b/evil-matchit-python.el
@@ -0,0 +1,293 @@
+;;; evil-matchit-python.el ---python 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)
+
+;; @return number of indent
+(defun evilmi--python-calculate-indent (line)
+  (let (prefix )
+    (if (string-match "^[ \t]*$" line)
+        ;; empty line
+        999
+      (if (string-match "^\\([ \t]+\\).*$" line)
+          (progn
+            (setq prefix (match-string 1 line))
+            ;; char code of tab is 9
+            (if (= (elt prefix 0) 9)
+                (length prefix)
+              (/ (length prefix) 4)
+              )
+            )
+        0
+        )
+      )
+    )
+  )
+
+;; jump from else to if, jump from finally to try
+;; only python need this hack, a wierd language
+(defun evilmi--python-move-to-first-open-tag (cur-indent)
+  (let (out-of-loop
+        keyword
+        where-to-go
+        regexp
+        (cur-line (buffer-substring-no-properties
+                   (line-beginning-position)
+                   (line-end-position)))
+        )
+
+    ;; extract keyword from current line
+    (if (string-match "^[ \t]*\\([a-z]+\\) *.*:$" cur-line)
+        (setq keyword (match-string 1 cur-line))
+      )
+
+    (cond
+     ((string= keyword "else")
+      (setq regexp "^[ \t]*\\(if\\) *.*:$")
+      )
+     ((or (string= keyword "finally") (string= keyword "except"))
+       (setq regexp "^[ \t]*\\(try\\) *.*:$")
+       )
+     )
+
+    (when regexp
+      (save-excursion
+        (while (not out-of-loop)
+          (forward-line -1)
+          (setq cur-line (buffer-substring-no-properties
+                          (line-beginning-position)
+                          (line-end-position)))
+
+          (when (and (= cur-indent (evilmi--python-calculate-indent cur-line))
+                     (string-match regexp cur-line)
+                     )
+            (setq where-to-go (line-beginning-position))
+            (setq out-of-loop t)
+            )
+
+          ;; if it's first line, we need get out of loop
+          (if (= (point-min) (line-beginning-position))
+              (setq out-of-loop t)
+            )
+          )
+        )
+      (when where-to-go
+        (goto-char where-to-go)
+        (skip-chars-forward " \t")
+        )
+      )
+    )
+  )
+
+(defun evilmi--python-move-to-next-open-tag (keyword cur-indent)
+  (let (out-of-loop
+        where-to-go
+        regexp
+        cur-line
+        )
+    (cond
+     ((string= keyword "try")
+      (setq regexp "^[ \t]*\\(except\\) *.*:$")
+      )
+     ((string= keyword "except")
+      (setq regexp "^[ \t]*\\(except\\|finally\\) *.*:$")
+      )
+     ( (or (string= keyword "elif") (string= keyword "if"))
+       (setq regexp "^[ \t]*\\(elif\\|else\\) *.*:$")
+       )
+     )
+
+    (save-excursion
+      (while (not out-of-loop)
+        (forward-line)
+        (setq cur-line (buffer-substring-no-properties
+                        (line-beginning-position)
+                        (line-end-position)))
+
+        (when (= cur-indent (evilmi--python-calculate-indent cur-line))
+          (if (string-match regexp cur-line)
+              (setq where-to-go (line-beginning-position))
+            )
+          (setq out-of-loop t)
+          )
+        ;; if it's last line, we need get out of loop
+        (if (= (point-max) (line-end-position))
+            (setq out-of-loop t)
+          )
+        )
+      )
+    (when where-to-go
+      (goto-char where-to-go)
+      (skip-chars-forward " \t")
+      )
+    )
+  )
+
+;;;###autoload
+(defun evilmi-python-get-tag ()
+  (let (rlt
+        (regexp "^[ \t]*\\([a-z]+\\) *.*:$")
+        (cur-line (buffer-substring-no-properties
+                   (line-beginning-position)
+                   (line-end-position)))
+        cur-indent
+        (tag-type 0)
+        keyword
+        p
+        cur-indent
+        )
+
+    (setq cur-indent (evilmi--python-calculate-indent cur-line))
+    ;; move cursor to the beginning of line
+    (if (string-match regexp cur-line)
+        ;; open tag
+        (progn
+          (setq keyword (match-string 1 cur-line))
+          (setq p (line-beginning-position))
+          (setq tag-type 0)
+          )
+      ;; closed tag
+      (progn
+        (setq keyword "")
+        (setq tag-type 1)
+        (setq p (line-end-position))
+        (save-excursion
+          ;; find the limit end from current line
+          (while (and (>= (evilmi--python-calculate-indent
+                           (buffer-substring-no-properties
+                            (line-beginning-position) (line-end-position))) 
cur-indent)
+                      (not (= p (point-max)))
+                      )
+            (forward-line 1)
+            (setq p (line-end-position))
+            )
+          ;; scroll back, skip all the empty lines
+          (let ((scrolling-back t)
+                my-indent
+                )
+            (while scrolling-back
+              (setq my-indent (evilmi--python-calculate-indent
+                               (buffer-substring-no-properties
+                                (line-beginning-position) 
(line-end-position))))
+
+              (if (or (= my-indent 999)
+                      (< my-indent cur-indent)
+                      (= (line-beginning-position) (point-min))
+                      )
+                  (forward-line -1)
+                (setq scrolling-back nil)
+                )
+              )
+            )
+          (setq p (line-end-position))
+          )
+        )
+      )
+
+    (setq rlt (list p tag-type keyword))
+    rlt
+    )
+  )
+
+;;;###autoload
+(defun evilmi-python-jump (rlt NUM)
+  (let ((p (nth 0 rlt))
+        (tag-type (nth 1 rlt))
+        (keyword (nth 2 rlt))
+        (cur-line (buffer-substring-no-properties
+                   (line-beginning-position)
+                   (line-end-position)))
+        cur-indent
+        dendent
+        where-to-jump-in-theory
+        )
+    (setq cur-indent (evilmi--python-calculate-indent cur-line))
+
+    ;; start from closed tag
+    (cond
+     ((=  1 tag-type)
+      (goto-char p)
+      ;; jump to open tag
+      (while (not dendent)
+        (forward-line -1)
+        ;; first line
+        (setq cur-line (buffer-substring-no-properties
+                        (line-beginning-position)
+                        (line-end-position)))
+
+        ;; skip empty lines
+        (when (not (string-match "^[ \t]*$" cur-line))
+          (if (< (evilmi--python-calculate-indent cur-line) cur-indent)
+              (progn
+                (setq dendent t)
+                (skip-chars-forward " \t")
+                (setq dendent t)
+                (evilmi--python-move-to-first-open-tag (1- cur-indent))
+                (setq where-to-jump-in-theory (point))
+                )
+            )
+          )
+        )
+      )
+
+     ;; start from open tag
+     ((=  0 tag-type)
+      ;; jump to closed tag
+      (while (not dendent)
+        (forward-line)
+        (setq cur-line (buffer-substring-no-properties
+                        (line-beginning-position)
+                        (line-end-position)))
+
+        ;; just skip empty line
+        (when (not (string-match "^[ \t]*$" cur-line))
+          (if (<= (evilmi--python-calculate-indent cur-line) cur-indent)
+              (progn
+                (setq dendent t)
+                )
+            (progn
+              ;; record the latest indented line info
+              (setq where-to-jump-in-theory (line-end-position))
+              )
+            )
+          )
+        ;; last line
+        (if (= (point-max) (line-end-position)) (setq dendent t))
+        )
+
+      (if where-to-jump-in-theory (goto-char where-to-jump-in-theory))
+
+      ;; TODO move the cursor to the next line started with keyword
+      (evilmi--python-move-to-next-open-tag keyword cur-indent)
+      )
+     )
+    where-to-jump-in-theory
+    )
+  )
+
+(provide 'evil-matchit-python)
diff --git a/evil-matchit.el b/evil-matchit.el
index 278129debd..757778a2cd 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: 0.0.7
+;; Version: 1.0.0
 ;; Keywords: matchit vim evil
 ;; Package-Requires: ((evil "1.0.7"))
 ;;
@@ -38,187 +38,95 @@
 ;;; Code:
 
 (require 'evil)
-(require 'sgml-mode)
 
-(defvar evilmi-html-major-modes
-  '(nxml-mode
-    web-mode
-    html-mode
-    nxhtml-mode
-    )
-  "major modes containing html tags")
-
-(defun evilmi--find-single-char-tag ()
-  )
-
-;; {}()
-;; @return (list found_tag is_end_tag)
-(defun evilmi--at-single-char-tag ()
-  (let ((char (following-char))
-        (found_tag nil)
-        (is_end_tag nil))
-
-    (if (= char (string-to-char "{")) (setq found_tag t) (setq is_end_tag nil))
-    (if (= char (string-to-char "}")) (setq found_tag t) (setq is_end_tag t))
-    (if (= char (string-to-char "(")) (setq found_tag t) (setq is_end_tag nil))
-    (if (= char (string-to-char ")")) (setq found_tag t) (setq is_end_tag t))
+(defvar evilmi-plugins '(emacs-lisp-mode
+                         ((evilmi-simple-get-tag evilmi-simple-jump))
+                         ))
 
-    (list found_tag is_end_tag)
-    )
-  )
-
-;; @return (list position_first_char found_tag is_end_tag)
-(defun evilmi--find-lt-or-gt-char-at-current-line ()
-  (let ((b (line-beginning-position))
-        (e (line-end-position))
-        (html-tag-char (string-to-char "<"))
-        (char (following-char))
-        (p (point))
-        (found_tag nil)
-        (is_end_tag nil)
-        )
-
-    (save-excursion
-      ;; search backward
-      (if (not (= char html-tag-char))
-          (while (and (<= b (point)) (not (= char 60)))
-            (setq char (following-char))
-            (setq p (point))
-            (backward-char)
-            )
-        )
-      ;; search forward
-      (if (not (= char html-tag-char))
-          (save-excursion
-            (while (and (>= e (point)) (not (= char 60)))
-              (setq char (following-char))
-              (setq p (point))
-              (forward-char)
-              )
-            )
+(defun evilmi--operate-on-item (NUM &optional FUNC)
+  (let (plugin
+        rlt
+        (jumped nil)
+        where-to-jump-in-theory
         )
 
-      ;; is end tag?
-      (when (and (= char html-tag-char) (< p e))
-        (goto-char p)
-        (forward-char)
-        (if (= (following-char) 47)
-            (progn
-              ;; </
-              (skip-chars-forward "^>")
-              (forward-char)
-              (setq p (point))
-              (setq found_tag t)
-              (setq is_end_tag t)
-              )
-          (progn
-            ;; < , looks fine
-            (backward-char)
-            (setq found_tag t)
-            )
-          )
-        )
-      )
-    (list p found_tag is_end_tag)
-    ))
-
-
-(defun evilmi--search-next-tag (NUM)
-  (let ((c (following-char))
-        )
-    (if (> NUM 0)
-        (cond
-         ((= c (string-to-char "}"))
-          (search-forward "{")
-          (backward-char)
-          (= (following-char) (string-to-char "{"))
-          )
-         ((= c (string-to-char "{"))
-          (search-backward "}")
-          (= (following-char) (string-to-char "}"))
-          )
-         ((= c (string-to-char ")"))
-          (search-forward "(")
-          (backward-char)
-          (= (following-char) (string-to-char "("))
-          )
-         ((= c (string-to-char "("))
-          (search-backward ")")
-          (= (following-char) (string-to-char ")"))
-          )
+    (setq plugin (plist-get evilmi-plugins major-mode))
+
+    (if plugin
+        (mapc
+         (lambda (elem)
+           (setq rlt (funcall (nth 0 elem)))
+           (when (and rlt (not jumped))
+             ;; before jump, we may need some operation
+             (if FUNC (funcall FUNC rlt))
+             ;; jump now
+             (setq where-to-jump-in-theory (funcall (nth 1 elem) rlt NUM))
+             ;; jump only once if the jump is successful
+             (setq jumped t)
+             )
+           )
+         plugin
          )
-      nil
       )
+    (if (not jumped)
+        (evilmi-simple-jump nil NUM)
+        )
+    where-to-jump-in-theory
     )
   )
 
-(defun evilmi--operate-on-item (NUM fn)
-  (let ((rlt (evilmi--find-lt-or-gt-char-at-current-line))
-        (test-single-char-tag (evilmi--at-single-char-tag))
-        (single-char-tag-exists-under-cursor)
-        )
-    (setq single-char-tag-exists-under-cursor (nth 0 test-single-char-tag))
-    (if (and (memq major-mode evilmi-html-major-modes)
-             (not single-char-tag-exists-under-cursor)
-             )
-        ;; prepare to jump
-        (when (nth 1 rlt)
-          (if (nth 2 rlt)
-              ;; it's the end tag
-              (progn
-                (funcall fn (nth 0 rlt))
-                (sgml-skip-tag-backward NUM)
-                )
-            ;; open tag
-            (progn
-              (funcall fn (nth 0 rlt))
-              (sgml-skip-tag-forward NUM)
-              )
-            )
-          )
-      ;; just use evil-jump item
-      (progn
-        ;; single character tag either in html file or not
-        ;; evil has its own API, so normal Emacs API may not work
-        (if (eq fn 'evilmi--push-mark)
-            (evil-visual-char)
-          )
-        (while (and (> NUM 0) single-char-tag-exists-under-cursor)
-          (evil-jump-item)
-          (setq NUM (1- NUM))
+(defun evilmi--push-mark (rlt)
+  (push-mark (nth 0 rlt) t t)
+  )
 
-          ;; next action depends on current char under cursor
-          (setq single-char-tag-exists-under-cursor (evilmi--search-next-tag 
NUM))
+(defun evilmi--init-plugins ()
+  ;; html
+  (autoload 'evilmi-html-get-tag "evil-matchit-html" nil t)
+  (autoload 'evilmi-html-jump "evil-matchit-html" nil t)
+  (mapc (lambda (mode)
+          (plist-put evilmi-plugins mode '((evilmi-simple-get-tag 
evilmi-simple-jump)
+                                           (evilmi-html-get-tag 
evilmi-html-jump)))
           )
-        )
-      )
-    )
-  )
+        '(web-mode html-mode nxml-mode nxhtml-mode sgml-mode))
+
+  ;; latex
+  (autoload 'evilmi-latex-get-tag "evil-matchit-latex" nil t)
+  (autoload 'evilmi-latex-jump "evil-matchit-latex" nil t)
+  (plist-put evilmi-plugins 'latex-mode '((evilmi-latex-get-tag 
evilmi-latex-jump)))
 
-(defun evilmi--push-mark (p)
-  (push-mark p t t)
+  ;; python
+  (autoload 'evilmi-python-get-tag "evil-matchit-python" nil t)
+  (autoload 'evilmi-python-jump "evil-matchit-python" nil t)
+  (plist-put evilmi-plugins 'python-mode '((evilmi-python-get-tag 
evilmi-python-jump)))
   )
 
 ;;;###autoload
 (defun evilmi-jump-items (&optional NUM)
   "jump between item/tag(s)"
   (interactive "p")
-  (evilmi--operate-on-item NUM 'goto-char)
+  (evilmi--operate-on-item NUM)
   )
 
 ;;;###autoload
 (defun evilmi-select-items (&optional NUM)
   "select item/tag(s)"
   (interactive "p")
-  (evilmi--operate-on-item NUM 'evilmi--push-mark)
+  (let (where-to-jump-in-theory )
+    (setq where-to-jump-in-theory (evilmi--operate-on-item NUM 
'evilmi--push-mark))
+    (if where-to-jump-in-theory (goto-char where-to-jump-in-theory))
+    )
   )
 
 ;;;###autoload
 (defun evilmi-delete-items (&optional NUM)
   "delete item/tag(s)"
   (interactive "p")
-  (evilmi--operate-on-item NUM 'evilmi--push-mark)
-  (kill-region (region-beginning) (region-end))
+  (let (where-to-jump-in-theory )
+    (setq where-to-jump-in-theory (evilmi--operate-on-item NUM 
'evilmi--push-mark))
+    (if where-to-jump-in-theory (goto-char where-to-jump-in-theory))
+    (kill-region (region-beginning) (region-end))
+    )
+  ;; need some hook here
   )
 
 ;;;###autoload
@@ -234,6 +142,7 @@
       )
     )
   (evil-normalize-keymaps)
+  (evilmi--init-plugins)
   )
 
 ;;;###autoload
@@ -251,7 +160,33 @@
   evil-matchit-mode turn-on-evil-matchit-mode
   "Global minor mode to emulate matchit.vim")
 
+;; @return (list position-first-char tag-type tag-keyword)
+
+;; {{ simple find/jump
+;; @return (list position-first-char tag-type tag-keyword) or nil
+(defun evilmi-simple-get-tag ()
+  (interactive)
+  (let ((char (following-char))
+        (tag-type -1)
+        (tag-keyword "")
+        (rlt nil)
+        )
 
+    (if (memq char (string-to-list "{[("))
+        (setq rlt (list (point) 0 (char-to-string char)))
+      )
+    (if (memq char (string-to-list "}])"))
+        (setq rlt (list (point) 1 (char-to-string char)))
+      )
+    rlt
+    )
+  )
+
+(defun evilmi-simple-jump (rlt NUM)
+  (interactive)
+  (evil-jump-item)
+  )
+;; }}
 
 (provide 'evil-matchit)
 
diff --git a/pkg.sh b/pkg.sh
index ef0d79e164..182d733914 100755
--- a/pkg.sh
+++ b/pkg.sh
@@ -1,5 +1,5 @@
 #!/bin/bash
-pkg=evil-matchit-0.0.7
+pkg=evil-matchit-1.0.0
 mkdir $pkg
 cp README.org $pkg
 cp *.el $pkg

Reply via email to