diff --git a/editor/elm-package.json b/editor/elm-package.json index ea42e5b8e..a2a712d8c 100644 --- a/editor/elm-package.json +++ b/editor/elm-package.json @@ -1,6 +1,6 @@ { "version": "1.0.0", - "summary": "w00t", + "summary": "Front-end for the Unison editor", "repository": "https://github.com/USER/PROJECT.git", "license": "MIT", "source-directories": [ @@ -8,9 +8,9 @@ ], "exposed-modules": ["Messages"], "native-modules" : true, + "elm-version" : "0.15.0 <= v < 0.16.0", "dependencies": { - "elm-lang/core" : "1.0.0 <= v < 2.0.0", - "Dandandan/Easing" : "1.0.1 <= v < 2.0.0", - "Dandandan/parser" : "5.0.1 <= v < 6.0.0" + "elm-lang/core" : "2.0.0 <= v < 3.0.0", + "evancz/elm-http" : "1.0.0 <= v < 2.0.0" } } diff --git a/editor/src/Elmz/Json/Decoder.elm b/editor/src/Elmz/Json/Decoder.elm index d744143e6..a53b17527 100644 --- a/editor/src/Elmz/Json/Decoder.elm +++ b/editor/src/Elmz/Json/Decoder.elm @@ -2,10 +2,10 @@ module Elmz.Json.Decoder where import Dict as M import Json.Decode as J -import Json.Decode (Decoder, andThen) +import Json.Decode exposing (Decoder, andThen) import List import Set -import Set (Set) +import Set exposing (Set) import String as S type alias Decoder a = J.Decoder a diff --git a/editor/src/Elmz/Json/Request.elm b/editor/src/Elmz/Json/Request.elm index 7557d2843..a30981a9e 100644 --- a/editor/src/Elmz/Json/Request.elm +++ b/editor/src/Elmz/Json/Request.elm @@ -1,27 +1,31 @@ module Elmz.Json.Request where -import Elmz.Json.Encoder (Encoder) +import Elmz.Json.Encoder exposing (Encoder) import Elmz.Json.Encoder as Encoder -import Elmz.Json.Decoder (Decoder) +import Elmz.Json.Decoder exposing (Decoder) import Elmz.Json.Decoder as Decoder import Elmz.Signal as Signals import Http import Maybe import Result import Signal +import Task exposing (Task) import Time type alias Request a b = - { encoder : a -> Http.Request String + { encoder : a -> Out String , decoder : Decoder b } +type alias Out a = { verb : String, url : String, body : a } type alias Host = String type alias Path = String type Status e = Inactive | Waiting | Failed e post : Host -> Path -> Encoder a -> Decoder b -> Request a b -post host path e d = Request (jsonPost e host path) d +post host path e d = + let out a = Out "POST" (host ++ "/" ++ path) (Encoder.render e a) + in Request out d contramap : (a0 -> a) -> Request a b -> Request a0 b contramap f r = { r | encoder <- r.encoder << f } @@ -32,35 +36,7 @@ map f r = { r | decoder <- Decoder.map f r.decoder } to : Request a b -> (b -> c) -> Request a c to r f = map f r -send : Request a b -> a -> Signal (Maybe a) -> Signal (Result (Status String) b) -send r az ma = - let a = Signals.justs ma |> Signal.map (Maybe.withDefault az) - waitings = Signal.map (always (Result.Err Waiting)) a - results = Http.send (Signal.map r.encoder a) |> Signal.map (decodeResponse r.decoder) - inactives = Signal.map (always (Result.Err Inactive)) (Time.delay 0 results) - in results `Signal.merge` inactives `Signal.merge` waitings - -isWaiting : Signal (Result (Status String) a) -> Signal Bool -isWaiting results = - let f r = case r of - Result.Err Waiting -> True - _ -> False - in Signal.map f results - -jsonGet : Encoder a -> Host -> String -> a -> Http.Request String -jsonGet = jsonRequest "GET" - -jsonPost : Encoder a -> Host -> String -> a -> Http.Request String -jsonPost = jsonRequest "POST" - -jsonRequest : String -> Encoder a -> Host -> String -> a -> Http.Request String -jsonRequest verb ja host path a = - Http.request verb (host ++ "/" ++ path) (Encoder.render ja a) [("Content-Type", "application/json")] - -decodeResponse : Decoder a -> Http.Response String -> Result (Status String) a -decodeResponse p r = case r of - Http.Success body -> case Decoder.decodeString p body of - Result.Err e -> Result.Err (Failed e) - Result.Ok a -> Result.Ok a - Http.Waiting -> Result.Err Waiting - Http.Failure code body -> Result.Err <| Failed ("error " ++ toString code ++ "\n" ++ body) +sendPost : Request a b -> a -> Task Http.Error b +sendPost r a = + let out = r.encoder a + in Http.post r.decoder out.url (Http.string out.body) diff --git a/editor/src/Elmz/Layout.elm b/editor/src/Elmz/Layout.elm index 726a54101..8103c203e 100644 --- a/editor/src/Elmz/Layout.elm +++ b/editor/src/Elmz/Layout.elm @@ -1,12 +1,11 @@ module Elmz.Layout where -import Array (Array) +import Array exposing (Array) import Color -import Color (Color) -import Graphics.Element (Direction, Element, Position) +import Color exposing (Color) +import Graphics.Element exposing (Direction, Element, Position) import Graphics.Element as E import List -import List ((::)) import Maybe type alias Pt = { x : Int, y: Int } @@ -147,7 +146,7 @@ fill c e = container (tag e) (widthOf e) (heightOf e) (Pt 0 0) e row : List (Layout k) -> List (Layout k) row ls = case ls of [] -> [] - _ -> let maxh = List.maximum (List.map heightOf ls) + _ -> let maxh = Maybe.withDefault 0 (List.maximum (List.map heightOf ls)) cell e = let diff = maxh - heightOf e in if diff == 0 then e else container (tag e) (widthOf e) maxh (Pt 0 (toFloat diff / 2 |> floor)) e @@ -156,7 +155,7 @@ row ls = case ls of column : List (Layout k) -> List (Layout k) column ls = case ls of [] -> [] - _ -> let maxw = List.maximum (List.map widthOf ls) + _ -> let maxw = Maybe.withDefault 0 (List.maximum (List.map widthOf ls)) cell e = let diff = maxw - widthOf e in if diff == 0 then e else container (tag e) maxw (heightOf e) (Pt (toFloat diff / 2 |> floor) 0) e @@ -165,7 +164,7 @@ column ls = case ls of leftAlignedColumn : List (Layout k) -> List (Layout k) leftAlignedColumn ls = case ls of [] -> [] - _ -> let maxw = List.maximum (List.map widthOf ls) + _ -> let maxw = Maybe.withDefault 0 (List.maximum (List.map widthOf ls)) cell e = let diff = maxw - widthOf e in if diff == 0 then e else container (tag e) maxw (heightOf e) (Pt 0 0) e diff --git a/editor/src/Elmz/Matcher.elm b/editor/src/Elmz/Matcher.elm index c94456060..5ab9b31b4 100644 --- a/editor/src/Elmz/Matcher.elm +++ b/editor/src/Elmz/Matcher.elm @@ -2,7 +2,7 @@ module Elmz.Matcher where import Debug import Elmz.Moore as Moore -import Elmz.Moore (Moore(..)) +import Elmz.Moore exposing (Moore(..)) import List import String @@ -39,7 +39,7 @@ model matches = out = List.filter (matches q.string) (q.values ++ r.values) -- tricky part is determining whether we need to do another search full = r.additionalResults <= 0 - lastExamined = List.maximum (-1 :: r.positionsExamined) + lastExamined = Maybe.withDefault (-1) (List.maximum r.positionsExamined) ok = -- we already have results for this query r.query == q.string || diff --git a/editor/src/Elmz/Moore.elm b/editor/src/Elmz/Moore.elm index bd29089b3..2bcdf2a93 100644 --- a/editor/src/Elmz/Moore.elm +++ b/editor/src/Elmz/Moore.elm @@ -1,8 +1,7 @@ module Elmz.Moore where import Signal -import Signal ((<~), (~), foldp, Signal) -import List ((::)) +import Signal exposing ((<~), (~), foldp, Signal) import Maybe type Moore i o = Moore o (i -> Maybe (Moore i o)) @@ -104,46 +103,5 @@ transform m i = let s i m = feed i m in extract <~ foldp s m i -{-| Unlike `transform`, only emits events when the input transitions to a new state. -} -transitions : Moore i o -> Signal i -> Signal o -transitions m i = - let s i (m,_) = case step i m of - Nothing -> (m, False) - Just m2 -> (m2, True) - states = foldp s (m, True) i - changes = Signal.map snd states - in Signal.keepWhen changes (extract m) ((extract << fst) <~ states) - unit : o -> Moore i o unit o = Moore o (always Nothing) - -{- -withInput : i -> Moore i o -> Moore i (i,o) -withInput i0 m = map2 (,) (echo i0) m - -dropRepeats : o -> Moore o o -dropRepeats prev = Moore ((==) prev) prev dropRepeats - -foldResult : (a -> r) -> (b -> r) -> Result a b -> r -foldResult f1 f2 e = case e of - Err a -> f1 a - Ok b -> f2 b - -either : Moore a (Result x y) -> Moore x b -> Moore y b -> Moore a b -either (Moore samei xy ki) left right = - let same a = samei a && foldResult (steady left) (steady right) xy - st a = case xy of - Err x -> either (ki a) (step left x) right - Ok y -> either (ki a) left (step right y) - o = case xy of - Err x -> extract left - Ok y -> extract right - in Moore same o st - -{-| Run the first argument until it emits `Err s`, then switch permanently to `f s`. -} -bind : Moore a (Result s b) -> (s -> Moore a b) -> Moore a b -bind (Moore same sb k) f = case sb of - Err s -> f s - Ok b -> Moore same b (\a -> bind (k a) f) - --} diff --git a/editor/src/Elmz/Movement.elm b/editor/src/Elmz/Movement.elm index 187e708c9..0ce45e62c 100644 --- a/editor/src/Elmz/Movement.elm +++ b/editor/src/Elmz/Movement.elm @@ -1,7 +1,7 @@ module Elmz.Movement where import Keyboard -import Signal ((<~), (~), Signal) +import Signal exposing ((<~), (~), Signal) import Signal import Elmz.Signal as Signals import Time diff --git a/editor/src/Elmz/Parser.elm b/editor/src/Elmz/Parser.elm new file mode 100644 index 000000000..6e8082e20 --- /dev/null +++ b/editor/src/Elmz/Parser.elm @@ -0,0 +1,138 @@ +module Elmz.Parser where + +import String +import Regex + +type alias Msg = List String +type alias Status = { message : Msg, committed : Bool } + +type alias Parser a = { string : String, offset : Int } -> Result Status (a, Int) + +parse : Parser a -> String -> Result String a +parse p s = case p { string = s, offset = 0 } of + Err e -> Err (String.join "\n" e.message) + Ok (a,_) -> Ok a + +unit : a -> Parser a +unit a _ = Ok (a, 0) + +fail : Parser a +fail s = Err { message = [], committed = False } + +map : (a -> b) -> Parser a -> Parser b +map f p s = case p s of + Ok (a, consumed) -> Ok (f a, consumed) + Err e -> Err e + +(<$>) : (a -> b) -> Parser a -> Parser b +(<$>) = map + +-- note: implementation not stack safe +many : Parser a -> Parser (List a) +many a s = case a s of + Err e -> if e.committed then Err e else Ok ([],0) + Ok (hd,consumed) -> case many a { s | offset <- s.offset + consumed } of + Err e -> Err e + Ok (tl,consumedTl) -> Ok (hd :: tl, consumed + consumedTl) + +some : Parser a -> Parser (List a) +some a = (::) <$> a <*> many a + +andThen : Parser a -> (a -> Parser b) -> Parser b +andThen p f s = case p s of + Err e -> Err e + Ok (a, consumed) -> + (if consumed > 0 then commit else identity) (f a) { s | offset <- s.offset + consumed } + +commit : Parser a -> Parser a +commit p s = case p s of + Err e -> Err { e | committed <- True } + r -> r + +attempt : Parser a -> Parser a +attempt p s = case p s of + Err e -> Err { e | committed <- False } + Ok a -> Ok a + +scope : String -> Parser a -> Parser a +scope lbl p s = case p s of + Err e -> Err { e | message <- lbl :: e.message } + Ok a -> Ok a + +label : String -> Parser a -> Parser a +label lbl p s = case p s of + Err e -> Err { e | message <- [lbl] } + Ok a -> Ok a + +or : Parser a -> Parser a -> Parser a +or p p2 s = case p s of + Ok a -> Ok a + Err e -> if e.committed then Err e else p2 s + +choice : List (Parser a) -> Parser a +choice = List.foldr or fail + +ap : Parser (a -> b) -> Parser a -> Parser b +ap f a = f `andThen` \f -> map f a + +satisfy : (Char -> Bool) -> Parser String +satisfy f s = + let sub = String.slice s.offset ((String.length s.string) `max` (s.offset + 1)) s.string + in if String.all f sub then Ok (sub, 1) else Err { message = [], committed = False } + +symbol : Char -> Parser String +symbol c = satisfy ((==) c) + +token : String -> Parser String +token t s = + if String.startsWith t (String.dropLeft s.offset s.string) + then Ok (t, String.length t) + else Err { message = ["expected " ++ t], committed = False } + +reset : { string : String, offset : Int } -> { string : String, offset : Int } +reset s = { string = String.dropLeft s.offset s.string, offset = 0 } + +digits : Parser String +digits = regex "\\d+" + +nonnegativeInt : Parser Int +nonnegativeInt = digits `andThen` \s -> case String.toInt s of + Err e -> label e fail + Ok n -> unit n + +int : Parser Int +int = optional (symbol '-') `andThen` \sign -> case sign of + Nothing -> nonnegativeInt + Just _ -> map negate nonnegativeInt + +float : Parser Float +float = regex "[+-]?\\d+\\.\\d+" `andThen` \s -> case String.toFloat s of + Err e -> label e fail + Ok n -> unit n + +optional : Parser a -> Parser (Maybe a) +optional p = map Just p `or` unit Nothing + +regex : String -> Parser String +regex r s = let compiled = Regex.regex r in case reset s of + s -> case List.map .match (Regex.find (Regex.AtMost 1) compiled s.string) of + [] -> Err { message = [], committed = False } + hd :: _ -> Ok (hd, String.length hd) + +infixl 4 <*> +infixl 4 <* +infixl 4 *> +infixl 4 <$ +infixl 4 <$> + +(<*>) : Parser (a -> b) -> Parser a -> Parser b +(<*>) = ap + +(<*) : Parser a -> Parser b -> Parser a +a <* b = unit always <*> a <*> b + +(<$) : a -> Parser b -> Parser a +a <$ p = map (always a) p + +(*>) : Parser a -> Parser b -> Parser b +a *> b = unit (\_ b -> b) <*> a <*> b diff --git a/editor/src/Elmz/Selection1D.elm b/editor/src/Elmz/Selection1D.elm index 58ecc0be1..10ce90bb9 100644 --- a/editor/src/Elmz/Selection1D.elm +++ b/editor/src/Elmz/Selection1D.elm @@ -1,13 +1,13 @@ {-| One-dimensional selection model. -} module Elmz.Selection1D where -import Elmz.Layout (Containment, Layout, Region) +import Elmz.Layout exposing (Containment, Layout, Region) import Elmz.Layout as Layout import Elmz.Movement as Movement -import Elmz.Moore (Moore(..)) +import Elmz.Moore exposing (Moore(..)) import Elmz.Moore as Moore import Elmz.Signal as Signals -import Graphics.Element (Element) +import Graphics.Element exposing (Element) import Graphics.Element as Element import Maybe import Result diff --git a/editor/src/Elmz/Signal.elm b/editor/src/Elmz/Signal.elm index da5be240c..b5f4052c5 100644 --- a/editor/src/Elmz/Signal.elm +++ b/editor/src/Elmz/Signal.elm @@ -5,37 +5,20 @@ import Debug import Elmz.Maybe import Keyboard import List -import List ((::)) import Maybe -import Execute import Mouse import Result -import Set -import Signal (..) +import Set exposing (Set) +import Signal exposing (..) import Text import Time -import Time (Time) +import Time exposing (Time) {-| Accumulates into a list using `foldp` during regions where `cond` is `True`, otherwise emits the empty list. -} accumulateWhen : Signal Bool -> Signal a -> Signal (List a) accumulateWhen cond a = foldpWhen cond (::) [] a |> map List.reverse -asyncUpdate : (Signal req -> Signal (model -> (Maybe req, model))) - -> Signal (model -> (Maybe req, model)) - -> req - -> model - -> Signal model -asyncUpdate responseActions actions req0 model0 = - let reqs = channel req0 - mergedActions = merge actions (responseActions (subscribe reqs)) - step action (_,model) = - let (req, model') = action model - in (Maybe.map (send reqs) req, model') - modelsWithMsgs = foldp step (Nothing,model0) mergedActions - msgs = Execute.schedule (map (Maybe.withDefault Execute.noop) (justs (map fst modelsWithMsgs))) - in during (map snd modelsWithMsgs) msgs - {-| Alternate sending `input` through `left` or `right` signal transforms, merging their results. -} alternate : (Signal (Maybe a) -> Signal c) @@ -63,7 +46,7 @@ delay h s = {-| Only emit when the input signal transitions from `True` to `False`. -} downs : Signal Bool -> Signal Bool -downs s = dropIf identity True s +downs s = filter not True s {-| Emits an event whenever there are two events that occur within `within` time of each other. -} doubleWithin : Time -> Signal s -> Signal () @@ -73,7 +56,7 @@ doubleWithin within s = Nothing -> False Just t1 -> if t2 - t1 < within then True else False in map2 f (delay Nothing (map Just ts)) ts - |> keepIf identity False + |> filter identity False |> map (always ()) {-| Evaluate the second signal for its effects, but return the first signal. -} @@ -141,7 +124,7 @@ flattenMaybe s = fromMaybe (constant Nothing) s {-| Ignore any events of `Nothing`. -} justs : Signal (Maybe a) -> Signal (Maybe a) -justs s = keepIf (Maybe.map (always True) >> Maybe.withDefault False) Nothing s +justs s = filter (Maybe.map (always True) >> Maybe.withDefault False) Nothing s {-| Event which fires with the given `a` whenever the keycode is pressed down. -} keyEvent : a -> Int -> Signal a @@ -151,20 +134,12 @@ keyEvent k code = map (always k) (ups (Keyboard.isDown code)) keyChordEvent : a -> List Keyboard.KeyCode -> Signal a keyChordEvent k codes = let - hazTehCodez : List Keyboard.KeyCode -> Bool + hazTehCodez : Set Keyboard.KeyCode -> Bool hazTehCodez pressed = - let pressed' = Set.fromList pressed - in List.all (\k -> Set.member k pressed') codes + List.all (\k -> Set.member k pressed) codes in map (always k) (ups (map hazTehCodez Keyboard.keysDown)) -loop : (Signal a -> Signal s -> Signal (b,s)) -> s -> Signal a -> Signal b -loop f s a = - let chan = channel s - bs = f a (sampleOn a (subscribe chan)) -- Signal (b,s) - in map2 always (map fst bs) - (Execute.complete (map (\(_,s) -> send chan s) bs)) - map2r : (a -> b -> c) -> Signal a -> Signal b -> Signal c map2r f a b = sampleOn b (map2 f a b) @@ -172,39 +147,6 @@ map2r f a b = sampleOn b (map2 f a b) mask : Signal Bool -> Signal a -> Signal (Maybe a) mask = map2 (\b a -> if b then Just a else Nothing) -{-| Merge two signals, using the combining function if any events co-occcur. -} -mergeWith : (a -> a -> a) -> Signal a -> Signal a -> Signal a -mergeWith resolve left right = - let boolLeft = always True <~ left - boolRight = always False <~ right - bothUpdated = (/=) <~ merge boolLeft boolRight ~ merge boolRight boolLeft - exclusive = dropWhen bothUpdated Nothing (Just <~ merge left right) - overlap = keepWhen bothUpdated Nothing (Just <~ map2 resolve left right) - combine m1 m2 = case Maybe.oneOf [m1, m2] of - Just a -> a - Nothing -> List.head [] -- impossible - in combine <~ exclusive ~ overlap - -{-| Merge two signals, composing the functions if any events co-occcur. -} -mergeWithBoth : Signal (a -> a) -> Signal (a -> a) -> Signal (a -> a) -mergeWithBoth = mergeWith (>>) - -{-| Merge the two signals. If events co-occur, emits `(Just a, Just b)`, -otherwise emits `(Just a, Nothing)` or `(Nothing, Just b)`. -} -oneOrBoth : Signal a -> Signal b -> Signal (Maybe a, Maybe b) -oneOrBoth a b = - let combine a b = case a of - (Nothing,_) -> b - (Just a,_) -> case b of - (_, Nothing) -> (Just a, Nothing) - (_, Just b) -> (Just a, Just b) - in mergeWith combine (map (\a -> (Just a, Nothing)) a) - (map (\b -> (Nothing, Just b)) b) - -{-| A signal which emits a single event after a specified time. -} -pulse : Time -> Signal () -pulse time = Time.delay time start - {-| Replace the first occurence of the input signal with `a`. -} replaceFirst : a -> Signal a -> Signal a replaceFirst a0 s = @@ -212,37 +154,21 @@ replaceFirst a0 s = f replace a = if replace then Debug.log ("replacing " ++ toString a) a0 else a in map2 f first s -{-| Emit updates to `s` only when it moves outside the current bin, - according to the function `within`. Otherwise emit no update but - take on the value `Nothing`. -} -quantize : (a -> r -> Bool) -> Signal r -> Signal a -> Signal (Maybe a) -quantize within bin s = - let f range a = if a `within` range then Nothing else Just a - in dropIf (Maybe.map (always False) >> Maybe.withDefault True) Nothing (f <~ bin ~ s) - {-| Repeat updates to a signal after it has remained steady for `t` elapsed time, and only if the current value tests true against `f`. -} repeatAfterIf : Time -> number -> (a -> Bool) -> Signal a -> Signal a repeatAfterIf time fps f s = let repeatable = map f s - delayedRep = repeatable |> keepIf identity False |> Time.since time |> map not + delayedRep = repeatable |> filter identity False |> Time.since time |> map not resetDelay = merge (always False <~ s) delayedRep repeats = Time.fpsWhen fps ((&&) <~ repeatable ~ dropRepeats resetDelay) in sampleOn repeats s -{-| A signal which emits a single event on or immediately after program start. -} -start : Signal () -start = - let chan = channel () - msg = send chan () - in sampleOn (subscribe chan) - (map2 always (constant ()) (Execute.schedule (constant msg))) - {-| Only emit updates of `s` when it settles into a steady state with no updates within the period `t`. Useful to avoid propagating updates when a value is changing too rapidly. -} steady : Time -> Signal a -> Signal a -steady t s = sampleOn (Time.since t s |> dropIf identity False) s +steady t s = sampleOn (Time.since t s |> filter not False) s {-| Like `sampleOn`, but the output signal refreshes whenever either signal updates. -} sampleOnMerge : Signal a -> Signal b -> Signal b @@ -279,7 +205,7 @@ unchanged a = map not (changed a) {-| Only emit when the input signal transitions from `False` to `True`. -} ups : Signal Bool -> Signal Bool -ups s = keepIf identity False s +ups s = filter identity False s zip : Signal a -> Signal b -> Signal (a,b) zip = map2 (,) diff --git a/editor/src/Execute.elm b/editor/src/Execute.elm deleted file mode 100644 index c97ab3d40..000000000 --- a/editor/src/Execute.elm +++ /dev/null @@ -1,38 +0,0 @@ -module Execute where - -{-| Execute scheduling and delivery of `Signal.Message` values. -} - -import Native.Execute -import Signal (Signal, Message) - -{-| The message which does nothing. -} -noop : Message -noop = Native.Execute.noop - -{-| Combine two messages into one. The first argument will -be delivered before the second. -} -combine : Message -> Message -> Message -combine = Native.Execute.combine - -{-| Schedule the input `Message` values for delivery. -The output signal has same event occurrences as the input signal, -and there is no guarantee that effects of message delivery will -be visible when the output `Signal ()` updates. - -Implementation uses `setTimeout(.., 0)` in Javascript to schedule -delivery of the `Message`. --} -schedule : Signal Message -> Signal () -schedule = Native.Execute.schedule - -{-| Schedule the input `Message` values for delivery and wait for -completion of each delivery. Unlike `schedule`, the output `Signal` -will refresh once per `Message` _after_ all effects of message -delivery have propagated through the signal graph. There will be -exactly one refresh of the output signal for each input `Message`, -but the implementation uses `setTimeout(.., 0)` in Javascript so -there aren't any guarantees about exact ordering of updates, -especially with regard to other events in the signal graph. --} -complete : Signal Message -> Signal () -complete = Native.Execute.complete diff --git a/editor/src/Native/Execute.js b/editor/src/Native/Execute.js deleted file mode 100644 index 9729f449b..000000000 --- a/editor/src/Native/Execute.js +++ /dev/null @@ -1,59 +0,0 @@ -Elm.Native.Execute = {}; -Elm.Native.Execute.make = function(localRuntime) { - - localRuntime.Native = localRuntime.Native || {}; - localRuntime.Native.Execute = localRuntime.Native.Execute || {}; - if (localRuntime.Native.Execute.values) { - return localRuntime.Native.Execute.values; - } - var Signal = Elm.Signal.make(localRuntime); - - function combine(thunk1, thunk2) { - return function() { - setTimeout( - function() { - thunk1(); - setTimeout(thunk2, 0); - }, - 0); - } - } - - // schedule : Signal Message -> Signal () - function schedule(msgs) { - var tuple0 = { ctor: "_Tuple0" }; - function scheduleForce(thunk) { - setTimeout(thunk, 0); - return tuple0; - } - return A2( Signal.map, scheduleForce, msgs ); - } - - // complete : Signal Message -> Signal () - function complete(msgs) { - var tuple0 = { ctor: "_Tuple0" }; - var output = Signal.constant(tuple0); - // need to nest the calls to `setTimeout` to ensure the output signal - // is refreshed *after* the message has been delivered - function scheduleForce(thunk) { - setTimeout( - function() { - thunk(); - setTimeout(function() { localRuntime.notify(output.id, tuple0); }, 0) - }, 0); - return tuple0; - } - var forced = A2( Signal.map, scheduleForce, msgs ); - function k(x) { return function(y) { return x; } } - // the sampleOn output is important, since the `map2` would otherwise - // emit an event when either a message comes in OR a message is delivered - return A2(Signal.sampleOn, output, A3( Signal.map2, k, output, forced)); - } - - return localRuntime.Native.Execute.values = { - schedule: schedule, - complete: complete, - combine: combine, - noop: function() {} - }; -}; diff --git a/editor/src/Unison/Action.elm b/editor/src/Unison/Action.elm index aa49b62d9..e6b0e79fe 100644 --- a/editor/src/Unison/Action.elm +++ b/editor/src/Unison/Action.elm @@ -1,10 +1,10 @@ module Unison.Action where import Elmz.Json.Encoder as Encoder -import Elmz.Json.Encoder (Encoder) +import Elmz.Json.Encoder exposing (Encoder) import Elmz.Json.Decoder as Decoder -import Elmz.Json.Decoder (Decoder) -import Unison.Symbol (Symbol) +import Elmz.Json.Decoder exposing (Decoder) +import Unison.Symbol exposing (Symbol) import Unison.Symbol as Symbol type Action diff --git a/editor/src/Unison/EditableTerm.elm b/editor/src/Unison/EditableTerm.elm index 523c1abef..b996f4ad7 100644 --- a/editor/src/Unison/EditableTerm.elm +++ b/editor/src/Unison/EditableTerm.elm @@ -2,25 +2,25 @@ module Unison.EditableTerm where import Debug import Elmz.Layout as Layout -import Elmz.Layout (Layout,Region) -import Elmz.Moore (Moore(..)) +import Elmz.Layout exposing (Layout,Region) +import Elmz.Moore exposing (Moore(..)) import Elmz.Moore as Moore import Elmz.Movement as Movement import Elmz.Trie as Trie -import Elmz.Trie (Trie) +import Elmz.Trie exposing (Trie) import Graphics.Element as Element -import Graphics.Element (Element) +import Graphics.Element exposing (Element) import List import Maybe import Unison.Path as Path -import Unison.Path (Path) -import Unison.Reference (Reference) -import Unison.Metadata (Metadata) +import Unison.Path exposing (Path) +import Unison.Reference exposing (Reference) +import Unison.Metadata exposing (Metadata) import Unison.Metadata as Metadata import Unison.Scope as Scope import Unison.Styles as Styles import Unison.Term as Term -import Unison.Term (Term) +import Unison.Term exposing (Term) import Unison.View as View import Unison.Node as Node diff --git a/editor/src/Unison/Editor.elm b/editor/src/Unison/Editor.elm index 63469fb0f..01cc098af 100644 --- a/editor/src/Unison/Editor.elm +++ b/editor/src/Unison/Editor.elm @@ -1,16 +1,15 @@ module Unison.Editor where import Debug -import Execute import Elmz.Json.Request as JR -import Elmz.Layout (Containment(Inside,Outside), Layout, Pt, Region) +import Elmz.Layout exposing (Containment(Inside,Outside), Layout, Pt, Region) import Elmz.Layout as Layout -import Elmz.Moore (Moore(..)) +import Elmz.Moore exposing (Moore(..)) import Elmz.Moore as Moore import Elmz.Movement as Movement import Elmz.Selection1D as Selection1D import Elmz.Signal as Signals -import Graphics.Element (Element) +import Graphics.Element exposing (Element) import Graphics.Element as Element import Graphics.Input.Field as Field import Maybe @@ -21,21 +20,21 @@ import Signal import Unison.Action as Action import Unison.EditableTerm as EditableTerm import Unison.SearchboxParser as SearchboxParser -import Unison.Hash (Hash) -import Unison.Metadata (Metadata) +import Unison.Hash exposing (Hash) +import Unison.Metadata exposing (Metadata) import Unison.Metadata as Metadata import Unison.Node as Node -import Unison.Path (Path) +import Unison.Path exposing (Path) import Unison.Path as Path -import Unison.Reference (Reference) +import Unison.Reference exposing (Reference) import Unison.Reference as Reference import Unison.Scope as Scope import Unison.Styles as Styles -import Unison.Term (Term) +import Unison.Term exposing (Term) import Unison.Term as Term import Unison.TermExplorer as TermExplorer import Unison.Terms as Terms -import Unison.Type (Type) +import Unison.Type exposing (Type) import Unison.Type as Type import Unison.View as View import Window @@ -205,7 +204,7 @@ model sink term0 = ignoreUpDown : Signal Field.Content -> Signal Field.Content ignoreUpDown s = - let k = Signal.sampleOn (Signal.keepIf (\a -> a.y /= 0) {x = 0, y = 0} Keyboard.arrows) + let k = Signal.sampleOn (Signal.filter (\a -> a.y /= 0) {x = 0, y = 0} Keyboard.arrows) (Signals.delay Field.noContent s) in Signal.merge k s diff --git a/editor/src/Unison/Hash.elm b/editor/src/Unison/Hash.elm index 02058324e..dde4067f3 100644 --- a/editor/src/Unison/Hash.elm +++ b/editor/src/Unison/Hash.elm @@ -1,9 +1,9 @@ module Unison.Hash where import Json.Decode as Decode -import Json.Decode (Decoder) +import Json.Decode exposing (Decoder) import Elmz.Json.Encoder as Encoder -import Elmz.Json.Encoder (Encoder) +import Elmz.Json.Encoder exposing (Encoder) type alias Hash = String diff --git a/editor/src/Unison/Metadata.elm b/editor/src/Unison/Metadata.elm index 3154b1aac..d88de1fab 100644 --- a/editor/src/Unison/Metadata.elm +++ b/editor/src/Unison/Metadata.elm @@ -2,19 +2,19 @@ module Unison.Metadata where import Array import Dict -import Elmz.Json.Decoder (Decoder, (#)) +import Elmz.Json.Decoder exposing (Decoder, (#)) import Elmz.Json.Decoder as Decoder -import Elmz.Json.Encoder (Encoder) +import Elmz.Json.Encoder exposing (Encoder) import Elmz.Json.Encoder as Encoder -import Elmz.Moore (Moore(..)) +import Elmz.Moore exposing (Moore(..)) import Elmz.Moore as Moore import List import Maybe import Unison.Hash as H -import Unison.Path (Path) +import Unison.Path exposing (Path) import Unison.Path as Path import Unison.Reference as R -import Unison.Symbol (Symbol) +import Unison.Symbol exposing (Symbol) import Unison.Symbol as Symbol type alias E = Path.E type alias Path = Path.Path -- to avoid conflict with Graphics.Collage.Path @@ -49,9 +49,7 @@ firstSymbol defaultName md = case md.names of firstName : String -> Metadata -> String firstName ifEmpty md = - if List.isEmpty md.names - then ifEmpty - else (List.head md.names).name + Maybe.withDefault ifEmpty (Maybe.map .name (List.head md.names)) type alias Names = List Symbol diff --git a/editor/src/Unison/Node.elm b/editor/src/Unison/Node.elm index ae1d1d200..b46de8469 100644 --- a/editor/src/Unison/Node.elm +++ b/editor/src/Unison/Node.elm @@ -4,25 +4,25 @@ module Unison.Node where import Dict as M import Maybe import Elmz.Json.Encoder as Encoder -import Elmz.Json.Encoder (Encoder) +import Elmz.Json.Encoder exposing (Encoder) import Elmz.Json.Decoder as Decoder -import Elmz.Json.Decoder (Decoder) -import Elmz.Json.Request (Request) +import Elmz.Json.Decoder exposing (Decoder) +import Elmz.Json.Request exposing (Request) import Elmz.Json.Request as Request import Set as S import Signal -import Signal ((<~),(~),Signal) +import Signal exposing ((<~),(~),Signal) import Unison.Action as A -import Unison.Action (Action) +import Unison.Action exposing (Action) import Unison.Metadata as MD -import Unison.Metadata (Metadata, Query) +import Unison.Metadata exposing (Metadata, Query) import Unison.Term as E import Unison.Path as Path import Unison.Reference as Reference -import Unison.Reference (Reference) -import Unison.Term (Term) +import Unison.Reference exposing (Reference) +import Unison.Term exposing (Term) import Unison.Type as T -import Unison.Type (Type) +import Unison.Type exposing (Type) type alias Path = Path.Path type alias Host = String diff --git a/editor/src/Unison/Path.elm b/editor/src/Unison/Path.elm index 281bcbf30..abe500cc6 100644 --- a/editor/src/Unison/Path.elm +++ b/editor/src/Unison/Path.elm @@ -1,14 +1,13 @@ module Unison.Path where -import Array (Array) +import Array exposing (Array) import Array as A import Elmz.Json.Decoder as Decoder -import Elmz.Json.Encoder (Encoder) +import Elmz.Json.Encoder exposing (Encoder) import Elmz.Json.Encoder as Encoder -import Json.Decode (Decoder) +import Json.Decode exposing (Decoder) import Json.Decode as Decode import List -import List ((::)) import String type E diff --git a/editor/src/Unison/Reference.elm b/editor/src/Unison/Reference.elm index ceeddec38..6f53f0344 100644 --- a/editor/src/Unison/Reference.elm +++ b/editor/src/Unison/Reference.elm @@ -1,14 +1,14 @@ module Unison.Reference where -import Dict (Dict) +import Dict exposing (Dict) import Dict import Elmz.Json.Encoder as Encoder -import Elmz.Json.Encoder (Encoder) +import Elmz.Json.Encoder exposing (Encoder) import Elmz.Json.Decoder as Decoder -import Elmz.Json.Decoder (Decoder) +import Elmz.Json.Decoder exposing (Decoder) import List import String -import Unison.Hash (Hash) +import Unison.Hash exposing (Hash) import Unison.Hash as H type Reference diff --git a/editor/src/Unison/Scope.elm b/editor/src/Unison/Scope.elm index d932c60da..13c001bc1 100644 --- a/editor/src/Unison/Scope.elm +++ b/editor/src/Unison/Scope.elm @@ -1,19 +1,18 @@ module Unison.Scope where import Debug -import Elmz.Layout (Region, Layout) +import Elmz.Layout exposing (Region, Layout) import Elmz.Layout as Layout import Elmz.Signal as Signals import Elmz.Movement as Movement -import Graphics.Element (Element) +import Graphics.Element exposing (Element) import Graphics.Element as Element import List -import List ((::)) import Maybe import Signal import Unison.Path as Path import Unison.Styles as Styles -import Unison.Term (Term) +import Unison.Term exposing (Term) import Unison.Term as Term import Unison.View as View diff --git a/editor/src/Unison/SearchboxParser.elm b/editor/src/Unison/SearchboxParser.elm index 58f2243fa..dba18c372 100644 --- a/editor/src/Unison/SearchboxParser.elm +++ b/editor/src/Unison/SearchboxParser.elm @@ -2,20 +2,18 @@ module Unison.SearchboxParser where import Debug import Elmz.Distance as Distance -import Elmz.Distance (Distance) +import Elmz.Distance exposing (Distance) import List -import Parser -import Parser (Parser, (<*), (*>), (<*>), (<$>), (<$)) -import Parser.Number -import Parser.Char +import Elmz.Parser as Parser +import Elmz.Parser exposing (Parser, (<*), (*>), (<*>), (<$>), (<$)) import Unison.Term as Term -import Unison.Term (Term) +import Unison.Term exposing (Term) import String import Set parser : { literal : Term -> a , query : String -> a - , combine : a -> Char -> a } + , combine : a -> String -> a } -> Parser a parser env = let lit = Parser.map env.literal literal @@ -32,14 +30,14 @@ space = Parser.satisfy ((==) ' ') parse : { literal : Term -> a , query : String -> a - , combine : a -> Char -> a } + , combine : a -> String -> a } -> String -> Result String a parse env = Parser.parse (parser env) parseTerm : String -> Result String Term parseTerm = Parser.parse literal -operator : Parser Char +operator : Parser String operator = let ops = Set.fromList (String.toList "!@#$%^&*-+|\\;.> Set.member c ops) @@ -55,13 +53,13 @@ blank : Parser Term blank = Parser.map (always Term.Blank) (Parser.symbol '_') int : Parser Term -int = Parser.map (Term.Lit << Term.Number << toFloat) Parser.Number.integer +int = Parser.map (Term.Lit << Term.Number << toFloat) (Parser.attempt Parser.int) float : Parser Term -float = Parser.map (Term.Lit << Term.Number) Parser.Number.float +float = Parser.map (Term.Lit << Term.Number) (Parser.attempt Parser.float) string : Parser Term -string = Parser.Char.between quote quote (until quote) +string = (Parser.symbol quote *> (until quote) <* Parser.symbol quote) |> Parser.map (Term.Lit << Term.Text) openString : Parser Term @@ -77,22 +75,20 @@ distance = pixels : Parser Distance pixels = let f n = Distance.Scale (toFloat n) Distance.Pixel - in f <$> Parser.Number.natural <* Parser.token "px" + in f <$> Parser.nonnegativeInt <* Parser.token "px" fraction : Parser Distance fraction = Parser.symbol '1' *> Parser.symbol '/' - *> (Parser.Number.natural <* Parser.symbol 'd') + *> (Parser.nonnegativeInt <* Parser.symbol 'd') |> Parser.map (\denominator -> Distance.Fraction (1.0 / toFloat denominator)) quote = '"' -- " until : Char -> Parser String until c = - Parser.map (String.concat << List.map String.fromChar) - (Parser.many (Parser.satisfy ((/=) c))) + Parser.map String.concat (Parser.many (Parser.satisfy ((/=) c))) until1 : Char -> Parser String until1 c = - Parser.map (String.concat << List.map String.fromChar) - (Parser.some (Parser.satisfy ((/=) c))) + Parser.map String.concat (Parser.some (Parser.satisfy ((/=) c))) diff --git a/editor/src/Unison/Styles.elm b/editor/src/Unison/Styles.elm index 721e3af7a..5ad06cf1d 100644 --- a/editor/src/Unison/Styles.elm +++ b/editor/src/Unison/Styles.elm @@ -1,20 +1,17 @@ module Unison.Styles where import Color -import Color (Color) -import Easing (Easing) -import Easing +import Color exposing (Color) import Elmz.Signal as Signals -import Elmz.Layout (Layout, Region) +import Elmz.Layout exposing (Layout, Region) import Elmz.Layout as L import Graphics.Input.Field as Field -import Graphics.Element (Element) +import Graphics.Element exposing (Element) import Graphics.Element as E import Graphics.Collage as C import List -import List ((::)) import Signal -import Text (Style) +import Text exposing (Style) import Text as T import Time @@ -62,16 +59,16 @@ menuHeader = , line = Nothing } codeText : String -> Element -codeText s = T.leftAligned (T.style code (T.fromString s)) +codeText s = E.leftAligned (T.style code (T.fromString s)) boldCodeText : String -> Element -boldCodeText s = T.leftAligned (T.style { code | bold <- True } (T.fromString s)) +boldCodeText s = E.leftAligned (T.style { code | bold <- True } (T.fromString s)) centeredCodeText : String -> Element -centeredCodeText s = T.centered (T.style code (T.fromString s)) +centeredCodeText s = E.centered (T.style code (T.fromString s)) menuHeaderText : String -> Element -menuHeaderText s = T.leftAligned (T.style menuHeader (T.fromString s)) +menuHeaderText s = E.leftAligned (T.style menuHeader (T.fromString s)) menuSeparator : Int -> Element menuSeparator width = @@ -111,10 +108,10 @@ currentSymbol : Element currentSymbol = outline' okColor 6 16 16 numericLiteral : String -> Element -numericLiteral s = T.leftAligned (T.style { code | color <- belizeHole } (T.fromString s)) +numericLiteral s = E.leftAligned (T.style { code | color <- belizeHole } (T.fromString s)) stringLiteral : String -> Element -stringLiteral s = T.leftAligned (T.style { code | color <- wisteria } (T.fromString s)) +stringLiteral s = E.leftAligned (T.style { code | color <- wisteria } (T.fromString s)) cells : k -> Element -> List (Layout k) -> Layout k cells k ifEmpty ls = let cs = List.map (\l -> L.fill bg (L.pad 5 0 l)) (L.row ls) in case cs of @@ -205,17 +202,6 @@ contain : Element -> Element contain e = E.container (E.widthOf e) (E.heightOf e) E.middle e -spinner : Signal Element -spinner = - let pct n = toFloat (n%60) / 60.0 - t = Signal.map pct (Signals.count (Time.fps 60)) - rect = E.color midnightBlue (E.spacer 5 10) - sep = E.spacer 1 1 - render pct = E.flow E.right - [ rect, sep - , E.opacity (Easing.easeInOutExpo pct) rect ] - in Signal.map render t - blank : Element blank = codeText "_" @@ -243,7 +229,3 @@ midnightBlue = Color.rgb 44 62 80 midnightBlueA alpha = Color.rgba 44 62 80 alpha concrete = Color.rgb 149 165 166 asbestos = Color.rgb 127 140 141 - -main = - let scene e = E.flow E.down [ E.spacer 1 50, E.flow E.right [ E.spacer 50 1, e]] - in Signal.map scene spinner diff --git a/editor/src/Unison/Symbol.elm b/editor/src/Unison/Symbol.elm index 659eba294..f09153f5c 100644 --- a/editor/src/Unison/Symbol.elm +++ b/editor/src/Unison/Symbol.elm @@ -1,9 +1,9 @@ module Unison.Symbol where import Elmz.Json.Encoder as Encoder -import Elmz.Json.Encoder (Encoder) +import Elmz.Json.Encoder exposing (Encoder) import Elmz.Json.Decoder as Decoder -import Elmz.Json.Decoder (Decoder) +import Elmz.Json.Decoder exposing (Decoder) type Fixity = InfixL | InfixR | Infix | Prefix diff --git a/editor/src/Unison/Term.elm b/editor/src/Unison/Term.elm index dc2069555..e712255c9 100644 --- a/editor/src/Unison/Term.elm +++ b/editor/src/Unison/Term.elm @@ -1,33 +1,32 @@ module Unison.Term where import Array -import Array (Array) +import Array exposing (Array) import Debug import Dict -import Dict (Dict) +import Dict exposing (Dict) import Elmz.Distance as Distance import Elmz.Maybe as EM -import Elmz.Layout (Layout) -import Elmz.Json.Encoder (Encoder) +import Elmz.Layout exposing (Layout) +import Elmz.Json.Encoder exposing (Encoder) import Elmz.Json.Encoder as Encoder -import Elmz.Json.Decoder (Decoder) +import Elmz.Json.Decoder exposing (Decoder) import Elmz.Json.Decoder as Decoder -import Elmz.Trie (Trie) +import Elmz.Trie exposing (Trie) import Elmz.Trie as Trie import List -import List ((::)) import Maybe import Set -import Set (Set) +import Set exposing (Set) import String import Unison.Reference as R -import Unison.Hash (Hash) +import Unison.Hash exposing (Hash) import Unison.Hash as H -import Unison.Metadata (Metadata) -import Unison.Symbol (Symbol,Fixity) +import Unison.Metadata exposing (Metadata) +import Unison.Symbol exposing (Symbol,Fixity) import Unison.Symbol as Symbol import Unison.Metadata as Metadata -import Unison.Path (..) +import Unison.Path exposing (..) import Unison.Path as Path import Unison.Type as T type alias E = Path.E diff --git a/editor/src/Unison/TermExplorer.elm b/editor/src/Unison/TermExplorer.elm index 7e5b8f887..4c68d5cda 100644 --- a/editor/src/Unison/TermExplorer.elm +++ b/editor/src/Unison/TermExplorer.elm @@ -1,17 +1,17 @@ module Unison.TermExplorer where import Debug -import Dict (Dict) +import Dict exposing (Dict) import Dict as Dict -import Elmz.Moore (Moore(..)) +import Elmz.Moore exposing (Moore(..)) import Elmz.Moore as Moore import Elmz.Layout as Layout -import Elmz.Layout (Layout) +import Elmz.Layout exposing (Layout) import Elmz.Movement as Movement import Elmz.Selection1D as Selection1D import Elmz.Matcher as Matcher import Graphics.Element as Element -import Graphics.Element (Element) +import Graphics.Element exposing (Element) import Graphics.Input.Field as Field import List import Maybe @@ -19,18 +19,18 @@ import Result import Signal import String import Unison.Metadata as Metadata -import Unison.Metadata (Metadata,Query) +import Unison.Metadata exposing (Metadata,Query) import Unison.Node as Node import Unison.Path as Path -import Unison.Path (Path) +import Unison.Path exposing (Path) import Unison.Reference as Reference -import Unison.Reference (Reference) +import Unison.Reference exposing (Reference) import Unison.SearchboxParser as SearchboxParser import Unison.Styles as Styles import Unison.Term as Term -import Unison.Term (Term) +import Unison.Term exposing (Term) import Unison.Type as Type -import Unison.Type (Type) +import Unison.Type exposing (Type) import Unison.View as View type alias LocalFocus = diff --git a/editor/src/Unison/Type.elm b/editor/src/Unison/Type.elm index f4753e341..6ecc912eb 100644 --- a/editor/src/Unison/Type.elm +++ b/editor/src/Unison/Type.elm @@ -1,16 +1,16 @@ module Unison.Type where -import Elmz.Json.Decoder (Decoder) +import Elmz.Json.Decoder exposing (Decoder) import Elmz.Json.Decoder as Decoder -import Elmz.Json.Encoder (Encoder) +import Elmz.Json.Encoder exposing (Encoder) import Elmz.Json.Encoder as Encoder import List import String -import Unison.Metadata (Metadata) +import Unison.Metadata exposing (Metadata) import Unison.Metadata as Metadata -import Unison.Reference (Reference) +import Unison.Reference exposing (Reference) import Unison.Reference as Reference -import Unison.Symbol (Symbol) +import Unison.Symbol exposing (Symbol) import Unison.Symbol as Symbol type Literal diff --git a/editor/src/Unison/View.elm b/editor/src/Unison/View.elm index 757e7475f..54c8ac2e3 100644 --- a/editor/src/Unison/View.elm +++ b/editor/src/Unison/View.elm @@ -4,28 +4,27 @@ import Array import Color import Debug import Elmz.Distance as Distance -import Elmz.Layout (Layout) +import Elmz.Layout exposing (Layout) import Elmz.Layout as L -import Elmz.Moore (Moore(..)) +import Elmz.Moore exposing (Moore(..)) import Elmz.Moore as Moore import Elmz.Trie as Trie -import Elmz.Trie (Trie) +import Elmz.Trie exposing (Trie) import List -import List ((::)) import Graphics.Element as E import Maybe import Unison.Reference as R -import Unison.Hash (Hash) -import Unison.Metadata (Metadata) -import Unison.Symbol (Fixity) +import Unison.Hash exposing (Hash) +import Unison.Metadata exposing (Metadata) +import Unison.Symbol exposing (Fixity) import Unison.Symbol as Symbol import Unison.Metadata as Metadata -import Unison.Styles (codeText) +import Unison.Styles exposing (codeText) import Unison.Styles as Styles -import Unison.Term (..) +import Unison.Term exposing (..) import Unison.Term as Term import Unison.Type as Type -import Unison.Path (..) +import Unison.Path exposing (..) import Unison.Path as Path import String import Text @@ -322,16 +321,16 @@ builtins env allowBreak availableWidth ambientPrec cur = in Just (L.embed t (E.spacer w' h')) App (Ref (R.Builtin "View.text")) style -> case e of -- todo, actually interpret style - Lit (Text s) -> Just (L.embed t (Text.leftAligned (Text.style Text.defaultStyle (Text.fromString s)))) + Lit (Text s) -> Just (L.embed t (E.leftAligned (Text.style Text.defaultStyle (Text.fromString s)))) App (App (App (Ref (R.Builtin "View.textbox")) (Ref (R.Builtin alignment))) (Lit (Term.Distance d))) style -> case e of Lit (Text s) -> -- todo, actually interpret style let f = case alignment of - "Text.left" -> Text.leftAligned - "Text.right" -> Text.rightAligned - "Text.center" -> Text.centered - "Text.justify" -> Text.justified + "Text.left" -> E.leftAligned + "Text.right" -> E.rightAligned + "Text.center" -> E.centered + "Text.justify" -> E.justified e = f (Text.style Text.defaultStyle (Text.fromString s)) rem = availableWidth `max` floor (Distance.pixels d (toFloat availableWidth)) e' = if E.widthOf e > rem then E.width rem e else e