Skip to content

Commit 1d69617

Browse files
committed
Merge pull request #641 from geraldus/better-error-handling
Better error handling for `haskell-mode-show-type-at`
2 parents 2532074 + a406686 commit 1d69617

File tree

1 file changed

+82
-39
lines changed

1 file changed

+82
-39
lines changed

haskell-commands.el

Lines changed: 82 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -597,10 +597,18 @@ GHCi."
597597
;;;###autoload
598598
(defun haskell-mode-show-type-at (&optional insert-value)
599599
"Show type of the thing at point or within active region asynchronously.
600-
Optional argument INSERT-VALUE indicates that recieved type signature should be
601-
inserted (but only if nothing happened since function invocation).
602-
This function requires GHCi-ng (see
603-
https://github.com/chrisdone/ghci-ng#using-with-haskell-mode for instructions)."
600+
This function requires GHCi-ng and `:set +c` option enabled by
601+
default (please follow GHCi-ng README available at URL
602+
`https://github.com/chrisdone/ghci-ng').
603+
604+
\\<haskell-interactive-mode-map>
605+
To make this function works sometimes you need to load the file in REPL
606+
first using command `haskell-process-load-or-reload' bound to
607+
\\[haskell-process-load-or-reload].
608+
609+
Optional argument INSERT-VALUE indicates that
610+
recieved type signature should be inserted (but only if nothing
611+
happened since function invocation)."
604612
(interactive "P")
605613
(let* ((pos (hs-utils/capture-expr-bounds))
606614
(req (hs-utils/compose-type-at-command pos))
@@ -626,41 +634,53 @@ https://github.com/chrisdone/ghci-ng#using-with-haskell-mode for instructions)."
626634
(min-pos (caar pos-reg))
627635
(max-pos (cdar pos-reg))
628636
(sig (hs-utils/reduce-string response))
629-
(split (split-string sig "\\W::\\W" t))
630-
(is-error (not (= (length split) 2))))
631-
632-
(if is-error
633-
;; neither popup presentation buffer
634-
;; nor insert response in error case
635-
(message "Wrong REPL response: %s" sig)
636-
(if insert-value
637-
;; Only insert type signature and do not present it
638-
(if (= (length hs-utils/async-post-command-flag) 1)
639-
(if wrap
640-
;; Handle region case
641-
(progn
642-
(deactivate-mark)
643-
(save-excursion
644-
(delete-region min-pos max-pos)
645-
(goto-char min-pos)
646-
(insert (concat "(" sig ")"))))
647-
;; Non-region cases
648-
(hs-utils/insert-type-signature sig))
649-
;; Some commands registered, prevent insertion
650-
(let* ((rev (reverse hs-utils/async-post-command-flag))
651-
(cs (format "%s" (cdr rev))))
652-
(message
653-
(concat
654-
"Type signature insertion was prevented. "
655-
"These commands were registered:"
656-
cs))))
657-
;; Present the result only when response is valid and not asked to
658-
;; insert result
659-
(let* ((expr (car split))
660-
(buf-name (concat ":type " expr)))
661-
(hs-utils/echo-or-present response buf-name))))
662-
663-
(hs-utils/async-stop-watching-changes init-buffer)))))))
637+
(res-type (hs-utils/parse-repl-response sig)))
638+
639+
(cl-case res-type
640+
;; neither popup presentation buffer
641+
;; nor insert response in error case
642+
('unknown-command
643+
(message
644+
(concat
645+
"This command requires GHCi-ng. "
646+
"Please read command description for details.")))
647+
('option-missing
648+
(message
649+
(concat
650+
"Could not infer type signature. "
651+
"You need to load file first. "
652+
"Also :set +c is required. "
653+
"Please read command description for details.")))
654+
('interactive-error (message "Wrong REPL response: %s" sig))
655+
(otherwise
656+
(if insert-value
657+
;; Only insert type signature and do not present it
658+
(if (= (length hs-utils/async-post-command-flag) 1)
659+
(if wrap
660+
;; Handle region case
661+
(progn
662+
(deactivate-mark)
663+
(save-excursion
664+
(delete-region min-pos max-pos)
665+
(goto-char min-pos)
666+
(insert (concat "(" sig ")"))))
667+
;; Non-region cases
668+
(hs-utils/insert-type-signature sig))
669+
;; Some commands registered, prevent insertion
670+
(let* ((rev (reverse hs-utils/async-post-command-flag))
671+
(cs (format "%s" (cdr rev))))
672+
(message
673+
(concat
674+
"Type signature insertion was prevented. "
675+
"These commands were registered:"
676+
cs))))
677+
;; Present the result only when response is valid and not asked to
678+
;; insert result
679+
(let* ((expr (car (split-string sig "\\W::\\W" t)))
680+
(buf-name (concat ":type " expr)))
681+
(hs-utils/echo-or-present response buf-name))))
682+
683+
(hs-utils/async-stop-watching-changes init-buffer))))))))
664684

665685
;;;###autoload
666686
(defun haskell-process-generate-tags (&optional and-then-find-this-tag)
@@ -970,5 +990,28 @@ execusion."
970990
(remove-hook
971991
'post-command-hook #'hs-utils/async-update-post-command-flag t)))
972992

993+
(defun hs-utils/parse-repl-response (r)
994+
"Parse response R from REPL and return special kind of result.
995+
The result is response string itself with speacial property
996+
response-type added.
997+
998+
This property could be of the following:
999+
1000+
+ unknown-command
1001+
+ option-missing
1002+
+ interactive-error
1003+
+ success"
1004+
(let ((first-line (car (split-string r "\n"))))
1005+
(cond
1006+
((string-match-p "^unknown command" first-line) 'unknown-command)
1007+
((string-match-p "^Couldn't guess that module name. Does it exist?"
1008+
first-line)
1009+
'option-missing)
1010+
((string-match-p "^<interactive>:" first-line) 'interactive-error)
1011+
(t 'success))))
1012+
1013+
1014+
1015+
9731016
(provide 'haskell-commands)
9741017
;;; haskell-commands.el ends here

0 commit comments

Comments
 (0)