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 #- sqlite-simple
#- stm #- stm
#- text #- text
#- text-zipper - text-zipper
- time - time
#- transformers #- transformers
#- unix #- unix

View file

@ -7,11 +7,15 @@ module TaskMachine.UI
import qualified Brick as B import qualified Brick as B
import qualified Brick.Focus as B import qualified Brick.Focus as B
import qualified Brick.Themes 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 Data.Vector as V
import qualified Graphics.Vty.Input.Events as VTY import qualified Graphics.Vty.Input.Events as VTY
import Text.Megaparsec
import TaskMachine.LTask import TaskMachine.LTask
import TaskMachine.Options import TaskMachine.Options
import TaskMachine.Task
import TaskMachine.UI.Popup import TaskMachine.UI.Popup
import TaskMachine.UI.TaskList import TaskMachine.UI.TaskList
import TaskMachine.UI.Types 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.Widget RName
placeholderNewTask = B.str "New: " B.<+> B.vLimit 1 (B.fill '_') 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 :: 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 :: UIState -> [B.Widget RName]
drawUIState s@UIState{errorPopup=Just p} = [renderPopupOk p, drawBaseLayer s] 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 _ s (VTY.EvKey (VTY.KChar 'q') []) = B.halt s
closeBehavior f s e = f s e -- wrapper around another behavior closeBehavior f s e = f s e -- wrapper around another behavior
{- focusBehavior :: (UIState -> VTY.Event -> NewState) -> UIState -> VTY.Event -> NewState
focusBehavior :: (UIState -> VTY.Event -> Result) -> UIState -> VTY.Event -> Result
focusBehavior _ s (VTY.EvKey (VTY.KChar '\t') []) = B.continue $ bigFocusNext s focusBehavior _ s (VTY.EvKey (VTY.KChar '\t') []) = B.continue $ bigFocusNext s
focusBehavior _ s (VTY.EvKey VTY.KBackTab []) = B.continue $ bigFocusPrev s focusBehavior _ s (VTY.EvKey VTY.KBackTab []) = B.continue $ bigFocusPrev s
focusBehavior f s e = f s e -- wrapper around another behavior 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 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@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 :: UIState -> B.BrickEvent RName () -> NewState
updateUIState s (B.VtyEvent e) = selectBehavior s e updateUIState s (B.VtyEvent e) = selectBehavior s e
@ -107,4 +153,5 @@ startUIState o = UIState
, focus = B.focusRing [BRTaskList, BRNewTask, BRTopBar] , focus = B.focusRing [BRTaskList, BRNewTask, BRTopBar]
, errorPopup = Nothing , errorPopup = Nothing
, tasks = taskList RTaskList V.empty , tasks = taskList RTaskList V.empty
, taskEdit = Nothing
} }

View file

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

View file

@ -87,6 +87,7 @@ data UIState = UIState
-- tasks -- tasks
, tasks :: TaskList RName , tasks :: TaskList RName
, taskEdit :: Maybe (B.Editor String RName)
} }
type NewState = B.EventM RName (B.Next UIState) 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 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 Purge - move completed tasks to a separate file
- c2018-09-18 Sort tasks by completion, priority, due date, description - 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 x2018-09-27 c2018-09-18 Quit using Esc or q