diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a05ff48ba3..54971b674f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -74,6 +74,7 @@ We refer to [GitHub issues](https://github.com/JabRef/jabref/issues) by using `# - We added a context menu to the bib(la)tex-source-editor to copy'n'paste. [#5007](https://github.com/JabRef/jabref/pull/5007) - We added a bibliographic references search, for finding references in several LaTeX files. This tool scans directories and shows which entries are used, how many times and where. - We added an option in preferences to allow for integers in field "edition" when running database in bibtex mode. [#4680](https://github.com/JabRef/jabref/issues/4680) +- We added the ability to use negation in export filter layouts. [#5138](https://github.com/JabRef/jabref/pull/5138) ### Fixed diff --git a/src/main/java/org/jabref/logic/layout/LayoutEntry.java b/src/main/java/org/jabref/logic/layout/LayoutEntry.java index 5133e3c487b..a58245eb067 100644 --- a/src/main/java/org/jabref/logic/layout/LayoutEntry.java +++ b/src/main/java/org/jabref/logic/layout/LayoutEntry.java @@ -251,6 +251,7 @@ private String handleOptionField(BibEntry bibtex, BibDatabase database) { private String handleFieldOrGroupStart(BibEntry bibtex, BibDatabase database) { Optional field; + boolean negated = false; if (type == LayoutHelper.IS_GROUP_START) { field = bibtex.getResolvedFieldOrAlias(FieldFactory.parseField(text), database); } else if (text.matches(".*(;|(\\&+)).*")) { @@ -258,8 +259,9 @@ private String handleFieldOrGroupStart(BibEntry bibtex, BibDatabase database) { String[] parts = text.split("\\s*(;|(\\&+))\\s*"); field = Optional.empty(); for (String part : parts) { - field = bibtex.getResolvedFieldOrAlias(FieldFactory.parseField(part), database); - if (!field.isPresent()) { + negated = part.startsWith("!"); + field = bibtex.getResolvedFieldOrAlias(FieldFactory.parseField(negated ? part.substring(1).trim() : part), database); + if (!(field.isPresent() ^ negated)) { break; } } @@ -268,14 +270,15 @@ private String handleFieldOrGroupStart(BibEntry bibtex, BibDatabase database) { String[] parts = text.split("\\s*(\\|+)\\s*"); field = Optional.empty(); for (String part : parts) { - field = bibtex.getResolvedFieldOrAlias(FieldFactory.parseField(part), database); - if (field.isPresent()) { + negated = part.startsWith("!"); + field = bibtex.getResolvedFieldOrAlias(FieldFactory.parseField(negated ? part.substring(1).trim() : part), database); + if (field.isPresent() ^ negated) { break; } } } - if ((!field.isPresent()) || ((type == LayoutHelper.IS_GROUP_START) + if ((!(field.isPresent() ^ negated)) || ((type == LayoutHelper.IS_GROUP_START) && field.get().equalsIgnoreCase(LayoutHelper.getCurrentGroup()))) { return null; } else { diff --git a/src/test/java/org/jabref/logic/layout/LayoutTest.java b/src/test/java/org/jabref/logic/layout/LayoutTest.java index e4d310ee379..0c857b944e9 100644 --- a/src/test/java/org/jabref/logic/layout/LayoutTest.java +++ b/src/test/java/org/jabref/logic/layout/LayoutTest.java @@ -100,6 +100,35 @@ void HTMLCharsWithDotlessIAndTiled() throws IOException { layoutText); } + @Test + public void beginConditionals() throws IOException { + BibEntry entry = new BibEntry(StandardEntryType.Misc) + .withField(StandardField.AUTHOR, "Author"); + + // || (OR) + String layoutText = layout("\\begin{editor||author}\\format[HTMLChars]{\\author}\\end{editor||author}", entry); + + assertEquals("Author", layoutText); + + // && (AND) + layoutText = layout("\\begin{editor&&author}\\format[HTMLChars]{\\author}\\end{editor&&author}", entry); + + assertEquals("", layoutText); + + // ! (NOT) + layoutText = layout("\\begin{!year}\\format[HTMLChars]{(no year)}\\end{!year}", entry); + + assertEquals("(no year)", layoutText); + + // combined (!a&&b) + layoutText = layout( + "\\begin{!editor&&author}\\format[HTMLChars]{\\author}\\end{!editor&&author}" + + "\\begin{editor&&!author}\\format[HTMLChars]{\\editor} (eds.)\\end{editor&&!author}", entry); + + assertEquals("Author", layoutText); + + } + /** * Test for http://discourse.jabref.org/t/the-wrapfilelinks-formatter/172 (the example in the help files) */