From 87ae01adc8be6516ba0d8adaee43b4ef56c8365e Mon Sep 17 00:00:00 2001 From: "Yann Esposito (Yogsototh)" Date: Mon, 7 Oct 2013 15:56:31 +0200 Subject: [PATCH] better presentation --- parsec.html | 110 +++++++++++-- parsec/10_Introduction/.030_advanced.md.swp | Bin 0 -> 12288 bytes parsec/10_Introduction/020_intro.md | 147 ++++++++++++++++++ parsec/10_Introduction/030_advanced.md | 34 ++++ parsec/10_Introduction/050_Base.md | 19 --- .../70_Combining_Monadic_Style.md | 14 -- .../10_Introduction/020_intro-000.md} | 2 +- .../10_Introduction/020_intro-001.md} | 1 + .../10_Introduction/020_intro-002.md} | 1 + parsec/_tmp/10_Introduction/020_intro-003.md | 8 + .../10_Introduction/020_intro-004.md} | 10 +- .../10_Introduction/020_intro-005.md} | 1 + parsec/_tmp/10_Introduction/020_intro-006.md | 24 +++ parsec/_tmp/10_Introduction/020_intro-007.md | 11 ++ parsec/_tmp/10_Introduction/020_intro-008.md | 22 +++ parsec/_tmp/10_Introduction/020_intro-009.md | 17 ++ .../_tmp/10_Introduction/030_advanced-000.md | 9 ++ .../_tmp/10_Introduction/030_advanced-001.md | 4 + .../_tmp/10_Introduction/030_advanced-002.md | 14 ++ .../_tmp/10_Introduction/030_advanced-003.md | 7 + parsec/examples/03.hs | 46 ++++++ parsec/examples/parseIP.hs | 38 +++++ parsec/gen | 19 ++- parsec/preview | 54 +------ parsec/watch | 55 +++++++ 25 files changed, 561 insertions(+), 106 deletions(-) create mode 100644 parsec/10_Introduction/.030_advanced.md.swp create mode 100644 parsec/10_Introduction/020_intro.md create mode 100644 parsec/10_Introduction/030_advanced.md delete mode 100644 parsec/10_Introduction/050_Base.md delete mode 100644 parsec/10_Introduction/70_Combining_Monadic_Style.md rename parsec/{10_Introduction/020_Origine.md => _tmp/10_Introduction/020_intro-000.md} (100%) rename parsec/{10_Introduction/030_Example.md => _tmp/10_Introduction/020_intro-001.md} (99%) rename parsec/{10_Introduction/040_Parsec.md => _tmp/10_Introduction/020_intro-002.md} (99%) create mode 100644 parsec/_tmp/10_Introduction/020_intro-003.md rename parsec/{10_Introduction/50_A_Parsec_Example.md => _tmp/10_Introduction/020_intro-004.md} (50%) rename parsec/{10_Introduction/60_Monadic_Style.md => _tmp/10_Introduction/020_intro-005.md} (99%) create mode 100644 parsec/_tmp/10_Introduction/020_intro-006.md create mode 100644 parsec/_tmp/10_Introduction/020_intro-007.md create mode 100644 parsec/_tmp/10_Introduction/020_intro-008.md create mode 100644 parsec/_tmp/10_Introduction/020_intro-009.md create mode 100644 parsec/_tmp/10_Introduction/030_advanced-000.md create mode 100644 parsec/_tmp/10_Introduction/030_advanced-001.md create mode 100644 parsec/_tmp/10_Introduction/030_advanced-002.md create mode 100644 parsec/_tmp/10_Introduction/030_advanced-003.md create mode 100644 parsec/examples/03.hs create mode 100644 parsec/examples/parseIP.hs create mode 100755 parsec/watch diff --git a/parsec.html b/parsec.html index d50017a..fb5b766 100644 --- a/parsec.html +++ b/parsec.html @@ -108,15 +108,23 @@
+

Parsec(s)

+

In reality there is many choices:

+
- attoparsec: fast
+- Bytestring-lexing: fast
+- Parsec 3: powerful, nice error reporting
+
+

A Parsec Example

