patat 0.11.0.0 → 0.12.0.0
raw patch · 10 files changed
+256/−48 lines, 10 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- Patat.Presentation.Internal: [evalWrap] :: EvalSettings -> !EvalSettingsWrap
- Patat.Presentation.Settings: EvalWrapCode :: EvalSettingsWrap
- Patat.Presentation.Settings: EvalWrapRaw :: EvalSettingsWrap
- Patat.Presentation.Settings: EvalWrapRawInline :: EvalSettingsWrap
- Patat.Presentation.Settings: [evalWrap] :: EvalSettings -> !EvalSettingsWrap
- Patat.Presentation.Settings: data EvalSettingsWrap
- Patat.Presentation.Settings: instance Data.Aeson.Types.FromJSON.FromJSON Patat.Presentation.Settings.EvalSettingsWrap
- Patat.Presentation.Settings: instance GHC.Show.Show Patat.Presentation.Settings.EvalSettingsWrap
+ Patat.Presentation: [psTabStop] :: PresentationSettings -> !Maybe (FlexibleNum Int)
+ Patat.Presentation.Display.Internal: [dsTabStop] :: DisplaySettings -> !Int
+ Patat.Presentation.Internal: [evalContainer] :: EvalSettings -> !EvalSettingsContainer
+ Patat.Presentation.Internal: [psTabStop] :: PresentationSettings -> !Maybe (FlexibleNum Int)
+ Patat.Presentation.Settings: EvalContainerCode :: EvalSettingsContainer
+ Patat.Presentation.Settings: EvalContainerInline :: EvalSettingsContainer
+ Patat.Presentation.Settings: EvalContainerNone :: EvalSettingsContainer
+ Patat.Presentation.Settings: [evalContainer] :: EvalSettings -> !EvalSettingsContainer
+ Patat.Presentation.Settings: [psTabStop] :: PresentationSettings -> !Maybe (FlexibleNum Int)
+ Patat.Presentation.Settings: data EvalSettingsContainer
+ Patat.Presentation.Settings: instance Data.Aeson.Types.FromJSON.FromJSON Patat.Presentation.Settings.EvalSettingsContainer
+ Patat.Presentation.Settings: instance GHC.Show.Show Patat.Presentation.Settings.EvalSettingsContainer
+ Patat.Transition.Matrix: instance Data.Aeson.Types.FromJSON.FromJSON Patat.Transition.Matrix.Config
+ Patat.Transition.Matrix: transition :: Config -> TransitionGen
- Patat.Presentation: PresentationSettings :: !Maybe (FlexibleNum Int) -> !Maybe (FlexibleNum Int) -> !Maybe MarginSettings -> !Maybe Wrap -> !Maybe Theme -> !Maybe Bool -> !Maybe (FlexibleNum Int) -> !Maybe Int -> !Maybe ExtensionList -> !Maybe ImageSettings -> !Maybe Bool -> !Maybe EvalSettingsMap -> !Maybe Bool -> !Maybe [FilePath] -> !Maybe SpeakerNotesSettings -> !Maybe TransitionSettings -> PresentationSettings
+ Patat.Presentation: PresentationSettings :: !Maybe (FlexibleNum Int) -> !Maybe (FlexibleNum Int) -> !Maybe MarginSettings -> !Maybe Wrap -> !Maybe (FlexibleNum Int) -> !Maybe Theme -> !Maybe Bool -> !Maybe (FlexibleNum Int) -> !Maybe Int -> !Maybe ExtensionList -> !Maybe ImageSettings -> !Maybe Bool -> !Maybe EvalSettingsMap -> !Maybe Bool -> !Maybe [FilePath] -> !Maybe SpeakerNotesSettings -> !Maybe TransitionSettings -> PresentationSettings
- Patat.Presentation.Display.Internal: DisplaySettings :: !Size -> !Wrap -> !Margins -> !Theme -> !SyntaxMap -> DisplaySettings
+ Patat.Presentation.Display.Internal: DisplaySettings :: !Size -> !Wrap -> !Int -> !Margins -> !Theme -> !SyntaxMap -> DisplaySettings
- Patat.Presentation.Internal: EvalSettings :: !Text -> !Bool -> !Bool -> !EvalSettingsWrap -> EvalSettings
+ Patat.Presentation.Internal: EvalSettings :: !Text -> !Bool -> !Bool -> !EvalSettingsContainer -> EvalSettings
- Patat.Presentation.Internal: PresentationSettings :: !Maybe (FlexibleNum Int) -> !Maybe (FlexibleNum Int) -> !Maybe MarginSettings -> !Maybe Wrap -> !Maybe Theme -> !Maybe Bool -> !Maybe (FlexibleNum Int) -> !Maybe Int -> !Maybe ExtensionList -> !Maybe ImageSettings -> !Maybe Bool -> !Maybe EvalSettingsMap -> !Maybe Bool -> !Maybe [FilePath] -> !Maybe SpeakerNotesSettings -> !Maybe TransitionSettings -> PresentationSettings
+ Patat.Presentation.Internal: PresentationSettings :: !Maybe (FlexibleNum Int) -> !Maybe (FlexibleNum Int) -> !Maybe MarginSettings -> !Maybe Wrap -> !Maybe (FlexibleNum Int) -> !Maybe Theme -> !Maybe Bool -> !Maybe (FlexibleNum Int) -> !Maybe Int -> !Maybe ExtensionList -> !Maybe ImageSettings -> !Maybe Bool -> !Maybe EvalSettingsMap -> !Maybe Bool -> !Maybe [FilePath] -> !Maybe SpeakerNotesSettings -> !Maybe TransitionSettings -> PresentationSettings
- Patat.Presentation.Settings: EvalSettings :: !Text -> !Bool -> !Bool -> !EvalSettingsWrap -> EvalSettings
+ Patat.Presentation.Settings: EvalSettings :: !Text -> !Bool -> !Bool -> !EvalSettingsContainer -> EvalSettings
- Patat.Presentation.Settings: PresentationSettings :: !Maybe (FlexibleNum Int) -> !Maybe (FlexibleNum Int) -> !Maybe MarginSettings -> !Maybe Wrap -> !Maybe Theme -> !Maybe Bool -> !Maybe (FlexibleNum Int) -> !Maybe Int -> !Maybe ExtensionList -> !Maybe ImageSettings -> !Maybe Bool -> !Maybe EvalSettingsMap -> !Maybe Bool -> !Maybe [FilePath] -> !Maybe SpeakerNotesSettings -> !Maybe TransitionSettings -> PresentationSettings
+ Patat.Presentation.Settings: PresentationSettings :: !Maybe (FlexibleNum Int) -> !Maybe (FlexibleNum Int) -> !Maybe MarginSettings -> !Maybe Wrap -> !Maybe (FlexibleNum Int) -> !Maybe Theme -> !Maybe Bool -> !Maybe (FlexibleNum Int) -> !Maybe Int -> !Maybe ExtensionList -> !Maybe ImageSettings -> !Maybe Bool -> !Maybe EvalSettingsMap -> !Maybe Bool -> !Maybe [FilePath] -> !Maybe SpeakerNotesSettings -> !Maybe TransitionSettings -> PresentationSettings
Files
- CHANGELOG.md +24/−0
- README.md +35/−20
- lib/Patat/Eval.hs +4/−4
- lib/Patat/Presentation/Display.hs +2/−1
- lib/Patat/Presentation/Display/CodeBlock.hs +22/−2
- lib/Patat/Presentation/Display/Internal.hs +1/−0
- lib/Patat/Presentation/Settings.hs +36/−20
- lib/Patat/Transition.hs +2/−0
- lib/Patat/Transition/Matrix.hs +128/−0
- patat.cabal +2/−1
CHANGELOG.md view
@@ -1,5 +1,29 @@ # Changelog +## 0.12.0.0 (2024-02-27)++ * Render tabs in code blocks by expanding them to spaces. The amount of+ spaces a tab character aligns to is customizable using `tabStop`, e.g.+ `tabStop: 8`. The default is 4.++ * Rename eval.wrap to eval.container (#167)++ `wrap` is used at the top-level of settings for wrapping at a certain+ column, and inside `eval` to determine the type in which the result+ is "wrapped". Using the same name for both is confusing, so this adds+ `eval.container` as the new name for `eval.wrap`. `eval.wrap` will continue+ to be supported for the forseeable future, but its use will be discouraged.++ This also changes the values (again keeping the original ones for+ backwards-compat), so the complete changes to a configuration would be:++ - `wrap: code` becomes `container: code`+ - `wrap: raw` becomes `container: none`+ - `wrap: rawInline` becomes `container: inline`++ * Add a `type: matrix` transition effect, loosely inspired by the 1999 science+ fiction movie.+ ## 0.11.0.0 (2024-02-14) * Support wrapping at a specific column (#164)
README.md view
@@ -21,7 +21,7 @@ - [Centering](#centering) and [re-wrapping](#line-wrapping) text to terminal width with proper indentation. - [Theming](#theming) support including 24-bit RGB.-- Hihgly portable as it only requires an ANSI terminal as opposed to+- Highly portable as it only requires an ANSI terminal as opposed to something like `ncurses`. @@ -42,6 +42,7 @@ - [Input format](#input-format) - [Configuration](#configuration) - [Line wrapping](#line-wrapping)+ - [Tab stop](#tab-stop) - [Margins](#margins) - [Auto advancing](#auto-advancing) - [Advanced slide splitting](#advanced-slide-splitting)@@ -266,7 +267,8 @@ Hello world. ``` -3. Within a slide, using a comment starting with `<!--config:`. These+3. In version 0.10 and later slides can be individually configured.+ Within a slide, using a comment starting with `<!--config:`. These settings can override configuration for that specific slide only. There should not be any whitespace between `<!--` and `config:`. @@ -302,8 +304,14 @@ Line wrapping can be enabled by setting `wrap: true` in the configuration. This will re-wrap all lines to fit the terminal width better. You can also ask patat-to wrap at a specific column using e.g. `wrap: 60`.+to wrap at a specific column using `wrap: number`, e.g. `wrap: 60`. +### Tab stop++In version 0.12 and later, the amount of spaces a `\t` character in a code block+aligns to can be customized by setting `tabStop: number` in the configuration.+The default is `4`.+ ### Margins Margins can be enabled by setting a `margins` entry in the configuration:@@ -336,9 +344,13 @@ #### Centering -To vertically center content, use `top: auto`. To horizontally center content,-use both `left: auto` and `right: auto`. For example:+Version 0.11 and later can center content. + - To vertically center content, use `top: auto`.+ - To horizontally center content, use both `left: auto` and `right: auto`.++For example:+ ```markdown --- title: Centered presentation@@ -611,7 +623,7 @@ #### Native Images support -`patat-0.8.0.0` and newer include images support for some terminal emulators.+Version 0.8 and later include images support for some terminal emulators. ```markdown ---@@ -656,7 +668,7 @@ [code evaluation](#evaluating-code). In order to do that, for example, we could configure `kitten` code snippets-to evaluate using [Kitty]'s command `icat`. This uses the `rawInline` code+to evaluate using [Kitty]'s command `icat`. This uses the `none` container setting to ensure that the resulting output is not wrapped in a code block, and the `fragment` and `replace` settings immediately replace the snippet. @@ -667,7 +679,7 @@ command: sed 's/^/kitten /' | bash replace: true fragment: false- wrap: rawInline+ container: none ... See, for example:@@ -712,7 +724,7 @@ command: irb --noecho --noverbose fragment: true # Optional replace: false # Optional- wrap: code # Optional+ container: code # Optional ... Here is an example of a code block that is evaluated:@@ -728,18 +740,20 @@ code of presentations downloaded from the internet before running them if they contain `eval` settings. -Aside from the command, there are two more options:+Aside from the command, there are three more options: - `fragment`: Introduce a pause (see [fragments](#fragmented-slides)) in between showing the original code block and the output. Defaults to `true`. - `replace`: Remove the original code block and replace it with the output rather than appending the output in a new code block. Defaults to `false`.- - `wrap`: By default, the output is wrapped in a code block again with the- original syntax highlighting. You can customize this behaviour by setting- `wrap` to:+ - `container`: By default, the output is wrapped in a code block again with+ the original syntax highlighting. You can customize this behaviour by+ setting `container` to: * `code`: the default setting.- * `raw`: no formatting applied.- * `rawInline`: no formatting applied and no trailing newline.+ * `none`: no formatting applied.+ * `inline`: no formatting applied and no trailing newline.+ - `wrap`: this is a deprecated name for `container`, used in version 0.11 and+ earlier. Setting `fragment: false` and `replace: true` offers a way to "filter" code blocks, which can be used to render ASCII graphics.@@ -766,7 +780,7 @@ ### Speaker Notes -`patat` supports comments which can be used as speaker notes.+Version 0.9 and later support comments which can be used as speaker notes. ```markdown ---@@ -817,10 +831,10 @@ ### Transitions -`patat` supports transitions in between slides. A relatively fast terminal-emulator (e.g. [Alacritty], [Kitty], [iTerm2])-is suggested when enabling this, to avoid too much flickering -- some-flickering is unavoidable since we redraw the entire screen on each frame.+Version 0.10 and later support transitions in between slides. A relatively+fast terminal emulator (e.g. [Alacritty], [Kitty], [iTerm2]) is suggested when+enabling this, to avoid too much flickering -- some flickering is unavoidable+since we redraw the entire screen on each frame. ```yaml patat:@@ -851,6 +865,7 @@ - `slideLeft`: slides the new slide in from right to left. - `dissolve`: changes characters over time.+ - `matrix`: loosely inspired by the 1999 science fiction movie. All transitions currently take these arguments:
lib/Patat/Eval.hs view
@@ -72,10 +72,10 @@ evalCommand <> ": exit code " <> T.pack (show i) <> "\n" <> erStderr let fmt = "eval"- blocks = case evalWrap of- EvalWrapCode -> [Pandoc.CodeBlock attr out]- EvalWrapRaw -> [Pandoc.RawBlock fmt out]- EvalWrapRawInline -> [Pandoc.Plain [Pandoc.RawInline fmt out]]+ blocks = case evalContainer of+ EvalContainerCode -> [Pandoc.CodeBlock attr out]+ EvalContainerNone -> [Pandoc.RawBlock fmt out]+ EvalContainerInline -> [Pandoc.Plain [Pandoc.RawInline fmt out]] pure $ case (evalFragment, evalReplace) of (False, True) -> [Append blocks] (False, False) -> [Append (orig : blocks)]
lib/Patat/Presentation/Display.hs view
@@ -60,8 +60,9 @@ settings = activeSettings pres ds = DisplaySettings { dsSize = canvasSize- , dsWrap = fromMaybe NoWrap $ psWrap settings , dsMargins = margins settings+ , dsWrap = fromMaybe NoWrap $ psWrap settings+ , dsTabStop = maybe 4 A.unFlexibleNum $ psTabStop settings , dsTheme = fromMaybe Theme.defaultTheme (psTheme settings) , dsSyntaxMap = pSyntaxMap }
lib/Patat/Presentation/Display/CodeBlock.hs view
@@ -1,5 +1,6 @@ -------------------------------------------------------------------------------- -- | Displaying code blocks, optionally with syntax highlighting.+{-# LANGUAGE BangPatterns #-} {-# LANGUAGE OverloadedStrings #-} module Patat.Presentation.Display.CodeBlock ( prettyCodeBlock@@ -7,6 +8,7 @@ --------------------------------------------------------------------------------+import Data.Char.WCWidth (wcwidth) import Data.Maybe (mapMaybe) import qualified Data.Text as T import Patat.Presentation.Display.Internal@@ -50,12 +52,30 @@ --------------------------------------------------------------------------------+-- | Expands tabs in code lines.+expandTabs :: Int -> Skylighting.SourceLine -> Skylighting.SourceLine+expandTabs tabStop = goTokens 0+ where+ goTokens _ [] = []+ goTokens col0 ((tokType, txt) : tokens) = goString col0 "" (T.unpack txt) $+ \col1 str -> (tokType, T.pack str) : goTokens col1 tokens++ goString :: Int -> String -> String -> (Int -> String -> k) -> k+ goString !col acc str k = case str of+ [] -> k col (reverse acc)+ '\t' : t -> goString (col + spaces) (replicate spaces ' ' ++ acc) t k+ c : t -> goString (col + wcwidth c) (c : acc) t k+ where+ spaces = tabStop - col `mod` tabStop+++-------------------------------------------------------------------------------- prettyCodeBlock :: DisplaySettings -> [T.Text] -> T.Text -> PP.Doc prettyCodeBlock ds classes rawCodeBlock = PP.vcat (map blockified sourceLines) <> PP.hardline where sourceLines :: [Skylighting.SourceLine]- sourceLines =+ sourceLines = map (expandTabs (dsTabStop ds)) $ [[]] ++ highlight (dsSyntaxMap ds) classes rawCodeBlock ++ [[]] prettySourceLine :: Skylighting.SourceLine -> PP.Doc@@ -65,7 +85,7 @@ prettyToken (tokenType, str) = themed ds (\theme -> syntaxHighlight theme tokenType)- (PP.string $ T.unpack str)+ (PP.text str) sourceLineLength :: Skylighting.SourceLine -> Int sourceLineLength line = sum [T.length str | (_, str) <- line]
lib/Patat/Presentation/Display/Internal.hs view
@@ -18,6 +18,7 @@ data DisplaySettings = DisplaySettings { dsSize :: !Size , dsWrap :: !Wrap+ , dsTabStop :: !Int , dsMargins :: !Margins , dsTheme :: !Theme.Theme , dsSyntaxMap :: !Skylighting.SyntaxMap
lib/Patat/Presentation/Settings.hs view
@@ -16,7 +16,7 @@ , ImageSettings (..) , EvalSettingsMap- , EvalSettingsWrap (..)+ , EvalSettingsContainer (..) , EvalSettings (..) , SpeakerNotesSettings (..)@@ -49,6 +49,7 @@ , psColumns :: !(Maybe (A.FlexibleNum Int)) , psMargins :: !(Maybe MarginSettings) , psWrap :: !(Maybe Wrap)+ , psTabStop :: !(Maybe (A.FlexibleNum Int)) , psTheme :: !(Maybe Theme.Theme) , psIncrementalLists :: !(Maybe Bool) , psAutoAdvanceDelay :: !(Maybe (A.FlexibleNum Int))@@ -71,6 +72,7 @@ , psColumns = on mplus psColumns l r , psMargins = on (<>) psMargins l r , psWrap = on mplus psWrap l r+ , psTabStop = on mplus psTabStop l r , psTheme = on (<>) psTheme l r , psIncrementalLists = on mplus psIncrementalLists l r , psAutoAdvanceDelay = on mplus psAutoAdvanceDelay l r@@ -90,9 +92,9 @@ instance Monoid PresentationSettings where mappend = (<>) mempty = PresentationSettings- Nothing Nothing Nothing Nothing Nothing Nothing Nothing- Nothing Nothing Nothing Nothing Nothing Nothing Nothing- Nothing Nothing+ Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing+ Nothing Nothing Nothing Nothing Nothing Nothing Nothing Nothing+ Nothing --------------------------------------------------------------------------------@@ -221,38 +223,52 @@ ---------------------------------------------------------------------------------data EvalSettingsWrap- = EvalWrapCode- | EvalWrapRaw- | EvalWrapRawInline+data EvalSettingsContainer+ = EvalContainerCode+ | EvalContainerNone+ | EvalContainerInline deriving (Show) ---------------------------------------------------------------------------------instance A.FromJSON EvalSettingsWrap where- parseJSON = A.withText "FromJSON EvalSettingsWrap" $ \txt -> case txt of- "code" -> pure EvalWrapCode- "raw" -> pure EvalWrapRaw- "rawInline" -> pure EvalWrapRawInline- _ -> fail $ "unknown wrap: " <> show txt+instance A.FromJSON EvalSettingsContainer where+ parseJSON = A.withText "FromJSON EvalSettingsContainer" $ \t -> case t of+ "code" -> pure EvalContainerCode+ "none" -> pure EvalContainerNone+ "inline" -> pure EvalContainerInline+ -- Deprecated names+ "raw" -> pure EvalContainerNone+ "rawInline" -> pure EvalContainerInline+ _ -> fail $ "unknown container: " <> show t -------------------------------------------------------------------------------- data EvalSettings = EvalSettings- { evalCommand :: !T.Text- , evalReplace :: !Bool- , evalFragment :: !Bool- , evalWrap :: !EvalSettingsWrap+ { evalCommand :: !T.Text+ , evalReplace :: !Bool+ , evalFragment :: !Bool+ , evalContainer :: !EvalSettingsContainer } deriving (Show) -------------------------------------------------------------------------------- instance A.FromJSON EvalSettings where parseJSON = A.withObject "FromJSON EvalSettings" $ \o -> EvalSettings- <$> o A..: "command"+ <$> o A..: "command" <*> o A..:? "replace" A..!= False <*> o A..:? "fragment" A..!= True- <*> o A..:? "wrap" A..!= EvalWrapCode+ <*> deprecated "wrap" "container" EvalContainerCode o+ where+ deprecated old new def obj = do+ mo <- obj A..:? old+ mn <- obj A..:? new+ case (mo, mn) of+ (Just _, Just _) -> fail $+ show old ++ " (deprecated) and " ++ show new ++ " " +++ "are both specified, please remove " ++ show old+ (Just o, Nothing) -> pure o+ (Nothing, Just n) -> pure n+ (Nothing, Nothing) -> pure def --------------------------------------------------------------------------------
lib/Patat/Transition.hs view
@@ -29,6 +29,7 @@ import Patat.Presentation.Settings (TransitionSettings (..)) import qualified Patat.Transition.Dissolve as Dissolve import Patat.Transition.Internal+import qualified Patat.Transition.Matrix as Matrix import qualified Patat.Transition.SlideLeft as SlideLeft import System.Random (uniformR) @@ -54,6 +55,7 @@ transitions :: NonEmpty (Text, Transition) transitions = ("dissolve", Transition Dissolve.transition) :|+ ("matrix", Transition Matrix.transition) : ("slideLeft", Transition SlideLeft.transition) : []
+ lib/Patat/Transition/Matrix.hs view
@@ -0,0 +1,128 @@+--------------------------------------------------------------------------------+{-# LANGUAGE TemplateHaskell #-}+module Patat.Transition.Matrix+ ( transition+ ) where+++--------------------------------------------------------------------------------+import Control.Monad (forM_, guard, when)+import qualified Data.Aeson.Extended as A+import qualified Data.Aeson.TH.Extended as A+import Data.Bifunctor (first)+import qualified Data.Vector as V+import qualified Data.Vector.Mutable as VM+import Patat.PrettyPrint.Matrix+import Patat.Size (Size (..))+import Patat.Transition.Internal+import System.Random.Stateful+++--------------------------------------------------------------------------------+data Config = Config+ { cDuration :: Maybe (A.FlexibleNum Double)+ , cFrameRate :: Maybe (A.FlexibleNum Int)+ }+++--------------------------------------------------------------------------------+data Particle = Particle+ { pX :: Double+ , pInitialY :: Double+ , pFinalY :: Double+ , pSpeed :: Double+ , pCell :: Cell+ }+++--------------------------------------------------------------------------------+particleY :: Particle -> Double -> Double+particleY p t = pInitialY p * (1 - t') + pFinalY p * t'+ where+ t' = min 1 (pSpeed p * t)+++--------------------------------------------------------------------------------+-- | Maximum speed of a particle, expressed as a factor of the minimum speed of+-- a particle.+particleMaxSpeed :: Double+particleMaxSpeed = 2+++--------------------------------------------------------------------------------+-- | Number of ghosts a particle leaves behind. Currently hardcoded but could+-- be moved to config.+particleGhosts :: Int+particleGhosts = 3+++--------------------------------------------------------------------------------+transition :: Config -> TransitionGen+transition config (Size rows cols) initial final rgen =+ first frame <$>+ evenlySpacedFrames+ (A.unFlexibleNum <$> cDuration config)+ (A.unFlexibleNum <$> cFrameRate config)+ where+ speeds :: V.Vector Double+ speeds = runStateGen_ rgen $ \g ->+ V.replicateM (rows * cols) (uniformRM (1, particleMaxSpeed) g)++ up :: V.Vector Bool+ up = runStateGen_ rgen $ \g ->+ V.replicateM (rows * cols) (uniformM g)++ ghosts :: Double -> [Double]+ ghosts baseSpeed =+ [ baseSpeed * (1 + fromIntegral i / fromIntegral particleGhosts)+ | i <- [0 .. particleGhosts]+ ]++ initialParticles :: [Particle]+ initialParticles = do+ (x, y, cell) <- posCells initial+ let idx = y * cols + x+ speed <- ghosts $ speeds V.! idx+ pure Particle+ { pX = fromIntegral x+ , pInitialY = fromIntegral y+ , pFinalY = if up V.! idx then 0 else fromIntegral rows+ , pSpeed = speed+ , pCell = cell+ }++ finalParticles :: [Particle]+ finalParticles = do+ (x, y, cell) <- posCells final+ let idx = y * cols + x+ speed <- ghosts $ speeds V.! idx+ pure Particle+ { pX = fromIntegral x+ , pInitialY = if up V.! idx then -1 else fromIntegral rows+ , pFinalY = fromIntegral y+ , pSpeed = speed+ , pCell = cell+ }++ posCells :: Matrix -> [(Int, Int, Cell)]+ posCells mat = do+ y <- [0 .. rows - 1]+ x <- [0 .. cols - 1]+ let cell = mat V.! (y * cols + x)+ guard . not $ cell == emptyCell+ pure (x, y, cell)++ frame :: Double -> Matrix+ frame t = V.create $ do+ mat <- VM.replicate (rows * cols) emptyCell+ forM_ (initialParticles ++ finalParticles) $ \particle ->+ let y = round $ particleY particle t+ x = round $ pX particle+ idx = y * cols + x in+ when (x >= 0 && x < cols && y >= 0 && y < rows) $+ VM.write mat idx $ pCell particle+ pure mat+++--------------------------------------------------------------------------------+$(A.deriveFromJSON A.dropPrefixOptions ''Config)
patat.cabal view
@@ -1,5 +1,5 @@ Name: patat-Version: 0.11.0.0+Version: 0.12.0.0 Synopsis: Terminal-based presentations using Pandoc Description: Terminal-based presentations using Pandoc. License: GPL-2@@ -97,6 +97,7 @@ Patat.Transition Patat.Transition.Internal Patat.Transition.Dissolve+ Patat.Transition.Matrix Patat.Transition.SlideLeft Other-modules: