Klimi's new dotfiles with stow.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

393 lines
15 KiB

преди 5 години
  1. ;;; haskell-completions.el --- Haskell Completion package -*- lexical-binding: t -*-
  2. ;; Copyright © 2015-2016 Athur Fayzrakhmanov. All rights reserved.
  3. ;; This file is part of haskell-mode package.
  4. ;; You can contact with authors using GitHub issue tracker:
  5. ;; https://github.com/haskell/haskell-mode/issues
  6. ;; This file is free software; you can redistribute it and/or modify
  7. ;; it under the terms of the GNU General Public License as published by
  8. ;; the Free Software Foundation; either version 3, or (at your option)
  9. ;; any later version.
  10. ;; This file is distributed in the hope that it will be useful,
  11. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ;; GNU General Public License for more details.
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with GNU Emacs; see the file COPYING. If not, write to
  16. ;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
  17. ;; Boston, MA 02110-1301, USA.
  18. ;;; Commentary:
  19. ;; This package provides completions related functionality for
  20. ;; Haskell Mode such grab completion prefix at point, and etc..
  21. ;; Some description
  22. ;; ================
  23. ;;
  24. ;; For major use function `haskell-completions-grab-prefix' is supposed, and
  25. ;; other prefix grabbing functions are used internally by it. So, only this
  26. ;; funciton have prefix minimal length functionality and invokes predicate
  27. ;; function `haskell-completions-can-grab-prefix'.
  28. ;;; Code:
  29. (require 'haskell-mode)
  30. (require 'haskell-process)
  31. (require 'haskell-interactive-mode)
  32. ;;;###autoload
  33. (defgroup haskell-completions nil
  34. "Settings for completions provided by `haskell-mode'"
  35. :link '(custom-manual "(haskell-mode)Completion support")
  36. :group 'haskell)
  37. (defcustom haskell-completions-complete-operators
  38. t
  39. "Should `haskell-completions-sync-repl-completion-at-point' complete operators.
  40. Note: GHCi prior to version 8.0.1 have bug in `:complete`
  41. command: when completing operators it returns a list of all
  42. imported identifiers (see Track ticket URL
  43. `https://ghc.haskell.org/trac/ghc/ticket/10576'). This leads to
  44. significant Emacs slowdown. To aviod slowdown you should set
  45. this variable to `nil'."
  46. :group 'haskell-completions
  47. :type 'boolean)
  48. (defvar haskell-completions--pragma-names
  49. (list "DEPRECATED"
  50. "INCLUDE"
  51. "INCOHERENT"
  52. "INLINABLE"
  53. "INLINE"
  54. "LANGUAGE"
  55. "LINE"
  56. "MINIMAL"
  57. "NOINLINE"
  58. "NOUNPACK"
  59. "OPTIONS"
  60. "OPTIONS_GHC"
  61. "OVERLAPPABLE"
  62. "OVERLAPPING"
  63. "OVERLAPS"
  64. "RULES"
  65. "SOURCE"
  66. "SPECIALIZE"
  67. "UNPACK"
  68. "WARNING")
  69. "A list of supported pragmas.
  70. This list comes from GHC documentation (URL
  71. `https://downloads.haskell.org/~ghc/7.10.1/docs/html/users_guide/pragmas.html'.")
  72. (defvar haskell-completions--keywords
  73. (list
  74. "as"
  75. "case"
  76. "class"
  77. "data family"
  78. "data instance"
  79. "data"
  80. "default"
  81. "deriving instance"
  82. "deriving"
  83. "do"
  84. "else"
  85. "family"
  86. "forall"
  87. "foreign import"
  88. "foreign"
  89. "hiding"
  90. "if"
  91. "import qualified"
  92. "import"
  93. "in"
  94. "infix"
  95. "infixl"
  96. "infixr"
  97. "instance"
  98. "let"
  99. "mdo"
  100. "module"
  101. "newtype"
  102. "of"
  103. "proc"
  104. "qualified"
  105. "rec"
  106. "signature"
  107. "then"
  108. "type family"
  109. "type instance"
  110. "type"
  111. "where")
  112. "A list of Haskell's keywords (URL `https://wiki.haskell.org/Keywords').
  113. Single char keywords and operator like keywords are not included
  114. in this list.")
  115. (defun haskell-completions-can-grab-prefix ()
  116. "Check if the case is appropriate for grabbing completion prefix.
  117. Returns t if point is either at whitespace character, or at
  118. punctuation, or at line end and preceeding character is not a
  119. whitespace or new line, otherwise returns nil.
  120. Returns nil in presence of active region."
  121. (when (not (region-active-p))
  122. (when (looking-at-p (rx (| space line-end punct)))
  123. (when (not (bobp))
  124. (save-excursion
  125. (backward-char)
  126. (not (looking-at-p (rx (| space line-end)))))))))
  127. (defun haskell-completions-grab-pragma-prefix ()
  128. "Grab completion prefix for pragma completions.
  129. Returns a list of form '(prefix-start-position
  130. prefix-end-position prefix-value prefix-type) for pramga names
  131. such as WARNING, DEPRECATED, LANGUAGE etc. Also returns
  132. completion prefixes for options in case OPTIONS_GHC pragma, or
  133. language extensions in case of LANGUAGE pragma. Obsolete OPTIONS
  134. pragma is supported also."
  135. (when (nth 4 (syntax-ppss))
  136. ;; We're inside comment
  137. (let ((p (point))
  138. (comment-start (nth 8 (syntax-ppss)))
  139. (case-fold-search nil)
  140. prefix-start
  141. prefix-end
  142. prefix-type
  143. prefix-value)
  144. (save-excursion
  145. (goto-char comment-start)
  146. (when (looking-at (rx "{-#" (1+ (| space "\n"))))
  147. (let ((pragma-start (match-end 0)))
  148. (when (> p pragma-start)
  149. ;; point stands after `{-#`
  150. (goto-char pragma-start)
  151. (when (looking-at (rx (1+ (| upper "_"))))
  152. ;; found suitable sequence for pragma name
  153. (let ((pragma-end (match-end 0))
  154. (pragma-value (match-string-no-properties 0)))
  155. (if (eq p pragma-end)
  156. ;; point is at the end of (in)complete pragma name
  157. ;; prepare resulting values
  158. (progn
  159. (setq prefix-start pragma-start)
  160. (setq prefix-end pragma-end)
  161. (setq prefix-value pragma-value)
  162. (setq prefix-type
  163. 'haskell-completions-pragma-name-prefix))
  164. (when (and (> p pragma-end)
  165. (or (equal "OPTIONS_GHC" pragma-value)
  166. (equal "OPTIONS" pragma-value)
  167. (equal "LANGUAGE" pragma-value)))
  168. ;; point is after pragma name, so we need to check
  169. ;; special cases of `OPTIONS_GHC` and `LANGUAGE` pragmas
  170. ;; and provide a completion prefix for possible ghc
  171. ;; option or language extension.
  172. (goto-char pragma-end)
  173. (when (re-search-forward
  174. (rx (* anything)
  175. (1+ (regexp "\\S-")))
  176. p
  177. t)
  178. (let* ((str (match-string-no-properties 0))
  179. (split (split-string str (rx (| space "\n")) t))
  180. (val (car (last split)))
  181. (end (point)))
  182. (when (and (equal p end)
  183. (not (string-match-p "#" val)))
  184. (setq prefix-value val)
  185. (backward-char (length val))
  186. (setq prefix-start (point))
  187. (setq prefix-end end)
  188. (setq
  189. prefix-type
  190. (if (not (equal "LANGUAGE" pragma-value))
  191. 'haskell-completions-ghc-option-prefix
  192. 'haskell-completions-language-extension-prefix
  193. )))))))))))))
  194. (when prefix-value
  195. (list prefix-start prefix-end prefix-value prefix-type)))))
  196. (defun haskell-completions-grab-identifier-prefix ()
  197. "Grab completion prefix for identifier at point.
  198. Returns a list of form '(prefix-start-position
  199. prefix-end-position prefix-value prefix-type) for haskell
  200. identifier at point depending on result of function
  201. `haskell-ident-pos-at-point'."
  202. (let ((pos-at-point (haskell-ident-pos-at-point))
  203. (p (point)))
  204. (when pos-at-point
  205. (let* ((start (car pos-at-point))
  206. (end (cdr pos-at-point))
  207. (type 'haskell-completions-identifier-prefix)
  208. (case-fold-search nil)
  209. value)
  210. ;; we need end position of result, becase of
  211. ;; `haskell-ident-pos-at-point' ignores trailing whitespace, e.g. the
  212. ;; result will be same for `map|` and `map |` invocations.
  213. (when (<= p end)
  214. (setq end p)
  215. (setq value (buffer-substring-no-properties start end))
  216. (when (string-match-p (rx bos upper) value)
  217. ;; we need to check if found identifier is a module name
  218. (save-excursion
  219. (goto-char (line-beginning-position))
  220. (when (re-search-forward
  221. (rx "import"
  222. (? (1+ space) "qualified")
  223. (1+ space)
  224. upper
  225. (1+ (| alnum ".")))
  226. p ;; bound
  227. t) ;; no-error
  228. (if (equal p (point))
  229. (setq type 'haskell-completions-module-name-prefix)
  230. (when (re-search-forward
  231. (rx (| " as " "("))
  232. start
  233. t)
  234. ;; but uppercase ident could occur after `as` keyword, or in
  235. ;; module imports after opening parenthesis, in this case
  236. ;; restore identifier type again, it's neccessary to
  237. ;; distinguish the means of completions retrieval
  238. (setq type 'haskell-completions-identifier-prefix))))))
  239. (when (nth 8 (syntax-ppss))
  240. ;; eighth element of syntax-ppss result is string or comment start,
  241. ;; so when it's not nil word at point is inside string or comment,
  242. ;; return special literal prefix type
  243. (setq type 'haskell-completions-general-prefix))
  244. ;; finally take in account minlen if given and return the result
  245. (when value (list start end value type)))))))
  246. (defun haskell-completions-grab-prefix (&optional minlen)
  247. "Grab prefix at point for possible completion.
  248. Returns a list of form '(prefix-start-position
  249. prefix-end-position prefix-value prefix-type) depending on
  250. situation, e.g. is it needed to complete pragma, module name,
  251. arbitrary identifier, etc. Returns nil in case it is
  252. impossible to grab prefix.
  253. Possible prefix types are:
  254. * haskell-completions-pragma-name-prefix
  255. * haskell-completions-ghc-option-prefix
  256. * haskell-completions-language-extension-prefix
  257. * haskell-completions-module-name-prefix
  258. * haskell-completions-identifier-prefix
  259. * haskell-completions-general-prefix
  260. the last type is used in cases when completing things inside comments.
  261. If provided optional MINLEN parameter this function will return
  262. result only if prefix length is not less than MINLEN."
  263. (when (haskell-completions-can-grab-prefix)
  264. (let ((prefix (cond
  265. ((haskell-completions-grab-pragma-prefix))
  266. ((haskell-completions-grab-identifier-prefix)))))
  267. (cond ((and minlen prefix)
  268. (when (>= (length (nth 2 prefix)) minlen)
  269. prefix))
  270. (prefix prefix)))))
  271. (defun haskell-completions--simple-completions (prefix)
  272. "Provide a list of completion candidates for given PREFIX.
  273. This function is used internally in
  274. `haskell-completions-completion-at-point' and
  275. `haskell-completions-sync-repl-completion-at-point'.
  276. It provides completions for haskell keywords, language pragmas,
  277. GHC's options, and language extensions.
  278. PREFIX should be a list such one returned by
  279. `haskell-completions-grab-identifier-prefix'."
  280. (cl-destructuring-bind (beg end _pfx typ) prefix
  281. (when (not (eql typ 'haskell-completions-general-prefix))
  282. (let ((candidates
  283. (cl-case typ
  284. ('haskell-completions-pragma-name-prefix
  285. haskell-completions--pragma-names)
  286. ('haskell-completions-ghc-option-prefix
  287. haskell-ghc-supported-options)
  288. ('haskell-completions-language-extension-prefix
  289. haskell-ghc-supported-extensions)
  290. (otherwise
  291. (append (when (bound-and-true-p haskell-tags-on-save)
  292. tags-completion-table)
  293. haskell-completions--keywords)))))
  294. (list beg end candidates)))))
  295. ;;;###autoload
  296. (defun haskell-completions-completion-at-point ()
  297. "Provide completion list for thing at point.
  298. This function is used in non-interactive `haskell-mode'. It
  299. provides completions for haskell keywords, language pragmas,
  300. GHC's options, and language extensions, but not identifiers."
  301. (let ((prefix (haskell-completions-grab-prefix)))
  302. (when prefix
  303. (haskell-completions--simple-completions prefix))))
  304. (defun haskell-completions-sync-repl-completion-at-point ()
  305. "A completion function used in `interactive-haskell-mode'.
  306. Completion candidates are provided quering current haskell
  307. process, that is sending `:complete repl' command.
  308. Completes all possible things: everything that can be completed
  309. with non-interactive function
  310. `haskell-completions-completion-at-point' plus identifier
  311. completions.
  312. Returns nil if no completions available."
  313. (let ((prefix-data (haskell-completions-grab-prefix)))
  314. (when prefix-data
  315. (cl-destructuring-bind (beg end pfx typ) prefix-data
  316. (when (and (not (eql typ 'haskell-completions-general-prefix))
  317. (or haskell-completions-complete-operators
  318. (not (save-excursion
  319. (goto-char (1- end))
  320. (haskell-mode--looking-at-varsym)))))
  321. ;; do not complete things in comments
  322. (if (cl-member
  323. typ
  324. '(haskell-completions-pragma-name-prefix
  325. haskell-completions-ghc-option-prefix
  326. haskell-completions-language-extension-prefix))
  327. ;; provide simple completions
  328. (haskell-completions--simple-completions prefix-data)
  329. ;; only two cases left: haskell-completions-module-name-prefix
  330. ;; and haskell-completions-identifier-prefix
  331. (let* ((is-import (eql typ 'haskell-completions-module-name-prefix))
  332. (candidates
  333. (when (and (haskell-session-maybe)
  334. (not (haskell-process-cmd
  335. (haskell-interactive-process)))
  336. ;; few possible extra checks would be:
  337. ;; (haskell-process-get 'is-restarting)
  338. ;; (haskell-process-get 'evaluating)
  339. )
  340. ;; if REPL is available and not busy try to query it for
  341. ;; completions list in case of module name or identifier
  342. ;; prefixes
  343. (haskell-completions-sync-complete-repl pfx is-import))))
  344. ;; append candidates with keywords
  345. (list beg end (append
  346. candidates
  347. haskell-completions--keywords)))))))))
  348. (defun haskell-completions-sync-complete-repl (prefix &optional import)
  349. "Return completion list for given PREFIX querying REPL synchronously.
  350. When optional IMPORT argument is non-nil complete PREFIX
  351. prepending \"import \" keyword (useful for module names). This
  352. function is supposed for internal use."
  353. (haskell-process-get-repl-completions
  354. (haskell-interactive-process)
  355. (if import
  356. (concat "import " prefix)
  357. prefix)))
  358. (provide 'haskell-completions)
  359. ;;; haskell-completions.el ends here