diff --git a/yi-misc-modes/src/Yi/Mode/Buffers.hs b/yi-misc-modes/src/Yi/Mode/Buffers.hs index 04050390a..5ad4d71ca 100644 --- a/yi-misc-modes/src/Yi/Mode/Buffers.hs +++ b/yi-misc-modes/src/Yi/Mode/Buffers.hs @@ -13,17 +13,19 @@ module Yi.Mode.Buffers (listBuffers) where import Control.Category ((>>>)) -import Control.Monad (forM_, mapM_, unless, when) +import Control.Monad (forM_, mapM_, unless, when + ,replicateM_) import Data.Functor (void) -import Lens.Micro.Platform ((.=), (%~), (.~), to, use) +import Lens.Micro.Platform ((.=), (%~), (.~), (%=), to, use) import Data.List.NonEmpty (NonEmpty( (:|) )) -import qualified Data.Text as T (intercalate, pack, append, Text) +import qualified Data.Text as T (intercalate, pack, append, Text + , justifyLeft) import Yi.Buffer import Yi.Editor import Yi.Types ( FBuffer(attributes) , Attributes(readOnly)) import Yi.Buffer.Misc (isUnchangedBuffer, replaceCharB - , gotoLnFrom ) + ,gotoLnFrom, rightB ) import Yi.Buffer.HighLevel (moveToSol, lineStreamB, topB) import Yi.Buffer.Basic (Direction(..), BufferRef(..)) import Yi.Keymap (Keymap, YiM, topKeymapA) @@ -52,7 +54,9 @@ listBuffers = do listBuffersName :: T.Text listBuffersName = "Buffer List" --- | Add Emacs-like properties to the list of buffers. +-- | Add Emacs-like properties to the list of buffers. Currently the +-- flags .%* means that . is the current buffer, % that is read only and * +-- that has been modified. bufferProperties :: NonEmpty BufferRef -> NonEmpty FBuffer -> [T.Text] bufferProperties (curRef :| extraRef) (curBuf :| extraBufs) = characterize '.' curRef curBuf @@ -63,40 +67,54 @@ bufferProperties (curRef :| extraRef) (curBuf :| extraBufs) = let roChar = if readOnly attr then '%' else ' ' modChar = if isUnchangedBuffer buf then ' ' else '*' in T.pack [cur, roChar, modChar, ' '] - `T.append` threeSpaceRef ref `T.append` " " + `T.append` fourSpaceRef ref `T.append` " " `T.append` identString buf - threeSpaceRef :: BufferRef -> T.Text - threeSpaceRef (BufferRef i) - | i < 10 = ti `T.append` " " - | i >= 10 && i < 100 = ti `T.append` " " - | i >= 100 && i < 1000 = ti `T.append` " " - | i >= 1000 && i < 10000 = ti - | otherwise = error "Too many buffersRefs" - where - ti = T.pack (show i) + fourSpaceRef :: BufferRef -> T.Text + fourSpaceRef (BufferRef i) = T.justifyLeft 4 ' ' (T.pack (show i)) + + +-- | Auxiliar function to extract the `BufferRef` from the format used in +-- this mode +extractBufferRef :: String -> BufferRef +extractBufferRef l = let ref' = read $ words (drop 4 l) !! 0 + in BufferRef ref' -- | Switch to the buffer with name at current name. If it it starts -- with a @/@ then assume it's a file and try to open it that way. switch :: YiM () switch = do - s <- (drop 4 . R.toString) <$> withCurrentBuffer readLnB - let ref = read $ (words s) !! 0 - withEditor $ switchToBufferE (BufferRef ref) + s <- R.toString <$> withCurrentBuffer readLnB + let ref = extractBufferRef s + withEditor $ switchToBufferE ref --- `setFlag ' '` is basically unsetting, so we make it general. -setFlag :: Char -> BufferM () -setFlag c = do +-- | `setFlag offset char move` puts on the current line at the given +-- `offset` from the beginning the character `char` and depending on move +-- whether we move down a line. This is a general template for all the +-- setting moves on the list buffer. +setFlag :: Int -> Char -> Bool -> BufferM () +setFlag n c move = do readOnlyA .= False - moveToSol >> replaceCharB c + moveToSol >> replicateM_ n rightB >> replaceCharB c readOnlyA .= True isLast <- atLastLine - unless isLast (void (gotoLnFrom 1)) + unless (isLast || not move) (void (gotoLnFrom 1)) setDeleteFlag,unsetDeleteFlag :: BufferM () -setDeleteFlag = setFlag 'D' -unsetDeleteFlag = setFlag ' ' +setDeleteFlag = setFlag 0 'D' True +unsetDeleteFlag = setFlag 0 ' ' True + +-- | Alternate the readonly status of a buffer on the list. +flipROFlag :: EditorM () +flipROFlag = do + s <- R.toString <$> withCurrentBuffer readLnB + let ref = extractBufferRef s + symbol = if s !! 1 == ' ' then '%' else ' ' + withGivenBuffer ref (readOnlyA %= not) + withCurrentBuffer (setFlag 1 symbol False) +-- | eXecute the flagged for deletion files on the list buffer. Then +-- refresh the list. executeDelete :: YiM () executeDelete = do bLines <- withCurrentBuffer (topB *> lineStreamB Forward) @@ -117,18 +135,20 @@ executeDelete = do -- __v__ → open buffer as read-only -- __g__ → reload buffer list -- __d__ → flag this file for deletion --- __g__ → delete files flagged for deletion +-- __x__ → delete files flagged for deletion +-- __%__ → set/unset files as read-only -- @ bufferKeymap :: Keymap -> Keymap bufferKeymap = important $ choice [ char 'p' ?>>! lineUp , oneOf [ char 'n', char ' ' ] >>! lineDown - , oneOf [ spec KEnter, char 'f' ] >>! (switch >> setReadOnly False) + , oneOf [ spec KEnter, char 'f' ] >>! switch , char 'v' ?>>! (switch >> setReadOnly True) , char 'g' ?>>! listBuffers , char 'd' ?>>! setDeleteFlag , char 'x' ?>>! executeDelete , char 'u' ?>>! unsetDeleteFlag + , char '%' ?>>! flipROFlag ] where setReadOnly = withCurrentBuffer . (.=) readOnlyA