Copyright | (c) 2008 Brent Yorgey |
---|---|
License | BSD-style (see LICENSE) |
Maintainer | <byorgey@gmail.com> |
Stability | unstable |
Portability | unportable |
Safe Haskell | None |
Language | Haskell2010 |
A library for creating simple interactive list editors, using a zipper to allow the user to navigate forward and back within the list and edit the list elements.
- data Action m a u
- = Comp (Action m a u) (Action m a u)
- | Fwd
- | Back
- | Delete
- | Modify (a -> a)
- | ModifyState (LState a u -> LState a u)
- | ModifyStateM (LState a u -> m (LState a u))
- | ModifyAllM (Zipper a -> m (Zipper a))
- | ModifyAll (Zipper a -> Zipper a)
- | ModifyM (a -> m a)
- | ModifyFwd ([a] -> [a])
- | ModifyBack ([a] -> [a])
- | ModifyWInp String (String -> a -> a)
- | ModifyWEditor (a -> String) (String -> a -> a)
- | InsFwd String (String -> a)
- | InsBack String (String -> a)
- | Output (a -> String)
- | Cancel
- | Done (LState a u -> m (Maybe (LState a u)))
- | Seq [Action m a u]
- | Help String (Action m a u)
- stdActions :: Monad m => [(Char, Action m a u)]
- (??) :: Action m a u -> String -> Action m a u
- data EditorConf m a u = EC {}
- edit :: MonadIO m => EditorConf m a u -> u -> NonEmpty a -> (Zipper a -> Zipper a) -> m (Maybe (u, [a]))
- data LCont a = LC (IO ([a], Maybe (LCont a)))
- editWCont :: MonadIO m => EditorConf m a u -> NonEmpty a -> u -> IO ([a], Maybe (LCont a)) -> (Zipper a -> Zipper a) -> m (Maybe (u, [a]))
- data Zipper a = LZ {}
- integrate :: Zipper a -> [a]
- differentiate :: NonEmpty a -> Zipper a
- fwd :: Zipper a -> Zipper a
- back :: Zipper a -> Zipper a
- data LState a b = LS {}
Example usage
Here is a simple example of using the ZipEdit library:
module Main where import System.Console.ZipEdit myEd = EC { display = const "" , ecPrompt = \n -> maybe "" show n ++ "? " , actions = [ ('+', Modify (+1) ?? "Increment the current number.") , ('i', InsFwd "Value to insert: " read ?? "Insert a number.") ] ++ stdActions } main = do mxs <- edit myEd [1..10] case mxs of Nothing -> putStrLn "Canceled." Just xs -> putStrLn ("Final edited version: " ++ show xs)
A session with this program might look something like this:
$ test 1? k 1? j 2? j 3? + 4? + 5? j 4? i Value to insert: 98 98? d Final edited version: [1,2,5,4,98,5,6,7,8,9,10]
For more sophisticated examples, see planethaskell.hs
and gmane.hs
in
http://code.haskell.org/~byorgey/code/hwn/utils.
Interface
Actions that can be taken by an editor in response to user input.
Comp (Action m a u) (Action m a u) | |
Fwd | move forward one item. |
Back | move back one item. |
Delete | delete the current item. |
Modify (a -> a) | modify the current item by applying the given function. |
ModifyState (LState a u -> LState a u) | modify complete state |
ModifyStateM (LState a u -> m (LState a u)) | modify complete state with IO. |
ModifyAllM (Zipper a -> m (Zipper a)) | modify everything with IO. |
ModifyAll (Zipper a -> Zipper a) | modify everything. |
ModifyM (a -> m a) | modify the current item by applying the given function, which gives its result in the IO monad. |
ModifyFwd ([a] -> [a]) | modify items following the current item by applying the given function. |
ModifyBack ([a] -> [a]) | modify items before the current item by applying the given function. |
ModifyWInp String (String -> a -> a) | Using the given string as a prompt, obtain a line of user input, and apply the given function to the user input to obtain a function for modifying the current item. |
ModifyWEditor (a -> String) (String -> a -> a) | Run the first function on the current item to produce a string, and open an editor (using the $EDITOR environment variable) on that string. After the user is done editing, pass the resulting string to the second function to obtain a function for modifying the current element. |
InsFwd String (String -> a) | Using the given string as a prompt, obtain a line of user input, and apply the given function to the user input to obtain a new item, which should be inserted forward of the current item. The inserted item becomes the new current item. |
InsBack String (String -> a) | Similar to InsFwd, except that the new item is inserted before the old current item. |
Output (a -> String) | output a string which is a function of the current item. |
Cancel | cancel the editing session. |
Done (LState a u -> m (Maybe (LState a u))) | complete the editing session, but if te function evaluates to Just and the suer answers y. In this case return the functions result. |
Seq [Action m a u] | perform a sequence of actions. |
Help String (Action m a u) | an action annotated with a help string. |
stdActions :: Monad m => [(Char, Action m a u)] Source #
Some standard actions which can be used in constructing editor configurations. The actions are: j - Fwd, k - Back, x - Delete, q - Cancel, d - Done.
data EditorConf m a u Source #
A configuration record determining the behavior of the editor.
EC | |
|
:: MonadIO m | |
=> EditorConf m a u | editor configuration |
-> u | initial userState |
-> NonEmpty a | the list to edit |
-> (Zipper a -> Zipper a) | startupModifier |
-> m (Maybe (u, [a])) |
Run the given editor on the given list, returning Nothing
if
the user canceled the editing process, or Just l
if the editing
process completed successfully, where l
is the final state of
the list being edited.
A continuation which can compute more of the list, along with (maybe) another continuation.
:: MonadIO m | |
=> EditorConf m a u | |
-> NonEmpty a | the list to edit |
-> u | initial userState |
-> IO ([a], Maybe (LCont a)) | |
-> (Zipper a -> Zipper a) | startupModifier |
-> m (Maybe (u, [a])) |
Like edit
, but with an additional parameter for a continuation
| which can be run to compute additional list elements and
| (optionally) another continuation.
differentiate :: NonEmpty a -> Zipper a Source #
Turn a list into a context with the focus on the first element.
fwd :: Zipper a -> Zipper a Source #
Move the focus to the next element. Do nothing if the focus is | already on the last element.