-
Notifications
You must be signed in to change notification settings - Fork 50
Support loading files from GitHub repositories #218
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 10 commits
ab89ad0
08e315a
784262c
1363393
9c7b233
a543a1b
a704404
6d77ab7
4b446f2
8b5f99a
cd313a8
146a6c5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,15 @@ | ||
module Try.Config where | ||
|
||
import Prelude | ||
|
||
loaderUrl :: String | ||
loaderUrl = "js/output" | ||
|
||
compileUrl :: String | ||
compileUrl = "http://localhost:8081" | ||
|
||
mainGist :: String | ||
mainGist = "7ad2b2eef11ac7dcfd14aa1585dd8f69" | ||
tag :: String | ||
tag = "load-from-github" | ||
|
||
mainGitHubExample :: String | ||
mainGitHubExample = "/purescript/trypurescript/" <> tag <> "/client/examples/Main.purs" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,15 @@ | ||
module Try.Config where | ||
|
||
import Prelude | ||
|
||
loaderUrl :: String | ||
loaderUrl = "https://compile.purescript.org/output" | ||
|
||
compileUrl :: String | ||
compileUrl = "https://compile.purescript.org" | ||
|
||
mainGist :: String | ||
mainGist = "7ad2b2eef11ac7dcfd14aa1585dd8f69" | ||
tag :: String | ||
tag = "load-from-github" | ||
|
||
mainGitHubExample :: String | ||
mainGitHubExample = "/purescript/trypurescript/" <> tag <> "/client/examples/Main.purs" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
module Main where | ||
|
||
import Prelude | ||
|
||
import Effect.Console (logShow) | ||
import Data.Map (Map, lookup, singleton) | ||
import TryPureScript (render, withConsole) | ||
|
||
-- | A Name consists of a first name and a last name | ||
data Name = Name String String | ||
|
||
-- | With compiler versions >= 0.8.2, we can derive | ||
-- | instances for Eq and Ord, making names comparable. | ||
derive instance eqName :: Eq Name | ||
derive instance ordName :: Ord Name | ||
|
||
-- | The Ord instance allows us to use Names as the | ||
-- | keys in a Map. | ||
phoneBook :: Map Name String | ||
phoneBook = singleton (Name "John" "Smith") "555-555-1234" | ||
|
||
main = render =<< withConsole do | ||
logShow (lookup (Name "John" "Smith") phoneBook) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module Main where | ||
|
||
import Prelude | ||
import Control.MonadPlus (guard) | ||
import Effect.Console (logShow) | ||
import Data.Array ((..)) | ||
import Data.Foldable (for_) | ||
import TryPureScript | ||
|
||
-- Find Pythagorean triples using an array comprehension. | ||
triples :: Int -> Array (Array Int) | ||
triples n = do | ||
z <- 1 .. n | ||
y <- 1 .. z | ||
x <- 1 .. y | ||
guard $ x * x + y * y == z * z | ||
pure [x, y, z] | ||
|
||
main = render =<< withConsole do | ||
for_ (triples 20) logShow |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
module Main where | ||
|
||
import Prelude | ||
import Effect.Console (logShow) | ||
import Data.Generic.Rep (class Generic) | ||
import Data.Eq.Generic (genericEq) | ||
import Data.Ord.Generic (genericCompare) | ||
import Data.Show.Generic (genericShow) | ||
import TryPureScript (render, withConsole) | ||
|
||
data Address = Address | ||
{ city :: String | ||
, state :: String | ||
} | ||
|
||
data Person = Person | ||
{ first :: String | ||
, last :: String | ||
, address :: Address | ||
} | ||
|
||
-- Generic instances can be derived by the compiler, | ||
-- using the derive keyword: | ||
derive instance genericAddress :: Generic Address _ | ||
|
||
derive instance genericPerson :: Generic Person _ | ||
|
||
-- Now we can write instances for standard type classes | ||
-- (Show, Eq, Ord) by using standard definitions | ||
instance showAddress :: Show Address where | ||
show = genericShow | ||
|
||
instance eqAddress :: Eq Address where | ||
eq = genericEq | ||
|
||
instance ordAddress :: Ord Address where | ||
compare = genericCompare | ||
|
||
instance showPerson :: Show Person where | ||
show = genericShow | ||
|
||
instance eqPerson :: Eq Person where | ||
eq = genericEq | ||
|
||
instance ordPerson :: Ord Person where | ||
compare = genericCompare | ||
|
||
main = render =<< withConsole do | ||
logShow $ Person | ||
{ first: "John" | ||
, last: "Smith" | ||
, address: Address | ||
{ city: "Faketown" | ||
, state: "CA" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
module Main where | ||
|
||
import Prelude | ||
|
||
import Effect.Console (log) | ||
import Data.Array ((..)) | ||
import Data.Foldable (for_) | ||
import TryPureScript (render, withConsole) | ||
|
||
main = render =<< withConsole do | ||
for_ (10 .. 1) \n -> log (show n <> "...") | ||
log "Lift off!" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
module Main where | ||
|
||
import Prelude | ||
|
||
import Data.Foldable (fold) | ||
import Effect (Effect) | ||
import TryPureScript (h1, h2, p, text, list, indent, link, render, code) | ||
|
||
main :: Effect Unit | ||
main = | ||
render $ fold | ||
[ h1 (text "Try PureScript!") | ||
, p (text "Try out the examples below, or create your own!") | ||
, h2 (text "Examples") | ||
, list (map fromExample examples) | ||
, h2 (text "Share Your Code") | ||
, p (text "A PureScript file can be loaded from GitHub from a gist or a repository. To share code using a gist, simply include the gist ID in the URL as follows:") | ||
, indent (p (code (text " try.purescript.org?gist=gist-id"))) | ||
, p (fold | ||
[ text "The Gist should contain PureScript modulenamed " | ||
thomashoneyman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
, code (text "Main") | ||
, text "in a file named " | ||
, code (text "Main.purs") | ||
, text " containing your PureScript code." | ||
]) | ||
, p (text "To share code from a repository, include the path to the source file the URL as follows:") | ||
, indent (p (code (text " try.purescript.org?github=/owner/repo/Source.purs"))) | ||
thomashoneyman marked this conversation as resolved.
Show resolved
Hide resolved
|
||
, p (fold | ||
[ text "The file should be a PureScript module named " | ||
, code (text "Main") | ||
, text " containing your PureScript code." | ||
]) | ||
] | ||
where | ||
fromExample { title, source } = | ||
link ("https://github.com/purescript/trypurescript/load-from-github/client/examples/" <> source) (text title) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this ought to use a tag from some kind of configuration rather than hardcoding the branch name, so that we can change these without breaking the currently released version. In practice we will want this to be the tag from the current version. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yea — I could thread this in as an argument to main, so that it can be accessed in various places taken from outside the PureScript code. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sounds good 👍 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I could also do that with the entire dev / prod configurations in that case — thoughts? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If that makes the overall setup simpler, sure, I don't see why not. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. On second thought, doing this would require some kind of text replacement processing pass to work. After all, this example is code loaded literally into the Try PureScript editor. Otherwise, we'd have to do something like read the current tag from data in the index.html file or something like that, but this would be user-visible code and I'm not a huge fan of that. Another option is to manually hard-code the tag as part of the release process and document where the tag would need to be updated -- we release so infrequently that this feels legitimately like an option. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. True - I think manually hardcoding the tag and documenting that it needs updating will work. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Perhaps we should split the repository README so that the main README is for users and there's a separate development guide. It could include instructions for developing, like we already have, but could also have a release guide which includes:
What do you think? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For now I've just added a note about the hardcoded tags to the README, but I think we probably do want a dedicated, separate development + release guide. |
||
|
||
examples = | ||
[ { title: "Algebraic Data Types" | ||
, source: "ADTs.purs" | ||
} | ||
, { title: "Loops" | ||
, source: "Loops.purs" | ||
} | ||
, { title: "Operators" | ||
, source: "Operators.purs" | ||
} | ||
, { title: "Records" | ||
, source: "Records.purs" | ||
} | ||
, { title: "Recursion" | ||
, source: "Recursion.purs" | ||
} | ||
, { title: "Do Notation" | ||
, source: "DoNotation.purs" | ||
} | ||
, { title: "Type Classes" | ||
, source: "TypeClasses.purs" | ||
} | ||
, { title: "Generic Programming" | ||
, source: "Generic.purs" | ||
} | ||
, { title: "QuickCheck" | ||
, source: "QuickCheck.purs" | ||
} | ||
] |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
module Main where | ||
|
||
import Prelude | ||
import Effect.Console (log) | ||
import TryPureScript (render, withConsole) | ||
|
||
type FilePath = String | ||
|
||
subdirectory :: FilePath -> FilePath -> FilePath | ||
subdirectory p1 p2 = p1 <> "/" <> p2 | ||
|
||
-- Functions can be given an infix alias | ||
-- The generated code will still use the original function name | ||
infixl 5 subdirectory as </> | ||
|
||
filepath :: FilePath | ||
filepath = "usr" </> "local" </> "bin" | ||
|
||
main = render =<< withConsole do | ||
log filepath |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
module Main where | ||
|
||
import Prelude | ||
import Data.Array (sort) | ||
import Test.QuickCheck (quickCheck, (===)) | ||
import TryPureScript (render, withConsole, h1, h2, p, text) | ||
|
||
main = do | ||
render $ h1 $ text "QuickCheck" | ||
render $ p $ text """QuickCheck is a Haskell library which allows us to assert properties | ||
hold for our functions. QuickCheck uses type classes to generate | ||
random test cases to verify those properties. | ||
purescript-quickcheck is a port of parts of the QuickCheck library to | ||
PureScript.""" | ||
render $ h2 $ text "Sort function is idempotent" | ||
render =<< withConsole do | ||
quickCheck \(xs :: Array Int) -> sort (sort xs) === sort xs | ||
render $ h2 $ text "Every array is sorted" | ||
render $ p $ text "This test should fail on some array which is not sorted" | ||
render =<< withConsole do | ||
quickCheck \(xs :: Array Int) -> sort xs === xs |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module Main where | ||
|
||
import Prelude | ||
import Effect.Console (log) | ||
import TryPureScript (render, withConsole) | ||
|
||
-- We can write functions which require certain record labels... | ||
showPerson o = o.lastName <> ", " <> o.firstName | ||
|
||
-- ... but we are free to call those functions with any | ||
-- additional arguments, such as "age" here. | ||
main = render =<< withConsole do | ||
log $ showPerson | ||
{ firstName: "John" | ||
, lastName: "Smith" | ||
, age: 30 | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
module Main where | ||
|
||
import Prelude | ||
import Effect.Console (logShow) | ||
import TryPureScript (render, withConsole) | ||
|
||
isOdd :: Int -> Boolean | ||
isOdd 0 = false | ||
isOdd n = isEven (n - 1) | ||
|
||
isEven :: Int -> Boolean | ||
isEven 0 = true | ||
isEven n = isOdd (n - 1) | ||
|
||
main = render =<< withConsole do | ||
logShow $ isEven 1000 | ||
logShow $ isEven 1001 |
Uh oh!
There was an error while loading. Please reload this page.