Merge branch 'master' into release
This commit is contained in:
commit
8233465a3f
@ -61,13 +61,23 @@ splitPkgMdl pkgmdl = case break (==':') pkgmdl of
|
|||||||
(mdl,"") -> (Nothing,mdl)
|
(mdl,"") -> (Nothing,mdl)
|
||||||
(pkg,_:mdl) -> (Just pkg,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 :: IOish m => ModuleInfo -> GhcModT m [String]
|
||||||
processExports minfo = do
|
processExports minfo = do
|
||||||
opt <- options
|
opt <- options
|
||||||
let
|
let
|
||||||
removeOps
|
removeOps
|
||||||
| operators opt = id
|
| operators opt = id
|
||||||
| otherwise = filter (isAlpha . head . getOccString)
|
| otherwise = filter (isNotOp . getOccString)
|
||||||
mapM (showExport opt minfo) $ removeOps $ G.modInfoExports minfo
|
mapM (showExport opt minfo) $ removeOps $ G.modInfoExports minfo
|
||||||
|
|
||||||
showExport :: IOish m => Options -> ModuleInfo -> Name -> GhcModT m String
|
showExport :: IOish m => Options -> ModuleInfo -> Name -> GhcModT m String
|
||||||
@ -87,10 +97,10 @@ showExport opt minfo e = do
|
|||||||
typeName <- tyResult >>= showThing dflag
|
typeName <- tyResult >>= showThing dflag
|
||||||
(" :: " ++ typeName) `justIf` detailed opt
|
(" :: " ++ typeName) `justIf` detailed opt
|
||||||
| otherwise = return Nothing
|
| otherwise = return Nothing
|
||||||
formatOp nm@(n:_)
|
formatOp nm
|
||||||
| isAlpha n = nm
|
| null nm = error "formatOp"
|
||||||
| otherwise = "(" ++ nm ++ ")"
|
| isNotOp nm = nm
|
||||||
formatOp "" = error "formatOp"
|
| otherwise = "(" ++ nm ++ ")"
|
||||||
inOtherModule :: IOish m => Name -> GhcModT m (Maybe TyThing)
|
inOtherModule :: IOish m => Name -> GhcModT m (Maybe TyThing)
|
||||||
inOtherModule nm = G.getModuleInfo (G.nameModule nm) >> G.lookupGlobalName nm
|
inOtherModule nm = G.getModuleInfo (G.nameModule nm) >> G.lookupGlobalName nm
|
||||||
justIf :: a -> Bool -> Maybe a
|
justIf :: a -> Bool -> Maybe a
|
||||||
|
@ -77,7 +77,10 @@ import Data.Monoid (Monoid)
|
|||||||
|
|
||||||
import Control.Applicative (Alternative)
|
import Control.Applicative (Alternative)
|
||||||
import Control.Arrow (first)
|
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)
|
import Control.Monad.Base (MonadBase, liftBase)
|
||||||
|
|
||||||
-- Monad transformer stuff
|
-- Monad transformer stuff
|
||||||
@ -270,16 +273,18 @@ runGhcModT :: IOish m
|
|||||||
=> Options
|
=> Options
|
||||||
-> GhcModT m a
|
-> GhcModT m a
|
||||||
-> m (Either GhcModError a, GhcModLog)
|
-> m (Either GhcModError a, GhcModLog)
|
||||||
runGhcModT opt action = do
|
runGhcModT opt action = gbracket newEnv delEnv $ \env -> do
|
||||||
env <- liftBase $ newGhcModEnv opt =<< getCurrentDirectory
|
|
||||||
r <- first (fst <$>) <$> (runGhcModT' env defaultState $ do
|
r <- first (fst <$>) <$> (runGhcModT' env defaultState $ do
|
||||||
dflags <- getSessionDynFlags
|
dflags <- getSessionDynFlags
|
||||||
defaultCleanupHandler dflags $ do
|
defaultCleanupHandler dflags $ do
|
||||||
initializeFlagsWithCradle opt (gmCradle env)
|
initializeFlagsWithCradle opt (gmCradle env)
|
||||||
action)
|
action)
|
||||||
liftBase $ cleanupGhcModEnv env
|
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
where
|
||||||
|
newEnv = liftBase $ newGhcModEnv opt =<< getCurrentDirectory
|
||||||
|
delEnv = liftBase . cleanupGhcModEnv
|
||||||
|
|
||||||
-- | @hoistGhcModT result@. Embed a GhcModT computation's result into a GhcModT
|
-- | @hoistGhcModT result@. Embed a GhcModT computation's result into a GhcModT
|
||||||
-- computation. Note that if the computation that returned @result@ modified the
|
-- computation. Note that if the computation that returned @result@ modified the
|
||||||
-- state part of GhcModT this cannot be restored.
|
-- state part of GhcModT this cannot be restored.
|
||||||
@ -366,6 +371,23 @@ withOptions changeOpt action = local changeEnv action
|
|||||||
instance (MonadBaseControl IO m) => MonadBase IO (GhcModT m) where
|
instance (MonadBaseControl IO m) => MonadBase IO (GhcModT m) where
|
||||||
liftBase = GhcModT . liftBase
|
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
|
instance (MonadBaseControl IO m) => MonadBaseControl IO (GhcModT m) where
|
||||||
newtype StM (GhcModT m) a = StGhcMod {
|
newtype StM (GhcModT m) a = StGhcMod {
|
||||||
unStGhcMod :: StM (StateT GhcModState
|
unStGhcMod :: StM (StateT GhcModState
|
||||||
@ -379,6 +401,8 @@ instance (MonadBaseControl IO m) => MonadBaseControl IO (GhcModT m) where
|
|||||||
{-# INLINE liftBaseWith #-}
|
{-# INLINE liftBaseWith #-}
|
||||||
{-# INLINE restoreM #-}
|
{-# INLINE restoreM #-}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
-- GHC cannot prove the following instances to be decidable automatically using
|
-- GHC cannot prove the following instances to be decidable automatically using
|
||||||
-- the FlexibleContexts extension as they violate the second Paterson Condition,
|
-- the FlexibleContexts extension as they violate the second Paterson Condition,
|
||||||
-- namely that: The assertion has fewer constructors and variables (taken
|
-- namely that: The assertion has fewer constructors and variables (taken
|
||||||
|
@ -54,8 +54,7 @@ withDirectory_ dir action =
|
|||||||
(\_ -> liftIO (setCurrentDirectory dir) >> action)
|
(\_ -> liftIO (setCurrentDirectory dir) >> action)
|
||||||
|
|
||||||
uniqTempDirName :: FilePath -> FilePath
|
uniqTempDirName :: FilePath -> FilePath
|
||||||
uniqTempDirName dir =
|
uniqTempDirName dir = ("ghc-mod"++) $ uncurry (++)
|
||||||
uncurry (++)
|
|
||||||
$ map escapeDriveChar *** map escapePathChar
|
$ map escapeDriveChar *** map escapePathChar
|
||||||
$ splitDrive dir
|
$ splitDrive dir
|
||||||
where
|
where
|
||||||
|
@ -26,6 +26,14 @@ package is called `ghc` there, not `ghc-mod`) and install the
|
|||||||
% cabal update && cabal install ghc-mod
|
% 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
|
## Using the development version
|
||||||
|
|
||||||
The easiest way to hack on ghc-mod is compile it, then add `dist/build/ghc-mod`
|
The easiest way to hack on ghc-mod is compile it, then add `dist/build/ghc-mod`
|
||||||
|
10
doc/Makefile
Normal file
10
doc/Makefile
Normal file
@ -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
|
41
doc/bug.piki
Normal file
41
doc/bug.piki
Normal file
@ -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_<package>.hs" is missing
|
||||||
|
|
||||||
|
Please create "Paths_<package>.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.
|
5
doc/copyright.piki
Normal file
5
doc/copyright.piki
Normal file
@ -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.
|
||||||
|
|
215
doc/emacs.piki
Normal file
215
doc/emacs.piki
Normal file
@ -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
|
||||||
|
|<
|
38
doc/ghc-mod.piki
Normal file
38
doc/ghc-mod.piki
Normal file
@ -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 \[<package>:\]<module>
|
||||||
|
!Displays symbols of <module>
|
||||||
|
?ghc-mod check <HaskellFile>
|
||||||
|
!Checks syntax with GHC
|
||||||
|
?ghc-mod expand <HaskellFile>
|
||||||
|
!Expands Template Haskell
|
||||||
|
?ghc-mod debug <HaskellFile>
|
||||||
|
!Displays debug information
|
||||||
|
?ghc-mod info <HaskellFile> <module> <expression>
|
||||||
|
!Displays information about the expression
|
||||||
|
?ghc-mod type <HaskellFile> <module> <line-no> <column-no>
|
||||||
|
!Displays the types of all expressions including the expression
|
||||||
|
?ghc-mod find <symbol>
|
||||||
|
!Finds all module names exporting <symbol>
|
||||||
|
?ghc-mod lint <HaskellFile>
|
||||||
|
!Checks synstax with Hlint
|
||||||
|
?ghc-mod root <HaskellFile>
|
||||||
|
!Finds the root directory for the Haskell file
|
||||||
|
?ghc-mod doc <module>
|
||||||
|
!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
|
||||||
|
|
||||||
|
<module> for "info" and "type" is not used, anything is OK.
|
||||||
|
It is necessary to maintain backward compatibility.
|
||||||
|
|
48
doc/ghc-modi.piki
Normal file
48
doc/ghc-modi.piki
Normal file
@ -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 <HaskellFile>
|
||||||
|
! Checks syntax with GHC
|
||||||
|
? find <symbol>
|
||||||
|
! Finds all module names exporting <symbol>
|
||||||
|
? info <HaskellFile> <expr>
|
||||||
|
! Displays information about the expression
|
||||||
|
? type <HaskellFile> <line> <column>
|
||||||
|
! Displays the types of all expressions including the expression
|
||||||
|
? lint \[hlint options\] <HaskellFile>
|
||||||
|
! Checks synstax with Hlint
|
||||||
|
? boot
|
||||||
|
! Displays boot information for Emacs front-end
|
||||||
|
? browse \[<package>:\]<module>
|
||||||
|
! Displays symbols of <module>
|
||||||
|
? 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 <error message>
|
||||||
|
! The session fails. ghc-modi gets finished.
|
3
doc/history.piki
Normal file
3
doc/history.piki
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
*History
|
||||||
|
|
||||||
|
Please see [ChangeLog https://github.com/kazu-yamamoto/ghc-mod/blob/master/ChangeLog].
|
26
doc/index.piki
Normal file
26
doc/index.piki
Normal file
@ -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]
|
||||||
|
|
28
doc/install.piki
Normal file
28
doc/install.piki
Normal file
@ -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
|
67
doc/preparation.piki
Normal file
67
doc/preparation.piki
Normal file
@ -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"))
|
||||||
|
|<
|
||||||
|
|
@ -22,8 +22,8 @@
|
|||||||
(setq expr (ghc-read-expression expr0))
|
(setq expr (ghc-read-expression expr0))
|
||||||
(setq info (ghc-get-info expr0))
|
(setq info (ghc-get-info expr0))
|
||||||
(setq mod (ghc-extact-module-from-info info)))
|
(setq mod (ghc-extact-module-from-info info)))
|
||||||
(setq pkg-ver-path (ghc-resolve-document-path mod))
|
(setq pkg-ver-path (and mod (ghc-resolve-document-path mod)))
|
||||||
(if (and pkg-ver-path mod)
|
(if pkg-ver-path
|
||||||
(ghc-display-document pkg-ver-path mod haskell-org expr)
|
(ghc-display-document pkg-ver-path mod haskell-org expr)
|
||||||
(message "No document found"))))
|
(message "No document found"))))
|
||||||
|
|
||||||
@ -75,7 +75,7 @@
|
|||||||
(apply 'concat (nreverse acc))))
|
(apply 'concat (nreverse acc))))
|
||||||
|
|
||||||
(defun ghc-extact-module-from-info (info)
|
(defun ghc-extact-module-from-info (info)
|
||||||
(when (string-match "\`\\([^']+\\)'" info)
|
(when (string-match "[`\u2018]\\([^'\u2019]+\\)['\u2019]" info)
|
||||||
(match-string 1 info)))
|
(match-string 1 info)))
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
@ -111,13 +111,12 @@
|
|||||||
(setq ghc-process-results nil)
|
(setq ghc-process-results nil)
|
||||||
(setq ghc-process-num-of-results (or n 1))
|
(setq ghc-process-num-of-results (or n 1))
|
||||||
(let ((pro (ghc-with-process cmd 'ghc-process-callback nil hook)))
|
(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
|
(condition-case nil
|
||||||
(while (null ghc-process-rendezvous)
|
(let ((inhibit-quit nil))
|
||||||
;; 0.01 is too fast for Emacs 24.4.
|
(while (and (null ghc-process-rendezvous) ghc-process-running)
|
||||||
;; (sit-for 0.1 t) may get stuck when tooltip is displayed.
|
(accept-process-output pro 0.1 nil t)))
|
||||||
(sit-for 0.1)
|
|
||||||
;; (discard-input) avoids getting stuck.
|
|
||||||
(discard-input))
|
|
||||||
(quit
|
(quit
|
||||||
(setq ghc-process-running nil))))
|
(setq ghc-process-running nil))))
|
||||||
ghc-process-results))
|
ghc-process-results))
|
||||||
|
@ -87,7 +87,7 @@ ghcModUsage =
|
|||||||
\ - help | --help\n\
|
\ - help | --help\n\
|
||||||
\ Print this help message.\n\
|
\ Print this help message.\n\
|
||||||
\\n\
|
\\n\
|
||||||
\ - list [FLAGS...]\n\
|
\ - list [FLAGS...] | modules [FLAGS...]\n\
|
||||||
\ List all visible modules.\n\
|
\ List all visible modules.\n\
|
||||||
\ Flags:\n\
|
\ Flags:\n\
|
||||||
\ -d\n\
|
\ -d\n\
|
||||||
|
Loading…
Reference in New Issue
Block a user