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 +3/−0
- LICENSE +21/−0
- README.md +69/−0
- Setup.hs +2/−0
- app/Main.hs +16/−0
- slate.cabal +72/−0
- src/Lib.hs +211/−0
- test/Spec.hs +2/−0
+ 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"