Skip to content
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

PR: Implement "Replace in selection" in the Editor #4638

Merged
merged 5 commits into from
Jul 6, 2017

Conversation

spillz
Copy link
Contributor

@spillz spillz commented Jun 22, 2017

Fixes #358


Supports replacing all instances of the search text with the replace text in a selection of text. Changes find/replace dialog to add buttons for "replace in selection" and "replace all" and removes the "replace all" checkbox. Tweaks behavior of automatically filling the searchbox depending on whether multiple lines were selected.

A refinement would be to either add shortcuts for the three buttons or combine the three buttons into one and use radio/combo to control scope.

Supports replacing all instances of the search text with the replace text in a selection of text. Changes find/replace dialog to add buttons for "replace in selection" and "replace all" and removes the "replace all" checkbox. Tweaks behavior of automatically filling the searchbox depending on whether multiple lines were selected.
@ccordoba12
Copy link
Member

@spillz, thanks for the extra effort. I'll let @rlaverde do the review.

Copy link
Member

@rlaverde rlaverde left a comment

Choose a reason for hiding this comment

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

I test it and works as expected, and I think the workflow is intuitive.

@@ -226,32 +238,36 @@ def toggle_highlighting(self, state):
else:
self.clear_matches()

def show(self):
def show(self, hide_replace = True):
Copy link
Member

Choose a reason for hiding this comment

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

Remove spaces around keyword argument:
def show(self, hide_replace=True)

@@ -267,7 +283,7 @@ def hide(self):

def show_replace(self):
"""Show replace widgets"""
self.show()
self.show(hide_replace = False)
Copy link
Member

Choose a reason for hiding this comment

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

Remove spaces around keyword argument:
self.show(self, hide_replace=True)

self.refresh()
else:
self.search_text.lineEdit().selectAll()
if hide_replace or len(text.splitlines())<=1:
Copy link
Member

Choose a reason for hiding this comment

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

Maybe a comment for explaining this behavior is missing: "When selecting several lines, and replace box is activated the text won't be replaced for the selection"



@Slot()
def replace_find_selection(self, focus_replace_text=False):
Copy link
Member

@rlaverde rlaverde Jun 22, 2017

Choose a reason for hiding this comment

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

I'm not sure if using a custom search is the best way, because the other searching methods use the findText function of QWebEngineView (they also use python regex when regex checkbox is activated).

Although I'm not sure if this could be implemented using QWebEngineView.findText because it doesn't support searching in a selection, also multiple selection should be managed adding more complexity.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

True that there is a small risk that there are different results for the two regex implementations. I think the risk is relatively small because we don't highlight find results when the user chooses a selection. And there's always UNDO...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually a bigger inconsistency is that I didn't implement the whole word restriction. DOH! And it might ultimately be simpler to use the QT implementation because python's re doesn't handle whole words. Let me give this some thought over the weekend.

@@ -329,7 +345,8 @@ def find_previous(self):
def text_has_been_edited(self, text):
"""Find text has been edited (this slot won't be triggered when
setting the search pattern combo box text programmatically"""
self.find(changed=True, forward=True, start_highlight_timer=True)
if not self.replace_widgets[0].isVisible() or len(to_text_string(self.editor.get_selected_text()).splitlines())<=1:
Copy link
Member

Choose a reason for hiding this comment

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

Add a comment for explaining this behavior too: "When selecting several lines, and replace box is activated, dynamically search is deactivated, for avoid changing the selection."

Copy link
Member

Choose a reason for hiding this comment

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

Also, this line is way to long. Please break it using a \

@rlaverde
Copy link
Member

@ccordoba12

I think this plugin need a refactoring (not as part of this PR) the different searching functions find replace_find replace_find_selection should use the same "backend", there is duplicated logic and functions use different ways to do something very similar.

@ccordoba12
Copy link
Member

Ok, but that's for Spyder 4.

cursor.beginEditBlock()
seltxt = to_text_string(self.editor.get_selected_text())
if not pattern:
replacement = re.sub(re.escape(search_text), re.escape(replace_text), seltxt, flags=re_flags)
Copy link
Member

