packages feed

yi-core 0.13.2 → 0.13.3

raw patch · 6 files changed

+87/−528 lines, 6 files

Files

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