about summary refs log tree commit diff
path: root/configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell.el
diff options
context:
space:
mode:
Diffstat (limited to 'configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell.el')
-rw-r--r--configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell.el528
1 files changed, 528 insertions, 0 deletions
diff --git a/configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell.el b/configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell.el
new file mode 100644
index 000000000000..641fea35676c
--- /dev/null
+++ b/configs/shared/emacs/.emacs.d/elpa/haskell-mode-20180601.143/haskell.el
@@ -0,0 +1,528 @@
+;;; haskell.el --- Top-level Haskell package -*- lexical-binding: t -*-
+
+;; Copyright © 2014 Chris Done.  All rights reserved.
+;;             2016 Arthur Fayzrakhmanov
+
+;; This file is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation; either version 3, or (at your option)
+;; any later version.
+
+;; This file is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'haskell-mode)
+(require 'haskell-hoogle)
+(require 'haskell-process)
+(require 'haskell-debug)
+(require 'haskell-interactive-mode)
+(require 'haskell-repl)
+(require 'haskell-load)
+(require 'haskell-commands)
+(require 'haskell-modules)
+(require 'haskell-string)
+(require 'haskell-completions)
+(require 'haskell-utils)
+(require 'haskell-customize)
+
+(defvar interactive-haskell-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map (kbd "C-c C-l") 'haskell-process-load-file)
+    (define-key map (kbd "C-c C-r") 'haskell-process-reload)
+    (define-key map (kbd "C-c C-t") 'haskell-process-do-type)
+    (define-key map (kbd "C-c C-i") 'haskell-process-do-info)
+    (define-key map (kbd "M-.") 'haskell-mode-jump-to-def-or-tag)
+    (define-key map (kbd "C-c C-k") 'haskell-interactive-mode-clear)
+    (define-key map (kbd "C-c C-c") 'haskell-process-cabal-build)
+    (define-key map (kbd "C-c C-v") 'haskell-cabal-visit-file)
+    (define-key map (kbd "C-c C-x") 'haskell-process-cabal)
+    (define-key map (kbd "C-c C-b") 'haskell-interactive-switch)
+    (define-key map (kbd "C-c C-z") 'haskell-interactive-switch)
+    map)
+  "Keymap for using `interactive-haskell-mode'.")
+
+;;;###autoload
+(define-minor-mode interactive-haskell-mode
+  "Minor mode for enabling haskell-process interaction."
+  :lighter " Interactive"
+  :keymap interactive-haskell-mode-map
+  (add-hook 'completion-at-point-functions
+            #'haskell-completions-sync-repl-completion-at-point
+            nil
+            t))
+
+(make-obsolete 'haskell-process-completions-at-point
+               'haskell-completions-sync-repl-completion-at-point
+               "June 19, 2015")
+
+(defun haskell-process-completions-at-point ()
+  "A `completion-at-point' function using the current haskell process."
+  (when (haskell-session-maybe)
+    (let ((process (haskell-process))
+          symbol-bounds)
+      (cond
+       ;; ghci can complete module names, but it needs the "import "
+       ;; string at the beginning
+       ((looking-back (rx line-start
+                          "import" (1+ space)
+                          (? "qualified" (1+ space))
+                          (group (? (char upper) ; modid
+                                    (* (char alnum ?' ?.)))))
+                      (line-beginning-position))
+        (let ((text (match-string-no-properties 0))
+              (start (match-beginning 1))
+              (end (match-end 1)))
+          (list start end
+                (haskell-process-get-repl-completions process text))))
+       ;; Complete OPTIONS, a completion list comes from variable
+       ;; `haskell-ghc-supported-options'
+       ((and (nth 4 (syntax-ppss))
+           (save-excursion
+             (let ((p (point)))
+               (and (search-backward "{-#" nil t)
+                  (search-forward-regexp "\\_<OPTIONS\\(?:_GHC\\)?\\_>" p t))))
+           (looking-back
+            (rx symbol-start "-" (* (char alnum ?-)))
+            (line-beginning-position)))
+        (list (match-beginning 0) (match-end 0) haskell-ghc-supported-options))
+       ;; Complete LANGUAGE, a list of completions comes from variable
+       ;; `haskell-ghc-supported-extensions'
+       ((and (nth 4 (syntax-ppss))
+           (save-excursion
+             (let ((p (point)))
+               (and (search-backward "{-#" nil t)
+                  (search-forward-regexp "\\_<LANGUAGE\\_>" p t))))
+           (setq symbol-bounds (bounds-of-thing-at-point 'symbol)))
+        (list (car symbol-bounds) (cdr symbol-bounds)
+              haskell-ghc-supported-extensions))
+       ((setq symbol-bounds (haskell-ident-pos-at-point))
+        (cl-destructuring-bind (start . end) symbol-bounds
+          (list start end
+                (haskell-process-get-repl-completions
+                 process (buffer-substring-no-properties start end)))))))))
+
+;;;###autoload
+(defun haskell-interactive-mode-return ()
+  "Handle the return key."
+  (interactive)
+  (cond
+   ;; At a compile message, jump to the location of the error in the
+   ;; source.
+   ((haskell-interactive-at-compile-message)
+    (next-error-internal))
+   ;; At the input prompt, handle the expression in the usual way.
+   ((haskell-interactive-at-prompt)
+    (haskell-interactive-handle-expr))
+   ;; At any other location in the buffer, copy the line to the
+   ;; current prompt.
+   (t
+    (haskell-interactive-copy-to-prompt))))
+
+;;;###autoload
+(defun haskell-session-kill (&optional leave-interactive-buffer)
+  "Kill the session process and buffer, delete the session.
+0. Prompt to kill all associated buffers.
+1. Kill the process.
+2. Kill the interactive buffer unless LEAVE-INTERACTIVE-BUFFER is not given.
+3. Walk through all the related buffers and set their haskell-session to nil.
+4. Remove the session from the sessions list."
+  (interactive)
+  (haskell-mode-toggle-interactive-prompt-state)
+  (unwind-protect
+      (let* ((session (haskell-session))
+             (name (haskell-session-name session))
+             (also-kill-buffers
+              (and haskell-ask-also-kill-buffers
+                   (y-or-n-p
+                    (format "Killing `%s'. Also kill all associated buffers?"
+                            name)))))
+        (haskell-kill-session-process session)
+        (unless leave-interactive-buffer
+          (kill-buffer (haskell-session-interactive-buffer session)))
+        (cl-loop for buffer in (buffer-list)
+                 do (with-current-buffer buffer
+                      (when (and (boundp 'haskell-session)
+                                 (string= (haskell-session-name haskell-session)
+                                          name))
+                        (setq haskell-session nil)
+                        (when also-kill-buffers
+                          (kill-buffer)))))
+        (setq haskell-sessions
+              (cl-remove-if (lambda (session)
+                              (string= (haskell-session-name session)
+                                       name))
+                            haskell-sessions)))
+    (haskell-mode-toggle-interactive-prompt-state t)))
+
+;;;###autoload
+(defun haskell-interactive-kill ()
+  "Kill the buffer and (maybe) the session."
+  (interactive)
+  (when (eq major-mode 'haskell-interactive-mode)
+    (haskell-mode-toggle-interactive-prompt-state)
+    (unwind-protect
+        (when (and (boundp 'haskell-session)
+                   haskell-session
+                   (y-or-n-p "Kill the whole session?"))
+          (haskell-session-kill t)))
+    (haskell-mode-toggle-interactive-prompt-state t)))
+
+(defun haskell-session-make (name)
+  "Make a Haskell session."
+  (when (haskell-session-lookup name)
+    (error "Session of name %s already exists!" name))
+  (let ((session (setq haskell-session
+                       (list (cons 'name name)))))
+    (add-to-list 'haskell-sessions session)
+    (haskell-process-start session)
+    session))
+
+(defun haskell-session-new-assume-from-cabal ()
+  "Prompt to create a new project based on a guess from the nearest Cabal file.
+If `haskell-process-load-or-reload-prompt' is nil, accept `default'."
+  (let ((name (haskell-session-default-name)))
+    (unless (haskell-session-lookup name)
+      (haskell-mode-toggle-interactive-prompt-state)
+      (unwind-protect
+          (if (or (not haskell-process-load-or-reload-prompt)
+                  (y-or-n-p (format "Start a new project named “%s”? " name)))
+              (haskell-session-make name))
+        (haskell-mode-toggle-interactive-prompt-state t)))))
+
+;;;###autoload
+(defun haskell-session ()
+  "Get the Haskell session, prompt if there isn't one or fail."
+  (or (haskell-session-maybe)
+      (haskell-session-assign
+       (or (haskell-session-from-buffer)
+           (haskell-session-new-assume-from-cabal)
+           (haskell-session-choose)
+           (haskell-session-new)))))
+
+;;;###autoload
+(defun haskell-interactive-switch ()
+  "Switch to the interactive mode for this session."
+  (interactive)
+  (let ((initial-buffer (current-buffer))
+        (buffer (haskell-session-interactive-buffer (haskell-session))))
+    (with-current-buffer buffer
+      (setq haskell-interactive-previous-buffer initial-buffer))
+    (unless (eq buffer (window-buffer))
+      (switch-to-buffer-other-window buffer))))
+
+(defun haskell-session-new ()
+  "Make a new session."
+  (let ((name (read-from-minibuffer "Project name: " (haskell-session-default-name))))
+    (when (not (string= name ""))
+      (let ((session (haskell-session-lookup name)))
+        (haskell-mode-toggle-interactive-prompt-state)
+        (unwind-protect
+            (if session
+                (when
+                    (y-or-n-p
+                     (format "Session %s already exists. Use it?" name))
+                  session)
+              (haskell-session-make name)))
+        (haskell-mode-toggle-interactive-prompt-state t)))))
+
+;;;###autoload
+(defun haskell-session-change ()
+  "Change the session for the current buffer."
+  (interactive)
+  (haskell-session-assign (or (haskell-session-new-assume-from-cabal)
+                              (haskell-session-choose)
+                              (haskell-session-new))))
+
+(defun haskell-process-prompt-restart (process)
+  "Prompt to restart the died PROCESS."
+  (let ((process-name (haskell-process-name process))
+        (cursor-in-echo-area t))
+    (if haskell-process-suggest-restart
+        (progn
+          (haskell-mode-toggle-interactive-prompt-state)
+          (unwind-protect
+              (cond
+               ((string-match "You need to re-run the 'configure' command."
+                              (haskell-process-response process))
+                (cl-case (read-char-choice
+                          (concat
+                           "The Haskell process ended. Cabal wants you to run "
+                           (propertize "cabal configure"
+                                       'face
+                                       'font-lock-keyword-face)
+                           " because there is a version mismatch. Re-configure (y, n, l: view log)?"
+                           "\n\n"
+                           "Cabal said:\n\n"
+                           (propertize (haskell-process-response process)
+                                       'face
+                                       'font-lock-comment-face))
+                          '(?l ?n ?y))
+                  (?y (let ((default-directory
+                              (haskell-session-cabal-dir
+                               (haskell-process-session process))))
+                        (message "%s"
+                                 (shell-command-to-string "cabal configure"))))
+                  (?l (let* ((response (haskell-process-response process))
+                             (buffer (get-buffer "*haskell-process-log*")))
+                        (if buffer
+                            (switch-to-buffer buffer)
+                          (progn (switch-to-buffer
+                                  (get-buffer-create "*haskell-process-log*"))
+                                 (insert response)))))
+                  (?n)))
+               (t
+                (cl-case (read-char-choice
+                          (propertize
+                           (format "The Haskell process `%s' has died. Restart? (y, n, l: show process log) "
+                                   process-name)
+                           'face
+                           'minibuffer-prompt)
+                          '(?l ?n ?y))
+                  (?y (haskell-process-start (haskell-process-session process)))
+                  (?l (let* ((response (haskell-process-response process))
+                             (buffer (get-buffer "*haskell-process-log*")))
+                        (if buffer
+                            (switch-to-buffer buffer)
+                          (progn (switch-to-buffer
+                                  (get-buffer-create "*haskell-process-log*"))
+                                 (insert response)))))
+                  (?n))))
+            ;; unwind
+            (haskell-mode-toggle-interactive-prompt-state t)))
+      (message "The Haskell process `%s' is dearly departed." process-name))))
+
+(defun haskell-process ()
+  "Get the current process from the current session."
+  (haskell-session-process (haskell-session)))
+
+;;;###autoload
+(defun haskell-kill-session-process (&optional session)
+  "Kill the process."
+  (interactive)
+  (let* ((session (or session (haskell-session)))
+         (existing-process (get-process (haskell-session-name session))))
+    (when (processp existing-process)
+      (haskell-interactive-mode-echo session "Killing process ...")
+      (haskell-process-set (haskell-session-process session) 'is-restarting t)
+      (delete-process existing-process))))
+
+;;;###autoload
+(defun haskell-interactive-mode-visit-error ()
+  "Visit the buffer of the current (or last) error message."
+  (interactive)
+  (with-current-buffer (haskell-session-interactive-buffer (haskell-session))
+    (if (progn (goto-char (line-beginning-position))
+               (looking-at haskell-interactive-mode-error-regexp))
+        (progn (forward-line -1)
+               (haskell-interactive-jump-to-error-line))
+      (progn (goto-char (point-max))
+             (haskell-interactive-mode-error-backward)
+             (haskell-interactive-jump-to-error-line)))))
+
+(defvar xref-prompt-for-identifier nil)
+
+;;;###autoload
+(defun haskell-mode-jump-to-tag (&optional next-p)
+  "Jump to the tag of the given identifier.
+
+Give optional NEXT-P parameter to override value of
+`xref-prompt-for-identifier' during definition search."
+  (interactive "P")
+  (let ((ident (haskell-string-drop-qualifier (haskell-ident-at-point)))
+        (tags-file-dir (haskell-cabal--find-tags-dir))
+        (tags-revert-without-query t))
+    (when (and ident
+               (not (string= "" (haskell-string-trim ident)))
+               tags-file-dir)
+      (let ((tags-file-name (concat tags-file-dir "TAGS")))
+        (cond ((file-exists-p tags-file-name)
+               (let ((xref-prompt-for-identifier next-p))
+                 (xref-find-definitions ident)))
+              (t (haskell-mode-generate-tags ident)))))))
+
+;;;###autoload
+(defun haskell-mode-after-save-handler ()
+  "Function that will be called after buffer's saving."
+  (when haskell-tags-on-save
+    (ignore-errors (haskell-mode-generate-tags))))
+
+;;;###autoload
+(defun haskell-mode-tag-find (&optional _next-p)
+  "The tag find function, specific for the particular session."
+  (interactive "P")
+  (cond
+   ((elt (syntax-ppss) 3) ;; Inside a string
+    (haskell-mode-jump-to-filename-in-string))
+   (t (call-interactively 'haskell-mode-jump-to-tag))))
+
+(defun haskell-mode-jump-to-filename-in-string ()
+  "Jump to the filename in the current string."
+  (let* ((string (save-excursion
+                   (buffer-substring-no-properties
+                    (1+ (search-backward-regexp "\"" (line-beginning-position) nil 1))
+                    (1- (progn (forward-char 1)
+                               (search-forward-regexp "\"" (line-end-position) nil 1))))))
+         (fp (expand-file-name string
+                               (haskell-session-cabal-dir (haskell-session)))))
+    (find-file
+     (read-file-name
+      ""
+      fp
+      fp))))
+
+;;;###autoload
+(defun haskell-interactive-bring ()
+  "Bring up the interactive mode for this session."
+  (interactive)
+  (let* ((session (haskell-session))
+         (buffer (haskell-session-interactive-buffer session)))
+    (pop-to-buffer buffer)))
+
+;;;###autoload
+(defun haskell-process-load-file ()
+  "Load the current buffer file."
+  (interactive)
+  (save-buffer)
+  (haskell-interactive-mode-reset-error (haskell-session))
+  (haskell-process-file-loadish (format "load \"%s\"" (replace-regexp-in-string
+                                                       "\""
+                                                       "\\\\\""
+                                                       (buffer-file-name)))
+                                nil
+                                (current-buffer)))
+
+;;;###autoload
+(defun haskell-process-reload ()
+  "Re-load the current buffer file."
+  (interactive)
+  (save-buffer)
+  (haskell-interactive-mode-reset-error (haskell-session))
+  (haskell-process-file-loadish "reload" t (current-buffer)))
+
+;;;###autoload
+(defun haskell-process-reload-file () (haskell-process-reload))
+
+(make-obsolete 'haskell-process-reload-file 'haskell-process-reload
+               "2015-11-14")
+
+;;;###autoload
+(defun haskell-process-load-or-reload (&optional toggle)
+  "Load or reload. Universal argument toggles which."
+  (interactive "P")
+  (if toggle
+      (progn (setq haskell-reload-p (not haskell-reload-p))
+             (message "%s (No action taken this time)"
+                      (if haskell-reload-p
+                          "Now running :reload."
+                        "Now running :load <buffer-filename>.")))
+    (if haskell-reload-p (haskell-process-reload) (haskell-process-load-file))))
+
+(make-obsolete 'haskell-process-load-or-reload 'haskell-process-load-file
+               "2015-11-14")
+
+;;;###autoload
+(defun haskell-process-cabal-build ()
+  "Build the Cabal project."
+  (interactive)
+  (haskell-process-do-cabal "build")
+  (haskell-process-add-cabal-autogen))
+
+;;;###autoload
+(defun haskell-process-cabal (p)
+  "Prompts for a Cabal command to run."
+  (interactive "P")
+  (if p
+      (haskell-process-do-cabal
+       (read-from-minibuffer "Cabal command (e.g. install): "))
+    (haskell-process-do-cabal
+     (funcall haskell-completing-read-function "Cabal command: "
+              (append haskell-cabal-commands
+                      (list "build --ghc-options=-fforce-recomp"))))))
+
+(defun haskell-process-file-loadish (command reload-p module-buffer)
+  "Run a loading-ish COMMAND that wants to pick up type errors\
+and things like that.  RELOAD-P indicates whether the notification
+should say 'reloaded' or 'loaded'.  MODULE-BUFFER may be used
+for various things, but is optional."
+  (let ((session (haskell-session)))
+    (haskell-session-current-dir session)
+    (when haskell-process-check-cabal-config-on-load
+      (haskell-process-look-config-changes session))
+    (let ((process (haskell-process)))
+      (haskell-process-queue-command
+       process
+       (make-haskell-command
+        :state (list session process command reload-p module-buffer)
+        :go (lambda (state)
+              (haskell-process-send-string
+               (cadr state) (format ":%s" (cl-caddr state))))
+        :live (lambda (state buffer)
+                (haskell-process-live-build
+                 (cadr state) buffer nil))
+        :complete (lambda (state response)
+                    (haskell-process-load-complete
+                     (car state)
+                     (cadr state)
+                     response
+                     (cl-cadddr state)
+                     (cl-cadddr (cdr state)))))))))
+
+;;;###autoload
+(defun haskell-process-minimal-imports ()
+  "Dump minimal imports."
+  (interactive)
+  (unless (> (save-excursion
+               (goto-char (point-min))
+               (haskell-navigate-imports-go)
+               (point))
+             (point))
+    (goto-char (point-min))
+    (haskell-navigate-imports-go))
+  (haskell-process-queue-sync-request (haskell-process)
+                                      ":set -ddump-minimal-imports")
+  (haskell-process-load-file)
+  (insert-file-contents-literally
+   (concat (haskell-session-current-dir (haskell-session))
+           "/"
+           (haskell-guess-module-name-from-file-name (buffer-file-name))
+           ".imports")))
+
+(defun haskell-interactive-jump-to-error-line ()
+  "Jump to the error line."
+  (let ((orig-line (buffer-substring-no-properties (line-beginning-position)
+                                                   (line-end-position))))
+    (and (string-match "^\\([^:]+\\):\\([0-9]+\\):\\([0-9]+\\)\\(-[0-9]+\\)?:" orig-line)
+         (let* ((file (match-string 1 orig-line))
+                (line (match-string 2 orig-line))
+                (col (match-string 3 orig-line))
+                (session (haskell-interactive-session))
+                (cabal-path (haskell-session-cabal-dir session))
+                (src-path (haskell-session-current-dir session))
+                (cabal-relative-file (expand-file-name file cabal-path))
+                (src-relative-file (expand-file-name file src-path)))
+           (let ((file (cond ((file-exists-p cabal-relative-file)
+                              cabal-relative-file)
+                             ((file-exists-p src-relative-file)
+                              src-relative-file))))
+             (when file
+               (other-window 1)
+               (find-file file)
+               (haskell-interactive-bring)
+               (goto-char (point-min))
+               (forward-line (1- (string-to-number line)))
+               (goto-char (+ (point) (string-to-number col) -1))
+               (haskell-mode-message-line orig-line)
+               t))))))
+
+(provide 'haskell)
+;;; haskell.el ends here