Use task list and edit tasks (again)
This commit is contained in:
parent
c1b1fddb76
commit
70c11f656d
5 changed files with 71 additions and 11 deletions
|
|
@ -32,7 +32,7 @@ dependencies:
|
||||||
#- sqlite-simple
|
#- sqlite-simple
|
||||||
#- stm
|
#- stm
|
||||||
#- text
|
#- text
|
||||||
#- text-zipper
|
- text-zipper
|
||||||
- time
|
- time
|
||||||
#- transformers
|
#- transformers
|
||||||
#- unix
|
#- unix
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 -}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -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
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue