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.

125 lines
5.4 KiB

4 years ago
  1. ;;; haskell-repl.el --- REPL evaluation -*- lexical-binding: t -*-
  2. ;; Copyright (c) 2014 Chris Done. All rights reserved.
  3. ;; This file is free software; you can redistribute it and/or modify
  4. ;; it under the terms of the GNU General Public License as published by
  5. ;; the Free Software Foundation; either version 3, or (at your option)
  6. ;; any later version.
  7. ;; This file is distributed in the hope that it will be useful,
  8. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. ;; GNU General Public License for more details.
  11. ;; You should have received a copy of the GNU General Public License
  12. ;; along with this program. If not, see <http://www.gnu.org/licenses/>.
  13. ;;; Code:
  14. (require 'cl-lib)
  15. (require 'haskell-interactive-mode)
  16. (require 'haskell-collapse)
  17. (require 'haskell-svg)
  18. (defun haskell-interactive-handle-expr ()
  19. "Handle an inputted expression at the REPL."
  20. (let ((expr (haskell-interactive-mode-input)))
  21. (if (string= "" (replace-regexp-in-string " " "" expr))
  22. ;; Just make a new prompt on space-only input
  23. (progn
  24. (goto-char (point-max))
  25. (insert "\n")
  26. (haskell-interactive-mode-prompt))
  27. (when (haskell-interactive-at-prompt)
  28. (cond
  29. ;; If already evaluating, then the user is trying to send
  30. ;; input to the REPL during evaluation. Most likely in
  31. ;; response to a getLine-like function.
  32. ((and (haskell-process-evaluating-p (haskell-interactive-process))
  33. (= (line-end-position) (point-max)))
  34. (goto-char (point-max))
  35. (let ((process (haskell-interactive-process))
  36. (string (buffer-substring-no-properties
  37. haskell-interactive-mode-result-end
  38. (point))))
  39. ;; here we need to go to end of line again as evil-mode
  40. ;; might have managed to put us one char back
  41. (goto-char (point-max))
  42. (insert "\n")
  43. ;; Bring the marker forward
  44. (setq haskell-interactive-mode-result-end
  45. (point-max))
  46. (haskell-process-set-sent-stdin process t)
  47. (haskell-process-send-string process string)))
  48. ;; Otherwise we start a normal evaluation call.
  49. (t (setq haskell-interactive-mode-old-prompt-start
  50. (copy-marker haskell-interactive-mode-prompt-start))
  51. (set-marker haskell-interactive-mode-prompt-start (point-max))
  52. (haskell-interactive-mode-history-add expr)
  53. (haskell-interactive-mode-do-expr expr)))))))
  54. (defun haskell-interactive-mode-do-expr (expr)
  55. (cond
  56. ((string-match "^:present " expr)
  57. (haskell-interactive-mode-do-presentation (replace-regexp-in-string "^:present " "" expr)))
  58. (t
  59. (haskell-interactive-mode-run-expr expr))))
  60. (defun haskell-interactive-mode-run-expr (expr)
  61. "Run the given expression."
  62. (let ((session (haskell-interactive-session))
  63. (process (haskell-interactive-process)))
  64. (haskell-process-queue-command
  65. process
  66. (make-haskell-command
  67. :state (list session process expr 0)
  68. :go (lambda (state)
  69. (goto-char (point-max))
  70. (insert "\n")
  71. (setq haskell-interactive-mode-result-end
  72. (point-max))
  73. (haskell-process-send-string (cadr state)
  74. (haskell-interactive-mode-multi-line (cl-caddr state)))
  75. (haskell-process-set-evaluating (cadr state) t))
  76. :live (lambda (state buffer)
  77. (unless (and (string-prefix-p ":q" (cl-caddr state))
  78. (string-prefix-p (cl-caddr state) ":quit"))
  79. (let* ((cursor (cl-cadddr state))
  80. (next (replace-regexp-in-string
  81. haskell-process-prompt-regex
  82. ""
  83. (substring buffer cursor))))
  84. (haskell-interactive-mode-eval-result (car state) next)
  85. (setf (cl-cdddr state) (list (length buffer)))
  86. nil)))
  87. :complete
  88. (lambda (state response)
  89. (haskell-process-set-evaluating (cadr state) nil)
  90. (unless (haskell-interactive-mode-trigger-compile-error state response)
  91. (haskell-interactive-mode-expr-result state response)))))))
  92. (defun haskell-interactive-mode-expr-result (state response)
  93. "Print the result of evaluating the expression."
  94. (let ((response
  95. (with-temp-buffer
  96. (insert response)
  97. (haskell-interactive-mode-handle-h)
  98. (buffer-string))))
  99. (when haskell-interactive-mode-eval-mode
  100. (unless (haskell-process-sent-stdin-p (cadr state))
  101. (haskell-interactive-mode-eval-as-mode (car state) response))))
  102. (haskell-interactive-mode-prompt (car state)))
  103. (defun haskell-interactive-mode-eval-as-mode (session text)
  104. "Insert TEXT font-locked according to `haskell-interactive-mode-eval-mode'."
  105. (with-current-buffer (haskell-session-interactive-buffer session)
  106. (let ((inhibit-read-only t))
  107. (delete-region (1+ haskell-interactive-mode-prompt-start) (point))
  108. (goto-char (point-max))
  109. (insert (haskell-fontify-as-mode (haskell-svg-maybe-render-images text)
  110. haskell-interactive-mode-eval-mode))
  111. (when haskell-interactive-mode-collapse
  112. (haskell-hide-toggle)))))
  113. (provide 'haskell-repl)