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.

430 lines
12 KiB

;;; haskell-customize.el --- Customization settings -*- lexical-binding: t -*-
;; Copyright (c) 2014 Chris Done. All rights reserved.
;; 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/>.
;;; Code:
(require 'cl-lib)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Customization variables
;;;###autoload
(defcustom haskell-process-load-or-reload-prompt nil
"Nil means there will be no prompts on starting REPL. Defaults will be accepted."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defgroup haskell nil
"Major mode for editing Haskell programs."
:link '(custom-manual "(haskell-mode)")
:group 'languages
:prefix "haskell-")
(defvar haskell-mode-pkg-base-dir (file-name-directory load-file-name)
"Package base directory of installed `haskell-mode'.
Used for locating additional package data files.")
;;;###autoload
(defcustom haskell-completing-read-function 'ido-completing-read
"Default function to use for completion."
:group 'haskell
:type '(choice
(function-item :tag "ido" :value ido-completing-read)
(function-item :tag "helm" :value helm--completing-read-default)
(function-item :tag "completing-read" :value completing-read)
(function :tag "Custom function")))
;;;###autoload
(defcustom haskell-process-type
'auto
"The inferior Haskell process type to use.
When set to 'auto (the default), the directory contents and
available programs will be used to make a best guess at the
process type:
If the project directory or one of its parents contains a
\"cabal.sandbox.config\" file, then cabal-repl will be used.
If there's a \"stack.yaml\" file and the \"stack\" executable can
be located, then stack-ghci will be used.
Otherwise if there's a *.cabal file, cabal-repl will be used.
If none of the above apply, ghci will be used."
:type '(choice (const auto) (const ghci) (const cabal-repl) (const stack-ghci))
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-wrapper-function
#'identity
"Wrap or transform haskell process commands using this function.
Can be set to a custom function which takes a list of arguments
and returns a possibly-modified list.
The following example function arranges for all haskell process
commands to be started in the current nix-shell environment:
(lambda (argv) (append (list \"nix-shell\" \"-I\" \".\" \"--command\" )
(list (mapconcat 'identity argv \" \"))))
See Info Node `(emacs)Directory Variables' for a way to set this option on
a per-project basis."
:group 'haskell-interactive
:type '(choice
(function-item :tag "None" :value identity)
(function :tag "Custom function")))
;;;###autoload
(defcustom haskell-ask-also-kill-buffers
t
"Ask whether to kill all associated buffers when a session
process is killed."
:type 'boolean
:group 'haskell-interactive)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Configuration
;;;###autoload
(defcustom haskell-doc-prettify-types t
"Replace some parts of types with Unicode characters like \"\"
when showing type information about symbols."
:group 'haskell-doc
:type 'boolean
:safe 'booleanp)
(defvar haskell-process-end-hook nil
"Hook for when the haskell process ends.")
;;;###autoload
(defgroup haskell-interactive nil
"Settings for REPL interaction via `haskell-interactive-mode'"
:link '(custom-manual "(haskell-mode)haskell-interactive-mode")
:group 'haskell)
;;;###autoload
(defcustom haskell-process-path-ghci
"ghci"
"The path for starting ghci."
:group 'haskell-interactive
:type '(choice string (repeat string)))
;;;###autoload
(defcustom haskell-process-path-cabal
"cabal"
"Path to the `cabal' executable."
:group 'haskell-interactive
:type '(choice string (repeat string)))
;;;###autoload
(defcustom haskell-process-path-stack
"stack"
"The path for starting stack."
:group 'haskell-interactive
:type '(choice string (repeat string)))
;;;###autoload
(defcustom haskell-process-args-ghci
'("-ferror-spans")
"Any arguments for starting ghci."
:group 'haskell-interactive
:type '(repeat (string :tag "Argument")))
;;;###autoload
(defcustom haskell-process-args-cabal-repl
'("--ghc-option=-ferror-spans")
"Additional arguments for `cabal repl' invocation.
Note: The settings in `haskell-process-path-ghci' and
`haskell-process-args-ghci' are not automatically reused as `cabal repl'
currently invokes `ghc --interactive'. Use
`--with-ghc=<path-to-executable>' if you want to use a different
interactive GHC frontend; use `--ghc-option=<ghc-argument>' to
pass additional flags to `ghc'."
:group 'haskell-interactive
:type '(repeat (string :tag "Argument")))
;;;###autoload
(defcustom haskell-process-args-stack-ghci
'("--ghc-options=-ferror-spans")
"Additional arguments for `stack ghci' invocation."
:group 'haskell-interactive
:type '(repeat (string :tag "Argument")))
;;;###autoload
(defcustom haskell-process-do-cabal-format-string
":!cd %s && %s"
"The way to run cabal comands. It takes two arguments -- the directory and the command.
See `haskell-process-do-cabal' for more details."
:group 'haskell-interactive
:type 'string)
;;;###autoload
(defcustom haskell-process-log
nil
"Enable debug logging to \"*haskell-process-log*\" buffer."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-show-debug-tips
t
"Show debugging tips when starting the process."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-notify-p
nil
"Notify using notifications.el (if loaded)?"
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-suggest-no-warn-orphans
t
"Suggest adding -fno-warn-orphans pragma to file when getting orphan warnings."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-suggest-hoogle-imports
nil
"Suggest to add import statements using Hoogle as a backend."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-suggest-hayoo-imports
nil
"Suggest to add import statements using Hayoo as a backend."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-hayoo-query-url
"http://hayoo.fh-wedel.de/json/?query=%s"
"Query url for json hayoo results."
:type 'string
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-suggest-haskell-docs-imports
nil
"Suggest to add import statements using haskell-docs as a backend."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-suggest-add-package
t
"Suggest to add packages to your .cabal file when Cabal says it
is a member of the hidden package, blah blah."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-suggest-language-pragmas
t
"Suggest adding LANGUAGE pragmas recommended by GHC."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-suggest-remove-import-lines
nil
"Suggest removing import lines as warned by GHC."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-suggest-overloaded-strings
t
"Suggest adding OverloadedStrings pragma to file when getting type mismatches with [Char]."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-check-cabal-config-on-load
t
"Check changes cabal config on loading Haskell files and
restart the GHCi process if changed.."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-prompt-restart-on-cabal-change
t
"Ask whether to restart the GHCi process when the Cabal file
has changed?"
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-auto-import-loaded-modules
nil
"Auto import the modules reported by GHC to have been loaded?"
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-reload-with-fbytecode
nil
"When using -fobject-code, auto reload with -fbyte-code (and
then restore the -fobject-code) so that all module info and
imports become available?"
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-use-presentation-mode
nil
"Use presentation mode to show things like type info instead of
printing to the message area."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-process-suggest-restart
t
"Suggest restarting the process when it has died"
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-interactive-mode-scroll-to-bottom
nil
"Scroll to bottom in the REPL always."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-interactive-popup-errors
t
"Popup errors in a separate buffer."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-interactive-mode-collapse
nil
"Collapse printed results."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-interactive-types-for-show-ambiguous
t
"Show types when there's no Show instance or there's an
ambiguous class constraint."
:type 'boolean
:group 'haskell-interactive)
(defvar haskell-interactive-prompt "λ> "
"The prompt to use.")
;;;###autoload
(defcustom haskell-interactive-mode-eval-mode
nil
"Use the given mode's font-locking to render some text."
:type '(choice function (const :tag "None" nil))
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-interactive-mode-hide-multi-line-errors
nil
"Hide collapsible multi-line compile messages by default."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-interactive-mode-delete-superseded-errors
t
"Whether to delete compile messages superseded by recompile/reloads."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-interactive-mode-include-file-name
t
"Include the file name of the module being compiled when
printing compilation messages."
:type 'boolean
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-import-mapping
'()
"Support a mapping from module to import lines.
E.g. '((\"Data.Map\" . \"import qualified Data.Map as M
import Data.Map (Map)
\"))
This will import
import qualified Data.Map as M
import Data.Map (Map)
when Data.Map is the candidate.
"
:type '(repeat (cons (string :tag "Module name")
(string :tag "Import lines")))
:group 'haskell-interactive)
;;;###autoload
(defcustom haskell-language-extensions
'()
"Language extensions in use. Should be in format: -XFoo,
-XNoFoo etc. The idea is that various tools written with HSE (or
any haskell-mode code that needs to be aware of syntactical
properties; such as an indentation mode) that don't know what
extensions to use can use this variable. Examples: hlint,
hindent, structured-haskell-mode, tool-de-jour, etc.
You can set this per-project with a .dir-locals.el file, in the
same vein as `haskell-indent-spaces'."
:group 'haskell
:type '(repeat 'string))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Accessor functions
(defun haskell-process-type ()
"Return `haskell-process-type', or a guess if that variable is 'auto."
(if (eq 'auto haskell-process-type)
(cond
;; User has explicitly initialized this project with cabal
((locate-dominating-file default-directory "cabal.sandbox.config")
'cabal-repl)
((and (locate-dominating-file default-directory "stack.yaml")
(executable-find "stack"))
'stack-ghci)
((locate-dominating-file
default-directory
(lambda (d)
(cl-find-if (lambda (f) (string-match-p ".\\.cabal\\'" f)) (directory-files d))))
'cabal-repl)
(t 'ghci))
haskell-process-type))
(provide 'haskell-customize)