Andrew Birkett's nobugs.org
Let’s make yi do k3wl stuff!
The emacs ‘comment-region’ function prepends each line the region with a comment character, such as ‘#’ for perl. Let’s recreate a simple commentRegion function in yi. Edit your ~/.yi/YiConfig.hs file by adding the following code:
commentRegionB :: BufferM () commentRegionB = do mark <- getSelectionMarkPointB p <- pointB let region = mkRegion mark p text <- readRegionB region let newText = unlines $ map ("# " ++ ) $ lines text replaceRegionB region newText
Also, remember to add it to the export list on the first line of the file, and then run M-x reconfigE. Now you can select a region (ctrl-space to set mark) and then do M-x commentRegionB.
The getSelectionMarkPointB and pointB function have type “BufferM Int”. In other words, they (potentially) modify a buffers state and yield an integer. Next, readRegionB has type “BufferM String” so it yields a string. We munge the string with some non-monadic haskell, and use replaceRegionB to update the buffer.
What did this function achieve? We’ve plumbed together various buffer-updating monads and standard haskell functions to create a compound BufferM action which, when executed, will modify the current buffer’s state to comment out the region.
So there was a caveat there: “when executed”. Who actually ‘runs’ this recipe? We’ll worry about that some other time. For now, it’s enough to know that you can ‘run’ these from within Yi by calling them via “M-x whatever”.
Before we move on, let’s refactor the code a bit to separate out useful functions.
currentRegionB :: BufferM Region currentRegionB = do mark <- getSelectionMarkPointB p <- pointB return $ mkRegion mark p mapCurrentRegionB :: (String -> String) -> BufferM () mapCurrentRegionB f = do region <- currentRegionB readRegionB region >>= replaceRegionB region . f commentRegionB :: BufferM () commentRegionB = do mapCurrentRegionB (unlines . map ("# " ++) . lines)
Now let’s move on to a slightly more complex example which involves the IO monad.