From 4f768a8bdf376af1034075f7a194b8866dd3377d Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Wed, 19 Nov 2014 09:07:34 +0900 Subject: [PATCH 01/13] adding docs in the piki format. --- doc/Makefile | 10 ++ doc/bug.piki | 41 +++++++++ doc/copyright.piki | 5 + doc/emacs.piki | 215 +++++++++++++++++++++++++++++++++++++++++++ doc/ghc-mod.piki | 38 ++++++++ doc/ghc-modi.piki | 48 ++++++++++ doc/history.piki | 3 + doc/index.piki | 26 ++++++ doc/install.piki | 28 ++++++ doc/preparation.piki | 67 ++++++++++++++ 10 files changed, 481 insertions(+) create mode 100644 doc/Makefile create mode 100644 doc/bug.piki create mode 100644 doc/copyright.piki create mode 100644 doc/emacs.piki create mode 100644 doc/ghc-mod.piki create mode 100644 doc/ghc-modi.piki create mode 100644 doc/history.piki create mode 100644 doc/index.piki create mode 100644 doc/install.piki create mode 100644 doc/preparation.piki diff --git a/doc/Makefile b/doc/Makefile new file mode 100644 index 0000000..2f5303a --- /dev/null +++ b/doc/Makefile @@ -0,0 +1,10 @@ +all: + piki template.html index.piki > index.html + piki template.html install.piki > install.html + piki template.html ghc-mod.piki > ghc-mod.html + piki template.html ghc-modi.piki > ghc-modi.html + piki template.html emacs.piki > emacs.html + piki template.html preparation.piki > preparation.html + piki template.html copyright.piki > copyright.html + piki template.html history.piki > history.html + piki template.html bug.piki > bug.html diff --git a/doc/bug.piki b/doc/bug.piki new file mode 100644 index 0000000..ce4e2d0 --- /dev/null +++ b/doc/bug.piki @@ -0,0 +1,41 @@ +*Bugs + +If you found a bug relating the ghc-mod/ghc-modi commands or the ghc-mod library or the haskell-mode sub module, please record a ["issue on github" https://github.com/kazu-yamamoto/ghc-mod/issues]. + +**ghc-mod + +***ghc-mod cannot work if a ".hsc" file exist + +Please convert it to ".hs" by "cabal build" or by hand with "hsc2hs". + +***ghc-mod cannot work if "Paths_.hs" is missing + +Please create "Paths_.hs" by "cabal build". If you want to create it by hand, please install the [cab http://www.mew.org/~kazu/proj/cab/en/] command. +Typing "cab genpaths" in your package directory would help you. + + +**ghc-modi + +***Ctr-c does not terminate ghc-modi + +ghc-modi uses multiple threads of Ghc monad. +Ghc monad installs its own signal handlers +and multiple threads of Ghc monad make the world messy. +I cannot find a workaround. +Just type RET to terminate ghc-modi. + + + + +**Emacs front end + +***C-xC-s modifies the timestamp of the file even if there is no modification. + +In order to reload the file and check the syntax with GHC API (ghc-modi), +it is necessary to update the timestamp of the file. +A temporary file cannot maintain consistency of module dependency graph. +If you know a workaround, please let me know. + +***M-C-d on a function or type cannot display it but the top of the page is displayed + +For instance, "open" on Mac removes "#anchor" from the "file:///" URL. So, the top of the file is displayed. Please use C-uM-C-d as workaround. diff --git a/doc/copyright.piki b/doc/copyright.piki new file mode 100644 index 0000000..1844b40 --- /dev/null +++ b/doc/copyright.piki @@ -0,0 +1,5 @@ +*Copyright and license + +Copyright of this package belongs to ["IIJ Innovation Institute Inc" http://www.iij-ii.co.jp/en/]. +This package is available under BSD3 license. + diff --git a/doc/emacs.piki b/doc/emacs.piki new file mode 100644 index 0000000..31171d5 --- /dev/null +++ b/doc/emacs.piki @@ -0,0 +1,215 @@ +* Usage of Emacs front-end + +** Key bindings + +?M-C-i +!Completes a name of keyword, module, class, function, types, language extensions, GHC flags, etc. +?M-/ +!Completes a name of local symbol. +?M-t +!Inserts template. In the beginning of a buffer, "module Foo where" is inserted. On the function without signature, inferred type is inserted. On a symbol "foo" without definition, "foo = undefined" is inserted or a proper module is imported. C-uM-t inserts a hole in this case. On a variable, the case is split. When checking with hlint, original code is replaced with hlint's suggestion if possible. +?M-C-d +!Browses the local document with your browser. On a module import line, the document of the module is browsed. On a function or type, its document is browsed. +?C-uM-C-d +!Browses the Hackage document of the module with your browser. +?M-C-m +!Loads information of symbols for modules in the current buffer. If you add a new line to import a module, type this. The idle timer executes this command anyway. +?C-cC-h +!Query somthing at the cursor for hoogle. +?C-xC-s +!Saves the buffer if necessary and runs syntax check. +?C-cC-c +!Toggle GHC and Hlint for syntax check. GHC is used for initial time. +?M-n +!Goes to the next warning or error. +?M-p +!Goes to the previous warning or error. +?M-? +!Displays the warning/error message in the current line. +?C-cC-i +!Displays the info of this expression in another window. +?C-cC-t +!Displays the type of this expression in the minibuffer. Type C-cC-t multiple time to enlarge the expression. +?C-cC-a +!Selects one of possible cases. +?C-cC-f +!Replaces a hole with user-typed functions followed by holes. +?C-cC-e +!Displays the expanded Template Haskell. +?C-cC-m +!Insert "import Module" for the function at the cursor. +?M-s +!Sort and merge import statements in the region. +?C-cC-j +!In the beginning of the buffer, errors of other files are displayed. Typing C-cC-j on the errors jumps to the fist file of the error sources. +?C-cC-k +!Kill the ghc-modi subprocess for this project. If you install dependency packages, this command should be executed to reflect that change. +?C-c< +!Make the indentation of the region shallower. +?C-c> +!Make the indentation of the region deeper. + +** Resolving import hell + +Here is an example story not to type "import Foo" when +you write a Haskell program. + +Type the following signature. +Note that "ByteString" can be completed with M-C-i. + +>| +foo :: [ByteString] -> [ByteString] -> [ByteString] +|< + +C-xC-s highlights the signature. +Typing M-t on the line results in: + +>| +import Data.ByteString (ByteString) + +foo :: [ByteString] -> [ByteString] -> [ByteString] +foo = undefined +|< + +Type M-C-m to load symbols of Data.ByteString. +Then edit the body of "foo". +Note that "append" can be completed with M-C-i. + +>| +import Data.ByteString (ByteString) + +foo :: [ByteString] -> [ByteString] -> [ByteString] +foo bs1 bs2 = B.append <$> bs1 <*> bs2 +|< + +C-xC-s highlights the body. +Type M-t to get: + +>| +import Data.ByteString (ByteString) +import Control.Applicative ((<*>)) +import Control.Applicative ((<$>)) +import qualified Data.ByteString as B + +foo :: [ByteString] -> [ByteString] -> [ByteString] +foo bs1 bs2 = B.append <$> bs1 <*> bs2 +|< + +Now select a region for import statements (for instance, +move the cursor, type C-SPC, and move the cursor) then +type M-s. + +>| +import Control.Applicative ((<$>), (<*>)) +import Data.ByteString (ByteString) +import qualified Data.ByteString as B + +foo :: [ByteString] -> [ByteString] -> [ByteString] +foo bs1 bs2 = B.append <$> bs1 <*> bs2 +|< + +**Type holes + +Consider the following broken example: + +>| +foo :: [a -> a] -> a -> a +foo xs = foldr bar id xs + where + bar = (:) +|< + +C-xC-s highlights the 2nd line. C-c? displays the following: + +>| +Couldn't match type `[a -> a]' with `a -> a' +Expected type: (a -> a) -> (a -> a) -> a -> a + Actual type: (a -> a) -> [a -> a] -> [a -> a] +... +|< + +Even in this situation, C-cC-t on 'id' displays 'a -> a' in the minibuffer. GHC's -fdefer-type-errors enables this magic. + +Also, you can make use of GHC's hole. Inserting "_" before "bar" and typing C-xC-s results in highlighting the second line again: + +>| +foo :: [a -> a] -> a -> a +foo xs = foldr _bar id xs + where + bar = (:) +|< + +C-c? displays: + +>| +Found hole `_bar' with type: (a -> a) -> (a -> a) -> a -> a +Where: `a' is a rigid type variable bound by + the type signature for foo :: [a -> a] -> a -> a + at /Users/kazu/c.hs:3:8 +Relevant bindings include + bar :: forall a. a -> [a] -> [a] (bound at /Users/kazu/c.hs:6:5) + xs :: [a -> a] (bound at /Users/kazu/c.hs:4:5) + foo :: [a -> a] -> a -> a (bound at /Users/kazu/c.hs:4:1) +... +|< + +**More type holes + +Suppose you have: + +>| +filterNothing :: [Maybe a] -> [a] +|< + +Typing M-t gets: + +>| +filterNothing :: [Maybe a] -> [a] +filterNothing = undefined +|< + +On the other hand, typing C-uM-t gets: + +>| +filterNothing :: [Maybe a] -> [a] +filterNothing xs = _body +|< + +Then, C-xC-s refreshes highlightings. When you type C-cC-f on "_body" and +type "filter" in the minibuffer, you get: + +>| +filterNothing :: [Maybe a] -> [a] +filterNothing xs = filter _body_1 _body_2 +|< + +** Case handling + +Suppose you have: + +>| +f :: [a] -> a +f x = _f_body +|< + +Typing M-t on "x" splits cases as follows: + +>| +f :: [a] -> a +f [] = _f_body +f (x:xs) = _f_body +|< + +Suppose you have: + +>| +f :: a -> Maybe a +f x = _f_body +|< + +Typing C-cC-a on "_f_body" and selecting one of possible cases in another window results in: + +>| +f :: a -> Maybe a +f x = Nothing +|< diff --git a/doc/ghc-mod.piki b/doc/ghc-mod.piki new file mode 100644 index 0000000..a96a99f --- /dev/null +++ b/doc/ghc-mod.piki @@ -0,0 +1,38 @@ +*The ghc-mod command + +?ghc-mod list +!Displays a list of modules +?ghc-mod lang +!Displays a list of language extensions +?ghc-mod flag +!Displays a list of GHC flags +?ghc-mod browse \[:\] +!Displays symbols of +?ghc-mod check +!Checks syntax with GHC +?ghc-mod expand +!Expands Template Haskell +?ghc-mod debug +!Displays debug information +?ghc-mod info +!Displays information about the expression +?ghc-mod type +!Displays the types of all expressions including the expression +?ghc-mod find +!Finds all module names exporting +?ghc-mod lint +!Checks synstax with Hlint +?ghc-mod root +!Finds the root directory for the Haskell file +?ghc-mod doc +!Finds the html document for the module +?ghc-mod boot +!Displays boot information for Emacs front-end +?ghc-mod version +!Displays the version of ghc-mod +?ghc-mod help +!Displays help messages + + for "info" and "type" is not used, anything is OK. +It is necessary to maintain backward compatibility. + diff --git a/doc/ghc-modi.piki b/doc/ghc-modi.piki new file mode 100644 index 0000000..3d45827 --- /dev/null +++ b/doc/ghc-modi.piki @@ -0,0 +1,48 @@ +*The ghc-modi command + +** Example + +>| +% ghc-modi +check Foo.hs +Foo.hs:7:15:Not in scope: `B.append' +OK +bye +NG quit +% +|< + +** Commands + +? check +! Checks syntax with GHC +? find +! Finds all module names exporting +? info +! Displays information about the expression +? type +! Displays the types of all expressions including the expression +? lint \[hlint options\] +! Checks synstax with Hlint +? boot +! Displays boot information for Emacs front-end +? browse \[:\] +! Displays symbols of +? quit (or empty string) +! Terminate ghc-modi + +** Options + +Option should be the form of Haskell's list of String (\[String\]). +Here is an example: + +>| +lint ["--ignore=Use camelCase", "--ignore=Eta reduce"] Foo.hs +|< + +** Session separators + +?OK +! The session succeeded. +?NG +! The session fails. ghc-modi gets finished. diff --git a/doc/history.piki b/doc/history.piki new file mode 100644 index 0000000..01f0e26 --- /dev/null +++ b/doc/history.piki @@ -0,0 +1,3 @@ +*History + +Please see [ChangeLog https://github.com/kazu-yamamoto/ghc-mod/blob/master/ChangeLog]. diff --git a/doc/index.piki b/doc/index.piki new file mode 100644 index 0000000..7766117 --- /dev/null +++ b/doc/index.piki @@ -0,0 +1,26 @@ +*Happy Haskell Programming + +The ["ghc-mod command" ghc-mod.html] and ["ghc-modi command" ghc-modi.html] are backend commands to enrich Haskell programming on editors +including Emacs, Vim, and Sublime. +ghc-mod and ghc-modi are based on the ["ghc-mod library" http://hackage.haskell.org/packages/archive/ghc-mod/latest/doc/html/Language-Haskell-GhcMod.html] +which is a wrapper of ["GHC API" http://www.haskell.org/ghc/docs/latest/html/libraries/ghc/] and [Cabal http://hackage.haskell.org/package/Cabal]. + +The ["ghc-mod package" http://hackage.haskell.org/package/ghc-mod] on Hackage +includes +the ghc-mod command, the ghc-modi command, the ghc-mod library, and +["Emacs front-end" emacs.html] (for historical reasons). +The ["source repository of ghc-mod" https://github.com/kazu-yamamoto/ghc-mod] is on github. + +**Emacs + +["Emacs front-end" emacs.html] is an extension of ["Haskell mode" https://github.com/haskell/haskell-mode]. They enable to complete Haskell symbols and to browse documents of modules. Syntax error highlighting with GHC/Hlint is also integrated. Moreover, you are free from "import hell". + +**Vim + +-[ghcmod-vim https://github.com/eagletmt/ghcmod-vim] +-[syntastic https://github.com/scrooloose/syntastic] + +**Sublime + +-[SublimeHaskell https://github.com/SublimeHaskell/SublimeHaskell] + diff --git a/doc/install.piki b/doc/install.piki new file mode 100644 index 0000000..43ba53d --- /dev/null +++ b/doc/install.piki @@ -0,0 +1,28 @@ +*Installing "ghc-mod" + +This page assumes that you are a Haskell programmer and you know the "cabal" command well. + +**Installing the ghc-mod package + +First of all, update Cabal's database: + +>| +% cabal update +|< + +Now install "ghc-mod": + +>| +% cabal install ghc-mod +|< + +This command installs the followings: + +?~/.cabal/bin/ghc-mod +!The ghc-mod commnad +?~/.cabal/bin/ghc-modi +!The ghc-modi commnad +?~/.cabal/lib/ghc-mod-x.y.z/* +!The ghc-mod library +?~/.cabal/share/ghc-mod-x.y.z/ghc*.el +!Elisp files to extend Haskell mode diff --git a/doc/preparation.piki b/doc/preparation.piki new file mode 100644 index 0000000..cbad20a --- /dev/null +++ b/doc/preparation.piki @@ -0,0 +1,67 @@ +* Preparing Emacs front-end + +**Downloading + +Please use *stable* [MELPA http://melpa-stable.milkbox.net/] to download Emacs front-end. So, your "~/.emacs" should be: + +>| +(require 'package) +(add-to-list 'package-archives + '("melpa" . "http://melpa-stable.milkbox.net/packages/")) +(package-initialize) +|< + +The package name is "ghc". +Please don't forget ["install the latest cabal command" install.html]. + +**Configuring "~/.emacs.el" + +Then, put the followings to your "~/.emacs.el" or "~/.emacs.d/init.el": + +>| +(autoload 'ghc-init "ghc" nil t) +(autoload 'ghc-debug "ghc" nil t) +(add-hook 'haskell-mode-hook (lambda () (ghc-init))) +|< + +IMPORTANT: if your haskell-mode-hook includes (flymake-mode), please remove it. + +**Testing + +Executes Emacs and opens a Haskell file by C-xC-f. And try to complete any keywords by M-C-i. + +**Debugging + +ghc-mod/ghc-modi must be compiled by GHC which you are actually using from Emacs. The version of Emacs front-end and ghc-mod/ghc-modi must be the same. To confirm this, type M-x ghc-debug. + +>| +Path: check if you are using intended programs. + ghc.el path: /Users/kazu/work/ghc-mod/elisp/ghc.el + ghc-mod path: /Users/kazu/Library/Haskell/bin/ghc-mod + ghc-modi path: /Users/kazu/Library/Haskell/bin/ghc-modi + ghc path: /usr/local/ghc-7.8/bin/ghc + +Version: all versions must be the same. + ghc.el version 4.1.0 + ghc-mod version 4.1.0 compiled by GHC 7.8.2 + ghc-modi version 4.1.0 compiled by GHC 7.8.2 + The Glorious Glasgow Haskell Compilation System, version 7.8.2 +|< + +If you put (setq ghc-debug t) to your ".emacs", you can watch the communication between Emacs front-end and ghc-modi in the "*GHC Debug*" buffer. + +**Customizing + +If you want to specify GHC options from Emacs, set "ghc-ghc-options". +The following is an example to specify the "-i" options to GHC. + +>| +(setq ghc-ghc-options '("-idir1" "-idir2")) +|< + +An example to specify HLint options: + +>| +(setq ghc-hlint-options '("--ignore=Use camelCase")) +|< + From 44a38782d85b44e5707cfc12db20483b3d7125ec Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Wed, 19 Nov 2014 09:09:10 +0900 Subject: [PATCH 02/13] Avoid use of discard-input. Fix #405. --- elisp/ghc-process.el | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/elisp/ghc-process.el b/elisp/ghc-process.el index 69cf75b..9fb92d8 100644 --- a/elisp/ghc-process.el +++ b/elisp/ghc-process.el @@ -112,12 +112,8 @@ (setq ghc-process-num-of-results (or n 1)) (let ((pro (ghc-with-process cmd 'ghc-process-callback nil hook))) (condition-case nil - (while (null ghc-process-rendezvous) - ;; 0.01 is too fast for Emacs 24.4. - ;; (sit-for 0.1 t) may get stuck when tooltip is displayed. - (sit-for 0.1) - ;; (discard-input) avoids getting stuck. - (discard-input)) + (while (and (null ghc-process-rendezvous) + (accept-process-output pro 2))) (quit (setq ghc-process-running nil)))) ghc-process-results)) From 7c4765bdefdc09f65ba14ecbd96848b46230cf7a Mon Sep 17 00:00:00 2001 From: Iku Iwasa Date: Wed, 26 Nov 2014 23:34:20 +0900 Subject: [PATCH 03/13] Remove timeout from loop in ghc-sync-process This fixes the possibility that ghc-process-running was left non-nil after timeout. Quit still can abort the loop. --- elisp/ghc-process.el | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/elisp/ghc-process.el b/elisp/ghc-process.el index 9fb92d8..97724d0 100644 --- a/elisp/ghc-process.el +++ b/elisp/ghc-process.el @@ -112,8 +112,9 @@ (setq ghc-process-num-of-results (or n 1)) (let ((pro (ghc-with-process cmd 'ghc-process-callback nil hook))) (condition-case nil - (while (and (null ghc-process-rendezvous) - (accept-process-output pro 2))) + (let ((inhibit-quit nil)) + (while (null ghc-process-rendezvous) + (accept-process-output pro))) (quit (setq ghc-process-running nil)))) ghc-process-results)) From 3a88db6c2bfdbcd9829a259568fd47fb18a8d3f6 Mon Sep 17 00:00:00 2001 From: Iku Iwasa Date: Sat, 29 Nov 2014 12:11:06 +0900 Subject: [PATCH 04/13] Update extract module regexp for unicode quotes GHC-7.8.x uses U+2018 and U+2019 for quotes. Also do not call ghc-resolve-document-path if module cannot be extracted in case of local functions. --- elisp/ghc-doc.el | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/elisp/ghc-doc.el b/elisp/ghc-doc.el index cfb5e61..46fe2aa 100644 --- a/elisp/ghc-doc.el +++ b/elisp/ghc-doc.el @@ -22,8 +22,8 @@ (setq expr (ghc-read-expression expr0)) (setq info (ghc-get-info expr0)) (setq mod (ghc-extact-module-from-info info))) - (setq pkg-ver-path (ghc-resolve-document-path mod)) - (if (and pkg-ver-path mod) + (setq pkg-ver-path (and mod (ghc-resolve-document-path mod))) + (if pkg-ver-path (ghc-display-document pkg-ver-path mod haskell-org expr) (message "No document found")))) @@ -75,7 +75,7 @@ (apply 'concat (nreverse acc)))) (defun ghc-extact-module-from-info (info) - (when (string-match "\`\\([^']+\\)'" info) + (when (string-match "[`\u2018]\\([^'\u2019]+\\)['\u2019]" info) (match-string 1 info))) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; From fb2dc5fca58df520456bc1c2954e7dffba2ee58e Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Sat, 29 Nov 2014 12:57:23 +0900 Subject: [PATCH 05/13] Fixing a race (#405). --- elisp/ghc-process.el | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/elisp/ghc-process.el b/elisp/ghc-process.el index 97724d0..33203b1 100644 --- a/elisp/ghc-process.el +++ b/elisp/ghc-process.el @@ -114,7 +114,7 @@ (condition-case nil (let ((inhibit-quit nil)) (while (null ghc-process-rendezvous) - (accept-process-output pro))) + (accept-process-output pro 0.1 nil t))) (quit (setq ghc-process-running nil)))) ghc-process-results)) From bf085ce8f161b474ea60de7bcaa85aaf59f12d26 Mon Sep 17 00:00:00 2001 From: Kazu Yamamoto Date: Mon, 1 Dec 2014 11:44:39 +0900 Subject: [PATCH 06/13] Yet another fix for #405. --- elisp/ghc-process.el | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/elisp/ghc-process.el b/elisp/ghc-process.el index 33203b1..00aed43 100644 --- a/elisp/ghc-process.el +++ b/elisp/ghc-process.el @@ -111,9 +111,11 @@ (setq ghc-process-results nil) (setq ghc-process-num-of-results (or n 1)) (let ((pro (ghc-with-process cmd 'ghc-process-callback nil hook))) + ;; ghc-process-running is now t. + ;; But if the process exits abnormally, it is set to nil. (condition-case nil (let ((inhibit-quit nil)) - (while (null ghc-process-rendezvous) + (while (and (null ghc-process-rendezvous) ghc-process-running) (accept-process-output pro 0.1 nil t))) (quit (setq ghc-process-running nil)))) From 6e6c0d99e29e78e58aa27304378e27fe99610aee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Tue, 16 Dec 2014 21:34:04 +0100 Subject: [PATCH 07/13] Add installation note about Nix --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index a691a12..54e474d 100644 --- a/README.md +++ b/README.md @@ -26,6 +26,14 @@ package is called `ghc` there, not `ghc-mod`) and install the % cabal update && cabal install ghc-mod ``` +### Nix & NixOS + +The installation is a little more involved in this environment as Nix needs some +ugly hacks to get packages using the GHC API to work, please refer to this +stackoverflow answer: + +http://stackoverflow.com/a/24228830 + ## Using the development version The easiest way to hack on ghc-mod is compile it, then add `dist/build/ghc-mod` From 80e826a199e48ceba892183ff625837817c6f422 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Wed, 17 Dec 2014 17:53:09 +0100 Subject: [PATCH 08/13] Prefix ghc-mod tmpdirs with "ghc-mod" --- Language/Haskell/GhcMod/Utils.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Language/Haskell/GhcMod/Utils.hs b/Language/Haskell/GhcMod/Utils.hs index 2773839..5182089 100644 --- a/Language/Haskell/GhcMod/Utils.hs +++ b/Language/Haskell/GhcMod/Utils.hs @@ -54,8 +54,7 @@ withDirectory_ dir action = (\_ -> liftIO (setCurrentDirectory dir) >> action) uniqTempDirName :: FilePath -> FilePath -uniqTempDirName dir = - uncurry (++) +uniqTempDirName dir = ("ghc-mod"++) $ uncurry (++) $ map escapeDriveChar *** map escapePathChar $ splitDrive dir where From 782f234981c10993ba7aed609455628138688a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Wed, 17 Dec 2014 17:52:50 +0100 Subject: [PATCH 09/13] Fix ghc-mod tempdirs not being removed on exit --- Language/Haskell/GhcMod/Monad.hs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Language/Haskell/GhcMod/Monad.hs b/Language/Haskell/GhcMod/Monad.hs index b2f1d96..dd1fab3 100644 --- a/Language/Haskell/GhcMod/Monad.hs +++ b/Language/Haskell/GhcMod/Monad.hs @@ -270,16 +270,18 @@ runGhcModT :: IOish m => Options -> GhcModT m a -> m (Either GhcModError a, GhcModLog) -runGhcModT opt action = do - env <- liftBase $ newGhcModEnv opt =<< getCurrentDirectory +runGhcModT opt action = gbracket newEnv delEnv $ \env -> do r <- first (fst <$>) <$> (runGhcModT' env defaultState $ do dflags <- getSessionDynFlags defaultCleanupHandler dflags $ do initializeFlagsWithCradle opt (gmCradle env) action) - liftBase $ cleanupGhcModEnv env return r + where + newEnv = liftBase $ newGhcModEnv opt =<< getCurrentDirectory + delEnv = liftBase . cleanupGhcModEnv + -- | @hoistGhcModT result@. Embed a GhcModT computation's result into a GhcModT -- computation. Note that if the computation that returned @result@ modified the -- state part of GhcModT this cannot be restored. From f023f4fc06aeaaff7ec1a28caae23de40cfde329 Mon Sep 17 00:00:00 2001 From: Dimitri 'phaazon' Sabadie Date: Mon, 22 Dec 2014 17:14:58 +0100 Subject: [PATCH 10/13] Fixed #422. --- Language/Haskell/GhcMod/Monad.hs | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/Language/Haskell/GhcMod/Monad.hs b/Language/Haskell/GhcMod/Monad.hs index dd1fab3..3b3b697 100644 --- a/Language/Haskell/GhcMod/Monad.hs +++ b/Language/Haskell/GhcMod/Monad.hs @@ -77,7 +77,10 @@ import Data.Monoid (Monoid) import Control.Applicative (Alternative) import Control.Arrow (first) -import Control.Monad (MonadPlus, void, liftM) +import Control.Monad (MonadPlus, void) +#if !MIN_VERSION_monad_control(1,0,0) +import Control.Monad (liftM) +#endif import Control.Monad.Base (MonadBase, liftBase) -- Monad transformer stuff @@ -368,6 +371,23 @@ withOptions changeOpt action = local changeEnv action instance (MonadBaseControl IO m) => MonadBase IO (GhcModT m) where liftBase = GhcModT . liftBase +#if MIN_VERSION_monad_control(1,0,0) + +instance (MonadBaseControl IO m) => MonadBaseControl IO (GhcModT m) where + type StM (GhcModT m) a = + StM (StateT GhcModState + (ErrorT GhcModError + (JournalT GhcModLog + (ReaderT GhcModEnv m) ) ) ) a + liftBaseWith f = GhcModT . liftBaseWith $ \runInBase -> + f $ runInBase . unGhcModT + + restoreM = GhcModT . restoreM + {-# INLINE liftBaseWith #-} + {-# INLINE restoreM #-} + +#else + instance (MonadBaseControl IO m) => MonadBaseControl IO (GhcModT m) where newtype StM (GhcModT m) a = StGhcMod { unStGhcMod :: StM (StateT GhcModState @@ -381,6 +401,8 @@ instance (MonadBaseControl IO m) => MonadBaseControl IO (GhcModT m) where {-# INLINE liftBaseWith #-} {-# INLINE restoreM #-} +#endif + -- GHC cannot prove the following instances to be decidable automatically using -- the FlexibleContexts extension as they violate the second Paterson Condition, -- namely that: The assertion has fewer constructors and variables (taken From fc7ce47e93c766ee87022db1e14eaf2768632e11 Mon Sep 17 00:00:00 2001 From: klapaucius Date: Fri, 19 Sep 2014 17:29:42 +0600 Subject: [PATCH 11/13] fix for varid bug in showExports & processExports --- Language/Haskell/GhcMod/Browse.hs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/Language/Haskell/GhcMod/Browse.hs b/Language/Haskell/GhcMod/Browse.hs index 7ff0d17..b5fc4aa 100644 --- a/Language/Haskell/GhcMod/Browse.hs +++ b/Language/Haskell/GhcMod/Browse.hs @@ -61,13 +61,23 @@ splitPkgMdl pkgmdl = case break (==':') pkgmdl of (mdl,"") -> (Nothing,mdl) (pkg,_:mdl) -> (Just pkg,mdl) +-- Haskell 2010: +-- small -> ascSmall | uniSmall | _ +-- ascSmall -> a | b | ... | z +-- uniSmall -> any Unicode lowercase letter +-- varid -> (small {small | large | digit | ' }) + +isNotOp :: String -> Bool +isNotOp (h:_) = isAlpha h || (h == '_') +isNotOp _ = error "isNotOp" + processExports :: IOish m => ModuleInfo -> GhcModT m [String] processExports minfo = do opt <- options let removeOps | operators opt = id - | otherwise = filter (isAlpha . head . getOccString) + | otherwise = filter (isNotOp . getOccString) mapM (showExport opt minfo) $ removeOps $ G.modInfoExports minfo showExport :: IOish m => Options -> ModuleInfo -> Name -> GhcModT m String @@ -87,10 +97,10 @@ showExport opt minfo e = do typeName <- tyResult >>= showThing dflag (" :: " ++ typeName) `justIf` detailed opt | otherwise = return Nothing - formatOp nm@(n:_) - | isAlpha n = nm - | otherwise = "(" ++ nm ++ ")" - formatOp "" = error "formatOp" + formatOp nm + | null nm = error "formatOp" + | isNotOp nm = nm + | otherwise = "(" ++ nm ++ ")" inOtherModule :: IOish m => Name -> GhcModT m (Maybe TyThing) inOtherModule nm = G.getModuleInfo (G.nameModule nm) >> G.lookupGlobalName nm justIf :: a -> Bool -> Maybe a From 76180ca73a878ea3c6763e119173d4c54f16d38d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Wed, 24 Dec 2014 22:35:21 +0100 Subject: [PATCH 12/13] "modules" command was missing from ghc-mod usage --- src/GHCMod.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/GHCMod.hs b/src/GHCMod.hs index b0c8307..1b5bad2 100644 --- a/src/GHCMod.hs +++ b/src/GHCMod.hs @@ -87,7 +87,7 @@ ghcModUsage = \ - help | --help\n\ \ Print this help message.\n\ \\n\ - \ - list [FLAGS...]\n\ + \ - list [FLAGS...] | modules [FLAGS...]\n\ \ List all visible modules.\n\ \ Flags:\n\ \ -d\n\ From f5ab347c030e9b191f7a8ed9b6e54760c6d6eeab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Gr=C3=B6ber?= Date: Wed, 31 Dec 2014 22:57:53 +0100 Subject: [PATCH 13/13] Add bump.sh script to master branch too --- scripts/bump.sh | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100755 scripts/bump.sh diff --git a/scripts/bump.sh b/scripts/bump.sh new file mode 100755 index 0000000..445622e --- /dev/null +++ b/scripts/bump.sh @@ -0,0 +1,31 @@ +#!/bin/sh + +if [ -z "$1" ]; then + echo "Usage: $0 VERSION" >&2 + exit 1 +fi + +VERSION=$1 + +if ! echo $VERSION | grep "^[0-9.]"; then + echo "invalid version"; + exit 1 +fi + +cd $(dirname $0)/.. + +sed -i 's/(defconst ghc-version ".*")/(defconst ghc-version "'"$VERSION"'")/' \ + elisp/ghc.el + +sed -r -i 's/^(Version:[[:space:]]*)[0-9.]+/\1'"$VERSION"'/' ghc-mod.cabal + +( tac ChangeLog; echo "\n$(date '+%Y-%m-%d') v$VERSION" ) | tac \ + > ChangeLog.tmp + +mv ChangeLog.tmp ChangeLog + +emacs -q -nw ChangeLog + +git add ChangeLog elisp/ghc.el ghc-mod.cabal +git commit -m "Bump version to $VERSION" +git tag "v$VERSION"