26
26
; ; This package provides completions related functionality for
27
27
; ; Haskell Mode such grab completion prefix at point, and etc..
28
28
29
+ ; ; Some description
30
+ ; ; ================
31
+ ; ;
32
+ ; ; For major use function `haskell-completions-grab-prefix' is supposed, and
33
+ ; ; other prefix grabbing functions are used internally by it. So, only this
34
+ ; ; funciton have prefix minimal length functionality and invokes predicate
35
+ ; ; function `haskell-completions-can-grab-prefix' .
36
+
29
37
; ;; Code:
30
38
39
+ (require 'haskell-mode )
40
+
41
+
31
42
(defun haskell-completions-can-grab-prefix ()
32
43
" Check if the case is appropriate for grabbing completion prefix.
33
44
Returns t if point is either at whitespace character, or at
@@ -42,5 +53,146 @@ whitespace or new line, otherwise returns nil.
42
53
(backward-char )
43
54
(not (looking-at (rx (| space line-end)))))))))
44
55
56
+ (defun haskell-completions-grab-pragma-prefix ()
57
+ " Grab completion prefix for pragma completions.
58
+ Returns a list of form '(prefix-start-position
59
+ prefix-end-position prefix-value prefix-type) for pramga names
60
+ such as WARNING, DEPRECATED, LANGUAGE and etc. Also returns
61
+ completion prefixes for options in case OPTIONS_GHC pragma, or
62
+ language extensions in case of LANGUAGE pragma. Obsolete OPTIONS
63
+ pragma is supported also."
64
+ (when (nth 4 (syntax-ppss ))
65
+ ; ; We're inside comment
66
+ (let ((p (point ))
67
+ (comment-start (nth 8 (syntax-ppss )))
68
+ (case-fold-search nil )
69
+ prefix-start
70
+ prefix-end
71
+ prefix-type
72
+ prefix-value)
73
+ (save-excursion
74
+ (goto-char comment-start)
75
+ (when (looking-at (rx " {-#" (1+ (| space " \n " ))))
76
+ (let ((pragma-start (match-end 0 )))
77
+ (when (> p pragma-start)
78
+ ; ; point stands after `{-#`
79
+ (goto-char pragma-start)
80
+ (when (looking-at (rx (1+ (| upper " _" ))))
81
+ ; ; found suitable sequence for pragma name
82
+ (let ((pragma-end (match-end 0 ))
83
+ (pragma-value (match-string-no-properties 0 )))
84
+ (if (eq p pragma-end)
85
+ ; ; point is at the end of (in)complete pragma name
86
+ ; ; prepare resulting values
87
+ (progn
88
+ (setq prefix-start pragma-start)
89
+ (setq prefix-end pragma-end)
90
+ (setq prefix-value pragma-value)
91
+ (setq prefix-type
92
+ 'haskell-completions-pragma-name-prefix ))
93
+ (when (and (> p pragma-end)
94
+ (or (equal " OPTIONS_GHC" pragma-value)
95
+ (equal " OPTIONS" pragma-value)
96
+ (equal " LANGUAGE" pragma-value)))
97
+ ; ; point is after pragma name, so we need to check
98
+ ; ; special cases of `OPTIONS_GHC` and `LANGUAGE` pragmas
99
+ ; ; and provide a completion prefix for possible ghc
100
+ ; ; option or language extension.
101
+ (goto-char pragma-end)
102
+ (when (re-search-forward
103
+ (rx (* anything)
104
+ (1+ (regexp " \\ S-" )))
105
+ p
106
+ t )
107
+ (let* ((str (match-string-no-properties 0 ))
108
+ (split (split-string str (rx (| space " \n " )) t ))
109
+ (val (car (last split)))
110
+ (end (point )))
111
+ (when (and (equal p end)
112
+ (not (string-match-p " #" val)))
113
+ (setq prefix-value val)
114
+ (backward-char (length val))
115
+ (setq prefix-start (point ))
116
+ (setq prefix-end end)
117
+ (setq
118
+ prefix-type
119
+ (if (not (equal " LANGUAGE" pragma-value))
120
+ 'haskell-completions-ghc-option-prefix
121
+ 'haskell-completions-language-extension-prefix
122
+ )))))))))))))
123
+ (when prefix-value
124
+ (list prefix-start prefix-end prefix-value prefix-type)))))
125
+
126
+ (defun haskell-completions-grab-identifier-prefix ()
127
+ " Grab completion prefix for identifier at point.
128
+ Returns a list of form '(prefix-start-position
129
+ prefix-end-position prefix-value prefix-type) for haskell
130
+ identifier at point depending on result of function
131
+ `haskell-ident-pos-at-point' ."
132
+ (let ((pos-at-point (haskell-ident-pos-at-point))
133
+ (p (point )))
134
+ (when pos-at-point
135
+ (let* ((start (car pos-at-point))
136
+ (end (cdr pos-at-point))
137
+ (type 'haskell-completions-identifier-prefix )
138
+ (case-fold-search nil )
139
+ value)
140
+ ; ; we need end position of result, becase of
141
+ ; ; `haskell-ident-pos-at-point' ignores trailing whitespace, e.g. the
142
+ ; ; result will be same for `map|` and `map |` invocations.
143
+ (when (<= p end)
144
+ (setq end p)
145
+ (setq value (buffer-substring-no-properties start end))
146
+ (when (string-match-p (rx bos upper) value)
147
+ ; ; we need to check if found identifier is a module name
148
+ (save-excursion
149
+ (goto-char (line-beginning-position ))
150
+ (when (re-search-forward
151
+ (rx " import"
152
+ (? (1+ space) " qualified" )
153
+ (1+ space)
154
+ upper
155
+ (1+ (| alnum " ." )))
156
+ p ; ; bound
157
+ t ) ; ; no-error
158
+ (if (equal p (point ))
159
+ (setq type 'haskell-completions-module-name-prefix )
160
+ (when (re-search-forward
161
+ (rx (| " as " " (" ))
162
+ start
163
+ t )
164
+ ; ; but uppercase ident could occur after `as` keyword, or in
165
+ ; ; module imports after opening parenthesis, in this case
166
+ ; ; restore identifier type again, it's neccessary to
167
+ ; ; distinguish the means of completions retrieval
168
+ (setq type 'haskell-completions-identifier-prefix ))))))
169
+ (when (nth 8 (syntax-ppss ))
170
+ ; ; eighth element of syntax-ppss result is string or comment start,
171
+ ; ; so when it's not nil word at point is inside string or comment,
172
+ ; ; return special literal prefix type
173
+ (setq type 'haskell-completions-general-prefix ))
174
+ ; ; finally take in account minlen if given and return the result
175
+ (when value (list start end value type)))))))
176
+
177
+ (defun haskell-completions-grab-prefix (&optional minlen )
178
+ " Grab prefix at point for possible completion.
179
+ Returns a list of form '(prefix-start-position
180
+ prefix-end-position prefix-value prefix-type) depending on
181
+ situation, e.g. is it needed to complete pragma, module name,
182
+ arbitrary identifier, and etc. Rerurns nil in case it is
183
+ impossible to grab prefix.
184
+
185
+ If provided optional MINLEN parameter this function will return
186
+ result only if prefix length is not less than MINLEN."
187
+ (when (haskell-completions-can-grab-prefix)
188
+ (let ((prefix (cond
189
+ ((haskell-completions-grab-pragma-prefix))
190
+ ((haskell-completions-grab-identifier-prefix)))))
191
+ (cond ((and minlen prefix)
192
+ (when (>= (length (nth 2 prefix)) minlen)
193
+ prefix))
194
+ (prefix prefix)))))
195
+
196
+
45
197
(provide 'haskell-completions )
46
198
; ;; haskell-completions.el ends here
0 commit comments