{-# LANGUAGE OverloadedStrings #-}
{-# OPTIONS_HADDOCK show-extensions #-}

-- |
-- Module      :  Yi.Keymap.Vim.Utils
-- License     :  GPL-2
-- Maintainer  :  yi-devel@googlegroups.com
-- Stability   :  experimental
-- Portability :  portable
--
-- Utils for the Vim keymap.

module Yi.Keymap.Vim.Utils
  ( mkBindingE
  , mkBindingY
  , mkStringBindingE
  , mkStringBindingY
  , splitCountedCommand
  , selectBinding
  , selectPureBinding
  , matchFromBool
  , mkMotionBinding
  , mkChooseRegisterBinding
  , pasteInclusiveB
  , addNewLineIfNecessary
  , indentBlockRegionB
  , addVimJumpHereE
  , exportRegisterToClipboard
  , pasteFromClipboard
  ) where

import           Lens.Micro.Platform               ((.=), use)
import           Control.Monad            (forM_, void, when)
import           Data.Char                (isSpace)
import           Data.Foldable            (asum)
import           Data.List                (group)
import qualified Data.Text                as T (unpack)
import           Safe                     (headDef)
import           Yi.Buffer                hiding (Insert)
import           Yi.Editor
import           Yi.Event                 (Event)
import           Yi.Keymap                (YiM)
import           Yi.Keymap.Vim.Common
import           Yi.Keymap.Vim.EventUtils (eventToEventString, splitCountedCommand)
import           Yi.Keymap.Vim.MatchResult
import           Yi.Keymap.Vim.Motion     (Move (Move), stringToMove)
import           Yi.Keymap.Vim.StateUtils (getMaybeCountE, modifyStateE,
                                           resetCountE, getRegisterE)
import           Yi.Monad                 (whenM)
import           Yi.Rope                  (YiString, countNewLines, last)
import qualified Yi.Rope                  as R (replicateChar, snoc, toString, fromString)
import           Yi.Utils                 (io)
import           System.Hclip             (getClipboard, setClipboard)

-- 'mkBindingE' and 'mkBindingY' are helper functions for bindings
-- where VimState mutation is not dependent on action performed
-- and prerequisite has form (mode == ... && event == ...)

mkStringBindingE :: VimMode -> RepeatToken
    -> (EventString, EditorM (), VimState -> VimState) -> VimBinding
mkStringBindingE :: VimMode
-> RepeatToken
-> (EventString, EditorM (), VimState -> VimState)
-> VimBinding
mkStringBindingE VimMode
mode RepeatToken
rtoken (EventString
eventString, EditorM ()
action, VimState -> VimState
mutate) = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
f
    where f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
f EventString
_ VimState
vs | VimState -> VimMode
vsMode VimState
vs VimMode -> VimMode -> Bool
forall a. Eq a => a -> a -> Bool
/= VimMode
mode = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch
          f EventString
evs VimState
_ = EditorM ()
-> (VimState -> VimState) -> RepeatToken -> EditorM RepeatToken
forall (m :: * -> *).
MonadEditor m =>
m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction EditorM ()
action VimState -> VimState
mutate RepeatToken
rtoken EditorM RepeatToken
-> MatchResult () -> MatchResult (EditorM RepeatToken)
forall a b. a -> MatchResult b -> MatchResult a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$
                    EventString
evs EventString -> EventString -> MatchResult ()
`matchesString` EventString
eventString

mkStringBindingY :: VimMode
    -> (EventString, YiM (), VimState -> VimState) -> VimBinding
mkStringBindingY :: VimMode
-> (EventString, YiM (), VimState -> VimState) -> VimBinding
mkStringBindingY VimMode
mode (EventString
eventString, YiM ()
action, VimState -> VimState
mutate) = (EventString -> VimState -> MatchResult (YiM RepeatToken))
-> VimBinding
VimBindingY EventString -> VimState -> MatchResult (YiM RepeatToken)
f
    where f :: EventString -> VimState -> MatchResult (YiM RepeatToken)
f EventString
_ VimState
vs | VimState -> VimMode
vsMode VimState
vs VimMode -> VimMode -> Bool
forall a. Eq a => a -> a -> Bool
/= VimMode
mode = MatchResult (YiM RepeatToken)
forall a. MatchResult a
NoMatch
          f EventString
evs VimState
_ = YiM () -> (VimState -> VimState) -> RepeatToken -> YiM RepeatToken
forall (m :: * -> *).
MonadEditor m =>
m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction YiM ()
action VimState -> VimState
mutate RepeatToken
Drop YiM RepeatToken -> MatchResult () -> MatchResult (YiM RepeatToken)
forall a b. a -> MatchResult b -> MatchResult a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$
                    EventString
evs EventString -> EventString -> MatchResult ()
`matchesString` EventString
eventString

mkBindingE :: VimMode -> RepeatToken -> (Event, EditorM (), VimState -> VimState) -> VimBinding
mkBindingE :: VimMode
-> RepeatToken
-> (Event, EditorM (), VimState -> VimState)
-> VimBinding
mkBindingE VimMode
mode RepeatToken
rtoken (Event
event, EditorM ()
action, VimState -> VimState
mutate) = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
f
    where f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
f EventString
evs VimState
vs = EditorM ()
-> (VimState -> VimState) -> RepeatToken -> EditorM RepeatToken
forall (m :: * -> *).
MonadEditor m =>
m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction EditorM ()
action VimState -> VimState
mutate RepeatToken
rtoken EditorM RepeatToken
-> MatchResult () -> MatchResult (EditorM RepeatToken)
forall a b. a -> MatchResult b -> MatchResult a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$
                     Bool -> MatchResult ()
matchFromBool (VimState -> VimMode
vsMode VimState
vs VimMode -> VimMode -> Bool
forall a. Eq a => a -> a -> Bool
== VimMode
mode Bool -> Bool -> Bool
&& EventString
evs EventString -> EventString -> Bool
forall a. Eq a => a -> a -> Bool
== Event -> EventString
eventToEventString Event
event)

mkBindingY :: VimMode -> (Event, YiM (), VimState -> VimState) -> VimBinding
mkBindingY :: VimMode -> (Event, YiM (), VimState -> VimState) -> VimBinding
mkBindingY VimMode
mode (Event
event, YiM ()
action, VimState -> VimState
mutate) = (EventString -> VimState -> MatchResult (YiM RepeatToken))
-> VimBinding
VimBindingY EventString -> VimState -> MatchResult (YiM RepeatToken)
f
    where f :: EventString -> VimState -> MatchResult (YiM RepeatToken)
f EventString
evs VimState
vs = YiM () -> (VimState -> VimState) -> RepeatToken -> YiM RepeatToken
forall (m :: * -> *).
MonadEditor m =>
m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction YiM ()
action VimState -> VimState
mutate RepeatToken
Drop YiM RepeatToken -> MatchResult () -> MatchResult (YiM RepeatToken)
forall a b. a -> MatchResult b -> MatchResult a
forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$
                     Bool -> MatchResult ()
matchFromBool (VimState -> VimMode
vsMode VimState
vs VimMode -> VimMode -> Bool
forall a. Eq a => a -> a -> Bool
== VimMode
mode Bool -> Bool -> Bool
&& EventString
evs EventString -> EventString -> Bool
forall a. Eq a => a -> a -> Bool
== Event -> EventString
eventToEventString Event
event)

combineAction :: MonadEditor m => m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction :: forall (m :: * -> *).
MonadEditor m =>
m () -> (VimState -> VimState) -> RepeatToken -> m RepeatToken
combineAction m ()
action VimState -> VimState
mutateState RepeatToken
rtoken = do
    m ()
action
    EditorM () -> m ()
forall a. EditorM a -> m a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM () -> m ()) -> EditorM () -> m ()
forall a b. (a -> b) -> a -> b
$ (VimState -> VimState) -> EditorM ()
modifyStateE VimState -> VimState
mutateState
    RepeatToken -> m RepeatToken
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
rtoken

-- | All impure bindings will be ignored.
selectPureBinding :: EventString -> VimState -> [VimBinding] -> MatchResult (EditorM RepeatToken)
selectPureBinding :: EventString
-> VimState -> [VimBinding] -> MatchResult (EditorM RepeatToken)
selectPureBinding EventString
evs VimState
state = [MatchResult (EditorM RepeatToken)]
-> MatchResult (EditorM RepeatToken)
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum ([MatchResult (EditorM RepeatToken)]
 -> MatchResult (EditorM RepeatToken))
-> ([VimBinding] -> [MatchResult (EditorM RepeatToken)])
-> [VimBinding]
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VimBinding -> MatchResult (EditorM RepeatToken))
-> [VimBinding] -> [MatchResult (EditorM RepeatToken)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VimBinding -> MatchResult (EditorM RepeatToken)
try
    where try :: VimBinding -> MatchResult (EditorM RepeatToken)
try (VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
matcher) = EventString -> VimState -> MatchResult (EditorM RepeatToken)
matcher EventString
evs VimState
state
          try (VimBindingY EventString -> VimState -> MatchResult (YiM RepeatToken)
_) = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

selectBinding :: EventString -> VimState -> [VimBinding] -> MatchResult (YiM RepeatToken)
selectBinding :: EventString
-> VimState -> [VimBinding] -> MatchResult (YiM RepeatToken)
selectBinding EventString
input VimState
state = [MatchResult (YiM RepeatToken)] -> MatchResult (YiM RepeatToken)
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Alternative f) =>
t (f a) -> f a
asum ([MatchResult (YiM RepeatToken)] -> MatchResult (YiM RepeatToken))
-> ([VimBinding] -> [MatchResult (YiM RepeatToken)])
-> [VimBinding]
-> MatchResult (YiM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (VimBinding -> MatchResult (YiM RepeatToken))
-> [VimBinding] -> [MatchResult (YiM RepeatToken)]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap VimBinding -> MatchResult (YiM RepeatToken)
try
    where try :: VimBinding -> MatchResult (YiM RepeatToken)
try (VimBindingY EventString -> VimState -> MatchResult (YiM RepeatToken)
matcher) = EventString -> VimState -> MatchResult (YiM RepeatToken)
matcher EventString
input VimState
state
          try (VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
matcher) = (EditorM RepeatToken -> YiM RepeatToken)
-> MatchResult (EditorM RepeatToken)
-> MatchResult (YiM RepeatToken)
forall a b. (a -> b) -> MatchResult a -> MatchResult b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap EditorM RepeatToken -> YiM RepeatToken
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (MatchResult (EditorM RepeatToken)
 -> MatchResult (YiM RepeatToken))
-> MatchResult (EditorM RepeatToken)
-> MatchResult (YiM RepeatToken)
forall a b. (a -> b) -> a -> b
$ EventString -> VimState -> MatchResult (EditorM RepeatToken)
matcher EventString
input VimState
state

setUnjumpMarks :: Point -> BufferM ()
setUnjumpMarks :: Point -> BufferM ()
setUnjumpMarks Point
p = do
    solP <- Point -> BufferM Point
solPointB Point
p
    lineStream <- indexedStreamB Forward solP
    let fstNonBlank =
            Point -> [Point] -> Point
forall a. a -> [a] -> a
headDef Point
solP [ Point
p' | (Point
p', Char
ch) <- [(Point, Char)]
lineStream, Bool -> Bool
not (Char -> Bool
isSpace Char
ch) Bool -> Bool -> Bool
|| Char
ch Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
'\n' ]
    (.= p)           . markPointA =<< getMarkB (Just "`")
    (.= fstNonBlank) . markPointA =<< getMarkB (Just "'")

