packages feed

slate (empty) → 0.2.0.0

raw patch · 8 files changed

+396/−0 lines, 8 filesdep +basedep +directorydep +filepathsetup-changed

Dependencies added: base, directory, filepath, optparse-applicative, slate

Files

+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for slate++## Unreleased changes
+ LICENSE view
@@ -0,0 +1,21 @@+MIT License++Copyright (c) 2017 evuez++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in all+copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE+SOFTWARE.
+ README.md view
@@ -0,0 +1,69 @@+# slate - a note taking tool.++A simple tool to take notes from your terminal.++Generates markdown [task lists](https://help.github.com/articles/about-task-lists/).++Lists are stored in `~/.config/slate/` and their default name is the name of your current directory. You can use any other name you want using the `--name` option.++## Install++```shell+$ stack install+```++## Usage++<pre>+$ slate --help++slate - a note taking tool.++Usage: slate COMMAND+  Slate++Available options:+  -h,--help                Show this help text++Available commands:+  add                      Add a note.+  done                     Mark a note as done.+  todo                     Mark a note as to-do.+  remove                   Remove a note.+  display                  Display a slate.+  rename                   Rename a slate.+  wipe                     Wipe a slate.++$ slate add "My first note."+$ slate add "New note!"+$ slate display+00 - My first note.+01 - New note!++$ slate done 0+$ slate display+<s>00 - My first note.</s>+01 - New note!++$ slate display --only=todo+01 - New note!++$ slate add "Fake note"+$ slate display+<s>00 - My first note.</s>+01 - New note!+02 - Fake note++$ slate remove 2+$ slate display+<s>00 - My first note.</s>+01 - New note!++$ slate wipe --only=todo+$ slate display+<s>00 - My first note.</s>++$ slate todo 0+$ slate display+00 - My first note.+</pre>
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,16 @@+module Main where++import Data.Semigroup ((<>))+import Lib+import Options.Applicative++main :: IO ()+main = do+  initialize+  parsedOpts <- execParser opts+  execute parsedOpts+  where+    opts =+      info+        (parser <**> helper)+        (fullDesc <> progDesc "Slate" <> header "slate - a note taking tool.")
+ slate.cabal view
@@ -0,0 +1,72 @@+-- This file has been generated from package.yaml by hpack version 0.20.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: 0c4dd43c3f2d0caa98d5db89c38d2085527502780a7656087a24d835af4321e8++name:           slate+version:        0.2.0.0+synopsis:       A note taking CLI tool.+description:    Please see the README on Github at <https://github.com/evuez/slate#readme>+homepage:       https://github.com/evuez/slate#readme+bug-reports:    https://github.com/evuez/slate/issues+author:         evuez+maintainer:     helloevuez@gmail.com+copyright:      Copyright (c) 2017, evuez+license:        MIT+license-file:   LICENSE+build-type:     Simple+cabal-version:  >= 1.10++extra-source-files:+    ChangeLog.md+    README.md++source-repository head+  type: git+  location: https://github.com/evuez/slate++library+  hs-source-dirs:+      src+  build-depends:+      base >=4.7 && <5+    , directory >=1.3+    , filepath >=1.4+    , optparse-applicative >=0.14+  exposed-modules:+      Lib+  other-modules:+      Paths_slate+  default-language: Haskell2010++executable slate+  main-is: Main.hs+  hs-source-dirs:+      app+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , directory >=1.3+    , filepath >=1.4+    , optparse-applicative >=0.14+    , slate+  other-modules:+      Paths_slate+  default-language: Haskell2010++test-suite slate-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  hs-source-dirs:+      test+  ghc-options: -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      base >=4.7 && <5+    , directory >=1.3+    , filepath >=1.4+    , optparse-applicative >=0.14+    , slate+  other-modules:+      Paths_slate+  default-language: Haskell2010
+ src/Lib.hs view
@@ -0,0 +1,211 @@+module Lib+  ( initialize+  , execute+  , parser+  ) where++import Data.Semigroup ((<>))+import Options.Applicative+import System.Directory+  ( createDirectoryIfMissing+  , getCurrentDirectory+  , getHomeDirectory+  , removeFile+  , renameFile+  )+import System.FilePath.Posix (takeBaseName)++type Slate = String++type Note = String++type NoteId = Int++type Filter = String++data Command+  = Add Slate+        Note+  | Done Slate+         NoteId+  | Todo Slate+         NoteId+  | Remove Slate+           NoteId+  | Display Slate+            Filter+  | Rename Slate+           Slate+  | Wipe Slate+         Filter+  deriving (Eq, Show)++-- Parsers+name :: Parser String+name =+  option+    str+    (long "name" <> short 'n' <> metavar "SLATE" <> help "Name of the slate." <>+     value "")++add :: Parser Command+add = Add <$> name <*> argument str (metavar "NOTE")++done :: Parser Command+done = Done <$> name <*> argument auto (metavar "NOTE ID")++todo :: Parser Command+todo = Todo <$> name <*> argument auto (metavar "NOTE ID")++remove :: Parser Command+remove = Remove <$> name <*> argument auto (metavar "NOTE ID")++display :: Parser Command+display =+  Display <$> name <*>+  option+    str+    (long "only" <> short 'o' <> help "Display only done / todo notes." <>+     value "")++rename :: Parser Command+rename =+  Rename <$> argument str (metavar "CURRENT" <> help "Current name.") <*>+  argument str (metavar "NEW" <> help "New name.")++wipe :: Parser Command+wipe =+  Wipe <$> name <*>+  option+    str+    (long "only" <> short 'o' <> help "Wipe only done / todo notes." <> value "")++parser :: Parser Command+parser =+  subparser+    (command "add" (info add (progDesc "Add a note.")) <>+     command "done" (info done (progDesc "Mark a note as done.")) <>+     command "todo" (info todo (progDesc "Mark a note as to-do.")) <>+     command "remove" (info remove (progDesc "Remove a note.")) <>+     command "display" (info display (progDesc "Display a slate.")) <>+     command "rename" (info rename (progDesc "Rename a slate.")) <>+     command "wipe" (info wipe (progDesc "Wipe a slate.")))++-- Commands+execute :: Command -> IO ()+execute (Add "" n) = getSlateName >>= (\s -> execute (Add s n))+execute (Add s n) =+  getSlatePath s >>= (\x -> appendFile x (" - [ ] " ++ n ++ "\n"))+execute (Done "" n) = getSlateName >>= (\x -> execute (Done x n))+execute (Done s n) = getSlatePath s >>= (\x -> markAsDone x n)+execute (Todo "" n) = getSlateName >>= (\x -> execute (Todo x n))+execute (Todo s n) = getSlatePath s >>= (\x -> markAsTodo x n)+execute (Remove "" n) = getSlateName >>= (\x -> execute (Remove x n))+execute (Remove s n) = getSlatePath s >>= (\x -> removeNote x n)+execute (Display "" f) = getSlateName >>= (\x -> execute (Display x f))+execute (Display s f) = getSlatePath s >>= (\x -> displaySlate x f)+execute (Rename sc sn) = renameSlate sc sn+execute (Wipe "" f) = getSlateName >>= (\x -> execute (Wipe x f))+execute (Wipe s "") = getSlatePath s >>= removeFile+execute (Wipe s f) = getSlatePath s >>= (\x -> wipeSlate x f)++-- Helpers+initialize :: IO ()+initialize = getConfigDirectory >>= (\c -> createDirectoryIfMissing True c)++getSlateName :: IO String+getSlateName = do+  directory <- getCurrentDirectory+  return $ takeBaseName directory++getConfigDirectory :: IO String+getConfigDirectory = do+  home <- getHomeDirectory+  return $ home ++ "/.config/slate/"++getSlatePath :: String -> IO FilePath+getSlatePath s = do+  dir <- getConfigDirectory+  return $ dir ++ s ++ ".md"++displaySlate :: String -> String -> IO ()+displaySlate s "" = do+  contents <- readFile s+  let notes = zipWith displayNote [0 ..] (lines contents)+  putStr $ unlines notes+displaySlate s "done" = do+  contents <- readFile s+  let notes = zipWith displayNote [0 ..] (lines contents)+  putStr $ unlines $ filter isNoteDone notes+displaySlate s "todo" = do+  contents <- readFile s+  let notes = zipWith displayNote [0 ..] (lines contents)+  putStr $ unlines $ filter (not . isNoteDone) notes+displaySlate _ f = putStr $ "\"" ++ f ++ "\" is not a valid filter."++displayNote :: Int -> String -> String+displayNote line (' ':'-':' ':'[':' ':']':note) = padInt line 2 ++ " -" ++ note+displayNote line (' ':'-':' ':'[':'x':']':note) =+  "\x1B[9m" ++ padInt line 2 ++ " -" ++ note ++ "\x1B[0m"+displayNote line _ =+  "\x1B[31m" +++  padInt line 2 ++ " - Parsing error: line is malformed" ++ "\x1B[0m"++isNoteDone :: String -> Bool+isNoteDone (' ':'-':' ':'[':'x':']':_) = True+isNoteDone ('\x1B':_) = True+isNoteDone _ = False++padInt :: Int -> Int -> String+padInt n s = replicate (s - length (show n)) '0' ++ show n++markAsDone :: FilePath -> Int -> IO ()+markAsDone s n = do+  contents <- readFile s+  let (x, y:t) = splitAt n (lines contents)+      c =+        case y of+          ' ':'-':' ':'[':' ':']':note -> " - [x]" ++ note+          note -> note+      tmp = s ++ ".tmp"+  writeFile (s ++ ".tmp") (unlines $ x ++ c : t)+  renameFile tmp s++markAsTodo :: FilePath -> Int -> IO ()+markAsTodo s n = do+  contents <- readFile s+  let (x, y:t) = splitAt n (lines contents)+      c =+        case y of+          ' ':'-':' ':'[':'x':']':note -> " - [ ]" ++ note+          note -> note+      tmp = s ++ ".tmp"+  writeFile tmp (unlines $ x ++ c : t)+  renameFile tmp s++removeNote :: FilePath -> Int -> IO ()+removeNote s n = do+  contents <- readFile s+  let (x, _:t) = splitAt n (lines contents)+      tmp = s ++ ".tmp"+  writeFile tmp (unlines $ x ++ t)+  renameFile tmp s++renameSlate :: String -> String -> IO ()+renameSlate sc sn = do+  current <- getSlatePath sc+  new <- getSlatePath sn+  renameFile current new++wipeSlate :: FilePath -> String -> IO ()+wipeSlate s "done" = do+  contents <- readFile s+  let tmp = s ++ ".tmp"+  writeFile tmp $ unlines $ filter (not . isNoteDone) (lines contents)+  renameFile tmp s+wipeSlate s "todo" = do+  contents <- readFile s+  let tmp = s ++ ".tmp"+  writeFile tmp $ unlines $ filter isNoteDone (lines contents)+  renameFile tmp s+wipeSlate _ f = putStr $ "\"" ++ f ++ "\" is not a valid filter."
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"