packages feed

shh 0.2.0.2 → 0.2.0.3

raw patch · 4 files changed

+132/−4 lines, 4 filesdep +hashabledep +temporarydep ~asyncdep ~basedep ~directorynew-component:exe:shhPVP: minor bump suggested

API additions: PVP suggests at least a minor version bump

Dependencies added: hashable, temporary

Dependency ranges changed: async, base, directory, split

API changes (from Hackage documentation)

+ Shh: class ExecArgs a
+ Shh: class Unit a

Files

README.md view
@@ -6,6 +6,8 @@ Shh is a library to enable convinient shell-like programming in Haskell. It works well in scripts, and from GHCi, allowing you to use GHCi as a shell. +It is also a wrapper tool around launching GHCi as a shell.+ It supports   * Automatically defining a function for each executable on your `$PATH`@@ -99,6 +101,20 @@     ls &!> StdOut  Redirect stderr of `ls` to wherever stdout is going.     StdOut <!& ls  Same as above +## Globbing++Currently Shh does not have any built in globbing support. Rather, it is+currently suggested to use another library to do globbing. For example,+using the [Glob](http://hackage.haskell.org/package/Glob) package, it is+possible to do something like++    wc =<< glob "*.md"++Certainly more verbose than the Bash equivalent, however, also more explicit,+which is probably a good thing. If this turns out to be too cumbersome, we+might introduce a more succinct globbing feature, though it will always be+explicit, and thus always more verbose than most other shells.+ ## Usage  Enable Temlpate Haskell and load the environment@@ -120,7 +136,31 @@ `initInteractive` function. This sets the line buffering appropriately and ensures the terminal is in canonical mode. +### Shh as a Shell++There is a tool called `shh` which is a fairly small wrapper around launching+GHCi which automatically loads your environment and allows you to have custom+config when using GHCi as a shell.++The `shh` binary will look in your `$SHH_DIR` (defaults to `$HOME/.shh`) for+a `Shell.hs`, `init.ghci` and `wrapper` files. If these don't exist default+ones will be created.++The `Shell.hs` file should contain any top level definitions that you would+like to be available in your Shell. By default it loads your environment.++The `init.ghci` file is loaded by GHCi after your `.ghci` files. This lets+you specify settings that you want to take effect when using GHCi as a shell.+By default it sets a shell-like prompt.++The `wrapper` file is an executable that is called with the command that is+to be executed. By default it just calls `exec` with the arguments passed to+it. The use-case for this is to be able to set up the environment for `shh`.+You might, for example, wrap the execution in a `nix-shell`. Either way,+it is up to you to make sure that the compiler, and packages you require are+available, either globally, or provided by the `wrapper` script.+ ### Script Usage -TODO: Fill this in once on Hackage.+TODO: Fill this in once the user experience is better.     
+ app/shh-app.hs view
@@ -0,0 +1,70 @@+{-# LANGUAGE LambdaCase #-}+module Main where++import Shh+import System.IO+import System.Environment+import System.IO.Temp+import System.Directory+import Data.Hashable (hash)+import Data.List.Split (splitOn)++defaultShell = "\+\{-# LANGUAGE TemplateHaskell #-}\n\+\module Shell where\n\+\import Shh\n\+\$(loadEnv SearchPath)\n\+\ "++defaultInitGhci = "\+\:seti -XNoOverloadedLists\n\+\import Shh\n\+\import Shh.Prompt\n\+\:set prompt-function promptFormat \"\\n\\ESC[1;32m[%u@%h:%w]λ \\ESC[0m\"\n\+\:set prompt-cont \"| \"\n\+\ "+++defaultWrapper = "\+\#! /usr/bin/env sh\n\+\exec \"$@\"\n\+\ "++debug = putStrLn++writeIfMissing :: FilePath -> String -> IO ()+writeIfMissing fp s = do+    doesFileExist fp >>= \case+        True -> pure ()+        False -> writeFile fp s++main :: IO ()+main = do+    a <- getArgs+    shhDir <- lookupEnv "SHH_DIR" >>= \case+        Nothing -> lookupEnv "HOME" >>= \case+            Nothing -> error "Please specify HOME or SHH_DIR environment variables"+            Just h  -> pure $ h <> "/.shh"+        Just s -> pure s++    let+        wrapped :: (Unit a, ExecArgs a) => a+        wrapped = exe (shhDir <> "/wrapper")+++    debug $ "Shh home is: " <> shhDir++    createDirectoryIfMissing False shhDir++    withCurrentDirectory shhDir $ do+        writeIfMissing "init.ghci" defaultInitGhci+        writeIfMissing "wrapper" defaultWrapper+        setPermissions "wrapper" $+            setOwnerExecutable True $+            setOwnerReadable True $+            setOwnerWritable True $+            emptyPermissions+        writeIfMissing "Shell.hs" defaultShell++    wrapped "ghci" "-ghci-script" (shhDir <> "/init.ghci") (shhDir <> "/Shell.hs")+
shh.cabal view
@@ -1,5 +1,5 @@ name:                shh-version:             0.2.0.2+version:             0.2.0.3 synopsis:            Simple shell scripting from Haskell description:         Provides a shell scripting environment for Haskell. It                      helps you all external binaries, and allows you to@@ -9,7 +9,7 @@ license-file:        LICENSE author:              Luke Clifton maintainer:          lukec@themk.net-copyright:           (c) 2018 Luke Clifton+copyright:           (c) 2018, 2019 Luke Clifton category:            System build-type:          Simple extra-source-files:  ChangeLog.md, README.md@@ -37,6 +37,23 @@   default-language:    Haskell2010   ghc-options: -Wall +executable shh+  ghc-options: -threaded+  default-language: Haskell2010+  build-depends:+    base >=4.9,+    async,+    hashable,+    hashable,+    temporary,+    directory,+    shh,+    split+  hs-source-dirs: app+  main-is: shh-app.hs+  build-tools:+    ghc+ executable shh-example   ghc-options: -threaded -with-rtsopts=-N   default-language: Haskell2010@@ -48,7 +65,6 @@   main-is: Example.hs   build-tools:     coreutils,-    vault,     vim    
src/Shh.hs view
@@ -48,6 +48,8 @@     , catchCode     -- | == Constructing Arguments     , ExecArg(..)+    , ExecArgs()+    , Unit()     -- | == Template Haskell helpers     , ExecReference(..)     , load