Use task list and edit tasks (again)

This commit is contained in:
Joscha 2018-09-28 17:10:41 +00:00
parent c1b1fddb76
commit 70c11f656d
5 changed files with 71 additions and 11 deletions

View file

@ -32,7 +32,7 @@ dependencies:
#- sqlite-simple
#- stm
#- text
#- text-zipper
- text-zipper
- time
#- transformers
#- unix

View file

@ -7,11 +7,15 @@ module TaskMachine.UI
import qualified Brick as B
import qualified Brick.Focus as B
import qualified Brick.Themes as B
import qualified Brick.Widgets.Edit as B
import qualified Data.Text.Zipper as T
import qualified Data.Vector as V
import qualified Graphics.Vty.Input.Events as VTY
import Text.Megaparsec
import TaskMachine.LTask
import TaskMachine.Options
import TaskMachine.Task
import TaskMachine.UI.Popup
import TaskMachine.UI.TaskList
import TaskMachine.UI.Types
@ -24,8 +28,11 @@ placeholderTopBar = B.str "Prune | Reload | Search: " B.<+> B.vLimit 1 (B.fill '
placeholderNewTask :: B.Widget RName
placeholderNewTask = B.str "New: " B.<+> B.vLimit 1 (B.fill '_')
drawTaskList :: Bool -> UIState -> B.Widget RName
drawTaskList focused s = renderTaskList (taskEdit s) focused (tasks s)
drawBaseLayer :: UIState -> B.Widget RName
drawBaseLayer s = B.vBox [placeholderTopBar, renderTaskList True (tasks s), placeholderNewTask]
drawBaseLayer s = B.vBox [placeholderTopBar, drawTaskList True s, placeholderNewTask]
drawUIState :: UIState -> [B.Widget RName]
drawUIState s@UIState{errorPopup=Just p} = [renderPopupOk p, drawBaseLayer s]
@ -52,16 +59,55 @@ closeBehavior _ s (VTY.EvKey VTY.KEsc []) = B.halt s
closeBehavior _ s (VTY.EvKey (VTY.KChar 'q') []) = B.halt s
closeBehavior f s e = f s e -- wrapper around another behavior
{-
focusBehavior :: (UIState -> VTY.Event -> Result) -> UIState -> VTY.Event -> Result
focusBehavior :: (UIState -> VTY.Event -> NewState) -> UIState -> VTY.Event -> NewState
focusBehavior _ s (VTY.EvKey (VTY.KChar '\t') []) = B.continue $ bigFocusNext s
focusBehavior _ s (VTY.EvKey VTY.KBackTab []) = B.continue $ bigFocusPrev s
focusBehavior f s e = f s e -- wrapper around another behavior
-}
taskListBehavior :: UIState -> VTY.Event -> NewState
-- Mark/unmark a task as completed
taskListBehavior s (VTY.EvKey (VTY.KChar 'x') []) = undefined s
-- Delete tasks
taskListBehavior s (VTY.EvKey (VTY.KChar 'd') []) = undefined s
-- Start editing a new task
taskListBehavior s (VTY.EvKey (VTY.KChar 'e') []) =
case taskListSelectedElement (tasks s) of
Nothing -> B.continue s -- TODO: Add notification popup
Just t ->
let edit = B.editor RTaskEdit (Just 1) (formatTask t)
in B.continue s{taskEdit=Just edit}
-- Update the task list (scroll etc.)
taskListBehavior s e = do
newTasks <- updateTaskList e (tasks s)
B.continue s{tasks=newTasks}
taskEditBehavior :: B.Editor String RName -> UIState -> VTY.Event -> NewState
taskEditBehavior _ s (VTY.EvKey VTY.KEsc []) = B.continue s{taskEdit=Nothing}
taskEditBehavior edit s (VTY.EvKey VTY.KHome []) = B.continue s{taskEdit=Just (B.applyEdit T.gotoBOL edit)}
taskEditBehavior edit s (VTY.EvKey VTY.KEnd []) = B.continue s{taskEdit=Just (B.applyEdit T.gotoEOL edit)}
taskEditBehavior edit s (VTY.EvKey VTY.KEnter []) = do -- TODO: Save changes to file
let editedText = unlines $ B.getEditContents edit
case parse pTask "edited task" editedText of
Left parseError -> undefined parseError -- TODO: Add notification here
Right newTask -> do
let newTaskList = taskListModify (const newTask) (tasks s)
B.continue s{tasks=newTaskList, taskEdit=Nothing}
taskEditBehavior edit s e = do
newEdit <- B.handleEditorEvent e edit
B.continue s{taskEdit=Just newEdit}
selectBehavior :: UIState -> VTY.Event -> NewState
-- Deal with popup if there is one
selectBehavior s@UIState{errorPopup=Just popup} e = undefined popup s e
selectBehavior s e = closeBehavior rootBehavior s e
-- Under the assumption that tasks can only be edited while the task list is focused, edit a task
selectBehavior s@UIState{taskEdit=Just edit} e = taskEditBehavior edit s e
-- If nothing immediately jumps out at you, see which part has focus.
selectBehavior s e =
case B.focusGetCurrent (focus s) of
Just BRTopBar -> closeBehavior (focusBehavior rootBehavior) s e
Just BRTaskList -> closeBehavior (focusBehavior taskListBehavior) s e
Just BRNewTask -> closeBehavior (focusBehavior rootBehavior) s e
Nothing -> closeBehavior (focusBehavior rootBehavior) s e
updateUIState :: UIState -> B.BrickEvent RName () -> NewState
updateUIState s (B.VtyEvent e) = selectBehavior s e
@ -107,4 +153,5 @@ startUIState o = UIState
, focus = B.focusRing [BRTaskList, BRNewTask, BRTopBar]
, errorPopup = Nothing
, tasks = taskList RTaskList V.empty
, taskEdit = Nothing
}

