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

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

[nongnu] elpa/d-mode 8d30f6b 246/346: Add back the old imenu implementat


From: ELPA Syncer
Subject: [nongnu] elpa/d-mode 8d30f6b 246/346: Add back the old imenu implementation for Emacs 25
Date: Sun, 29 Aug 2021 11:00:39 -0400 (EDT)

branch: elpa/d-mode
commit 8d30f6b3595ed204626f75af470846c5fd8fdf11
Author: Vladimir Panteleev <git@thecybershadow.net>
Commit: Vladimir Panteleev <git@thecybershadow.net>

    Add back the old imenu implementation for Emacs 25
---
 d-mode.el      | 305 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 tests/imenu.d  |  19 +---
 tests/imenu2.d |  20 ++++
 3 files changed, 325 insertions(+), 19 deletions(-)

diff --git a/d-mode.el b/d-mode.el
index c1ebebb..e69cff9 100644
--- a/d-mode.el
+++ b/d-mode.el
@@ -381,6 +381,22 @@ The expression is added to 
`compilation-error-regexp-alist' and
   d (append (list "delete" "throw")
            (c-lang-const d-type-modifier-kwds)))
 
+;; D: Like `c-regular-keywords-regexp', but contains keywords which
+;; cannot occur in a function type.  For Emacs 25 imenu.
+(c-lang-defconst d-non-func-type-kwds-re
+  d (concat "\\<"
+           (c-make-keywords-re t
+             (c--set-difference (c-lang-const c-keywords)
+                                (append (c-lang-const c-primitive-type-kwds)
+                                        (c-lang-const 
d-decl-storage-class-kwds))
+                                :test 'string-equal))))
+
+;; D: Like `c-regular-keywords-regexp', but contains keywords which
+;; cannot occur in a function name.  For Emacs 25 imenu.
+(c-lang-defconst d-non-func-name-kwds-re
+  d (concat "\\<"
+           (c-make-keywords-re t (c-lang-const c-keywords))))
+
 (c-lang-defconst c-block-stmt-1-kwds
   ;; Statement keywords followed directly by a substatement.
   d '("do" "else" "finally" "try" "in" "body"))
@@ -545,6 +561,291 @@ Each list item should be a regexp matching a single 
identifier."
 (easy-menu-define d-menu d-mode-map "D Mode Commands"
   (cons "D" (c-lang-const c-mode-menu d)))
 
+;;----------------------------------------------------------------------------
+
+;; Old imenu implementation - regular expressions:
+
+(eval-when-compile
+  (defconst d--imenu-rx-def-start
+    '(seq
+      ;; Conditionals
+      (zero-or-one
+       "else"
+       (zero-or-more space))
+      (zero-or-one
+       "version"
+       (zero-or-more space)
+       "("
+       (zero-or-more space)
+       (one-or-more (any "a-zA-Z0-9_"))
+       (zero-or-more space)
+       ")"
+       (zero-or-more space))
+
+      (zero-or-more
+       (or
+       word-start
+       (or
+        ;; StorageClass
+        "deprecated"
+        "static"
+        "extern"
+        "abstract"
+        "final"
+        "override"
+        "synchronized"
+        "scope"
+        "nothrow"
+        "pure"
+        "ref"
+        (seq
+         (or
+          "extern"
+          "deprecated"
+          "package"
+          )
+         (zero-or-more space)
+         "("
+         (zero-or-more space)
+         (one-or-more (not (any "()")))
+         (zero-or-more space)
+         ")")
+
+        ;; VisibilityAttribute
+        "private"
+        "package"
+        "protected"
+        "public"
+        "export"
+        )
+
+       ;; AtAttribute
+       (seq
+        "@"
+        (one-or-more (any "a-zA-Z0-9_"))
+        (zero-or-one
+         (zero-or-more space)
+         "("
+         (zero-or-more space)
+         (one-or-more (not (any "()")))
+         (zero-or-more space)
+         ")")))
+       (zero-or-more space))
+
+      )))
+
+(defconst d-imenu-method-name-pattern
+  (rx
+   ;; Whitespace
+   bol
+   (zero-or-more space)
+
+   (eval d--imenu-rx-def-start)
+
+   ;; Type
+   (group
+    (one-or-more (any "a-zA-Z0-9_.*![]()")))
+   (one-or-more space)
+
+   ;; Function name
+   (group
+    (one-or-more (any "a-zA-Z0-9_")))
+   (zero-or-more space)
+
+   ;; Type arguments
+   (zero-or-one
+    "(" (zero-or-more (not (any ")"))) ")"
+    (zero-or-more (any " \t\n")))
+
+   ;; Arguments
+   "("
+   (zero-or-more (not (any "()")))
+   (zero-or-more
+    "("
+    (zero-or-more (not (any "()")))
+    ")"
+    (zero-or-more (not (any "()"))))
+   ")"
+   (zero-or-more (any " \t\n"))
+
+   ;; Pure/const etc.
+   (zero-or-more
+    (one-or-more (any "a-z@"))
+    symbol-end
+    (zero-or-more (any " \t\n")))
+
+   (zero-or-more
+    "//"
+    (zero-or-more not-newline)
+    (zero-or-more space))
+
+   ;; ';' or 'if' or '{'
+   (or
+    ";"
+    (and
+     (zero-or-more (any " \t\n"))
+     (or "if" "{")))
+   ))
+
+(defun d-imenu-method-index-function ()
+  "Find D function declarations for imenu."
+  (and
+   (let ((pt))
+     (setq pt (re-search-backward d-imenu-method-name-pattern nil t))
+     ;; The method name regexp will match lines like
+     ;; "return foo(x);" or "static if(x) {"
+     ;; so we exclude type name 'static' or 'return' here
+     (while (let ((type (match-string 1))
+                 (name (match-string 2)))
+              (and pt name
+                   (save-match-data
+                    (or
+                     (string-match (c-lang-const d-non-func-type-kwds-re) type)
+                     (string-match (c-lang-const d-non-func-name-kwds-re) 
name)))))
+       (setq pt (re-search-backward d-imenu-method-name-pattern nil t)))
+     pt)
+   ;; Do not count invisible definitions.
+   (let ((invis (invisible-p (point))))
+     (or (not invis)
+         (progn
+           (while (and invis
+                       (not (bobp)))
+             (setq invis (not (re-search-backward
+                               d-imenu-method-name-pattern nil 'move))))
+           (not invis))))))
+
+(defvar d-imenu-generic-expression
+  `(("*Classes*"
+     ,(rx
+       bol
+       (zero-or-more space)
+       (eval d--imenu-rx-def-start)
+       word-start
+       "class"
+       (one-or-more (syntax whitespace))
+       (submatch
+       (one-or-more
+        (any ?_
+             (?0 . ?9)
+             (?A . ?Z)
+             (?a . ?z)))))
+     1)
+    ("*Interfaces*"
+     ,(rx
+       bol
+       (zero-or-more space)
+       (eval d--imenu-rx-def-start)
+       word-start
+       "interface"
+       (one-or-more (syntax whitespace))
+       (submatch
+       (one-or-more
+        (any ?_
+             (?0 . ?9)
+             (?A . ?Z)
+             (?a . ?z)))))
+     1)
+    ("*Structs*"
+     ,(rx
+       bol
+       (zero-or-more space)
+       (eval d--imenu-rx-def-start)
+       word-start
+       "struct"
+       (one-or-more (syntax whitespace))
+       (submatch
+       (one-or-more
+        (any ?_
+             (?0 . ?9)
+             (?A . ?Z)
+             (?a . ?z)))))
+     1)
+    ("*Templates*"
+     ,(rx
+       bol
+       (zero-or-more space)
+       (eval d--imenu-rx-def-start)
+       (zero-or-one
+       "mixin"
+       (one-or-more (syntax whitespace)))
+       word-start
+       "template"
+       (one-or-more (syntax whitespace))
+       (submatch
+       (one-or-more
+        (any ?_
+             (?0 . ?9)
+             (?A . ?Z)
+             (?a . ?z)))))
+     1)
+    ("*Enums*"
+     ,(rx
+       bol
+       (zero-or-more space)
+       (eval d--imenu-rx-def-start)
+       word-start
+       "enum"
+       (one-or-more (syntax whitespace))
+       (submatch
+       (one-or-more
+        (any ?_
+             (?0 . ?9)
+             (?A . ?Z)
+             (?a . ?z))))
+       (zero-or-more (any " \t\n"))
+       (or ":" "{"))
+     1)
+    ;; NB: We can't easily distinguish aliases declared outside
+    ;; functions from local ones, so just search for those that are
+    ;; declared at the beginning of lines.
+    ("*Aliases*"
+     ,(rx
+       bol
+       (eval d--imenu-rx-def-start)
+       "alias"
+       (one-or-more (syntax whitespace))
+       (submatch
+       (one-or-more
+        (any ?_
+             (?0 . ?9)
+             (?A . ?Z)
+             (?a . ?z))))
+       (zero-or-more (syntax whitespace))
+       (zero-or-one
+        "("
+        (zero-or-more (not (any "()")))
+        ")"
+        (zero-or-more (syntax whitespace)))
+       "=")
+     1)
+    ("*Aliases*"
+     ,(rx
+       bol
+       (eval d--imenu-rx-def-start)
+       "alias"
+       (one-or-more (syntax whitespace))
+       (one-or-more
+       (not (any ";")))
+       (one-or-more (syntax whitespace))
+       (submatch
+       (one-or-more
+        (any ?_
+             (?0 . ?9)
+             (?A . ?Z)
+             (?a . ?z))))
+       (zero-or-more (syntax whitespace))
+       ";"
+       (zero-or-more (syntax whitespace))
+       (or
+       eol
+       "//"
+       "/*")
+       )
+     1)
+    (nil d-imenu-method-index-function 2)))
+
+;; New imenu implementation - use cc-mode machinery:
+
 (defun d-imenu-create-index-function ()
   "Create imenu entries for D-mode."
   (goto-char (point-min))
@@ -834,7 +1135,9 @@ Key bindings:
   (easy-menu-add d-menu)
   (c-run-mode-hooks 'c-mode-common-hook 'd-mode-hook)
   (c-update-modeline)
-  (cc-imenu-init nil #'d-imenu-create-index-function))
+  (if (fboundp 'c-get-fontification-context)
+      (cc-imenu-init nil #'d-imenu-create-index-function)
+    (cc-imenu-init d-imenu-generic-expression)))
 
 ;;----------------------------------------------------------------------------
 
diff --git a/tests/imenu.d b/tests/imenu.d
index f2e6875..5b4dd0b 100644
--- a/tests/imenu.d
+++ b/tests/imenu.d
@@ -1,5 +1,5 @@
 // #run: (d-test-get-imenu-lines)
-// #out: (4 6 11 14 17 19 22 25 33 34 37 40 43 46 49 52 54 56 67 75 78 81 84 
87 89 93 94 96 97 99 104 109 111)
+// #out: (4 6 11 14 17 19 22 25 33 34 37 40 43 46 49 52 54 56 67 75 78 81 84 
87 89 93 94)
 
 void foo(int x) {}
 
@@ -92,20 +92,3 @@ string relativePath(CaseSensitive cs = 
CaseSensitive.osDefault)
 
 inout(ubyte) bytes(){}
 immutable(ubyte) bytes(){}
-
-void run(Parameter!("foo()") command) {}
-Parameter!("foo()") run(string command) {}
-
-string[string] environment;
-
-static import std.process;
-
-alias
-       Number
-       =
-       int;
-
-static if (false)
-       int fun();
-else
-       int gun();
diff --git a/tests/imenu2.d b/tests/imenu2.d
new file mode 100644
index 0000000..dd1ec13
--- /dev/null
+++ b/tests/imenu2.d
@@ -0,0 +1,20 @@
+// #min-version: 26.1
+// #run: (d-test-get-imenu-lines)
+// #out: (5 6 8 13 18 20)
+
+void run(Parameter!("foo()") command) {}
+Parameter!("foo()") run(string command) {}
+
+string[string] environment;
+
+static import std.process;
+
+alias
+       Number
+       =
+       int;
+
+static if (false)
+       int fun();
+else
+       int gun();



reply via email to

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