darcs

Patch 655 resolve isssue1920: last regrets prompt in interactive mode

Title resolve isssue1920: last regrets prompt in interactive mode
Superseder Nosy List
Related Issues
Status rejected Assigned To
Milestone

Created on 2011-08-13.15:39:24 by weissi, last changed 2011-12-27.22:19:26 by kowey.

Files
File name Status Uploaded Type Edit Remove
resolve-isssue1920_-last-regrets-prompt-in-interactive-mode.dpatch weissi, 2011-08-13.15:39:24 application/octet-stream
See mailing list archives for discussion on individual patches.
Messages
msg14640 (view) Author: kowey Date: 2011-08-13.15:50:17
oops! I set weissi to work on this during CamHac 2011, but it turns out 
that Florent already submitted patch630!

Sorry weissi! :-(

[One more reason why we really ought to have automated issue-patch 
linking in roundup!]
msg14861 (view) Author: kowey Date: 2011-12-27.21:24:36
Was sure nice meeting you at the sprint, Johannes. Hope you had fun :-)


Attaching my review so I don't lose my place.  Trying to work out which 
of the two implementations we should apply, and what ideas to merge.

Bottom line is that I'd be happy to apply this in principle and then do 
tests plus some minor touch-ups (and have Johannes review said touch-ups 
if he's available).  

Haven't looked at the other implementation yet, though.

We need to fix our tests to add a last-regrets prompt to
record/amend tests

resolve isssue1920: last regrets prompt in interactive mode
-----------------------------------------------------------
> ] hunk ./src/Darcs/Commands/AmendRecord.hs 152
>                                        (filter (==All) opts)
>                                        (Just primSplitter)
>                                        (map toFilePath <$> files)
> -                 chosenPatches <- runSelection (selectChanges First 
ch) context
> +                 chosenPatches <- runSelection (selectChanges First 
True ch) context

So what we have here is that record/amend-record have a last-regrets
prompt and the other commands don't, so we modify all of them, adding
'True' if we want the prompt and 'False' otherwise.

I think one thing we've discovered in Darcs is that boolean flags tend
to travel around the code base a lot and get confusing when you have
more than one of them at a time.  We've since taken to just making up
our own little 2 member enums for that (eg. data Regrets = Regrets |
NoRegrets) for a little extra safety/clarity.

Also, I wonder if this is something we really want as a parameter to the
function, or if we're better off with one function and maybe something
like a selectChangesWithRegrets First ch.  The idea then would be that
people would use selectChanges by default, and selectChangesWithRegrets
would be a rarer case.

> hunk ./src/Darcs/SelectChanges.hs 314

Functions in SelectChanges now just thread the new askLastRegrets Bool
down to textSelect.

>  -- | The actual interactive selection process.
> hunk ./src/Darcs/SelectChanges.hs 415
> -textSelect :: forall p C(x y) . Patchy p => WhichChanges ->
> +textSelect :: forall p C(x y) . Patchy p => WhichChanges -> Bool ->
>               FL (TaggedPatch p) C(x y) -> PatchChoices p C(x y)
>               -> PatchSelectionM p IO (PatchChoices p C(x y))
> hunk ./src/Darcs/SelectChanges.hs 418
> -textSelect whch tps' pcs = do
> +textSelect whch askLastRegrets tps' pcs = do
>      userSelection <- execStateT (skipMundane whch >>
>                                   showCur whch >>
>                                   textSelect' whch) $
> hunk ./src/Darcs/SelectChanges.hs 425
>                       ISC { total = lengthFL tps'
>                           , current = 0
>                           , tps = FZipper NilRL tps'
> -                         , choices = pcs }
> +                         , choices = pcs
> +                         , lastRegretsPrompt = askLastRegrets }

textSelect then sets the ISC tuple accordingly.  The ISC tuple was
introduced to avoid the code smell of the ever-growing-parameter-list
code smell.  Seems like it's working.

