yi-core 0.13.2 → 0.13.3
raw patch · 6 files changed
+87/−528 lines, 6 files
Files
- src/Yi/Core.hs +1/−51
- src/Yi/MiniBuffer.hs +4/−28
- src/Yi/Misc.hs +81/−5
- src/Yi/Snippets.hs +0/−419
- src/Yi/Snippets/Haskell.hs +0/−22
- yi-core.cabal +1/−3
src/Yi/Core.hs view
@@ -41,7 +41,7 @@ , runAction , withSyntax , focusAllSyntax- , forkAction+ , onYiVar ) where import Prelude hiding (elem, mapM_, or)@@ -157,56 +157,6 @@ UI.main ui -- transfer control to UI --- | Runs a 'YiM' action in a separate thread.------ Notes:------ * It seems to work but I don't know why------ * Maybe deadlocks?------ * If you're outputting into the Yi window, you should really limit--- the rate at which you do so: for example, the Pango front-end will--- quite happily segfault/double-free if you output too fast.------ I am exporting this for those adventurous to play with but I have--- only discovered how to do this a night before the release so it's--- rather experimental. A simple function that prints a message once a--- second, 5 times, could be written like this:------ @--- printer :: YiM ThreadId--- printer = do--- mv <- io $ newMVar (0 :: Int)--- forkAction (suicide mv) MustRefresh $ do--- c <- io $ do--- modifyMVar_ mv (return . succ)--- tryReadMVar mv--- case c of--- Nothing -> printMsg "messaging unknown time"--- Just x -> printMsg $ "message #" <> showT x--- where--- suicide mv = tryReadMVar mv >>= \case--- Just i | i >= 5 -> return True--- _ -> threadDelay 1000000 >> return False--- @-forkAction :: (YiAction a x, Show x)- => IO Bool- -- ^ runs after we insert the action: this may be a- -- thread delay or a thread suicide or whatever else;- -- when delay returns False, that's our signal to- -- terminate the thread.- -> IsRefreshNeeded- -- ^ should we refresh after each action- -> a- -- ^ The action to actually run- -> YiM ThreadId-forkAction delay ref ym = onYiVar $ \yi yv -> do- let loop = do- yiOutput yi ref [makeAction ym]- delay >>= \b -> when b loop- t <- forkIO loop- return (yv, t) recoverMode :: [AnyMode] -> FBuffer -> FBuffer recoverMode tbl buffer = case fromMaybe (AnyMode emptyMode) (find (\(AnyMode m) -> modeName m == oldName) tbl) of
src/Yi/MiniBuffer.hs view
@@ -27,14 +27,12 @@ , getAllModeNames, matchingBufferNames, anyModeByNameM , anyModeName, (:::)(..), LineNumber, RegexTag , FilePatternTag, ToKill, CommandArguments(..)- , commentRegion, promptingForBuffer, debugBufferContent+ , commentRegion, promptingForBuffer ) where -import Control.Concurrent (threadDelay)-import Lens.Micro.Platform (use, (%=))-import Control.Monad (forM, void, when, (<=<), (>=>))+import Lens.Micro.Platform (use, (%=))+import Control.Monad (forM, void, (<=<), (>=>)) import Data.Foldable (find, toList)-import Data.IORef (newIORef, readIORef, writeIORef) import qualified Data.List.PointedList.Circular as PL (find, insertRight) import Data.Maybe (catMaybes, fromJust, fromMaybe) import Data.Proxy (Proxy)@@ -47,7 +45,7 @@ import Yi.Buffer import Yi.Completion import Yi.Config (modeTable)-import Yi.Core (forkAction, runAction)+import Yi.Core (runAction) import Yi.Editor import Yi.History (historyFinishGen, historyMove, historyStartGen) import Yi.Keymap@@ -56,29 +54,7 @@ import qualified Yi.Rope as R (YiString, fromText, toText) import Yi.String (commonTPrefix) import Yi.Style (defaultStyle)-import Yi.Utils (io) import Yi.Window (bufkey)---- | Prints out the rope of the current buffer as-is to stdout.------ The only way to stop it is to close the buffer in question which--- should free up the 'BufferRef'.-debugBufferContent :: YiM ()-debugBufferContent = promptingForBuffer "buffer to trace:"- debugBufferContentUsing (\_ x -> x)--debugBufferContentUsing :: BufferRef -> YiM ()-debugBufferContentUsing b = do- mv <- io $ newIORef mempty- keepGoing <- io $ newIORef True- let delay = threadDelay 100000 >> readIORef keepGoing- void . forkAction delay NoNeedToRefresh $- findBuffer b >>= \case- Nothing -> io $ writeIORef keepGoing True- Just _ -> do- ns <- withGivenBuffer b elemsB :: YiM R.YiString- io $ readIORef mv >>= \c ->- when (c /= ns) (print ns >> void (writeIORef mv ns)) -- | Prompts for a buffer name, turns it into a 'BufferRef' and passes -- it on to the handler function. Uses all known buffers for hinting.
src/Yi/Misc.hs view
@@ -19,9 +19,11 @@ , printFileInfoE, debugBufferContent ) where -import Control.Monad (filterM, (>=>))+import Control.Concurrent+import Control.Monad (filterM, (>=>), when, void) import Control.Monad.Base (liftBase) import Data.Char (chr, isAlpha, isLower, isUpper, ord)+import Data.IORef import Data.List ((\\)) import Data.Maybe (isNothing) import qualified Data.Text as T (Text, append, concat, isPrefixOf,@@ -38,11 +40,13 @@ import System.FriendlyPath (expandTilda, isAbsolute') import Yi.Buffer import Yi.Completion (completeInList')-import Yi.Editor (EditorM, printMsg, withCurrentBuffer)-import Yi.Keymap (YiM)-import Yi.MiniBuffer (debugBufferContent, mkCompleteFn, withMinibufferGen)+import Yi.Core (onYiVar)+import Yi.Editor (EditorM, printMsg, withCurrentBuffer, withGivenBuffer, findBuffer)+import Yi.Keymap (YiM, makeAction, YiAction)+import Yi.MiniBuffer (mkCompleteFn, withMinibufferGen, promptingForBuffer) import Yi.Monad (gets)-import qualified Yi.Rope as R (fromText)+import qualified Yi.Rope as R (fromText, YiString)+import Yi.Types (IsRefreshNeeded(..), Yi(..)) import Yi.Utils (io) -- | Given a possible starting path (which if not given defaults to@@ -212,3 +216,75 @@ , bufInfoPercent bufInfo , "]" ]++-- | Runs a 'YiM' action in a separate thread.+--+-- Notes:+--+-- * It seems to work but I don't know why+--+-- * Maybe deadlocks?+--+-- * If you're outputting into the Yi window, you should really limit+-- the rate at which you do so: for example, the Pango front-end will+-- quite happily segfault/double-free if you output too fast.+--+-- I am exporting this for those adventurous to play with but I have+-- only discovered how to do this a night before the release so it's+-- rather experimental. A simple function that prints a message once a+-- second, 5 times, could be written like this:+--+-- @+-- printer :: YiM ThreadId+-- printer = do+-- mv <- io $ newMVar (0 :: Int)+-- forkAction (suicide mv) MustRefresh $ do+-- c <- io $ do+-- modifyMVar_ mv (return . succ)+-- tryReadMVar mv+-- case c of+-- Nothing -> printMsg "messaging unknown time"+-- Just x -> printMsg $ "message #" <> showT x+-- where+-- suicide mv = tryReadMVar mv >>= \case+-- Just i | i >= 5 -> return True+-- _ -> threadDelay 1000000 >> return False+-- @+forkAction :: (YiAction a x, Show x)+ => IO Bool+ -- ^ runs after we insert the action: this may be a+ -- thread delay or a thread suicide or whatever else;+ -- when delay returns False, that's our signal to+ -- terminate the thread.+ -> IsRefreshNeeded+ -- ^ should we refresh after each action+ -> a+ -- ^ The action to actually run+ -> YiM ThreadId+forkAction delay ref ym = onYiVar $ \yi yv -> do+ let loop = do+ yiOutput yi ref [makeAction ym]+ delay >>= \b -> when b loop+ t <- forkIO loop+ return (yv, t)++-- | Prints out the rope of the current buffer as-is to stdout.+--+-- The only way to stop it is to close the buffer in question which+-- should free up the 'BufferRef'.+debugBufferContent :: YiM ()+debugBufferContent = promptingForBuffer "buffer to trace:"+ debugBufferContentUsing (\_ x -> x)++debugBufferContentUsing :: BufferRef -> YiM ()+debugBufferContentUsing b = do+ mv <- io $ newIORef mempty+ keepGoing <- io $ newIORef True+ let delay = threadDelay 100000 >> readIORef keepGoing+ void . forkAction delay NoNeedToRefresh $+ findBuffer b >>= \case+ Nothing -> io $ writeIORef keepGoing True+ Just _ -> do+ ns <- withGivenBuffer b elemsB :: YiM R.YiString+ io $ readIORef mv >>= \c ->+ when (c /= ns) (print ns >> void (writeIORef mv ns))
− src/Yi/Snippets.hs
@@ -1,419 +0,0 @@-{-# LANGUAGE CPP #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE FunctionalDependencies #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE TemplateHaskell #-}-{-# OPTIONS_HADDOCK show-extensions #-}---- |--- Module : Yi.Snippets--- License : GPL-2--- Maintainer : yi-devel@googlegroups.com--- Stability : experimental--- Portability : portable--module Yi.Snippets where--import GHC.Generics (Generic)--import Control.Applicative (some)-import Control.Arrow (second)-import Lens.Micro.Platform (use, (.=))-import Control.Monad.RWS (MonadPlus (mplus), MonadReader (ask),- MonadState, MonadTrans (..),- MonadWriter (tell), RWST, evalRWST,- filterM, forM, forM_, liftM2, unless,- when, (<>))-import Data.Binary (Binary)-import Data.Char (isSpace)-import Data.Default (Default, def)-import Data.Foldable (find)-import Data.List (foldl', groupBy, intersperse, nub, sort)-import Data.Maybe (catMaybes)-import qualified Data.Text as T (Text)-import Data.Typeable (Typeable)-import Yi.Buffer-import Yi.Editor (withCurrentBuffer)-import Yi.Keymap (Action)-import Yi.Keymap.Keys-import qualified Yi.Rope as R-import Yi.TextCompletion (resetComplete, wordCompleteString')-import Yi.Types (YiVariable)--type SnippetCmd = RWST (Int, Int) [MarkInfo] () BufferM--data SnippetMark = SimpleMark !Int- | ValuedMark !Int R.YiString- | DependentMark !Int---data MarkInfo = SimpleMarkInfo { userIndex :: !Int- , startMark :: !Mark }- | ValuedMarkInfo { userIndex :: !Int- , startMark :: !Mark- , endMark :: !Mark }- | DependentMarkInfo { userIndex :: !Int- , startMark :: !Mark- , endMark :: !Mark }- deriving (Eq, Show, Generic)--instance Binary MarkInfo--newtype BufferMarks = BufferMarks { bufferMarks :: [MarkInfo] }- deriving (Eq, Show, Monoid, Typeable, Binary)--newtype DependentMarks = DependentMarks { marks :: [[MarkInfo]] }- deriving (Eq, Show, Monoid, Typeable, Binary)--instance Default BufferMarks where- def = BufferMarks []--instance Default DependentMarks where- def = DependentMarks []--instance YiVariable BufferMarks-instance YiVariable DependentMarks--instance Ord MarkInfo where- a `compare` b = userIndex a `compare` userIndex b--cursor :: Int -> SnippetMark-cursor = SimpleMark--cursorWith :: Int -> R.YiString -> SnippetMark-cursorWith = ValuedMark--dep :: Int -> SnippetMark-dep = DependentMark--isDependentMark :: MarkInfo -> Bool-isDependentMark (SimpleMarkInfo{}) = False-isDependentMark (ValuedMarkInfo{}) = False-isDependentMark (DependentMarkInfo{}) = True--bufferMarkers :: MarkInfo -> [Mark]-bufferMarkers (SimpleMarkInfo _ s) = [s]-bufferMarkers m = [startMark m, endMark m]---- used to translate a datatype into a snippet cmd for--- freely combining data with '&'-class MkSnippetCmd a b | a -> b where- mkSnippetCmd :: a -> SnippetCmd b--instance MkSnippetCmd String () where- mkSnippetCmd = text . R.fromString--instance MkSnippetCmd R.YiString () where- mkSnippetCmd = text--instance MkSnippetCmd T.Text () where- mkSnippetCmd = text . R.fromText--instance MkSnippetCmd (SnippetCmd a) a where- mkSnippetCmd = id---- mkSnippetCmd for 'cursor...'-functions-instance MkSnippetCmd SnippetMark () where- mkSnippetCmd (SimpleMark i) = do- mk <- mkMark- tell [SimpleMarkInfo i mk]-- mkSnippetCmd (ValuedMark i str) = do- start <- mkMark- lift $ insertN str- end <- mkMark- tell [ValuedMarkInfo i start end]-- mkSnippetCmd (DependentMark i) = do- start <- mkMark- end <- mkMark- tell [DependentMarkInfo i start end]---- create a mark at current position-mkMark :: MonadTrans t => t BufferM Mark-mkMark = lift $ do p <- pointB- newMarkB $ MarkValue p Backward---- Indentation support has been temporarily removed-text :: R.YiString -> SnippetCmd ()-text txt = do- (_, indent) <- ask- indentSettings <- lift indentSettingsB- lift . foldl' (>>) (return ()) .- intersperse (newlineB >> indentToB indent) .- map (if expandTabs indentSettings- then insertN . expand indentSettings ""- else insertN) $ lines' txt- where- lines' txt' = case R.last txt' of- Just '\n' -> R.lines txt' <> [mempty]- _ -> R.lines txt-- expand :: IndentSettings -> R.YiString -> R.YiString -> R.YiString- expand is str rst = case R.head rst of- Nothing -> R.reverse str- Just '\t' -> let t = R.replicateChar (tabSize is) ' ' <> str- in expand is t (R.drop 1 rst)- Just s -> expand is (s `R.cons` str) rst---- unfortunatelly data converted to snippets are no monads, but '&' is--- very similar to '>>' and '&>' is similar to '>>=', since--- SnippetCmd's can be used monadically-infixr 5 &-(&) :: (MkSnippetCmd a any , MkSnippetCmd b c) => a -> b -> SnippetCmd c-str & rst = mkSnippetCmd str >> mkSnippetCmd rst--(&>) :: (MkSnippetCmd a b, MkSnippetCmd c d) => a -> (b -> c) -> SnippetCmd d-str &> rst = mkSnippetCmd str >>= mkSnippetCmd . rst--runSnippet :: Bool -> SnippetCmd a -> BufferM a-runSnippet deleteLast s = do- line <- lineOf =<< pointB- indent <- indentOfCurrentPosB- (a, markInfo) <- evalRWST s (line, indent) ()- unless (null markInfo) $ do- let newMarks = sort $ filter (not . isDependentMark) markInfo- let newDepMarks = filter (not . len1) $- groupBy belongTogether $- sort markInfo- getBufferDyn >>= putBufferDyn.(BufferMarks newMarks `mappend`)- unless (null newDepMarks) $- getBufferDyn >>= putBufferDyn.(DependentMarks newDepMarks `mappend`)- moveToNextBufferMark deleteLast- return a- where- len1 (_:[]) = True- len1 _ = False-- belongTogether a b = userIndex a == userIndex b--updateUpdatedMarks :: [Update] -> BufferM ()-updateUpdatedMarks upds = findEditedMarks upds >>=- mapM_ updateDependents--findEditedMarks :: [Update] -> BufferM [MarkInfo]-findEditedMarks upds = fmap (nub . concat) (mapM findEditedMarks' upds)- where- findEditedMarks' :: Update -> BufferM [MarkInfo]- findEditedMarks' upd = do- let p = updatePoint upd- ms <- return . nub . concat . marks =<< getBufferDyn- ms' <- forM ms $ \m ->do- r <- adjMarkRegion m- return $ if (updateIsDelete upd && p `nearRegion` r)- || p `inRegion` r- then Just m- else Nothing- return . catMaybes $ ms'--dependentSiblings :: MarkInfo -> [[MarkInfo]] -> [MarkInfo]-dependentSiblings mark deps =- case find (elem mark) deps of- Nothing -> []- Just lst -> filter (not . (mark==)) lst--updateDependents :: MarkInfo -> BufferM ()-updateDependents m = getBufferDyn >>= updateDependents' m . marks--updateDependents' :: MarkInfo -> [[MarkInfo]] -> BufferM ()-updateDependents' mark deps =- case dependentSiblings mark deps of- [] -> return ()- deps' -> do- txt <- markText mark- forM_ deps' $ \d -> do- dTxt <- markText d- when (txt /= dTxt) $ setMarkText txt d--markText :: MarkInfo -> BufferM R.YiString-markText m = markRegion m >>= readRegionB--setMarkText :: R.YiString -> MarkInfo -> BufferM ()-setMarkText txt (SimpleMarkInfo _ start) = do- p <- use $ markPointA start- c <- readAtB p- if isSpace c- then insertNAt txt p- else do- r <- regionOfPartNonEmptyAtB unitViWordOnLine Forward p- modifyRegionB (const txt) r--setMarkText txt mi = do- start <- use $ markPointA $ startMark mi- end <- use $ markPointA $ endMark mi- let r = mkRegion start end- modifyRegionB (const txt) r- when (start == end) $- markPointA (endMark mi) .= end + Point (R.length txt)--withSimpleRegion :: MarkInfo -> (Region -> BufferM Region) -> BufferM Region-withSimpleRegion (SimpleMarkInfo _ s) f = do- p <- use $ markPointA s- c <- readAtB p- if isSpace c- then return $ mkRegion p p -- return empty region- else f =<< regionOfPartNonEmptyAtB unitViWordOnLine Forward p-withSimpleRegion r _ = error $ "withSimpleRegion: " <> show r--markRegion :: MarkInfo -> BufferM Region-markRegion m@SimpleMarkInfo{} = withSimpleRegion m $ \r -> do- os <- findOverlappingMarksWith safeMarkRegion concat True r m- rOs <- mapM safeMarkRegion os- return . mkRegion (regionStart r) $ foldl' minEnd (regionEnd r) rOs- where- minEnd end r = if regionEnd r < end- then end- else min end $ regionStart r--markRegion m = liftM2 mkRegion- (use $ markPointA $ startMark m)- (use $ markPointA $ endMark m)--safeMarkRegion :: MarkInfo -> BufferM Region-safeMarkRegion m@(SimpleMarkInfo _ _) = withSimpleRegion m return-safeMarkRegion m = markRegion m--adjMarkRegion :: MarkInfo -> BufferM Region-adjMarkRegion s@(SimpleMarkInfo _ _) = markRegion s--adjMarkRegion m = do- s <- use $ markPointA $ startMark m- e <- use $ markPointA $ endMark m- c <- readAtB e- when (isWordChar c) $ do adjustEnding e- repairOverlappings e- e' <- use $ markPointA $ endMark m- s' <- adjustStart s e'- return $ mkRegion s' e'- where- adjustEnding end = do- r' <- regionOfPartNonEmptyAtB unitViWordOnLine Forward end- markPointA (endMark m) .= (regionEnd r')-- adjustStart s e = do- txt <- readRegionB (mkRegion s e)- let sP = s + (Point . R.length $ R.takeWhile isSpace txt)- when (sP > s) $- markPointA (startMark m) .= sP- return sP-- -- test if we generated overlappings and repair- repairOverlappings origEnd = do overlappings <- allOverlappingMarks True m- unless (null overlappings) $- markPointA (endMark m) .= origEnd--findOverlappingMarksWith :: (MarkInfo -> BufferM Region)- -> ([[MarkInfo]] -> [MarkInfo])- -> Bool -> Region -> MarkInfo -> BufferM [MarkInfo]-findOverlappingMarksWith fMarkRegion flattenMarks border r m =- let markFilter = filter (m /=) . flattenMarks . marks- regOverlap = fmap (regionsOverlap border r) . fMarkRegion- in fmap markFilter getBufferDyn >>= filterM regOverlap--findOverlappingMarks :: ([[MarkInfo]] -> [MarkInfo]) -> Bool -> Region ->- MarkInfo -> BufferM [MarkInfo]-findOverlappingMarks = findOverlappingMarksWith markRegion--regionsOverlappingMarks :: Bool -> Region -> MarkInfo -> BufferM [MarkInfo]-regionsOverlappingMarks = findOverlappingMarks concat--overlappingMarks :: Bool -> Bool -> MarkInfo -> BufferM [MarkInfo]-overlappingMarks border belongingTogether mark = do- r <- markRegion mark- findOverlappingMarks (if belongingTogether- then dependentSiblings mark- else concat)- border- r- mark--allOverlappingMarks :: Bool -> MarkInfo -> BufferM [MarkInfo]-allOverlappingMarks border = overlappingMarks border False--dependentOverlappingMarks :: Bool -> MarkInfo -> BufferM [MarkInfo]-dependentOverlappingMarks border = overlappingMarks border True--nextBufferMark :: Bool -> BufferM (Maybe MarkInfo)-nextBufferMark deleteLast = do- BufferMarks ms <- getBufferDyn- if null ms- then return Nothing- else do- let mks = if deleteLast then const $ tail ms else (tail ms <>)- putBufferDyn . BufferMarks . mks $ [head ms]- return . Just $ head ms--isDependentMarker :: (MonadState FBuffer m, Functor m) => Mark -> m Bool-isDependentMarker bMark = do- DependentMarks ms <- getBufferDyn- return . elem bMark . concatMap bufferMarkers . concat $ ms--safeDeleteMarkB :: Mark -> BufferM ()-safeDeleteMarkB m = do- b <- isDependentMarker m- unless b (deleteMarkB m)--moveToNextBufferMark :: Bool -> BufferM ()-moveToNextBufferMark deleteLast = nextBufferMark deleteLast >>= \case- Just p -> mv p- Nothing -> return ()- where- mv (SimpleMarkInfo _ m) = do- moveTo =<< use (markPointA m)- when deleteLast $ safeDeleteMarkB m-- mv (ValuedMarkInfo _ s e) = do- sp <- use $ markPointA s- ep <- use $ markPointA e- deleteRegionB (mkRegion sp ep)- moveTo sp- when deleteLast $ do- safeDeleteMarkB s- safeDeleteMarkB e-- mv r = error $ "moveToNextBufferMark.mv: " <> show r---- Keymap support--newtype SupertabExt = Supertab (R.YiString -> Maybe (BufferM ()))--instance Monoid SupertabExt where- mempty = Supertab $ const Nothing-- (Supertab f) `mappend` (Supertab g) =- Supertab $ \s -> f s `mplus` g s--superTab :: (MonadInteract m Action Event) => Bool -> SupertabExt -> m ()-superTab caseSensitive (Supertab expander) =- some (spec KTab ?>>! doSuperTab) >> deprioritize >>! resetComplete- where- doSuperTab = do canExpand <- withCurrentBuffer $ do- sol <- atSol- ws <- hasWhiteSpaceBefore- return $ sol || ws- if canExpand- then insertTab- else runCompleter-- insertTab = withCurrentBuffer $ mapM_ insertB =<< tabB-- runCompleter = do w <- withCurrentBuffer readPrevWordB- case expander w of- Just cmd -> withCurrentBuffer $ bkillWordB >> cmd- _ -> autoComplete-- autoComplete = wordCompleteString' caseSensitive >>=- withCurrentBuffer . (bkillWordB >>) . (insertN . R.fromText)---- | Convert snippet description list into a SuperTab extension-fromSnippets :: Bool -> [(R.YiString, SnippetCmd ())] -> SupertabExt-fromSnippets deleteLast snippets =- Supertab $ \str -> lookup str $ map (second $ runSnippet deleteLast) snippets--snippet :: MkSnippetCmd a b => a -> SnippetCmd b-snippet = mkSnippetCmd
− src/Yi/Snippets/Haskell.hs
@@ -1,22 +0,0 @@-{-# OPTIONS_HADDOCK show-extensions #-}---- |--- Module : Yi.Snippets.Haskell--- License : GPL-2--- Maintainer : yi-devel@googlegroups.com--- Stability : experimental--- Portability : portable--module Yi.Snippets.Haskell where--import qualified Yi.Rope as R (singleton)-import Yi.Snippets (SnippetCmd, cursor, cursorWith, snippet, (&))--hsFunction :: SnippetCmd ()-hsFunction = snippet $- cursorWith 1 (R.singleton 'f') & " :: " & cursor 2 & "\n" &- cursor 3 & " = " & cursor 4 & "\n"--hsClass :: SnippetCmd ()-hsClass = snippet $- "class " & cursor 1 & " " & cursor 2 & " where\n " & cursor 3
yi-core.cabal view
@@ -3,7 +3,7 @@ -- see: https://github.com/sol/hpack name: yi-core-version: 0.13.2+version: 0.13.3 synopsis: Yi editor core library category: Yi homepage: https://github.com/yi-editor/yi#readme@@ -151,8 +151,6 @@ Yi.PersistentState Yi.Process Yi.Rectangle- Yi.Snippets- Yi.Snippets.Haskell Yi.Search Yi.Search.Internal Yi.String