emacs.d/elpa/racket-mode-20200402.1703/racket-xp-complete.el

113 lines
4.1 KiB
EmacsLisp
Raw Normal View History

2020-03-24 18:20:37 +01:00
;;; racket-xp-complete.el -*- lexical-binding: t -*-
;; Copyright (c) 2013-2020 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 'racket-complete)
(require 'racket-describe)
(defvar racket--xp-binding-completions nil
"Used by `racket-xp-complete-at-point'.")
(defvar racket--xp-module-completions nil
"Used by `racket-xp-complete-at-point' and initialized by
`racket-xp-mode'.")
(defun racket-xp-complete-at-point ()
"A value for the variable `completion-at-point-functions'.
- Within a textually apparent \"require\" form, when completing:
- A symbol immediately after an opening paren: Candidates are
names of require transformers.
- Another symbol: Candidates are absolute module paths like
\"racket/path\".
- Anything `thing-at-point' thinks is a filename: Candidates
are from `completion-file-name-table'.
- Otherwise, when completing a symbol: Candidates are bindings as
found by drracket/checks-syntax plus our own back end analysis
of imported bindings."
(cond ((racket--in-require-form-p)
(or (racket--call-with-completion-prefix-positions
(lambda (beg end)
(if (eq ?\( (char-syntax (char-before beg)))
(racket--xp-capf-require-transformers beg end)
(racket--xp-capf-absolute-module-paths beg end))))
(racket--xp-capf-relative-module-paths)))
(t
(racket--call-with-completion-prefix-positions
#'racket--xp-capf-bindings))))
(defun racket--xp-capf-bindings (beg end)
(list beg
end
(completion-table-dynamic
(lambda (prefix)
(all-completions prefix racket--xp-binding-completions)))
:predicate #'identity
:exclusive 'no
:company-location (racket--xp-make-company-location-proc)
:company-doc-buffer (racket--xp-make-company-doc-buffer-proc)))
(defun racket--xp-capf-require-transformers (beg end)
"Note: Currently this returns too many candidates -- all
available bindings, not just those that are require transformers.
Although not ideal, I think it's less-worse than having some
hardwired list of require transformers. In general with
completion candidates, if you have to err, better to err on the
side of too many not too few. Having said that, someday maybe our
back end could give us the exact subset of available bindings
that are require transformers."
(racket--xp-capf-bindings beg end))
(defun racket--xp-capf-absolute-module-paths (beg end)
(list beg
end
(completion-table-dynamic
(lambda (prefix)
(all-completions prefix racket--xp-module-completions)))
:exclusive 'no))
(defun racket--xp-capf-relative-module-paths ()
(pcase (thing-at-point 'filename t)
((and (pred stringp) str)
(list (beginning-of-thing 'filename)
(end-of-thing 'filename)
(completion-file-name-table str #'file-exists-p t)
:exclusive 'no ))))
(defun racket--xp-make-company-location-proc ()
(when (racket--cmd-open-p)
(let ((how (buffer-file-name)))
(lambda (str)
(let ((str (substring-no-properties str)))
(pcase (racket--cmd/await nil `(def ,how ,str))
(`(,path ,line ,_) (cons path line))))))))
(defun racket--xp-make-company-doc-buffer-proc ()
(when (racket--cmd-open-p)
(let ((how (buffer-file-name)))
(lambda (str)
(let ((str (substring-no-properties str)))
(racket--do-describe how nil str))))))
(provide 'racket-xp-complete)
;; racket-xp-complete.el ends here