emacs.d/elpa/racket-mode-20200411.1959/racket-imenu.el
2020-04-13 12:29:54 +02:00

89 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