Skip to content
This repository has been archived by the owner on Mar 25, 2024. It is now read-only.

Commit

Permalink
Merge branch 'release/0.10.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
smallhadroncollider committed Feb 8, 2018
2 parents 812cd02 + 4dca839 commit fc2b7f3
Show file tree
Hide file tree
Showing 23 changed files with 361 additions and 414 deletions.
9 changes: 5 additions & 4 deletions .bin/build
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,10 @@ mkdir -p "releases/$1/taskell/DEBIAN"
mkdir -p "releases/$1/taskell/usr/local/bin"
LINUX_DIR=$(ls .stack-work/install | grep linux)

tar -czvf "releases/$1/taskell-$1_x86-64-linux.tar.gz" ".stack-work/install/$LINUX_DIR/lts-9.13/8.0.2/bin/taskell" > /dev/null
tar -czvf "releases/$1/taskell-$1_x86-64-linux.tar.gz" --directory=".stack-work/install/$LINUX_DIR/lts-10.4/8.2.2/bin" "taskell"
tar -czvf "releases/$1/taskell-$1_x86-64-mac.tar.gz" --directory=".stack-work/install/x86_64-osx/lts-10.4/8.2.2/bin" "taskell"

tar -czvf "releases/$1/taskell-$1_x86-64-mac.tar.gz" ".stack-work/install/x86_64-osx/lts-9.13/8.0.2/bin/taskell" > /dev/null

cp ".stack-work/install/$LINUX_DIR/lts-9.13/8.0.2/bin/taskell" "releases/$1/taskell/usr/local/bin"
cp ".stack-work/install/$LINUX_DIR/lts-10.4/8.2.2/bin/taskell" "releases/$1/taskell/usr/local/bin"

echo "Package: taskell
Version: $1
Expand All @@ -32,6 +31,8 @@ docker run -v "$PWD/releases/$1":/usr/src/app -w /usr/src/app debian dpkg-deb --
mv "releases/$1/taskell.deb" "releases/$1/taskell-$1_x86-64-linux.deb"
rm -rf "releases/$1/taskell"

open "releases/$1"

printf "
Release Template

Expand Down
2 changes: 1 addition & 1 deletion .bin/taskell
Original file line number Diff line number Diff line change
@@ -1 +1 @@
stack build --pedantic && stack exec taskell $@
stack build && stack exec taskell $@
16 changes: 7 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# Taskell

A CLI task manager, written in Haskell
A CLI kanban board/task manager, written in Haskell

- Tasks stored in a Markdown file in the current working directory - for easy version control
- Uses `vim` style key-bindings
- Per project task lists
- Stored using Markdown
- Clean diffs for easy version control
- `vim` style key-bindings

![Demo](https://github.com/smallhadroncollider/taskell/blob/img/demo.gif?raw=true)

Expand All @@ -17,7 +19,7 @@ You can install Taskell on your Mac using [Homebrew](https://brew.sh):
brew install smallhadroncollider/taskell/taskell
```

There are bottles (binaries) available for High Sierra and Sierra. If these are not available for your computer, homebrew will build Taskell from scratch using [Stack](https://docs.haskellstack.org/), which can take a while, particularly on older machines.
There are bottles (binaries) available for High Sierra and Sierra. If these are not available for your computer, Homebrew will build Taskell from scratch using [Stack](https://docs.haskellstack.org/), which can take a while, particularly on older machines.

### Debian/Ubuntu

Expand All @@ -35,8 +37,6 @@ Run `sudo dnf install ncurses-compat-libs` then download and run binary as descr
- `taskell`: will use `taskell.md` in the cwd - offers to create if not found
- `taskell filename.md`: will use `filename.md` in the cwd - offers to create if not found

Taskell also supports `.json` files: `taskell filename.json`

## Controls

- `a`: add a task to bottom (`Enter`/`Esc` to stop)
Expand Down Expand Up @@ -66,7 +66,7 @@ Taskell also supports `.json` files: `taskell filename.json`

### Tips

- If you're using a simple two-column "Todo" and "Done" then use the space bar to mark an item as complete while staying in the "Todo" list. If you're using a more complicated column setup then you will want to use `H`/`L` to move tasks between columns.
- If you're using a simple two-column "To Do" and "Done" then use the space bar to mark an item as complete while staying in the "To Do" list. If you're using a more complicated column setup then you will want to use `H`/`L` to move tasks between columns.

## Storage

Expand All @@ -82,8 +82,6 @@ Stores in a local `taskell.md` file:
- Do That
```

Taskell also support `.json` files

---

## Roadmap
Expand Down
13 changes: 7 additions & 6 deletions app/Main.hs
Original file line number Diff line number Diff line change
@@ -1,26 +1,27 @@
module Main where

import Render (render)
import Control.Monad (when)
import Flow.State (create)
import Persistence.Taskell (exists, readJSON)
import Persistence.Taskell (exists, readFile)
import System.Console.Terminal.Size (Window(..), size)

import App (go)

getSize :: IO (Int, Int)
getSize = do
s <- size
case s of
Just (Window h w) -> return (w, h)
Nothing -> return (80, 30)

-- read JSON then render
-- read file then render
start :: FilePath -> IO ()
start path = do
json <- readJSON path
content <- Persistence.Taskell.readFile path
s <- getSize
render path $ create s json
go $ create path s content

-- if taskell.json exists/created then start
-- if taskell.md exists/created then start
main :: IO ()
main = do
(ex, path) <- exists
Expand Down
16 changes: 15 additions & 1 deletion roadmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

- Nix support?
- apt-get repository
- Use case examples in README

## Refactoring

- Use Brick for UI
- Break up State module
- Simplify state by composing Actions
- Refactor UI code - passing around too many variables
- Use a map in Actions to tidy things up/add custom key support
- Add some tests
- Avoid having to normalise the state?

## Bugs

Expand All @@ -27,6 +30,9 @@
- Add custom key support
- Add Trello import
- Add `--convert-to-md` and `--convert-to-json` options
- Multi-select mode
- Sub-lists
- Spell check?

## Done

Expand Down Expand Up @@ -88,3 +94,11 @@
- Empty tasks aren't obviously selectable
- Pressing `e` on a blank list breaks things
- Add support for Markdown
- Fixed Unicode support
- Scrolling
- New list outside view doesn't scroll
- New item outside view doesn't scroll
- Vertical scrolling falls behind
- Use concurrency for IO
- Search UI
- Vertical scrolling hides list titles
34 changes: 34 additions & 0 deletions src/App.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
module App (go) where

import Control.Monad (void)
import Control.Monad.IO.Class (liftIO)
import Flow.State (State, Mode(..), lists, continue, path, mode)
import Brick
import Persistence.Taskell (writeFile)

import Flow.Actions (event)

import UI.Draw (draw, chooseCursor, scroll)
import UI.Attr (attrMap')
import UI.Types (ResourceName(..))

-- store
store :: State -> IO State
store s = do
Persistence.Taskell.writeFile (lists s) (path s)
return (Flow.State.continue s)

-- App code
handleEvent :: State -> BrickEvent ResourceName e -> EventM ResourceName (Next State)
handleEvent s' (VtyEvent e) = let s = event e s' in
case mode s of
Shutdown -> Brick.halt s
Write _ -> scroll s >> liftIO (store s) >>= Brick.continue
_ -> scroll s >> Brick.continue s
handleEvent s _ = Brick.continue s

app :: App State e ResourceName
app = App draw chooseCursor handleEvent return attrMap'

go :: State -> IO ()
go initial = void (defaultMain app initial)
4 changes: 2 additions & 2 deletions src/Config.hs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ defaultPath :: FilePath
defaultPath = "taskell.md"

width :: Int
width = 30
width = 25

padding :: Int
padding = 4
padding = 3
18 changes: 6 additions & 12 deletions src/Data/Taskell/List.hs
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
{-# LANGUAGE DeriveGeneric #-}

module Data.Taskell.List where

import GHC.Generics (Generic)
import Data.Aeson (FromJSON, ToJSON)
import Data.Text (Text)

import Prelude hiding (splitAt, filter)
import Data.Sequence (Seq, (|>), (!?), (><), deleteAt, splitAt, filter)
Expand All @@ -12,15 +9,12 @@ import qualified Data.Taskell.Seq as S
import Data.Taskell.Task (Task, blank, contains)

data List = List {
title :: String,
title :: Text,
tasks :: Seq Task
} deriving (Generic, Show, Eq)

instance FromJSON List
instance ToJSON List
} deriving (Show, Eq)

-- useful functions
empty :: String -> List
empty :: Text -> List
empty t = List {
title = t,
tasks = S.empty
Expand All @@ -29,7 +23,7 @@ empty t = List {
new :: List -> List
new = append blank

updateTitle :: List -> String -> List
updateTitle :: List -> Text -> List
updateTitle ls s = ls { title = s }

newAt :: Int -> List -> List
Expand Down Expand Up @@ -61,5 +55,5 @@ deleteTask i l = l { tasks = deleteAt i (tasks l) }
getTask :: Int -> List -> Maybe Task
getTask i l = tasks l !? i

searchFor :: String -> List -> List
searchFor :: Text -> List -> List
searchFor s l = l { tasks = filter (contains s) (tasks l)}
5 changes: 3 additions & 2 deletions src/Data/Taskell/Lists.hs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module Data.Taskell.Lists where

import Prelude hiding (length)
import Data.Text (Text)
import Data.Maybe (fromMaybe)
import Data.Sequence (Seq, fromList, (!?), (|>), deleteAt, length)
import qualified Data.Taskell.Seq as S
Expand Down Expand Up @@ -33,7 +34,7 @@ changeList (list, i) ts dir = do
let list' = update list ts a' -- update extracted list
return $ update next list' b' -- update next list

newList :: String -> Lists -> Lists
newList :: Text -> Lists -> Lists
newList s ts = ts |> empty s

delete :: Int -> Lists -> Lists
Expand All @@ -47,7 +48,7 @@ exists i ts = case ts !? i of
shiftBy :: Int -> Int -> Lists -> Maybe Lists
shiftBy = S.shiftBy

search :: String -> Lists -> Lists
search :: Text -> Lists -> Lists
search s ls = searchFor s <$> ls

appendToLast' :: Task -> Lists -> Maybe Lists
Expand Down
34 changes: 0 additions & 34 deletions src/Data/Taskell/String.hs

This file was deleted.

29 changes: 11 additions & 18 deletions src/Data/Taskell/Task.hs
Original file line number Diff line number Diff line change
@@ -1,39 +1,32 @@
{-# LANGUAGE DeriveGeneric #-}

module Data.Taskell.Task where

import GHC.Generics (Generic)
import Data.Aeson (FromJSON, ToJSON)
import Data.List (isInfixOf)
import qualified Data.Taskell.String as S
import Data.Text (Text, snoc, length, null, isInfixOf)
import qualified Data.Taskell.Text as T

newtype Task = Task {
description :: String
} deriving (Generic, Show, Eq)

instance ToJSON Task
instance FromJSON Task
description :: Text
} deriving (Show, Eq)

blank :: Task
blank = Task { description = "" }

clear :: Task -> Task
clear _ = blank

new :: String -> Task
new :: Text -> Task
new s = Task { description = s }

append :: Char -> Task -> Task
append c t = t { description = description t ++ [c] }
append c t = t { description = Data.Text.snoc (description t) c }

backspace :: Task -> Task
backspace t = t { description = S.backspace (description t) }
backspace t = t { description = T.backspace (description t) }

characters :: Task -> Int
characters = length . description
characters = Data.Text.length . description

contains :: String -> Task -> Bool
contains s t = s `isInfixOf` description t
contains :: Text -> Task -> Bool
contains s t = s `Data.Text.isInfixOf` description t

isBlank :: Task -> Bool
isBlank t = null $ description t
isBlank t = Data.Text.null $ description t
33 changes: 33 additions & 0 deletions src/Data/Taskell/Text.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module Data.Taskell.Text (
backspace,
wrap
) where

import Data.Text (Text, foldl', singleton, snoc, init, null, append, strip, empty)
import Data.List (foldl')
import Brick.Widgets.Core (textWidth)

backspace :: Text -> Text
backspace s = if not (Data.Text.null s) then Data.Text.init s else s

-- wrapping
spl' :: [Text] -> Char -> [Text]
spl' ts c
| c == ' ' = ts ++ [" "] ++ [empty]
| Prelude.null ts = [Data.Text.singleton c]
| otherwise = Prelude.init ts ++ [Data.Text.snoc (Prelude.last ts) c]

spl :: Text -> [Text]
spl = Data.Text.foldl' spl' [empty]

wrap :: Int -> Text -> [Text]
wrap width = Data.List.foldl' (combine width) [] . spl

combine :: Int -> [Text] -> Text -> [Text]
combine width acc s = if nl then acc ++ [strip s] else Data.Taskell.Text.append (l `Data.Text.append` s) acc
where l = if Prelude.null acc then "" else last acc
nl = textWidth l + textWidth s > width

append :: Text -> [Text] -> [Text]
append s l = l' ++ [s]
where l' = if Prelude.null l then l else Prelude.init l
Loading

0 comments on commit fc2b7f3

Please sign in to comment.