phoityne-vscode 0.0.16.0 → 0.0.17.0
raw patch · 6 files changed
+226/−89 lines, 6 files
Files
- Changelog.md +7/−0
- README.md +114/−39
- app/Phoityne/GHCi/Command.hs +34/−25
- app/Phoityne/VSCode/Core.hs +67/−24
- app/Phoityne/VSCode/TH/LaunchRequestArgumentsJSON.hs +3/−0
- phoityne-vscode.cabal +1/−1
Changelog.md view
@@ -1,4 +1,11 @@ +20171008 phoityne-vscode-0.0.17.0+ * [FIX] loading modules after ghci started, on ghc-8.2.1.+ * [ADD] [24](https://github.com/phoityne/phoityne-vscode/issues/24) : add variable "ghciInitialPrompt" to launch.json file.+ * [ADD] [28](https://github.com/phoityne/phoityne-vscode/issues/28) : escape backslash of startup hs file path.+ * [ADD] to set any start point, added startup function and arguments valiables in the launch.json file.++ 20170910 phoityne-vscode-0.0.16.0 * [ADD] supported ghc-8.2.0. * [ADD] check hackage phoityen version, and show message for needs of updating.
README.md view
@@ -7,13 +7,16 @@ ## Information -* [2017/09/10] phoityne-vscode released. - * Marketplace [phoityne-vscode-0.0.14](https://marketplace.visualstudio.com/items?itemName=phoityne.phoityne-vscode)- * hackage [phoityne-vscode-0.0.16.0](https://hackage.haskell.org/package/phoityne-vscode) +* [2017/10/08] phoityne-vscode released. + * Marketplace [phoityne-vscode-0.0.15](https://marketplace.visualstudio.com/items?itemName=phoityne.phoityne-vscode)+ * hackage [phoityne-vscode-0.0.17.0](https://hackage.haskell.org/package/phoityne-vscode) __Need update from hackage !!.__ * Release Summary- * [ADD] supported ghc-8.2.0.-+ * [FIX] loading modules after ghci started, on ghc-8.2.1.+ * [ADD] [24](https://github.com/phoityne/phoityne-vscode/issues/24) : add variable "ghciInitialPrompt" to launch.json file.+ * [ADD] [28](https://github.com/phoityne/phoityne-vscode/issues/28) : escape backslash of startup hs file path.+ * [ADD] to set any start point, added startup function and arguments valiables in the launch.json file.+  (This sample project is available from [here](https://github.com/phoityne/stack-project-template).)@@ -21,11 +24,8 @@ ## Important -* __LIMITATION__: Breakpoint can be set in a .hs file which defineds "module ... where". - Phoityne can handle modules which match its folder hierarchy and file name. * __LIMITATION__: Source file extension must be ".hs" * __LIMITATION__: Can not use STDIN handle while debugging. -* __LIMITATION__: Changing ghci prompt is not allowed in the .ghci file. * When you start debugging for the first time, .vscode/tasks.json will be created automatically. Then you can use F6, F7, F8 shortcut key. * F5 : start debug * F6 : show command menu (for stack watch)@@ -41,37 +41,7 @@ * F10 : step next * F11 : step into --## Install---### Run stack install-- % stack install phoityne-vscode- . . . . .- %--Add 'phoityne-vscode.exe' to PATH environment.-- % where $path:phoityne-vscode.exe- C:\Users\[user name]\AppData\Roaming\local\bin\phoityne-vscode.exe- - % phoityne-vscode --version- phoityne-vscode-0.0.15.0- %- % code----### Install vscode extensions--1. run VSCode and open stack project __Folder__ from file menu. -2. open Extensions from side menu of VSCode.-3. search "haskell" -4. select "[__Haskell GHCi debug viewer Phoityne__](https://marketplace.visualstudio.com/items?itemName=phoityne.phoityne-vscode)"- - ## Features ### Run to Cursor@@ -141,6 +111,46 @@ * supportsDelayedStackTraceLoading : no +## Install+++### Run stack install++ % stack install phoityne-vscode+ . . . . .+ %++Add 'phoityne-vscode.exe' to PATH environment.++Windows)++ % where $path:phoityne-vscode.exe+ C:\Users\[user name]\AppData\Roaming\local\bin\phoityne-vscode.exe+ + % phoityne-vscode --version+ phoityne-vscode-x.x.x.x+ %+ % code++linux)++ $ which phoityne-vscode+ ~/.local/bin/phoityne-vscode+ $+ $ phoityne-vscode --version+ phoityne-vscode-x.x.x.x+ $+ $ code++### Install vscode extensions++1. run VSCode and open stack project __Folder__ from file menu. +2. open Extensions from side menu of VSCode.+3. search "haskell" +4. select "[__Haskell GHCi debug viewer Phoityne__](https://marketplace.visualstudio.com/items?itemName=phoityne.phoityne-vscode)"++ + ## Configuration ### __.vscode/launch.json__@@ -148,12 +158,77 @@ |NAME|REQUIRED OR OPTIONAL|DEFAULT SETTING|DESCRIPTION| |:--|:--:|:--|:--| |startup|required|${workspaceRoot}/test/Spec.hs|debug startup file, will be loaded automatically.|+|startupFunc|optional|"" (empty string)|debug startup function, will be run instead of main function.|+|startupArgs|optional|"" (empty string)|arguments for startup function. set as string type.| |ghciCmd|required|stack ghci --test --no-load --no-build --main-is TARGET --ghci-options -fprint-evld-with-show|launch ghci command, must be Prelude module loaded. For example, "ghci -i${workspaceRoot}/src", "cabal exec -- ghci -i${workspaceRoot}/src"| |ghciPrompt|required|H>>=|ghci command prompt string.|+|ghciInitialPrompt|optional|"Prelude> "|initial pormpt of ghci. set it when using custom prompt. e.g. set in .ghci| |stopOnEntry|required|true|stop or not after debugger launched.+|mainArgs|optional|"" (empty string)|main arguments.| |logFile|required|${workspaceRoot}/.vscode/phoityne.log|internal log file.| |logLevel|required|WARNING|internal log level.|-|mainArgs|optional|-|main arguments.|+++#### changing ghci initial prompt ++If you change ghci prompt in .ghci file, or ghci prompt is changed from "Prelude>" by applying _NoImplicitPrelude_ extension, set the initial prompt variable to same prompt string.++ % diff .vscode/launch.json.old .vscode/launch.json+ 19c19+ < "ghciInitialPrompt": "Prelude> " // default value.+ ---+ > "ghciInitialPrompt": "> " // e.g.+ %++Make sure needs of the last space, and don't forget adding it.+++#### setting the startup hs file++Set the startup variable to the path of .hs file in which main function is defined.++ % diff .vscode/launch.json.old .vscode/launch.json+ 10c10+ < "startup": "${workspaceRoot}/test/Spec.hs", // default value.+ ---+ > "startup": "${workspaceRoot}/app/run.hs", // e.g.+ %+++#### setting the startup function++If you want to run the specific function instead of main function, set the startupFunc variable. +For example, when specifying the following startDebug function,++ startDebug :: String -> IO ()+ startDebug name = do+ putStrLn "hello"+ putStrLn name ++set the valiavles in the launch.json file.++ % diff .vscode/launch.json.old .vscode/launch.json+ 11c12+ < "startupFunc": "", // default value.+ < "startupArgs": "", // default value.+ ---+ > "startupFunc": "startDebug", // e.g.+ > "startupArgs": "\"phoityne\"", // e.g.+ %+++#### changing log level++For debuging phoityen itself, change the log level to DEBUG. +Adding Issue with the debug log.++ % diff .vscode/launch.json.old .vscode/launch.json+ 12c12+ < "logLevel": "WARNING", // default value.+ ---+ > "logLevel": "DEBUG", // e.g.+ %+ ### __.vscode/tasks.json__
app/Phoityne/GHCi/Command.hs view
@@ -20,6 +20,7 @@ , setFuncBreak , delete , traceMain+ , traceFunc , trace , step , stepLocal@@ -51,12 +52,7 @@ _HS_FILE_EXT :: String _HS_FILE_EXT = ".hs" --- |----_GHCI_PROMPT :: String-_GHCI_PROMPT = "Prelude> " - -- | -- type OutputHandler = String -> IO ()@@ -121,9 +117,10 @@ -> [GHCiOption] -> FilePath -> String+ -> String -> M.Map String String -> IO (Either ErrorData GHCiProcess)-start outHdl cmd opts cwd pmt envs = do+start outHdl cmd opts cwd initPmt pmt envs = do outHdl $ L.intercalate " " $ (cmd : opts) ++ ["in " ++ cwd, "\n"] runProcess cmd opts cwd pmt envs >>= withProcess where@@ -154,7 +151,7 @@ Right _ -> return $ Right ghci endOfStartMsg msg- | U.endswith _GHCI_PROMPT msg = True+ | U.endswith initPmt msg = True | endOfModLoadPrompt (last (lines msg)) = True | otherwise = False @@ -210,7 +207,7 @@ -> FilePath -> IO (Either ErrorData [ModuleName]) loadFile ghci outHdl cmdArg = do- let cmd = ":load " ++ cmdArg+ let cmd = ":load " ++ (normalize cmdArg) outHdl $ cmd ++ "\n" writeLine ghci cmd >>= \case Left err -> return $ Left err@@ -232,23 +229,30 @@ Left err -> return $ Left err Right msg -> do outHdl msg- withLoadResultMsg (takeLastMsg msges)- - -- | - -- Ok, modules loaded: Lib, Main, LibSpec. -> [Lib, Main, LibSpec]- -- Failed, modules loaded: none.- --- withLoadResultMsg msg- | U.startswith "Ok," msg =- return $ Right- $ U.split ", "- $ U.replace "Ok, modules loaded: " ""- $ init- $ U.strip- $ msg- | otherwise = return $ Left $ "file load error. '" ++ cmdArg ++ "'"+ return . Right $ foldr getModName [] msges++ -- |+ -- H>>= :load d:\haskell\unit-testing/test/Spec.hs+ -- [1 of 3] Compiling Lib ( D:\haskell\unit-testing\src\Lib.hs, interpreted )+ -- [2 of 3] Compiling LibSpec ( D:\haskell\unit-testing\test\LibSpec.hs, interpreted )+ -- [3 of 3] Compiling Main ( D:\haskell\unit-testing\test\Spec.hs, interpreted )+ -- Ok, 3 modules loaded.+ -- H>>= + -- + getModName msg acc = case parse getModNameParser "getModNameParser" msg of+ Right mod -> mod:acc+ Left _ -> acc + getModNameParser = + manyTill anyChar (try (string " Compiling ")) >> manyTill anyChar (char ' ')+ + normalize path+ | True == L.isPrefixOf "\"" path = path+ | False == L.isInfixOf " " path = path+ | otherwise = "\"" ++ path ++ "\""+ + -- | -- loadModule :: GHCiProcess -> OutputHandler -> [ModuleName] -> IO (Either ErrorData ())@@ -318,8 +322,13 @@ -- | -- traceMain :: GHCiProcess -> OutputHandler -> IO (Either ErrorData (Maybe SourcePosition))-traceMain ghci outHdl = do- let cmd = ":trace main"+traceMain ghci outHdl = traceFunc ghci outHdl "main" ""++-- |+--+traceFunc :: GHCiProcess -> OutputHandler -> String -> String -> IO (Either ErrorData (Maybe SourcePosition))+traceFunc ghci outHdl func args = do+ let cmd = ":trace " ++ func ++ if null args then "" else " " ++ args exec ghci outHdl cmd >>= \case Left err -> return $ Left err Right msg -> return $ mayException msg
app/Phoityne/VSCode/Core.hs view
@@ -123,6 +123,9 @@ , breakPointDatasDebugContextData :: BreakPointDatas , workspaceDebugContextData :: FilePath , startupDebugContextData :: FilePath+ , startupFuncDebugContextData :: String+ , startupArgsDebugContextData :: String+ , startupModuleDebugContextData :: ModuleName , debugStartedDebugContextData :: Bool , debugStoppedPosDebugContextData :: Maybe G.SourcePosition , currentFrameIdDebugContextData :: Int@@ -295,6 +298,9 @@ , breakPointDatasDebugContextData = M.fromList [] , workspaceDebugContextData = "" , startupDebugContextData = ""+ , startupFuncDebugContextData = ""+ , startupArgsDebugContextData = ""+ , startupModuleDebugContextData = "" , debugStartedDebugContextData = False , debugStoppedPosDebugContextData = Nothing , currentFrameIdDebugContextData = 0@@ -575,7 +581,9 @@ ctx <- takeMVar mvarCtx putMVar mvarCtx ctx { workspaceDebugContextData = J.workspaceLaunchRequestArguments args- , startupDebugContextData = J.startupLaunchRequestArguments args+ , startupDebugContextData = U.replace "\\" "/" (J.startupLaunchRequestArguments args)+ , startupFuncDebugContextData = maybe "" (\s->if null (U.strip s) then "" else (U.strip s)) (J.startupFuncLaunchRequestArguments args)+ , startupArgsDebugContextData = maybe "" (id) (J.startupArgsLaunchRequestArguments args) , stopOnEntryDebugContextData = J.stopOnEntryLaunchRequestArguments args } @@ -592,9 +600,12 @@ prepareTasksJsonFile + let initPmt = maybe _GHCI_PROMPT id (J.ghciInitialPromptLaunchRequestArguments args)+ debugM _LOG_NAME $ "ghci initial prompt [" ++ initPmt ++ "]." runGHCi mvarCtx (J.ghciCmdLaunchRequestArguments args)+ initPmt (J.ghciPromptLaunchRequestArguments args) (J.ghciEnvLaunchRequestArguments args) >>= ghciLaunched @@ -635,12 +646,14 @@ ctx <- takeMVar mvarCtx putMVar mvarCtx ctx{ghciProcessDebugContextData = Just ghciProc} - startupRes <- loadHsFile mvarCtx (J.startupLaunchRequestArguments args)-- when (False == startupRes) $ do- let msg = L.intercalate " " ["startup load error.", J.startupLaunchRequestArguments args]- sendErrorEvent mvarCtx $ msg ++ "\n"-+ loadHsFile mvarCtx (startupDebugContextData ctx) >>= \case+ Left _ -> do+ let msg = L.intercalate " " ["startup load error.", startupDebugContextData ctx]+ sendErrorEvent mvarCtx $ msg ++ "\n"+ Right modName -> do+ ctx <- takeMVar mvarCtx+ putMVar mvarCtx ctx{startupModuleDebugContextData = modName}+ setMainArgs ghciProc (J.mainArgsLaunchRequestArguments args) >>= \case Right _ -> return () Left err -> do@@ -760,7 +773,9 @@ source = J.sourceSetBreakpointsRequestArguments args path = J.pathSource source reqBps = J.breakpointsSetBreakpointsRequestArguments args- bps = map (convBp cwd path) reqBps+ startup = startupDebugContextData ctx+ stMod = startupModuleDebugContextData ctx+ bps = map (convBp cwd path startup stMod) reqBps delete path resBody <- insert bps@@ -778,9 +793,9 @@ sendResponse mvarCtx $ J.encode $ J.errorSetBreakpointsResponse resSeq req msg sendErrorEvent mvarCtx msg - convBp cwd path (J.SourceBreakpoint lineNo colNo cond hitCond) =+ convBp cwd path startup stMod (J.SourceBreakpoint lineNo colNo cond hitCond) = BreakPointData {- nameBreakPointData = src2mod cwd path+ nameBreakPointData = src2mod cwd path startup stMod , srcPosBreakPointData = G.SourcePosition path lineNo (maybe (-1) id colNo) (-1) (-1) , breakNoBreakPointData = Nothing , conditionBreakPointData = normalizeCond cond@@ -1144,13 +1159,19 @@ cfs <- defaultFrame pos foldM (convTrace2Frame cwd) cfs dats - convTrace2Frame cwd xs (G.StackFrame traceId funcName (G.SourcePosition file sl sc el ec)) = return $ - J.StackFrame traceId funcName (J.Source (Just (src2mod cwd file)) file Nothing Nothing) sl sc el ec : xs+ convTrace2Frame cwd xs (G.StackFrame traceId funcName (G.SourcePosition file sl sc el ec)) = do+ ctx <- readMVar mvarCtx+ let startup = startupDebugContextData ctx+ stMod = startupModuleDebugContextData ctx + return $ J.StackFrame traceId funcName (J.Source (Just (src2mod cwd file startup stMod)) file Nothing Nothing) sl sc el ec : xs+ defaultFrame (G.SourcePosition file sl sc el ec) = do ctx <- readMVar mvarCtx- let cwd = workspaceDebugContextData ctx- csf = J.StackFrame 0 "[BP]" (J.Source (Just (src2mod cwd file)) file Nothing Nothing) sl sc el ec+ let startup = startupDebugContextData ctx+ stMod = startupModuleDebugContextData ctx+ cwd = workspaceDebugContextData ctx+ csf = J.StackFrame 0 "[BP]" (J.Source (Just (src2mod cwd file startup stMod)) file Nothing Nothing) sl sc el ec return [csf] outHdl = debugM _LOG_NAME@@ -1426,8 +1447,18 @@ -- | -- ---src2mod :: FilePath -> FilePath -> String-src2mod cwd src +src2mod :: FilePath -> FilePath -> FilePath -> String -> String+src2mod cwd src startup stMod + | normalized == startup = stMod+ | otherwise = path2mod cwd src+ where+ normalized = U.replace "\\" "/" src++-- |+--+--+path2mod :: FilePath -> FilePath -> String+path2mod cwd src | length cwd >= length src = "" | otherwise = L.intercalate "." $ map takeBaseName@@ -1460,16 +1491,17 @@ runGHCi :: MVar DebugContextData -> String -> String+ -> String -> M.Map String String -> IO (Either G.ErrorData G.GHCiProcess)-runGHCi mvarCtx cmdStr pmt envs = do+runGHCi mvarCtx cmdStr initPmt pmt envs = do ctx <- readMVar mvarCtx let cmdList = filter (not.null) $ U.split " " cmdStr cmd = head cmdList opts = tail cmdList cwd = workspaceDebugContextData ctx - G.start outHdl cmd opts cwd pmt envs+ G.start outHdl cmd opts cwd initPmt pmt envs where outHdl = sendStdoutEvent mvarCtx @@ -1478,11 +1510,11 @@ -- | -- ---loadHsFile :: MVar DebugContextData -> FilePath -> IO Bool+loadHsFile :: MVar DebugContextData -> FilePath -> IO (Either G.ErrorData ModuleName) loadHsFile mvarCtx path = ghciProcessDebugContextData <$> (readMVar mvarCtx) >>= \case Nothing -> do sendErrorEvent mvarCtx $ "load file fail.[" ++ path ++ "]" ++ " ghci not started."- return False+ return $ Left "" Just ghciProc -> G.loadFile ghciProc outHdl path >>= withFileLoadResult ghciProc where@@ -1491,13 +1523,17 @@ withFileLoadResult _ (Left err) = do sendErrorEvent mvarCtx $ "load file fail.[" ++ path ++ "]" ++ " " ++ err- return False+ return $ Left "" + withFileLoadResult _ (Right []) = do+ sendErrorEvent mvarCtx $ "load file fail.[" ++ path ++ "]"+ return $ Left ""+ withFileLoadResult ghciProc (Right mods) = G.loadModule ghciProc outHdl mods >>= \case Left err -> do sendErrorEvent mvarCtx $ "load module fail. " ++ show mods ++ " " ++ err- return False- Right _ -> return True+ return $ Left ""+ Right _ -> return . Right $ last mods -- |@@ -1695,7 +1731,14 @@ -- | -- withModified True _ = sendRestartEvent mvarCtx - withModified False ghciProc = G.traceMain ghciProc outHdl >>= \case+ withModified False ghciProc = do+ ctx <- readMVar mvarCtx+ if null (startupFuncDebugContextData ctx)+ then withFunc ghciProc "main" ""+ else withFunc ghciProc (startupFuncDebugContextData ctx) (startupArgsDebugContextData ctx)+ + + withFunc ghciProc func args = G.traceFunc ghciProc outHdl func args >>= \case Left err -> do -- end of debugging successfully. debugM _LOG_NAME $ show err
app/Phoityne/VSCode/TH/LaunchRequestArgumentsJSON.hs view
@@ -25,6 +25,9 @@ , stopOnEntryLaunchRequestArguments :: Bool -- Phoityne specific argument. required. , mainArgsLaunchRequestArguments :: Maybe String -- Phoityne specific argument. required. , ghciEnvLaunchRequestArguments :: M.Map String String -- Phoityne specific argument. required.+ , ghciInitialPromptLaunchRequestArguments :: Maybe String -- Phoityne specific argument. required.+ , startupFuncLaunchRequestArguments :: Maybe String+ , startupArgsLaunchRequestArguments :: Maybe String } deriving (Show, Read, Eq)
phoityne-vscode.cabal view
@@ -1,5 +1,5 @@ name: phoityne-vscode-version: 0.0.16.0+version: 0.0.17.0 synopsis: ghci debug viewer on Visual Studio Code description: Please see README.md license: BSD3