herms 1.8.2.1 → 1.8.2.2
raw patch · 5 files changed
+58/−53 lines, 5 filesdep ~brickdep ~vty
Dependency ranges changed: brick, vty
Files
- README.md +16/−15
- app/herms.hs +32/−29
- herms.cabal +5/−5
- src/ReadConfig.hs +1/−1
- src/Types.hs +4/−3
README.md view
@@ -26,19 +26,18 @@ ### Installation -#### PATH setup+At the moment, Herm's can only be installed via [stack](https://docs.haskellstack.org/en/stable/README/) or [cabal](https://www.haskell.org/cabal/), but standalone binaries are in the works! -Firstly, make sure that the following is added to your PATH:+If you're interested developing/hacking Herm's instead of just using it, see [Contributing.md](Contibuting.md) instead. +##### Via Stack _(recommended)_:+ ```-~/.cabal/bin+stack update+stack install herms ``` -#### Download and install--At the moment, Herm's can only be compiled from source, but binaries are in the works!--##### Manually cloning and installing from source with Stack _(recommended)_:+##### Manually cloning and installing from source with Stack ``` git clone https://github.com/JackKiefer/herms@@ -49,6 +48,8 @@ ##### Via Hackage and Cabal: +_Note_: Your milage may vary with dependency resolution+ ``` cabal update cabal install herms@@ -56,20 +57,20 @@ ##### Manually with Cabal: -Your milage may vary with dependency resolution+_Note_: Your milage may vary with dependency resolution ``` git clone https://github.com/JackKiefer/herms cd herms cabal update-cabal install -j+cabal install ``` ### Usage -#### Command-line interface +#### Command-line interface -Herm's has a pretty intuitive interface for users familiar with other command-line programs! +Herm's has a pretty intuitive interface for users familiar with other command-line programs! Below is the exhaustive list of all commands and their functionalities. Take a gander! @@ -78,7 +79,7 @@ herms list [-g|--group] [--tags TAGS] list recipes [--name-only ]- + herms add add a new recipe (interactively) herms edit RECIPE_NAME edit a recipe@@ -89,7 +90,7 @@ herms view RECIPE_NAMES [-s|--serving INT] view the particular recipes [-t|--step]- [-c|--convert CONV_UNIT] + [-c|--convert CONV_UNIT] herms shopping RECIPE_NAMES [-s|--serving INT] generate shopping list for particular recipes @@ -129,7 +130,7 @@ - `defaultUnit` : The default unit system to show recipes in. Options: `Imperial`, `Metric`, `None`. Setting to `None` will simply show recipes in whatever unit system they're stored in. - `defaultServingSize` : Default serving size to calculate when showing recipes. Can be any non-negative integer; set to `0` for no default. This can be useful when you're always cooking for the same number of people!-- `recipesFile` : The recipes file and relative location. Make sure the file already exists by running `touch FILENAME` before running Herm's or it will throw a fit. This option currently supports relative location, as well; if your data directory is `~/herms/data`, for example, and you want a recipe file in your home directoy called `~/GrandmasHugeCookbook.herms`, set this option to `"../../GrandmasHugeCookbook.herms"`.+- `recipesFile` : The recipes file to us. This option currently supports relative (but not absolute) location, as well; if your data directory is `~/herms/data`, for example, and you want a recipe file in your home directoy called `~/GrandmasHugeCookbook.herms`, set this option to `"../../GrandmasHugeCookbook.herms"`. ---
app/herms.hs view
@@ -20,6 +20,9 @@ import UnitConversions import ReadConfig import Paths_herms+import Control.Exception+import GHC.IO.Exception+import Foreign.C.Error -- Global constants versionStr :: String@@ -56,16 +59,16 @@ then do config <- getConfig recipeBook <- getRecipeBookWith config- let recpName = if isNothing oldRecp then recipeName newRecipe else recipeName (fromJust oldRecp)+ let recpName = maybe (recipeName newRecipe) recipeName oldRecp unless (isNothing (readRecipeRef recpName recipeBook)) $ removeSilent [recpName] fileName <- getDataFileName (recipesFile config) appendFile fileName (show newRecipe ++ "\n") putStrLn "Recipe saved!" else if response == "n" || response == "N"- then do+ then putStrLn "Changes discarded." else if response == "e" || response == "E"- then do+ then doEdit newRecipe oldRecp else do@@ -83,7 +86,7 @@ saveOrDiscard input origRecp where serving = show $ servingSize recp ingrList = adjustIngredients (servingSize recp % 1) $ ingredients recp- toStr = (\ f -> unlines (map f ingrList))+ toStr f = unlines (map f ingrList) amounts = toStr (showFrac . quantity) units = toStr unit ingrs = toStr ingredientName@@ -111,7 +114,7 @@ importFile target = do config <- getConfig recipeBook <- getRecipeBookWith config- otherRecipeBook <- (map read . lines) <$> readFile target+ otherRecipeBook <- map read . lines <$> readFile target let recipeEq = (==) `on` recipeName let newRecipeBook = deleteFirstsBy recipeEq recipeBook otherRecipeBook ++ otherRecipeBook@@ -123,19 +126,23 @@ forM_ otherRecipeBook $ \recipe -> putStrLn $ " " ++ recipeName recipe -view :: [String] -> Int -> String -> IO ()-view targets serv convName = do- config <- getConfig- recipeBook <- getRecipeBookWith config- let servings = case serv of- 0 -> (case defaultServingSize config of+getServingsAndConv :: Int -> String -> Config -> (Maybe Int, Conversion)+getServingsAndConv serv convName config = (servings, conv)+ where servings = case serv of+ 0 -> case defaultServingSize config of 0 -> Nothing- j -> Just j)+ j -> Just j i -> Just i- let conv = case convName of+ conv = case convName of "metric" -> Metric "imperial" -> Imperial- _ -> (defaultUnit config)+ _ -> defaultUnit config++view :: [String] -> Int -> String -> IO ()+view targets serv convName = do+ config <- getConfig+ recipeBook <- getRecipeBookWith config+ let (servings, conv) = getServingsAndConv serv convName config forM_ targets $ \ target -> putText $ case readRecipeRef target recipeBook of Nothing -> target ~~ " does not exist\n"@@ -145,15 +152,7 @@ viewByStep targets serv convName = do config <- getConfig recipeBook <- getRecipeBookWith config- let servings = case serv of- 0 -> (case defaultServingSize config of- 0 -> Nothing- j -> Just j)- i -> Just i- let conv = case convName of- "metric" -> Metric- "imperial" -> Imperial- _ -> (defaultUnit config)+ let (servings, conv) = getServingsAndConv serv convName config hSetBuffering stdout NoBuffering forM_ targets $ \ target -> case readRecipeRef target recipeBook of Nothing -> putStr $ target ++ " does not exist\n"@@ -214,12 +213,13 @@ showTags = fontColor Green $ (intercalate ", " . tags) recipe takeFullWords :: String -> String-takeFullWords = (unwords . takeFullWords' 0 . words)- where takeFullWords' n (x:[]) | (length x + n) > 40 = []+takeFullWords = unwords . takeFullWords' 0 . words+ where takeFullWords' _ [] = []+ takeFullWords' n [x] | (length x + n) > 40 = [] | otherwise = [x] takeFullWords' n (x:xs) | (length x + n) > 40 = [x ++ "..."] | otherwise =- [x] ++ takeFullWords' ((length x) + n) xs+ x : takeFullWords' (length x + n) xs -- | @replaceDataFile fp str@ replaces the target data file @fp@ with -- the new content @str@ in a safe manner: it opens a temporary file@@ -233,7 +233,10 @@ hClose tempHandle fileName <- getDataFileName fp removeFile fileName- renameFile tempName fileName+ let exdev e = if ioe_errno e == Just ((\(Errno a) -> a) eXDEV)+ then copyFile tempName fileName >> removeFile tempName+ else throw e+ renameFile tempName fileName `catch` exdev -- | @removeWithVerbosity v recipes@ deletes the @recipes@ from the -- book, listing its work only if @v@ is set to @True@.@@ -430,9 +433,9 @@ (progDesc "show location of recipe and config files")) versionOption :: Parser (a -> a)-versionOption = infoOption versionStr +versionOption = infoOption versionStr (long "version"- <> short 'v' + <> short 'v' <> help "Show version") -- @prsr is the main parser of all CLI arguments.
herms.cabal view
@@ -6,9 +6,9 @@ -- The package description description: HeRM's: a Haskell-based Recipe Manager for delicious kitchen recipes-tested-with: GHC == 7.10.3- GHC == 8.0.2+tested-with: GHC == 8.4.1 GHC == 8.2.2+ GHC == 8.0.2 -- The package version. See the Haskell package versioning policy (PVP) -- for standards guiding when and how versions should be incremented.@@ -16,7 +16,7 @@ -- PVP summary: +-+------- New features or improvements with significant API change -- | | +----- Bugfixes and improvements with minor change to API -- | | | +--- Bugfixes and improvements with no change to API-version: 1.8.2.1+version: 1.8.2.2 -- A short (one-line) description of the package. synopsis: A command-line manager for delicious kitchen recipes@@ -80,14 +80,14 @@ -- Other library packages from which modules are imported. build-depends: ansi-terminal >= 0.7.0 && <= 0.8.1 , base >=4.8 && <5- , brick >= 0.35 && < 0.36+ , brick >= 0.19 && < 0.37 , directory >= 0.0 , microlens >=0.4 && <0.5 , microlens-th >=0.4 && <0.5 , optparse-applicative >=0.14 && <0.15 , semigroups >= 0.18.3 && <= 0.18.4 , split >=0.2 && <0.3- , vty >=5.21 && < 5.22+ , vty >=5.15 && < 5.22 -- Directories containing source files.
src/ReadConfig.hs view
@@ -22,7 +22,7 @@ instance Exception ConfigParseError dropComments :: String -> String-dropComments = unlines . map (head . (splitOn "--")) . lines+dropComments = unlines . map (head . splitOn "--") . lines getConfig :: IO Config getConfig = do
src/Types.hs view
@@ -2,6 +2,7 @@ import Data.List import Data.List.Split+import Data.Maybe import Data.Ratio import Data.Ord import RichText@@ -53,7 +54,7 @@ showIngredient servings i = qty ++ u ++ ingredientName i ++ att where qty = if quantity i == 0 then ""- else (showFrac (quantity i * (servings % 1))) ++ " "+ else showFrac (quantity i * (servings % 1)) ++ " " u = if null (unit i) then "" else unit i ++ " " att = if null (attribute i) then "" else ", " ++ attribute i @@ -73,7 +74,7 @@ adjustIngredients :: Ratio Int -> [Ingredient] -> [Ingredient] adjustIngredients factor = map adjustIngredient where adjustIngredient ingredient =- ingredient{ quantity = (quantity ingredient * factor) }+ ingredient{ quantity = quantity ingredient * factor } showRecipe :: Recipe -> Maybe Int -> RichText showRecipe r maybeServings = showRecipeHeader r maybeServings@@ -86,7 +87,7 @@ ~~ bold "\nIngredients:\n" ~~ unlines (map ((++) "* " . showIngredient servings) (ingredients r)) where filler = replicate (length (recipeName r) + 2) '-'- servings = maybe (servingSize r) id maybeServings+ servings = fromMaybe (servingSize r) maybeServings nameBox = fontColor Magenta $ bold $ "+--" ~~ filler ~~ "+\n" ~~ "| " ~~ recipeName r ~~ " |\n" ~~ "+--" ~~ filler ~~ "+\n"