{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_HADDOCK show-extensions #-}
module Yi.Keymap.Emacs.Utils
( UnivArgument
, argToInt
, askQuitEditor
, askSaveEditor
, modifiedQuitEditor
, withMinibuffer
, queryReplaceE
, isearchKeymap
, cabalConfigureE
, cabalBuildE
, reloadProjectE
, executeExtendedCommandE
, evalRegionE
, readUniversalArg
, scrollDownE
, scrollUpE
, switchBufferE
, killBufferE
, insertNextC
, findFile
, findFileReadOnly
, findFileNewTab
, promptFile
, promptTag
, justOneSep
, joinLinesE
, countWordsRegion
)
where
import Control.Applicative (Alternative ((<|>), many, some), optional)
import Lens.Micro.Platform (use, (.=))
import Control.Monad (filterM, replicateM_, void)
import Control.Monad.Base ()
import Data.List ((\\))
import Data.Maybe (fromMaybe)
import Data.Monoid ((<>))
import qualified Data.Text as T (Text, concat, null, pack, singleton, snoc, unpack, unwords)
import System.FilePath (takeDirectory, takeFileName, (</>))
import System.FriendlyPath ()
import Yi.Buffer
import Yi.Command (cabalBuildE, cabalConfigureE, reloadProjectE)
import Yi.Core (quitEditor)
import Yi.Editor
import Yi.Eval (execEditorAction, getAllNamesInScope)
import Yi.File (deservesSave, editFile, fwriteBufferE, openingNewFile)
import Yi.Keymap (Keymap, KeymapM, YiM, write)
import Yi.Keymap.Keys
import Yi.MiniBuffer
import Yi.Misc (promptFile)
import Yi.Monad (gets)
import Yi.Rectangle (getRectangle)
import Yi.Regex (makeSearchOptsM)
import qualified Yi.Rope as R (countNewLines, fromText, length, replicateChar, toText, words)
import Yi.Search
import Yi.String (showT)
import Yi.Tag
import Yi.Utils (io)
type UnivArgument = Maybe Int
askQuitEditor :: YiM ()
askQuitEditor :: YiM ()
askQuitEditor = Bool -> [FBuffer] -> YiM ()
askIndividualSave Bool
True ([FBuffer] -> YiM ()) -> YiM [FBuffer] -> YiM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< YiM [FBuffer]
getModifiedBuffers
askSaveEditor :: YiM ()
askSaveEditor :: YiM ()
askSaveEditor = Bool -> [FBuffer] -> YiM ()
askIndividualSave Bool
False ([FBuffer] -> YiM ()) -> YiM [FBuffer] -> YiM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< YiM [FBuffer]
getModifiedBuffers
getModifiedBuffers :: YiM [FBuffer]
getModifiedBuffers :: YiM [FBuffer]
getModifiedBuffers = (FBuffer -> YiM Bool) -> [FBuffer] -> YiM [FBuffer]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM FBuffer -> YiM Bool
deservesSave ([FBuffer] -> YiM [FBuffer]) -> YiM [FBuffer] -> YiM [FBuffer]
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< (Editor -> [FBuffer]) -> YiM [FBuffer]
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets Editor -> [FBuffer]
bufferSet
askIndividualSave :: Bool -> [FBuffer] -> YiM ()
askIndividualSave :: Bool -> [FBuffer] -> YiM ()
askIndividualSave Bool
True [] = YiM ()
modifiedQuitEditor
askIndividualSave Bool
False [] = () -> YiM ()
forall a. a -> YiM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
askIndividualSave Bool
hasQuit allBuffers :: [FBuffer]
allBuffers@(FBuffer
firstBuffer : [FBuffer]
others) =
YiM BufferRef -> YiM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (EditorM BufferRef -> YiM BufferRef
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (Text -> KeymapEndo -> EditorM BufferRef
spawnMinibufferE Text
saveMessage (Keymap -> KeymapEndo
forall a b. a -> b -> a
const Keymap
askKeymap)))
where
saveMessage :: Text
saveMessage = [Text] -> Text
T.concat [ Text
"do you want to save the buffer: "
, Text
bufferName
, Text
"? (y/n/", if Bool
hasQuit then Text
"q/" else Text
"", Text
"c/!)"
]
bufferName :: Text
bufferName = FBuffer -> Text
identString FBuffer
firstBuffer
askKeymap :: Keymap
askKeymap = [Keymap] -> Keymap
forall (m :: * -> *) w e a.
(MonadInteract m w e, MonadFail m) =>
[m a] -> m a
choice ([ Char -> Event
char Char
'n' Event -> YiM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! YiM ()
noAction
, Char -> Event
char Char
'y' Event -> YiM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! YiM ()
yesAction
, Char -> Event
char Char
'!' Event -> YiM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! YiM ()
allAction
, [Event] -> I Event Action Event
forall event (m :: * -> *) w.
(Ord event, MonadInteract m w event, MonadFail m) =>
[event] -> m event
oneOf [Char -> Event
char Char
'c', Event -> Event
ctrl (Event -> Event) -> Event -> Event
forall a b. (a -> b) -> a -> b
$ Char -> Event
char Char
'g']
I Event Action Event -> EditorM () -> Keymap
forall (m :: * -> *) a x b.
(MonadInteract m Action Event, YiAction a x, Show x) =>
m b -> a -> m ()
>>! EditorM ()
closeBufferAndWindowE
] [Keymap] -> [Keymap] -> [Keymap]
forall a. [a] -> [a] -> [a]
++ [Char -> Event
char Char
'q' Event -> YiM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! YiM ()
quitEditor | Bool
hasQuit])
yesAction :: YiM ()
yesAction = do YiM Bool -> YiM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (YiM Bool -> YiM ()) -> YiM Bool -> YiM ()
forall a b. (a -> b) -> a -> b
$ BufferRef -> YiM Bool
fwriteBufferE (FBuffer -> BufferRef
bkey FBuffer
firstBuffer)
EditorM () -> YiM ()
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor EditorM ()
closeBufferAndWindowE
YiM ()
continue
noAction :: YiM ()
noAction = do EditorM () -> YiM ()
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor EditorM ()
closeBufferAndWindowE
YiM ()
continue
allAction :: YiM ()
allAction = do (BufferRef -> YiM Bool) -> [BufferRef] -> YiM ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ BufferRef -> YiM Bool
fwriteBufferE ([BufferRef] -> YiM ()) -> [BufferRef] -> YiM ()
forall a b. (a -> b) -> a -> b
$ (FBuffer -> BufferRef) -> [FBuffer] -> [BufferRef]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap FBuffer -> BufferRef
bkey [FBuffer]
allBuffers
EditorM () -> YiM ()
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor EditorM ()
closeBufferAndWindowE
Bool -> [FBuffer] -> YiM ()
askIndividualSave Bool
hasQuit []
continue :: YiM ()
continue = Bool -> [FBuffer] -> YiM ()
askIndividualSave Bool
hasQuit [FBuffer]
others
modifiedQuitEditor :: YiM ()
modifiedQuitEditor :: YiM ()
modifiedQuitEditor =
do modifiedBuffers <- YiM [FBuffer]
getModifiedBuffers
if null modifiedBuffers
then quitEditor
else withEditor $ void (spawnMinibufferE modifiedMessage (const askKeymap))
where
modifiedMessage :: Text
modifiedMessage = Text
"Modified buffers exist really quit? (y/n)"
askKeymap :: Keymap
askKeymap = [Keymap] -> Keymap
forall (m :: * -> *) w e a.
(MonadInteract m w e, MonadFail m) =>
[m a] -> m a
choice [ Char -> Event
char Char
'n' Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! EditorM ()
noAction
, Char -> Event
char Char
'y' Event -> YiM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! YiM ()
quitEditor
]
noAction :: EditorM ()
noAction = EditorM ()
closeBufferAndWindowE
selfSearchKeymap :: Keymap
selfSearchKeymap :: Keymap
selfSearchKeymap = do
Event (KASCII c) [] <- I Event Action Event
forall event (m :: * -> *) w.
(Ord event, MonadInteract m w event) =>
m event
anyEvent
write . isearchAddE $ T.singleton c
searchKeymap :: Keymap
searchKeymap :: Keymap
searchKeymap = Keymap
selfSearchKeymap Keymap -> KeymapEndo
forall a. I Event Action a -> I Event Action a -> I Event Action a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> [Keymap] -> Keymap
forall (m :: * -> *) w e a.
(MonadInteract m w e, MonadFail m) =>
[m a] -> m a
choice
[
Event -> Event
ctrl (Char -> Event
char Char
'r') Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! EditorM ()
isearchPrevE
, Event -> Event
ctrl (Char -> Event
char Char
's') Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! EditorM ()
isearchNextE
, Event -> Event
ctrl (Char -> Event
char Char
'w') Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! EditorM ()
isearchWordE
, 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 ()
isearchHistory 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 ()
isearchHistory (-Int
1)
, Key -> Event
spec Key
KBS Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! EditorM ()
isearchDelE
]
isearchKeymap :: Direction -> Keymap
isearchKeymap :: Direction -> Keymap
isearchKeymap Direction
dir =
do EditorM () -> Keymap
forall (m :: * -> *) ev a x.
(MonadInteract m Action ev, YiAction a x, Show x) =>
a -> m ()
write (EditorM () -> Keymap) -> EditorM () -> Keymap
forall a b. (a -> b) -> a -> b
$ Direction -> EditorM ()
isearchInitE Direction
dir
I Event Action [()] -> Keymap
forall (f :: * -> *) a. Functor f => f a -> f ()
void (I Event Action [()] -> Keymap) -> I Event Action [()] -> Keymap
forall a b. (a -> b) -> a -> b
$ Keymap -> I Event Action [()]
forall a. I Event Action a -> I Event Action [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
many Keymap
searchKeymap
[Keymap] -> Keymap
forall (m :: * -> *) w e a.
(MonadInteract m w e, MonadFail m) =>
[m a] -> m a
choice [ Event -> Event
ctrl (Char -> Event
char Char
'g') Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! EditorM ()
isearchCancelE
, [Event] -> I Event Action Event
forall event (m :: * -> *) w.
(Ord event, MonadInteract m w event, MonadFail m) =>
[event] -> m event
oneOf [Event -> Event
ctrl (Char -> Event
char Char
'm'), Key -> Event
spec Key
KEnter]
I Event Action Event -> EditorM () -> Keymap
forall (m :: * -> *) a x b.
(MonadInteract m Action Event, YiAction a x, Show x) =>
m b -> a -> m ()
>>! EditorM () -> EditorM ()
forall a. EditorM a -> EditorM ()
isearchFinishWithE EditorM ()
resetRegexE
]
Keymap -> KeymapEndo
forall (f :: * -> *) w e a.
MonadInteract f w e =>
f a -> f a -> f a
<|| EditorM () -> Keymap
forall (m :: * -> *) ev a x.
(MonadInteract m Action ev, YiAction a x, Show x) =>
a -> m ()
write EditorM ()
isearchFinishE
queryReplaceE :: YiM ()
queryReplaceE :: YiM ()
queryReplaceE = Text -> (Text -> YiM ()) -> YiM ()
withMinibufferFree Text
"Replace:" ((Text -> YiM ()) -> YiM ()) -> (Text -> YiM ()) -> YiM ()
forall a b. (a -> b) -> a -> b
$ \Text
replaceWhat ->
Text -> (Text -> YiM ()) -> YiM ()
withMinibufferFree Text
"With:" ((Text -> YiM ()) -> YiM ()) -> (Text -> YiM ()) -> YiM ()
forall a b. (a -> b) -> a -> b
$ \Text
replaceWith -> do
b <- (Editor -> BufferRef) -> YiM BufferRef
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets Editor -> BufferRef
currentBuffer
win <- use currentWindowA
let repStr = Text -> YiString
R.fromText Text
replaceWith
replaceKm =
[Keymap] -> Keymap
forall (m :: * -> *) w e a.
(MonadInteract m w e, MonadFail m) =>
[m a] -> m a
choice [ Char -> Event
char Char
'n' Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! Window -> BufferRef -> SearchExp -> EditorM ()
qrNext Window
win BufferRef
b SearchExp
re
, Char -> Event
char Char
'!' Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! Window -> BufferRef -> SearchExp -> YiString -> EditorM ()
qrReplaceAll Window
win BufferRef
b SearchExp
re YiString
repStr
, [Event] -> I Event Action Event
forall event (m :: * -> *) w.
(Ord event, MonadInteract m w event, MonadFail m) =>
[event] -> m event
oneOf [Char -> Event
char Char
'y', Char -> Event
char Char
' '] I Event Action Event -> EditorM () -> Keymap
forall (m :: * -> *) a x b.
(MonadInteract m Action Event, YiAction a x, Show x) =>
m b -> a -> m ()
>>! Window -> BufferRef -> SearchExp -> YiString -> EditorM ()
qrReplaceOne Window
win BufferRef
b SearchExp
re YiString
repStr
, [Event] -> I Event Action Event
forall event (m :: * -> *) w.
(Ord event, MonadInteract m w event, MonadFail m) =>
[event] -> m event
oneOf [Char -> Event
char Char
'q', Event -> Event
ctrl (Char -> Event
char Char
'g')] I Event Action Event -> EditorM () -> Keymap
forall (m :: * -> *) a x b.
(MonadInteract m Action Event, YiAction a x, Show x) =>
m b -> a -> m ()
>>! EditorM ()
qrFinish
]
Right re = makeSearchOptsM [] (T.unpack replaceWhat)
question = [Text] -> Text
T.unwords [ Text
"Replacing", Text
replaceWhat
, Text
"with", Text
replaceWith, Text
" (y,n,q,!):"
]
withEditor $ do
setRegexE re
void $ spawnMinibufferE question (const replaceKm)
qrNext win b re
executeExtendedCommandE :: YiM ()
executeExtendedCommandE :: YiM ()
executeExtendedCommandE = Text -> (Text -> YiM [Text]) -> (Text -> YiM ()) -> YiM ()
withMinibuffer Text
"M-x" Text -> YiM [Text]
forall {b}. b -> YiM [Text]
scope Text -> YiM ()
act
where
act :: Text -> YiM ()
act = String -> YiM ()
execEditorAction (String -> YiM ()) -> (Text -> String) -> Text -> YiM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack
scope :: b -> YiM [Text]
scope = YiM [Text] -> b -> YiM [Text]
forall a b. a -> b -> a
const (YiM [Text] -> b -> YiM [Text]) -> YiM [Text] -> b -> YiM [Text]
forall a b. (a -> b) -> a -> b
$ (String -> Text) -> [String] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map String -> Text
T.pack ([String] -> [Text]) -> YiM [String] -> YiM [Text]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> YiM [String]
getAllNamesInScope
evalRegionE :: YiM ()
evalRegionE :: YiM ()
evalRegionE = do
YiM YiString -> YiM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (YiM YiString -> YiM ()) -> YiM YiString -> YiM ()
forall a b. (a -> b) -> a -> b
$ BufferM YiString -> YiM YiString
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM Region
getSelectRegionB BufferM Region -> (Region -> BufferM YiString) -> BufferM YiString
forall a b. BufferM a -> (a -> BufferM b) -> BufferM b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Region -> BufferM YiString
readRegionB)
() -> YiM ()
forall a. a -> YiM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
insertNextC :: UnivArgument -> KeymapM ()
insertNextC :: UnivArgument -> Keymap
insertNextC UnivArgument
a = do c <- I Event Action Event
forall event (m :: * -> *) w.
(Ord event, MonadInteract m w event) =>
m event
anyEvent
write $ replicateM_ (argToInt a) $ insertB (eventToChar c)
argToInt :: UnivArgument -> Int
argToInt :: UnivArgument -> Int
argToInt = Int -> UnivArgument -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
1
digit :: (Event -> Event) -> KeymapM Char
digit :: (Event -> Event) -> KeymapM Char
digit Event -> Event
f = (Event -> Event) -> Char -> Char -> KeymapM Char
forall (m :: * -> *) w.
(MonadFail m, MonadInteract m w Event) =>
(Event -> Event) -> Char -> Char -> m Char
charOf Event -> Event
f Char
'0' Char
'9'
tt :: KeymapM Char
tt :: KeymapM Char
tt = do
Event (KASCII c) _ <- (I Event Action Event
-> I Event Action Event -> I Event Action Event)
-> [I Event Action Event] -> I Event Action Event
forall a. (a -> a -> a) -> [a] -> a
forall (t :: * -> *) a. Foldable t => (a -> a -> a) -> t a -> a
foldr1 I Event Action Event
-> I Event Action Event -> I Event Action Event
forall a. I Event Action a -> I Event Action a -> I Event Action a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
(<|>) ([I Event Action Event] -> I Event Action Event)
-> [I Event Action Event] -> I Event Action Event
forall a b. (a -> b) -> a -> b
$ (Char -> I Event Action Event) -> String -> [I Event Action Event]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Event -> I Event Action Event
forall event (m :: * -> *) w.
(Ord event, MonadInteract m w event) =>
event -> m event
event (Event -> I Event Action Event)
-> (Char -> Event) -> Char -> I Event Action Event
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Char -> Event
metaCh ) [Char
'0'..Char
'9']
return c
readUniversalArg :: KeymapM (Maybe Int)
readUniversalArg :: KeymapM UnivArgument
readUniversalArg = I Event Action Int -> KeymapM UnivArgument
forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional ((Char -> Event
ctrlCh Char
'u' Event -> I Event Action Int -> I Event Action Int
forall (m :: * -> *) action a.
MonadInteract m action Event =>
Event -> m a -> m a
?>> (String -> Int
forall a. Read a => String -> a
read (String -> Int) -> I Event Action String -> I Event Action Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> KeymapM Char -> I Event Action String
forall a. I Event Action a -> I Event Action [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some ((Event -> Event) -> KeymapM Char
digit Event -> Event
forall a. a -> a
id) I Event Action Int -> I Event Action Int -> I Event Action Int
forall a. I Event Action a -> I Event Action a -> I Event Action a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> Int -> I Event Action Int
forall a. a -> I Event Action a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Int
4)) I Event Action Int -> I Event Action Int -> I Event Action Int
forall a. I Event Action a -> I Event Action a -> I Event Action a
forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> (String -> Int
forall a. Read a => String -> a
read (String -> Int) -> I Event Action String -> I Event Action Int
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> KeymapM Char -> I Event Action String
forall a. I Event Action a -> I Event Action [a]
forall (f :: * -> *) a. Alternative f => f a -> f [a]
some KeymapM Char
tt))
findFileAndDo :: T.Text
-> BufferM a
-> YiM ()
findFileAndDo :: forall a. Text -> BufferM a -> YiM ()
findFileAndDo Text
prompt BufferM a
act = Text -> (Text -> YiM ()) -> YiM ()
promptFile Text
prompt ((Text -> YiM ()) -> YiM ()) -> (Text -> YiM ()) -> YiM ()
forall a b. (a -> b) -> a -> b
$ \Text
filename -> do
Text -> YiM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg (Text -> YiM ()) -> Text -> YiM ()
forall a b. (a -> b) -> a -> b
$ Text
"loading " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
filename
String -> BufferM a -> YiM ()
forall a. String -> BufferM a -> YiM ()
openingNewFile (Text -> String
T.unpack Text
filename) BufferM a
act
findFile :: YiM ()
findFile :: YiM ()
findFile = Text -> BufferM () -> YiM ()
forall a. Text -> BufferM a -> YiM ()
findFileAndDo Text
"find file:" (BufferM () -> YiM ()) -> BufferM () -> YiM ()
forall a b. (a -> b) -> a -> b
$ () -> BufferM ()
forall a. a -> BufferM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
findFileReadOnly :: YiM ()
findFileReadOnly :: YiM ()
findFileReadOnly = Text -> BufferM () -> YiM ()
forall a. Text -> BufferM a -> YiM ()
findFileAndDo Text
"find file (read only):" (BufferM () -> YiM ()) -> BufferM () -> YiM ()
forall a b. (a -> b) -> a -> b
$ (Bool -> Identity Bool) -> FBuffer -> Identity FBuffer
forall c. HasAttributes c => Lens' c Bool
Lens' FBuffer Bool
readOnlyA ((Bool -> Identity Bool) -> FBuffer -> Identity FBuffer)
-> Bool -> BufferM ()
forall s (m :: * -> *) a b.
MonadState s m =>
ASetter s s a b -> b -> m ()
.= Bool
True
findFileNewTab :: YiM ()
findFileNewTab :: YiM ()
findFileNewTab = Text -> (Text -> YiM ()) -> YiM ()
promptFile Text
"find file (new tab): " ((Text -> YiM ()) -> YiM ()) -> (Text -> YiM ()) -> YiM ()
forall a b. (a -> b) -> a -> b
$ \Text
filename -> do
EditorM () -> YiM ()
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor EditorM ()
newTabE
Text -> YiM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg (Text -> YiM ()) -> Text -> YiM ()
forall a b. (a -> b) -> a -> b
$ Text
"loading " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
filename
YiM (Either Text BufferRef) -> YiM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (YiM (Either Text BufferRef) -> YiM ())
-> (String -> YiM (Either Text BufferRef)) -> String -> YiM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> YiM (Either Text BufferRef)
editFile (String -> YiM ()) -> String -> YiM ()
forall a b. (a -> b) -> a -> b
$ Text -> String
T.unpack Text
filename
scrollDownE :: UnivArgument -> BufferM ()
scrollDownE :: UnivArgument -> BufferM ()
scrollDownE UnivArgument
a = case UnivArgument
a of
UnivArgument
Nothing -> BufferM ()
downScreenB
Just Int
n -> Int -> BufferM ()
scrollB Int
n
scrollUpE :: UnivArgument -> BufferM ()
scrollUpE :: UnivArgument -> BufferM ()
scrollUpE UnivArgument
a = case UnivArgument
a of
UnivArgument
Nothing -> BufferM ()
upScreenB
Just Int
n -> Int -> BufferM ()
scrollB (Int -> Int
forall a. Num a => a -> a
negate Int
n)
switchBufferE :: YiM ()
switchBufferE :: YiM ()
switchBufferE = Text
-> (BufferRef -> YiM ())
-> ([BufferRef] -> [BufferRef] -> [BufferRef])
-> YiM ()
promptingForBuffer Text
"switch to buffer:"
(EditorM () -> YiM ()
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM () -> YiM ())
-> (BufferRef -> EditorM ()) -> BufferRef -> YiM ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. BufferRef -> EditorM ()
switchToBufferE) (\[BufferRef]
o [BufferRef]
b -> ([BufferRef]
b [BufferRef] -> [BufferRef] -> [BufferRef]
forall a. Eq a => [a] -> [a] -> [a]
\\ [BufferRef]
o) [BufferRef] -> [BufferRef] -> [BufferRef]
forall a. [a] -> [a] -> [a]
++ [BufferRef]
o)
killBufferE :: YiM ()
killBufferE :: YiM ()
killBufferE = Text
-> (BufferRef -> YiM ())
-> ([BufferRef] -> [BufferRef] -> [BufferRef])
-> YiM ()
promptingForBuffer Text
"kill buffer:" BufferRef -> YiM ()
k (\[BufferRef]
o [BufferRef]
b -> [BufferRef]
o [BufferRef] -> [BufferRef] -> [BufferRef]
forall a. [a] -> [a] -> [a]
++ ([BufferRef]
b [BufferRef] -> [BufferRef] -> [BufferRef]
forall a. Eq a => [a] -> [a] -> [a]
\\ [BufferRef]
o))
where
k :: BufferRef -> YiM ()
k :: BufferRef -> YiM ()
k BufferRef
b = do
buf <- EditorM FBuffer -> YiM FBuffer
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM FBuffer -> YiM FBuffer)
-> ((Editor -> FBuffer) -> EditorM FBuffer)
-> (Editor -> FBuffer)
-> YiM FBuffer
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Editor -> FBuffer) -> EditorM FBuffer
forall s (m :: * -> *) a. MonadState s m => (s -> a) -> m a
gets ((Editor -> FBuffer) -> YiM FBuffer)
-> (Editor -> FBuffer) -> YiM FBuffer
forall a b. (a -> b) -> a -> b
$ BufferRef -> Editor -> FBuffer
findBufferWith BufferRef
b
ch <- deservesSave buf
let askKeymap = [Keymap] -> Keymap
forall (m :: * -> *) w e a.
(MonadInteract m w e, MonadFail m) =>
[m a] -> m a
choice [ Char -> Event
char Char
'n' Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! EditorM ()
closeBufferAndWindowE
, Char -> Event
char Char
'y' Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! EditorM ()
delBuf EditorM () -> EditorM () -> EditorM ()
forall a b. EditorM a -> EditorM b -> EditorM b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> EditorM ()
closeBufferAndWindowE
, Char -> Event
ctrlCh Char
'g' Event -> EditorM () -> Keymap
forall (m :: * -> *) a x.
(MonadInteract m Action Event, YiAction a x, Show x) =>
Event -> a -> m ()
?>>! EditorM ()
closeBufferAndWindowE
]
delBuf = BufferRef -> EditorM ()
forall (m :: * -> *). MonadEditor m => BufferRef -> m ()
deleteBuffer BufferRef
b
question = FBuffer -> Text
identString FBuffer
buf Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
" changed, close anyway? (y/n)"
withEditor $
if ch
then void $ spawnMinibufferE question (const askKeymap)
else delBuf
justOneSep :: UnivArgument -> BufferM ()
justOneSep :: UnivArgument -> BufferM ()
justOneSep UnivArgument
u = BufferM Char
readB BufferM Char -> (Char -> BufferM ()) -> BufferM ()
forall a b. BufferM a -> (a -> BufferM b) -> BufferM b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Char
c ->
BufferM Point
pointB BufferM Point -> (Point -> BufferM ()) -> BufferM ()
forall a b. BufferM a -> (a -> BufferM b) -> BufferM b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Point
point -> case Point
point of
Point Int
0 -> if Char -> Bool
isSep Char
c then BufferM ()
deleteSeparators else Char -> BufferM ()
insertMult Char
c
Point Int
x ->
if Char -> Bool
isSep Char
c
then BufferM ()
deleteSeparators
else Point -> BufferM Char
readAtB (Int -> Point
Point (Int -> Point) -> Int -> Point
forall a b. (a -> b) -> a -> b
$ Int
x Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
1) BufferM Char -> (Char -> BufferM ()) -> BufferM ()
forall a b. BufferM a -> (a -> BufferM b) -> BufferM b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \Char
d ->
if Char -> Bool
isSep Char
d
then TextUnit -> Direction -> BufferM ()
moveB TextUnit
Character Direction
Backward BufferM () -> BufferM () -> BufferM ()
forall a b. BufferM a -> BufferM b -> BufferM b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> BufferM ()
deleteSeparators
else Char -> BufferM ()
insertMult Char
' '
where
isSep :: Char -> Bool
isSep Char
c = Char
c Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
/= Char
'\n' Bool -> Bool -> Bool
&& Char -> Bool
isAnySep Char
c
insertMult :: Char -> BufferM ()
insertMult Char
c = YiString -> BufferM ()
insertN (YiString -> BufferM ()) -> YiString -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Int -> Char -> YiString
R.replicateChar (Int -> (Int -> Int) -> UnivArgument -> Int
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Int
1 (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1) UnivArgument
u) Char
c
deleteSeparators :: BufferM ()
deleteSeparators = do
TextUnit -> (Direction, BoundarySide) -> Direction -> BufferM ()
genMaybeMoveB TextUnit
unitSepThisLine (Direction
Backward, BoundarySide
InsideBound) Direction
Backward
TextUnit -> Direction -> BufferM ()
moveB TextUnit
Character Direction
Forward
(Char -> Bool) -> BufferM () -> BufferM ()
forall a. (Char -> Bool) -> BufferM a -> BufferM ()
doIfCharB Char -> Bool
isSep (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ TextUnit -> Direction -> BufferM ()
deleteB TextUnit
unitSepThisLine Direction
Forward
joinLinesE :: UnivArgument -> BufferM ()
joinLinesE :: UnivArgument -> BufferM ()
joinLinesE UnivArgument
Nothing = () -> BufferM ()
forall a. a -> BufferM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
joinLinesE (Just Int
_) = do
TextUnit -> Direction -> BufferM ()
moveB TextUnit
VLine Direction
Forward
BufferM ()
moveToSol BufferM () -> BufferM () -> BufferM ()
forall a b. BufferM a -> BufferM b -> BufferM b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (YiString -> YiString) -> TextUnit -> Direction -> BufferM ()
transformB (YiString -> YiString -> YiString
forall a b. a -> b -> a
const YiString
" ") TextUnit
Character Direction
Backward BufferM () -> BufferM () -> BufferM ()
forall a b. BufferM a -> BufferM b -> BufferM b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> UnivArgument -> BufferM ()
justOneSep UnivArgument
forall a. Maybe a
Nothing
maybeList :: [a] -> [a] -> [a]
maybeList :: forall a. [a] -> [a] -> [a]
maybeList [a]
def [] = [a]
def
maybeList [a]
_ [a]
ls = [a]
ls
maybeTag :: Tag -> T.Text -> Tag
maybeTag :: Tag -> Text -> Tag
maybeTag Tag
def Text
t = if Text -> Bool
T.null Text
t then Tag
def else Text -> Tag
Tag Text
t
promptTag :: YiM ()
promptTag :: YiM ()
promptTag = do
defaultTag <- BufferM Tag -> YiM Tag
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM Tag -> YiM Tag) -> BufferM Tag -> YiM Tag
forall a b. (a -> b) -> a -> b
$ Text -> Tag
Tag (Text -> Tag) -> (YiString -> Text) -> YiString -> Tag
forall b c a. (b -> c) -> (a -> b) -> a -> c
. YiString -> Text
R.toText (YiString -> Tag) -> BufferM YiString -> BufferM Tag
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> TextUnit -> BufferM YiString
readUnitB TextUnit
unitWord
tagTable <- withEditor getTags
let hinter = [Text] -> YiM [Text]
forall a. a -> YiM a
forall (m :: * -> *) a. Monad m => a -> m a
return ([Text] -> YiM [Text]) -> (Text -> [Text]) -> Text -> YiM [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> [Text] -> [Text]
forall a. Int -> [a] -> [a]
take Int
10 ([Text] -> [Text]) -> (Text -> [Text]) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> [Text])
-> (TagTable -> Text -> [Text]) -> Maybe TagTable -> Text -> [Text]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (String -> [Text]
forall a. String -> [a]
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> [Text]) -> (Text -> String) -> Text -> [Text]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack) TagTable -> Text -> [Text]
hintTags Maybe TagTable
tagTable
let completer = Text -> YiM Text
forall a. a -> YiM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Text -> YiM Text) -> (Text -> Text) -> Text -> YiM Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text -> Text)
-> (TagTable -> Text -> Text) -> Maybe TagTable -> Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text -> Text
forall a. a -> a
id TagTable -> Text -> Text
completeTag Maybe TagTable
tagTable
p = Text
"Find tag: (default " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Tag -> Text
_unTag Tag
defaultTag Text -> Char -> Text
`T.snoc` Char
')'
withMinibufferGen "" hinter p completer (const $ return ()) $
gotoTag . maybeTag defaultTag
gotoTag :: Tag -> YiM ()
gotoTag :: Tag -> YiM ()
gotoTag Tag
tag =
(TagTable -> YiM ()) -> YiM ()
visitTagTable ((TagTable -> YiM ()) -> YiM ()) -> (TagTable -> YiM ()) -> YiM ()
forall a b. (a -> b) -> a -> b
$ \TagTable
tagTable ->
case Tag -> TagTable -> [(String, Int)]
lookupTag Tag
tag TagTable
tagTable of
[] -> Text -> YiM ()
forall (m :: * -> *). MonadEditor m => Text -> m ()
printMsg (Text -> YiM ()) -> Text -> YiM ()
forall a b. (a -> b) -> a -> b
$ Text
"No tags containing " Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Tag -> Text
_unTag Tag
tag
(String
filename, Int
line):[(String, Int)]
_ -> String -> BufferM Int -> YiM ()
forall a. String -> BufferM a -> YiM ()
openingNewFile String
filename (BufferM Int -> YiM ()) -> BufferM Int -> YiM ()
forall a b. (a -> b) -> a -> b
$ Int -> BufferM Int
gotoLn Int
line
visitTagTable :: (TagTable -> YiM ()) -> YiM ()
visitTagTable :: (TagTable -> YiM ()) -> YiM ()
visitTagTable TagTable -> YiM ()
act = do
posTagTable <- EditorM (Maybe TagTable) -> YiM (Maybe TagTable)
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor EditorM (Maybe TagTable)
getTags
case posTagTable of
Just TagTable
tagTable -> TagTable -> YiM ()
act TagTable
tagTable
Maybe TagTable
Nothing -> Text -> (Text -> YiM ()) -> YiM ()
promptFile Text
"Visit tags table: (default tags)" ((Text -> YiM ()) -> YiM ()) -> (Text -> YiM ()) -> YiM ()
forall a b. (a -> b) -> a -> b
$ \Text
path -> do
let p :: String
p = Text -> String
T.unpack Text
path
filename :: String
filename = String -> String -> String
forall a. [a] -> [a] -> [a]
maybeList String
"tags" (String -> String) -> String -> String
forall a b. (a -> b) -> a -> b
$ String -> String
takeFileName String
p
tagTable <- IO TagTable -> YiM TagTable
forall (m :: * -> *) a. MonadBase IO m => IO a -> m a
io (IO TagTable -> YiM TagTable) -> IO TagTable -> YiM TagTable
forall a b. (a -> b) -> a -> b
$ String -> IO TagTable
importTagTable (String -> IO TagTable) -> String -> IO TagTable
forall a b. (a -> b) -> a -> b
$ String -> String
takeDirectory String
p String -> String -> String
</> String
filename
withEditor $ setTags tagTable
act tagTable
countWordsRegion :: YiM ()
countWordsRegion :: YiM ()
countWordsRegion = do
(l, w, c) <- EditorM (Int, Int, Int) -> YiM (Int, Int, Int)
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM (Int, Int, Int) -> YiM (Int, Int, Int))
-> EditorM (Int, Int, Int) -> YiM (Int, Int, Int)
forall a b. (a -> b) -> a -> b
$ do
t <- BufferM YiString -> EditorM YiString
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM YiString -> EditorM YiString)
-> BufferM YiString -> EditorM YiString
forall a b. (a -> b) -> a -> b
$ BufferM (Region, Int, Int)
getRectangle BufferM (Region, Int, Int)
-> ((Region, Int, Int) -> BufferM YiString) -> BufferM YiString
forall a b. BufferM a -> (a -> BufferM b) -> BufferM b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \(Region
reg, Int
_, Int
_) -> Region -> BufferM YiString
readRegionB Region
reg
let nls = YiString -> Int
R.countNewLines YiString
t
return (if nls == 0 then 1 else nls, length $ R.words t, R.length t)
printMsg $ T.unwords [ "Region has", showT l, p l "line" <> ","
, showT w, p w "word" <> ", and"
, showT c, p w "character" <> "."
]
where
p :: a -> p -> p
p a
x p
w = if a
x a -> a -> Bool
forall a. Eq a => a -> a -> Bool
== a
1 then p
w else p
w p -> p -> p
forall a. Semigroup a => a -> a -> a
<> p
"s"