-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA512 On Wed, Nov 26, 2008 at 5:03 PM, Gwern Branwen wrote: > setBufferContents doesn't seem to exist. At least, recursive grep > can't find anything but setBuffer.
OK, so I found two ways to do this: > setBufferContents :: (MonadEditor m) => String -> m BufferRef > setBufferContents article = withEditor $ stringToNewBuffer "Ireader article" > (B.fromString article) And there seems to be a function almost identical to stringToNewBuffer, in Buffer/Misc.hs, 'newB :: BufferRef -> String -> LB.ByteString -> FBuffer'. I assume the important thing there is it doesn't return a BufferRef. So, setting a buffer is solved. But reading the buffer isn't. Trying to figure out 'newB' lead me to look at the definition of FBuffer, which has the line: > , rawbuf :: !(BufferImpl syntax) BufferImpl, in Yi/Buffer/Implementation.hs, has the line: > FBufferData { mem :: !ByteRope -- ^ buffer text So, if I had a 'getCurrentBuffer :: FBuffer', then presumably I could then do 'contents :: ByteRope; contents = mem (getBuffer)', and then finally convert the ByteRope to String with a 'Data.ByteRope.toString'. As it happens, i can't do getCurrentBuffer, it seems. The only possibilities seem to involve an 'Editor' in the type signature, which doesn't seem to be accessible in a YiM. But there is a 'getBufferWithName :: String -> EditorM BufferRef', and I can make the assumption that my ireader buffer has a fixed name. So now I have my BufferRef. Great. Once we have a BufferRef, we need to follow that BufferRef to the FBuffer it is actually referencing. We do a search - 'grep -R BufferRef|grep FBuffer', and we turn up: Buffer/Misc.hs:keyB :: FBuffer -> BufferRef Buffer/Misc.hs:newB :: BufferRef -> String -> LB.ByteString -> FBuffer Editor.hs: ,buffers :: !(M.Map BufferRef FBuffer) Editor.hs:buffersA :: Accessor Editor (M.Map BufferRef FBuffer) Editor.hs:insertBuffer :: FBuffer -> EditorM BufferRef Editor.hs:findBuffer :: BufferRef -> EditorM (Maybe FBuffer) Editor.hs:findBufferWith :: BufferRef -> Editor -> FBuffer keyB is the wrong direction (we already have the BufferRef); newB is likewise useless; buffers is a false hit; I've no idea what buffersA does. insertBuffer is interesting, but not what we're looking for. findBufferWith has a need for Editor, which isn't accessible. So we go with findBuffer. A little type-checking later, and we wind up with: > *Main> :T join $ liftM findBuffer $ getBufferWithName "Ireader article" > join $ liftM findBuffer $ getBufferWithName "Ireader article" :: EditorM > (Maybe FBuffer) So: > getFbuffer :: EditorM FBuffer > getFbuffer = liftM fromJust $ $ join $ liftM findBuffer $ getBufferWithName > "Ireader article" Now to apply 'mem' and get my ByteRope.... Oops. mem is defined in Buffer/Implementation.hs. And Implementation.hs is not public, and Buffer.hs does not export FBufferData nor any queries on it. So we can't use it. But I've been at this a while, and the only viable alternative looks to be some hideous hack involving the Region operators (which do get access to stuff in Implementation) - it'd probably involve creating a region covering the entire buffer, and then I could call 'readRegionB :: Region -> BufferM String'. So instead I'm just going to edit the cabal and make Yi.Buffer.Implementation - and also Data.ByteRope, for that matter - public and reinstall. One compile later, I realize that not only is Implementation not public, the BufferImpl export is hiding all the accessors. An edit and another compile later... But of course, FBuffer isn't actually a FBufferData. That would be too easy. So, we track FBuffer down to Buffer/Misc.hs, and see: > , rawbuf :: !(BufferImpl syntax) There are no helpful comments here, but we already know BufferImpl is where all the good stuff is, so we just toss in a rawbuf into our getFbuffer definition... Oh no! *Main Data.Maybe Yi.Buffer.Misc> :T liftM (rawbuf . fromJust) $ join $ liftM (findBuffer) $ getBufferWithName "Ireader article" :1:7: Cannot use record selector `rawbuf' as a function due to escaped type variables Probable fix: use pattern-matching syntax instead In the first argument of `(.)', namely `rawbuf' In the first argument of `liftM', namely `(rawbuf . fromJust)' In the first argument of `($)', namely `liftM (rawbuf . fromJust)' What the heck is all that? Dunno. I mean, presumably a pattern-matching version would look like this: > bar (FBuffer {rawbuf = a}) = a No, that doesn't work either. Let's do one more stab - we can pattern-match in case expressions too: > bar a = case a of > FBuffer { rawbuf = x } -> x No dice. /home/gwern/.yi/yi.hs:101:9: Inferred type is less polymorphic than expected Quantified type variable `syntax' escapes When checking an existential match that binds x :: BufferImpl syntax The pattern(s) have type(s): FBuffer The body has type: BufferImpl syntax In a case alternative: FBuffer {rawbuf = x} -> x In the expression: case a of { FBuffer {rawbuf = x} -> x } At around here, I give up and go to #haskell, where povman tells me that my initial attempt is wrong - I can't return just x. Rather some existential thing-a-ma-bobies mean that I have to immediately do something with that x, so the right definition is > bar a = case a of > FBuffer { rawbuf = x } -> toString $ mem x But... there's always a catch. This actually returns a [Word8]. So we chuck in a 'show' call. Let's give them more pleasant names: > getBufferRef :: EditorM FBuffer > getBufferRef = liftM fromJust $ join $ liftM findBuffer $ getBufferWithName > "Ireader article" > getBufferContents :: FBuffer -> String > getBufferContents a = case a of > FBuffer { rawbuf = x } -> show $ toString $ mem x > getBuffer :: EditorM String > getBuffer = liftM getBufferContents getBufferRef So presumably our actual invocation would be 'newarticle saveAndNewArticle :: YiM () > saveAndNewArticle = do olddb let newarticle = liftM > getBufferContents getBufferRef > let newdb = liftM (updateSetLast olddb) newarticle > liftM writeDB newdb > let nextarticle = liftM getLatestArticle newdb > liftM setBufferContents nextarticle > return () But this is rife with all sorts of strange monad issues that are driving me crazy and I just can't get past them. I've spent something like 5 or 6 hours today going through Yi and trying stuff again and again and it has driven me nuts and it has left me with chattering teeth and bloody scalp. We really need to make this stuff easier. I vote that we start by adding some basic primitives like a getCurrentBuffer :: YiM String... - -- gwern -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEAREKAAYFAkkuBEkACgkQvpDo5Pfl1oJ+kwCeIak9tOc/TDqLlk8z+5lYjcqY zzgAoJAMCm7a4soMiScZA/Ut7VQOJ3ha =aLKm -----END PGP SIGNATURE----- --~--~---------~--~----~------------~-------~--~----~ Yi development mailing list yi-devel@googlegroups.com http://groups.google.com/group/yi-devel -~----------~----~----~----~------~----~------~--~---