diff --git a/libraries/Graphics/Input.elm b/libraries/Graphics/Input.elm index ad69a3a..bef7776 100644 --- a/libraries/Graphics/Input.elm +++ b/libraries/Graphics/Input.elm @@ -1,4 +1,3 @@ - module Graphics.Input where import Basics (String) @@ -9,118 +8,158 @@ import Graphics.Element (Element) import Maybe (Maybe) import JavaScript (JSString) +{-| DOCUMENT STRUCTURE + +This module is for creating standard input widgets such as buttons and +text boxes. In general, functions in this library return a signal representing +events from the user. + +The simplest inputs are *one-way inputs*, meaning the user can update +them, but the programmer cannot. If you need to update an input from +within the program you want the slightly more complex *two-way inputs*. +This document will always show the one-way inputs first, *then* the +two-way inputs. + +# Buttons +@docs button, customButton, buttons, customButtons + +# Fields +@docs field, password, email, fields, FieldState, emptyFieldState + +# Checkboxes +@docs checkbox, checkboxes + +# Drop Downs +@docs stringDropDown, dropDown + +# Mouse Hover +@docs hoverable, hoverables + +-} + id x = x --- Create a group of buttons. --- --- * The first argument is the default value of the `events` signal. --- * The `events` signal represents all of the activity in this group --- of buttons. --- * The `button` function creates a button --- with the given name, like “Submit” or “Cancel”. --- The `a` value is sent to `events` whenever the button is pressed. +{-| Create a group of buttons. + + * The first argument is the default value of the `events` signal. + * The `events` signal represents all of the activity in this group + of buttons. + * The `button` function creates a button + with the given name, like “Submit” or “Cancel”. + The `a` value is sent to `events` whenever the button is pressed. +-} buttons : a -> { events : Signal a, button : a -> String -> Element } buttons = Native.Graphics.Input.buttons --- Create a button with a given label. The result is an `Element` and --- a signal of units. This signal triggers whenever the button is pressed. +{-| Create a button with a given label. The result is an `Element` and +a signal of units. This signal triggers whenever the button is pressed. +-} button : String -> (Element, Signal ()) button txt = let pool = buttons () in (pool.button () txt, pool.events) --- Create a group of custom buttons. --- --- * The first argument is the default value of the `events` signal. --- * The `events` signal represents all of the activity in this group --- of custom buttons. --- * The `customButton` function creates a button with three different visual --- states, one for up, hovering, and down. The resulting button has dimensions --- large enough to fit all three possible `Elements`. --- The `a` value is sent to `events` whenever the button is pressed. +{-| Create a group of custom buttons. + + * The first argument is the default value of the `events` signal. + * The `events` signal represents all of the activity in this group + of custom buttons. + * The `customButton` function creates a button with three different visual + states, one for up, hovering, and down. The resulting button has dimensions + large enough to fit all three possible `Elements`. + The `a` value is sent to `events` whenever the button is pressed. +-} customButtons : a -> { events : Signal a, customButton : a -> Element -> Element -> Element -> Element } customButtons = Native.Graphics.Input.customButtons --- Create a button with custom states for up, hovering, and down --- (given in that order). The result is an `Element` and --- a signal of units. This signal triggers whenever the button is pressed. +{-| Create a button with custom states for up, hovering, and down +(given in that order). The result is an `Element` and a signal of +units. This signal triggers whenever the button is pressed. +-} customButton : Element -> Element -> Element -> (Element, Signal ()) customButton up hover down = let pool = customButtons () in (pool.customButton () up hover down, pool.events) --- Create a group of checkboxes. --- --- * The first argument is the default value of the `events` signal. --- * The `events` signal represents all of the activity in this group --- of checkboxes. --- * The `checkbox` function creates a --- checkbox with a given state. The `(Bool -> a)` function is used --- when the checkbox is modified. It takes the new state and turns --- it into a value that can be sent to `events`. For example, this --- lets you add an ID to distinguish between checkboxes. +{-| Create a group of checkboxes. + + * The first argument is the default value of the `events` signal. + * The `events` signal represents all of the activity in this group + of checkboxes. + * The `checkbox` function creates a + checkbox with a given state. The `(Bool -> a)` function is used + when the checkbox is modified. It takes the new state and turns + it into a value that can be sent to `events`. For example, this + lets you add an ID to distinguish between checkboxes. +-} checkboxes : a -> { events : Signal a, checkbox : (Bool -> a) -> Bool -> Element } checkboxes = Native.Graphics.Input.checkboxes --- Create a checkbox with a given start state. Unlike `button`, this result --- is a *signal* of elements. That is because a checkbox has state that --- updates based on user input. --- The boolean signal represents the current state of the checkbox. +{-| Create a checkbox with a given start state. Unlike `button`, this +result is a *signal* of elements. That is because a checkbox has state +that updates based on user input. The boolean signal represents the +current state of the checkbox. +-} checkbox : Bool -> (Signal Element, Signal Bool) checkbox b = let cbs = checkboxes b in (lift (cbs.checkbox id) cbs.events, cbs.events) --- Detect when the mouse is hovering over some elements. This --- allows you to create and destroy elements dynamically and still --- detect hover information. +{-| Detect when the mouse is hovering over some elements. This +allows you to create and destroy elements dynamically and still +detect hover information. +-} hoverables : a -> { events : Signal a, hoverable : (Bool -> a) -> Element -> Element } hoverables = Native.Graphics.Input.hoverables --- Detect when the mouse is hovering over a specifici `Element`. +{-| Detect when the mouse is hovering over a specifici `Element`. -} hoverable : Element -> (Element, Signal Bool) hoverable elem = let pool = hoverables False in (pool.hoverable id elem, pool.events) --- Represents the current state of a text field. The `string` represents the --- characters filling the text field. The `selectionStart` and `selectionEnd` --- values represent what the user has selected with their mouse or keyboard. --- For example: --- --- { string="She sells sea shells", selectionStart=3, selectionEnd=0 } --- --- This means the user highlighted the substring `"She"` backwards. +{-| Represents the current state of a text field. The `string` represents the +characters filling the text field. The `selectionStart` and `selectionEnd` +values represent what the user has selected with their mouse or keyboard. +For example: + + { string="She sells sea shells", selectionStart=3, selectionEnd=0 } + +This means the user highlighted the substring `"She"` backwards. +-} type FieldState = { string:String, selectionStart:Int, selectionEnd:Int } --- Create a group of text input fields. --- --- * The first argument is the default value of the `events` signal. --- * The `events` signal represents all of the activity in this group --- of text fields. --- * The `field` function creates a --- field with the given ghost text and initial field state. --- When the field is modified, the `(FieldState -> a)` function --- takes the new state and turns --- it into a value that can be sent to `events`. For example, this --- lets you add an ID to distinguish between input fields. +{-| Create a group of text input fields. + + * The first argument is the default value of the `events` signal. + * The `events` signal represents all of the activity in this group + of text fields. + * The `field` function creates a + field with the given ghost text and initial field state. + When the field is modified, the `(FieldState -> a)` function + takes the new state and turns + it into a value that can be sent to `events`. For example, this + lets you add an ID to distinguish between input fields. +-} fields : a -> { events : Signal a, field : (FieldState -> a) -> String -> FieldState -> Element } fields = Native.Graphics.Input.fields --- The empty field state: --- --- { string="", selectionStart=0, selectionEnd=0 } +{-| The empty field state: + + { string="", selectionStart=0, selectionEnd=0 } +-} emptyFieldState : FieldState emptyFieldState = { string="", selectionStart=0, selectionEnd=0 } --- Create a field with the given default text. The output is an element that --- updates to match the user input and a signal of strings representing the --- content of the field. +{-| Create a field with the given default text. The output is an element +that updates to match the user input and a signal of strings representing +the content of the field. +-} field : String -> (Signal Element, Signal String) field placeHolder = let tfs = fields emptyFieldState @@ -128,7 +167,7 @@ field placeHolder = in (lift (tfs.field id placeHolder) changes, dropRepeats (lift .string changes)) --- Same as `field` but the UI element blocks out each characters. +{-| Same as `field` but the UI element blocks out each characters. -} password : String -> (Signal Element, Signal String) password placeHolder = let tfs = Native.Graphics.Input.passwords emptyFieldState @@ -136,9 +175,10 @@ password placeHolder = in (lift (tfs.field id placeHolder) changes, dropRepeats (lift .string changes)) --- Same as `field` but it adds an annotation that this field is for email --- addresses. This is helpful for auto-complete and for mobile users who may --- get a custom keyboard with an `@` and `.com` button. +{-| Same as `field` but it adds an annotation that this field is for email +addresses. This is helpful for auto-complete and for mobile users who may +get a custom keyboard with an `@` and `.com` button. +-} email : String -> (Signal Element, Signal String) email placeHolder = let tfs = Native.Graphics.Input.emails emptyFieldState @@ -146,15 +186,17 @@ email placeHolder = in (lift (tfs.field id placeHolder) changes, dropRepeats (lift .string changes)) --- Create a drop-down menu. When the user selects a string, --- the current state of the drop-down is set to the associated --- value. This lets you avoid manually mapping the string onto --- functions and values. +{-| Create a drop-down menu. When the user selects a string, +the current state of the drop-down is set to the associated +value. This lets you avoid manually mapping the string onto +functions and values. +-} dropDown : [(String,a)] -> (Signal Element, Signal a) dropDown = Native.Graphics.Input.dropDown --- Create a drop-down menu for selecting strings. The resulting --- signal of strings represents the string that is currently selected. +{-| Create a drop-down menu for selecting strings. The resulting +signal of strings represents the string that is currently selected. +-} stringDropDown : [String] -> (Signal Element, Signal String) stringDropDown strs = dropDown (List.map (\s -> (s,s)) strs) \ No newline at end of file diff --git a/libraries/List.elm b/libraries/List.elm index a08ffbe..6e5dfe0 100644 --- a/libraries/List.elm +++ b/libraries/List.elm @@ -4,128 +4,163 @@ module List where import open Basics import Native.List --- Add an element to the front of a list `(1 :: [2,3] == [1,2,3])` +{-| DOCUMENT STRUCTURE + +A library for manipulating lists of values. Every value in a list must have +the same type. + +# Basics +@docs (::), (++), length, reverse, map + +# Sub-lists +@docs head, tail, last, filter, take, drop + +# Putting Lists Together +@docs concat, concatMap, join, intersperse, zip, zipWith + +# Taking Lists Apart +@docs split, partition, unzip + +# Folds +@docs foldr, foldl, foldr1, foldl1, scanl, scanl1 + +# Special Folds +@docs susm, product, maximum, minimum, all, any, and, or + +-} + +{-| Add an element to the front of a list `(1 :: [2,3] == [1,2,3])` -} (::) : a -> [a] -> [a] (::) = Native.List.cons --- Puts two appendable things together: --- --- [1,1] ++ [2,3] == [1,1,2,3] --- "abc" ++ "123" == "abc123" +{-| Puts two appendable things together: + + [1,1] ++ [2,3] == [1,1,2,3] + "abc" ++ "123" == "abc123" +-} (++) : appendable -> appendable -> appendable (++) = Native.List.append --- Extract the first element of a list. List must be non-empty. --- `(head [1,2,3] == 1)` +{-| Extract the first element of a list. List must be non-empty. +`(head [1,2,3] == 1)` +-} head : [a] -> a head = Native.List.head --- Extract the elements after the head of the list. List must be non-empty. --- `(tail [1,2,3] == [2,3])` +{-| Extract the elements after the head of the list. List must be non-empty. +`(tail [1,2,3] == [2,3])` +-} tail : [a] -> [a] tail = Native.List.tail --- Extract the last element of a list. List must be non-empty. --- `(last [1,2,3] == 3)` +{-| Extract the last element of a list. List must be non-empty. +`(last [1,2,3] == 3)` +-} last : [a] -> a last = Native.List.last --- Check if a list is empty `(isEmpty [] == True)` +{-| Check if a list is empty `(isEmpty [] == True)` -} isEmpty : [a] -> Bool isEmpty xs = case xs of [] -> True _ -> False --- Apply a function to every element of a list: `(map sqrt [1,4,9] == [1,2,3])` +{-| Apply a function to every element of a list: `(map sqrt [1,4,9] == [1,2,3])` -} map : (a -> b) -> [a] -> [b] map = Native.List.map --- Reduce a list from the left: `(foldl (::) [] "gateman" == "nametag")` +{-| Reduce a list from the left: `(foldl (::) [] "gateman" == "nametag")` -} foldl : (a -> b -> b) -> b -> [a] -> b foldl = Native.List.foldl --- Reduce a list from the right: `(foldr (+) 0 [1,2,3] == 6)` +{-| Reduce a list from the right: `(foldr (+) 0 [1,2,3] == 6)` -} foldr : (a -> b -> b) -> b -> [a] -> b foldr = Native.List.foldr --- Reduce a list from the left without a base case. List must be non-empty. +{-| Reduce a list from the left without a base case. List must be non-empty. -} foldl1 : (a -> a -> a) -> [a] -> a foldl1 = Native.List.foldl1 --- Reduce a list from the right without a base case. List must be non-empty. +{-| Reduce a list from the right without a base case. List must be non-empty. -} foldr1 : (a -> a -> a) -> [a] -> a foldr1 = Native.List.foldr1 --- Reduce a list from the left, building up all of the intermediate results into a list. --- --- scanl (+) 0 [1,2,3,4] == [0,1,3,6,10] +{-| Reduce a list from the left, building up all of the intermediate results into a list. + + scanl (+) 0 [1,2,3,4] == [0,1,3,6,10] +-} scanl : (a -> b -> b) -> b -> [a] -> [b] scanl = Native.List.scanl --- Same as scanl but it doesn't require a base case. List must be non-empty. --- --- scanl1 (+) [1,2,3,4] == [1,3,6,10] +{-| Same as scanl but it doesn't require a base case. List must be non-empty. + + scanl1 (+) [1,2,3,4] == [1,3,6,10] +-} scanl1 : (a -> a -> a) -> [a] -> [a] scanl1 = Native.List.scanl1 --- Filter out elements which do not satisfy the predicate: `(filter isLower "AaBbCc" == "abc")` +{-| Keep only elements that satisfy the predicate: +`(filter isLower "AaBbCc" == "abc")` +-} filter : (a -> Bool) -> [a] -> [a] filter = Native.List.filter --- Determine the length of a list: `(length "innumerable" == 11)` +{-| Determine the length of a list: `(length "innumerable" == 11)` -} length : [a] -> Int length = Native.List.length --- Reverse a list. `(reverse [1..4] == [4,3,2,1])` +{-| Reverse a list. `(reverse [1..4] == [4,3,2,1])` -} reverse : [a] -> [a] reverse = Native.List.reverse --- Check to see if all elements satisfy the predicate. +{-| Check to see if all elements satisfy the predicate. -} all : (a -> Bool) -> [a] -> Bool all = Native.List.all --- Check to see if any elements satisfy the predicate. +{-| Check to see if any elements satisfy the predicate. -} any : (a -> Bool) -> [a] -> Bool any = Native.List.any --- Check to see if all elements are True. +{-| Check to see if all elements are True. -} and : [Bool] -> Bool and = foldl (&&) True --- Check to see if any elements are True. +{-| Check to see if any elements are True. -} or : [Bool] -> Bool or = foldl (||) False --- Concatenate a list of appendable things: --- --- concat ["tree","house"] == "treehouse" +{-| Concatenate a list of appendable things: + + concat ["tree","house"] == "treehouse" +-} concat : [appendable] -> appendable concat = Native.List.concat --- Map a given function onto a list and flatten the resulting lists. --- --- concatMap f xs == concat (map f xs) +{-| Map a given function onto a list and flatten the resulting lists. + + concatMap f xs == concat (map f xs) +-} concatMap : (a -> appendable) -> [a] -> appendable concatMap f list = concat (map f list) --- Get the sum of the list elements. `(sum [1..4] == 10)` +{-| Get the sum of the list elements. `(sum [1..4] == 10)` -} sum : [number] -> number sum = foldl (+) 0 --- Get the product of the list elements. `(product [1..4] == 24)` +{-| Get the product of the list elements. `(product [1..4] == 24)` -} product : [number] -> number product = foldl (*) 1 --- Find the maximum element in a non-empty list: `maximum [1,4,2] == 4` +{-| Find the maximum element in a non-empty list: `maximum [1,4,2] == 4` -} maximum : [comparable] -> comparable maximum = foldl1 max --- Find the minimum element in a non-empty list: `minimum [3,2,1] == 1` +{-| Find the minimum element in a non-empty list: `minimum [3,2,1] == 1` -} minimum : [comparable] -> comparable minimum = foldl1 min --- Split a list based on the predicate. +{-| Split a list based on the predicate. -} partition : (a -> Bool) -> [a] -> ([a],[a]) partition pred lst = case lst of @@ -133,44 +168,49 @@ partition pred lst = x::xs -> let (bs,cs) = partition pred xs in if pred x then (x::bs,cs) else (bs,x::cs) --- Combine two lists, combining them into tuples pairwise. --- If one list is longer, the extra elements are dropped. --- --- zip [1,2,3] [6,7] == [(1,6),(2,7)] --- zip == zipWith (,) +{-| Combine two lists, combining them into tuples pairwise. +If one list is longer, the extra elements are dropped. + + zip [1,2,3] [6,7] == [(1,6),(2,7)] + zip == zipWith (,) +-} zip : [a] -> [b] -> [(a,b)] zip = Native.List.zip --- Combine two lists, combining them with the given function. --- If one list is longer, the extra elements are dropped. --- --- zipWith (+) [1,2,3] [1,2,3,4] == [2,4,6] +{-| Combine two lists, combining them with the given function. +If one list is longer, the extra elements are dropped. + + zipWith (+) [1,2,3] [1,2,3,4] == [2,4,6] +-} zipWith : (a -> b -> c) -> [a] -> [b] -> [c] zipWith = Native.List.zipWith --- Decompose a list of tuples. +{-| Decompose a list of tuples. -} unzip : [(a,b)] -> ([a],[b]) unzip pairs = case pairs of [] -> ([],[]) (x,y)::ps -> let (xs,ys) = (unzip ps) in (x::xs,y::ys) --- Split a list with a given seperator. --- --- split "," "hello,there,friend" == ["hello", "there", "friend"] +{-| Split a list with a given seperator. + + split "," "hello,there,friend" == ["hello", "there", "friend"] +-} split : [a] -> [a] -> [[a]] split = Native.List.split --- Places the given value between all of the lists in the second argument --- and concatenates the result. --- --- join "a" ["H","w","ii","n"] == "Hawaiian" +{-| Places the given value between all of the lists in the second +argument and concatenates the result. + + join "a" ["H","w","ii","n"] == "Hawaiian" +-} join : appendable -> [appendable] -> appendable join = Native.List.join --- Places the given value between all members of the given list. --- --- intersperse ' ' "INCEPTION" == "I N C E P T I O N" +{-| Places the given value between all members of the given list. + + intersperse ' ' "INCEPTION" == "I N C E P T I O N" +-} intersperse : a -> [a] -> [a] intersperse sep xs = case xs of @@ -178,14 +218,16 @@ intersperse sep xs = [a] -> [a] [] -> [] --- Take the first n members of a list: `(take 2 [1,2,3,4] == [1,2])` +{-| Take the first n members of a list: `(take 2 [1,2,3,4] == [1,2])` -} take : Int -> [a] -> [a] take = Native.List.take --- Drop the first n members of a list: `(drop 2 [1,2,3,4] == [3,4])` +{-| Drop the first n members of a list: `(drop 2 [1,2,3,4] == [3,4])` -} drop : Int -> [a] -> [a] drop = Native.List.drop --- Creates a list with n copies of a value: `(replicate 3 (0,0) == [(0,0),(0,0),(0,0)]` +{-| Creates a list with *n* copies of a value: +`(repeat 3 (0,0) == [(0,0),(0,0),(0,0)]` +-} repeat : Int -> a -> [a] repeat = Native.List.repeat