emacs-elpa-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[nongnu] elpa/evil-matchit ede6382955 206/244: enhance verilog mode


From: ELPA Syncer
Subject: [nongnu] elpa/evil-matchit ede6382955 206/244: enhance verilog mode
Date: Thu, 6 Jan 2022 02:59:02 -0500 (EST)

branch: elpa/evil-matchit
commit ede6382955ef8330f4f765c6536089bd32781052
Author: Chen Bin <chenbin.sh@gmail.com>
Commit: Chen Bin <chenbin.sh@gmail.com>

    enhance verilog mode
---
 evil-matchit-sdk.el         | 16 ++++++++--
 evil-matchit-verilog.el     | 72 +++++++++++++++++++++++++++------------------
 tests/evil-matchit-tests.el | 36 ++++++++++++++++++++++-
 3 files changed, 92 insertions(+), 32 deletions(-)

diff --git a/evil-matchit-sdk.el b/evil-matchit-sdk.el
index 2f42609a95..973c63b672 100644
--- a/evil-matchit-sdk.el
+++ b/evil-matchit-sdk.el
@@ -18,7 +18,7 @@
 (defvar evilmi-sdk-extract-keyword-howtos
   '(("^[ \t]*\\([a-z]+\!?\\)\\( .*\\| *\\)$" 1)
     ("^.* \\(do\\) |[a-z0-9A-Z,|]+|$" 1))
-  "The list of HOWTO on extracting keyword from current line.
+  "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
@@ -321,8 +321,8 @@ Rule is looked up in HOWTOS."
   "Use RLT, NUM, MATCH-TAGS and HOWTOS to jump.
 Return nil if no matching tag found.  Please note (point) is changed
 after calling this function."
