Skip to content
This repository was archived by the owner on Sep 6, 2021. It is now read-only.

Improved Find/Replace UI#6175

Merged
couzteau merged 7 commits into
masterfrom
pflynn/findreplace-ui
Dec 10, 2013
Merged

Improved Find/Replace UI#6175
couzteau merged 7 commits into
masterfrom
pflynn/findreplace-ui

Conversation

@peterflynn
Copy link
Copy Markdown
Member

Not done yet, but pushed in case anyone else (@larz0?) wants to play with it.

Finished so far:

  • Replace is now a single UI rather than a 3-stage "wizard." Instead of Yes/No/Stop, there's a single Replace button.
  • Replace now shares most of its code with Find, so Replace gets incremental search, match highlighting, match counting, and tickmark indicators.
  • Enter is treated as Find Next instead of closing the search bar. (And Shift+Enter = Find Prev)
  • Streamlined UI: match count hovers inside query field, regexp errors appear in a popup below the query field, next/prev buttons don't dynamically show/hide, related buttons are clustered tightly, and eliminated labels in favor of prompt text inside the replace field.
  • Explicit toggles for regexp & case-insensitive -- no longer auto-detecting based on what the query string looks like. Toggles are shared across Find, Replace, & FindInFiles and are persisted as a pref.
  • Find Next uses editor cursor pos rather than an invisible saved pos (this is part of the future Correct Find Next Behavior story, but it simplified the code here so I went ahead & did it now).
  • Keyboard shortcut for Replace button -- just use the regular Replace shortcut while the bar is open. So you can do a replace operation entirely from the keyboard, just using the Find Next & Replace shortcuts.
  • Unit tests

Not implemented yet:

  • Decide whether to unify Find & Replace into a single command (i.e. you'd never see the simpler Find-only UI anymore)
  • Final visual polish -- make search/replace fields dynamically fill available width? Etc.

Things to test:

  • Find
  • Replace
  • Replace All (no functionality changed inside the panel, but make sure launching the panel works right)
  • Find in Files

…ut not

yet picking up any of the enhanced functionality from Find)
result highlighting, tickmarks, result count, etc. They are still separate
commands for now, with Find having a simpler UI.
* Treat Enter as Find Next instead of closing the bar. Removes Enter key
handling and "commit" event from ModalBar.
* Move error message into popup & clean up how its shown/hidden. Make text
field border red whenever error is shown. Same for FindInFiles, as well.
* Remove redundant "Skip" button in Replace UI
* Make next/prev and Replace/All button pairs flush
* Move result-count label inside search field
* Fix all existing unit tests (removing some that are no longer applicable
with the new Enter key behavior).
@ghost ghost assigned couzteau Dec 4, 2013
…d of

deciding based on heuristics. (NOT changed in Find in Files yet, though)
* Change Find Next to use editor cursor pos rather than an invisible saved
pos (part of future story "Correct Find Next behavior", but also simplifies
code). With simple unit test.
* Make all Find/Replace buttons non-tabbable for now, to match existing
next/prev buttons
* Move Find in Files "no results" message back into search bar (as opposed
to drop-down error popup)
* Hide regexp error popup when sliding out Find in Files bar, just as we
do for Find/Replace
* Fix existing bug in Find in Files where prepopulated regexp text was not
checked for errors
* Persist regex/case toggle state as a pref (shared across Find, Replace &
Find in Files)
* Unit tests for new Sprint 35 find/replace features
* Replace keyboard shortcut acts like clicking the Replace button while
search bar is open
* Show keyboard shortcuts in search bar tooltips
* UI polish: make regex/case option snug with search field; make replace
buttons snug with replace field; don't overlap borders of snug buttons
(caused border to appear darker when disabled due to alpha)
Comment thread src/search/FindReplace.js Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be a good time to join this template with the Find in Files ones and use Mustache to decide what to display or not, since both have several similar parts and will have more once we have more Find in Files features. At the moment it could be done like:

<div class="search-input-container">
    <input type="text" id="find-what" value="{{value}}" placeholder="{{Strings.CMD_FIND}}" />
    <div class="error"></div>
    <span id="find-counter"></span>
</div>
<button id="find-case-sensitive" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_CASESENSITIVE_HINT}}"><div class="button-icon"></div></button>
<button id="find-regexp" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_REGEXP_HINT}}"><div class="button-icon"></div></button>

{{#hasPrevNext}}
<div class="navigator">
    <button id="find-prev" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_PREV_HINT}}">{{Strings.BUTTON_PREV}}</button>
    <button id="find-next" class="btn no-focus" tabindex="-1" title="{{Strings.BUTTON_NEXT_HINT}}">{{Strings.BUTTON_NEXT}}</button>
</div>
{{/hasPrevNext}}

