task (empty) → 0.0.1
raw patch · 5 files changed
+347/−0 lines, 5 filesdep +aesondep +attoparsecdep +basesetup-changed
Dependencies added: aeson, attoparsec, base, bytestring, containers, csv-enumerator, directory, filepath, old-locale, random, text, time, unix
Files
- LICENSE +30/−0
- README.md +134/−0
- Setup.hs +2/−0
- src/Task.hs +142/−0
- task.cabal +39/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c)2012, Sean Seefried++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * 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.++ * Neither the name of Mark Wotton nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++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.
+ README.md view
@@ -0,0 +1,134 @@+# Commands++## task start++### Usage++~~~+task start <description> <key/value...>+~~~++++### Flags:++~~~+-t, --time <time> start at time+-k, --key-value=<key/value> Add key/value pair+~~~++Each key/value pair is of the form <key>:<value> where <key> and <value> are both JSON strings.++## task finish++Finish the current task, if there is one.++### Usage++~~~+task finish+~~~++### Flags++~~~+-t, --time <time> finish at time as long as it is after start time and not in future.+~~~++## task modify++Modifies a single entry if it wouldn't overlap with another one or finish in the future.++### Usage++~~~+task modify <flags>+~~~++### Flags++~~~+--id <id> Modify the task with id <id>+-s, --start <start> Modify start time to <start>+-f, --finish <finish> Modify finish time to <finish>+~~~++## task delete++### Usage++~~~+task delete <flags>+~~~++### Flags++~~~+-- id <id> Delete the task with id <id>+~~~++## task query++Allows you to query the database++### Usage++~~~+task query <flags...>+~~~++### Flags++~~~+-f, --format Format+ %s start time+ %f finish time+ %c category+ %d description+ %k<key> key/value pair for key <key>+ %K all key value pairs, comma seperated+ +--gt <time> Show all entries greater than <time>. Combines with other flags.+--ge <time> Like --gt but "greater than or equal to"+--lt <time> Like --gt but "less than"+--le <time> Like --gt but "less than or equal to"+~~~++## task export++### Usage++~~~+task export <path>+~~~++### Flags++~~~+--csv Export as CSV. Incompatible with --json+--json Export as JSON. Incompatible with --csv+~~~++# Appendix++## Valid keys++Keys can be any valid identifier other than `id`, `start`, `finish`, `category`, `description`. +See *Identifiers*.++## Identifiers++Acceptable characters for ids are JSON strings. JSON strings are++1. any Unicode character except `"` or the `\` control character.+2. a `\` followed by any of:++* `"`. Quotation mark.+* `\`. Backslash.+* `/`. Forward slash.+* `b`. Backspace.+* `f`. Formfeed.+* `n`. Newline.+* `r`. Carriage return.+* `t`. Horizontal tab+* `u` and 4 hexadecimal digits.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ src/Task.hs view
@@ -0,0 +1,142 @@+{-# LANGUAGE OverloadedStrings, PatternGuards #-}+--+-- Author: Sean Seefried+-- Date: Wed 21 Dec 2011+--+module Main where++-- library imports+import Data.Text (Text)+import qualified Data.Text as T+import Text.Printf+import System.Environment (getArgs, getProgName)+import Control.Monad+import System.Exit+import Data.Map (Map)+import qualified Data.Map as Map++-- friends+import StringUtils+import Time++-- The commands+import StartCmd +import ModifyCmd+import ClearCmd+import FinishCmd+import ExportCmd+import CurrentCmd++import GetOpt++main :: IO ()+main = do+ zt <- getZonedTime+ name <- getProgName+ args <- getArgs+ let cmdMap = commandMap name zt+ dispatch (cmd:argsForCmd) =+ case Map.lookup cmd cmdMap of+ Just cmd -> cmdHandler cmd argsForCmd+ Nothing -> printf "%s: '%s' is not a command. See '%s --help'.\n" name cmd name+ when (wantsHelp args) $ do+ putStr $ topLevelHelp name zt+ exitWith ExitSuccess+ let (cmd:restArgs) = args+ when (cmd == "help" && length restArgs > 0) $ do+ putStrLn $ helpFor (head restArgs) cmdMap+ exitWith ExitSuccess+ -- now dispatch+ dispatch args++helpFor :: String -> Map String Command -> String+helpFor cmd cmdMap = case Map.lookup cmd cmdMap of+ Just cmd -> printf "%s\n\n%s" (cmdDesc cmd) (cmdHelp cmd)+ Nothing -> printf "Can't get help for unknown command '%s'" cmd++--------------++data Command = Cmd { cmdId :: String+ , cmdDesc :: String+ , cmdHelp :: String+ , cmdHandler :: [String] -> IO () }++--+-- Note to maintainer:+--+-- The 'cmdHelp' string should not end in a newline.+--+commands :: String -> ZonedTime -> [Command]+commands name zt =+ [ Cmd "start"+ "Start a new task"+ (usageInfo (printf "Usage: %s start [<flags>...]\n\nFlags:" name)+ (startCmdOpts zt))+ (startCmd zt)+ , Cmd "current"+ "Describe the current task"+ (usageInfo (printf "Usage: %s current" name) [])+ (currentCmd zt)+ , Cmd "clear"+ "Clear current task"+ (printf "Usage: %s clear" name)+ clearCmd+ , Cmd "finish"+ "Finish current task"+ (usageInfo (printf "Usage: %s finish [<flags>...]\n\nFlags:" name)+ (finishCmdOpts zt))+ (finishCmd zt)+ , Cmd "modify"+ "Modify a task entry"+ (error "not defined")+ undefined+ , Cmd "delete"+ "Delete a task entry"+ (error "not defined")+ undefined+ , Cmd "query"+ "Query task entries"+ (error "not defined")+ undefined+ , Cmd "export"+ "Export task data in a variety of formats"+ (usageInfo (printf "Usage: %s export [<flags>...]\n\nFlags:" name)+ (exportCmdOpts zt))+ (exportCmd zt)++ ]++commandMap :: String -> ZonedTime -> Map String Command+commandMap name zt = foldl (\m cmd -> Map.insert (cmdId cmd) cmd m) Map.empty (commands name zt)++-----------++topLevelHelp :: String -> ZonedTime -> String+topLevelHelp name zt = unlines $ [+ printf "Usage: %s <command> <flags...>" name+ , ""+ , "Commands:"+ ] ++ (indent 2 . twoColumns 4 $ map f $ commands name zt) +++ [ ""+ , printf "See '%s help <command>' for more information on a specific command." name]++ where f cmd = (cmdId cmd, cmdDesc cmd)++wantsHelp :: [String] -> Bool+wantsHelp args = containsHelp args || length args == 0 || (head args == "help" && length args == 1)++containsHelp :: [String] -> Bool+containsHelp = any pred+ where+ pred s = any (eq s) ["-h", "--help", "-?"]+ eq s s' = strip s == s'+------------------------------++test :: IO ()+test = do+ zt <- getZonedTime+ let mtime = parseTaskTime zt "00:23"+ case mtime of+ Just time -> printf "Local: %s\nUTC: %s\n"+ (show $ utcToZonedTime (zonedTimeZone zt) time) (show time)+ Nothing -> return ()
+ task.cabal view
@@ -0,0 +1,39 @@+Name: task+Version: 0.0.1+Synopsis: A command line tool for keeping track of tasks you worked on+Description: 'task' is a simple command line tool for keeping track of + tasks you are working on. Tasks are kept in a simple+ persistent store. Each task can be tagged with arbitrary+ key/value pairs and the results can be exported to CSV files+ filtered on said key/value pairs.+License: BSD3+License-file: LICENSE+Author: Sean Seefried+Maintainer: sean.seefried@gmail.com++Category: Network+Build-type: Simple+Cabal-version: >= 1.8+Extra-Source-Files: README.md++Source-Repository head+ type: git+ location: git://github.com/sseefried/task.git++Executable task+ Main-is: Task.hs+ Build-depends: base >= 2 && <= 4.5.0.0,+ random,+ containers,+ text,+ time,+ filepath,+ unix,+ directory,+ attoparsec,+ bytestring,+ aeson,+ old-locale,+ csv-enumerator+ + hs-source-dirs: src