Skip to content

Commit

Permalink
Handle regular expressions in global search [WIP]
Browse files Browse the repository at this point in the history
Fixes JabRef#5349

Validate regex before setting activesearch.

Adds a validator to the search field

Fixes JabRef#5349
  • Loading branch information
CaptainDaVinci committed Oct 15, 2019
1 parent b3cda90 commit ba0d0ad
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 3 deletions.
7 changes: 6 additions & 1 deletion src/main/java/org/jabref/gui/entryeditor/SourceTab.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javax.swing.undo.UndoManager;

Expand Down Expand Up @@ -112,7 +113,11 @@ public SourceTab(BibDatabaseContext bibDatabaseContext, CountingUndoManager undo
this.stateManager = stateManager;

stateManager.activeSearchQueryProperty().addListener((observable, oldValue, newValue) -> {
searchHighlightPattern = newValue.flatMap(SearchQuery::getPatternForWords);
try {
searchHighlightPattern = newValue.flatMap(SearchQuery::getPatternForWords);
} catch (PatternSyntaxException e) {
LOGGER.error(e.getMessage());
}
highlightSearchPattern();
});

Expand Down
7 changes: 6 additions & 1 deletion src/main/java/org/jabref/gui/preview/PreviewViewer.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javafx.beans.InvalidationListener;
import javafx.beans.Observable;
Expand Down Expand Up @@ -62,7 +63,11 @@ public class PreviewViewer extends ScrollPane implements InvalidationListener {
private boolean registered;

private ChangeListener<Optional<SearchQuery>> listener = (queryObservable, queryOldValue, queryNewValue) -> {
searchHighlightPattern = queryNewValue.flatMap(SearchQuery::getPatternForWords);
try {
searchHighlightPattern = queryNewValue.flatMap(SearchQuery::getPatternForWords);
} catch (PatternSyntaxException e) {
LOGGER.error(e.getMessage());
}
highlightSearchPattern();
};

Expand Down
35 changes: 34 additions & 1 deletion src/main/java/org/jabref/gui/search/GlobalSearchBar.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,13 @@
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;

import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.application.Platform;
import javafx.beans.binding.Bindings;
import javafx.css.PseudoClass;
import javafx.event.Event;
Expand Down Expand Up @@ -48,13 +51,18 @@
import org.jabref.gui.search.rules.describer.SearchDescribers;
import org.jabref.gui.util.BindingsHelper;
import org.jabref.gui.util.DefaultTaskExecutor;
import org.jabref.gui.util.IconValidationDecorator;
import org.jabref.gui.util.TooltipTextUtil;
import org.jabref.logic.l10n.Localization;
import org.jabref.logic.search.SearchQuery;
import org.jabref.model.entry.Author;
import org.jabref.preferences.JabRefPreferences;
import org.jabref.preferences.SearchPreferences;

import de.saxsys.mvvmfx.utils.validation.FunctionBasedValidator;
import de.saxsys.mvvmfx.utils.validation.ValidationMessage;
import de.saxsys.mvvmfx.utils.validation.Validator;
import de.saxsys.mvvmfx.utils.validation.visualization.ControlsFxVisualizer;
import impl.org.controlsfx.skin.AutoCompletePopup;
import org.controlsfx.control.textfield.AutoCompletionBinding;
import org.fxmisc.easybind.EasyBind;
Expand All @@ -81,6 +89,7 @@ public class GlobalSearchBar extends HBox {
private final Tooltip tooltip = new Tooltip();
private final StateManager stateManager;
private SearchDisplayMode searchDisplayMode;
private Validator regexValidator;

public GlobalSearchBar(JabRefFrame frame, StateManager stateManager) {
super();
Expand Down Expand Up @@ -137,6 +146,15 @@ public GlobalSearchBar(JabRefFrame frame, StateManager stateManager) {
searchField.setMaxWidth(initialSize);
HBox.setHgrow(searchField, Priority.ALWAYS);

regexValidator = new FunctionBasedValidator<>(
searchField.textProperty(),
query -> !(regularExp.isSelected() && !validRegex()),
ValidationMessage.error(Localization.lang("Invalid regular expression"))
);
ControlsFxVisualizer visualizer = new ControlsFxVisualizer();
visualizer.setDecoration(new IconValidationDecorator(Pos.CENTER_LEFT));
Platform.runLater(() -> { visualizer.initVisualization(regexValidator.getValidationStatus(), searchField); });

Timer searchTask = FxTimer.create(java.time.Duration.ofMillis(SEARCH_DELAY), this::performSearch);
searchField.textProperty().addListener((observable, oldValue, newValue) -> searchTask.restart());

Expand Down Expand Up @@ -219,15 +237,30 @@ public void performSearch() {
return;
}

// Invalid regular expression
if (!regexValidator.getValidationStatus().isValid()) {
currentResults.setText(Localization.lang("Invalid regular expression"));
return;
}

SearchQuery searchQuery = new SearchQuery(this.searchField.getText(), this.caseSensitive.isSelected(), this.regularExp.isSelected());
if (!searchQuery.isValid()) {
informUserAboutInvalidSearchQuery();
return;
}

stateManager.setSearchQuery(searchQuery);
}

private boolean validRegex() {
try {
Pattern.compile(searchField.getText());
} catch (PatternSyntaxException e) {
LOGGER.debug(e.getMessage());
return false;
}
return true;
}

private void informUserAboutInvalidSearchQuery() {
searchField.pseudoClassStateChanged(CLASS_NO_RESULTS, true);

Expand Down
1 change: 1 addition & 0 deletions src/main/resources/l10n/JabRef_en.properties
Original file line number Diff line number Diff line change
Expand Up @@ -1399,6 +1399,7 @@ should\ contain\ a\ four\ digit\ number=should contain a four digit number
should\ contain\ a\ valid\ page\ number\ range=should contain a valid page number range
No\ results\ found.=No results found.
Found\ %0\ results.=Found %0 results.
Invalid\ Regex=Invalid Regex
plain\ text=plain text
This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ regular\ expression\ <b>%0</b>=This search contains entries in which any field contains the regular expression <b>%0</b>
This\ search\ contains\ entries\ in\ which\ any\ field\ contains\ the\ term\ <b>%0</b>=This search contains entries in which any field contains the term <b>%0</b>
Expand Down

0 comments on commit ba0d0ad

Please sign in to comment.