mirror of
https://github.com/CrystalSplitter/ghcitui.git
synced 2024-09-11 10:55:29 +03:00
Reorganise modules, clean up formatting
This moves the ghcitui libs which don't require Brick to ghcitui-core, and the other library files to ghcitui-brick.
This commit is contained in:
parent
301446ee85
commit
4e533fe4bb
@ -1,6 +1,6 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
module AppConfig (AppConfig(..), defaultConfig, resolveStartupSplashPath) where
|
module AppConfig (AppConfig (..), defaultConfig, resolveStartupSplashPath) where
|
||||||
|
|
||||||
import Data.Maybe (fromMaybe)
|
import Data.Maybe (fromMaybe)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
@ -31,6 +31,7 @@ data AppConfig = AppConfig
|
|||||||
-- ^ Display the debug console on start up.
|
-- ^ Display the debug console on start up.
|
||||||
, getDebugLogPath :: !FilePath
|
, getDebugLogPath :: !FilePath
|
||||||
, getVerbosity :: !Int
|
, getVerbosity :: !Int
|
||||||
|
-- ^ Verbosity level.
|
||||||
, getStartupSplashPath :: !(Maybe FilePath)
|
, getStartupSplashPath :: !(Maybe FilePath)
|
||||||
, getCmd :: !T.Text
|
, getCmd :: !T.Text
|
||||||
-- ^ Command to run to initialise the interpreter.
|
-- ^ Command to run to initialise the interpreter.
|
||||||
|
@ -44,12 +44,13 @@ import qualified Lens.Micro as Lens
|
|||||||
import AppConfig (AppConfig (..), resolveStartupSplashPath)
|
import AppConfig (AppConfig (..), resolveStartupSplashPath)
|
||||||
import qualified AppInterpState as AIS
|
import qualified AppInterpState as AIS
|
||||||
import AppTopLevel (AppName (..))
|
import AppTopLevel (AppName (..))
|
||||||
import Ghcitui.Ghcid.Daemon (toggleBreakpointLine) -- Re-export
|
|
||||||
|
import qualified Ghcitui.Brick.SourceWindow as SourceWindow
|
||||||
|
import Ghcitui.Ghcid.Daemon (toggleBreakpointLine)
|
||||||
import qualified Ghcitui.Ghcid.Daemon as Daemon
|
import qualified Ghcitui.Ghcid.Daemon as Daemon
|
||||||
import qualified Ghcitui.Ghcid.LogConfig as LogConfig
|
import qualified Ghcitui.Ghcid.LogConfig as LogConfig
|
||||||
import qualified Ghcitui.Loc as Loc
|
import qualified Ghcitui.Loc as Loc
|
||||||
import qualified SourceWindow
|
import qualified Ghcitui.Util as Util
|
||||||
import qualified Util
|
|
||||||
|
|
||||||
data ActiveWindow
|
data ActiveWindow
|
||||||
= ActiveCodeViewport
|
= ActiveCodeViewport
|
||||||
@ -59,16 +60,10 @@ data ActiveWindow
|
|||||||
| ActiveDialogHelp
|
| ActiveDialogHelp
|
||||||
deriving (Show, Eq, Ord)
|
deriving (Show, Eq, Ord)
|
||||||
|
|
||||||
data MaxState = NoMaxState
|
|
||||||
|
|
||||||
-- \| Maximised | Minimised
|
|
||||||
|
|
||||||
-- | Size information of the current GHCiTUI main boxes.
|
-- | Size information of the current GHCiTUI main boxes.
|
||||||
data WidgetSizes = WidgetSizes
|
data WidgetSizes = WidgetSizes
|
||||||
{ _wsInfoWidth :: !Int
|
{ _wsInfoWidth :: !Int
|
||||||
, _wsInfoMaxState :: !MaxState
|
|
||||||
, _wsReplHeight :: !Int
|
, _wsReplHeight :: !Int
|
||||||
, _wsReplMaxState :: !MaxState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{- | Application state wrapper.
|
{- | Application state wrapper.
|
||||||
@ -152,8 +147,7 @@ selectedFile = _selectedFile
|
|||||||
setSelectedFile :: (MonadIO m) => Maybe FilePath -> AppState n -> m (AppState n)
|
setSelectedFile :: (MonadIO m) => Maybe FilePath -> AppState n -> m (AppState n)
|
||||||
setSelectedFile mayFP appState =
|
setSelectedFile mayFP appState =
|
||||||
if mayFP == _selectedFile appState
|
if mayFP == _selectedFile appState
|
||||||
then
|
then -- If we're selecting the same file again, do nothing.
|
||||||
-- If we're selecting the same file again, do nothing.
|
|
||||||
pure appState
|
pure appState
|
||||||
else do
|
else do
|
||||||
-- Update the source map with the new file, and replace the window contents.
|
-- Update the source map with the new file, and replace the window contents.
|
||||||
@ -340,9 +334,7 @@ makeInitialState appConfig target cwd = do
|
|||||||
, _currentWidgetSizes =
|
, _currentWidgetSizes =
|
||||||
WidgetSizes
|
WidgetSizes
|
||||||
{ _wsInfoWidth = 30
|
{ _wsInfoWidth = 30
|
||||||
, _wsInfoMaxState = NoMaxState
|
|
||||||
, _wsReplHeight = 11 -- 10 plus 1 for the entry line.
|
, _wsReplHeight = 11 -- 10 plus 1 for the entry line.
|
||||||
, _wsReplMaxState = NoMaxState
|
|
||||||
}
|
}
|
||||||
, splashContents
|
, splashContents
|
||||||
, _sourceWindow = SourceWindow.mkSourcWindow SourceList ""
|
, _sourceWindow = SourceWindow.mkSourcWindow SourceList ""
|
||||||
|
@ -13,4 +13,4 @@ data AppName
|
|||||||
| ModulesViewport
|
| ModulesViewport
|
||||||
| TraceViewport
|
| TraceViewport
|
||||||
| SourceList
|
| SourceList
|
||||||
deriving (Eq, Show, Ord)
|
deriving (Eq, Show, Ord)
|
||||||
|
@ -31,12 +31,12 @@ import qualified AppState
|
|||||||
import AppTopLevel (AppName (..))
|
import AppTopLevel (AppName (..))
|
||||||
import qualified DrawSourceViewer
|
import qualified DrawSourceViewer
|
||||||
import qualified Events
|
import qualified Events
|
||||||
|
import qualified Ghcitui.Brick.SourceWindow as SourceWindow
|
||||||
import qualified Ghcitui.Ghcid.Daemon as Daemon
|
import qualified Ghcitui.Ghcid.Daemon as Daemon
|
||||||
import qualified Ghcitui.Loc as Loc
|
import qualified Ghcitui.Loc as Loc
|
||||||
import qualified Ghcitui.NameBinding as NameBinding
|
import qualified Ghcitui.NameBinding as NameBinding
|
||||||
|
import qualified Ghcitui.Util as Util
|
||||||
import qualified HelpText
|
import qualified HelpText
|
||||||
import qualified SourceWindow
|
|
||||||
import qualified Util
|
|
||||||
|
|
||||||
-- | Alias for 'AppState AppName' convenience.
|
-- | Alias for 'AppState AppName' convenience.
|
||||||
type AppS = AppState AppName
|
type AppS = AppState AppName
|
||||||
@ -316,7 +316,8 @@ brickApp =
|
|||||||
-- | Start the Brick UI
|
-- | Start the Brick UI
|
||||||
launchBrick :: AppConfig.AppConfig -> T.Text -> FilePath -> IO ()
|
launchBrick :: AppConfig.AppConfig -> T.Text -> FilePath -> IO ()
|
||||||
launchBrick conf target cwd = do
|
launchBrick conf target cwd = do
|
||||||
T.putStrLn $ "Starting up GHCiTUI with: '" <> AppConfig.getCmd conf <> "'..."
|
T.putStrLn $ "Starting up GHCiTUI with: `" <> AppConfig.getCmd conf <> "`..."
|
||||||
|
T.putStrLn "This can take a while..."
|
||||||
initialState <- makeInitialState conf target cwd
|
initialState <- makeInitialState conf target cwd
|
||||||
_ <- B.defaultMain brickApp initialState
|
_ <- B.defaultMain brickApp initialState
|
||||||
T.putStrLn "GHCiTUI has shut down; have a nice day :)"
|
T.putStrLn "GHCiTUI has shut down; have a nice day :)"
|
||||||
|
@ -5,7 +5,7 @@ module DrawSourceViewer (drawSourceViewer) where
|
|||||||
import qualified Brick as B
|
import qualified Brick as B
|
||||||
import qualified Brick.Widgets.Center as B
|
import qualified Brick.Widgets.Center as B
|
||||||
import Brick.Widgets.Core ((<+>), (<=>))
|
import Brick.Widgets.Core ((<+>), (<=>))
|
||||||
import Control.Error
|
import Control.Error (fromMaybe)
|
||||||
import Data.Function ((&))
|
import Data.Function ((&))
|
||||||
import Data.Functor ((<&>))
|
import Data.Functor ((<&>))
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
@ -16,10 +16,10 @@ import Lens.Micro ((^.))
|
|||||||
import AppState (AppState)
|
import AppState (AppState)
|
||||||
import qualified AppState
|
import qualified AppState
|
||||||
import AppTopLevel (AppName (..))
|
import AppTopLevel (AppName (..))
|
||||||
|
import qualified Ghcitui.Brick.SourceWindow as SourceWindow
|
||||||
import qualified Ghcitui.Ghcid.Daemon as Daemon
|
import qualified Ghcitui.Ghcid.Daemon as Daemon
|
||||||
import qualified Ghcitui.Loc as Loc
|
import qualified Ghcitui.Loc as Loc
|
||||||
import qualified SourceWindow
|
import qualified Ghcitui.Util as Util
|
||||||
import qualified Util
|
|
||||||
|
|
||||||
-- | Make the primary viewport widget.
|
-- | Make the primary viewport widget.
|
||||||
drawSourceViewer :: AppState AppName -> B.Widget AppName
|
drawSourceViewer :: AppState AppName -> B.Widget AppName
|
||||||
@ -95,7 +95,7 @@ drawSourceViewer' s sourceWindow = composedTogether
|
|||||||
isSelectedLine lineno = Just lineno == sourceWindow ^. SourceWindow.srcSelectedLineL
|
isSelectedLine lineno = Just lineno == sourceWindow ^. SourceWindow.srcSelectedLineL
|
||||||
|
|
||||||
composedTogether :: B.Widget AppName
|
composedTogether :: B.Widget AppName
|
||||||
composedTogether = SourceWindow.renderSourceWindow createWidget sourceWindow
|
composedTogether = SourceWindow.renderSourceWindow createWidget sourceWindow
|
||||||
where
|
where
|
||||||
createWidget lineno _old lineTxt =
|
createWidget lineno _old lineTxt =
|
||||||
styliseLine $ composedTogetherHelper lineno lineTxt
|
styliseLine $ composedTogetherHelper lineno lineTxt
|
||||||
@ -152,13 +152,13 @@ drawSourceViewer' s sourceWindow = composedTogether
|
|||||||
, gutterDigitWidth = Util.getNumDigits $ sourceWindowLength sourceWindow
|
, gutterDigitWidth = Util.getNumDigits $ sourceWindowLength sourceWindow
|
||||||
, isSelected = isSelectedLine lineno
|
, isSelected = isSelectedLine lineno
|
||||||
}
|
}
|
||||||
where
|
where
|
||||||
breakpoints :: [Int]
|
breakpoints :: [Int]
|
||||||
breakpoints =
|
breakpoints =
|
||||||
maybe
|
maybe
|
||||||
mempty
|
mempty
|
||||||
(\f -> Daemon.getBpInFile f (AppState.interpState s))
|
(\f -> Daemon.getBpInFile f (AppState.interpState s))
|
||||||
(AppState.selectedFile s)
|
(AppState.selectedFile s)
|
||||||
|
|
||||||
originalLookupLineNo :: Int
|
originalLookupLineNo :: Int
|
||||||
originalLookupLineNo =
|
originalLookupLineNo =
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
{-# LANGUAGE NamedFieldPuns #-}
|
|
||||||
{-# LANGUAGE BlockArguments #-}
|
{-# LANGUAGE BlockArguments #-}
|
||||||
|
{-# LANGUAGE NamedFieldPuns #-}
|
||||||
|
|
||||||
module Events (handleEvent, handleCursorPosition) where
|
module Events (handleEvent, handleCursorPosition) where
|
||||||
|
|
||||||
@ -19,10 +19,10 @@ import AppState
|
|||||||
import AppTopLevel
|
import AppTopLevel
|
||||||
( AppName (..)
|
( AppName (..)
|
||||||
)
|
)
|
||||||
|
import qualified Ghcitui.Brick.SourceWindow as SourceWindow
|
||||||
import qualified Ghcitui.Ghcid.Daemon as Daemon
|
import qualified Ghcitui.Ghcid.Daemon as Daemon
|
||||||
import qualified Ghcitui.Loc as Loc
|
import qualified Ghcitui.Loc as Loc
|
||||||
import qualified SourceWindow
|
import Ghcitui.Util (showT)
|
||||||
import Util (showT)
|
|
||||||
|
|
||||||
-- | Handle any Brick event and update the state.
|
-- | Handle any Brick event and update the state.
|
||||||
handleEvent :: B.BrickEvent AppName e -> B.EventM AppName (AppState AppName) ()
|
handleEvent :: B.BrickEvent AppName e -> B.EventM AppName (AppState AppName) ()
|
||||||
@ -250,7 +250,6 @@ handleSrcWindowEvent (B.VtyEvent (V.EvKey key ms))
|
|||||||
moveSelectedLineby 1
|
moveSelectedLineby 1
|
||||||
| key `elem` [V.KUp, V.KChar 'k'] = do
|
| key `elem` [V.KUp, V.KChar 'k'] = do
|
||||||
moveSelectedLineby (-1)
|
moveSelectedLineby (-1)
|
||||||
|
|
||||||
| key == V.KPageDown = do
|
| key == V.KPageDown = do
|
||||||
scrollPage SourceWindow.Down
|
scrollPage SourceWindow.Down
|
||||||
| key == V.KPageUp = do
|
| key == V.KPageUp = do
|
||||||
@ -287,7 +286,7 @@ moveSelectedLineby movAmnt = do
|
|||||||
-- These two lines need to be re-rendered.
|
-- These two lines need to be re-rendered.
|
||||||
invalidateCachedLine oldLineno
|
invalidateCachedLine oldLineno
|
||||||
invalidateCachedLine newLineno
|
invalidateCachedLine newLineno
|
||||||
B.put $ writeDebugLog ("Selected line is: " <> Util.showT newLineno) movedAppState
|
B.put $ writeDebugLog ("Selected line is: " <> showT newLineno) movedAppState
|
||||||
|
|
||||||
scrollPage :: SourceWindow.ScrollDir -> B.EventM AppName (AppState AppName) ()
|
scrollPage :: SourceWindow.ScrollDir -> B.EventM AppName (AppState AppName) ()
|
||||||
scrollPage dir = do
|
scrollPage dir = do
|
||||||
@ -342,7 +341,7 @@ invalidateLineCache = B.invalidateCache
|
|||||||
|
|
||||||
-- | Run a DaemonIO function on a given interpreter state, within an EventM monad.
|
-- | Run a DaemonIO function on a given interpreter state, within an EventM monad.
|
||||||
runDaemon
|
runDaemon
|
||||||
:: (Ord n)
|
:: (Ord n)
|
||||||
=> (Daemon.InterpState () -> Daemon.DaemonIO (Daemon.InterpState ()))
|
=> (Daemon.InterpState () -> Daemon.DaemonIO (Daemon.InterpState ()))
|
||||||
-> AppState n
|
-> AppState n
|
||||||
-> B.EventM n m (AppState n)
|
-> B.EventM n m (AppState n)
|
||||||
@ -360,7 +359,9 @@ runDaemon2
|
|||||||
-> AppState n
|
-> AppState n
|
||||||
-> B.EventM n m (AppState n, a)
|
-> B.EventM n m (AppState n, a)
|
||||||
runDaemon2 f appState = do
|
runDaemon2 f appState = do
|
||||||
(interp, x) <- liftIO $ (Daemon.run . f) appState.interpState >>= \case
|
(interp, x) <-
|
||||||
|
liftIO $
|
||||||
|
(Daemon.run . f) appState.interpState >>= \case
|
||||||
Right out -> pure out
|
Right out -> pure out
|
||||||
Left er -> error $ show er
|
Left er -> error $ show er
|
||||||
newState <- selectPausedLine appState{interpState = interp}
|
newState <- selectPausedLine appState{interpState = interp}
|
||||||
@ -431,4 +432,4 @@ handleDialogHelp _ = pure ()
|
|||||||
|
|
||||||
-- | Stop the TUI.
|
-- | Stop the TUI.
|
||||||
quit :: AppState n -> B.EventM n s ()
|
quit :: AppState n -> B.EventM n s ()
|
||||||
quit appState = liftIO (Daemon.quit appState.interpState) >> B.halt
|
quit appState = liftIO (Daemon.quit appState.interpState) >> B.halt
|
||||||
|
269
app/HelpText.hs
269
app/HelpText.hs
@ -7,137 +7,138 @@ import Data.String (IsString)
|
|||||||
-- import Data.FileEmbed
|
-- import Data.FileEmbed
|
||||||
|
|
||||||
helpText :: (IsString a) => a
|
helpText :: (IsString a) => a
|
||||||
helpText = "\
|
helpText =
|
||||||
\GHCITUI MANUAL() GHCITUI MANUAL()\n\
|
"\
|
||||||
\\n\
|
\GHCITUI MANUAL() GHCITUI MANUAL()\n\
|
||||||
\NAME\n\
|
\\n\
|
||||||
\ GHCiTUI MANUAL -\n\
|
\NAME\n\
|
||||||
\\n\
|
\ GHCiTUI MANUAL -\n\
|
||||||
\CLI SYNOPSIS\n\
|
\\n\
|
||||||
\ Usage: ghcitui [OPTIONS] [TARGET]\n\
|
\CLI SYNOPSIS\n\
|
||||||
\\n\
|
\ Usage: ghcitui [OPTIONS] [TARGET]\n\
|
||||||
\ ghcitui: A TUI interface for GHCi\n\
|
\\n\
|
||||||
\\n\
|
\ ghcitui: A TUI interface for GHCi\n\
|
||||||
\ Available options:\n\
|
\\n\
|
||||||
\ -h,--help Show this help text\n\
|
\ Available options:\n\
|
||||||
\ -d,--debug-console Display the debug console\n\
|
\ -h,--help Show this help text\n\
|
||||||
\ -c,--cmd CMD Command to start the internal\n\
|
\ -d,--debug-console Display the debug console\n\
|
||||||
\ interpreter\n\
|
\ -c,--cmd CMD Command to start the internal\n\
|
||||||
\ -C,--workdir DIR Set working dir\n\
|
\ interpreter\n\
|
||||||
\\n\
|
\ -C,--workdir DIR Set working dir\n\
|
||||||
\STARTING AND STOPPING\n\
|
\\n\
|
||||||
\ Starting\n\
|
\STARTING AND STOPPING\n\
|
||||||
\ GHCiTUI runs a REPL in the current directory by default. By default,\n\
|
\ Starting\n\
|
||||||
\ it launches cabal repl.\n\
|
\ GHCiTUI runs a REPL in the current directory by default. By default,\n\
|
||||||
\\n\
|
\ it launches cabal repl.\n\
|
||||||
\ $ cd your/cabal/project/root/directory\n\
|
\\n\
|
||||||
\ $ ghcitui\n\
|
\ $ cd your/cabal/project/root/directory\n\
|
||||||
\\n\
|
\ $ ghcitui\n\
|
||||||
\ You can specify another starting directory with the -C <DIR> flag.\n\
|
\\n\
|
||||||
\\n\
|
\ You can specify another starting directory with the -C <DIR> flag.\n\
|
||||||
\ $ ghcitui -C some/other/directory\n\
|
\\n\
|
||||||
\\n\
|
\ $ ghcitui -C some/other/directory\n\
|
||||||
\ Stopping\n\
|
\\n\
|
||||||
\ To quit, press <ESC> or q while in the code viewport panel to quit.\n\
|
\ Stopping\n\
|
||||||
\ While not in the code viewport panel, you may press <ESC> to get to\n\
|
\ To quit, press <ESC> or q while in the code viewport panel to quit.\n\
|
||||||
\ the viewport panel.\n\
|
\ While not in the code viewport panel, you may press <ESC> to get to\n\
|
||||||
\\n\
|
\ the viewport panel.\n\
|
||||||
\LAYOUT\n\
|
\\n\
|
||||||
\ GHCiTUI is an in-terminal viewer for GHCi. The TUI is broken up into\n\
|
\LAYOUT\n\
|
||||||
\ three primary panels, with some additional auxiliary panels for spe‐\n\
|
\ GHCiTUI is an in-terminal viewer for GHCi. The TUI is broken up into\n\
|
||||||
\ cial use cases:\n\
|
\ three primary panels, with some additional auxiliary panels for spe‐\n\
|
||||||
\\n\
|
\ cial use cases:\n\
|
||||||
\ ┌──────────────────┬──────┐\n\
|
\\n\
|
||||||
\ │ │ Info │\n\
|
\ ┌──────────────────┬──────┐\n\
|
||||||
\ │ │ │\n\
|
\ │ │ Info │\n\
|
||||||
\ │ Source Viewer │ │\n\
|
\ │ │ │\n\
|
||||||
\ │ │ │\n\
|
\ │ Source Viewer │ │\n\
|
||||||
\ │ │ │\n\
|
\ │ │ │\n\
|
||||||
\ ├──────────────────┤ │\n\
|
\ │ │ │\n\
|
||||||
\ │ │ │\n\
|
\ ├──────────────────┤ │\n\
|
||||||
\ │ Live Interpreter │ │\n\
|
\ │ │ │\n\
|
||||||
\ │ │ │\n\
|
\ │ Live Interpreter │ │\n\
|
||||||
\ └──────────────────┴──────┘\n\
|
\ │ │ │\n\
|
||||||
\\n\
|
\ └──────────────────┴──────┘\n\
|
||||||
\ Source Viewer: This panel shows source code. You can step, continue,\n\
|
\\n\
|
||||||
\ and toggle breakpoints among other operations in this panel.\n\
|
\ Source Viewer: This panel shows source code. You can step, continue,\n\
|
||||||
\\n\
|
\ and toggle breakpoints among other operations in this panel.\n\
|
||||||
\ Live Interpreter: This panel shows the GHCi/REPL passthrough. You can\n\
|
\\n\
|
||||||
\ enter expressions and GHCi commands here like you would normally,\n\
|
\ Live Interpreter: This panel shows the GHCi/REPL passthrough. You can\n\
|
||||||
\ with some additional keybindings.\n\
|
\ enter expressions and GHCi commands here like you would normally,\n\
|
||||||
\\n\
|
\ with some additional keybindings.\n\
|
||||||
\ Info: This panel displays miscellaneous info about whatever is cur‐\n\
|
\\n\
|
||||||
\ rently running. For example, it can display the current bindings,\n\
|
\ Info: This panel displays miscellaneous info about whatever is cur‐\n\
|
||||||
\ loaded modules, and the current program trace.\n\
|
\ rently running. For example, it can display the current bindings,\n\
|
||||||
\\n\
|
\ loaded modules, and the current program trace.\n\
|
||||||
\NAVIGATION\n\
|
\\n\
|
||||||
\ At any point in time, you can revert back to the Source Viewer panel\n\
|
\NAVIGATION\n\
|
||||||
\ with the <Esc> key, and you can always quit by hitting <Esc> in the\n\
|
\ At any point in time, you can revert back to the Source Viewer panel\n\
|
||||||
\ Source Viewer panel.\n\
|
\ with the <Esc> key, and you can always quit by hitting <Esc> in the\n\
|
||||||
\\n\
|
\ Source Viewer panel.\n\
|
||||||
\KEYBINDINGS\n\
|
\\n\
|
||||||
\ At this time, keybindings are hardcoded. This will hopefully change\n\
|
\KEYBINDINGS\n\
|
||||||
\ in the future with a keybinding configuration file.\n\
|
\ At this time, keybindings are hardcoded. This will hopefully change\n\
|
||||||
\\n\
|
\ in the future with a keybinding configuration file.\n\
|
||||||
\ Source Viewer\n\
|
\\n\
|
||||||
\ • Ctrl+x: Toggle between the Source Viewer and the Live Interpreter\n\
|
\ Source Viewer\n\
|
||||||
\ panels.\n\
|
\ • Ctrl+x: Toggle between the Source Viewer and the Live Interpreter\n\
|
||||||
\\n\
|
\ panels.\n\
|
||||||
\ • <Esc>, q: Quit.\n\
|
\\n\
|
||||||
\\n\
|
\ • <Esc>, q: Quit.\n\
|
||||||
\ • <Up>, k: Move the cursor up. (j and k from Vim keybinds)\n\
|
\\n\
|
||||||
\\n\
|
\ • <Up>, k: Move the cursor up. (j and k from Vim keybinds)\n\
|
||||||
\ • <Down>, j: Move the cursor down. (j and k from Vim keybinds).\n\
|
\\n\
|
||||||
\\n\
|
\ • <Down>, j: Move the cursor down. (j and k from Vim keybinds).\n\
|
||||||
\ • <PgUp>: Move the source viewer one page up.\n\
|
\\n\
|
||||||
\\n\
|
\ • <PgUp>: Move the source viewer one page up.\n\
|
||||||
\ • <PgDown>: Move the source viewer one page down.\n\
|
\\n\
|
||||||
\\n\
|
\ • <PgDown>: Move the source viewer one page down.\n\
|
||||||
\ • +, -: Increase/decrease the Info panel size.\n\
|
\\n\
|
||||||
\\n\
|
\ • +, -: Increase/decrease the Info panel size.\n\
|
||||||
\ • b: Toggle breakpoint at current line. Not every line in a source\n\
|
\\n\
|
||||||
\ file can have a breakpoint placed on it.\n\
|
\ • b: Toggle breakpoint at current line. Not every line in a source\n\
|
||||||
\\n\
|
\ file can have a breakpoint placed on it.\n\
|
||||||
\ • s: Advance execution by one step. Same as the :step in GHCi.\n\
|
\\n\
|
||||||
\\n\
|
\ • s: Advance execution by one step. Same as the :step in GHCi.\n\
|
||||||
\ • c: Advance execution until next breakpoint. Same as :continue in\n\
|
\\n\
|
||||||
\ GHCi.\n\
|
\ • c: Advance execution until next breakpoint. Same as :continue in\n\
|
||||||
\\n\
|
\ GHCi.\n\
|
||||||
\ • t: Advance execution until next breakpoint under tracing. Same as\n\
|
\\n\
|
||||||
\ :trace in GHCi.\n\
|
\ • t: Advance execution until next breakpoint under tracing. Same as\n\
|
||||||
\\n\
|
\ :trace in GHCi.\n\
|
||||||
\ Live Interpreter (REPL)\n\
|
\\n\
|
||||||
\ • Ctrl+x: Toggle between the Source Viewer and the Live Interpreter\n\
|
\ Live Interpreter (REPL)\n\
|
||||||
\ panels.\n\
|
\ • Ctrl+x: Toggle between the Source Viewer and the Live Interpreter\n\
|
||||||
\\n\
|
\ panels.\n\
|
||||||
\ • <Esc>: Switch to Source Viewer.\n\
|
\\n\
|
||||||
\\n\
|
\ • <Esc>: Switch to Source Viewer.\n\
|
||||||
\ • <Up>: Scroll back in time through the REPL command history.\n\
|
\\n\
|
||||||
\\n\
|
\ • <Up>: Scroll back in time through the REPL command history.\n\
|
||||||
\ • <Down>: Scroll forward in time through the REPL command history.\n\
|
\\n\
|
||||||
\\n\
|
\ • <Down>: Scroll forward in time through the REPL command history.\n\
|
||||||
\ • <PgUp>: Scroll the Live Interpreter window one page up.\n\
|
\\n\
|
||||||
\\n\
|
\ • <PgUp>: Scroll the Live Interpreter window one page up.\n\
|
||||||
\ • <PgDown>: Scroll the Live Interpreter window one page down.\n\
|
\\n\
|
||||||
\\n\
|
\ • <PgDown>: Scroll the Live Interpreter window one page down.\n\
|
||||||
\ • Ctrl+n: Toggle scrolling mode.\n\
|
\\n\
|
||||||
\\n\
|
\ • Ctrl+n: Toggle scrolling mode.\n\
|
||||||
\ • +, - while in scrolling mode: Increase/decrease the live panel\n\
|
\\n\
|
||||||
\ size.\n\
|
\ • +, - while in scrolling mode: Increase/decrease the live panel\n\
|
||||||
\\n\
|
\ size.\n\
|
||||||
\ • <Enter>: Enter a command to the REPL.\n\
|
\\n\
|
||||||
\\n\
|
\ • <Enter>: Enter a command to the REPL.\n\
|
||||||
\ Modules\n\
|
\\n\
|
||||||
\ • Ctrl+x: Switch to the Live Interpreter.\n\
|
\ Modules\n\
|
||||||
\\n\
|
\ • Ctrl+x: Switch to the Live Interpreter.\n\
|
||||||
\ • <Esc>: Switch to Source Viewer.\n\
|
\\n\
|
||||||
\\n\
|
\ • <Esc>: Switch to Source Viewer.\n\
|
||||||
\ • <Up>, k: Move the module selection up.\n\
|
\\n\
|
||||||
\\n\
|
\ • <Up>, k: Move the module selection up.\n\
|
||||||
\ • <Down>, j: Move the module selection down.\n\
|
\\n\
|
||||||
\\n\
|
\ • <Down>, j: Move the module selection down.\n\
|
||||||
\ • +, -: Increase/decrease the info panel size.\n\
|
\\n\
|
||||||
\\n\
|
\ • +, -: Increase/decrease the info panel size.\n\
|
||||||
\ • <Enter>, o: Open the selected module.\n\
|
\\n\
|
||||||
\\n\
|
\ • <Enter>, o: Open the selected module.\n\
|
||||||
\ GHCITUI MANUAL()"
|
\\n\
|
||||||
|
\ GHCITUI MANUAL()"
|
||||||
|
@ -3,8 +3,8 @@
|
|||||||
|
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
import qualified Paths_ghcitui as CabalPkg
|
|
||||||
import qualified Data.Version
|
import qualified Data.Version
|
||||||
|
import qualified Paths_ghcitui as CabalPkg
|
||||||
|
|
||||||
import Control.Applicative (many)
|
import Control.Applicative (many)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
@ -42,7 +42,7 @@ parseOpts = do
|
|||||||
( Opt.long "daemon-log"
|
( Opt.long "daemon-log"
|
||||||
<> Opt.help daemonLogHelp
|
<> Opt.help daemonLogHelp
|
||||||
<> Opt.metavar "LOGFILE"
|
<> Opt.metavar "LOGFILE"
|
||||||
<> Opt.value "/tmp/ghcitui.log"
|
<> Opt.value "stderr"
|
||||||
)
|
)
|
||||||
cmd <-
|
cmd <-
|
||||||
Opt.strOption
|
Opt.strOption
|
||||||
@ -71,7 +71,7 @@ parseOpts = do
|
|||||||
"File path for debugging daemon logs."
|
"File path for debugging daemon logs."
|
||||||
<> " Used with -v."
|
<> " Used with -v."
|
||||||
<> " Setting this to 'stdout' or 'stderr' sends logs to each, respectively."
|
<> " Setting this to 'stdout' or 'stderr' sends logs to each, respectively."
|
||||||
<> " Defaults to /tmp/ghcitui.log."
|
<> " Defaults to 'stderr'"
|
||||||
|
|
||||||
-- | The cabal package version.
|
-- | The cabal package version.
|
||||||
programVersion :: String
|
programVersion :: String
|
||||||
@ -98,4 +98,4 @@ main = do
|
|||||||
where
|
where
|
||||||
programName = "ghcitui"
|
programName = "ghcitui"
|
||||||
programDescription = Opt.progDesc (programName <> ": A TUI interface for GHCi")
|
programDescription = Opt.progDesc (programName <> ": A TUI interface for GHCi")
|
||||||
parserInfo = Opt.info (Opt.helper <*> parseOpts) (Opt.fullDesc <> programDescription)
|
parserInfo = Opt.info (Opt.helper <*> parseOpts) (Opt.fullDesc <> programDescription)
|
||||||
|
@ -4,14 +4,19 @@ version: 0.1.0.0
|
|||||||
synopsis: A Terminal User Interface (TUI) for GHCi
|
synopsis: A Terminal User Interface (TUI) for GHCi
|
||||||
|
|
||||||
description:
|
description:
|
||||||
A visual interface for GHCi debug mode inside the terminal.
|
A terminal user interface for GHCi debug mode.
|
||||||
|
.
|
||||||
Features:
|
Features:
|
||||||
* A source view window, with debug keybindings.
|
.
|
||||||
* Live variable bindings.
|
* A source view window, with debug keybindings.
|
||||||
* Live loaded modules.
|
.
|
||||||
* Visible trace history.
|
* Live variable bindings.
|
||||||
* An GHCi session in the current context.
|
.
|
||||||
|
* Live loaded modules.
|
||||||
|
.
|
||||||
|
* Visible trace history.
|
||||||
|
.
|
||||||
|
* An GHCi session in the current context.
|
||||||
|
|
||||||
bug-reports: https://github.com/CrystalSplitter/ghcitui
|
bug-reports: https://github.com/CrystalSplitter/ghcitui
|
||||||
license: BSD-3-Clause
|
license: BSD-3-Clause
|
||||||
@ -19,7 +24,7 @@ license-file: LICENSE
|
|||||||
author: Jordan 'CrystalSplitter' R AW
|
author: Jordan 'CrystalSplitter' R AW
|
||||||
maintainer: crystal@crystalwobsite.gay
|
maintainer: crystal@crystalwobsite.gay
|
||||||
copyright: Jordan R AW
|
copyright: Jordan R AW
|
||||||
category: Debug
|
category: Debug
|
||||||
extra-source-files: CHANGELOG.md
|
extra-source-files: CHANGELOG.md
|
||||||
, LICENSE
|
, LICENSE
|
||||||
, MANUAL.rst
|
, MANUAL.rst
|
||||||
@ -35,21 +40,21 @@ executable ghcitui
|
|||||||
, brick
|
, brick
|
||||||
, containers >= 0.6.7 && < 0.8
|
, containers >= 0.6.7 && < 0.8
|
||||||
, errors ^>= 2.3.0
|
, errors ^>= 2.3.0
|
||||||
, ghcitui-lib
|
, ghcitui-core
|
||||||
|
, ghcitui-brick
|
||||||
, microlens ^>= 0.4.13.1
|
, microlens ^>= 0.4.13.1
|
||||||
, microlens-th ^>= 0.4.3.14
|
, microlens-th ^>= 0.4.3.14
|
||||||
, optparse-applicative ^>= 0.18.1.0
|
, optparse-applicative ^>= 0.18.1.0
|
||||||
, safe ^>= 0.3.19
|
, safe ^>= 0.3.19
|
||||||
, text ^>= 2.0.2
|
, text ^>= 2.0.2
|
||||||
, text-zipper ^>= 0.13
|
, text-zipper ^>= 0.13
|
||||||
|
, vector ^>= 0.13.1.0
|
||||||
, vty ^>= 5.38
|
, vty ^>= 5.38
|
||||||
, word-wrap ^>= 0.5
|
, word-wrap ^>= 0.5
|
||||||
, vector ^>= 0.13.1.0
|
|
||||||
hs-source-dirs: app
|
hs-source-dirs: app
|
||||||
other-modules: BrickUI
|
other-modules: BrickUI
|
||||||
, AppState
|
, AppState
|
||||||
, AppTopLevel
|
, AppTopLevel
|
||||||
, Util
|
|
||||||
, AppInterpState
|
, AppInterpState
|
||||||
, AppConfig
|
, AppConfig
|
||||||
, DrawSourceViewer
|
, DrawSourceViewer
|
||||||
@ -57,7 +62,6 @@ executable ghcitui
|
|||||||
, HelpText
|
, HelpText
|
||||||
-- Cabal autogen module for package version info.
|
-- Cabal autogen module for package version info.
|
||||||
, Paths_ghcitui
|
, Paths_ghcitui
|
||||||
, SourceWindow
|
|
||||||
ghc-options: -rtsopts
|
ghc-options: -rtsopts
|
||||||
-threaded
|
-threaded
|
||||||
-Wall
|
-Wall
|
||||||
@ -75,8 +79,8 @@ executable ghcitui
|
|||||||
MonoLocalBinds
|
MonoLocalBinds
|
||||||
NamedFieldPuns
|
NamedFieldPuns
|
||||||
|
|
||||||
library ghcitui-lib
|
library ghcitui-core
|
||||||
hs-source-dirs: lib
|
hs-source-dirs: lib/ghcitui-core
|
||||||
build-depends: base >= 4.17 && < 5
|
build-depends: base >= 4.17 && < 5
|
||||||
, array ^>= 0.5.4.0
|
, array ^>= 0.5.4.0
|
||||||
, containers >= 0.6.7 && < 0.8
|
, containers >= 0.6.7 && < 0.8
|
||||||
@ -109,6 +113,27 @@ library ghcitui-lib
|
|||||||
MonoLocalBinds
|
MonoLocalBinds
|
||||||
NamedFieldPuns
|
NamedFieldPuns
|
||||||
|
|
||||||
|
library ghcitui-brick
|
||||||
|
hs-source-dirs: lib/ghcitui-brick
|
||||||
|
build-depends: base >= 4.17 && < 5
|
||||||
|
, brick
|
||||||
|
, containers >= 0.6.7 && < 0.8
|
||||||
|
, errors ^>= 2.3.0
|
||||||
|
, ghcitui-core
|
||||||
|
, microlens ^>= 0.4.13.1
|
||||||
|
, microlens-th ^>= 0.4.3.14
|
||||||
|
, text ^>= 2.0.2
|
||||||
|
, vector ^>= 0.13.1.0
|
||||||
|
exposed-modules: Ghcitui.Brick.SourceWindow
|
||||||
|
ghc-options: -Wall
|
||||||
|
-Wcompat
|
||||||
|
-Wincomplete-record-updates
|
||||||
|
-Wpartial-fields
|
||||||
|
-Wredundant-constraints
|
||||||
|
default-language: Haskell2010
|
||||||
|
default-extensions: OverloadedStrings
|
||||||
|
MonoLocalBinds
|
||||||
|
NamedFieldPuns
|
||||||
|
|
||||||
test-suite spec
|
test-suite spec
|
||||||
hs-source-dirs: test
|
hs-source-dirs: test
|
||||||
@ -116,7 +141,7 @@ test-suite spec
|
|||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
build-depends: base >= 4.17 && < 5
|
build-depends: base >= 4.17 && < 5
|
||||||
, hspec ^>= 2.11.5
|
, hspec ^>= 2.11.5
|
||||||
, ghcitui-lib
|
, ghcitui-core
|
||||||
other-modules: LocSpec
|
other-modules: LocSpec
|
||||||
, UtilSpec
|
, UtilSpec
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
module Ghcitui.Util (showT, splitBy, linesToText) where
|
|
||||||
|
|
||||||
import Data.Text (Text, breakOn, drop, length, pack)
|
|
||||||
import Prelude hiding (drop, length)
|
|
||||||
|
|
||||||
-- | Split text based on a delimiter.
|
|
||||||
splitBy
|
|
||||||
:: Text
|
|
||||||
-- ^ Delimeter.
|
|
||||||
-> Text
|
|
||||||
-- ^ Text to split on.
|
|
||||||
-> [Text]
|
|
||||||
splitBy "" source = [source]
|
|
||||||
splitBy delim source =
|
|
||||||
case breakOn delim source of
|
|
||||||
(l, "") -> [l]
|
|
||||||
(l, r) -> l : splitBy delim (drop (length delim) r)
|
|
||||||
|
|
||||||
-- | Convert Strings to Text.
|
|
||||||
linesToText :: [String] -> Text
|
|
||||||
linesToText = pack . Prelude.unlines
|
|
||||||
|
|
||||||
-- | 'show' but to Text.
|
|
||||||
showT :: (Show a) => a -> Text
|
|
||||||
showT = pack . show
|
|
@ -1,8 +1,9 @@
|
|||||||
{-# LANGUAGE BlockArguments #-}
|
{-# LANGUAGE BlockArguments #-}
|
||||||
{-# LANGUAGE NamedFieldPuns #-}
|
{-# LANGUAGE NamedFieldPuns #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
|
|
||||||
module SourceWindow
|
module Ghcitui.Brick.SourceWindow
|
||||||
( SourceWindow (srcElements)
|
( SourceWindow (srcElements)
|
||||||
|
|
||||||
-- * Creation
|
-- * Creation
|
||||||
@ -26,7 +27,7 @@ module SourceWindow
|
|||||||
, srcSelectedLineL
|
, srcSelectedLineL
|
||||||
, srcWindowStartL
|
, srcWindowStartL
|
||||||
|
|
||||||
-- * Misc
|
-- * Misc
|
||||||
, srcWindowLength
|
, srcWindowLength
|
||||||
) where
|
) where
|
||||||
|
|
||||||
@ -38,14 +39,20 @@ import Lens.Micro ((^.))
|
|||||||
import qualified Lens.Micro as Lens
|
import qualified Lens.Micro as Lens
|
||||||
import Lens.Micro.TH (makeLensesFor)
|
import Lens.Micro.TH (makeLensesFor)
|
||||||
|
|
||||||
import qualified Util
|
import qualified Ghcitui.Util as Util
|
||||||
|
|
||||||
data SourceWindow n e = SourceWindow
|
-- | Hold data regarding a code source viewing window.
|
||||||
{ srcElements :: !(Vec.Vector e)
|
data SourceWindow name elem = SourceWindow
|
||||||
|
{ srcElements :: !(Vec.Vector elem)
|
||||||
|
-- ^ The actual entries for each source window.
|
||||||
, srcWindowStart :: !Int
|
, srcWindowStart :: !Int
|
||||||
|
-- ^ The starting position of the window, as a line number (1-indexed).
|
||||||
|
-- No lines before this line number is rendered.
|
||||||
, srcWindowEnd :: !(Maybe Int)
|
, srcWindowEnd :: !(Maybe Int)
|
||||||
, srcName :: !n
|
, srcName :: !name
|
||||||
|
-- ^ The name of the window.
|
||||||
, srcSelectedLine :: !(Maybe Int)
|
, srcSelectedLine :: !(Maybe Int)
|
||||||
|
-- ^ The currently selected line in the window.
|
||||||
}
|
}
|
||||||
deriving (Show)
|
deriving (Show)
|
||||||
|
|
||||||
@ -58,11 +65,15 @@ makeLensesFor
|
|||||||
]
|
]
|
||||||
''SourceWindow
|
''SourceWindow
|
||||||
|
|
||||||
|
-- | Render a 'SourceWindow' into a Brick 'B.Widget'.
|
||||||
renderSourceWindow
|
renderSourceWindow
|
||||||
:: (Ord n)
|
:: (Ord n)
|
||||||
=> (Int -> Bool -> e -> B.Widget n)
|
=> (Int -> Bool -> e -> B.Widget n)
|
||||||
|
-- ^ Render function.
|
||||||
-> SourceWindow n e
|
-> SourceWindow n e
|
||||||
|
-- ^ 'SourceWindow' to render.
|
||||||
-> B.Widget n
|
-> B.Widget n
|
||||||
|
-- ^ The newly created widget.
|
||||||
renderSourceWindow func srcW = B.reportExtent (srcName srcW) (B.Widget B.Greedy B.Greedy renderM)
|
renderSourceWindow func srcW = B.reportExtent (srcName srcW) (B.Widget B.Greedy B.Greedy renderM)
|
||||||
where
|
where
|
||||||
renderM = do
|
renderM = do
|
||||||
@ -85,6 +96,10 @@ renderSourceWindow func srcW = B.reportExtent (srcName srcW) (B.Widget B.Greedy
|
|||||||
remainingElements = srcWindowLength srcW - startZeroIdx
|
remainingElements = srcWindowLength srcW - startZeroIdx
|
||||||
elems = srcElements srcW
|
elems = srcElements srcW
|
||||||
|
|
||||||
|
{- | Return the length of the full contents of the source code stored in the window.
|
||||||
|
|
||||||
|
Note, does NOT return the current length/height/size of the rendered widget.
|
||||||
|
-}
|
||||||
srcWindowLength :: SourceWindow n e -> Int
|
srcWindowLength :: SourceWindow n e -> Int
|
||||||
srcWindowLength = Vec.length . srcElements
|
srcWindowLength = Vec.length . srcElements
|
||||||
|
|
||||||
@ -122,6 +137,7 @@ scrollTo pos srcW@SourceWindow{srcWindowEnd = Just windowEnd} =
|
|||||||
<$> srcSelectedLine srcW
|
<$> srcSelectedLine srcW
|
||||||
scrollTo _ srcW = srcW
|
scrollTo _ srcW = srcW
|
||||||
|
|
||||||
|
-- | Direction to scroll by.
|
||||||
data ScrollDir = Up | Down deriving (Eq, Show)
|
data ScrollDir = Up | Down deriving (Eq, Show)
|
||||||
|
|
||||||
-- | Scroll by a full page in a direction.
|
-- | Scroll by a full page in a direction.
|
||||||
@ -139,7 +155,14 @@ srcWindowScrollPage' dir srcW =
|
|||||||
where
|
where
|
||||||
windowEnd = fromMaybe 1 $ srcWindowEnd srcW
|
windowEnd = fromMaybe 1 $ srcWindowEnd srcW
|
||||||
|
|
||||||
setSelectionTo :: (Ord n) => Int -> SourceWindow n e -> B.EventM n m (SourceWindow n e)
|
-- | Set the selection to a given position, and scroll the window accordingly.
|
||||||
|
setSelectionTo
|
||||||
|
:: (Ord n)
|
||||||
|
=> Int
|
||||||
|
-- ^ Line number to set the selection to (1-indexed)
|
||||||
|
-> SourceWindow n e
|
||||||
|
-- ^ Source window to update.
|
||||||
|
-> B.EventM n m (SourceWindow n e)
|
||||||
setSelectionTo pos srcW@SourceWindow{srcSelectedLine = Just sl, srcWindowEnd = Just end} =
|
setSelectionTo pos srcW@SourceWindow{srcSelectedLine = Just sl, srcWindowEnd = Just end} =
|
||||||
if pos < srcWindowStart srcW || pos > end
|
if pos < srcWindowStart srcW || pos > end
|
||||||
then srcWindowMoveSelectionBy delta srcW
|
then srcWindowMoveSelectionBy delta srcW
|
||||||
@ -150,7 +173,13 @@ setSelectionTo pos srcW@SourceWindow{srcSelectedLine = Just sl, srcWindowEnd = J
|
|||||||
setSelectionTo _ srcW = pure srcW
|
setSelectionTo _ srcW = pure srcW
|
||||||
|
|
||||||
-- | Move the selected line by a given amount.
|
-- | Move the selected line by a given amount.
|
||||||
srcWindowMoveSelectionBy :: (Ord n) => Int -> SourceWindow n e -> B.EventM n m (SourceWindow n e)
|
srcWindowMoveSelectionBy
|
||||||
|
:: (Ord n)
|
||||||
|
=> Int
|
||||||
|
-- ^ Delta to move the selected line.
|
||||||
|
-> SourceWindow n e
|
||||||
|
-- ^ Source window to update.
|
||||||
|
-> B.EventM n m (SourceWindow n e)
|
||||||
srcWindowMoveSelectionBy amnt sw = do
|
srcWindowMoveSelectionBy amnt sw = do
|
||||||
srcW' <- updateSrcWindowEnd sw
|
srcW' <- updateSrcWindowEnd sw
|
||||||
case srcWindowEnd srcW' of
|
case srcWindowEnd srcW' of
|
||||||
@ -185,9 +214,9 @@ mkSourcWindow
|
|||||||
-- ^ Name for the source window.
|
-- ^ Name for the source window.
|
||||||
-> T.Text
|
-> T.Text
|
||||||
-- ^ Text contents of the source window (to be split up).
|
-- ^ Text contents of the source window (to be split up).
|
||||||
-> SourceWindow.SourceWindow n T.Text
|
-> SourceWindow n T.Text
|
||||||
mkSourcWindow name text =
|
mkSourcWindow name text =
|
||||||
SourceWindow.SourceWindow
|
SourceWindow
|
||||||
{ srcElements = lineVec
|
{ srcElements = lineVec
|
||||||
, srcWindowStart = 1
|
, srcWindowStart = 1
|
||||||
, srcSelectedLine = Just 1
|
, srcSelectedLine = Just 1
|
||||||
@ -195,4 +224,4 @@ mkSourcWindow name text =
|
|||||||
, srcWindowEnd = Nothing
|
, srcWindowEnd = Nothing
|
||||||
}
|
}
|
||||||
where
|
where
|
||||||
lineVec = Vec.fromList (T.lines text)
|
lineVec = Vec.fromList (T.lines text)
|
@ -19,7 +19,7 @@ module Ghcitui.Ghcid.Daemon
|
|||||||
|
|
||||||
-- * Startup and shutdown
|
-- * Startup and shutdown
|
||||||
, startup
|
, startup
|
||||||
, StartupConfig(..)
|
, StartupConfig (..)
|
||||||
, quit
|
, quit
|
||||||
|
|
||||||
-- * Base operations with the daemon
|
-- * Base operations with the daemon
|
||||||
@ -50,7 +50,7 @@ module Ghcitui.Ghcid.Daemon
|
|||||||
, run
|
, run
|
||||||
, DaemonIO
|
, DaemonIO
|
||||||
, DaemonError
|
, DaemonError
|
||||||
, LogOutput(..)
|
, LogOutput (..)
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Control.Error
|
import Control.Error
|
||||||
@ -62,14 +62,14 @@ import qualified Data.Text.IO as T
|
|||||||
import qualified Language.Haskell.Ghcid as Ghcid
|
import qualified Language.Haskell.Ghcid as Ghcid
|
||||||
import System.IO (stderr)
|
import System.IO (stderr)
|
||||||
|
|
||||||
|
import Ghcitui.Ghcid.LogConfig (LogLevel (..), LogOutput (..))
|
||||||
import qualified Ghcitui.Ghcid.ParseContext as ParseContext
|
import qualified Ghcitui.Ghcid.ParseContext as ParseContext
|
||||||
|
import Ghcitui.Ghcid.StartupConfig (StartupConfig)
|
||||||
|
import qualified Ghcitui.Ghcid.StartupConfig as StartupConfig
|
||||||
import qualified Ghcitui.Loc as Loc
|
import qualified Ghcitui.Loc as Loc
|
||||||
import qualified Ghcitui.NameBinding as NameBinding
|
import qualified Ghcitui.NameBinding as NameBinding
|
||||||
import Ghcitui.Util (showT)
|
import Ghcitui.Util (showT)
|
||||||
import qualified Ghcitui.Util as Util
|
import qualified Ghcitui.Util as Util
|
||||||
import Ghcitui.Ghcid.LogConfig (LogLevel(..), LogOutput(..))
|
|
||||||
import Ghcitui.Ghcid.StartupConfig (StartupConfig)
|
|
||||||
import qualified Ghcitui.Ghcid.StartupConfig as StartupConfig
|
|
||||||
|
|
||||||
data InterpState a = InterpState
|
data InterpState a = InterpState
|
||||||
{ _ghci :: Ghcid.Ghci
|
{ _ghci :: Ghcid.Ghci
|
||||||
@ -111,7 +111,7 @@ instance Show (InterpState a) where
|
|||||||
in msg
|
in msg
|
||||||
|
|
||||||
{- | Create an empty/starting interpreter state.
|
{- | Create an empty/starting interpreter state.
|
||||||
Usually you don't want to call this directly. Instead use 'startup'.
|
Usually you don't want to call this directly. Instead use 'startup'.
|
||||||
-}
|
-}
|
||||||
emptyInterpreterState :: (Monoid a) => Ghcid.Ghci -> StartupConfig -> InterpState a
|
emptyInterpreterState :: (Monoid a) => Ghcid.Ghci -> StartupConfig -> InterpState a
|
||||||
emptyInterpreterState ghci startupConfig =
|
emptyInterpreterState ghci startupConfig =
|
||||||
@ -132,14 +132,15 @@ emptyInterpreterState ghci startupConfig =
|
|||||||
|
|
||||||
-- | Reset anything context-based in a 'InterpState'.
|
-- | Reset anything context-based in a 'InterpState'.
|
||||||
contextReset :: (Monoid a) => InterpState a -> InterpState a
|
contextReset :: (Monoid a) => InterpState a -> InterpState a
|
||||||
contextReset state = state {
|
contextReset state =
|
||||||
func = Nothing
|
state
|
||||||
, pauseLoc = Nothing
|
{ func = Nothing
|
||||||
, stack = mempty
|
, pauseLoc = Nothing
|
||||||
, bindings = Right mempty
|
, stack = mempty
|
||||||
, status = Right mempty
|
, bindings = Right mempty
|
||||||
, traceHist = mempty
|
, status = Right mempty
|
||||||
}
|
, traceHist = mempty
|
||||||
|
}
|
||||||
|
|
||||||
-- | Append a string to the interpreter's history.
|
-- | Append a string to the interpreter's history.
|
||||||
appendExecHist :: T.Text -> InterpState a -> InterpState a
|
appendExecHist :: T.Text -> InterpState a -> InterpState a
|
||||||
@ -278,8 +279,7 @@ stepInto
|
|||||||
stepInto func = execMuted (":step " <> func)
|
stepInto func = execMuted (":step " <> func)
|
||||||
|
|
||||||
{- | Analogue to @:history@.
|
{- | Analogue to @:history@.
|
||||||
|
Returns either a 'Left' error message, or a 'Right' list of trace breakpoints.
|
||||||
Returns either the 'Left' error messager, or 'Right': list the trace breakpoints.
|
|
||||||
-}
|
-}
|
||||||
history :: InterpState a -> DaemonIO (InterpState a, Either T.Text [T.Text])
|
history :: InterpState a -> DaemonIO (InterpState a, Either T.Text [T.Text])
|
||||||
history state = do
|
history state = do
|
||||||
@ -309,8 +309,8 @@ load :: (Monoid a) => FilePath -> InterpState a -> DaemonIO (InterpState a)
|
|||||||
load filepath = execMuted (T.pack $ ":load " <> filepath)
|
load filepath = execMuted (T.pack $ ":load " <> filepath)
|
||||||
|
|
||||||
{- | Execute an arbitrary command, as if it was directly written in GHCi.
|
{- | Execute an arbitrary command, as if it was directly written in GHCi.
|
||||||
It is unlikely you want to call this directly, and instead want to call
|
It is unlikely you want to call this directly, and instead want to call
|
||||||
one of the wrapped functions or 'execMuted' or 'execCleaned'.
|
one of the wrapped functions or 'execMuted' or 'execCleaned'.
|
||||||
-}
|
-}
|
||||||
exec :: (Monoid a) => T.Text -> InterpState a -> ExceptT DaemonError IO (InterpState a, [T.Text])
|
exec :: (Monoid a) => T.Text -> InterpState a -> ExceptT DaemonError IO (InterpState a, [T.Text])
|
||||||
exec cmd state@InterpState{_ghci} = do
|
exec cmd state@InterpState{_ghci} = do
|
||||||
@ -476,7 +476,7 @@ logDebug msg state =
|
|||||||
where
|
where
|
||||||
output = logOutput state
|
output = logOutput state
|
||||||
|
|
||||||
--Log a message at the Error level.
|
-- Log a message at the Error level.
|
||||||
logError :: (MonadIO m) => T.Text -> InterpState a -> m ()
|
logError :: (MonadIO m) => T.Text -> InterpState a -> m ()
|
||||||
logError msg state =
|
logError msg state =
|
||||||
liftIO $ do
|
liftIO $ do
|
||||||
@ -514,7 +514,7 @@ data DaemonError
|
|||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
{- | An IO operation that can fail into a DaemonError.
|
{- | An IO operation that can fail into a DaemonError.
|
||||||
Execute them to IO through 'run'.
|
Execute them to IO through 'run'.
|
||||||
-}
|
-}
|
||||||
type DaemonIO r = ExceptT DaemonError IO r
|
type DaemonIO r = ExceptT DaemonError IO r
|
||||||
|
|
@ -4,4 +4,4 @@ module Ghcitui.Ghcid.LogConfig where
|
|||||||
newtype LogLevel = LogLevel Int deriving (Eq, Ord, Show)
|
newtype LogLevel = LogLevel Int deriving (Eq, Ord, Show)
|
||||||
|
|
||||||
-- | Determines where the daemon logs are written.
|
-- | Determines where the daemon logs are written.
|
||||||
data LogOutput = LogOutputStdOut | LogOutputStdErr | LogOutputFile FilePath deriving (Show)
|
data LogOutput = LogOutputStdOut | LogOutputStdErr | LogOutputFile FilePath deriving (Show)
|
@ -1,9 +1,11 @@
|
|||||||
module Ghcitui.Ghcid.StartupConfig (StartupConfig(..)) where
|
module Ghcitui.Ghcid.StartupConfig (StartupConfig (..)) where
|
||||||
|
|
||||||
import Ghcitui.Ghcid.LogConfig (LogLevel, LogOutput)
|
import Ghcitui.Ghcid.LogConfig (LogLevel, LogOutput)
|
||||||
|
|
||||||
-- | Configuration passed during Daemon 'startup'
|
-- | Configuration passed during Daemon 'startup'
|
||||||
data StartupConfig = StartupConfig
|
data StartupConfig = StartupConfig
|
||||||
{ logLevel :: !LogLevel
|
{ logLevel :: !LogLevel
|
||||||
|
-- ^ How much do we want to log?
|
||||||
, logOutput :: !LogOutput
|
, logOutput :: !LogOutput
|
||||||
}
|
-- ^ Where do we log?
|
||||||
|
}
|
@ -1,9 +1,28 @@
|
|||||||
module Util (getNumDigits, formatDigits, clamp, showT) where
|
module Ghcitui.Util (showT, splitBy, linesToText, clamp, getNumDigits, formatDigits) where
|
||||||
|
|
||||||
import Data.Text (Text, pack)
|
import Data.Text (Text, breakOn, drop, length, pack)
|
||||||
|
import Prelude hiding (drop, length)
|
||||||
|
|
||||||
|
-- | Split text based on a delimiter.
|
||||||
|
splitBy
|
||||||
|
:: Text
|
||||||
|
-- ^ Delimeter.
|
||||||
|
-> Text
|
||||||
|
-- ^ Text to split on.
|
||||||
|
-> [Text]
|
||||||
|
splitBy "" source = [source]
|
||||||
|
splitBy delim source =
|
||||||
|
case breakOn delim source of
|
||||||
|
(l, "") -> [l]
|
||||||
|
(l, r) -> l : splitBy delim (drop (length delim) r)
|
||||||
|
|
||||||
|
-- | Convert Strings to Text.
|
||||||
|
linesToText :: [String] -> Text
|
||||||
|
linesToText = pack . Prelude.unlines
|
||||||
|
|
||||||
|
-- | 'show' but to Text.
|
||||||
showT :: (Show a) => a -> Text
|
showT :: (Show a) => a -> Text
|
||||||
showT = Data.Text.pack . show
|
showT = pack . show
|
||||||
|
|
||||||
-- Return the number of digits in a given integral
|
-- Return the number of digits in a given integral
|
||||||
getNumDigits :: (Integral a) => a -> Int
|
getNumDigits :: (Integral a) => a -> Int
|
Loading…
Reference in New Issue
Block a user