View file

@ -2,6 +2,7 @@ module TaskMachine.UI.TaskList
( TaskList
, taskList
, renderTaskList
, updateTaskList
, taskListElements
, taskListFilter
, taskListSelectedElement
@ -11,12 +12,12 @@ module TaskMachine.UI.TaskList
--import Data.Void
import qualified Brick as B
import qualified Brick.Widgets.Edit as B
import qualified Brick.Widgets.List as B
import qualified Data.Vector as V
import qualified Graphics.Vty as VTY
--import qualified Brick.Focus as B
--import qualified Brick.Widgets.Edit as B
--import qualified Data.Text.Zipper as T
--import qualified Graphics.Vty as VTY
--import Text.Megaparsec
import TaskMachine.LTask
@ -37,9 +38,17 @@ newList name ltasks = B.list name ltasks 1
taskList :: n -> V.Vector LTask -> TaskList n
taskList name ltasks = TaskList{visibleTasks=newList name ltasks, invisibleTasks=V.empty}
-- TODO: render while editing
renderTaskList :: (Ord n, Show n) => Bool -> TaskList n -> B.Widget n
renderTaskList focus tl = B.renderList (const $ renderTask . toTask) focus (visibleTasks tl)
renderLTask :: (Ord n, Show n) => Maybe (B.Editor String n) -> Bool -> LTask -> B.Widget n
renderLTask (Just e) True _ = B.renderEditor (B.str . unlines) True e
renderLTask _ _ lt = renderTask (toTask lt)
renderTaskList :: (Ord n, Show n) => Maybe (B.Editor String n) -> Bool -> TaskList n -> B.Widget n
renderTaskList edit focus tl = B.renderList (renderLTask edit) focus (visibleTasks tl)
updateTaskList :: (Ord n) => VTY.Event -> TaskList n -> B.EventM n (TaskList n)
updateTaskList e tl = do
updatedList <- B.handleListEventVi B.handleListEvent e (visibleTasks tl)
pure tl{visibleTasks=updatedList}
{- Managing tasks -}

View file

@ -87,6 +87,7 @@ data UIState = UIState
-- tasks
, tasks :: TaskList RName
, taskEdit :: Maybe (B.Editor String RName)
}
type NewState = B.EventM RName (B.Next UIState)

View file

@ -4,4 +4,7 @@
- c2018-09-18 Offer to clean up file when loading (adding creation/completion dates)
- c2018-09-18 Purge - move completed tasks to a separate file
- c2018-09-18 Sort tasks by completion, priority, due date, description
- c2018-09-28 Load file in initial app action
- c2018-09-28 Move cursor to beginning of task description when editing tasks
- c2018-09-28 Syntax highlighting while editing tasks
x2018-09-27 c2018-09-18 Quit using Esc or q