addVimJumpAtE :: Point -> EditorM ()
addVimJumpAtE :: Point -> EditorM ()
addVimJumpAtE Point
p = do
    BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Point -> BufferM ()
setUnjumpMarks Point
p
    Point -> EditorM ()
addJumpAtE Point
p

addVimJumpHereE :: EditorM ()
addVimJumpHereE :: EditorM ()
addVimJumpHereE = do
    BufferM () -> EditorM ()
forall (m :: * -> *) a. MonadEditor m => BufferM a -> m a
withCurrentBuffer (BufferM () -> EditorM ()) -> BufferM () -> EditorM ()
forall a b. (a -> b) -> a -> b
$ Point -> BufferM ()
setUnjumpMarks (Point -> BufferM ()) -> BufferM Point -> BufferM ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< BufferM Point
pointB
    EditorM ()
addJumpHereE

mkMotionBinding :: RepeatToken -> (VimMode -> Bool) -> VimBinding
mkMotionBinding :: RepeatToken -> (VimMode -> Bool) -> VimBinding
mkMotionBinding RepeatToken
token VimMode -> Bool
condition = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE EventString -> VimState -> MatchResult (EditorM RepeatToken)
f
  where
    -- TODO: stringToMove and go both to EventString
    f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
    f :: EventString -> VimState -> MatchResult (EditorM RepeatToken)
