Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge branch 'docs'

  • Loading branch information...
commit be2d9a8c31b6fe15368b59a95aaa98c84256d2e6 2 parents d2a393b + 1c9bc83
@willdonnelly authored
Showing with 100 additions and 84 deletions.
  1. +56 −63 Config/Dyre.hs
  2. +44 −21 README.mkd
View
119 Config/Dyre.hs
@@ -18,69 +18,68 @@ program (recompiling if applicable), and persist state across restarts,
but it has no impact whatsoever on the rest of the library whether it
is used or not.
-A full example of using Dyre's recompilation and relaunching features
-is as follows:
-
->-- DyreExample.hs --
->module DyreExample where
->
->import qualified Config.Dyre as Dyre
->
->import Config.Dyre.Relaunch
->import System.IO
->
->data Config = Config { message :: String, errorMsg :: Maybe String }
->data State = State { bufferLines :: [String] } deriving (Read, Show)
->
->defaultConfig :: Config
->defaultConfig = Config "Dyre Example v0.1" Nothing
->
->showError :: Config -> String -> Config
->showError cfg msg = cfg { errorMsg = Just msg }
->
->realMain Config{message = message, errorMsg = errorMsg } = do
-> (State buffer) <- restoreTextState $ State []
-> case errorMsg of
-> Nothing -> return ()
-> Just em -> putStrLn $ "Error: " ++ em
-> putStrLn message
-> mapM putStrLn . reverse $ buffer
-> putStr "> " >> hFlush stdout
-> input <- getLine
-> case input of
-> "exit" -> return ()
-> "quit" -> return ()
-> other -> relaunchWithTextState (State $ other:buffer) Nothing
->
->dyreExample = Dyre.wrapMain $ Dyre.defaultParams
-> { Dyre.projectName = "dyreExample"
-> , Dyre.realMain = realMain
-> , Dyre.showError = showError
-> }
+A full example of using most of Dyre's major features is as follows:
+
+ -- DyreExample.hs --
+ module DyreExample where
+
+ import qualified Config.Dyre as Dyre
+ import Config.Dyre.Relaunch
+
+ import System.IO
+
+ data Config = Config { message :: String, errorMsg :: Maybe String }
+ data State = State { bufferLines :: [String] } deriving (Read, Show)
+
+ defaultConfig :: Config
+ defaultConfig = Config "Dyre Example v0.1" Nothing
+
+ showError :: Config -> String -> Config
+ showError cfg msg = cfg { errorMsg = Just msg }
+
+ realMain Config{message = message, errorMsg = errorMsg } = do
+ (State buffer) <- restoreTextState $ State []
+ case errorMsg of
+ Nothing -> return ()
+ Just em -> putStrLn $ "Error: " ++ em
+ putStrLn message
+ mapM putStrLn . reverse $ buffer
+ putStr "> " >> hFlush stdout
+ input <- getLine
+ case input of
+ "exit" -> return ()
+ "quit" -> return ()
+ other -> relaunchWithTextState (State $ other:buffer) Nothing
+
+ dyreExample = Dyre.wrapMain $ Dyre.defaultParams
+ { Dyre.projectName = "dyreExample"
+ , Dyre.realMain = realMain
+ , Dyre.showError = showError
+ }
Notice that all of the program logic is contained in the 'DyreExample'
-module. The main module of the program is absolutely trivial.
+module. The main module of the program is absolutely trivial, being
+essentially just the default configuration for the program:
->-- Main.hs --
->module Main where
->import DyreExample
->main = dyreExample defaultConfig
+ -- Main.hs --
+ import DyreExample
+ main = dyreExample defaultConfig
-When reading the above program, bear in mind exactly how much of the
+When reading the above program, notice that the majority of the
code is simply *program logic*. Dyre is designed to intelligently
-handle recompilation with a bare minimum of program modification.
+handle recompilation with a minimum of programmer work.
Some mention should be made of Dyre's defaults. The 'defaultParams'
structure used in the example defines reasonable default values for
-several configuration items. In the absence of any other definitions,
-Dyre will default to outputting status messages to stderr, not hiding
-any packages during compilation, and passing no special options to GHC.
-
-Also, Dyre will expect configuration files to be placed at the path
-'$XDG_CONFIG_HOME/<app>/<app>.hs', and it will store cache files in
-the '$XDG_CACHE_HOME/<app>/' directory. The 'System.Environment.XDG'
-module will be used to determine these paths, so refer to it for
-behaviour on Windows platforms.
+most configuration items. The three elements defined above are the
+only elements that must be overridden. For documentation of the
+parameters, consult the 'Config.Dyre.Params' module.
+
+In the absence of any customization, Dyre will search for configuration
+files in '$XDG_CONFIG_HOME/<appName>/<appName>.hs', and will store
+cache files in '$XDG_CACHE_HOME/<appName>/' directory. The module
+'System.Environment.XDG' is used for this purpose, which also provides
+analogous behaviour on Windows.
-}
module Config.Dyre ( wrapMain, Params(..), defaultParams ) where
@@ -94,14 +93,8 @@ import Config.Dyre.Compat ( customExec )
import Config.Dyre.Options ( getForceReconf, getDenyReconf, getDebug, withDyreOptions )
import Config.Dyre.Paths ( getPaths, maybeModTime )
--- | A set of reasonable defaults for configuring Dyre. If the minimal set of
--- fields are modified, the program will use the XDG-defined locations for
--- configuration and cache files (see 'System.Environment.XDG.BaseDir' for
--- details), pass no special options to GHC, and will output status messages
--- to stderr.
---
--- The fields that will have to be filled are 'projectName', 'realMain', and
--- 'showError'
+-- | A set of reasonable defaults for configuring Dyre. The fields that
+-- have to be filled are 'projectName', 'realMain', and 'showError'.
defaultParams :: Params cfgType
defaultParams = Params
{ projectName = undefined
View
65 README.mkd
@@ -16,15 +16,13 @@ into an entry-point function.
A complete, working example can be seen here:
-- DyreExample.hs --
- module DyreExample ( dyreExample, Config(..), defaultConf ) where
+ module DyreExample ( dyreExample ) where
import qualified Config.Dyre as Dyre
- data Config = Config { message :: String }
- defaultConf = Config "Hello, world!"
- confError (Config message) error = Config $ "Error:" ++ error ++ "\n" ++ message
+ confError cfgMessage error = "Error:" ++ error ++ "\n" ++ cfgMessage
- realMain (Config message) = do
+ realMain message = do
putStrLn "Entered Main Function"
putStrLn message
@@ -34,28 +32,53 @@ A complete, working example can be seen here:
, Dyre.realMain = realMain
}
+This code defines a simple library which will display a message on stdout. It
+uses Dyre to provide configuration of what exactly the message is. The default
+configuration could look something like this:
+
-- Main.hs --
import DyreExample
- main = dyreExample defaultConf
+ main = dyreExample "This is the default configuration"
+
+While a user's custom configuration would be more like this:
+
+ -- dyreExample.hs --
+ import DyreExample
+ main = dyreExample "This is a custom configuration"
+
+This example can be run without installing. Simply run `Main.hs`[^1] with the
+argument '--dyre-debug', to tell it to search for a configuration file in the
+current directory. If the custom configuration exists, it will be compiled and
+executed, or the default message will be displayed if there is no custom
+configuration.
+
+The `Dyre.wrapMain` function is how Dyre is meant to be invoked. It is passed
+a set of parameters which configure how it operates. Most parameters have some
+good defaults defined in `Dyre.defaultParams`, except for the three defined in
+the above code. For a program to successfully run, those three parameters must
+be overridden.
+
+The `Dyre.projectName` element is used to search for a custom configuration, the
+`Dyre.showError` element is called with compile errors to store the information
+in the program configuration, and `Dyre.realMain` is the function which is
+ultimately the main program entry point.
+
+For the other parameters Dyre uses, consult the `Config.Dyre.Params` module
+documentation.
-The function `dyreExample` which is obtained from the `wrapMain` function is the
-new program entry point. When called with a configuration, it will hand off the
-control to Dyre, which will proceed to recompile and run the custom configuration
-as needed. Eventually, the flow of control will pass back into the `realMain`
-function, at which time Dyre is completely out of the picture.
+[^1] You can compile it with `ghc --make`, or simply use `runhaskell Main.hs`.
Restarting and Persistent State
-------------------------------
-Restarting is handled by the `Config.Dyre.Relaunch` module. The important
-functions are the `relaunchWithState`, and `restoreState` functions. Together,
-they require that your state type be a member of the `Read` and `Show`
-typeclasses.
+Restarting is handled by the `Config.Dyre.Relaunch` module. To simply restart,
+discarding all state information, use the `relaunchMaster` function.
-State can be saved with the `relaunchWithState` function, which takes a state
-and an optional list of arguments. The master binary will be executed with the
-arguments after writing the state to disk.
+If the state needs to be preserved, there are two pairs of functions available.
+When your program starts, you will want to use ether the `restoreTextState` or
+the `restoreBinaryState` function. Both of these take a default state which is
+returned when there is no persisted state to use.
-State is restored with the `restoreState` function. The function takes a default
-state, which is returned when there is no state saved to disk, and should only
-be called once, as the state file is removed after that.
+Then to restart and persist the state, use the function `relaunchWithTextState`
+or `relaunchWithBinaryState` corresponding to your chosen restore function. The
+state will be persisted and your program restarted for you.
Please sign in to comment.
Something went wrong with that request. Please try again.