{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_HADDOCK show-extensions #-}
module Yi.Mode.Interactive where
import Control.Concurrent (threadDelay)
import Lens.Micro.Platform (use, (%~), (.=))
import Data.Monoid ((<>))
import qualified Data.Text as T (Text)
import Yi.Buffer
import Yi.Core (sendToProcess, startSubprocess, withSyntax)
import Yi.Editor
import Yi.History (historyFinishGen, historyMoveGen, historyStartGen)
import Yi.Keymap (YiM, topKeymapA)
import Yi.Keymap.Keys (Key (KEnter, KHome), char, choice, meta, spec, (<||), (?>>!))
import Yi.Lexer.Alex (Tok)
import Yi.Lexer.Compilation (Token)
import qualified Yi.Mode.Compilation as Compilation (mode)
import Yi.Mode.Common (lookupMode)
import Yi.Monad (gets)
import qualified Yi.Rope as R (YiString, fromText, toString, toText)
import qualified Yi.Syntax.OnlineTree as OnlineTree (Tree)
import Yi.Utils (io)
mode :: Mode (OnlineTree.Tree (Tok Token))
mode :: Mode (Tree (Tok Token))
mode = Mode (Tree (Tok Token))
Compilation.mode
{ modeApplies :: FilePath -> YiString -> Bool
modeApplies = FilePath -> YiString -> Bool
forall a b. a -> b -> Bool
modeNeverApplies,
modeName :: Text
modeName = Text
"interactive",
modeKeymap :: KeymapSet -> KeymapSet
modeKeymap = (Keymap -> Identity Keymap) -> KeymapSet -> Identity KeymapSet
Lens' KeymapSet Keymap
topKeymapA ((Keymap -> Identity Keymap) -> KeymapSet -> Identity KeymapSet)
-> (Keymap -> Keymap) -> KeymapSet -> KeymapSet
forall s t a b. ASetter s t a b -> (a -> b) -> s -> t
%~ Keymap -> Keymap -> Keymap
forall (f :: * -> *) w e a.
MonadInteract f w e =>
f a -> f a -> f a
(<||)
([Keymap] -> Keymap
forall (m :: * -> *) w e a.
(MonadInteract m w e, MonadFail m) =>
[m a] -> m a
choice
[Key -> Event
spec Key
KHome Event -> BufferM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! BufferM ()
moveToSol,
Key -> Event
spec Key
KEnter Event -> YiM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! do
Bool
eof <- BufferM Bool -> YiM Bool
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer BufferM Bool
atLastLine
if Bool
eof
then YiM ()
feedCommand
else (forall syntax. Mode syntax -> syntax -> Action) -> YiM ()
forall x a.
(Show x, YiAction a x) =>
(forall syntax. Mode syntax -> syntax -> a) -> YiM ()
withSyntax forall syntax. Mode syntax -> syntax -> Action
modeFollow,
Event -> Event
meta (Char -> Event
char Char
'p') Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! Int -> EditorM ()
interactHistoryMove Int
1,
Event -> Event
meta (Char -> Event
char Char
'n') Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! Int -> EditorM ()
interactHistoryMove (-Int
1)
])
}
interactId :: T.Text
interactId :: Text
interactId = Text
"Interact"
interactHistoryMove :: Int -> EditorM ()
interactHistoryMove :: Int -> EditorM ()
interactHistoryMove Int
delta =
Text -> Int -> EditorM Text -> EditorM Text
historyMoveGen Text
interactId Int
delta (YiString -> Text
R.toText (YiString -> Text) -> EditorM YiString -> EditorM Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BufferM YiString -> EditorM YiString
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer BufferM YiString
getInput) EditorM Text -> (Text -> EditorM ()) -> EditorM ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Text -> EditorM ()
inp
where
inp :: Text -> EditorM ()
inp = BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ())
-> (Text -> BufferM ()) -> Text -> EditorM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. YiString -> BufferM ()
setInput (YiString -> BufferM ())
-> (Text -> YiString) -> Text -> BufferM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> YiString
R.fromText
interactHistoryFinish :: EditorM ()
interactHistoryFinish :: EditorM ()
interactHistoryFinish =
Text -> EditorM Text -> EditorM ()
historyFinishGen Text
interactId (YiString -> Text
R.toText (YiString -> Text) -> EditorM YiString -> EditorM Text
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BufferM YiString -> EditorM YiString
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer BufferM YiString
getInput)
interactHistoryStart :: EditorM ()
interactHistoryStart :: EditorM ()
interactHistoryStart = Text -> EditorM ()
historyStartGen Text
interactId
getInputRegion :: BufferM Region
getInputRegion :: BufferM Region
getInputRegion = do Mark
mo <- Maybe FilePath -> BufferM Mark
getMarkB (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
"StdOUT")
Point
p <- BufferM () -> BufferM Point
forall a. BufferM a -> BufferM Point
pointAt BufferM ()
botB
Point
q <- Getting Point FBuffer Point -> BufferM Point
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting Point FBuffer Point -> BufferM Point)
-> Getting Point FBuffer Point -> BufferM Point
forall a b. (a -> b) -> a -> b
$ Mark -> Lens' FBuffer Point
markPointA Mark
mo
Region -> BufferM Region
forall (m :: * -> *) a. Monad m => a -> m a
return (Region -> BufferM Region) -> Region -> BufferM Region
forall a b. (a -> b) -> a -> b
$ Point -> Point -> Region
mkRegion Point
p Point
q
getInput :: BufferM R.YiString
getInput :: BufferM YiString
getInput = Region -> BufferM YiString
readRegionB (Region -> BufferM YiString) -> BufferM Region -> BufferM YiString
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< BufferM Region
getInputRegion
setInput :: R.YiString -> BufferM ()
setInput :: YiString -> BufferM ()
setInput YiString
val = (Region -> YiString -> BufferM ())
-> YiString -> Region -> BufferM ()
forall a b c. (a -> b -> c) -> b -> a -> c
flip Region -> YiString -> BufferM ()
replaceRegionB YiString
val (Region -> BufferM ()) -> BufferM Region -> BufferM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< BufferM Region
getInputRegion
spawnProcess :: String -> [String] -> YiM BufferRef
spawnProcess :: FilePath -> [FilePath] -> YiM BufferRef
spawnProcess = Mode (Tree (Tok Token)) -> FilePath -> [FilePath] -> YiM BufferRef
forall syntax.
Mode syntax -> FilePath -> [FilePath] -> YiM BufferRef
spawnProcessMode Mode (Tree (Tok Token))
mode
spawnProcessMode :: Mode syntax -> FilePath -> [String] -> YiM BufferRef
spawnProcessMode :: Mode syntax -> FilePath -> [FilePath] -> YiM BufferRef
spawnProcessMode Mode syntax
interMode FilePath
cmd [FilePath]
args = do
BufferRef
b <- FilePath
-> [FilePath]
-> (Either SomeException ExitCode -> YiM ())
-> YiM BufferRef
forall x.
FilePath
-> [FilePath]
-> (Either SomeException ExitCode -> YiM x)
-> YiM BufferRef
startSubprocess FilePath
cmd [FilePath]
args (YiM () -> Either SomeException ExitCode -> YiM ()
forall a b. a -> b -> a
const (YiM () -> Either SomeException ExitCode -> YiM ())
-> YiM () -> Either SomeException ExitCode -> YiM ()
forall a b. (a -> b) -> a -> b
$ () -> YiM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ())
EditorM () -> YiM ()
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor EditorM ()
interactHistoryStart
AnyMode
mode' <- AnyMode -> YiM AnyMode
lookupMode (AnyMode -> YiM AnyMode) -> AnyMode -> YiM AnyMode
forall a b. (a -> b) -> a -> b
$ Mode syntax -> AnyMode
forall syntax. Mode syntax -> AnyMode
AnyMode Mode syntax
interMode
BufferM () -> YiM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> YiM ()) -> BufferM () -> YiM ()
forall a b. (a -> b) -> a -> b
$ do
Mark
m1 <- Maybe FilePath -> BufferM Mark
getMarkB (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
"StdERR")
Mark
m2 <- Maybe FilePath -> BufferM Mark
getMarkB (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
"StdOUT")
Mark -> (MarkValue -> MarkValue) -> BufferM ()
modifyMarkB Mark
m1 (\MarkValue
v -> MarkValue
v {markGravity :: Direction
markGravity = Direction
Backward})
Mark -> (MarkValue -> MarkValue) -> BufferM ()
modifyMarkB Mark
m2 (\MarkValue
v -> MarkValue
v {markGravity :: Direction
markGravity = Direction
Backward})
AnyMode -> BufferM ()
setAnyMode AnyMode
mode'
BufferRef -> YiM BufferRef
forall (m :: * -> *) a. Monad m => a -> m a
return BufferRef
b
feedCommand :: YiM ()
feedCommand :: YiM ()
feedCommand = do
BufferRef
b <- (Editor -> BufferRef) -> YiM BufferRef
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets Editor -> BufferRef
currentBuffer
EditorM () -> YiM ()
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor EditorM ()
interactHistoryFinish
FilePath
cmd <- BufferM FilePath -> YiM FilePath
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM FilePath -> YiM FilePath)
-> BufferM FilePath -> YiM FilePath
forall a b. (a -> b) -> a -> b
$ do
BufferM ()
botB
BufferM ()
newlineB
Mark
me <- Maybe FilePath -> BufferM Mark
getMarkB (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
"StdERR")
Mark
mo <- Maybe FilePath -> BufferM Mark
getMarkB (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
"StdOUT")
Point
p <- BufferM Point
pointB
Point
q <- Getting Point FBuffer Point -> BufferM Point
forall s (m :: * -> *) a. MonadState s m => Getting a s a -> m a
use (Getting Point FBuffer Point -> BufferM Point)
-> Getting Point FBuffer Point -> BufferM Point
forall a b. (a -> b) -> a -> b
$ Mark -> Lens' FBuffer Point
markPointA Mark
mo
YiString
cmd <- Region -> BufferM YiString
readRegionB (Region -> BufferM YiString) -> Region -> BufferM YiString
forall a b. (a -> b) -> a -> b
$ Point -> Point -> Region
mkRegion Point
p Point
q
Mark -> Lens' FBuffer Point
markPointA Mark
me ((Point -> Identity Point) -> FBuffer -> Identity FBuffer)
-> Point -> BufferM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Point
p
Mark -> Lens' FBuffer Point
markPointA Mark
mo ((Point -> Identity Point) -> FBuffer -> Identity FBuffer)
-> Point -> BufferM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Point
p
FilePath -> BufferM FilePath
forall (m :: * -> *) a. Monad m => a -> m a
return (FilePath -> BufferM FilePath) -> FilePath -> BufferM FilePath
forall a b. (a -> b) -> a -> b
$ YiString -> FilePath
R.toString YiString
cmd
EditorM () -> YiM ()
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor EditorM ()
interactHistoryStart
BufferRef -> FilePath -> YiM ()
sendToProcess BufferRef
b FilePath
cmd
queryReply :: BufferRef -> String -> YiM R.YiString
queryReply :: BufferRef -> FilePath -> YiM YiString
queryReply BufferRef
buf FilePath
cmd = do
Point
start <- BufferRef -> BufferM Point -> YiM Point
forall (m :: * -> *) a.
MonadEditor m =>
BufferRef -> BufferM a -> m a
withGivenBuffer BufferRef
buf (BufferM ()
botB BufferM () -> BufferM Point -> BufferM Point
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> BufferM Point
pointB)
BufferRef -> FilePath -> YiM ()
sendToProcess BufferRef
buf (FilePath
cmd FilePath -> FilePath -> FilePath
forall a. Semigroup a => a -> a -> a
<> FilePath
"\n")
IO () -> YiM ()
forall (m :: * -> *) a. MonadBase IO m => IO a -> m a
io (IO () -> YiM ()) -> IO () -> YiM ()
forall a b. (a -> b) -> a -> b
$ Int -> IO ()
threadDelay Int
50000
BufferRef -> BufferM YiString -> YiM YiString
forall (m :: * -> *) a.
MonadEditor m =>
BufferRef -> BufferM a -> m a
withGivenBuffer BufferRef
buf (BufferM YiString -> YiM YiString)
-> BufferM YiString -> YiM YiString
forall a b. (a -> b) -> a -> b
$ do
BufferM ()
botB
BufferM ()
moveToSol
BufferM ()
leftB
Point
end <- BufferM Point
pointB
YiString
result <- Region -> BufferM YiString
readRegionB (Point -> Point -> Region
mkRegion Point
start Point
end)
BufferM ()
botB
YiString -> BufferM YiString
forall (m :: * -> *) a. Monad m => a -> m a
return YiString
result