-
Notifications
You must be signed in to change notification settings - Fork 58
Find in repl #439
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Find in repl #439
Conversation
…ut don't implement search functionality
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work, I'm excited to have this feature. A few changes I'd like to see:
Esc
and/or^G
(ideally both) should cancel the search and return to the regular prompt. I could not figure out any way to cancel the search other than deleting what I had typed and then hittingEnter
. Since then, I figured out that^R
actually cancels the search, but I would expect hitting^R
to find the next matching item in the history, not cancel.- Making the prompt less verbose, as explained in my other comment.
- After finding something with a search and hitting
Enter
, the text of that history entry is placed in the REPL prompt, but it is not checked. In other words, if you select something from the history that has an error, it will appear in white letters, and will not turn red until you type something else or move the cursor. Ideally, the prompt entry would be checked immediately.
Making REPLPrompt
a sum type seems like exactly the right way to handle this. The refactoring you talked about sounds great, and we should definitely be looking for ways to clean up and simplify the code, but I don't think we need to do that big refactoring before merging this.
Yes, I think all can be done easily except for the "next matching item" thing. I'd tried that before, but maybe I can workaround it... Probably some nasty code would be required...
Agree
Oh! didn't spot that out. I'll change it |
Oh, to be clear, I was not saying you have to do that for this PR. I was just saying that's what I would expect ^R to do, if it does anything at all. But for this PR let's not worry about it. |
Also, I just went and made #450 which uses ^G to display a dialog with the scenario goal. So forget what I said about ^G, just |
Well It turned out to be easier than expected
I read that 10 minutes later hahaha also added ^G as a command. I'm removing it |
The new commits:
|
src/Swarm/TUI/Model.hs
Outdated
lastEntry :: Text -> REPLHistory -> Maybe Text | ||
lastEntry t h = case filter (liftA2 (&&) matchesText isREPLEntry) $ toList $ h ^. replSeq of | ||
[] -> Nothing | ||
rh : _ -> Just $ replItemText rh |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure if the issue is here, but it seems like only the first command of a multi-command (separated by ;
) line is returned. For example:
- enter
create "tree"; make "log"
- search for
create
The prompt contains [find create: "create "tree""] create
. I would have expect the full command to be displayed, e.g. [find create: "create "tree"; make "log""]
- instead of full line that was entered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the problem is that it is backwards. 😄 @TristanCacqueray , I assume that you typed create "tree"
some time previously in your history, before you typed create "tree"; make "log"
. The REPL history is stored as a Data.Sequence.Seq
with the newest entry at the end. For example, see
Lines 264 to 268 in 7c9e46d
addREPLItem :: REPLHistItem -> REPLHistory -> REPLHistory | |
addREPLItem t h = | |
h | |
& replSeq %~ (|> t) | |
& replIndex .~ 1 + replLength h |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha yes, that is it :-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I did interpret the repl history backwards 😵💫
|
||
-- | Creates the repl form as a decorated form. | ||
mkReplForm :: REPLPrompt -> Form REPLPrompt AppEvent Name | ||
mkReplForm r = newForm [(replPromptAsWidget r <+>) @@= editTextField promptTextL REPLInput (Just 1)] r |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should not repeat the search input, it is already displayed in the [find XX]
. For example, in bash:
$
CTRL-R(reverse-i-search)``':
swarm(reverse-i-search``swarm': ./dist-newstyle/build/...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the thing happening is that the form display the text, and also does the decorator. Should be only one of both
@@ -590,25 +612,49 @@ handleREPLEvent s (Key V.KUp) = | |||
continue $ s & adjReplHistIndex Older | |||
handleREPLEvent s (Key V.KDown) = | |||
continue $ s & adjReplHistIndex Newer | |||
handleREPLEvent s (ControlKey 'r') = continue $ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pressing CTRL-R should scroll back in the history, to access previous matching entry.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's what it is doing. See the SearchPrompt
case below.
As suggested, drop null appending Co-authored-by: Tristan de Cacqueray <[email protected]>
src/Swarm/TUI/Controller.hs
Outdated
case lastEntry t hist of | ||
Nothing -> | ||
(uiState . uiReplForm .~ mkReplForm (CmdPrompt "")) | ||
. (uiState . uiReplType .~ Nothing) | ||
. (uiState . uiError .~ Nothing) | ||
$ s | ||
Just found | ||
| T.null t -> | ||
(uiState . uiReplForm .~ mkReplForm (CmdPrompt "")) | ||
. (uiState . uiReplType .~ Nothing) | ||
. (uiState . uiError .~ Nothing) | ||
$ s | ||
| otherwise -> | ||
validateREPLForm | ||
. (uiState . uiReplForm .~ mkReplForm (CmdPrompt found)) | ||
. (uiState . uiReplType .~ Nothing) | ||
. (uiState . uiError .~ Nothing) | ||
$ s |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
. (uiState . uiReplType .~ Nothing)
. (uiState . uiError .~ Nothing)
is repeated in every branch here, can we factor it out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Indeed
@@ -590,25 +612,49 @@ handleREPLEvent s (Key V.KUp) = | |||
continue $ s & adjReplHistIndex Older | |||
handleREPLEvent s (Key V.KDown) = | |||
continue $ s & adjReplHistIndex Newer | |||
handleREPLEvent s (ControlKey 'r') = continue $ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that's what it is doing. See the SearchPrompt
case below.
src/Swarm/TUI/Controller.hs
Outdated
in s & uiState . uiReplForm .~ newform | ||
SearchPrompt ftext rh -> case toList $ rh ^. replSeq of | ||
[] -> s | ||
_ : rhis -> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand correctly, when pressing Ctrl-R
repeatedly this simply removes one element from the history and reconstructs the SearchPrompt
with the new history which is now one element shorter. The problem is that the removed element may or may not have matched the search text. So you have to press Ctrl-R
repeatedly to get rid of all the non-matching history items (during which time it looks like nothing is happening) until finally reaching the one that matched; then pressing Ctrl-R
again finally causes it to switch to the next matching history item.
Also, it is not very efficient to convert the Data.Seq
to a list, pattern-match on it, then reconstruct a Seq
from the tail of the list. Instead you should use something like Data.Sequence.viewl
or viewr
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I think the problem is that if you type many times the same command, It will appear many times in the history and you al filtering out once at time.
Using Data.Seq
directly is by far a better solution... you still have the problem of repeated elements in history I'll work that around
src/Swarm/TUI/Controller.hs
Outdated
in s & uiState . uiReplForm .~ newform | ||
handleREPLEvent s EscapeKey = | ||
continue $ | ||
(uiState . uiReplForm .~ mkReplForm (CmdPrompt "")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It makes sense for Esc
to exit a search. However, I do not like the idea of Esc also clearing the normal prompt. Here is the scenario I am imagining: the player types a long and complex input, which does not type check. They want to find out why, so they hit Enter
to see the pop-up error message. Once they are done reading the error message, they hit Esc
to close it, intending to go back to edit their input, but oops, they accidentally hit Esc
twice --- and now the input they worked so hard on is completely gone! We had talked about having Ctrl-C
clear the input (see #65), but that is much harder to do accidentally.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh that's a good point!
src/Swarm/TUI/Model.hs
Outdated
lastEntry :: Text -> REPLHistory -> Maybe Text | ||
lastEntry t h = case filter (liftA2 (&&) matchesText isREPLEntry) $ toList $ h ^. replSeq of | ||
[] -> Nothing | ||
rh : _ -> Just $ replItemText rh |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, the problem is that it is backwards. 😄 @TristanCacqueray , I assume that you typed create "tree"
some time previously in your history, before you typed create "tree"; make "log"
. The REPL history is stored as a Data.Sequence.Seq
with the newest entry at the end. For example, see
Lines 264 to 268 in 7c9e46d
addREPLItem :: REPLHistItem -> REPLHistory -> REPLHistory | |
addREPLItem t h = | |
h | |
& replSeq %~ (|> t) | |
& replIndex .~ 1 + replLength h |
hlint suggestion Co-authored-by: Brent Yorgey <[email protected]>
… back and forth to list. Add new function for user friendly search
New commits:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the hard work getting this into shape! I am excited to use this feature. The code looks great now and everything seems to work as expected.
Works great, thanks! |
This PR solves #85. It's still a little bit rough since it only shows the last entry in history with the given text.
The solution if found is making the prompt a sum type. This allow to handle reple events differently depending on which mode the repl is. I've found this more difficult to implement than expected. The main problems I've found are
UIState
is a huge data type. Maybe putting al repl-related stuff within the same record could improve things a little bitpromptUpdateL
which can handle many parts of the logic. I think this is better than having a hugehandleREPLEvent
function.All of this would imply a big refactor tough.