1313module Yi.Mode.Buffers (listBuffers ) where
1414
1515import Control.Category ((>>>) )
16- import Control.Monad (forM_ , mapM_ , unless , when )
16+ import Control.Monad (forM_ , mapM_ , unless , when
17+ ,replicateM_ )
1718import Data.Functor (void )
18- import Lens.Micro.Platform ((.=) , (%~) , (.~) , to , use )
19+ import Lens.Micro.Platform ((.=) , (%~) , (.~) , (%=) , to , use )
1920import Data.List.NonEmpty (NonEmpty ( (:|) ))
20- import qualified Data.Text as T (intercalate , pack , append , Text )
21+ import qualified Data.Text as T (intercalate , pack , append , Text
22+ , justifyLeft )
2123import Yi.Buffer
2224import Yi.Editor
2325import Yi.Types ( FBuffer (attributes )
2426 , Attributes (readOnly ))
2527import Yi.Buffer.Misc (isUnchangedBuffer , replaceCharB
26- , gotoLnFrom )
28+ ,gotoLnFrom , rightB )
2729import Yi.Buffer.HighLevel (moveToSol , lineStreamB , topB )
2830import Yi.Buffer.Basic (Direction (.. ), BufferRef (.. ))
2931import Yi.Keymap (Keymap , YiM , topKeymapA )
@@ -52,7 +54,9 @@ listBuffers = do
5254 listBuffersName :: T. Text
5355 listBuffersName = " Buffer List"
5456
55- -- | Add Emacs-like properties to the list of buffers.
57+ -- | Add Emacs-like properties to the list of buffers. Currently the
58+ -- flags .%* means that . is the current buffer, % that is read only and *
59+ -- that has been modified.
5660bufferProperties :: NonEmpty BufferRef -> NonEmpty FBuffer -> [T. Text ]
5761bufferProperties (curRef :| extraRef) (curBuf :| extraBufs) =
5862 characterize ' .' curRef curBuf
@@ -63,40 +67,54 @@ bufferProperties (curRef :| extraRef) (curBuf :| extraBufs) =
6367 let roChar = if readOnly attr then ' %' else ' '
6468 modChar = if isUnchangedBuffer buf then ' ' else ' *'
6569 in T. pack [cur, roChar, modChar, ' ' ]
66- `T.append` threeSpaceRef ref `T.append` " "
70+ `T.append` fourSpaceRef ref `T.append` " "
6771 `T.append` identString buf
6872
69- threeSpaceRef :: BufferRef -> T. Text
70- threeSpaceRef (BufferRef i)
71- | i < 10 = ti `T.append` " "
72- | i >= 10 && i < 100 = ti `T.append` " "
73- | i >= 100 && i < 1000 = ti `T.append` " "
74- | i >= 1000 && i < 10000 = ti
75- | otherwise = error " Too many buffersRefs "
76- where
77- ti = T. pack ( show i)
73+ fourSpaceRef :: BufferRef -> T. Text
74+ fourSpaceRef (BufferRef i) = T. justifyLeft 4 ' ' ( T. pack ( show i) )
75+
76+
77+ -- | Auxiliar function to extract the `BufferRef` from the format used in
78+ -- this mode
79+ extractBufferRef :: String -> BufferRef
80+ extractBufferRef l = let ref' = read $ words ( drop 4 l) !! 0
81+ in BufferRef ref'
7882
7983-- | Switch to the buffer with name at current name. If it it starts
8084-- with a @/@ then assume it's a file and try to open it that way.
8185switch :: YiM ()
8286switch = do
83- s <- ( drop 4 . R. toString) <$> withCurrentBuffer readLnB
84- let ref = read $ ( words s) !! 0
85- withEditor $ switchToBufferE ( BufferRef ref)
87+ s <- R. toString <$> withCurrentBuffer readLnB
88+ let ref = extractBufferRef s
89+ withEditor $ switchToBufferE ref
8690
87- -- `setFlag ' '` is basically unsetting, so we make it general.
88- setFlag :: Char -> BufferM ()
89- setFlag c = do
91+ -- | `setFlag offset char move` puts on the current line at the given
92+ -- `offset` from the beginning the character `char` and depending on move
93+ -- whether we move down a line. This is a general template for all the
94+ -- setting moves on the list buffer.
95+ setFlag :: Int -> Char -> Bool -> BufferM ()
96+ setFlag n c move = do
9097 readOnlyA .= False
91- moveToSol >> replaceCharB c
98+ moveToSol >> replicateM_ n rightB >> replaceCharB c
9299 readOnlyA .= True
93100 isLast <- atLastLine
94- unless isLast (void (gotoLnFrom 1 ))
101+ unless ( isLast || not move) (void (gotoLnFrom 1 ))
95102
96103setDeleteFlag ,unsetDeleteFlag :: BufferM ()
97- setDeleteFlag = setFlag ' D'
98- unsetDeleteFlag = setFlag ' '
104+ setDeleteFlag = setFlag 0 ' D' True
105+ unsetDeleteFlag = setFlag 0 ' ' True
106+
107+ -- | Alternate the readonly status of a buffer on the list.
108+ flipROFlag :: EditorM ()
109+ flipROFlag = do
110+ s <- R. toString <$> withCurrentBuffer readLnB
111+ let ref = extractBufferRef s
112+ symbol = if s !! 1 == ' ' then ' %' else ' '
113+ withGivenBuffer ref (readOnlyA %= not )
114+ withCurrentBuffer (setFlag 1 symbol False )
99115
116+ -- | eXecute the flagged for deletion files on the list buffer. Then
117+ -- refresh the list.
100118executeDelete :: YiM ()
101119executeDelete = do
102120 bLines <- withCurrentBuffer (topB *> lineStreamB Forward )
@@ -117,18 +135,20 @@ executeDelete = do
117135-- __v__ → open buffer as read-only
118136-- __g__ → reload buffer list
119137-- __d__ → flag this file for deletion
120- -- __g__ → delete files flagged for deletion
138+ -- __x__ → delete files flagged for deletion
139+ -- __%__ → set/unset files as read-only
121140-- @
122141bufferKeymap :: Keymap -> Keymap
123142bufferKeymap = important $ choice
124143 [ char ' p' ?>>! lineUp
125144 , oneOf [ char ' n' , char ' ' ] >>! lineDown
126- , oneOf [ spec KEnter , char ' f' ] >>! ( switch >> setReadOnly False )
145+ , oneOf [ spec KEnter , char ' f' ] >>! switch
127146 , char ' v' ?>>! (switch >> setReadOnly True )
128147 , char ' g' ?>>! listBuffers
129148 , char ' d' ?>>! setDeleteFlag
130149 , char ' x' ?>>! executeDelete
131150 , char ' u' ?>>! unsetDeleteFlag
151+ , char ' %' ?>>! flipROFlag
132152 ]
133153 where
134154 setReadOnly = withCurrentBuffer . (.=) readOnlyA
0 commit comments