f EventString
evs VimState
state | VimMode -> Bool
condition (VimState -> VimMode
vsMode VimState
state) =
        (Move -> EditorM RepeatToken)
-> MatchResult Move -> MatchResult (EditorM RepeatToken)
forall a b. (a -> b) -> MatchResult a -> MatchResult b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String -> Move -> EditorM RepeatToken
go (String -> Move -> EditorM RepeatToken)
-> (EventString -> String)
-> EventString
-> Move
-> EditorM RepeatToken
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> Text
_unEv (EventString -> Move -> EditorM RepeatToken)
-> EventString -> Move -> EditorM RepeatToken
forall a b. (a -> b) -> a -> b
$ EventString
evs) (EventString -> MatchResult Move
stringToMove EventString
evs)
    f EventString
_ VimState
_ = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

    go :: String -> Move -> EditorM RepeatToken
    go :: String -> Move -> EditorM RepeatToken
go String
evs (Move RegionStyle
_style Bool
isJump Maybe Int -> BufferM ()
move) = do
        count <- EditorM (Maybe Int)
getMaybeCountE
        prevPoint <- withCurrentBuffer $ do
            p <- pointB
            move count
            leftOnEol
            return p
        when isJump $ addVimJumpAtE prevPoint
        resetCountE

        sticky <- withCurrentBuffer $ use stickyEolA

        -- moving with j/k after $ sticks cursor to the right edge
        when (evs == "$") . withCurrentBuffer $ stickyEolA .= True
        when (evs `elem` group "jk" && sticky) $
            withCurrentBuffer $ moveToEol >> moveXorSol 1
        when (evs `notElem` group "jk$") . withCurrentBuffer $ stickyEolA .= False

        let m = String -> Char