whitespaces = many (oneOf "\t ")
-number = many1 digit
-
Right "   \t "  -- whitespaces on "   \t "
-Right ""        -- whitespaces on "32"
-Right "32"      -- number on "32"
+number = many1 digit
+symbol = oneOf "!#$%&|*+-/:<=>?@^_~"
+
"   \t "  -- whitespaces on "   \t "
+""        -- whitespaces on "32"
+"32"      -- number on "32"
 
 -- number on "   \t 32  "
-Left "number" (line 1, column 1):
+"number" (line 1, column 1):
 unexpected " "
 expecting digit
@@ -128,19 +136,93 @@ number = many1 digit number' :: Parser Int number' = do string_of_number <- many1 digit - return (read string_of_number) + return (read string_of_number)
"32" :: [Char]  -- number on "32"
 32   :: Int     -- number' on "32"
-

Monadic style

-
isolatedNumber :: Parser String
-isolatedNumber = do
-    _ <- whitespaces
-    n <- number
-    _ <- whitespaces
-    return n
-
Right "32"      -- isolatedNumber on "   \t 32 "
+

Combining Monadic style

+


S = aSbε

+
s = (do
+        a <- char 'a'
+        mid <- S
+        b <- char 'b'
+        return (a:mid) ++ b:[]) 
+    <|> string ""
+
""          -- s on ""
+"aaabbb"    -- s on "aaabbb"
+"aabb"      -- s on "aabbb"
+-- s on "aaabb"
+S (line1 1, column 4):
+unexpected end of input
+expecting "b"
+
+
+

Applicative style

+


S = aSbε

+
s = concat3 <$> string "a" <*> s <*> char "b"
+    <|> string ""
+    where
+        concat3 x y z = x ++ y ++ z
+
+
+

Applicative Style usefull with Data types

+
data IP = IP Int Int Int Int
+
+parseIP = IP <$>
+            number <*  char '.' <*>
+            number <*  char '.' <*>
+            number <*  char '.' <*>
+            number
+
+monadicParseIP = do
+    d1 <- number
+    char '.'
+    d2 <- number
+    char '.'
+    d3 <- number
+    char '.'
+    d4 <- number
+    return (IP d1 d2 d3 d4)
+
+
+

Write number correctly

+
number :: Parser Int
+number = do
+    x <- read <$> many1 digit
+    guard (0 <= x && x < 256) <?>
+        "Number between 0 and 255 (here " ++ show x ++ ")"
+    return (fromIntegral x)
+
>>> test parseIP "parseIP" "823.32.80.113"
+"parseIP" (line 1, column 4):
+unexpected "."
+expecting digit or Number between 0 and 255 (here 823)
+
+
+

So

+ +

Time to do something cool

+
+
+

A Simple DSL

+

Let's write a minimal DSL

+
+
+

Useful definitions

+

try tries to parse and backtracks if it fails.

+
(<||>) parser1 parser2 = try parser1 <|> parser2
+

lexeme, just skip spaces.

+
lexeme parser = whitespaces *> parser <* whitespaces
+
+
+

Data Structure

+

Remember from text to data structure

