Skip to content

Commit

Permalink
add due time #9
Browse files Browse the repository at this point in the history
  • Loading branch information
soywod committed Dec 28, 2019
1 parent d039f58 commit 8003f96
Show file tree
Hide file tree
Showing 10 changed files with 138 additions and 80 deletions.
10 changes: 9 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [0.3.0] - 2019-12-28

### Added

- Due time [#9]

### Changed

- Make `+` optional in `context` and `worktime` commands [#16]
Expand All @@ -20,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added

- Worktime date range [#9]
- Due time [#9]

### Fixed

Expand Down Expand Up @@ -93,7 +100,8 @@ First release :tada:

- Linux binaries

[unreleased]: https://github.com/unfog-io/unfog-cli/compare/v0.2.2...HEAD
[unreleased]: https://github.com/unfog-io/unfog-cli/compare/v0.3.0...HEAD
[0.2.2]: https://github.com/unfog-io/unfog-cli/compare/v0.2.2...v0.3.0
[0.2.2]: https://github.com/unfog-io/unfog-cli/compare/v0.2.1...v0.2.2
[0.2.1]: https://github.com/unfog-io/unfog-cli/compare/v0.2.0...v0.2.1
[0.2.0]: https://github.com/unfog-io/unfog-cli/compare/v0.1.4...v0.2.0
Expand Down
100 changes: 53 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,25 @@ A simple task and time manager, written in [Haskell](https://www.haskell.org).

## Table of contents

* [Installation](#installation)
* [From binaries](#from-binaries)
* [From sources](#from-sources)
* [Usage](#usage)
* [Create](#create)
* [Show](#read)
* [List](#list)
* [Update](#update)
* [Toggle](#toggle)
* [Done](#done)
* [Delete](#delete)
* [Remove](#remove)
* [Context](#context)
* [Worktime](#worktime)
* [Options](#options)
* [JSON](#json)
* [Contributing](#contributing)
* [Changelog](https://github.com/unfog-io/unfog-cli/blob/master/CHANGELOG.md#changelog)
* [Credits](#credits)
* [Installation](#installation)
* [From binaries](#from-binaries)
* [From sources](#from-sources)
* [Usage](#usage)
* [Create](#create)
* [Show](#read)
* [List](#list)
* [Update](#update)
* [Toggle](#toggle)
* [Done](#done)
* [Delete](#delete)
* [Remove](#remove)
* [Context](#context)
* [Worktime](#worktime)
* [Options](#options)
* [JSON](#json)
* [Contributing](#contributing)
* [Changelog](https://github.com/unfog-io/unfog-cli/blob/master/CHANGELOG.md#changelog)
* [Credits](#credits)

## Installation
### From binaries
Expand Down Expand Up @@ -57,16 +57,28 @@ stack install

To create a task, you need:

- A description
- A list of tags *(optional)*
- A description
- A list of tags *(optional)*
- A due time *(optional)*

```bash
unfog create <desc> <+tag1> <+tag2> ...
unfog create <desc> <+tag1> <+tag2> <:due:time>...
```

![image](https://user-images.githubusercontent.com/10437171/69493623-1145aa80-0eb1-11ea-8e34-f14bb3c831bc.png)

*Note: a tag should always start by `+`.*
A tag should start by `+` and should be composed of alpha numeral chars.

A due time should follow the format `:DDMMYY:HHMM`, where almost everything is
optional. Each omitted field is replaced by the current date one. Here some
use cases (given now = `2019/12/22 10:00`):

| Given arg | Due time |
| --- | --- |
| `:21` | 2019/12/21 00:00 |
| `:18:8` | 2019/12/18 08:00 |
| `::12` | 2019/12/22 12:00 |
| `:1010` | 2019/10/10 00:00 |

### Show

Expand All @@ -87,7 +99,7 @@ unfog list
### Update

```bash
unfog update <id> <desc> <+tag1> <-tag2> ...
unfog update <id> <desc> <+tag1> <-tag2> <:due:time>...
```

### Toggle
Expand Down Expand Up @@ -135,6 +147,8 @@ unfog context <+tag1> <+tag2> ...

The special context `+done` allows you to see done tasks:

*Note: the `+` can be omitted.*

```bash
unfog context +done
```
Expand All @@ -149,23 +163,16 @@ Shows the total worktime spent on tasks belonging to the given context, grouped
by days. An empty context will show the worktime of all your tasks.

You can also filter them with a date range. Min date starts by `[`, and max
date by `]`. The date range should follow the format `DDMMYY:HHMM`, where
almost everything is optional. Default fields are based on the current date.
Here some use cases (given now = `2019/12/22 10:00`):

| Given arg | Result |
| --- | --- |
| `[21` | Starting at 2019/12/21 00:00 |
| `[18:8` | Starting at 2019/12/18 08:00 |
| `]:12` | Ending at 2019/12/22 12:00 |
| `[1010 ]1510` | Between 2019/10/10 00:00 and 2019/10/15 23:59 |
date by `]`. The date range should follow the due time format (see [#create]).

```bash
unfog wtime <+tag1> <+tag2> <[min> <]max> ...
unfog wtime <+tag1> <+tag2> <[min:range> <]max:range> ...
```

![image](https://user-images.githubusercontent.com/10437171/69493775-2ae7f180-0eb3-11ea-88a3-a59eb088830e.png)

*Note: the `+` can be omitted.*

## Options
### JSON

Expand All @@ -185,20 +192,19 @@ Task {
pos: Int
desc: String
tags: [String]
active: 0 | 1
active: TimeRecord
due: TimeRecord
done: 0 | 1
wtime: WtimeRecord
}
Worktime {
total: WtimeRecord,
wtimes: [{
date: String (day)
wtime: WtimeRecord,
}]
wtime: {
total: TimeRecord,
wtimes: [{
date: String (day)
wtime: TimeRecord,
}]
}
}
WtimeRecord {
TimeRecord {
approx: String (worktime approximation)
human: String (full worktime)
micro: Int (worktime in micro seconds)
Expand All @@ -209,7 +215,7 @@ WtimeRecord {

This is useful to create user interafaces. Here the list of current implementations:

- [Unfog.vim](https://github.com/unfog-io/unfog-vim) for Vim/Neovim
- [Unfog.vim](https://github.com/unfog-io/unfog-vim) for Vim/Neovim

## Contributing

Expand Down
2 changes: 1 addition & 1 deletion package.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: unfog
version: 0.2.2
version: 0.3.0
github: "unfog-io/unfog-cli"
license: BSD3
author: "Clément DOUIN"
Expand Down
6 changes: 3 additions & 3 deletions src/Command.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import Utils
import qualified Parsec

data Command
= CreateTask UTCTime Ref Id Pos Desc [Tag] (Maybe Duration)
| UpdateTask UTCTime Ref Id Pos Desc [Tag] (Maybe Duration)
= CreateTask UTCTime Ref Id Pos Desc [Tag] (Maybe UTCTime)
| UpdateTask UTCTime Ref Id Pos Desc [Tag] (Maybe UTCTime)
| StartTask UTCTime Ref Id
| StopTask UTCTime Ref Id
| MarkAsDoneTask UTCTime Ref Id Id
Expand Down Expand Up @@ -74,7 +74,7 @@ createTask t args state = CreateTask t ref id pos desc tags due
pos = -1
desc = Parsec._desc args
tags = Parsec._tags args `union` _ctx state
due = Nothing
due = Parsec.parseDue t args

updateTask :: UTCTime -> Parsec.ArgTree -> State -> Command
updateTask t args state = case Parsec._id args of
Expand Down
4 changes: 2 additions & 2 deletions src/Event.hs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import Data.Time
import Task

data Event
= TaskCreated UTCTime Ref Id Pos Desc [Tag] (Maybe Duration)
| TaskUpdated UTCTime Ref Id Pos Desc [Tag] (Maybe Duration)
= TaskCreated UTCTime Ref Id Pos Desc [Tag] (Maybe UTCTime)
| TaskUpdated UTCTime Ref Id Pos Desc [Tag] (Maybe UTCTime)
| TaskStarted UTCTime Ref Id
| TaskStopped UTCTime Ref Id
| TaskMarkedAsDone UTCTime Ref Id
Expand Down
29 changes: 21 additions & 8 deletions src/Parsec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ data Arg
| SetId Int
| AddTag String
| DelTag String
| SetDue ArgDate
| SetMinDate ArgDate
| SetMaxDate ArgDate
| AddWord String
Expand All @@ -39,6 +40,7 @@ data ArgTree = ArgTree { _type :: ArgType
, _id :: Int
, _desc :: String
, _tags :: [String]
, _due :: Maybe ArgDate
, _minDate :: Maybe ArgDate
, _maxDate :: Maybe ArgDate
, _opts :: ArgOpts
Expand All @@ -50,6 +52,7 @@ emptyArgTree = ArgTree { _id = 0
, _cmd = ""
, _desc = ""
, _tags = []
, _due = Nothing
, _minDate = Nothing
, _maxDate = Nothing
, _opts = ArgOpts False
Expand Down Expand Up @@ -80,6 +83,7 @@ createExpr = do
many1
$ (AddWord <$> wordExpr)
<|> (AddTag <$> addTagExpr)
<|> (SetDue <$> dueExpr)
<|> (AddOpt <$> optExpr)
skipSpaces
return $ cmd : rest
Expand Down Expand Up @@ -161,9 +165,9 @@ worktimeExpr = do
skipSpaces
rest <-
many
$ (SetMinDate <$> minDateExpr)
$ (AddTag <$> addCtxTagExpr)
<|> (SetMinDate <$> minDateExpr)
<|> (SetMaxDate <$> maxDateExpr)
<|> (AddTag <$> addCtxTagExpr)
<|> (AddOpt <$> optExpr)
skipSpaces
return $ cmd : rest
Expand Down Expand Up @@ -240,34 +244,39 @@ delTagExpr = do

numbers :: Int -> ReadP Int
numbers c = do
skipSpaces
n <- count c (satisfy isDigit)
skipSpaces
return $ if null n then 0 else read n

dueExpr :: ReadP ArgDate
dueExpr = dateTimeExpr ':' <|> dateWithoutTimeExpr ':'

minDateExpr :: ReadP ArgDate
minDateExpr = dateWithTimeExpr '[' <|> dateWithoutTimeExpr '['
minDateExpr = dateTimeExpr '[' <|> dateWithoutTimeExpr '['

maxDateExpr :: ReadP ArgDate
maxDateExpr = dateWithTimeExpr ']' <|> dateWithoutTimeExpr ']'
maxDateExpr = dateTimeExpr ']' <|> dateWithoutTimeExpr ']'

dateWithTimeExpr :: Char -> ReadP ArgDate
dateWithTimeExpr ord = do
dateTimeExpr :: Char -> ReadP ArgDate
dateTimeExpr ord = do
skipSpaces
char ord
days <- numbers 0 <|> numbers 1 <|> numbers 2
months <- numbers 0 <|> numbers 1 <|> numbers 2
years <- numbers 0 <|> numbers 2
char ':'
hours <- numbers 0 <|> numbers 1 <|> numbers 2
mins <- numbers 0 <|> numbers 1 <|> numbers 2
eof <|> (munch1 (== ' ') >> return ())
return $ ArgDate days months years hours mins

dateWithoutTimeExpr :: Char -> ReadP ArgDate
dateWithoutTimeExpr ord = do
skipSpaces
char ord
days <- numbers 1 <|> numbers 2
months <- numbers 0 <|> numbers 1 <|> numbers 2
years <- numbers 0 <|> numbers 2
eof <|> (munch1 (== ' ') >> return ())
return $ ArgDate days months years 0 0

optExpr :: ReadP String
Expand Down Expand Up @@ -324,6 +333,7 @@ eval tree arg = case arg of
DelTag tag -> tree { _tags = _tags tree \\ [tag] }
AddWord desc -> tree { _desc = desc' }
where desc' = if null (_desc tree) then desc else _desc tree ++ " " ++ desc
SetDue due -> tree { _due = Just due }
SetMinDate min -> tree { _minDate = Just min }
SetMaxDate max -> tree { _maxDate = Just max }
AddOpt opt -> tree { _opts = opts }
Expand Down Expand Up @@ -356,6 +366,9 @@ parseDate now defHours defMins defSecs (ArgDate d mo y h m) = Just
dateStr = printf "%.4d-%.2d-%.2d" years months days
timeStr = printf "%.2d:%.2d:%.2d" hours mins defSecs

parseDue :: UTCTime -> ArgTree -> Maybe UTCTime
parseDue now args = _due args >>= parseDate now 0 0 0

parseMinDate :: UTCTime -> ArgTree -> Maybe UTCTime
parseMinDate now args = _minDate args >>= parseDate now 0 0 0

Expand Down
2 changes: 1 addition & 1 deletion src/Query.hs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,6 @@ execute args state events query = do
putStrLn "unfog <help|h>"
putStrLn "unfog <version|v>"

ShowVersion -> printVersion rtype "0.2.2"
ShowVersion -> printVersion rtype "0.3.0"

Query.Error command message -> printErr rtype $ command ++ ": " ++ message
6 changes: 4 additions & 2 deletions src/State.hs
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ apply :: UTCTime -> State -> Event -> State
apply now state event = case event of
TaskCreated _ _ref _id _pos _desc _tags due -> state { _tasks = nextTasks }
where
newTask = emptyTask { _ref, _id, _pos, _desc, _tags, _due = due }
due' = realToFrac <$> flip diffUTCTime now <$> due
newTask = emptyTask { _ref, _id, _pos, _desc, _tags, _due = due' }
nextTasks = _tasks state ++ [newTask]

TaskUpdated _ ref _ _pos _desc _tags due -> state { _tasks = nextTasks }
where
update task = task { _pos, _desc, _tags, _due = due }
due' = realToFrac <$> diffUTCTime now <$> due
update task = task { _pos, _desc, _tags, _due = due' }
nextTasks = getNextTasks ref update

TaskStarted start ref _ -> state { _tasks = getNextTasks ref update }
Expand Down
Loading

0 comments on commit 8003f96

Please sign in to comment.