forall a. HasCallStack => [a] -> a
head String
evs
        when (m `elem` ('f' : "FtT")) $ do
            let c = String -> Char
forall a. HasCallStack => [a] -> a
Prelude.last String
evs
                (dir, style) =
                    case m of
                        Char
'f' -> (Direction
Forward, RegionStyle
Inclusive)
                        Char
't' -> (Direction
Forward, RegionStyle
Exclusive)
                        Char
'F' -> (Direction
Backward, RegionStyle
Inclusive)
                        Char
'T' -> (Direction
Backward, RegionStyle
Exclusive)
                        Char
_ -> String -> (Direction, RegionStyle)
forall a. HasCallStack => String -> a
error String
"can't happen"
                command = Char -> Direction -> RegionStyle -> GotoCharCommand
GotoCharCommand Char
c Direction
dir RegionStyle
style
            modifyStateE $ \VimState
s -> VimState
s { vsLastGotoCharCommand = Just command}

        return token

mkChooseRegisterBinding :: (VimState -> Bool) -> VimBinding
mkChooseRegisterBinding :: (VimState -> Bool) -> VimBinding
mkChooseRegisterBinding VimState -> Bool
statePredicate = (EventString -> VimState -> MatchResult (EditorM RepeatToken))
-> VimBinding
VimBindingE (String -> VimState -> MatchResult (EditorM RepeatToken)
f (String -> VimState -> MatchResult (EditorM RepeatToken))
-> (EventString -> String)
-> EventString
-> VimState
-> MatchResult (EditorM RepeatToken)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack (Text -> String) -> (EventString -> Text) -> EventString -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. EventString -> Text
_unEv)
    where f :: String -> VimState -> MatchResult (EditorM RepeatToken)
f String
"\"" VimState
s | VimState -> Bool
statePredicate VimState
s = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
PartialMatch
          f [Char
'"', Char
c] VimState
s | VimState -> Bool
statePredicate VimState
s = EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
forall a. a -> MatchResult a
WholeMatch (EditorM RepeatToken -> MatchResult (EditorM RepeatToken))
-> EditorM RepeatToken -> MatchResult (EditorM RepeatToken)
forall a b. (a -> b) -> a -> b
$ do
              (VimState -> VimState) -> EditorM ()
modifyStateE ((VimState -> VimState) -> EditorM ())
-> (VimState -> VimState) -> EditorM ()
forall a b. (a -> b) -> a -> b
$ \VimState
s' -> VimState
s' { vsActiveRegister = c }
              RepeatToken -> EditorM RepeatToken
