al-imenu.el 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. ;;; al-imenu.el --- Additional functionality for imenu
  2. ;; Copyright © 2014–2017 Alex Kost
  3. ;; This program is free software; you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation, either version 3 of the License, or
  6. ;; (at your option) any later version.
  7. ;;
  8. ;; This program is distributed in the hope that it will be useful,
  9. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. ;; GNU General Public License for more details.
  12. ;;
  13. ;; You should have received a copy of the GNU General Public License
  14. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  15. ;;; Code:
  16. (cl-defun al/add-to-imenu (regexp &key (index 1) title append)
  17. "Add REGEXP with INDEX and TITLE to `imenu-generic-expression'.
  18. If APPEND is nil, add the new element at the end."
  19. (add-to-list 'imenu-generic-expression
  20. (list title regexp index)
  21. append))
  22. ;;; Lisp sections
  23. ;; If you have sections in lisp/elisp files that begin with ";;;", you
  24. ;; may use the following code to add "Sections" entry in `imenu':
  25. ;;
  26. ;; (add-hook 'emacs-lisp-mode-hook 'al/imenu-add-sections)
  27. ;; (add-hook 'lisp-mode-hook 'al/imenu-add-sections)
  28. (defvar al/imenu-sections-re "^;;; \\(.+\\)$"
  29. "Regexp used for \"Sections\" imenu entries.")
  30. (defvar al/imenu-sections-group "Sections"
  31. "Group name in imenu index of \"Sections\" entries.
  32. If nil, put the entries in a top level. See MENU-TITLE in
  33. `imenu-generic-expression' variable for details.")
  34. ;;;###autoload
  35. (defun al/imenu-add-sections (&optional regexp)
  36. "Add REGEXP as a \"Sections\" element to `imenu-generic-expression'.
  37. If REGEXP is nil, use `al/imenu-sections-re'."
  38. (al/add-to-imenu (or regexp al/imenu-sections-re)
  39. :title al/imenu-sections-group
  40. :append t))
  41. ;;; JS sections
  42. ;; To have "Sections" entry in javascript buffers:
  43. ;;
  44. ;; (add-hook 'js-mode-hook 'al/imenu-add-js-sections)
  45. (defvar al/imenu-js-sections-re "^/// \\(.+\\)$"
  46. "Regexp used for \"Sections\" imenu entries in `js-mode'.")
  47. ;;;###autoload
  48. (defun al/imenu-add-js-sections (&optional regexp)
  49. "Add REGEXP as a \"Sections\" element to `imenu-generic-expression'.
  50. If REGEXP is nil, use `al/imenu-sections-re'."
  51. (al/imenu-add-sections al/imenu-js-sections-re)
  52. (setq-local imenu-create-index-function 'al/js-imenu-create-index))
  53. (declare-function js--imenu-create-index "js" nil)
  54. (declare-function imenu--generic-function "imenu" (patterns))
  55. (defun al/js-imenu-create-index ()
  56. "Create an index alist for the current js buffer.
  57. The function is suitable for `imenu-create-index-function'
  58. variable and intended to be used instead of
  59. `js--imenu-create-index' in js buffers. It adds the same entries
  60. as the latter function and also create elements for
  61. `imenu-generic-expression'."
  62. (let ((js-index (js--imenu-create-index))
  63. (generic-index
  64. (save-excursion
  65. (save-restriction
  66. (widen)
  67. (imenu--generic-function imenu-generic-expression)))))
  68. (append js-index generic-index)))
  69. ;;; `use-package' entries
  70. ;; Idea from <https://github.com/jwiegley/use-package/issues/80>.
  71. (defvar al/imenu-use-package-re
  72. (rx bol "(use-package" (+ whitespace)
  73. (? ?\")
  74. (group (+ (or (syntax word) (syntax symbol))))
  75. (? ?\"))
  76. "Regexp used for `use-package' entries in imenu.")
  77. (defvar al/imenu-use-package-group "use-package"
  78. "Group name in imenu index of use-package entries.
  79. If nil, put the entries in a top level. See MENU-TITLE in
  80. `imenu-generic-expression' variable for details.")
  81. ;;;###autoload
  82. (defun al/imenu-add-use-package ()
  83. "Add `al/imenu-use-package-re' to `imenu-generic-expression'."
  84. (al/add-to-imenu al/imenu-use-package-re
  85. :title al/imenu-use-package-group))
  86. ;;; (with-)eval-after-load entries
  87. (defvar al/imenu-eval-after-load-re
  88. (rx bol "(" (zero-or-one "with-") "eval-after-load" (+ whitespace)
  89. (zero-or-one (or ?\" ?'))
  90. (group (+ (or (syntax word) (syntax symbol))))
  91. (zero-or-one ?\"))
  92. "Regexp used for `eval-after-load' and `with-eval-after-load'
  93. entries in imenu.")
  94. (defvar al/imenu-eval-after-load-group "(with-)eval-after-load")
  95. ;;;###autoload
  96. (defun al/imenu-add-eval-after-load ()
  97. "Add `al/imenu-eval-after-load-re' to `imenu-generic-expression'."
  98. (al/add-to-imenu al/imenu-eval-after-load-re
  99. :title al/imenu-eval-after-load-group))
  100. (provide 'al-imenu)
  101. ;;; al-imenu.el ends here