-  (let* ((orig-tag-type (nth 1 (nth 1 rlt)))
-         (orig-tag-info (nth 1 rlt))
+  (let* ((orig-tag-info (nth 1 rlt))
+         (orig-tag-type (nth 1 orig-tag-info))
          cur-tag-type
          cur-tag-info
          (level 1)
@@ -458,4 +458,14 @@ after calling this function."
       (setq start (match-end 0)))
     count))
 
+(defun evilmi-sdk-n-lines (n)
+  "Return content of N lines from current position."
+  (unless (and n (> n 1)) (setq n 1))
+  (let* (beg end str)
+    (save-excursion
+      (setq beg (line-beginning-position))
+      (forward-line (1- n))
+      (setq end (line-end-position)))
+    (cons beg end)))
+
 (provide 'evil-matchit-sdk)
diff --git a/evil-matchit-verilog.el b/evil-matchit-verilog.el
index 2f5c8a61db..12548852f5 100644
--- a/evil-matchit-verilog.el
+++ b/evil-matchit-verilog.el
@@ -27,10 +27,9 @@
 ;;
 ;;; Code:
 
-;; OPTIONAL, you don't need SDK to write a plugin for evil-matchit
-;; but SDK do 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 'cl-lib)
 (require 'evil-matchit-sdk)
+(require 'semantic/lex)
 
 ;; {{ Sample verilog code:
 ;; module dff_lab;
@@ -89,41 +88,58 @@
     ("fork" () ("join" "join_any" "join_none") "MONOGAMY")
     ("begin" () "end")
     ("`ifn?def" "`else" "`endif" "MONOGAMY")
-    ("`celldefine" () "`endcelldefine" "MONOGAMY")
-    ))
+    ("`celldefine" () "`endcelldefine" "MONOGAMY")))
+
+(defvar evilmi-verilog-block-begin-prefix
+  "^if\\(n?def\\)?\\|else\\( if\\)?\\|initial\\|always$"
+  "Keyword before the block \"begin\".")
+
+(defun evilmi-verilog-open-bracket-p (token)
+  (let* ((beg (cadr token))
+         (end (cddr token)))
+    (string= "begin" (buffer-substring-no-properties beg end))))
+
+(defun evilmi-verilog-parse-at-point ()
+  (let* ((range (evilmi-sdk-n-lines 3))
+         (tokens (semantic-lex (car range) (cdr range)))
+         info)
+    (when (and tokens (> (length tokens) 1))
+      (let* ((first-token (car tokens))
+             (beg (cadr first-token))
+             (end (cddr first-token))
+             start
+             bracket)
+        (when (and (string-match evilmi-verilog-block-begin-prefix
+                                 (buffer-substring-no-properties beg end))
+                   (setq bracket
+                         (cl-find-if #'evilmi-verilog-open-bracket-p (cdr 
tokens))))
+          (setq start (line-beginning-position))
+          ;; move focus to the "begin"
+          (goto-char (cadr bracket))
+          (setq info (evilmi-sdk-get-tag evilmi-verilog-match-tags
+                                         
evilmi-verilog-extract-keyword-howtos))
+          (setq info (cons start (cdr info))))))
+    ;; "info" is as same type as `evil-sdk-get-tag' returns
+    info))
 
 ;;;###autoload
 (defun evilmi-verilog-get-tag ()
   "Get tag at point."
   (let* ((info (evilmi-sdk-get-tag evilmi-verilog-match-tags
-                                        
evilmi-verilog-extract-keyword-howtos)))
+                                   evilmi-verilog-extract-keyword-howtos)))
     (if evilmi-debug (message "evilmi-verilog-get-tag called => %s" info))
-    ;; hack if current line is `if' or `else if'
-    (unless info
-      (let* ((cur-line (evilmi-sdk-curline))
-             next-line
-             (pos (line-beginning-position)))
-        (when (string-match "^[ \t]*\\(if\\(n?def\\)?\\|else\\( if\\)?\\).*" 
cur-line)
-          ;; second chance for if else statement
-          (save-excursion
-            (forward-line 1)
-            (setq info (evilmi-sdk-get-tag evilmi-verilog-match-tags
-                                                
evilmi-verilog-extract-keyword-howtos)))
-          ;; move to the next line now. maybe there exist end statement
-          (when info
-            (forward-line 1)
-            (setq info (cons pos (cdr info)))))))
-    info))
+    (or info (evilmi-verilog-parse-at-point))))
 
 ;;;###autoload
 (defun evilmi-verilog-jump (info num)
   "Use INFO returned by `evilmi-verlog-get-tag' and NUM to jump to matched 
tag."
-  (let* ((orig-keyword (evilmi-sdk-keyword (cadr info))))
-    (if evilmi-debug (message "evilmi-verilog-jump called => %s" info))
-    (evilmi-sdk-jump info
-                     num
-                     evilmi-verilog-match-tags
-                     evilmi-verilog-extract-keyword-howtos)))
+  (when info
+    (let* ((orig-keyword (evilmi-sdk-keyword (cadr info))))
+      (if evilmi-debug (message "evilmi-verilog-jump called => %s" info))
+      (evilmi-sdk-jump info
+                       num
+                       evilmi-verilog-match-tags
+                       evilmi-verilog-extract-keyword-howtos))))
 
 (provide 'evil-matchit-verilog)
 ;;; evil-matchit-verilog.el ends here
diff --git a/tests/evil-matchit-tests.el b/tests/evil-matchit-tests.el
index 6a247246e0..12247b6761 100644
--- a/tests/evil-matchit-tests.el
+++ b/tests/evil-matchit-tests.el
@@ -340,8 +340,42 @@
     (evilmi-jump-items)
     (should (string= "END IF" (evilmi-sdk-curline)))
 
-    ;; upper case conditional statement
     (should (eq major-mode 'f90-mode))))
 
+(ert-deftest evilmi-test-verilog ()
+  (with-temp-buffer
+    (insert "`ifdef behavioral\n"
+            " `include \"groupA_beh.v \";\n"
+            " `include \"groupB_beh.v \";\n"
+            " `include \"ctrl_beh.v \";\n"
+            "`else\n"
+            " `include \"groupA_synth.v \";\n"
+            " `include \"groupB_ synth.v \";\n"
+            " `include \"ctrl_ synth.v \";\n"
+            "`endif\n"
+            )
+    (verilog-mode)
+
+    (goto-char (point-min))
+    (evilmi-jump-items)
+    (should (string= "`else" (evilmi-sdk-curline)))
+    (evilmi-jump-items)
+    (should (string= "`endif" (evilmi-sdk-curline)))
+    (evilmi-jump-items)
+    (should (string= "`ifdef behavioral" (evilmi-sdk-curline)))
+
+    (erase-buffer)
+    (insert "always @(WRITE or READ or STATUS) // test \n"
+            " /* hello */"
+            "  begin\n"
+            "  out = 9;\n"
+            "  end\n"
+            " // more comment\n")
+    (goto-char (point-min))
+    (evilmi-jump-items)
+    (should (string= "end" (thing-at-point 'symbol)))
+
+    (should (eq major-mode 'verilog-mode))))
+
 (ert-run-tests-batch-and-exit)
 ;;; evil-matchit-tests.el ends here



reply via email to

[Prev in Thread] Current Thread [Next in Thread]