packages feed

ihaskell 0.6.0.0 → 0.6.1.0

raw patch · 10 files changed

+206/−30 lines, 10 filesdep ~aeson

Dependency ranges changed: aeson

Files

Hspec.hs view
@@ -2,7 +2,7 @@ -- Keep all the language pragmas here so it can be compiled separately. module Main where import Prelude-import GHC+import GHC hiding (Qualified) import GHC.Paths import Data.IORef import Control.Monad@@ -62,7 +62,7 @@   interpret libdir False $ Eval.evaluate state string publish   out <- readIORef outputAccum   pagerOut <- readIORef pagerAccum-  return (reverse out, unlines $ reverse pagerOut)+  return (reverse out, unlines . map extractPlain . reverse $ pagerOut)  evaluationComparing comparison string = do     let indent (' ':x) = 1 + indent x
html/kernel.js view
@@ -10,7 +10,7 @@             var onload = function(){                 console.log('Kernel haskell kernel.js is loading.'); -                // add here logic that shoudl be run once per **page load**+                // add here logic that should be run once per **page load**                 // like adding specific UI, or changing the default value                 // of codecell highlight. @@ -47,10 +47,16 @@                             // This is necessary, otherwise sometimes highlighting just doesn't happen.                             // This may be an IPython bug.                             c.code_mirror.setOption('mode', 'ihaskell');-                            c.auto_highlight();+                            c.force_highlight('ihaskell');                         }                     }                 });+                if(IPython.notebook.set_codemirror_mode){+                    // this first one will not be necessary in the future+                    // neither should the loop on all cells above+                    IPython.notebook.set_codemirror_mode('null')+                    IPython.notebook.set_codemirror_mode('ihaskell')+                }                  // Prevent the pager from surrounding everything with a <pre>                 IPython.Pager.prototype.append_text = function (text) {
ihaskell.cabal view
@@ -7,7 +7,7 @@ -- PVP summary:      +-+------- breaking API changes --                   | | +----- non-breaking API additions --                   | | | +--- code changes with no API change-version:             0.6.0.0+version:             0.6.1.0  -- A short (one-line) description of the package. synopsis:            A Haskell backend kernel for the IPython project.@@ -55,7 +55,7 @@   hs-source-dirs:      src   default-language:    Haskell2010   build-depends:       -                       aeson                >=0.6 && < 0.9,+                       aeson                >=0.7 && < 0.9,                        base                 >=4.6 && < 4.9,                        base64-bytestring    >=1.0,                        bytestring           >=0.10,@@ -106,6 +106,7 @@                    IHaskell.Convert.IpynbToLhs                    IHaskell.Convert.LhsToIpynb                    IHaskell.Eval.Completion+                   IHaskell.Eval.Inspect                    IHaskell.Eval.Evaluate                    IHaskell.Eval.Info                    IHaskell.Eval.Lint@@ -114,6 +115,7 @@                    IHaskell.Eval.ParseShell                    IHaskell.Eval.Util                    IHaskell.IPython+                   IHaskell.IPython.Stdin                    IHaskell.Flags                    IHaskell.Types                    IHaskell.BrokenPackages
src/IHaskell/Eval/Evaluate.hs view
@@ -12,6 +12,7 @@     liftIO,     typeCleaner,     globalImports,+    formatType,     ) where  import           ClassyPrelude hiding (init, last, liftIO, head, hGetContents, tail, try)@@ -183,9 +184,10 @@                              pkg <- db                              depId <- depends pkg                              dep <- filter ((== depId) . installedPackageId) db-                             guard-                               (iHaskellPkgName `isPrefixOf` packageIdString (packageConfigId dep))+                             let idString = packageIdString' dflags (packageConfigId dep)+                             guard (iHaskellPkgName `isPrefixOf` idString) +                            -- ideally the Paths_ihaskell module could provide a way to get the hash too                            -- (ihaskell-0.2.0.5-f2bce922fa881611f72dfc4a854353b9), for now. Things will end badly if you also                            -- happen to have an ihaskell-0.2.0.5-ce34eadc18cf2b28c8d338d0f3755502 installed.@@ -282,14 +284,14 @@                  when (getLintStatus kernelState /= LintOff) $ liftIO $ do                    lintSuggestions <- lint cmds                    unless (noResults lintSuggestions) $-                     output $ FinalResult lintSuggestions "" []+                     output $ FinalResult lintSuggestions [] []                   runUntilFailure kernelState (map unloc cmds ++ [storeItCommand execCount])                -- Print all parse errors.                errs -> do                  forM_ errs $ \err -> do                    out <- evalCommand output err kernelState-                   liftIO $ output $ FinalResult (evalResult out) "" []+                   liftIO $ output $ FinalResult (evalResult out) [] []                  return kernelState    return updated { getExecutionCounter = execCount + 1 }@@ -315,7 +317,7 @@       -- Output things only if they are non-empty.       let empty = noResults result && null helpStr && null (evalComms evalOut)       unless empty $-        liftIO $ output $ FinalResult result helpStr (evalComms evalOut)+        liftIO $ output $ FinalResult result [plain helpStr] (evalComms evalOut)        -- Make sure to clear all comms we've started.       let newState = evalState evalOut { evalComms = [] }
src/IHaskell/Eval/Hoogle.hs view
@@ -66,7 +66,7 @@ urlEncode :: String -> String urlEncode [] = [] urlEncode (ch:t)-  | (isAscii ch && isAlphaNum ch) || ch `P.elem` "-_.~" = ch : urlEncode t+  | (isAscii ch && isAlphaNum ch) || ch `P.elem` ("-_.~" :: String) = ch : urlEncode t   | not (isAscii ch) = P.foldr escape (urlEncode t) (eightBs [] (P.fromEnum ch))   | otherwise = escape (P.fromEnum ch) (urlEncode t)   where
+ src/IHaskell/Eval/Inspect.hs view
@@ -0,0 +1,51 @@+{-# LANGUAGE CPP, NoImplicitPrelude, OverloadedStrings, DoAndIfThenElse, FlexibleContexts #-}++{- |+Description:    Generates inspections when asked for by the frontend.++-}+module IHaskell.Eval.Inspect (inspect) where++import           ClassyPrelude+import qualified Prelude as P++import           Data.List.Split (splitOn)++import           Exception (ghandle)++import           IHaskell.Eval.Evaluate (Interpreter)+import           IHaskell.Display+import           IHaskell.Eval.Util (getType)+import           IHaskell.Types++-- | Characters used in Haskell operators.+operatorChars :: String+operatorChars = "!#$%&*+./<=>?@\\^|-~:"++-- | Whitespace characters.+whitespace :: String+whitespace = " \t\n"++-- | Compute the identifier that is being queried.+getIdentifier :: String -> Int -> String+getIdentifier code pos = identifier+  where+    chunks = splitOn whitespace code+    lastChunk = P.last chunks :: String+    identifier =+      if all (`elem` operatorChars) lastChunk+        then "(" ++ lastChunk ++ ")"+        else lastChunk+++inspect :: String -- ^ Code in the cell+        -> Int    -- ^ Cursor position in the cell+        -> Interpreter (Maybe Display)+inspect code pos = do+  let identifier = getIdentifier code pos+      handler :: SomeException -> Interpreter (Maybe a)+      handler _  = return Nothing+  response <- ghandle handler (Just <$> getType identifier)+  let prefix = identifier ++ " :: "+      fmt str = Display [plain $ prefix ++ str]+  return $ fmt <$> response
src/IHaskell/Eval/Lint.hs view
@@ -1,4 +1,4 @@-{-# LANGUAGE NoImplicitPrelude, QuasiQuotes, ViewPatterns #-}+{-# LANGUAGE FlexibleContexts, NoImplicitPrelude, QuasiQuotes, ViewPatterns #-}  module IHaskell.Eval.Lint (lint) where 
+ src/IHaskell/IPython/Stdin.hs view
@@ -0,0 +1,113 @@+{-# LANGUAGE OverloadedStrings, DoAndIfThenElse #-}++-- | This module provides a way in which the Haskell standard input may be forwarded to the IPython+-- frontend and thus allows the notebook to use the standard input.+--+-- This relies on the implementation of file handles in GHC, and is generally unsafe and terrible.+-- However, it is difficult to find another way to do it, as file handles are generally meant to+-- point to streams and files, and not networked communication protocols.+--+-- In order to use this module, it must first be initialized with two things. First of all, in order+-- to know how to communicate with the IPython frontend, it must know the kernel profile used for+-- communication. For this, use @recordKernelProfile@ once the profile is known. Both this and+-- @recordParentHeader@ take a directory name where they can store this data.+--+-- Finally, the module must know what @execute_request@ message is currently being replied to (which+-- will request the input). Thus, every time the language kernel receives an @execute_request@+-- message, it should inform this module via @recordParentHeader@, so that the module may generate+-- messages with an appropriate parent header set. If this is not done, the IPython frontends will+-- not recognize the target of the communication.+--+-- Finally, in order to activate this module, @fixStdin@ must be called once. It must be passed the+-- same directory name as @recordParentHeader@ and @recordKernelProfile@. Note that if this is being+-- used from within the GHC API, @fixStdin@ /must/ be called from within the GHC session not from+-- the host code.+module IHaskell.IPython.Stdin (fixStdin, recordParentHeader, recordKernelProfile) where++import           Control.Concurrent+import           Control.Applicative ((<$>))+import           Control.Concurrent.Chan+import           Control.Monad+import           GHC.IO.Handle+import           GHC.IO.Handle.Types+import           System.IO+import           System.Posix.IO+import           System.IO.Unsafe+import qualified Data.Map as Map++import           IHaskell.IPython.Types+import           IHaskell.IPython.ZeroMQ+import           IHaskell.IPython.Message.UUID as UUID++stdinInterface :: MVar ZeroMQStdin+{-# NOINLINE stdinInterface #-}+stdinInterface = unsafePerformIO newEmptyMVar++-- | Manipulate standard input so that it is sourced from the IPython frontend. This function is+-- build on layers of deep magical hackery, so be careful modifying it.+fixStdin :: String -> IO ()+fixStdin dir = do+  -- Initialize the stdin interface.+  profile <- read <$> readFile (dir ++ "/.kernel-profile")+  interface <- serveStdin profile+  putMVar stdinInterface interface+  void $ forkIO $ stdinOnce dir++stdinOnce :: String -> IO ()+stdinOnce dir = do+  -- Create a pipe using and turn it into handles.+  (readEnd, writeEnd) <- createPipe+  newStdin <- fdToHandle readEnd+  stdinInput <- fdToHandle writeEnd+  hSetBuffering newStdin NoBuffering+  hSetBuffering stdinInput NoBuffering++  -- Store old stdin and swap in new stdin.+  oldStdin <- hDuplicate stdin+  hDuplicateTo newStdin stdin++  loop stdinInput oldStdin newStdin++  where+    loop stdinInput oldStdin newStdin = do+      let FileHandle _ mvar = stdin+      threadDelay $ 150 * 1000+      empty <- isEmptyMVar mvar+      if not empty+        then loop stdinInput oldStdin newStdin+        else do+          line <- getInputLine dir+          hPutStr stdinInput $ line ++ "\n"+          loop stdinInput oldStdin newStdin++-- | Get a line of input from the IPython frontend.+getInputLine :: String -> IO String+getInputLine dir = do+  StdinChannel req rep <- readMVar stdinInterface++  -- Send a request for input.+  uuid <- UUID.random+  parentHeader <- read <$> readFile (dir ++ "/.last-req-header")+  let header = MessageHeader+        { username = username parentHeader+        , identifiers = identifiers parentHeader+        , parentHeader = Just parentHeader+        , messageId = uuid+        , sessionId = sessionId parentHeader+        , metadata = Map.fromList []+        , msgType = InputRequestMessage+        }+  let msg = RequestInput header ""+  writeChan req msg++  -- Get the reply.+  InputReply _ value <- readChan rep+  return value++recordParentHeader :: String -> MessageHeader -> IO ()+recordParentHeader dir header =+  writeFile (dir ++ "/.last-req-header") $ show header++recordKernelProfile :: String -> Profile -> IO ()+recordKernelProfile dir profile =+  writeFile (dir ++ "/.kernel-profile") $ show profile
src/IHaskell/Types.hs view
@@ -127,7 +127,7 @@   , useSvg = True   , useShowErrors = False   , useShowTypes = False-  , usePager = False+  , usePager = True   , openComms = empty   , kernelDebug = False   }@@ -173,7 +173,8 @@                       |                         FinalResult                           { outputs :: Display        -- ^ Display outputs.-                          , pagerOut :: String        -- ^ Text to display in the IPython pager.+                          , pagerOut :: [DisplayData] -- ^ Mimebundles to display in the IPython+                                                      -- pager.                           , startComms :: [CommInfo]  -- ^ Comms to start.                           }   deriving Show
src/Main.hs view
@@ -19,10 +19,12 @@ import           System.Posix.Signals import qualified Data.Map as Map import           Data.String.Here (hereFile)+import qualified Data.Text as T  -- IHaskell imports. import           IHaskell.Convert (convert) import           IHaskell.Eval.Completion (complete)+import           IHaskell.Eval.Inspect (inspect) import           IHaskell.Eval.Evaluate import           IHaskell.Display import           IHaskell.Eval.Info@@ -235,7 +237,7 @@   -- re-display with the updated output.   displayed <- liftIO $ newMVar []   updateNeeded <- liftIO $ newMVar False-  pagerOutput <- liftIO $ newMVar ""+  pagerOutput <- liftIO $ newMVar []   let clearOutput = do         header <- dupHeader replyHeader ClearOutputMessage         send $ ClearOutput header True@@ -296,8 +298,8 @@           let pager = pagerOut result           unless (null pager) $             if usePager state-              then modifyMVar_ pagerOutput (return . (++ pager ++ "\n"))-              else sendOutput $ Display [html pager]+              then modifyMVar_ pagerOutput (return . (++ pager))+              else sendOutput $ Display pager    let execCount = getExecutionCounter state   -- Let all frontends know the execution count and code that's about to run@@ -314,7 +316,7 @@   -- Take pager output if we're using the pager.   pager <- if usePager state              then liftIO $ readMVar pagerOutput-             else return ""+             else return []   return     (updatedState, ExecuteReply                      { header = replyHeader@@ -334,17 +336,16 @@       reply = CompleteReply replyHeader (map pack completions) start end Map.empty True   return (state, reply) --- Reply to the object_info_request message. Given an object name, return the associated type--- calculated by GHC.-replyTo _ ObjectInfoRequest { objectName = oname } replyHeader state = do-  docs <- pack <$> info (unpack oname)-  let reply = ObjectInfoReply-        { header = replyHeader-        , objectName = oname-        , objectFound = strip docs /= ""-        , objectTypeString = docs-        , objectDocString = docs-        }+replyTo _ req@InspectRequest{} replyHeader state = do+  result <- inspect (unpack $ inspectCode req) (inspectCursorPos req)+  let reply =+        case result of+          Just (Display datas) -> InspectReply+            { header = replyHeader+            , inspectStatus = True+            , inspectData = datas+            }+          _ -> InspectReply { header = replyHeader, inspectStatus = False, inspectData = [] }   return (state, reply)  -- TODO: Implement history_reply.