+
data Tree = Node Element [Tree]
diff --git a/parsec/10_Introduction/.030_advanced.md.swp b/parsec/10_Introduction/.030_advanced.md.swp new file mode 100644 index 0000000000000000000000000000000000000000..2fbb2b683904879d91682f8c223caaefceeea430 GIT binary patch literal 12288 zcmeI2%T5$Q6ov~;+##rOe;gKE)O1%fCEZ<}s%nNwh_2Mc zM=TrGi z^OgAW`voC-Mc+R>y>_1Z{QSTdy_u%=%FSfbIu%T1Rymb=>9t9#zM0wj)@tgl3G<-r zuFu!EWVkESK!wvuc>X3F!3NmCSp&I`rtS=i`MKG8F*s7YMK`W*o{i%kHoykh02^Qf zY=8~00XDz}F028c4TzV>?oyRut!f8Owbfs4*Z><~18jf|umLu}2G{@_U;}J`4X}a# z(164z^_zo2d;rDw|Ks=nqah)FfG^+xyaA8FBd`b>U=rL0*T671x{5jA6Zi-Yz+3Pd zyaF0@z*8^^MnDY=gCX!8XZQxbfX?n7Oz`qS+&NG1+>PWYv;#i1v%uL$KQe;g+UhR4EhRPkB zwT2I1{I3#2cyTu& zp&~wyJ?XT6F}{~6%r2H)&azkssFmMU Parsec lets you construct parsers by combining high-order Combinators +> to create larger expressions. +> +> Combinator parsers are written and used within the same programming language +> as the rest of the program. +> +> The parsers are first-class citizens of the languages [...]" + +## Parsec(s) + +In reality there is many choices: + + - attoparsec: fast + - Bytestring-lexing: fast + - Parsec 3: powerful, nice error reporting + +## A Parsec Example + +``` haskell +whitespaces = many (oneOf "\t ") +number = many1 digit +symbol = oneOf "!#$%&|*+-/:<=>?@^_~" +``` + +``` haskell +" \t " -- whitespaces on " \t " +"" -- whitespaces on "32" +"32" -- number on "32" + +-- number on " \t 32 " +"number" (line 1, column 1): +unexpected " " +expecting digit +``` + +## Monadic style + +``` haskell +number :: Parser String +number = many1 digit + +number' :: Parser Int +number' = do + string_of_number <- many1 digit + return (read string_of_number) +``` + +``` haskell +"32" :: [Char] -- number on "32" +32 :: Int -- number' on "32" +``` + +## Combining Monadic style + +$$ S = aSb | ε $$ + +``` haskell +s = (do + a <- char 'a' + mid <- S + b <- char 'b' + return (a:mid) ++ b:[]) + <|> string "" + +``` + +``` haskell +"" -- s on "" +"aaabbb" -- s on "aaabbb" +"aabb" -- s on "aabbb" +-- s on "aaabb" +S (line1 1, column 4): +unexpected end of input +expecting "b" +``` + +## Applicative style + +$$ S = aSb | ε $$ + +``` haskell +s = concat3 <$> string "a" <*> s <*> char "b" + <|> string "" + where + concat3 x y z = x ++ y ++ z +``` + +## Applicative Style usefull with Data types + +``` haskell +data IP = IP Int Int Int Int + +parseIP = IP <$> + number <* char '.' <*> + number <* char '.' <*> + number <* char '.' <*> + number + +monadicParseIP = do + d1 <- number + char '.' + d2 <- number + char '.' + d3 <- number + char '.' + d4 <- number + return (IP d1 d2 d3 d4) +``` + +## Write number correctly + +``` haskell +number :: Parser Int +number = do + x <- read <$> many1 digit + guard (0 <= x && x < 256) + "Number between 0 and 255 (here " ++ show x ++ ")" + return (fromIntegral x) +``` + +``` haskell +>>> test parseIP "parseIP" "823.32.80.113" +"parseIP" (line 1, column 4): +unexpected "." +expecting digit or Number between 0 and 255 (here 823) +``` diff --git a/parsec/10_Introduction/030_advanced.md b/parsec/10_Introduction/030_advanced.md new file mode 100644 index 0000000..177ab69 --- /dev/null +++ b/parsec/10_Introduction/030_advanced.md @@ -0,0 +1,34 @@ +## So + +- combination of simple parsers +- error messages with `()` +- embed result in data type using Applicative style +- Not shown, use another monad with the parser + +Time to do something cool + +## A Simple DSL + +Let's write a minimal DSL + +## Useful definitions + +`try` tries to parse and backtracks if it fails. + +``` haskell +(<||>) parser1 parser2 = try parser1 <|> parser2 +``` + +`lexeme`, just skip spaces. + +``` haskell +lexeme parser = whitespaces *> parser <* whitespaces +``` + +## Data Structure + +Remember from text to data structure + +``` haskell +data Tree = Node Element [Tree] +``` diff --git a/parsec/10_Introduction/050_Base.md b/parsec/10_Introduction/050_Base.md deleted file mode 100644 index de7510e..0000000 --- a/parsec/10_Introduction/050_Base.md +++ /dev/null @@ -1,19 +0,0 @@ -## [Write Yourself a Scheme in 48 Hours](https://en.wikibooks.org/wiki/Write_Yourself_a_Scheme_in_48_Hours/First_Steps) - - -~~~ {.haskell} -import Text.Parsec -type Parser a = Parsec String () a -~~~ - -~~~ {.haskell} -symbol :: Parser Char -symbol = oneOf "!#$%&|*+-/:<=>?@^_~" -~~~ - -~~~ {.haskell} -readExpr :: String -> String -readExpr input = case parse symbol "lisp" input of - Left err -> "No match: " ++ show err - Right val -> "Found: " ++ show val -~~~ diff --git a/parsec/10_Introduction/70_Combining_Monadic_Style.md b/parsec/10_Introduction/70_Combining_Monadic_Style.md deleted file mode 100644 index 339eaaf..0000000 --- a/parsec/10_Introduction/70_Combining_Monadic_Style.md +++ /dev/null @@ -1,14 +0,0 @@ -## Monadic style - -``` haskell -isolatedNumber :: Parser String -isolatedNumber = do - _ <- whitespaces - n <- number - _ <- whitespaces - return n -``` - -``` haskell -Right "32" -- isolatedNumber on " \t 32 " -``` diff --git a/parsec/10_Introduction/020_Origine.md b/parsec/_tmp/10_Introduction/020_intro-000.md similarity index 100% rename from parsec/10_Introduction/020_Origine.md rename to parsec/_tmp/10_Introduction/020_intro-000.md index 9c7a980..b32b645 100644 --- a/parsec/10_Introduction/020_Origine.md +++ b/parsec/_tmp/10_Introduction/020_intro-000.md @@ -1,7 +1,7 @@ ## Parsing - Latin pars (ōrātiōnis), meaning part (of speech). - **analysing a string of symbols** - **formal grammar**. + diff --git a/parsec/10_Introduction/030_Example.md b/parsec/_tmp/10_Introduction/020_intro-001.md similarity index 99% rename from parsec/10_Introduction/030_Example.md rename to parsec/_tmp/10_Introduction/020_intro-001.md index 62cbb2c..56efb7b 100644 --- a/parsec/10_Introduction/030_Example.md +++ b/parsec/_tmp/10_Introduction/020_intro-001.md @@ -9,3 +9,4 @@ From String: To data structure: ![AST](parsec/img/mp/AST.png)\ + diff --git a/parsec/10_Introduction/040_Parsec.md b/parsec/_tmp/10_Introduction/020_intro-002.md similarity index 99% rename from parsec/10_Introduction/040_Parsec.md rename to parsec/_tmp/10_Introduction/020_intro-002.md index c9e1235..6354d30 100644 --- a/parsec/10_Introduction/040_Parsec.md +++ b/parsec/_tmp/10_Introduction/020_intro-002.md @@ -7,3 +7,4 @@ > as the rest of the program. > > The parsers are first-class citizens of the languages [...]" + diff --git a/parsec/_tmp/10_Introduction/020_intro-003.md b/parsec/_tmp/10_Introduction/020_intro-003.md new file mode 100644 index 0000000..2051f8a --- /dev/null +++ b/parsec/_tmp/10_Introduction/020_intro-003.md @@ -0,0 +1,8 @@ +## Parsec(s) + +In reality there is many choices: + + - attoparsec: fast + - Bytestring-lexing: fast + - Parsec 3: powerful, nice error reporting + diff --git a/parsec/10_Introduction/50_A_Parsec_Example.md b/parsec/_tmp/10_Introduction/020_intro-004.md similarity index 50% rename from parsec/10_Introduction/50_A_Parsec_Example.md rename to parsec/_tmp/10_Introduction/020_intro-004.md index 7716f33..a626e85 100644 --- a/parsec/10_Introduction/50_A_Parsec_Example.md +++ b/parsec/_tmp/10_Introduction/020_intro-004.md @@ -3,15 +3,17 @@ ``` haskell whitespaces = many (oneOf "\t ") number = many1 digit +symbol = oneOf "!#$%&|*+-/:<=>?@^_~" ``` ``` haskell -Right " \t " -- whitespaces on " \t " -Right "" -- whitespaces on "32" -Right "32" -- number on "32" +" \t " -- whitespaces on " \t " +"" -- whitespaces on "32" +"32" -- number on "32" -- number on " \t 32 " -Left "number" (line 1, column 1): +"number" (line 1, column 1): unexpected " " expecting digit ``` + diff --git a/parsec/10_Introduction/60_Monadic_Style.md b/parsec/_tmp/10_Introduction/020_intro-005.md similarity index 99% rename from parsec/10_Introduction/60_Monadic_Style.md rename to parsec/_tmp/10_Introduction/020_intro-005.md index 3028deb..0e38ba0 100644 --- a/parsec/10_Introduction/60_Monadic_Style.md +++ b/parsec/_tmp/10_Introduction/020_intro-005.md @@ -14,3 +14,4 @@ number' = do "32" :: [Char] -- number on "32" 32 :: Int -- number' on "32" ``` + diff --git a/parsec/_tmp/10_Introduction/020_intro-006.md b/parsec/_tmp/10_Introduction/020_intro-006.md new file mode 100644 index 0000000..7802e8c --- /dev/null +++ b/parsec/_tmp/10_Introduction/020_intro-006.md @@ -0,0 +1,24 @@ +## Combining Monadic style + +$$ S = aSb | ε $$ + +``` haskell +s = (do + a <- char 'a' + mid <- S + b <- char 'b' + return (a:mid) ++ b:[]) + <|> string "" + +``` + +``` haskell +"" -- s on "" +"aaabbb" -- s on "aaabbb" +"aabb" -- s on "aabbb" +-- s on "aaabb" +S (line1 1, column 4): +unexpected end of input +expecting "b" +``` + diff --git a/parsec/_tmp/10_Introduction/020_intro-007.md b/parsec/_tmp/10_Introduction/020_intro-007.md new file mode 100644 index 0000000..3fc7358 --- /dev/null +++ b/parsec/_tmp/10_Introduction/020_intro-007.md @@ -0,0 +1,11 @@ +## Applicative style + +$$ S = aSb | ε $$ + +``` haskell +s = concat3 <$> string "a" <*> s <*> char "b" + <|> string "" + where + concat3 x y z = x ++ y ++ z +``` + diff --git a/parsec/_tmp/10_Introduction/020_intro-008.md b/parsec/_tmp/10_Introduction/020_intro-008.md new file mode 100644 index 0000000..01fbbd9 --- /dev/null +++ b/parsec/_tmp/10_Introduction/020_intro-008.md @@ -0,0 +1,22 @@ +## Applicative Style usefull with Data types + +``` haskell +data IP = IP Int Int Int Int + +parseIP = IP <$> + number <* char '.' <*> + number <* char '.' <*> + number <* char '.' <*> + number + +monadicParseIP = do + d1 <- number + char '.' + d2 <- number + char '.' + d3 <- number + char '.' + d4 <- number + return (IP d1 d2 d3 d4) +``` + diff --git a/parsec/_tmp/10_Introduction/020_intro-009.md b/parsec/_tmp/10_Introduction/020_intro-009.md new file mode 100644 index 0000000..d48edd4 --- /dev/null +++ b/parsec/_tmp/10_Introduction/020_intro-009.md @@ -0,0 +1,17 @@ +## Write number correctly + +``` haskell +number :: Parser Int +number = do + x <- read <$> many1 digit + guard (0 <= x && x < 256) + "Number between 0 and 255 (here " ++ show x ++ ")" + return (fromIntegral x) +``` + +``` haskell +>>> test parseIP "parseIP" "823.32.80.113" +"parseIP" (line 1, column 4): +unexpected "." +expecting digit or Number between 0 and 255 (here 823) +``` diff --git a/parsec/_tmp/10_Introduction/030_advanced-000.md b/parsec/_tmp/10_Introduction/030_advanced-000.md new file mode 100644 index 0000000..9f09790 --- /dev/null +++ b/parsec/_tmp/10_Introduction/030_advanced-000.md @@ -0,0 +1,9 @@ +## So + +- combination of simple parsers +- error messages with `()` +- embed result in data type using Applicative style +- Not shown, use another monad with the parser + +Time to do something cool + diff --git a/parsec/_tmp/10_Introduction/030_advanced-001.md b/parsec/_tmp/10_Introduction/030_advanced-001.md new file mode 100644 index 0000000..6012060 --- /dev/null +++ b/parsec/_tmp/10_Introduction/030_advanced-001.md @@ -0,0 +1,4 @@ +## A Simple DSL + +Let's write a minimal DSL + diff --git a/parsec/_tmp/10_Introduction/030_advanced-002.md b/parsec/_tmp/10_Introduction/030_advanced-002.md new file mode 100644 index 0000000..13867de --- /dev/null +++ b/parsec/_tmp/10_Introduction/030_advanced-002.md @@ -0,0 +1,14 @@ +## Useful definitions + +`try` tries to parse and backtracks if it fails. + +``` haskell +(<||>) parser1 parser2 = try parser1 <|> parser2 +``` + +`lexeme`, just skip spaces. + +``` haskell +lexeme parser = whitespaces *> parser <* whitespaces +``` + diff --git a/parsec/_tmp/10_Introduction/030_advanced-003.md b/parsec/_tmp/10_Introduction/030_advanced-003.md new file mode 100644 index 0000000..f500ab5 --- /dev/null +++ b/parsec/_tmp/10_Introduction/030_advanced-003.md @@ -0,0 +1,7 @@ +## Data Structure + +Remember from text to data structure + +``` haskell +data Tree = Node Element [Tree] +``` diff --git a/parsec/examples/03.hs b/parsec/examples/03.hs new file mode 100644 index 0000000..9da1359 --- /dev/null +++ b/parsec/examples/03.hs @@ -0,0 +1,46 @@ +import Control.Applicative hiding (many, (<|>)) +import Text.Parsec +import Data.Typeable + +type Parser a = Parsec String () a + +sa :: Parser String +sa = concat3 <$> string "a" <*> sa <*> string "b" <|> string "" + where + concat3 x y z = x ++ y ++ z + +s :: Parser String +s = s' <|> epsilon + +epsilon = string "" + +s' :: Parser String +s' = do + a <- string "a" + mid <- s + b <- string "b" + return (a ++ mid ++ b) + +main :: IO () +main = do + test s "S" "aaabbb" + test s "S" "aabbb" + test s "S" "aab" + test s "S" "" + test sa "S'" "aaabbb" + test sa "S'" "aabbb" + test sa "S'" "aab" + test sa "S'" "" + test parseIP "parseIP" "123.32.80.113" + test parseIP "parseIP" "823.32.80.113" + +test :: (Typeable a, Show a) => Parser a -> String -> String -> IO () +test parser description string = do + putStrLn $ "-- " ++ description ++ " on '" ++ string ++ "'" + let res = parse parser description string + putStr $ show res + case res of + Left err -> return () + Right value -> putStr $ " :: " ++ show (typeOf value) + putStrLn "" + diff --git a/parsec/examples/parseIP.hs b/parsec/examples/parseIP.hs new file mode 100644 index 0000000..49c599f --- /dev/null +++ b/parsec/examples/parseIP.hs @@ -0,0 +1,38 @@ +{-# LANGUAGE DeriveDataTypeable #-} +import Control.Applicative hiding (many, (<|>)) +import Text.Parsec +import Data.Typeable +import Control.Monad (guard) + +type Parser a = Parsec String () a + +data IP = IP Int Int Int Int deriving (Show,Typeable) + +parseIP :: Parser IP +parseIP = IP <$> + number <* char '.' <*> + number <* char '.' <*> + number <* char '.' <*> + number + +number :: Parser Int +number = do + x <- read <$> many1 digit + guard (0 <= x && x < 256) "Number between 0 and 255 (here " ++ show x ++ ")" + return (fromIntegral x) + +main :: IO () +main = do + test parseIP "parseIP" "123.32.80.113" + test parseIP "parseIP" "823.32.80.113" + +test :: (Typeable a, Show a) => Parser a -> String -> String -> IO () +test parser description string = do + putStrLn $ "-- " ++ description ++ " on '" ++ string ++ "'" + let res = parse parser description string + putStr $ show res + case res of + Left err -> return () + Right value -> putStr $ " :: " ++ show (typeOf value) + putStrLn "" + diff --git a/parsec/gen b/parsec/gen index ac5fc32..45acacd 100755 --- a/parsec/gen +++ b/parsec/gen @@ -10,14 +10,31 @@ fi cd $scriptdir htmldir="_html" +tmpdir="_tmp" [[ -e $htmldir ]] && \rm -rf $htmldir +[[ -e $tmpdir ]] && \rm -rf $tmpdir mkdir -p $htmldir + +# split a markdown file on ## +splitMarkdown() { + dstdir=$tmpdir/${1:h} + mdfic=$tmpdir/${1:r} + [[ ! -d $dstdir ]] && mkdir -p $dstdir + awk '/^## /{ dest=sprintf("'$mdfic'-%03d.md",n); print dest; n++ } { print $0 > dest}' $1 +} + # Convert all slides from markdown for slide in **/*.{md,html}(.N); do dst="$htmldir/${slide:r}.html" [[ ! -e ${dst:h} ]] && mkdir -p ${dst:h} case ${slide:e} in - md) pandoc -f markdown -t html $slide > $dst;; + md) i=0 + for tmpfic in $(splitMarkdown $slide); do + ((i++)) + print "Split $tmpfic" + dst="$( print -- ${tmpfic:r}.html | sed 's#'$tmpdir'#'$htmldir'#' )" + pandoc -f markdown -t html $tmpfic > $dst + done ;; html) cp $slide $dst;; esac done diff --git a/parsec/preview b/parsec/preview index 6300957..1d4b52d 100755 --- a/parsec/preview +++ b/parsec/preview @@ -1,55 +1,3 @@ #!/usr/bin/env zsh -error(){print -- $* >&2; exit 1} - -(($#<2)) && error "usage: ${0:t} [once] cmd dirs..." - -ONCE=0 -[[ $1 = "once" ]] && { ONCE=1; shift } - -(($#<2)) && error "usage: ${0:t} [once] cmd dirs..." - -cmd="$1" -shift - -typeset -a listDir -listDir=( $@ ) - -isRecentlyModified() { - local fic="$1" - local mtime=0 - currenttime=$(date +"%s") - case $(uname) in - Darwin) mtime=$(stat -f %m $fic);; - Linux) mtime=$(stat --printf %Y $fic);; - *) mtime=$(stat --printf %Y $fic);; - esac - (( $currenttime - $mtime < 2 )) -} - -checkfile=".last_watched" -((ONCE == 0)) && \ - [[ -e $checkfile ]] && \ - isRecentlyModified $checkfile && \ - error "Wait at least 2 second if you killed the process" - -execIfChanged() { - isRecentlyModified $1 && { print -- "$cmd $1"; eval "$cmd $1"} -} - -typeset -A listFic -while true; do - listFic=() - for d in $listDir; do - if [[ -d $d ]]; then - for fic in $d/**/*(.); do - execIfChanged $fic - done - else - execIfChanged $d - fi - done - ((ONCE == 1)) && break - touch $checkfile - sleep 2 -done +./watch ./gen *.html 10_Introduction diff --git a/parsec/watch b/parsec/watch new file mode 100755 index 0000000..6300957 --- /dev/null +++ b/parsec/watch @@ -0,0 +1,55 @@ +#!/usr/bin/env zsh + +error(){print -- $* >&2; exit 1} + +(($#<2)) && error "usage: ${0:t} [once] cmd dirs..." + +ONCE=0 +[[ $1 = "once" ]] && { ONCE=1; shift } + +(($#<2)) && error "usage: ${0:t} [once] cmd dirs..." + +cmd="$1" +shift + +typeset -a listDir +listDir=( $@ ) + +isRecentlyModified() { + local fic="$1" + local mtime=0 + currenttime=$(date +"%s") + case $(uname) in + Darwin) mtime=$(stat -f %m $fic);; + Linux) mtime=$(stat --printf %Y $fic);; + *) mtime=$(stat --printf %Y $fic);; + esac + (( $currenttime - $mtime < 2 )) +} + +checkfile=".last_watched" +((ONCE == 0)) && \ + [[ -e $checkfile ]] && \ + isRecentlyModified $checkfile && \ + error "Wait at least 2 second if you killed the process" + +execIfChanged() { + isRecentlyModified $1 && { print -- "$cmd $1"; eval "$cmd $1"} +} + +typeset -A listFic +while true; do + listFic=() + for d in $listDir; do + if [[ -d $d ]]; then + for fic in $d/**/*(.); do + execIfChanged $fic + done + else + execIfChanged $d + fi + done + ((ONCE == 1)) && break + touch $checkfile + sleep 2 +done