packages feed

yi-0.3: Yi/Keymap/JP.hs

{-# LANGUAGE FlexibleContexts #-}
module Yi.Keymap.Normal where

import Control.Monad.State
import Data.Char
import Yi.Keymap.Emacs.Utils (insertSelf)
import Yi.Yi
import qualified Yi.Interact as I (choice, I())

leftHand, rightHand :: [String]
leftHand = ["qwert", "asdfg", "zxcvb"]
rightHand = ["yuiop", "hjkl;", "nm,./"]

{-

qqq www eee rrr ttt yyy uuu iii ooo ppp
 aaa sss ddd fff ggg hhh jjj kkk lll ;;;
  zzz xxx ccc vvv bbb nnn mmm ,,, ... ///

-}

type Process a = (StateT TextUnit (I.I Event Action)) a


-- data Mark = Paste | SetMark | Cut | Copy | SwitchMark
-- data Special = Complete | Undo | Indent | Search

{-
data Action = TextA Direction Unit Operation
            | YiA (YiM ())
            | EditorA
-}

selfInsertKeymap :: Process ()
selfInsertKeymap = do
  Event (KASCII c) [] <- satisfy isPrintableEvent
  write (insertSelf c)
      where isPrintableEvent (Event (KASCII c) []) = c >= ' '
            isPrintableEvent _ = False

retKeymap :: Process ()
retKeymap = do
  Event KEnter [] <- anyEvent
  write (insertSelf '\n')

insertKeymap :: StateT TextUnit (I Event Action) ()
insertKeymap = do
  keyEv 'g'
  many (selfInsertKeymap <|> retKeymap <|> quickCmdKeymap)
  Event KEnter [MCtrl] <- anyEvent
  return ()

quickCmdKeymap :: (MonadInteract m Action Event) => m ()
quickCmdKeymap = I.choice $ concat $ zipWith (zipWith mkCmd) commands rightHand
    where mkCmd cmd ch = do
            Event (KASCII c) [MCtrl] <- anyEvent
            when (c /= ch) $ fail $ "expected " ++ [ch]
            write (cmd Character)

quitKeymap :: Process ()
quitKeymap = do
  keyEv 'q'
  write quitEditor

unrecognized :: Process ()
unrecognized = do
  e <- anyEvent
  write (msgEditor $ "unrecognized: " ++ show e)

commandsKeymap :: Process ()
commandsKeymap = quitKeymap <|| (I.choice $ insertKeymap : (concat $ (cmds ++ unts))) <|| unrecognized
    where
      cmds :: [[Process ()]]
      cmds = zipWith (zipWith mkCmd) commands rightHand
      unts = zipWith (zipWith mkUnt) units leftHand
      mkCmd :: (TextUnit -> BufferM ()) -> Char -> Process ()
      mkCmd cmd ch = do
            keyEv ch
            currentUnit <- get
            write (cmd currentUnit)
      mkUnt unt ch = do
        keyEv ch
        put unt

keyEv :: (MonadInteract m w Event) => Char -> m Event
keyEv c = satisfy (== Event (KASCII c) [])

keymap :: Keymap
keymap = runProcess $ (many commandsKeymap >> return ())


{-
Commands: (right hand)


                cop  cut del del com
                 pop  pas mov mov sea '''
                  mpp  mxp xpo xpo und

com: complete
und: undo
sea: start incremental search of the Unit at point
pop: pop-yank
pas: paste
xpo: transpose in given direction
''': search start from empty
mxp: exchange point and mark
mpp: mark pop
cop: copy

-}

commands :: [[TextUnit -> BufferM ()]]
commands = [[copy, cut,   del  b, del f,  complete],
            [pop,  paste, move b, move f, search],
            [mpp,  mxp,   xpo  b, xpo  f, undo]]
    where copy = todo
          cut = todo
          pop = todo
          mpp = todo
          mxp = todo
          complete = todo
          paste = todo
          search = todo
          undo = const undoB
          move dir u = execB Move u dir
          del dir u = deleteB u dir
          xpo dir u = execB Transpose u dir
          b = Backward
          f = Forward
          todo = \_ -> return ()


{-
Units: (left hand)


doc pag col ver   ovr
 par lin wor cha   ins
  *** *** *** sea   buf
-}

document, page, column :: TextUnit
document = Character
page = Character
column = Character

units :: [[TextUnit]]
units = [
         [document, page, column, VLine],
         [Paragraph, Line, Word, Character]
        ]

runProcess :: Process () -> Keymap
runProcess p = fmap fst $ runStateT p Character

{-
ins: go to insert mode
ovr: go to overwrite mode
sea: navigate searched items.


... free
*** reserved for normal emacs usage.

----------


C-: briefly switch to character mode
M-: briefly switch to word mode

C-mode: go to that mode

-}