>  textSelect' whch = do
>    z <- gets tps
> -  when (not $ rightmost z) $
> -       do
> -         textSelectOne whch
> -         textSelect' whch
> +  if (not $ rightmost z)
> +      then do textSelectOne whch
> +              textSelect' whch
> +      else textAskConfirm whch

This implements the trigger for the last regrets prompt

> +optionsConfirm :: String -> [KeyPress]
> +optionsConfirm jn =
> +    [ KeyPress 'd' ("confirm "++jn)
> +    , KeyPress 'q' ("cancel "++jn) ]

I would have called this optionsLastRegrets

> +-- | Asks the user for last regrets about the selection.
> +-- The message is 'Confirm record? [Dqjk], or ? for help:'
> +textAskConfirm :: forall p C(x y). Patchy p => WhichChanges
> +                     -> InteractiveSelectionM p C(x y) ()
> +textAskConfirm whichch = do

I would have called this textAskRegrets

> +    reask_user
> +    where reask_user = gets lastRegretsPrompt >>= \lr ->
> +              when lr $
> +                  do jn <- asks jobname
> +                     let prompt' = "Confirm " ++ jn ++ "?"
> +                     yorn <- liftIO $ promptChar $
> +                         PromptConfig { pPrompt = prompt'
> +                                      , pBasicCharacters =
> +                                          keysFor $ [ optionsConfirm 
jn
> +                                                    , optionsNav 
"hunk" ]
> +                                      , pAdvancedCharacters = []
> +                                      , pDefault = Just 'd'
> +                                      , pHelp = "?h" }
> +                     case yorn of
> +                       'd' -> return ()
> +                       'k' -> backOne >> showCur whichch >> 
textSelect' whichch
> +                       'q' -> liftIO $ do putStrLn $ jn++" 
cancelled."
> +                                          exitWith $ ExitSuccess
> +                       '?' -> do liftIO $ putStrLn $
> +                                     helpFor jn [optionsConfirm jn]
> +                                                [optionsNav "hunk"]
> +                                 reask_user
> +                       _ -> reask_user

Some potential trouble spots:

- This assumes we want to go back to textSelect', which is fine for now
  but I wonder if it will surprise us later on if the code grows.  I
  wonder if there is a way to avoid trouble there?

- Minor UI problem: we should probably find a way to use `thing`
  instead of assuming we want the word 'hunk' here (incidentally
  we want 'change' instead of 'hunk')

- A bit of of repetition here.
    [optionsConfirm jn] [optionsNav "hunk"]
  I think I would have done something like
     optionsBasic = optionsConfirm jn
     optionsAdv   = optionsNav "hunk"

Nothing that really bothers me a lot though.

> +noLastRegrets ::InteractiveSelectionM p C(x y) ()
> +noLastRegrets = modify (\isc -> isc { lastRegretsPrompt = False })

> hunk ./src/Darcs/SelectChanges.hs 753
>                 'p' -> liftIO $ unseal2 printPatchPager reprCur
>                 'l' -> printSelected whichch >> showCur whichch
>                 'x' -> liftIO $ unseal2 printSummary reprCur
> -               'd' -> skipAll
> +               'd' -> noLastRegrets >> skipAll
>                 'a' ->
>                     do
>                       askConfirmation
> hunk ./src/Darcs/SelectChanges.hs 757
> +                     noLastRegrets
>                       modChoices $ selectAllMiddles (whichch == Last 
|| whichch == FirstReversed)
>                       skipAll
>                 'q' -> liftIO $

Nice. These make sure you don't get an extra prompt if you hit 'd' or
'a' early on
msg14869 (view) Author: kowey Date: 2011-12-27.22:19:25
Alright, I guess if we do take this, we should go with the first 
implementation, which covers a bit more ground.  Thanks anyway and sorry 
for the needless work!
History
Date User Action Args
2011-08-13 15:39:24weissicreate
2011-08-13 15:50:17koweysetmessages: + msg14640
2011-12-27 21:24:37koweysetmessages: + msg14861
2011-12-27 22:19:26koweysetstatus: needs-screening -> rejected
messages: + msg14869