Skip to content

Commit 2ba1d10

Browse files
committed
Rewrite core functionality of haskell-mode-show-type-at
Make function asyncronous, remove unnecessary synchronous `haskell-mode-type-at` function. Insert type signature only if nothing changed and there was valid response. Present result in case of presentation mode, otherwise put it in echo area. Do not present result if asked to insert result.
1 parent 789f2a1 commit 2ba1d10

File tree

1 file changed

+64
-56
lines changed

1 file changed

+64
-56
lines changed

haskell-commands.el

Lines changed: 64 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -495,36 +495,6 @@ GHCi."
495495
(error (propertize "No reply. Is :loc-at supported?"
496496
'face 'compilation-error)))))))
497497

498-
(defun haskell-mode-type-at ()
499-
"Get the type of the thing at point. Requires the :type-at
500-
command from GHCi."
501-
(let ((pos (or (when (region-active-p)
502-
(cons (region-beginning)
503-
(region-end)))
504-
(haskell-spanable-pos-at-point)
505-
(cons (point)
506-
(point)))))
507-
(when pos
508-
(replace-regexp-in-string
509-
"\n$"
510-
""
511-
(save-excursion
512-
(haskell-process-queue-sync-request
513-
(haskell-interactive-process)
514-
(replace-regexp-in-string
515-
"\n"
516-
" "
517-
(format ":type-at %s %d %d %d %d %s"
518-
(buffer-file-name)
519-
(progn (goto-char (car pos))
520-
(line-number-at-pos))
521-
(1+ (current-column))
522-
(progn (goto-char (cdr pos))
523-
(line-number-at-pos))
524-
(1+ (current-column))
525-
(buffer-substring-no-properties (car pos)
526-
(cdr pos))))))))))
527-
528498
;;;###autoload
529499
(defun haskell-process-cd (&optional not-interactive)
530500
"Change directory."
@@ -620,33 +590,71 @@ command from GHCi."
620590

621591
;;;###autoload
622592
(defun haskell-mode-show-type-at (&optional insert-value)
623-
"Show the type of the thing at point."
593+
"Show type of the thing at point or within active region asynchronously.
594+
Optional argument INSERT-VALUE indicates that recieved type signature should be
595+
inserted (but only if nothing happened since function invocation).
596+
This function requires GHCi-ng (see
597+
https://github.com/chrisdone/ghci-ng#using-with-haskell-mode for instructions)."
624598
(interactive "P")
625-
(let ((ty (haskell-mode-type-at))
626-
(orig (point)))
627-
(unless (= (aref ty 0) ?\n)
628-
;; That seems to be what happens when `haskell-mode-type-at` fails
629-
(if insert-value
630-
(let ((ident-pos (or (haskell-ident-pos-at-point)
631-
(cons (point) (point)))))
632-
(cond
633-
((region-active-p)
634-
(delete-region (region-beginning)
635-
(region-end))
636-
(insert "(" ty ")")
637-
(goto-char (1+ orig)))
638-
((= (line-beginning-position) (car ident-pos))
639-
(goto-char (line-beginning-position))
640-
(insert (haskell-fontify-as-mode ty 'haskell-mode)
641-
"\n"))
642-
(t
643-
(save-excursion
644-
(goto-char (car ident-pos))
645-
(let ((col (current-column)))
646-
(save-excursion (insert "\n")
647-
(indent-to col))
648-
(insert (haskell-fontify-as-mode ty 'haskell-mode)))))))
649-
(message "%s" (haskell-fontify-as-mode ty 'haskell-mode))))))
599+
(let* ((pos (hs-utils/capture-expr-bounds))
600+
(req (hs-utils/compose-type-at-command pos))
601+
(process (haskell-interactive-process))
602+
(buf (current-buffer))
603+
(pos-reg (cons pos (region-active-p))))
604+
(haskell-process-queue-command
605+
process
606+
(make-haskell-command
607+
:state (list process req buf insert-value pos-reg)
608+
:go
609+
(lambda (state)
610+
(let* ((prc (car state))
611+
(req (nth 1 state)))
612+
(hs-utils/async-watch-changes)
613+
(haskell-process-send-string prc req)))
614+
:complete
615+
(lambda (state response)
616+
(let* ((init-buffer (nth 2 state))
617+
(insert-value (nth 3 state))
618+
(pos-reg (nth 4 state))
619+
(wrap (cdr pos-reg))
620+
(min-pos (caar pos-reg))
621+
(max-pos (cdar pos-reg))
622+
(sig (hs-utils/reduce-string response))
623+
(split (split-string sig "\\W::\\W" t))
624+
(is-error (not (= (length split) 2))))
625+
626+
(if is-error
627+
;; neither popup presentation buffer
628+
;; nor insert response in error case
629+
(message "Wrong REPL response: %s" sig)
630+
(if insert-value
631+
;; Only insert type signature and do not present it
632+
(if (= (length hs-utils/async-post-command-flag) 1)
633+
(if wrap
634+
;; Handle region case
635+
(progn
636+
(deactivate-mark)
637+
(save-excursion
638+
(delete-region min-pos max-pos)
639+
(goto-char min-pos)
640+
(insert (concat "(" sig ")"))))
641+
;; Non-region cases
642+
(hs-utils/insert-type-signature sig))
643+
;; Some commands registered, prevent insertion
644+
(let* ((rev (reverse hs-utils/async-post-command-flag))
645+
(cs (format "%s" (cdr rev))))
646+
(message
647+
(concat
648+
"Type signature insertion was prevented. "
649+
"These commands were registered:"
650+
cs))))
651+
;; Present the result only when response is valid and not asked to
652+
;; insert result
653+
(let* ((expr (car split))
654+
(buf-name (concat ":type " expr)))
655+
(hs-utils/echo-or-present response buf-name))))
656+
657+
(hs-utils/async-stop-watching-changes init-buffer)))))))
650658

651659
;;;###autoload
652660
(defun haskell-process-generate-tags (&optional and-then-find-this-tag)

0 commit comments

Comments
 (0)