summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2020-03-31 17:12:09 -0700
committerBen Sima <ben@bsima.me>2020-03-31 17:12:09 -0700
commit9493e2dbf9671d55fea2a96aa057589670e9673a (patch)
tree6702a9bc37826d8fd1f522a7ab16a7a2b696447d
parent721cca4b1372e222c6841ddc57bb952271d72dc7 (diff)
Massively improve the que-website
curl was throwing an exception if the file got too long, because I was passing the entire file contents in the arguments to curl. I tried using a tmp file but that didn't work for some reason. So I switched to req and that seems to work well. I also made it faster by serving all pages concurrently, and I spruced up the CSS a ton.
-rw-r--r--Run/Que/Website.hs102
-rw-r--r--Run/Que/index.md47
-rw-r--r--Run/Que/quescripts.md38
-rw-r--r--Run/Que/style.css114
-rw-r--r--default.nix7
5 files changed, 230 insertions, 78 deletions
diff --git a/Run/Que/Website.hs b/Run/Que/Website.hs
index 1de6bca..e6b458c 100644
--- a/Run/Que/Website.hs
+++ b/Run/Que/Website.hs
@@ -1,45 +1,77 @@
+{-# LANGUAGE RecordWildCards #-}
+{-# LANGUAGE NoImplicitPrelude #-}
+{-# LANGUAGE LambdaCase #-}
+
-- | spawns a few processes that serve the que.run website
module Run.Que.Website where
-import Prelude
+import qualified Control.Concurrent.Async as Async
+import qualified Data.ByteString.Char8 as BS
+import qualified Data.Text as Text
+import Network.HTTP.Req
+import Protolude
import System.Environment as Environment
import System.FilePath ( (</>) )
import qualified System.Process as Process
+import qualified System.Exit as Exit
main :: IO ()
main = do
- args <- Environment.getArgs
- let [src, ns] = if length args == 2
- then take 2 args
- else if length args == 1
- then args ++ ["/"]
- else error "usage: que-website <srcdir> [namespace]"
- homepage <- getHomepageHtml (src </> "style.css") (src </> "index.md")
- client <- readFile $ src </> "client.py"
+ (src, ns) <- Environment.getArgs >>= \case
+ [src] -> return (src, "/")
+ [src, ns] -> return (src, ns)
+ _ -> Exit.die "usage: que-website <srcdir> [namespace]"
+
putStrLn $ "serving " ++ src ++ " at " ++ ns
- loop ns homepage client
-
-loop :: String -> FilePath -> FilePath -> IO ()
-loop ns homepage client =
- serve (ns </> "index.html") homepage
- >> serve (ns </> "_client/python") client
- >> loop ns homepage client
-
-getHomepageHtml :: String -> String -> IO String
-getHomepageHtml style index = Process.readProcess
- "pandoc"
- [ "--self-contained"
- , "--css"
- , style
- , "-i"
- , index
- , "--from"
- , "markdown"
- , "--to"
- , "html"
- ]
- []
-
-serve :: FilePath -> FilePath -> IO ()
-serve path file =
- Process.callProcess "curl" ["https://que.run" ++ path, "-d", file]
+ loop (Text.pack ns) $ Sources { index = src </> "index.md"
+ , client = src </> "client.py"
+ , quescripts = src </> "quescripts.md"
+ , style = src </> "style.css"
+ }
+
+data Sources = Sources
+ { index :: FilePath
+ , quescripts :: FilePath
+ , client :: FilePath
+ , style :: FilePath
+ }
+
+loop :: Text -> Sources -> IO ()
+loop ns pages@Sources {..} = do
+ _ <-
+ Async.runConcurrently
+ $ (,,,)
+ <$> Async.Concurrently
+ (toHtml style index >>= serve (https "que.run" /: ns /: "index.html"))
+ <*> Async.Concurrently
+ ( BS.readFile client
+ >>= serve (https "que.run" /: ns /: "_client" /: "python")
+ )
+ <*> Async.Concurrently
+ ( toHtml style quescripts
+ >>= serve (https "que.run" /: ns /: "_page" /: "quescripts")
+ )
+ loop ns pages
+
+
+toHtml :: FilePath -> FilePath -> IO ByteString
+toHtml style md =
+ BS.pack
+ <$> Process.readProcess
+ "pandoc"
+ [ "--self-contained"
+ , "--css"
+ , style
+ , "-i"
+ , md
+ , "--from"
+ , "markdown"
+ , "--to"
+ , "html"
+ ]
+ []
+
+serve :: Url scheme -> ByteString -> IO ()
+serve path content = runReq defaultHttpConfig $ do
+ _ <- req POST path (ReqBodyBs content) ignoreResponse mempty
+ liftIO $ return ()
diff --git a/Run/Que/index.md b/Run/Que/index.md
index b619de7..59a7ad8 100644
--- a/Run/Que/index.md
+++ b/Run/Que/index.md
@@ -12,7 +12,7 @@ que is the concurrent, async runtime in the cloud
HTTP routes on que.run are Golang-like channels with a namespace and a
path. For example: `https://que.run/example/path/subpath`.
-## download the client
+## Quickstart
There is a simple script `que` that acts as a client you can use to
interact with the `que.run` service.
@@ -25,44 +25,13 @@ Download it to somewhere on your `$PATH` and make it executable:
The client requires a recent version of Python 3.
-## examples
+## Quescripts
-Here are some example applications, I will update these in the coming
-weeks with additional useful scripts.
+We are collecting a repository of scripts that make awesome use of que:
-### desktop notifications
+- remote desktop notifications
+- two-way communication with your phone
+- ephemeral, serverless chat rooms
+- collaborative jukebox
-Lets say we are running a job that takes a long time, maybe we are
-compiling or running a large test suite. Instead of watching the
-terminal until it completes, or flipping back to check on it every so
-often, we can create a listener that displays a popup notification when
-the job finishes.
-
-In one terminal run the listener:
-
- que example/notify --then "notify-send '\que' '\msg'"
-
-In some other terminal run the job that takes forever:
-
- runtests ; echo "tests are done" | que example/notify -
-
-When terminal 2 succeeds, terminal 1 will print "tests are done", then
-call the `notify-send` command, which displays a notification toast in
-Linux with title "`example/notify`" and content "`tests are done`".
-
-Que paths are multi-producer and multi-consumer, so you can add as many
-terminals as you want.
-
-On macOS you could use:
-
- osascript -e 'display notification "\msg" with title "\que"'
-
-in place of notify-send.
-
-### ephemeral, serverless chat rooms
-
-coming soon...
-
-### collaborative jukebox
-
-coming soon...
+<a id="quescripts-btn" href="_page/quescripts">See the examples</a>
diff --git a/Run/Que/quescripts.md b/Run/Que/quescripts.md
new file mode 100644
index 0000000..204328a
--- /dev/null
+++ b/Run/Que/quescripts.md
@@ -0,0 +1,38 @@
+% Quescripts
+
+## Remote desktop notifications
+
+Lets say we are running a job that takes a long time, maybe we are
+compiling or running a large test suite. Instead of watching the
+terminal until it completes, or flipping back to check on it every so
+often, we can create a listener that displays a popup notification when
+the job finishes.
+
+In one terminal run the listener:
+
+ que example/notify --then "notify-send '\que' '\msg'"
+
+In some other terminal run the job that takes forever:
+
+ runtests ; echo "tests are done" | que example/notify -
+
+When terminal 2 succeeds, terminal 1 will print "tests are done", then
+call the `notify-send` command, which displays a notification toast in
+Linux with title "`example/notify`" and content "`tests are done`".
+
+Que paths are multi-producer and multi-consumer, so you can add as many
+terminals as you want.
+
+On macOS you could use:
+
+ osascript -e 'display notification "\msg" with title "\que"'
+
+in place of notify-send.
+
+## Ephemeral, serverless chat rooms
+
+coming soon
+
+## Collaborative jukebox
+
+coming soon
diff --git a/Run/Que/style.css b/Run/Que/style.css
index fa73fa4..1933a5d 100644
--- a/Run/Que/style.css
+++ b/Run/Que/style.css
@@ -1,4 +1,112 @@
-/* perfect motherfucking css framework */
-body{max-width:650px;margin:40px auto;padding:0 10px;font:18px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";color:#444}h1,h2,h3{line-height:1.2}@media (prefers-color-scheme: dark){body{color:white;background:#444}a:link{color:#5bf}a:visited{color:#ccf}}
+:root {
+ /* base (http://chriskempson.com/projects/base16/) */
+ --base00: #181818;
+ --base01: #282828;
+ --base02: #383838;
+ --base03: #585858;
+ --base04: #b8b8b8;
+ --base05: #d8d8d8;
+ --base06: #e8e8e8;
+ --base07: #f8f8f8;
-/* my stuff */
+ /* highlights */
+ --base08: #ab4642;
+ --base09: #dc9656;
+ --base0A: #f7ca88;
+ --base0B: #a1b56c;
+ --base0C: #86c1b9;
+ --base0D: #7cafc2;
+ --base0E: #ba8baf;
+ --base0F: #a16946;
+}
+
+@import 'https://fonts.googleapis.com/css?family=Galada:400|Open+Sans:400,300';
+
+/* dark theme */
+@media ( prefers-color-scheme: dark ), ( prefers-color-scheme: no-preference ) {
+ body
+ { color: var(--base05);
+ ; background: var(--base00)
+ }
+
+ header, h1, h2, h3
+ { color: var(--base0A) }
+
+ a:link, a:link button, a:visited, a:visited button
+ { color: var(--base0D) }
+
+ a:hover
+ { color: var(--base0C) }
+
+ pre
+ { background-color: var(--base01) }
+
+ code
+ { color: var(--base0B)
+ }
+}
+
+/* light theme */
+
+@media ( prefers-color-scheme: light) {
+ body
+ { background-color: var(--base07)
+ ; color: var(--base00)
+ }
+
+ pre
+ { background-color: var(--base06) }
+
+ code
+ { color: var(--base0B) }
+}
+
+/* structure and layout */
+
+body
+{ max-width: 650px
+; margin: 40px auto
+; padding: 0 10px
+; font: 18px/1.5
+ "Open Sans",
+ sans-serif,
+ "Apple Color Emoji",
+ "Segoe UI Emoji",
+ "Segoe UI Symbol",
+ "Noto Color Emoji"
+; display: flex
+; flex-direction: column
+; align-items: auto
+}
+
+header#title-block-header,
+h1,
+h2,
+h3
+{ line-height: 1.2
+; align-self: center
+; text-transform: lowercase
+}
+
+pre
+{ padding: .5rem }
+
+pre,code
+{ overflow-x: scroll
+; white-space: pre
+}
+
+#quescripts-btn
+{ border-width: 2px
+; border-style: solid
+}
+
+#quescripts-btn
+{ font-size: 1.2rem
+; padding: 1rem
+; text-decoration: none
+; text-align: center
+; display: block
+; max-width: 400px
+; margin: auto
+}
diff --git a/default.nix b/default.nix
index 13ded48..5622c74 100644
--- a/default.nix
+++ b/default.nix
@@ -176,6 +176,11 @@ in rec {
Run.Que.Website = buildGhc {
name = "Run.Que.Website";
nick = "que-website";
- deps = [ "process" ];
+ deps = [
+ "async"
+ "process"
+ "protolude"
+ "req"
+ ];
};
}