{{#hasReplace}}
<input type="text" id="replace-with" placeholder="{{Strings.REPLACE_PLACEHOLDER}}"/>
<button id="replace-yes" class="btn no-focus" tabindex="-1">{{Strings.BUTTON_REPLACE}}</button>
<button id="replace-all" class="btn no-focus" tabindex="-1">{{Strings.BUTTON_REPLACE_ALL}}</button>
{{/hasReplace}}

<div class="no-results-message">{{FIND_NO_RESULTS}}</div></div>
{{#label}}
<div class="message">
    <span id="searchlabel">{{{label}}}</span>
</div>
{{/label}}

And then Create the template with:

Mustache.render(searchDialogTemplate, {
    value       : initialQuery || "",
    label       : "",     // Will have a value in Find in Files
    hasPrevNext : true,   // False for Find in Files
    hasReplace  : false,  // True for Replace
    Strings     : Strings
});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2nd that. Much prefer to have HTML code in a template file

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've combined the Find & Replace HTML fully, and I'll move it into an external file, but I'd like to keep this separate from the Find in Files UI for now because I expect they will diverge further over time (e.g. Find in Files will have additional options for choosing the set of files, etc.) and it's not clear yet how much would be shared.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately this template is pretty ugly because horizontal (inline/inline-block layouts are extremely sensitive to whitespace). So it either has to be minified, or have every line start/end with a comment...

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. Makes sense to keep them separate. Maybe we could use partials to reuse the parts that dont change between both templates. Like the input and buttons.

@couzteau
Copy link
Copy Markdown
Member

couzteau commented Dec 6, 2013

Q: Is it's necessary to update the Copyright notes for FindReplace, FindInFiles ... to 2013?

@peterflynn
Copy link
Copy Markdown
Member Author

@couzteau For existing files we don't need to increment the copyright year. Only newly-created files need the latest year.

Comment thread src/search/FindInFiles.js
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will FindReplace and FindInFiles be merged later? wondering wether a e method such as updatePrefsFromSearchBar should live in a module such as FindUtils, I suppose there are more candidates for such refactoring, ie handleQueryChange

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my note above. I don't expect they'll ever be fully combined because there are just too many differences. But they could certainly share more code in the future than they do today. I think that's probably out of scope for this story, though.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will still be nice to move this new functions to a new utils file and refactor more code on later PRs.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's so much churn coming in this code with the overall Find epic, that I'd like to to try to clean it up too heavily right away. Let's let the dust start settling a tiny bit more and then see what the common patterns are.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. I was thinking that we could later try to join the Find Modal Bars objects in one, with most of the regexp stuff there and then just extend them in Find in Files or Find when is required. I think that this is where most of the stuff is shared at the moment. New things might come up with the next features.

@couzteau
Copy link
Copy Markdown
Member

couzteau commented Dec 6, 2013

I love the side effect of being able to use find replace as interactive regex tester!

Comment thread src/search/FindReplace.js
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Has there been an API change in CodeMirror? Wondering because the new implementation does not return anything to cm.operation anymore

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On master this line is the same: we don't return a value to cm.operation(). Afaik operation() has never expected or used any return values.

You might be thinking of the return found; line that's removed below -- which is outside the operation() call, returning from findNext() overall. I removed that as a cleanup because this is now recorded in state.lastMatch.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

got it. The diff is difficult to read.

@couzteau
Copy link
Copy Markdown
Member

couzteau commented Dec 7, 2013

Done with initial review.

* Move Find/Replace UI into a template (must use a hack to hide linebreaks
from the browser though, since whitespace changes the spacing between
neighboring inline elements).
* Force Tab/Shift+Tab to cycle between the two fields in Replace bar,
instead of closing it. Tab behavior unchanged (vs. master) in Find &
Find in Files bars.
* If Replace bar wraps due to very narrow window, break only at the gap
between the Find UI & Replace UI.
@peterflynn
Copy link
Copy Markdown
Member Author

@couzteau Changes pushed. The only thing I haven't addressed yet is Raymond's comment about switching directly between the Find/Replace & Find in Files bars with the keyboard. I have a fix for that but since it's a little hacky I'd like to test it locally a bit more first before pushing it up.

Comment thread src/htmlContent/findinfiles-bar.html Outdated
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of having to pad with an empty html comment, you can achieve the same layout by just moving down > from the prior end tag as in the following example.

<div class="search-input-container"><input type="text" id="find-what" value="{{value}}" /><div class="error"></div
  ><button id='find-case-sensitive' class='btn no-focus' tabindex='-1' title='{{BUTTON_CASESENSITIVE_HINT}}'><div class='button-icon'></div></button>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That might be even harder to read than the comment hack though... anyone else have an opinion or idea for a good way to get around this?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea is to remove the gaps between inline elements, correct? Have you tried using a flex box layout in the dialog? I think it can also be done if you put float:left or display:inline-block on everything.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Felxbox will work great if we want the input fields take the whole left over space split in an equal way. The same way we used it for the Find in Files and Replace tiles in the bottom panel.

same time for an instant (one sliding in while the other sliding out). Since
more of the UI uses overlapping names now, that causes more problems than
in the past.
Ideally, ModalBar would enforce that only one is open at a time, but the
close() options are too tightly controlled by the clients right now
(especially QuickOpen). So we use a side channel to ensure that the two
modal bars that now conflict directly (FindReplace, FindInFiles) don't
overlap.

Also, small cleanups: use double quotes in HTML templates; use underscores
for FindReplace APIs intended to be called only by FindInFiles.
@peterflynn
Copy link
Copy Markdown
Member Author

@couzteau Changes pushed to address @RaymondLim's double-quotes comment and the bug he found on Fri related to switching between Find in Files and Find/Replace.

@couzteau
Copy link
Copy Markdown
Member

Looks good now. Merging.

couzteau added a commit that referenced this pull request Dec 10, 2013
@couzteau couzteau merged commit 19af046 into master Dec 10, 2013
@couzteau couzteau deleted the pflynn/findreplace-ui branch December 10, 2013 23:46
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants