Skip to content

Commit 03ced31

Browse files
authored
Merge pull request #1543 from haskell/hask-proc
inf-haskell
2 parents 738bc42 + e2d2585 commit 03ced31

File tree

6 files changed

+448
-746
lines changed

6 files changed

+448
-746
lines changed

doc/haskell-mode.texi

Lines changed: 124 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,13 @@ interpreter (e.g. GHCi).
6767
* Module templates:: Module templates
6868
* Declaration scanning:: How to navigate in a source file
6969
* Compilation:: How to compile
70-
* Inferior Haskell interpreter:: How to interact with GHCi (1)
71-
* Interactive Haskell:: How to interact with GHCi (2)
70+
* Interactive Haskell:: How to interact with GHCi
7271
* Editing Cabal files:: Cabal support
7372
* Browsing Haddocks:: Using @code{w3m} to browse documentation
7473
* Spell checking strings and comments:: Using @code{flyspell-prog-mode}
7574
* Aligning code:: Aligning code using @code{align-regexp}
7675
* Rectangular commands:: Manage indentation manually
76+
* REPL:: GHCi REPL
7777
* Collapsing Haskell code:: View more code on screen
7878
* Getting Help and Reporting Bugs:: How to improve Haskell Mode
7979
* Concept index:: Index of Haskell Mode concepts
@@ -1148,49 +1148,6 @@ temporarily by invoking @code{haskell-compile} with a prefix argument
11481148
same customized compile command, invoke @code{recompile} (bound to
11491149
@kbd{g}) inside the @samp{*haskell-compilation*} buffer.
11501150

1151-
@node Inferior Haskell interpreter
1152-
@chapter Inferior Haskell interpreter
1153-
1154-
@findex inferior-haskell-find-definition
1155-
@findex inferior-haskell-find-haddock
1156-
@findex inferior-haskell-info
1157-
@findex inferior-haskell-load-and-run
1158-
@findex inferior-haskell-load-file
1159-
@findex inferior-haskell-mode
1160-
@findex inferior-haskell-reload-file
1161-
@findex inferior-haskell-start-process
1162-
@findex inferior-haskell-type
1163-
@vindex haskell-program-name
1164-
@vindex inferior-haskell-mode-hook
1165-
1166-
The major mode @code{inferior-haskell-mode} provides support for
1167-
interacting with an inferior Haskell process based on
1168-
@code{comint-mode}.
1169-
1170-
By default the @code{haskell-mode-map} keymap is setup to use this mode:
1171-
1172-
@table @kbd
1173-
@item C-c C-z
1174-
is bound to @code{switch-to-haskell}
1175-
@item C-c C-b
1176-
is bound to @code{switch-to-haskell}
1177-
@item C-c C-l
1178-
is bound to @code{inferior-haskell-load-file}
1179-
@item C-c C-t
1180-
is bound to @code{inferior-haskell-type}
1181-
@item C-c C-i
1182-
is bound to @code{inferior-haskell-info}
1183-
@end table
1184-
1185-
The Haskell interpreter used by the inferior Haskell mode is
1186-
auto-detected by default, but is customizable via the
1187-
@code{haskell-program-name} variable.
1188-
1189-
Currently, GHCi and Hugs are support as Haskell interpreter.
1190-
1191-
TODO/WRITEME
1192-
@c write about supported features
1193-
11941151
@node Interactive Haskell
11951152
@chapter Interactive Haskell
11961153

@@ -2593,6 +2550,128 @@ This will insert the contents of the last killed rectangle.
25932550
As with all Emacs modifier combos, you can type @kbd{C-x r C-h} to find
25942551
out what keys are bound beginning with the @kbd{C-x r} prefix.
25952552

2553+
@node REPL
2554+
@chapter Using GHCi REPL within Emacs
2555+
2556+
To start the REPL you can run one of the following:
2557+
2558+
@itemize
2559+
@item @kbd{M-x run-haskell}
2560+
@item @kbd{M-x switch-to-haskell}
2561+
@end itemize
2562+
2563+
This repl works with @uref{https://www.emacswiki.org/emacs/ComintMode, Comint}.
2564+
So you will feel at home if you are already using @kbd{M-x Shell} or @kbd{M-x ielm}.
2565+
2566+
@code{Inf-Haskell} is a Major mode for running GHCi, with comint.
2567+
2568+
Important key bindings in @code{Inf-haskell}:
2569+
2570+
@table @kbd
2571+
@item RET
2572+
invokes @kbd{comint-send-input}. Sends the input to the GHCi process, evaluates
2573+
the line and returns the output.
2574+
2575+
@item C-d or <delete>
2576+
deletes the forward character
2577+
2578+
@item <C-up> or M-p
2579+
invokes @kbd{comint-previous-input}. Cycle backwards through input history,
2580+
saving input.
2581+
2582+
@item <C-down> or M-n
2583+
invokes @kbd{comint-next-input}. Cycle forwards through input history.
2584+
2585+
@item C-c C-c
2586+
invokes @kbd{comint-interrupt-subjob}. Sends KeyboardInterrupt signal.
2587+
2588+
@item C-c C-\
2589+
invokes @kbd{comint-quit-subjob}. Sends KeyboardInterrupt signal.
2590+
2591+
@item C-c C-z
2592+
invokes @kbd{comint-stop-subjob}. Kills the GHCi process.
2593+
2594+
@item C-c M-r
2595+
invokes @kbd{comint-previous-matching-input-from-input}. If you are familiar
2596+
with @kbd{C-r} in bash. This is the same as that. Searches backwards through
2597+
input history for match for current input.
2598+
2599+
@item C-c M-s
2600+
invokes @kbd{comint-next-matching-input-from-input}. Searches forwards through
2601+
input history for match for current input.
2602+
2603+
@item C-c C-l
2604+
invokes @kbd{comint-dynamic-list-input-ring}. Displays a list of recent inputs
2605+
entered into the current buffer.
2606+
2607+
@item C-c M-o
2608+
invokes @kbd{comint-clear-buffer}. Clears the buffer (Only with Emacs 25.X and above)
2609+
2610+
@item C-c C-n
2611+
invokes @kbd{comint-next-prompt}. Goes to the start of the previous REPL prompt.
2612+
2613+
@item C-c C-p
2614+
invokes @kbd{comint-previous-prompt}. Goes to the start of the next REPL prompt.
2615+
2616+
@item C-c C-o
2617+
invokes @kbd{comint-delete-output}. Clears the output of the most recently evaluated
2618+
expression.
2619+
2620+
@item C-c C-e
2621+
invokes @kbd{comint-show-maximum-output}. Moves the point to the end of the buffer.
2622+
2623+
@item C-c C-u
2624+
invokes @kbd{comint-kill-input}. Kills backward, the line at point. (Use this when you have typed in an expression into the prompt
2625+
but you dont want to evaluate it.)
2626+
2627+
@item C-c C-w
2628+
invokes @kbd{backward-kill-word}. Kills backward, the word at point
2629+
2630+
@item C-c C-s
2631+
invokes @kbd{comint-write-output}. Write output from interpreter since last
2632+
input to FILENAME. Any prompt at the end of the output is not written.
2633+
@end table
2634+
2635+
@section Relevant defcustoms:
2636+
2637+
@multitable @columnfractions .40 .20 .40
2638+
@headitem Interpreter (defcustom) @tab Default Value @tab Possible Values
2639+
@item @code{haskell-process-type} @tab @code{'auto} @tab @code{'stack-ghci, 'cabal-repl, 'ghci, 'auto}
2640+
@item @code{inferior-haskell-hook} @tab @code{nil} @tab -
2641+
@item @code{haskell-process-path-ghci} @tab @code{ghci} @tab -
2642+
@item @code{haskell-process-args-ghci} @tab @code{-ferror-spans} @tab -
2643+
@item @code{haskell-process-path-cabal} @tab @code{cabal} @tab -
2644+
@item @code{haskell-process-args-cabal-repl} @tab @code{--ghc-option=-ferror-spans} @tab -
2645+
@item @code{haskell-process-path-stack} @tab @code{stack} @tab -
2646+
@item @code{haskell-process-args-stack-ghci} @tab @code{--ghci-options=-ferror-spans --no-build --no-load} @tab -
2647+
@end multitable
2648+
2649+
@section More on @code{haskell-process-type}
2650+
2651+
The Haskell interpreter used by @code{Inf-Haskell} is auto-detected by default,
2652+
but is customizable with defcustom @code{haskell-process-type}. The values
2653+
recognized by it are (default is 'auto):
2654+
2655+
@itemize
2656+
@item @code{'stack-ghci}
2657+
@item @code{'cabal-repl}
2658+
@item @code{'ghci}
2659+
@item @code{'auto}
2660+
@end itemize
2661+
2662+
if the @code{haskell-process-type} is @code{'auto}, the directories are searched for
2663+
@code{cabal.sandbox.config} or @code{stack.yaml} or @code{*.cabal} file.
2664+
If the file is present, then appropriate process is started.
2665+
2666+
When @code{cabal.sandbox.config} is found @code{haskell-process-type} is @code{'cabal-repl}.
2667+
Similarly, when @code{stack.yaml} is found @code{haskell-process-type} is @code{'stack-ghci}.
2668+
Similarly, when @code{xyz.cabal} is found @code{haskell-process-type} is @code{'cabal-repl}.
2669+
When nothing is found @code{haskell-process-type} is @code{'ghci}. When more than one
2670+
file such as @code{cabal.sandbox.config} and @code{stack.yaml} are found the following
2671+
preference is followed.
2672+
2673+
@code{cabal.sandbox.config} > @code{stack.yaml} > @code{*.cabal}
2674+
25962675
@node Collapsing Haskell code
25972676
@chapter Collapsing Haskell code
25982677

haskell-customize.el

Lines changed: 58 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,11 @@ be located, then stack-ghci will be used.
6464
Otherwise if there's a *.cabal file, cabal-repl will be used.
6565
6666
If none of the above apply, ghci will be used."
67-
:type '(choice (const auto) (const ghci) (const cabal-repl) (const stack-ghci) (const cabal-new-repl))
67+
:type '(choice (const auto)
68+
(const ghci)
69+
(const cabal-repl)
70+
(const stack-ghci)
71+
(const cabal-new-repl))
6872
:group 'haskell-interactive)
6973

7074
(defcustom haskell-process-wrapper-function
@@ -177,6 +181,22 @@ pass additional flags to `ghc'."
177181
:group 'haskell-interactive
178182
:type '(repeat (string :tag "Argument")))
179183

184+
(defcustom haskell-process-path-ghc
185+
"ghc"
186+
"Path for The Glorious Glasgow Haskell Compiler")
187+
188+
(defcustom haskell-process-args-ghc
189+
"--make -ferror-spans -Wall -fforce-recomp"
190+
"Any arguments for starting ghc.")
191+
192+
(defcustom haskell-process-args-cabal-build
193+
"--ghc-options=\"-ferror-spans -Wall -fforce-recomp\""
194+
"Arguments while doing cabal build.")
195+
196+
(defcustom haskell-process-args-stack-build
197+
"--ghc-options=\"-ferror-spans -Wall\""
198+
"Additional arguments for `stack build' invocation.")
199+
180200
(defcustom haskell-process-do-cabal-format-string
181201
":!cd %s && %s"
182202
"The way to run cabal comands. It takes two arguments -- the directory and the command.
@@ -415,22 +435,43 @@ imports."
415435
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
416436
;; Accessor functions
417437

438+
(defvar inferior-haskell-root-dir nil
439+
"The path which is considered as project root, this is determined by the
440+
presence of a *.cabal file or stack.yaml file or something similar.")
441+
418442
(defun haskell-process-type ()
419-
"Return `haskell-process-type', or a guess if that variable is 'auto."
420-
(if (eq 'auto haskell-process-type)
421-
(cond
422-
;; User has explicitly initialized this project with cabal
423-
((locate-dominating-file default-directory "cabal.sandbox.config")
424-
'cabal-repl)
425-
((and (locate-dominating-file default-directory "stack.yaml")
426-
(executable-find "stack"))
427-
'stack-ghci)
428-
((locate-dominating-file
429-
default-directory
430-
(lambda (d)
431-
(cl-find-if (lambda (f) (string-match-p ".\\.cabal\\'" f)) (directory-files d))))
432-
'cabal-repl)
433-
(t 'ghci))
434-
haskell-process-type))
443+
"Return `haskell-process-type', or a guess if that variable is 'auto.
444+
This function also sets the `inferior-haskell-root-dir'"
445+
(let ((cabal-sandbox (locate-dominating-file default-directory
446+
"cabal.sandbox.config"))
447+
(stack (locate-dominating-file default-directory
448+
"stack.yaml"))
449+
(cabal (locate-dominating-file default-directory
450+
(lambda (d)
451+
(cl-find-if
452+
(lambda (f)
453+
(string-match-p ".\\.cabal\\'" f))
454+
(directory-files d))))))
455+
(if (eq 'auto haskell-process-type)
456+
(cond
457+
;; User has explicitly initialized this project with cabal
458+
((and cabal-sandbox
459+
(executable-find "cabal"))
460+
(setq inferior-haskell-root-dir cabal-sandbox)
461+
'cabal-repl)
462+
((and stack
463+
(executable-find "stack"))
464+
(setq inferior-haskell-root-dir stack)
465+
'stack-ghci)
466+
((and cabal
467+
(executable-find "cabal"))
468+
(setq inferior-haskell-root-dir cabal)
469+
'cabal-repl)
470+
((executable-find "ghc")
471+
(setq inferior-haskell-root-dir default-directory)
472+
'ghci)
473+
(t
474+
(error "Could not find any installation of GHC.")))
475+
haskell-process-type)))
435476

436477
(provide 'haskell-customize)

haskell-doc.el

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1848,6 +1848,14 @@ This function switches to and potentially loads many buffers."
18481848
;; return the result
18491849
doc ))))
18501850

1851+
(defun inferior-haskell-kind (sym)
1852+
"Find the kind of SYM with `:kind' ghci feature."
1853+
(inferior-haskell-get-result (format ":kind %s" sym)))
1854+
1855+
(defun inferior-haskell-type (sym)
1856+
"Find the type of SYM with `:type' ghci feature."
1857+
(inferior-haskell-get-result (format ":type (%s)" sym)))
1858+
18511859
(provide 'haskell-doc)
18521860

18531861
;;; haskell-doc.el ends here

0 commit comments

Comments
 (0)