90 lines
3.1 KiB
EmacsLisp
90 lines
3.1 KiB
EmacsLisp
![]() |
;;; racket-imenu.el
|
||
|
|
||
|
;; Copyright (c) 2013-2016 by Greg Hendershott.
|
||
|
;; Portions Copyright (C) 1985-1986, 1999-2013 Free Software Foundation, Inc.
|
||
|
|
||
|
;; Author: Greg Hendershott
|
||
|
;; URL: https://github.com/greghendershott/racket-mode
|
||
|
|
||
|
;; License:
|
||
|
;; This 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 2, or (at your option)
|
||
|
;; any later version. This 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. See
|
||
|
;; http://www.gnu.org/licenses/ for details.
|
||
|
|
||
|
(require 'cl-lib)
|
||
|
(require 'imenu)
|
||
|
|
||
|
(defun racket--variables-imenu ()
|
||
|
(set (make-local-variable 'imenu-case-fold-search) t)
|
||
|
(set (make-local-variable 'imenu-create-index-function)
|
||
|
#'racket--imenu-create-index-function))
|
||
|
|
||
|
(defun racket--imenu-create-index-function ()
|
||
|
"A function for the variable `imenu-create-index-function'.
|
||
|
|
||
|
Knows about Racket module forms, and prefixes identiers with
|
||
|
their parent module name(s)."
|
||
|
(save-excursion
|
||
|
(goto-char (point-min))
|
||
|
(racket--next-sexp)
|
||
|
(racket--walk-sexps "")))
|
||
|
|
||
|
(defun racket--walk-sexps (prefix)
|
||
|
"With point at the start of a sexp, walk all the sepxs.
|
||
|
|
||
|
`racket--menu-sexp' will walk into Racket module forms and call
|
||
|
us recursively."
|
||
|
(cl-loop append (racket--menu-sexp prefix) into xs
|
||
|
while (racket--next-next-sexp)
|
||
|
finally return xs))
|
||
|
|
||
|
(defun racket--menu-sexp (prefix)
|
||
|
"Return the identifier for the sexp at point if any, else nil.
|
||
|
|
||
|
If sexp at point is a Racket module form, descend and walk that."
|
||
|
(cond ((looking-at (rx "(define" (* (or (syntax word) (syntax symbol)))
|
||
|
(+ (syntax whitespace))
|
||
|
(? ?\()
|
||
|
(group (+ (or (syntax word) (syntax symbol))))))
|
||
|
(let* ((beg (match-beginning 1))
|
||
|
(beg (if imenu-use-markers
|
||
|
(save-excursion (goto-char beg) (point-marker))
|
||
|
beg)))
|
||
|
(list (cons (concat prefix (match-string-no-properties 1))
|
||
|
beg))))
|
||
|
((looking-at (rx "(module" (? (any ?+ ?*))
|
||
|
(+ (syntax whitespace))
|
||
|
(group (+ (or (syntax word) (syntax symbol))))))
|
||
|
(save-excursion
|
||
|
(goto-char (match-end 1))
|
||
|
(racket--next-sexp)
|
||
|
(racket--walk-sexps (concat prefix (match-string-no-properties 1) ":"))))
|
||
|
(t nil)))
|
||
|
|
||
|
(defun racket--next-sexp ()
|
||
|
"Move point to start of next sexp in buffer."
|
||
|
(forward-sexp 1)
|
||
|
(forward-sexp -1))
|
||
|
|
||
|
(defun racket--next-next-sexp ()
|
||
|
"If another sexp, move point to its start and return t, else return nil."
|
||
|
(condition-case nil
|
||
|
(progn
|
||
|
(forward-sexp 1)
|
||
|
(let ((orig (point)))
|
||
|
(forward-sexp 1)
|
||
|
(if (or (eobp) (equal orig (point)))
|
||
|
nil
|
||
|
(forward-sexp -1)
|
||
|
t)))
|
||
|
(scan-error nil)))
|
||
|
|
||
|
(provide 'racket-imenu)
|
||
|
|
||
|
;;; racket-imenu.el ends here
|