Choose a reason for hiding this comment

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

This line is also too long. Please make it in 79 columns

@ccordoba12
Copy link
Member

@rlaverde, did you test this locally to see if it's working as expected?

@rlaverde
Copy link
Member

did you test this locally to see if it's working as expected?

yes

Damien Moore and others added 2 commits June 22, 2017 22:21
Handles whole word restriction on matches and more fully deactivates
dynamic search when user changes the find/replace options when the replace
box is activated and a multiple lines in the editor are selected.
@spillz
Copy link
Contributor Author

spillz commented Jun 25, 2017

The latest changes handle the whole word option and take care of deactivating the dynamic search multiple line selections. In my testing I noticed a few little bugs in the way that the original implementation of "replace all" works. I haven't fixed that here, but that could be the subject of a different PR.

@ccordoba12
Copy link
Member

Our tests are failing because you left a print statement behind.

In my testing I noticed a few little bugs in the way that the original implementation of "replace all" works

Could you fix them here too? I mean, if they are simple enough, we could use the opportunity to fix them.

@spillz
Copy link
Contributor Author

spillz commented Jun 25, 2017

Could you fix them here too? I mean, if they are simple enough, we could use the opportunity to fix them.

They aren't trivial to fix. They stem from the mixed use of QT and python re in the original implementation.

Sorry about the print statement. Removed it.

@ccordoba12
Copy link
Member

They aren't trivial to fix. They stem from the mixed use of QT and python re in the original implementation.

Ok, no problem. Please open an issue about them so we don't forget to fix them.

Sorry about the print statement. Removed it.

No problem, that's why we have a test to check for no print's.

@ccordoba12
Copy link
Member

@rlaverde, please give a last review to @spillz changes to see if we can merge them after his last changes.

#If whole words is checked we need to check that each match
#is actually a whole word before replacing
word_flags = 0 if case else re.IGNORECASE
replacement = re.sub(pattern, _word_replacer, seltxt, flags=re_flags)
Copy link
Member

@rlaverde rlaverde Jun 27, 2017

Choose a reason for hiding this comment

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

Why _word_replacer is needed? I think this could be achieved changing the pattern, like other functions do:

if words:
    pattern = r"\b{}\b".format(pattern)

@spillz
Copy link
Contributor Author

spillz commented Jun 29, 2017 via email

@ccordoba12
Copy link
Member

@rlaverde, please take a decision about this one. We could leave it for 3.2.1 if you prefer.

@rlaverde
Copy link
Member

But if someone puts in "" as their regex then they will be replacing instances of "\b" that start with a whole word. But maybe it is enough to make sure the pattern compiles before enclosing it in \b?

Yes, I also think that will be enough, please implement it using "\b...\b"

@rlaverde, please take a decision about this one. We could leave it for 3.2.1 if you prefer.

I think this could be in 3.2, Only the change for whole words is missing.

@ccordoba12
Copy link
Member

@spillz, please address @rlaverde comment ASAP if you want to see this in 3.2. You have until tomorrow (Wednesday) to do that.

Else I'll move this for 3.2.1.

@spillz
Copy link
Contributor Author

spillz commented Jul 5, 2017 via email

@ccordoba12
Copy link
Member

That's fine. Thanks a lot for taking the time to do it.

…lways show and focus replace box after pressing Ctrl+R
@ccordoba12 ccordoba12 changed the title Implement replace in selection in the Editor PR: Implement replace in selection in the Editor Jul 6, 2017
@ccordoba12
Copy link
Member

@rlaverde, please take a look at this one and approve it, if it's ready.

@ccordoba12
Copy link
Member

Thanks for your work @spillz!

@ccordoba12 ccordoba12 changed the title PR: Implement replace in selection in the Editor PR: Implement "Replace in selection" in the Editor Jul 6, 2017
@ccordoba12 ccordoba12 merged commit c109aff into spyder-ide:3.x Jul 6, 2017
ccordoba12 added a commit that referenced this pull request Jul 6, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants