packages feed

halive (empty) → 0.1.0.0

raw patch · 5 files changed

+184/−0 lines, 5 filesdep +basedep +bin-package-dbdep +directorysetup-changed

Dependencies added: base, bin-package-db, directory, filepath, foreign-store, fsnotify, ghc, ghc-paths, system-filepath, transformers

Files

+ LICENSE view
@@ -0,0 +1,26 @@+Copyright (c) 2015, Luke Iannini+All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are+met:++1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.++2. Redistributions in binary form must reproduce the above copyright+   notice, this list of conditions and the following disclaimer in the+   documentation and/or other materials provided with the+   distribution.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ exec/main.hs view
@@ -0,0 +1,12 @@+import Halive+import Banner+import System.Environment++main :: IO ()+main = do+    args <- getArgs+    case args of+        [] -> putStrLn "Usage: halive <main.hs> <include dir>"+        (mainName:includeDirs) -> do+            putStrLn banner+            recompiler mainName includeDirs
+ halive.cabal view
@@ -0,0 +1,119 @@+-- Initial halive.cabal generated by cabal init.  For further +-- documentation, see http://haskell.org/cabal/users-guide/++name:                halive+version:             0.1.0.0+synopsis:            A live recompiler+description:         +  > ██╗  ██╗ █████╗ ██╗     ██╗██╗   ██╗███████╗+  > ██║  ██║██╔══██╗██║     ██║██║   ██║██╔════╝+  > ███████║███████║██║     ██║██║   ██║█████╗  +  > ██╔══██║██╔══██║██║     ██║╚██╗ ██╔╝██╔══╝  +  > ██║  ██║██║  ██║███████╗██║ ╚████╔╝ ███████╗+  > ╚═╝  ╚═╝╚═╝  ╚═╝╚══════╝╚═╝  ╚═══╝  ╚══════╝+  +  Live recompiler for Haskell+  +  <<http://lukexi.github.io/HaliveDemo.gif Halive Demo>>+  +  Halive uses the GHC API to instantly recompile+  and reload your code any time you change it.+  +  Usage:+  @cabal install@+  +  and then+  +  @halive \<path\/to\/mymain.hs> \<extra-include-dirs>@+  +  Any time you change a file in the current directory or its+  subdirectories,+  halive will recompile and rerun the @main@ function in the file you gave+  it.+  +  If the program is long-running (e.g. a daemon, GUI or game loop) it will+  be+  killed and restarted. Learn how to maintain state in the next section.+  +  Try a live-coding GL demo by running @halive demo\/Main.hs@ (in the+  source package)+  and changing values in @Main.hs@ and @Green.hs@+  (requires @gl@, @GLFW-b@, @foreign-store@, @linear@, and @random@).+  +  == Keeping values alive+  #keeping-values-alive#+  +  To keep state alive, import @Halive.Utils@ and wrap+  your value in @reacquire@ along with a unique identifier, like:+  +  @win \<- reacquire 0 (setupGLFW \"HotGLFW\" 640 480)@+  +  to only create the resource the first time you run the program, and then+  reuse it on subsequent recompilations.+  +  You can see this in action in @test\/glfw.hs@.+  +  Thanks to Chris Done\'s+  <https://hackage.haskell.org/package/foreign-store @foreign-store@>+  library for enabling this.+  +  == Notes+  #notes#+  +  Creating, updating, and deleting modules in the include path should+  work fine during a Halive session.+  +  Halive also supports Cabal sandboxes;+  if run within a directory containing a cabal.sandbox.config file it will+  use the package database defined therein.+  +  Halive also works nicely with either batch-processing or run-loop type+  programs — if the program finishes, it will be restarted on next save,+  and if it\'s still running, it will be killed and restarted on save.+  +  To kill Halive during run-loop type programs, you may need to hold down+  Ctrl-C+  to get GHC to recognize the double-Control-C-kill sequence.+  +  <http://twitter.com/lukexi \@lukexi>+homepage:            tree.is+license:             BSD2+license-file:        LICENSE+author:              Luke Iannini+maintainer:          lukexi@me.com+-- copyright:           +category:            Development+build-type:          Simple+-- extra-source-files:  +cabal-version:       >=1.10++source-repository head+  type: git+  location: git://github.com/lukexi/halive.git++library+  hs-source-dirs:      src+  exposed-modules:+    Halive.Utils+  default-language:    Haskell2010+  ghc-options:         -Wall+  build-depends:+    base,+    foreign-store+  ++executable halive+  main-is:             main.hs+  hs-source-dirs:      exec+  default-language:    Haskell2010+  ghc-options:         -Wall -threaded -dynamic+  -- other-modules:       +  -- other-extensions:    +  build-depends:+    base >=4.7 && <4.9,+    ghc, ghc-paths, bin-package-db,+    transformers,+    directory, +    filepath, +    fsnotify, +    system-filepath
+ src/Halive/Utils.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE ScopedTypeVariables #-}+module Halive.Utils where+import Foreign.Store+import Data.Word++-- | Takes a unique integer representing your value,+-- along with an IO action to create the first instance+-- of your value to be used on subsequent recompilations.+reacquire :: forall a. Word32 -> IO a -> IO a+reacquire storeID create = do+    -- See if an existing store exists.+    maybeStore <- lookupStore storeID :: IO (Maybe (Store a))+    case maybeStore of+        -- If so, return the value inside+        Just store -> readStore store+        -- Otherwise, create the value, store it, and return it.+        Nothing -> do+            value <- create+            writeStore (Store storeID) value+            return value++-- TODO: a version of forkIO that records each threadID so they+-- can be killed when the program restarts, probably via+-- a 'killOldThreads' function the user calls at the +-- start of their program.