first commit
This commit is contained in:
commit
7e6b53458b
|
@ -0,0 +1,7 @@
|
|||
result
|
||||
dist-newstyle
|
||||
.cache
|
||||
_site
|
||||
*.local
|
||||
*~
|
||||
*.agdai
|
|
@ -0,0 +1,4 @@
|
|||
packages: ../achille .
|
||||
|
||||
package achille
|
||||
flags: +pandoc
|
|
@ -0,0 +1,80 @@
|
|||
body {
|
||||
font-family: sans-serif;
|
||||
font-size: 13px;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
padding: 1em;
|
||||
display: grid;
|
||||
box-sizing: border-box;
|
||||
justify-content: center;
|
||||
line-height: 1.54;
|
||||
min-height: 100vh;
|
||||
background: #dce0df;
|
||||
grid-template: "a m" 1fr
|
||||
"f f" / 240px 1fr;
|
||||
gap: 2em;
|
||||
}
|
||||
|
||||
a {
|
||||
/* text-decoration-line: overline; */
|
||||
text-decoration-thickness: 1px;
|
||||
text-decoration-color: rgba(0, 0, 0, 0.2);
|
||||
transition: .5s text-decoration-color;
|
||||
}
|
||||
|
||||
a:hover {
|
||||
text-decoration-color: rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
ul {
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
/* aside info */
|
||||
#summary img {
|
||||
border-radius: 2px;
|
||||
max-width: 100%;
|
||||
display: block;
|
||||
}
|
||||
#summary figure { margin: 0 0 1em; }
|
||||
#summary table td:first-child {
|
||||
padding-right: 1em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
/* pubs list */
|
||||
#publications ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0 0 0 2em;
|
||||
position: relative;
|
||||
}
|
||||
#publications ul::before {
|
||||
content: attr(data-year);
|
||||
position: absolute;
|
||||
writing-mode: vertical-rl;
|
||||
text-orientation: upright;
|
||||
left: 0;
|
||||
top: .4em;
|
||||
line-height: 1em;
|
||||
opacity: .5;
|
||||
}
|
||||
#publications p { margin: 0; }
|
||||
#publications li+li {margin: 1em 0 0}
|
||||
#publications .title a {
|
||||
text-decoration: none;
|
||||
color: #000;
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
}
|
||||
#publications .buttons a {
|
||||
display: inline-block;
|
||||
text-decoration: none;
|
||||
border: 1px solid #666;
|
||||
font-size: .8em;
|
||||
padding: 0 .5em;
|
||||
border-radius: 4px;
|
||||
}
|
||||
#publications .buttons a+a {
|
||||
margin: 0 0 0 .5em;
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
## Lucas Escot
|
||||
|
||||
As of 2022, I am a PhD student at [TU Delft](https://tudelft.nl),
|
||||
in the [Programming Languages Group](https://pl.ewi.tudelft.nl/),
|
||||
under the supervision of Jesper Cockx. My work revolves around generic programming
|
||||
in dependently-typed languages.
|
||||
|
||||
## Misc
|
||||
|
||||
I use to enjoy drawing, and you can find some of my works on
|
||||
[acatalepsie.fr](https://acatalepsie.fr). With a group of friends we run the
|
||||
[sbi.re](https://sbi.re) network, for which we self-host a bunch of services.
|
||||
It is here that I host my [personal blog](https://sbi.re/~lucas) where I ramble on the most --- which is, not a lot --- in French.
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,28 @@
|
|||
- title: Practical generic programming over a universe of native datatypes
|
||||
slug: generics-agda-2022
|
||||
authors:
|
||||
- Lucas Escot
|
||||
- name: Jesper Cockx
|
||||
url: https://jesper.sikanda.be
|
||||
file: papers/generics-agda-icfp22.pdf
|
||||
doi: "10.1145/3547644"
|
||||
venue:
|
||||
name: ICFP 2022
|
||||
url: https://icfp22.sigplan.org/
|
||||
|
||||
- title: "Reasonable Agda is correct Haskell: Writing verified Haskell using agda2hs"
|
||||
slug: agda2hs-2022
|
||||
authors:
|
||||
- name: Jesper Cockx
|
||||
url: https://jesper.sikanda.be
|
||||
- name: Orestis Melkonian
|
||||
url: http://omelkonian.github.io/
|
||||
- Lucas Escot
|
||||
- name: James Chapman
|
||||
url: https://jmchapman.io
|
||||
- Ulf Norell
|
||||
file: papers/agda2hs-haskell22.pdf
|
||||
doi: "10.1145/3546189.3549920"
|
||||
venue:
|
||||
name: Haskell 2022
|
||||
url: https://www.haskell.org/haskell-symposium/2022/
|
|
@ -0,0 +1,36 @@
|
|||
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||
|
||||
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
|
||||
=vIQQ
|
||||
-----END PGP PUBLIC KEY BLOCK-----
|
Binary file not shown.
After Width: | Height: | Size: 43 KiB |
|
@ -0,0 +1,9 @@
|
|||
<!-- <figure><img src="/profile.webp"></figure> -->
|
||||
|
||||
--------- ---------------------------------------
|
||||
Mail [lucas@escot.me](mailto:lucas@escot.me)
|
||||
Phone (+33) 6 88 62 63 86
|
||||
GPG [lescot.gpg](/lescot.gpg)
|
||||
Github [flupe](https://github.com/flupe)
|
||||
Sourcehut [flupe](https://sr.ht/~flupe)
|
||||
--------- ---------------------------------------
|
|
@ -0,0 +1,42 @@
|
|||
cabal-version: >=1.10
|
||||
name: escot
|
||||
version: 0.1.0.0
|
||||
author: flupe
|
||||
maintainer: lucas@escot.me
|
||||
build-type: Simple
|
||||
|
||||
executable escot
|
||||
main-is: Main.hs
|
||||
hs-source-dirs: src
|
||||
other-modules: Config
|
||||
build-depends: base
|
||||
, filepath
|
||||
, achille
|
||||
, data-default
|
||||
, pandoc
|
||||
, pandoc-types
|
||||
, text
|
||||
, bytestring
|
||||
, filepath
|
||||
, aeson
|
||||
, yaml
|
||||
, binary
|
||||
, containers
|
||||
, sort
|
||||
, feed
|
||||
, time
|
||||
, lucid
|
||||
, optparse-applicative
|
||||
, process
|
||||
, directory
|
||||
default-extensions: BlockArguments
|
||||
, TupleSections
|
||||
, OverloadedStrings
|
||||
, ScopedTypeVariables
|
||||
, DeriveGeneric
|
||||
, DeriveAnyClass
|
||||
, RecordWildCards
|
||||
, NamedFieldPuns
|
||||
ghc-options: -threaded
|
||||
-j8
|
||||
default-language: Haskell2010
|
|
@ -0,0 +1,39 @@
|
|||
module Config (config, ropts, wopts, SiteConfig(..), def) where
|
||||
|
||||
import Data.Default
|
||||
import Data.Text (Text)
|
||||
import Text.Pandoc.Options as Pandoc
|
||||
import Achille (Config(..))
|
||||
|
||||
|
||||
config :: Achille.Config
|
||||
config = def
|
||||
{ deployCmd = Just $ "rsync -avzzr " <> root <> "_site/ --chmod=755 acatalepsie:/var/www/html"
|
||||
, contentDir = root <> "content"
|
||||
, outputDir = root <> "_site"
|
||||
, cacheFile = root <> ".cache"
|
||||
-- , ignore = [ "**/*.agdai"
|
||||
-- , "**/*~"
|
||||
-- ]
|
||||
} where root = "/home/flupe/dev/site/"
|
||||
|
||||
|
||||
ropts :: Pandoc.ReaderOptions
|
||||
ropts = def { readerExtensions = pandocExtensions }
|
||||
|
||||
wopts :: Pandoc.WriterOptions
|
||||
wopts = def { writerHTMLMathMethod = KaTeX "" }
|
||||
|
||||
|
||||
data SiteConfig = SiteConfig
|
||||
{ title :: Text
|
||||
, description :: Text
|
||||
, image :: Text
|
||||
}
|
||||
|
||||
instance Default SiteConfig where
|
||||
def = SiteConfig
|
||||
{ title = "sbbls"
|
||||
, description = "my personal web space, for your enjoyment"
|
||||
, image = "https://acatalepsie.fr/assets/card.png"
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
{-# LANGUAGE LambdaCase, TypeSynonymInstances, FlexibleInstances, MultiParamTypeClasses, OverloadedStrings #-}
|
||||
{-# LANGUAGE DuplicateRecordFields #-}
|
||||
|
||||
module Main where
|
||||
|
||||
import GHC.Generics (Generic)
|
||||
import Data.Aeson (FromJSON)
|
||||
import Data.Binary (Binary)
|
||||
import Control.Monad ((>=>))
|
||||
import System.FilePath
|
||||
import Data.Text (Text)
|
||||
import Data.List (intersperse)
|
||||
import Lucid
|
||||
import Data.Yaml
|
||||
import Control.Applicative ((<|>))
|
||||
|
||||
import Achille
|
||||
import Achille.Writable (Writable)
|
||||
import qualified Achille.Writable as Writable
|
||||
import Achille.Internal.IO (AchilleIO)
|
||||
|
||||
import Achille.Task.Pandoc
|
||||
|
||||
import Data.Functor
|
||||
import Config (config, ropts, wopts, SiteConfig(title))
|
||||
import Text.Pandoc.Options
|
||||
|
||||
|
||||
-- Bibliography info
|
||||
|
||||
data Author = Author
|
||||
{ name :: Text
|
||||
, url :: Maybe Text
|
||||
, orcid :: Maybe Text
|
||||
} deriving (Eq, Show, Generic, Binary)
|
||||
|
||||
instance FromJSON Author where
|
||||
parseJSON o =
|
||||
withObject "Author info"
|
||||
(\v -> Author <$> v .: "name"
|
||||
<*> v .:? "url"
|
||||
<*> v .:? "orcid") o
|
||||
<|> withText "Author name" (\n -> pure $ Author n Nothing Nothing) o
|
||||
|
||||
data Venue = Venue
|
||||
{ name :: Text
|
||||
, url :: Text
|
||||
} deriving (Eq, Show, Generic, Binary, FromJSON)
|
||||
|
||||
data Publication = Publication
|
||||
{ title :: Text
|
||||
, slug :: Text
|
||||
, authors :: [Author]
|
||||
, file :: Maybe Text
|
||||
, doi :: Maybe Text
|
||||
, venue :: Venue
|
||||
} deriving (Eq, Show, Generic, Binary, FromJSON)
|
||||
|
||||
parseYaml :: (AchilleIO m, FromJSON a) => FilePath -> Task m a
|
||||
parseYaml p = do
|
||||
res <- decodeEither' <$> readBS p
|
||||
case res of
|
||||
Left err -> fail (prettyPrintParseException err)
|
||||
Right ok -> return ok
|
||||
|
||||
|
||||
-- compile markdown with custom options and extensions
|
||||
compileMD = compilePandocWith def { readerExtensions = pandocExtensions } def
|
||||
|
||||
-- writing Html to disk (efficiently)
|
||||
instance AchilleIO m => Writable m (Html ()) where
|
||||
write to = Writable.write to . renderBS
|
||||
|
||||
|
||||
main = achille do
|
||||
match_ "assets/*" $ copyFile
|
||||
match_ "static/*" $ copyFileAs (makeRelative "static/")
|
||||
match_ "papers/*" $ copyFile
|
||||
|
||||
summary <- matchFile "summary.md" compileMD
|
||||
pubs :: [Publication] <- matchFile "publications.yaml" parseYaml
|
||||
|
||||
watch summary $ watch pubs $ match_ "index.md" \src -> do
|
||||
compileMD src
|
||||
<&> renderIndex summary (renderPublications pubs)
|
||||
>>= write (src -<.> "html")
|
||||
|
||||
-- TODO: fix year
|
||||
renderPublications :: [Publication] -> Html ()
|
||||
renderPublications pubs = section_ [ id_ "publications" ] do
|
||||
h2_ "Publications"
|
||||
ul_ [ data_ "year" "2022" ] $ foldMap renderPub pubs
|
||||
where renderPub :: Publication -> Html ()
|
||||
renderPub Publication {..} = li_ [id_ slug] do
|
||||
p_ [class_ "title"] $ a_ [href_ ("#" <> slug)] $ toHtmlRaw title
|
||||
p_ [class_ "authors"] $ renderAuthors (reverse (fmap renderAuthor authors))
|
||||
let Venue vName vUrl = venue
|
||||
p_ [class_ "venue"] $ a_ [href_ vUrl] $ toHtmlRaw vName
|
||||
p_ [class_ "buttons"] do
|
||||
maybe mempty (\url -> a_ [href_ ("/" <> url)] "PDF") file
|
||||
maybe mempty (\doi -> a_ [href_ ("https://doi.org/" <> doi)] "DOI") doi
|
||||
|
||||
renderAuthor :: Author -> Html ()
|
||||
renderAuthor (Author name url orcid) =
|
||||
case url of
|
||||
Nothing -> toHtmlRaw name
|
||||
Just url -> a_ [href_ url] (toHtmlRaw name)
|
||||
|
||||
renderAuthors :: [Html ()] -> Html ()
|
||||
renderAuthors [] = mempty
|
||||
renderAuthors [one] = one
|
||||
renderAuthors (last:others) =
|
||||
mconcat (intersperse ", " (reverse others)) <> " and " <> last
|
||||
|
||||
renderIndex :: Text -> Html () -> Text -> Html ()
|
||||
renderIndex summary pubs body =
|
||||
doctypehtml_ do
|
||||
head_ do
|
||||
meta_ [ name_ "viewport"
|
||||
, content_ "width=device-width, initial-scale=1.0, user-scalable=yes"
|
||||
]
|
||||
meta_ [ name_ "theme-color", content_ "#000000" ]
|
||||
meta_ [ name_ "robots", content_ "index, follow" ]
|
||||
meta_ [ charset_ "utf-8" ]
|
||||
link_ [ rel_ "stylesheet", href_ "/assets/theme.css" ]
|
||||
link_ [ rel_ "shortcut icon"
|
||||
, type_ "image/svg"
|
||||
, href_ "/assets/favicon.svg"
|
||||
]
|
||||
-- meta_ [ property_ "og:title", content_ title ]
|
||||
-- meta_ [ property_ "og:type", content_ "website" ]
|
||||
-- meta_ [ property_ "og:image", content_ image ]
|
||||
-- meta_ [ property_ "og:description", content_ description ]
|
||||
title_ "Lucas Escot"
|
||||
|
||||
body_ do
|
||||
aside_ [id_ "summary"] $ toHtmlRaw summary
|
||||
main_ do
|
||||
section_ $ toHtmlRaw body
|
||||
pubs
|
||||
footer_ do
|
||||
"2021 · "
|
||||
a_ [ href_ "https://creativecommons.org/licenses/by-nc/2.0/" ]
|
||||
"CC BY-NC 2.0"
|
Loading…
Reference in New Issue