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