hspresent 0.1 → 0.2
raw patch · 3 files changed
+105/−33 lines, 3 filesdep +array
Dependencies added: array
Files
- Main.hs +78/−26
- README.md +9/−1
- hspresent.cabal +18/−6
Main.hs view
@@ -1,10 +1,30 @@ import System.Environment import System.Exit import System.IO+import Data.Array.IArray import Data.ByteString.Char8 (pack) import Graphics.Vty +-- pad left fills the left side with pad chars, pad right fills the right side+-- with pad chars+data Pad = Pad { padLeft :: String -> String+ , padRight :: String -> String }++type Frame = [String]++-- an immutable array of frames, one-indexed+type Presentation = Array Int Frame++newPad :: Char -> Int -> Pad+newPad c w = Pad { padLeft = padl+ , padRight = padr }+ where+ pad' t = replicate (w - length t) c+ shorten = take w+ padl t = pad' t ++ shorten t+ padr t = shorten t ++ pad' t+ -- |Split an input list split :: Eq a => [a] -> [[a]] -> [[[a]]] split _ [] = [[]]@@ -12,48 +32,80 @@ | tok == x = [] : split tok xs | otherwise = let (x':xs') = split tok xs in (x:x') : xs' --- |Render a string as an Image, and right pad it with some character.-bsLine :: String -> Char -> Int -> Image-bsLine txt fill width = renderBS attr $ pack txt'+-- |Convert a string to an image+toImage :: String -> Image+toImage = renderBS attr . pack++-- |Render a frame. The first pair of Ints is the tuple (screen width, screen+-- height), the second pair of Ints is the two numbers to display in the lower+-- right corner, likely the tuple (slide num, total slides).+renderFrame :: Frame -> (Int, Int) -> (Int, Int) -> Image+renderFrame (title:body) (w, h) (num, tot) = vertcat $ map toImage text where- txt' = ' ' : txt ++ (replicate (width - length txt - 2) fill)+ p = newPad ' ' w+ t = padRight p (' ' : title)+ sep = replicate w '-'+ body' = take (min (h - 3) (length body)) body -- maybe shorten body+ bodyLines = [padRight p (' ':b) | b <- body']+ vsep = [padRight p "" | _ <- [1 .. h - length body - 3]]+ foot = padLeft p (show num ++ " / " ++ show tot)+ text = foldl (++) [] [[t, sep], bodyLines, vsep, [foot]] + -- |Take a Vty and a list of frames, and do the presentation; this function -- terminates when q or Ctrl-C are entered.-loop :: Vty -> [[String]] -> IO ()-loop vty frames = loop' 0+loop :: Vty -> Presentation -> IO ()+loop vty pres = loop' minFrame where- maxframe = length frames - 1- formatText w [] = empty- formatText w (x:xs) = (bsLine x ' ' w) <-> (formatText w xs)+ (minFrame, maxFrame) = bounds pres loop' n = do- let (title:text) = frames !! n- (w, h) <- getSize vty- let im = bsLine title ' ' w <->- bsLine "" '-' w <->- formatText w text- update vty (pic { pCursor = NoCursor,- pImage = im })- ev <- getEvent vty- case ev of- EvKey KLeft _ -> loop' (max 0 (n-1))- EvKey KRight _ -> loop' (min maxframe (n+1))- EvKey (KASCII 'q') _ -> return ()- EvKey (KASCII 'c') [MCtrl] -> return ()- _ -> loop' n+ let frame = pres ! n+ dims <- getSize vty+ blankVty vty+ update vty $ pic { pCursor = NoCursor,+ pImage = renderFrame frame dims (n, maxFrame) }+ eventLoop+ where+ eventLoop = do ev <- getEvent vty+ case ev of+ EvKey KLeft _ -> loop' (max minFrame (n-1))+ EvKey KRight _ -> loop' (min maxFrame (n+1))+ EvKey KHome _ -> loop' minFrame+ EvKey KEnd _ -> loop' maxFrame+ EvKey (KASCII 'q') _ -> return ()+ EvKey (KASCII 'c') [MCtrl] -> return ()+ EvKey (KASCII 'r') _ -> blankVty vty >> loop' n+ _ -> eventLoop +-- |Sometimes the vty module gets confused and leaves artifacts from previous+-- slides on the screen. Calling blankvty a few times seems to fix this.+blankVty :: Vty -> IO ()+blankVty vty = do+ (w, h) <- getSize vty+ let lines = [replicate w ' ' | _ <- [1..h]]+ update vty $ pic { pCursor = NoCursor+ , pImage = vertcat $ map toImage lines}+ refresh vty++-- |Parse an input file, representing a presentation, into a presentation+makeFrames :: String -> Presentation+makeFrames xs = listArray (1, length frames) frames+ where+ frames = concatMap copyFrames $ basicSplit xs+ basicSplit = split "--" . lines+ copyFrames = cf [] . split "."+ cf _ [] = []+ cf h (x:xs) = let p = h ++ x in p : cf (p ++ [[]]) xs+ main = do args <- getArgs presentation <- parse args h <- openFile presentation ReadMode frames <- fmap makeFrames $ hGetContents h vty <- mkVty- refresh vty loop vty frames shutdown vty where- makeFrames s = split "--" $ lines s- parse ["-h"] = usage parse [x] = return x parse _ = usage
README.md view
@@ -10,15 +10,23 @@ This will compile hspresent, and install an `hspresent` command line program. +You can download the latest stable release of hspresent on+[Hackage](http://hackage.haskell.org/package/hspresent). The git repository is+online at `git://github.com/eklitzke/hspresent.git`.+ Usage ----- Invoke like `hspresent /path/to/your/presentation`. Left and right arrow keys move between slides, and hitting `q` or `Ctrl-C` quits the presentation. The file format is really simple right now. Slides are separated by lines-consisting of the characters `--`. That's it. Here's an example presentation:+consisting of the characters `--`. You can put the single character `.` on a+line to demarcate a "split" frame. A split frame really creates a new frame with+the contents of the previous frame copied at the front (this is similar to how+beamer works). That's it. Here's an example presentation: the title of the first slide this is+ . really cool -- the title of the second slide
hspresent.cabal view
@@ -1,7 +1,7 @@ Author: Evan Klitzke Maintainer: Evan Klitzke <evan@eklitzke.org> Name: hspresent-Version: 0.1+Version: 0.2 Cabal-Version: >= 1.2 License: BSD3 License-File: LICENSE@@ -9,14 +9,26 @@ Copyright: (c) 2009 by Evan Klitzke Synopsis: A terminal presentation tool Description:- Give fancy presentations in your terminal.- + Hspresent is a simple program that lets you give powerpoint-like presentations+ in your terminal (for certain definitions of powerpoint-like). It's extremely+ basic and unintelligent. Don't expect much.+ .+ Invoke like `hspresent /path/to/your/presentation`. Left and right arrow keys+ move between slides, and hitting `q` or `Ctrl-C` quits the presentation.+ .+ The file format is really simple right now. Slides are separated by lines+ consisting of the characters `--`. You can put the single character `.` on a+ line to demarcate a split frame. A split frame really creates a new frame with+ the contents of the previous frame copied at the front (this is similar to how+ beamer works).+ Build-Type: Simple Executable hspresent Main-Is: Main.hs Library- Build-Depends: base < 5- , bytestring- , vty+ Build-Depends: array+ , base < 5+ , bytestring+ , vty