forall a. a -> EditorM a
forall (m :: * -> *) a. Monad m => a -> m a
return RepeatToken
Continue
          f String
_ VimState
_ = MatchResult (EditorM RepeatToken)
forall a. MatchResult a
NoMatch

indentBlockRegionB :: Int -> Region -> BufferM ()
indentBlockRegionB :: Int -> Region -> BufferM ()
indentBlockRegionB Int
count Region
reg = do
  indentSettings <- BufferM IndentSettings
indentSettingsB
  (start, lengths) <- shapeOfBlockRegionB reg
  moveTo start
  forM_ (zip [1..] lengths) $ \(Int
i, Int
_) -> do
      BufferM Bool -> BufferM () -> BufferM ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
whenM (Bool -> Bool
not (Bool -> Bool) -> BufferM Bool -> BufferM Bool
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> BufferM Bool
atEol) (BufferM () -> BufferM ()) -> BufferM () -> BufferM ()
forall a b. (a -> b) -> a -> b
$ do
        let w :: Int
w = IndentSettings -> Int
shiftWidth IndentSettings
indentSettings
        if Int
count Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
        then YiString -> BufferM ()
insertN (YiString -> BufferM ()) -> YiString -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Int -> Char -> YiString
R.replicateChar (Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
w) Char
' '
        else Int -> BufferM ()
forall {t}. (Eq t, Num t) => t -> BufferM ()
go (Int -> Int
forall a. Num a => a -> a
abs Int
count Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
w)
      Point -> BufferM ()
moveTo Point
start
      BufferM Int -> BufferM ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (BufferM Int -> BufferM ()) -> BufferM Int -> BufferM ()
forall a b. (a -> b) -> a -> b
$ Int -> BufferM Int
lineMoveRel Int
i
  moveTo start
  where
      go :: t -> BufferM ()
go t
0 = () -> BufferM ()
forall a. a -> BufferM a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
      go t
n = do
          c <- BufferM Char
readB
          when (c == ' ') $
              deleteN 1 >> go (n - 1)


pasteInclusiveB :: YiString -> RegionStyle -> BufferM ()
pasteInclusiveB :: YiString -> RegionStyle -> BufferM ()
pasteInclusiveB YiString
rope RegionStyle
style = do
  p0 <- BufferM Point
pointB
  insertRopeWithStyleB rope style
  if countNewLines rope == 0 && style `elem` [ Exclusive, Inclusive ]
    then leftB
    else moveTo p0

trailingNewline :: YiString -> Bool
trailingNewline :: YiString -> Bool
trailingNewline YiString
t = case YiString -> Maybe Char
Yi.Rope.last YiString
t of
  Just Char
'\n' -> Bool
True
  Maybe Char
_         -> Bool
False

addNewLineIfNecessary :: YiString -> YiString
addNewLineIfNecessary :: YiString -> YiString
addNewLineIfNecessary YiString
rope =
  if YiString -> Bool
trailingNewline YiString
rope then YiString
rope else YiString
rope YiString -> Char -> YiString
`R.snoc` Char
'\n'

pasteFromClipboard :: YiM ()
pasteFromClipboard :: YiM ()
pasteFromClipboard = do
  text <- (String -> YiString) -> YiM String -> YiM YiString
forall a b. (a -> b) -> YiM a -> YiM b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap String -> YiString
R.fromString (YiM String -> YiM YiString) -> YiM String -> YiM YiString
forall a b. (a -> b) -> a -> b
$ IO String -> YiM String
forall (m :: * -> *) a. MonadBase IO m => IO a -> m a
io IO String
getClipboard
  withCurrentBuffer $ insertRopeWithStyleB text Inclusive

exportRegisterToClipboard :: RegisterName -> YiM ()
exportRegisterToClipboard :: Char -> YiM ()
exportRegisterToClipboard Char
name = do
  mbr <- EditorM (Maybe Register) -> YiM (Maybe Register)
forall a. EditorM a -> YiM a
forall (m :: * -> *) a. MonadEditor m => EditorM a -> m a
withEditor (EditorM (Maybe Register) -> YiM (Maybe Register))
-> EditorM (Maybe Register) -> YiM (Maybe Register)
forall a b. (a -> b) -> a -> b
$ Char -> EditorM (Maybe Register)
getRegisterE Char
name
  io . setClipboard $ maybe "" (R.toString . regContent) mbr