boon/cheat-sheet.hs

243 lines
7.7 KiB
Haskell
Raw Normal View History

2016-11-15 21:35:36 +01:00
{-# LANGUAGE RankNTypes #-}
{-# OPTIONS_GHC -pgmF marxup -F #-}
{-# LANGUAGE TupleSections, RecordWildCards, RecursiveDo, OverloadedStrings #-}
module Main (main) where
2016-08-31 21:58:55 +02:00
2016-11-15 21:35:36 +01:00
import Data.Char (toUpper,chr)
2016-08-27 21:46:23 +02:00
import Prelude hiding (mapM,sequence,Num(..),(/))
2014-10-18 23:16:06 +02:00
import MarXup
import MarXup.Latex
2016-08-27 21:46:23 +02:00
import MarXup.Tex hiding (label)
import Graphics.Diagrams
2014-10-18 23:16:06 +02:00
import MarXup.Diagram
import Control.Lens (set)
import Data.Traversable
2016-11-15 21:35:36 +01:00
import Data.List (isSuffixOf,isPrefixOf)
2016-08-27 21:46:23 +02:00
import Algebra.Classes
2016-11-15 23:18:35 +01:00
import Layout
import System.Environment
2016-11-15 21:35:36 +01:00
2014-10-18 23:16:06 +02:00
preamble body = do
documentClass "article" ["10pt"]
usepackage "fontspec" []
cmd "setsansfont" (tex "DejaVu Sans")
2016-11-15 21:35:36 +01:00
-- cmd "setmainfont" (tex "DejaVu Serif")
2014-10-18 23:16:06 +02:00
usepackage "tikz" []
usepackage "graphicx" []
usepackage "amssymb" []
usepackage "varwidth" []
2014-10-24 21:04:58 +02:00
usepackage "geometry" ["margin=1cm","paper=a4paper","landscape"]
2014-10-18 23:16:06 +02:00
env "document" body
2016-09-01 22:36:00 +02:00
data CheatSheet = CS
2016-11-15 21:35:36 +01:00
{ leftHandK, rightHandK :: [[String]] -- keycap glyphs
2016-11-15 23:18:35 +01:00
, commandsInfo, selectorsInfo :: [(String, (TeX,Argument,TeX))]
2016-09-01 22:36:00 +02:00
}
2016-11-15 21:35:36 +01:00
commandArgument :: String -> Argument
commandArgument x | "region" `isSuffixOf` x = TextRegion
| "character" `isSuffixOf` x = Char
| "map" `isSuffixOf` x = Prefix
| "avy" `isPrefixOf` x = Char
commandArgument "boon-enclose" = Bin Enclosure TextRegion
commandArgument "selectContent" = TextRegion
commandArgument "" = Reserved
commandArgument _ = None
upKey :: Char -> Char
upKey c = case [c] of
2014-10-18 23:16:06 +02:00
"'" -> head "\""
2016-09-01 22:36:00 +02:00
";" -> ':'
2014-10-18 23:16:06 +02:00
"," -> '<'
"." -> '>'
"/" -> '?'
_ -> toUpper c
data Argument = Bin Argument Argument | None | Char | SearchObject | TextRegion | Prefix | Enclosure | Reserved
argColor :: Argument -> String
argColor a = case a of
None -> "gray"
Char -> "red"
SearchObject -> "orange"
Prefix -> "yellow"
2019-08-25 22:05:02 +02:00
TextRegion -> "cyan"
2014-10-18 23:16:06 +02:00
Bin _ _ -> "purple"
_ -> "white"
2016-11-15 21:35:36 +01:00
varwidth :: forall a. String -> Tex a -> Tex a
2014-10-18 23:16:06 +02:00
varwidth x body = env "varwidth" ((braces $ tex x) >> cmd0 "centering" >> body)
keySize :: Constant
keySize = 65
2016-11-15 21:35:36 +01:00
massageInfo :: (Integer, (String,String)) -> (String, (TeX,Argument,TeX))
massageInfo (c,(mnemonic,command)) = ([chr (fromIntegral c)],(cmdTex,arg,textual mnemonic))
where (cmdTex,arg) | command == "nil" = (italic "reserved",Reserved)
| otherwise = (textual (shortenCommand command),commandArgument command)
shortenCommand :: String -> String
shortenCommand c | "boon-" `isPrefixOf` c = shortenCommand (drop 5 c)
shortenCommand c | "-map" `isSuffixOf` c = shortenCommand (dropR 4 c)
shortenCommand c = c
dropR :: forall a. Int -> [a] -> [a]
dropR n = reverse . drop n . reverse
keyHalf :: [(String, (TeX, Argument, TeX))]
-> String -> TexDiagram Object
2019-08-25 22:37:45 +02:00
keyHalf kmInfo k = do
let (act,arg,mnem) = case lookup k kmInfo of
Nothing -> (mempty,Reserved,mempty)
Just (act,arg,mnem) -> (act,arg,mnem)
up <- using (fill (argColor arg)) $ draw $ box "keyHalf"
upK <- label "k" $ textSize Huge $ sans $ textual $ k
upT <- label "scr" $ varwidth "45pt" $ sans $ textSize ScriptSize $ act
m <- (label "mnem" $ sans $ textSize Tiny $ mnem)
m # SW .=. up # SW
up # E .=. upT # E
up # W .=. upK # W
width up === constant keySize
height up === constant (keySize / 2)
return up
2016-11-15 21:35:36 +01:00
keyDiagram :: [(String, (TeX, Argument, TeX))] -> String -> Diagram TeX Tex Object
keyDiagram kmInfo k = do
2016-08-27 21:46:23 +02:00
b <- using (set lineWidth thick) $ draw $ box "keyB"
2016-11-15 21:35:36 +01:00
up <- keyHalf kmInfo (map upKey k)
down <- keyHalf kmInfo k
2014-10-18 23:16:06 +02:00
up # S .=. down # N
b # NW .=. up # NW
b # NE .=. up # NE
b # SE .=. down # SE
return b
2016-08-27 21:46:23 +02:00
keyFull :: Constant -> String -> TeX -> Argument -> TexDiagram Object
2014-10-18 23:16:06 +02:00
keyFull w k act arg = do
2016-08-27 21:46:23 +02:00
b <- using (set lineWidth thick . fill (argColor arg)) $ draw $ box "kf"
2014-10-18 23:16:06 +02:00
width b === constant w
height b === constant keySize
2016-08-27 21:46:23 +02:00
k' <- label "huge" $ textSize Huge $ textual $ k
act' <- label "scr2" $ varwidth "55pt" $ sans $ textSize ScriptSize $ act
2014-10-18 23:16:06 +02:00
k' # NW .=. b # NW
act' # S .=. b # S
return b
keyDist :: Constant
keyDist = 5
2016-11-15 21:35:36 +01:00
argDescs :: [(Argument, TeX)]
2014-10-24 21:04:58 +02:00
argDescs =
[(Bin Enclosure TextRegion, "First an enclosure, then a region")
,(None,"No Argument")
,(Char,"A character")
,(SearchObject,"A search space")
,(TextRegion,"A region")
,(Prefix,"(Prefix map)")
2014-10-24 22:40:05 +02:00
-- ,(Enclosure,"An enclosure")
2014-10-24 21:04:58 +02:00
,(Reserved,"(Reserved key)")]
2016-08-27 21:46:23 +02:00
legend :: TexDiagram ()
2014-10-24 21:04:58 +02:00
legend = do
2016-08-27 21:46:23 +02:00
txt <- label "legleg" (textSize Tiny $ "Color corresponds to the type of expected argument:")
2014-10-24 21:04:58 +02:00
ds <- forM argDescs $
\ (arg,desc) -> do
2016-08-27 21:46:23 +02:00
b <- using (set lineWidth thick . fill (argColor arg)) $ draw $ box "legend"
2014-10-24 21:04:58 +02:00
width b === constant 15
height b === constant 15
2016-08-27 21:46:23 +02:00
l <- label "desc" desc
2014-10-24 21:04:58 +02:00
b # E .=. l # W
return b
2016-08-27 21:46:23 +02:00
let ds' = ds++[txt]
align xpart (map (# W) ds')
spread vdist (constant 5) ds'
2014-10-24 21:04:58 +02:00
2016-08-27 21:46:23 +02:00
matrixDiag :: [[TexDiagram Object]] -> TexDiagram [[Object]]
2014-10-18 23:16:06 +02:00
matrixDiag matrix = do
keys <- mapM sequence $ reverse $ matrix
spread hdist (constant keyDist) $ (keys !! 1)
spread vdist (constant keyDist) $ map head keys
alignMatrix $ map (map (# Center)) keys
return $ reverse keys
2016-11-15 21:35:36 +01:00
keyBDiag :: CheatSheet -> TexDiagram ()
2016-09-01 22:36:00 +02:00
keyBDiag CS {..} = do
2016-11-15 23:18:35 +01:00
keys <- matrixDiag (map (map (keyDiagram commandsInfo)) (leftHandK +++ rightHandK))
2014-10-18 23:16:06 +02:00
esc <- keyFull keySize "esc" "back to normal mode" None
2016-08-27 21:46:23 +02:00
esc # SW .=. (keys !! 0 !! 0) # NW + (Point zero (constant keyDist))
2014-10-18 23:16:06 +02:00
bar <- keyFull (keySize * 6 + keyDist * 5) "space" "select region" TextRegion
2016-08-27 21:46:23 +02:00
keys !! 2 !! 2 # SW .=. bar # NW + (Point zero (constant keyDist))
2014-10-18 23:16:06 +02:00
return ()
2016-11-15 21:35:36 +01:00
regDiag :: CheatSheet -> TexDiagram ()
2016-09-01 22:36:00 +02:00
regDiag CS {..} = do
2016-08-27 21:46:23 +02:00
txt <- label "lhtrs" "Left-hand text region specifiers:"
2016-11-15 23:18:35 +01:00
keys <- matrixDiag (map (map (keyHalf selectorsInfo)) leftHandK)
2016-08-27 21:46:23 +02:00
spread vdist (constant 7) [keys!!0!!0,txt]
2014-10-18 23:16:06 +02:00
return ()
2016-11-15 21:35:36 +01:00
2014-10-18 23:16:06 +02:00
(+++) :: [[a]] -> [[a]] -> [[a]]
x +++ y = zipWith (++) x y
2016-11-15 21:35:36 +01:00
main :: IO ()
2016-09-01 22:36:00 +02:00
main = do
2016-11-15 23:18:35 +01:00
[flavor] <- getArgs
let cs = CS {leftHandK = [], rightHandK = []
,commandsInfo = ("",(mempty,Reserved,mempty)):
map massageInfo (Layout.commandMap ++ Layout.movesMap)
,selectorsInfo = map massageInfo Layout.selectMap
}
let cs' = case flavor of
"colemak" -> cs {
leftHandK = [["q","w","f","p","g"]
,["a","r","s","t","d"]
,["z","x","c","v","b"]]
,rightHandK = [["j","l","u","y",";",""]
,["h","n","e","i","o","'"]
,["k","m",",",".","/",""]]}
"qwerty" -> cs
{leftHandK = [["q","w","e","r","t"]
,["a","s","d","f","g"]
,["z","x","c","v","b"]]
,rightHandK = [["y","u","i","o","p",""]
,["h","j","k","l",";","'"]
,["n","m",",",".","/",""]]}
2019-08-25 22:37:45 +02:00
"qwertz" -> cs
{leftHandK = [["q","w","e","r","t"]
,["a","s","d","f","g"]
,["y","x","c","v","b"]]
,rightHandK = [["z","u","i","o","p",""]
,["h","j","k","l","ö","ä"]
,["n","m",";",":","-",""]]}
"workman" -> cs
{leftHandK = [["q","d","r","w","b"]
,["a","s","h","t","g"]
,["z","x","m","c","v"]]
,rightHandK = [["j","f","u","p","k",";"]
,["y","n","e","o","i","'"]
,["k","l",",",".","/",""]]}
2016-11-15 23:18:35 +01:00
renderTex Plain flavor (docu cs')
2014-10-18 23:16:06 +02:00
2016-09-01 22:36:00 +02:00
docu :: CheatSheet -> TeX
docu csData = preamble «
2014-10-30 22:22:34 +01:00
BOON cheat sheet. It is recommended to read the TUTORIAL to make sense of this. The color of a key indicates the type of argument it expects.
2014-10-18 23:16:06 +02:00
2014-10-30 22:22:34 +01:00
Command mode bindings.
2016-09-01 22:36:00 +02:00
@keyBDiag(csData)
2014-10-18 23:16:06 +02:00
2014-10-24 22:40:05 +02:00
@vspace"1em"
2016-08-27 21:46:23 +02:00
2016-09-01 22:36:00 +02:00
@regDiag(csData)
2016-08-27 21:46:23 +02:00
@hfill
@legend
2014-10-18 23:16:06 +02:00
»